vida
This commit is contained in:
parent
25270f4772
commit
efed275353
Binary file not shown.
@ -368,8 +368,27 @@
|
|||||||
<div class="clr-col-12">
|
<div class="clr-col-12">
|
||||||
<h5>Customer Details:</h5>
|
<h5>Customer Details:</h5>
|
||||||
<p><strong>Name:</strong> {{ rowSelected.name }}</p>
|
<p><strong>Name:</strong> {{ rowSelected.name }}</p>
|
||||||
<p><strong>Phone:</strong> {{ rowSelected.phone }}</p>
|
<p><strong>Active:</strong> {{ rowSelected.active }}</p>
|
||||||
|
<p><strong>Visa Entry Type:</strong> {{ rowSelected.visa_entry_typename }}</p>
|
||||||
|
<p><strong>Visa Duration:</strong> {{ rowSelected.visa_durationname }}</p>
|
||||||
|
<p><strong>Visa Processing:</strong> {{ rowSelected.visa_processingname }}</p>
|
||||||
|
<p><strong>Travel Start Date:</strong> {{ rowSelected.travel_start_date }}</p>
|
||||||
|
<p><strong>Travel End Date:</strong> {{ rowSelected.travel_end_date }}</p>
|
||||||
|
<p><strong>Passport Number:</strong> {{ rowSelected.passport_number }}</p>
|
||||||
|
<p><strong>Passport Issue Date:</strong> {{ rowSelected.passport_issue_date }}</p>
|
||||||
|
<p><strong>Passport Expiry Date:</strong> {{ rowSelected.passport_expiry_date }}</p>
|
||||||
<p><strong>Email:</strong> {{ rowSelected.email }}</p>
|
<p><strong>Email:</strong> {{ rowSelected.email }}</p>
|
||||||
|
<p><strong>Phone Number:</strong> {{ rowSelected.phone_number }}</p>
|
||||||
|
<p><strong>Birth Place:</strong> {{ rowSelected.birth_place }}</p>
|
||||||
|
<p><strong>Date of Birth:</strong> {{ rowSelected.date_of_birth }}</p>
|
||||||
|
<p><strong>Gender:</strong> {{ rowSelected.gendername }}</p>
|
||||||
|
<p><strong>Profession:</strong> {{ rowSelected.profession }}</p>
|
||||||
|
<p><strong>Visa Cost:</strong> {{ rowSelected.visa_cost }}</p>
|
||||||
|
<p><strong>Referrer:</strong> {{ rowSelected.referrername }}</p>
|
||||||
|
<p><strong>Nationality:</strong> {{ rowSelected.nationalityname }}</p>
|
||||||
|
<p><strong>Supplier:</strong> {{ rowSelected.suppliername }}</p>
|
||||||
|
<p><strong>Agent:</strong> {{ rowSelected.agentname }}</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -112,8 +112,26 @@ export class EditstepperComponent implements OnInit {
|
|||||||
supplier: [null],
|
supplier: [null],
|
||||||
|
|
||||||
agent: [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
|
// Change to Horizontal Layout
|
||||||
@ -207,6 +225,8 @@ export class EditstepperComponent implements OnInit {
|
|||||||
this.toastr.error("Not Added");
|
this.toastr.error("Not Added");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.rowSelected = this.entryForm.value;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.ngOnInit();
|
this.ngOnInit();
|
||||||
}, 500);
|
}, 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 {
|
isValidemail(email: string): boolean {
|
||||||
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
const emailPattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||||
return emailPattern.test(email);
|
return emailPattern.test(email);
|
||||||
@ -349,13 +409,14 @@ export class EditstepperComponent implements OnInit {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
updategender(gender: string): void {
|
selectgender;
|
||||||
this.entryForm.get('gender').setValue(gender);
|
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
|
//currency field start
|
||||||
@ -366,4 +427,37 @@ export class EditstepperComponent implements OnInit {
|
|||||||
this.rowSelected.visa_cost = this.rowSelected.visa_cost?.replace(/,/g, '');
|
this.rowSelected.visa_cost = this.rowSelected.visa_cost?.replace(/,/g, '');
|
||||||
}
|
}
|
||||||
//currency field end
|
//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); });
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,9 +19,6 @@
|
|||||||
<clr-icon shape="plus"></clr-icon>ADD
|
<clr-icon shape="plus"></clr-icon>ADD
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button id="add" class="btn btn-primary" (click)="gotositebuilder()">
|
|
||||||
<clr-icon shape="plus"></clr-icon>SiteBuilder
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ng-container *ngIf="!isCardview"> <!-- GET ALL --> <clr-datagrid [clrDgLoading]="loading"
|
<ng-container *ngIf="!isCardview"> <!-- GET ALL --> <clr-datagrid [clrDgLoading]="loading"
|
||||||
|
|||||||
@ -197,49 +197,6 @@ export class Visa_applicationComponent implements OnInit {
|
|||||||
onUpdate(id) {
|
onUpdate(id) {
|
||||||
this.modalEdit = false;
|
this.modalEdit = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//console.log("in update");
|
//console.log("in update");
|
||||||
console.log("id " + id);
|
console.log("id " + id);
|
||||||
console.log(this.rowSelected);
|
console.log(this.rowSelected);
|
||||||
@ -255,48 +212,6 @@ export class Visa_applicationComponent implements OnInit {
|
|||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}, (error) => {
|
}, (error) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
if (error.status >= 200 && error.status <= 299) {
|
if (error.status >= 200 && error.status <= 299) {
|
||||||
@ -463,9 +378,6 @@ export class Visa_applicationComponent implements OnInit {
|
|||||||
// updateaction
|
// updateaction
|
||||||
|
|
||||||
|
|
||||||
gotositebuilder() {
|
|
||||||
this.router.navigate(["/cns-portal/SiteBuilder"]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { environment } from 'src/environments/environment';
|
|||||||
})
|
})
|
||||||
export class SiteTreeservice {
|
export class SiteTreeservice {
|
||||||
private baseURL = "SiteTree/SiteTree";
|
private baseURL = "SiteTree/SiteTree";
|
||||||
private dlfbaseURL = environment.builderUrl+"/entityBuilder";
|
private dlfbaseURL = environment.builderUrl + "/entityBuilder";
|
||||||
private nodeURL = environment.nodeUrl;
|
private nodeURL = environment.nodeUrl;
|
||||||
|
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ export class SiteTreeservice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createHtmlPages(data: any, projId: number): Observable<any> {
|
createHtmlPages(data: any, projId: number): Observable<any> {
|
||||||
return this.apiRequest.post(`sureops/createFile?projId=` + projId, data);
|
return this.apiRequest.post(`sureops/deploy?projId=` + projId, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@ -49,6 +49,8 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- 🔁 Regenerate Button at top of wireframe page -->
|
<!-- 🔁 Regenerate Button at top of wireframe page -->
|
||||||
|
<!-- part 2 code -->
|
||||||
|
<!--
|
||||||
<div style="text-align: right; margin: 10px 0;">
|
<div style="text-align: right; margin: 10px 0;">
|
||||||
<button (click)="regenerateAllModifiedSections()"
|
<button (click)="regenerateAllModifiedSections()"
|
||||||
style="background: orange; color: white; border: none; padding: 8px 14px; border-radius: 4px; cursor: pointer;">
|
style="background: orange; color: white; border: none; padding: 8px 14px; border-radius: 4px; cursor: pointer;">
|
||||||
@ -73,11 +75,121 @@
|
|||||||
<button (click)="copyToClipboard(pageName)">📋</button>
|
<button (click)="copyToClipboard(pageName)">📋</button>
|
||||||
<button (click)="downloadHtml(pageName)">⬇️</button>
|
<button (click)="downloadHtml(pageName)">⬇️</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<!-- ✅ Render whole page in one block -->
|
<!-- ✅ Render whole page in one block -->
|
||||||
<div class="canvas-section">
|
<!-- <div class="canvas-section">
|
||||||
<div [innerHTML]="pageSections[pageName]['FullPage']"></div>
|
<div [innerHTML]="pageSections[pageName]['FullPage']"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- part 3 -->
|
||||||
|
<!-- 🔁 Regenerate + Save Buttons -->
|
||||||
|
<div style="display: flex; justify-content: space-between; margin-bottom: 10px;">
|
||||||
|
<div>
|
||||||
|
<button (click)="regenerateAllModifiedSections()" style="background: orange; color: white; border: none; padding: 8px 14px; border-radius: 4px; cursor: pointer;">
|
||||||
|
♻️ Regenerate Modified
|
||||||
|
</button>
|
||||||
|
<button (click)="uploadHtmlFiles(37388)" style="background: green; color: white; border: none; padding: 8px 14px; border-radius: 4px; cursor: pointer;">
|
||||||
|
💾 Save All HTML Files
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<!-- Global Style Controls -->
|
||||||
|
<select [(ngModel)]="liveStyles.fontSize">
|
||||||
|
<option value="">Font Size</option>
|
||||||
|
<option *ngFor="let size of ['12px', '14px', '16px', '18px', '20px', '24px', '28px']" [value]="size">{{ size }}</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select [(ngModel)]="liveStyles.fontWeight">
|
||||||
|
<option value="">Font Weight</option>
|
||||||
|
<option *ngFor="let weight of ['normal', 'bold', 'lighter']" [value]="weight">{{ weight }}</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select [(ngModel)]="liveStyles.textAlign">
|
||||||
|
<option value="">Align</option>
|
||||||
|
<option value="left">Left</option>
|
||||||
|
<option value="center">Center</option>
|
||||||
|
<option value="right">Right</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<input type="color" [(ngModel)]="liveStyles.color" title="Text Color" />
|
||||||
|
<input type="color" [(ngModel)]="liveStyles.background" title="Background Color" />
|
||||||
|
|
||||||
|
<button (click)="applyStyleToSelection()" style="background: #555; color: white; padding: 6px 10px; border-radius: 4px;">🎨 Apply Style</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Navbar Link Manager -->
|
||||||
|
<!-- <div *ngIf="selectedNavbarPage" class="navbar-link-manager">
|
||||||
|
<h3>🔗 Navbar Link Manager ({{ selectedNavbarPage }})</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let link of navbarLinks[selectedNavbarPage]; let i = index">
|
||||||
|
<input [(ngModel)]="link.label" placeholder="Link Label" />
|
||||||
|
<select [(ngModel)]="link.href">
|
||||||
|
<option *ngFor="let page of availablePages" [value]="page.href">{{ page.label }}</option>
|
||||||
|
</select>
|
||||||
|
<button (click)="removeLink(selectedNavbarPage, i)">❌</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<button (click)="addLink(selectedNavbarPage)">➕ Add Link</button>
|
||||||
|
<button (click)="applyNavbarChanges(selectedNavbarPage)">✅ Apply Changes</button>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 🔗 Navbar Link Editor Modal -->
|
||||||
|
<div *ngIf="selectedNavbarPage" class="navbar-popup-overlay">
|
||||||
|
<div class="navbar-popup-content">
|
||||||
|
<h3>🔗 Navbar Link Manager ({{ selectedNavbarPage }})</h3>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li *ngFor="let link of navbarLinks[selectedNavbarPage]; let i = index">
|
||||||
|
<input [(ngModel)]="link.label" placeholder="Link Label" />
|
||||||
|
<select [(ngModel)]="link.href">
|
||||||
|
<option *ngFor="let page of availablePages" [value]="page.href">{{ page.label }}</option>
|
||||||
|
</select>
|
||||||
|
<button (click)="removeLink(selectedNavbarPage, i)">❌</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div style="margin-top: 10px;">
|
||||||
|
<button (click)="addLink(selectedNavbarPage)">➕ Add Link</button>
|
||||||
|
<button (click)="applyNavbarChanges(selectedNavbarPage)">✅ Apply</button>
|
||||||
|
<button (click)="selectedNavbarPage = null">❌ Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ✅ Pages List -->
|
||||||
|
<div class="canvas-wrapper">
|
||||||
|
<div class="canvas-page" *ngFor="let pageName of pageRenderOrder">
|
||||||
|
<div class="canvas-header">
|
||||||
|
<button (click)="regenerateWireframe(pageName)">♻️</button>
|
||||||
|
<h3 (click)="selectNavbar(pageName)" style="cursor: pointer;">
|
||||||
|
{{ pageName }} <span title="Edit Navbar">🧭</span>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="canvas-actions">
|
||||||
|
<button (click)="copyToClipboard(pageName)">📋</button>
|
||||||
|
<button (click)="downloadHtml(pageName)">⬇️</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ✅ Render and Edit Section -->
|
||||||
|
<div class="canvas-section">
|
||||||
|
<div [innerHTML]="pageSections[pageName]?.FullPage"
|
||||||
|
|
||||||
|
contenteditable="true"
|
||||||
|
class="editable-html"
|
||||||
|
(blur)="onEdit(pageName, $event)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|||||||
@ -64,3 +64,29 @@
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: #fff;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@ -5,24 +5,31 @@ import { ActivatedRoute } from '@angular/router';
|
|||||||
import { SiteTreeservice } from '../SiteBuilderGrid/SiteTree.service';
|
import { SiteTreeservice } from '../SiteBuilderGrid/SiteTree.service';
|
||||||
import { COMMON_CSS } from './common-css';
|
import { COMMON_CSS } from './common-css';
|
||||||
import { ToastrService } from 'ngx-toastr';
|
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({
|
@Component({
|
||||||
selector: 'app-wireframe-renderer',
|
selector: 'app-wireframe-renderer',
|
||||||
templateUrl: './wireframe-renderer.component.html',
|
templateUrl: './wireframe-renderer.component.html',
|
||||||
styleUrls: ['./wireframe-renderer.component.scss']
|
styleUrls: ['./wireframe-renderer.component.scss'],
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
export class WireframeRendererComponent implements OnInit {
|
export class WireframeRendererComponent implements OnInit {
|
||||||
@Input() node: any;
|
@Input() node: any;
|
||||||
@Input() title: string = '';
|
@Input() title: string = '';
|
||||||
commonCss: string = COMMON_CSS;
|
commonCss: string = COMMON_CSS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
jsonInput = '';
|
jsonInput = '';
|
||||||
initialPrompt = '';
|
initialPrompt = '';
|
||||||
|
|
||||||
id: number;
|
id: number;
|
||||||
|
allPagePrompts: Record<string, Record<string, string>> = {};
|
||||||
|
initialGeneratedPrompts: Record<string, Record<string, string>> = {};
|
||||||
|
promptHashCache: Record<string, string> = {};
|
||||||
|
pageSections: Record<string, { FullPage: SafeHtml }> = {};
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -30,9 +37,6 @@ export class WireframeRendererComponent implements OnInit {
|
|||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private sanitizer: DomSanitizer,
|
private sanitizer: DomSanitizer,
|
||||||
private toastr: ToastrService,
|
private toastr: ToastrService,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -42,6 +46,7 @@ export class WireframeRendererComponent implements OnInit {
|
|||||||
|
|
||||||
this.fetchTreeById(this.id);
|
this.fetchTreeById(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wireframe-renderer.component.ts (add this helper method)
|
// wireframe-renderer.component.ts (add this helper method)
|
||||||
getKeys(obj: any): string[] {
|
getKeys(obj: any): string[] {
|
||||||
return Object.keys(obj || {});
|
return Object.keys(obj || {});
|
||||||
@ -78,14 +83,9 @@ export class WireframeRendererComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// all prompt in one map
|
// all prompt in one map
|
||||||
|
|
||||||
allPagePrompts: Record<string, Record<string, string>> = {};
|
|
||||||
initialGeneratedPrompts: Record<string, Record<string, string>> = {};
|
|
||||||
|
|
||||||
|
|
||||||
// Recursively walk the tree and generate prompts for each section
|
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
async generatePromptsForAllSections(treeJsonString: string) {
|
async generatePromptsForAllSections(treeJsonString: string) {
|
||||||
try {
|
try {
|
||||||
@ -98,14 +98,14 @@ export class WireframeRendererComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Step 3
|
// Step 3
|
||||||
async processPages(treeJson: any) {
|
pageRenderOrder: string[] = []; // 🚀 New array to hold correct page order
|
||||||
|
|
||||||
|
async processPages(treeJson: any) {
|
||||||
console.log('tree is : ', treeJson)
|
console.log('tree is : ', treeJson)
|
||||||
for (const [pageName, sections] of Object.entries(treeJson)) {
|
for (const [pageName, sections] of Object.entries(treeJson)) {
|
||||||
|
this.pageRenderOrder.push(pageName); // ✅ Track the order of pages
|
||||||
// child page prompt map
|
// child page prompt map
|
||||||
const sectionPrompts: Record<string, string> = {};
|
const sectionPrompts: Record<string, string> = {};
|
||||||
|
|
||||||
if (sections['Children']) {
|
if (sections['Children']) {
|
||||||
// 👇 Recursively handle child pages
|
// 👇 Recursively handle child pages
|
||||||
console.log(' child is : ', sections['Children'])
|
console.log(' child is : ', sections['Children'])
|
||||||
@ -113,7 +113,6 @@ export class WireframeRendererComponent implements OnInit {
|
|||||||
await this.processPages(sections['Children']); // ✅ Fix: recursive + awaited
|
await this.processPages(sections['Children']); // ✅ Fix: recursive + awaited
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop other sections
|
// Loop other sections
|
||||||
for (const [sectionName, sectionDescription] of Object.entries(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
|
const prompt = await this.generatePromptFromSection(sectionName, sectionDescription); // ✅ await
|
||||||
sectionPrompts[sectionName] = prompt;
|
sectionPrompts[sectionName] = prompt;
|
||||||
|
|
||||||
// console.log( sectionName, ': ', prompt)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🧠 Store all prompts for that page
|
// 🧠 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
|
this.initialGeneratedPrompts[pageName] = JSON.parse(JSON.stringify(sectionPrompts)); // Deep clone
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('✅ FINAL PROMPT MAP:', this.allPagePrompts);
|
console.log('✅ FINAL PROMPT MAP:', this.allPagePrompts);
|
||||||
|
|
||||||
await this.processAllPagesLiveUpdate()
|
await this.processAllPagesLiveUpdate()
|
||||||
@ -174,124 +169,120 @@ HTML Only. No CSS.
|
|||||||
✅ Use placeholders for image/icon blocks where appropriate (e.g., <div style="width:100px;height:30px;background:#ccc;"></div>)`;
|
✅ Use placeholders for image/icon blocks where appropriate (e.g., <div style="width:100px;height:30px;background:#ccc;"></div>)`;
|
||||||
|
|
||||||
|
|
||||||
// Step 4
|
|
||||||
async generatePromptFromSection(
|
async generatePromptFromSection(
|
||||||
sectionName: string,
|
sectionName: string,
|
||||||
sectionDescription: string,
|
sectionDescription: string,
|
||||||
headerId: number = 35,
|
headerId: number = 35,
|
||||||
operationType: string = 'template 1',
|
operationType: string = 'template 1'
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// const fieldType = sectionName.toLowerCase().replace(/\s+/g, '').replace(/section$/, '').trim();
|
const fieldType = sectionName.toLowerCase().replace(/section$/i, '').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
|
|
||||||
|
|
||||||
this.siteTreeService.getDlf(headerId, operationType, fieldType).subscribe({
|
this.siteTreeService.getDlf(headerId, operationType, fieldType).subscribe({
|
||||||
next: async (res) => {
|
next: async (res) => {
|
||||||
try {
|
try {
|
||||||
const jsonBlock = res?.javacode;
|
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 enhancedPrompt = `
|
||||||
const parsedJson = typeof jsonBlock === 'string' ? JSON.parse(jsonBlock) : jsonBlock;
|
🎯 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 || ''}"
|
if (this.promptHashCache[hash]) {
|
||||||
- Section name: "${sectionName}"
|
return resolve(this.promptHashCache[hash]);
|
||||||
- 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('{}');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// const enhanced = await this.callLlm(enhancedPrompt);
|
||||||
|
// this.promptHashCache[hash] = enhanced;
|
||||||
|
|
||||||
|
resolve(baseJsonString);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('❌ JSON parse error:', err);
|
console.error('❌ JSON parse error:', err);
|
||||||
resolve('{}');
|
resolve('{}');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: () => resolve('{}')
|
||||||
console.error('❌ API error:', err);
|
|
||||||
resolve('{}');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cachedPromptHashes: Record<string, Record<string, string>> = {};
|
||||||
|
sectionHtmls: Record<string, Record<string, string>> = {};
|
||||||
|
|
||||||
|
// 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<void>[] = [];
|
||||||
|
|
||||||
|
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<string, string>) {
|
||||||
|
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 = `<style>${COMMON_CSS}</style>\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<string, string> = {};
|
pageHtmlMap: Record<string, string> = {};
|
||||||
generatedPages: { name: string, html: string }[] = [];
|
generatedPages: { name: string, html: string }[] = [];
|
||||||
|
|
||||||
pageSections: Record<string, { FullPage: SafeHtml }> = {}; // 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 = `
|
|
||||||
<style>${COMMON_CSS}</style>
|
|
||||||
${sectionHtmls.join('\n')}`;
|
|
||||||
|
|
||||||
// ✅ Bypass Angular sanitizer
|
|
||||||
const safeHtml: SafeHtml = this.sanitizer.bypassSecurityTrustHtml(htmlWithCss);
|
|
||||||
|
|
||||||
this.pageSections[pageName] = { FullPage: safeHtml };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 6
|
// Step 6
|
||||||
async generateJson(data: { jsonStructure: any, sectionType: string }): Promise<string> {
|
async generateJson(data: { jsonStructure: any, sectionType: string }): Promise<string> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@ -310,7 +301,7 @@ ${finalJsonString}
|
|||||||
|
|
||||||
this.siteTreeService.generateHtml(payload).subscribe({
|
this.siteTreeService.generateHtml(payload).subscribe({
|
||||||
next: (res) => {
|
next: (res) => {
|
||||||
console.log('✅ Response from HTML API:', res);
|
console.log('✅ Response from HTML API ', payload.sectionType, ' : ', res);
|
||||||
if (res && res.msg) {
|
if (res && res.msg) {
|
||||||
resolve(res.msg);
|
resolve(res.msg);
|
||||||
} else {
|
} else {
|
||||||
@ -318,12 +309,12 @@ ${finalJsonString}
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
console.error('❌ HTML API Error:', err);
|
console.error(payload.sectionType, '❌ HTML API Error:', err);
|
||||||
resolve('⚠️ HTML API call failed.');
|
resolve('⚠️ HTML API call failed.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} 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.');
|
resolve('⚠️ Invalid JSON structure.');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -469,7 +460,7 @@ ${finalJsonString}
|
|||||||
|
|
||||||
|
|
||||||
// // Step 6
|
// // Step 6
|
||||||
async calLlm(data): Promise<string> {
|
async callLlm(data): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
console.log('call Llm Start ')
|
console.log('call Llm Start ')
|
||||||
const payload = {
|
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<string, string> = {};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
selectedElementSelector = '';
|
||||||
|
styleMap: Record<string, any> = {
|
||||||
|
'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<string, { label: string, href: string }[]> = {};
|
||||||
|
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 <ul class="nav-1"> from links
|
||||||
|
const ulHtml = `<ul class="nav-1">` + links.map(link => {
|
||||||
|
return `<li><a href="${link.href}">${link.label}</a></li>`;
|
||||||
|
}).join('') + `</ul>`;
|
||||||
|
|
||||||
|
// Replace all instances of <ul class="nav-1">...</ul>
|
||||||
|
const updatedHtml = html.replace(/<ul class="nav-1"([\s\S]*?)<\/ul>/g, ulHtml);
|
||||||
|
console.log(' new html ', updatedHtml);
|
||||||
|
|
||||||
|
const safe = this.sanitizer.bypassSecurityTrustHtml(updatedHtml);
|
||||||
|
this.pageSections[pageName] = { FullPage: safe };
|
||||||
|
|
||||||
|
this.toastr.success('✅ Navbar updated for all nav-1 instances!');
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyNavbarChanges(pageName: string) {
|
||||||
|
// const links = this.navbarLinks[pageName] || [];
|
||||||
|
// const htmlContent = this.pageSections[pageName]?.FullPage?.toString() || '';
|
||||||
|
|
||||||
|
// if (!htmlContent) return;
|
||||||
|
|
||||||
|
// // Create a temporary container to parse and manipulate the HTML
|
||||||
|
// const wrapper = document.createElement('div');
|
||||||
|
// wrapper.innerHTML = htmlContent;
|
||||||
|
|
||||||
|
// // Find all navbar UL elements
|
||||||
|
// const navMenus = wrapper.querySelectorAll('ul.nav-1');
|
||||||
|
|
||||||
|
// if (navMenus.length === 0) {
|
||||||
|
// console.warn('No navigation menus found with class "nav-1"');
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Update each navigation menu found
|
||||||
|
// navMenus.forEach(ul => {
|
||||||
|
// // step 1 clear the old vals in html
|
||||||
|
// ul.innerHTML = '';
|
||||||
|
|
||||||
|
// // creating a new one and appending
|
||||||
|
// links.forEach(link => {
|
||||||
|
// const listItem = document.createElement('li');
|
||||||
|
// const anchor = document.createElement('a');
|
||||||
|
|
||||||
|
// // Set attributes safely using setAttribute
|
||||||
|
// anchor.setAttribute('href', link.href);
|
||||||
|
// anchor.textContent = link.label;
|
||||||
|
|
||||||
|
// listItem.appendChild(anchor);
|
||||||
|
// ul.appendChild(listItem);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // Get the updated HTML content
|
||||||
|
// const updatedHtml = wrapper.innerHTML;
|
||||||
|
|
||||||
|
// // Sanitize and update the page content
|
||||||
|
// const safeHtml = this.sanitizer.bypassSecurityTrustHtml(updatedHtml);
|
||||||
|
// this.pageSections[pageName] = { FullPage: safeHtml };
|
||||||
|
|
||||||
|
// this.toastr.success('✅ Navbar updated for all nav-1 instances!');
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // Step 4
|
||||||
|
// async generatePromptFromSection(
|
||||||
|
// sectionName: string,
|
||||||
|
// sectionDescription: string,
|
||||||
|
// headerId: number = 35,
|
||||||
|
// operationType: string = 'template 1',
|
||||||
|
// ): Promise<string> {
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// this.siteTreeService.getDlf(headerId, operationType, fieldType).subscribe({
|
||||||
|
// next: async (res) => {
|
||||||
|
// try {
|
||||||
|
// const jsonBlock = res?.javacode;
|
||||||
|
// if (!jsonBlock) {
|
||||||
|
// resolve('{}');
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // console.log( fieldType , ' json is : ', jsonBlock)
|
||||||
|
|
||||||
|
// const parsedJson = typeof jsonBlock === 'string' ? JSON.parse(jsonBlock) : jsonBlock;
|
||||||
|
|
||||||
|
// // const updatedJson = this.replaceContentRecursively(parsedJson, sectionDescription);
|
||||||
|
// const formattedJson = JSON.stringify(parsedJson, null, 2);
|
||||||
|
// // 🧠 Build prompt to LLM with section info + json + full page prompt
|
||||||
|
// // // 🧠 LLM enhancement: Content update without changing structure
|
||||||
|
// const smartPrompt = `
|
||||||
|
// 🔁 Enhance this JSON content while keeping the structure exactly same.
|
||||||
|
|
||||||
|
// Section Name: ${sectionName}
|
||||||
|
// Section Description: ${sectionDescription}
|
||||||
|
// Full Page Prompt: ${this.initialPrompt || ''}
|
||||||
|
|
||||||
|
// ✅ Replace or fill only content fields like: "title", "description", "text", "label", "placeholder", "heading", etc.
|
||||||
|
// ❌ Do NOT change or restructure keys, nesting, or CSS class names.
|
||||||
|
// ❌ Do NOT remove or add new blocks unless it's strictly a content array (like testimonials or FAQs).
|
||||||
|
|
||||||
|
// JSON Input:
|
||||||
|
// ${formattedJson}
|
||||||
|
|
||||||
|
// ⬇️ Return only the updated JSON with better content.
|
||||||
|
// `;
|
||||||
|
|
||||||
|
|
||||||
|
// // console.log('enhanced query ', smartPrompt);
|
||||||
|
|
||||||
|
// // // const finalJson = await this.calLlm(enhancedPrompt);
|
||||||
|
// // resolve(formattedJson);
|
||||||
|
|
||||||
|
// const enhancedJson = await this.calLlm(smartPrompt);
|
||||||
|
|
||||||
|
// // Return directly the enhanced JSON
|
||||||
|
// resolve(enhancedJson || formattedJson);
|
||||||
|
|
||||||
|
// } catch (err) {
|
||||||
|
// console.error('❌ JSON parse error:', err);
|
||||||
|
// resolve('{}');
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// error: (err) => {
|
||||||
|
// console.error('❌ API error:', err);
|
||||||
|
// resolve('{}');
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // 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 = `
|
||||||
|
// <style>${COMMON_CSS}</style>
|
||||||
|
// ${sectionHtmls.join('\n')}`;
|
||||||
|
|
||||||
|
// // ✅ Bypass Angular sanitizer
|
||||||
|
// const safeHtml: SafeHtml = this.sanitizer.bypassSecurityTrustHtml(htmlWithCss);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
// }
|
||||||
|
|
||||||
// // Step 4
|
// // Step 4
|
||||||
// generatePromptFromSection(
|
// generatePromptFromSection(
|
||||||
|
|||||||
@ -110,11 +110,10 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- Popup Dialog -->
|
<!-- Popup Dialog -->
|
||||||
<div *ngIf="showPopup"
|
<!-- <div *ngIf="showPopup"
|
||||||
style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center; z-index: 1000;">
|
style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); display: flex; align-items: center; justify-content: center; z-index: 1000;">
|
||||||
<div style="background: white; padding: 20px; width: 500px; border-radius: 8px; position: relative;">
|
<div style="background: white; padding: 20px; width: 500px; border-radius: 8px; position: relative;">
|
||||||
|
|
||||||
<!-- CLOSE BUTTON -->
|
|
||||||
<button (click)="showPopup = false"
|
<button (click)="showPopup = false"
|
||||||
style="position: absolute; top: 10px; right: 10px; background: #ff4d4f; border: none; color: white; border-radius: 50%; width: 30px; height: 30px; font-size: 18px; cursor: pointer;">
|
style="position: absolute; top: 10px; right: 10px; background: #ff4d4f; border: none; color: white; border-radius: 50%; width: 30px; height: 30px; font-size: 18px; cursor: pointer;">
|
||||||
×
|
×
|
||||||
@ -130,4 +129,39 @@
|
|||||||
Generate
|
Generate
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Popup Dialog with improved z-index and animations -->
|
||||||
|
<div *ngIf="showPopup" [@fadeIn] class="modal-overlay"
|
||||||
|
style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.75); display: flex; align-items: center; justify-content: center; z-index: 1000;">
|
||||||
|
<div class="chart-box" [@slideIn]
|
||||||
|
style="width: 600px; max-height: none; padding: 24px; box-shadow: 0 8px 24px rgba(0,0,0,0.25); border-radius: 8px; border: none; transform-origin: center; background-color: snow">
|
||||||
|
|
||||||
|
<!-- Close button -->
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
|
||||||
|
<h3 style="margin: 0; color: #333; font-weight: 500;">Generate Site Structure</h3>
|
||||||
|
<button (click)="showPopup = false" [@pulseOnHover]
|
||||||
|
style="background: transparent; border: none; color: #666; font-size: 24px; cursor: pointer; padding: 4px; height: 36px; width: 36px; border-radius: 50%; transition: all 0.2s ease; display: flex; align-items: center; justify-content: center; color: #f5f5f5;">
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p style="margin-bottom: 16px; color: #666;">Describe your website structure in plain language:</p>
|
||||||
|
|
||||||
|
<textarea [(ngModel)]="rawInputText" rows="8" [@focusBorder]
|
||||||
|
class="tag-input"
|
||||||
|
style="width: 100%; margin-bottom: 20px; font-family: inherit; resize: vertical; transition: border 0.3s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.05);"></textarea>
|
||||||
|
|
||||||
|
<div style="display: flex; justify-content: flex-end; gap: 12px;">
|
||||||
|
<button (click)="showPopup = false" [@buttonHover]
|
||||||
|
style="padding: 8px 16px; background: #f5f5f5; color: #333; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; transition: all 0.2s ease;">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button (click)="generateJson()" [@buttonHover]
|
||||||
|
style="padding: 8px 18px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(0,0,0,0.2);">
|
||||||
|
Generate Structure
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1,3 +1,146 @@
|
|||||||
|
// .controls {
|
||||||
|
// margin-bottom: 20px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .controls textarea {
|
||||||
|
// width: 100%;
|
||||||
|
// height: 200px;
|
||||||
|
// padding: 10px;
|
||||||
|
// font-size: 14px;
|
||||||
|
// font-family: monospace;
|
||||||
|
// border: 1px solid #ccc;
|
||||||
|
// border-radius: 4px;
|
||||||
|
// resize: vertical;
|
||||||
|
// box-sizing: border-box;
|
||||||
|
// margin-bottom: 10px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .controls button {
|
||||||
|
// padding: 10px 20px;
|
||||||
|
// background-color: #1976d2;
|
||||||
|
// color: white;
|
||||||
|
// border: none;
|
||||||
|
// border-radius: 4px;
|
||||||
|
// cursor: pointer;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .controls button:hover {
|
||||||
|
// background-color: #1565c0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .toolbar {
|
||||||
|
// display: flex;
|
||||||
|
// gap: 10px;
|
||||||
|
// align-items: flex-start;
|
||||||
|
// padding: 1rem;
|
||||||
|
// background-color: #f7f7f7;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// textarea {
|
||||||
|
// width: 300px;
|
||||||
|
// height: 120px;
|
||||||
|
// font-family: monospace;
|
||||||
|
// padding: 10px;
|
||||||
|
// border-radius: 8px;
|
||||||
|
// border: 1px solid #ccc;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// button {
|
||||||
|
// padding: 10px 20px;
|
||||||
|
// background-color: #3f51b5;
|
||||||
|
// color: white;
|
||||||
|
// border: none;
|
||||||
|
// border-radius: 6px;
|
||||||
|
// cursor: pointer;
|
||||||
|
// transition: background-color 0.3s ease;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// button:hover {
|
||||||
|
// background-color: #303f9f;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// mat-tab-group {
|
||||||
|
// margin: 1rem;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .tab-content {
|
||||||
|
// padding: 1rem;
|
||||||
|
// background-color: #fafafa;
|
||||||
|
// border: 1px solid #ddd;
|
||||||
|
// border-radius: 10px;
|
||||||
|
// min-height: 400px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// .active-tab {
|
||||||
|
// border-bottom: 2px solid #007bff;
|
||||||
|
// color: #007bff;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .tab-button {
|
||||||
|
// padding: 8px 16px;
|
||||||
|
// margin-right: 8px;
|
||||||
|
// background: #f1f1f1;
|
||||||
|
// border: none;
|
||||||
|
// border-bottom: 2px solid transparent;
|
||||||
|
// cursor: pointer;
|
||||||
|
// color: black; /* 👈 Text color black */
|
||||||
|
// font-weight: bold;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .tab-button.active {
|
||||||
|
// border-bottom: 2px solid #000;
|
||||||
|
// background: #e0e0e0;
|
||||||
|
// color: black; /* 👈 Ensure active tab also stays black */
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// .editor-container {
|
||||||
|
// position: relative; /* 🔑 Important to contain absolute button */
|
||||||
|
// max-width: 1200px;
|
||||||
|
// margin: 0 auto;
|
||||||
|
// font-family: 'Segoe UI', sans-serif;
|
||||||
|
// padding: 20px;
|
||||||
|
// background-color: #ffffff;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// .style-panel {
|
||||||
|
// position: fixed;
|
||||||
|
// top: 100px;
|
||||||
|
// right: 20px;
|
||||||
|
// width: 220px;
|
||||||
|
// padding: 15px;
|
||||||
|
// background: white;
|
||||||
|
// border: 1px solid #ccc;
|
||||||
|
// border-radius: 6px;
|
||||||
|
// box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||||
|
// z-index: 9999;
|
||||||
|
|
||||||
|
// h4 {
|
||||||
|
// margin-bottom: 10px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// label {
|
||||||
|
// display: block;
|
||||||
|
// margin-bottom: 10px;
|
||||||
|
// font-size: 13px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// input {
|
||||||
|
// width: 100%;
|
||||||
|
// padding: 4px;
|
||||||
|
// margin-top: 2px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// button {
|
||||||
|
// margin-right: 8px;
|
||||||
|
// padding: 6px 12px;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
@ -104,4 +247,20 @@ mat-tab-group {
|
|||||||
padding: 20px;
|
padding: 20px;
|
||||||
background-color: #ffffff;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
.modal-overlay *{
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
:host {
|
||||||
|
--zoom-level: 1;
|
||||||
|
--primary-color: #2196f3;
|
||||||
|
--spacing-unit: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--level: 0;
|
||||||
|
--primary-color: #2196f3;
|
||||||
|
--border-color: #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,17 +3,55 @@ import { treeVisualizerService } from './tree-visualizer.service';
|
|||||||
import { SiteTreeservice } from './SiteBuilderGrid/SiteTree.service';
|
import { SiteTreeservice } from './SiteBuilderGrid/SiteTree.service';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
|
import { ViewChild } from '@angular/core';
|
||||||
|
import { trigger, transition, style, animate, state } from '@angular/animations';
|
||||||
|
// Make sure path is correct
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-tree-visualizer',
|
selector: 'app-tree-visualizer',
|
||||||
templateUrl: './tree-visualizer.component.html',
|
templateUrl: './tree-visualizer.component.html',
|
||||||
styleUrls: ['./tree-visualizer.component.scss']
|
styleUrls: ['./tree-visualizer.component.scss'],
|
||||||
|
animations: [
|
||||||
|
trigger('fadeIn', [
|
||||||
|
transition(':enter', [
|
||||||
|
style({ opacity: 0 }),
|
||||||
|
animate('200ms ease-out', style({ opacity: 1 }))
|
||||||
|
]),
|
||||||
|
transition(':leave', [
|
||||||
|
animate('200ms ease-in', style({ opacity: 0 }))
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
trigger('slideIn', [
|
||||||
|
transition(':enter', [
|
||||||
|
style({ transform: 'scale(0.9)', opacity: 0 }),
|
||||||
|
animate('300ms ease-out', style({ transform: 'scale(1)', opacity: 1 }))
|
||||||
|
]),
|
||||||
|
transition(':leave', [
|
||||||
|
animate('200ms ease-in', style({ transform: 'scale(0.9)', opacity: 0 }))
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
trigger('buttonHover', [
|
||||||
|
state('void', style({ transform: 'translateY(0)' })),
|
||||||
|
state('hover', style({ transform: 'translateY(-2px)', boxShadow: '0 4px 8px rgba(0,0,0,0.2)' }))
|
||||||
|
]),
|
||||||
|
trigger('focusBorder', [
|
||||||
|
state('void', style({ borderColor: '#ccc' })),
|
||||||
|
state('focus', style({ borderColor: '#1976d2', boxShadow: '0 0 0 2px rgba(25,118,210,0.2)' }))
|
||||||
|
]),
|
||||||
|
trigger('pulseOnHover', [
|
||||||
|
state('void', style({ backgroundColor: 'transparent' })),
|
||||||
|
state('hover', style({ backgroundColor: 'rgba(0,0,0,0.05)' }))
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
})
|
})
|
||||||
export class TreeVisualizerComponent {
|
export class TreeVisualizerComponent {
|
||||||
|
|
||||||
activeTab: 'sitemap' | 'wireframe' = 'sitemap';
|
activeTab: 'sitemap' | 'wireframe' = 'sitemap';
|
||||||
showPopup: boolean = false;
|
showPopup: boolean = false;
|
||||||
|
openPopup() {
|
||||||
|
this.showPopup = true;
|
||||||
|
}
|
||||||
inputJson: string = `{
|
inputJson: string = `{
|
||||||
"Login": {
|
"Login": {
|
||||||
"Navbar": {},
|
"Navbar": {},
|
||||||
@ -75,9 +113,7 @@ after click this icard inside we upload excel of student data, icard template, a
|
|||||||
this.fetchTreeById(this.id);
|
this.fetchTreeById(this.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
openPopup() {
|
|
||||||
this.showPopup = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
convertJson() {
|
convertJson() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user