$p.apiDeleteSite
概要¶
AjaxのPOSTリクエストにより、サイトを削除します。
構文¶
JavaScript¶
各パラメータの説明¶
| パラメータ名 | 説明 | 必須 |
|---|---|---|
| id | 削除対象のサイトID | ○ |
| done | API通信成功 | ○ |
| fail | API通信失敗 | - |
| always | 完了時 | - |
使用例¶
JavaScript¶
$p.apiDeleteSite({
id: 123,
done: function (data) {
console.log(data);
console.log('サイト情報の削除に成功しました。');
},
fail: function () {
console.log('サイト情報の削除に失敗しました。');
},
always: function () {
console.log('サイト情報の削除が完了しました。');
}
});
サンプルコード¶
Note
コード内の【 ... 】は適宜修正してください。
1. サイト廃止申請のレコードから、確認のうえサイトを削除する
使わなくなったサイトの削除を、「サイト廃止申請」テーブルで受け付けます。申請者が対象のサイトIDと廃止理由を入力し、プロセス「対象確認」を押すと、$p.apiGetSiteで対象サイトのタイトル・種別・親フォルダIDを取得してレコードに記録します。承認のあと、テナント管理者がプロセス「削除実行」を押すと、もう一度$p.apiGetSiteで取得して記録と一致することを確かめてから$p.apiDeleteSiteでサイトを削除し、削除日時を記録します。
実務での使いどころ¶
現場の利用者がテーブルを作る運用が広がると、使い終わったサイトが削除されずに残りがちです。画面からのサイト削除は、サイトを1つずつ開いてタイトル・ログインID・パスワードを入力して行うもので、廃止の申請や承認とはつながりません。このサンプルを使えば、廃止を申請レコードで受け付け、承認を経てから、そのレコードのボタンで削除まで行えます。誰が、いつ、何のために、どのサイトを削除したかが申請レコードに残ります。
申請者は対象をサイトIDで指定しますが、IDの入力ミスで別のサイトを消してしまうのは避けなければなりません。そこで「対象確認」で対象サイトのタイトルと種別をレコードに記録し、承認者が「何を削除するのか」を目で確かめられるようにします。「削除実行」では削除の直前にもう一度サイトを取得し、確認時の記録と一致しない場合(申請後にサイトが改名された場合など)は削除しません。
$p.apiDeleteSiteは、サイトIDの代わりにレコードのIDを渡してもエラーにならず、そのレコードが属するサイトをまるごと削除します。また、フォルダを削除すると配下のサイトも一緒に削除されます。このサンプルは、削除の前に必ず$p.apiGetSiteで対象を確かめ(レコードのIDには「見つからない」エラーが返ります)、フォルダは受け付けません。
「対象を取得して記録し、実行の直前に一致を確かめてから実行する」という形は、サイトの削除以外の取り消しにくい操作にも応用できます。
事前準備¶
1:テーブルに以下の項目を有効化してください。
| 項目コード | 内容 |
|---|---|
| タイトル(Title) | 件名(例:「旧・備品管理サイトの廃止」) |
| 分類A(ClassA) | 対象サイトID。申請者が入力します |
| 分類B(ClassB) | 対象サイトのタイトル。「対象確認」でスクリプトが記録します |
| 分類C(ClassC) | 対象サイトの種別(Issues/Results/Wikis)。「対象確認」でスクリプトが記録します |
| 数値A(NumA) | 対象サイトの親フォルダのサイトID。「対象確認」でスクリプトが記録します |
| 日付A(DateA) | 削除日時。「削除実行」でスクリプトが記録します。時刻まで表示する書式にします |
| 内容(Body) | 廃止理由 |
| 管理者(Manager) | 承認者 |
| 担当者(Owner) | 申請者 |
| 状況(Status) | 選択肢一覧に「100,下書き」「200,確認済」「300,承認済」「900,削除済」「910,却下」を設定します |
2:「エディタ」タブの「状況による制御」で、状況が「確認済」「承認済」「削除済」「却下」のときに分類A〜分類C・数値Aを読み取り専用にしてください。確認したあとで対象サイトIDや記録を書き換えられないようにするためです。「下書き」では読み取り専用にしないでください(スクリプトが記録した値を保存できなくなります)。同じ理由で、日付A(削除日時)は「承認済」のときに読み取り専用にしないでください。
3:「テーブルの管理 > プロセス」タブで、以下のプロセスを追加します。いずれも、画面種別は「編集」、実行種別は「追加したボタン」、アクション種別は「保存」にします。
| 名称 | 現在の状況 | 変更後の状況 | OnClick | アクセス制御 |
|---|---|---|---|---|
| 対象確認 | 下書き | 確認済 | confirmTargetSite($(this)) | (指定しない) |
| 承認 | 確認済 | 承認済 | (なし) | 承認者 |
| 却下 | 確認済 | 却下 | (なし) | 承認者 |
| 削除実行 | 承認済 | 削除済 | deleteTargetSite($(this)) | テナント管理者 |
「削除実行」の確認ダイアログはスクリプトが出すため、プロセスの「確認メッセージ」は設定しないでください。
4:スクリプトを登録します。
4-1:「テーブルの管理 > スクリプト」タブで「新規作成」を選択する。
4-2:タイトル: 任意の名前(例:サイト廃止申請)
4-3:スクリプト: 下記サンプルコードを貼り付け
4-4:出力先:「編集」にチェック
JavaScript¶
/**
* ================================================================
* サンプル01 サイト廃止申請のレコードから、確認のうえサイトを削除する
* ================================================================
*
* 【概要】
* 使わなくなったサイトの削除を「サイト廃止申請」テーブルで受け付けます。
* 編集画面のプロセスボタンから、次の処理を行います。
* ・対象確認:$p.apiGetSite で対象サイトのタイトル・種別・親フォルダIDを
* 取得してレコードに記録し、状況を「確認済」にする
* (承認者が、何を削除するのかを確かめられるようにする)
* ・削除実行:もう一度 $p.apiGetSite で取得し、記録と一致することを
* 確かめてから $p.apiDeleteSite で削除し、削除日時を記録して
* 状況を「削除済」にする
* 承認・却下は標準のプロセスだけで行い、このスクリプトは関わりません。
*
* 【安全のための確認】
* ・$p.apiDeleteSite にレコードのIDを渡すと、エラーにならず、そのレコードが
* 属するサイトがまるごと削除されます。$p.apiGetSite はレコードのIDに対して
* エラー(404)を返すため、削除の前に必ず $p.apiGetSite で確かめます。
* ・フォルダを削除すると配下のサイトも一緒に削除されるため、フォルダは
* 対象にしません。
* ・申請後にサイトの改名や入れ替わりがあった場合に備え、削除の直前に
* タイトルと種別が記録と一致するかを確かめます。
*
* 【ポイント】
* OnClick を設定したプロセスは、ボタンを押しただけでは保存されません。
* API の呼び出しが成功したあとに $p.set で項目へ値を入れてから
* $p.execProcess を呼ぶと、その値と一緒に保存し、状況を変更します。
* 確認で問題が見つかったときや、API の呼び出しが失敗したときは
* $p.execProcess を呼ばないため、状況は変わりません。
*
* 【使い方】
* 下記の定数を、実際に使用する項目コードに置き換えてください。
* あわせて「テーブルの管理 > プロセス」で、以下のプロセスを追加して
* ください(いずれも 画面種別:編集、実行種別:追加したボタン、
* アクション種別:保存)。
* ・対象確認:現在の状況 下書き → 変更後の状況 確認済
* OnClick:confirmTargetSite($(this))
* ・削除実行:現在の状況 承認済 → 変更後の状況 削除済
* OnClick:deleteTargetSite($(this))
* アクセス制御でテナント管理者だけに表示する
* ================================================================
*/
// ===== 設定 =====
// 対象サイトIDの項目コード(申請者が入力する)
const TARGET_SITE_ID_COLUMN = 'ClassA';
// 対象サイトのタイトルを記録する項目コード
const TARGET_TITLE_COLUMN = 'ClassB';
// 対象サイトの種別(Issues/Results/Wikis)を記録する項目コード
const TARGET_TYPE_COLUMN = 'ClassC';
// 対象サイトの親フォルダのサイトIDを記録する項目コード
const TARGET_PARENT_ID_COLUMN = 'NumA';
// 削除日時を記録する項目コード
const DELETED_AT_COLUMN = 'DateA';
// フォルダの種別
const FOLDER_TYPE = 'Sites';
// ===== 共通処理 =====
function showError(text) {
$p.clearMessage();
$p.setMessage('#Message', JSON.stringify({
Css: 'alert-error',
Text: text,
}));
}
// APIの失敗応答から、表示用のメッセージを取り出す
function getErrorMessage(jqXHR) {
try {
return JSON.parse(jqXHR.responseText).Message;
} catch (e) {
return `HTTP ${jqXHR.status}`;
}
}
// 入力された対象サイトID(数字でなければ null)
function getTargetSiteId() {
const value = String($p.getValue(TARGET_SITE_ID_COLUMN) || '').trim();
return /^\d+$/.test(value) ? Number(value) : null;
}
// 対象サイトを取得する。取得できなかったときはエラーを表示し、onFound を呼ばない
function getTargetSite(siteId, onFound) {
$p.apiGetSite({
id: siteId,
done: function (data) {
// data.Response.Data に SiteId, Title, ReferenceType, ParentId などが入っている
onFound(data.Response.Data);
},
fail: function (jqXHR) {
if (jqXHR.status === 404) {
// レコードのIDや、存在しないサイトIDを指定したときはここに来る
showError(`サイトID ${siteId} のサイトが見つかりません。`);
} else {
showError(`サイトID ${siteId} のサイトを取得できませんでした。${getErrorMessage(jqXHR)}`);
}
},
});
}
function formatNow() {
const now = new Date();
const pad = (n) => String(n).padStart(2, '0');
return `${now.getFullYear()}/${pad(now.getMonth() + 1)}/${pad(now.getDate())} ` +
`${pad(now.getHours())}:${pad(now.getMinutes())}`;
}
// ===== プロセス「対象確認」 =====
function confirmTargetSite($button) {
const siteId = getTargetSiteId();
if (siteId === null) {
showError('対象サイトIDを数字で入力してください。');
return;
}
getTargetSite(siteId, function (site) {
// フォルダは配下のサイトごと削除されるため、対象にしない
if (site.ReferenceType === FOLDER_TYPE) {
showError(`サイトID ${siteId} はフォルダです。フォルダは対象にできません。`);
return;
}
// 取得した内容を記録し、保存して状況を「確認済」にする
$p.set($p.getControl(TARGET_TITLE_COLUMN), site.Title);
$p.set($p.getControl(TARGET_TYPE_COLUMN), site.ReferenceType);
$p.set($p.getControl(TARGET_PARENT_ID_COLUMN), site.ParentId);
$p.execProcess($button);
});
}
// ===== プロセス「削除実行」 =====
function deleteTargetSite($button) {
const siteId = getTargetSiteId();
if (siteId === null) {
showError('対象サイトIDを数字で入力してください。');
return;
}
const recordedTitle = $p.getValue(TARGET_TITLE_COLUMN);
const recordedType = $p.getValue(TARGET_TYPE_COLUMN);
// 削除の直前にもう一度取得し、記録と一致するかを確かめる
getTargetSite(siteId, function (site) {
if (site.ReferenceType === FOLDER_TYPE) {
showError(`サイトID ${siteId} はフォルダです。フォルダは対象にできません。`);
return;
}
if (site.Title !== recordedTitle || site.ReferenceType !== recordedType) {
showError(
`サイトID ${siteId} の現在の内容(タイトル「${site.Title}」、種別 ${site.ReferenceType})が、` +
`確認時の記録(タイトル「${recordedTitle}」、種別 ${recordedType})と一致しないため、削除しません。`,
);
return;
}
if (!confirm(`サイト「${site.Title}」(サイトID:${siteId})を削除します。よろしいですか?`)) {
return;
}
$p.apiDeleteSite({
id: siteId,
done: function () {
// 削除日時を記録し、保存して状況を「削除済」にする
$p.set($p.getControl(DELETED_AT_COLUMN), formatNow());
$p.execProcess($button);
},
fail: function (jqXHR) {
showError(`サイト「${site.Title}」(サイトID:${siteId})を削除できませんでした。${getErrorMessage(jqXHR)}`);
},
});
});
}
「削除実行」は、テナント管理者の利用者に限って押せるようにしてください(サイトを削除するAPIは、テナント管理者でないと実行できません)。
削除したサイトは、親フォルダのごみ箱に入ります。誤って削除した場合は、ごみ箱から復元できます。
対象にできるのはテーブル(期限付きテーブル・記録テーブル・Wiki)のみです。フォルダは配下のサイトごと削除されるため、「対象確認」でも「削除実行」でもエラーにします。フォルダの削除は、配下のサイトを確かめたうえで画面から行ってください。
サイトの削除に成功したあと、レコードの保存が入力チェック(必須項目の未入力など)で止まると、サイトは削除済みなのに状況が「承認済」のまま残ります。この場合はサイトがごみ箱にあることを確認し、レコードの状況を手で直してください。
