スポンサーリンク

【pleasanter】スクリプト~ユーザーにより項目の編集可否を切り替える~ユーザー組織あたりをあれこれやってみたシリーズ⑤

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

ユーザー組織あたりをあれこれやってみたシリーズ。前回は、組織で条件分岐してボタン表示。ユーザー・組織を入力、というのをやりました。
【pleasanter】スクリプト~ボタンでユーザー、組織を入力~ユーザー組織あたりをあれこれやってみたシリーズ④

今回も、ユーザー、組織、グループに関連するところの「スクリプト」をやってみようと思います。

今回は、許可された人だけある項目の入力が可能で、ほかの人々は入力・編集ができない。というのをやってみようと思います。

今回やることをざっくり。以下のようなことをやりながら学びました。

・エディタの選択肢の指定:ユーザーIDを指定してプルダウンリストを絞り込み
以下スクリプト
・配列にユーザーIDを代入する
・ログインユーザーのIDを取得する
・配列をループして、ユーザーIDがあるかないかをチェック
・breakでループを抜ける
・条件により、項目を編集不可にする

・エディタの選択肢の指定;グループIDでプルダウンリストを絞り込み
以下スクリプト
・$p.apiGroupsGet:グループIDからグループ情報を取得
・$p.apiGroupsGetで取得したGroupMembersからmapを使用してユーザーIDの配列を作成する
・$p.apiGroupsGetは非同期処理である
・promiseを使った場合

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

1.やってみた

(1)やりたいこと

許可された人のIDでログインしている場合のみ、分類A、分類B、説明Aが編集可能となる。
また、分類Aで選択できるユーザーは以下の許可された人のみとする。

許可された人は
ユーザーID:7, 山田さん(総務部)
ユーザーID:8, 加藤さん(経理部)
ユーザーID:10, 鈴木さん(総務部)
ユーザーID:11, 伊藤さん(経理部)

(2)エディタの設定

分類A:選択肢一覧に以下コードを入力
※対象ユーザーが多い場合は「検索機能を使う」にチェック(本テストサイトではユーザーが少ないため検索機能を使うにチェックは入れない)
(これでよいのかわからないが、やってみたらできた)
ユーザー、グループ、組織あたりのリストについては以下の記事でやっています。
【pleasanter】ユーザー、組織、グループあたりをあれこれやってみた②~フィルター、ソート

[
    {
        "TableName": "Users",
        "View": {
            "ColumnFilterHash": {
                "UserId": "[7,8,10,11]"
            }
        }
    }
]

分類B:選択肢一覧に以下設定
100,承認
200,否認

説明A:マークダウン

(3)スクリプト

$p.events.on_editor_load = function () {
    //許可された人のユーザーIDを配列に代入
    const kyokaUsers = [ 7, 8, 10 ,11 ];
    //ログインユーザーのid取得しをuserIdに代入
    const userId = $p.userId();
    //分岐用変数flagを用意。初期値はfalse
    let flag = false;
    //配列kyokaUsersをループ。userIdと一致した場合flagをtrueに
    for ( let i = 0; i <= kyokaUsers.length; i++ ) {
        if ( userId === kyokaUsers[i] ) {
            flag = true;
            break;
        }
    }
    //flagがfalseの場合分類A,B、説明Aを編集不可にする。
    //flagがtrueの場合は編集不可にしない。
    if ( flag === false ) {
        $('#Results_ClassA').prop('disabled',true);
        $('#Results_ClassB').prop('disabled',true);
        $('#Results_DescriptionA').prop('disabled',true);
    }
}

(4)実際の動き

許可されているユーザー、伊藤さん(ID11)が操作した場合。
分類A,B、説明Aとも入力できます。

許可されているユーザー以外、ID11岡田さんがログインして操作した場合、分類A、B、説明Aとも入力できません。

(5)コードの解説

上から順に

$p.events.on_editor_load = function () { 処理 }

もうおなじみですね。編集画面を起動したときに{}内の処理が実行されます。
「処理」の部分に走らせたいコードを書いていきます。

//許可された人のユーザーIDを配列に代入
const kyokaUsers = [ 7, 8, 10 ,11 ];

配列 kyokaUsers に、ユーザーIDを代入しています。
配列とは何ぞや?という方は調べてみてくださいね。何個も値を入れられる変数みたいなものです。便利です。

//ログインユーザーのid取得しをuserIdに代入
const userId = $p.userId();

前回もやりましたね。ログインしている人のユーザーIDを取得し、変数 userId に代入しています。
$p.userId がログインしているユーザーのIDを取得する、プリザンターさんが用意してくれている関数です。

//分岐用変数flagを用意。初期値はfalse
let flag = false;

あとで、userId が kyokaUsers の中にいるかな?を確認します。いたら目印フラッグをたてる、いなければ立てない、ということをしたいので、そのための目印フラッグ変数 flag を宣言しておきます。初期値を false にしています。

