Skip to content
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel

### Added

- Guestbooks: Added `getGuestbookResponsesByGuestbookId` use case and repository support for retrieving paginated guestbook responses as structured JSON.
- Guestbooks: Added `downloadGuestbookResponsesByCollectionId` and `downloadGuestbookResponsesOfAGuestbook` use cases and repository support for exporting guestbook responses as raw CSV content.
- Guestbooks: Added optional `includeStats` support to `getGuestbooksByCollectionId`, returning `usageCount` and `responseCount` when requested.
- Files: Added `getFileCitationByFormat` use case, repository method, and `FileCitationFormat` enum to support Dataverse file citation exports in `EndNote`, `RIS`, `BibTeX`, `CSL`, and `Internal` formats.
- Collections: Added `allowedDatasetTypes` field to the [Collection](./src/collections/domain/models/Collection.ts) model. This field is optional and only populated the feature is enabled on the installation and configured on the collection.
- Collections: Added theme information when retrieving a collection using `getCollection`.
Expand Down
76 changes: 73 additions & 3 deletions docs/useCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ The different use cases currently available in the package are classified below,
- [Guestbooks read use cases](#guestbooks-read-use-cases)
- [Get a Guestbook](#get-a-guestbook)
- [Get Guestbooks By Collection Id](#get-guestbooks-by-collection-id)
- [Get Guestbook Responses By Guestbook Id](#get-guestbook-responses-by-guestbook-id)
- [Download Guestbook Responses By Collection Id](#download-guestbook-responses-by-collection-id)
- [Download Guestbook Responses Of A Guestbook](#download-guestbook-responses-of-a-guestbook)
- [Guestbooks write use cases](#guestbooks-write-use-cases)
- [Create a Guestbook](#create-a-guestbook)
- [Set Guestbook Enabled](#set-guestbook-enabled)
Expand Down Expand Up @@ -3168,21 +3171,88 @@ _See [use case](../src/guestbooks/domain/useCases/GetGuestbook.ts) implementatio
#### Get Guestbooks By Collection Id

Returns all [Guestbook](../src/guestbooks/domain/models/Guestbook.ts) entries available for a collection.
Set `includeStats` to `true` to include `usageCount` and `responseCount` for each guestbook.

##### Example call:

```typescript
import { getGuestbooksByCollectionId } from '@iqss/dataverse-client-javascript'

const collectionIdOrAlias = 'root'
const includeStats = true

getGuestbooksByCollectionId.execute(collectionIdOrAlias).then((guestbooks: Guestbook[]) => {
/* ... */
})
getGuestbooksByCollectionId
.execute(collectionIdOrAlias, includeStats)
.then((guestbooks: Guestbook[]) => {
/* ... */
})
```

_See [use case](../src/guestbooks/domain/useCases/GetGuestbooksByCollectionId.ts) implementation_.

#### Get Guestbook Responses By Guestbook Id

Returns paginated [GuestbookResponse](../src/guestbooks/domain/models/GuestbookResponse.ts) entries for a guestbook.

##### Example call:

```typescript
import { getGuestbookResponsesByGuestbookId } from '@iqss/dataverse-client-javascript'

const guestbookId = 123
const limit = 10
const offset = 0

getGuestbookResponsesByGuestbookId
.execute(guestbookId, limit, offset)
.then((guestbookResponses: GuestbookResponse[]) => {
/* ... */
})
```

_See [use case](../src/guestbooks/domain/useCases/getGuestbookResponsesByGuestbookId.ts) implementation_.

#### Download Guestbook Responses By Collection Id

Downloads all guestbook responses for a collection and returns the raw response body, typically CSV content.

##### Example call:

```typescript
import { downloadGuestbookResponsesByCollectionId } from '@iqss/dataverse-client-javascript'

const collectionIdOrAlias = 'root'

downloadGuestbookResponsesByCollectionId
.execute(collectionIdOrAlias)
.then((csvResponse: string) => {
/* ... */
})
```

_See [use case](../src/guestbooks/domain/useCases/DownloadGuestbookResponsesByCollectionId.ts) implementation_.

#### Download Guestbook Responses Of A Guestbook

Downloads guestbook responses for one guestbook in a collection and returns the raw response body, typically CSV content.

##### Example call:

```typescript
import { downloadGuestbookResponsesOfAGuestbook } from '@iqss/dataverse-client-javascript'

const collectionIdOrAlias = 'root'
const guestbookId = 123

downloadGuestbookResponsesOfAGuestbook
.execute(collectionIdOrAlias, guestbookId)
.then((csvResponse: string) => {
/* ... */
})
```

_See [use case](../src/guestbooks/domain/useCases/DownloadGuestbookResponsesOfAGuestbook.ts) implementation_.

### Guestbooks Write Use Cases

#### Create a Guestbook
Expand Down
13 changes: 13 additions & 0 deletions src/guestbooks/domain/dtos/GuestbookResponsesDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Guestbook } from '../models/Guestbook'
import { GuestbookResponse } from '../models/GuestbookResponse'

export interface GuestbookResponsesDTO {
guestbook: Guestbook
responses: GuestbookResponse[]
pagination?: GuestbookResponsesPaginationDTO
}

export interface GuestbookResponsesPaginationDTO {
next?: string
totalResponses: number
}
2 changes: 2 additions & 0 deletions src/guestbooks/domain/models/Guestbook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ export interface Guestbook {
customQuestions: GuestbookCustomQuestion[]
createTime: string
dataverseId: number
usageCount?: number
responseCount?: number
}
27 changes: 27 additions & 0 deletions src/guestbooks/domain/models/GuestbookResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
export interface GuestbookResponse {
id: number
dataset: string
datasetPid: string
date: string
type: EventType
fileName?: string
fileId?: number
filePid?: string
userName: string
email?: string
institution?: string
position?: string
customQuestions?: GuestbookResponseCustomQuestion[]
}

export interface GuestbookResponseCustomQuestion {
question: string
response: string
}

export enum EventType {
ACCESS_REQUEST = 'AccessRequest',
DOWNLOAD = 'Download',
SUBSET = 'Subset',
EXPLORE = 'Explore'
}
16 changes: 15 additions & 1 deletion src/guestbooks/domain/repositories/IGuestbooksRepository.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import { CreateGuestbookDTO } from '../dtos/CreateGuestbookDTO'
import { Guestbook } from '../models/Guestbook'
import { GuestbookResponse } from '../models/GuestbookResponse'

export interface IGuestbooksRepository {
createGuestbook(
collectionIdOrAlias: number | string,
guestbook: CreateGuestbookDTO
): Promise<number>
getGuestbook(guestbookId: number): Promise<Guestbook>
getGuestbooksByCollectionId(collectionIdOrAlias: number | string): Promise<Guestbook[]>
getGuestbooksByCollectionId(
collectionIdOrAlias: number | string,
includeStats?: boolean,
includeInherited?: boolean
): Promise<Guestbook[]>
getGuestbookResponsesByGuestbookId(
guestbookId: number,
limit?: number,
offset?: number
): Promise<GuestbookResponse[]>
downloadGuestbookResponsesByCollectionId(
collectionIdOrAlias: number | string,
guestbookId?: number
): Promise<string>
setGuestbookEnabled(
collectionIdOrAlias: number | string,
guestbookId: number,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { IGuestbooksRepository } from '../repositories/IGuestbooksRepository'

export class DownloadGuestbookResponsesByCollectionId implements UseCase<string> {
constructor(private readonly guestbooksRepository: IGuestbooksRepository) {}

/**
* Downloads all guestbook responses for a collection.
*
* The collection can be identified by either its alias/identifier or numeric database id.
* The returned string is the raw response body from the Dataverse API, which is typically
* saved by callers as a CSV file or printed directly.
*
* @param {number | string} collectionIdOrAlias - Collection alias/identifier or numeric database id.
* @returns {Promise<string>} Raw response body returned by the Dataverse API.
*/
async execute(collectionIdOrAlias: number | string): Promise<string> {
return await this.guestbooksRepository.downloadGuestbookResponsesByCollectionId(
collectionIdOrAlias
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { IGuestbooksRepository } from '../repositories/IGuestbooksRepository'

export class DownloadGuestbookResponsesOfAGuestbook implements UseCase<string> {
constructor(private readonly guestbooksRepository: IGuestbooksRepository) {}

/**
Comment thread
ChengShi-1 marked this conversation as resolved.
* Downloads guestbook responses for one guestbook in a collection.
*
* The collection can be identified by either its alias/identifier or numeric database id.
* The returned string is the raw response body from the Dataverse API, which is typically
* saved by callers as a CSV file or printed directly.
*
* @param {number | string} collectionIdOrAlias - Collection alias/identifier or numeric database id.
* @param {number} guestbookId - Guestbook identifier to restrict the export.
* @returns {Promise<string>} Raw response body returned by the Dataverse API.
*/
async execute(collectionIdOrAlias: number | string, guestbookId: number): Promise<string> {
return await this.guestbooksRepository.downloadGuestbookResponsesByCollectionId(
collectionIdOrAlias,
guestbookId
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { GuestbookResponse } from '../models/GuestbookResponse'
import { IGuestbooksRepository } from '../repositories/IGuestbooksRepository'

export class GetGuestbookResponsesByGuestbookId implements UseCase<GuestbookResponse[]> {
constructor(private readonly guestbooksRepository: IGuestbooksRepository) {}

/**
* Returns guestbook responses for one guestbook.
*
* @param {number} guestbookId - Guestbook identifier.
* @param {number} limit - Maximum number of responses to return.
* @param {number} offset - Number of responses to skip.
* @returns {Promise<GuestbookResponse[]>}
*/
async execute(guestbookId: number, limit = 10, offset = 0): Promise<GuestbookResponse[]> {
return await this.guestbooksRepository.getGuestbookResponsesByGuestbookId(
guestbookId,
limit,
offset
)
}
}
18 changes: 16 additions & 2 deletions src/guestbooks/domain/useCases/GetGuestbooksByCollectionId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,23 @@ export class GetGuestbooksByCollectionId implements UseCase<Guestbook[]> {
* Returns all guestbooks available for a given collection.
*
* @param {number | string} collectionIdOrAlias - Collection identifier (numeric id or alias).
* @param {boolean} [includeStats=false] - Include usage and response counts for each guestbook.
* @param {boolean} [includeInherited=false] - Include guestbooks inherited from hierarchical owners.
* @returns {Promise<Guestbook[]>}
*/
async execute(collectionIdOrAlias: number | string): Promise<Guestbook[]> {
return await this.guestbooksRepository.getGuestbooksByCollectionId(collectionIdOrAlias)
async execute(
collectionIdOrAlias: number | string,
includeStats = false,
includeInherited = false
): Promise<Guestbook[]> {
if (!includeStats && !includeInherited) {
return await this.guestbooksRepository.getGuestbooksByCollectionId(collectionIdOrAlias)
}

return await this.guestbooksRepository.getGuestbooksByCollectionId(
collectionIdOrAlias,
includeStats,
includeInherited
)
}
}
24 changes: 24 additions & 0 deletions src/guestbooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { GuestbooksRepository } from './infra/repositories/GuestbooksRepository'
import { CreateGuestbook } from './domain/useCases/CreateGuestbook'
import { DownloadGuestbookResponsesByCollectionId } from './domain/useCases/DownloadGuestbookResponsesByCollectionId'
import { DownloadGuestbookResponsesOfAGuestbook } from './domain/useCases/DownloadGuestbookResponsesOfAGuestbook'
import { GetGuestbook } from './domain/useCases/GetGuestbook'
import { GetGuestbookResponsesByGuestbookId } from './domain/useCases/GetGuestbookResponsesByGuestbookId'
import { GetGuestbooksByCollectionId } from './domain/useCases/GetGuestbooksByCollectionId'
import { SetGuestbookEnabled } from './domain/useCases/SetGuestbookEnabled'
import { AssignDatasetGuestbook } from './domain/useCases/AssignDatasetGuestbook'
Expand All @@ -9,15 +12,27 @@ import { RemoveDatasetGuestbook } from './domain/useCases/RemoveDatasetGuestbook
const guestbooksRepository = new GuestbooksRepository()

const createGuestbook = new CreateGuestbook(guestbooksRepository)
const downloadGuestbookResponsesByCollectionId = new DownloadGuestbookResponsesByCollectionId(
guestbooksRepository
)
const downloadGuestbookResponsesOfAGuestbook = new DownloadGuestbookResponsesOfAGuestbook(
guestbooksRepository
)
const getGuestbook = new GetGuestbook(guestbooksRepository)
const getGuestbookResponsesByGuestbookId = new GetGuestbookResponsesByGuestbookId(
guestbooksRepository
)
const getGuestbooksByCollectionId = new GetGuestbooksByCollectionId(guestbooksRepository)
const setGuestbookEnabled = new SetGuestbookEnabled(guestbooksRepository)
const assignDatasetGuestbook = new AssignDatasetGuestbook(guestbooksRepository)
const removeDatasetGuestbook = new RemoveDatasetGuestbook(guestbooksRepository)

export {
createGuestbook,
downloadGuestbookResponsesByCollectionId,
downloadGuestbookResponsesOfAGuestbook,
getGuestbook,
getGuestbookResponsesByGuestbookId,
getGuestbooksByCollectionId,
setGuestbookEnabled,
assignDatasetGuestbook,
Expand All @@ -29,4 +44,13 @@ export {
CreateGuestbookCustomQuestionDTO,
CreateGuestbookOptionDTO
} from './domain/dtos/CreateGuestbookDTO'
export {
GuestbookResponsesDTO,
GuestbookResponsesPaginationDTO
} from './domain/dtos/GuestbookResponsesDTO'
export { Guestbook, GuestbookCustomQuestion, GuestbookOption } from './domain/models/Guestbook'
export {
EventType,
GuestbookResponse,
GuestbookResponseCustomQuestion
} from './domain/models/GuestbookResponse'
Loading
Loading