スポンサーリンク

【pleasanter】サーバースクリプト~プルダウンリスト作成~ユーザー組織あたりをあれこれやってみたシリーズ⑩

プリザンター
スポンサーリンク
※当サイトは広告を含みます

ユーザー、組織あたりについてあれこれやってみたシリーズ、第10回。
前回までの2回はサーバースクリプト関連をやっています。
【pleasanter】サーバースクリプト~context,user,dept~ユーザー組織あたりをあれこれやってみたシリーズ⑧
【pleasanter】サーバースクリプト~group~ユーザー組織あたりをあれこれやってみたシリーズ⑨

今回は、サーバースクリプトで分類項目に動的にプルダウンリストを作成する、というのをやってみたいと思います。

※おことわり
2024年1月時点の情報です。プリザンターのバージョンは 1.3.20.0 です。Google Chrome でやっています。
javascript,html,cssともに初心者です。調べながら、やってみながら、きっとこうすればいいんだ!という感じで書いていますので、間違っている場合、効率的な書き方ではない可能性が大いにあります。間違ってるよ!とか、こうしたほうがいいよ!ということがありましたら、コメント等で教えていただけると大変ありがたいです。

1.はじめに

選択肢を〇〇部のユーザーだけに絞り込みしたい、等はよくあるパターンだと思います。以前の記事でやったように項目のエディタで絞り込みなどもできますが、サーバースクリプトを利用すると、さらに柔軟に動的な選択肢の変更などができます。(あんまりやったことないけど多分そう)

途中で、user や dept 、group 等がちょいちょい出てきます。プロパティやメソッド、使い方が分からなくなったら、前回前々回の記事で確認してください。わたしは、あれ?どうやるんだっけと自分で書いたにもかかわらず、振り返り思い出しながら行きつ戻りつやってます。

2.サーバースクリプトで分類項目にプルダウンリストを作成する

公式マニュアルはこちら
開発者向け機能:サーバスクリプト:columns.AddChoiceHash

columns.[カラム名].AddChoiceHash(key, value);
とありますね。

やってみましょうか。

まず、ポイントは
・プルダウンリストを設定したい分類項目の選択肢にはあらかじめなにかしら入力しておく
・サーバースクリプトの『条件』は「画面表示の前」または「行表示の前」とする

適当なサイトで分類Aに設定していきます。

①エディタ

テーブルの管理>エディタ>分類Aの詳細設定画面

選択肢一覧になにかしら入力しておきます。こうしないと、スクリプトを書いてもプルダウンリストが表示されません。

②サーバースクリプト

サーバースクリプトに以下のコードを入力します。条件は「画面表示の前」とします。

columns.ClassA.AddChoiceHash(100, 'みかん');
columns.ClassA.AddChoiceHash(200, 'いちご');
columns.ClassA.AddChoiceHash(300, 'メロン');

新規作成で、分類Aをみてみると、サーバースクリプトに書いた選択肢が選択できますね

配列に入れてみたりして、こんな風に書くこともできます。

const arr = ['AAA','BBB','CCC','DDD','EEE','FFF'];
for ( let i = 0; i < arr.length; i++ ) {
    columns.ClassA.AddChoiceHash(i, arr[i]);
}

値と表示値の二次元配列にしてみたりして、こんな風にしてみてもできました。

const arr = [[100,"AAA"],[200,"BBB"],[300,"CCC"]];
  
arr.forEach((val) => {
    columns.ClassA.AddChoiceHash(val[0], val[1]);
})

3.ログインユーザーの所属部署のユーザーを選択肢に設定する

これ、ありそうですよね。

前々回やった、user や dept も絡めてやってみましょう。

(1)ざっくりとした手順。

以下のようにやればよさそうですね。

①ログインユーザーの部署IDを取得:context.DeptId

②その部署IDからdeptオブジェクトをゲット:depts.Get(deptId)

③そのdeptオブジェクトから所属メンバー(user)をゲット:dept.GetMembers()

④そのメンバーたちをひとつずつ選択肢に追加していく

(2)エディタの設定

分類Aにサーバースクリプトで選択肢を設定していきます。
なにかしらを選択肢に設定しておかなければいけないので、[[Users*]]と入力しておきます。

(3)コード

以下のコードをサーバースクリプトに入力します。

