1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-06 17:43:46 +00:00
seahub/frontend/src/utils/utils.js

1762 lines
48 KiB
JavaScript
Raw Normal View History

import { mediaUrl, gettext, serviceURL, siteRoot, isPro, fileAuditEnabled, canGenerateShareLink, canGenerateUploadLink, shareLinkPasswordMinLength, username, folderPermEnabled, onlyofficeConverterExtensions, enableOnlyoffice, enableSeadoc, enableFileTags } from './constants';
import TextTranslation from './text-translation';
import React from 'react';
import toaster from '../components/toast';
import PermissionDeniedTip from '../components/permission-denied-tip';
import { compareTwoString } from './compare-two-string';
import { PRIVATE_FILE_TYPE } from '../constants';
export const Utils = {
2024-07-18 03:58:42 +00:00
keyCodes: {
2023-09-05 12:21:24 +00:00
enter: 13,
2024-07-18 03:58:42 +00:00
esc: 27,
space: 32,
2024-07-18 03:58:42 +00:00
tab: 9,
up: 38,
down: 40
},
2024-07-18 03:58:42 +00:00
bytesToSize: function (bytes) {
if (typeof(bytes) == 'undefined') return ' ';
2018-11-22 03:26:00 +00:00
if (bytes < 0) return '--';
const sizes = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
2018-11-22 03:26:00 +00:00
if (bytes === 0) return bytes + ' ' + sizes[0];
2018-11-22 03:26:00 +00:00
const i = parseInt(Math.floor(Math.log(bytes) / Math.log(1000)), 10);
if (i === 0) return bytes + ' ' + sizes[i];
return (bytes / (1000 ** i)).toFixed(1) + ' ' + sizes[i];
},
2024-07-18 03:58:42 +00:00
isHiDPI: function () {
var pixelRatio = window.devicePixelRatio ? window.devicePixelRatio : 1;
if (pixelRatio > 1) {
return true;
} else {
return false;
}
},
2024-07-18 03:58:42 +00:00
isDesktop: function () {
return window.innerWidth >= 768;
},
2024-07-18 03:58:42 +00:00
isWeChat: function () {
2019-10-15 02:16:48 +00:00
let ua = window.navigator.userAgent.toLowerCase();
let isWeChat = ua.match(/MicroMessenger/i) == 'micromessenger';
let isEnterpriseWeChat = ua.match(/MicroMessenger/i) == 'micromessenger' && ua.match(/wxwork/i) == 'wxwork';
return isEnterpriseWeChat || isWeChat;
},
FILEEXT_ICON_MAP: {
// text file
'txt': 'txt.png',
2024-08-06 03:46:09 +00:00
// markdown file
'md': 'md.png',
// pdf file
2024-07-18 03:58:42 +00:00
'pdf': 'pdf.png',
// document file
2024-07-18 03:58:42 +00:00
'doc': 'word.png',
'docx': 'word.png',
'odt': 'word.png',
'fodt': 'word.png',
2024-07-18 03:58:42 +00:00
'ppt': 'ppt.png',
'pptx': 'ppt.png',
'odp': 'ppt.png',
'fodp': 'ppt.png',
2024-07-18 03:58:42 +00:00
'xls': 'excel.png',
'xlsx': 'excel.png',
'ods': 'excel.png',
'fods': 'excel.png',
// video
'mp4': 'video.png',
'ogv': 'video.png',
'webm': 'video.png',
'mov': 'video.png',
'flv': 'video.png',
'wmv': 'video.png',
'rmvb': 'video.png',
// music file
2024-07-18 03:58:42 +00:00
'mp3': 'music.png',
'oga': 'music.png',
'ogg': 'music.png',
'wav': 'music.png',
'flac': 'music.png',
'opus': 'music.png',
'aac': 'music.png',
'ac3': 'music.png',
'wma': 'music.png',
// image file
2024-07-18 03:58:42 +00:00
'jpg': 'pic.png',
'jpeg': 'pic.png',
'png': 'pic.png',
'svg': 'pic.png',
'gif': 'pic.png',
'bmp': 'pic.png',
'ico': 'pic.png',
'heic': 'pic.png',
// photoshop file
2024-08-06 03:46:09 +00:00
'psd': 'psd.png',
2024-08-26 02:46:51 +00:00
// zip file
'zip': 'zip.png',
'rar': 'zip.png',
'tar': 'zip.png',
2024-08-06 03:46:09 +00:00
// style file
'css': 'css.png',
// sdoc file
'sdoc': 'sdoc.png',
'sdoc_notification': 'sdoc_notification.ico',
// default
2024-07-18 03:58:42 +00:00
'default': 'file.png',
},
// check if a file is an image
2024-07-18 03:58:42 +00:00
imageCheck: function (filename) {
// no file ext
if (filename.lastIndexOf('.') == -1) {
return false;
}
var file_ext = filename.substr(filename.lastIndexOf('.') + 1).toLowerCase();
var image_exts = ['gif', 'jpeg', 'jpg', 'png', 'ico', 'bmp', 'tif', 'tiff', 'jfif', 'heic'];
if (image_exts.indexOf(file_ext) != -1) {
return true;
} else {
return false;
}
},
2024-07-18 03:58:42 +00:00
pdfCheck: function (filename) {
if (filename.lastIndexOf('.') == -1) {
return false;
}
var file_ext = filename.substr(filename.lastIndexOf('.') + 1).toLowerCase();
var image_exts = ['pdf'];
if (image_exts.indexOf(file_ext) != -1) {
return true;
} else {
return false;
}
},
2024-07-18 03:58:42 +00:00
getShareLinkPermissionList: function (itemType, permission, path, canEdit) {
// itemType: library, dir, file
// permission: rw, r, admin, cloud-edit, preview, custom-*
let permissionOptions = [];
const { isCustomPermission } = Utils.getUserPermission(permission);
if (isCustomPermission) {
permissionOptions.push('preview_download');
permissionOptions.push('preview_only');
return permissionOptions;
}
if (permission == 'rw' || permission == 'admin' || permission == 'r') {
permissionOptions.push('preview_download');
}
permissionOptions.push('preview_only');
if (itemType == 'library' || itemType == 'dir') {
if (permission == 'rw' || permission == 'admin') {
permissionOptions.push('download_upload');
}
} else {
if (this.isEditableOfficeFile(path) && (permission == 'rw' || permission == 'admin') && canEdit) {
permissionOptions.push('edit_download');
}
// not support
// if (this.isEditableOfficeFile(path) && (permission == 'cloud-edit')) {
// permissionOptions.push('cloud_edit');
// }
}
return permissionOptions;
},
2024-07-18 03:58:42 +00:00
getShareLinkPermissionStr: function (permissions) {
const { can_edit, can_download, can_upload } = permissions;
switch (`${can_edit} ${can_download} ${can_upload}`) {
case 'false true false':
return 'preview_download';
case 'false false false':
return 'preview_only';
case 'false true true':
return 'download_upload';
case 'true true false':
return 'edit_download';
case 'true false false':
return 'cloud_edit';
}
},
2024-07-18 03:58:42 +00:00
isEditableOfficeFile: function (filename) {
// no file ext
if (filename.lastIndexOf('.') == -1) {
return false;
}
var file_ext = filename.substr(filename.lastIndexOf('.') + 1).toLowerCase();
var exts = ['docx', 'pptx', 'xlsx'];
if (exts.indexOf(file_ext) != -1) {
return true;
} else {
return false;
}
},
// check if a file is a video
2024-07-18 03:58:42 +00:00
videoCheck: function (filename) {
// no file ext
if (filename.lastIndexOf('.') == -1) {
return false;
}
var file_ext = filename.substr(filename.lastIndexOf('.') + 1).toLowerCase();
var exts = ['mp4', 'ogv', 'webm', 'mov'];
if (exts.indexOf(file_ext) != -1) {
return true;
} else {
return false;
}
},
2024-07-18 03:58:42 +00:00
checkDuplicatedNameInList: function (list, targetName) {
return list.some(object => {
return object.name === targetName;
});
},
2024-07-18 03:58:42 +00:00
encodePath: function (path) {
// IE8 does not support 'map()'
/*
return path.split('/').map(function(e) {
return encodeURIComponent(e);
}).join('/');
*/
2018-12-17 04:03:37 +00:00
if (!path) {
return '';
}
2018-10-16 10:19:51 +00:00
var path_arr = path.split('/');
var path_arr_ = [];
for (var i = 0, len = path_arr.length; i < len; i++) {
path_arr_.push(encodeURIComponent(path_arr[i]));
}
return path_arr_.join('/');
},
2024-07-18 03:58:42 +00:00
HTMLescape: function (html) {
return document.createElement('div')
2018-10-25 06:42:53 +00:00
.appendChild(document.createTextNode(html))
.parentNode
.innerHTML;
},
2024-07-18 03:58:42 +00:00
generateDialogTitle: function (title, operationTarget) {
/*
* @param title: gettext('...{placeholder}...')
*/
/*
const targetStr = this.HTMLescape(operationTarget);
const str = `<span class="op-target ellipsis ellipsis-op-target" title=${targetStr}>${targetStr}</span>`;
return title.replace('{placeholder}', str);
*/
return title.replace('{placeholder}', operationTarget);
},
2024-07-18 03:58:42 +00:00
getFileName: function (filePath) {
let lastIndex = filePath.lastIndexOf('/');
2024-07-18 03:58:42 +00:00
return filePath.slice(lastIndex + 1);
2018-11-14 02:55:11 +00:00
},
/**
* input: '/abc/bc/cb'
* output: ['/abc', '/abc/bc', '/abc/bc/cb'];
*/
2024-07-18 03:58:42 +00:00
getPaths: function (path) {
let paths = path.split('/').slice(1);
let result = [];
2024-07-18 03:58:42 +00:00
while (paths.length) {
result.push('/' + paths.join('/'));
paths.pop();
}
return result.reverse();
},
/**
* input:
2018-12-17 14:34:54 +00:00
* eg: /
* ../abc/abc/
* ../abc/bc
* output(return):
* eg: /
* abc
* bc
*/
2024-07-18 03:58:42 +00:00
getFolderName: function (path) {
2018-12-17 14:34:54 +00:00
if (path === '/') {
return path;
}
path = path[path.length - 1] !== '/' ? path : path.slice(0, path.length - 1);
2018-12-17 14:34:54 +00:00
return path.slice(path.lastIndexOf('/') + 1);
},
2018-11-22 03:26:00 +00:00
/*
return dirname of a path.
if path is '/', return '/'.
*/
2024-07-18 03:58:42 +00:00
getDirName: function (path) {
2018-11-22 03:26:00 +00:00
let dir = path.slice(0, path.lastIndexOf('/'));
if (dir === '') {
return '/';
} else {
return dir;
}
},
2024-07-18 03:58:42 +00:00
isChildPath: function (child, parent) {
2018-11-22 03:26:00 +00:00
let p = this.getDirName(child);
return p === parent;
},
2024-07-18 03:58:42 +00:00
isAncestorPath: function (ancestor, path) {
2018-11-22 03:26:00 +00:00
return path.indexOf(ancestor) > -1;
},
2024-07-18 03:58:42 +00:00
renameAncestorPath: function (path, ancestor, newAncestor) {
2019-02-20 03:54:25 +00:00
return path.replace(ancestor, newAncestor);
2018-11-22 03:26:00 +00:00
},
2024-07-18 03:58:42 +00:00
joinPath: function (pathA, pathB) {
if (pathA[pathA.length - 1] === '/') {
2018-11-22 03:26:00 +00:00
return pathA + pathB;
} else {
return pathA + '/' + pathB;
}
},
2024-07-18 03:58:42 +00:00
isSupportUploadFolder: function () {
return navigator.userAgent.indexOf('Firefox') != -1 ||
navigator.userAgent.indexOf('Chrome') > -1 ||
navigator.userAgent.indexOf('Safari') > -1;
},
isIEBrowser: function () { // is ie <= ie11 not include Edge
2019-06-04 08:18:32 +00:00
var userAgent = navigator.userAgent;
2019-06-21 05:59:17 +00:00
var isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1;
var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1;
2019-06-04 08:18:32 +00:00
return isIE || isIE11;
},
2024-07-18 03:58:42 +00:00
getDefaultLibIconUrl: function (isBig) {
let size = Utils.isHiDPI() ? 48 : 24;
size = isBig ? 256 : size;
let icon_name = 'lib.png';
return mediaUrl + 'img/lib/' + size + '/' + icon_name;
},
2024-07-18 03:58:42 +00:00
getLibIconUrl: function (repo, isBig) {
let permission = repo.permission || repo.share_permission; // Compatible with regular repo and repo shared
let size = Utils.isHiDPI() ? 48 : 24;
size = isBig ? 256 : size;
let icon_name = 'lib.png';
if (repo.encrypted) {
icon_name = 'lib-encrypted.png';
}
switch (permission) {
case 'r':
icon_name = 'lib-readonly.png';
break;
case 'preview':
icon_name = 'lib-cloud-preview.png';
break;
case 'cloud-edit':
icon_name = 'lib-cloud-preview-edit.png';
break;
}
// must be the last
if (repo.status == 'read-only') {
icon_name = 'lib-readonly.png';
}
return mediaUrl + 'img/lib/' + size + '/' + icon_name;
},
getDirentIcon: function (dirent, isBig) {
if (!dirent) return '';
2024-08-12 09:08:49 +00:00
let size = Utils.isHiDPI() ? 48 : 24;
size = isBig ? 192 : size;
if (dirent.type == 'file') {
return Utils.getFileIconUrl(dirent.name);
} else {
let readonly = false;
if (dirent.permission && (dirent.permission === 'r' || dirent.permission === 'preview')) {
readonly = true;
}
2024-08-12 09:08:49 +00:00
return Utils.getFolderIconUrl(readonly, size, dirent.has_been_shared_out);
}
},
2024-08-05 13:04:31 +00:00
getAdminTemplateDirentIcon: function (dirent) {
2019-09-24 04:18:53 +00:00
if (dirent.is_file) {
2024-08-05 13:04:31 +00:00
return this.getFileIconUrl(dirent.obj_name);
2019-09-24 04:18:53 +00:00
} else {
return this.getFolderIconUrl();
}
},
2024-07-18 03:58:42 +00:00
getFolderIconUrl: function (readonly = false, size, sharedOut) {
if (!size) {
size = Utils.isHiDPI() ? 48 : 24;
}
size = size > 24 ? 192 : 24;
return `${mediaUrl}img/folder${readonly ? '-read-only' : ''}${sharedOut ? '-shared-out' : ''}-${size}.png`;
},
2024-08-05 13:04:31 +00:00
getFileIconUrl: function (filename) {
let file_ext = '';
if (filename.lastIndexOf('.') == -1) {
2024-08-12 09:08:49 +00:00
return mediaUrl + 'img/file/256/' + Utils.FILEEXT_ICON_MAP['default'];
} else {
file_ext = filename.substr(filename.lastIndexOf('.') + 1).toLowerCase();
}
2024-08-12 09:08:49 +00:00
if (Utils.FILEEXT_ICON_MAP[file_ext]) {
return mediaUrl + 'img/file/256/' + Utils.FILEEXT_ICON_MAP[file_ext];
} else {
2024-08-12 09:08:49 +00:00
return mediaUrl + 'img/file/256/' + Utils.FILEEXT_ICON_MAP['default'];
}
},
2024-07-18 03:58:42 +00:00
getLibIconTitle: function (repo) {
var title;
2024-07-18 03:58:42 +00:00
let permission = repo.permission || repo.share_permission; // Compatible with regular repo and repo shared
if (repo.encrypted) {
title = gettext('Encrypted library');
} else if (repo.is_admin) { // shared with 'admin' permission
title = gettext('Admin access');
} else {
2024-07-18 03:58:42 +00:00
switch (permission) {
case 'rw':
title = gettext('Read-Write library');
break;
case 'r':
title = gettext('Read-Only library');
break;
case 'cloud-edit':
title = gettext('Online Read-Write library');
break;
case 'preview':
title = gettext('Online Read-Only library');
break;
}
}
return title;
},
2024-07-18 03:58:42 +00:00
getFolderIconTitle: function (options) {
var title;
2024-07-18 03:58:42 +00:00
switch (options.permission) {
case 'rw':
title = gettext('Read-Write folder');
break;
case 'r':
title = gettext('Read-Only folder');
break;
case 'cloud-edit':
title = gettext('Online Read-Write folder');
break;
case 'preview':
title = gettext('Online Read-Only folder');
break;
}
return title;
},
2024-07-18 03:58:42 +00:00
getFolderOperationList: function (isRepoOwner, currentRepoInfo, dirent, isContextmenu) {
let list = [];
const { SHARE, DOWNLOAD, DELETE, RENAME, MOVE, COPY, PERMISSION, OPEN_VIA_CLIENT } = TextTranslation;
const permission = dirent.permission;
const { isCustomPermission, customPermission } = Utils.getUserPermission(permission);
if (isContextmenu) {
if (permission == 'rw' || permission == 'r') {
list.push(DOWNLOAD);
}
if (isCustomPermission && customPermission.permission.download) {
list.push(DOWNLOAD);
}
if (Utils.isHasPermissionToShare(currentRepoInfo, permission, dirent)) {
list.push(SHARE);
}
if (permission == 'rw' || permission == 'cloud-edit') {
list.push(DELETE, 'Divider');
}
if (isCustomPermission && customPermission.permission.delete) {
list.push(DELETE, 'Divider');
}
}
if (permission == 'rw' || permission == 'cloud-edit') {
list.push(RENAME, MOVE);
}
if (isCustomPermission && customPermission.permission.modify) {
list.push(RENAME, MOVE);
}
if (permission == 'rw' || permission == 'cloud-edit') {
list.push(COPY);
}
if (isCustomPermission && customPermission.permission.copy) {
list.push(COPY);
}
if (permission == 'rw') {
2024-07-18 03:58:42 +00:00
if (folderPermEnabled && ((isRepoOwner && currentRepoInfo.has_been_shared_out) || currentRepoInfo.is_admin)) {
list.push('Divider', PERMISSION);
}
list.push('Divider', OPEN_VIA_CLIENT);
}
if (permission == 'r' && !currentRepoInfo.encrypted) {
list.push(COPY);
}
// if the last item of menuList is Divider, delete the last item
if (list[list.length - 1] === 'Divider') {
list.pop();
}
return list;
},
2024-07-18 03:58:42 +00:00
getFileOperationList: function (isRepoOwner, currentRepoInfo, dirent, isContextmenu) {
let list = [];
const {
SHARE, DOWNLOAD, DELETE, RENAME, MOVE, COPY, TAGS, UNLOCK, LOCK, UNFREEZE_DOCUMENT, FREEZE_DOCUMENT,
HISTORY, ACCESS_LOG, PROPERTIES, OPEN_VIA_CLIENT, ONLYOFFICE_CONVERT,
CONVERT_AND_EXPORT, CONVERT_TO_MARKDOWN, CONVERT_TO_DOCX, EXPORT_DOCX, CONVERT_TO_SDOC, EXPORT_SDOC
} = TextTranslation;
const permission = dirent.permission;
const { isCustomPermission, customPermission } = Utils.getUserPermission(permission);
if (isContextmenu) {
if (permission == 'rw' || permission == 'r') {
list.push(DOWNLOAD);
}
if (isCustomPermission && customPermission.permission.download) {
list.push(DOWNLOAD);
}
if (Utils.isHasPermissionToShare(currentRepoInfo, permission, dirent)) {
list.push(SHARE);
}
if (permission == 'rw' || permission == 'cloud-edit') {
if (!dirent.is_locked || (dirent.is_locked && dirent.locked_by_me)) {
list.push(DELETE);
}
list.push('Divider');
}
if (isCustomPermission && customPermission.permission.delete) {
if (!dirent.is_locked || (dirent.is_locked && dirent.locked_by_me)) {
list.push(DELETE);
}
list.push('Divider');
}
}
if (permission == 'rw' || permission == 'cloud-edit') {
if (!dirent.is_locked || (dirent.is_locked && dirent.locked_by_me)) {
list.push(RENAME, MOVE);
}
}
if (isCustomPermission && customPermission.permission.modify) {
if (!dirent.is_locked || (dirent.is_locked && dirent.locked_by_me)) {
list.push(RENAME, MOVE);
}
}
if (permission == 'rw' || permission == 'cloud-edit') {
list.push(COPY);
}
if (isCustomPermission) {
if (customPermission.permission.copy) {
list.push(COPY);
}
}
if (permission == 'rw') {
if (enableFileTags) {
list.push(TAGS);
}
if (isPro) {
if (dirent.is_locked) {
2021-01-26 08:54:12 +00:00
if (dirent.locked_by_me || dirent.lock_owner == 'OnlineOffice' || isRepoOwner || currentRepoInfo.is_admin) {
2024-04-11 10:26:48 +00:00
if (!dirent.name.endsWith('.sdoc')) {
list.push(UNLOCK);
}
}
} else {
2023-11-29 08:14:38 +00:00
if (!dirent.name.endsWith('.sdoc')) {
2023-11-14 08:06:45 +00:00
list.push(LOCK);
}
}
}
list.push('Divider');
2023-11-29 08:14:38 +00:00
if (isPro && !dirent.is_locked && dirent.name.endsWith('.sdoc')) {
list.push(FREEZE_DOCUMENT);
}
2024-04-11 10:26:48 +00:00
if (isPro && dirent.is_locked && dirent.name.endsWith('.sdoc')) {
list.push(UNFREEZE_DOCUMENT);
}
2023-11-29 08:14:38 +00:00
2023-09-14 06:36:58 +00:00
}
if ((permission == 'rw' || permission == 'cloud-edit') && enableSeadoc && !currentRepoInfo.encrypted) {
2024-01-22 04:13:31 +00:00
if (dirent.name.endsWith('.md') || dirent.name.endsWith('.docx')) {
2023-09-18 02:20:47 +00:00
list.push(CONVERT_TO_SDOC);
}
2023-09-14 06:36:58 +00:00
2023-09-18 02:20:47 +00:00
if (dirent.name.endsWith('.sdoc')) {
if (Utils.isDesktop()) {
let subOpList = [CONVERT_TO_MARKDOWN, CONVERT_TO_DOCX, EXPORT_DOCX, EXPORT_SDOC];
list.push({ ...CONVERT_AND_EXPORT, subOpList });
} else {
list.push(CONVERT_TO_MARKDOWN);
list.push(CONVERT_TO_DOCX);
list.push(EXPORT_DOCX);
list.push(EXPORT_SDOC);
}
2023-09-18 02:20:47 +00:00
}
2023-09-14 06:36:58 +00:00
}
if (permission == 'rw') {
list.push('Divider');
list.push(PROPERTIES, HISTORY);
if (isPro && fileAuditEnabled) {
list.push(ACCESS_LOG);
}
list.push('Divider', OPEN_VIA_CLIENT);
}
if (permission == 'r') {
if (!currentRepoInfo.encrypted) {
list.push(COPY);
}
list.push(HISTORY);
}
if (permission == 'rw' && enableOnlyoffice &&
onlyofficeConverterExtensions.includes(Utils.getFileExtension(dirent.name, false))) {
list.push(ONLYOFFICE_CONVERT);
}
// if the last item of menuList is Divider, delete the last item
if (list[list.length - 1] === 'Divider') {
list.pop();
}
// Remove adjacent excess 'Divider'
for (let i = 0; i < list.length; i++) {
if (list[i] === 'Divider' && list[i + 1] === 'Divider') {
list.splice(i, 1);
i--;
}
}
return list;
},
getFileExtension: function (fileName, withoutDot) {
let parts = fileName.toLowerCase().split('.');
return withoutDot ? parts.pop() : '.' + parts.pop();
},
2024-07-18 03:58:42 +00:00
getDirentOperationList: function (isRepoOwner, currentRepoInfo, dirent, isContextmenu) {
const operationListGetter = dirent.type === 'dir' ? Utils.getFolderOperationList : Utils.getFileOperationList;
return operationListGetter(isRepoOwner, currentRepoInfo, dirent, isContextmenu);
},
2024-07-18 03:58:42 +00:00
sharePerms: function (permission) {
var title;
2024-07-18 03:58:42 +00:00
switch (permission) {
case 'rw':
title = gettext('Read-Write');
break;
case 'r':
title = gettext('Read-Only');
break;
case 'admin':
title = gettext('Admin');
break;
case 'cloud-edit':
title = gettext('Online Read-Write');
break;
case 'preview':
title = gettext('Online Read-Only');
break;
case 'invisible':
title = gettext('Invisible');
break;
}
return title;
},
2024-07-18 03:58:42 +00:00
sharePermsExplanation: function (permission) {
2019-01-24 09:15:01 +00:00
var title;
2024-07-18 03:58:42 +00:00
switch (permission) {
2019-01-24 09:15:01 +00:00
case 'rw':
title = gettext('User can read, write, upload, download and sync files.');
2019-01-24 09:15:01 +00:00
break;
case 'r':
title = gettext('User can read, download and sync files.');
2019-01-24 09:15:01 +00:00
break;
case 'admin':
title = gettext('Besides Write permission, user can also share the library.');
2019-01-24 09:15:01 +00:00
break;
case 'cloud-edit':
2019-04-17 03:02:23 +00:00
title = gettext('User can view and edit file online via browser. Files can\'t be downloaded.');
2019-01-24 09:15:01 +00:00
break;
case 'preview':
title = gettext('User can only view files online via browser. Files can\'t be downloaded.');
2019-01-24 09:15:01 +00:00
break;
case 'invisible':
title = gettext('User can not see this folder.');
break;
2019-01-24 09:15:01 +00:00
}
return title;
},
2024-07-18 03:58:42 +00:00
getShareLinkPermissionObject: function (permission) {
switch (permission) {
case 'preview_download':
return {
value: permission,
text: gettext('Preview and download'),
permissionDetails: {
'can_edit': false,
'can_download': true,
'can_upload': false
}
};
case 'preview_only':
return {
value: permission,
text: gettext('Preview only'),
permissionDetails: {
'can_edit': false,
'can_download': false,
'can_upload': false
}
};
case 'download_upload':
return {
value: permission,
text: gettext('Download and upload'),
permissionDetails: {
'can_edit': false,
'can_download': true,
'can_upload': true
}
};
case 'edit_download':
return {
value: permission,
text: gettext('Edit on cloud and download'),
permissionDetails: {
'can_edit': true,
'can_download': true,
'can_upload': false
}
};
case 'cloud_edit':
return {
value: permission,
text: gettext('Edit on cloud only'),
permissionDetails: {
'can_edit': true,
'can_download': false,
'can_upload': false
}
};
}
return {
text: '',
};
},
2024-07-18 03:58:42 +00:00
formatSize: function (options) {
/*
* param: {bytes, precision}
*/
var bytes = options.bytes;
var precision = options.precision || 0;
2018-11-30 09:18:41 +00:00
var kilobyte = 1000;
var megabyte = kilobyte * 1000;
var gigabyte = megabyte * 1000;
var terabyte = gigabyte * 1000;
if ((bytes >= 0) && (bytes < kilobyte)) {
return bytes + ' B';
} else if ((bytes >= kilobyte) && (bytes < megabyte)) {
return (bytes / kilobyte).toFixed(precision) + ' KB';
} else if ((bytes >= megabyte) && (bytes < gigabyte)) {
return (bytes / megabyte).toFixed(precision) + ' MB';
} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
return (bytes / gigabyte).toFixed(precision) + ' GB';
} else if (bytes >= terabyte) {
return (bytes / terabyte).toFixed(precision) + ' TB';
} else {
return bytes + ' B';
}
2018-12-13 12:42:51 +00:00
},
2024-07-18 03:58:42 +00:00
formatBitRate: function (bits) {
2019-01-08 03:26:20 +00:00
var Bs;
if (typeof bits !== 'number') {
return '';
2019-01-08 03:26:20 +00:00
}
Bs = bits / 8;
if (Bs >= 1000000000) {
return (Bs / 1000000000).toFixed(2) + ' GB/s';
2019-01-08 03:26:20 +00:00
}
if (Bs >= 1000000) {
return (Bs / 1000000).toFixed(2) + ' MB/s';
2019-01-08 03:26:20 +00:00
}
if (Bs >= 1000) {
return (Bs / 1000).toFixed(2) + ' kB/s';
2019-01-08 03:26:20 +00:00
}
return Bs.toFixed(2) + ' B/s';
},
2024-07-18 03:58:42 +00:00
isMarkdownFile: function (filePath) {
2018-12-13 12:42:51 +00:00
let index = filePath.lastIndexOf('.');
if (index === -1) {
return false;
} else {
let type = filePath.substring(index).toLowerCase();
if (type === '.md' || type === '.markdown') {
return true;
} else {
return false;
}
}
},
2024-07-18 03:58:42 +00:00
isSdocFile: function (filePath) {
let index = filePath.lastIndexOf('.');
if (index === -1) {
return false;
} else {
let type = filePath.substring(index).toLowerCase();
if (type === '.sdoc') {
return true;
} else {
return false;
}
}
},
isDocxFile: function (filePath) {
let index = filePath.lastIndexOf('.');
if (index === -1) {
return false;
} else {
let type = filePath.substring(index).toLowerCase();
if (type === '.docx') {
return true;
} else {
return false;
}
}
},
isDescriptionSupportedFile: function (filePath) {
return Utils.isSdocFile(filePath) || Utils.isMarkdownFile(filePath) || Utils.pdfCheck(filePath) || Utils.isDocxFile(filePath);
},
2024-07-18 03:58:42 +00:00
isFileMetadata: function (type) {
return type === PRIVATE_FILE_TYPE.FILE_EXTENDED_PROPERTIES;
},
2024-07-18 03:58:42 +00:00
isInternalFileLink: function (url, repoID) {
var re = new RegExp(serviceURL + '/lib/' + repoID + '/file.*');
return re.test(url);
},
2024-07-18 03:58:42 +00:00
isInternalMarkdownLink: function (url, repoID) {
// eslint-disable-next-line
2019-01-24 07:41:01 +00:00
var re = new RegExp(serviceURL + '/lib/' + repoID + '.*\.md$');
2019-01-17 08:33:27 +00:00
return re.test(url);
},
2024-07-18 03:58:42 +00:00
isInternalDirLink: function (url, repoID) {
2019-01-24 07:41:01 +00:00
var re = new RegExp(serviceURL + '/library/' + repoID + '.*');
2019-01-17 08:33:27 +00:00
return re.test(url);
},
2024-07-18 03:58:42 +00:00
getPathFromInternalMarkdownLink: function (url, repoID) {
// eslint-disable-next-line
2019-01-24 07:41:01 +00:00
var re = new RegExp(serviceURL + '/lib/' + repoID + '/file' + '(.*\.md)');
2019-01-17 08:33:27 +00:00
var array = re.exec(url);
var path = decodeURIComponent(array[1]);
return path;
},
2024-07-18 03:58:42 +00:00
getPathFromInternalDirLink: function (url, repoID) {
2019-01-30 03:48:15 +00:00
var re = new RegExp(serviceURL + '/library/' + repoID + '(/.*)');
2019-01-17 08:33:27 +00:00
var array = re.exec(url);
var path = decodeURIComponent(array[1]);
2019-01-30 03:48:15 +00:00
path = path.slice(1);
path = path.slice(path.indexOf('/'));
2019-01-17 08:33:27 +00:00
return path;
},
2024-07-18 03:58:42 +00:00
isWikiInternalMarkdownLink: function (url, slug) {
slug = encodeURIComponent(slug);
// eslint-disable-next-line
var re = new RegExp(serviceURL + '/published/' + slug + '.*\.md$');
2019-01-24 07:41:01 +00:00
return re.test(url);
},
2024-07-18 03:58:42 +00:00
isWikiInternalDirLink: function (url, slug) {
slug = encodeURIComponent(slug);
var re = new RegExp(serviceURL + '/published/' + slug + '.*');
2019-01-24 07:41:01 +00:00
return re.test(url);
},
2024-07-18 03:58:42 +00:00
getPathFromWikiInternalMarkdownLink: function (url, slug) {
slug = encodeURIComponent(slug);
// eslint-disable-next-line
var re = new RegExp(serviceURL + '/published/' + slug + '(.*\.md)');
2019-01-24 07:41:01 +00:00
var array = re.exec(url);
2019-01-30 03:48:15 +00:00
var path = array[1];
try {
path = decodeURIComponent(path);
2024-07-18 03:58:42 +00:00
} catch (err) {
2019-01-30 03:48:15 +00:00
path = path.replace(/%/g, '%25');
path = decodeURIComponent(path);
}
2019-01-24 07:41:01 +00:00
return path;
},
2024-07-18 03:58:42 +00:00
getPathFromWikiInternalDirLink: function (url, slug) {
slug = encodeURIComponent(slug);
var re = new RegExp(serviceURL + '/published/' + slug + '(/.*)');
2019-01-24 07:41:01 +00:00
var array = re.exec(url);
2019-01-30 03:48:15 +00:00
var path = array[1];
try {
path = decodeURIComponent(path);
2024-07-18 03:58:42 +00:00
} catch (err) {
2019-01-30 03:48:15 +00:00
path = path.replace(/%/g, '%25');
path = decodeURIComponent(path);
}
2019-01-24 07:41:01 +00:00
return path;
},
2024-07-18 03:58:42 +00:00
compareTwoWord: function (wordA, wordB) {
// compare wordA and wordB at lower case
// if wordA >= wordB, return 1
// if wordA < wordB, return -1
return compareTwoString(wordA, wordB);
},
// compare two strings which may have digits in them
// and compare those digits as number instead of string
2024-07-18 03:58:42 +00:00
compareStrWithNumbersIn: function (a, b) {
var reParts = /\d+|\D+/g;
var reDigit = /\d/;
var aParts = a.match(reParts);
var bParts = b.match(reParts);
var isDigitPart;
var len = Math.min(aParts.length, bParts.length);
2024-07-18 03:58:42 +00:00
var aPart; var bPart;
if (aParts && bParts &&
(isDigitPart = reDigit.test(aParts[0])) == reDigit.test(bParts[0])) {
// Loop through each substring part to compare the overall strings.
for (var i = 0; i < len; i++) {
aPart = aParts[i];
bPart = bParts[i];
if (isDigitPart) {
aPart = parseInt(aPart, 10);
bPart = parseInt(bPart, 10);
}
if (aPart != bPart) {
return aPart < bPart ? -1 : 1;
}
// Toggle the value of isDigitPart since the parts will alternate.
isDigitPart = !isDigitPart;
}
}
// Use normal comparison.
return (a >= b) - (a <= b);
},
2024-07-18 03:58:42 +00:00
sortRepos: function (repos, sortBy, sortOrder) {
const _this = this;
let comparator;
switch (`${sortBy}-${sortOrder}`) {
case 'name-asc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
if (!a.repo_name) {
return 1;
}
if (!b.repo_name) {
return -1;
}
var result = _this.compareTwoWord(a.repo_name, b.repo_name);
return result;
};
break;
case 'name-desc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
if (!a.repo_name) {
return -1;
}
if (!b.repo_name) {
return 1;
}
var result = _this.compareTwoWord(a.repo_name, b.repo_name);
return -result;
};
break;
case 'time-asc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
return a.last_modified < b.last_modified ? -1 : 1;
};
break;
case 'time-desc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
return a.last_modified < b.last_modified ? 1 : -1;
};
break;
2019-05-29 05:57:12 +00:00
case 'size-asc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
if (a.size === b.size) {
2019-05-29 08:44:37 +00:00
let result = _this.compareTwoWord(a.repo_name, b.repo_name);
return result;
}
2019-05-30 08:01:18 +00:00
return a.size_original < b.size_original ? -1 : 1;
2019-05-29 05:57:12 +00:00
};
break;
case 'size-desc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
if (a.size === b.size) {
2019-05-29 08:44:37 +00:00
let result = _this.compareTwoWord(a.repo_name, b.repo_name);
return -result;
}
2019-05-30 08:01:18 +00:00
return a.size_original < b.size_original ? 1 : -1;
2019-05-29 05:57:12 +00:00
};
break;
}
repos.sort(comparator);
return repos;
},
2024-07-18 03:58:42 +00:00
sortDirents: function (items, sortBy, sortOrder) {
const _this = this;
let comparator;
switch (`${sortBy}-${sortOrder}`) {
case 'name-asc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
var result = _this.compareTwoWord(a.name, b.name);
return result;
};
break;
case 'name-desc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
var result = _this.compareTwoWord(a.name, b.name);
return -result;
};
break;
case 'time-asc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
return a.mtime < b.mtime ? -1 : 1;
};
break;
case 'time-desc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
return a.mtime < b.mtime ? 1 : -1;
};
break;
2019-05-29 05:57:12 +00:00
case 'size-asc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
2019-05-29 05:57:12 +00:00
if (a.type == 'dir' && b.type == 'dir') {
return 0;
}
2019-05-30 08:01:18 +00:00
return a.size_original < b.size_original ? -1 : 1;
2019-05-29 05:57:12 +00:00
};
break;
case 'size-desc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
2019-05-29 05:57:12 +00:00
if (a.type == 'dir' && b.type == 'dir') {
return 0;
}
2019-05-30 08:01:18 +00:00
return a.size_original < b.size_original ? 1 : -1;
2019-05-29 05:57:12 +00:00
};
break;
}
items.sort((a, b) => {
if (a.type == 'dir' && b.type == 'file') {
return -1;
} else if (a.type == 'file' && b.type == 'dir') {
return 1;
} else {
return comparator(a, b);
}
});
return items;
2019-01-24 07:41:01 +00:00
},
// sort dirents in shared folder
2024-07-18 03:58:42 +00:00
sortDirentsInSharedDir: function (items, sortBy, sortOrder) {
const _this = this;
let comparator;
switch (`${sortBy}-${sortOrder}`) {
case 'name-asc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
let result;
if (a.is_dir) {
result = _this.compareTwoWord(a.folder_name, b.folder_name);
} else {
result = _this.compareTwoWord(a.file_name, b.file_name);
}
return result;
};
break;
case 'name-desc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
let result;
if (a.is_dir) {
result = _this.compareTwoWord(a.folder_name, b.folder_name);
} else {
result = _this.compareTwoWord(a.file_name, b.file_name);
}
return -result;
};
break;
case 'time-asc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
return a.last_modified < b.last_modified ? -1 : 1;
};
break;
case 'time-desc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
return a.last_modified < b.last_modified ? 1 : -1;
};
break;
case 'size-asc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
if (a.is_dir) {
return 0;
} else {
return a.size < b.size ? -1 : 1;
}
};
break;
case 'size-desc':
2024-07-18 03:58:42 +00:00
comparator = function (a, b) {
if (a.is_dir) {
return 0;
} else {
return a.size < b.size ? 1 : -1;
}
};
break;
}
items.sort((a, b) => {
if (a.is_dir && !b.is_dir) {
return -1;
} else if (!a.is_dir && b.is_dir) {
return 1;
} else {
return comparator(a, b);
}
});
return items;
},
/*
* only used in the 'catch' part of a seafileAPI request
*/
2024-07-18 03:58:42 +00:00
getErrorMsg: function (error, showPermissionDeniedTip) {
let errorMsg = '';
if (error.response) {
if (error.response.status == 403) {
if (showPermissionDeniedTip) {
toaster.danger(
<PermissionDeniedTip />,
2024-07-18 03:58:42 +00:00
{ id: 'permission_denied', duration: 3600 }
);
}
errorMsg = gettext('Permission denied');
} else if (error.response.status == 429) {
errorMsg = gettext('Too many requests');
} else if (error.response.data &&
error.response.data['error_msg']) {
errorMsg = error.response.data['error_msg'];
} else {
errorMsg = gettext('Error');
}
} else {
errorMsg = gettext('Please check the network.');
}
return errorMsg;
},
2024-07-18 03:58:42 +00:00
changeMarkdownNodes: function (nodes, fn) {
nodes.forEach((item) => {
fn(item);
if (item.children && item.children.length > 0) {
Utils.changeMarkdownNodes(item.children, fn);
2019-01-24 07:41:01 +00:00
}
});
return nodes;
},
2024-07-18 03:58:42 +00:00
chooseLanguage: function (suffix) {
2019-02-01 10:44:10 +00:00
let mode;
2024-07-18 03:58:42 +00:00
switch (suffix) {
2019-02-01 10:44:10 +00:00
case 'py':
mode = 'python';
break;
case 'js':
mode = 'javascript';
break;
case 'c':
mode = 'c';
2019-02-01 10:44:10 +00:00
break;
case 'cpp':
mode = 'cpp';
2019-02-01 10:44:10 +00:00
break;
case 'cs':
mode = 'csharp';
break;
case 'java':
mode = 'java';
2019-02-01 10:44:10 +00:00
break;
case 'mdf':
mode = 'text/x-sql';
break;
case 'html':
mode = 'html';
break;
case 'sh':
mode = 'shell';
2019-02-01 10:44:10 +00:00
break;
default:
mode = suffix;
}
return mode;
},
DARK_COLOR_MAP: {
// old color
'red': '#D11507',
'orange': '#FF8C00',
'yellow': '#EDEF00',
'green': '#006400',
'cyan': '#00E0E1',
'blue': '#2510A3',
'indigo': '#350C56',
'purple': '#551054',
'pink': '#E3A5B0',
'azure': '#C4D0D0',
'lime': '#00E100',
'teal': '#006A6B',
'gray': '#545454',
// new color
'#FFA8A8': '#E49090',
'#FFA94D': '#E39136',
'#FFD43B': '#E0B815',
'#A0EC50': '#83CF32',
'#A9E34B': '#8DC72E',
'#63E6BE': '#43CAA4',
'#4FD2C9': '#2DB9B0',
'#72C3FC': '#57ABE3',
'#91A7FF': '#7A91E7',
'#E599F7': '#CC82DE',
'#B197FC': '#9B82E5',
'#F783AC': '#DF6D97',
'#CED4DA': '#A8ADB2',
},
2024-07-18 03:58:42 +00:00
getDarkColor: function (color) {
let darkColor;
darkColor = this.DARK_COLOR_MAP[color];
return darkColor;
},
2024-07-18 03:58:42 +00:00
getCopySuccessfulMessage: function (dirNames) {
let message;
let dirNamesLength = dirNames.length;
if (dirNamesLength === 1) {
message = gettext('Successfully copied %(name)s.');
} else if (dirNamesLength === 2) {
message = gettext('Successfully copied %(name)s and 1 other item.');
} else {
message = gettext('Successfully copied %(name)s and %(amount)s other items.');
message = message.replace('%(amount)s', dirNamesLength - 1);
}
message = message.replace('%(name)s', dirNames[0]);
return message;
},
2024-07-18 03:58:42 +00:00
getMoveSuccessMessage: function (dirNames) {
let message;
let dirNamesLength = dirNames.length;
if (dirNamesLength === 1) {
message = gettext('Successfully moved %(name)s.');
} else if (dirNamesLength === 2) {
message = gettext('Successfully moved %(name)s and 1 other item.');
} else {
message = gettext('Successfully moved %(name)s and %(amount)s other items.');
message = message.replace('%(amount)s', dirNamesLength - 1);
}
message = message.replace('%(name)s', dirNames[0]);
return message;
},
2024-07-18 03:58:42 +00:00
getCopyFailedMessage: function (dirNames) {
let message;
let dirNamesLength = dirNames.length;
if (dirNamesLength > 1) {
message = gettext('Failed to copy %(name)s and %(amount)s other item(s).');
message = message.replace('%(amount)s', dirNamesLength - 1);
} else {
message = gettext('Failed to copy %(name)s.');
}
message = message.replace('%(name)s', dirNames[0]);
return message;
},
2024-07-18 03:58:42 +00:00
getMoveFailedMessage: function (dirNames) {
let message;
let dirNamesLength = dirNames.length;
if (dirNamesLength > 1) {
message = gettext('Failed to move %(name)s and %(amount)s other item(s).');
message = message.replace('%(amount)s', dirNamesLength - 1);
} else {
message = gettext('Failed to move %(name)s.');
}
message = message.replace('%(name)s', dirNames[0]);
return message;
},
2024-07-18 03:58:42 +00:00
handleSearchedItemClick: function (searchedItem) {
2019-04-26 03:34:11 +00:00
if (searchedItem.is_dir === true) {
let url = siteRoot + 'library/' + searchedItem.repo_id + '/' + searchedItem.repo_name + searchedItem.path;
let newWindow = window.open('about:blank');
newWindow.location.href = url;
} else {
let url = siteRoot + 'lib/' + searchedItem.repo_id + '/file' + Utils.encodePath(searchedItem.path);
let newWindow = window.open('about:blank');
newWindow.location.href = url;
}
},
2024-07-18 03:58:42 +00:00
generatePassword: function (length, hasNum = 1, hasChar = 1, hasSymbol = 1) {
var password = '';
// 65~90A~Z
2024-07-18 03:58:42 +00:00
password += String.fromCharCode(Math.floor((Math.random() * (90 - 65)) + 65));
// 97~122a~z
2024-07-18 03:58:42 +00:00
password += String.fromCharCode(Math.floor((Math.random() * (122 - 97)) + 97));
// 48~570~9
2024-07-18 03:58:42 +00:00
password += String.fromCharCode(Math.floor((Math.random() * (57 - 48)) + 48));
// 33~47!~/
2024-07-18 03:58:42 +00:00
password += String.fromCharCode(Math.floor((Math.random() * (47 - 33)) + 33));
// 33~47!~/
// 48~570~9
// 58~64:~@
// 65~90A~Z
// 91~96[~`
// 97~122a~z
// 123~127{~
for (var i = 0; i < length - 4; i++) {
2024-07-18 03:58:42 +00:00
var num = Math.floor((Math.random() * (127 - 33)) + 33);
password += String.fromCharCode(num);
2019-05-06 08:08:34 +00:00
}
2019-05-06 08:08:34 +00:00
return password;
2019-06-04 08:18:32 +00:00
},
2024-07-18 03:58:42 +00:00
pathNormalize: function (originalPath) {
2019-06-20 10:25:10 +00:00
let oldPath = originalPath.split('/');
let newPath = [];
for (let i = 0; i < oldPath.length; i++) {
if (oldPath[i] === '.' || oldPath[i] === '') {
continue;
} else if (oldPath[i] === '..') {
newPath.pop();
} else {
newPath.push(oldPath[i]);
2019-06-20 06:40:11 +00:00
}
}
2019-06-20 10:03:26 +00:00
return newPath.join('/');
2019-06-20 06:40:11 +00:00
},
2024-07-18 03:58:42 +00:00
getEventData: function (event, data) {
2019-06-04 08:18:32 +00:00
if (event.target.dataset) {
return event.target.dataset[data];
}
return event.target.getAttribute('data-' + data);
2019-06-21 09:54:06 +00:00
},
/**
* Check whether user has permission to share a dirent.
2019-06-21 13:09:12 +00:00
* If dirent is none, then check whether the user can share the repo
2019-06-21 13:16:05 +00:00
* scene 1: root path or folder path, control the share button in the toolbar
* scene 2: selected a dirent, control the share button in the toolbar dropdown-menu
* scene 3: dirent list(grid list), control the share button in the dirent-item or righe-menu
*
* @param {*} repoInfo
* @param {*} userDirPermission
* @param {*} dirent
2019-06-21 09:54:06 +00:00
*/
2024-07-18 03:58:42 +00:00
isHasPermissionToShare: function (repoInfo, userDirPermission, dirent) {
const { isCustomPermission, customPermission } = Utils.getUserPermission(userDirPermission);
if (isCustomPermission) {
const { download_external_link } = customPermission.permission;
return download_external_link;
}
2019-06-21 09:54:06 +00:00
let { is_admin: isAdmin, is_virtual: isVirtual, encrypted: repoEncrypted, owner_email: ownerEmail } = repoInfo;
let isRepoOwner = ownerEmail === username;
2019-06-21 13:09:12 +00:00
if (repoEncrypted) {
return true;
2019-06-21 13:09:12 +00:00
}
// for 'file' & 'dir'
if (dirent) {
if (userDirPermission == 'rw' || userDirPermission == 'r') {
// can generate internal link
return true;
2019-06-21 09:54:06 +00:00
}
2019-06-21 13:09:12 +00:00
}
2019-06-21 09:54:06 +00:00
2019-06-21 13:09:12 +00:00
// the root path or the dirent type is dir
let hasGenerateShareLinkPermission = false;
if (canGenerateShareLink && (userDirPermission == 'rw' || userDirPermission == 'r')) {
hasGenerateShareLinkPermission = true;
return hasGenerateShareLinkPermission;
}
2019-06-21 09:54:06 +00:00
2019-06-21 13:09:12 +00:00
let hasGenerateUploadLinkPermission = false;
if (canGenerateUploadLink && (userDirPermission == 'rw')) {
hasGenerateUploadLinkPermission = true;
return hasGenerateUploadLinkPermission;
2019-06-21 09:54:06 +00:00
}
2019-06-21 13:09:12 +00:00
let hasDirPrivateSharePermission = false;
if (!isVirtual && (isRepoOwner || isAdmin)) {
hasDirPrivateSharePermission = true;
return hasDirPrivateSharePermission;
2019-06-21 09:54:06 +00:00
}
2019-06-21 13:09:12 +00:00
return false;
},
2024-07-18 03:58:42 +00:00
registerGlobalVariable: function (namespace, key, value) {
if (!window[namespace]) {
window[namespace] = {};
}
window[namespace][key] = value;
},
2024-07-18 03:58:42 +00:00
formatTime: function (seconds) {
var ss = parseInt(seconds);
var mm = 0;
var hh = 0;
if (ss > 60) {
mm = parseInt(ss / 60);
ss = parseInt(ss % 60);
}
if (mm > 60) {
hh = parseInt(mm / 60);
mm = parseInt(mm % 60);
}
var result = ('00' + parseInt(ss)).slice(-2);
if (mm > 0) {
result = ('00' + parseInt(mm)).slice(-2) + ':' + result;
} else {
result = '00:' + result;
}
if (hh > 0) {
result = ('00' + parseInt(hh)).slice(-2) + ':' + result;
} else {
result = '00:' + result;
}
return result;
},
hasNextPage(curPage, perPage, totalCount) {
return curPage * perPage < totalCount;
},
2024-07-18 03:58:42 +00:00
getStrengthLevel: function (pwd) {
const _this = this;
var num = 0;
if (pwd.length < shareLinkPasswordMinLength) {
return 0;
} else {
for (var i = 0; i < pwd.length; i++) {
// return the unicode
// bitwise OR
num |= _this.getCharMode(pwd.charCodeAt(i));
}
return _this.calculateBitwise(num);
}
},
2024-07-18 03:58:42 +00:00
getCharMode: function (n) {
if (n >= 48 && n <= 57) // nums
return 1;
if (n >= 65 && n <= 90) // uppers
return 2;
if (n >= 97 && n <= 122) // lowers
return 4;
else
return 8;
},
2024-07-18 03:58:42 +00:00
calculateBitwise: function (num) {
var level = 0;
for (var i = 0; i < 4; i++) {
// bitwise AND
2024-07-18 03:58:42 +00:00
if (num & 1) level++;
// Right logical shift
2024-07-18 03:58:42 +00:00
num >>>= 1;
}
return level;
},
2024-07-18 03:58:42 +00:00
getSharedPermission: function (item) {
let permission = item.permission;
if (item.is_admin) {
permission = 'admin';
}
if (item.permission.startsWith('custom-')) {
permission = item.permission.slice(7);
}
return permission;
},
2024-07-18 03:58:42 +00:00
getUserPermission: function (userPerm) {
const { custom_permission } = window;
const common_permissions = ['rw', 'r', 'admin', 'cloud-edit', 'preview'];
// visit the shared repo(virtual repo) by custom permission
if (!custom_permission || common_permissions.indexOf(userPerm) > -1) {
return { isCustomPermission: false };
}
// userPerm is startsWith 'custom-'
if (custom_permission) {
const permissionId = custom_permission.id;
const userPermId = parseInt(userPerm.split('-')[1]);
if (permissionId === userPermId) {
return { isCustomPermission: true, customPermission: custom_permission };
}
// TODO user set custom permission on folder
}
return { isCustomPermission: false };
},
2019-05-06 08:08:34 +00:00
// for a11y
2024-07-18 03:58:42 +00:00
onKeyDown: function (e) {
if (e.key == 'Enter' || e.key == 'Space') {
e.target.click();
}
},
2024-07-18 03:58:42 +00:00
updateTabTitle: function (content) {
const title = document.getElementsByTagName('title')[0];
title.innerText = content;
},
2024-07-18 03:58:42 +00:00
generateHistoryURL: function (siteRoot, repoID, path) {
if (!siteRoot || !repoID || !path) return '';
return siteRoot + 'repo/file_revisions/' + repoID + '/?p=' + this.encodePath(path);
2023-07-06 06:56:31 +00:00
},
2024-07-18 03:58:42 +00:00
generateRevisionURL: function (siteRoot, repoID, path) {
2023-07-06 06:56:31 +00:00
if (!siteRoot || !repoID || !path) return '';
return siteRoot + 'repo/sdoc_revision/' + repoID + '/?p=' + this.encodePath(path);
2023-07-07 08:07:14 +00:00
},
2024-07-18 03:58:42 +00:00
generateRevisionsURL: function (siteRoot, repoID, path) {
2023-07-07 08:07:14 +00:00
if (!siteRoot || !repoID || !path) return '';
return siteRoot + 'repo/sdoc_revisions/' + repoID + '/?p=' + this.encodePath(path);
},
2024-07-18 03:58:42 +00:00
isFunction: function (functionToCheck) {
const getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
},
getUrlSearches() {
const search = location.search;
let searchParams = {};
if (search.length === 0) {
return searchParams;
}
let allSearches = search.split('?')[1];
let allSearchesArr = allSearches.split('&');
allSearchesArr.forEach(item => {
let itemArr = item.split('=');
searchParams[itemArr[0]] = decodeURI(itemArr[1]);
});
return searchParams;
},
// If value is null, delete the search parameter; else, add or update the search parameter.
updateSearchParameter(key, value) {
const { origin, pathname } = location;
const searchParams = this.getUrlSearches();
searchParams[key] = value;
let newSearch = '?';
for (let key in searchParams) {
let value = searchParams[key];
if (value) {
newSearch = newSearch === '?' ? `?${key}=${value}` : `${newSearch}&${key}=${value}`;
}
}
history.replaceState(null, '', origin + pathname + newSearch);
},
2024-05-13 05:54:15 +00:00
isRelativePath(url) {
let RgExp = new RegExp('^(?:[a-z]+:)?//', 'i');
return !RgExp.test(url);
},
isMac() {
const platform = navigator.platform;
return (platform == 'Mac68K') || (platform == 'MacPPC') || (platform == 'Macintosh') || (platform == 'MacIntel');
},
2024-05-13 05:54:15 +00:00
};
2024-05-14 10:02:31 +00:00
export const isMobile = (typeof (window) !== 'undefined') && (window.innerWidth < 768 || navigator.userAgent.toLowerCase().match(/(ipod|ipad|iphone|android|coolpad|mmp|smartphone|midp|wap|xoom|symbian|j2me|blackberry|wince)/i) != null);
export const evaluatePasswordStrength = (password) => {
let strength = 0;
const length = password.length;
const hasUppercase = /[A-Z]/.test(password);
const hasLowercase = /[a-z]/.test(password);
const hasNumbers = /\d/.test(password);
const hasSpecialChars = /[`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\]/.test(password);
// Increased strength based on length
if (length === 0) return 'empty';
if (length >= 16) strength += 4;
else if (length >= 12) strength += 3;
else if (length >= 8) strength += 2;
else if (length >= 6) strength += 1;
// Increased strength based on character type
if (hasUppercase) strength += 1;
if (hasLowercase) strength += 1;
if (hasNumbers) strength += 1;
if (hasSpecialChars) strength += 1;
// Determine password strength
if (strength >= 8) return 'very_strong';
if (strength >= 6) return 'strong';
if (strength >= 4) return 'medium';
return 'weak';
};
export const validatePassword = (password) => {
const { userStrongPasswordRequired } = window.app.pageOptions;
const passwordStrength = evaluatePasswordStrength(password);
const requiredStrengths = userStrongPasswordRequired ? ['strong', 'very_strong'] : ['medium', 'strong', 'very_strong'];
return requiredStrengths.includes(passwordStrength);
};
export const validateName = (newName) => {
let isValid = true;
let errMessage = '';
if (!newName || !newName.trim()) {
isValid = false;
errMessage = gettext('Name is required');
return { isValid, errMessage };
}
if (newName.includes('/')) {
isValid = false;
errMessage = gettext('Name cannot contain slash');
return { isValid, errMessage };
}
if (newName.includes('`')) {
isValid = false;
errMessage = gettext('Name cannot contain backtick');
return { isValid, errMessage };
}
if (newName.includes('\\')) {
isValid = false;
errMessage = gettext('Name cannot contain backslash');
return { isValid, errMessage };
}
return { isValid, errMessage };
};