mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-26 09:53:20 +01:00
Reconfigure Link to include icon & comment for easier drag & drop
This commit is contained in:
parent
e4bdbe256a
commit
8da10cf863
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import {ExposeMixin, ExposeValue} from "../Expose/ExposeMixin";
|
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 {Et2Widget} from "../Et2Widget/Et2Widget";
|
||||||
import {et2_IDetachedDOM} from "../et2_core_interfaces";
|
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
|
* 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>.
|
* 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()
|
* 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
|
// @ts-ignore TypeScript says there's something wrong with types
|
||||||
@ -32,20 +33,37 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
|
|||||||
return [
|
return [
|
||||||
...super.styles,
|
...super.styles,
|
||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
cursor: pointer;
|
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
|
text-decoration: underline
|
||||||
}
|
}
|
||||||
/** Style based on parent **/
|
|
||||||
:host-context(et2-link-string) {
|
/** Style based on parent **/
|
||||||
|
|
||||||
|
:host(et2-link-string) div {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
:host-context(et2-link-list):hover {
|
|
||||||
|
:host-context(et2-link-list):hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -119,7 +137,7 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
|
|||||||
constructor()
|
constructor()
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
this._title = "";
|
this._title = Et2Link.MISSING_TITLE;
|
||||||
this.__linkHook = "view";
|
this.__linkHook = "view";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,9 +146,34 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
|
|||||||
super.connectedCallback();
|
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()
|
render()
|
||||||
@ -145,7 +188,12 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
|
|||||||
.replace(this.breakTitle, this.breakTitle.trimEnd() + "\u200B")
|
.replace(this.breakTitle, this.breakTitle.trimEnd() + "\u200B")
|
||||||
.replace(/ /g, '\u00a0');
|
.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)
|
public set title(_title)
|
||||||
@ -200,7 +248,6 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
|
|||||||
{
|
{
|
||||||
this.app = _value.app;
|
this.app = _value.app;
|
||||||
this.entryId = _value.id;
|
this.entryId = _value.id;
|
||||||
this._title = Et2Link.MISSING_TITLE;
|
|
||||||
|
|
||||||
if(_value.title)
|
if(_value.title)
|
||||||
{
|
{
|
||||||
@ -216,6 +263,7 @@ export class Et2Link extends ExposeMixin<Et2Widget>(Et2Widget(LitElement)) imple
|
|||||||
this.dataset[key] = _value[key];
|
this.dataset[key] = _value[key];
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
this.requestUpdate("value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,47 +45,54 @@ export class Et2LinkList extends Et2LinkString
|
|||||||
return [
|
return [
|
||||||
...super.styles,
|
...super.styles,
|
||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
display:flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
column-gap: 10px;
|
column-gap: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
div {
|
|
||||||
|
div {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
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-name: new_entry_pulse, new_entry_clear;
|
||||||
animation-duration: 5s;
|
animation-duration: 5s;
|
||||||
animation-delay: 0s, 30s;
|
animation-delay: 0s, 30s;
|
||||||
animation-fill-mode: forwards;
|
animation-fill-mode: forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CSS for child elements */
|
/* CSS for child elements */
|
||||||
::slotted(*):after {
|
|
||||||
/* Reset from Et2LinkString */
|
::slotted(*):after {
|
||||||
content: initial;
|
/* Reset from Et2LinkString */
|
||||||
}
|
content: initial;
|
||||||
::slotted(et2-vfs-mime), ::slotted(et2-image-expose) {
|
}
|
||||||
width: 16px;
|
|
||||||
}
|
::slotted(*)::part(icon) {
|
||||||
::slotted(et2-link) {
|
width: 1rem;
|
||||||
flex: 1 1 auto;
|
}
|
||||||
}
|
|
||||||
::slotted(.remark) {
|
::slotted(et2-link) {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
width: 20%;
|
}
|
||||||
}
|
|
||||||
::slotted(.delete_button) {
|
::slotted(.remark) {
|
||||||
visibility: hidden;
|
flex: 1 1 auto;
|
||||||
width: 16px;
|
width: 20%;
|
||||||
order: 5;
|
}
|
||||||
}
|
|
||||||
|
::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;
|
const id = typeof link.id === "string" ? link.id : link.link_id;
|
||||||
return html`
|
return html`
|
||||||
${this._thumbnailTemplate(link)}
|
|
||||||
<et2-link slot="${this._get_row_id(link)}" app="${link.app}" entryId="${id}"
|
<et2-link slot="${this._get_row_id(link)}" app="${link.app}" entryId="${id}"
|
||||||
._parent=${this}
|
._parent=${this}
|
||||||
.value=${link}></et2-link>
|
.value=${link}></et2-link>
|
||||||
<et2-description slot="${this._get_row_id(link)}" ._parent=${this} class="remark"
|
|
||||||
value="${link.remark}"></et2-description>
|
|
||||||
${this._deleteButtonTemplate(link)}
|
${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
|
* Build the delete button
|
||||||
@ -658,7 +637,7 @@ export class Et2LinkList extends Et2LinkString
|
|||||||
|
|
||||||
protected _set_comment(link, comment)
|
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)
|
if(!remark)
|
||||||
{
|
{
|
||||||
console.warn("Could not find link to comment on", link);
|
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
|
// Append "" to make sure it's a string, not undefined
|
||||||
remark.classList.remove("loading");
|
remark.classList.remove("loading");
|
||||||
// Update internal data & displayed comment
|
// Update internal data
|
||||||
remark.value = link.remark = comment + "";
|
link.remark = comment + "";
|
||||||
// Update link widget
|
// Update link widget
|
||||||
remark.parentElement.querySelector("et2-link").value = link;
|
remark.value = link;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -32,18 +32,30 @@ export class Et2LinkString extends Et2Widget(LitElement) implements et2_IDetache
|
|||||||
return [
|
return [
|
||||||
...super.styles,
|
...super.styles,
|
||||||
css`
|
css`
|
||||||
:host {
|
:host {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
display: inline;
|
display: inline;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
/* CSS for child elements */
|
|
||||||
::slotted(*):after {
|
::slotted(*) {
|
||||||
content: ", "
|
display: inline;
|
||||||
}
|
}
|
||||||
::slotted(*:last-child):after {
|
|
||||||
content:initial;
|
::slotted(*):hover {
|
||||||
}
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* CSS for child elements */
|
||||||
|
|
||||||
|
::slotted(*):after {
|
||||||
|
content: ", "
|
||||||
|
}
|
||||||
|
|
||||||
|
::slotted(*:last-child):after {
|
||||||
|
content: initial;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -1057,24 +1057,33 @@ div.et2_file input.et2_file_upload {
|
|||||||
* Autocomplete in dialogs - fix so they go over/out of the dialog
|
* Autocomplete in dialogs - fix so they go over/out of the dialog
|
||||||
*/
|
*/
|
||||||
.ui-dialog * ul.ui-autocomplete {
|
.ui-dialog * ul.ui-autocomplete {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link wiget(s)
|
* 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*/
|
/* Link entry - x button*/
|
||||||
div.et2_link_entry {
|
div.et2_link_entry {
|
||||||
width: 99%;
|
width: 99%;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.et2_link_entry:after {
|
div.et2_link_entry:after {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
content: ".";
|
content: ".";
|
||||||
height: 0;
|
height: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
margin: -20px;
|
margin: -20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Special layout for inside nm grid */
|
/* Special layout for inside nm grid */
|
||||||
@ -1314,19 +1323,23 @@ ul.et2_link_string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
et2-link-list et2-link {
|
et2-link-list et2-link {
|
||||||
color: initial;
|
color: initial;
|
||||||
width: 30%;
|
width: 30%;
|
||||||
}
|
}
|
||||||
|
|
||||||
et2-link-list et2-link:hover {
|
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_link_list .icon img,
|
||||||
.et2_vfs .icon img {
|
.et2_vfs .icon img {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 16px;
|
height: 16px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.et2_vfsPath {
|
div.et2_vfsPath {
|
||||||
|
Loading…
Reference in New Issue
Block a user