Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Sv translation
languageen

Sometimes in our apps we want to store hierarchical structures. In our case let's call them areas. In our case there will be one root area and infinite number of child areas with limited number of levels. In the dataset every area will store refrence to its parent area except the root one.

Using custom view and some JS magic we can the show the hierarchy like this:

The actual source code of this view is not really important and most likely will differ case to case. 

Functions

Let's explain functions to work with hierarchy. We assume that our dataset is called "AREAS" and has at least 2 attributes "ID" and "PARENT_AREA" (translated to L_ID and L_PARENT_AREA codes).

Parents

In case we want list area and all it's parents we can use formula function listHierarchicalParentMembersForAttribute. In our case the usage is:

Code Block
languagegroovy
def allParentAreas = listHierarchicalParentMembersForAttribute('AREAS', isEqualFilter('L_ID', areaId), 'L_ID', 'L_PARENT_AREA')
def allParentAreasIds = allParentAreas.collect { it.value }

Now we have IDs of current area and all it's parents in allParentAreasIds variable. We can use it to get records from another dataset for example:

Code Block
languagegroovy
def userRows = readDataset('USERS_AREA',-1,isInFilter('L_AREA_ID', allParentAreasIds as String[]), null)

Children

We can do the same with children as with parents. Difference is that now we get all child areas:

Code Block
languagegroovy
def allChildAreas = listHierarchicalChildMembersForAttribute('AREAS', isInFilter('L_ID', adminAreaIds as String[]), 'L_ID', 'L_PARENT_AREA')
def allChildAreasIds = allChildAreas.collect { it.value }


Areas hierarchy extension

Here's the custom view shown above:

View file
nameAreas hierarchy.zip
height250

And this is its formula config:

Code Block
languagegroovy
linenumberstrue
//importFromExt(User group management,AreaFunctions)

def w = currentDomain()
def userId = getCurrentUser().id

def adminOfAreasId = []
def adminOf = readDataset('USERS_AREA', -1, andFilter(isEqualFilter('L_USER_ID',userId as String), isEqualFilter('M_ADMIN', 1)), null)
if (adminOf.size() > 0) {
  def adminOfAreas = adminOf.collect { it.getValues()['L_AREA_ID'] }
  def allAreas = listHierarchicalChildMembersForAttribute('AREAS', isInFilter('L_ID', adminOfAreas as String[]), 'L_ID', 'L_PARENT_AREA')
  adminOfAreasId = allAreas.collect { it.value }
}
def userOfAreasId = []
def userOf = readDataset('USERS_AREA', -1, andFilter(isEqualFilter('L_USER_ID',userId as String), isEqualFilter('M_USER', 1)), null)
if (userOf.size() > 0) {
  def userOfAreas = userOf.collect { it.getValues()['L_AREA_ID'] }
  def allAreas = listHierarchicalChildMembersForAttribute('AREAS', isInFilter('L_ID', userOfAreas as String[]), 'L_ID', 'L_PARENT_AREA')
  userOfAreasId = allAreas.collect { it.value }
}

def ww = readDataset('SYSTEM.COMPANIES', 1, isEqualFilter('L_SCHEMA', w.schemaName), null)
def company = [:]
company << ww[0].values
company.siteCount = countDataset('CONSTRUCTION_SITES', null)

def d = readDataset('AREAS',-1,null,null)
def areas = []
d.each { area -> 
  def v = [:]
  v << area.values
  v.siteCount = countDataset('CONSTRUCTION_SITES', isEqualFilter('L_AREA', v.L_ID))
  areas << v
}
def s = readDataset('CONSTRUCTION_SITES',-1,null,null)
def sites = []
s.each {
  sites << it.values
}
sites = sites.groupBy { it['L_AREA'] }
def conf = [areas:areas, company:company, sitesByArea:sites]
def groups = listUsersGroupsInDomain()
conf.isAdmin = AreaFunctions.isCompanyAdmin()
if (conf.isAdmin || adminOfAreasId.size() > 0) {
conf.addUrl = "/bi/report/detail.report.layout.rvd.actionbutton:openpopup/4oKi0kz5B7?t:ac=76&vr=76-22lVk46y9a"
conf.adminOfAreas = adminOfAreasId  
}
conf.isCompanyUser = groups.contains('Company users')

conf.userOfAreasId = userOfAreasId
conf.areaDetailUrl = '/bi/reports/areadetail?areaId='

