Api: Add a paste button to et2-link-to widget

Paste lets you link filemanager files previously put into the clipboard via filemanager context menu
This commit is contained in:
nathan 2024-03-20 14:23:56 -06:00
parent f4466a01b4
commit 335f618736
3 changed files with 171 additions and 6 deletions

View File

@ -534,8 +534,14 @@ export class EgwPopupActionImplementation implements EgwActionImplementation {
// egwAction is a circular structure and can't be stringified so just take what we want
// Hopefully that's enough for the action handlers
for (const k in selected) {
if (selected[k].id) clipboard.selected.push({id: selected[k].id, data: selected[k].data});
}
if(selected[k].id)
{
clipboard.selected.push({
id: selected[k].id,
data: {...(window.egw.dataGetUIDdata(selected[k].id)?.data ?? {}), ...selected[k].data}
});
}
}
// Save it in session
window.egw.setSessionItem('phpgwapi', 'egw_clipboard', JSON.stringify(clipboard));
@ -561,8 +567,14 @@ export class EgwPopupActionImplementation implements EgwActionImplementation {
// egwAction is a circular structure and can't be stringified so just take what we want
// Hopefully that's enough for the action handlers
for (const k in selected) {
if (selected[k].id) clipboard.selected.push({id: selected[k].id, data: selected[k].data});
}
if(selected[k].id)
{
clipboard.selected.push({
id: selected[k].id,
data: {...(window.egw.dataGetUIDdata(selected[k].id)?.data ?? {}), ...selected[k].data}
});
}
}
// Save it in session
window.egw.setSessionItem('phpgwapi', 'egw_clipboard', JSON.stringify(clipboard));

View File

@ -0,0 +1,101 @@
import {Et2VfsSelectDialog} from "../Et2Vfs/Et2VfsSelectDialog";
import {css, html, TemplateResult} from "lit";
import {SearchResult} from "../Et2Widget/SearchMixin";
/**
* Select files from the file clipboard to paste
*/
export class Et2LinkPasteDialog extends Et2VfsSelectDialog
{
static get styles()
{
return [
...super.styles,
css`
/* Hide the unwanted stuff */
#toolbar, #path {
display: none;
}
`
];
}
constructor()
{
super();
this.searchUrl = "";
this.multiple = true;
this._appList = [];
}
/**
* Override double-click on directory, can't go into it
*
* @param {MouseEvent} event
*/
handleFileDoubleClick(event : MouseEvent)
{
// just select it
this.handleFileClick(event);
}
protected localSearch<DataType extends SearchResult>(search : string, searchOptions : object, localOptions : DataType[] = []) : Promise<DataType[]>
{
const files = getClipboardFiles();
// We don't care if they're directories, treat them all as files (no double click, all selectable)
files.forEach(f => f.isDir = false);
return super.localSearch(search, searchOptions, files);
}
protected noResultsTemplate() : TemplateResult
{
return html`
<div class="search__empty vfs_select__empty">
<et2-image src="filemanager"></et2-image>
${this.egw().lang("clipboard is empty!")}
</div>`;
}
}
/**
* Get any files that are in the system clipboard
*
* @return {string[]} Paths
*/
export function getClipboardFiles()
{
let clipboard_files = [];
if(typeof window.egw.getSessionItem('phpgwapi', 'egw_clipboard') != 'undefined')
{
let clipboard = JSON.parse(window.egw.getSessionItem('phpgwapi', 'egw_clipboard')) || {
type: [],
selected: []
};
if(clipboard.type.indexOf('file') >= 0)
{
for(let i = 0; i < clipboard.selected.length; i++)
{
let split = clipboard.selected[i].id.split('::');
if(split.shift() == 'filemanager')
{
const data = clipboard.selected[i].data ?? {};
clipboard_files.push({
value: split.join("::"),
name: data.name ?? clipboard.selected[i].id,
mime: data.mime,
isDir: data.is_dir ?? false,
path: data.path ?? split.join("::"),
downloadUrl: data.download_url
});
}
}
}
}
return clipboard_files;
}
customElements.define("et2-link-paste-dialog", Et2LinkPasteDialog);

View File

@ -24,6 +24,7 @@ import type {ValidationType} from "@lion/form-core/types/validate/ValidateMixinT
import {ManualMessage} from "../Validators/ManualMessage";
import {Et2Tabs} from "../Layout/Et2Tabs/Et2Tabs";
import {Et2VfsSelectButton} from "../Et2Vfs/Et2VfsSelectButton";
import {Et2LinkPasteDialog, getClipboardFiles} from "./Et2LinkPasteDialog";
/**
* Choose an existing entry, VFS file or local file, and link it to the current entry.
@ -96,7 +97,8 @@ export class Et2LinkTo extends Et2InputWidget(ScopedElementsMixin(FormControlMix
...super.scopedElements,
'et2-button': Et2Button,
'et2-link-entry': Et2LinkEntry,
'et2-vfs-select': Et2VfsSelectButton
'et2-vfs-select': Et2VfsSelectButton,
'et2-link-paste-dialog': Et2LinkPasteDialog
};
}
@ -139,11 +141,17 @@ export class Et2LinkTo extends Et2InputWidget(ScopedElementsMixin(FormControlMix
// otherwise it only gives an error on server-side
let method = null;
let method_id = null;
let pasteEnabled = false;
let pasteTooltip = ""
if(this.value && this.value.to_id && typeof this.value.to_id != 'object')
{
method = 'EGroupware\\Api\\Etemplate\\Widget\\Link::ajax_link_existing';
method_id = this.value.to_app + ':' + this.value.to_id;
let clipboard_files = getClipboardFiles();
pasteEnabled = clipboard_files.length > 0;
}
return html`
<slot name="before"></slot>
<et2-vfs-select
@ -159,7 +167,30 @@ export class Et2LinkTo extends Et2InputWidget(ScopedElementsMixin(FormControlMix
label=${this.egw().lang("copy")}></et2-button>
<et2-button slot="footer" image="move" id="move" style="order:3" noSubmit="true"
label=${this.egw().lang("move")}></et2-button>
</et2-vfs-select>`;
</et2-vfs-select>
<et2-vfs-select image="linkpaste" aria-label=${this.egw().lang("paste files")} noSubmit="true"
title=${this.egw().lang("paste files")}
?readonly=${this.readonly}
?disabled=${!pasteEnabled}
method=${method || nothing}
method-id=${method_id || nothing}
multiple
@click=${(e) =>
{
// Pre-select all files
let files = [];
getClipboardFiles().forEach(f => files.push(f.value));
e.target.firstElementChild.value = files;
e.target.firstElementChild.requestUpdate();
}}
.onchange=${this.handleVfsSelected}
>
<et2-link-paste-dialog open
title=${this.egw().lang("paste")}
.buttonLabel=${this.egw().lang("paste")}
></et2-link-paste-dialog>
</et2-vfs-select>
`;
}
/**
@ -435,6 +466,27 @@ export class Et2LinkTo extends Et2InputWidget(ScopedElementsMixin(FormControlMix
}
}
handleFilePaste([button, files])
{
if(!button)
{
return;
}
let values = {};
for(var i = 0; i < files.length; i++)
{
values['link:' + files[i]] = {
app: 'link',
id: files[i],
type: 'unknown',
icon: 'link',
remark: '',
title: files[i]
};
}
this._link_result(values);
}
handleVfsSelected(event, select : Et2VfsSelectButton)
{
let values = true;