@carlonicora/nextjs-jsonapi 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AbstractService-B2n_JdiC.d.mts → AbstractService-BsY6W3Ej.d.mts} +1 -1
- package/dist/{AbstractService-DtQTYovo.d.ts → AbstractService-wLid8dB0.d.ts} +1 -1
- package/dist/AuthComponent-hxOPs9o8.d.mts +11 -0
- package/dist/AuthComponent-hxOPs9o8.d.ts +11 -0
- package/dist/{BlockNoteEditor-BLVXQPXV.mjs → BlockNoteEditor-6TBRDBCF.mjs} +7 -7
- package/dist/{BlockNoteEditor-ZTDHULFT.js → BlockNoteEditor-BCPDRNLK.js} +17 -17
- package/dist/{BlockNoteEditor-ZTDHULFT.js.map → BlockNoteEditor-BCPDRNLK.js.map} +1 -1
- package/dist/{chunk-6GKHCVF6.js → chunk-32HM6MDD.js} +1 -1
- package/dist/chunk-32HM6MDD.js.map +1 -0
- package/dist/{chunk-A5DDIABK.js → chunk-EZK3H6EJ.js} +206 -206
- package/dist/{chunk-A5DDIABK.js.map → chunk-EZK3H6EJ.js.map} +1 -1
- package/dist/{chunk-WEC4YMOS.js → chunk-FPMPTR7S.js} +778 -590
- package/dist/chunk-FPMPTR7S.js.map +1 -0
- package/dist/{chunk-RZO2LOW4.js → chunk-FYRFMABS.js} +181 -183
- package/dist/chunk-FYRFMABS.js.map +1 -0
- package/dist/{chunk-DD3KISNB.mjs → chunk-HAG77QBV.mjs} +1 -1
- package/dist/chunk-HAG77QBV.mjs.map +1 -0
- package/dist/{chunk-2LM6LCJW.mjs → chunk-JLN6UWII.mjs} +41 -2
- package/dist/chunk-JLN6UWII.mjs.map +1 -0
- package/dist/{chunk-JC3WJK65.js → chunk-LJRD4SRV.js} +41 -2
- package/dist/chunk-LJRD4SRV.js.map +1 -0
- package/dist/{chunk-3APORDYP.mjs → chunk-LUHQILAI.mjs} +700 -512
- package/dist/chunk-LUHQILAI.mjs.map +1 -0
- package/dist/{chunk-7C5RAEBO.mjs → chunk-MA2L2PL2.mjs} +2 -4
- package/dist/chunk-MA2L2PL2.mjs.map +1 -0
- package/dist/{chunk-PYF2U6WG.mjs → chunk-NPPQNSXN.mjs} +11 -1
- package/dist/{chunk-PYF2U6WG.mjs.map → chunk-NPPQNSXN.mjs.map} +1 -1
- package/dist/{chunk-HMHGLXWC.js → chunk-WZJDLITG.js} +11 -1
- package/dist/chunk-WZJDLITG.js.map +1 -0
- package/dist/{chunk-IWFGEPAA.mjs → chunk-X53MF5ZN.mjs} +2 -2
- package/dist/client/index.d.mts +8 -4
- package/dist/client/index.d.ts +8 -4
- package/dist/client/index.js +9 -7
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +8 -6
- package/dist/components/index.d.mts +20 -3
- package/dist/components/index.d.ts +20 -3
- package/dist/components/index.js +13 -7
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +12 -6
- package/dist/{user.fields-CbdObSmS.d.mts → content.fields-cHPdM8GJ.d.mts} +10 -1
- package/dist/{user.fields-CbdObSmS.d.ts → content.fields-cHPdM8GJ.d.ts} +10 -1
- package/dist/{AuthComponent-m6Qp4Hz6.d.ts → content.interface-C_PGZMuy.d.ts} +1 -11
- package/dist/{AuthComponent-CPLvEerw.d.mts → content.interface-D_WS6CrB.d.mts} +1 -11
- package/dist/contexts/index.d.mts +2 -1
- package/dist/contexts/index.d.ts +2 -1
- package/dist/contexts/index.js +7 -7
- package/dist/contexts/index.mjs +6 -6
- package/dist/core/index.d.mts +6 -3
- package/dist/core/index.d.ts +6 -3
- package/dist/core/index.js +2 -2
- package/dist/core/index.mjs +1 -1
- package/dist/features/index.d.mts +7 -17
- package/dist/features/index.d.ts +7 -17
- package/dist/features/index.js +4 -4
- package/dist/features/index.mjs +3 -3
- package/dist/hooks/index.d.mts +4 -4
- package/dist/hooks/index.d.ts +4 -4
- package/dist/hooks/index.js +7 -7
- package/dist/hooks/index.mjs +6 -6
- package/dist/index.d.mts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -3
- package/dist/index.mjs +2 -2
- package/dist/permissions/index.d.mts +3 -2
- package/dist/permissions/index.d.ts +3 -2
- package/dist/permissions/index.js +2 -2
- package/dist/permissions/index.mjs +1 -1
- package/dist/server/index.d.mts +2 -1
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +2 -2
- package/dist/server/index.mjs +1 -1
- package/dist/shadcnui/index.js +5 -3
- package/dist/shadcnui/index.js.map +1 -1
- package/dist/shadcnui/index.mjs +4 -2
- package/dist/{types-BUAlgqqh.d.ts → types-B2QRyqyK.d.ts} +1 -1
- package/dist/{types-iVdVY7ba.d.mts → types-CgvNmxTd.d.mts} +1 -1
- package/dist/{types-Bl61ob-7.d.mts → types-t2PyXhDu.d.mts} +4 -0
- package/dist/{types-Bl61ob-7.d.ts → types-t2PyXhDu.d.ts} +4 -0
- package/dist/utils/index.d.mts +27 -3
- package/dist/utils/index.d.ts +27 -3
- package/dist/utils/index.js +16 -2
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +15 -1
- package/package.json +1 -1
- package/src/client/index.ts +3 -1
- package/src/components/index.ts +1 -0
- package/src/core/registry/ModuleRegistry.ts +16 -1
- package/src/features/content/components/index.ts +1 -0
- package/src/features/content/components/lists/ContentsList.tsx +67 -0
- package/src/features/content/components/lists/ContentsListById.tsx +30 -0
- package/src/features/content/components/lists/RelevantContentsList.tsx +30 -0
- package/src/features/content/components/lists/index.ts +3 -0
- package/src/features/content/data/content.fields.ts +0 -2
- package/src/features/content/hooks/index.ts +1 -0
- package/src/features/content/hooks/useContentTableStructure.tsx +132 -0
- package/src/permissions/types.ts +3 -0
- package/src/utils/icons.tsx +40 -0
- package/src/utils/index.ts +1 -0
- package/dist/chunk-2LM6LCJW.mjs.map +0 -1
- package/dist/chunk-3APORDYP.mjs.map +0 -1
- package/dist/chunk-6GKHCVF6.js.map +0 -1
- package/dist/chunk-7C5RAEBO.mjs.map +0 -1
- package/dist/chunk-DD3KISNB.mjs.map +0 -1
- package/dist/chunk-HMHGLXWC.js.map +0 -1
- package/dist/chunk-JC3WJK65.js.map +0 -1
- package/dist/chunk-RZO2LOW4.js.map +0 -1
- package/dist/chunk-WEC4YMOS.js.map +0 -1
- /package/dist/{BlockNoteEditor-BLVXQPXV.mjs.map → BlockNoteEditor-6TBRDBCF.mjs.map} +0 -0
- /package/dist/{chunk-IWFGEPAA.mjs.map → chunk-X53MF5ZN.mjs.map} +0 -0
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { ClassValue } from 'clsx';
|
|
2
2
|
export { ClassValue } from 'clsx';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import { ReactElement } from 'react';
|
|
5
|
-
import { M as ModuleWithPermissions, a as Action } from '../types-
|
|
4
|
+
import { ReactElement, ReactNode } from 'react';
|
|
5
|
+
import { M as ModuleWithPermissions, a as Action } from '../types-t2PyXhDu.js';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { PartialBlock } from '@blocknote/core';
|
|
8
|
+
import { LucideIcon } from 'lucide-react';
|
|
9
|
+
import { A as ApiDataInterface } from '../ApiDataInterface-DPP8s46n.js';
|
|
8
10
|
|
|
9
11
|
declare function cn(...inputs: ClassValue[]): string;
|
|
10
12
|
|
|
@@ -197,4 +199,26 @@ declare class BlockNoteWordDiffRendererUtil {
|
|
|
197
199
|
};
|
|
198
200
|
}
|
|
199
201
|
|
|
200
|
-
|
|
202
|
+
declare const getIconByModule: (params: {
|
|
203
|
+
module: ModuleWithPermissions;
|
|
204
|
+
className?: string;
|
|
205
|
+
}) => ReactNode;
|
|
206
|
+
declare const getIcon: (params: {
|
|
207
|
+
element: ApiDataInterface;
|
|
208
|
+
className?: string;
|
|
209
|
+
}) => ReactNode;
|
|
210
|
+
declare const getIconByModuleName: (params: {
|
|
211
|
+
name: string;
|
|
212
|
+
className?: string;
|
|
213
|
+
}) => ReactNode;
|
|
214
|
+
declare const getLucideIcon: (params: {
|
|
215
|
+
element: ApiDataInterface;
|
|
216
|
+
}) => LucideIcon | null;
|
|
217
|
+
declare const getLucideIconByModule: (params: {
|
|
218
|
+
module: ModuleWithPermissions;
|
|
219
|
+
}) => LucideIcon | null;
|
|
220
|
+
declare const getLucideIconByModuleName: (params: {
|
|
221
|
+
name: string;
|
|
222
|
+
}) => LucideIcon | null;
|
|
223
|
+
|
|
224
|
+
export { type BlockDiffOptions, BlockNoteDiffUtil, BlockNoteWordDiffRendererUtil, type DiffBlock, type DiffResult, type EntityObject, type FormatOption, TableOptions, type UserObject, type WordDiff, cn, composeRefs, entityObjectSchema, exists, formatDate, getIcon, getIconByModule, getIconByModuleName, getLucideIcon, getLucideIconByModule, getLucideIconByModuleName, getTableComponents, getTableOptions, useComposedRefs, useIsMobile, userObjectSchema };
|
package/dist/utils/index.js
CHANGED
|
@@ -12,7 +12,15 @@
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
var _chunkLJRD4SRVjs = require('../chunk-LJRD4SRV.js');
|
|
22
|
+
require('../chunk-WZJDLITG.js');
|
|
23
|
+
require('../chunk-AGAJMJ4T.js');
|
|
16
24
|
require('../chunk-7QVYU63E.js');
|
|
17
25
|
|
|
18
26
|
|
|
@@ -28,5 +36,11 @@ require('../chunk-7QVYU63E.js');
|
|
|
28
36
|
|
|
29
37
|
|
|
30
38
|
|
|
31
|
-
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
exports.BlockNoteDiffUtil = _chunkLJRD4SRVjs.BlockNoteDiffUtil; exports.BlockNoteWordDiffRendererUtil = _chunkLJRD4SRVjs.BlockNoteWordDiffRendererUtil; exports.TableOptions = _chunkLJRD4SRVjs.TableOptions; exports.cn = _chunkLJRD4SRVjs.cn; exports.composeRefs = _chunkLJRD4SRVjs.composeRefs; exports.entityObjectSchema = _chunkLJRD4SRVjs.entityObjectSchema; exports.exists = _chunkLJRD4SRVjs.exists; exports.formatDate = _chunkLJRD4SRVjs.formatDate; exports.getIcon = _chunkLJRD4SRVjs.getIcon; exports.getIconByModule = _chunkLJRD4SRVjs.getIconByModule; exports.getIconByModuleName = _chunkLJRD4SRVjs.getIconByModuleName; exports.getLucideIcon = _chunkLJRD4SRVjs.getLucideIcon; exports.getLucideIconByModule = _chunkLJRD4SRVjs.getLucideIconByModule; exports.getLucideIconByModuleName = _chunkLJRD4SRVjs.getLucideIconByModuleName; exports.getTableComponents = _chunkLJRD4SRVjs.getTableComponents; exports.getTableOptions = _chunkLJRD4SRVjs.getTableOptions; exports.useComposedRefs = _chunkLJRD4SRVjs.useComposedRefs; exports.useIsMobile = _chunkLJRD4SRVjs.useIsMobile; exports.userObjectSchema = _chunkLJRD4SRVjs.userObjectSchema;
|
|
32
46
|
//# sourceMappingURL=index.js.map
|
package/dist/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/utils/index.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,uDAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/utils/index.js"],"names":[],"mappings":"AAAA;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,uDAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B,gCAA6B;AAC7B;AACE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACF,ymCAAC","file":"/home/runner/work/nextjs-jsonapi/nextjs-jsonapi/dist/utils/index.js"}
|
package/dist/utils/index.mjs
CHANGED
|
@@ -7,12 +7,20 @@ import {
|
|
|
7
7
|
entityObjectSchema,
|
|
8
8
|
exists,
|
|
9
9
|
formatDate,
|
|
10
|
+
getIcon,
|
|
11
|
+
getIconByModule,
|
|
12
|
+
getIconByModuleName,
|
|
13
|
+
getLucideIcon,
|
|
14
|
+
getLucideIconByModule,
|
|
15
|
+
getLucideIconByModuleName,
|
|
10
16
|
getTableComponents,
|
|
11
17
|
getTableOptions,
|
|
12
18
|
useComposedRefs,
|
|
13
19
|
useIsMobile,
|
|
14
20
|
userObjectSchema
|
|
15
|
-
} from "../chunk-
|
|
21
|
+
} from "../chunk-JLN6UWII.mjs";
|
|
22
|
+
import "../chunk-NPPQNSXN.mjs";
|
|
23
|
+
import "../chunk-RBIVEH2K.mjs";
|
|
16
24
|
import "../chunk-PAWJFY3S.mjs";
|
|
17
25
|
export {
|
|
18
26
|
BlockNoteDiffUtil,
|
|
@@ -23,6 +31,12 @@ export {
|
|
|
23
31
|
entityObjectSchema,
|
|
24
32
|
exists,
|
|
25
33
|
formatDate,
|
|
34
|
+
getIcon,
|
|
35
|
+
getIconByModule,
|
|
36
|
+
getIconByModuleName,
|
|
37
|
+
getLucideIcon,
|
|
38
|
+
getLucideIconByModule,
|
|
39
|
+
getLucideIconByModuleName,
|
|
26
40
|
getTableComponents,
|
|
27
41
|
getTableOptions,
|
|
28
42
|
useComposedRefs,
|
package/package.json
CHANGED
package/src/client/index.ts
CHANGED
|
@@ -10,15 +10,17 @@ export * from "./hooks";
|
|
|
10
10
|
export * from "./request";
|
|
11
11
|
export * from "./token";
|
|
12
12
|
|
|
13
|
-
import { useCompanyTableStructure } from "../features/company/hooks";
|
|
14
13
|
// Table generator registration (must be in client-only context)
|
|
14
|
+
import { useCompanyTableStructure } from "../features/company/hooks";
|
|
15
15
|
import { useRoleTableStructure } from "../features/role/hooks";
|
|
16
16
|
import { useUserTableStructure } from "../features/user/hooks";
|
|
17
17
|
import { registerTableGenerator } from "../hooks";
|
|
18
18
|
|
|
19
|
+
export * from "../features/content/hooks";
|
|
19
20
|
export * from "../features/role/hooks";
|
|
20
21
|
export * from "../features/user/hooks";
|
|
21
22
|
|
|
22
23
|
registerTableGenerator("roles", useRoleTableStructure);
|
|
23
24
|
registerTableGenerator("users", useUserTableStructure);
|
|
24
25
|
registerTableGenerator("companies", useCompanyTableStructure);
|
|
26
|
+
// Note: Content registration moved to app-level to support app-specific cellTopic
|
package/src/components/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from "./tables";
|
|
|
10
10
|
|
|
11
11
|
export * from "../features/auth/components";
|
|
12
12
|
export * from "../features/company/components";
|
|
13
|
+
export * from "../features/content/components";
|
|
13
14
|
export * from "../features/feature/components";
|
|
14
15
|
export * from "../features/notification/components";
|
|
15
16
|
export * from "../features/role/components";
|
|
@@ -49,6 +49,15 @@ class ModuleRegistryClass {
|
|
|
49
49
|
}
|
|
50
50
|
throw new Error(`Module not found: ${moduleName}`);
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
findByModelName(modelName: string): ModuleWithPermissions {
|
|
54
|
+
// Direct lookup by registry key (e.g., "Article", "Document")
|
|
55
|
+
const module = this._modules.get(modelName);
|
|
56
|
+
if (!module) {
|
|
57
|
+
throw new Error(`Module not found for model: ${modelName}`);
|
|
58
|
+
}
|
|
59
|
+
return module as ModuleWithPermissions;
|
|
60
|
+
}
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
export const ModuleRegistry = new ModuleRegistryClass();
|
|
@@ -59,6 +68,12 @@ export const Modules = new Proxy({} as ModuleDefinitions, {
|
|
|
59
68
|
if (prop === "findByName") {
|
|
60
69
|
return (name: string) => ModuleRegistry.findByName(name);
|
|
61
70
|
}
|
|
71
|
+
if (prop === "findByModelName") {
|
|
72
|
+
return (name: string) => ModuleRegistry.findByModelName(name);
|
|
73
|
+
}
|
|
62
74
|
return ModuleRegistry.get(prop as keyof ModuleDefinitions);
|
|
63
75
|
},
|
|
64
|
-
}) as ModuleDefinitions & {
|
|
76
|
+
}) as ModuleDefinitions & {
|
|
77
|
+
findByName: (name: string) => ModuleWithPermissions;
|
|
78
|
+
findByModelName: (name: string) => ModuleWithPermissions;
|
|
79
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./lists";
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
4
|
+
import { Modules } from "../../../../core";
|
|
5
|
+
import { usePageUrlGenerator } from "../../../../hooks";
|
|
6
|
+
import { HoverCard, HoverCardContent, HoverCardTrigger, Link } from "../../../../shadcnui";
|
|
7
|
+
import { getIconByModule } from "../../../../utils";
|
|
8
|
+
import { ContributorsList } from "../../../user/components";
|
|
9
|
+
import { ContentInterface } from "../../data";
|
|
10
|
+
|
|
11
|
+
type ContentsListProps = {
|
|
12
|
+
contentList: ContentInterface[];
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function ContentsList({ contentList }: ContentsListProps) {
|
|
16
|
+
const t = useTranslations();
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="flex min-h-0 w-full flex-col overflow-y-auto">
|
|
20
|
+
<h2 className="text-xl font-semibold">{t(`foundations.content.news`)}</h2>
|
|
21
|
+
<div className="flex flex-col">
|
|
22
|
+
{contentList.map((content) => (
|
|
23
|
+
<ContentsListElement content={content} key={content.id} />
|
|
24
|
+
))}
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
type ContentsListElementProps = {
|
|
31
|
+
content: ContentInterface;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function ContentsListElement({ content }: ContentsListElementProps) {
|
|
35
|
+
const generateUrl = usePageUrlGenerator();
|
|
36
|
+
|
|
37
|
+
const contentModule = content.contentType ? Modules.findByModelName(content.contentType) : undefined;
|
|
38
|
+
const link = contentModule ? generateUrl({ page: contentModule, id: content.id }) : "#";
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div className="hover:bg-muted flex w-full flex-col gap-y-2 border-b p-2 py-4">
|
|
42
|
+
<div className="flex w-full justify-between gap-x-2">
|
|
43
|
+
<HoverCard>
|
|
44
|
+
<HoverCardTrigger asChild>
|
|
45
|
+
<Link href={link} className="flex w-full items-center justify-start gap-2 font-semibold">
|
|
46
|
+
{contentModule && getIconByModule({ module: contentModule, className: "h-4 w-4" })}
|
|
47
|
+
{content.name}
|
|
48
|
+
</Link>
|
|
49
|
+
</HoverCardTrigger>
|
|
50
|
+
<HoverCardContent className="flex max-h-96 w-96 flex-col gap-y-4 overflow-y-auto">
|
|
51
|
+
<Link href={link} className="font-semibold">
|
|
52
|
+
{content.name}
|
|
53
|
+
</Link>
|
|
54
|
+
<div className="text-xs">{content.abstract}</div>
|
|
55
|
+
</HoverCardContent>
|
|
56
|
+
</HoverCard>
|
|
57
|
+
<ContributorsList content={content} />
|
|
58
|
+
</div>
|
|
59
|
+
{/* <div className="text-muted-foreground text-xs">{content.tldr}</div>
|
|
60
|
+
{content.topics.length > 0 && (
|
|
61
|
+
<div className="flex w-full items-center justify-between">
|
|
62
|
+
<TopicBadgesList topics={content.topics} limit={1} />
|
|
63
|
+
</div>
|
|
64
|
+
)} */}
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
4
|
+
import { ContentListTable } from "../../../../components";
|
|
5
|
+
import { Modules } from "../../../../core";
|
|
6
|
+
import { DataListRetriever, useDataListRetriever } from "../../../../hooks";
|
|
7
|
+
import { ContentFields, ContentInterface, ContentService } from "../../data";
|
|
8
|
+
|
|
9
|
+
type ContentsListByIdProps = {
|
|
10
|
+
contentIds: string[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function ContentsListById({ contentIds }: ContentsListByIdProps) {
|
|
14
|
+
const t = useTranslations();
|
|
15
|
+
|
|
16
|
+
const data: DataListRetriever<ContentInterface> = useDataListRetriever({
|
|
17
|
+
module: Modules.Content,
|
|
18
|
+
retriever: (params) => ContentService.findMany(params),
|
|
19
|
+
retrieverParams: { contentIds: contentIds },
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ContentListTable
|
|
24
|
+
data={data}
|
|
25
|
+
fields={[ContentFields.name, ContentFields.authors, ContentFields.updatedAt]}
|
|
26
|
+
tableGeneratorType={Modules.Content}
|
|
27
|
+
title={t(`generic.relevant`)}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useTranslations } from "next-intl";
|
|
4
|
+
import { ContentListTable } from "../../../../components";
|
|
5
|
+
import { Modules } from "../../../../core";
|
|
6
|
+
import { DataListRetriever, useDataListRetriever } from "../../../../hooks";
|
|
7
|
+
import { ContentFields, ContentInterface, ContentService } from "../../data";
|
|
8
|
+
|
|
9
|
+
type RelevantContentsListProps = {
|
|
10
|
+
id: string;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export function RelevantContentsList({ id }: RelevantContentsListProps) {
|
|
14
|
+
const t = useTranslations();
|
|
15
|
+
|
|
16
|
+
const data: DataListRetriever<ContentInterface> = useDataListRetriever({
|
|
17
|
+
module: Modules.Content,
|
|
18
|
+
retriever: (params) => ContentService.findRelevant(params),
|
|
19
|
+
retrieverParams: { id: id },
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<ContentListTable
|
|
24
|
+
data={data}
|
|
25
|
+
fields={[ContentFields.name, ContentFields.authors, ContentFields.relevance, ContentFields.updatedAt]}
|
|
26
|
+
tableGeneratorType={Modules.Content}
|
|
27
|
+
title={t(`generic.relevant`)}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./useContentTableStructure";
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { ColumnDef } from "@tanstack/react-table";
|
|
4
|
+
import { useTranslations } from "next-intl";
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
import { cellDate, cellId, ContributorsList } from "../../../components";
|
|
7
|
+
import { Modules } from "../../../core";
|
|
8
|
+
import { TableContent, usePageUrlGenerator, UseTableStructureHook } from "../../../hooks";
|
|
9
|
+
import { Link, Tooltip, TooltipContent, TooltipTrigger } from "../../../shadcnui";
|
|
10
|
+
import { getIconByModule } from "../../../utils";
|
|
11
|
+
import { ContentFields, ContentInterface } from "../data";
|
|
12
|
+
|
|
13
|
+
export const useContentTableStructure = <U extends string = ContentFields>(
|
|
14
|
+
params: Parameters<UseTableStructureHook<ContentInterface, U>>[0],
|
|
15
|
+
): ReturnType<UseTableStructureHook<ContentInterface, U>> => {
|
|
16
|
+
const t = useTranslations();
|
|
17
|
+
const generateUrl = usePageUrlGenerator();
|
|
18
|
+
|
|
19
|
+
const tableData = useMemo(() => {
|
|
20
|
+
return params.data.map((content: ContentInterface) => {
|
|
21
|
+
const entry: TableContent<ContentInterface> = {
|
|
22
|
+
jsonApiData: content,
|
|
23
|
+
};
|
|
24
|
+
entry[ContentFields.contentId] = content.id;
|
|
25
|
+
params.fields.forEach((field) => {
|
|
26
|
+
entry[field as string] = content[field as keyof ContentInterface];
|
|
27
|
+
});
|
|
28
|
+
return entry;
|
|
29
|
+
});
|
|
30
|
+
}, [params.data, params.fields]);
|
|
31
|
+
|
|
32
|
+
const fieldColumnMap: Partial<Record<string, () => any>> = {
|
|
33
|
+
[ContentFields.contentId]: () =>
|
|
34
|
+
cellId({
|
|
35
|
+
name: "contentId",
|
|
36
|
+
checkedIds: params.checkedIds,
|
|
37
|
+
toggleId: params.toggleId,
|
|
38
|
+
}),
|
|
39
|
+
[ContentFields.name]: () => ({
|
|
40
|
+
id: "name",
|
|
41
|
+
accessorKey: "name",
|
|
42
|
+
header: t(`foundations.content.fields.name.label`),
|
|
43
|
+
cell: ({ row }: { row: TableContent<ContentInterface> }) => {
|
|
44
|
+
const content: ContentInterface = row.original.jsonApiData;
|
|
45
|
+
|
|
46
|
+
const contentModule = content.contentType ? Modules.findByModelName(content.contentType) : undefined;
|
|
47
|
+
const link = contentModule ? generateUrl({ page: contentModule, id: content.id }) : "#";
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Tooltip>
|
|
51
|
+
<TooltipTrigger className="flex items-center justify-start space-x-2">
|
|
52
|
+
<>
|
|
53
|
+
{contentModule && getIconByModule({ module: contentModule, className: "h-4 w-4" })}
|
|
54
|
+
<Link href={link}>{content.name}</Link>
|
|
55
|
+
</>
|
|
56
|
+
</TooltipTrigger>
|
|
57
|
+
<TooltipContent>{content.tldr}</TooltipContent>
|
|
58
|
+
</Tooltip>
|
|
59
|
+
);
|
|
60
|
+
},
|
|
61
|
+
enableSorting: false,
|
|
62
|
+
enableHiding: false,
|
|
63
|
+
}),
|
|
64
|
+
[ContentFields.relevance]: () => ({
|
|
65
|
+
id: "relevance",
|
|
66
|
+
accessorKey: "relevance",
|
|
67
|
+
header: t(`generic.relevance`),
|
|
68
|
+
cell: ({ row }: { row: TableContent<ContentInterface> }) => {
|
|
69
|
+
const content: ContentInterface = row.original.jsonApiData;
|
|
70
|
+
|
|
71
|
+
if (!content.relevance) return <></>;
|
|
72
|
+
|
|
73
|
+
const response = `${content.relevance.toFixed(0)}%`;
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div className="relative flex h-5 w-20 items-center justify-center overflow-hidden rounded border text-center">
|
|
77
|
+
<div
|
|
78
|
+
className={`bg-accent absolute top-0 left-0 h-full opacity-${Math.round(content.relevance)}`}
|
|
79
|
+
style={{ width: `${content.relevance}%` }}
|
|
80
|
+
></div>
|
|
81
|
+
<span
|
|
82
|
+
className={`relative text-xs ${content.relevance < 40 ? "text-muted-foreground" : "text-accent-foreground font-semibold"}`}
|
|
83
|
+
>
|
|
84
|
+
{response}
|
|
85
|
+
</span>
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
},
|
|
89
|
+
enableSorting: false,
|
|
90
|
+
enableHiding: false,
|
|
91
|
+
}),
|
|
92
|
+
[ContentFields.authors]: () => ({
|
|
93
|
+
id: "authors",
|
|
94
|
+
accessorKey: "authors",
|
|
95
|
+
header: t(`generic.relationships.author.label`),
|
|
96
|
+
cell: ({ row }: { row: TableContent<ContentInterface> }) => {
|
|
97
|
+
const content: ContentInterface = row.original.jsonApiData;
|
|
98
|
+
return <ContributorsList content={content} />;
|
|
99
|
+
},
|
|
100
|
+
enableSorting: false,
|
|
101
|
+
enableHiding: false,
|
|
102
|
+
}),
|
|
103
|
+
[ContentFields.createdAt]: () =>
|
|
104
|
+
cellDate({
|
|
105
|
+
name: "createdAt",
|
|
106
|
+
title: t(`generic.date.create`),
|
|
107
|
+
}),
|
|
108
|
+
[ContentFields.updatedAt]: () =>
|
|
109
|
+
cellDate({
|
|
110
|
+
name: "updatedAt",
|
|
111
|
+
title: t(`generic.date.update`),
|
|
112
|
+
}),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const columns = useMemo(() => {
|
|
116
|
+
return params.fields
|
|
117
|
+
.map((field) => {
|
|
118
|
+
// First check local fieldColumnMap
|
|
119
|
+
const localHandler = fieldColumnMap[field];
|
|
120
|
+
if (localHandler) return localHandler();
|
|
121
|
+
|
|
122
|
+
// Fallback to customCells from context
|
|
123
|
+
const customHandler = params.context?.customCells?.[field];
|
|
124
|
+
if (customHandler) return customHandler({ t });
|
|
125
|
+
|
|
126
|
+
return undefined;
|
|
127
|
+
})
|
|
128
|
+
.filter((col) => col !== undefined) as ColumnDef<TableContent<ContentInterface>>[];
|
|
129
|
+
}, [params.fields, fieldColumnMap, t, generateUrl, params.context?.customCells]);
|
|
130
|
+
|
|
131
|
+
return useMemo(() => ({ data: tableData, columns: columns }), [tableData, columns]);
|
|
132
|
+
};
|
package/src/permissions/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { LucideIcon } from "lucide-react";
|
|
1
2
|
import { ApiRequestDataTypeInterface } from "../core/interfaces/ApiRequestDataTypeInterface";
|
|
2
3
|
import { FieldSelector } from "../core/fields/FieldSelector";
|
|
3
4
|
|
|
@@ -80,6 +81,7 @@ export type ModuleWithPermissions = ApiRequestDataTypeInterface & {
|
|
|
80
81
|
pageUrl?: string;
|
|
81
82
|
feature?: string;
|
|
82
83
|
moduleId?: string;
|
|
84
|
+
icon?: LucideIcon;
|
|
83
85
|
inclusions?: Record<
|
|
84
86
|
string,
|
|
85
87
|
{
|
|
@@ -99,6 +101,7 @@ export type ModuleFactory = (params: {
|
|
|
99
101
|
model: any;
|
|
100
102
|
feature?: string;
|
|
101
103
|
moduleId?: string;
|
|
104
|
+
icon?: LucideIcon;
|
|
102
105
|
inclusions?: Record<
|
|
103
106
|
string,
|
|
104
107
|
{
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { LucideIcon } from "lucide-react";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
import { ApiDataInterface, Modules } from "../core";
|
|
4
|
+
import { ContentInterface } from "../features/content/data/content.interface";
|
|
5
|
+
import { ModuleWithPermissions } from "../permissions";
|
|
6
|
+
import { cn } from "./cn";
|
|
7
|
+
|
|
8
|
+
export const getIconByModule = (params: { module: ModuleWithPermissions; className?: string }): ReactNode => {
|
|
9
|
+
const IconComponent = getLucideIconByModule({ module: params.module });
|
|
10
|
+
if (!IconComponent) return null;
|
|
11
|
+
return <IconComponent className={cn(``, params.className)} />;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const getIcon = (params: { element: ApiDataInterface; className?: string }): ReactNode => {
|
|
15
|
+
const IconComponent = getLucideIcon({ element: params.element });
|
|
16
|
+
if (!IconComponent) return null;
|
|
17
|
+
return <IconComponent className={cn(``, params.className)} />;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const getIconByModuleName = (params: { name: string; className?: string }): ReactNode => {
|
|
21
|
+
return getIconByModule({ module: Modules.findByModelName(params.name), className: params.className });
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const getLucideIcon = (params: { element: ApiDataInterface }): LucideIcon | null => {
|
|
25
|
+
if (params.element.type === "contents") {
|
|
26
|
+
const contentType = (params.element as ContentInterface).contentType;
|
|
27
|
+
if (!contentType) return null;
|
|
28
|
+
return getLucideIconByModule({ module: Modules.findByModelName(contentType) });
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return getLucideIconByModule({ module: Modules.findByName(params.element.type) });
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const getLucideIconByModule = (params: { module: ModuleWithPermissions }): LucideIcon | null => {
|
|
35
|
+
return params.module.icon ?? null;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const getLucideIconByModuleName = (params: { name: string }): LucideIcon | null => {
|
|
39
|
+
return getLucideIconByModule({ module: Modules.findByModelName(params.name) });
|
|
40
|
+
};
|
package/src/utils/index.ts
CHANGED