1
0

本記事はQmonus Value Streamの投稿キャンペーン記事です。

はじめに

個人開発でアプリのコードを書くのはまあ良いとしても、管理のために必要なCRUD処理のコードを書くのは結構億劫だし、価値も生み出せているとは言えないのでやりたくない作業の1つだと思う。

そこで今回は、AdminJSを利用してサクッと管理画面の開発をしたいと思う。また、カスタムのコンポーネントを作成してそれを適用するという事もやってみようと思う。

AdminJSで管理画面をサクッと開発

今回はMySQLをデータベースとして利用しているアプリの管理画面を開発する。アプリの方ではORMを利用していないが、管理画面の開発ではPrismaを利用する(AdminJSのアダプターにPrisnaがあること、DDLから簡単にPrisma schemaを作成できること、の2点でそうすることにした)。

prisma schemaの作成

まずはprisma schemaを作成する。

npx prisma initprisma/schema.prisma.envが作成される。.envを以下のように書き換えてMySQLの接続情報を設定する。

.env
DATABASE_URL="mysql://root:@localhost:3306/sample_db"

続いて現在のDDLに基づいて、prisma schemaを以下のコマンドで作成し、prisma clientを作成する。

$ npx prisma db pull
$ npx prisma generate

これでPrismaの事前準備は完了。

AdminJSをExpressサーバーに導入する

今回はNode.jsのExpressサーバーを管理画面のサーバーとすることにしたので、AdminJSのExpress用のプラグインを利用してAdminJSの設定をする。

src/app.js
import AdminJS from 'adminjs';
import AdminJSExpress from '@adminjs/express';
import express from 'express';
import { Database, Resource, getModelByName } from '@adminjs/prisma';
import { PrismaClient } from '@prisma/client';

const PORT = 3080;
const prisma = new PrismaClient();
AdminJS.registerAdapter({ Database, Resource });

const start = async () => {
	const app = express();

	const adminOptions = {
		resources: [
			{
				resource: { model: getModelByName('users'), client: prisma },
				options: {}
			},
			{
				resource: { model: getModelByName('todos'), client: prisma },
				options: {}
			},
			...
		]
	};
	const admin = new AdminJS(adminOptions);

	const adminRouter = AdminJSExpress.buildRouter(admin);
	app.use(admin.options.rootPath, adminRouter);

	app.listen(PORT, () => {
		console.log(`AdminJS started on http://localhost:${PORT}${admin.options.rootPath}`);
	});
};

await start();

上記のコードの内、adminOptionsの部分などはprismaのアダプター用の設定で、それ以外はexpressのプラグインの設定になる。詳細は以下の参考に書かれている通り。

ここまで設定すると、以下の画像のようにCRUDを行る管理画面が立ち上がるようになる。
image.png

あとは画面にある各種ボタンからCRUDを行って管理する感じになる。

ここまでAdminJSでの管理画面の開発は完了になる。続けて、カスタムコンポーネントとCSSスタイルの上書きをやってみたいと思う。

カスタムコンポーネントを適用する

AdminJSではReactコンポーネントを独自に実装することで、カスタムコンポーネントとして適用できる。

AdminJSのデフォルトの入力項目の実装は、HTMLのinputタグで改行ができない。今回はこれをテキストアリアに変えることで改行も入力できるようにしてみる。

まずはReactのコンポーネントを実装する必要があるが、ReactがわからなくてもChatGPT等の生成AIに頼めば以下のようなコードは簡単に生成してくれるので、それを利用すればReactわからん!という状態でもなんとかなるだろう(管理画面の作りこみをしたいわけではないので)。

src/adminjs/components/TextareaEdit.tsx
import React from 'react';
import { BasePropertyProps } from 'adminjs';

const TextareaEdit: React.FC<BasePropertyProps> = (props) => {
	const { record, property, onChange } = props;

	return (
		<div className="mb-4">
			<label className="block text-sm mb-2">{property.label}</label>
			<textarea
				className="mt-1 block w-full p-2 border border-gray-300 rounded-md shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
				rows={5}
				value={record.params[property.path] || ''}
				onChange={(e) => onChange(property.path, e.target.value)}
			/>
		</div>
	);
};