const vdept = depts.Get(context.DeptId);
if (vdept) {
    const members = vdept.GetMembers();
    for (let member of members) {
        columns.ClassA.AddChoiceHash(member.UserId, member.Name)
    }
}

(4)設定した結果の画面

新規作成をクリックして、確認してみましょう。総務部の鈴木花子さんがログインしている場合です。
鈴木さんが所属している総務部の面々が選択肢に表示されています。

(5)コードの解説

const vdept = depts.Get(context.DeptId);

①ログインユーザーの部署IDを取得:context.DeptId
②部署IDからdeptオブジェクトを取得:depts.Get
取得したdeptオブジェクトを変数 vdept に代入

①②をまとめてやっちゃってます。
変数だかメソッドだか混乱してしまうので、変数の前にvを付けることにしました。。。

if (vdept) { ・・・ }

メンバーの取得に行きたいところですが、そのまえにエラー対応をかまします。
ログインユーザーがどこの部にも所属していなかったりして、vdeptにdeptオブジェクトが入らない場合、deptオブジェクトからっぽのまま先に進もうとすると、ブブーっとエラーになってしまうので 上記の if(vdept) で 判定します。vdeptが空っぽ( undefind )の場合、false になります。そうでなければ true になります。判定して true であれば{}内の処理に進みます。false であれば{}内の処理を行わないのでなにも起こりません。

const members = vdept.GetMembers();

取得した deptオブジェクトのメソッド、GetMembers を発動して、部署に所属している user コレクションを変数 members に代入します。コレクションは「集まり」というイメージです。

for (let member of members) { ・・・ }

userオブジェクトのコレクション members から user をひとつずつ取り出して member に代入しています。取り出した user を持ちこんで{}内の処理を行います。

columns.ClassA.AddChoiceHash(member.UserId, member.Name)

{}内の処理です。分類Aの選択肢を設定しています。
member は user オブジェクトなのでプロパティにUserId と Name を持っています。
プロパティは オブジェクトに ドット( . ) でつないで取得できます。
UserId を key(値)に、Name を value(表示名) に設定しています。

4.選択した部署に所属しているユーザーを選択肢に設定する

ちょっとだけ変化。選択した部署のユーザーを選択肢に設定するをやってみます。

ポイントは

選択肢設定のスクリプトのトリガーになる項目に「自動ポストバック」をオンにしておく。

自動ポストバックをオンにしておくことで、部署を変更するとすぐサーバー側に値が渡ります(多分)

(1)エディタの設定

分類A:選択肢一覧に [[Users*]](または[[Users]]を設定)

分類B:選択肢一覧に [[Depts]] を設定。「自動ポストバック」のチェックをON。

(2)コード

サーバースクリプトに以下のコードを入力します。条件は「画面表示の前」とします。

const vDeptId = model.ClassB;
const vDept = depts.Get(vDeptId);
if ( vDept ) {
    const members = vDept.GetMembers();
    for (let member of members) {
        columns.ClassA.AddChoiceHash(member.UserId, member.Name);
    }
}

(3)結果の画面イメージ

分類Bの部署を選択すると、分類Aのユーザーの欄に選択した部署のユーザーが選択肢として表示されました。

(4)コードの解説

ざっくりコード解説。

const vDeptId = model.ClassB;
model はレコードの情報を持つオブジェクトです。
公式マニュアル 開発者向け機能:サーバスクリプト:model
model.ClassB とすることで、分類Bの値を取得することができます。取得した値を変数 vDeptId に代入しています。const としていますが、let でも大丈夫です。
参考:【JavaScriptの基本】letとconstの使い分け

const vDept = depts.Get(vDeptId);
取得した組織ID(vDeptId)から、depts.Get でその組織IDの組織の dept オブジェクトを取得し、変数 vDept に代入しています。

if ( vDept ) {・・・ }
前項でもやりました。エラー対応です。新規作成した時点では分類Bはなにも指定されていないため、vDept は空っぽです。その状態で GetMembers をしようとするとエラーになってしまうため、vDept が空っぽではない場合のみ、{}内の処理を行うようにしています。

const members = vDept.GetMembers();
前項でもやりました。deptオブジェクトのメソッド GetMembers で、分類Bで指定した組織に所属しているユーザーを取得し、変数 members に代入します。members にはユーザーオブジェクトがコレクションとして入っています。コレクション、つまりたくさん(複数)というわけですね。

