* Api: Add some options to merge: merge individually, merge & link, merge & email, download

This commit is contained in:
nathan
2024-05-17 15:56:56 -06:00
parent 50dfa86150
commit ff94af1f7d
6 changed files with 447 additions and 88 deletions

View File

@@ -0,0 +1,145 @@
import {customElement} from "lit/decorators/custom-element.js";
import {Et2Widget} from "../Et2Widget/Et2Widget";
import {css, html, LitElement} from "lit";
import shoelace from "../Styles/shoelace";
import {Et2VfsSelectDialog} from "../Et2Vfs/Et2VfsSelectDialog";
import {property} from "lit/decorators/property.js";
import {Et2Dialog} from "./Et2Dialog";
import {state} from "lit/decorators/state.js";
@customElement("et2-merge-dialog")
export class Et2MergeDialog extends Et2Widget(LitElement)
{
static get styles()
{
return [
super.styles,
shoelace,
css`
:host {
}
et2-details::part(content) {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
`,
];
}
@property()
application : string
@property()
path : string
// Can't merge "& send" if no email template selected
@state()
canEmail = false;
private get dialog() : Et2VfsSelectDialog
{
return <Et2VfsSelectDialog><unknown>this.shadowRoot.querySelector("et2-vfs-select-dialog");
}
public async getComplete() : Promise<{
documents : { path : string, mime : string }[],
options : { [key : string] : string | boolean }
}>
{
await this.updateComplete;
const [button, value] = await this.dialog.getComplete();
if(!button)
{
return {documents: [], options: this.optionValues};
}
const documents = [];
Array.from(<ArrayLike<string>>value).forEach(value =>
{
const fileInfo = this.dialog.fileInfo(value) ?? [];
documents.push({path: value, mime: fileInfo.mime})
});
let options = this.optionValues;
if(button == Et2Dialog.OK_BUTTON)
{
options.download = true;
}
return {documents: documents, options: options};
}
public get optionValues()
{
const optionValues = {
download: false
};
this.dialog.querySelectorAll(":not([slot='footer'])").forEach(e =>
{
if(typeof e.getValue == "function")
{
optionValues[e.getAttribute("id")] = e.getValue() === "true" ? true : e.getValue();
}
});
return optionValues;
}
private option(component_name)
{
return this.dialog.querySelector("et2-details > [id='" + component_name + "']");
}
protected handleFileSelect(event)
{
// Disable PDF checkbox for only email files selected
let canPDF = false;
const oldCanEmail = this.canEmail;
this.canEmail = false;
this.dialog.value.forEach(path =>
{
if(this.dialog.fileInfo(path).mime !== "message/rfc822")
{
canPDF = true;
}
else
{
this.canEmail = true;
}
});
this.option("pdf").disabled = !canPDF;
this.requestUpdate("canEmail", oldCanEmail);
}
render()
{
return html`
<et2-vfs-select-dialog
class=egw_app_merge_document"
path=${this.path}
multiple="true"
buttonLabel="Download"
.title="${this.egw().lang("Insert in document")}"
.open=${true}
@et2-select=${this.handleFileSelect}
>
${this.canEmail ?
html`
<et2-button slot="footer" id="send" label="Merge &amp; send" image="mail"
noSubmit="true"></et2-button> ` :
html`
<et2-button slot="footer" id="send" label="Merge" image="etemplate/merge"
noSubmit="true"></et2-button>`
}
<et2-details>
<span slot="summary">${this.egw().lang("Merge options")}</span>
<et2-checkbox label="Save as PDF" id="pdf"></et2-checkbox>
<et2-checkbox id="link"
label="${this.egw().lang("Link to each %1", <string>this.egw().link_get_registry(this.application, "entry") || this.egw().lang("entry"))}"
></et2-checkbox>
<et2-checkbox label="Merge individually" id="individual"></et2-checkbox>
</et2-details>
</et2-vfs-select-dialog>`;
}
}

View File

@@ -49,6 +49,7 @@ import './Et2Date/Et2DateTimeReadonly';
import './Et2Date/Et2DateTimeToday';
import './Et2Description/Et2Description';
import './Et2Dialog/Et2Dialog';
import './Et2Dialog/Et2MergeDialog';
import './Et2DropdownButton/Et2DropdownButton';
import './Et2Email/Et2Email';
import './Expose/Et2ImageExpose';

View File

