mirror of
https://github.com/nextcloud/server.git
synced 2026-02-20 00:12:30 -05:00
feat(files): add FileAction service
Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
This commit is contained in:
parent
014a57e541
commit
bdbe477337
5 changed files with 191 additions and 2 deletions
|
|
@ -20,11 +20,12 @@
|
|||
*
|
||||
*/
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
import { registerFileAction, Permission, FileAction, Node } from '@nextcloud/files'
|
||||
import { Permission, Node } from '@nextcloud/files'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import axios from '@nextcloud/axios'
|
||||
import TrashCan from '@mdi/svg/svg/trash-can.svg?raw'
|
||||
|
||||
import { registerFileAction, FileAction } from '../services/FileAction'
|
||||
import logger from '../logger'
|
||||
|
||||
registerFileAction(new FileAction({
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ import { Fragment } from 'vue-fragment'
|
|||
import { join } from 'path'
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import { translate } from '@nextcloud/l10n'
|
||||
import CancelablePromise from 'cancelable-promise'
|
||||
import FileIcon from 'vue-material-design-icons/File.vue'
|
||||
import FolderIcon from 'vue-material-design-icons/Folder.vue'
|
||||
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
|
||||
|
|
|
|||
184
apps/files/src/services/FileAction.ts
Normal file
184
apps/files/src/services/FileAction.ts
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2023 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license AGPL-3.0-or-later
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import { Node } from '@nextcloud/files'
|
||||
import logger from '../logger'
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
OC: any;
|
||||
_nc_fileactions: FileAction[] | undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: remove and move to @nextcloud/files
|
||||
* @see https://github.com/nextcloud/nextcloud-files/pull/608
|
||||
*/
|
||||
interface FileActionData {
|
||||
/** Unique ID */
|
||||
id: string
|
||||
/** Translatable string displayed in the menu */
|
||||
displayName: (files: Node[], view) => string
|
||||
/** Svg as inline string. <svg><path fill="..." /></svg> */
|
||||
iconSvgInline: (files: Node[], view) => string
|
||||
/** Condition wether this action is shown or not */
|
||||
enabled?: (files: Node[], view) => boolean
|
||||
/**
|
||||
* Function executed on single file action
|
||||
* @returns true if the action was executed, false otherwise
|
||||
* @throws Error if the action failed
|
||||
*/
|
||||
exec: (file: Node, view) => Promise<boolean>,
|
||||
/**
|
||||
* Function executed on multiple files action
|
||||
* @returns true if the action was executed, false otherwise
|
||||
* @throws Error if the action failed
|
||||
*/
|
||||
execBatch?: (files: Node[], view) => Promise<boolean[]>
|
||||
/** This action order in the list */
|
||||
order?: number,
|
||||
/** Make this action the default */
|
||||
default?: boolean,
|
||||
/**
|
||||
* If true, the renderInline function will be called
|
||||
*/
|
||||
inline?: (file: Node, view) => boolean,
|
||||
/**
|
||||
* If defined, the returned html element will be
|
||||
* appended before the actions menu.
|
||||
*/
|
||||
renderInline?: (file: Node, view) => HTMLElement,
|
||||
}
|
||||
|
||||
export class FileAction {
|
||||
|
||||
private _action: FileActionData
|
||||
|
||||
constructor(action: FileActionData) {
|
||||
this.validateAction(action)
|
||||
this._action = action
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this._action.id
|
||||
}
|
||||
|
||||
get displayName() {
|
||||
return this._action.displayName
|
||||
}
|
||||
|
||||
get iconSvgInline() {
|
||||
return this._action.iconSvgInline
|
||||
}
|
||||
|
||||
get enabled() {
|
||||
return this._action.enabled
|
||||
}
|
||||
|
||||
get exec() {
|
||||
return this._action.exec
|
||||
}
|
||||
|
||||
get execBatch() {
|
||||
return this._action.execBatch
|
||||
}
|
||||
|
||||
get order() {
|
||||
return this._action.order
|
||||
}
|
||||
|
||||
get default() {
|
||||
return this._action.default
|
||||
}
|
||||
|
||||
get inline() {
|
||||
return this._action.inline
|
||||
}
|
||||
|
||||
get renderInline() {
|
||||
return this._action.renderInline
|
||||
}
|
||||
|
||||
private validateAction(action: FileActionData) {
|
||||
if (!action.id || typeof action.id !== 'string') {
|
||||
throw new Error('Invalid id')
|
||||
}
|
||||
|
||||
if (!action.displayName || typeof action.displayName !== 'function') {
|
||||
throw new Error('Invalid displayName function')
|
||||
}
|
||||
|
||||
if (!action.iconSvgInline || typeof action.iconSvgInline !== 'function') {
|
||||
throw new Error('Invalid iconSvgInline function')
|
||||
}
|
||||
|
||||
if (!action.exec || typeof action.exec !== 'function') {
|
||||
throw new Error('Invalid exec function')
|
||||
}
|
||||
|
||||
// Optional properties --------------------------------------------
|
||||
if ('enabled' in action && typeof action.enabled !== 'function') {
|
||||
throw new Error('Invalid enabled function')
|
||||
}
|
||||
|
||||
if ('execBatch' in action && typeof action.execBatch !== 'function') {
|
||||
throw new Error('Invalid execBatch function')
|
||||
}
|
||||
|
||||
if ('order' in action && typeof action.order !== 'number') {
|
||||
throw new Error('Invalid order')
|
||||
}
|
||||
|
||||
if ('default' in action && typeof action.default !== 'boolean') {
|
||||
throw new Error('Invalid default')
|
||||
}
|
||||
|
||||
if ('inline' in action && typeof action.inline !== 'function') {
|
||||
throw new Error('Invalid inline function')
|
||||
}
|
||||
|
||||
if ('renderInline' in action && typeof action.renderInline !== 'function') {
|
||||
throw new Error('Invalid renderInline function')
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export const registerFileAction = function(action: FileAction): void {
|
||||
if (typeof window._nc_fileactions === 'undefined') {
|
||||
window._nc_fileactions = []
|
||||
logger.debug('FileActions initialized')
|
||||
}
|
||||
|
||||
// Check duplicates
|
||||
if (window._nc_fileactions.find(search => search.id === action.id)) {
|
||||
logger.error(`FileAction ${action.id} already registered`, { action })
|
||||
return
|
||||
}
|
||||
|
||||
window._nc_fileactions.push(action)
|
||||
}
|
||||
|
||||
export const getFileActions = function(): FileAction[] {
|
||||
return window._nc_fileactions || []
|
||||
}
|
||||
|
|
@ -22,11 +22,13 @@
|
|||
import { emit } from '@nextcloud/event-bus'
|
||||
import { generateRemoteUrl } from '@nextcloud/router'
|
||||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
import { registerFileAction, Permission, FileAction, Node } from '@nextcloud/files'
|
||||
import { Permission, Node } from '@nextcloud/files'
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import axios from '@nextcloud/axios'
|
||||
import History from '@mdi/svg/svg/history.svg?raw'
|
||||
|
||||
import { registerFileAction, FileAction } from '../../../files/src/services/FileAction'
|
||||
|
||||
registerFileAction(new FileAction({
|
||||
id: 'restore',
|
||||
displayName() {
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
"blueimp-md5": "^2.19.0",
|
||||
"browserslist-useragent-regexp": "^3.0.2",
|
||||
"camelcase": "^6.3.0",
|
||||
"cancelable-promise": "^4.3.1",
|
||||
"clipboard": "^2.0.11",
|
||||
"colord": "^2.9.3",
|
||||
"core-js": "^3.24.0",
|
||||
|
|
|
|||
Loading…
Reference in a new issue