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 src/app/drive/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface DriveFolderData {
uuid: string;
type?: string;
user?: UserResumeData;
caducityDate?: string;
}

export interface DriveFolderMetadataPayload {
Expand Down Expand Up @@ -63,6 +64,7 @@ export interface DriveFileData {
sharings?: { type: string; id: string }[];
uuid: string;
user?: UserResumeData;
caducityDate?: string;
}

interface Thumbnail {
Expand Down
7 changes: 6 additions & 1 deletion src/app/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,10 @@
"restore": "Wiederherstellen",
"delete-permanently": "Lösche dauerhaft"
},
"autoDelete": {
"inDays_one": "In {{count}} Tag",
"inDays_other": "In {{count}} Tagen"
},
"automaticDisposal": {
"badge": "Neues Update",
"title": "Automatische Papierkorb-Entsorgung",
Expand Down Expand Up @@ -1454,7 +1458,8 @@
"name": "Name",
"modified": "Modifiziert",
"size": "Größe",
"actions": "Aktionen"
"actions": "Aktionen",
"autoDelete": "Automatisches Löschen"
}
},
"viewMode": {
Expand Down
7 changes: 6 additions & 1 deletion src/app/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,10 @@
"restore": "Restore",
"delete-permanently": "Delete permanently"
},
"autoDelete": {
"inDays_one": "In {{count}} day",
"inDays_other": "In {{count}} days"
},
"automaticDisposal": {
"badge": "New update",
"title": "Automatic Trash disposal",
Expand Down Expand Up @@ -1536,7 +1540,8 @@
"name": "Name",
"modified": "Modified",
"size": "Size",
"actions": "Actions"
"actions": "Actions",
"autoDelete": "Auto-delete"
}
},
"viewMode": {
Expand Down
7 changes: 6 additions & 1 deletion src/app/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,10 @@
"restore": "Restaurar",
"delete-permanently": "Eliminar permanentemente"
},
"autoDelete": {
"inDays_one": "En {{count}} día",
"inDays_other": "En {{count}} días"
},
"automaticDisposal": {
"badge": "Nueva actualización",
"title": "Eliminación automática de la Papelera",
Expand Down Expand Up @@ -1514,7 +1518,8 @@
"name": "Nombre",
"modified": "Modificado",
"size": "Tamaño",
"actions": "Acciones"
"actions": "Acciones",
"autoDelete": "Eliminación automática"
}
},
"viewMode": {
Expand Down
7 changes: 6 additions & 1 deletion src/app/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,10 @@
"restore": "Restaurer",
"delete-permanently": "Supprimer définitivement"
},
"autoDelete": {
"inDays_one": "Dans {{count}} jour",
"inDays_other": "Dans {{count}} jours"
},
"automaticDisposal": {
"badge": "Nouvelle mise à jour",
"title": "Élimination automatique de la Corbeille",
Expand Down Expand Up @@ -1460,7 +1464,8 @@
"name": "Nom",
"modified": "Modifié",
"size": "Taille",
"actions": "Actions"
"actions": "Actions",
"autoDelete": "Suppression automatique"
}
},
"viewMode": {
Expand Down
7 changes: 6 additions & 1 deletion src/app/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,10 @@
"restore": "Ripristino",
"delete-permanently": "Elimina definitivamente"
},
"autoDelete": {
"inDays_one": "Tra {{count}} giorno",
"inDays_other": "Tra {{count}} giorni"
},
"automaticDisposal": {
"badge": "Nuovo aggiornamento",
"title": "Eliminazione automatica del Cestino",
Expand Down Expand Up @@ -1567,7 +1571,8 @@
"name": "Nome",
"modified": "Ultima modifica",
"size": "Dimensione",
"actions": "Azioni"
"actions": "Azioni",
"autoDelete": "Eliminazione automatica"
}
},
"viewMode": {
Expand Down
7 changes: 6 additions & 1 deletion src/app/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -1190,6 +1190,10 @@
"restore": "Восстановить",
"delete-permanently": "Удалить навсегда"
},
"autoDelete": {
"inDays_one": "Через {{count}} день",
"inDays_other": "Через {{count}} дней"
},
"automaticDisposal": {
"badge": "Новое обновление",
"title": "Автоматическая очистка Корзины",
Expand Down Expand Up @@ -1473,7 +1477,8 @@
"name": "Имя",
"modified": "Изменено",
"size": "Размер",
"actions": "Действия"
"actions": "Действия",
"autoDelete": "Автоматическое удаление"
}
},
"viewMode": {
Expand Down
7 changes: 6 additions & 1 deletion src/app/i18n/locales/tw.json
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,10 @@
"restore": "還原",
"delete-permanently": "永久刪除"
},
"autoDelete": {
"inDays_one": "{{count}} 天後",
"inDays_other": "{{count}} 天後"
},
"automaticDisposal": {
"badge": "新更新",
"title": "自動清空垃圾桶",
Expand Down Expand Up @@ -1466,7 +1470,8 @@
"name": "名稱",
"modified": "修改日期",
"size": "大小",
"actions": "操作"
"actions": "操作",
"autoDelete": "自動刪除"
}
},
"viewMode": {
Expand Down
7 changes: 6 additions & 1 deletion src/app/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -1214,6 +1214,10 @@
"restore": "恢复",
"delete-permanently": "永久删除"
},
"autoDelete": {
"inDays_one": "{{count}} 天后",
"inDays_other": "{{count}} 天后"
},
"automaticDisposal": {
"badge": "新更新",
"title": "自动清空垃圾箱",
Expand Down Expand Up @@ -1501,7 +1505,8 @@
"name": "名称",
"modified": "修改日期",
"size": "大小",
"actions": "操作"
"actions": "操作",
"autoDelete": "自动删除"
}
},
"viewMode": {
Expand Down
10 changes: 10 additions & 0 deletions src/components/Skeleton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,13 @@ export const skinSkeleton = [
<div key={'skin-skeleton-3'} className="ml-3 h-4 w-24 rounded bg-gray-5" />,
<div key={'skin-skeleton-4'} className="ml-4 h-4 w-20 rounded bg-gray-5" />,
];

export const skinSkeletonTrash = [
<div key={'skin-skeleton-1'} className="mr-3 flex w-full flex-row items-center space-x-4">
<div className="h-8 w-8 rounded-md bg-gray-5" />
<div className="h-4 w-full rounded bg-gray-5" />
</div>,
<div key={'skin-skeleton-auto-delete'} className="h-4 w-32 rounded bg-gray-5" />,
<div key={'skin-skeleton-2'} className="h-4 w-64 rounded bg-gray-5" />,
<div key={'skin-skeleton-3'} className="ml-3 h-4 w-24 rounded bg-gray-5" />,
];
31 changes: 31 additions & 0 deletions src/services/date.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,35 @@ describe('dateService', () => {

expect(isBefore).toBe(false);
});

describe('calculateDaysUntilDate', () => {
test('when target date is undefined, then returns 0', () => {
const result = dateService.calculateDaysUntilDate();
expect(result).toBe(0);
});

test('when target date is in the past, then returns 0', () => {
const pastDate = dayjs().subtract(5, 'day').toISOString();
const result = dateService.calculateDaysUntilDate(pastDate);
expect(result).toBe(0);
});

test('when target date is 10 days in the future, then returns 10', () => {
const futureDate = dayjs().add(10, 'day').toISOString();
const result = dateService.calculateDaysUntilDate(futureDate);
expect(result).toBe(10);
});

test('when target date is tomorrow, then returns 1', () => {
const tomorrow = dayjs().add(1, 'day').toISOString();
const result = dateService.calculateDaysUntilDate(tomorrow);
expect(result).toBe(1);
});

test('when target date is a Date object 30 days ahead, then returns 30', () => {
const futureDate = dayjs().add(30, 'day').toDate();
const result = dateService.calculateDaysUntilDate(futureDate);
expect(result).toBe(30);
});
});
});
10 changes: 10 additions & 0 deletions src/services/date.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,23 @@ export const formatDefaultDate = (date: Date | string | number, translate: (key:
return dayjs(date).format(`D MMM, YYYY [${translatedAt}] HH:mm`);
};

function calculateDaysUntilDate(targetDate?: string | Date): number {
if (!targetDate) return 0;

const target = dayjs(targetDate);
const now = dayjs();
const diffDays = target.diff(now, 'day');
return Math.max(diffDays, 0);
}

const dateService = {
format,
fromNow,
isDateOneBefore,
getCurrentDate,
getExpirationDate,
formatDefaultDate,
calculateDaysUntilDate,
};

export default dateService;
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import storageSelectors from 'app/store/slices/storage/storage.selectors';
import { fetchSortedFolderContentThunk } from 'app/store/slices/storage/storage.thunks/fetchSortedFolderContentThunk';
import React, { memo, useCallback, useState } from 'react';
import { connect, useSelector } from 'react-redux';
import { getListHeaders } from './getListHeaders';

import { ListShareLinksItem, Role } from '@internxt/sdk/dist/drive/share/types';
import navigationService from 'services/navigation.service';
import { useTranslationContext } from 'app/i18n/provider/TranslationProvider';
import { skinSkeleton } from 'components/Skeleton';
import { moveItemsToTrash } from '../../../../../views/Trash/services';
import { skinSkeleton, skinSkeletonTrash } from 'components/Skeleton';
import { moveItemsToTrash } from 'views/Trash/services';
import { OrderDirection, OrderSettings } from 'app/core/types';
import shareService from 'app/share/services/share.service';
import { AppDispatch, RootState } from 'app/store';
Expand All @@ -31,7 +32,7 @@ import {
contextMenuTrashItems,
contextMenuWorkspaceFile,
contextMenuWorkspaceFolder,
} from './DriveItemContextMenu';
} from '../DriveItemContextMenu';
import { List } from '@internxt/ui';
import { DownloadManager } from 'app/network/DownloadManager';