export default TextareaEdit;

続いてこのコンポーネントをAdminJSに適用するための設定を実装するが、以下のようなComponentLoaderで読み込んだコンポーネントのオブジェクトを作成し、それをexportしておき、それを適用したいresourceのオプションで設定する。

src/adminjs/components.js
import { ComponentLoader } from 'adminjs';

const componentLoader = new ComponentLoader();

const Components = {
	TextareaEdit: componentLoader.add('TextareaEdit', './components/TextareaEdit')
};

export { componentLoader, Components };
src/app.js
import AdminJS from 'adminjs';
import AdminJSExpress from '@adminjs/express';
import express from 'express';
import { Database, Resource, getModelByName } from '@adminjs/prisma';
import { PrismaClient } from '@prisma/client';
import { Components, componentLoader } from './adminjs/components.js';

const PORT = 3080;
const prisma = new PrismaClient();
AdminJS.registerAdapter({ Database, Resource });

const start = async () => {
	const app = express();

	const adminOptions = {
		resources: [
			{
				resource: { model: getModelByName('users'), client: prisma },
				options: {
					properties: {
						name: {
							type: 'string',
							components: {
								edit: Components.TextareaEdit,  // <- ここに設定する							
                            }
						}
					}
				}
			},
            ...
		],
		componentLoader,
	};
	const admin = new AdminJS(adminOptions);

	const adminRouter = AdminJSExpress.buildRouter(admin);
	app.use(admin.options.rootPath, adminRouter);

	app.listen(PORT, () => {
		console.log(`AdminJS started on http://localhost:${PORT}${admin.options.rootPath}`);
	});
};

await start();

上記のような設定をすると、以下のようにカスタムコンポーネントが適用されて、inputではなくtextareaになることが確認できる。
image.png

上記はTailwind CSSが適用されてそのスタイルに装飾されているが、それについては次の項で見ていく。

Tailwind CSSを適用する

カスタムコンポーネントを適用するで見たように、適用したコンポーネントにはTailwind CSSのスタイルが適用されていた。これはAdminJSのassetsでスタイルを指定することで実現できる。

src/app.js
...
import * as url from 'url';
import path from 'path';

const PORT = 3000;
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));

const prisma = new PrismaClient();
AdminJS.registerAdapter({ Database, Resource });

const start = async () => {
	const app = express();

	const adminOptions = {
		resources: [
			{
				...
			},
            ...
		],
		componentLoader,
		assets: {
			styles: ['/tailwind.css']
		}
	};
	const admin = new AdminJS(adminOptions);

	const adminRouter = AdminJSExpress.buildRouter(admin);
	app.use(admin.options.rootPath, adminRouter);
	app.use(express.static(path.join(__dirname, '../public')));

	app.listen(PORT, () => {
		console.log(`AdminJS started on http://localhost:${PORT}${admin.options.rootPath}`);
	});
};

await start();

実装としては、上記のようにadminOptionsassetsの設定を行い、assets.stylesで指定したCSSファイルがExpressのstaticの機能で配信されるようにすればよい。今回は./publicディレクトリをstaticの対象にしているので、./public/tailwind.cssというCSSがAdminJSのスタイルとして追加で設定されるようになる。

ところで./public/tailwind.cssを作成する方法だが、Get started with Tailwind CSSに書かれている方法を利用する。
つまり、contentにTailwind CSSを利用しているファイルのパスを指定して、

$ npx tailwindcss -i ./src/styles/tailwind.css -o ./public/tailwind.css --watch

というコマンドを実行すれば作成できる。

tailwind.config.js
export default {
	content: [
		'./src/adminjs/components/**/*.tsx'
	],
	theme: {
		extend: {}
	},
	plugins: []
};
src/styles/tailwind.css
@tailwind base;
@tailwind components;
@tailwind utilities;

まとめとして

今回はAdminJSを利用してサクッと管理画面を開発する方法を見てきた。また、カスタムコンポーネントを適用し、カスタムコンポーネントを実装する際にTailwind CSSを利用できるようにする方法もみてきた。
ほんの30分程度で管理画面を作成してやりたいことができるようになったので、管理画面が必要になった時には今後もAdminJSを利用していきたいと思った。

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