Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2c79b64
feat: add file citation download
ChengShi-1 May 26, 2026
19b8624
update changelog
ChengShi-1 May 27, 2026
e5442a5
Merge branch 'develop' into CiteDataFile-Integration
ChengShi-1 Jun 10, 2026
4eecfeb
update package
ChengShi-1 Jun 10, 2026
1d9a1e4
Merge branch 'develop' into CiteDataFile-Integration
ChengShi-1 Jun 10, 2026
25e1368
feat: add edit guestbook use case, and apply GuestbookDTO to both edi…
ChengShi-1 Jun 23, 2026
5518176
feat: edit guestbook integration
ChengShi-1 Jun 24, 2026
b53808d
feat: guestbook response page
ChengShi-1 Jun 24, 2026
f8853d5
Merge branch 'ManageGuestbook' into 1002-edit-guestbook-and-guestbook…
ChengShi-1 Jun 25, 2026
e0c57c5
fix: increase test coverage
ChengShi-1 Jun 25, 2026
ca340f6
fix: e2e test error
ChengShi-1 Jun 25, 2026
cc8dd2f
fix: make guestbooks enabled by default
ChengShi-1 Jun 26, 2026
260297d
feat: copy guestbook action button
ChengShi-1 Jun 26, 2026
6c547a6
fix: accessibility test error
ChengShi-1 Jun 26, 2026
1839bd6
fix: Lint error
ChengShi-1 Jun 26, 2026
fd320fc
fix: update guestbookDTO
ChengShi-1 Jul 1, 2026
c9e321e
Merge branch 'ManageGuestbook' into 1002-edit-guestbook-and-guestbook…
ChengShi-1 Jul 1, 2026
d62152e
fix: copilot review
ChengShi-1 Jul 1, 2026
97cddaa
Merge with develop branch
ChengShi-1 Jul 2, 2026
e504ed5
Merge branch 'develop' into CiteDataFile-Integration
ChengShi-1 Jul 22, 2026
228cd56
Merge pull request #995 from IQSS/CiteDataFile-Integration
sekmiller Jul 23, 2026
fd0d679
Merge pull request #992 from IQSS/ManageGuestbook
sekmiller Jul 24, 2026
9e82b53
Merge branch 'develop' of https://github.com/IQSS/dataverse-frontend …
ChengShi-1 Jul 30, 2026
d740540
fix: unit test
ChengShi-1 Jul 30, 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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel
### Added

