Skip to content

Commit

Permalink
feat: restrict/unrestrict file feature
Browse files Browse the repository at this point in the history
  • Loading branch information
ChengShi-1 committed Mar 3, 2025
1 parent fa6299a commit c7b80bd
Show file tree
Hide file tree
Showing 20 changed files with 715 additions and 16 deletions.
2 changes: 1 addition & 1 deletion dev-env/.env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
POSTGRES_VERSION=13
DATAVERSE_DB_USER=dataverse
SOLR_VERSION=9.3.0
SOLR_VERSION=9.8.0
REGISTRY=docker.io
S3_ACCESS_KEY=<S3_ACCESS_KEY>
S3_SECRET_KEY=<S3_SECRET_KEY>
18 changes: 17 additions & 1 deletion public/locales/en/file.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"options": {
"metadata": "Metadata",
"restrict": "Restrict",
"unrestrict": "Unrestrict",
"replace": "Replace",
"delete": "Delete"
}
Expand All @@ -65,5 +66,20 @@
"delete": "Delete"
},
"fileDeletedSuccess": "The file has been deleted.",
"defaultFileDeleteError": "Something went wrong deleting the file. Try again later."
"defaultFileDeleteError": "Something went wrong deleting the file. Try again later.",
"restriction": {
"fileRestrictdSuccess": "The file has been restricted.",
"fileUnrestrictedSuccess": "The file has been unrestricted.",
"restrictAccess": "Restrict Access",
"restrictionInfoP1": "Restricting limits access to published files. People who want to use the restricted files can request access by default. ",
"restrictionInfoP2": "If you disable request access, you must add information about access to the Terms of Access field.",
"restrictionInfoP3": "Learn about restricting files and dataset access in the ",
"userGuide": "User Guide",
"termsOfAccess": "Terms of Access for Restricted Files",
"enableAccessRequest": "Enable access request",
"saveChanges": "Save Changes",
"cancelChanges": "Cancel Changes",
"messagePublishedDataset": "Files will not be changed from previously published versions of the dataset.",
"message": "The file will be unrestricted."
}
}
10 changes: 6 additions & 4 deletions src/dataset/domain/models/Dataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,12 +246,12 @@ export class DatasetVersion {
public readonly isLatest: boolean,
public readonly isInReview: boolean,
public readonly latestVersionPublishingStatus: DatasetPublishingStatus,
public readonly someDatasetVersionHasBeenReleased: boolean
public readonly someDatasetVersionHasBeenReleased: boolean,
public readonly termsOfAccess?: TermsOfAccess
) {}

