这是indexloc提供的服务,不要输入任何密码
Skip to content

Issue/357 create details page for editing content of a document #389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"editor.codeActionsOnSave": {
"source.organizeImports": "always"
},
// This config make my local change the import path with space in bracket eg: { foo, bar },
// You need to run `npm run codecheck` to reformatting the code.
// So I comment this stuff to prevent reformatting the import code with space in bracket
// "editor.codeActionsOnSave": {
// "source.organizeImports": "always"
// },
"javascript.preferences.quoteStyle": "single",
"typescript.preferences.quoteStyle": "single",
"html.format.indentInnerHtml": true,
Expand Down
16 changes: 16 additions & 0 deletions functions/src/definitions/FieldType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Field type enum
*/
export enum FieldType {
InputText = "input-text",
TextLine = "text-line",
TextboxRich = "textbox-rich",
TextRich = "text-rich",
DatePicker = "datepicker",
Date = "date",
FileUpload = "file-upload",
Switcher = "switcher",
Radio = "radio",
Checkbox = "checkbox",
Dropdown = "dropdown"
}
11 changes: 8 additions & 3 deletions functions/src/models/TanamDocumentField.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import {LocalizedString} from "./LocalizedString";
import {FieldType} from './../definitions/FieldType';
import {LocalizedString, Translations} from "./LocalizedString";

export interface ITanamDocumentField {
weight: number;
title: LocalizedString;
description: LocalizedString;
type: string;
type: FieldType | string;
fieldType: FieldType;
validators: string[] | null;
}

