Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e0024eb
Collaborative Description text was rendering incorrectly,fixed it
UdayRajSahai2 Jul 21, 2026
5c5e2a2
Merge pull request #422 from CivicDataLab/418-bug-collaborative-descr…
Abhishekfm Aug 6, 2026
254d2fd
chore: update package dependencies and improve package-lock.json stru…
Abhishekfm Aug 10, 2026
e4d6841
docs: add Google Search Console setup and sitemap validation handover
Aug 10, 2026
bb3872b
chore: trigger dev deploy to pick up fixed NEXT_PUBLIC_GA_ID secret
Aug 10, 2026
19e983a
chore: update environment configuration and Node.js version
Abhishekfm Aug 10, 2026
f1e3858
chore: update package-lock.json and GitHub workflows
Abhishekfm Aug 10, 2026
2a8c96a
chore: trigger dev deploy to disable GA on dev environment
Aug 10, 2026
96bf4c0
Merge pull request #431 from CivicDataLab/deps-issue
Abhishekfm Aug 11, 2026
8c4e14f
Add scrollToId function for smooth scrolling
saqibmanan Aug 11, 2026
e09b1e8
Refactor use cases edit pages to improve query handling and state man…
Abhishekfm Aug 12, 2026
386e335
Merge pull request #432 from CivicDataLab/fix/use-case
Abhishekfm Aug 12, 2026
a35adb7
chore: enhance GitHub workflows with linting step
Abhishekfm Aug 12, 2026
7bd9b31
Refactor use cases edit pages to enhance query invalidation and state…
Abhishekfm Aug 12, 2026
30c3563
Merge pull request #433 from CivicDataLab/fix/use-case
Abhishekfm Aug 12, 2026
be1bd31
Refactor i18n configuration to improve locale handling
Abhishekfm Aug 12, 2026
10aff13
Refactor AI model edit pages to enhance query management and state ha…
Abhishekfm Aug 14, 2026
9e05a47
Made check so that logout page does not come,fixed session issue show…
UdayRajSahai2 Aug 18, 2026
f230904
Implement pagination in CollaborativesListingClient component
Abhishekfm Aug 18, 2026
26f19d7
Merge pull request #434 from CivicDataLab/locale-intl
saqibmanan Aug 21, 2026
0cb389a
Merge pull request #435 from CivicDataLab/fix-aimodels
saqibmanan Aug 21, 2026
14f0271
Merge pull request #436 from CivicDataLab/fix-login-issues
saqibmanan Aug 21, 2026
07d472b
Merge pull request #437 from CivicDataLab/collabratives-client-pagina…
saqibmanan Aug 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ NEXT_PUBLIC_PLATFORM_PROTOCOL=https
NEXT_PUBLIC_PLATFORM_PORT=3000


# Google Analytics
NEXT_PUBLIC_GA_ID='G-XXXXXXXXXX'
# Google Analytics
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX

FEATURE_SITEMAPS='false'
FEATURE_SITEMAP_BACKEND_BASE_URL= http://backendurl/api
Expand Down
13 changes: 8 additions & 5 deletions .github/workflows/deploy-Dataspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,21 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: '24'
cache: 'npm'

- name: Install dependencies
run: npm install --legacy-peer-deps
run: npm install

- name: Generate
run: npm run generate:ci
env:
BACKEND_GRAPHQL_URL: ${{ vars.BACKEND_GRAPHQL_URL }}
NODE_ENV: production

- name: Lint
run: npm run lint

- name: Build
run: npm run build

Expand Down Expand Up @@ -95,8 +98,8 @@ jobs:
if: github.ref_name == 'dev'
uses: CivicDataLab/CivicDataSpace-test/.github/workflows/run-smoke.yml@CI
secrets:
HOME_URL_DEV: ${{ secrets.HOME_URL_DEV }}
TEST_EMAIL_1: ${{ secrets.TEST_EMAIL_1 }}
HOME_URL_DEV: ${{ secrets.HOME_URL_DEV }}
TEST_EMAIL_1: ${{ secrets.TEST_EMAIL_1 }}
TEST_PASSWORD_1: ${{ secrets.TEST_PASSWORD_1 }}
TEST_EMAIL_2: ${{ secrets.TEST_EMAIL_2 }}
TEST_EMAIL_2: ${{ secrets.TEST_EMAIL_2 }}
TEST_PASSWORD_2: ${{ secrets.TEST_PASSWORD_2 }}
8 changes: 6 additions & 2 deletions .github/workflows/pre-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
NEXT_PUBLIC_PLATFORM_DOMAIN: ${{ vars.NEXT_PUBLIC_PLATFORM_DOMAIN }}
strategy:
matrix:
node-version: [20.x]
node-version: [24.x]

steps:
- uses: actions/checkout@v4
Expand All @@ -41,11 +41,15 @@ jobs:
cache: 'npm'

- name: Install dependencies
run: npm ci --force
run: npm ci

- name: Generate GraphQL types (CI-safe)
run: npm run generate
env:
BACKEND_GRAPHQL_URL: ${{vars.BACKEND_GRAPHQL_URL}}

