Skip to content

管理画面の使い勝手改善 ​

第6版作成 最終更新 (日本時間)
確認バージョン1.5.7.01.5.8.1

サイトの管理画面は、本体を改修しなくても拡張スタイル・拡張スクリプト(必要に応じて拡張 HTML)で使い勝手を改善できます。このページでは次の 4 つのカスタマイズを紹介します。

カスタマイズ使う機能
項目設定欄の高さを拡げる拡張スタイル
項目一覧に物理名を表示する拡張スタイル
計算式入力欄を複数行にする拡張スクリプト + 拡張スタイル
コードエディタにフォーマッターを追加する拡張 HTML + 拡張スクリプト + 拡張スタイル

項目設定欄の高さを拡げる ​

エディタや一覧などのタブにある項目設定欄(項目を選択するリスト)の高さを拡げます。

仕組み ​

項目設定欄には .h250 クラスが付いており、高さは 250px です。

css
.h250 {
    height: 250px;
}

site.css には高さ指定用のクラスが .h100 から .h600 まで 50px 刻みで用意されていますが、どのクラスを付けるかはサーバ側のプログラムでハードコードされているため変更できません(例: エディタタブの項目設定欄は controlWrapperCss: " h250" 固定。SiteUtilities.cs#L7685-L7688)。確認したソースでは、これらのクラスは legacy.scss#L3392-L3434 に定義されています。そこで、拡張スタイルで CSS を上書きします。

設定 ​

拡張スタイルとして次の CSS を配置します。

css
[id$="ColumnsWrapper"] {
    height: 500px !important;
}
  • 項目設定欄の ID はタブごとに異なりますが、いずれも ColumnsWrapper で終わる命名規則なので、後方一致セレクタで一括指定しています。
  • 500px は標準の倍の値です。環境に合わせて調整してください。

高さを 500px に拡げたエディタの項目設定欄

項目一覧に物理名を表示する ​

項目設定欄のリストには、表示名(「親テーブル」など)だけが表示され、ClassA のような物理名は詳細画面を開かないと分かりません。リンクやスクリプトを設定するときにすぐ物理名を確認できるよう、表示名の後ろに物理名を表示します。

仕組み ​

リストの各項目は次のような li 要素で、data-value 属性に物理名が入っています。

html
<li
    class="ui-widget-content ui-selectee"
    title="分類A"
    data-order="8"
    data-value="ClassA">
        [記録テーブル(子テーブル)] 親テーブル
</li>

CSS の attr() 関数と疑似要素 ::after を組み合わせて、この値を表示します。

設定 ​

拡張スタイルとして次の CSS を配置します。

css
[id$="ColumnsWrapper"] ol li::after {
    content: " (" attr(data-value) ")";
    color: gray;
}

項目一覧の各項目の後ろに (IssueId) のような物理名が表示された様子

計算式入力欄を複数行にする ​

管理画面の「計算式」タブの計算式入力欄は単一行のテキストボックスなので、拡張計算式のように長い処理を書くと見渡しにくくなります。拡張スクリプトと拡張スタイルで、計算方法が「拡張」のときだけ入力欄を複数行(textarea)に切り替えます。

INFO

バージョン 1.5.7.0 を対象にしています。

仕組み ​

計算式の設定ダイアログは SiteUtilities.FormulaDialog で生成されており、計算式・条件外の計算式はどちらも FieldTextBox(最終的に <input type="text">)です。CSS で高さを広げても input では改行を入力できないため、ダイアログを開いたタイミングで要素を textarea に置き換えます。

図を読み込み中…

  • 計算式欄には always-send クラスが付いています。プリザンターは送信時に .always-send を持つコントロールを走査して $p.setData で値を収集します(_data.js)。
  • そのため、元の id・class・data-* 属性を textarea に引き継げば、保存処理を追加実装する必要はありません。

対象の入力欄は次の 2 つです。

ID内容
#Formula条件に一致した場合の計算式
#FormulaOutOfCondition条件に一致しなかった場合の計算式

設定 ​

次の 2 ファイルを配置し、プリザンターを再起動して拡張機能を読み込みます。

ファイル配置先役割
FormulaMultiline.jsApp_Data/Parameters/ExtendedScripts/input を textarea へ置換
FormulaMultiline.cssApp_Data/Parameters/ExtendedStyles/高さ・リサイズなどの見た目を調整
js
$(function () {
    $(document).on('dialogopen', function (e) {
        if (e.target.id !== 'FormulaDialog') return;

        updateFormulaControls();
    });

    $(document).on('change', '#FormulaCalculationMethod', function () {
        updateFormulaControls();
    });

    function updateFormulaControls() {
        var tagName = $('#FormulaCalculationMethod').val() === 'Extended'
            ? 'textarea'
            : 'input';

        $('#FormulaDialog #Formula, #FormulaDialog #FormulaOutOfCondition')
            .each(function () {
                replaceControl(this, tagName);
            });
    }

    function replaceControl(control, tagName) {
        if (control.tagName.toLowerCase() === tagName) return;

        var replacement = document.createElement(tagName);

        Array.prototype.forEach.call(control.attributes, function (attr) {
            if (attr.name !== 'type' && attr.name !== 'value') {
                replacement.setAttribute(attr.name, attr.value);
            }
        });

        replacement.value = control.value;
        if (tagName === 'textarea') {
            replacement.rows = 10;
            replacement.classList.add('formula-multiline');
        } else {
            replacement.type = 'text';
            replacement.classList.remove('formula-multiline');
        }
        control.replaceWith(replacement);
    }
});
css
#FormulaDialog .formula-multiline {
    box-sizing: border-box;
    width: 100%;
    min-height: 12rem;
    resize: vertical;
    overflow-x: auto;
    overflow-wrap: normal;
    white-space: pre;
    line-height: 1.5;
    font-family: Consolas, "Courier New", monospace;
    tab-size: 4;
}