for (let member of members) {
columns.ClassA.AddChoiceHash(member.UserId, member.Name)
}

前項でもやりました。ユーザーのコレクションである members からひとつずつ user オブジェクトを取り出して 変数 member に代入し、その user オブジェクトから UserId,Name を取得し、選択肢の値、表示値として追加していっています。

(5)注意点と ClearChoiceHash

ちょっと気になった点

①部署選択前の部署が空欄の状態で、部署絞り込み前の全ユーザーが表示されてしまう。

②ユーザーを選択後、部署を変更しても、selectされていたユーザーは残ってしまう。

解消法

①は、ClearChoiceHash を入れることで解決できました。
ClearChoiceHash は選択肢をクリアするメソッドです。
公式マニュアル 開発者向け機能:サーバスクリプト:columns.ClearChoiceHash

3行目に ClearChoiceHash を入れています。

const vDeptId = model.ClassB;
const vDept = depts.Get(vDeptId);
columns.ClassA.ClearChoiceHash();
if ( vDept ) {
    const members = vDept.GetMembers();
    for (let member of members) {
        columns.ClassA.AddChoiceHash(member.UserId, member.Name);
    }
}

これで部署が空欄の時は選択肢が表示されなくなりました。

②の解消法は。。。わかりませんでした。状況は下図のようなものです。

(6)同じことをサーバースクリプトを使わずに、エディタでやる場合

本題から外れますが。
分類A(ユーザ)の選択肢一覧に以下のコードを入力することで、サーバースクリプトを使わずに分類Bの指定した部署で分類Aのユーザーの絞り込みが実現できます。
user のテーブルの、DeptId カラムで組織IDでフィルタしているんですね。
ユーザー組織シリーズの第2回、および分類項目のフィルタで似たようなことをやっています

[
    {
        "TableName": "Users",
        "View": {
            "ColumnFilterExpressions": {
                "DeptId": "[@ClassB]"
            }
        }
    }
]

5.ログインユーザーの部署、かつ承認者グループに登録されている人を選択肢に表示する

(1)やりたいこと

各部署に承認できる人が決められていたとして、承認できる人を「承認者」グループに登録していたとします。
ログインユーザーの組織の「承認者」に該当するユーザーを選択肢に表示する、というのをやってみたいと思います。

(2)エディタの設定

分類A「承認者」にログインユーザーの部署の「承認者」を選択肢として表示します。

選択肢一覧に [[Users]] を入力しておきます。

(3)コード

サーバースクリプトに以下のコードを入力します。条件は「画面表示の前」とします。

const vGroup = groups.Get(2);
const vdept = depts.Get(context.DeptId);
columns.ClassA.ClearChoiceHash();
if (vdept) {
    const vMembers = vdept.GetMembers();
    for (let vMember of vMembers) {
        if (vGroup.ContainsUser(vMember.UserId)){
            columns.ClassA.AddChoiceHash(vMember.UserId, vMember.Name);
        }
    }
}

(4)結果

総務部の鈴木花子さんがログインしたときの画面。総務部かつ承認者グループに所属している田中さんと山田さんが選択肢に表示されました。

(5)コードの解説

コードの解説をかいつまんで。

const vGroup = groups.Get(2);
groups.Get で、承認者グループ(グループID=2)のグループオブジェクトを取得し、変数 vGroup に代入します。

const vdept = depts.Get(context.DeptId);
depts.Get(context.DeptId) で、ログインユーザーの部署IDを取得し、その部署IDから depts.Get() で dept オブジェクトを取得し、vdept に代入します。

columns.ClassA.ClearChoiceHash();
一旦、分類Aの選択肢をクリアします。

if (vdept) {・・・}
変数 vdept に値が入っている場合のみ、{}内の処理に進みます。

const vMembers = vdept.GetMembers();
GetMembers() で vdeptの組織 に所属しているユーザーを取得し、vMembers に代入します。

for (let vMember of vMembers) {・・・}
vMembers から ひとつずつユーザーを取り出し vMember に代入します。その vMember を持って{}内の処理に進みます。

if (vGroup.ContainsUser(vMember.UserId)){ columns.ClassA.AddChoiceHash(vMember.UserId, vMember.Name);
}