- Manage Guestbooks page integration, including:
- a guestbooks table with sorting, enable/disable actions, preview, and per-guestbook response download
- a guestbooks table with sorting, edit, enable/disable actions, preview, and per-guestbook response download
- Create Guestbook and Download All Responses actions
- the Create Guestbook page
- the Create and Edit Guestbook pages
- a checkbox for including guestbooks from parent collections
Comment thread
ChengShi-1 marked this conversation as resolved.
- Dataset Templates UI integration, including create/edit flows, previews, and skeleton states.

Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@dnd-kit/sortable": "8.0.0",
"@dnd-kit/utilities": "3.2.2",
"@faker-js/faker": "7.6.0",
"@iqss/dataverse-client-javascript": "v2.2.0-alpha.9",
"@iqss/dataverse-client-javascript": "2.2.0-alpha.11",
"@iqss/dataverse-design-system": "*",
"@istanbuljs/nyc-config-typescript": "1.0.2",
"@tanstack/react-table": "8.9.2",
Expand Down
2 changes: 1 addition & 1 deletion public/locales/en/datasetTemplates.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"create": "Create Dataset Template",
"makeDefault": "Make Default",
"default": "Default",
"view": "View",
"view": "Preview",
"copy": "Copy",
"edit": "Edit Template",
"delete": "Delete",
Comment thread
ChengShi-1 marked this conversation as resolved.
Expand Down
34 changes: 32 additions & 2 deletions public/locales/en/guestbooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,24 @@
"enable": "Enable",
"disable": "Disable",
"downloadAllResponses": "Download All Responses",
"view": "View",
"view": "Preview",
"copy": "Copy",
"edit": "Edit",
"delete": "Delete",
"downloadResponses": "Download responses",
"viewResponses": "View Responses"
},
"errors": {
"getGuestbook": "Something went wrong getting the guestbook. Try again later.",
"editGuestbook": "Something went wrong editing the guestbook. Try again later.",
"getGuestbookResponses": "Something went wrong getting guestbook responses. Try again later.",
"toggleEnabled": "Something went wrong updating the guestbook status. Try again later.",
"downloadResponses": "Something went wrong downloading guestbook responses. Try again later."
},
"alerts": {
"statusUpdated": "The guestbook status has been updated.",
"downloadStarted": "Your download has started."
"downloadStarted": "Your download has started.",
"updated": "The guestbook has been updated."
},
"preview": {
"title": "Preview Guestbook",
Expand Down Expand Up @@ -94,5 +98,31 @@
},
"submit": "Create Dataset Guestbook",
"cancel": "Cancel"
},
"edit": {
"title": "Edit Dataset Guestbook"
},
"responses": {
"title": "Guestbook Responses",
"info": "Click \"Download Responses\" to download all collected responses for this guestbook, as a CSV file. To navigate and analyze your collected responses, we recommend importing this CSV file into Excel, Google Sheets or similar software.",
"guestbookName": "Guestbook Name",
"downloadButton": "Download Responses",
"count_one": "{{count}} Response",
"count_other": "{{count}} Responses",
"noRecords": "No records found.",
"table": {
"dataset": "Dataset",
"date": "Date",
"type": "Type",
"file": "File",
"user": "User",
"customQuestions": "Custom Questions"
},
"eventTypes": {
"AccessRequest": "Access Request",
"Download": "Download",
"Subset": "Subset",
"Explore": "Explore"
}
}
}
2 changes: 1 addition & 1 deletion public/locales/es/datasetTemplates.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"create": "Crear plantilla de conjunto de datos",
"makeDefault": "Hacer predeterminada",
"default": "Predeterminada",
"view": "Ver",
"view": "Vista previa",
"copy": "Copiar",
"edit": "Editar plantilla",
"delete": "Eliminar"
Expand Down
34 changes: 32 additions & 2 deletions public/locales/es/guestbooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,24 @@
"enable": "Habilitar",
"disable": "Deshabilitar",
"downloadAllResponses": "Descargar todas las respuestas",
"view": "Ver",
"view": "Vista previa",
"copy": "Copiar",
"edit": "Editar",
"delete": "Eliminar",
"downloadResponses": "Descargar respuestas",
"viewResponses": "Ver respuestas"
},
"errors": {
"getGuestbook": "Algo salió mal al obtener el libro de visitas. Inténtalo de nuevo más tarde.",
"editGuestbook": "Algo salió mal al editar el libro de visitas. Inténtalo de nuevo más tarde.",
"getGuestbookResponses": "Algo salió mal al obtener las respuestas del libro de visitas. Inténtalo de nuevo más tarde.",
"toggleEnabled": "Algo salió mal al actualizar el estado del libro de visitas. Inténtalo de nuevo más tarde.",
"downloadResponses": "Algo salió mal al descargar las respuestas del libro de visitas. Inténtalo de nuevo más tarde."
},
"alerts": {
"statusUpdated": "El estado del libro de visitas se ha actualizado.",
"downloadStarted": "La descarga ha comenzado."
"downloadStarted": "La descarga ha comenzado.",
"updated": "El libro de visitas se ha actualizado."
},
"preview": {
"title": "Vista previa del libro de visitas",
Expand Down Expand Up @@ -94,5 +98,31 @@
},
"submit": "Crear libro de visitas del dataset",
"cancel": "Cancelar"
},
"edit": {
"title": "Editar libro de visitas del dataset"
},
"responses": {
"title": "Respuestas del libro de visitas",
"info": "Haz clic en \"Descargar respuestas\" para descargar todas las respuestas recopiladas para este libro de visitas como archivo CSV. Para navegar y analizar las respuestas recopiladas, recomendamos importar este archivo CSV en Excel, Google Sheets o software similar.",
"guestbookName": "Nombre del libro de visitas",
"downloadButton": "Descargar respuestas",
"count_one": "{{count}} respuesta",
"count_other": "{{count}} respuestas",
"noRecords": "No se encontraron registros.",
"table": {
"dataset": "Dataset",
"date": "Fecha",
"type": "Tipo",
"file": "Fichero",
"user": "Usuario",
"customQuestions": "Preguntas personalizadas"
},
"eventTypes": {
"AccessRequest": "Solicitud de acceso",
"Download": "Descarga",
"Subset": "Subconjunto",
"Explore": "Explorar"
}
}
}
3 changes: 2 additions & 1 deletion src/guestbooks/domain/models/Guestbook.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
export type GuestbookQuestionType = 'text' | 'textarea' | 'options'

