diff --git a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application.zip b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application.zip new file mode 100644 index 0000000..aea0074 Binary files /dev/null and b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application.zip differ diff --git a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/VisaOrderWorkflow/editstepper.component.html b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/VisaOrderWorkflow/editstepper.component.html index bdafd0d..ac8395b 100644 --- a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/VisaOrderWorkflow/editstepper.component.html +++ b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/VisaOrderWorkflow/editstepper.component.html @@ -368,8 +368,27 @@
Customer Details:

Name: {{ rowSelected.name }}

-

Phone: {{ rowSelected.phone }}

+

Active: {{ rowSelected.active }}

+

Visa Entry Type: {{ rowSelected.visa_entry_typename }}

+

Visa Duration: {{ rowSelected.visa_durationname }}

+

Visa Processing: {{ rowSelected.visa_processingname }}

+

Travel Start Date: {{ rowSelected.travel_start_date }}

+

Travel End Date: {{ rowSelected.travel_end_date }}

+

Passport Number: {{ rowSelected.passport_number }}

+

Passport Issue Date: {{ rowSelected.passport_issue_date }}

+

Passport Expiry Date: {{ rowSelected.passport_expiry_date }}

Email: {{ rowSelected.email }}

+

Phone Number: {{ rowSelected.phone_number }}

+

Birth Place: {{ rowSelected.birth_place }}

+

Date of Birth: {{ rowSelected.date_of_birth }}

+

Gender: {{ rowSelected.gendername }}

+

Profession: {{ rowSelected.profession }}

+

Visa Cost: {{ rowSelected.visa_cost }}

+

Referrer: {{ rowSelected.referrername }}

+

Nationality: {{ rowSelected.nationalityname }}

+

Supplier: {{ rowSelected.suppliername }}

+

Agent: {{ rowSelected.agentname }}

