Reconfigure Link to include icon & comment for easier drag & drop

This commit is contained in:
nathan 2023-05-17 16:55:05 -06:00
parent e4bdbe256a
commit 8da10cf863
4 changed files with 153 additions and 101 deletions

View File

@ -11,7 +11,7 @@
import {ExposeMixin, ExposeValue} from "../Expose/ExposeMixin";
import {css, html, LitElement} from "@lion/core";
import {css, html, LitElement, TemplateResult} from "@lion/core";
import {Et2Widget} from "../Et2Widget/Et2Widget";
import {et2_IDetachedDOM} from "../et2_core_interfaces";
@ -22,6 +22,7 @@ import {et2_IDetachedDOM} from "../et2_core_interfaces";
* You can set it directly in the properties (application, entryId) or use set_value() to
* pass an object {app: string, id: string, [title: string]} or string in the form <application>::<ID>.
* If title is not specified, it will be fetched using framework's egw.link_title()
*
*/
// @ts-ignore TypeScript says there's something wrong with types
@ -32,20 +33,37 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
return [
...super.styles,
css`
:host {
:host {
display: block;
cursor: pointer;
}
:host:hover {
}
.link {
display: flex;
gap: 0.5rem;
}
.link__title {
flex: 2 1 50%;
}
.link__remark {
flex: 1 1 50%
}
:host:hover {
text-decoration: underline
}
/** Style based on parent **/
:host-context(et2-link-string) {
}
/** Style based on parent **/
:host(et2-link-string) div {
display: inline;
}
:host-context(et2-link-list):hover {
}
:host-context(et2-link-list):hover {
text-decoration: none;
}
}
`
];
}
@ -119,7 +137,7 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
constructor()
{
super();
this._title = "";
this._title = Et2Link.MISSING_TITLE;
this.__linkHook = "view";
}
@ -128,9 +146,34 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
super.connectedCallback();
}
createRenderRoot()
/**
* Build a thumbnail for the link
* @param link
* @returns {TemplateResult}
* @protected
*/
protected _thumbnailTemplate(link : LinkInfo) : TemplateResult
{
return this;
// If we have a mimetype, use a Et2VfsMime
// Files have path set in 'icon' property, and mime in 'type'
if(link.type && link.icon)
{
return html`
<et2-vfs-mime part="icon" class="link__icon" ._parent=${this} .value=${Object.assign({
name: link.title,
mime: link.type,
path: link.icon
}, link)}
></et2-vfs-mime>`;
}
return html`
<et2-image-expose
part="icon"
class="link__icon"
._parent=${this}
href="${link.href}"
src=${this.egw().image("" + link.icon)}
></et2-image-expose>`;
}
render()
@ -145,7 +188,12 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
.replace(this.breakTitle, this.breakTitle.trimEnd() + "\u200B")
.replace(/ /g, '\u00a0');
}
return html`${title}`;
return html`
<div part="base" class="link et2_link">
${this._thumbnailTemplate({id: this.entryId, app: this.app, ...this.dataset})}
<span part="title" class="link__title">${title}</span>
<span part="remark" class="link__remark">${this.dataset.remark}</span>
</div>`;
}
public set title(_title)
@ -200,7 +248,6 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
{
this.app = _value.app;
this.entryId = _value.id;
this._title = Et2Link.MISSING_TITLE;
if(_value.title)
{
@ -216,6 +263,7 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
this.dataset[key] = _value[key];
})
}
this.requestUpdate("value");
}

View File