- name: Lint
run: npm run lint

- name: Build application
run: npm run build --if-present
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Creates a layer from node:alpine image.
# FROM chub.cloud.gov.in/mit6c0-ogd/node-16:nic_server
FROM node:alpine
FROM node:24-alpine


# RUN echo 'deb http://deb.debian.org/debian stretch main' >> apk update \
Expand Down
35 changes: 31 additions & 4 deletions app/[locale]/(user)/collaboratives/CollaborativesListingClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import { ComponentType, useState } from 'react';
import Image from 'next/image';
import GraphqlPagination from '@/app/[locale]/dashboard/components/GraphqlPagination/graphqlPagination';
import { graphql } from '@/gql';
import { TypeCollaborative } from '@/gql/generated/graphql';
import { useQuery } from '@tanstack/react-query';
import { Button, Card, Icon, SearchInput, Select, Text } from 'opub-ui';

import { GraphQLPublic } from '@/lib/api';
import { getCollaborativeDetailUrl } from '@/lib/collaborativesRouting';
import { cn, formatDate, generateJsonLd } from '@/lib/utils';
import BreadCrumbs from '@/components/BreadCrumbs';
import { Icons } from '@/components/icons';
Expand Down Expand Up @@ -86,6 +86,8 @@ const PublishedCollaboratives = graphql(`
const CollaborativesListingClient = () => {
const [searchTerm, setSearchTerm] = useState('');
const [sortBy, setSortBy] = useState('title_asc');
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(9);

const {
data: collaborativesData,
Expand Down Expand Up @@ -142,6 +144,17 @@ const CollaborativesListingClient = () => {
return 0;
});

const totalPages = Math.max(
1,
Math.ceil(filteredAndSortedCollaboratives.length / pageSize)
);
const safePage = Math.min(currentPage, totalPages);
const start = (safePage - 1) * pageSize;
const paginatedCollaboratives = filteredAndSortedCollaboratives.slice(
start,
start + pageSize
);

const jsonLd = generateJsonLd({
'@context': 'https://schema.org',
'@type': 'WebPage',
Expand Down Expand Up @@ -225,9 +238,11 @@ const CollaborativesListingClient = () => {
className={cn('w-full', Styles.Search)}
onSubmit={(e) => {
setSearchTerm(e);
setCurrentPage(1);
}}
onClear={() => {
setSearchTerm('');
setCurrentPage(1);
}}
name={'Start typing to search for any collaborative'}
/>
Expand Down Expand Up @@ -271,6 +286,7 @@ const CollaborativesListingClient = () => {
]}
onChange={(e: any) => {
setSortBy(e);
setCurrentPage(1);
}}
/>
</div>
Expand All @@ -297,8 +313,18 @@ const CollaborativesListingClient = () => {
<>
{/* Collaboratives Grid */}
{filteredAndSortedCollaboratives.length > 0 ? (
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
{filteredAndSortedCollaboratives.map(
<GraphqlPagination
totalRows={filteredAndSortedCollaboratives.length}
pageSize={pageSize}
currentPage={safePage}
onPageChange={setCurrentPage}
onPageSizeChange={(newSize) => {
setPageSize(newSize);
setCurrentPage(1);
}}
view="collapsed"
>
{paginatedCollaboratives.map(
(collaborative: TypeCollaborative) => (
<Card
key={collaborative.id}
Expand Down Expand Up @@ -362,7 +388,7 @@ const CollaborativesListingClient = () => {
/>
)
)}
</div>
</GraphqlPagination>
) : (
<div className="flex flex-col items-center justify-center gap-4 py-20">
<Icon source={Icons.search} size={48} color="subdued" />
Expand All @@ -376,6 +402,7 @@ const CollaborativesListingClient = () => {
<Button
onClick={() => {
setSearchTerm('');
setCurrentPage(1);
}}
kind="secondary"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export async function generateMetadata({
image: `${process.env.NEXT_PUBLIC_PLATFORM_URL}/og.png`,
},
});
} catch (error) {
} catch {
// Fallback to generic metadata if the API call fails
return generatePageMetadata({
title: `Collaborative Details | CivicDataSpace`,
Expand Down
2 changes: 1 addition & 1 deletion app/[locale]/(user)/collaboratives/components/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const PrimaryDetails = ({ data, isLoading }: { data: any; isLoading: any }) => {
<Button
kind="tertiary"
className="lg:hidden"
onClick={(e) => setOpen(true)}
onClick={() => setOpen(true)}
>
<div className="flex items-center gap-2 py-2">
<Icon source={Icons.info} size={24} color="default" />
Expand Down
3 changes: 1 addition & 2 deletions app/[locale]/(user)/components/ListingComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { fetchData } from '@/fetch';
import { useTourTrigger } from '@/hooks/use-tour-trigger';
import {
Button,
ButtonGroup,
Card,
Icon,
Pill,
Expand Down Expand Up @@ -237,7 +236,7 @@ const ListingComponent: React.FC<ListingProps> = ({
const [variables, setVariables] = useState('');
const [open, setOpen] = useState(false);
const [queryParams, setQueryParams] = useReducer(queryReducer, initialState);
const [view, setView] = useState<'collapsed' | 'expanded'>('collapsed');
const [view] = useState<'collapsed' | 'expanded'>('collapsed');

const count = facets?.total ?? 0;
const datasetDetails = facets?.results ?? [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const PrimaryData: React.FC<PrimaryDataProps> = ({ data, isLoading }) => {
<Button
kind="tertiary"
className="lg:hidden"
onClick={(e) => setOpen(true)}
onClick={() => setOpen(true)}
>
<div className="flex items-center gap-2 py-2">
<Icon source={Icons.info} size={24} color="default" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useParams } from 'next/navigation';
import { stripMarkdown } from '@/app/[locale]/(user)/search/components/UnifiedListingComponent';
import { graphql } from '@/gql';
import { useQuery } from '@tanstack/react-query';
import {
Expand Down
2 changes: 1 addition & 1 deletion app/[locale]/(user)/publishers/PublishersListingClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useState } from 'react';
import Image from 'next/image';
import { graphql } from '@/gql';
import { useQuery } from '@tanstack/react-query';
import { Button, ButtonGroup, Spinner, Text } from 'opub-ui';
import { Button, ButtonGroup, Text } from 'opub-ui';

import { GraphQL } from '@/lib/api';
import { cn, generateJsonLd } from '@/lib/utils';
Expand Down
29 changes: 18 additions & 11 deletions app/[locale]/(user)/search/components/UnifiedListingComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
'use client';

import React, { useEffect, useReducer, useRef, useState } from 'react';
import React, { useEffect, useMemo, useReducer, useRef, useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import GraphqlPagination from '@/app/[locale]/dashboard/components/GraphqlPagination/graphqlPagination';
import {
Button,
ButtonGroup,
Card,
Icon,
Pill,
SearchInput,
Select,
Expand Down Expand Up @@ -315,7 +313,7 @@ const UnifiedListingComponent: React.FC<UnifiedListingProps> = ({
const [variables, setVariables] = useState('');
const [open, setOpen] = useState(false);
const [queryParams, setQueryParams] = useReducer(queryReducer, initialState);
const [view, setView] = useState<'collapsed' | 'expanded'>('collapsed');
const [view] = useState<'collapsed' | 'expanded'>('collapsed');
const [persistedTypeCounts, setPersistedTypeCounts] = useState<
Record<string, number>
>({});
Expand Down Expand Up @@ -382,10 +380,6 @@ const UnifiedListingComponent: React.FC<UnifiedListingProps> = ({
setQueryParams({ type: 'SET_SORT', payload: sortOption });
};

const handleOrderChange = (sortOrder: string) => {
setQueryParams({ type: 'SET_ORDER', payload: sortOrder });
};

const handleTypeFilter = (types: string) => {
setQueryParams({ type: 'SET_TYPES', payload: types });
};
Expand Down Expand Up @@ -444,7 +438,10 @@ const UnifiedListingComponent: React.FC<UnifiedListingProps> = ({
);

// Get type counts from aggregations
const typeCounts = aggregations.types || {};
const typeCounts = useMemo(
() => aggregations.types || {},
[aggregations.types]
);
const liveTypeCounts = Object.entries(typeCounts).reduce(
(acc, [key, value]) => {
if (typeof value === 'number') {
Expand All @@ -457,13 +454,23 @@ const UnifiedListingComponent: React.FC<UnifiedListingProps> = ({
const displayTypeCounts = { ...persistedTypeCounts, ...liveTypeCounts };

useEffect(() => {
if (Object.keys(liveTypeCounts).length === 0) return;
const counts = Object.entries(typeCounts).reduce(
(acc, [key, value]) => {
if (typeof value === 'number') {
acc[key] = value;
}
return acc;
},
{} as Record<string, number>
);

if (Object.keys(counts).length === 0) return;

setPersistedTypeCounts((prev) => {
const next = { ...prev };
let changed = false;

Object.entries(liveTypeCounts).forEach(([key, value]) => {
Object.entries(counts).forEach(([key, value]) => {
if (next[key] !== value) {
next[key] = value;
changed = true;
Expand Down
2 changes: 1 addition & 1 deletion app/[locale]/(user)/sectors/SectorsListing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const SectorsListing = () => {

useEffect(() => {
refetch();
}, [searchText]);
}, [searchText, refetch]);

const handleSortChange = (e: string) => {
const [field, direction] = e.split('_');
Expand Down
2 changes: 1 addition & 1 deletion app/[locale]/(user)/usecases/components/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const PrimaryDetails = ({ data, isLoading }: { data: any; isLoading: any }) => {
<Button
kind="tertiary"
className="lg:hidden"
onClick={(e) => setOpen(true)}
onClick={() => setOpen(true)}
>
<div className="flex items-center gap-2 py-2">
<Icon source={Icons.info} size={24} color="default" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ const Admin = () => {
useEffect(() => {
usersList.refetch();
setRefetch(false);
}, [refetch]);
}, [refetch, usersList]);

return (
<div>
Expand Down
Loading
Loading