Link fixes

- Fix file that was linked then removed before first save was still linked on save
- Use events for better decoupling between Et2LinkTo & Et2LinkList
This commit is contained in:
nathan 2022-12-12 10:32:08 -07:00
parent 0f37d2f437
commit 9acda4b390
2 changed files with 82 additions and 15 deletions

View File

@ -111,12 +111,29 @@ export class Et2LinkList extends Et2LinkString
this._handleRowHover = this._handleRowHover.bind(this); this._handleRowHover = this._handleRowHover.bind(this);
this._handleRowContext = this._handleRowContext.bind(this); this._handleRowContext = this._handleRowContext.bind(this);
this._handleChange = this._handleChange.bind(this);
} }
connectedCallback() connectedCallback()
{ {
super.connectedCallback(); super.connectedCallback();
this._createContextMenu(); this._createContextMenu();
// Look for LinkTo and listen for change so we can update
this.getInstanceManager().DOMContainer.querySelectorAll("et2-link-to").forEach(link =>
{
link.addEventListener("et2-change", this._handleChange);
})
}
disconnectedCallback()
{
super.disconnectedCallback();
this.getInstanceManager().DOMContainer.querySelectorAll("et2-link-to").forEach(link =>
{
link.removeEventListener("et2-change", this._handleChange);
})
} }
protected _listTemplate() protected _listTemplate()
@ -230,6 +247,20 @@ export class Et2LinkList extends Et2LinkString
} }
} }
/**
* We listen to LinkTo widgets so we can update
*
* @param _ev
* @protected
*/
protected _handleChange(_ev)
{
if(_ev && typeof _ev.currentTarget)
{
this.get_links(_ev.detail || []);
}
}
/** /**
* Build a thumbnail for the link * Build a thumbnail for the link
* @param link * @param link
@ -300,14 +331,25 @@ export class Et2LinkList extends Et2LinkString
let link_element = <HTMLElement>this.querySelector("et2-link[slot='" + this._get_row_id(link) + "']"); let link_element = <HTMLElement>this.querySelector("et2-link[slot='" + this._get_row_id(link) + "']");
link_element.classList.add("loading"); link_element.classList.add("loading");
this.dispatchEvent(new CustomEvent("before_delete", {detail: link})); this.dispatchEvent(new CustomEvent("et2-before-delete", {detail: link}));
let removeLink = () => {this.querySelectorAll("[slot='" + this._get_row_id(link) + "']").forEach(e => e.remove());}; let removeLink = () =>
{
this.querySelectorAll("[slot='" + this._get_row_id(link) + "']").forEach(e => e.remove());
if(this._link_list.indexOf(link) != -1)
{
this._link_list.splice(this._link_list.indexOf(link), 1);
}
this.dispatchEvent(new CustomEvent("et2-delete", {bubbles: true, detail: link}));
};
// Unsaved entry, had no ID yet // Unsaved entry, had no ID yet
if(typeof this.entryId !== "string" && this.entryId[link.link_id]) if(!this.entryId || typeof this.entryId !== "string" && this.entryId[link.link_id])
{ {
delete this.entryId[link.link_id]; if(this.entryId)
{
delete this.entryId[link.link_id];
}
removeLink(); removeLink();
} }
else if(typeof this.entryId == "string" && link.link_id) else if(typeof this.entryId == "string" && link.link_id)

View File

@ -21,8 +21,6 @@ import {Et2LinkEntry} from "./Et2LinkEntry";
import {egw} from "../../jsapi/egw_global"; import {egw} from "../../jsapi/egw_global";
import {et2_vfsSelect} from "../et2_widget_vfs"; import {et2_vfsSelect} from "../et2_widget_vfs";
import {LinkInfo} from "./Et2Link"; import {LinkInfo} from "./Et2Link";
import {Et2LinkList} from "./Et2LinkList";
import {et2_DOMWidget} from "../et2_core_DOMWidget";
import {ValidationType} from "@lion/form-core/types/validate/ValidateMixinTypes"; import {ValidationType} from "@lion/form-core/types/validate/ValidateMixinTypes";
import {ManualMessage} from "../Validators/ManualMessage"; import {ManualMessage} from "../Validators/ManualMessage";
@ -109,6 +107,8 @@ export class Et2LinkTo extends Et2InputWidget(ScopedElementsMixin(FormControlMix
this.handleEntrySelected = this.handleEntrySelected.bind(this); this.handleEntrySelected = this.handleEntrySelected.bind(this);
this.handleEntryCleared = this.handleEntryCleared.bind(this); this.handleEntryCleared = this.handleEntryCleared.bind(this);
this.handleLinkButtonClick = this.handleLinkButtonClick.bind(this); this.handleLinkButtonClick = this.handleLinkButtonClick.bind(this);
this.handleLinkDeleted = this.handleLinkDeleted.bind(this);
} }
firstUpdated() firstUpdated()
@ -118,6 +118,18 @@ export class Et2LinkTo extends Et2InputWidget(ScopedElementsMixin(FormControlMix
this._fileButtons(); this._fileButtons();
} }
connectedCallback()
{
super.connectedCallback();
this.getInstanceManager().DOMContainer.addEventListener("et2-delete", this.handleLinkDeleted);
}
disconnectedCallback()
{
super.disconnectedCallback();
this.getInstanceManager().DOMContainer.removeEventListener("et2-delete", this.handleLinkDeleted);
}
/** /**
* @return {TemplateResult} * @return {TemplateResult}
* @protected * @protected
@ -308,15 +320,11 @@ export class Et2LinkTo extends Et2InputWidget(ScopedElementsMixin(FormControlMix
} }
} }
// Look for a link-list so we can refresh it // Send an event so listeners can update
let list_widget = (<Et2LinkList><unknown>(<et2_DOMWidget>this.getParent()).getDOMNode().querySelector('et2-link-list')); this.dispatchEvent(new CustomEvent("et2-change", {
// If there's an array of data (entry is not yet saved), updating the list with only server info will bubbles: true,
// not work, so add them in explicitly. detail: typeof success == "object" ? Object.values(success) : []
if(list_widget && success) }));
{
// Update link list, passing data if server provided it
list_widget.get_links(typeof success == "object" ? Object.values(success) : []);
}
} }
else else
{ {
@ -422,6 +430,23 @@ export class Et2LinkTo extends Et2InputWidget(ScopedElementsMixin(FormControlMix
this.createLink(link_info) this.createLink(link_info)
} }
/**
* Handle a link being removed
*
* Event is thrown every time a link is removed (from a LinkList) but we only care if the
* entry hasn't been saved yet and has no ID. In this case we've been keeping the list
* to submit and link server-side so we have to remove the deleted link from our list.
*
* @param {CustomEvent} e
*/
handleLinkDeleted(e : CustomEvent)
{
if(e && e.detail && this.value && typeof this.value.to_id == "object")
{
delete this.value.to_id[e.detail.link_id || ""]
}
}
get link_button() : Et2Button get link_button() : Et2Button
{ {
return this.shadowRoot.querySelector("#link_button"); return this.shadowRoot.querySelector("#link_button");