feat(myshares): new version of myshares sections, supporting grants Users + Tokens
This commit is contained in:
@@ -138,6 +138,36 @@ function normalizeDateBucket(value) {
|
||||
return String(date.getFullYear());
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a future expiry value into a human-readable bucket label.
|
||||
* Buckets (soonest-first): Expired | Tomorrow | In less than 7 days | In less than 30 days | <YYYY> | No expiration
|
||||
*
|
||||
* Accepts the same input types as `normalizeDateBucket`.
|
||||
*
|
||||
* @param {string | number | Date | null | undefined} value
|
||||
* @returns {string}
|
||||
*/
|
||||
function normalizeExpiryBucket(value) {
|
||||
if (value === null || value === undefined) {
|
||||
return i18n.t('expiryBucket.noExpiry', 'No expiration');
|
||||
}
|
||||
/** @type {Date} */
|
||||
let date;
|
||||
if (value instanceof Date) {
|
||||
date = value;
|
||||
} else if (typeof value === 'number') {
|
||||
date = new Date(value < 1e12 ? value * 1000 : value);
|
||||
} else {
|
||||
date = new Date(value);
|
||||
}
|
||||
const daysUntil = Math.floor((date.getTime() - Date.now()) / 86_400_000);
|
||||
if (daysUntil < 0) return i18n.t('expiryBucket.expired', 'Expired');
|
||||
if (daysUntil <= 1) return i18n.t('expiryBucket.tomorrow', 'Tomorrow');
|
||||
if (daysUntil <= 7) return i18n.t('expiryBucket.week', 'In less than 7 days');
|
||||
if (daysUntil <= 30) return i18n.t('expiryBucket.month', 'In less than 30 days');
|
||||
return String(date.getFullYear());
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a file size in bytes to a coarse, human-readable bucket label.
|
||||
*
|
||||
@@ -167,4 +197,15 @@ function sizeBucket(bytes) {
|
||||
return i18n.t('sizeBucket.huge', '> 5 GB');
|
||||
}
|
||||
|
||||
export { escapeHtml, formatDateShort, formatDateTime, formatFileSize, formatQuotaSize, isEmailValid, isTextViewable, normalizeDateBucket, sizeBucket };
|
||||
export {
|
||||
escapeHtml,
|
||||
formatDateShort,
|
||||
formatDateTime,
|
||||
formatFileSize,
|
||||
formatQuotaSize,
|
||||
isEmailValid,
|
||||
isTextViewable,
|
||||
normalizeDateBucket,
|
||||
normalizeExpiryBucket,
|
||||
sizeBucket
|
||||
};
|
||||
|
||||
@@ -239,6 +239,10 @@ const OxiIcons = {
|
||||
576,
|
||||
'M160 32c-35.3 0-64 28.7-64 64l0 224c0 35.3 28.7 64 64 64l352 0c35.3 0 64-28.7 64-64l0-224c0-35.3-28.7-64-64-64L160 32zM396 138.7l96 144c4.9 7.4 5.4 16.8 1.2 24.6S480.9 320 472 320l-144 0-48 0-80 0c-9.2 0-17.6-5.3-21.6-13.6s-2.9-18.2 2.9-25.4l64-80c4.6-5.7 11.4-9 18.7-9s14.2 3.3 18.7 9l17.3 21.6 56-84C360.5 132 368 128 376 128s15.5 4 20 10.7zM192 128a32 32 0 1 1 64 0 32 32 0 1 1 -64 0zM48 120c0-13.3-10.7-24-24-24S0 106.7 0 120L0 344c0 75.1 60.9 136 136 136l320 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-320 0c-48.6 0-88-39.4-88-88l0-224z'
|
||||
],
|
||||
'infinity': [
|
||||
640,
|
||||
'M0 256c0-88.4 71.6-160 160-160 50.4 0 97.8 23.7 128 64l32 42.7 32-42.7c30.2-40.3 77.6-64 128-64 88.4 0 160 71.6 160 160S568.4 416 480 416c-50.4 0-97.8-23.7-128-64l-32-42.7-32 42.7c-30.2 40.3-77.6 64-128 64-88.4 0-160-71.6-160-160zm280 0l-43.2-57.6c-18.1-24.2-46.6-38.4-76.8-38.4-53 0-96 43-96 96s43 96 96 96c30.2 0 58.7-14.2 76.8-38.4L280 256zm80 0l43.2 57.6c18.1 24.2 46.6 38.4 76.8 38.4 53 0 96-43 96-96s-43-96-96-96c-30.2 0-58.7 14.2-76.8 38.4L360 256z'
|
||||
],
|
||||
'info-circle': [
|
||||
512,
|
||||
'M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336l24 0 0-64-24 0c-13.3 0-24-10.7-24-24s10.7-24 24-24l48 0c13.3 0 24 10.7 24 24l0 88 8 0c13.3 0 24 10.7 24 24s-10.7 24-24 24l-80 0c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z'
|
||||
|
||||
+32
-3
@@ -81,9 +81,9 @@
|
||||
|
||||
/**
|
||||
* @typedef {Object} UpdateShare
|
||||
* @property {string|null} password
|
||||
* @property {number|null} expires_at - timestamp
|
||||
* @property {SharePermissions|null} permissions
|
||||
* @property {string|null} [password]
|
||||
* @property {number|null} [expires_at]
|
||||
* @property {SharePermissions|null} [permissions]
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -334,6 +334,35 @@
|
||||
* @property {string|undefined} [next_cursor] - Absent when the last page is reached.
|
||||
*/
|
||||
|
||||
/**
|
||||
* One (subject, permissions) entry within an outgoing resource item.
|
||||
* @typedef {Object} OutgoingResourceGrant
|
||||
* @property {string} grant_id
|
||||
* @property {'user'|'token'} subject_type
|
||||
* @property {string} subject_id
|
||||
* @property {string} subject_display - Username (users) or share name (tokens).
|
||||
* @property {'viewer'|'editor'|'admin'} role
|
||||
* @property {string} granted_at - ISO-8601
|
||||
* @property {string|null} [expires_at] - ISO-8601 or absent.
|
||||
* @property {boolean} has_password - True when a token subject has a password set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* One item returned by `GET /api/grants/outgoing/resources`.
|
||||
* @typedef {Object} OutgoingResourceItem
|
||||
* @property {ResourceTypeEnum} resource_type
|
||||
* @property {string} first_shared_at - ISO-8601 earliest grant date.
|
||||
* @property {FileItem|FolderItem} resource - Full resource details.
|
||||
* @property {OutgoingResourceGrant[]} grants - One entry per (subject, permissions).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Response for `GET /api/grants/outgoing/resources`.
|
||||
* @typedef {Object} OutgoingResourcesResponse
|
||||
* @property {OutgoingResourceItem[]} items
|
||||
* @property {string|undefined} [next_cursor] - Absent when the last page is reached.
|
||||
*/
|
||||
|
||||
/**
|
||||
* One item returned by `GET /api/favorites/resources`.
|
||||
* `resource_type` discriminates the shape of `resource`.
|
||||
|
||||
Reference in New Issue
Block a user