vGroup.ContainsUser(vMember.UserId) でメンバーのユーザーIDがvGroup(グループID2の承認者グループ)に含まれるかどうかを判定します。
判定結果がTrueの場合、分類Aの選択肢に追加します。

6.選択したグループに登録されているユーザーを選択肢に表示する(ユーザーのみ)

(1)やりたいこと

分類Bでグループを選択。

選択したグループのユーザーを選択肢に表示する。

分類Bで選択できるのは「承認者グループ(グループID2)」「効率化推進チーム(グループID4)」のみとします。この二つのグループに登録されているのはユーザーであり、組織は登録されていません。

(2)エディタ

分類B

・選択肢一覧に以下のコードを入力しておき、グループ2,4のみ選択可能としておきます。
・「自動ポストバック」をオンにしておきます。

[
    {
        "TableName": "Groups",
        "View": {
            "ColumnFilterHash": {
                "GroupId": "[2,4]"
            },
            "ColumnSorterHash": {
                "GroupId": "asc"
            }
        }
    }
]

分類A

・選択肢一覧に [[Users*]]を入力しておきます。

(3)コード

サーバースクリプトに以下のコードを入力します。条件は「画面表示の前」とします。

//いったん分類Aの選択肢をクリア
columns.ClassA.ClearChoiceHash();
//分類Bから選択したグループIDをvGroupId に代入 
const vGroupId = model.ClassB;
//vGroupIdに値がある場合のみ、処理進む
if ( vGroupId ) {
    //グループIDからグループオブジェクトを取得
    const vGroup = groups.Get(vGroupId);
    //グループオブジェクトからメンバー(登録されているユーザー)を所得
    const vMembers = vGroup.GetMembers();
    //メンバーを一人ずつループ処理
    for ( let vMember of vMembers) {
        //メンバーのユーザーIDからユーザーオブジェクトを取得
        let vUser = users.Get(vMember.UserId);
        //分類Aの選択肢に登録
        columns.ClassA.AddChoiceHash(vMember.UserId, vUser.Name);
    }
}

(4)注意点

グループに含まれるのがユーザである、という前提のもとに上記のコードは成り立ちます。組織が含まれる場合はエラーとなります。組織とユーザーが混在している場合は後述7の処理でやります。

7.選択したグループに登録されているユーザーを選択肢に表示する(ユーザー、グループ混在)

(1)やりたいこと

前項6でやったこととだいたい同じです。分類Bで選択したグループに含まれるユーザーを分類Aの選択肢に設定します。

前項と違うのは、分類Bで選択するグループは、ユーザーだけを登録しているグループ以外にも、組織をグループに登録しているものもある、ということです。

(2)エディタの設定

分類B

・選択肢一覧に [[Groups*]] と指定します。今回グループの限定はしていません。(※)
・「自動ポストバック」をオンにします。
※[[Groups]] と指定すると、サイトにアクセス権が付与されているグループのみが選択肢に表示されます。今回Groupにアクセス権を設定していないので、アクセス権の有無に関係なくすべてのグループが表示される [[Groups*]] を設定しています。
参考:テーブルの管理:エディタ:項目の詳細設定:選択肢一覧:グループ

分類A

・選択肢一覧に [[Users*]]と指定します。

(3)コード

以下のコードをサーバースクリプトに入力します。条件は「画面表示の前」とします。

//いったん分類Aの選択肢をクリア
columns.ClassA.ClearChoiceHash();
//分類Bから選択したグループIDをvGroupId に代入 
const vGroupId = model.ClassB;
//vGroupIdに値がある場合のみ、処理進む
if ( vGroupId ) {
    const vGroup = groups.Get(vGroupId);   //グループIDからグループを取得         
    const vMembers = vGroup.GetMembers();  //グループの構成メンバーを取得
    let arrUserId = [];     //配列を用意
 //グループのメンバーをループ
    for ( let vMember of vMembers) {
 //メンバーの組織IDが0ではない場合、組織IDから組織を取得、組織のユーザーを配列にプッシュ
         if ( vMember.DeptId !== 0 ) {
             let zDept = depts.Get(vMember.DeptId)
             for ( let zUser of zDept.GetMembers()) {
                 arrUserId.push(zUser.UserId);
             }
         } else if ( vMember.UserId !== 0 ) {
 //メンバーのユーザーIDが0ではない場合、そのままユーザーを配列にプッシュ
             arrUserId.push(vMember.UserId);
         }
    }

 //作成した配列からユーザーIDを取り出し、分類Aの選択肢に追加
    for ( let vUserId of arrUserId) {
 //ユーザーIDが1(adminstorator)が含まれる場合は選択肢に入れない
         if (vUserId !== 1 ) { 
             let vUser = users.Get(vUserId);
             columns.ClassA.AddChoiceHash(vUser.UserId, vUser.Name);
        }
    }
}

