From ce3e8e821700b085849c860e44758a29ff56e8ec Mon Sep 17 00:00:00 2001 From: Abhishekfm Date: Thu, 27 Aug 2026 14:35:59 +0530 Subject: [PATCH] Refactor dashboard components and enhance translation support - Added BhashiniTranslation component to support multilingual capabilities across the dashboard. - Updated CSS to ensure proper styling for the translation plugin and maintain UI integrity. - Enhanced error handling in GraphQL functions to validate document structure. --- .../components/Resources/index.tsx | 35 ++--- .../[entityType]/[entitySlug]/layout.tsx | 25 ++-- .../[entitySlug]/profile/userProfile.tsx | 33 +++-- .../[entityType]/[entitySlug]/schema.ts | 10 +- .../components/CollaborativeSubdomainNav.tsx | 3 + .../dashboard/components/dashboard-nav.tsx | 2 +- .../dashboard/components/main-footer.tsx | 18 ++- .../dashboard/components/main-nav.tsx | 2 + .../BhashiniTranslation.tsx | 57 +++++++++ components/BhashiniTranslation/index.ts | 1 + components/RichTextEditor/RichTextEditor.tsx | 120 ++++++++++-------- config/dashboard.ts | 2 +- config/site.ts | 2 +- lib/api.ts | 21 +++ styles/globals.css | 27 ++++ tsconfig.json | 2 - 16 files changed, 253 insertions(+), 107 deletions(-) create mode 100644 components/BhashiniTranslation/BhashiniTranslation.tsx create mode 100644 components/BhashiniTranslation/index.ts diff --git a/app/[locale]/(user)/datasets/[datasetIdentifier]/components/Resources/index.tsx b/app/[locale]/(user)/datasets/[datasetIdentifier]/components/Resources/index.tsx index a98c45c0..f2ea914e 100644 --- a/app/[locale]/(user)/datasets/[datasetIdentifier]/components/Resources/index.tsx +++ b/app/[locale]/(user)/datasets/[datasetIdentifier]/components/Resources/index.tsx @@ -5,19 +5,12 @@ import { useParams } from 'next/navigation'; import PdfPreview from '@/app/[locale]/(user)/components/PdfPreview'; import { graphql } from '@/gql'; import { useQuery } from '@tanstack/react-query'; -import { - Button, - Dialog, - Format, - Icon, - Spinner, - Table, - Text, -} from 'opub-ui'; +import { Button, Dialog, Format, Icon, Spinner, Table, Text } from 'opub-ui'; import { GraphQL } from '@/lib/api'; import { Icons } from '@/components/icons'; import styles from './Resources.module.scss'; + const datasetResourceQuery: any = graphql(` query datasetResources($datasetId: UUID!) { datasetResources(datasetId: $datasetId) { @@ -78,7 +71,11 @@ const Resources = () => { View All Columns - + { header: column, cell: ({ cell }: any) => { const value = cell.getValue(); - return {value !== null ? value.toString() : 'N/A'}; + return ( + {value !== null ? value?.toString() : 'N/A'} + ); }, })) || []; @@ -164,7 +163,12 @@ const Resources = () => { Preview - + {row.original.format === 'PDF' ? ( {
Files in this Dataset - All files associated with this Dataset which can be downloaded{' '} + All files associated with this Dataset which can be + downloaded{' '}
@@ -221,8 +226,8 @@ const Resources = () => { className="mt-5 flex flex-col gap-6 border-1 border-solid border-greyExtralight bg-surfaceDefault p-4 lg:mx-0 lg:p-6" >
-
-
+
+
{item.fileDetails?.format && ( )} diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/layout.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/layout.tsx index 7398763d..5f5df954 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/layout.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/layout.tsx @@ -28,22 +28,19 @@ export default function OrgDashboardLayout({ children }: DashboardLayoutProps) { isLoading: boolean; error: any; refetch: any; - } = useQuery([`entity_details_${params.entityType}`], () => - GraphQL( - params.entityType === 'organization' && getOrgDetailsQryDoc, - { - [params.entityType]: params.entitySlug, - }, - { slug: params.entitySlug } - ) + } = useQuery( + [`entity_details_${params.entityType}`, params.entitySlug], + () => + GraphQL( + getOrgDetailsQryDoc, + { + [params.entityType]: params.entitySlug, + }, + { slug: params.entitySlug } + ), + { enabled: params.entityType === 'organization' } ); - - useEffect(() => { - EntityDetailsQryRes.refetch(); - }, [EntityDetailsQryRes]); - - useEffect(() => { if (EntityDetailsQryRes.data) { setEntityDetails(EntityDetailsQryRes.data); diff --git a/app/[locale]/dashboard/[entityType]/[entitySlug]/profile/userProfile.tsx b/app/[locale]/dashboard/[entityType]/[entitySlug]/profile/userProfile.tsx index ad763289..4dd59948 100644 --- a/app/[locale]/dashboard/[entityType]/[entitySlug]/profile/userProfile.tsx +++ b/app/[locale]/dashboard/[entityType]/[entitySlug]/profile/userProfile.tsx @@ -35,9 +35,12 @@ const updateUserMutation: any = graphql(` } `); -const githubRegex = /^https:\/\/github\.com\/[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}$/; -const linkedinRegex = /^https:\/\/(?:www\.)?linkedin\.com\/in\/[a-zA-Z0-9-]+\/?$/; -const twitterRegex = /^https:\/\/(?:www\.)?(?:twitter\.com|x\.com)\/[a-zA-Z0-9_]+\/?$/; +const githubRegex = + /^https:\/\/github\.com\/[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}$/; +const linkedinRegex = + /^https:\/\/(?:www\.)?linkedin\.com\/in\/[a-zA-Z0-9-]+\/?$/; +const twitterRegex = + /^https:\/\/(?:www\.)?(?:twitter\.com|x\.com)\/[a-zA-Z0-9_]+\/?$/; const prettyField = (f: string) => { switch (f) { @@ -160,16 +163,22 @@ const UserProfile = () => { toast('Please fill all the required fields'); return; } - if (formData.githubProfile && !githubRegex.test(formData.githubProfile)) { + if (formData.githubProfile && !githubRegex.test(formData.githubProfile)) { toast.error('GitHub URL: Enter a valid URL.'); return; } - if (formData.linkedinProfile && !linkedinRegex.test(formData.linkedinProfile)) { - toast.error('LinkedIn URL: Enter a valid URL.'); + if ( + formData.linkedinProfile && + !linkedinRegex.test(formData.linkedinProfile) + ) { + toast.error('LinkedIn URL: Enter a valid URL.'); return; } - if (formData.twitterProfile && !twitterRegex.test(formData.twitterProfile)) { - toast.error('Twitter URL: Enter a valid URL.'); + if ( + formData.twitterProfile && + !twitterRegex.test(formData.twitterProfile) + ) { + toast.error('Twitter URL: Enter a valid URL.'); return; } @@ -208,7 +217,7 @@ const UserProfile = () => { onChange={(e) => setFormData({ ...formData, firstName: e })} />
-
+
{
-
+
{ onChange={(e) => setFormData({ ...formData, email: e })} />
-
+
{
-
+
+
diff --git a/app/[locale]/dashboard/components/dashboard-nav.tsx b/app/[locale]/dashboard/components/dashboard-nav.tsx index 2071ec61..d678bad0 100644 --- a/app/[locale]/dashboard/components/dashboard-nav.tsx +++ b/app/[locale]/dashboard/components/dashboard-nav.tsx @@ -7,7 +7,7 @@ import { usePathname } from 'next/navigation'; import { useMetaKeyPress } from '@/hooks/use-meta-key-press'; import { Divider, Icon, IconButton, Text, Tooltip } from 'opub-ui'; -import { SidebarNavItem } from 'types'; +import { SidebarNavItem } from '@/types'; import { cn } from '@/lib/utils'; import { Icons } from '@/components/icons'; import styles from '../dashboard.module.scss'; diff --git a/app/[locale]/dashboard/components/main-footer.tsx b/app/[locale]/dashboard/components/main-footer.tsx index cd06b754..934261e2 100644 --- a/app/[locale]/dashboard/components/main-footer.tsx +++ b/app/[locale]/dashboard/components/main-footer.tsx @@ -110,14 +110,24 @@ const MainFooter = () => { ))}
- Made in India. A DataSpace product by + + Made in India. A{' '} + DataSpace product + by{' '} + - CivicDataLab - + CivicDataLab +
diff --git a/app/[locale]/dashboard/components/main-nav.tsx b/app/[locale]/dashboard/components/main-nav.tsx index 1c87263a..0d5cfce8 100644 --- a/app/[locale]/dashboard/components/main-nav.tsx +++ b/app/[locale]/dashboard/components/main-nav.tsx @@ -20,6 +20,7 @@ import { import { useDashboardStore } from '@/config/store'; import { GraphQL } from '@/lib/api'; +import BhashiniTranslation from '@/components/BhashiniTranslation'; import { Icons } from '@/components/icons'; import { UserDetailsQryDoc } from '../[entityType]/[entitySlug]/schema'; import { allOrganizationsListingDoc } from '../[entityType]/schema'; @@ -291,6 +292,7 @@ export function MainNav({ hideSearch = false }) { )}
)} +
diff --git a/components/BhashiniTranslation/BhashiniTranslation.tsx b/components/BhashiniTranslation/BhashiniTranslation.tsx new file mode 100644 index 00000000..9c74c46c --- /dev/null +++ b/components/BhashiniTranslation/BhashiniTranslation.tsx @@ -0,0 +1,57 @@ +'use client'; + +import { useEffect, useRef } from 'react'; +import Script from 'next/script'; + +const BHASHINI_SCRIPT_ID = 'bhashini-website-translation'; +const BHASHINI_SCRIPT_SRC = + 'https://translation-plugin.bhashini.co.in/v3/website_translation_utility.js'; +const BHASHINI_HOLDER_ID = '__bhashini-plugin-holder'; + +function getHolder() { + let holder = document.getElementById(BHASHINI_HOLDER_ID); + if (!holder) { + holder = document.createElement('div'); + holder.id = BHASHINI_HOLDER_ID; + holder.hidden = true; + document.body.appendChild(holder); + } + return holder; +} + +export default function BhashiniTranslation() { + const containerRef = useRef(null); + + useEffect(() => { + const container = containerRef.current; + if (!container) return; + + const holder = getHolder(); + while (holder.firstChild) { + container.appendChild(holder.firstChild); + } + + return () => { + while (container.firstChild) { + holder.appendChild(container.firstChild); + } + }; + }, []); + + return ( + <> +
+