static Builder = class {
public readonly labels: DatasetLabel[] = []

constructor(
public readonly id: number,
public readonly title: string,
Expand All @@ -261,7 +261,8 @@ export class DatasetVersion {
public readonly isLatest: boolean,
public readonly isInReview: boolean,
public readonly latestVersionPublishingStatus: DatasetPublishingStatus,
public readonly someDatasetVersionHasBeenReleased: boolean
public readonly someDatasetVersionHasBeenReleased: boolean,
public readonly termsOfAccess?: TermsOfAccess
) {
this.createLabels()
}
Expand Down Expand Up @@ -327,7 +328,8 @@ export class DatasetVersion {
this.isLatest,
this.isInReview,
this.latestVersionPublishingStatus,
this.someDatasetVersionHasBeenReleased
this.someDatasetVersionHasBeenReleased,
this.termsOfAccess
)
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/dataset/infrastructure/mappers/JSDatasetVersionMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ import {
import {
DatasetPublishingStatus,
DatasetVersion,
DatasetVersionNumber
DatasetVersionNumber,
TermsOfAccess
} from '../../domain/models/Dataset'

export class JSDatasetVersionMapper {
static toVersion(
jDatasetVersionId: number,
jsDatasetVersionInfo: JSDatasetVersionInfo,
jsDatasetTitle: string,
jsDatasetCitation: string,
jsDatasetPublicationDate?: string
jsDatasetPublicationDate?: string,
jsDatasettermsOfAccess?: TermsOfAccess
): DatasetVersion {
return new DatasetVersion.Builder(
jDatasetVersionId,
Expand All @@ -24,7 +27,8 @@ export class JSDatasetVersionMapper {
true, // TODO Connect with dataset version isLatest
false, // TODO Connect with dataset version isInReview
this.toStatus(jsDatasetVersionInfo.state),
this.toSomeDatasetVersionHasBeenReleased(jsDatasetVersionInfo, jsDatasetPublicationDate)
this.toSomeDatasetVersionHasBeenReleased(jsDatasetVersionInfo, jsDatasetPublicationDate),
jsDatasettermsOfAccess
)
}

Expand Down
1 change: 1 addition & 0 deletions src/files/domain/repositories/FileRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ export interface FileRepository {
) => Promise<void>
addUploadedFiles: (datasetId: number | string, files: UploadedFileDTO[]) => Promise<void>
delete: (fileId: number | string) => Promise<void>
restrict: (fileId: number | string, restrict: boolean) => Promise<void>
}
9 changes: 9 additions & 0 deletions src/files/domain/useCases/restrictFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { FileRepository } from '../repositories/FileRepository'

export function restrictFile(
fileRepository: FileRepository,
fileId: number | string,
restrict: boolean
): Promise<void> {
return fileRepository.restrict(fileId, restrict)
}
7 changes: 6 additions & 1 deletion src/files/infrastructure/FileJSDataverseRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {
addUploadedFilesToDataset,
UploadedFileDTO,
ReadError,
deleteFile
deleteFile,
restrictFile
} from '@iqss/dataverse-client-javascript'
import { FileCriteria } from '../domain/models/FileCriteria'
import { DomainFileMapper } from './mappers/DomainFileMapper'
Expand Down Expand Up @@ -308,4 +309,8 @@ export class FileJSDataverseRepository implements FileRepository {
delete(fileId: number | string): Promise<void> {
return deleteFile.execute(fileId)
}

restrict(fileId: number | string, restrict: boolean): Promise<void> {
return restrictFile.execute(fileId, restrict)
}
}
4 changes: 3 additions & 1 deletion src/files/infrastructure/mappers/JSFileMapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export class JSFileMapper {
jsDataset.versionId,
jsDataset.versionInfo,
JSDatasetMapper.toDatasetTitle(jsDataset.metadataBlocks),
datasetCitation
datasetCitation,
jsDataset.publicationDate,
jsDataset.termsOfUse?.termsOfAccess
)
return {
id: this.toFileId(jsFile.id),
Expand Down
5 changes: 4 additions & 1 deletion src/sections/file/File.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,13 @@ export function File({ repository, id, datasetVersionNumber }: FileProps) {
<EditFileMenu
fileId={file.id}
fileRepository={repository}
isRestricted={file.access.restricted}
datasetInfo={{
persistentId: file.datasetPersistentId,
releasedVersionExists:
file.datasetVersion.someDatasetVersionHasBeenReleased
file.datasetVersion.someDatasetVersionHasBeenReleased,
termsOfAccessForRestrictedFiles:
file.datasetVersion.termsOfAccess?.termsOfAccessForRestrictedFiles
}}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,27 @@ import { useTranslation } from 'react-i18next'
import { DropdownButton } from '@iqss/dataverse-design-system'
import { FileRepository } from '@/files/domain/repositories/FileRepository'
import { DeleteFileButton } from './delete-file-button/DeleteFileButton'
import { RestrictFileButton } from './restrict-file-button/RestrictFileButton'

interface EditFileMenuProps {
fileId: number
fileRepository: FileRepository
isRestricted: boolean
datasetInfo: EditFileMenuDatasetInfo
}

export interface EditFileMenuDatasetInfo {
persistentId: string
releasedVersionExists: boolean
termsOfAccessForRestrictedFiles?: string
}

export const EditFileMenu = ({ fileId, fileRepository, datasetInfo }: EditFileMenuProps) => {
export const EditFileMenu = ({
fileId,
fileRepository,
datasetInfo,
isRestricted
}: EditFileMenuProps) => {
const { t } = useTranslation('file')

return (
Expand All @@ -25,9 +33,13 @@ export const EditFileMenu = ({ fileId, fileRepository, datasetInfo }: EditFileMe
variant="secondary">
{/* 👇 These buttons are commented out but I keep them because they are the next thing to be developed.*/}
{/* <DropdownButtonItem>{t('actionButtons.editFileMenu.options.metadata')}</DropdownButtonItem>
<DropdownButtonItem>{t('actionButtons.editFileMenu.options.restrict')}</DropdownButtonItem>
<DropdownButtonItem>{t('actionButtons.editFileMenu.options.replace')}</DropdownButtonItem> */}

<RestrictFileButton
fileId={fileId}
isRestricted={isRestricted}
fileRepository={fileRepository}
datasetInfo={datasetInfo}
/>
<DeleteFileButton fileId={fileId} fileRepository={fileRepository} datasetInfo={datasetInfo} />
</DropdownButton>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { toast } from 'react-toastify'
import { DropdownButtonItem } from '@iqss/dataverse-design-system'
import { FileRepository } from '@/files/domain/repositories/FileRepository'
import { QueryParamKey, Route } from '@/sections/Route.enum'
import { DatasetNonNumericVersionSearchParam } from '@/dataset/domain/models/Dataset'
import { ConfirmRestrictFileModal } from './confirm-restrict-file-modal/ConfirmRestrictFileModal'
import { EditFileMenuDatasetInfo } from '../EditFileMenu'
import { useRestrictFile } from './useRestrictFile'

interface RestrictFileButtonProps {
fileId: number
isRestricted: boolean
fileRepository: FileRepository
datasetInfo: EditFileMenuDatasetInfo
}

export const RestrictFileButton = ({
fileId,
isRestricted,
fileRepository,
datasetInfo
}: RestrictFileButtonProps) => {
const [showConfirmationModal, setShowConfirmationModal] = useState(false)
const navigate = useNavigate()
const { t } = useTranslation('file')

const { handleRestrictFile, isRestrictingFile, errorRestrictingFile } = useRestrictFile({
isRestricted,
fileRepository,
onSuccessfulRestrict: closeModalAndNavigateToDataset
})
const handleOpenModal = () => setShowConfirmationModal(true)
const handleCloseModal = () => setShowConfirmationModal(false)

function closeModalAndNavigateToDataset() {
setShowConfirmationModal(false)

const searchParams = new URLSearchParams()
searchParams.set(QueryParamKey.PERSISTENT_ID, datasetInfo.persistentId)
searchParams.set(QueryParamKey.VERSION, DatasetNonNumericVersionSearchParam.DRAFT)
isRestricted
? toast.success(t('restriction.fileUnrestrictedSuccess'))
: toast.success(t('restriction.fileRestrictdSuccess'))
navigate(`${Route.DATASETS}?${searchParams.toString()}`)
}

return (
<>
<DropdownButtonItem onClick={handleOpenModal}>
{isRestricted
? t('actionButtons.editFileMenu.options.unrestrict')
: t('actionButtons.editFileMenu.options.restrict')}
</DropdownButtonItem>
<ConfirmRestrictFileModal
show={showConfirmationModal}
handleClose={handleCloseModal}
handleRestrict={() => handleRestrictFile(fileId)}
datasetReleasedVersionExists={datasetInfo.releasedVersionExists}
termsOfAccessForRestrictedFiles={datasetInfo.termsOfAccessForRestrictedFiles}
isRestrictingFile={isRestrictingFile}
errorRestrictingFile={errorRestrictingFile}
isRestricted={isRestricted}
/>
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@import 'node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module';

.message {
color: $dv-warning-color;

&.error {
color: $dv-danger-color;
}

svg {
min-width: fit-content;
}
}

.restriction_form {
padding-top: 0.5em;
padding-bottom: 0.5em;
}

.restriction_info {
padding-top: 0.5em;
padding-bottom: 0.5em;
color: $dv-subtext-color;
}
Loading

0 comments on commit c7b80bd

Please sign in to comment.