(4)結果

効率化推進チーム(ユーザーが登録されている)を選択した場合、グループに所属するユーザーが分類Aの選択肢に表示されます。
総務経理グループ(組織である総務部と経理部が登録されている)を選択した場合、総務部のユーザー、経理部のユーザーが分類Aの選択肢に表示されます。

(5)コードの解説

コードの解説は(3)コード内のコメントにて割愛させていただきます。

流れとしては
①グループをゲット
②グループから構成メンバーをゲット
③ユーザーIDを格納しておく配列を用意
④構成メンバーをループ
⑤ー1:構成メンバーが組織の場合、その組織のメンバーのユーザーIDをひとつずつゲットして、配列に追加代入
⑤ー2:構成メンバーがユーザーの場合、そのユーザーIDを配列に追加代入
⑥配列をループして、ユーザーIDを選択肢に追加
です。

あんまり利用シーンはなさそうですが。

8.最後に

いろいろやってみましたが、利用シーンがありそうなのは1,2,3くらいかなあと思いました。

今回の学習のキモは
columns.ClassA.AddChoiceHash
columns.ClassA.ClearChoiceHash

その他
model.ClassB 等とすると、レコードの項目の値が取得できる
エラー対応 変数が空っぽでないか判定してから処理を進む if ( vDeptId ) 等
Groups.Get, Get.Members 等前回、前々回やったことがちょいちょいさしはさまれて出てきたこと。

長くなってしまいました。およみいただきありがとうございました。

9.参考文献・記事

【プリザンター】 番外編)グループに組織を含めて選択項目と連携した選択肢候補を動的に設定する方法

javascriptのオブジェクトをループさせる

【JavaScriptの基本】letとconstの使い分け

プリザンター公式マニュアルより

開発者向け機能:サーバスクリプト:columns.AddChoiceHash

開発者向け機能:サーバスクリプト:columns.ClearChoiceHash

開発者向け機能:サーバスクリプト:model

テーブルの管理:エディタ:項目の詳細設定:選択肢一覧:グループ

内部リンク
■ユーザー組織あたりをあれこれやってみたシリーズ
【pleasanter】ユーザー、組織、グループあたりをあれこれやってみた①
【pleasanter】ユーザー、組織、グループあたりをあれこれやってみた②~プルダウンリストのフィルター、ソート
【pleasanter】ユーザー、組織あたりをあれこれやってみた③~ルックアップ
【pleasanter】スクリプト~ボタンでユーザー、組織を入力~ユーザー組織あたりをあれこれやってみたシリーズ④
【pleasanter】スクリプト~ユーザーにより項目の編集可否を切り替える~ユーザー組織あたりをあれこれやってみたシリーズ⑤
【pleasanter】スクリプト~セクションの表示・非表示~ユーザー組織あたりをあれこれやってみたシリーズ⑥
【pleasanter】スクリプト~タブの表示・非表示~ユーザー組織あたりをあれこれやってみたシリーズ⑦
【pleasanter】サーバースクリプト~context,user,dept~ユーザー組織あたりをあれこれやってみたシリーズ⑧
【pleasanter】サーバースクリプト~group~ユーザー組織あたりをあれこれやってみたシリーズ⑨
【pleasanter】サーバースクリプト~プルダウンリスト作成~ユーザー組織あたりをあれこれやってみたシリーズ⑩
【pleasanter】サーバースクリプト~一覧のフィルター~ユーザー組織あたりをあれこれやってみたシリーズ⑪
【pleasanter】サーバースクリプト~一覧のフィルター2~ユーザー組織あたりをあれこれやってみたシリーズ⑫

■選択肢関連

分類項目のフィルタ

コメント

タイトルとURLをコピーしました