//配列kyokaUsersをループ。userIdと一致した場合flagをtrueに
for ( let i = 0; i <= kyokaUsers.length; i++ ) {
if ( userId === kyokaUsers[i] ) {
flag = true;
break;
}
}

配列をループしてひとつづつ配列のユーザーIDとログインIDを比較します。
一致したら flag を true にします。
一致した場合、そのあとはもうやっても無駄なので、 break でループを抜けます。

//flagがfalseの場合分類A,B、説明Aを編集不可にする。
//flagがtrueの場合は編集不可にしない。
if ( flag === false ) {
$(‘#Results_ClassA’).prop(‘disabled’,true);
$(‘#Results_ClassB’).prop(‘disabled’,true);
$(‘#Results_DescriptionA’).prop(‘disabled’,true);
}

flag が false の場合(つまりログインユーザーのIDが配列 kyokaUsers に含まれなかった場合)分類A、B、説明Aを編集不可にします。
要素.prop(‘disabled’,true) については前回やりましたね。

と、まあ、こんな感じです。
ユーザーIDをスクリプト内で配列に入れておくのは、なんだか行けてない感じはします。
許可ユーザーの変更があったとき、いちいちスクリプト内を見に行って、チマチマ変更しないといけない、さらにエディタのユーザー選択肢のフィルタでもIDを直接しているのでそちらもへんこうしなければいけない。なんかイマイチ。ですが、あくまで例なので!

2.グループを使ってやってみた

ここから先は、私の趣味の探求領域です。配列でIDを指定したが、配列ではなくグループを使って、上記の挙動をできないか?というところをやってみました。
サーバースクリプトを使う、拡張SQLを利用数等するほうがよいと思うのですが、ここでは意地でもスクリプトでやってみる方法を試しています。ほんとうに趣味の実験なので、読むだけ時間の無駄になるかもなので、悪しからず。

(1)やりたいこと

許可された人のIDでログインしている場合のみ、分類A、分類B、説明Aが編集可能となる。
また、分類Aで選択できるユーザーは以下の許可された人のみとする。

許可された人は
ユーザーID:7, 山田さん(総務部)
ユーザーID:8, 加藤さん(経理部)
ユーザーID:10, 鈴木さん(総務部)
ユーザーID:11, 伊藤さん(経理部)

上記1と同じです。許可されて人たちをグループ「許可された人」に登録します。

(2)グループの登録

グループ「許可された人」に山田さん(ID7)、加藤さん(ID8)、鈴木さん(ID10)、伊藤さん(ID11)を登録します。グループのIDは 4 です。

(3)エディタの設定

分類A:選択肢一覧に以下コードを入力
※対象ユーザーが多い場合は「検索機能を使う」にチェック(本テストサイトではユーザーが少ないため検索機能を使うにチェックは入れない)
グループ4でユーザーをフィルタします。

[
    {
        "TableName": "Users",
        "View": {
            "ColumnFilterHash": {
                "Groups": "[4]"
            }
        }
    }
]

分類B:選択肢一覧に以下設定
100,承認
200,否認

説明A:マークダウン

(4)コード

$p.events.on_editor_load = function () {
    $p.apiGroupsGet({
        id: 4,
        done: function (data) {
            const arr = data.Response.Data[0].GroupMembers;
            const kyokaUsers = arr.map(function(item){
                return item.split(",")[1];
            })
            const userId = $p.userId();
            let flag = false;
            for ( let i = 0; i <= kyokaUsers.length; i++ ) {
                if ( userId == kyokaUsers[i] ) {
                    flag = true;
                    break;
                }
            }

            if ( flag == false ) {
                $('#Results_ClassA').prop('disabled', true);         
                $('#Results_ClassB').prop('disabled', true);  
                $('#Results_DescriptionA').prop('disabled', true);  
            }
        }
    })
}

(5)コードの解説

1と同じ部分は割愛します。

$p.apiGroupsGet
を使用して、グループIDからグループ情報を取得しています。
https://pleasanter.org/manual/script-api-groups-get

取得したグループ情報は下図のようなイメージで取得されています。

Response の Data の中の GroupMembers を取り出せばよさそうですが、
[ ‘ User, 7, false’, ‘ Uset, 8, false’, ‘ Uset, 10, false’, ‘ Uset, 11, false’ ]
のようになっており、配列 [ ] の中に文字列で ‘ User, 7, false’ ってなっていて、ここの真ん中の数字だけほしいんだけどなあ、ということになります。

そこで、mapというやつを使ってみました。配列から新たに配列を作成する関数です。
詳しい解説は割愛します(というか詳しい説明ができない)以下のサイト等を参考としてください。
https://www.sejuku.net/blog/21812

const arr = data.Response.Data[0].GroupMembers;
ここで arr は [ ‘ User, 7, false’, ‘ Uset, 8, false’, ‘ Uset, 10, false’, ‘ Uset, 11, false’ ] です。

arr.map(function(item){ 配列の要素一つ一つに対して行う処理 })
itemには配列から取り出したまずは1つめの要素 ‘ User, 7, false’ が入り、そのあとすべての要素一つ一つが順番に処理されます。

item.split(“,”)[1];
これを分解すると
item.split(“,”)
‘ User, 7, false’ を カンマで分割して配列にしています。
[‘User’, 7, ‘false’] となります。
それに[1]をつけて
item.split(“,”)[1]
配列から2つ目の要素を取り出しています。(配列は 0番目から始まりますので2番目は[1]と書きます)
つまり [‘User’, 7, ‘false’][1] と書き換えられます。
変数を使って書き換えると
arr = [‘User’, 7, ‘false’];
arr[1]
となります。
つまるところ、 ‘ User, 7, false’ から 7 を取り出しています。

return item.split(“,”)[1];
つまり return 7; ということになります。
returnした 7 を新たな配列 kyokaUsers に push しています。

で、最終的に 配列 kyokaUsers は [7,8,10,11] になります。

で、そのあとの処理も done: の中で行っています。
$p.apiGroupsGet は非同期処理ですので、これを行った後にやりたい処理はdoneの中に入れる必要があります。
もしくは promise async awite 等を使う必要があります。

非同期処理についてはここでは詳しく述べませんが(というか説明できるだけの知識がない)

$p.events.on_editor_load = function () {
   処理1
   $p.apiGroupsGet
   処理2
}

という処理の記述の場合、処理が行われる順番は
処理1
処理2
$p.apiGroupsGet
です。
非同期処理は後回しにされるんです。
なので、処理2を$p.apiGroupsGetの後に行いたい場合、$p.apiGroupsGetのdoneの中に書くんですね。
$p.events.on_editor_load = function () {
  処理1
$p.apiGroupsGet({
done: 処理
処理2
})
}

これまでvbaしかやったことのない身には js の非同期処理は衝撃でした。
は?書いた順番通りにやらないってどゆこと?って。

(6)promise を使って書いてみた

生まれて初めてpromiseを使ってみた。
なぜならば、会社のプリザンターはEdgeのIEモードに載っているので、promiseが使えないので、入れ子地獄で書くしかないのである。
以下、コピペの見様見真似で、意味わからんけど書いてみた。動くことは動く。が、ひょっとしてとんでもない書き方をしているのかもわからない。そのうえ前より長くなってしまったではないか!
async awite はさらに意味が分からなかったので、まだ書けず。そのうちに!

$p.events.on_editor_load = function () {

    const groupId = 4;

    get(groupId).then(function(responce){
        const kyokaUsers = responce;
        let flag = false;
        const userId = $p.userId();

        for ( let i = 0; i <= kyokaUsers.length; i++ ) {
            if ( userId == kyokaUsers[i] ) {
                flag = true;
                break;
            }
        }

        if ( flag == false ) {

             $('#Results_ClassA').prop('disabled', true);         
             $('#Results_ClassB').prop('disabled', true);  
             $('#Results_DescriptionA').prop('disabled', true); 
        }
    })
}

function get(groupId) {

    return new Promise(function(resolve) {

        $p.apiGroupsGet({
            id: groupId,
            done: function (data) {
                const arr = data.Response.Data[0].GroupMembers;
                const arr2 = arr.map(function(item){
                    return item.split(",")[1];
                })
                resolve(arr2);
            }
        })      
    });    
}

3.最後に

後半はごめんなさい。私の趣味の実験で、長くなってしまいました。
ユーザー、組織シリーズ、まだやります。

4.参考文献・記事

開発者向け機能:スクリプト:$p.apiGroupsGet
https://pleasanter.org/manual/script-api-groups-get

【JavaScript入門】配列処理をするmap()の使い方とMapオブジェクトの解説!
https://www.sejuku.net/blog/21812

JavaScriptのPromiseの仕組みについて現役エンジニアが解説【初心者向け】
https://magazine.techacademy.jp/magazine/49775

【jQuery入門】disabled属性の設定・解除・判定方法まとめ!
https://www.sejuku.net/blog/44465

【jQuery入門】prop(attr)の使い方と属性値の取得・設定まとめ!
https://www.sejuku.net/blog/36294

HTML 要素の disabled 属性と readonly 属性の違いと正しい使い方
https://blog1.mammb.com/entry/2020/01/05/090000

内部リンク 
■プリザンターボタン関連 (ボタンは以前あれこれやりました)
【pleasanter】編集画面にボタンを追加の実践例~ボタン表示・非表示、日付・ユーザーのセット~
【pleasanter】編集画面のボタンを表示したり非表示にしたりする~スタイル・スクリプトの利用~
【pleasanter】スクリプトでボタンを編集画面に追加する
【pleasanter】拡張HTML~フィールドの右(左)に追加テキストを表示、ボタンの表示

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

コメント

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