1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

プリザンターの一覧画面を「一定時間ごとに更新したい」という要望はよくあります。今回は本体コードを変更せず拡張フィールド拡張スクリプトだけで自動リロードを実装します。

要件は次の 3 点です。

  • 一覧画面を一定間隔で更新する
  • 画面全体の再遷移ではなく Ajax 更新にする
  • 既存のローディング表示を使い回しつつ、更新中メッセージも出す

実装方針

  • 更新処理は $p.send() を使って一覧の GridRows を再取得する
    • プリザンター標準の Ajax 経路を通るため、既存のローディング表示がそのまま使える
  • 拡張フィールドで「ON/OFF」と「更新間隔(秒)」を持つ
  • 拡張スクリプトでタイマー実行・排他制御・メッセージ表示を行う

拡張フィールドの準備

対象テーブルに次の 2 項目を作成します(名前は例です)。

  • CheckRefreshTimer: 自動更新 ON/OFF
  • NumRefreshSpan: 更新間隔(秒)

App_Data/Parameters/ExtendedFields/ に、次の設定ファイルを配置します。

App_Data/Parameters/ExtendedFields/CheckRefreshTimer.json
{
  "Name": "CheckRefreshTimer",
  "FieldType": "Filter",
  "TypeName": "bit",
  "LabelText": "自動更新ON/OFF"
}

"FieldType": "Filter" を指定すると、一覧画面のフィルター領域(#ViewFilters)に表示されます。

App_Data/Parameters/ExtendedFields/NumRefreshSpan.json
{
  "Name": "NumRefreshSpan",
  "FieldType": "Filter",
  "TypeName": "decimal",
  "LabelText": "更新間隔(秒)",
  "DefaultInput": 30
}

設定ファイルを追加・変更したら、まずプリザンターの管理者権限ユーザーでログインした状態で、ブラウザから次のURLにアクセスして反映します。
ベースパスの有無は環境依存です。

  • ベースパスなし: https://{ドメイン}/admins/reloadparameters
  • ベースパスあり: https://{ドメイン}/{ベースパス}/admins/reloadparameters(例: https://example.com/pleasanter/admins/reloadparameters

未ログイン状態や管理者権限のないユーザーでアクセスしても反映できません。

"FieldType": "Filter" の項目は、一覧画面のフィルター領域に自動表示されます。必要に応じて対象テーブルの「エディタ > 一覧」で表示順を調整してください。

サンプルでは CheckRefreshTimerNumRefreshSpan を使います。環境で物理名が違う場合は、後述スクリプトのセレクタを読み替えてください。

拡張スクリプト

App_Data/Parameters/ExtendedScripts/ に以下を配置します。

ExtendedScripts/ListAutoReload.js
(function () {
  'use strict';

  // ===== 設定 =====
  var MIN_SEC = 10;
  var MAX_SEC = 3600;
  var DEFAULT_SEC = 60;
  var CHECK_SELECTOR = '#CheckRefreshTimer'; // 自動更新ON/OFF(拡張フィールド)
  var INTERVAL_SELECTOR = '#NumRefreshSpan'; // 更新間隔秒(拡張フィールド)
  var MESSAGE_TARGET = '#Message';
  var GRID_TRIGGER_SELECTOR = '[data-action="GridRows"][data-method="post"]';

  // 一覧画面以外では何もしない
  if (!$('#Grid').length) return;

  var timerId = null;
  var busy = false;

  // 既存 Ajax と干渉しないための簡易排他
  $(document)
    .off('.autoReloadBusy')
    .on('ajaxStart.autoReloadBusy', function () {
      busy = true;
    })
    .on('ajaxStop.autoReloadBusy', function () {
      busy = false;
    });

  function toInt(value, fallback) {
    var n = parseInt(value, 10);
    return Number.isFinite(n) ? n : fallback;
  }

  function getEnabled() {
    var $check = $(CHECK_SELECTOR);
    if (!$check.length) return false;
    return $check.prop('checked') || $check.val() === '1' || $check.val() === 'true';
  }

  function getIntervalSec() {
    var $interval = $(INTERVAL_SELECTOR);
    var sec = toInt($interval.val(), DEFAULT_SEC);
    if (sec < MIN_SEC) sec = MIN_SEC;
    if (sec > MAX_SEC) sec = MAX_SEC;
    return sec;
  }

  function setInfo(text) {
    if (!$p || typeof $p.setMessage !== 'function') return;
    $p.clearMessage();
    $p.setMessage(
      MESSAGE_TARGET,
      JSON.stringify({
        Css: 'alert-information',
        Text: text
      })
    );
  }

  function reloadGridByAjax() {
    if (busy) return;
    if (!getEnabled()) return;
    // タブが非表示の間は不要な負荷を避けるため更新しない
    if (document.hidden) return;

    var $trigger = $(GRID_TRIGGER_SELECTOR).first();
    if (!$trigger.length) {
      setInfo('自動更新対象(GridRows)が見つからないため更新をスキップしました');
      return;
    }

    setInfo('一覧を更新中...');

    // プリザンター標準の Ajax 送信を使う
    // 既存のローディング表示がそのまま表示される
    $p.send($trigger);
  }

  function restartTimer() {
    if (timerId) {
      clearInterval(timerId);
      timerId = null;
    }
    if (!getEnabled()) return;

    var intervalMs = getIntervalSec() * 1000;
    timerId = setInterval(reloadGridByAjax, intervalMs);
  }

  // 初期化
  restartTimer();

  // 設定変更時にタイマーを再起動
  $(document)
    .off('change.autoReload', CHECK_SELECTOR)
    .off('change.autoReload', INTERVAL_SELECTOR)
    .on('change.autoReload', CHECK_SELECTOR + ',' + INTERVAL_SELECTOR, function () {
      restartTimer();
    });

  // タブ復帰時に取りこぼし防止
  $(document)
    .off('visibilitychange.autoReload')
    .on('visibilitychange.autoReload', function () {
      if (!document.hidden) {
        reloadGridByAjax();
      }
    });
})();

設定ポイント

  • 実行タイミングは「画面表示の後」に設定する
  • 適用対象は対象テーブルの一覧画面に限定する
  • CheckRefreshTimer が OFF のときはタイマーを停止する
  • 間隔は 10 秒未満にしない(過負荷防止)

拡張スクリプトの設定は、プリザンターの「管理 > 開発者向け機能 > 拡張スクリプト」から行います。

自動更新対象(GridRows)が見つからない と表示される場合は、次を確認してください。

  • 対象画面が一覧画面か(#Grid がある画面か)
  • GridRows の送信トリガー要素がカスタマイズで変更されていないか
  • CHECK_SELECTOR / INTERVAL_SELECTOR が実環境の物理名に合っているか

動作イメージ

  1. CheckRefreshTimer を ON にする
  2. NumRefreshSpan に 30 を設定する
  3. 30 秒ごとに $p.send()GridRows を Ajax 取得
  4. 更新中は標準ローディング + メッセージ領域に「一覧を更新中...」を表示

まとめ

拡張フィールドと拡張スクリプトだけで、一覧画面の定期リロードを実装できました。

  • 本体コードは未変更
  • 更新は Ajax で実行
  • ローディングは標準表示を再利用
  • 「更新中」メッセージも標準メッセージ領域で表示

まずは 30〜60 秒程度から始め、利用者数やテーブル件数に合わせて間隔を調整すると運用しやすくなります。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?