スクリプトのポイントは次のとおりです。

  • 計算式ダイアログはサーバから内容を動的に取得して表示するため、ページ読み込み時ではなく jQuery UI の dialogopen イベントで置換します。
  • #FormulaCalculationMethod の変更も監視し、「拡張」なら textarea、「通常」なら input に切り替えます。
  • type と value 以外の属性を複製するので、入力必須の検証属性や always-send クラスも維持されます。
  • 既に目的の要素になっている場合は何もしないため、ダイアログを繰り返し開いても要素は二重に生成されません。

スタイルは resize: vertical で下端をドラッグして高さを変えられるようにし、white-space: pre と overflow-wrap: normal で長い行を折り返さず横スクロールで表示します。

動作確認 ​

サイトの管理画面で「計算式」タブを開き、「新規」または既存の計算式を選択します。計算方法を「拡張」にすると計算式欄が複数行になり、Enter キーで改行できます。「通常」に戻すと単一行に戻ります。

計算方法「拡張」で複数行の入力欄になった計算式ダイアログ

js
(function () {
    const unitPrice = model.NumA || 0;
    const quantity = model.NumB || 0;
    const discountRate = model.NumC || 0;

    return unitPrice * quantity * (1 - discountRate);
})()

通常計算式を対象外にしている理由 ​

計算方法表示改行を含む式の保存
通常単一行非対応
拡張複数行対応
  • 通常計算式は保存時に FormulaBuilder.Parts で文字列を半角スペースで分割し、各要素を Trim して Formula オブジェクトに変換します(FormulaBuilder.cs)。改行は区切りとして扱われないため、改行位置によっては演算子と項目名が同じ要素に入って無効な式になります。保存できた場合も、再度開くと Formula.ToString で組み立て直された 1 行の式が表示されます。
  • 拡張計算式は入力文字列をそのまま FormulaScript に保存するため(FormulaBuilder.cs)、改行が保存後も維持されます。

カスタマイズ ​

初期表示の高さを変えるには、スクリプトの rows と CSS の min-height を変更します。

diff
-            replacement.rows = 10;
+            replacement.rows = 16;
diff
-    min-height: 12rem;
+    min-height: 20rem;

長い行を横スクロールではなく入力欄の幅で折り返すには、CSS を次のように変更します。

diff
-    overflow-wrap: normal;
-    white-space: pre;
+    overflow-wrap: anywhere;
+    white-space: pre-wrap;

コードエディタにフォーマッターを追加する ​