export interface GuestbookOption {
id?: number
value: string
displayOrder: number
}

export interface GuestbookCustomQuestion {
id?: number | string
id?: number
question: string
required: boolean
displayOrder: number
Expand Down
6 changes: 3 additions & 3 deletions src/guestbooks/domain/models/GuestbookResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ export interface GuestbookResponse {
datasetPid: string
date: string
type: EventType
fileName?: string
email?: string
fileId?: number
fileName?: string
filePid?: string
userName: string
email?: string
institution?: string
position?: string
userName: string
customQuestions?: GuestbookResponseCustomQuestion[]
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { PaginationInfo } from '@/shared/pagination/domain/models/PaginationInfo'

export class GuestbookResponsesPaginationInfo extends PaginationInfo<GuestbookResponsesPaginationInfo> {
constructor(page = 1, pageSize = 10, totalItems = 0, itemName = 'Response') {
super(page, pageSize, totalItems, itemName)
}
}
5 changes: 3 additions & 2 deletions src/guestbooks/domain/repositories/GuestbookRepository.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { type CreateGuestbookDTO } from '@iqss/dataverse-client-javascript'
import { GuestbookDTO } from '../useCases/DTOs/GuestbookDTO'
import { Guestbook } from '../models/Guestbook'
import { GuestbookResponseSubset } from '../models/GuestbookResponse'

export interface GuestbookRepository {
createGuestbook: (
collectionIdOrAlias: number | string,
guestbook: CreateGuestbookDTO
guestbook: GuestbookDTO
) => Promise<number>
editGuestbook: (guestbookId: number, guestbook: GuestbookDTO) => Promise<void>
getGuestbook: (guestbookId: number) => Promise<Guestbook>
getGuestbooksByCollectionId: (
collectionIdOrAlias: number | string,
Expand Down
28 changes: 28 additions & 0 deletions src/guestbooks/domain/useCases/DTOs/GuestbookDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { GuestbookQuestionType } from '../../models/Guestbook'

export interface GuestbookDTO {
name: string
enabled: boolean
emailRequired: boolean
nameRequired: boolean
institutionRequired: boolean
positionRequired: boolean
createTime?: string
customQuestions?: GuestbookCustomQuestionDTO[]
}

export interface GuestbookCustomQuestionDTO {
id?: number
question: string
required: boolean
displayOrder: number
type: GuestbookQuestionType
hidden: boolean
optionValues?: GuestbookOptionDTO[]
}

export interface GuestbookOptionDTO {
id?: number
value: string
displayOrder: number
}
4 changes: 2 additions & 2 deletions src/guestbooks/domain/useCases/createGuestbook.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { type CreateGuestbookDTO } from '@iqss/dataverse-client-javascript'
import { GuestbookRepository } from '../repositories/GuestbookRepository'
import { GuestbookDTO } from './DTOs/GuestbookDTO'

export function createGuestbook(
guestbookRepository: GuestbookRepository,
collectionIdOrAlias: number | string,
guestbook: CreateGuestbookDTO
guestbook: GuestbookDTO
): Promise<number> {
return guestbookRepository.createGuestbook(collectionIdOrAlias, guestbook)
}
10 changes: 10 additions & 0 deletions src/guestbooks/domain/useCases/editGuestbook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { GuestbookRepository } from '../repositories/GuestbookRepository'
import { GuestbookDTO } from './DTOs/GuestbookDTO'

export function editGuestbook(
guestbookRepository: GuestbookRepository,
guestbookId: number,
guestbook: GuestbookDTO
): Promise<void> {
return guestbookRepository.editGuestbook(guestbookId, guestbook)
}
15 changes: 15 additions & 0 deletions src/guestbooks/domain/useCases/getGuestbooksByCollectionId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Guestbook } from '../models/Guestbook'
import { GuestbookRepository } from '../repositories/GuestbookRepository'

export function getGuestbooksByCollectionId(
guestbookRepository: GuestbookRepository,
collectionIdOrAlias: number | string,
includeStats?: boolean,
includeInherited?: boolean
): Promise<Guestbook[]> {
return guestbookRepository.getGuestbooksByCollectionId(
collectionIdOrAlias,
includeStats,
includeInherited
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import {
createGuestbook,
downloadGuestbookResponsesByCollectionId,
downloadGuestbookResponsesOfAGuestbook as downloadGuestbookResponsesByGuestbookId,
type CreateGuestbookDTO,
type CreateGuestbookDTO as JSDataverseCreateGuestbookDTO,
editGuestbook,
type EditGuestbookDTO as JSDataverseEditGuestbookDTO,
type GuestbookResponseSubset,
getGuestbooksByCollectionId,
getGuestbook,
Expand All @@ -13,17 +15,26 @@ import {
} from '@iqss/dataverse-client-javascript'
import { GuestbookRepository } from '../../domain/repositories/GuestbookRepository'
import { Guestbook } from '../../domain/models/Guestbook'
import { GuestbookDTO } from '../../domain/useCases/DTOs/GuestbookDTO'

const normalizeGuestbook = (guestbook: Guestbook): Guestbook => ({
...guestbook,
customQuestions: guestbook.customQuestions ?? []
})

export class GuestbookJSDataverseRepository implements GuestbookRepository {
createGuestbook(
collectionIdOrAlias: number | string,
guestbook: CreateGuestbookDTO
): Promise<number> {
return createGuestbook.execute(guestbook, collectionIdOrAlias)
createGuestbook(collectionIdOrAlias: number | string, guestbook: GuestbookDTO): Promise<number> {
return createGuestbook.execute(guestbook as JSDataverseCreateGuestbookDTO, collectionIdOrAlias)
}

editGuestbook(guestbookId: number, guestbook: GuestbookDTO): Promise<void> {
return editGuestbook.execute(guestbookId, guestbook as JSDataverseEditGuestbookDTO)
}

getGuestbook(guestbookId: number): Promise<Guestbook> {
return getGuestbook.execute(guestbookId).then((guestbook) => guestbook as Guestbook)
return getGuestbook
.execute(guestbookId)
.then((guestbook) => normalizeGuestbook(guestbook as Guestbook))
}

getGuestbooksByCollectionId(
Expand All @@ -33,7 +44,7 @@ export class GuestbookJSDataverseRepository implements GuestbookRepository {
): Promise<Guestbook[]> {
return getGuestbooksByCollectionId
.execute(collectionIdOrAlias, includeStats, includeInherited)
.then((guestbooks) => guestbooks as Guestbook[])
.then((guestbooks) => (guestbooks as Guestbook[]).map(normalizeGuestbook))
}

getGuestbookResponsesByGuestbookId(
Expand Down
Loading
Loading