conf.columnName = translate(['':'Name','ja':'名前'])
conf.columnParentArea = translate(['':'Parent area','ja':'親エリア'])
conf.columnSites = translate(['':'Sites','ja':'建設現場'])
conf.buttonSearch = translate(['':'Search','ja':'検索'])
conf.buttonShowAsHierarchy = translate(['':'Show as hierarchy','ja':'階層を表示'])
conf.buttonShowDetails = translate(['':'Show details','ja':'詳細を表示'])
conf.buttonShowAsList = translate(['':'Show as list','ja':'リスト表示'])
conf.detailsSiteLimit = translate(['':'Site limit','ja':'サイト制限'])
conf.detailsAllocatedSites = translate(['':'Allocated sites:','ja':'割り当てられたサイト'])
conf.buttonHideDetails = translate(['':'Hide details:','ja':'詳細を非表示'])
conf.unlimited = translate(['':'Unlimited','ja':'制限なし'])
conf.companyLabel = translate(['':'Company','ja':'会社'])
conf.levelLabel = translate(['':'Level','ja':'レベル'])

return conf

General concept is that users can open details only of certain areas based on USER_AREAS dataset value where users can be assigned as Area admins or Area users.

Explanation of some interesting lines in the code:

#7 - Fetch areas where user is set as admin

#10 - Get all child areas for these areas as user is admin in child areas too

#14 - Do the same as user

#21 - Read company record which represents current domain, it will be displayed when there is no area

#24 - Count number of sites in the company

#31 - Count sites for each area

#43 - When user is admin of at least one area, pass link to action button to add new area

#52 - Localization for all labels used in the custom view


Sv translation
languageja

アプリでは階層構造を保存したいことがある。この場合、それらをエリアと呼ぶことにする。この場合、ルート・エリアが1つ、レベル数に制限のある子エリアが無限に存在することになる。データセットには、ルート・エリア以外のすべてのエリアが親エリアへの参照を格納する。アプリでは階層構造を保存したいことがあります。この場合、それらをエリアと呼ぶことにします。この場合、ルート・エリアが1つ、レベル数に制限のある子エリアが無限に存在することになります。データセットには、ルート・エリア以外のすべてのエリアが親エリアへの参照を格納します。

カスタムビューといくつかのJSマジックを使って、このような階層を表示することができます:

このビューの実際のソースコードはあまり重要ではなく、ケースバイケースであろう。このビューの実際のソースコードはあまり重要ではなく、ケースバイケースです。

機能

階層を扱う関数を説明しよう。データセットは 階層を扱う関数を説明します。データセットは "AREAS "と呼ばれ、少なくとも2つの属性 "ID "と "PARENT_AREA"(L_IDとL_PARENT_AREAコードに変換)を持っていると仮定する。AREAコードに変換)を持っていると仮定します。

両親

エリアとそのすべての親をリストアップしたい場合は、関数 listHierarchicalParentMembersForAttribute を使用します。この場合、使い方は次のようになります:

Code Block
languagegroovy
def allParentAreas = listHierarchicalParentMembersForAttribute('AREAS', isEqualFilter('L_ID', areaId), 'L_ID', 'L_PARENT_AREA')
def allParentAreasIds = allParentAreas.collect { it.value }

これで、allParentAreasIds変数に、現在のエリアとそのすべての親のIDが入ったことになる。この変数を使って、たとえば別のデータセットからレコードを取得することができる:これで、allParentAreasIds変数に、現在のエリアとそのすべての親のIDが入ったことになります。この変数を使って、たとえば別のデータセットからレコードを取得することができます:

Code Block
languagegroovy
def userRows = readDataset('USERS_AREA',-1,isInFilter('L_AREA_ID', allParentAreasIds as String[]), null)

子供たち

親と同じように子供にもできる。違うのは、今はすべての子供のエリアを手に入れられるということだ:親と同じように子供にもできます。違うのは、今はすべての子供のエリアを手に入れられるということです:

Code Block
languagegroovy
def allChildAreas = listHierarchicalChildMembersForAttribute('AREAS', isInFilter('L_ID', adminAreaIds as String[]), 'L_ID', 'L_PARENT_AREA')
def allChildAreasIds = allChildAreas.collect { it.value }

エリア・ヒエラルキーの拡大

これが上のカスタムビューだ:これが上のカスタムビューです:

そしてこれがそのフォーミュラ構成だ:そしてこれがそのフォーミュラ構成になります:

Code Block
languagegroovy
linenumberstrue
//importFromExt(User group management,AreaFunctions)

def w = currentDomain()
def userId = getCurrentUser().id

