Fix some readonly issues where widgets were not looking readonly

- Editable tags were still editable if the select was readonly
- LinkTo could still select an app (readonly not passed on)
- Hide the dropdown for multi-select when readonly
This commit is contained in:
nathan 2023-02-03 14:08:27 -07:00
parent 3a695bd45d
commit 1d8d4f9c72
5 changed files with 63 additions and 22 deletions

View File

@ -163,7 +163,7 @@ export class Et2LinkEntry extends Et2InputWidget(FormControlMixin(SlotMixin(LitE
} }
if(changedProperties.has("readonly")) if(changedProperties.has("readonly"))
{ {
this._appNode.readonly = this.readonly; this._appNode.readonly = this._appNode.disabled = this.readonly;
this._searchNode.readonly = this.readonly; this._searchNode.readonly = this.readonly;
} }
// Pass some properties on to app selection // Pass some properties on to app selection

View File

@ -139,6 +139,7 @@ export class Et2LinkTo extends Et2InputWidget(ScopedElementsMixin(FormControlMix
return html` return html`
<et2-link-entry .onlyApp="${this.onlyApp}" <et2-link-entry .onlyApp="${this.onlyApp}"
.applicationList="${this.applicationList}" .applicationList="${this.applicationList}"
.readonly=${this.readonly}
@sl-select=${this.handleEntrySelected} @sl-select=${this.handleEntrySelected}
@sl-clear="${this.handleEntryCleared}"> @sl-clear="${this.handleEntryCleared}">
</et2-link-entry> </et2-link-entry>

View File

@ -88,36 +88,51 @@ export class Et2Select extends Et2WithSearchMixin(Et2WidgetWithSelect)
.select__label { .select__label {
display: block; display: block;
text-overflow: ellipsis; text-overflow: ellipsis;
/* This is usually not used due to flex, but is the basis for ellipsis calculation */ /* This is usually not used due to flex, but is the basis for ellipsis calculation */
width: 10ex; width: 10ex;
} }
/** multiple=true uses tags for each value **/ /** multiple=true uses tags for each value **/
/* styling for icon inside tag (not option) */ /* styling for icon inside tag (not option) */
.tag_image {
.tag_image {
margin-right: var(--sl-spacing-x-small); margin-right: var(--sl-spacing-x-small);
} }
/* Maximum height + scrollbar on tags (+ other styling) */
.select__tags { /* Maximum height + scrollbar on tags (+ other styling) */
.select__tags {
margin-left: 0px; margin-left: 0px;
max-height: initial; max-height: initial;
overflow-y: auto; overflow-y: auto;
gap: 0.1rem 0.5rem; gap: 0.1rem 0.5rem;
} }
.select--medium .select__tags {
.select--medium .select__tags {
padding-top: 2px; padding-top: 2px;
padding-bottom: 2px; padding-bottom: 2px;
} }
:host([rows]) .select__tags {
:host([rows]) .select__tags {
max-height: calc(var(--rows, 5) * 1.35rem); max-height: calc(var(--rows, 5) * 1.35rem);
} }
/* Keep overflow tag right-aligned. It's the only sl-tag. */
.select__tags sl-tag { /* Keep overflow tag right-aligned. It's the only sl-tag. */
.select__tags sl-tag {
margin-left: auto; margin-left: auto;
} }
select:hover {
select:hover {
box-shadow: 1px 1px 1px rgb(0 0 0 / 60%); box-shadow: 1px 1px 1px rgb(0 0 0 / 60%);
}` }
/* Hide dropdown trigger when multiple & readonly */
:host([readonly][multiple]) .select__icon {
display: none;
}
`
]; ];
} }

View File

@ -365,9 +365,14 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
this._addNodes(); this._addNodes();
} }
// Update any tags if edit mode changes // Update any tags if edit mode changes
if(changedProperties.has("editModeEnabled")) if(changedProperties.has("editModeEnabled") || changedProperties.has("readonly"))
{ {
this.shadowRoot.querySelectorAll(".select__tags > *").forEach(tag => tag.editable = this.editModeEnabled); // Required because we explicitly create tags instead of doing it in render()
this.shadowRoot.querySelectorAll(".select__tags > *").forEach((tag : Et2Tag) =>
{
tag.editable = this.editModeEnabled && !this.readonly;
tag.removable = !this.readonly;
});
} }
} }
@ -411,7 +416,7 @@ export const Et2WithSearchMixin = <T extends Constructor<LitElement>>(superclass
protected _createTagNode(item) protected _createTagNode(item)
{ {
let tag = <Et2Tag>document.createElement(this.tagTag); let tag = <Et2Tag>document.createElement(this.tagTag);
tag.editable = this.editModeEnabled; tag.editable = this.editModeEnabled && !this.readonly;
return tag; return tag;
} }

View File

@ -28,6 +28,9 @@ async function before(editable = true)
sinon.stub(element, "egw").returns(window.egw); sinon.stub(element, "egw").returns(window.egw);
await element.updateComplete; await element.updateComplete;
let tags = [];
element.shadowRoot.querySelectorAll(element.tagTag).forEach((t : Et2Tag) => tags.push(t.updateComplete));
await Promise.all(tags);
return element; return element;
} }
@ -120,6 +123,21 @@ describe("Editable tag", () =>
assert.equal(element.value, "change select too", "Tag change did not cause value change in parent select (allowFreeEntries was on)"); assert.equal(element.value, "change select too", "Tag change did not cause value change in parent select (allowFreeEntries was on)");
}); });
it("Does not have edit button when readonly", async() =>
{
element.readonly = true;
await element.updateComplete;
let tag = element.shadowRoot.querySelectorAll(element.tagTag);
assert.isAbove(tag.length, 0, "No tags found");
let wait = [];
tag.forEach((t : Et2Tag) => wait.push(t.updateComplete))
await Promise.all(wait);
assert.isNull(tag[0].shadowRoot.querySelector("et2-button-icon[label='edit*']"), "Unexpected edit button");
});
}); });
describe("Select is not editable", () => describe("Select is not editable", () =>
{ {
@ -130,6 +148,8 @@ describe("Select is not editable", () =>
{ {
let tag = element.shadowRoot.querySelectorAll(element.tagTag); let tag = element.shadowRoot.querySelectorAll(element.tagTag);
assert.isAbove(tag.length, 0, "No tags found"); assert.isAbove(tag.length, 0, "No tags found");
assert.isNull(tag[0].shadowRoot.querySelector("et2-button-icon[label='edit*']"), "Unexpected edit button"); assert.isNull(tag[0].shadowRoot.querySelector("et2-button-icon[label='edit*']"), "Unexpected edit button");
}); });
}); });