@@ -17,13 +17,14 @@ import {et2_createWidget} from "../etemplate/et2_core_widget";
import type {IegwAppLocal} from "./egw_global";
import Sortable from 'sortablejs/modular/sortable.complete.esm.js';
import {et2_valueWidget} from "../etemplate/et2_core_valueWidget";
import {nm_action} from "../etemplate/et2_extension_nextmatch_actions";
import {fetchAll, nm_action} from "../etemplate/et2_extension_nextmatch_actions";
import {Et2Dialog} from "../etemplate/Et2Dialog/Et2Dialog";
import {Et2Favorites} from "../etemplate/Et2Favorites/Et2Favorites";
import {loadWebComponent} from "../etemplate/Et2Widget/Et2Widget";
import {Et2VfsSelectDialog} from "../etemplate/Et2Vfs/Et2VfsSelectDialog";
import {Et2Checkbox} from "../etemplate/Et2Checkbox/Et2Checkbox";
import type {EgwAction} from "../egw_action/EgwAction";
import {Et2MergeDialog} from "../etemplate/Et2Dialog/Et2MergeDialog";
import {EgwActionObject} from "../egw_action/EgwActionObject";
import type {Et2Details} from "../etemplate/Layout/Et2Details/Et2Details";
/**
* Type for push-message
@@ -804,7 +805,6 @@ export abstract class EgwApp
// Find what we need
let nm = null;
let action = _action;
let as_pdf = null;
// Find Select all
while(nm == null && action.parent != null)
@@ -824,28 +824,76 @@ export abstract class EgwApp
let split = _selected[i].id.split("::");
ids.push(split[1]);
}
let document = await this._getMergeDocument(nm?.getInstanceManager(), _action);
if(!document.document)
let document = await this._getMergeDocument(nm?.getInstanceManager(), _action, _selected);
if(!document.documents || document.documents.length == 0)
{
return;
}
let vars = {
..._action.data.merge_data,
document: document.document,
pdf: document.pdf ?? false,
options: document.options,
select_all: all,
id: ids
};
if(document.mime == "message/rfc822")
if(document.options.link)
{
vars.options.app = this.appname;
}
// Just one file, an email - merge & edit or merge & send
if(document.documents.length == 1 && document.documents[0].mime == "message/rfc822")
{
vars.document = document.documents[0].path;
return this._mergeEmail(_action.clone(), vars);
}
else
{
vars.id = JSON.stringify(ids);
vars.document = document.documents.map(f => f.path);
}
if(document.documents.length == 1 && !document.options.individual)
{
// Only 1 document, we can open it
vars.id = JSON.stringify(ids);
this.egw.open_link(this.egw.link('/index.php', vars), '_blank');
}
else
{
// Multiple files, or merging individually - will result in multiple documents that we can't just open
vars.menuaction = vars.menuaction.replace("merge_entries", "ajax_merge_multiple");
vars.menuaction += "&merge=" + vars.merge;
let mergedFiles = [];
// Check for an email template - all other files will be merged & attached
let email = document.documents.find(f => f.mime == "message/rfc822");
// Can we do this in one, or do we have to split it up for feedback?
if(!vars.options.individual && !email)
{
// Handle it all on the server in one request
mergedFiles = await this.egw.request(vars.menuaction, [vars.id, vars.document, vars.options]);
}
else
{
// Merging documents, merge email, attach to email, send.
// Handled like this here so we can give feedback, server could do it all in one request
let idGroup = await new Promise<string[]>((resolve) =>
{
if(all)
{
fetchAll(ids, nm, idsArr => resolve(vars.options.individual ? idsArr : [idsArr]));
}
else
{
resolve(vars.options.individual ? ids : [ids])
}
});
Et2Dialog.long_task(null /*done*/, this.egw.lang("Merging"),
email ? this.egw.lang("Merging into %1 and sending", email.path) : this.egw.lang("Merging into %1", vars.document.join(", ")),
vars.menuaction,
idGroup.map((ids) => {return [Array.isArray(ids) ? ids : [ids], vars.document, vars.options];}), this.egw
);
}
}
this.egw.open_link(this.egw.link('/index.php', vars), '_blank');
}
/**
@@ -855,10 +903,9 @@ export abstract class EgwApp
* @protected
*/
protected _getMergeDocument(et2?, action? : EgwAction) : Promise<{
document : string,
pdf : boolean,
mime : string
protected _getMergeDocument(et2?, action? : EgwAction, selected? : EgwActionObject[]) : Promise<{
documents : { path : string; mime : string }[];
options : { [p : string] : string | boolean }
}>
{
let path = action?.data?.merge_data?.directory ?? "";
@@ -871,51 +918,28 @@ export abstract class EgwApp
d = "/" + d;
}
});
let fileSelect = <Et2VfsSelectDialog><unknown>loadWebComponent('et2-vfs-select-dialog', {
class: "egw_app_merge_document",
title: this.egw.lang("Insert in document"),
mode: "open",
path: path ?? dirs?.pop() ?? "",
open: true
let fileSelect = <Et2MergeDialog><unknown>loadWebComponent('et2-merge-dialog', {
application: this.appname,
path: dirs.pop() || ""
}, et2.widgetContainer);
if(!et2)
{
document.body.append(fileSelect);
}
let pdf = <Et2Checkbox><unknown>loadWebComponent("et2-checkbox", {
slot: "footer",
label: "As PDF"
}, fileSelect);
// Disable PDF checkbox for emails
fileSelect.addEventListener("et2-select", e =>
// Start details open when you have multiple selected
fileSelect.updateComplete.then(() =>
{
let canPDF = true;
fileSelect.value.forEach(path =>
{
if(fileSelect.fileInfo(path).mime == "message/rfc822")
{
canPDF = false;
}
});
pdf.disabled = !canPDF;
// @ts-ignore
(<Et2Details>fileSelect.shadowRoot.querySelector('et2-details')).open = selected.length > 1;
});
return fileSelect.getComplete().then((values) =>
{
if(!values[0])
{
return {document: '', pdf: false, mime: ""};
}
// Remove when done
fileSelect.getComplete().then(() => {fileSelect.remove();});
const value = values[1].pop() ?? "";
const fileInfo = fileSelect.fileInfo(value) ?? {};
fileSelect.remove();
return {document: value, pdf: pdf.getValue(), mime: fileInfo.mime ?? ""};
});
return fileSelect.getComplete();
}
/**
* Merging into an email
* Merge into an email, then open it in compose for a single, send directly for multiple
*
* @param {object} data
* @protected