管理画面のスクリプト・サーバスクリプト・スタイルの編集ダイアログにフォーマット(自動整形)ボタンを追加し、JavaScript と CSS のコードをワンクリックで整形できるようにします。整形には外部ライブラリの js-beautify を CDN から読み込んで使います。

スクリプトの編集ダイアログに追加された Format ボタンと整形後のコード

仕組み ​

v2 テーマで EnableCodeEditor が有効な場合、スクリプト・サーバスクリプト・スタイルの編集欄は <code-editor> カスタム要素で描画され、内部では CodeMirror 6 が Shadow DOM 内で動いています(codeEditor.ts)。

text
<div class="field-wide">
  <p class="field-label">
    <label for="ScriptBody">スクリプト</label>
  </p>
  <div class="field-control">
    <div class="container-normal">
      <code-editor>
        <textarea id="ScriptBody" class="control-codeeditor" data-lang="javascript">
          ...コード...
        </textarea>
      </code-editor>
    </div>
  </div>
</div>

項目を囲む div のクラスは field-wide だけで、ほかの画面の項目に付く field-normal は付きません。スクリプト・サーバスクリプト・スタイルの欄は fieldCss: "field-wide" で出力され(SiteUtilities.cs#L17046-L17053)、先頭に空白の無い fieldCss は既定の field-normal を置き換えるためです(HtmlFields.cs#L1188-L1194、Css.cs#L9-L26)。そのため、拡張スクリプトでは .field-normal, .field-wide の両方で項目を探します。

EnableCodeEditor が無効な場合は <code-editor> がなく、通常の textarea が直接描画されます。ここで紹介する実装はどちらでも動きます。

ダイアログテキストエリア IDdata-langフォーマッター
#ScriptDialogScriptBodyjavascriptjs_beautify
#ServerScriptDialogServerScriptBodyjavascriptjs_beautify
#StyleDialogStyleBodycsscss_beautify

図を読み込み中…

設定 ​

拡張機能ファイル役割
拡張 HTMLHtmlHeaderBottom.htmlCDN から js-beautify を読み込む
拡張スタイルApp_Data/Parameters/ExtendedStyles/AdminCodeFormatter.cssフォーマットボタンの見た目
拡張スクリプトApp_Data/Parameters/ExtendedScripts/AdminCodeFormatter.jsボタンの追加と整形処理

拡張 HTML の HtmlHeaderBottom.html で jsDelivr からライブラリを読み込みます(CDN の使い方は CDN のライブラリを使う を参照)。

html
<script src="https://cdn.jsdelivr.net/npm/js-beautify@1.15.1/js/lib/beautify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/js-beautify@1.15.1/js/lib/beautify-css.min.js"></script>

ボタンは、説明項目の左下にあるメディアコントロール(.bottom-tools)のスタイルに合わせ、コードエディタの左下に配置します。

css
/* --- フォーマットボタンコンテナ --- */
.fmt-tools {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

/* --- ボタンスタイル --- */
.fmt-tools .fmt-btn {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 0;
  margin: 0;
  background-color: transparent;
  border: 0;
  color: var(--nonColor07, #666);
  cursor: pointer;
  outline: 0;
  font-size: 12px;
}

.fmt-tools .fmt-btn:hover {
  color: var(--nonColor04, #3c3c3c);
}

.fmt-tools .fmt-btn .fmt-btn-icon {
  padding: 0;
  margin: 0;
  font-size: 18px;
  font-variation-settings:
    "FILL" 1,
    "wght" 400,
    "GRAD" 0,
    "opsz" 20;
}
  • .fmt-tools は説明項目の .bottom-tools と同じ display: flex; gap: 8px; margin-top: 4px; のレイアウトです。
  • ボタンは .md-btn と同様の透明背景・ボーダーなしのアイコンボタンで、Material Symbols のアイコンには .md-btn-icon と同じ font-variation-settings を適用しています。
  • テーマの CSS 変数(--nonColor07 など)を使っているので、どのテーマでもなじみます。
ExtendedScripts/AdminCodeFormatter.js(全文)
js
$(function () {
  var DIALOGS = '#ScriptDialog, #ServerScriptDialog, #StyleDialog';
  if (!$(DIALOGS).length) return;

  $(document).on('dialogopen', function (e) {
    var $dlg = $(e.target);
    if (!$dlg.is(DIALOGS)) return;
    addFormatButton($dlg);
  });

  function addFormatButton($dialog) {
    var $textarea = $dialog.find('textarea[data-lang]');
    if (!$textarea.length) return;

    // スクリプト等の欄は field-wide だけで field-normal が付かない
    var $field = $textarea.closest('.field-normal, .field-wide');
    if ($field.find('.fmt-tools').length) return;

    var $tools = $('<div>', { class: 'fmt-tools' });
    var $btn = $('<button>', {
      type: 'button',
      class: 'fmt-btn',
      title: 'コードを整形'
    }).append(
      $('<span>', {
        class: 'fmt-btn-icon material-symbols-outlined',
        text: 'code'
      }),
      $('<span>', { text: 'Format' })
    );

    $btn.on('click', function () {
      formatCode($textarea);
    });

    $tools.append($btn);
    $field.find('.field-control').append($tools);
  }

  function formatCode($textarea) {
    var lang = $textarea.attr('data-lang');
    var code = $textarea.val();
    var opts = {
      indent_size: 4,
      indent_char: ' ',
      eol: '\r\n',
      end_with_newline: false
    };
    var formatted;

    try {
      formatted = lang === 'css'
        ? css_beautify(code, opts)
        : js_beautify(code, opts);
    } catch (e) {
      alert('フォーマットに失敗しました: ' + e.message);
      return;
    }

    var codeEditor = $textarea.closest('code-editor')[0];
    if (codeEditor && codeEditor.editor) {
      var view = codeEditor.editor;
      view.dispatch({
        changes: {
          from: 0,
          to: view.state.doc.length,
          insert: formatted
        }
      });
    } else {
      $textarea.val(formatted);
      $p.set($textarea, formatted);
    }
  }
});

スクリプトのポイントは次のとおりです。

  • 実行条件:#ScriptDialog・#ServerScriptDialog・#StyleDialog が DOM にあるときだけ動きます。これらはテーブルの管理画面でだけ描画されるので、通常のレコード画面では何もしません。
  • ボタンの追加:ダイアログの内容はサーバから動的に取得されるため、jQuery UI の dialogopen イベントで対象ダイアログが開かれたときにボタンを追加します。既に .fmt-tools があれば追加しません。
  • ボタンの位置:.bottom-tools と同じように、コードエディタのフィールドの .field-control の末尾に追加するので、エディタの左下に表示されます。
  • 言語の切替:textarea の data-lang が css なら css_beautify、それ以外は js_beautify で整形します。
  • CodeMirror が有効な場合:<code-editor> 要素の editor プロパティから EditorView を取得し、dispatch() で全体を置き換えます。CodeMirror の変更リスナーが textarea と $p.data を自動で同期するので、追加の更新処理は不要です。
  • CodeMirror が無効な場合:textarea に値を直接セットし、$p.set() で $p.data を更新します。

整形ルール ​

既定のオプションは、プリザンターのリポジトリの .editorconfig に合わせています。

.editorconfig値js-beautify オプション
indent_size4indent_size: 4
indent_stylespaceindent_char: ' '
end_of_linecrlfeol: '\r\n'
insert_final_newlinefalseend_with_newline: false

trim_trailing_whitespace = true は js-beautify の既定の動作と一致するため、オプションの指定は不要です。インデント幅などを変えたい場合は opts を変更します。

diff
-      indent_size: 4,
+      indent_size: 2,

関連ページ ​

変更履歴

第6版記事の確認版を繰り返す表現を整理する
第5版管理画面のレシピにスクリーンショットを追加し、コードフォーマッターが 1.5.8.1 で動くよう修正
第4版画面カスタマイズ集のコードを 1.5.8.1 のソースで検証し、動かなかったサンプルを修正
第3版記事のファイル名に並び順の番号を付け、元記事リンクを frontmatter の sources に移行
第2版ナビゲーション・テーマに統合 FAB・メニューアイコン・確認ゲートなどを追加し、管理画面にコードフォーマッターを追加
第1版「画面カスタマイズ集」セクションの記事を追加