オープンソースのWikiであるGROWIにはプラグイン機能が用意されています。自社のデータを表示したり、表示をカスタマイズするのに利用できます。
今回は、GROWIプラグインとしてGoogleスプレッドシートをAPI化するSSSAPIのデータを表示するプラグインを作成しました。業務システムでGoogleスプレッドシートを利用している企業は多いので、そのデータをGROWI内で表示できます。
プラグインの動作
Remark Directiveとして、以下のように記述します。 []
内には、SSSAPIのURLを記述します。
::sssapi[https://api.sssapi.app/ID]
オプションとして、 show
を使って一覧表示に利用するカラムを指定できます。カラム名は、SSSAPIのデータに合わせてください。
::sssapi[https://api.sssapi.app/ID]{show=id,title,date}
各行をクリックすると、テーブルの下に詳細データを表示します。ここではすべてのフィールドが表示対象になります。
プラグインを追加する
利用する際には、GROWIの管理画面の プラグイン
にて追加してください。URLは https://github.com/goofmint/growi-plugin-sssapi
です。
コードについて
コードはgoofmint/growi-plugin-sssapi: GROWI plugin integrated with SSSAPIにて公開しています。ライセンスはMIT Licenseになります。
最初に ::sssapi
というRemark Directiveを処理します。この記述があれば、 a
タグに変換します。また、 sssapi = true
を追加して、他の a
タグとの区別をつけています。
vist
メソッドで、RemarkのAST leafDirective
を処理します。2つ目の引数を指定すると、そのディレクティブの場合のみ呼び出されるので便利です。 leafDirective
は、行頭で ::
から始まるディレクティブです。
export const remarkPlugin: Plugin = () => {
return (tree: Node) => {
// ::plugin[xxx]{hello=growi} -> leafDirective
visit(tree, 'leafDirective', (node: Node) => {
const n = node as unknown as GrowiNode;
if (n.name !== 'sssapi') return;
const data = n.data || (n.data = {});
// Render your component
const { url } = n.children[0] || { url: '' };
data.hName = 'a'; // Tag name
data.hChildren = []; // Children
// Set properties
data.hProperties = {
href: url,
title: JSON.stringify({ ...n.attributes, ...{ sssapi: true } }), // Pass to attributes to the component
};
});
};
};
外部データを取得して表示
GROWI 7.2から、React Hooksに対応しました。今回のプラグインではそれを使ってSSSAPIからデータを取得し、表示に反映しています。
export const helloGROWI = (Tag: React.FunctionComponent<any>): React.FunctionComponent<any> => {
return ({ children, ...props }) => {
try {
const { react } = growiFacade;
const { useEffect, useState } = react;
// 外部データを取得して適用するためのstate
const [rows, setRows] = useState<{[key: string]: string}[]>([]);
// ヘッダー情報
const [headers, setHeaders] = useState<string[]>([]);
// 行をクリックした際に表示する詳細情報
const [detail, setDetail] = useState<{[key: string]: string} | null>(null);
// SSSAPIからデータを取得する
const getData = async(url: string) => {
const response = await fetch(url);
const json = await response.json();
setRows(json);
setHeaders(Object.keys(json[0] || {}));
};
const { sssapi, show } = JSON.parse(props.title);
// sssapiがtrueの場合のみ処理を行う
if (sssapi) {
const { href } = props;
// データの取得
useEffect(() => {
getData(href);
}, [href]);
// 表示するフィールド(オプション)
const displayFields = show ? show.split(',') : [];
return (
{ /* 表示処理 */}
);
}
}
catch (err) {
// console.error(err);
}
// Return the original component if an error occurs
return (
<Tag {...props}>{children}</Tag>
);
};
};
表示処理
表示についてはReactで表示し、行のクリックで detail
にデータを入れているだけです。
return (
<>
<table className='table'>
<thead>
<tr>
{headers.map(header => (
(displayFields.length > 0 && !displayFields.includes(header)) ? null
: <th key={header}>{header}</th>
))}
</tr>
</thead>
<tbody>
{rows.map((row, rowIndex) => (
<tr
key={rowIndex}
onClick={() => setDetail(row)}
>
{headers.map(header => (
(displayFields.length > 0 && !displayFields.includes(header)) ? null
: <td key={header}>{row[header]}</td>
))}
</tr>
))}
</tbody>
</table>
{detail && (
<div>
<ul>
{Object.entries(detail).map(([key, value]) => (
<li key={key}>{key}:<br />
{value}
</li>
))}
</ul>
</div>
)}
</>
);
GROWIコミュニティについて
プラグインの使い方や要望などがあれば、ぜひGROWIコミュニティにお寄せください。実現できそうなものがあれば、なるべく対応します。他にもヘルプチャンネルなどもありますので、ぜひ参加してください!
まとめ
GROWIプラグインを使うと、表示を自由に拡張できます。足りない機能があれば、どんどん追加できます。ぜひ、自分のWikiをカスタマイズしましょう。