def adminOfAreasId = []
def adminOf = readDataset('USERS_AREA', -1, andFilter(isEqualFilter('L_USER_ID',userId as String), isEqualFilter('M_ADMIN', 1)), null)
if (adminOf.size() > 0) {
  def adminOfAreas = adminOf.collect { it.getValues()['L_AREA_ID'] }
  def allAreas = listHierarchicalChildMembersForAttribute('AREAS', isInFilter('L_ID', adminOfAreas as String[]), 'L_ID', 'L_PARENT_AREA')
  adminOfAreasId = allAreas.collect { it.value }
}
def userOfAreasId = []
def userOf = readDataset('USERS_AREA', -1, andFilter(isEqualFilter('L_USER_ID',userId as String), isEqualFilter('M_USER', 1)), null)
if (userOf.size() > 0) {
  def userOfAreas = userOf.collect { it.getValues()['L_AREA_ID'] }
  def allAreas = listHierarchicalChildMembersForAttribute('AREAS', isInFilter('L_ID', userOfAreas as String[]), 'L_ID', 'L_PARENT_AREA')
  userOfAreasId = allAreas.collect { it.value }
}

def ww = readDataset('SYSTEM.COMPANIES', 1, isEqualFilter('L_SCHEMA', w.schemaName), null)
def company = [:]
company << ww[0].values
company.siteCount = countDataset('CONSTRUCTION_SITES', null)

def d = readDataset('AREAS',-1,null,null)
def areas = []
d.each { area -> 
  def v = [:]
  v << area.values
  v.siteCount = countDataset('CONSTRUCTION_SITES', isEqualFilter('L_AREA', v.L_ID))
  areas << v
}
def s = readDataset('CONSTRUCTION_SITES',-1,null,null)
def sites = []
s.each {
  sites << it.values
}
sites = sites.groupBy { it['L_AREA'] }
def conf = [areas:areas, company:company, sitesByArea:sites]
def groups = listUsersGroupsInDomain()
conf.isAdmin = AreaFunctions.isCompanyAdmin()
if (conf.isAdmin || adminOfAreasId.size() > 0) {
conf.addUrl = "/bi/report/detail.report.layout.rvd.actionbutton:openpopup/4oKi0kz5B7?t:ac=76&vr=76-22lVk46y9a"
conf.adminOfAreas = adminOfAreasId  
}
conf.isCompanyUser = groups.contains('Company users')

conf.userOfAreasId = userOfAreasId
conf.areaDetailUrl = '/bi/reports/areadetail?areaId='

conf.columnName = translate(['':'Name','ja':'名前'])
conf.columnParentArea = translate(['':'Parent area','ja':'親エリア'])
conf.columnSites = translate(['':'Sites','ja':'建設現場'])
conf.buttonSearch = translate(['':'Search','ja':'検索'])
conf.buttonShowAsHierarchy = translate(['':'Show as hierarchy','ja':'階層を表示'])
conf.buttonShowDetails = translate(['':'Show details','ja':'詳細を表示'])
conf.buttonShowAsList = translate(['':'Show as list','ja':'リスト表示'])
conf.detailsSiteLimit = translate(['':'Site limit','ja':'サイト制限'])
conf.detailsAllocatedSites = translate(['':'Allocated sites:','ja':'割り当てられたサイト'])
conf.buttonHideDetails = translate(['':'Hide details:','ja':'詳細を非表示'])
conf.unlimited = translate(['':'Unlimited','ja':'制限なし'])
conf.companyLabel = translate(['':'Company','ja':'会社'])
conf.levelLabel = translate(['':'Level','ja':'レベル'])

return conf

一般的なコンセプトは、USER_AREASデータセットの値に基づいて、ユーザーが特定のエリアの詳細のみを開くことができるというものです。

コード中の興味深い行について説明します:

#7 - ユーザーが管理者として設定されているエリアを取得するユーザーが管理者として設定されているエリアを取得

#10 - 子エリアも管理者であるため、これらのエリアの子エリアを全て取得する。子エリアも管理者であるため、これらのエリアの子エリアを全て取得

#14 - ユーザーと同じことをする

#21 - 現在のドメインを表すcompanyレコードを読み込む。現在のドメインを表すcompanyレコードを読み込む

#24 - 会社のサイト数を数える

#31 - 各エリアのサイト数を数える

#43 - ユーザーが少なくとも1つのエリアの管理者である場合、新しいエリアを追加するアクションボタンにリンクを渡す

#52 - カスタムビューで使用される全てのラベルのローカライズ