Expand All @@ -21,15 +23,17 @@ export class TanamDocumentField {
constructor(id: string, json: ITanamDocumentField) {
this.id = id;
this.weight = json.weight;
this.title = json.title;
this.title = new LocalizedString(json.title as Translations) ?? json.title;
this.description = json.description;
this.type = json.type;
this.fieldType = json.fieldType;
this.validators = json.validators;
}

public id: string;
public weight: number;
public title: LocalizedString;
public fieldType: FieldType;
public description: LocalizedString;
public readonly type: string;
public readonly validators: string[] | null;
Expand All @@ -43,6 +47,7 @@ export class TanamDocumentField {
return {
weight: this.weight,
title: this.title.toJson(),
fieldType: this.fieldType,
description: this.description.toJson(),
type: this.type,
validators: this.validators,
Expand Down
7 changes: 7 additions & 0 deletions hosting/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions hosting/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@types/node": "^18.19.33",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.3.0",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^7.10.0",
"@typescript-eslint/parser": "^7.10.0",
"autoprefixer": "^10.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,15 @@ import {
TextArea,
} from "@/components/Form";
import Loader from "@/components/common/Loader";
import Notification from "@/components/common/Notification";
import PageHeader from "@/components/common/PageHeader";
import {ErrorPage} from '@/components/Error/ErrorPage';
import {useTanamDocumentFields} from "@/hooks/useTanamDocumentFields";
import {useTanamDocumentType} from "@/hooks/useTanamDocumentTypes";
import {useTanamDocument} from "@/hooks/useTanamDocuments";
import {UserNotification} from "@/models/UserNotification";
import {TanamDocumentField} from "@functions/models/TanamDocumentField";
import {Timestamp} from "firebase/firestore";
import {useParams, useRouter} from "next/navigation";
import {Suspense, useEffect, useState} from "react";
import {Suspense, useState} from "react";

const DocumentDetailsPage = () => {
const router = useRouter();
Expand All @@ -31,17 +30,12 @@ const DocumentDetailsPage = () => {
const {data: documentFields, error: fieldsError} = useTanamDocumentFields(documentTypeId);

const [readonlyMode] = useState<boolean>(true);
const [notification, setNotification] = useState<UserNotification | null>(null);

if (!!document?.documentType && document?.documentType !== documentTypeId) {
router.push(`/content/${document?.documentType}/${document?.id}`);
return <Loader />;
}

useEffect(() => {
setNotification(documentError ?? typeError ?? fieldsError);
}, [documentError]);

const renderFormElement = (field: TanamDocumentField, value: any) => {
const formgroupKey = `formgroup-${field.id}`;
const inputKey = `input-${field.id}`;
Expand Down Expand Up @@ -101,14 +95,24 @@ const DocumentDetailsPage = () => {
}
};

if (documentError || typeError || fieldsError) {
return (
<>
<ErrorPage
pageName={documentType?.titleSingular.translated ?? "Document details"}
notificationType="error"
notificationTitle="Error loading document"
notificationMessage={documentError?.message || typeError?.message || fieldsError?.message || "Unknown error"}
/>
</>
);
}

return (
<>
<Suspense fallback={<Loader />}>
{documentType ? <PageHeader pageName={documentType.titleSingular.translated} /> : <Loader />}
</Suspense>
{notification && (
<Notification type={notification.type} title={notification.title} message={notification.message} />
)}
{documentType && document && (
<div className="grid grid-cols-1 gap-9">
<ContentCard key={document.id} title={document.data[documentType.titleField] as string}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"use client";
import ContentCard from "@/components/Containers/ContentCard";
import {
DynamicForm,
DynamicFormProps
} from "@/components/Form";
import Loader from "@/components/common/Loader";
import PageHeader from "@/components/common/PageHeader";
import {ErrorPage} from '@/components/Error/ErrorPage';
import {useTanamDocumentFields} from "@/hooks/useTanamDocumentFields";
import {useTanamDocumentType} from "@/hooks/useTanamDocumentTypes";
import {useParams} from "next/navigation";
import {Suspense, useState, useEffect} from "react";

const DocumentCreatePage = () => {
const {documentTypeId} = useParams<{documentTypeId: string;}>() ?? {};
const {data: documentType, error: typeError} = useTanamDocumentType(documentTypeId);
const {data: documentFields, error: fieldsError} = useTanamDocumentFields(documentTypeId);

const [entry, setEntry] = useState<DynamicFormProps>({
readonlyMode: false,
fields: []
});

useEffect(() => {
if (documentFields) {
setEntry({
...entry,
fields: documentFields.map((field) => ({
id: field.id,
label: field.title.translated,
placeholder: field.title.translated,
fieldType: field.fieldType,
value: ""
}))
});
}
}, [documentFields]);

const handleSave = (value: { [key: string]: any }) => {
console.log("handleSave ::", value);
};

if (typeError || fieldsError) {
return (
<>
<ErrorPage
pageName={documentType?.titleSingular.translated ?? "Document details"}
notificationType="error"
notificationTitle="Error loading document"
notificationMessage={typeError?.message || fieldsError?.message || "Unknown error"}
/>
</>
);
}

return (
<>
<Suspense fallback={<Loader />}>
{documentType ? <PageHeader pageName={documentType.titleSingular.translated} /> : <Loader />}
</Suspense>
{documentType && (
<div className="grid grid-cols-1 gap-9">
<ContentCard title={`Create New ${documentType.titleSingular.translated}`}>
entry :: {JSON.stringify(entry)}
<DynamicForm readonlyMode={entry.readonlyMode} fields={entry.fields} onSave={handleSave} />
</ContentCard>
</div>
)}
</>
);
};

export default DocumentCreatePage;
41 changes: 27 additions & 14 deletions hosting/src/app/(protected)/content/[documentTypeId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,46 @@
"use client";
import {DocumentTypeGenericList} from "@/components/DocumentType/DocumentTypeGenericList";
import {Button} from "@/components/Button";
import Loader from "@/components/common/Loader";
import Notification from "@/components/common/Notification";
import PageHeader from "@/components/common/PageHeader";
import {ErrorPage} from '@/components/Error/ErrorPage';
import {useTanamDocumentType} from "@/hooks/useTanamDocumentTypes";
import {useTanamDocuments} from "@/hooks/useTanamDocuments";
import {Suspense, useEffect, useState} from "react";
import {useParams} from "next/navigation";
import {UserNotification} from "@/models/UserNotification";
import {useParams, useRouter} from "next/navigation";
import {Suspense} from "react";

export default function DocumentTypeDocumentsPage() {
const router = useRouter();
const {documentTypeId} = useParams<{documentTypeId: string}>() ?? {};
const {data: documents, error: docsError} = useTanamDocuments(documentTypeId);
const {data: documentType} = useTanamDocumentType(documentTypeId);
const [notification, setNotification] = useState<UserNotification | null>(null);
const {data: documentType, error: typesError} = useTanamDocumentType(documentTypeId);

useEffect(() => {
setNotification(docsError);
}, [docsError]);
const handleCreateNewDocumentType = () => {
router.push(`/content/${documentTypeId}/create`);
};

const pageActions = [
<Button key="createNewDocument" onClick={handleCreateNewDocumentType} title={`Create New ${documentType?.titleSingular.translated ?? "Document"}`} />
]

if (docsError || typesError) {
return (
<>
<ErrorPage
pageName={documentType?.titleSingular.translated ?? "Document details"}
notificationType="error"
notificationTitle="Error loading document"
notificationMessage={docsError?.message || typesError?.message || "Unknown error"}
/>
</>
);
}

return (
<>
<Suspense fallback={<Loader />}>
{documentType ? <PageHeader pageName={documentType.titlePlural.translated} /> : <Loader />}
{documentType ? <PageHeader pageName={documentType.titlePlural.translated} pageActions={pageActions} /> : <Loader />}
</Suspense>
{notification && (
<Notification type={notification.type} title={notification.title} message={notification.message} />
)}
{docsError && <Notification type="error" title="Error fetching documents" message={docsError.message} />}
<Suspense fallback={<Loader />}>
{documentType ? <DocumentTypeGenericList documents={documents} documentType={documentType} /> : <Loader />}
</Suspense>
Expand Down
49 changes: 0 additions & 49 deletions hosting/src/app/(protected)/content/article/[documentId]/page.tsx

This file was deleted.

34 changes: 0 additions & 34 deletions hosting/src/app/(protected)/content/article/page.tsx

This file was deleted.

Loading
Loading