import { html, css, LitElement, PropertyValues } from "lit"; import { customElement, property, state, query } from "lit/decorators.js"; import { repeat } from "lit/directives/repeat.js"; import "@shoelace-style/shoelace/dist/themes/light.css"; import { SlSelect, SlOption, SlDivider, SlIcon, SlInput, } from "@shoelace-style/shoelace"; import Drawflow, { DrawflowNode } from "drawflow"; import number123 from "@tabler/icons/outline/number-123.svg"; import checkbox from "@tabler/icons/outline/checkbox.svg"; import blockquote from "@tabler/icons/outline/blockquote.svg"; import highlight from "@tabler/icons/outline/highlight.svg"; import microphone from "@tabler/icons/outline/microphone.svg"; import file from "@tabler/icons/outline/file.svg"; import squares from "@tabler/icons/outline/squares.svg"; const NO_NODE_SELECTED: DrawflowNode = { id: -1, name: "unselect", inputs: {}, outputs: {}, pos_x: 0, pos_y: 0, class: "unselect", data: {}, html: "", typenode: false, }; @customElement("webwriter-quiz-tasks-select") export class WebWriterQuizTasksSelect extends LitElement { @property({ type: Object }) accessor quiz; @property({ type: Object }) accessor options = []; @property({ type: String }) accessor value; @state() accessor searchTerm = ""; @query("sl-input") accessor searchElement!: SlInput; @query("sl-select") accessor selectElement!: SlSelect; static styles = css` .nodeSelect { width: 100%; } sl-select::part(listbox) { width: 250px; height: 250px; } sl-select::part(tags) { width: 80px; } sl-select::part(tag) { max-width: 40%; /* Adjust the width to your needs */ white-space: nowrap; /* Ensure text is in one line */ overflow: hidden; /* Hide overflowing text */ text-overflow: ellipsis; /* Add "..." if text overflows */ } sl-select.two-tags::part(tag) { display: inline-flex; /* Keep the layout as inline flex */ max-width: 30px; /* Control the minimum width */ white-space: nowrap; /* Ensure the text stays in one line */ overflow: hidden; /* Hide overflowing content */ text-overflow: ellipsis; /* Add ellipsis for truncated content */ box-sizing: border-box; /* Include padding/border in width calculation */ } .node-option-visible { display: block; } .node-option-hidden { display: none; } .icon-header { display: flex; align-items: center; gap: 7px; } `; /* */ // Move the option gathering logic to firstUpdated lifecycle method firstUpdated() { const containersSlot = this.quiz?.shadowRoot.querySelector("slot"); const assignedElements = containersSlot.assignedElements(); // Filter nodes with class "ww-widget" and add them to this.options const tasks = assignedElements.filter((el) => el.tagName.toLowerCase().includes("webwriter-task") ); let taskOptions = []; tasks.forEach((task) => { const taskContent = task.children; const prompt = taskContent[0]; const taskElement = taskContent[1]; //(TODO: after Thesis) - Add Support for Speech Quiz Task if (!taskElement.tagName.toLowerCase().includes("speech")) { taskOptions = [ ...taskOptions, { task: task, prompt: prompt, taskElement: taskElement }, ]; } }); this.options = [...this.options, ...taskOptions]; } protected updated(_changedProperties: PropertyValues): void { const partTags = this.selectElement.shadowRoot?.querySelector('div[part="tags"]'); if (partTags?.childElementCount >= 2) { this.selectElement.classList.add("two-tags"); } else { this.selectElement.classList.remove("two-tags"); } } render() { return html` Select task(s) from the quiz ${this.options.length === 0 ? html`No tasks found in the quiz. ` : html` ${repeat( this.options, (element) => element.id, (element, index) => html` ${`${index + 1}. ${element.taskElement.tagName .replace("WEBWRITER-", "") .toLowerCase() .replace(/^./, (str) => str.toUpperCase())}`} ${element.taskElement.tagName.toLowerCase().includes("order") ? html` ` : element.taskElement.tagName.toLowerCase().includes("choice") ? html`` : element.taskElement.tagName.toLowerCase().includes("text") ? html`` : element.taskElement.tagName.toLowerCase().includes("mark") ? html`` : element.taskElement.tagName.toLowerCase().includes("speech") ? html`` : null}

(${element.prompt.textContent.substring(0, 10) + "..."})

` )}`}
`; } private _handleElementSelect(event: Event) { if ( event.target instanceof HTMLElement && event.target.tagName.toLowerCase() === "sl-select" ) { const selectedValue = (event.target as SlSelect).value; // If it's not an array, just assign it as-is this.value = selectedValue; } } }