UNPKG

@rangertechnologies/ngnxt

Version:

This library was used for creating dymanic UI based on the input JSON/data

444 lines 182 kB
// AP 22JAN25 - form preview and All form elements import { Component, Input } from '@angular/core'; import { v4 as uuidv4 } from 'uuid'; import { VERSION } from '../../../../environments/version'; import * as i0 from "@angular/core"; import * as i1 from "../../../services/form-builder.service"; import * as i2 from "@angular/common"; import * as i3 from "@angular/forms"; import * as i4 from "../../../components/datatable/datatable.component"; import * as i5 from "@angular/material/tooltip"; import * as i6 from "../../booklet/booklet.component"; export class ElementComponent { formBuilderService; //@Output() elementButtonClicked = new EventEmitter<string>(); bookletJSON; bookletId; field; formElements = []; elements = []; bookId; sections = { basic: true, // Basic Elements open by default advanced: true // Advanced Elements closed by default }; basicElements = []; advancedElements = []; elementDisabledArray; version = VERSION.version; //SKS10MAR25 get version from environment/version.ts book; selectedElement = null; isSelectTablePopup = false; currentType; addTable = true; dots = Array(6); draggedIndex = null; //subscription: any; constructor(formBuilderService) { this.formBuilderService = formBuilderService; } // AP-06MAR25 New Design Change Elements Basic , Advanced // AP-06MAR25 Add RichText Area // AP-12MAR25 Add Date ngOnInit() { this.basicElements = [ { "type": "Text", "img": "Text", "label": "Text" }, { "type": "TextArea", "img": "TextArea", "label": "Text Area" }, { "type": "RichTextArea", "img": "RichText", "label": "Rich Text" }, { "type": "Number", "img": "Number", "label": "Number" }, { "type": "Label", "img": "Label", "label": "Label" }, { "type": "Image", "img": "Image", "label": "Image" }, { "type": "Email", "img": "Email", "label": "Email" }, { "type": "Date", "img": "Date", "label": "Date" }, { "type": "Time", "img": "Time", "label": "Time" }, { "type": "DateTime", "img": "DateTime", "label": "DateTime" }, { "type": "Line", "img": "line", "label": "Line" }, { "type": "Space", "img": "space", "label": "Space" }, { "type": "Boolean", "img": "Boolean", "label": "Boolean" }, ]; this.advancedElements = [ { "type": "Book", "img": "Search", "label": "Book" }, { "type": "Calendar", "img": "Calendar", "label": "Calendar" }, { "type": "List", "img": "Search", "label": "List" }, { "type": "File", "img": "File", "label": "Files" }, { "type": "Table", "img": "Table", "label": "Table" }, { "type": "Checkbox", "img": "CheckBox", "label": "Checkbox" }, { "type": "Radio", "img": "Radio", "label": "Radio" }, { "type": "Dropdown", "img": "Drop", "label": "Dropdown" }, ]; this.elementDisabledArray = { Table: [ 'Book', 'Calendar', "Boolean", 'List', 'Table', 'Checkbox', 'Radio', 'Dropdown', 'TextArea', 'RichTextArea', 'Number', 'Label', 'Image', 'Email', 'Date', 'Time', 'DateTime', 'Line', 'Space' ] }; this.formBuilderService.formElements$.subscribe(elements => { setTimeout(() => { this.formElements = elements.map(field => ({ ...field })); }, 0); }); if (this.bookletJSON && (this.bookletJSON !== '')) { this.initializeForm(); } else { this.formBuilderService.newBook(); } // AP-12MAR25 - Added to handle bookletId if (this.bookletId) { localStorage.setItem('unique_id', this.bookletId); } this.book = this.formBuilderService.getBook(); this.formBuilderService.selectedElement$.subscribe(index => { const elements = this.formBuilderService.getElements(); if (index >= 0) { this.selectedElement = elements[index]; } // SKS19MAR25 for fieldMeta checking if (this.selectedElement?.type === 'Table') { this.selectedElement['fieldsMeta'] = typeof this.selectedElement.fieldsMeta === 'string' ? this.selectedElement.fieldsMeta : JSON.stringify(this.selectedElement['fieldsMeta'] || []); } // this.formElements = [...elements] }); } // Add these methods toggleSection(section) { this.sections[section] = !this.sections[section]; } isSectionOpen(section) { return this.sections[section]; } // AP - 26FEB25 - Added ngOnChanges to handle changes in bookletJSON ngOnChanges(changes) { if (changes['bookletJSON'] && changes['bookletJSON'].currentValue) { if (this.bookletJSON && (this.bookletJSON !== '')) { this.initializeForm(); } else { this.formBuilderService.newBook(); } } } initializeForm() { if (!this.bookletJSON || !this.bookletJSON.bookQuestionsMap) { console.warn("Invalid bookletJSON structure"); return; } this.formElements = []; this.formBuilderService.clearElements(); this.formBuilderService.intializeBook(this.bookletJSON); const bookQuestionsMap = this.bookletJSON.bookQuestionsMap; const bookQuestionsMapKeys = Object.keys(bookQuestionsMap); if (bookQuestionsMapKeys.length === 0) return; // Check for empty object early for (const key of bookQuestionsMapKeys) { const subQuestions = bookQuestionsMap[key]?.subQuestions; if (Array.isArray(subQuestions)) { subQuestions.forEach((subQuestion) => { // AP-04APR24 If subQuestion.style exists as a string and is empty, replace it with a default style object if (typeof subQuestion.style === "string" && subQuestion.style.trim() === "") { subQuestion.style = { "labelClass": null, "labelStyle": null, "labelValueStyle": null, "inputClass": null, "inputStyle": null, "showLabel": true, "bookStyle": null, "direction": "ltr", "questionStyle": null }; } }); } } this.formElements = this.formBuilderService.getElements(); } // ngOnDestroy() { // this.subscription.unsubscribe(); // } // drop(event: CdkDragDrop<string[]>) { // moveItemInArray(this.formElements, event.previousIndex, event.currentIndex); // //AP-10MAR25 Update order properties to match new indices // this.formElements.forEach((element, index) => { // element.order = index + 1; // }); // this.formBuilderService.updateElementsOrder(this.formElements); // } // Add this method to handle element selection selectElement(index) { this.selectedFieldIndex = index; // element is selected this.formBuilderService.setSelectedElement(index); this.book = this.formBuilderService.getBook(); //const element = this.formElements[index]; // this.elementButtonClicked.emit(element.type); } //selectedIndex: number | null = null; selectedFieldIndex = null; // element is cleared selectHeading(event) { this.formBuilderService.selectHeading(event); //AP-10MAR25 Updates the selected heading in the service this.book = this.formBuilderService.getBook(); //AP-10MAR25 Retrieves the updated book/form data } addElement(type) { const unique_id = uuidv4(); this.currentType = type; if (this.selectedElement?.type === 'Table' && this.addTable) { this.isSelectTablePopup = true; } else { const newElement = { id: unique_id, uid: unique_id, type, name: null, questionText: null, question: null, helpText: null, errorMessage: null, isReadOnly: false, isHidden: false, required: false, referenceField: null, additionalRichContent: null, groupName: null, isDateBackward: false, title: null, subTitle: null, size: 12, isDateForward: false, isOptional: false, isTitle: false, nextQuestion: null, allowedFileExtensions: null, questionNumber: this.formBuilderService.getElements().length + 1, order: this.formElements.length + 1, questionBookId: this.bookletId, parentQuestion: null, fieldsMeta: [], recordTypeName: null, recordTypeId: null, trackingId: null, dateText: null, timeText: null, recordId: null, qbReference: null, qbReferenceQuestions: null, questionBookSubTitle: null, style: { labelClass: null, labelStyle: null, labelValueStyle: null, inputClass: null, inputStyle: null, showLabel: true, bookStyle: null, direction: 'ltr', questionStyle: null, }, subText: { endpoint: null, variable: null, field: null, defaultField: null, sourceQuestionId: null, valueField: null, labelField: null, isDependentField: false, dependentValue: null, queryField: null, queryValue: null, queryValueReference: null, uniqueKey: null, }, imageData: null, boolean: false, options: type === 'Dropdown' || type === 'Radio' || type === 'Checkbox' ? [] : null, imageSize: type === 'Image' ? { width: 150, height: 150 } : null, tableConfig: type === 'Table' ? { isNosIndicator: true, addInlineRecord: true, isPagination: true, actionButton: true, isDeleteRow: true, isEditRow: true, searchBar: true, isButtons: true, itemsPerPage: 10, } : null, }; this.formBuilderService.addElement(newElement); this.formElements = this.formBuilderService.getElements(); // SKS19MAR25 fieldsmeta check this.formElements = this.formElements.map(ele => { if (ele.type === 'Table') { ele.fieldsMeta = typeof ele.fieldsMeta === 'string' ? ele.fieldsMeta : JSON.stringify(ele.fieldsMeta || []); } return ele; }); this.addTable = true; } } // Remove an element by index removeElement(field, index) { this.formBuilderService.removeElementComponent(field.id); this.formElements = this.formBuilderService.getElements(); // SKS19MAR25 fieldsmeta check this.formElements = this.formElements.map(ele => { if (ele.type === 'Table') { ele.fieldsMeta = typeof ele.fieldsMeta === 'string' ? ele.fieldsMeta : JSON.stringify(ele.fieldsMeta || []); } return ele; }); } onDragStart(event, index) { this.draggedIndex = index; event.dataTransfer?.setData('text/plain', index.toString()); } // Allow dropping by preventing default onDragOver(event, index) { event.preventDefault(); } // Handle drop event onDrop(event, dropIndex) { event.preventDefault(); if (this.draggedIndex === null || this.draggedIndex === dropIndex) return; const draggedItem = this.formElements[this.draggedIndex]; // Remove dragged item from old position and insert it in new position this.formElements.splice(this.draggedIndex, 1); this.formElements.splice(dropIndex, 0, draggedItem); //AP-28MAR25 Update questionNumber dynamically based on new order this.formElements.forEach((element, index) => { element.questionNumber = index + 1; }); // Reset dragged index this.draggedIndex = null; // Notify service about the update this.formBuilderService.updateElementsOrder(this.formElements); } toggleBoolean(field) { field.boolean = !field.boolean; } getFontStyles(field) { const styles = { 'font-family': field.font || 'Helvetica Neue', 'font-weight': field.fontWeight || '400', 'font-size': field.fontSize || '14px', 'width': field.size ? `${(field.size / 12) * 100}%` : '100%', 'text-align': field.textAlign || 'left', 'border-radius': '5px', 'border-width': field.lineWidth ? `${field.lineWidth}px` : '1px', // 'border-style': field.lineStyle?.toLowerCase() || 'solid', 'color': field.fontColor || '#000000', // 'border-color': field.color || '#EFF8FF', 'margin-top': field.paddingTop ? `${field.paddingTop}px` : '0px', 'margin-bottom': field.paddingBottom ? `${field.paddingBottom}px` : '10px' }; return styles; } getLineStyles(field) { const styles = { 'font-family': field.font || 'Helvetica Neue', 'font-weight': field.fontWeight || '400', 'font-size': field.fontSize || '14px', 'width': field.size ? `${(field.size / 12) * 100}%` : '100%', 'text-align': field.textAlign || 'left', 'border-radius': '5px', 'border-width': field.lineWidth ? `${field.lineWidth}px` : '1px', 'border-style': field.lineStyle?.toLowerCase() || 'solid', 'color': field.fontColor || '#000000', //'border-color': field.color || '#EFF8FF', 'margin-top': field.paddingTop ? `${field.paddingTop}px` : '0px', 'margin-bottom': field.paddingBottom ? `${field.paddingBottom}px` : '10px' }; return styles; } // SKS13MAR25 table popup conformation based element add onClose() { this.isSelectTablePopup = false; this.addTable = false; this.addElement(this.currentType); } // SKS13MAR25 column element add inside a table addOnTable() { this.addTable = true; this.isSelectTablePopup = false; const elements = [...this.formBuilderService.getElements()]; // Find the element and update its columns const index = elements.findIndex(el => el.id === this.selectedElement.id); const rowNum = this.formElements[index].columns ? this.formElements[index].columns?.length : 0; const unique_id = uuidv4(); const tableElement = { label: `Header Lable ${rowNum}`, fieldName: `fieldName${rowNum}`, type: this.currentType, id: unique_id }; this.formBuilderService.addTableElement(tableElement, this.selectedFieldIndex); this.formElements = this.formBuilderService.getElements(); // SKS19MAR25 fieldsmeta checking this.formElements = this.formElements.map(ele => { if (ele.type === 'Table') { ele.fieldsMeta = typeof ele.fieldsMeta === 'string' ? ele.fieldsMeta : JSON.stringify(ele.fieldsMeta || []); } return ele; }); // this.addTableData(unique_id, fieldName) } addTableData(fieldId, fieldName) { // this.formBuilderService.addTablefieldData(tableElement); } columnSelected(event) { // console.log(event) // SKS19MAR25 table column update this.formBuilderService.setSelectedTableElement(this.selectedFieldIndex, event); } removeColumn(event) { // console.log(event) this.formBuilderService.removeSelectedTableElement(this.selectedFieldIndex, event); } // SKS25MAR25 image add async fileChangeEvent(index, event) { const file = event.target.files[0]; if (file) { try { const imageData = await this.readFileAsDataURL(file); this.formElements[index].imageData = imageData; this.formElements[index].orgImageData = imageData; // Initialize logo size if not already set if (!this.formElements[index].imageSize) { this.formElements[index].imageSize = { width: 150, height: 150 }; } await this.formBuilderService.elementUpdate(index, this.formElements[index]); } catch (error) { console.error("Error reading file:", error); } } } readFileAsDataURL(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result); reader.onerror = (error) => reject(error); reader.readAsDataURL(file); }); } // SKS2APR25 disabled element isElementDisabled(elementType) { if (this.selectedElement) { const elements = this.elementDisabledArray[this.selectedElement.type]; if (elements) { return elements.includes(elementType); } } return false; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ElementComponent, deps: [{ token: i1.FormBuilderService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ElementComponent, selector: "app-element", inputs: { bookletJSON: "bookletJSON", bookletId: "bookletId" }, usesOnChanges: true, ngImport: i0, template: "<!-- AP 22JAN25 - form preview and All form elements -->\n<!-- AP 25FEB25 - All elements update -->\n<div class=\"center-frame\">\n <!-- Form Builder Section All Elements -->\n <div class=\"form-builder\">\n <!-- Basic Elements Toggle -->\n <div class=\"toggle-header\" (click)=\"toggleSection('basic')\">\n <div class=\"head-elements\">Basic Elements</div>\n <img [src]=\"sections.basic ? '../assets/icons/arrow-down.svg' : '../assets/icons/arrow-right.svg'\"\n alt=\"Toggle Arrow\" class=\"arrow-icon\">\n </div>\n\n <div *ngIf=\"sections.basic\">\n <ng-container *ngFor=\"let element of basicElements\">\n <div class=\"element\" [class.disabled]=\"isElementDisabled(element.type)\"\n (click)=\"!isElementDisabled(element.type) && addElement(element.type)\"\n [draggable]=\"!isElementDisabled(element.type)\" [matTooltip]=\"isElementDisabled(element.type) ? 'This element is not supported when a ' + (selectedElement?.type || 'certain element') + ' is present' : null\">\n <img src=\"../assets/icons/{{ element.img }}.svg\" class=\"element-icon\">\n <div class=\"hover-label\">{{ element.label }}</div>\n <div class=\"drag-dots\">\n <div class=\"dot\" *ngFor=\"let dot of dots\"></div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- Advanced Elements Toggle -->\n <div class=\"toggle-header\" (click)=\"toggleSection('advanced')\">\n <div class=\"head-elements\">Advanced Elements</div>\n <img [src]=\"sections.advanced ? '../assets/icons/arrow-down.svg' : '../assets/icons/arrow-right.svg'\"\n alt=\"Toggle Arrow\" class=\"arrow-icon\">\n </div>\n\n <div *ngIf=\"sections.advanced\">\n <ng-container *ngFor=\"let element of advancedElements\">\n <div class=\"element\" [class.disabled]=\"isElementDisabled(element.type)\"\n (click)=\"!isElementDisabled(element.type) && addElement(element.type)\"\n [draggable]=\"!isElementDisabled(element.type)\" [matTooltip]=\"isElementDisabled(element.type) ? 'This element is not supported when a ' + (selectedElement?.type || 'certain element') + ' is present' : null\">\n <img src=\"../assets/icons/{{ element.img }}.svg\">\n <div class=\"hover-label\">{{ element.label }}</div>\n <div class=\"drag-dots\">\n <div class=\"dot\" *ngFor=\"let dot of dots\"></div>\n </div>\n </div>\n </ng-container>\n </div>\n\n <!-- SKS10MAR25 footer version show -->\n <div class=\"sticky-footer-version\">\n {{version}}\n </div>\n </div>\n <!-- AP-27MAR25 Remove CDK drag and drop replace draggable function -->\n <div class=\"form-preview\">\n <!-- AP-10MAR25 Heading -->\n <div class=\"field-container\"\n style=\"width: 100%;background-color: #EFF8FF; border: 1px solid #E6F3FF;display: flex;justify-content: center;margin-bottom:10px\"\n (click)=\"selectHeading('Header')\">\n <div class=\"label-container\" style=\"padding: 10px;\">\n <div *ngIf=\"book?.records\">\n <div *ngIf=\"book.records[0].title == ''\" style=\"color:#3f4a525c\">Heading</div>\n <div *ngIf=\"book.records[0].title !== ''\">{{book.records[0].title}}</div>\n </div>\n </div>\n </div>\n\n <ng-container *ngFor=\"let field of formElements; let i = index\" getProperties().elementProps>\n\n <!-- TextBox -->\n <div *ngIf=\"field.type === 'Text'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isOptional\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Label' }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <input type=\"text\" class=\"custom-input\" [placeholder]=\"field.question || 'Enter text'\"\n [readonly]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\"\n [value]=\"field.defaultValue ? field.defaultValue : '' \" />\n </div>\n </div>\n </div>\n\n <!-- AP-19MAR25 Line Element -->\n <div *ngIf=\"field.type === 'Line'\" class=\"line-field\" (click)=\"selectElement(i)\"\n [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\" (dragstart)=\"onDragStart($event, i)\"\n (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"line-element\">\n <div></div>\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n <hr class=\"custom-line\" style=\"display: inline-flex\" [ngStyle]=\"getLineStyles(field)\" />\n </div>\n\n <!--SKS25MAR25 Image Upload Element -->\n <div *ngIf=\"field.type === 'Image'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\" (dragstart)=\"onDragStart($event, i)\"\n (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\" [ngStyle]=\"getFontStyles(field)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Upload Image' }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <div>\n <div class=\"logo-container\">\n <!-- Logo preview area -->\n <div class=\"logo-preview\" *ngIf=\"field.imageData\">\n <img [src]=\"field.imageData\" />\n </div>\n\n <!-- Upload button -->\n <div *ngIf=\"!field.imageData\" class=\"logo-upload-placeholder\">\n <label for=\"logo-upload-{{i}}\" class=\"logo-upload-label\">\n <img src=\"../assets/icons/Image.svg\" alt=\"Upload\" />\n <span>Upload Image</span>\n </label>\n <input type=\"file\" id=\"logo-upload-{{i}}\" accept=\"image/*\" (change)=\"fileChangeEvent(i, $event)\"\n style=\"display: none;\" />\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Space Element -->\n <div *ngIf=\"field.type === 'Space'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\" style=\"height:93px\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <label [class.required]=\"field.isRequired\"></label>\n <div class=\"top-right\" style=\"margin: -11px -11px 0 0;\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Boolean Element -->\n <div *ngIf=\"field.type === 'Boolean'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{ field.questionText\n ? field.questionText : 'Boolean'}}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <input type=\"checkbox\" [checked]=\"field.boolean\" (change)=\"toggleBoolean(field)\"\n [value]=\"field.defaultValue ? field.defaultValue : ''\" />\n </div>\n </div>\n\n <!-- Calendar -->\n <div *ngIf=\"field.type === 'Calendar'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Select Date'\n }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n\n </div>\n <input type=\"date\" class=\"custom-input\" [readonly]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\"\n [value]=\"field.defaultValue ? field.defaultValue : ''\" />\n </div>\n </div>\n </div>\n\n <!-- AP -12MAR25 Date -->\n <div *ngIf=\"field.type === 'Date'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Select Date'\n }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n\n </div>\n <input type=\"date\" class=\"custom-input\" [readonly]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\"\n [value]=\"field.defaultValue ? field.defaultValue : ''\" />\n </div>\n </div>\n </div>\n\n <!-- AP-21MAR25 Add Time element -->\n <!-- Time Field -->\n <div *ngIf=\"field.type === 'Time'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <label [class.required]=\"field.isRequired\">{{ field.questionText ? field.questionText : 'Time' }}</label>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <input type=\"time\" class=\"custom-input\" [readonly]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\"\n [value]=\"field.defaultValue ? field.defaultValue : ''\" />\n </div>\n </div>\n </div>\n\n <!-- AP-28MAR25 DateTime -->\n <div *ngIf=\"field.type === 'DateTime'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Select Date & Time'\n }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <input type=\"datetime-local\" class=\"custom-input\" [readonly]=\"field.isReadOnly\"\n [class.hidden]=\"field.isHidden\" />\n </div>\n </div>\n </div>\n\n <!-- Email -->\n <div *ngIf=\"field.type === 'Email'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\"> {{ field.questionText ? field.questionText : 'Label' }}\n </label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <input type=\"email\" class=\"custom-input\" [placeholder]=\"field.question || 'Enter email'\"\n [readonly]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\"\n [value]=\"field.defaultValue ? field.defaultValue : ''\" />\n </div>\n </div>\n </div>\n\n <!-- Numbers -->\n <div *ngIf=\"field.type === 'Number'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Label' }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <input type=\"number\" class=\"custom-input\" [placeholder]=\"field.question || 'Enter number'\"\n [readonly]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\"\n [value]=\"field.defaultValue ? field.defaultValue : ''\" />\n </div>\n </div>\n </div>\n\n <!-- TextArea -->\n <div *ngIf=\"field.type === 'TextArea'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Enter your text'}}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <textarea class=\"custom-textarea\" [placeholder]=\"field.question || 'Enter detailed text here...'\"\n [style.height.px]=\"field.size || 100\" [readonly]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\"\n [value]=\"field.defaultValue ? field.defaultValue : ''\"></textarea>\n </div>\n </div>\n </div>\n\n <!-- RichText -->\n <div *ngIf=\"field.type === 'RichTextArea'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Enter your text'}}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <textarea class=\"custom-textarea\" [placeholder]=\"field.question || 'Enter detailed text here...'\"\n [style.height.px]=\"field.size || 100\" [readonly]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\"\n [value]=\"field.defaultValue ? field.defaultValue : ''\"></textarea>\n </div>\n </div>\n </div>\n\n <!-- Label -->\n <div *ngIf=\"field.type === 'Label'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Label' }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Book -->\n <div *ngIf=\"field.type === 'Book'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Label' }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <lib-booklet [bookletJSON]=\"field.qbReferenceQuestions\"></lib-booklet>\n </div>\n </div>\n </div>\n\n <!-- File -->\n <div *ngIf=\"field.type === 'File'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Upload File'\n }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <input type=\"file\" class=\"custom-input\" [readonly]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\" />\n </div>\n </div>\n </div>\n\n <!-- CheckBox -->\n <div *ngIf=\"field.type === 'Checkbox'\" class=\"checkbox-field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">\n {{ field.questionText ? field.questionText : 'Label' }}\n </label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n\n <div class=\"checkbox-options-container\">\n <div *ngFor=\"let option of field.options\" class=\"checkbox-option\">\n <input type=\"checkbox\" [id]=\"option.value + i\" [name]=\"field.id\"\n [value]=\"option.value || field.defaultValue\" class=\"checkbox-input\" [disabled]=\"field.isReadOnly\"\n [class.hidden]=\"field.isHidden\">\n <label [for]=\"option.value + i\" class=\"checkbox-label\">{{ option.value }}</label>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Radio -->\n <div *ngIf=\"field.type === 'Radio'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Label' }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <div class=\"radio-options-container\">\n <div *ngFor=\"let option of field.options; let j = index\" class=\"radio-option\">\n <input type=\"radio\" [id]=\"'radio-' + field.id + '-' + j\" [name]=\"'radio-group-' + field.id\"\n [value]=\"option.value || field.defaultValue\" [(ngModel)]=\"field.selectedValue\" class=\"radio-input\"\n [disabled]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\">\n <label [for]=\"'radio-' + field.id + '-' + j\" class=\"radio-label\"> {{ option.value }}</label>\n </div>\n </div>\n </div>\n </div>\n </div>\n <!-- Dropdown -->\n <div *ngIf=\"field.type === 'Dropdown'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Label' }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <select id=\"options\" class=\"dropdown\" [disabled]=\"field.isReadOnly\" [class.hidden]=\"field.isHidden\">\n <option *ngFor=\"let option of field.options\" [value]=\"option.value || field.defaultValue\"> {{ option.value\n }} </option>\n </select>\n </div>\n </div>\n </div>\n\n <!-- Table -->\n <!-- AP-06MAR25 -->\n <div *ngIf=\"field.type === 'Table'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\" style=\"overflow: hidden;\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Label' }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <div class=\"nxt-table-container\">\n <nxt-datatable isButtons [question]=\"field\" from=\"formBuilder\" [apiMeta]=\"field.subText\"\n [tableConfig]=\"field.tableConfig\" tableId=\"\" direction=\"ltr\" tableWidth=\"auto\" isEditable=true\n (columnSelected)=columnSelected($event) (removeColumn)=removeColumn($event)>\n </nxt-datatable>\n </div>\n </div>\n </div>\n </div>\n\n <!-- List -->\n <!-- AP-06MAR25 - List data show-->\n <div *ngIf=\"field.type === 'List'\" class=\"field-container\" (click)=\"selectElement(i)\"\n [ngStyle]=\"getFontStyles(field)\" [class.highlight]=\"selectedFieldIndex === i\" draggable=\"true\"\n (dragstart)=\"onDragStart($event, i)\" (dragover)=\"onDragOver($event, i)\" (drop)=\"onDrop($event, i)\">\n <div class=\"field-wrapper\">\n <div class=\"field-content\">\n <div class=\"label-container\">\n <div>\n <label [class.required]=\"field.isRequired\" *ngIf=\"field.style?.showLabel !== false\">{{\n field.questionText ? field.questionText : 'Label' }}</label>\n </div>\n <div class=\"top-right\">\n <img src=\"../assets/icons/drag-dots.svg\" alt=\"Drag\" class=\"drag-dot\" />\n <img src=\"../assets/icons/Trash.svg\" (click)=\"removeElement(field, i)\" class=\"delete-icon\" />\n </div>\n </div>\n <input type=\"text\" class=\"custom-input\" placeholder=\"Search...\" [readonly]=\"field.isReadOnly\"\n [class.hidden]=\"field.isHidden\" [value]=\"field.defaultValue ? field.defaultValue : ''\" />\n </div>\n </div>\n </div>\n\n </ng-container>\n </div>\n</div>\n<!-- SKS13MAR25 popup conformation box -->\n<div class=\"dialog-overlay\" *ngIf=\"isSelectTablePopup\">\n <div class=\"dialog-box\">\n <button class=\"close-btn-fb\" (click)=\"onClose()\">\u2715</button>\n <p>These element want to add a table</p>\n <div class=\"b