From e1ab343a5d6de32eedf2ca86bb81521a7441bafa Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 17 Dec 2021 14:47:19 -0700 Subject: [PATCH] WIP on Et2Description. Shows improvement in nm render speed. --- api/js/etemplate/ActivateLinksDirective.ts | 66 ++++++++ .../Et2Description/Et2Description.ts | 151 ++++++++++++++++++ api/js/etemplate/Et2Widget/Et2Widget.ts | 13 +- api/js/etemplate/etemplate2.ts | 3 + 4 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 api/js/etemplate/ActivateLinksDirective.ts create mode 100644 api/js/etemplate/Et2Description/Et2Description.ts diff --git a/api/js/etemplate/ActivateLinksDirective.ts b/api/js/etemplate/ActivateLinksDirective.ts new file mode 100644 index 0000000000..810f2e1d42 --- /dev/null +++ b/api/js/etemplate/ActivateLinksDirective.ts @@ -0,0 +1,66 @@ +import {Directive, directive, html, repeat} from "@lion/core"; +import {et2_activateLinks} from "./et2_core_common"; + +/** + * Activates links in text + * + * @example + * this.value = "This text has links to https://www.egroupware.org"; + * ... + * render() + * { + * return html`activateLinks(this.value)`; + * } + * renders as: + * egroupware.org + */ +class ActivateLinksDirective extends Directive +{ + render(text_with_urls, _target) + { + let list = et2_activateLinks(text_with_urls); + + return html`${repeat(list, (item, index) => + { + // No urls in this section + if(typeof item == "string" || typeof item == "number") + { + // Just text. Easy (framework handles \n) + return item; + } + // Url found, deal with it + else if(item && item.text) + { + if(!item.href) + { + console.warn("et2_activateLinks gave bad data", item, _target); + item.href = ""; + } + let click = null; + let target = null; + + // open mailto links depending on preferences in mail app + if(item.href.substr(0, 7) == "mailto:" && + egw.user('apps').mail && + egw.preference('force_mailto', 'addressbook') != '1') + { + click = function(event) + { + egw.open_link(this); + return false; + }.bind(item.href); + item.href = "#"; + } + + if(typeof _target != "undefined" && _target && _target != "_self" && item.href.substr(0, 7) != "mailto:") + { + target = _target; + } + return html`${item.text}`; + } + })}`; + } + +} + +export const activateLinks = directive(ActivateLinksDirective); \ No newline at end of file diff --git a/api/js/etemplate/Et2Description/Et2Description.ts b/api/js/etemplate/Et2Description/Et2Description.ts new file mode 100644 index 0000000000..295b9b2f65 --- /dev/null +++ b/api/js/etemplate/Et2Description/Et2Description.ts @@ -0,0 +1,151 @@ +/** + * EGroupware eTemplate2 - Description WebComponent + * + * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License + * @package api + * @link https://www.egroupware.org + * @author Nathan Gray + */ + +import {Et2Widget} from "../Et2Widget/Et2Widget"; +import {html, css, LitElement} from "@lion/core"; +import {et2_IDetachedDOM} from "../et2_core_interfaces"; +import {activateLinks} from "../ActivateLinksDirective"; + +export class Et2Description extends Et2Widget(LitElement) implements et2_IDetachedDOM +{ + + protected _value : string = ""; + + static get styles() + { + return [ + ...super.styles, + css` + :host { + white-space: pre-wrap; + }` + ]; + } + + static get properties() + { + return { + ...super.properties, + value: String, + } + } + + set_value(value) + { + this.value = value; + } + + get value() + { + return this._value; + } + + set value(_value : string) + { + let oldValue = this.value; + + if(!_value) + { + _value = ""; + } + + // Do we do this here, or in transformAttributes()? + if(!this.no_lang) + { + _value = this.egw().lang(_value); + } + + if(_value && (_value + "").indexOf('%s') != -1) + { + _value = _value.replace(/%s/g, _value); + } + + this._value = _value; + this.requestUpdate('value', oldValue); + } + + render() + { + + // Add hover action button (Edit) + if(this.hover_action) + { + // TODO + } + if(this.extra_link_popup || this.mime) + { + // TODO + } + + + // If there's a link, wrap that + if(this.href && this._value) + { + return this.wrapLink(this.href, this._value); + } + // If we want to activate links inside, do that + else if(this.activateLinks && this._value) + { + return this.getActivatedValue(this._value, this.href ? this.extra_link_target : '_blank'); + } + // Just do the value + else + { + return html`${this._value}`; + } + } + + protected wrapLink(href, value) + { + if(href.indexOf('/') == -1 && href.split('.').length >= 3 && + !(href.indexOf('mailto:') != -1 || href.indexOf('://') != -1 || href.indexOf('javascript:') != -1) + ) + { + href = "/index.php?menuaction=" + href; + } + if(href.charAt(0) == '/') // link relative to eGW + { + href = egw.link(href); + } + return html`${value}`; + } + + protected getActivatedValue(value, target) + { + return html`${activateLinks(value, target)}`; + } + + getDetachedAttributes(attrs) + { + attrs.push("id", "value", "class"); + } + + getDetachedNodes() : HTMLElement[] + { + return [this]; + } + + setDetachedAttributes(_nodes : HTMLElement[], _values : object, _data? : any) : void + { + // Do nothing, since we can't actually stop being a DOM node... + } + + loadFromXML() + { + // nope + } + + loadingFinished() + { + // already done, I'm a wc with no children + } +} + +// @ts-ignore TypeScript is not recognizing that this widget is a LitElement +customElements.define("et2-description", Et2Description); \ No newline at end of file diff --git a/api/js/etemplate/Et2Widget/Et2Widget.ts b/api/js/etemplate/Et2Widget/Et2Widget.ts index 7549a985a7..45eefe8fcf 100644 --- a/api/js/etemplate/Et2Widget/Et2Widget.ts +++ b/api/js/etemplate/Et2Widget/Et2Widget.ts @@ -143,6 +143,14 @@ const Et2WidgetMixin = (superClass) => }, /*** Style type attributes ***/ + /** + * Disable any translations for the widget + */ + no_lang: { + type: Boolean, + reflect: false + }, + /** * Used by Et2Box to determine alignment. * Allowed values are left, right @@ -1172,7 +1180,7 @@ function transformAttributes(widget, mgr : et2_arrayMgr, attributes) } // Set as attribute or property, as appropriate - if(widget.getAttributeNames().indexOf(attribute) >= 0) + if(widget.getAttributeNames().indexOf(attribute) >= 0 || property.reflect) { // Set as attribute (reflected in DOM) widget.setAttribute(attribute, attrValue); @@ -1195,4 +1203,5 @@ function transformAttributes(widget, mgr : et2_arrayMgr, attributes) } } } -} \ No newline at end of file +} + diff --git a/api/js/etemplate/etemplate2.ts b/api/js/etemplate/etemplate2.ts index b2224a20f9..73969b1a95 100644 --- a/api/js/etemplate/etemplate2.ts +++ b/api/js/etemplate/etemplate2.ts @@ -25,8 +25,11 @@ import '../jsapi/egw_json.js'; import {egwIsMobile} from "../egw_action/egw_action_common.js"; import './Et2Box/Et2Box'; import './Et2Button/Et2Button'; +import './Et2Date/Et2Date'; +import './Et2Date/Et2DateReadonly' import './Et2Date/Et2DateTime'; import './Et2Date/Et2DateTimeReadonly'; +import './Et2Description/Et2Description'; import './Et2Textarea/Et2Textarea'; import './Et2Textbox/Et2Textbox'; import './Et2Colorpicker/Et2Colorpicker';