diff --git a/package-lock.json b/package-lock.json index 9d9626f..0e816f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.3.0", "license": "ISC", "dependencies": { - "basiscore": "^2.38.0" + "basiscore": "^2.38.6" }, "devDependencies": { "@types/dragula": "^3.7.1", @@ -771,9 +771,9 @@ "dev": true }, "node_modules/basiscore": { - "version": "2.38.0", - "resolved": "https://registry.npmjs.org/basiscore/-/basiscore-2.38.0.tgz", - "integrity": "sha512-cddL3uAFC2IfGO5YYvrpT2qnpnFtAEQg8ftua1z6dGyrQTo+FllvmTSRP8WBhjJbOC/YDr9UkuL6kpF9qY6yMw==", + "version": "2.38.6", + "resolved": "https://registry.npmjs.org/basiscore/-/basiscore-2.38.6.tgz", + "integrity": "sha512-Z61Zs9bYMn7oUXoy+JydhBBRwjQvWE6OPF5IsNtHoZqRVaL5sjrfP8+RvHPMfE3JWRMcDurVqIignFWah4Y7mg==", "dependencies": { "@types/pako": "^2.0.3", "alasql": "^1.7.3", diff --git a/package.json b/package.json index 3ff5062..4bbce28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "schema-maker", - "version": "1.3.0", + "version": "2.0.0", "description": "Simple client side component for create schema in base of Manzoomeh Negaran schema standard.", "main": "schema-maker.js", "types": "schema-maker.d.ts", @@ -48,6 +48,6 @@ "webpack-dev-server": "^4.7.3" }, "dependencies": { - "basiscore": "^2.38.0" + "basiscore": "^2.38.6" } } diff --git a/server/schema-server.js b/server/schema-server.js index 2dbc402..f8314e4 100644 --- a/server/schema-server.js +++ b/server/schema-server.js @@ -67,7 +67,7 @@ router.get("/add-to-log", async function (req, res) { router.post("/chatnormal", (req, res) => { return res.json({ - "data":"با توجه به دوران زمان کمپین، از 10 تا 20 اسفند ماه 1403 فرصت دارید تا با 49% تخفیف از بیسیس پنل خرید کنید و بسیاری از مشکلات سال آینده را با کمک هوش مصنوعی حل کنید. همچنین، با خرید مجموعه‌ای از امکانات بیسیس پنل (حداقل 50 میلیون تومان)، از گارانتی بدون سوال تا 3 ماه بهره‌مند خواهید شد. این یعنی شما می‌توانید با استفاده از تمام امکانات بیسیس پنل و به ویژه دستیار هوش مصنوعی که قابلیت اتصال به CRM را دارد، آینده سازمان خود را به راحتی برنامه‌ریزی کرده و از خدمات ما با خیالی آسوده بهره‌برداری کنید. توجه: به دلیل شرایط ویژه این کمپین، در حال حاضر امکان ارائه دسترسی‌های محدود برای آشنایی با امکانات پنل وجود ندارد. اما علاقه‌مندان می‌توانند با استفاده از تخفیف‌های ویژه و گارانتی بازگشت پول بدون سوال، از خدمات ما بهره‌مند شوند و در صورت عدم رضایت، پول خود را بازگشت دهند. این فرصت استثنایی به شما این امکان را می‌دهد که از تمام پتانسیل‌های بیسیس پنل برای بهبود عملکرد سازمان خود بهره‌مند شوید.", + "message":"با توجه به دوران زمان کمپین، از 10 تا 20 اسفند ماه 1403 فرصت دارید تا با 49%", "json" : false }) }) diff --git a/src/components/ai/AIComponent.ts b/src/components/ai/AIComponent.ts index d3ac6e0..29b588b 100644 --- a/src/components/ai/AIComponent.ts +++ b/src/components/ai/AIComponent.ts @@ -4,37 +4,25 @@ import layout from "./assets/layout.html"; import "./assets/style.css"; import ToolboxModule from "../modules/base-class/ToolboxModule"; import IWorkspaceComponent from "../workspace/IWorkspaceComponent"; -import WorkspaceComponent from "../workspace/WorkspaceComponent"; -import CreateUI from "../workspace/createUI"; -import * as Prism from "prismjs"; import { IToken } from "basiscore"; -import SchemaMakerComponent from "../schema-maker/SchemaMakerComponent"; -import IModuleFactory from "../modules/IModuleFactory"; -export default class AIcomponent extends ComponentBase - - { - private createUICom : CreateUI - private timeoutId; - private _rkey : string ; - private _aiUrl:string; - private chatInput : HTMLInputElement; +export default class AIcomponent extends ComponentBase { + private timeoutId; + private _rkey: string; + private _aiUrl: string; + private chatInput: HTMLInputElement; public _internalSourceId: string; - private workSpace : WorkspaceComponent private resultSourceIdToken: IToken; - + private readonly _modules: Map = new Map< - number, - - ToolboxModule ->(); + number, + ToolboxModule + >(); constructor(owner: IUserDefineComponent) { super(owner, layout, "data-bc-sm-workspace-container"); - this.createUICom = new CreateUI(owner, this) } public async initializeAsync(): Promise { - this._rkey= await this.owner.getAttributeValueAsync("rkey") - this._aiUrl = await this.owner.getAttributeValueAsync("aiUrl") + this._aiUrl = await this.owner.getAttributeValueAsync("aiUrl"); this.resultSourceIdToken = this.owner.getAttributeToken("resultSourceId"); const resultSourceId = await this.resultSourceIdToken?.getValueAsync(); this._internalSourceId = this.owner.getRandomName(resultSourceId); @@ -54,65 +42,70 @@ export default class AIcomponent extends ComponentBase // ); // schemaCommand.parentElement.appendChild(script_tag); // scriptElement.remove(); - } - public async runAsync(source?: ISource, ) { - + public async runAsync(source?: ISource) { this.crateUI(); - } - crateUI(){ - - const sendMessageButton : HTMLElement = this.container.querySelector(".SendMessage") - this.chatInput = this.container.querySelector("#chat") - const firstSection : HTMLElement = this.container.querySelector(".MESection") - const chatInputSection :HTMLElement = this.container.querySelector(".chatInputBox") - sendMessageButton.addEventListener("click" , (e) => { - - firstSection.style.display="none" - chatInputSection.classList.add("extend_chat_box") - this.sendMessage(this.chatInput.value) - } ) - this.chatInput.addEventListener("keydown", (e) => { - if (e.key === 'Enter') { //checks whether the pressed key is "Enter" - firstSection.style.display="none" - chatInputSection.classList.add("extend_chat_box") - if (e.shiftKey) { - this.insertNewLine(); - e.preventDefault(); // Prevent the default behavior - // Allow Shift + Enter to insert a new line in the textarea - // No need to call preventDefault() here, as the default behavior is what we want - } - - else{ - e.preventDefault(); - if (this.chatInput.value != '') { + crateUI() { + const sendMessageButton: HTMLElement = + this.container.querySelector(".SendMessage"); + this.chatInput = this.container.querySelector("#chat"); + const firstSection: HTMLElement = + this.container.querySelector(".MESection"); + const chatInputSection: HTMLElement = + this.container.querySelector(".chatInputBox"); + sendMessageButton.addEventListener("click", (e) => { + firstSection.style.display = "none"; + chatInputSection.classList.add("extend_chat_box"); + this.sendMessage(this.chatInput.value); + }); + this.chatInput.addEventListener("keydown", (e) => { + const sendButton = this.container.querySelector(".SendMessage") + sendButton.classList.add("send_button_active") + if(this.chatInput.value.length > 3 ){ + if (e.key === "Enter") { + //checks whether the pressed key is "Enter" + firstSection.style.display = "none"; + chatInputSection.classList.add("extend_chat_box"); + if (e.shiftKey) { + this.insertNewLine(); + e.preventDefault(); // Prevent the default behavior + } + else { + e.preventDefault(); + if (this.chatInput.value != "") { this.sendMessage(this.chatInput.value); - this.chatInput.value = ''; + this.chatInput.value = ""; + } } } } - }); + else{ + sendButton.classList.remove("send_button_active") + } + + }); } - async sendMessage(value:string ){ - const submitButton = document.querySelector(".SendMessageMain") - const stopBtn = document.createElement("div") - stopBtn.classList.add("stop-btn") - stopBtn.innerHTML = `` - stopBtn.addEventListener("click" , function(){ - // stopWriter() - - }) + async sendMessage(value: string) { + const currentDiv = this.container.querySelector("#current_section"); + const sendButton = this.container.querySelector(".SendMessage") + sendButton.classList.remove("send_button_active") + const submitButton = document.querySelector(".SendMessageMain"); + const stopBtn = document.createElement("div"); + stopBtn.classList.add("stop-btn"); + stopBtn.innerHTML = ``; + stopBtn.addEventListener("click", function () { + // stopWriter() + }); submitButton?.parentNode.insertBefore(stopBtn, submitButton.nextSibling); - // document.querySelector('.loadChatSection ').style.overflowY='auto' - - - // opacityIcon(chatvalue,true) + // document.querySelector('.loadChatSection ').style.overflowY='auto' + + // opacityIcon(chatvalue,true) - let chatvalue2: HTMLInputElement = this.container.querySelector("#chat") - const newDiv = document.createElement("div") - newDiv.setAttribute("class" , "user_question") + let chatvalue2: HTMLInputElement = this.container.querySelector("#chat"); + const newDiv = document.createElement("div"); + newDiv.setAttribute("class", "user_question"); newDiv.innerHTML = ` basis @@ -126,21 +119,33 @@ export default class AIcomponent extends ComponentBase - ` - this.container.querySelector("#chatbox").appendChild(newDiv) + + `; + const loadingDiv = document.createElement("div") + loadingDiv.classList.add("schemamaker_istyping_loading") + loadingDiv.innerHTML = `is typing + + + + ` + this.container.querySelector("#chatbox").appendChild(newDiv); + this.container.querySelector("#chatbox").appendChild(loadingDiv); + const messageResult = await this.requestJsonAsync(this._aiUrl, "POST", { - message: chatvalue2.value + message: chatvalue2.value, }); - - if(messageResult.json == true){ - - - // note: be care for last parameter - const newDiv = document.createElement("div") - newDiv.setAttribute("class" , "bot_answer") - const viewButton = document.createElement("button") - viewButton.textContent = "مشاهده فرم" - viewButton.classList.add("button-view-schema") + + if (messageResult.json == true) { + const loaderElement = this.container.querySelector(".schemamaker_istyping_loading"); + if (loaderElement) { + loaderElement.remove() + } + // note: be care for last parameter + const newDiv = document.createElement("div"); + newDiv.setAttribute("class", "bot_answer"); + const viewButton = document.createElement("button"); + viewButton.textContent = "مشاهده فرم"; + viewButton.classList.add("button-view-schema"); newDiv.innerHTML = ` basis @@ -153,202 +158,207 @@ export default class AIcomponent extends ComponentBase - ` - newDiv.appendChild(viewButton) - this.container.querySelector("#chatbox").appendChild(newDiv) - const formElements = document.querySelectorAll("[data-bc-sm-question-module]") - - - viewButton.addEventListener("click" , (e) => { - - this.createUICom.createUIFromQuestionSchema(messageResult.message, this.container, true); - const designTab :HTMLElement= document.querySelector('[data-bc-sm-tab-button="sm-design-tab"]') - designTab.click() - // note : the document.querySelector is wrong - - const newJson = JSON.stringify(messageResult.message, null, 4); - - const html = Prism.highlight(newJson, Prism.languages.json, "json"); - document.querySelector( - "[data-bc-sm-preview-json]" - ).innerHTML =html; - const rowsParent = document.querySelector('[data-drop-acceptable-container-schema-type]') - const rows = rowsParent.querySelectorAll('[data-schema-type="question"]') - - rows.forEach(el => { - - var schemaId = el.getAttribute("data-schema-Id"); - const owner : HTMLElement = el as HTMLElement - const factory = this.owner.dc.resolve("IModuleFactory"); - - const module = factory.create(schemaId, owner, this, false, false); - this._modules.set(module.usedForId, module); + `; + newDiv.appendChild(viewButton); + this.container.querySelector("#chatbox").appendChild(newDiv); + const formElements = document.querySelectorAll( + "[data-bc-sm-question-module]" + ); + + viewButton.addEventListener("click", async (e) => { + const workspaceComponent = + this.owner.dc.resolve("WorkspaceComponent"); + this.owner.setSource( + workspaceComponent.SourceId, + messageResult.message + ); + await workspaceComponent.generateAndSetQuestionSchema( + messageResult.message + ); + const designTab: HTMLElement = document.querySelector( + '[data-bc-sm-tab-button="sm-design-tab"]' + ); + designTab.click(); + }); - }) - - }) - - // try { - + // } catch (error) { // console.log("erro" , error) // } - } - else{ - const newDiv = document.createElement("div") - newDiv.setAttribute("class" , "bot_answer") + } else { + + const newDiv = document.createElement("div"); + newDiv.setAttribute("class", "bot_answer"); newDiv.innerHTML = ` basis - +
- ` - stopBtn.classList.add("stop-btn") - stopBtn.innerHTML = `` - stopBtn.addEventListener("click" , (e) => { - this.stopWriter() + `; + stopBtn.classList.add("stop-btn"); + stopBtn.innerHTML = ``; + stopBtn.addEventListener("click", (e) => { - }) - document.querySelector(".chatInputBox ").appendChild(stopBtn) - this.container.querySelector("#chatbox").appendChild(newDiv) + + this.stopWriter(); + }); + document.querySelector(".chatInputBox ").appendChild(stopBtn); + this.container.querySelector("#chatbox").appendChild(newDiv); + const currentDiv = this.container.querySelector("#current_section") - this.startTypewriter(messageResult.data, currentDiv); + this.startTypewriter(messageResult.message, currentDiv); + } - chatvalue2.value="" - document.querySelector("#current_section")?.removeAttribute("id") - -// scrollToBottom() - -} -async requestJsonAsync( - url: string, - method: "POST" | "GET" = "GET", - data?: object -): Promise { - const init: any = { - method: method - }; - if (data) { - init.body = JSON.stringify(data); + chatvalue2.value = ""; + + document.querySelector("#current_section")?.removeAttribute("id"); + + // scrollToBottom() + } + async requestJsonAsync( + url: string, + method: "POST" | "GET" = "GET", + data?: object + ): Promise { + const init: any = { + method: method, + }; + if (data) { + init.body = JSON.stringify(data); + } + const response = await fetch(url, init); + const result = await response.json(); + return result; } - const response = await fetch(url, init); - const result = await response.json(); - return result; -} - - - - -public getComponent(): IUserDefineComponent { - return this.owner; -} -public onRemove(moduleId: number) {} -public getModule(moduleId: number): ToolboxModule { - return this._modules.get(moduleId); -} -private removeSpanAndBrTags(str) { - return str.replace(/<\/?(span|br|div)\b[^>]*>/g, ""); -} + public getComponent(): IUserDefineComponent { + return this.owner; + } + public onRemove(moduleId: number) {} + public getModule(moduleId: number): ToolboxModule { + return this._modules.get(moduleId); + } + private removeSpanAndBrTags(str) { + return str.replace(/<\/?(span|br|div)\b[^>]*>/g, ""); + } -private startTypewriter (text: string, containerId: Element): void { - const typewriterElement =containerId; + private startTypewriter(text: string, containerId: Element): void { + const loading_section = this.container.querySelector(".schemamaker_istyping_loading") + if(loading_section){ + loading_section?.remove() + } + + const typewriterElement = containerId; if (!typewriterElement) { - console.error(`Element with id ${containerId} not found.`); + console.error(`Element with id ${containerId} not found.`); - return; + return; } let index = 0; const loaderElement = typewriterElement.querySelector(".typing-loader"); if (loaderElement) { - loaderElement.classList.remove("typing-loader"); + loaderElement.classList.remove("typing-loader"); } - typewriterElement.innerHTML = ''; // Clear previous content + typewriterElement.innerHTML = ""; // Clear previous content const typeWriter = (): void => { - if (index < text.length) { - const char = text.charAt(index); - - // Handle ** for