@ -45,47 +45,54 @@ export class Et2LinkList extends Et2LinkString
return [
...super.styles,
css`
:host {
display:flex;
:host {
display: flex;
flex-direction: column;
column-gap: 10px;
overflow: hidden;
}
div {
}
div {
display: flex;
gap: 10px;
}
div:hover {
background-color: var(--highlight-background-color);
}
}
div.zip_highlight {
div:hover {
background-color: var(--highlight-background-color);
}
div.zip_highlight {
animation-name: new_entry_pulse, new_entry_clear;
animation-duration: 5s;
animation-delay: 0s, 30s;
animation-fill-mode: forwards;
}
}
/* CSS for child elements */
::slotted(*):after {
/* Reset from Et2LinkString */
content: initial;
}
::slotted(et2-vfs-mime), ::slotted(et2-image-expose) {
width: 16px;
}
::slotted(et2-link) {
flex: 1 1 auto;
}
::slotted(.remark) {
flex: 1 1 auto;
width: 20%;
}
::slotted(.delete_button) {
visibility: hidden;
width: 16px;
order: 5;
}
/* CSS for child elements */
::slotted(*):after {
/* Reset from Et2LinkString */
content: initial;
}
::slotted(*)::part(icon) {
width: 1rem;
}
::slotted(et2-link) {
flex: 1 1 auto;
}
::slotted(.remark) {
flex: 1 1 auto;
width: 20%;
}
::slotted(.delete_button) {
visibility: hidden;
width: 16px;
order: 5;
}
`
];
}
@ -181,12 +188,9 @@ export class Et2LinkList extends Et2LinkString
{
const id = typeof link.id === "string" ? link.id : link.link_id;
return html`
${this._thumbnailTemplate(link)}
<et2-link slot="${this._get_row_id(link)}" app="${link.app}" entryId="${id}"
._parent=${this}
.value=${link}></et2-link>
<et2-description slot="${this._get_row_id(link)}" ._parent=${this} class="remark"
value="${link.remark}"></et2-description>
${this._deleteButtonTemplate(link)}
`;
}
@ -329,31 +333,6 @@ export class Et2LinkList extends Et2LinkString
}
}
/**
* Build a thumbnail for the link
* @param link
* @returns {TemplateResult}
* @protected
*/
protected _thumbnailTemplate(link) : TemplateResult
{
// If we have a mimetype, use a Et2VfsMime
// Files have path set in 'icon' property, and mime in 'type'
if(link.type && link.icon)
{
return html`
<et2-vfs-mime slot="${this._get_row_id(link)}" ._parent=${this} .value=${Object.assign({
name: link.title,
mime: link.type,
path: link.icon
}, link)}></et2-vfs-mime>`;
}
return html`
<et2-image-expose
slot="${this._get_row_id(link)}" ._parent=${this}
href="${link.href}"
src=${this.egw().image("" + link.icon)}></et2-image-expose>`;
}
/**
* Build the delete button
@ -658,7 +637,7 @@ export class Et2LinkList extends Et2LinkString
protected _set_comment(link, comment)
{
let remark = this.querySelector(".remark[slot='" + this._get_row_id(link) + "']");
let remark = this.querySelector("et2-link[slot='" + this._get_row_id(link) + "']");
if(!remark)
{
console.warn("Could not find link to comment on", link);
@ -702,10 +681,10 @@ export class Et2LinkList extends Et2LinkString
{
// Append "" to make sure it's a string, not undefined
remark.classList.remove("loading");
// Update internal data & displayed comment
remark.value = link.remark = comment + "";
// Update internal data
link.remark = comment + "";
// Update link widget
remark.parentElement.querySelector("et2-link").value = link;
remark.value = link;
}
});
}

View File

@ -32,18 +32,30 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache
return [
...super.styles,
css`
:host {
:host {
list-style-type: none;
display: inline;
padding: 0px;
}
/* CSS for child elements */
::slotted(*):after {
content: ", "
}
::slotted(*:last-child):after {
content:initial;
}
}
::slotted(*) {
display: inline;
}
::slotted(*):hover {
text-decoration: underline;
}
/* CSS for child elements */
::slotted(*):after {
content: ", "
}
::slotted(*:last-child):after {
content: initial;
}
`
];
}

View File

@ -1057,24 +1057,33 @@ div.et2_file input.et2_file_upload {
* Autocomplete in dialogs - fix so they go over/out of the dialog
*/
.ui-dialog * ul.ui-autocomplete {
position: fixed;
position: fixed;
}
/**
* Link wiget(s)
*/
et2-link-string et2-link::part(base) {
display: inline;
}
et2-link-string > et2-link::part(icon), et2-link-string > et2-link::part(remark) {
display: none;
}
/* Link entry - x button*/
div.et2_link_entry {
width: 99%;
white-space: nowrap;
width: 99%;
white-space: nowrap;
}
div.et2_link_entry:after {
display: inline-block;
content: ".";
height: 0;
visibility: hidden;
margin: -20px;
display: inline-block;
content: ".";
height: 0;
visibility: hidden;
margin: -20px;
}
/* Special layout for inside nm grid */
@ -1314,19 +1323,23 @@ ul.et2_link_string {
}
et2-link-list et2-link {
color: initial;
width: 30%;
color: initial;
width: 30%;
}
et2-link-list et2-link:hover {
text-decoration: initial;
text-decoration: initial;
}
et2-link-list > et2-link::part(icon) {
width: 1rem;
}
.et2_link_list .icon img,
.et2_vfs .icon img {
width: 16px;
height: 16px;
display: inline-block;
width: 16px;
height: 16px;
display: inline-block;
}
div.et2_vfsPath {