@hedhog/blog 0.0.1 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- package/frontend/author/components/author.screen.ts +105 -0
- package/frontend/author/components/create-panel.tsx +10 -3
- package/frontend/author/components/update-panel.tsx +7 -2
- package/frontend/author/react-query/requests.ts +7 -6
- package/frontend/category/components/category.screen.ts +105 -0
- package/frontend/category/components/create-panel.tsx +10 -3
- package/frontend/category/components/update-panel.tsx +7 -2
- package/frontend/category/react-query/requests.ts +7 -6
- package/frontend/post/components/create-panel.tsx +10 -3
- package/frontend/post/components/post.screen.ts +105 -0
- package/frontend/post/components/update-panel.tsx +7 -2
- package/frontend/post/react-query/requests.ts +7 -6
- package/package.json +1 -1
- package/frontend/author/components/create-panel.d.ts +0 -9
- package/frontend/author/components/create-panel.d.ts.map +0 -1
- package/frontend/author/components/create-panel.js +0 -42
- package/frontend/author/components/create-panel.js.map +0 -1
- package/frontend/author/components/update-panel.d.ts +0 -7
- package/frontend/author/components/update-panel.d.ts.map +0 -1
- package/frontend/author/components/update-panel.js +0 -52
- package/frontend/author/components/update-panel.js.map +0 -1
- package/frontend/author/react-query/handlers.d.ts +0 -5
- package/frontend/author/react-query/handlers.d.ts.map +0 -1
- package/frontend/author/react-query/handlers.js +0 -30
- package/frontend/author/react-query/handlers.js.map +0 -1
- package/frontend/author/react-query/requests.d.ts +0 -10
- package/frontend/author/react-query/requests.d.ts.map +0 -1
- package/frontend/author/react-query/requests.js +0 -48
- package/frontend/author/react-query/requests.js.map +0 -1
- package/frontend/category/components/create-panel.d.ts +0 -9
- package/frontend/category/components/create-panel.d.ts.map +0 -1
- package/frontend/category/components/create-panel.js +0 -48
- package/frontend/category/components/create-panel.js.map +0 -1
- package/frontend/category/components/update-panel.d.ts +0 -7
- package/frontend/category/components/update-panel.d.ts.map +0 -1
- package/frontend/category/components/update-panel.js +0 -61
- package/frontend/category/components/update-panel.js.map +0 -1
- package/frontend/category/react-query/handlers.d.ts +0 -5
- package/frontend/category/react-query/handlers.d.ts.map +0 -1
- package/frontend/category/react-query/handlers.js +0 -30
- package/frontend/category/react-query/handlers.js.map +0 -1
- package/frontend/category/react-query/requests.d.ts +0 -10
- package/frontend/category/react-query/requests.d.ts.map +0 -1
- package/frontend/category/react-query/requests.js +0 -49
- package/frontend/category/react-query/requests.js.map +0 -1
- package/frontend/post/components/create-panel.d.ts +0 -9
- package/frontend/post/components/create-panel.d.ts.map +0 -1
- package/frontend/post/components/create-panel.js +0 -54
- package/frontend/post/components/create-panel.js.map +0 -1
- package/frontend/post/components/update-panel.d.ts +0 -7
- package/frontend/post/components/update-panel.d.ts.map +0 -1
- package/frontend/post/components/update-panel.js +0 -64
- package/frontend/post/components/update-panel.js.map +0 -1
- package/frontend/post/react-query/handlers.d.ts +0 -5
- package/frontend/post/react-query/handlers.d.ts.map +0 -1
- package/frontend/post/react-query/handlers.js +0 -30
- package/frontend/post/react-query/handlers.js.map +0 -1
- package/frontend/post/react-query/requests.d.ts +0 -10
- package/frontend/post/react-query/requests.d.ts.map +0 -1
- package/frontend/post/react-query/requests.js +0 -48
- package/frontend/post/react-query/requests.js.map +0 -1
@@ -0,0 +1,105 @@
|
|
1
|
+
import { PageTitle } from "@/components/custom/page-title";
|
2
|
+
import DataPanel from "@/components/panels/data-panel";
|
3
|
+
import { useAuthorDelete } from "@/features/blog/author";
|
4
|
+
import { useApp } from "@/hooks/use-app";
|
5
|
+
import { isPlural } from "@/lib/utils";
|
6
|
+
import { Author } from "@/types/models";
|
7
|
+
import { IconEdit, IconPlus, IconTrash } from "@tabler/icons-react";
|
8
|
+
import { useState } from "react";
|
9
|
+
import { useTranslation } from "react-i18next";
|
10
|
+
import AuthorCreatePanel from "./components/author-create-panel";
|
11
|
+
import { AuthorUpdatePanel } from "./components/author-update-panel";
|
12
|
+
|
13
|
+
export default function Page() {
|
14
|
+
const [selectedItems, setSelectedItems] = useState<Author[]>([]);
|
15
|
+
const { mutate: deleteAuthor } = useAuthorDelete();
|
16
|
+
const { openSheet, confirm, closeSheet } = useApp();
|
17
|
+
const { t } = useTranslation(["author", "modules", "actions"]);
|
18
|
+
|
19
|
+
const openCreate = () => {
|
20
|
+
const id = openSheet({
|
21
|
+
title: t("create", { ns: "actions" }),
|
22
|
+
description: t("createText", { ns: "author" }),
|
23
|
+
children: () => <AuthorCreatePanel onCreated={() => closeSheet(id)} />,
|
24
|
+
});
|
25
|
+
|
26
|
+
return id;
|
27
|
+
};
|
28
|
+
|
29
|
+
const openDelete = (items: Author[]) => {
|
30
|
+
return confirm({
|
31
|
+
title: `${t("delete", { ns: "actions" })} ${items.length} ${isPlural(items.length) ? t("items", { ns: "actions" }) : t("item", { ns: "actions" })}`,
|
32
|
+
description: t("deleteText", { ns: "author" }),
|
33
|
+
})
|
34
|
+
.then(() =>
|
35
|
+
deleteAuthor(
|
36
|
+
items.map((item) => item.id).filter((id) => id !== undefined),
|
37
|
+
),
|
38
|
+
)
|
39
|
+
.catch(() => setSelectedItems(items));
|
40
|
+
};
|
41
|
+
|
42
|
+
const openUpdate = (item: Author) => {
|
43
|
+
const id = openSheet({
|
44
|
+
children: () => (
|
45
|
+
<AuthorUpdatePanel data={item} onUpdated={() => closeSheet(id)} />
|
46
|
+
),
|
47
|
+
title: t("edit", { ns: "author" }),
|
48
|
+
description: t("editText", { ns: "author" }),
|
49
|
+
});
|
50
|
+
|
51
|
+
return id;
|
52
|
+
};
|
53
|
+
|
54
|
+
return (
|
55
|
+
<>
|
56
|
+
<PageTitle title={t("author", { ns: "modules" })} />
|
57
|
+
<DataPanel
|
58
|
+
url="/author"
|
59
|
+
layout="table"
|
60
|
+
id="author"
|
61
|
+
selectable
|
62
|
+
columns={[
|
63
|
+
{ key: "id", header: "ID", width: 64 },
|
64
|
+
{ key: "name", header: t("name", { ns: "author" }) },
|
65
|
+
]}
|
66
|
+
selected={selectedItems as Author[]}
|
67
|
+
multiple
|
68
|
+
hasSearch
|
69
|
+
sortable
|
70
|
+
onItemDoubleClick={(item) => openUpdate(item)}
|
71
|
+
menuActions={[
|
72
|
+
{
|
73
|
+
icon: <IconEdit className="mr-1 w-8 cursor-pointer" />,
|
74
|
+
label: t("edit", { ns: "actions" }),
|
75
|
+
tooltip: t("editTooltip", { ns: "author" }),
|
76
|
+
handler: (items: Author[]) => {
|
77
|
+
if (items.length === 1) openUpdate(items[0]);
|
78
|
+
},
|
79
|
+
show: "once",
|
80
|
+
},
|
81
|
+
{
|
82
|
+
icon: <IconTrash className="mr-1 w-8 cursor-pointer" />,
|
83
|
+
label: t("delete", { ns: "actions" }),
|
84
|
+
tooltip: t("deleteTooltip", { ns: "author" }),
|
85
|
+
variant: "destructive",
|
86
|
+
handler: (items: Author[]) => {
|
87
|
+
openDelete(items);
|
88
|
+
},
|
89
|
+
show: "some",
|
90
|
+
},
|
91
|
+
{
|
92
|
+
icon: <IconPlus className="mr-1 w-8 cursor-pointer" />,
|
93
|
+
label: t("create", { ns: "actions" }),
|
94
|
+
tooltip: t("createTooltip", { ns: "author" }),
|
95
|
+
variant: "default",
|
96
|
+
handler: () => {
|
97
|
+
openCreate();
|
98
|
+
},
|
99
|
+
show: "none",
|
100
|
+
},
|
101
|
+
]}
|
102
|
+
/>
|
103
|
+
</>
|
104
|
+
);
|
105
|
+
}
|
@@ -1,6 +1,9 @@
|
|
1
|
-
import
|
1
|
+
import { Overlay } from "@/components/custom/overlay";
|
2
|
+
import FormPanel, { FormPanelRef } from "@/components/panels/form-panel";
|
3
|
+
import { TabPanel } from "@/components/panels/tab-panel";
|
2
4
|
import { EnumFieldType } from "@/enums/EnumFieldType";
|
3
|
-
import {
|
5
|
+
import { useAuthorGet, useAuthorUpdate } from "@/features/blog/author";
|
6
|
+
import useEffectAfterFirstUpdate from "@/hooks/use-effect-after-first-update";
|
4
7
|
import { Author } from "@/types/models";
|
5
8
|
import { forwardRef, useImperativeHandle, useRef } from "react";
|
6
9
|
import { useTranslation } from "react-i18next";
|
@@ -13,7 +16,7 @@ export type AuthorCreatePanelProps = {
|
|
13
16
|
onCreated?: (data: Author) => void;
|
14
17
|
};
|
15
18
|
|
16
|
-
|
19
|
+
const AuthorCreatePanel = forwardRef(
|
17
20
|
({ onCreated }: AuthorCreatePanelProps, ref) => {
|
18
21
|
const formRef = useRef<FormPanelRef>(null);
|
19
22
|
const { t } = useTranslation(["author", "actions"]);
|
@@ -58,3 +61,7 @@ export const AuthorCreatePanel = forwardRef(
|
|
58
61
|
);
|
59
62
|
},
|
60
63
|
);
|
64
|
+
|
65
|
+
AuthorCreatePanel.displayName = "AuthorCreatePanel";
|
66
|
+
|
67
|
+
export default AuthorCreatePanel;
|
@@ -5,16 +5,17 @@ import { EnumFieldType } from "@/enums/EnumFieldType";
|
|
5
5
|
import { useAuthorGet, useAuthorUpdate } from "@/features/author";
|
6
6
|
import useEffectAfterFirstUpdate from "@/hooks/use-effect-after-first-update";
|
7
7
|
import { Author } from "@/types/models";
|
8
|
-
import { t } from "i18next";
|
9
8
|
import { forwardRef, useImperativeHandle, useRef } from "react";
|
9
|
+
import { useTranslation } from "react-i18next";
|
10
10
|
|
11
11
|
export type AuthorUpdatePanelProps = {
|
12
12
|
data: Author;
|
13
13
|
onUpdated?: (data: Author) => void;
|
14
14
|
};
|
15
15
|
|
16
|
-
|
16
|
+
const AuthorUpdatePanel = forwardRef(
|
17
17
|
({ data, onUpdated }: AuthorUpdatePanelProps, ref) => {
|
18
|
+
const { t } = useTranslation(["person-types", "actions"]);
|
18
19
|
const { data: item, isLoading } = useAuthorGet(data.id as number);
|
19
20
|
const { mutate: authorUpdate } = useAuthorUpdate();
|
20
21
|
const formRef = useRef<FormPanelRef>(null);
|
@@ -68,3 +69,7 @@ export const AuthorUpdatePanel = forwardRef(
|
|
68
69
|
);
|
69
70
|
},
|
70
71
|
);
|
72
|
+
|
73
|
+
AuthorUpdatePanel.displayName = "AuthorUpdatePanel";
|
74
|
+
|
75
|
+
export default AuthorUpdatePanel;
|
@@ -10,13 +10,13 @@ export function requests() {
|
|
10
10
|
return request<PaginationResult<Author>>({
|
11
11
|
url: "/author",
|
12
12
|
params,
|
13
|
-
});
|
13
|
+
}).then((res) => res.data);
|
14
14
|
};
|
15
15
|
|
16
16
|
const authorGet = async (id: number) => {
|
17
17
|
return request<Author>({
|
18
18
|
url: `/author/${id}`,
|
19
|
-
});
|
19
|
+
}).then((res) => res.data);
|
20
20
|
};
|
21
21
|
|
22
22
|
const authorCreate = async (data: Author) => {
|
@@ -24,7 +24,7 @@ export function requests() {
|
|
24
24
|
url: "/author",
|
25
25
|
method: HttpMethod.POST,
|
26
26
|
data: data,
|
27
|
-
});
|
27
|
+
}).then((res) => res.data);
|
28
28
|
};
|
29
29
|
|
30
30
|
const authorDelete = async (ids: number[]) => {
|
@@ -32,15 +32,16 @@ export function requests() {
|
|
32
32
|
url: "/author",
|
33
33
|
data: { ids },
|
34
34
|
method: HttpMethod.DELETE,
|
35
|
-
});
|
35
|
+
}).then((res) => res.data);
|
36
36
|
};
|
37
37
|
|
38
|
-
const authorUpdate = async (id: number
|
38
|
+
const authorUpdate = async (params: { id: number; data: Author }) => {
|
39
|
+
const { id, data } = params;
|
39
40
|
return request<Author>({
|
40
41
|
url: `/author/${id}`,
|
41
42
|
method: HttpMethod.PATCH,
|
42
43
|
data: data,
|
43
|
-
});
|
44
|
+
}).then((res) => res.data);
|
44
45
|
};
|
45
46
|
|
46
47
|
return {
|
@@ -0,0 +1,105 @@
|
|
1
|
+
import { PageTitle } from "@/components/custom/page-title";
|
2
|
+
import DataPanel from "@/components/panels/data-panel";
|
3
|
+
import { useCategoryDelete } from "@/features/blog/category";
|
4
|
+
import { useApp } from "@/hooks/use-app";
|
5
|
+
import { isPlural } from "@/lib/utils";
|
6
|
+
import { Category } from "@/types/models";
|
7
|
+
import { IconEdit, IconPlus, IconTrash } from "@tabler/icons-react";
|
8
|
+
import { useState } from "react";
|
9
|
+
import { useTranslation } from "react-i18next";
|
10
|
+
import CategoryCreatePanel from "./components/category-create-panel";
|
11
|
+
import { CategoryUpdatePanel } from "./components/category-update-panel";
|
12
|
+
|
13
|
+
export default function Page() {
|
14
|
+
const [selectedItems, setSelectedItems] = useState<Category[]>([]);
|
15
|
+
const { mutate: deleteCategory } = useCategoryDelete();
|
16
|
+
const { openSheet, confirm, closeSheet } = useApp();
|
17
|
+
const { t } = useTranslation(["category", "modules", "actions"]);
|
18
|
+
|
19
|
+
const openCreate = () => {
|
20
|
+
const id = openSheet({
|
21
|
+
title: t("create", { ns: "actions" }),
|
22
|
+
description: t("createText", { ns: "category" }),
|
23
|
+
children: () => <CategoryCreatePanel onCreated={() => closeSheet(id)} />,
|
24
|
+
});
|
25
|
+
|
26
|
+
return id;
|
27
|
+
};
|
28
|
+
|
29
|
+
const openDelete = (items: Category[]) => {
|
30
|
+
return confirm({
|
31
|
+
title: `${t("delete", { ns: "actions" })} ${items.length} ${isPlural(items.length) ? t("items", { ns: "actions" }) : t("item", { ns: "actions" })}`,
|
32
|
+
description: t("deleteText", { ns: "category" }),
|
33
|
+
})
|
34
|
+
.then(() =>
|
35
|
+
deleteCategory(
|
36
|
+
items.map((item) => item.id).filter((id) => id !== undefined),
|
37
|
+
),
|
38
|
+
)
|
39
|
+
.catch(() => setSelectedItems(items));
|
40
|
+
};
|
41
|
+
|
42
|
+
const openUpdate = (item: Category) => {
|
43
|
+
const id = openSheet({
|
44
|
+
children: () => (
|
45
|
+
<CategoryUpdatePanel data={item} onUpdated={() => closeSheet(id)} />
|
46
|
+
),
|
47
|
+
title: t("edit", { ns: "category" }),
|
48
|
+
description: t("editText", { ns: "category" }),
|
49
|
+
});
|
50
|
+
|
51
|
+
return id;
|
52
|
+
};
|
53
|
+
|
54
|
+
return (
|
55
|
+
<>
|
56
|
+
<PageTitle title={t("category", { ns: "modules" })} />
|
57
|
+
<DataPanel
|
58
|
+
url="/category"
|
59
|
+
layout="table"
|
60
|
+
id="category"
|
61
|
+
selectable
|
62
|
+
columns={[
|
63
|
+
{ key: "id", header: "ID", width: 64 },
|
64
|
+
{ key: "name", header: t("name", { ns: "category" }) },
|
65
|
+
]}
|
66
|
+
selected={selectedItems as Category[]}
|
67
|
+
multiple
|
68
|
+
hasSearch
|
69
|
+
sortable
|
70
|
+
onItemDoubleClick={(item) => openUpdate(item)}
|
71
|
+
menuActions={[
|
72
|
+
{
|
73
|
+
icon: <IconEdit className="mr-1 w-8 cursor-pointer" />,
|
74
|
+
label: t("edit", { ns: "actions" }),
|
75
|
+
tooltip: t("editTooltip", { ns: "category" }),
|
76
|
+
handler: (items: Category[]) => {
|
77
|
+
if (items.length === 1) openUpdate(items[0]);
|
78
|
+
},
|
79
|
+
show: "once",
|
80
|
+
},
|
81
|
+
{
|
82
|
+
icon: <IconTrash className="mr-1 w-8 cursor-pointer" />,
|
83
|
+
label: t("delete", { ns: "actions" }),
|
84
|
+
tooltip: t("deleteTooltip", { ns: "category" }),
|
85
|
+
variant: "destructive",
|
86
|
+
handler: (items: Category[]) => {
|
87
|
+
openDelete(items);
|
88
|
+
},
|
89
|
+
show: "some",
|
90
|
+
},
|
91
|
+
{
|
92
|
+
icon: <IconPlus className="mr-1 w-8 cursor-pointer" />,
|
93
|
+
label: t("create", { ns: "actions" }),
|
94
|
+
tooltip: t("createTooltip", { ns: "category" }),
|
95
|
+
variant: "default",
|
96
|
+
handler: () => {
|
97
|
+
openCreate();
|
98
|
+
},
|
99
|
+
show: "none",
|
100
|
+
},
|
101
|
+
]}
|
102
|
+
/>
|
103
|
+
</>
|
104
|
+
);
|
105
|
+
}
|
@@ -1,9 +1,12 @@
|
|
1
|
+
import { Overlay } from "@/components/custom/overlay";
|
1
2
|
import FormPanel, {
|
2
3
|
FormPanelRef,
|
3
4
|
getFieldsLocale,
|
4
|
-
} from "@/components/
|
5
|
+
} from "@/components/panels/form-panel";
|
6
|
+
import { TabPanel } from "@/components/panels/tab-panel";
|
5
7
|
import { EnumFieldType } from "@/enums/EnumFieldType";
|
6
|
-
import {
|
8
|
+
import { useCategoryGet, useCategoryUpdate } from "@/features/blog/category";
|
9
|
+
import useEffectAfterFirstUpdate from "@/hooks/use-effect-after-first-update";
|
7
10
|
import { Category } from "@/types/models";
|
8
11
|
import { forwardRef, useImperativeHandle, useRef } from "react";
|
9
12
|
import { useTranslation } from "react-i18next";
|
@@ -16,7 +19,7 @@ export type CategoryCreatePanelProps = {
|
|
16
19
|
onCreated?: (data: Category) => void;
|
17
20
|
};
|
18
21
|
|
19
|
-
|
22
|
+
const CategoryCreatePanel = forwardRef(
|
20
23
|
({ onCreated }: CategoryCreatePanelProps, ref) => {
|
21
24
|
const formRef = useRef<FormPanelRef>(null);
|
22
25
|
const { t } = useTranslation(["category", "actions"]);
|
@@ -47,3 +50,7 @@ export const CategoryCreatePanel = forwardRef(
|
|
47
50
|
);
|
48
51
|
},
|
49
52
|
);
|
53
|
+
|
54
|
+
CategoryCreatePanel.displayName = "CategoryCreatePanel";
|
55
|
+
|
56
|
+
export default CategoryCreatePanel;
|
@@ -8,16 +8,17 @@ import { EnumFieldType } from "@/enums/EnumFieldType";
|
|
8
8
|
import { useCategoryGet, useCategoryUpdate } from "@/features/category";
|
9
9
|
import useEffectAfterFirstUpdate from "@/hooks/use-effect-after-first-update";
|
10
10
|
import { Category } from "@/types/models";
|
11
|
-
import { t } from "i18next";
|
12
11
|
import { forwardRef, useImperativeHandle, useRef } from "react";
|
12
|
+
import { useTranslation } from "react-i18next";
|
13
13
|
|
14
14
|
export type CategoryUpdatePanelProps = {
|
15
15
|
data: Category;
|
16
16
|
onUpdated?: (data: Category) => void;
|
17
17
|
};
|
18
18
|
|
19
|
-
|
19
|
+
const CategoryUpdatePanel = forwardRef(
|
20
20
|
({ data, onUpdated }: CategoryUpdatePanelProps, ref) => {
|
21
|
+
const { t } = useTranslation(["person-types", "actions"]);
|
21
22
|
const { data: item, isLoading } = useCategoryGet(data.id as number);
|
22
23
|
const { mutate: categoryUpdate } = useCategoryUpdate();
|
23
24
|
const formRef = useRef<FormPanelRef>(null);
|
@@ -57,3 +58,7 @@ export const CategoryUpdatePanel = forwardRef(
|
|
57
58
|
);
|
58
59
|
},
|
59
60
|
);
|
61
|
+
|
62
|
+
CategoryUpdatePanel.displayName = "CategoryUpdatePanel";
|
63
|
+
|
64
|
+
export default CategoryUpdatePanel;
|
@@ -11,13 +11,13 @@ export function requests() {
|
|
11
11
|
return request<PaginationResult<Category>>({
|
12
12
|
url: "/category",
|
13
13
|
params,
|
14
|
-
});
|
14
|
+
}).then((res) => res.data);
|
15
15
|
};
|
16
16
|
|
17
17
|
const categoryGet = async (id: number) => {
|
18
18
|
return request<Category>({
|
19
19
|
url: `/category/${id}`,
|
20
|
-
});
|
20
|
+
}).then((res) => res.data);
|
21
21
|
};
|
22
22
|
|
23
23
|
const categoryCreate = async (data: Category) => {
|
@@ -25,7 +25,7 @@ export function requests() {
|
|
25
25
|
url: "/category",
|
26
26
|
method: HttpMethod.POST,
|
27
27
|
data: formatDataWithLocale(data),
|
28
|
-
});
|
28
|
+
}).then((res) => res.data);
|
29
29
|
};
|
30
30
|
|
31
31
|
const categoryDelete = async (ids: number[]) => {
|
@@ -33,15 +33,16 @@ export function requests() {
|
|
33
33
|
url: "/category",
|
34
34
|
data: { ids },
|
35
35
|
method: HttpMethod.DELETE,
|
36
|
-
});
|
36
|
+
}).then((res) => res.data);
|
37
37
|
};
|
38
38
|
|
39
|
-
const categoryUpdate = async (id: number
|
39
|
+
const categoryUpdate = async (params: { id: number; data: Category }) => {
|
40
|
+
const { id, data } = params;
|
40
41
|
return request<Category>({
|
41
42
|
url: `/category/${id}`,
|
42
43
|
method: HttpMethod.PATCH,
|
43
44
|
data: formatDataWithLocale(data),
|
44
|
-
});
|
45
|
+
}).then((res) => res.data);
|
45
46
|
};
|
46
47
|
|
47
48
|
return {
|
@@ -1,6 +1,9 @@
|
|
1
|
-
import
|
1
|
+
import { Overlay } from "@/components/custom/overlay";
|
2
|
+
import FormPanel, { FormPanelRef } from "@/components/panels/form-panel";
|
3
|
+
import { TabPanel } from "@/components/panels/tab-panel";
|
2
4
|
import { EnumFieldType } from "@/enums/EnumFieldType";
|
3
|
-
import {
|
5
|
+
import { usePostGet, usePostUpdate } from "@/features/blog/post";
|
6
|
+
import useEffectAfterFirstUpdate from "@/hooks/use-effect-after-first-update";
|
4
7
|
import { Post } from "@/types/models";
|
5
8
|
import { forwardRef, useImperativeHandle, useRef } from "react";
|
6
9
|
import { useTranslation } from "react-i18next";
|
@@ -13,7 +16,7 @@ export type PostCreatePanelProps = {
|
|
13
16
|
onCreated?: (data: Post) => void;
|
14
17
|
};
|
15
18
|
|
16
|
-
|
19
|
+
const PostCreatePanel = forwardRef(
|
17
20
|
({ onCreated }: PostCreatePanelProps, ref) => {
|
18
21
|
const formRef = useRef<FormPanelRef>(null);
|
19
22
|
const { t } = useTranslation(["post", "actions"]);
|
@@ -72,3 +75,7 @@ export const PostCreatePanel = forwardRef(
|
|
72
75
|
);
|
73
76
|
},
|
74
77
|
);
|
78
|
+
|
79
|
+
PostCreatePanel.displayName = "PostCreatePanel";
|
80
|
+
|
81
|
+
export default PostCreatePanel;
|
@@ -0,0 +1,105 @@
|
|
1
|
+
import { PageTitle } from "@/components/custom/page-title";
|
2
|
+
import DataPanel from "@/components/panels/data-panel";
|
3
|
+
import { usePostDelete } from "@/features/blog/post";
|
4
|
+
import { useApp } from "@/hooks/use-app";
|
5
|
+
import { isPlural } from "@/lib/utils";
|
6
|
+
import { Post } from "@/types/models";
|
7
|
+
import { IconEdit, IconPlus, IconTrash } from "@tabler/icons-react";
|
8
|
+
import { useState } from "react";
|
9
|
+
import { useTranslation } from "react-i18next";
|
10
|
+
import PostCreatePanel from "./components/post-create-panel";
|
11
|
+
import { PostUpdatePanel } from "./components/post-update-panel";
|
12
|
+
|
13
|
+
export default function Page() {
|
14
|
+
const [selectedItems, setSelectedItems] = useState<Post[]>([]);
|
15
|
+
const { mutate: deletePost } = usePostDelete();
|
16
|
+
const { openSheet, confirm, closeSheet } = useApp();
|
17
|
+
const { t } = useTranslation(["post", "modules", "actions"]);
|
18
|
+
|
19
|
+
const openCreate = () => {
|
20
|
+
const id = openSheet({
|
21
|
+
title: t("create", { ns: "actions" }),
|
22
|
+
description: t("createText", { ns: "post" }),
|
23
|
+
children: () => <PostCreatePanel onCreated={() => closeSheet(id)} />,
|
24
|
+
});
|
25
|
+
|
26
|
+
return id;
|
27
|
+
};
|
28
|
+
|
29
|
+
const openDelete = (items: Post[]) => {
|
30
|
+
return confirm({
|
31
|
+
title: `${t("delete", { ns: "actions" })} ${items.length} ${isPlural(items.length) ? t("items", { ns: "actions" }) : t("item", { ns: "actions" })}`,
|
32
|
+
description: t("deleteText", { ns: "post" }),
|
33
|
+
})
|
34
|
+
.then(() =>
|
35
|
+
deletePost(
|
36
|
+
items.map((item) => item.id).filter((id) => id !== undefined),
|
37
|
+
),
|
38
|
+
)
|
39
|
+
.catch(() => setSelectedItems(items));
|
40
|
+
};
|
41
|
+
|
42
|
+
const openUpdate = (item: Post) => {
|
43
|
+
const id = openSheet({
|
44
|
+
children: () => (
|
45
|
+
<PostUpdatePanel data={item} onUpdated={() => closeSheet(id)} />
|
46
|
+
),
|
47
|
+
title: t("edit", { ns: "post" }),
|
48
|
+
description: t("editText", { ns: "post" }),
|
49
|
+
});
|
50
|
+
|
51
|
+
return id;
|
52
|
+
};
|
53
|
+
|
54
|
+
return (
|
55
|
+
<>
|
56
|
+
<PageTitle title={t("post", { ns: "modules" })} />
|
57
|
+
<DataPanel
|
58
|
+
url="/post"
|
59
|
+
layout="table"
|
60
|
+
id="post"
|
61
|
+
selectable
|
62
|
+
columns={[
|
63
|
+
{ key: "id", header: "ID", width: 64 },
|
64
|
+
{ key: "name", header: t("name", { ns: "post" }) },
|
65
|
+
]}
|
66
|
+
selected={selectedItems as Post[]}
|
67
|
+
multiple
|
68
|
+
hasSearch
|
69
|
+
sortable
|
70
|
+
onItemDoubleClick={(item) => openUpdate(item)}
|
71
|
+
menuActions={[
|
72
|
+
{
|
73
|
+
icon: <IconEdit className="mr-1 w-8 cursor-pointer" />,
|
74
|
+
label: t("edit", { ns: "actions" }),
|
75
|
+
tooltip: t("editTooltip", { ns: "post" }),
|
76
|
+
handler: (items: Post[]) => {
|
77
|
+
if (items.length === 1) openUpdate(items[0]);
|
78
|
+
},
|
79
|
+
show: "once",
|
80
|
+
},
|
81
|
+
{
|
82
|
+
icon: <IconTrash className="mr-1 w-8 cursor-pointer" />,
|
83
|
+
label: t("delete", { ns: "actions" }),
|
84
|
+
tooltip: t("deleteTooltip", { ns: "post" }),
|
85
|
+
variant: "destructive",
|
86
|
+
handler: (items: Post[]) => {
|
87
|
+
openDelete(items);
|
88
|
+
},
|
89
|
+
show: "some",
|
90
|
+
},
|
91
|
+
{
|
92
|
+
icon: <IconPlus className="mr-1 w-8 cursor-pointer" />,
|
93
|
+
label: t("create", { ns: "actions" }),
|
94
|
+
tooltip: t("createTooltip", { ns: "post" }),
|
95
|
+
variant: "default",
|
96
|
+
handler: () => {
|
97
|
+
openCreate();
|
98
|
+
},
|
99
|
+
show: "none",
|
100
|
+
},
|
101
|
+
]}
|
102
|
+
/>
|
103
|
+
</>
|
104
|
+
);
|
105
|
+
}
|
@@ -5,16 +5,17 @@ import { EnumFieldType } from "@/enums/EnumFieldType";
|
|
5
5
|
import { usePostGet, usePostUpdate } from "@/features/post";
|
6
6
|
import useEffectAfterFirstUpdate from "@/hooks/use-effect-after-first-update";
|
7
7
|
import { Post } from "@/types/models";
|
8
|
-
import { t } from "i18next";
|
9
8
|
import { forwardRef, useImperativeHandle, useRef } from "react";
|
9
|
+
import { useTranslation } from "react-i18next";
|
10
10
|
|
11
11
|
export type PostUpdatePanelProps = {
|
12
12
|
data: Post;
|
13
13
|
onUpdated?: (data: Post) => void;
|
14
14
|
};
|
15
15
|
|
16
|
-
|
16
|
+
const PostUpdatePanel = forwardRef(
|
17
17
|
({ data, onUpdated }: PostUpdatePanelProps, ref) => {
|
18
|
+
const { t } = useTranslation(["person-types", "actions"]);
|
18
19
|
const { data: item, isLoading } = usePostGet(data.id as number);
|
19
20
|
const { mutate: postUpdate } = usePostUpdate();
|
20
21
|
const formRef = useRef<FormPanelRef>(null);
|
@@ -82,3 +83,7 @@ export const PostUpdatePanel = forwardRef(
|
|
82
83
|
);
|
83
84
|
},
|
84
85
|
);
|
86
|
+
|
87
|
+
PostUpdatePanel.displayName = "PostUpdatePanel";
|
88
|
+
|
89
|
+
export default PostUpdatePanel;
|
@@ -10,13 +10,13 @@ export function requests() {
|
|
10
10
|
return request<PaginationResult<Post>>({
|
11
11
|
url: "/post",
|
12
12
|
params,
|
13
|
-
});
|
13
|
+
}).then((res) => res.data);
|
14
14
|
};
|
15
15
|
|
16
16
|
const postGet = async (id: number) => {
|
17
17
|
return request<Post>({
|
18
18
|
url: `/post/${id}`,
|
19
|
-
});
|
19
|
+
}).then((res) => res.data);
|
20
20
|
};
|
21
21
|
|
22
22
|
const postCreate = async (data: Post) => {
|
@@ -24,7 +24,7 @@ export function requests() {
|
|
24
24
|
url: "/post",
|
25
25
|
method: HttpMethod.POST,
|
26
26
|
data: data,
|
27
|
-
});
|
27
|
+
}).then((res) => res.data);
|
28
28
|
};
|
29
29
|
|
30
30
|
const postDelete = async (ids: number[]) => {
|
@@ -32,15 +32,16 @@ export function requests() {
|
|
32
32
|
url: "/post",
|
33
33
|
data: { ids },
|
34
34
|
method: HttpMethod.DELETE,
|
35
|
-
});
|
35
|
+
}).then((res) => res.data);
|
36
36
|
};
|
37
37
|
|
38
|
-
const postUpdate = async (id: number
|
38
|
+
const postUpdate = async (params: { id: number; data: Post }) => {
|
39
|
+
const { id, data } = params;
|
39
40
|
return request<Post>({
|
40
41
|
url: `/post/${id}`,
|
41
42
|
method: HttpMethod.PATCH,
|
42
43
|
data: data,
|
43
|
-
});
|
44
|
+
}).then((res) => res.data);
|
44
45
|
};
|
45
46
|
|
46
47
|
return {
|
package/package.json
CHANGED
@@ -1,9 +0,0 @@
|
|
1
|
-
import { Author } from "@/types/models";
|
2
|
-
export type AuthorCreatePanelRef = {
|
3
|
-
submit: () => void;
|
4
|
-
};
|
5
|
-
export type AuthorCreatePanelProps = {
|
6
|
-
onCreated?: (data: Author) => void;
|
7
|
-
};
|
8
|
-
export declare const AuthorCreatePanel: any;
|
9
|
-
//# sourceMappingURL=create-panel.d.ts.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"create-panel.d.ts","sourceRoot":"","sources":["create-panel.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAIxC,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AAEF,eAAO,MAAM,iBAAiB,KA4C7B,CAAC"}
|