+
diff --git a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/VisaOrderWorkflow/editstepper.component.ts b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/VisaOrderWorkflow/editstepper.component.ts index 0e3560c..7b5a175 100644 --- a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/VisaOrderWorkflow/editstepper.component.ts +++ b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/VisaOrderWorkflow/editstepper.component.ts @@ -112,8 +112,26 @@ export class EditstepperComponent implements OnInit { supplier: [null], agent: [null], - + }); + + + this.getallvisa_entry_type(); + + this.getallvisa_duration(); + + this.getallvisa_processing(); + + this.getallgender(); + + this.getallreferrer(); + + this.getallnationality(); + + this.getallsupplier(); + + this.getallagent(); + } // Change to Horizontal Layout @@ -207,6 +225,8 @@ export class EditstepperComponent implements OnInit { this.toastr.error("Not Added"); } }); + this.rowSelected = this.entryForm.value; + setTimeout(() => { this.ngOnInit(); }, 500); @@ -330,11 +350,51 @@ export class EditstepperComponent implements OnInit { } } + updategender(gender: string): void { + this.entryForm.get('gender').setValue(gender); + } + + updategenderEdit(gender: string): void { this.rowSelected.gender = gender } + + + + + rsModaldescription = false; + goToReplaceStringdescription(row) { + this.rowSelected = row; this.rsModaldescription = true; + } + + + + selectvisa_entry_type; + getallvisa_entry_type() { + this.mainService.getAllvisa_entry_type().subscribe(data => { + this.selectvisa_entry_type = data; + console.log(data); + }, (error) => { console.log(error); }); + } + + selectvisa_duration; + getallvisa_duration() { + this.mainService.getAllvisa_duration().subscribe(data => { + this.selectvisa_duration = data; + console.log(data); + }, (error) => { console.log(error); }); + } + + selectvisa_processing; + getallvisa_processing() { + this.mainService.getAllvisa_processing().subscribe(data => { + this.selectvisa_processing = data; + console.log('visa processing ', data); + }, (error) => { console.log(error); }); + } + isValidemail(email: string): boolean { const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; return emailPattern.test(email); @@ -349,13 +409,14 @@ export class EditstepperComponent implements OnInit { - updategender(gender: string): void { - this.entryForm.get('gender').setValue(gender); + selectgender; + getallgender() { + this.mainService.getAllgender().subscribe(data => { + this.selectgender = data; + console.log(data); + }, (error) => { console.log(error); }); } - updategenderEdit(gender: string): void { this.rowSelected.gender = gender } - - //currency field start @@ -366,4 +427,37 @@ export class EditstepperComponent implements OnInit { this.rowSelected.visa_cost = this.rowSelected.visa_cost?.replace(/,/g, ''); } //currency field end + + selectreferrer; + getallreferrer() { + this.mainService.getAllreferrer().subscribe(data => { + this.selectreferrer = data; + console.log(data); + }, (error) => { console.log(error); }); + } + + selectnationality; + getallnationality() { + this.mainService.getAllnationality().subscribe(data => { + this.selectnationality = data; + console.log(data); + }, (error) => { console.log(error); }); + } + + selectsupplier; + getallsupplier() { + this.mainService.getAllsupplier().subscribe(data => { + this.selectsupplier = data; + console.log(data); + }, (error) => { console.log(error); }); + } + + selectagent; + getallagent() { + this.mainService.getAllagent().subscribe(data => { + this.selectagent = data; + console.log(data); + }, (error) => { console.log(error); }); + } + } diff --git a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/Visa_application.component.html b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/Visa_application.component.html index 704f659..0914ffc 100644 --- a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/Visa_application.component.html +++ b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/BuilderComponents/vpspack/Visa_application/Visa_application.component.html @@ -19,9 +19,6 @@ ADD - { console.log(error); if (error.status >= 200 && error.status <= 299) { @@ -463,9 +378,6 @@ export class Visa_applicationComponent implements OnInit { // updateaction - gotositebuilder() { - this.router.navigate(["/cns-portal/SiteBuilder"]); - } } diff --git a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/SiteBuilderGrid/SiteTree.service.ts b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/SiteBuilderGrid/SiteTree.service.ts index 27bf0b8..287877f 100644 --- a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/SiteBuilderGrid/SiteTree.service.ts +++ b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/SiteBuilderGrid/SiteTree.service.ts @@ -8,7 +8,7 @@ import { environment } from 'src/environments/environment'; }) export class SiteTreeservice { private baseURL = "SiteTree/SiteTree"; - private dlfbaseURL = environment.builderUrl+"/entityBuilder"; + private dlfbaseURL = environment.builderUrl + "/entityBuilder"; private nodeURL = environment.nodeUrl; @@ -52,7 +52,7 @@ export class SiteTreeservice { } createHtmlPages(data: any, projId: number): Observable { - return this.apiRequest.post(`sureops/createFile?projId=` + projId, data); + return this.apiRequest.post(`sureops/deploy?projId=` + projId, data); } diff --git a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi 2.zip b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi 2.zip new file mode 100644 index 0000000..4831ce7 Binary files /dev/null and b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi 2.zip differ diff --git a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.html b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.html index 2a0d8c5..ef14df5 100644 --- a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.html +++ b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.html @@ -49,6 +49,8 @@ + + -
+ + + + + +
+
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + + + + + + + + + +
+
+
+ +

+ {{ pageName }} 🧭 +

