13
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

本記事は、OSSのノーコード・ローコード開発ツール「プリザンター」 Advent Calendar 2022 の8日目の記事です。

前置き

Pleasanterでフォルダ作ってサイトをまとめて移動して、さらにつくって・・・を繰り返した結果、あのサイトどこだっけ?ってなりませんか?なりますよね?そんなときのためのサイトマップを作ってみたいと思います。

作るサイトのイメージ

image.png
使い方は、サイトID(フォルダのID)を指定し、「サイトマップ」ボタンをクリックすることで、説明欄に表示されるというもの。
結果はマークダウン形式にして、リンクを設定します。

仕組み

以前の記事で、サイト情報を拡張SQLで取得する方法を説明しましたが、大枠はこの仕組みの流用です。ただ、今回は階層を掘っていくため関数の再帰呼び出しでフォルダ配下の全てのサイト情報を取得します。

〇ざっくり処理の流れ

  1. サイトIDに紐づく子サイトを拡張SQLで取得
  2. 取得結果をループし、サイト情報を書き出し
  3. ループの中でさらにサイトIDに紐づく子サイトを拡張SQLで取得→2へ(以下再帰)

テーブル設定

サイトIDとサイトマップを表示する項目を追加し、スクリプトを実行するためのボタンをプロセスで設定。
image.png
後述するスクリプトの関数SiteMapを呼び出します。

実装

拡張SQL

SiteMap.json.sql
基本は前回のほぼ同じ。サイトマップ表示用にSiteIDだけでなく、Title、ReferenceTypeも取得するように変更。

SELECT [SiteId],[Title],[ReferenceType]
FROM [Sites]
WHERE [ParentId]=@ParentId

SiteMap.json

{
    "Name": "SiteMap",
    "Api": true
}

拡張SQLのセットになるJSON

スクリプト

ツリー構造を表現するため、再帰呼び出しするたびにインデント(スペースの数)を加味しています。

//プロセスから呼ばれるメイン関数
const SiteMap = async () => {
    $p.set($p.getControl('DescriptionA'), '[md]  \n');
    //最初に親サイトの情報を取得・設定
    let parentSiteData = await ApiGetSite($p.getControl('NumA').val());
    SetSiteName(parentSiteData,0);
    //拡張SQLにより、子サイトを検索
    let res = await GetSites($p.getControl('NumA').val());
    //取得サイトをループ処理
    if(res.Response.Data.Table.length > 0){
        await SetSiteNames(res.Response.Data.Table,1);
        document.getElementById('UpdateCommand').click();
    }    
};

//再帰呼び出しされる関数
const SetSiteNames = async (table,indent) => {
    //サイトマップの階層を表現するためのインデント
    let num = indent;
    for (let data of table) {
        console.log(data.SiteId);
        //サイト名を設定
        SetSiteName(data, num) 
        //さらに子サイトを検索
        let res = await GetSites(data.SiteId);
        if(res.Response.Data.Table.length > 0){
            //インデントを加味した上で再帰呼び出し
            indent++;
            await SetSiteNames(res.Response.Data.Table, indent);
            indent = num;
        }
    }
};

//取得したサイト情報をサイトマップとして整形して説明欄に設定する
const SetSiteName = async (data, indent) => {
    let strIndent = '';
    //サイトマップに表示する文言を成形
    let msg = `${data.SiteId}:${data.Title}:${data.ReferenceType}`
    //設定されたインデント分スペースを設定
    for (let i = 0; i < indent; i ++){
        strIndent = strIndent + ' ';
    }    
    let descA = $p.getControl('DescriptionA').val();
    //マークダウンに設定するURLを生成
    let url = SetURL(data.SiteId);
    //説明欄に追記
    $p.set($p.getControl('DescriptionA'), `${descA}${strIndent}[${msg}](${url})  \n`);
};

//サイトマップに設定するURLを生成
const SetURL = (siteId) => {
    let uri = new URL(window.location.href);    
    let url = `${uri.origin}/items/${siteId}/index`;
    return url   
}

//拡張SQLによる子サイトの検索
const GetSites = async (siteId) => {
    let data = {
        "ApiVersion": 1.1,        
        "Name": "SiteMap",
         "Params": {
            "ParentId": siteId
        }
    }
    let uri = new URL(window.location.href);
    let url = `${uri.origin}/api/extended/sql`;
    let response = await fetch(url, {
        method: 'POST',
        body: JSON.stringify(data),
        headers: {
            'Content-Type': 'application/json'            
            },
    });
    return response.json();
};

//APIによるサイト情報取得
const ApiGetSite = async (siteId) => {
    let res;
    await $p.apiGetSite({
        id: siteId,
        done: function (data) {
            res = data.Response.Data;
        }
    });
    return res;
}

注意点

再帰的にSQLを発行する処理を実行するすため、サイト数が多ければ多いなりにシステムへの性能負荷が高まります。巨大なサイト群で実行したい場合は注意が必要です。

13
1
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
13
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?