mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-22 14:41:29 +01:00
WIP VFS Select: split off dialog and made button its own component for easier backward compatability
This commit is contained in:
parent
23ec5ee796
commit
379729daff
@ -90,8 +90,9 @@ export function inputBasicTests(before : Function, test_value : string, value_se
|
|||||||
// Shows as empty / no value
|
// Shows as empty / no value
|
||||||
let value = (<Element><unknown>element).querySelector(value_selector) || (<Element><unknown>element).shadowRoot.querySelector(value_selector);
|
let value = (<Element><unknown>element).querySelector(value_selector) || (<Element><unknown>element).shadowRoot.querySelector(value_selector);
|
||||||
assert.isDefined(value, "Bad value selector '" + value_selector + "'");
|
assert.isDefined(value, "Bad value selector '" + value_selector + "'");
|
||||||
|
assert.isNotNull(value, "Bad value selector '" + value_selector + "'");
|
||||||
|
|
||||||
assert.equal(value.textContent.trim(), "", "Displaying something when there is no value");
|
assert.equal(value.innerText.trim(), "", "Displaying something when there is no value");
|
||||||
if(element.multiple)
|
if(element.multiple)
|
||||||
{
|
{
|
||||||
assert.isEmpty(element.get_value());
|
assert.isEmpty(element.get_value());
|
||||||
|
@ -15,7 +15,7 @@ import {property} from "lit/decorators/property.js";
|
|||||||
import {state} from "lit/decorators/state.js";
|
import {state} from "lit/decorators/state.js";
|
||||||
import {classMap} from "lit/directives/class-map.js";
|
import {classMap} from "lit/directives/class-map.js";
|
||||||
import {repeat} from "lit/directives/repeat.js";
|
import {repeat} from "lit/directives/repeat.js";
|
||||||
import {FileInfo} from "./Et2VfsSelect";
|
import {FileInfo} from "./Et2VfsSelectDialog";
|
||||||
import {SlBreadcrumbItem} from "@shoelace-style/shoelace";
|
import {SlBreadcrumbItem} from "@shoelace-style/shoelace";
|
||||||
import {HasSlotController} from "../Et2Widget/slot";
|
import {HasSlotController} from "../Et2Widget/slot";
|
||||||
|
|
||||||
|
154
api/js/etemplate/Et2Vfs/Et2VfsSelectButton.ts
Normal file
154
api/js/etemplate/Et2Vfs/Et2VfsSelectButton.ts
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/**
|
||||||
|
* EGroupware eTemplate2 - Button to open a vfs select dialog
|
||||||
|
*
|
||||||
|
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
|
||||||
|
* @package api
|
||||||
|
* @link https://www.egroupware.org
|
||||||
|
* @author Nathan Gray
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Et2InputWidget} from "../Et2InputWidget/Et2InputWidget";
|
||||||
|
import {html, LitElement, nothing} from "lit";
|
||||||
|
import {HasSlotController} from "../Et2Widget/slot";
|
||||||
|
import {property} from "lit/decorators/property.js";
|
||||||
|
import {FileInfo} from "./Et2VfsSelectDialog";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Button to open a file selection dialog, and return the selected path(s) as a value
|
||||||
|
* @since 23.1
|
||||||
|
*
|
||||||
|
* @dependency et2-vfs-select-dialog
|
||||||
|
* @dependency et2-button
|
||||||
|
*
|
||||||
|
* @slot prefix - Before the toolbar
|
||||||
|
* @slot suffix - Like prefix, but after
|
||||||
|
*
|
||||||
|
* @event change - Emitted when the control's value changes.
|
||||||
|
*
|
||||||
|
* @csspart form-control-input - The textbox's wrapper.
|
||||||
|
* @csspart form-control-help-text - The help text's wrapper.
|
||||||
|
* @csspart prefix - The container that wraps the prefix slot.
|
||||||
|
* @csspart suffix - The container that wraps the suffix slot.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class Et2VfsSelectButton extends Et2InputWidget(LitElement)
|
||||||
|
{
|
||||||
|
/** Icon for the button */
|
||||||
|
@property() image : string;
|
||||||
|
|
||||||
|
/** Currently selected files */
|
||||||
|
@property() value : string[] | FileInfo[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The dialog’s label as displayed in the header.
|
||||||
|
* You should always include a relevant label, as it is required for proper accessibility.
|
||||||
|
*/
|
||||||
|
@property() title : string = "Select";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog mode
|
||||||
|
* Quickly sets button label, multiple, selection and for "select-dir", mime-type
|
||||||
|
**/
|
||||||
|
@property({type: String}) mode : "open" | "open-multiple" | "saveas" | "select-dir";
|
||||||
|
|
||||||
|
/** Button label */
|
||||||
|
@property({type: String}) buttonLabel : string = "Select";
|
||||||
|
|
||||||
|
/** Provide a suggested filename for saving */
|
||||||
|
@property() filename : string = "";
|
||||||
|
|
||||||
|
/** Allow selecting multiple files */
|
||||||
|
@property({type: Boolean}) multiple = false;
|
||||||
|
|
||||||
|
/** Start path in VFS. Leave unset to use the last used path. */
|
||||||
|
@property() path : string = "";
|
||||||
|
|
||||||
|
/** Limit display to the given mime-type */
|
||||||
|
@property() mime : string | string[] | RegExp = "";
|
||||||
|
|
||||||
|
/** Server side callback to process selected value(s) in
|
||||||
|
* app.class.method or class::method format. The first parameter will
|
||||||
|
* be Method ID, the second the file list. 'download' is reserved and it
|
||||||
|
* means it should use download_baseUrl instead of path in value (no method
|
||||||
|
* will be actually executed).
|
||||||
|
*/
|
||||||
|
@property() method : string = "";
|
||||||
|
/** ID passed to method */
|
||||||
|
@property() method_id : string;
|
||||||
|
|
||||||
|
protected readonly hasSlotController = new HasSlotController(this, '');
|
||||||
|
|
||||||
|
//private _dialog : Et2VfsSelectDialog = this.shadowRoot.querySelector("et2-vfs-select-dialog") ?? null;
|
||||||
|
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
this.handleClick = this.handleClick.bind(this);
|
||||||
|
this.handleDialogClose = this.handleDialogClose.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected handleClick(event)
|
||||||
|
{
|
||||||
|
const dialog : any = this.shadowRoot.querySelector("et2-vfs-select-dialog");
|
||||||
|
if(dialog && typeof dialog.show == "function")
|
||||||
|
{
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected handleDialogClose(event)
|
||||||
|
{
|
||||||
|
debugger;
|
||||||
|
this.value = dialog.value ?? [];
|
||||||
|
|
||||||
|
if(this.method && this.method == "download")
|
||||||
|
{
|
||||||
|
// download
|
||||||
|
}
|
||||||
|
else if(this.method)
|
||||||
|
{
|
||||||
|
this.sendFiles();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected sendFiles()
|
||||||
|
|
||||||
|
protected dialogTemplate()
|
||||||
|
{
|
||||||
|
return html`
|
||||||
|
<et2-vfs-select-dialog
|
||||||
|
.title=${this.title ?? nothing}
|
||||||
|
.value=${this.value ?? nothing}
|
||||||
|
.mode=${this.mode ?? nothing}
|
||||||
|
.multiple=${this.multiple ?? nothing}
|
||||||
|
.path=${this.path ?? nothing}
|
||||||
|
.filename=${this.filename ?? nothing}
|
||||||
|
.mime=${this.mime ?? nothing}
|
||||||
|
.buttonLabel=${this.buttonLabel ?? nothing}
|
||||||
|
@close=${this.handleDialogClose}
|
||||||
|
>
|
||||||
|
|
||||||
|
</et2-vfs-select-dialog>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render()
|
||||||
|
{
|
||||||
|
const hasUserDialog = this.hasSlotController.test("[default]");
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<et2-button image=${this.image || "filemanager/navbar"}
|
||||||
|
?disabled=${this.disabled}
|
||||||
|
?readonly=${this.readonly}
|
||||||
|
.noSubmit=${true}
|
||||||
|
@click=${this.handleClick}
|
||||||
|
>
|
||||||
|
</et2-button>
|
||||||
|
<slot>${hasUserDialog ? nothing : this.dialogTemplate()}</slot>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("et2-vfs-select", Et2VfsSelectButton);
|
@ -23,6 +23,7 @@ import {HasSlotController} from "../Et2Widget/slot";
|
|||||||
import {IegwAppLocal} from "../../jsapi/egw_global";
|
import {IegwAppLocal} from "../../jsapi/egw_global";
|
||||||
import {Et2Select} from "../Et2Select/Et2Select";
|
import {Et2Select} from "../Et2Select/Et2Select";
|
||||||
import {Et2VfsSelectRow} from "./Et2VfsSelectRow";
|
import {Et2VfsSelectRow} from "./Et2VfsSelectRow";
|
||||||
|
import {Et2VfsPath} from "./Et2VfsPath";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @summary Select files (including directories) from the VFS
|
* @summary Select files (including directories) from the VFS
|
||||||
@ -32,7 +33,7 @@ import {Et2VfsSelectRow} from "./Et2VfsSelectRow";
|
|||||||
* @dependency et2-select
|
* @dependency et2-select
|
||||||
* @dependency et2-vfs-select-row
|
* @dependency et2-vfs-select-row
|
||||||
*
|
*
|
||||||
* @slot title - Optional additions to title. Works best with `et2-button-icon`.
|
* @slot title - Optional additions to title.
|
||||||
* @slot toolbar - Toolbar containing controls for search & navigation
|
* @slot toolbar - Toolbar containing controls for search & navigation
|
||||||
* @slot prefix - Before the toolbar
|
* @slot prefix - Before the toolbar
|
||||||
* @slot suffix - Like prefix, but after
|
* @slot suffix - Like prefix, but after
|
||||||
@ -48,7 +49,7 @@ import {Et2VfsSelectRow} from "./Et2VfsSelectRow";
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export class Et2VfsSelect extends Et2InputWidget(LitElement) implements SearchMixinInterface
|
export class Et2VfsSelectDialog extends Et2InputWidget(LitElement) implements SearchMixinInterface
|
||||||
{
|
{
|
||||||
static get styles()
|
static get styles()
|
||||||
{
|
{
|
||||||
@ -145,7 +146,7 @@ export class Et2VfsSelect extends Et2InputWidget(LitElement) implements SearchMi
|
|||||||
|
|
||||||
get _searchNode() : HTMLInputElement { return this.shadowRoot.querySelector("#search");}
|
get _searchNode() : HTMLInputElement { return this.shadowRoot.querySelector("#search");}
|
||||||
|
|
||||||
get _pathNode() : HTMLElement { return this.shadowRoot.querySelector("#path");}
|
get _pathNode() : Et2VfsPath { return this.shadowRoot.querySelector("#path");}
|
||||||
|
|
||||||
get _listNode() : HTMLElement { return this.shadowRoot.querySelector("#listbox");}
|
get _listNode() : HTMLElement { return this.shadowRoot.querySelector("#listbox");}
|
||||||
|
|
||||||
@ -194,7 +195,7 @@ export class Et2VfsSelect extends Et2InputWidget(LitElement) implements SearchMi
|
|||||||
mime: this.mime || null,
|
mime: this.mime || null,
|
||||||
name: this.title
|
name: this.title
|
||||||
};
|
};
|
||||||
return this.egw().request(this.egw().link(this.egw().ajaxUrl(this.egw().decodePath(Et2VfsSelect.SERVER_URL))),
|
return this.egw().request(this.egw().link(this.egw().ajaxUrl(this.egw().decodePath(Et2VfsSelectDialog.SERVER_URL))),
|
||||||
[content, attrs]).then((results) =>
|
[content, attrs]).then((results) =>
|
||||||
{
|
{
|
||||||
debugger;
|
debugger;
|
||||||
@ -579,7 +580,7 @@ export class Et2VfsSelect extends Et2InputWidget(LitElement) implements SearchMi
|
|||||||
// -1 because we're in keyDown handler, and value is from _before_ this key was pressed
|
// -1 because we're in keyDown handler, and value is from _before_ this key was pressed
|
||||||
if(this._searchNode.value.length - 1 > 0)
|
if(this._searchNode.value.length - 1 > 0)
|
||||||
{
|
{
|
||||||
this._searchTimeout = window.setTimeout(() => {this.startSearch()}, Et2VfsSelect.SEARCH_TIMEOUT);
|
this._searchTimeout = window.setTimeout(() => {this.startSearch()}, Et2VfsSelectDialog.SEARCH_TIMEOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,7 +606,7 @@ export class Et2VfsSelect extends Et2InputWidget(LitElement) implements SearchMi
|
|||||||
@click=${() => this.setPath("/apps/favorites")}
|
@click=${() => this.setPath("/apps/favorites")}
|
||||||
></et2-button>
|
></et2-button>
|
||||||
<et2-select id="app" emptyLabel="Applications" noLang="1"
|
<et2-select id="app" emptyLabel="Applications" noLang="1"
|
||||||
.select_options=${this.appList}
|
.select_options=${this._appList}
|
||||||
@change=${(e) => this.setPath("/apps/" + e.target.value)}
|
@change=${(e) => this.setPath("/apps/" + e.target.value)}
|
||||||
>
|
>
|
||||||
</et2-select>
|
</et2-select>
|
||||||
@ -733,10 +734,10 @@ export class Et2VfsSelect extends Et2InputWidget(LitElement) implements SearchMi
|
|||||||
<div
|
<div
|
||||||
part="path"
|
part="path"
|
||||||
>
|
>
|
||||||
<input id="path"
|
<et2-vfs-path id="path"
|
||||||
value=${this.path}
|
.value=${this.path}
|
||||||
@onchange=${this.startSearch}
|
@change=${() => {this.setPath(this._pathNode.value)}}
|
||||||
/>
|
></et2-vfs-path>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
id="listbox"
|
id="listbox"
|
||||||
@ -784,7 +785,7 @@ export class Et2VfsSelect extends Et2InputWidget(LitElement) implements SearchMi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
customElements.define("et2-vfs-select", Et2VfsSelect);
|
customElements.define("et2-vfs-select-dialog", Et2VfsSelectDialog);
|
||||||
|
|
||||||
export interface FileInfo
|
export interface FileInfo
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
import {html, LitElement} from "lit";
|
import {html, LitElement} from "lit";
|
||||||
import {Et2Widget} from "../Et2Widget/Et2Widget";
|
import {Et2Widget} from "../Et2Widget/Et2Widget";
|
||||||
import {FileInfo} from "./Et2VfsSelect";
|
import {FileInfo} from "./Et2VfsSelectDialog";
|
||||||
import {property} from "lit/decorators/property.js";
|
import {property} from "lit/decorators/property.js";
|
||||||
import {state} from "lit/decorators/state.js";
|
import {state} from "lit/decorators/state.js";
|
||||||
import {classMap} from "lit/directives/class-map.js";
|
import {classMap} from "lit/directives/class-map.js";
|
||||||
|
@ -98,7 +98,8 @@ import "./Layout/Et2Split/Et2Split";
|
|||||||
import "./Layout/RowLimitedMixin";
|
import "./Layout/RowLimitedMixin";
|
||||||
import "./Et2Vfs/Et2VfsMime";
|
import "./Et2Vfs/Et2VfsMime";
|
||||||
import "./Et2Vfs/Et2VfsPath";
|
import "./Et2Vfs/Et2VfsPath";
|
||||||
import "./Et2Vfs/Et2VfsSelect";
|
import "./Et2Vfs/Et2VfsSelectButton";
|
||||||
|
import "./Et2Vfs/Et2VfsSelectDialog";
|
||||||
import "./Et2Vfs/Et2VfsSelectRow";
|
import "./Et2Vfs/Et2VfsSelectRow";
|
||||||
import "./Et2Vfs/Et2VfsUid";
|
import "./Et2Vfs/Et2VfsUid";
|
||||||
import "./Et2Textbox/Et2Password";
|
import "./Et2Textbox/Et2Password";
|
||||||
|
Loading…
Reference in New Issue
Block a user