+ +
+ + +
+
+ + +
+
+
+
+
+
diff --git a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.scss b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.scss index c11de29..9e84084 100644 --- a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.scss +++ b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.scss @@ -64,3 +64,29 @@ border-radius: 6px; background: #fff; } + + +.editable-html:focus { + outline: 2px solid #007bff; + background: #fcfcfc; +} +.navbar-popup-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 9999; +} + +.navbar-popup-content { + background: white; + padding: 20px; + width: 500px; + max-width: 90%; + border-radius: 8px; +} diff --git a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.ts b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.ts index 9cf5201..9c52b0a 100644 --- a/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.ts +++ b/visaproject-front-f/authsec_angular/frontend/angular-clarity-master/src/app/modules/main/fnd/SiteTreeBuilder/WireframesUi/wireframe-renderer.component.ts @@ -5,24 +5,31 @@ import { ActivatedRoute } from '@angular/router'; import { SiteTreeservice } from '../SiteBuilderGrid/SiteTree.service'; import { COMMON_CSS } from './common-css'; import { ToastrService } from 'ngx-toastr'; +import * as sha256 from 'crypto-js/sha256'; +import SHA256 from 'crypto-js/sha256'; +import { trigger, transition, style, animate, state } from '@angular/animations'; +// Make sure path is correct + @Component({ selector: 'app-wireframe-renderer', templateUrl: './wireframe-renderer.component.html', - styleUrls: ['./wireframe-renderer.component.scss'] + styleUrls: ['./wireframe-renderer.component.scss'], }) + + export class WireframeRendererComponent implements OnInit { @Input() node: any; @Input() title: string = ''; commonCss: string = COMMON_CSS; - - - jsonInput = ''; initialPrompt = ''; - id: number; + allPagePrompts: Record> = {}; + initialGeneratedPrompts: Record> = {}; + promptHashCache: Record = {}; + pageSections: Record = {}; constructor( @@ -30,9 +37,6 @@ export class WireframeRendererComponent implements OnInit { private route: ActivatedRoute, private sanitizer: DomSanitizer, private toastr: ToastrService, - - - ) { } ngOnInit(): void { @@ -42,6 +46,7 @@ export class WireframeRendererComponent implements OnInit { this.fetchTreeById(this.id); } + // wireframe-renderer.component.ts (add this helper method) getKeys(obj: any): string[] { return Object.keys(obj || {}); @@ -78,14 +83,9 @@ export class WireframeRendererComponent implements OnInit { } }); } + // all prompt in one map - allPagePrompts: Record> = {}; - initialGeneratedPrompts: Record> = {}; - - - // Recursively walk the tree and generate prompts for each section - // Step 2 async generatePromptsForAllSections(treeJsonString: string) { try { @@ -98,14 +98,14 @@ export class WireframeRendererComponent implements OnInit { } // Step 3 - async processPages(treeJson: any) { + pageRenderOrder: string[] = []; // 🚀 New array to hold correct page order + async processPages(treeJson: any) { console.log('tree is : ', treeJson) for (const [pageName, sections] of Object.entries(treeJson)) { - + this.pageRenderOrder.push(pageName); // ✅ Track the order of pages // child page prompt map const sectionPrompts: Record = {}; - if (sections['Children']) { // 👇 Recursively handle child pages console.log(' child is : ', sections['Children']) @@ -113,7 +113,6 @@ export class WireframeRendererComponent implements OnInit { await this.processPages(sections['Children']); // ✅ Fix: recursive + awaited } - // Loop other sections for (const [sectionName, sectionDescription] of Object.entries(sections)) { @@ -123,9 +122,6 @@ export class WireframeRendererComponent implements OnInit { const prompt = await this.generatePromptFromSection(sectionName, sectionDescription); // ✅ await sectionPrompts[sectionName] = prompt; - - // console.log( sectionName, ': ', prompt) - } // 🧠 Store all prompts for that page @@ -133,7 +129,6 @@ export class WireframeRendererComponent implements OnInit { this.initialGeneratedPrompts[pageName] = JSON.parse(JSON.stringify(sectionPrompts)); // Deep clone } - console.log('✅ FINAL PROMPT MAP:', this.allPagePrompts); await this.processAllPagesLiveUpdate() @@ -174,124 +169,120 @@ HTML Only. No CSS. ✅ Use placeholders for image/icon blocks where appropriate (e.g.,
)`; - // Step 4 + async generatePromptFromSection( sectionName: string, sectionDescription: string, headerId: number = 35, - operationType: string = 'template 1', + operationType: string = 'template 1' ): Promise { return new Promise((resolve) => { - // const fieldType = sectionName.toLowerCase().replace(/\s+/g, '').replace(/section$/, '').trim(); - const fieldType = sectionName - .toLowerCase() - .replace(/section$/i, '') // remove trailing 'section' - .replace(/\s{2,}/g, ' ') // multiple spaces to single space - .trim(); // trim leading/trailing spaces + const fieldType = sectionName.toLowerCase().replace(/section$/i, '').trim(); this.siteTreeService.getDlf(headerId, operationType, fieldType).subscribe({ next: async (res) => { try { const jsonBlock = res?.javacode; + if (!jsonBlock) return resolve('{}'); - // console.log( fieldType , ' json is : ', jsonBlock) + const baseJson = typeof jsonBlock === 'string' ? JSON.parse(jsonBlock) : jsonBlock; + const baseJsonString = JSON.stringify(baseJson, null, 2); - if (jsonBlock) { - const parsedJson = typeof jsonBlock === 'string' ? JSON.parse(jsonBlock) : jsonBlock; + const enhancedPrompt = ` + 🎯 Enhance the content of this section using the following context. + + 🧠 Instructions: + - You are given an existing JSON structure for a UI section. + - Your job is to update ONLY the content-related fields like "text", "title", "label", "description", and "placeholder". + - You must NOT change the structure, hierarchy, tags, keys, class names, or styling values. + - You must NOT add or remove any keys or elements. + - You must return ONLY the updated JSON structure in valid format. + + 📄 Page Prompt: + "${this.initialPrompt}" + + 📦 Section Name: + "${sectionName}" + + 📘 Section Description: + "${sectionDescription}" + + 📌 Existing JSON (modify this only): + ${baseJsonString} + + 🚫 Do NOT include: + - Any explanation, commentary, or markdown + - Any prefix like "Here is the updated JSON" + - Any new elements that were not already present + + ✅ Output Requirement: + Only return the updated JSON structure — nothing else. + `; - // const updatedJson = this.replaceContentRecursively(parsedJson, sectionDescription); - const finalJsonString = JSON.stringify(parsedJson, null, 2); - // 🧠 Build prompt to LLM with section info + json + full page prompt - const enhancedPrompt = ` -📘 You are an intelligent layout enhancer. -Your task is to update and fill in the values of a given UI section JSON based on the following information: + const hash = sha256(enhancedPrompt).toString(); -- Page-level prompt: "${this.initialPrompt || ''}" -- Section name: "${sectionName}" -- Section description: "${sectionDescription}" - -You must only update relevant values like "title", "text", "description", "label", "placeholder", etc. - -⚠️ DO NOT change the structure. Only update content values. - -JSON: -${finalJsonString} - -✅ Return only the updated JSON. Do not return any explanation. -`; - - // console.log('enhanced query ', enhancedPrompt); - - // const finalJson = await this.calLlm(enhancedPrompt); - resolve(finalJsonString); - } else { - resolve('{}'); + if (this.promptHashCache[hash]) { + return resolve(this.promptHashCache[hash]); } + + // const enhanced = await this.callLlm(enhancedPrompt); + // this.promptHashCache[hash] = enhanced; + + resolve(baseJsonString); } catch (err) { console.error('❌ JSON parse error:', err); resolve('{}'); } }, - error: (err) => { - console.error('❌ API error:', err); - resolve('{}'); - } + error: () => resolve('{}') }); }); } + cachedPromptHashes: Record> = {}; + sectionHtmls: Record> = {}; + + // Step 1 - Generate SHA-256 Hash + + getPromptHash(prompt: string): string { + return SHA256(prompt).toString(); + } + + + // Step 2 - Enhance per section with Hash Check + LLM call in Parallel + + async processAllPagesLiveUpdate() { + const htmlGenerationTasks: Promise[] = []; + + for (const [pageName, sectionMap] of Object.entries(this.allPagePrompts)) { + htmlGenerationTasks.push(this.processPageSections(pageName, sectionMap)); + } + + await Promise.all(htmlGenerationTasks); + } + + async processPageSections(pageName: string, sectionMap: Record) { + const sectionHtmls: string[] = []; + + const htmlTasks = Object.entries(sectionMap).map(async ([sectionName, jsonPrompt]) => { + const html = await this.generateJson({ sectionType: sectionName, jsonStructure: jsonPrompt }); + sectionHtmls.push(html); + }); + + await Promise.all(htmlTasks); + + const finalHtml = `\n${sectionHtmls.join('\n')}`; + const safeHtml = this.sanitizer.bypassSecurityTrustHtml(finalHtml); + + this.pageSections[pageName] = { FullPage: safeHtml }; + } - // replaceContentRecursively(obj: any, replacement: string): any { - // if (Array.isArray(obj)) { - // return obj.map(item => this.replaceContentRecursively(item, replacement)); - // } else if (typeof obj === 'object' && obj !== null) { - // const updated = {}; - // for (const [key, value] of Object.entries(obj)) { - // // Replace specific fields if they are strings - // if (['description', 'text', 'label', 'title', 'subtext'].includes(key.toLowerCase()) && typeof value === 'string') { - // updated[key] = replacement; - // } else { - // updated[key] = this.replaceContentRecursively(value, replacement); - // } - // } - // return updated; - // } - // return obj; - // } pageHtmlMap: Record = {}; generatedPages: { name: string, html: string }[] = []; - pageSections: Record = {}; // final UI map - - // Step 5 - generate html code via java Api through prompt - async processAllPagesLiveUpdate() { - for (const [pageName, sectionMap] of Object.entries(this.allPagePrompts)) { - const sectionHtmls: string[] = []; - - for (const [sectionName, promptText] of Object.entries(sectionMap)) { - console.log(`🚀 Generating HTML for: ${pageName} > ${sectionName}`); - - const response = await this.generateJson({ sectionType: sectionName, jsonStructure: promptText }); - const html = response || '⚠️ No response received.'; - - sectionHtmls.push(html); - } - - // ✅ Inject common CSS once per page - const htmlWithCss = ` - - ${sectionHtmls.join('\n')}`; - - // ✅ Bypass Angular sanitizer - const safeHtml: SafeHtml = this.sanitizer.bypassSecurityTrustHtml(htmlWithCss); - - this.pageSections[pageName] = { FullPage: safeHtml }; - } - } - // Step 6 async generateJson(data: { jsonStructure: any, sectionType: string }): Promise { return new Promise((resolve) => { @@ -310,7 +301,7 @@ ${finalJsonString} this.siteTreeService.generateHtml(payload).subscribe({ next: (res) => { - console.log('✅ Response from HTML API:', res); + console.log('✅ Response from HTML API ', payload.sectionType, ' : ', res); if (res && res.msg) { resolve(res.msg); } else { @@ -318,12 +309,12 @@ ${finalJsonString} } }, error: (err) => { - console.error('❌ HTML API Error:', err); + console.error(payload.sectionType, '❌ HTML API Error:', err); resolve('⚠️ HTML API call failed.'); } }); } catch (err) { - console.error('❌ JSON parsing error before sending to API:', err); + console.error(data.sectionType, '❌ JSON parsing error before sending to API:', err); resolve('⚠️ Invalid JSON structure.'); } }); @@ -469,7 +460,7 @@ ${finalJsonString} // // Step 6 - async calLlm(data): Promise { + async callLlm(data): Promise { return new Promise((resolve, reject) => { console.log('call Llm Start ') const payload = { @@ -492,6 +483,337 @@ ${finalJsonString} }); } + activeEditTarget: string | null = null; + liveStyles = { + background: '', + color: '', + fontSize: '', + padding: '', + margin: '', + fontWeight: '', + textAlign: '', + }; + + selectEditable(pageName: string) { + this.activeEditTarget = pageName; + } + + applyLiveStyles() { + const target = document.querySelector(`[data-target='${this.activeEditTarget}']`) as HTMLElement; + if (target) { + Object.keys(this.liveStyles).forEach((prop) => { + if (this.liveStyles[prop]) { + target.style[prop] = this.liveStyles[prop]; + } + }); + } + this.toastr.success(`🎨 Style updated for: ${this.activeEditTarget}`); + } + + // 🔁 Track raw edits + rawEdits: Record = {}; + + + + selectedElementSelector = ''; + styleMap: Record = { + 'hero-header': { 'background': '#fdfdfd', 'text-align': 'center' }, + 'btn-filled': { 'background': '#000', 'color': '#fff' }, + 'hero-heading': { 'font-size': '36px', 'font-weight': 'bold' }, + // Add all classes you want to allow editing + }; + + getAllCssSelectors(): string[] { + return Object.keys(this.styleMap); + } + + + applyCssFromMap() { + this.updateLiveStyles(); + } + + updateLiveStyles() { + const styleSheetId = 'dynamic-css-style'; + let styleEl = document.getElementById(styleSheetId) as HTMLStyleElement; + + if (!styleEl) { + styleEl = document.createElement('style'); + styleEl.id = styleSheetId; + document.head.appendChild(styleEl); + } + + let css = ''; + for (const selector in this.styleMap) { + css += `.${selector} {`; + for (const prop in this.styleMap[selector]) { + css += `${prop}: ${this.styleMap[selector][prop]};`; + } + css += '}'; + } + + styleEl.innerHTML = css; + } + + onEdit(pageName: string, event: any) { + const newHtml = event.target.innerHTML; + this.pageSections[pageName]['FullPage'] = this.sanitizer.bypassSecurityTrustHtml(newHtml); + } + + applyStyleToSelection() { + const selection = window.getSelection(); + if (!selection || selection.rangeCount === 0) return; + + const range = selection.getRangeAt(0); + const selectedText = range.extractContents(); + + const span = document.createElement('span'); + + // Apply styles + if (this.liveStyles.color) span.style.color = this.liveStyles.color; + if (this.liveStyles.background) span.style.backgroundColor = this.liveStyles.background; + if (this.liveStyles.fontSize) span.style.fontSize = this.liveStyles.fontSize; + if (this.liveStyles.fontWeight) span.style.fontWeight = this.liveStyles.fontWeight; + if (this.liveStyles.textAlign) span.style.textAlign = this.liveStyles.textAlign; + span.appendChild(selectedText); + + range.insertNode(span); + selection.removeAllRanges(); + } + + // new today 25 april + // New Variables + selectedNavbarPage: string = ''; + navbarLinks: Record = {}; + availablePages: { label: string, href: string }[] = []; + + // Select Navbar Section + selectNavbar(pageName: string) { + const html = this.pageSections[pageName]['FullPage']?.toString() || ''; + + if (html.includes('class="nav-1"') || html.includes('navbar')) { + this.selectedNavbarPage = pageName; + this.extractNavbarLinks(pageName, html); + } else { + alert('No Navbar found on this page.'); + } + } + + // Extract links from navbar HTML + extractNavbarLinks(pageName: string, html: string) { + const tempDiv = document.createElement('div'); + tempDiv.innerHTML = html; + + const navLinks = Array.from(tempDiv.querySelectorAll('.nav-1 li a')); + this.navbarLinks[pageName] = navLinks.map(link => ({ + label: link.textContent?.trim() || '', + href: link.getAttribute('href') || '#' + })); + + // Also prepare available pages list + this.availablePages = Object.keys(this.pageSections).map(p => ({ + label: p, + href: `${p.replace(/\s+/g, '-').toLowerCase()}.html` + })); + } + + // Add new link + addLink(pageName: string) { + this.navbarLinks[pageName].push({ label: '', href: '#' }); + } + + // Remove a link + removeLink(pageName: string, index: number) { + this.navbarLinks[pageName].splice(index, 1); + } + + // Apply Changes to navbar + applyNavbarChanges(pageName: string) { + const links = this.navbarLinks[pageName] || []; + + const html = this.pageSections[pageName]?.FullPage?.toString() || ''; + if (!html) return; + + // Build new