mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-25 09:23:28 +01:00
Collabora: Get insert placeholder dialog working again
This commit is contained in:
parent
59da89fe8b
commit
3ce5aebe12
160
api/js/etemplate/Et2Select/Et2Listbox.ts
Normal file
160
api/js/etemplate/Et2Select/Et2Listbox.ts
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import {SlMenu, SlMenuItem} from "@shoelace-style/shoelace";
|
||||||
|
import {Et2widgetWithSelectMixin} from "./Et2WidgetWithSelectMixin";
|
||||||
|
import {RowLimitedMixin} from "../Layout/RowLimitedMixin";
|
||||||
|
import shoelace from "../Styles/shoelace";
|
||||||
|
import {css, html, TemplateResult} from "@lion/core";
|
||||||
|
import {SelectOption} from "./FindSelectOptions";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A selectbox that shows more than one row at a time
|
||||||
|
*
|
||||||
|
* Set rows attribute to adjust how many rows are visible at once
|
||||||
|
*
|
||||||
|
* Use Et2Selectbox in most cases, it's better.
|
||||||
|
*/
|
||||||
|
export class Et2Listbox extends RowLimitedMixin(Et2widgetWithSelectMixin(SlMenu))
|
||||||
|
{
|
||||||
|
|
||||||
|
static get styles()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
// Parent (SlMenu) returns a single cssResult, not an array
|
||||||
|
shoelace,
|
||||||
|
super.styles,
|
||||||
|
css`
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
--icon-width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(img), img {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
/* Get rid of padding before/after options */
|
||||||
|
padding: 0px;
|
||||||
|
|
||||||
|
/* No horizontal scrollbar, even if options are long */
|
||||||
|
overflow-x: clip;
|
||||||
|
}
|
||||||
|
/* Ellipsis when too small */
|
||||||
|
sl-menu-item.menu-item__label {
|
||||||
|
display: block;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
/* This is usually not used due to flex, but is the basis for ellipsis calculation */
|
||||||
|
width: 10ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host([rows])::part(base) {
|
||||||
|
max-height: calc(var(--rows, 5) * 1.9rem);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get properties()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
...super.properties,
|
||||||
|
/**
|
||||||
|
* Toggle between single and multiple selection
|
||||||
|
*/
|
||||||
|
multiple: {
|
||||||
|
type: Boolean,
|
||||||
|
reflect: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(...args : any[])
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this.handleSelect = this.handleSelect.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback()
|
||||||
|
{
|
||||||
|
super.connectedCallback();
|
||||||
|
|
||||||
|
this.addEventListener("sl-select", this.handleSelect);
|
||||||
|
|
||||||
|
this.updateComplete.then(() =>
|
||||||
|
{
|
||||||
|
this.addEventListener("sl-change", this._triggerChange);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an item was selected
|
||||||
|
*
|
||||||
|
* Toggle the checkmark and fire the changed event
|
||||||
|
*
|
||||||
|
* @param {MouseEvent} event
|
||||||
|
*/
|
||||||
|
handleSelect(event : CustomEvent)
|
||||||
|
{
|
||||||
|
let item = event.detail?.item;
|
||||||
|
if(!item)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.multiple)
|
||||||
|
{
|
||||||
|
this.getAllItems().forEach((i) => i.checked = false);
|
||||||
|
item.checked = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.checked = !item.checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.dispatchEvent(new Event("change"));
|
||||||
|
}
|
||||||
|
|
||||||
|
get value()
|
||||||
|
{
|
||||||
|
let value = this.getAllItems()
|
||||||
|
.filter((item) => item.checked)
|
||||||
|
.map((item) => item.value);
|
||||||
|
return this.multiple ? value : value.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
set value(new_value : String[] | String)
|
||||||
|
{
|
||||||
|
const oldValue = this.value;
|
||||||
|
if(typeof new_value == "string")
|
||||||
|
{
|
||||||
|
new_value = [new_value]
|
||||||
|
}
|
||||||
|
this.getAllItems().forEach((item) => item.checked = false);
|
||||||
|
for(let i = 0; i < new_value.length; i++)
|
||||||
|
{
|
||||||
|
const value = new_value[i];
|
||||||
|
(<SlMenuItem>this.querySelector("[value='" + value + "']")).checked = true;
|
||||||
|
}
|
||||||
|
this.requestUpdate("value", oldValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
_optionTemplate(option : SelectOption) : TemplateResult
|
||||||
|
{
|
||||||
|
let icon = option.icon ? html`
|
||||||
|
<et2-image slot="prefix" part="icon" style="width: var(--icon-width)"
|
||||||
|
src="${option.icon}"></et2-image>` : "";
|
||||||
|
|
||||||
|
// Tag used must match this.optionTag, but you can't use the variable directly.
|
||||||
|
// Pass option along so SearchMixin can grab it if needed
|
||||||
|
return html`
|
||||||
|
<sl-menu-item value="${option.value}"
|
||||||
|
title="${!option.title || this.noLang ? option.title : this.egw().lang(option.title)}"
|
||||||
|
class="${option.class}" .option=${option}>
|
||||||
|
${icon}
|
||||||
|
${this.noLang ? option.label : this.egw().lang(option.label)}
|
||||||
|
</sl-menu-item>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("et2-listbox", Et2Listbox);
|
@ -173,6 +173,15 @@ export class et2_placeholder_select extends et2_inputWidget
|
|||||||
this._do_insert_callback(submit_value);
|
this._do_insert_callback(submit_value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if(submit_button_id == 'cancel')
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Keep dialog open
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
|
|
||||||
this.dialog = new Et2Dialog(this.egw());
|
this.dialog = new Et2Dialog(this.egw());
|
||||||
@ -448,12 +457,12 @@ export class et2_placeholder_snippet_select extends et2_placeholder_select
|
|||||||
app.onchange = (node, widget) =>
|
app.onchange = (node, widget) =>
|
||||||
{
|
{
|
||||||
entry.set_value({app: widget.get_value()});
|
entry.set_value({app: widget.get_value()});
|
||||||
placeholder_list.set_select_options(this._get_placeholders(app.get_value(), "addresses"));
|
placeholder_list.set_select_options(this._get_placeholders(app.value, "addresses"));
|
||||||
}
|
}
|
||||||
placeholder_list.onchange = this._on_placeholder_select.bind(this);
|
placeholder_list.onchange = this._on_placeholder_select.bind(this);
|
||||||
entry.onchange = this._on_placeholder_select.bind(this);
|
entry.onchange = this._on_placeholder_select.bind(this);
|
||||||
|
|
||||||
app.set_value(app.get_value());
|
app.set_value(app.value);
|
||||||
this._on_placeholder_select();
|
this._on_placeholder_select();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,16 +472,22 @@ export class et2_placeholder_snippet_select extends et2_placeholder_select
|
|||||||
*/
|
*/
|
||||||
_on_placeholder_select()
|
_on_placeholder_select()
|
||||||
{
|
{
|
||||||
|
let app = <Et2Select><unknown>this.dialog.template.widgetContainer.getDOMWidgetById("app");
|
||||||
let entry = <Et2LinkEntry><unknown>this.dialog.template.widgetContainer.getDOMWidgetById("entry");
|
let entry = <Et2LinkEntry><unknown>this.dialog.template.widgetContainer.getDOMWidgetById("entry");
|
||||||
let placeholder_list = <Et2Select><unknown>this.dialog.template.widgetContainer.getDOMWidgetById("placeholder_list");
|
let placeholder_list = <Et2Select><unknown>this.dialog.template.widgetContainer.getDOMWidgetById("placeholder_list");
|
||||||
let preview_content = <Et2Description><unknown>this.dialog.template.widgetContainer.getDOMWidgetById("preview_content");
|
let preview_content = <Et2Description><unknown>this.dialog.template.widgetContainer.getDOMWidgetById("preview_content");
|
||||||
|
let placeholder = "";
|
||||||
|
if(app && app.value)
|
||||||
|
{
|
||||||
|
placeholder = Object.keys(et2_placeholder_snippet_select.placeholders[<string>app.value]["addresses"])[<string>placeholder_list.value];
|
||||||
|
}
|
||||||
|
|
||||||
if(placeholder_list.value && entry.get_value())
|
if(placeholder && entry.get_value())
|
||||||
{
|
{
|
||||||
// Show the selected placeholder replaced with value from the selected entry
|
// Show the selected placeholder replaced with value from the selected entry
|
||||||
this.egw().json(
|
this.egw().json(
|
||||||
'EGroupware\\Api\\Etemplate\\Widget\\Placeholder::ajax_fill_placeholders',
|
'EGroupware\\Api\\Etemplate\\Widget\\Placeholder::ajax_fill_placeholders',
|
||||||
[placeholder_list.value, {app: "addressbook", id: entry.get_value()}],
|
[placeholder, {app: "addressbook", id: entry.get_value()}],
|
||||||
function(_content)
|
function(_content)
|
||||||
{
|
{
|
||||||
if(!_content)
|
if(!_content)
|
||||||
@ -525,11 +540,11 @@ export class et2_placeholder_snippet_select extends et2_placeholder_select
|
|||||||
_get_placeholders(appname : string, group : string)
|
_get_placeholders(appname : string, group : string)
|
||||||
{
|
{
|
||||||
let options = [];
|
let options = [];
|
||||||
Object.keys(et2_placeholder_snippet_select.placeholders[appname][group]).map((key) =>
|
Object.keys(et2_placeholder_snippet_select.placeholders[appname][group]).map((key, index) =>
|
||||||
{
|
{
|
||||||
options.push(
|
options.push(
|
||||||
{
|
{
|
||||||
value: key,
|
value: index,
|
||||||
label: this.egw().lang(et2_placeholder_snippet_select.placeholders[appname][group][key])
|
label: this.egw().lang(et2_placeholder_snippet_select.placeholders[appname][group][key])
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -66,6 +66,7 @@ import './Et2Nextmatch/Headers/AccountFilterHeader';
|
|||||||
import './Et2Nextmatch/Headers/CustomFilterHeader';
|
import './Et2Nextmatch/Headers/CustomFilterHeader';
|
||||||
import './Et2Nextmatch/Headers/EntryHeader';
|
import './Et2Nextmatch/Headers/EntryHeader';
|
||||||
import './Et2Nextmatch/Headers/FilterHeader';
|
import './Et2Nextmatch/Headers/FilterHeader';
|
||||||
|
import './Et2Select/Et2Listbox';
|
||||||
import './Et2Select/Et2Select';
|
import './Et2Select/Et2Select';
|
||||||
import './Et2Select/Et2SelectAccount';
|
import './Et2Select/Et2SelectAccount';
|
||||||
import './Et2Select/Et2SelectCategory';
|
import './Et2Select/Et2SelectCategory';
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
<select id="group"/>
|
<select id="group"/>
|
||||||
|
|
||||||
</vbox>
|
</vbox>
|
||||||
<select id="placeholder_list" rows="10"/>
|
<et2-listbox id="placeholder_list" rows="10"/>
|
||||||
</hbox>
|
</hbox>
|
||||||
<hbox class="preview">
|
<hbox class="preview">
|
||||||
<description id="preview_placeholder"/>
|
<description id="preview_placeholder"/>
|
||||||
<button background_image="true" id="insert_placeholder" label="Insert" statustext="Insert placeholder"
|
<button background_image="true" id="insert_placeholder" label="Insert" statustext="Insert placeholder"
|
||||||
image="export"></button>
|
align="right" image="export"></button>
|
||||||
</hbox>
|
</hbox>
|
||||||
<hrule/>
|
<hrule/>
|
||||||
<link-entry id="entry" label="Preview with entry"/>
|
<link-entry id="entry" label="Preview with entry"/>
|
||||||
@ -23,6 +23,7 @@
|
|||||||
<description id="preview_content"/>
|
<description id="preview_content"/>
|
||||||
<buttononly background_image="true" id="insert_content" label="Insert"
|
<buttononly background_image="true" id="insert_content" label="Insert"
|
||||||
statustext="Insert merged content"
|
statustext="Insert merged content"
|
||||||
|
align="right"
|
||||||
image="export"></buttononly>
|
image="export"></buttononly>
|
||||||
</hbox>
|
</hbox>
|
||||||
</vbox>
|
</vbox>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<vbox id="outer_box">
|
<vbox id="outer_box">
|
||||||
<vbox id="selects">
|
<vbox id="selects">
|
||||||
<select id="app"/>
|
<select id="app"/>
|
||||||
<select id="placeholder_list"/>
|
<et2-listbox id="placeholder_list" rows="10"/>
|
||||||
</vbox>
|
</vbox>
|
||||||
<hrule/>
|
<hrule/>
|
||||||
<link-entry id="entry" label="Select entry" only_app="addressbook"/>
|
<link-entry id="entry" label="Select entry" only_app="addressbook"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user