diff --git a/src/app/i18n/locales/de.json b/src/app/i18n/locales/de.json index 4d928e6ca9..3576fd6721 100644 --- a/src/app/i18n/locales/de.json +++ b/src/app/i18n/locales/de.json @@ -1163,6 +1163,28 @@ "item-menu": { "restore": "Wiederherstellen", "delete-permanently": "Lösche dauerhaft" + }, + "automaticDisposal": { + "badge": "Neues Update", + "title": "Automatische Papierkorb-Entsorgung", + "close": "Schließen", + "description": "Alle in den Papierkorb verschobenen Elemente werden nun\nautomatisch dauerhaft gelöscht nach:", + "freeUsers": { + "duration": "1 Tag", + "label": "für kostenlose Benutzer" + }, + "essentialUsers": { + "duration": "7 Tage", + "label": "für Essential-Benutzer" + }, + "premiumUsers": { + "duration": "14 Tage", + "label": "für Premium-Benutzer" + }, + "ultimateUsers": { + "duration": "30 Tage", + "label": "für Ultimate-Benutzer" + } } }, "tasks": { diff --git a/src/app/i18n/locales/en.json b/src/app/i18n/locales/en.json index 10465c8282..40c2e4f912 100644 --- a/src/app/i18n/locales/en.json +++ b/src/app/i18n/locales/en.json @@ -1248,6 +1248,28 @@ "item-menu": { "restore": "Restore", "delete-permanently": "Delete permanently" + }, + "automaticDisposal": { + "badge": "New update", + "title": "Automatic Trash disposal", + "close": "Close", + "description": "Now all the items moved to Trash will be\npermanently deleted automatically after:", + "freeUsers": { + "duration": "1 day", + "label": "for free users" + }, + "essentialUsers": { + "duration": "7 days", + "label": "for essential users" + }, + "premiumUsers": { + "duration": "14 days", + "label": "for premium users" + }, + "ultimateUsers": { + "duration": "30 days", + "label": "for ultimate users" + } } }, "tasks": { diff --git a/src/app/i18n/locales/es.json b/src/app/i18n/locales/es.json index fa6c84e867..914c273228 100644 --- a/src/app/i18n/locales/es.json +++ b/src/app/i18n/locales/es.json @@ -1225,6 +1225,28 @@ "item-menu": { "restore": "Restaurar", "delete-permanently": "Eliminar permanentemente" + }, + "automaticDisposal": { + "badge": "Nueva actualización", + "title": "Eliminación automática de la Papelera", + "close": "Cerrar", + "description": "Ahora todos los elementos movidos a la Papelera se eliminarán\npermanentemente de forma automática después de:", + "freeUsers": { + "duration": "1 día", + "label": "para usuarios gratuitos" + }, + "essentialUsers": { + "duration": "7 días", + "label": "para usuarios esenciales" + }, + "premiumUsers": { + "duration": "14 días", + "label": "para usuarios premium" + }, + "ultimateUsers": { + "duration": "30 días", + "label": "para usuarios ultimate" + } } }, "tasks": { diff --git a/src/app/i18n/locales/fr.json b/src/app/i18n/locales/fr.json index 26faa6331a..96bfef8e97 100644 --- a/src/app/i18n/locales/fr.json +++ b/src/app/i18n/locales/fr.json @@ -1176,6 +1176,28 @@ "item-menu": { "restore": "Restaurer", "delete-permanently": "Supprimer définitivement" + }, + "automaticDisposal": { + "badge": "Nouvelle mise à jour", + "title": "Élimination automatique de la Corbeille", + "close": "Fermer", + "description": "Désormais, tous les éléments déplacés dans la Corbeille seront\nsupprimés définitivement automatiquement après:", + "freeUsers": { + "duration": "1 jour", + "label": "pour les utilisateurs gratuits" + }, + "essentialUsers": { + "duration": "7 jours", + "label": "pour les utilisateurs essentiels" + }, + "premiumUsers": { + "duration": "14 jours", + "label": "pour les utilisateurs premium" + }, + "ultimateUsers": { + "duration": "30 jours", + "label": "pour les utilisateurs ultimate" + } } }, "tasks": { diff --git a/src/app/i18n/locales/it.json b/src/app/i18n/locales/it.json index 40ad67861e..0969174182 100644 --- a/src/app/i18n/locales/it.json +++ b/src/app/i18n/locales/it.json @@ -1283,6 +1283,28 @@ "item-menu": { "restore": "Ripristino", "delete-permanently": "Elimina definitivamente" + }, + "automaticDisposal": { + "badge": "Nuovo aggiornamento", + "title": "Eliminazione automatica del Cestino", + "close": "Chiudi", + "description": "Ora tutti gli elementi spostati nel Cestino verranno\neliminati definitivamente automaticamente dopo:", + "freeUsers": { + "duration": "1 giorno", + "label": "per utenti gratuiti" + }, + "essentialUsers": { + "duration": "7 giorni", + "label": "per utenti essenziali" + }, + "premiumUsers": { + "duration": "14 giorni", + "label": "per utenti premium" + }, + "ultimateUsers": { + "duration": "30 giorni", + "label": "per utenti ultimate" + } } }, "tasks": { diff --git a/src/app/i18n/locales/ru.json b/src/app/i18n/locales/ru.json index a15c66cf0b..5e549f2f51 100644 --- a/src/app/i18n/locales/ru.json +++ b/src/app/i18n/locales/ru.json @@ -1189,6 +1189,28 @@ "item-menu": { "restore": "Восстановить", "delete-permanently": "Удалить навсегда" + }, + "automaticDisposal": { + "badge": "Новое обновление", + "title": "Автоматическая очистка Корзины", + "close": "Закрыть", + "description": "Теперь все элементы, перемещенные в Корзину, будут\nавтоматически удалены навсегда после:", + "freeUsers": { + "duration": "1 день", + "label": "для бесплатных пользователей" + }, + "essentialUsers": { + "duration": "7 дней", + "label": "для пользователей Essential" + }, + "premiumUsers": { + "duration": "14 дней", + "label": "для пользователей Premium" + }, + "ultimateUsers": { + "duration": "30 дней", + "label": "для пользователей Ultimate" + } } }, "tasks": { diff --git a/src/app/i18n/locales/tw.json b/src/app/i18n/locales/tw.json index e65d08a474..da9c8fe92e 100644 --- a/src/app/i18n/locales/tw.json +++ b/src/app/i18n/locales/tw.json @@ -1178,6 +1178,28 @@ "item-menu": { "restore": "還原", "delete-permanently": "永久刪除" + }, + "automaticDisposal": { + "badge": "新更新", + "title": "自動清空垃圾桶", + "close": "關閉", + "description": "現在所有移至垃圾桶的項目將在以下時間後\n自動永久刪除:", + "freeUsers": { + "duration": "1天", + "label": "免費用戶" + }, + "essentialUsers": { + "duration": "7天", + "label": "基礎用戶" + }, + "premiumUsers": { + "duration": "14天", + "label": "高級用戶" + }, + "ultimateUsers": { + "duration": "30天", + "label": "終極用戶" + } } }, "tasks": { diff --git a/src/app/i18n/locales/zh.json b/src/app/i18n/locales/zh.json index e3cb6af9b9..be90f57298 100644 --- a/src/app/i18n/locales/zh.json +++ b/src/app/i18n/locales/zh.json @@ -1213,6 +1213,28 @@ "item-menu": { "restore": "恢复", "delete-permanently": "永久删除" + }, + "automaticDisposal": { + "badge": "新更新", + "title": "自动清空垃圾箱", + "close": "关闭", + "description": "现在所有移至垃圾箱的项目将在以下时间后\n自动永久删除:", + "freeUsers": { + "duration": "1天", + "label": "免费用户" + }, + "essentialUsers": { + "duration": "7天", + "label": "基础用户" + }, + "premiumUsers": { + "duration": "14天", + "label": "高级用户" + }, + "ultimateUsers": { + "duration": "30天", + "label": "终极用户" + } } }, "tasks": { diff --git a/src/app/store/slices/ui/index.ts b/src/app/store/slices/ui/index.ts index e1e3f8e96e..d13716e861 100644 --- a/src/app/store/slices/ui/index.ts +++ b/src/app/store/slices/ui/index.ts @@ -32,6 +32,7 @@ interface UISliceState { currentEditingNameDirty: string; isGlobalSearch: boolean; isShareWhithTeamDialogOpen: boolean; + isAutomaticTrashDisposalDialogOpen: boolean; } const initialState: UISliceState = { @@ -64,6 +65,7 @@ const initialState: UISliceState = { currentEditingNameDirty: '', isGlobalSearch: false, isShareWhithTeamDialogOpen: false, + isAutomaticTrashDisposalDialogOpen: false, }; export const uiSlice = createSlice({ @@ -166,6 +168,9 @@ export const uiSlice = createSlice({ setIsShareWhithTeamDialogOpen: (state: UISliceState, action: PayloadAction) => { state.isShareWhithTeamDialogOpen = action.payload; }, + setIsAutomaticTrashDisposalDialogOpen: (state: UISliceState, action: PayloadAction) => { + state.isAutomaticTrashDisposalDialogOpen = action.payload; + }, }, }); @@ -192,6 +197,7 @@ export const { setIsGlobalSearch, setIsItemDetailsDialogOpen, setIsShareWhithTeamDialogOpen, + setIsAutomaticTrashDisposalDialogOpen, } = uiSlice.actions; export const uiActions = uiSlice.actions; diff --git a/src/services/storage-keys.ts b/src/services/storage-keys.ts index 561165bfea..2e7a08392b 100644 --- a/src/services/storage-keys.ts +++ b/src/services/storage-keys.ts @@ -5,6 +5,7 @@ export const STORAGE_KEYS = { FOLDER_ACCESS_TOKEN: 'folderAccessToken', FILE_ACCESS_TOKEN: 'fileAccessToken', GCLID: 'gclid', + HAS_SEEN_TRASH_DISPOSAL_DIALOG: 'hasSeenTrashDisposalDialog', THEMES: { MANAGEMENTID_THEME_AVAILABLE_LOCAL_STORAGE_KEY: 'managementid_theme_enabled', ID_MANAGEMENT_THEME_AVAILABLE_LOCAL_STORAGE_KEY: 'id_management_theme_enabled', diff --git a/src/views/Trash/Trash.tsx b/src/views/Trash/Trash.tsx index 572055cf2f..39c6df97da 100644 --- a/src/views/Trash/Trash.tsx +++ b/src/views/Trash/Trash.tsx @@ -10,6 +10,12 @@ import { storageActions } from 'app/store/slices/storage'; import { getTrashPaginated, getWorkspaceTrashPaginated } from './services'; import storageThunks from 'app/store/slices/storage/storage.thunks'; import workspacesSelectors from 'app/store/slices/workspaces/workspaces.selectors'; +import { uiActions } from 'app/store/slices/ui'; +import { useAppSelector } from 'app/store/hooks'; +import AutomaticTrashDisposalDialog from './components/AutomaticTrashDisposalDialog'; +import { userSelectors } from 'app/store/slices/user'; +import localStorageService from 'services/local-storage.service'; +import { STORAGE_KEYS } from 'services/storage-keys'; export interface TrashViewProps { isLoadingItemsOnTrash: boolean; @@ -17,17 +23,32 @@ export interface TrashViewProps { dispatch: AppDispatch; } +const shouldShowTrashDisposalDialog = (hasSignedToday: boolean): boolean => { + const hasSeenDialog = localStorageService.get(STORAGE_KEYS.HAS_SEEN_TRASH_DISPOSAL_DIALOG); + return !hasSignedToday && !hasSeenDialog; +}; + +const markTrashDisposalDialogAsSeen = (): void => { + localStorageService.set(STORAGE_KEYS.HAS_SEEN_TRASH_DISPOSAL_DIALOG, 'true'); +}; + const TrashView = (props: TrashViewProps) => { const { items, isLoadingItemsOnTrash } = props; const { translate } = useTranslationContext(); const workspaceSelected = useSelector(workspacesSelectors.getSelectedWorkspace); + const hasSignedToday = useAppSelector(userSelectors.hasSignedToday); const getTrash = workspaceSelected ? getWorkspaceTrashPaginated : getTrashPaginated; useEffect(() => { const { dispatch } = props; dispatch(storageThunks.resetNamePathThunk()); dispatch(storageActions.clearSelectedItems()); + + if (shouldShowTrashDisposalDialog(hasSignedToday)) { + dispatch(uiActions.setIsAutomaticTrashDisposalDialogOpen(true)); + markTrashDisposalDialogAsSeen(); + } }, []); return ( @@ -41,6 +62,7 @@ const TrashView = (props: TrashViewProps) => { items={items} getTrashPaginated={getTrash} /> + ); }; diff --git a/src/views/Trash/components/AutomaticTrashDisposalDialog.tsx b/src/views/Trash/components/AutomaticTrashDisposalDialog.tsx new file mode 100644 index 0000000000..6c568d8485 --- /dev/null +++ b/src/views/Trash/components/AutomaticTrashDisposalDialog.tsx @@ -0,0 +1,51 @@ +import { useTranslationContext } from 'app/i18n/provider/TranslationProvider'; +import { Button, Modal } from '@internxt/ui'; +import { RootState } from 'app/store'; +import { useAppDispatch, useAppSelector } from 'app/store/hooks'; +import { uiActions } from 'app/store/slices/ui'; + +const USER_TIERS = ['freeUsers', 'essentialUsers', 'premiumUsers', 'ultimateUsers'] as const; + +const AutomaticTrashDisposalDialog = (): JSX.Element => { + const { translate } = useTranslationContext(); + const dispatch = useAppDispatch(); + const isOpen = useAppSelector((state: RootState) => state.ui.isAutomaticTrashDisposalDialogOpen); + + const onClose = (): void => { + dispatch(uiActions.setIsAutomaticTrashDisposalDialogOpen(false)); + }; + + return ( + +
+ + {translate('trash.automaticDisposal.badge')} + + +

{translate('trash.automaticDisposal.title')}

+ +
+

{translate('trash.automaticDisposal.description')}

+
    + {USER_TIERS.map((tier) => ( +
  • + + {translate(`trash.automaticDisposal.${tier}.duration`)} + {' '} + {translate(`trash.automaticDisposal.${tier}.label`)} +
  • + ))} +
+
+ +
+ +
+
+
+ ); +}; + +export default AutomaticTrashDisposalDialog;