Expand All @@ -57,7 +58,7 @@ interface DriveExplorerListProps {

type ObjectWithId = { id: string | number };

type SortField = 'type' | 'name' | 'updatedAt' | 'size';
type SortField = 'type' | 'name' | 'updatedAt' | 'size' | 'caducityDate';

type ContextMenuDriveItem = DriveItemData | Pick<DriveItemData, SortField> | (ListShareLinksItem & { code: string });

Expand Down Expand Up @@ -139,6 +140,7 @@ const DriveExplorerList: React.FC<DriveExplorerListProps> = memo((props) => {
const currentFolderId = useAppSelector(storageSelectors.currentFolderId);
const isRecents = props.title === translate('views.recents.head');
const isTrash = props.title === translate('trash.trash');
const skeleton = isTrash ? skinSkeletonTrash : skinSkeleton;

const sortBy = (value: { field: SortField; direction: 'ASC' | 'DESC' }) => {
let direction = OrderDirection.Asc;
Expand Down Expand Up @@ -167,6 +169,12 @@ const DriveExplorerList: React.FC<DriveExplorerListProps> = memo((props) => {
if (value.field === 'size') {
resetDriveOrder({ dispatch, orderType: 'size', direction, currentFolderId });
}

if (value.field === 'caducityDate') {
if (isTrash) {
props.resetPaginationState();
}
}
};

function handleMouseEnter() {
Expand Down Expand Up @@ -451,32 +459,8 @@ const DriveExplorerList: React.FC<DriveExplorerListProps> = memo((props) => {
/>
)}
<ShareWithTeamDialog item={props.selectedItems[0]} roles={roles} />
<List<DriveItemData, 'type' | 'name' | 'updatedAt' | 'size'>
header={[
{
label: translate('drive.list.columns.name'),
width: 'flex grow items-center min-w-driveNameHeader',
name: 'name',
orderable: !isRecents,
defaultDirection: 'ASC',
buttonDataCy: 'driveListHeaderNameButton',
textDataCy: 'driveListHeaderNameButtonText',
},
{
label: translate('drive.list.columns.modified'),
width: 'w-date',
name: 'updatedAt',
orderable: !isRecents,
defaultDirection: 'ASC',
},
{
label: translate('drive.list.columns.size'),
orderable: !isRecents && !isTrash,
defaultDirection: 'ASC',
width: 'w-size',
name: 'size',
},
]}
<List<DriveItemData, 'type' | 'name' | 'updatedAt' | 'size' | 'caducityDate'>
header={getListHeaders(translate, isRecents, isTrash)}
checkboxDataCy="driveListHeaderCheckbox"
disableKeyboardShortcuts={props.disableKeyboardShortcuts || props.showStopSharingConfirmation}
items={props.items}
Expand All @@ -485,7 +469,7 @@ const DriveExplorerList: React.FC<DriveExplorerListProps> = memo((props) => {
itemComposition={[(item) => createDriveListItem(item, props.isTrash)]}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
skinSkeleton={skinSkeleton}
skinSkeleton={skeleton}
emptyState={<></>}
onNextPage={onEndOfScroll}
onEnterPressed={(driveItem) => {
Expand Down
Loading
Loading