Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ This changelog follows the principles of [Keep a Changelog](https://keepachangel

### Added

- Guestbooks: Added optional `includeStats` support to `getGuestbooksByCollectionId`, returning `usageCount` and `responseCount` when requested.

### Changed

### Fixed
Expand Down
10 changes: 7 additions & 3 deletions docs/useCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -2932,17 +2932,21 @@ _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_.
Expand Down
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
}
5 changes: 5 additions & 0 deletions src/guestbooks/domain/models/GuestbookResponse.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface GuestbookResponse {
[key: string]: unknown
guestbookId?: number
dataverseId?: number
}
14 changes: 13 additions & 1 deletion src/guestbooks/domain/repositories/IGuestbooksRepository.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
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
): Promise<Guestbook[]>
getGuestbookResponsesByDataverseId(
dataverseId: number | string,
guestbookId?: number
): Promise<GuestbookResponse[]>
downloadGuestbookResponsesByDataverseId(
dataverseId: 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,20 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { IGuestbooksRepository } from '../repositories/IGuestbooksRepository'

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

/**
* Downloads all guestbook responses for a dataverse collection.
*
* The dataverse 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} dataverseId - Dataverse alias/identifier or numeric database id.
* @returns {Promise<string>} Raw response body returned by the Dataverse API.
*/
async execute(dataverseId: number | string): Promise<string> {
return await this.guestbooksRepository.downloadGuestbookResponsesByDataverseId(dataverseId)
}
}
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) {}

/**
* Downloads guestbook responses for one guestbook in a dataverse collection.
*
* The dataverse 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} dataverseId - Dataverse 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(dataverseId: number | string, guestbookId: number): Promise<string> {
return await this.guestbooksRepository.downloadGuestbookResponsesByDataverseId(
dataverseId,
guestbookId
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { GuestbookResponse } from '../models/GuestbookResponse'
import { IGuestbooksRepository } from '../repositories/IGuestbooksRepository'

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

/**
* Returns all guestbook responses for a dataverse collection.
*
* @param {number | string} dataverseId - Dataverse identifier.
* @returns {Promise<GuestbookResponse[]>}
*/
async execute(dataverseId: number | string): Promise<GuestbookResponse[]> {
return await this.guestbooksRepository.getGuestbookResponsesByDataverseId(dataverseId)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { UseCase } from '../../../core/domain/useCases/UseCase'
import { GuestbookResponse } from '../models/GuestbookResponse'
import { IGuestbooksRepository } from '../repositories/IGuestbooksRepository'

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

/**
* Returns guestbook responses for one guestbook in a dataverse collection.
*
* @param {number | string} dataverseId - Dataverse identifier.
* @param {number} guestbookId - Guestbook identifier filter.
* @returns {Promise<GuestbookResponse[]>}
*/
async execute(dataverseId: number | string, guestbookId: number): Promise<GuestbookResponse[]> {
return await this.guestbooksRepository.getGuestbookResponsesByDataverseId(
dataverseId,
guestbookId
)
}
}
12 changes: 10 additions & 2 deletions src/guestbooks/domain/useCases/GetGuestbooksByCollectionId.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,17 @@ 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.
* @returns {Promise<Guestbook[]>}
*/
async execute(collectionIdOrAlias: number | string): Promise<Guestbook[]> {
return await this.guestbooksRepository.getGuestbooksByCollectionId(collectionIdOrAlias)
async execute(collectionIdOrAlias: number | string, includeStats = false): Promise<Guestbook[]> {
if (!includeStats) {
return await this.guestbooksRepository.getGuestbooksByCollectionId(collectionIdOrAlias)
}

Comment on lines +16 to +19
return await this.guestbooksRepository.getGuestbooksByCollectionId(
collectionIdOrAlias,
includeStats
)
}
}
21 changes: 21 additions & 0 deletions src/guestbooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { GuestbooksRepository } from './infra/repositories/GuestbooksRepository'
import { CreateGuestbook } from './domain/useCases/CreateGuestbook'
import { DownloadGuestbookResponsesByDataverseId } from './domain/useCases/DownloadGuestbookResponsesByDataverseId'
import { DownloadGuestbookResponsesOfAGuestbook } from './domain/useCases/DownloadGuestbookResponsesOfAGuestbook'
import { GetGuestbook } from './domain/useCases/GetGuestbook'
import { GetGuestbookResponsesByDataverseId } from './domain/useCases/GetGuestbookResponsesByDataverseId'
import { GetGuestbookResponsesOfAGuestbook } from './domain/useCases/GetGuestbookResponsesOfAGuestbook'
import { GetGuestbooksByCollectionId } from './domain/useCases/GetGuestbooksByCollectionId'
import { SetGuestbookEnabled } from './domain/useCases/SetGuestbookEnabled'
import { AssignDatasetGuestbook } from './domain/useCases/AssignDatasetGuestbook'
Expand All @@ -9,15 +13,31 @@ import { RemoveDatasetGuestbook } from './domain/useCases/RemoveDatasetGuestbook
const guestbooksRepository = new GuestbooksRepository()

