From bda088a23482611cd6a5eb5b8121540c66382646 Mon Sep 17 00:00:00 2001 From: Abhishekfm Date: Fri, 14 Nov 2025 13:29:47 +0530 Subject: [PATCH 1/3] Nextjs and other dependencies have been updated with required code changes. --- .eslintrc.js | 20 - .eslintrc.json | 10 - .../[collaborativeSlug]/page.tsx | 13 +- .../(user)/components/ListingComponent.tsx | 135 +- .../datasets/[datasetIdentifier]/page.tsx | 15 +- .../publishers/[publisherSlug]/page.tsx | 16 +- .../organization/[organizationSlug]/page.tsx | 14 +- .../(user)/sectors/[sectorSlug]/page.tsx | 12 +- .../usecases/[useCaseSlug]/Dashboards.tsx | 24 +- .../(user)/usecases/[useCaseSlug]/page.tsx | 9 +- .../[entitySlug]/admin/addUser.tsx | 8 +- .../[entitySlug]/aimodels/edit/[id]/page.tsx | 7 +- .../[entitySlug]/aimodels/page.tsx | 22 +- .../charts/components/ChartsList.tsx | 16 +- .../[entitySlug]/collaboratives/page.tsx | 133 +- .../[id]/edit/components/EditMetadata.tsx | 3 +- .../[entitySlug]/dataset/[id]/edit/layout.tsx | 5 +- .../dataset/[id]/edit/metadata/page.tsx | 5 +- .../[entitySlug]/dataset/[id]/edit/page.tsx | 13 +- .../edit/resources/components/PreviewData.tsx | 1 - .../dataset/[id]/edit/resources/page.tsx | 5 +- .../dataset/[id]/edit/review/page.tsx | 7 +- .../[entitySlug]/dataset/[id]/page.tsx | 26 +- .../dataset/components/content.tsx | 54 +- .../dataset/new/components/new-dataset.tsx | 7 +- .../[entitySlug]/dataset/page-layout.tsx | 45 +- .../[entitySlug]/dataset/page.tsx | 142 +- .../[entityType]/[entitySlug]/page.tsx | 18 +- .../usecases/edit/[id]/dashboards/page.tsx | 52 +- .../[entitySlug]/usecases/page.tsx | 100 +- .../dashboard/components/main-nav.tsx | 4 +- app/[locale]/layout.tsx | 11 +- app/sitemap/[entityPage]/route.ts | 4 +- eslint.config.mjs | 56 + global.d.ts | 2 +- hooks/use-meta-key-press.ts | 8 +- hooks/use-on-click-outside.tsx | 2 +- package-lock.json | 18358 +++++++++------- package.json | 27 +- postcss.config.js | 2 +- styles/globals.css | 2 - 41 files changed, 11521 insertions(+), 7892 deletions(-) delete mode 100644 .eslintrc.js delete mode 100644 .eslintrc.json create mode 100644 eslint.config.mjs diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 580c14e7..00000000 --- a/.eslintrc.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - parser: '@typescript-eslint/parser', - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'next', - 'prettier', - ], - rules: { - 'no-unused-vars': 'off', - '@typescript-eslint/no-unused-vars': ['warn'], - '@typescript-eslint/no-explicit-any': ['off'], - 'react/display-name': 'off', - '@next/next/no-html-link-for-pages': 'off', - 'prefer-const': 'off', - '@typescript-eslint/no-var-requires': 'off', - '@next/next/no-img-element': 'off', - }, - ignorePatterns: ['**/generated/**/*.ts', 'node_modules/', 'dist/'], -} diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 10c89b4e..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "ignorePatterns": ["**/generated/**/*.ts"], - "extends": ["eslint:recommended", "next"], - "rules": { - "no-unused-vars": "off", - // "@typescript-eslint/no-unused-vars": ["warn"], - "react/display-name": "off", - "@next/next/no-html-link-for-pages": "off" - } -} diff --git a/app/[locale]/(user)/collaboratives/[collaborativeSlug]/page.tsx b/app/[locale]/(user)/collaboratives/[collaborativeSlug]/page.tsx index 4be3188a..2fc14eed 100644 --- a/app/[locale]/(user)/collaboratives/[collaborativeSlug]/page.tsx +++ b/app/[locale]/(user)/collaboratives/[collaborativeSlug]/page.tsx @@ -26,10 +26,15 @@ const CollaborativeInfoQuery = graphql(` export async function generateMetadata({ params, }: { - params: { collaborativeSlug: string }; + params: Promise<{ collaborativeSlug: string }>; }): Promise { + const { collaborativeSlug } = await params; try { - const data = await GraphQLPublic(CollaborativeInfoQuery, {}, { pk: params.collaborativeSlug }); + const data = await GraphQLPublic( + CollaborativeInfoQuery, + {}, + { pk: collaborativeSlug } + ); const Collaborative = data?.collaborative; return generatePageMetadata({ @@ -41,7 +46,7 @@ export async function generateMetadata({ openGraph: { type: 'article', locale: 'en_US', - url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/collaboratives/${params.collaborativeSlug}`, + url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/collaboratives/${collaborativeSlug}`, title: `${Collaborative?.title} | Collaborative Data | CivicDataSpace`, description: Collaborative?.summary || @@ -59,7 +64,7 @@ export async function generateMetadata({ openGraph: { type: 'article', locale: 'en_US', - url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/collaboratives/${params.collaborativeSlug}`, + url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/collaboratives/${collaborativeSlug}`, title: `Collaborative Details | CivicDataSpace`, description: `Explore open data and curated datasets in this collaborative.`, siteName: 'CivicDataSpace', diff --git a/app/[locale]/(user)/components/ListingComponent.tsx b/app/[locale]/(user)/components/ListingComponent.tsx index 96c3a297..16f5c358 100644 --- a/app/[locale]/(user)/components/ListingComponent.tsx +++ b/app/[locale]/(user)/components/ListingComponent.tsx @@ -1,8 +1,11 @@ -'use client' +'use client'; -import GraphqlPagination from '@/app/[locale]/dashboard/components/GraphqlPagination/graphqlPagination'; +import React, { useEffect, useMemo, useReducer, useRef, useState } from 'react'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; +import GraphqlPagination from '@/app/[locale]/dashboard/components/GraphqlPagination/graphqlPagination'; +import { fetchData } from '@/fetch'; +import { useTourTrigger } from '@/hooks/use-tour-trigger'; import { Button, ButtonGroup, @@ -14,53 +17,52 @@ import { Text, Tray, } from 'opub-ui'; -import React, { useEffect, useMemo, useReducer, useRef, useState } from 'react'; +import { cn, formatDate } from '@/lib/utils'; import BreadCrumbs from '@/components/BreadCrumbs'; import { Icons } from '@/components/icons'; import { Loading } from '@/components/loading'; -import { fetchData } from '@/fetch'; -import { cn, formatDate } from '@/lib/utils'; import Filter from '../datasets/components/FIlter/Filter'; import Styles from '../datasets/dataset.module.scss'; -import { useTourTrigger } from '@/hooks/use-tour-trigger'; // Helper function to strip markdown and HTML tags for card preview const stripMarkdown = (markdown: string): string => { if (!markdown) return ''; - return markdown - // Remove code blocks first (before other replacements) - .replace(/```[\s\S]*?```/g, '') - // Remove inline code - .replace(/`([^`]+)`/g, '$1') - // Remove images - .replace(/!\[([^\]]*)\]\([^)]+\)/g, '$1') - // Remove links - .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') - // Remove headers - .replace(/^#{1,6}\s+/gm, '') - // Remove bold - .replace(/\*\*([^*]+)\*\*/g, '$1') - .replace(/__([^_]+)__/g, '$1') - // Remove italic - .replace(/\*([^*]+)\*/g, '$1') - .replace(/_([^_]+)_/g, '$1') - // Remove strikethrough - .replace(/~~([^~]+)~~/g, '$1') - // Remove blockquotes - .replace(/^\s*>\s+/gm, '') - // Remove horizontal rules - .replace(/^(-{3,}|_{3,}|\*{3,})$/gm, '') - // Remove list markers - .replace(/^\s*[-*+]\s+/gm, '') - .replace(/^\s*\d+\.\s+/gm, '') - // Remove HTML tags - .replace(/<[^>]*>/g, '') - // Remove extra whitespace and newlines - .replace(/\n\s*\n/g, '\n') - .replace(/\n/g, ' ') - .replace(/\s+/g, ' ') - .trim(); + return ( + markdown + // Remove code blocks first (before other replacements) + .replace(/```[\s\S]*?```/g, '') + // Remove inline code + .replace(/`([^`]+)`/g, '$1') + // Remove images + .replace(/!\[([^\]]*)\]\([^)]+\)/g, '$1') + // Remove links + .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') + // Remove headers + .replace(/^#{1,6}\s+/gm, '') + // Remove bold + .replace(/\*\*([^*]+)\*\*/g, '$1') + .replace(/__([^_]+)__/g, '$1') + // Remove italic + .replace(/\*([^*]+)\*/g, '$1') + .replace(/_([^_]+)_/g, '$1') + // Remove strikethrough + .replace(/~~([^~]+)~~/g, '$1') + // Remove blockquotes + .replace(/^\s*>\s+/gm, '') + // Remove horizontal rules + .replace(/^(-{3,}|_{3,}|\*{3,})$/gm, '') + // Remove list markers + .replace(/^\s*[-*+]\s+/gm, '') + .replace(/^\s*\d+\.\s+/gm, '') + // Remove HTML tags + .replace(/<[^>]*>/g, '') + // Remove extra whitespace and newlines + .replace(/\n\s*\n/g, '\n') + .replace(/\n/g, ' ') + .replace(/\s+/g, ' ') + .trim() + ); }; // Interfaces @@ -170,7 +172,9 @@ const useUrlParams = ( // Merge locked filters with URL filters Object.entries(lockedFilters).forEach(([category, values]) => { if (values.length > 0) { - filters[category] = Array.from(new Set([...(filters[category] || []), ...values])); + filters[category] = Array.from( + new Set([...(filters[category] || []), ...values]) + ); } }); @@ -258,7 +262,7 @@ const ListingComponent: React.FC = ({ lockedFilters = {}, }) => { useTourTrigger(true, 1500); - + const [facets, setFacets] = useState<{ results: any[]; total: number; @@ -273,7 +277,10 @@ const ListingComponent: React.FC = ({ const datasetDetails = facets?.results ?? []; // Stabilize lockedFilters reference to prevent infinite loops - const stableLockedFilters = useMemo(() => lockedFilters, [JSON.stringify(lockedFilters)]); + const stableLockedFilters = useMemo( + () => lockedFilters, + [JSON.stringify(lockedFilters)] + ); useUrlParams(queryParams, setQueryParams, setVariables, stableLockedFilters); const latestFetchId = useRef(0); @@ -282,7 +289,7 @@ const ListingComponent: React.FC = ({ if (variables) { const currentFetchId = ++latestFetchId.current; - fetchData(type,variables) + fetchData(type, variables) .then((res) => { // Only set if this is the latest call if (currentFetchId === latestFetchId.current) { @@ -341,7 +348,7 @@ const ListingComponent: React.FC = ({ label: bucket.key, value: bucket.key, })); - } + } // Handle key-value object format (current backend format) else if (value && typeof value === 'object' && !Array.isArray(value)) { acc[key] = Object.entries(value).map(([label, count]) => ({ @@ -400,7 +407,10 @@ const ListingComponent: React.FC = ({
-
+
= ({ .filter((value) => category !== 'sort') .map((value) => { // Check if this filter value is locked - const isLocked = stableLockedFilters[category]?.includes(value); + const isLocked = + stableLockedFilters[category]?.includes(value); return ( handleRemoveFilter(category, value)} + onRemove={ + isLocked + ? undefined + : () => handleRemoveFilter(category, value) + } > {value} @@ -552,14 +567,14 @@ const ListingComponent: React.FC = ({ : item?.organization?.logo ? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${item.organization.logo}` : '/org.png'; - - const geographies = item.geographies && item.geographies.length > 0 - ? item.geographies - : null; - const sdgs = item.sdgs && item.sdgs.length > 0 - ? item.sdgs - : null; + const geographies = + item.geographies && item.geographies.length > 0 + ? item.geographies + : null; + + const sdgs = + item.sdgs && item.sdgs.length > 0 ? item.sdgs : null; const MetadataContent = [ { @@ -593,7 +608,9 @@ const ListingComponent: React.FC = ({ if (sdgs && sdgs.length > 0) { // Format SDGs for display - const sdgDisplay = sdgs.map((sdg: any) => `${sdg.code} - ${sdg.name}`).join(', '); + const sdgDisplay = sdgs + .map((sdg: any) => `${sdg.code} - ${sdg.name}`) + .join(', '); MetadataContent.push({ icon: Icons.target, @@ -657,7 +674,13 @@ const ListingComponent: React.FC = ({ } iconColor="warning" href={`${redirectionURL}/${item.id}`} - data-tour={index === 0 && type === 'dataset' ? 'dataset-card' : index === 0 && type === 'usecase' ? 'usecase-card' : undefined} + data-tour={ + index === 0 && type === 'dataset' + ? 'dataset-card' + : index === 0 && type === 'usecase' + ? 'usecase-card' + : undefined + } /> ); })} diff --git a/app/[locale]/(user)/datasets/[datasetIdentifier]/page.tsx b/app/[locale]/(user)/datasets/[datasetIdentifier]/page.tsx index f4803aa1..e38dd185 100644 --- a/app/[locale]/(user)/datasets/[datasetIdentifier]/page.tsx +++ b/app/[locale]/(user)/datasets/[datasetIdentifier]/page.tsx @@ -21,13 +21,14 @@ const datasetMetaQuery: any = graphql(` export async function generateMetadata({ params, }: { - params: { datasetIdentifier: string }; + params: Promise<{ datasetIdentifier: string }>; }) { + const { datasetIdentifier } = await params; try { const res: any = await GraphQL( datasetMetaQuery, {}, - { datasetId: params.datasetIdentifier } + { datasetId: datasetIdentifier } ); const dataset = res?.getDataset; @@ -38,7 +39,7 @@ export async function generateMetadata({ openGraph: { type: 'dataset', locale: 'en_US', - url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/datasets/${params.datasetIdentifier}`, + url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/datasets/${datasetIdentifier}`, title: dataset?.title, description: dataset?.description, siteName: 'CivicDataSpace', @@ -51,10 +52,12 @@ export async function generateMetadata({ } } -export default function Page({ +export default async function Page({ params, }: { - params: { datasetIdentifier: string }; + params: Promise<{ datasetIdentifier: string }>; }) { - return ; + const { datasetIdentifier } = await params; + + return ; } diff --git a/app/[locale]/(user)/publishers/[publisherSlug]/page.tsx b/app/[locale]/(user)/publishers/[publisherSlug]/page.tsx index b527b770..913afd5e 100644 --- a/app/[locale]/(user)/publishers/[publisherSlug]/page.tsx +++ b/app/[locale]/(user)/publishers/[publisherSlug]/page.tsx @@ -21,12 +21,13 @@ const userInfo = graphql(` export async function generateMetadata({ params, }: { - params: { publisherSlug: string }; + params: Promise<{ publisherSlug: string }>; }): Promise { + const { publisherSlug } = await params; const data = await GraphQL( userInfo, {}, - { userId: extractPublisherId(params.publisherSlug) } + { userId: extractPublisherId(publisherSlug) } ); const user = data.userById; @@ -49,7 +50,7 @@ export async function generateMetadata({ user?.bio || 'Explore datasets and use cases by this publisher.', type: 'profile', siteName: 'CivicDataSpace', - url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/publishers/${params.publisherSlug}`, + url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/publishers/${publisherSlug}`, image: user?.profilePicture?.url ? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${user.profilePicture.url}` : `${process.env.NEXT_PUBLIC_PLATFORM_URL}/og.png`, @@ -58,14 +59,13 @@ export async function generateMetadata({ }); } -export default function PublisherPage({ +export default async function PublisherPage({ params, }: { - params: { publisherSlug: string }; + params: Promise<{ publisherSlug: string }>; }) { + const { publisherSlug } = await params; return ( - + ); } diff --git a/app/[locale]/(user)/publishers/organization/[organizationSlug]/page.tsx b/app/[locale]/(user)/publishers/organization/[organizationSlug]/page.tsx index 5e9f25a9..5f6962cd 100644 --- a/app/[locale]/(user)/publishers/organization/[organizationSlug]/page.tsx +++ b/app/[locale]/(user)/publishers/organization/[organizationSlug]/page.tsx @@ -21,12 +21,13 @@ const orgDataQuery = graphql(` export async function generateMetadata({ params, }: { - params: { organizationSlug: string }; + params: Promise<{ organizationSlug: string }>; }): Promise { + const { organizationSlug } = await params; const data = await GraphQL( orgDataQuery, {}, - { id: extractPublisherId(params.organizationSlug) } + { id: extractPublisherId(organizationSlug) } ); const org = data.organization; @@ -49,7 +50,7 @@ export async function generateMetadata({ org?.description || 'Explore datasets and use cases by this publisher.', type: 'profile', siteName: 'CivicDataSpace', - url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/publishers/${params.organizationSlug}`, + url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/publishers/${organizationSlug}`, image: org?.logo?.url ? `${process.env.NEXT_PUBLIC_BACKEND_URL}/${org.logo.url}` : `${process.env.NEXT_PUBLIC_PLATFORM_URL}/og.png`, @@ -58,14 +59,15 @@ export async function generateMetadata({ }); } -export default function OrgPage({ +export default async function OrgPage({ params, }: { - params: { organizationSlug: string }; + params: Promise<{ organizationSlug: string }>; }) { + const { organizationSlug } = await params; return ( ); } diff --git a/app/[locale]/(user)/sectors/[sectorSlug]/page.tsx b/app/[locale]/(user)/sectors/[sectorSlug]/page.tsx index b81e5bdd..eaf319b8 100644 --- a/app/[locale]/(user)/sectors/[sectorSlug]/page.tsx +++ b/app/[locale]/(user)/sectors/[sectorSlug]/page.tsx @@ -20,12 +20,13 @@ const sectorQueryDoc = graphql(` export async function generateMetadata({ params, }: { - params: { sectorSlug: string }; + params: Promise<{ sectorSlug: string }>; }) { + const { sectorSlug } = await params; const data = await GraphQL( sectorQueryDoc, {}, - { filters: { slug: params.sectorSlug } } + { filters: { slug: sectorSlug } } ); const sector = data?.sectors?.[0]; @@ -38,7 +39,7 @@ export async function generateMetadata({ openGraph: { type: 'article', locale: 'en_US', - url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/sectors/${params.sectorSlug}`, + url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/sectors/${sectorSlug}`, title: `${sector?.name} | Sector Data | CivicDataSpace`, description: sector?.description || @@ -52,12 +53,13 @@ export async function generateMetadata({ const SectorDetailsPage = async ({ params, }: { - params: { sectorSlug: string }; + params: Promise<{ sectorSlug: string }>; }) => { + const { sectorSlug } = await params; const data = await GraphQL( sectorQueryDoc, {}, - { filters: { slug: params.sectorSlug } } + { filters: { slug: sectorSlug } } ); const sector = data?.sectors?.[0]; diff --git a/app/[locale]/(user)/usecases/[useCaseSlug]/Dashboards.tsx b/app/[locale]/(user)/usecases/[useCaseSlug]/Dashboards.tsx index b8525066..056e45bc 100644 --- a/app/[locale]/(user)/usecases/[useCaseSlug]/Dashboards.tsx +++ b/app/[locale]/(user)/usecases/[useCaseSlug]/Dashboards.tsx @@ -18,16 +18,28 @@ const DashboardsList: any = graphql(` `); const Dashboards = () => { - const params = useParams(); + const params = useParams<{ useCaseSlug?: string }>(); + const useCaseSlug = params?.useCaseSlug; + + const usecaseId = + typeof useCaseSlug === 'string' ? Number.parseInt(useCaseSlug, 10) : NaN; + + const isValidId = !Number.isNaN(usecaseId); + const { data, isLoading } = useQuery<{ usecaseDashboards: any }>( - ['fetch_dashboardData', params.useCaseSlug], - () => GraphQL(DashboardsList, {}, { usecaseId: +params.useCaseSlug }), + ['fetch_dashboardData', usecaseId], + () => GraphQL(DashboardsList, {}, { usecaseId }), { refetchOnMount: true, refetchOnReconnect: true, + enabled: isValidId, } ); + if (!isValidId) { + return null; + } + return (
{isLoading ? ( @@ -51,7 +63,11 @@ const Dashboards = () => { className="flex h-[100px] w-full items-center rounded-4 bg-surfaceDefault p-5 shadow-card" target="_blank" > - + {dashboard.name} diff --git a/app/[locale]/(user)/usecases/[useCaseSlug]/page.tsx b/app/[locale]/(user)/usecases/[useCaseSlug]/page.tsx index ed9223dc..6c87caf2 100644 --- a/app/[locale]/(user)/usecases/[useCaseSlug]/page.tsx +++ b/app/[locale]/(user)/usecases/[useCaseSlug]/page.tsx @@ -26,10 +26,11 @@ const UseCaseInfoQuery = graphql(` export async function generateMetadata({ params, }: { - params: { useCaseSlug: string }; + params: Promise<{ useCaseSlug: string }>; }): Promise { + const { useCaseSlug } = await params; try { - const data = await GraphQLPublic(UseCaseInfoQuery, {}, { pk: params.useCaseSlug }); + const data = await GraphQLPublic(UseCaseInfoQuery, {}, { pk: useCaseSlug }); const UseCase = data?.useCase; return generatePageMetadata({ @@ -41,7 +42,7 @@ export async function generateMetadata({ openGraph: { type: 'article', locale: 'en_US', - url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/usecases/${params.useCaseSlug}`, + url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/usecases/${useCaseSlug}`, title: `${UseCase?.title} | Sector Data | CivicDataSpace`, description: UseCase?.summary || @@ -59,7 +60,7 @@ export async function generateMetadata({ openGraph: { type: 'article', locale: 'en_US', - url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/usecases/${params.useCaseSlug}`, + url: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/usecases/${useCaseSlug}`, title: `Use Case Details | CivicDataSpace`, description: `Explore open data and curated datasets in this use case.`, siteName: 'CivicDataSpace', diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/admin/addUser.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/admin/addUser.tsx index b3056dc6..dc5da2e5 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/admin/addUser.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/admin/addUser.tsx @@ -265,9 +265,11 @@ const AddUser = ({ disabled={!formData.userId || !formData.roleId} onClick={() => { setIsOpen(false); - isEdit - ? updateMutate({ input: formData }) - : mutate({ input: formData }); + if (isEdit) { + updateMutate({ input: formData }); + } else { + mutate({ input: formData }); + } }} > {isEdit ? 'Update' : 'Add'} diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/aimodels/edit/[id]/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/aimodels/edit/[id]/page.tsx index 8998e2d5..24d728a9 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/aimodels/edit/[id]/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/aimodels/edit/[id]/page.tsx @@ -1,12 +1,13 @@ import { redirect } from 'next/navigation'; -export default function AIModelEditPage({ +export default async function AIModelEditPage({ params, }: { - params: { entityType: string; entitySlug: string; id: string }; + params: Promise<{ entityType: string; entitySlug: string; id: string }>; }) { + const { entityType, entitySlug, id } = await params; // Redirect to the details page by default redirect( - `/dashboard/${params.entityType}/${params.entitySlug}/aimodels/edit/${params.id}/details` + `/dashboard/${entityType}/${entitySlug}/aimodels/edit/${id}/details` ); } diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/aimodels/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/aimodels/page.tsx index 4bee0a5f..d59aa7df 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/aimodels/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/aimodels/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useEffect } from 'react'; +import { use, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { graphql } from '@/gql'; import { useMutation, useQuery } from '@tanstack/react-query'; @@ -56,8 +56,12 @@ const createAIModel: any = graphql(` export default function AIModelsPage({ params, }: { - params: { entityType: string; entitySlug: string }; + params: Promise<{ entityType: string; entitySlug: string }>; }) { + const { entityType, entitySlug } = use(params) as { + entityType: string; + entitySlug: string; + }; const router = useRouter(); const [navigationTab, setNavigationTab] = useQueryState('tab', parseAsString); @@ -86,7 +90,7 @@ export default function AIModelsPage({ GraphQL( allAIModels, { - [params.entityType]: params.entitySlug, + [entityType]: entitySlug, }, { filters: { @@ -118,7 +122,7 @@ export default function AIModelsPage({ GraphQL( deleteAIModel, { - [params.entityType]: params.entitySlug, + [entityType]: entitySlug, }, { modelId: data.id } ), @@ -143,7 +147,7 @@ export default function AIModelsPage({ GraphQL( createAIModel, { - [params.entityType]: params.entitySlug, + [entityType]: entitySlug, }, { input: { @@ -159,7 +163,7 @@ export default function AIModelsPage({ onSuccess: (response: any) => { toast(`AI Model created successfully`); router.push( - `/dashboard/${params.entityType}/${params.entitySlug}/aimodels/edit/${response.createAiModel.data.id}/details` + `/dashboard/${entityType}/${entitySlug}/aimodels/edit/${response.createAiModel.data.id}/details` ); AllAIModels.refetch(); }, @@ -177,7 +181,7 @@ export default function AIModelsPage({ {row.original.displayName} @@ -277,7 +281,9 @@ export default function AIModelsPage({ ) : ( <>
-
+
= ({ icon={Icons.delete} color="interactive" onClick={() => { - row.original.typename === 'TypeResourceChart' - ? deleteResourceChartmutation.mutate({ - chartId: row.original.id, - }) - : deleteResourceChartImagemutation.mutate({ - resourceChartImageId: row.original.id, - }); + if (row.original.typename === 'TypeResourceChart') { + deleteResourceChartmutation.mutate({ + chartId: row.original.id, + }); + } else { + deleteResourceChartImagemutation.mutate({ + resourceChartImageId: row.original.id, + }); + } }} > Delete diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/collaboratives/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/collaboratives/page.tsx index b00b17a7..c80da93b 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/collaboratives/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/collaboratives/page.tsx @@ -1,7 +1,7 @@ 'use client'; import { useEffect } from 'react'; -import { useRouter } from 'next/navigation'; +import { useParams, useRouter } from 'next/navigation'; import { graphql } from '@/gql'; import { useMutation, useQuery } from '@tanstack/react-query'; import { parseAsString, useQueryState } from 'next-usequerystate'; @@ -17,7 +17,10 @@ import { ActionBar } from '../dataset/components/action-bar'; import { Navigation } from '../dataset/components/navigate-org-datasets'; const allCollaboratives: any = graphql(` - query CollaborativesData($filters: CollaborativeFilter, $order: CollaborativeOrder) { + query CollaborativesData( + $filters: CollaborativeFilter + $order: CollaborativeOrder + ) { collaboratives(filters: $filters, order: $order) { title id @@ -58,50 +61,46 @@ const unPublishCollaborative: any = graphql(` } `); -export default function CollaborativePage({ - params, -}: { - params: { entityType: string; entitySlug: string }; -}) { +export default function CollaborativePage() { const router = useRouter(); + const params = useParams<{ entityType?: string; entitySlug?: string }>(); + const entityType = params?.entityType; + const entitySlug = params?.entitySlug; - const [navigationTab, setNavigationTab] = useQueryState('tab', parseAsString); + const isValidParams = + typeof entityType === 'string' && typeof entitySlug === 'string'; - let navigationOptions = [ - { - label: 'Drafts', - url: `drafts`, - selected: navigationTab === 'drafts', - }, - { - label: 'Published', - url: `published`, - selected: navigationTab === 'published', - }, - ]; + const ownerArgs: Record | null = isValidParams + ? { [entityType]: entitySlug } + : null; - const AllCollaboratives: { data: any; isLoading: boolean; refetch: any } = useQuery( - [`fetch_Collaboratives`], - () => - GraphQL( - allCollaboratives, - { - [params.entityType]: params.entitySlug, - }, - { + const [navigationTab, setNavigationTab] = useQueryState('tab', parseAsString); + + const AllCollaboratives: { data: any; isLoading: boolean; refetch: any } = + useQuery( + [ + 'fetch_Collaboratives', + entityType, + entitySlug, + navigationTab ?? 'drafts', + ], + () => + GraphQL(allCollaboratives, ownerArgs || {}, { filters: { status: navigationTab === 'published' ? 'PUBLISHED' : 'DRAFT', }, order: { modified: 'DESC' }, - } - ) - ); + }), + { enabled: isValidParams } + ); useEffect(() => { if (navigationTab === null || navigationTab === undefined) setNavigationTab('drafts'); - AllCollaboratives.refetch(); - }, [navigationTab]); + if (isValidParams) { + AllCollaboratives.refetch(); + } + }, [navigationTab, isValidParams]); const DeleteCollaborativeMutation: { mutate: any; @@ -110,17 +109,15 @@ export default function CollaborativePage({ } = useMutation( [`delete_Collaborative`], (data: { id: string }) => - GraphQL( - deleteCollaborative, - { - [params.entityType]: params.entitySlug, - }, - { collaborativeId: data.id } - ), + GraphQL(deleteCollaborative, ownerArgs || {}, { + collaborativeId: data.id, + }), { onSuccess: () => { toast(`Deleted Collaborative successfully`); - AllCollaboratives.refetch(); + if (isValidParams) { + AllCollaboratives.refetch(); + } }, onError: (err: any) => { toast('Error: ' + err.message.split(':')[0]); @@ -134,21 +131,16 @@ export default function CollaborativePage({ error: any; } = useMutation( [`create_Collaborative`], - () => - GraphQL( - AddCollaborative, - { - [params.entityType]: params.entitySlug, - }, - [] - ), + () => GraphQL(AddCollaborative, ownerArgs || {}, []), { onSuccess: (response: any) => { toast(`Collaborative created successfully`); - router.push( - `/dashboard/${params.entityType}/${params.entitySlug}/collaboratives/edit/${response.addCollaborative.id}/details` - ); - AllCollaboratives.refetch(); + if (isValidParams && entityType && entitySlug) { + router.push( + `/dashboard/${entityType}/${entitySlug}/collaboratives/edit/${response.addCollaborative.id}/details` + ); + AllCollaboratives.refetch(); + } }, onError: (err: any) => { toast('Error: ' + err.message.split(':')[0]); @@ -163,17 +155,15 @@ export default function CollaborativePage({ } = useMutation( [`unpublish_collaborative`], (data: { id: string }) => - GraphQL( - unPublishCollaborative, - { - [params.entityType]: params.entitySlug, - }, - { collaborativeId: data.id } - ), + GraphQL(unPublishCollaborative, ownerArgs || {}, { + collaborativeId: data.id, + }), { onSuccess: () => { toast(`Unpublished collaborative successfully`); - AllCollaboratives.refetch(); + if (isValidParams) { + AllCollaboratives.refetch(); + } }, onError: (err: any) => { toast('Error: ' + err.message.split(':')[0]); @@ -181,6 +171,23 @@ export default function CollaborativePage({ } ); + if (!isValidParams) { + return null; + } + + let navigationOptions = [ + { + label: 'Drafts', + url: `drafts`, + selected: navigationTab === 'drafts', + }, + { + label: 'Published', + url: `published`, + selected: navigationTab === 'published', + }, + ]; + const collaborativesListColumns = [ { accessorKey: 'title', @@ -197,7 +204,7 @@ export default function CollaborativePage({ {row.original.title} diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/components/EditMetadata.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/components/EditMetadata.tsx index 0abdf21b..9939e507 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/components/EditMetadata.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/components/EditMetadata.tsx @@ -303,7 +303,7 @@ export function EditMetadata({ id }: { id: string }) { }; } - (dataset?.metadata || []).length > 0 && + if ((dataset?.metadata || []).length > 0) { (dataset?.metadata || []).map((field) => { if ( field.metadataItem.dataType === 'MULTISELECT' && @@ -321,6 +321,7 @@ export function EditMetadata({ id }: { id: string }) { defaultVal[field.metadataItem.id] = field.value; } }); + } defaultVal['description'] = dataset?.description || ''; diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/layout.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/layout.tsx index 2585c303..cb22f34a 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/layout.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/layout.tsx @@ -5,16 +5,17 @@ import { DatasetEditStatusProvider } from './context'; interface DashboardLayoutProps { children?: React.ReactNode; - params: { id: string }; + params: Promise<{ id: string }>; } export default async function Layout({ children, params, }: DashboardLayoutProps) { + const resolvedParams = await params; return ( - {children} + {children} ); } diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/metadata/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/metadata/page.tsx index e0e8ea5d..40884c51 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/metadata/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/metadata/page.tsx @@ -4,12 +4,13 @@ import styles from '../edit.module.scss'; export default async function Page({ params, }: { - params: { id: string; entitySlug: string }; + params: Promise<{ id: string; entitySlug: string }>; }) { + const { id } = await params; return ( //
- +
//
); diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/page.tsx index 80fffea2..fd6e0a16 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/page.tsx @@ -5,16 +5,21 @@ import styles from './edit.module.scss'; import { EditPage } from './page-layout'; -export default async function Page({ params }: { params: { id: string } }) { +export default async function Page({ + params, +}: { + params: Promise<{ id: string }>; +}) { + const { id } = await params; const queryClient = getQueryClient(); // eslint-disable-next-line @typescript-eslint/no-unused-vars const dehydratedState = dehydrate(queryClient); return ( // -
- -
+
+ +
//
); } diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/resources/components/PreviewData.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/resources/components/PreviewData.tsx index 5e0e7ebb..628ff77b 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/resources/components/PreviewData.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/resources/components/PreviewData.tsx @@ -15,7 +15,6 @@ const PreviewData = ({ previewData }: EditProps) => { cell: ({ cell }: any) => { const value = cell.getValue(); return {value !== null ? value?.toString() : 'N/A'}; - ``; }, })) || []; diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/resources/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/resources/page.tsx index 0b4dd3a7..42d82356 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/resources/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/resources/page.tsx @@ -7,8 +7,9 @@ import { DistibutionPage } from './page-layout'; export default async function Page({ params, }: { - params: { entityType: string; entitySlug: string; id: string }; + params: Promise<{ entityType: string; entitySlug: string; id: string }>; }) { + const resolvedParams = await params; const queryClient = getQueryClient(); // eslint-disable-next-line @typescript-eslint/no-unused-vars const dehydratedState = dehydrate(queryClient); @@ -16,7 +17,7 @@ export default async function Page({ return ( //
- +
//
); diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/review/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/review/page.tsx index c1ba0adf..c99a2e86 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/review/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/edit/review/page.tsx @@ -1,6 +1,11 @@ import { InProgress } from '@/components/in-progress'; -export default async function Page() { +export default async function Page({ + params, +}: { + params: Promise<{ id: string }>; +}) { + await params; return ( <> diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/page.tsx index 0646b554..e64d505a 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/[id]/page.tsx @@ -1,12 +1,32 @@ 'use client'; import React from 'react'; -import { notFound } from 'next/navigation'; +import { notFound, useParams } from 'next/navigation'; + +// import { usePRouter } from '@/hooks/use-prouter'; +// import { Divider, Icon, Tab, TabList, TabPanel, Tabs, Text } from 'opub-ui'; import { testDataset } from '@/config/dashboard'; -export default function Page({ params }: { params: { id: string } }) { - const data = testDataset[params.id]; +// import { Icons } from '@/components/icons'; +// import { InProgress } from '@/components/in-progress'; +// import { ActionBar } from '../components/action-bar'; + +export default function Page() { + const params = useParams<{ id: string }>(); + const datasetId = params?.id; + // const router = usePRouter(); + // React.useEffect(() => { + // router.prefetch(`/dashboard/dataset/${params.id}/edit`); + // }, []); + + // get demo data + + if (typeof datasetId !== 'string') { + notFound(); + } + + const data = testDataset[datasetId]; if (!data) { notFound(); } diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/components/content.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/components/content.tsx index 8b949079..ce3e5103 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/components/content.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/components/content.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useRouter } from 'next/navigation'; +import { useParams, useRouter } from 'next/navigation'; import { graphql } from '@/gql'; import { useMutation } from '@tanstack/react-query'; import { Button, Icon, Text, toast } from 'opub-ui'; @@ -26,38 +26,38 @@ const createDatasetMutationDoc: any = graphql(` } } `); -export const Content = ({ - params, -}: { - params: { entityType: string; entitySlug: string }; -}) => { +export const Content = () => { const router = useRouter(); + const params = useParams<{ entityType?: string; entitySlug?: string }>(); + const entityType = params?.entityType; + const entitySlug = params?.entitySlug; + + const isValidParams = + typeof entityType === 'string' && typeof entitySlug === 'string'; + + const ownerArgs: Record | null = isValidParams + ? { [entityType]: entitySlug } + : null; const CreateDatasetMutation: { mutate: any; isLoading: boolean; error: any } = - useMutation( - () => - GraphQL( - createDatasetMutationDoc, - { - [params.entityType]: params.entitySlug, - }, - [] - ), - { - onSuccess: (data: any) => { - if (data.addDataset.success) { - toast('Dataset created successfully!'); + useMutation(() => GraphQL(createDatasetMutationDoc, ownerArgs || {}, []), { + onSuccess: (data: any) => { + if (data.addDataset.success) { + toast('Dataset created successfully!'); + if (isValidParams && entityType && entitySlug) { router.push( - `/dashboard/${params.entityType}/${params.entitySlug}/dataset/${data?.addDataset?.data?.id}/edit/metadata` - ); - } else { - toast( - 'Error: ' + data.addDataset.errors.fieldErrors[0].messages[0] + `/dashboard/${entityType}/${entitySlug}/dataset/${data?.addDataset?.data?.id}/edit/metadata` ); } - }, - } - ); + } else { + toast('Error: ' + data.addDataset.errors.fieldErrors[0].messages[0]); + } + }, + }); + + if (!isValidParams) { + return null; + } return (
diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/new/components/new-dataset.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/new/components/new-dataset.tsx index 1e54f02c..6130171c 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/new/components/new-dataset.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/new/components/new-dataset.tsx @@ -43,8 +43,7 @@ export function CreateDataset({ return ( { - mutatePatch && - defaultVal && + if (mutatePatch && defaultVal) { mutatePatch({ dataset_data: { title: value.title, @@ -52,8 +51,9 @@ export function CreateDataset({ id: defaultVal.id, }, }); + } - mutate && + if (mutate) { mutate({ dataset_data: { title: value.title, @@ -61,6 +61,7 @@ export function CreateDataset({ dataset_type: value.type, }, }); + } }} formOptions={{ defaultValues: defaultValue }} submitRef={submitRef} diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/page-layout.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/page-layout.tsx index 87139153..feb8203f 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/page-layout.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/page-layout.tsx @@ -28,34 +28,35 @@ const createDatasetMutationDoc: any = graphql(` `); export const Page = () => { - const params = useParams<{ - entityType: string; - entitySlug: string; - }>(); - const router = useRouter(); + const params = useParams<{ entityType?: string; entitySlug?: string }>(); + const entityType = params?.entityType; + const entitySlug = params?.entitySlug; + + const isValidParams = + typeof entityType === 'string' && typeof entitySlug === 'string'; + + const ownerArgs: Record | null = isValidParams + ? { [entityType]: entitySlug } + : null; + const router = useRouter(); const queryClient = useQueryClient(); const { mutate, isLoading } = useMutation( - () => - GraphQL( - createDatasetMutationDoc, - { - [params.entityType]: params.entitySlug, - }, - [] - ), + () => GraphQL(createDatasetMutationDoc, ownerArgs || {}, []), { onSuccess: (data: any) => { if (data.addDataset.success) { toast('Dataset created successfully!'); - queryClient.invalidateQueries({ - queryKey: [`create_dataset_${params.entityType}`], - }); + if (isValidParams && entityType) { + queryClient.invalidateQueries({ + queryKey: [`create_dataset_${entityType}`], + }); - router.push( - `/dashboard/${params.entityType}/${params.entitySlug}/dataset/${data?.addDataset?.data?.id}/edit/metadata` - ); + router.push( + `/dashboard/${entityType}/${entitySlug}/dataset/${data?.addDataset?.data?.id}/edit/metadata` + ); + } } else { toast('Error: ' + data.addDataset.errors.fieldErrors[0].messages[0]); } @@ -63,6 +64,10 @@ export const Page = () => { } ); + if (!isValidParams) { + return null; + } + // React.useEffect(() => { // router.prefetch('/dashboard/dataset/new'); // }, []); @@ -80,7 +85,7 @@ export const Page = () => { isLoading={isLoading} /> - + ); }; diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/page.tsx index c6f99c91..c717633f 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/dataset/page.tsx @@ -1,21 +1,21 @@ 'use client'; import { useEffect } from 'react'; -import { useRouter } from 'next/navigation'; +import { useParams, useRouter } from 'next/navigation'; import { graphql } from '@/gql'; import { useMutation, useQuery } from '@tanstack/react-query'; import { parseAsString, useQueryState } from 'next-usequerystate'; import { Button, DataTable, IconButton, Text, toast } from 'opub-ui'; import { GraphQL } from '@/lib/api'; +import { formatDate } from '@/lib/utils'; import { Icons } from '@/components/icons'; import { LinkButton } from '@/components/Link'; import { Loading } from '@/components/loading'; +import { useTourTrigger } from '@/hooks/use-tour-trigger'; import { ActionBar } from './components/action-bar'; import { Content } from './components/content'; import { Navigation } from './components/navigate-org-datasets'; -import { formatDate } from '@/lib/utils'; -import { useTourTrigger } from '@/hooks/use-tour-trigger'; const allDatasetsQueryDoc: any = graphql(` query allDatasetsQuery($filters: DatasetFilter, $order: DatasetOrder) { @@ -65,51 +65,47 @@ const unPublishDataset: any = graphql(` } `); -export default function DatasetPage({ - params, -}: { - params: { entityType: string; entitySlug: string }; -}) { +export default function DatasetPage() { useTourTrigger(true, 1500); - const router = useRouter(); + const params = useParams<{ entityType?: string; entitySlug?: string }>(); + const entityType = params?.entityType; + const entitySlug = params?.entitySlug; - const [navigationTab, setNavigationTab] = useQueryState('tab', parseAsString); + const isValidParams = + typeof entityType === 'string' && typeof entitySlug === 'string'; - let navigationOptions = [ - { - label: 'Drafts', - url: `drafts`, - selected: navigationTab === 'drafts', - }, - { - label: 'Published', - url: `published`, - selected: navigationTab === 'published', - }, - ]; + const ownerArgs: Record | null = isValidParams + ? { [entityType]: entitySlug } + : null; + + const [navigationTab, setNavigationTab] = useQueryState('tab', parseAsString); const AllDatasetsQuery: { data: any; isLoading: boolean; refetch: any } = - useQuery([`fetch_datasets_org_dashboard`], () => - GraphQL( - allDatasetsQueryDoc, - { - [params.entityType]: params.entitySlug, - }, - { + useQuery( + [ + `fetch_datasets_org_dashboard`, + entityType, + entitySlug, + navigationTab ?? 'drafts', + ], + () => + GraphQL(allDatasetsQueryDoc, ownerArgs || {}, { filters: { status: navigationTab === 'published' ? 'PUBLISHED' : 'DRAFT', }, order: { modified: 'DESC' }, - } - ) + }), + { enabled: isValidParams } ); useEffect(() => { if (navigationTab === null || navigationTab === undefined) setNavigationTab('drafts'); - AllDatasetsQuery.refetch(); - }, [navigationTab]); + if (isValidParams) { + AllDatasetsQuery.refetch(); + } + }, [navigationTab, isValidParams]); const DeleteDatasetMutation: { mutate: any; @@ -118,17 +114,15 @@ export default function DatasetPage({ } = useMutation( [`delete_dataset`], (data: { datasetId: string }) => - GraphQL( - deleteDatasetMutationDoc, - { - [params.entityType]: params.entitySlug, - }, - { datasetId: data.datasetId } - ), + GraphQL(deleteDatasetMutationDoc, ownerArgs || {}, { + datasetId: data.datasetId, + }), { onSuccess: () => { toast(`Deleted dataset successfully`); - AllDatasetsQuery.refetch(); + if (isValidParams) { + AllDatasetsQuery.refetch(); + } }, onError: (err: any) => { toast('Error: ' + err.message.split(':')[0]); @@ -136,31 +130,20 @@ export default function DatasetPage({ } ); const CreateDatasetMutation: { mutate: any; isLoading: boolean; error: any } = - useMutation( - () => - GraphQL( - createDatasetMutationDoc, - { - [params.entityType]: params.entitySlug, - }, - [] - ), - { - onSuccess: (data: any) => { - if (data.addDataset.success) { - toast('Dataset created successfully!'); - + useMutation(() => GraphQL(createDatasetMutationDoc, ownerArgs || {}, []), { + onSuccess: (data: any) => { + if (data.addDataset.success) { + toast('Dataset created successfully!'); + if (isValidParams && entityType && entitySlug) { router.push( - `/dashboard/${params.entityType}/${params.entitySlug}/dataset/${data?.addDataset?.data?.id}/edit/metadata` - ); - } else { - toast( - 'Error: ' + data.addDataset.errors.fieldErrors[0].messages[0] + `/dashboard/${entityType}/${entitySlug}/dataset/${data?.addDataset?.data?.id}/edit/metadata` ); } - }, - } - ); + } else { + toast('Error: ' + data.addDataset.errors.fieldErrors[0].messages[0]); + } + }, + }); const UnpublishDatasetMutation: { mutate: any; isLoading: boolean; @@ -168,17 +151,13 @@ export default function DatasetPage({ } = useMutation( [`unpublish_dataset`], (data: { datasetId: string }) => - GraphQL( - unPublishDataset, - { - [params.entityType]: params.entitySlug, - }, - { datasetId: data.datasetId } - ), + GraphQL(unPublishDataset, ownerArgs || {}, { datasetId: data.datasetId }), { onSuccess: () => { toast(`Unpublished dataset successfully`); - AllDatasetsQuery.refetch(); + if (isValidParams) { + AllDatasetsQuery.refetch(); + } }, onError: (err: any) => { toast('Error: ' + err.message.split(':')[0]); @@ -186,6 +165,23 @@ export default function DatasetPage({ } ); + if (!isValidParams) { + return null; + } + + let navigationOptions = [ + { + label: 'Drafts', + url: `drafts`, + selected: navigationTab === 'drafts', + }, + { + label: 'Published', + url: `published`, + selected: navigationTab === 'published', + }, + ]; + const datasetsListColumns = [ { accessorKey: 'title', @@ -197,7 +193,7 @@ export default function DatasetPage({ {row.original.title} @@ -282,7 +278,7 @@ export default function DatasetPage({ ) : AllDatasetsQuery.isLoading ? ( ) : ( - + )} {/* */} diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/page.tsx index e01da9e7..83f9428c 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/page.tsx @@ -1,18 +1,10 @@ -'use client'; +import { redirect } from 'next/navigation'; -import { useEffect } from 'react'; -import { useRouter } from 'next/navigation'; - -export default function Page({ +export default async function Page({ params, }: { - params: { entityType: string; entitySlug: string }; + params: Promise<{ entityType: string; entitySlug: string }>; }) { - const router = useRouter(); - - useEffect(() => { - router.push(`/dashboard/${params.entityType}/${params.entitySlug}/dataset?tab=drafts`); - }, [params, router]); - - return null; // prevent rendering anything before redirect + const { entityType, entitySlug } = await params; + redirect(`/dashboard/${entityType}/${entitySlug}/dataset?tab=drafts`); } diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/usecases/edit/[id]/dashboards/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/usecases/edit/[id]/dashboards/page.tsx index 0aed444a..6105375a 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/usecases/edit/[id]/dashboards/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/usecases/edit/[id]/dashboards/page.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'; import Link from 'next/link'; +import { useParams } from 'next/navigation'; import { graphql } from '@/gql'; import { useMutation, useQuery } from '@tanstack/react-query'; import { Button, Icon, Text, TextField, toast } from 'opub-ui'; @@ -73,8 +74,26 @@ const deleteDashboard: any = graphql(` } `); -const Dashboard = ({ params }: { params: { entityType: string; entitySlug: string; id: string } }) => { - const usecaseId = parseInt(params.id); +const Dashboard = () => { + const params = useParams<{ entityType?: string; entitySlug?: string; id?: string }>(); + const entityType = params?.entityType; + const entitySlug = params?.entitySlug; + const idParam = params?.id; + + const isValidParams = + typeof entityType === 'string' && + typeof entitySlug === 'string' && + typeof idParam === 'string'; + + const usecaseId = isValidParams && idParam + ? Number.parseInt(idParam, 10) + : NaN; + + const isValidId = !Number.isNaN(usecaseId) && isValidParams; + + const ownerArgs: Record | null = isValidParams + ? { [entityType]: entitySlug } + : null; const [dashboards, setDashboards] = useState< Array<{ id: string; name: string; link: string }> @@ -83,10 +102,11 @@ const Dashboard = ({ params }: { params: { entityType: string; entitySlug: strin useQuery( ['fetch_dashboardData', usecaseId], - () => GraphQL(dashboardList, { [params.entityType]: params.entitySlug }, { usecaseId }), + () => GraphQL(dashboardList, ownerArgs || {}, { usecaseId }), { refetchOnMount: true, refetchOnReconnect: true, + enabled: isValidId, onSuccess: (res: any) => { setDashboards(res.usecaseDashboards || []); setPreviousState( @@ -100,7 +120,7 @@ const Dashboard = ({ params }: { params: { entityType: string; entitySlug: strin const { mutate: addDashboard, isLoading: addLoading } = useMutation( ({ usecaseId }: { usecaseId: number }) => - GraphQL(AddDashboard, { [params.entityType]: params.entitySlug }, { usecaseId }), + GraphQL(AddDashboard, ownerArgs || {}, { usecaseId }), { onSuccess: (res: any) => { const newDashboard = res.addUsecaseDashboard.data; @@ -116,7 +136,7 @@ const Dashboard = ({ params }: { params: { entityType: string; entitySlug: strin ); const { mutate: saveDashboard, isLoading: saveLoading } = useMutation( ({ id, name, link }: { id: string; name: string; link: string }) => - GraphQL(updateDashboard, { [params.entityType]: params.entitySlug }, { id, name, link }), + GraphQL(updateDashboard, ownerArgs || {}, { id, name, link }), { onSuccess: ({ updateUsecaseDashboard }: any) => { toast.success('Changes saved'); @@ -132,7 +152,7 @@ const Dashboard = ({ params }: { params: { entityType: string; entitySlug: strin ); const { mutate: removeDashboard, isLoading: deleteLoading } = useMutation( - (id: number) => GraphQL(deleteDashboard, { [params.entityType]: params.entitySlug }, { id }), + (id: number) => GraphQL(deleteDashboard, ownerArgs || {}, { id }), { onSuccess: (_, id) => { setDashboards((prev) => prev.filter((d) => d.id !== id.toString())); @@ -144,6 +164,18 @@ const Dashboard = ({ params }: { params: { entityType: string; entitySlug: strin } ); + const { setStatus } = useEditStatus(); + + useEffect(() => { + setStatus( + saveLoading || addLoading || deleteLoading ? 'loading' : 'success' + ); // update based on mutation state + }, [saveLoading, addLoading, deleteLoading, setStatus]); + + if (!isValidId) { + return null; + } + const handleChange = (id: string, field: 'name' | 'link', value: string) => { setDashboards((prev) => prev.map((d) => (d.id === id ? { ...d, [field]: value } : d)) @@ -173,14 +205,6 @@ const Dashboard = ({ params }: { params: { entityType: string; entitySlug: strin removeDashboard(Number(id)); }; - const { setStatus } = useEditStatus(); - - useEffect(() => { - setStatus( - saveLoading || addLoading || deleteLoading ? 'loading' : 'success' - ); // update based on mutation state - }, [saveLoading, addLoading, deleteLoading]); - return (
Dashboard diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/usecases/page.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/usecases/page.tsx index 28e60d4c..d5c91837 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/usecases/page.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/usecases/page.tsx @@ -1,7 +1,7 @@ 'use client'; import { useEffect } from 'react'; -import { useRouter } from 'next/navigation'; +import { useParams, useRouter } from 'next/navigation'; import { graphql } from '@/gql'; import { useMutation, useQuery } from '@tanstack/react-query'; import { parseAsString, useQueryState } from 'next-usequerystate'; @@ -58,50 +58,44 @@ const unPublishUseCase: any = graphql(` } `); -export default function DatasetPage({ - params, -}: { - params: { entityType: string; entitySlug: string }; -}) { +export default function DatasetPage() { const router = useRouter(); + const params = useParams<{ entityType?: string; entitySlug?: string }>(); + const entityType = params?.entityType; + const entitySlug = params?.entitySlug; - const [navigationTab, setNavigationTab] = useQueryState('tab', parseAsString); + const isValidParams = + typeof entityType === 'string' && typeof entitySlug === 'string'; - let navigationOptions = [ - { - label: 'Drafts', - url: `drafts`, - selected: navigationTab === 'drafts', - }, - { - label: 'Published', - url: `published`, - selected: navigationTab === 'published', - }, - ]; + const ownerArgs: Record | null = isValidParams + ? { [entityType]: entitySlug } + : null; + + const [navigationTab, setNavigationTab] = useQueryState('tab', parseAsString); const AllUseCases: { data: any; isLoading: boolean; refetch: any } = useQuery( - [`fetch_UseCases`], + [`fetch_UseCases`, entityType, entitySlug, navigationTab ?? 'drafts'], () => GraphQL( allUseCases, - { - [params.entityType]: params.entitySlug, - }, + ownerArgs || {}, { filters: { status: navigationTab === 'published' ? 'PUBLISHED' : 'DRAFT', }, order: { modified: 'DESC' }, } - ) + ), + { enabled: isValidParams } ); useEffect(() => { if (navigationTab === null || navigationTab === undefined) setNavigationTab('drafts'); - AllUseCases.refetch(); - }, [navigationTab]); + if (isValidParams) { + AllUseCases.refetch(); + } + }, [navigationTab, isValidParams]); const DeleteUseCaseMutation: { mutate: any; @@ -112,15 +106,15 @@ export default function DatasetPage({ (data: { id: string }) => GraphQL( deleteUseCase, - { - [params.entityType]: params.entitySlug, - }, + ownerArgs || {}, { useCaseId: data.id } ), { onSuccess: () => { toast(`Deleted UseCase successfully`); - AllUseCases.refetch(); + if (isValidParams) { + AllUseCases.refetch(); + } }, onError: (err: any) => { toast('Error: ' + err.message.split(':')[0]); @@ -134,21 +128,16 @@ export default function DatasetPage({ error: any; } = useMutation( [`delete_Usecase`], - () => - GraphQL( - AddUseCase, - { - [params.entityType]: params.entitySlug, - }, - [] - ), + () => GraphQL(AddUseCase, ownerArgs || {}, []), { onSuccess: (response: any) => { toast(`UseCase created successfully`); - router.push( - `/dashboard/${params.entityType}/${params.entitySlug}/usecases/edit/${response.addUseCase.id}/details` - ); - AllUseCases.refetch(); + if (isValidParams && entityType && entitySlug) { + router.push( + `/dashboard/${entityType}/${entitySlug}/usecases/edit/${response.addUseCase.id}/details` + ); + AllUseCases.refetch(); + } }, onError: (err: any) => { toast('Error: ' + err.message.split(':')[0]); @@ -164,21 +153,38 @@ export default function DatasetPage({ (data: { id: string }) => GraphQL( unPublishUseCase, - { - [params.entityType]: params.entitySlug, - }, + ownerArgs || {}, { useCaseId: data.id } ), { onSuccess: () => { toast(`Unpublished usecase successfully`); - AllUseCases.refetch(); + if (isValidParams) { + AllUseCases.refetch(); + } }, onError: (err: any) => { toast('Error: ' + err.message.split(':')[0]); }, } ); + + if (!isValidParams) { + return null; + } + + let navigationOptions = [ + { + label: 'Drafts', + url: `drafts`, + selected: navigationTab === 'drafts', + }, + { + label: 'Published', + url: `published`, + selected: navigationTab === 'published', + }, + ]; const datasetsListColumns = [ { accessorKey: 'title', @@ -195,7 +201,7 @@ export default function DatasetPage({ {row.original.title} diff --git a/app/[locale]/dashboard/components/main-nav.tsx b/app/[locale]/dashboard/components/main-nav.tsx index 5a32f3d4..41e64edd 100644 --- a/app/[locale]/dashboard/components/main-nav.tsx +++ b/app/[locale]/dashboard/components/main-nav.tsx @@ -129,7 +129,7 @@ export function MainNav({ hideSearch = false }) { } }; return ( -