テナント・組織・グループ・ユーザーの管理画面に設定タブを足す
本体の標準機能ではありません
1.5.8.1 の管理画面(テナント・組織・グループ・ユーザー)には、一覧の列や既定値を変える設定がありません。このページは改修する場合の設計メモです。
目的は、次の設定を管理画面でも持てるようにすることです。
- ガイド(一覧の上に出す
GridGuide、編集画面の上に出すEditorGuide) - 一覧に出す列(
GridColumns) - リンクのダイアログに出す列(
LinkColumns) - エディタの設定(列ごとの既定値
DefaultInput、版を上げるタイミングAutoVerUpType) - 履歴一覧に出す列(
HistoryColumns) - 列ごとのプロパティ(表示名・選択肢・既定値・入力必須など)
- 外せない列(必ず表示する列)
前提にした現行実装(1.5.8.1)
タブの構成
各管理画面の EditorTabs() が作るタブです。設定用のタブはありません。
| 画面 | タブ | 定義 |
|---|---|---|
| テナント | 全般、SCIM トークン(SCIM が有効なとき)、サーバースクリプト(特権ユーザーで、契約とパラメータでサーバースクリプト・バックグラウンドサーバースクリプトが有効なとき) | TenantUtilities.cs#L617-L641 |
| グループ | 全般、メンバー・子グループ・変更履歴(いずれも既存のレコードだけ) | GroupUtilities.cs#L1163 |
| 組織 | 全般、変更履歴(既存のレコードで、公開表示でないとき) | DeptUtilities.cs#L1098-L1113 |
| ユーザー | 全般、メールアドレス(EnableManageTenant でないときの既存レコード)、変更履歴(既存のレコード) | UserUtilities.cs#L1720-L1741 |
SiteSettings は毎回作り直している
管理画面の SiteSettings は SiteSettingsUtilities の TenantsSiteSettings()・DeptsSiteSettings()・GroupsSiteSettings()・UsersSiteSettings() が、DB を読まずにその場で作っています(SiteSettingsUtilities.cs#L521-L535 など)。
var ss = new SiteSettings()
{
ReferenceType = "Tenants"
};
ss.Init(context: context);
ss.SetLinks(context: context);
ss.SetChoiceHash(context: context, withLink: false);
context.SetPermissionType(
ss: ss,
type: Permissions.Admins(context: context));
ss.TableType = tableTypes;
return ss;そのため列の構成や既定値はいつも定義(Definition_Column)どおりです。
| 比較 | サイト | テナント・組織・グループ・ユーザー |
|---|---|---|
| 設定の保存先 | Sites.SiteSettings(JSON) | なし |
| ガイド | Sites.GridGuide・Sites.EditorGuide の独立した列 | なし |
GridColumns・EditorColumns・LinkColumns・HistoryColumns | 保存される | 定義の既定 |
列ごとの DefaultInput など | ColumnHash として保存される | 定義の既定 |
AutoVerUpType | 保存される | 未設定(null) |
AutoVerUpType は、更新時に版を上げるか決める Versions.MustVerUp() が ss.AutoVerUpType を見ています(Versions.cs#L43-L61)。管理画面の各 Utilities も更新時に MustVerUp() を呼んでいるので、SiteSettings を保存できるようにすれば効きます。
AutoVerUpType | 値 | 動作 |
|---|---|---|
Default | 1 | 更新者が前回と違うか、前回の更新と日付が違うときに版を上げる(未設定もこの動作) |
Always | 2 | 毎回版を上げる |
Disabled | 3 | 版を上げない |
設定の対象になる列
一覧・エディタの設定の対象は、Definition_Column で GridEnabled・EditorEnabled が 1 の列です。1.5.8.1 の定義では次のとおりです(Required が 1 の列に ※)。
| 画面 | 一覧・エディタの両方 | 一覧だけ | エディタだけ |
|---|---|---|---|
| テナント | Language・Theme・TimeZone | - | - |
| グループ | GroupId※・GroupName※・Body・Disabled | - | LdapSync |
| 組織 | DeptId※・DeptCode※・DeptName※・Body・Disabled | - | - |
| ユーザー | UserId※・LoginId※・Name・UserCode・Language※・Theme・Gender・Birthday・Body・Manager・Disabled・Lockout など | Dept・DeptCode・TimeZoneInfo※ | DeptId・TimeZone・Password・PasswordValidate※ など |
既存の設定用の部品
サイト設定の部品は SiteUtilities にあります。
| 部品 | 公開範囲 | 備考 |
|---|---|---|
GuideEditor(context, ss, siteModel) | public | SiteModel を引数に取る(SiteUtilities.cs#L6386-L6390) |
GridSettingsEditor(context, ss) | private | #L6574 |
EditorSettingsEditor(context, ss) | private | #L7402 |
LinksSettingsEditor(context, ss) | private | #L9588 |
HistoriesSettingsEditor(context, ss) | private | #L9665 |
GridColumnDialog(context, ss, column)・EditorColumnDialog(context, ss, column, titleColumns) | public | 列のプロパティのダイアログ(#L6777、#L8121) |
GuideEditor は SiteModel への依存を外すか、管理画面ごとに同じものを作る必要があります。一覧・エディタ・リンク・履歴の部品は SiteSettings だけを受け取るので、公開範囲を広げれば管理画面からも呼べます。
保存方式
| 方式 | 内容 | 利点 | 欠点 |
|---|---|---|---|
A. 各テーブルに SiteSettings 列を足す | Tenants・Groups・Depts・Users に SiteSettings nvarchar(max) を追加 | サイトと同じ形。SiteSettings クラスと既存の部品をそのまま使える | CodeDefiner の再実行と DB の列追加が要る |
B. TenantSettings に入れる | テナントの既存の TenantSettings に持たせる | テナントなら列の追加が要らない | テナント以外には入れ物がなく、形がそろわない |
| C. 画面ごとの設定クラスを作る | GroupSettings などを新設 | 型で管理できる | クラスごとに列の追加が要る |
A が素直です。ガイドはサイトでは独立した列ですが、SiteSettings クラスに GridGuide・EditorGuide のフィールドがあるので(SiteSettings.cs#L111-L113)、JSON の中に入れれば独立した列は要りません。テナントは既存の TenantSettings 列(バックグラウンドサーバースクリプトの保存先)とは別に SiteSettings 列を足すことになります。
図を読み込み中…
改修の手順
1. 列の定義を足す
App_Data/Definitions/Definition_Column/ に Tenants_SiteSettings.json・Groups_SiteSettings.json・Depts_SiteSettings.json・Users_SiteSettings.json を足します。ひな形は Sites_SiteSettings.json です(Sites_SiteSettings.json)。
{
"Id": "Tenants_SiteSettings",
"ModelName": "Tenant",
"TableName": "Tenants",
"Label": "テナント",
"ColumnName": "SiteSettings",
"LabelText": "管理画面設定",
"No": "XXX",
"TypeName": "nvarchar",
"TypeCs": "SiteSettings",
"RecordingData": ".RecordingJson(context: context)",
"MaxLength": "-1",
"Nullable": "1",
"NotForm": "1",
"ByDataRow": "GetSiteSettings(context: context, dataRow: dataRow)",
"BySession": "context.SessionData.Get(\"SiteSettings\")?.ToString().DeserializeSiteSettings(context: context) ?? new SiteSettings(context: context, referenceType: ReferenceType)"
}No はテーブル内の既存の番号と重ならない値にします。
2. CodeDefiner を実行し、DB に列を足す
CodeDefiner を実行すると Libraries/DataSources/Rds.cs と TenantModel.cs・GroupModel.cs・DeptModel.cs・UserModel.cs が再生成され、SiteSettings プロパティと SQL の列が入ります。既存の環境には ALTER TABLE で 4 つのテーブルに列を足します。CodeDefiner の仕組みは CodeDefiner を参照してください。
3. SiteSettingsUtilities で DB から読む
public static SiteSettings TenantsSiteSettings(
Context context,
int tenantId = 0,
Sqls.TableTypes tableTypes = Sqls.TableTypes.Normal)
{
var ss = tenantId > 0
? Repository.ExecuteTable(
context: context,
statements: Rds.SelectTenants(
column: Rds.TenantsColumn().SiteSettings(),
where: Rds.TenantsWhere().TenantId(tenantId)))
.AsEnumerable()
.FirstOrDefault()
?.String("SiteSettings")
?.DeserializeSiteSettings(context: context)
?? new SiteSettings() { ReferenceType = "Tenants" }
: new SiteSettings() { ReferenceType = "Tenants" };
ss.Init(context: context);
ss.SetLinks(context: context);
ss.SetChoiceHash(context: context, withLink: false);
context.SetPermissionType(
ss: ss,
type: Permissions.Admins(context: context));
ss.TableType = tableTypes;
return ss;
}4. タブと設定画面を足す
各 Utilities の EditorTabs() に、既存レコードのときだけ出るタブを足します(ガイド・一覧・リンク・エディタ・履歴)。
.Li(
_using: tenantModel.MethodType != BaseModel.MethodTypes.New,
action: () => hb
.A(
href: "#GridSettingsEditor",
text: Displays.Grid(context: context)))
// LinksSettingsEditor・EditorSettingsEditor・HistoriesSettingsEditor・ガイドも同様パネル側は SiteUtilities の部品を呼びます(公開範囲を広げたうえで)。
hb
.GridSettingsEditor(context: context, ss: ss)
.LinksSettingsEditor(context: context, ss: ss)
.EditorSettingsEditor(context: context, ss: ss)
.HistoriesSettingsEditor(context: context, ss: ss);既存の「変更履歴」タブ(FieldSetHistories)は履歴を見るためのもので、ここで足す履歴の設定(履歴一覧に出す列)とは別のタブです。設定タブは管理者だけに出すよう、context.HasPrivilege などで制御します。
5. SetByForm と Update で保存する
SiteModel.SetByForm() は設定画面から来た値を SiteSettings に反映しています。同じ処理を各 XxxModel.SetByForm() に足し、Update() で SiteSettings 列に保存します。列のプロパティのダイアログから来た値は SiteSettings.SetColumnProperty() で反映します。
// SiteModel.SetByForm() の該当部分の形
case "AutoVerUpType":
SiteSettings.AutoVerUpType = (Versions.AutoVerUpTypes)value.ToInt();
break;SiteSettings はサイト(期限付きテーブル・記録テーブルなど)向けの設計なので、カレンダー・ガント・カンバンなど管理画面に関係ない設定は画面に出さないようにします。
外せない列
エディタの設定には「外せない列」の仕組みがすでにあります。EditorSettingsEditor が Required == true の列名を EditorColumnsNessesaryColumns、警告文を EditorColumnsNessesaryMessage という hidden に入れ(SiteUtilities.cs#L7700-L7710)、画面側の fieldselectable.js がその列を無効にしようとすると警告を出して止めます。
fieldselectable.js は '#' + columnsId + 'NessesaryColumns' と '#' + columnsId + 'NessesaryMessage' を探す汎用の作りです(fieldselectable.js#L118-L133)。一覧(GridColumns)にも同じ仕組みを付けるなら、サーバー側で GridColumnsNessesaryColumns と GridColumnsNessesaryMessage の hidden を出すだけで、スクリプトは変えずに済みます。
.Hidden(
controlId: "GridColumnsNessesaryMessage",
value: Messages.CanNotDisabled(
context: context,
data: "COLUMNNAME").Text)
.Hidden(
controlId: "GridColumnsNessesaryColumns",
value: Jsons.ToJson(
ss.GetGridColumnNames()
?.Where(o => ss.GridColumn(o)?.Required == true)))どの列を外せなくするかは Definition_Column の Required で決まります。前述の表のとおり、1.5.8.1 でもグループ・組織・ユーザーの ID や名前の列の多くはすでに Required が 1 です。
影響範囲
- CodeDefiner の生成物(
Rds.cs・各Model.cs)が変わるので、改修の差分は大きくなります。既存の管理画面の動作は、SiteSettings列が空なら今と同じです。 - 既存環境への展開では、4 つのテーブルへの列追加が要ります。