const createGuestbook = new CreateGuestbook(guestbooksRepository)
const downloadGuestbookResponsesByDataverseId = new DownloadGuestbookResponsesByDataverseId(
guestbooksRepository
)
const downloadGuestbookResponsesOfAGuestbook = new DownloadGuestbookResponsesOfAGuestbook(
guestbooksRepository
)
const getGuestbook = new GetGuestbook(guestbooksRepository)
const getGuestbookResponsesByDataverseId = new GetGuestbookResponsesByDataverseId(
guestbooksRepository
)
const getGuestbookResponsesOfAGuestbook = new GetGuestbookResponsesOfAGuestbook(
guestbooksRepository
)
const getGuestbooksByCollectionId = new GetGuestbooksByCollectionId(guestbooksRepository)
const setGuestbookEnabled = new SetGuestbookEnabled(guestbooksRepository)
const assignDatasetGuestbook = new AssignDatasetGuestbook(guestbooksRepository)
const removeDatasetGuestbook = new RemoveDatasetGuestbook(guestbooksRepository)

export {
createGuestbook,
downloadGuestbookResponsesByDataverseId,
downloadGuestbookResponsesOfAGuestbook,
getGuestbook,
getGuestbookResponsesByDataverseId,
getGuestbookResponsesOfAGuestbook,
getGuestbooksByCollectionId,
setGuestbookEnabled,
assignDatasetGuestbook,
Expand All @@ -30,3 +50,4 @@ export {
CreateGuestbookOptionDTO
} from './domain/dtos/CreateGuestbookDTO'
export { Guestbook, GuestbookCustomQuestion, GuestbookOption } from './domain/models/Guestbook'
export { GuestbookResponse } from './domain/models/GuestbookResponse'
36 changes: 34 additions & 2 deletions src/guestbooks/infra/repositories/GuestbooksRepository.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { ApiRepository } from '../../../core/infra/repositories/ApiRepository'
import { CreateGuestbookDTO } from '../../domain/dtos/CreateGuestbookDTO'
import { Guestbook } from '../../domain/models/Guestbook'
import { GuestbookResponse } from '../../domain/models/GuestbookResponse'
import { IGuestbooksRepository } from '../../domain/repositories/IGuestbooksRepository'

export class GuestbooksRepository extends ApiRepository implements IGuestbooksRepository {
private readonly guestbooksResourceName: string = 'guestbooks'
private readonly datasetsResourceName: string = 'datasets'
private readonly dataversesResourceName: string = 'dataverses'

public async createGuestbook(
collectionIdOrAlias: number | string,
Expand Down Expand Up @@ -33,18 +35,48 @@ export class GuestbooksRepository extends ApiRepository implements IGuestbooksRe
}

public async getGuestbooksByCollectionId(
collectionIdOrAlias: number | string
collectionIdOrAlias: number | string,
includeStats = false
): Promise<Guestbook[]> {
return this.doGet(
this.buildApiEndpoint(this.guestbooksResourceName, `${collectionIdOrAlias}/list`),
true
true,
includeStats ? { includeStats } : {}
)
.then((response) => response.data.data as Guestbook[])
.catch((error) => {
throw error
})
}

public async getGuestbookResponsesByDataverseId(
dataverseId: number | string,
guestbookId?: number
): Promise<GuestbookResponse[]> {
const endpoint = `/${this.dataversesResourceName}/${dataverseId}/guestbookResponses`
const queryParams = guestbookId === undefined ? {} : { guestbookId }

return this.doGet(endpoint, true, queryParams)
.then((response) => response.data.data as GuestbookResponse[])
.catch((error) => {
throw error
})
}

public async downloadGuestbookResponsesByDataverseId(
dataverseId: number | string,
guestbookId?: number
): Promise<string> {
const endpoint = `/${this.dataversesResourceName}/${dataverseId}/guestbookResponses`
const queryParams = guestbookId === undefined ? {} : { guestbookId }

return this.doGet(endpoint, true, queryParams)
.then((response) => response.data as string)
.catch((error) => {
throw error
})
}

public async setGuestbookEnabled(
collectionIdOrAlias: number | string,
guestbookId: number,
Expand Down
Loading
Loading