- if (char === '*' && text.charAt(index + 1) === '*') { - index += 2; // Skip the ** - - const h2Element = document.createElement('h2'); - typewriterElement.appendChild(h2Element); - - let h2Text = ''; - while (index < text.length && !(text.charAt(index) === '*' && text.charAt(index + 1) === '*')) { - h2Text += text.charAt(index); - index++; - } - - let h2Index = 0; - const typeH2 = (): void => { - if (h2Index < h2Text.length) { - h2Element.textContent += h2Text.charAt(h2Index); - h2Index++; - const delay = h2Text.charAt(h2Index - 1) === ' ' ? 50 : 10; - this.timeoutId = setTimeout(typeH2, delay); - } else { - index += 2; // Skip the closing ** - this.timeoutId = setTimeout(typeWriter, 10); - } - }; + if (index < text.length) { + + const loadingPart = this.container.querySelector(".schemamaker_istyping_loading") + if(loadingPart){ + loadingPart.remove() + } + + const char = text.charAt(index); + + // Handle ** for

+ if (char === "*" && text.charAt(index + 1) === "*") { + index += 2; // Skip the ** + + const h2Element = document.createElement("h2"); + typewriterElement.appendChild(h2Element); + + let h2Text = ""; + while ( + index < text.length && + !(text.charAt(index) === "*" && text.charAt(index + 1) === "*") + ) { + h2Text += text.charAt(index); + index++; + } - typeH2(); + let h2Index = 0; + const typeH2 = (): void => { + if (h2Index < h2Text.length) { + h2Element.textContent += h2Text.charAt(h2Index); + h2Index++; + const delay = h2Text.charAt(h2Index - 1) === " " ? 50 : 10; + this.timeoutId = setTimeout(typeH2, delay); + } else { + index += 2; // Skip the closing ** + this.timeoutId = setTimeout(typeWriter, 10); } - // Handle newlines (\r\n) for

- else if (char === '\r' && text.charAt(index + 1) === '\n') { - index += 2; // Skip the \r\n + }; - const pElement = document.createElement('p'); - typewriterElement.appendChild(pElement); + typeH2(); + } + // Handle newlines (\r\n) for

+ else if (char === "\r" && text.charAt(index + 1) === "\n") { + index += 2; // Skip the \r\n - this.timeoutId = setTimeout(typeWriter, 10); - } else { - if (!typewriterElement.lastElementChild || typewriterElement.lastElementChild.tagName === 'H2') { - const divElement = document.createElement('div'); - typewriterElement.appendChild(divElement); - } - typewriterElement.lastElementChild.textContent += char; - index++; - const delay = char === ' ' ? 50 : 10; - this.timeoutId = setTimeout(typeWriter, delay); - } - } else if (index === text.length) { - // clearStopBtn(); // Assuming this is a function defined elsewhere + const pElement = document.createElement("p"); + typewriterElement.appendChild(pElement); + + this.timeoutId = setTimeout(typeWriter, 10); } else { - const h2Elements = document.querySelectorAll('h2'); - h2Elements.forEach((h2) => { - h2.style.borderRight = 'none'; - }); + if ( + !typewriterElement.lastElementChild || + typewriterElement.lastElementChild.tagName === "H2" + ) { + const divElement = document.createElement("div"); + typewriterElement.appendChild(divElement); + } + typewriterElement.lastElementChild.textContent += char; + index++; + const delay = char === " " ? 50 : 10; + this.timeoutId = setTimeout(typeWriter, delay); } + } else if (index === text.length) { + + this.clearStopBtn(); + // clearStopBtn(); // Assuming this is a function defined elsewhere + } else { + const h2Elements = document.querySelectorAll("h2"); + h2Elements.forEach((h2) => { + h2.style.borderRight = "none"; + }); + } }; // Start the typewriter effect typeWriter(); -}; -stopWriter (){ - clearTimeout(this.timeoutId); - this.clearStopBtn(); -} -clearStopBtn(){ - const stopButton: HTMLElement = this.container.querySelector(".stop-btn") - stopButton.remove() -} - insertNewLine() { - let currentValue = this.chatInput.value; - let updatedValue = currentValue + '\n'; - this.chatInput.value = updatedValue; -} - + } + stopWriter() { + clearTimeout(this.timeoutId); + + this.clearStopBtn(); + } + clearStopBtn() { + const stopButton: HTMLElement = this.container.querySelector(".stop-btn"); + stopButton.remove(); + } + insertNewLine() { + let currentValue = this.chatInput.value; + let updatedValue = currentValue + "\n"; + this.chatInput.value = updatedValue; + } } diff --git a/src/components/ai/assets/style.css b/src/components/ai/assets/style.css index 4ff82dd..913a60a 100644 --- a/src/components/ai/assets/style.css +++ b/src/components/ai/assets/style.css @@ -18,7 +18,7 @@ } [data-bc-chatSection-sm] .chatInputBox{ position: relative; - transition: all 1s ease-in-out; + /* transition: all 1s ease-in-out; */ } [data-bc-chatSection-sm] .SendMessage{ position: absolute; @@ -27,8 +27,8 @@ cursor: pointer; z-index: 999; opacity: 0.5; - - /* pointer-events: none; */ + cursor: pointer; + pointer-events: none; } [data-bc-chatSection-sm] #chat{ direction: rtl; @@ -37,6 +37,8 @@ padding-top: 10px; width: 500px; height: 90px; + border: 1px solid rgb(200 204 207 / var(--tw-border-opacity, 1)); + font-size: 14px; } [data-bc-chatSection-sm] .chatNodata{ padding-top: 10px;padding-left: 50px;padding-left: 50px; @@ -61,11 +63,14 @@ display: flex; direction: rtl; gap: 15px; + align-items: center; } [data-bc-chatSection-sm] .userDetail{ display: flex; flex-direction: column; justify-content: center; + direction: rtl; + text-align: right; } #chatbox{ width: 100%; @@ -103,3 +108,48 @@ left: 60px; cursor: pointer; } +#chat:focus { + outline-width: 0; + outline: none; +} +.user_question .userName{ + text-align: right; +} +.send_button_active{ + opacity: 1 !important; + pointer-events: all !important; +} +.jumping-dots span { + position: relative; + bottom: 0px; + display: inline-block; + width: 3px; + height: 3px; + background-color: #ccc; + animation: jump 2s infinite; + border-radius: 50%; +} +.jumping-dots .dot-1{ + animation-delay: 200ms; +} +.jumping-dots .dot-2{ + animation-delay: 400ms; +} +.jumping-dots .dot-3{ + animation-delay: 600ms; +} + +@keyframes jump { + 0% {bottom: 0px;} + 20% {bottom: 5px;} + 40% {bottom: 0px;} +} +.schemamaker_istyping_loading{ + direction: rtl !important; + text-align: right !important; +} +.bot_answer .userDetail div{ + direction: rtl !important; + text-align: right !important; + line-height: 30px; +} \ No newline at end of file diff --git a/src/components/schema-maker/SchemaMakerComponent.ts b/src/components/schema-maker/SchemaMakerComponent.ts index feb07bd..bca0570 100644 --- a/src/components/schema-maker/SchemaMakerComponent.ts +++ b/src/components/schema-maker/SchemaMakerComponent.ts @@ -55,14 +55,15 @@ export default class SchemaMakerComponent "defaultQuestionsUrl", "" ); - const rkey = await this.owner.getAttributeValueAsync( - "rkey", - "" - ); + const aiURL = await this.owner.getAttributeValueAsync( "aiUrl", "" ); + const aifeature = await this.owner.getAttributeValueAsync( + "aifeature", + "" + ); const groupsUrl = await this.owner.getAttributeValueAsync("groupsUrl", ""); this.owner.addTrigger([this.sourceId]); this.container.querySelectorAll("basis").forEach((element) => { @@ -76,8 +77,8 @@ export default class SchemaMakerComponent if (element.getAttribute("core") == "component.schemaMaker.workspace") { if (resultSourceId) { element.setAttribute("resultSourceId", resultSourceId); - element.setAttribute("rkey", rkey); element.setAttribute("aiUrl" , aiURL) + element.setAttribute("aifeature" , aifeature) } } // else if (element.getAttribute("core") == "component.schemaMaker.AI") { diff --git a/src/components/workspace/IWorkspaceComponent.ts b/src/components/workspace/IWorkspaceComponent.ts index 290331c..4f41d54 100644 --- a/src/components/workspace/IWorkspaceComponent.ts +++ b/src/components/workspace/IWorkspaceComponent.ts @@ -1,13 +1,14 @@ -import { IQuestionSchema, IUserDefineComponent } from "basiscore"; +import { IQuestionSchema, IUserDefineComponent, SourceId } from "basiscore"; import ToolboxModule from "../modules/base-class/ToolboxModule"; -import ISchemaMakerSchema, { ModuleType } from "../ISchemaMakerSchema"; export default interface IWorkspaceComponent { getComponent(): IUserDefineComponent; onRemove(moduleId: number); getModule(moduleId: number): ToolboxModule; + generateAndSetQuestionSchema(question: IQuestionSchema); + SourceId: SourceId; } export interface IQuestionSchemaBuiltIn extends IQuestionSchema { mid: number; groupHashId: string; -} \ No newline at end of file +} diff --git a/src/components/workspace/WorkspaceComponent.ts b/src/components/workspace/WorkspaceComponent.ts index e2ea4c9..4ddf7ab 100644 --- a/src/components/workspace/WorkspaceComponent.ts +++ b/src/components/workspace/WorkspaceComponent.ts @@ -22,7 +22,6 @@ import ContainerModule from "../modules/ContainerModule"; import * as Prism from "prismjs"; import "../../../node_modules/prismjs/components/prism-json"; import "../../../node_modules/prismjs/themes/prism-coy.css"; -import CreateUI from "./createUI" export default class WorkspaceComponent extends ComponentBase @@ -45,16 +44,19 @@ export default class WorkspaceComponent private _objectTypeUrl: string; private _groupsUrl: string; private _defaultQuestionsUrl: string; - public createUICom : CreateUI - public _rkey : string - public _aiUrl : string + public _aifeature: string; + public _aiUrl: string; + public get SourceId() { + return this._sourceId; + } constructor(owner: IUserDefineComponent) { super(owner, layout, "data-bc-sm-workspace-container"); this._textArea = this.container.querySelector("[data-get-edit-json]"); this.errorContainer = this.container.querySelector("[data-get-edit-error]"); this.initDragula(); - - this.createUICom = new CreateUI(owner, this) + this.owner.dc.registerInstance("WorkspaceComponent", this); + + (window).$wsc = this; } public getModule(moduleId: number): ToolboxModule { @@ -109,7 +111,6 @@ export default class WorkspaceComponent module.usedForId?.toString() ?? "-1" ); this._modules.set(module.usedForId, module); - }; const removeModuleOnSpill = (el: Element) => { @@ -218,11 +219,14 @@ export default class WorkspaceComponent this._saveDraft = (await this.owner.getAttributeValueAsync("saveDraft", "false")) == "true"; this._noAccessToEdit = - (await this.owner.getAttributeValueAsync("noAccessToEdit", "false")) == "true"; + (await this.owner.getAttributeValueAsync("noAccessToEdit", "false")) == + "true"; + + this._sourceId = await this.owner.getAttributeValueAsync("DataMemberName"); - this._rkey= await this.owner.getAttributeValueAsync("rkey") - this._aiUrl= await this.owner.getAttributeValueAsync("aiUrl") - + this._aifeature = await this.owner.getAttributeValueAsync("aifeature"); + this._aiUrl = await this.owner.getAttributeValueAsync("aiUrl"); + this.resultSourceIdToken = this.owner.getAttributeToken("resultSourceId"); this._objectTypeUrl = await this.owner.getAttributeValueAsync( "objectTypeUrl", @@ -261,10 +265,9 @@ export default class WorkspaceComponent } this.container .querySelector("[data-bc-sm-schema-result]") - .addEventListener("click", (e) =>{ - this.delay(this.generateAndSetQuestionSchemaAsync.bind(this), e) - } - ); + .addEventListener("click", (e) => { + this.delay(this.onPreviewBtnClick.bind(this), e); + }); // this.container // .querySelector("[data-bc-sm-save-draft]") @@ -279,7 +282,6 @@ export default class WorkspaceComponent // "click", // this.loadDraft.bind(this, "bc-sm-manually-draft") // ); - // tab event const tabs = this.container.querySelector("[data-bc-sm-tabs]"); @@ -292,12 +294,12 @@ export default class WorkspaceComponent tabButton.forEach((btn) => { btn.addEventListener("click", (e) => { - const currentElement = e.target as Element - - if(currentElement.getAttribute("data-bc-sm-ai") == "true"){ + const currentElement = e.target as Element; + + if (currentElement.getAttribute("data-bc-sm-ai") == "true") { this.cancelEditJson(); } - + const name = (e.target as Element).attributes.getNamedItem( "data-bc-sm-tab-button" ).value; @@ -389,7 +391,7 @@ export default class WorkspaceComponent jsonCopy.setAttribute("data-get-btn-disabled", ""); jsonSave.setAttribute("data-get-btn-disabled", ""); editForm.setAttribute("data-get-btn-disabled", ""); - this.createUICom.createUIFromQuestionSchema(json, this.container,this._noAccessToEdit); + this.createUIFromQuestionSchema(json); } catch (error) { this.errorContainer.style.display = "flex"; this.errorContainer.textContent = error.message; @@ -404,23 +406,6 @@ export default class WorkspaceComponent } } }); - - // note : - // const saveFormFirstTab = this.container.querySelector( - // "[data-bc-sm-save-form-first-tab]" - // ); - // saveFormFirstTab.addEventListener("click" ,async (e) => { - // // this.delay(this.generateAndSetQuestionSchemaAsync.bind(this), e) - // const retVal = await this.generateQuestionSchemaAsync(); - // this.owner.setSource(this._internalSourceId, retVal); - // this._result = retVal as JSON; - - // this.owner.setSource(resultSourceId, this._result); - // console.log("dddd" , retVal) - // // this.createUICom.createUIFromQuestionSchema(this._result, this.container,this._noAccessToEdit); - // }) - - if (resultSourceId && resultSourceId != "") { jsonSave?.addEventListener("click", async (e) => { @@ -428,8 +413,6 @@ export default class WorkspaceComponent this.owner.setSource(resultSourceId, this._result); } }); - - } else if (!resultSourceId || resultSourceId == "") { jsonSave.remove(); } @@ -462,16 +445,29 @@ export default class WorkspaceComponent this.container.querySelector("[data-bc-sm-object-type]").remove(); this.container.querySelector("[data-bc-sm-schema-group]").remove(); } - this.container.querySelectorAll("basis").forEach((element) => { - if (element.getAttribute("core") == "component.schemaMaker.AI") { - if (resultSourceId) { - element.setAttribute("rkey", this._rkey); - element.setAttribute("aiUrl", this._aiUrl); - element.setAttribute("resultSourceId", resultSourceId); - + this.container.querySelectorAll("basis").forEach(async (element) => { + + const hasAiFeature = await this.owner.getAttributeValueAsync("aifeature"); + if(hasAiFeature == "true"){ + if (element.getAttribute("core") == "component.schemaMaker.AI") { + if (resultSourceId) { + element.setAttribute("aiUrl", this._aiUrl); + element.setAttribute("resultSourceId", resultSourceId); + } } } - + else{ + const aiTab = this.container.querySelector('[data-bc-sm-tab-button="sm-ai-tab"]') + const aiBody = this.container.querySelector('[data-bc-sm-tab-section="sm-ai-tab"]') + const designTab = this.container.querySelector('[data-bc-sm-tab-button="sm-design-tab"]') + const designBody = this.container.querySelector('[data-bc-sm-tab-section="sm-design-tab"]') + aiTab.remove() + aiBody.remove() + designTab.setAttribute("data-sys-sm-active-tab","active") + designTab.setAttribute("data-bc-sm-tab-button-mode","active") + designBody.setAttribute("data-bc-sm-tab-section-mode" , "active") + } + }); } @@ -484,7 +480,7 @@ export default class WorkspaceComponent break; } case this._sourceId: { - this.createUICom.createUIFromQuestionSchema(source.rows[0] , this.container,this._noAccessToEdit); + this.createUIFromQuestionSchema(source.rows[0]); break; } } @@ -495,7 +491,93 @@ export default class WorkspaceComponent } } } + public createUIFromQuestionSchema(question: IQuestionSchema) { + const board = this.container.querySelector("[data-bc-sm-board]"); + board.innerHTML = ""; + this.createUIElements(board, question, false, this._noAccessToEdit); + } + + private createUIElements( + board: Element, + questionSchema: IQuestionSchema, + isABuiltIn: boolean, + noAccessToEdit: boolean + ) { + if (questionSchema) { + const sections = new Map(); + if (questionSchema.sections) { + questionSchema.sections.forEach((x) => { + const sectionModule = this.createContainer( + "section", + "section", + x, + isABuiltIn, + noAccessToEdit + ); + sections.set(x.id, sectionModule); + board.appendChild(sectionModule); + }); + } + if (questionSchema.questions) { + questionSchema.questions.forEach((question) => { + const questionModule = this.createContainer( + "question", + "question", + question, + isABuiltIn, + noAccessToEdit + ); + if (question.sectionId && sections.has(question.sectionId)) { + const section = sections.get(question.sectionId); + section + .querySelector("[data-drop-acceptable-container-schema-type]") + .appendChild(questionModule); + } else { + board.appendChild(questionModule); + } + if (question.parts) { + question.parts.forEach((part) => { + const partModule = this.createContainer( + part.viewType, + "question", + part, + isABuiltIn, + noAccessToEdit + ); + const partContainer = questionModule.querySelector( + `[data-bc-question-part-number="${part.part}"]` + ); + partContainer.appendChild(partModule); + }); + } + }); + } + } + } + private createContainer( + schemaId: string, + schemaType: ModuleType, + data: any, + isABuiltIn: boolean, + noAccessToEdit: boolean + ): Element { + const container = document.createElement("div"); + container.setAttribute("data-schema-id", schemaId); + container.setAttribute("data-schema-type", schemaType); + const factory = this.owner.dc.resolve("IModuleFactory"); + const module = factory.create( + schemaId, + container, + this, + isABuiltIn, + noAccessToEdit, + data + ); + container.setAttribute("data-bc-module-id", module.usedForId.toString()); + this._modules.set(module.usedForId, module); + return container; + } private cancelEditJson(): void { const jsonDownload = this.container.querySelector( @@ -540,42 +622,57 @@ export default class WorkspaceComponent findElementByPropId(array: Array, propId: number) { return array.find((element) => element.propId === propId); } - private async generateQuestionSchemaAsync(): Promise< - Partial - > { + private async generateQuestionSchemaAsync(): Promise { const source = await this.owner.waitToGetSourceAsync(this._sourceId); const schema = source.rows[0] as ISchemaMakerSchema; const detailSource = this.owner.tryToGetSource("details.data"); - let lid - let schemaName - let schemaVersion - if(detailSource){ - const rowProperties = detailSource.rows[0]?.properties; - - schemaVersion = this.findElementByPropId(rowProperties, 3)?.added - ? this.findElementByPropId(rowProperties, 3)?.added[0].parts[0].values[0].value - : this.findElementByPropId(rowProperties, 3)?.edited ? - this.findElementByPropId(rowProperties, 3)?.edited[0].parts[0].values[0].value: undefined; - lid = - this.findElementByPropId(rowProperties, 2)?.added ? this.findElementByPropId(rowProperties, 2)?.added[0].parts[0].values[0] - .value : this.findElementByPropId(rowProperties, 2)?.edited ? - this.findElementByPropId(rowProperties, 2)?.edited[0].parts[0].values[0] - .value : undefined - schemaName = this.findElementByPropId(rowProperties, 1)?.added - ? this.findElementByPropId(rowProperties, 1)?.added[0].parts[0].values[0] - .value - : this.findElementByPropId(rowProperties, 1)?.edited - ? this.findElementByPropId(rowProperties, 1)?.edited[0].parts[0].values[0] - .value - : undefined; + let lid; + let schemaName; + let schemaVersion; + if (detailSource) { + const rowProperties = detailSource.rows[0]?.properties; + + schemaVersion = this.findElementByPropId(rowProperties, 3)?.added + ? this.findElementByPropId(rowProperties, 3)?.added[0].parts[0] + .values[0].value + : this.findElementByPropId(rowProperties, 3)?.edited + ? this.findElementByPropId(rowProperties, 3)?.edited[0].parts[0] + .values[0].value + : undefined; + lid = this.findElementByPropId(rowProperties, 2)?.added + ? this.findElementByPropId(rowProperties, 2)?.added[0].parts[0] + .values[0].value + : this.findElementByPropId(rowProperties, 2)?.edited + ? this.findElementByPropId(rowProperties, 2)?.edited[0].parts[0] + .values[0].value + : undefined; + schemaName = this.findElementByPropId(rowProperties, 1)?.added + ? this.findElementByPropId(rowProperties, 1)?.added[0].parts[0] + .values[0].value + : this.findElementByPropId(rowProperties, 1)?.edited + ? this.findElementByPropId(rowProperties, 1)?.edited[0].parts[0] + .values[0].value + : undefined; } - lid = lid ?? document.querySelector(".bc_language_id [data-sys-select-option]")["value"] ?parseInt(document.querySelector(".bc_language_id [data-sys-select-option]")["value"]) : undefined + lid = + lid ?? + document.querySelector(".bc_language_id [data-sys-select-option]")[ + "value" + ] + ? parseInt( + document.querySelector(".bc_language_id [data-sys-select-option]")[ + "value" + ] + ) + : undefined; schemaName = schemaName ?? document.querySelector(".bc_schema_name [data-bc-text-input]")["value"]; schemaVersion = schemaVersion ?? - document.querySelector(".bc_schema_version [data-bc-text-input]")["value"]; + document.querySelector(".bc_schema_version [data-bc-text-input]")[ + "value" + ]; const mid = parseInt( this.container.querySelector( @@ -618,26 +715,24 @@ export default class WorkspaceComponent const usedForId = parseInt(id); const module = this._modules.get(usedForId); if (module instanceof ContainerModule) { - module.fillSchema(retVal); } } } }); - return retVal; + return retVal as any; } delay(callback, e) { setTimeout(() => { callback(e); }, 50); } - private async generateAndSetQuestionSchemaAsync(e: MouseEvent) { - e.preventDefault(); - const retVal = await this.generateQuestionSchemaAsync(); - this.owner.setSource(this._internalSourceId, retVal); - this._result = retVal as JSON; + + public generateAndSetQuestionSchema(question: IQuestionSchema) { + this.owner.setSource(this._internalSourceId, question); + this._result = question as any as JSON; // Prism highlight - const json = JSON.stringify(retVal, null, 4); + const json = JSON.stringify(question, null, 4); const html = Prism.highlight(json, Prism.languages.json, "json"); this.container.querySelector( "[data-bc-sm-preview-json]" @@ -646,7 +741,7 @@ export default class WorkspaceComponent // json for download this.container.querySelector( "[data-get-json-for-download]" - ).innerText = JSON.stringify(retVal); + ).innerText = JSON.stringify(question); this.container .querySelector("[data-bc-sm-json-download]") .setAttribute("data-get-btn-disabled", ""); @@ -666,6 +761,11 @@ export default class WorkspaceComponent ) as HTMLElement ).click(); } + private async onPreviewBtnClick(e: MouseEvent) { + e.preventDefault(); + const retVal = await this.generateQuestionSchemaAsync(); + this.generateAndSetQuestionSchema(retVal); + } private applyPropertyResult(userAction: IUserActionResult) { const module = this._modules.get(userAction.usedForId); @@ -681,7 +781,7 @@ export default class WorkspaceComponent private async loadDraft(draftName: string) { const schema = JSON.parse(localStorage.getItem(draftName)); - this.createUICom.createUIFromQuestionSchema(schema, this.container, this._noAccessToEdit); + this.createUIFromQuestionSchema(schema); } async loadObjectTypes() { @@ -726,7 +826,7 @@ export default class WorkspaceComponent let questionsBuiltIn: IQuestionSchemaBuiltIn = questions.sources[0].data[0]; const board = this.container.querySelector("[data-bc-sm-board]"); - this.createUICom.createUIElements(board, questionsBuiltIn, true, false); + this.createUIElements(board, questionsBuiltIn, true, false); } removeDefaultQuestions() { diff --git a/src/components/workspace/assets/layout.html b/src/components/workspace/assets/layout.html index 17ff1d4..3dba079 100644 --- a/src/components/workspace/assets/layout.html +++ b/src/components/workspace/assets/layout.html @@ -1,7 +1,7 @@

- +
diff --git a/src/components/workspace/createUI.ts b/src/components/workspace/createUI.ts deleted file mode 100644 index 51bf5b1..0000000 --- a/src/components/workspace/createUI.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { IUserDefineComponent } from "basiscore"; -import { ModuleType } from "../ISchemaMakerSchema"; -import { IQuestionSchema } from "basiscore"; -import IModuleFactory from "../modules/IModuleFactory"; -import ToolboxModule from "../modules/base-class/ToolboxModule"; -import IWorkspaceComponent from "./IWorkspaceComponent"; -// , container?:Element, json?:IQuestionSchema, noAccessToEdit?: boolean, -// workSpace?: WorkspaceComponent -export default class CreateUI { - private owner : IUserDefineComponent - private workSpace : IWorkspaceComponent - private readonly _modules: Map = new Map< - number, - ToolboxModule - >(); - constructor(owner: IUserDefineComponent, workspace? : IWorkspaceComponent) { - this.owner = owner - this.workSpace = workspace - } - public createUIFromQuestionSchema(question: IQuestionSchema, container : Element,accessToEdit : boolean) { - // note : be care for document.querselevtor , should be container - const board = document.querySelector("[data-bc-sm-board]"); - board.innerHTML = ""; - this.createUIElements(board, question, false, accessToEdit); - } - - createUIElements( - board: Element, - questionSchema: IQuestionSchema, - isABuiltIn: boolean, - noAccessToEdit: boolean - ) { - if (questionSchema) { - const sections = new Map(); - if (questionSchema.sections) { - questionSchema.sections.forEach((x) => { - const sectionModule = this.createContainer( - questionSchema, - "section", - "section", - x, - isABuiltIn, - noAccessToEdit - ); - sections.set(x.id, sectionModule); - board.appendChild(sectionModule); - }); - } - if (questionSchema.questions) { - questionSchema.questions.forEach((question) => { - const questionModule = this.createContainer( - questionSchema, - "question", - "question", - question, - isABuiltIn, - noAccessToEdit - ); - if (question.sectionId && sections.has(question.sectionId)) { - const section = sections.get(question.sectionId); - section - .querySelector("[data-drop-acceptable-container-schema-type]") - .appendChild(questionModule); - } else { - board.appendChild(questionModule); - } - if (question.parts) { - question.parts.forEach((part) => { - const partModule = this.createContainer( - questionSchema, - part.viewType, - "question", - part, - isABuiltIn, - noAccessToEdit - ); - const partContainer = questionModule.querySelector( - `[data-bc-question-part-number="${part.part}"]` - ); - partContainer.appendChild(partModule); - }); - } - }); - } - } - } - createContainer( - question: IQuestionSchema, - schemaId: string, - schemaType: ModuleType, - data: any, - isABuiltIn: boolean, - noAccessToEdit: boolean - ): Element { - const container = document.createElement("div"); - container.setAttribute("data-schema-id", schemaId); - container.setAttribute("data-schema-type", schemaType); - const factory = this.owner.dc.resolve("IModuleFactory"); - const module = factory.create(schemaId, container, this.workSpace , isABuiltIn, noAccessToEdit, data); - container.setAttribute("data-bc-module-id", module.usedForId.toString()); - this._modules.set(module.usedForId, module); - return container; - } - -} \ No newline at end of file diff --git a/wwwroot/component/new/index.html b/wwwroot/component/new/index.html index acba17e..637004c 100644 --- a/wwwroot/component/new/index.html +++ b/wwwroot/component/new/index.html @@ -17,7 +17,7 @@

Sample autocomplete Data Url: /server/autocomplete?term=${term}

+ detailsApiUrl="/server" detailsParamUrl="/detailsform" aifeature="true" rkey="asdasd" aiUrl="http://localhost:8080/server/chat">