Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/211 edit publish alert messages #217

Merged
merged 18 commits into from
Nov 23, 2023
Merged
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
14 changes: 12 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,19 @@
"unused-imports/no-unused-imports": "error",
"unused-imports/no-unused-vars": [
"warn",
{ "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" }
{
"vars": "all",
"varsIgnorePattern": "^_",
"args": "after-used",
"argsIgnorePattern": "^_"
}
],
"@typescript-eslint/no-empty-function": [
"error",
{
"allow": ["arrowFunctions"]
}
],
"@typescript-eslint/no-empty-function": ["error", { "allow": ["arrowFunctions"] }],
"react/react-in-jsx-scope": "off",
"prettier/prettier": [
"error",
Expand Down
24 changes: 24 additions & 0 deletions public/locales/en/dataset.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,30 @@
"uploadFiles": "Upload Files"
},
"alerts": {
"publishInProgress": {
"heading": "Publish in Progress",
"alertText": "The dataset is locked while the persistent identifiers are being registered or updated, and/or the physical files are being validated."
},
"filesUpdated": {
"heading": "Success!",
"alertText": "One or more files have been updated."
},
"termsUpdated": {
"heading": "Success!",
"alertText": "The terms for this dataset have been updated."
},
"thumbnailUpdated": {
"heading": "Success!",
"alertText": "Dataset thumbnail updated."
},
"datasetDeleted": {
"heading": "Success!",
"alertText": "This dataset draft has been deleted."
},
"metadataUpdated": {
"heading": "Success!",
"alertText": "The metadata for this dataset has been updated."
},
"draftVersion": {
"heading": "This draft version needs to be published",
"alertText": "When ready for sharing, please <b>publish</b> it so that others can see these changes"
Expand Down
23 changes: 23 additions & 0 deletions src/alert/domain/models/Alert.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { AlertVariant } from '@iqss/dataverse-design-system/dist/components/alert/AlertVariant'

export enum AlertMessageKey {
DRAFT_VERSION = 'draftVersion',
REQUESTED_VERSION_NOT_FOUND = 'requestedVersionNotFound',
REQUESTED_VERSION_NOT_FOUND_SHOW_DRAFT = 'requestedVersionNotFoundShowDraft',
SHARE_UNPUBLISHED_DATASET = 'shareUnpublishedDataset',
UNPUBLISHED_DATASET = 'unpublishedDataset',
METADATA_UPDATED = 'metadataUpdated',
FILES_UPDATED = 'filesUpdated',
TERMS_UPDATED = 'termsUpdated',
THUMBNAIL_UPDATED = 'thumbnailUpdated',
DATASET_DELETED = 'datasetDeleted',
PUBLISH_IN_PROGRESS = 'publishInProgress'
}

export class Alert {
constructor(
public readonly variant: AlertVariant,
public readonly messageKey: AlertMessageKey,
public dynamicFields?: object
) {}
}
42 changes: 9 additions & 33 deletions src/dataset/domain/models/Dataset.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AlertVariant } from '@iqss/dataverse-design-system/dist/components/alert/AlertVariant'
import { Alert, AlertMessageKey } from '../../../alert/domain/models/Alert'

export enum DatasetLabelSemanticMeaning {
DATASET = 'dataset',
Expand All @@ -24,22 +24,6 @@ export class DatasetLabel {
) {}
}

export enum DatasetAlertMessageKey {
DRAFT_VERSION = 'draftVersion',
REQUESTED_VERSION_NOT_FOUND = 'requestedVersionNotFound',
REQUESTED_VERSION_NOT_FOUND_SHOW_DRAFT = 'requestedVersionNotFoundShowDraft',
SHARE_UNPUBLISHED_DATASET = 'shareUnpublishedDataset',
UNPUBLISHED_DATASET = 'unpublishedDataset'
}

export class DatasetAlert {
constructor(
public readonly variant: AlertVariant,
public readonly message: DatasetAlertMessageKey,
public readonly dynamicFields?: object
) {}
}

export enum MetadataBlockName {
CITATION = 'citation',
GEOSPATIAL = 'geospatial',
Expand Down Expand Up @@ -286,7 +270,7 @@ export class Dataset {
public readonly version: DatasetVersion,
public readonly citation: string,
public readonly labels: DatasetLabel[],
public readonly alerts: DatasetAlert[],
public readonly alerts: Alert[],
public readonly summaryFields: DatasetMetadataBlock[],
public readonly license: DatasetLicense,
public readonly metadataBlocks: DatasetMetadataBlocks,
Expand Down Expand Up @@ -327,7 +311,7 @@ export class Dataset {

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

constructor(
public readonly persistentId: string,
Expand Down Expand Up @@ -398,7 +382,7 @@ export class Dataset {
this.version.publishingStatus === DatasetPublishingStatus.DRAFT &&
this.permissions.canPublishDataset
) {
this.alerts.push(new DatasetAlert('warning', DatasetAlertMessageKey.DRAFT_VERSION))
this.alerts.push(new Alert('warning', AlertMessageKey.DRAFT_VERSION))
}
if (this.version.requestedVersion) {
if (this.version.latestVersionStatus == DatasetPublishingStatus.RELEASED) {
Expand All @@ -407,20 +391,16 @@ export class Dataset {
returnedVersion: `${this.version.toString()}`
}
this.alerts.push(
new DatasetAlert(
'warning',
DatasetAlertMessageKey.REQUESTED_VERSION_NOT_FOUND,
dynamicFields
)
new Alert('warning', AlertMessageKey.REQUESTED_VERSION_NOT_FOUND, dynamicFields)
)
} else {
const dynamicFields = {
requestedVersion: this.version.requestedVersion
}
this.alerts.push(
new DatasetAlert(
new Alert(
'warning',
DatasetAlertMessageKey.REQUESTED_VERSION_NOT_FOUND_SHOW_DRAFT,
AlertMessageKey.REQUESTED_VERSION_NOT_FOUND_SHOW_DRAFT,
dynamicFields
)
)
Expand All @@ -430,14 +410,10 @@ export class Dataset {
if (this.permissions.canPublishDataset) {
const dynamicFields = { privateUrl: this.privateUrl.urlSnippet + this.privateUrl.token }
this.alerts.push(
new DatasetAlert(
'info',
DatasetAlertMessageKey.SHARE_UNPUBLISHED_DATASET,
dynamicFields
)
new Alert('info', AlertMessageKey.SHARE_UNPUBLISHED_DATASET, dynamicFields)
)
} else {
this.alerts.push(new DatasetAlert('warning', DatasetAlertMessageKey.UNPUBLISHED_DATASET))
this.alerts.push(new Alert('warning', AlertMessageKey.UNPUBLISHED_DATASET))
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/sections/alerts/AlertContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createContext, useContext } from 'react'

import { Alert, AlertMessageKey } from '../../alert/domain/models/Alert'

interface DatasetAlertContextProps {
datasetAlerts: Alert[]
addDatasetAlert: (newAlert: Alert) => void
removeDatasetAlert: (alertId: AlertMessageKey) => void
}

export const AlertContext = createContext<DatasetAlertContextProps>({
datasetAlerts: [],
addDatasetAlert: /* istanbul ignore next */ () => {},
removeDatasetAlert: /* istanbul ignore next */ () => {}
})
export const useAlertContext = () => useContext(AlertContext)
31 changes: 31 additions & 0 deletions src/sections/alerts/AlertProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { PropsWithChildren, useState } from 'react'
import { AlertContext } from './AlertContext'

import { Alert, AlertMessageKey } from '../../alert/domain/models/Alert'

export const AlertProvider = ({ children }: PropsWithChildren) => {
const [datasetAlerts, setDatasetAlerts] = useState<Alert[]>([])

const addDatasetAlert = (newAlert: Alert) => {
// Check if an alert with the same id already exists
const alertExists = datasetAlerts.some((alert) => alert.messageKey === newAlert.messageKey)

// If it doesn't exist, add it to the array
if (!alertExists) datasetAlerts.push(newAlert)
}

const removeDatasetAlert = (alertId: AlertMessageKey) => {
setDatasetAlerts(datasetAlerts.filter((alert) => alert.messageKey !== alertId))
}

return (
<AlertContext.Provider
value={{
datasetAlerts,
addDatasetAlert,
removeDatasetAlert
}}>
{children}
</AlertContext.Provider>
)
}
4 changes: 4 additions & 0 deletions src/sections/alerts/Alerts.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.container > * {
margin-top: 1em;
margin-right: 0.5em;
}
32 changes: 32 additions & 0 deletions src/sections/alerts/Alerts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Alert as AlertComponent } from '@iqss/dataverse-design-system'

import { useTranslation } from 'react-i18next'
import styles from './Alerts.module.scss'
import parse from 'html-react-parser'
import { useAlertContext } from './AlertContext'
import { Alert } from '../../alert/domain/models/Alert'

export function Alerts() {
const { t } = useTranslation('dataset')
const { datasetAlerts } = useAlertContext()
return (
<div className={styles.container}>
{datasetAlerts.map((alert: Alert, index) => {
const translatedMsg = alert.dynamicFields
? t(`alerts.${alert.messageKey}.alertText`, alert.dynamicFields)
: t(`alerts.${alert.messageKey}.alertText`)
const translatedHeading = t(`alerts.${alert.messageKey}.heading`)
const alertKey = `alert-${index}`
return (
<AlertComponent
key={alertKey}
variant={alert.variant}
customHeading={translatedHeading}
dismissible={false}>
{parse(translatedMsg)}
</AlertComponent>
)
})}
</div>
)
}
5 changes: 4 additions & 1 deletion src/sections/dataset/DatasetFactory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { SettingJSDataverseRepository } from '../../settings/infrastructure/Sett
import { FilePermissionsProvider } from '../file/file-permissions/FilePermissionsProvider'
import { SettingsProvider } from '../settings/SettingsProvider'
import { DatasetProvider } from './DatasetProvider'
import { AlertProvider } from '../alerts/AlertProvider'

const datasetRepository = new DatasetJSDataverseRepository()
const fileRepository = new FileJSDataverseRepository()
Expand All @@ -24,7 +25,9 @@ export class DatasetFactory {
<SettingsProvider repository={settingRepository}>
<MetadataBlockInfoProvider repository={metadataBlockInfoRepository}>
<AnonymizedProvider>
<DatasetWithSearchParams />
<AlertProvider>
<DatasetWithSearchParams />
</AlertProvider>
</AnonymizedProvider>
</MetadataBlockInfoProvider>
</SettingsProvider>
Expand Down
35 changes: 7 additions & 28 deletions src/sections/dataset/dataset-alerts/DatasetAlerts.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,13 @@
import { Alert } from '@iqss/dataverse-design-system'
import { DatasetAlert } from '../../../dataset/domain/models/Dataset'
import { useTranslation } from 'react-i18next'
import styles from './DatasetAlerts.module.scss'
import parse from 'html-react-parser'
import { useAlertContext } from '../../alerts/AlertContext'
import { Alerts } from '../../alerts/Alerts'
import { Alert } from '../../../alert/domain/models/Alert'

interface DatasetAlertsProps {
alerts: DatasetAlert[]
alerts: Alert[]
}

export function DatasetAlerts({ alerts }: DatasetAlertsProps) {
const { t } = useTranslation('dataset')

return (
<div className={styles.container}>
{alerts.map((alert: DatasetAlert, index) => {
const translatedMsg = alert.dynamicFields
? t(`alerts.${alert.message}.alertText`, alert.dynamicFields)
: t(`alerts.${alert.message}.alertText`)
const translatedHeading = t(`alerts.${alert.message}.heading`)
const alertKey = `alert-${index}`
return (
<Alert
key={alertKey}
variant={alert.variant}
customHeading={translatedHeading}
dismissible={false}>
{parse(translatedMsg)}
</Alert>
)
})}
</div>
)
const { addDatasetAlert } = useAlertContext()
alerts.forEach((alert) => addDatasetAlert(alert))
return <Alerts></Alerts>
}
10 changes: 10 additions & 0 deletions src/stories/WithAlerts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { StoryFn } from '@storybook/react'
import { AlertProvider } from '../sections/alerts/AlertProvider'

export const WithAlerts = (Story: StoryFn) => {
return (
<AlertProvider>
<Story />
</AlertProvider>
)
}
3 changes: 2 additions & 1 deletion src/stories/dataset/Dataset.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import { WithDatasetDraftAsOwner } from './WithDatasetDraftAsOwner'
import { WithDatasetNotFound } from './WithDatasetNotFound'
import { WithDatasetLoading } from './WithDatasetLoading'
import { WithLoggedInUser } from '../WithLoggedInUser'
import { WithAlerts } from '../WithAlerts'

const meta: Meta<typeof Dataset> = {
title: 'Pages/Dataset',
component: Dataset,
decorators: [WithI18next, WithCitationMetadataBlockInfo, WithSettings],
decorators: [WithI18next, WithCitationMetadataBlockInfo, WithSettings, WithAlerts],
parameters: {
// Sets the delay for all stories.
chromatic: { delay: 15000, pauseAnimationAtEnd: true }
Expand Down
Loading