Custom Detail Task
Membuat komponen Micro Frontend (MFE) yang tampil sebagai custom Detail View di tab Detail task melalui slot custom_views.DETAILS pada Addon.
Secara default, tab Detail sebuah task menampilkan tampilan bawaan AlurKerja. Bila perlu tampilan kustom — kartu ringkasan, layout multi-kolom, integrasi data eksternal, atau visualisasi — Anda bisa menggantinya dengan komponen React Anda sendiri yang dibungkus sebagai Addon dengan slot custom_views.DETAILS.
Hasil Akhir
Jika Addon Anda mendaftarkan komponen di slot custom_views.DETAILS, AlurKerja akan me-load komponen tersebut di tab Detail seperti berikut.
Tampilan di atas menunjukkan komponen MFE kustom sudah ter-render dan menampilkan data sesuai konteks task.
Konsep
Yang menentukan sebuah view tampil di tab Input atau tab Detail adalah slot tempat ia dideklarasikan di custom_views pada index.json Addon:
| Slot | Tab yang dirender |
|---|---|
custom_views.FORMS | Tab Input (writable form) |
custom_views.DETAILS | Tab Detail (umumnya read-only) |
Klasifikasi ini tidak di-hardcode di Studio — Studio mengiterasi custom_views.DETAILS, lalu mengambil label tampilan dari section details di index.json.
views/src/TaskSummaryView.tsx ← 1. Komponen React (AlurkerjaMfeProps)
│
▼
views/webpack.config.js exposes ← 2. Expose lewat Module Federation
│ './task_summary_view'
▼
index.json custom_views.DETAILS ← 3. Daftarkan: "ticket_summary": "task_summary_view"
index.json details ← 4. Beri label tampilan
│
▼
yarn build → alurkerja addon publish ← 5. Build + publish via CLI
│
▼
Studio → tab Detail ← 6. VerifikasiDetail View bersifat read-only. Komponen di slot DETAILS umumnya hanya membaca data (mis. via form.getValues() atau fetch ke API) lalu menampilkannya — bukan menerima input. Tombol submit/aksi ditangani oleh platform.
Prasyarat
- Node.js & yarn/npm untuk membangun bundle MFE.
- AlurKerja CLI sudah terpasang dan login ke environment target — lihat AlurKerja CLI.
- Project Addon sudah disiapkan (struktur folder Addon +
index.json) — lihat Pembuatan Addon pada AlurKerja.
Step 1 — Buat Komponen Detail View
Buat file komponen di views/src/. Pakai tipe prop AlurkerjaMfeProps (didefinisikan di views/src/type/AlurkerjaType.ts), yang menyediakan:
form— helper React Hook Form:getValues,watch,register,setValue,control.alurkerjaParams— konteks runtime:apiBaseUrl,token,activeTenant,probis,taskId, dst.
Karena ini Detail View, komponen umumnya membaca data lalu menampilkannya (read-only).
File: views/src/TaskSummaryView.tsx
import React, { useEffect, useState } from "react";
import { AlurkerjaMfeProps } from "./type/AlurkerjaType";
export default function TaskSummaryView({ form, alurkerjaParams }: AlurkerjaMfeProps) {
// Baca data yang sudah ada di form (mis. hasil action sebelumnya).
const values = form.getValues?.() ?? {};
const ticket = values?.ticket_summary ?? values?.value ?? {};
const { apiBaseUrl, token, activeTenant, taskId } = alurkerjaParams ?? {};
// (Opsional) ambil detail tambahan dari API.
const [detail, setDetail] = useState<any>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
if (!apiBaseUrl || !ticket?.id) return;
setLoading(true);
fetch(`${apiBaseUrl}/api/tickets/${ticket.id}`, {
headers: {
Authorization: `Bearer ${token}`,
"X-Tenant": activeTenant ?? "",
},
})
.then((r) => r.json())
.then(setDetail)
.catch(() => setDetail(null))
.finally(() => setLoading(false));
}, [apiBaseUrl, token, activeTenant, ticket?.id]);
const priority = detail?.priority ?? ticket?.priority ?? "Normal";
const priorityColor =
priority === "High" ? "bg-red-100 text-red-700" :
priority === "Medium" ? "bg-yellow-100 text-yellow-700" :
"bg-gray-100 text-gray-700";
const row = (label: string, value?: React.ReactNode) => (
<div className="grid grid-cols-[180px_1fr] gap-3 py-2 border-b border-gray-100">
<span className="text-sm text-gray-500">{label}</span>
<span className="text-sm text-gray-900">{value ?? "-"}</span>
</div>
);
return (
<div className="card max-w-4xl mx-auto p-4">
<h2 className="text-2xl font-bold text-gray-900 mb-6">Ringkasan Tiket</h2>
{loading && <p className="text-sm text-gray-500">Memuat detail…</p>}
<div className="bg-white rounded-lg">
{row("Nomor Tiket", detail?.nomor ?? ticket?.nomor)}
{row("Pelapor", detail?.reporter ?? ticket?.reporter)}
{row("Prioritas", (
<span className={`inline-block rounded px-2 py-0.5 text-xs ${priorityColor}`}>
{priority}
</span>
))}
{row("Dibuat", detail?.created_at ?? ticket?.created_at)}
{row("Task ID", taskId)}
</div>
</div>
);
}Pola data: Detail/Action views membaca field langsung (ticket_summary, nomor, dst.). Config views (CREATE/EDIT) memakai prefix value. (mis. value.fileName). Komponen view tidak berisi tombol submit — aksi ditangani oleh platform.
Step 2 — Expose Komponen di Webpack
Tambahkan komponen baru ke exposes pada ModuleFederationPlugin di views/webpack.config.js:
new ModuleFederationPlugin({
name: 'task_summary_view', // ← samakan dengan component_scope di index.json
filename: 'remoteEntry.js',
exposes: {
'./task_summary_view': './src/TaskSummaryView.tsx', // ← samakan dengan custom_views
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
'react-hook-form': { singleton: true },
},
}),Aturan penamaan: key di exposes ('./task_summary_view') harus sama persis dengan nilai yang dipakai di custom_views.DETAILS ("task_summary_view", tanpa ./). Gunakan snake_case, tanpa spasi/karakter khusus.
Step 3 — Daftarkan di custom_views.DETAILS
Edit index.json. Tambahkan entri pada slot DETAILS (key = identifier detail, value = nama komponen yang di-expose):
"custom_views": {
"DETAILS": {
"ticket_summary": "task_summary_view"
}
}Step 4 — Beri Nama Tampilan di Section details
Label yang tampil di tab Detail Studio diambil dari section details (paralel dengan forms / views):
"details": {
"ticket_summary": {
"name": "Ringkasan Tiket",
"description": "Detail view yang menampilkan ringkasan tiket."
}
}Perbedaan Input vs Detail:
- Input — sebuah form wajib ada di
formsdancustom_views.FORMS. - Detail — cukup ada di
custom_views.DETAILS; label diambil daridetails. Sectiondetailsmembuat label lebih rapi, mekanisme tab Detail-nya berpusat padacustom_views.DETAILS.
Potongan index.json yang sudah lengkap untuk bagian ini:
{
"component_scope": "task_summary_view",
"custom_views": {
"DETAILS": {
"ticket_summary": "task_summary_view"
}
},
"details": {
"ticket_summary": {
"name": "Ringkasan Tiket",
"description": "Detail view yang menampilkan ringkasan tiket."
}
}
}Validasi JSON sebelum lanjut:
python3 -c "import json; d=json.load(open('index.json')); print('OK'); print(d['custom_views']['DETAILS']); print(d['details'])"Step 5 — Build & Publish
Karena ada perubahan kode di views/src, wajib rebuild bundle MFE:
cd views
yarn build # atau: npm run build → output ke views/dist
cd ..Lalu publish via AlurKerja CLI (jalankan di terminal interaktif — CLI akan meminta tenant id):
alurkerja addon publishBila perubahan hanya di index.json (Step 3 & 4) tanpa menyentuh kode view, rebuild tidak diperlukan — cukup publish ulang. Karena di sini kita menambah komponen baru (Step 1), build tetap wajib.
Step 6 — Verifikasi
- Buka Addon di Studio, masuk ke task/elemen yang relevan.
- Pindah ke tab Detail (FormTabSwitcher: Input ↔ Detail).
- Komponen
task_summary_viewdi-load via Module Federation dan tampil dengan label "Ringkasan Tiket".
Cek konsistensi cepat
Pastikan setiap komponen yang dirujuk di custom_views benar-benar di-expose:
python3 - <<'PY'
import json, re
d = json.load(open('index.json'))
exposed = set(re.findall(r"\./([A-Za-z0-9_]+)':", open('views/webpack.config.js').read()))
refs = set()
for v in d.get('custom_views', {}).values():
refs.update(v.values() if isinstance(v, dict) else [v])
missing = refs - exposed
print("Exposed:", sorted(exposed))
print("Direferensikan:", sorted(refs))
print("BELUM di-expose:", missing or "tidak ada — semua valid")
PYTroubleshooting
| Gejala | Penyebab & Solusi |
|---|---|
| View tidak muncul di tab Detail | Pastikan entri ada di custom_views.DETAILS (bukan FORMS / VIEWS / CONFIGS). |
| Komponen gagal load / blank | Nilai di custom_views.DETAILS tidak cocok dengan key exposes di webpack. Samakan (tanpa ./). |
| Build gagal | Ada komponen dirujuk di custom_views tapi file/expose-nya belum ada. Lengkapi Step 1 & 2. |
| Perubahan tidak terlihat | Lupa yarn build atau lupa publish ulang via CLI. |
| Label salah/kosong di tab Detail | Tambahkan/rapikan entri di section details. |
Ringkasan Checklist
- Step 1 —
views/src/TaskSummaryView.tsxdibuat (pakaiAlurkerjaMfeProps). - Step 2 — di-expose di
views/webpack.config.jssebagai'./task_summary_view'. - Step 3 — terdaftar di
index.json→custom_views.DETAILS. - Step 4 — label tampilan di
index.json→details. - Step 5 —
yarn buildlalualurkerja addon publish. - Step 6 — komponen muncul di tab Detail Studio.
Lihat Juga
- AlurKerja CLI — setup CLI & publish addon.
- Pembuatan Addon pada AlurKerja — anatomi
index.jsondan slotcustom_viewslain (FORMS / VIEWS / DETAILS / CONFIGS / ACTIONS). - BPMN Adding Form — sisi konfigurasi form di User Task.
