This commit is contained in:
string 2025-06-09 10:17:39 +05:30
parent 0ced644864
commit 5e70585afc
28 changed files with 11547 additions and 1690 deletions

View File

@ -62,6 +62,9 @@
<clr-dg-column [clrDgField]="'Java Code'"> <ng-container *clrDgHideableColumn="{hidden: false}"> javacode <clr-dg-column [clrDgField]="'Java Code'"> <ng-container *clrDgHideableColumn="{hidden: false}"> javacode
</ng-container></clr-dg-column> </ng-container></clr-dg-column>
<!-- <clr-dg-column [clrDgField]="'tag'"> <ng-container *clrDgHideableColumn="{hidden: false}"> Tag
</ng-container></clr-dg-column> -->
<clr-dg-column [clrDgField]="'Active'"> <ng-container *clrDgHideableColumn="{hidden: false}"> Active <clr-dg-column [clrDgField]="'Active'"> <ng-container *clrDgHideableColumn="{hidden: false}"> Active
</ng-container></clr-dg-column> </ng-container></clr-dg-column>
@ -107,6 +110,9 @@
style="cursor: pointer; align-items: center;"><clr-icon shape="details"></clr-icon> style="cursor: pointer; align-items: center;"><clr-icon shape="details"></clr-icon>
</clr-dg-cell> </clr-dg-cell>
<!-- <clr-dg-cell>{{user.tag }}</clr-dg-cell> -->
<clr-dg-cell>{{user. active }}</clr-dg-cell> <clr-dg-cell>{{user. active }}</clr-dg-cell>
@ -377,6 +383,14 @@
placeholder="Textarea"> </textarea> placeholder="Textarea"> </textarea>
</div> </div>
<div class="clr-col-sm-12">
<label>Tag</label>
<select name="tag" [(ngModel)]="rowSelected.tag">
<option [value]="null">Choose Tag</option>
<option *ngFor=" let item of selectTagdata" [value]="item.id">{{item.name }}</option>
</select>
</div>
</div> </div>
@ -497,6 +511,14 @@
<textarea cols="10" rows="2" formControlName="javacode" placeholder="Textarea"> </textarea> <textarea cols="10" rows="2" formControlName="javacode" placeholder="Textarea"> </textarea>
</div> </div>
<div class="clr-col-sm-12">
<label> Tag</label>
<select formControlName="tag">
<option [value]="null">Choose Tag</option>
<option *ngFor="let item of selectTagdata " [value]="item.id">{{item.name}}</option>
</select>
</div>
</div> </div>

View File

@ -10,6 +10,7 @@ import { UserInfoService } from 'src/app/services/user-info.service';
import { SiteTreeservice } from '../SiteBuilderGrid/SiteTree.service'; import { SiteTreeservice } from '../SiteBuilderGrid/SiteTree.service';
import { COMMON_CSS } from '../WireframesUi/common-css'; import { COMMON_CSS } from '../WireframesUi/common-css';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { Tagservice } from '../Tag/Tag.service';
declare var JsBarcode: any; declare var JsBarcode: any;
@Component({ @Component({
selector: 'app-Design_lbrary', selector: 'app-Design_lbrary',
@ -44,6 +45,7 @@ export class Design_lbraryComponent implements OnInit {
modaldelete = false; modaldelete = false;
modalEdit = false; modalEdit = false;
modalAdd = false; modalAdd = false;
selectTagdata;
public entryForm: FormGroup; public entryForm: FormGroup;
loading = false; loading = false;
product; product;
@ -61,6 +63,7 @@ export class Design_lbraryComponent implements OnInit {
private _fb: FormBuilder, private _fb: FormBuilder,
private siteTreeService: SiteTreeservice, private siteTreeService: SiteTreeservice,
private route: ActivatedRoute, private route: ActivatedRoute,
private tagService: Tagservice,
) { } ) { }
// component button // component button
@ -74,6 +77,7 @@ export class Design_lbraryComponent implements OnInit {
} }
this.userrole = this.userInfoService.getRoles(); this.userrole = this.userInfoService.getRoles();
this.getData(); this.getData();
this.getallTags();
this.entryForm = this._fb.group({ this.entryForm = this._fb.group({
name: [null], name: [null],
@ -82,6 +86,8 @@ export class Design_lbraryComponent implements OnInit {
active: [false], active: [false],
htmljson: [null], htmljson: [null],
tag: [null],
css: [null], css: [null],
templatetype: [null], templatetype: [null],
@ -247,6 +253,14 @@ export class Design_lbraryComponent implements OnInit {
this.rowSelected = row; this.rsModaljavacode = true; this.rowSelected = row; this.rsModaljavacode = true;
} }
getallTags() {
this.tagService.getAll().subscribe(data => {
this.selectTagdata = data;
console.log('tag data ', data);
}, (error) => { console.log(error); });
}
// updateaction // updateaction
public htmlContent: string = ''; public htmlContent: string = '';

View File

@ -31,15 +31,5 @@ export class Design_lbraryservice {
} }
// updateaction // updateaction
} }

View File

@ -15,11 +15,9 @@
<button id="add" class="btn btn-primary" (click)="goToAdd(product)"> <button id="add" class="btn btn-primary" (click)="goToAdd(product)">
<clr-icon shape="plus"></clr-icon>ADD <clr-icon shape="plus"></clr-icon>ADD
</button> </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"
[(clrDgSelected)]="selected"> [(clrDgSelected)]="selected">
<clr-dg-placeholder> <clr-dg-placeholder>
@ -29,7 +27,7 @@
<div *ngIf="error;else loadingSpinner">{{error}}</div> <div *ngIf="error;else loadingSpinner">{{error}}</div>
</clr-dg-placeholder> </clr-dg-placeholder>
<clr-dg-column [clrDgField]="' name'"> <ng-container *clrDgHideableColumn="{hidden: false}"> Name <clr-dg-column [clrDgField]="' name'"> <ng-container *clrDgHideableColumn="{hidden: false}">Website Name
</ng-container></clr-dg-column> </ng-container></clr-dg-column>
@ -49,7 +47,7 @@
<clr-dg-row *clrDgItems="let user of product?.slice()?.reverse()" [clrDgItem]="user"> <clr-dg-row *clrDgItems="let user of product?.slice()?.reverse()" [clrDgItem]="user">
<clr-dg-cell>{{user. name }}</clr-dg-cell> <clr-dg-cell>{{user.name }}</clr-dg-cell>
<clr-dg-cell (click)="goToReplaceStringdescription (user.description)" <clr-dg-cell (click)="goToReplaceStringdescription (user.description)"
@ -57,7 +55,7 @@
</clr-dg-cell> </clr-dg-cell>
<clr-dg-cell>{{user. active }}</clr-dg-cell> <clr-dg-cell>{{user.active }}</clr-dg-cell>
<!-- who column --> <!-- who column -->
@ -98,6 +96,9 @@
</clr-dg-pagination> </clr-dg-pagination>
</clr-dg-footer> </clr-dg-footer>
</clr-datagrid> </ng-container> </clr-datagrid> </ng-container>
<ng-template #showInfo> <ng-template #showInfo>
<div class="alert alert-info" role="alert"> <div class="alert alert-info" role="alert">
<div class="alert-items"> <div class="alert-items">
@ -110,13 +111,20 @@
</div> </div>
</div> </div>
</div> </div>
</ng-template><ng-container *ngIf="isCardview"> </ng-template><ng-container *ngIf="isCardview">
<div *ngIf="product; else showInfo" class="clr-row clr-align-items-start clr-justify-content-start"> <div *ngIf="product; else showInfo" class="clr-row clr-align-items-start clr-justify-content-start">
<div *ngFor="let app of product| filter:search; let index = i" class="clr-col-auto"> <div *ngFor="let app of product| filter:search; let index = i" class="clr-col-auto">
<div class="clr-row"> <div class="clr-row">
<div class="clr-col-lg-12 clr-col-md-4 clr-col-sm-4 clr-col-12" style="width: 410px;"> <div class="clr-col-lg-12 clr-col-md-4 clr-col-sm-4 clr-col-12" style="width: 410px;">
<div class="card" style="padding: 10px; " <div class="card" style="padding: 10px; "
[style.background-color]="cardmodal.cardColor !== '' ? cardmodal.cardColor : 'white'"> [style.background-color]="cardmodal.cardColor !== '' ? cardmodal.cardColor : 'white'">
<div class="card-body" <div class="card-body"
style="display: grid; grid-template-columns: repeat(13, 1fr); grid-template-rows: repeat(7, 1fr); gap: 5px;"> style="display: grid; grid-template-columns: repeat(13, 1fr); grid-template-rows: repeat(7, 1fr); gap: 5px;">
<ng-container *ngFor="let item of dashboardArray"> <ng-container *ngFor="let item of dashboardArray">
@ -224,20 +232,107 @@
</div> </div>
</div> </div>
</ng-container> </ng-container>
</div>
<!-- card view start -->
<!-- <div *ngIf="isCardview" class="project-container" style="height: 600px; overflow-y: scroll;">
<div *ngIf="product else showInfo" class="clr-row clr-align-items-start clr-justify-content-start"
style="margin: 0px;">
<div *ngFor="let app of product | filter:search; let index = i" class="clr-col-auto">
<div class="clr-row">
<div class="clr-col-lg-12 clr-col-md-4 clr-col-sm-4 clr-col-12" style="width: 410px;">
<div class="card" (click)="gotositebuilder(app.id)">
<div class="card-header">
<div class="clr-row">
<div class="clr-col-5">
<b style="font-size: 15px; display: inline-block;
width: 180px;
white-space: nowrap;
overflow: hidden !important;
text-overflow: ellipsis;" [title]="app.name"> {{app.name}}</b>
</div>
</div>
<div class="card-title1" id="word">
<b class="word" style="font-size: 15px; " [title]="app.projectName">{{app.projectName}}</b>
</div>
<div class="clr-row">
<div class="clr-col-9">
<div class="card-title1" id="word">
<b style="font-size: 15px;" class="p2" [title]="app.description">{{app.description}}</b>
</div>
</div>
<div class="clr-col-3"
style="text-align: right; display: flex; align-items: center; justify-content: flex-end; padding:0;">
</div>
</div>
</div>
<div style="padding: 0 10px;cursor: pointer;position:relative; "
(click)="openModal(app.id);$event.stopPropagation();">
<clr-progress-bar [clrValue]="app.progressValue" clrLabeled></clr-progress-bar>
</div>
<div class="card-block" style="padding: 10px 10px 0px 10px;">
<div class="card-text">
<div class="clr-row">
<div class="clr-col-7">
<span *ngFor="let tech of app?.technology?.slice(0, 6); let i = index">
<span class="label label-light-blue p7 wordwrap" style="margin-top: .4em;" [title]="tech">
{{tech}}</span>
</span>
</div>
<div class="clr-col-5" (click)="stopRedirection($event)" style="-ms-flex-align: end;">
<div class="profile-pics">
<ng-container *ngFor="let imageitem of app?.images; let i = index">
<img (click)="openprofile(app.id); $event.stopPropagation();"
[src]="imageitem?.image ? imageitem?.image : '../../../../../assets/images/images.png'"
[title]="imageitem?.user_name" [style.z-index]="i + 2" [style.left.rem]="i * 0.9"
[style.display]="i < 5 ? 'block' : 'none'" />
</ng-container>
</div>
</div>
</div>
</div>
<div class="card-footer" style="padding: 0px 10px 6px 10px">
<button class="btn btn-sm btn-link"> Last Updated On: {{app.updatedAt|date}}</button> <span
style="margin: 0 0 0 10px; padding: 5px;" class="label p7"><clr-icon
shape="calendar"></clr-icon>&nbsp;{{app.createdAt | timePipe}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
<!-- card view end -->
<clr-modal [(clrModalOpen)]="rsModaldescription" [clrModalSize]="'xl'" [clrModalStaticBackdrop]="true"> <clr-modal [(clrModalOpen)]="rsModaldescription" [clrModalSize]="'xl'" [clrModalStaticBackdrop]="true">
<div class="modal-body"> <div class="modal-body">
<textarea class="form-control" style="width:100%; height: 400px;" readonly>{{rowSelected}}</textarea> <textarea class="form-control" style="width:100%; height: 400px;" readonly>{{rowSelected}}</textarea>
</div> </div>
</clr-modal> </clr-modal>
<!-- // EDIT DATA......... --> <!-- // EDIT DATA......... -->
<clr-modal [(clrModalOpen)]="modalEdit" [clrModalSize]="'lg'" [clrModalStaticBackdrop]="true"> <clr-modal [(clrModalOpen)]="modalEdit" [clrModalSize]="'lg'" [clrModalStaticBackdrop]="true">
<h3 class="modal-title">Update Site Builder <!--update button --> <h3 class="modal-title">Update Site Builder <!--update button -->
@ -251,7 +346,7 @@
<form> <form>
<div class="clr-row"> <div class="clr-row">
<div class="clr-col-sm-12"> <div class="clr-col-sm-12">
<label>Name</label> <label>Website Name</label>
<input class="clr-input" type="text" [(ngModel)]="rowSelected.name" name="name" /> <input class="clr-input" type="text" [(ngModel)]="rowSelected.name" name="name" />
</div> </div>
@ -270,8 +365,51 @@
<h6> List of logoupload</h6>
<div class="clr-row" style="margin-top: 10px;">
<table class="table">
<thead>
<tr>
<th>No</th>
<th> File</th>
<th>File Name</th>
<th>Preview</th>
<th>Cancel</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let attach of FileDatalogoupload; let i=index">
<td style="width: 70px;"><input type="text" class="clr-input" value={{i+1}} [readonly]="true"> </td>
<td><input type="file" (change)="onFileChangedlogoupload($event, i)" accept="image/*" />
</td>
<td>{{attach.uploadedfile_name}}</td>
<td> <img [src]="attach.filePreview" alt="File Preview" [ngModelOptions]="{standalone: true}"
name="filePreview" width="100px" height="100px"></td>
<td>
<clr-signpost style="padding-right: 10px;">
<clr-icon shape="trash" class="is-error" aria-label="Icon Button Trigger"
clrSignpostTrigger></clr-icon>
<clr-signpost-content [clrPosition]="'bottom-middle'" *clrIfOpen>
<div style="text-align: center;"><b>Are you sure?</b></div>
<button class="btn btn-outline" [clrSignpostTrigger]="false">cancel</button>&nbsp;
<button class="btn btn-primary" (click)="deleteRowlogoupload(i,attach.id)">Delete</button>
</clr-signpost-content>
</clr-signpost>
</td>
</tr>
</tbody>
<button type="button" class="btn btn-primary button1" style="margin-left: 20px;"
(click)="onAddLineslogoupload()">
<clr-icon shape="plus"></clr-icon>
</button>
</table>
</div>
<!-- form code start --> <!-- form code start -->
<div *ngIf="checkFormCode"> <div *ngIf="checkFormCode">
@ -290,8 +428,8 @@
[(ngModel)]="rowSelected[field.extValue]" class="clr-input" /> [(ngModel)]="rowSelected[field.extValue]" class="clr-input" />
<!-- Textarea --> <label *ngSwitchCase="'textarea'">{{ field.fieldName }}</label> <!-- Textarea --> <label *ngSwitchCase="'textarea'">{{ field.fieldName }}</label>
<textarea *ngSwitchCase="'textarea'" name="{{ field.extValue }}" [(ngModel)]="rowSelected[field.extValue]" <textarea *ngSwitchCase="'textarea'" name="{{ field.extValue }}"
col="10" row="2"></textarea> [(ngModel)]="rowSelected[field.extValue]" col="10" row="2"></textarea>
<!-- Checkbox --> <label *ngSwitchCase="'checkbox'">{{ field.fieldName }}</label><br> <!-- Checkbox --> <label *ngSwitchCase="'checkbox'">{{ field.fieldName }}</label><br>
<input *ngSwitchCase="'checkbox'" [type]="field.fieldType" name="{{ field.extValue }}" <input *ngSwitchCase="'checkbox'" [type]="field.fieldType" name="{{ field.extValue }}"
@ -308,8 +446,8 @@
</div> </div>
</form> </form>
</div> </div>
</clr-modal> </clr-modal>
<clr-modal [(clrModalOpen)]="modaldelete" [clrModalSize]="'lg'" [clrModalStaticBackdrop]="true"> <clr-modal [(clrModalOpen)]="modaldelete" [clrModalSize]="'lg'" [clrModalStaticBackdrop]="true">
<div class="modal-body" *ngIf="rowSelected.id"> <div class="modal-body" *ngIf="rowSelected.id">
<h1 class="delete">Are You Sure Want to delete?</h1> <h1 class="delete">Are You Sure Want to delete?</h1>
<h2 class="heading">{{rowSelected.id}}</h2> <h2 class="heading">{{rowSelected.id}}</h2>
@ -318,16 +456,17 @@
<button type="button" (click)="delete(rowSelected.id)" class="btn btn-primary">Delete</button> <button type="button" (click)="delete(rowSelected.id)" class="btn btn-primary">Delete</button>
</div> </div>
</div> </div>
</clr-modal> </clr-modal>
<!-- ADD FORM ..... --> <!-- ADD FORM ..... -->
<clr-modal [(clrModalOpen)]="modalAdd" [clrModalSize]="'lg'" [clrModalStaticBackdrop]="true"> <clr-modal [(clrModalOpen)]="modalAdd" [clrModalSize]="'lg'" [clrModalStaticBackdrop]="true">
<h3 class="modal-title">Add Site Builder <h3 class="modal-title">Add Site Builder
<!-- aeroplane icon --> <!-- aeroplane icon -->
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
<a *ngIf="userrole.includes('ROLE_ADMIN')" style="float: right;" href="javascript:void(0)" role="tooltip" <a *ngIf="userrole?.includes('ROLE_ADMIN')" style="float: right;" href="javascript:void(0)" role="tooltip"
aria-haspopup="true" class="tooltip tooltip-sm tooltip-bottom-left"> aria-haspopup="true" class="tooltip tooltip-sm tooltip-bottom-left">
<a id="build_extension" [routerLink]="['../extension/all']" [queryParams]="{ formCode: 'Visa_status_formCode' }"> <a id="build_extension" [routerLink]="['../extension/all']"
[queryParams]="{ formCode: 'Visa_status_formCode' }">
<clr-icon shape="airplane" size="32"></clr-icon> <clr-icon shape="airplane" size="32"></clr-icon>
</a> </a>
<span class="tooltip-content">Form Extension</span> <span class="tooltip-content">Form Extension</span>
@ -338,7 +477,7 @@
<div class="clr-row" style="height: fit-content;"> <div class="clr-row" style="height: fit-content;">
<div class="clr-col-sm-12"> <div class="clr-col-sm-12">
<label> Name</label> <label>Website Name</label>
<input class="clr-input" type="text" formControlName="name" /> <input class="clr-input" type="text" formControlName="name" />
</div> </div>
@ -351,16 +490,47 @@
<label> Active</label> <label> Active</label>
<input type="checkbox" formControlName="active" clrToggle /> <input type="checkbox" formControlName="active" clrToggle />
</div> </div>
</div> </div>
<h6> List of logoupload</h6>
<div class="clr-row" style="margin-top: 10px;">
<table class="table">
<thead>
<tr>
<th>No</th>
<th> File</th>
<th>File Name</th>
<th>Preview</th>
<th>Cancel</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let attach of FileDatalogoupload; let i=index">
<td style="width: 70px;"><input type="text" class="clr-input" value={{i+1}} [readonly]="true"> </td>
<td><input type="file" (change)="onFileChangedlogoupload($event, i)"
accept="image/*" /><!--accept=".pdf,.doc,.docx,.jpg,.msg"-->
</td>
<td>{{attach.uploadedfile_name}}</td>
<td> <img [src]="attach.filePreview" alt="File Preview" [ngModelOptions]="{standalone: true}"
name="filePreview" width="100px" height="100px"></td>
<td>
<a (click)="deleteRowlogoupload(i)">
<clr-icon shape="trash" class="is-error"></clr-icon>
</a>
</td>
</tr>
</tbody>
<button type="button" class="btn btn-primary button1" style="margin-left: 20px;"
(click)="onAddLineslogoupload()">
<clr-icon shape="plus"></clr-icon>
</button>
</table>
</div>
<!-- form code start --> <!-- form code start -->
<div *ngIf="checkFormCode"> <div *ngIf="checkFormCode">
@ -392,11 +562,6 @@
</div> </div>
</form> </form>
</div> </div>
</clr-modal> </clr-modal>
<!-- htmlpopup -->
<!-- htmlpopup -->

View File

@ -59,19 +59,21 @@ export class SiteTreeComponent implements OnInit {
) { } ) { }
// component button // component button
ngOnInit(): void { ngOnInit(): void {
this.getData();
if (this.cardmodeldata !== '') { if (this.cardmodeldata !== '') {
this.cardmodal = JSON.parse(this.cardmodeldata); this.cardmodal = JSON.parse(this.cardmodeldata);
this.dashboardArray = this.cardmodal.dashboard.slice(); this.dashboardArray = this.cardmodal.dashboard.slice();
console.log(this.dashboardArray) console.log('card data ', this.dashboardArray)
} }
this.userrole = this.userInfoService.getRoles(); this.userrole = this.userInfoService.getRoles();
this.getData();
this.entryForm = this._fb.group({ this.entryForm = this._fb.group({
name: [null], name: [null],
description: [null], description: [null],
active: [false], active: [true],
}); // component_button200 }); // component_button200
// form code start // form code start
@ -99,11 +101,15 @@ export class SiteTreeComponent implements OnInit {
} }
FileDataLogoupload: any[];
selectedLogoupload: any[];
error; error;
getData() { getData() {
this.mainService.getAll().subscribe((data) => { this.mainService.getAll().subscribe((data) => {
console.log(data); console.log(data);
this.product = data; this.product = data;
console.log('site data ', this.product);
if (this.product.length == 0) { if (this.product.length == 0) {
this.error = "No Data Available" this.error = "No Data Available"
} }
@ -116,6 +122,15 @@ export class SiteTreeComponent implements OnInit {
} }
onEdit(row) { onEdit(row) {
this.rowSelected = row; this.rowSelected = row;
this.selectedlogoupload = [];
this.mainService.uploadLogouploadgetById(row.id, this.tableName).subscribe(uploaddata => {
console.log(uploaddata);
this.FileDatalogoupload = uploaddata;
})
this.modalEdit = true; this.modalEdit = true;
} }
onDelete(row) { onDelete(row) {
@ -149,6 +164,13 @@ export class SiteTreeComponent implements OnInit {
this.ngOnInit(); this.ngOnInit();
}, 500); }, 500);
for (let i = 0; i < this.selectedlogoupload.length; i++) {
this.mainService.uploadLogoupload(data.id, this.tableName, this.selectedlogoupload[i]).subscribe(uploaddata => {
console.log(uploaddata);
})
}
}, (error) => { }, (error) => {
console.log(error); console.log(error);
if (error.status >= 200 && error.status <= 299) { if (error.status >= 200 && error.status <= 299) {
@ -178,6 +200,13 @@ export class SiteTreeComponent implements OnInit {
this.ngOnInit(); this.ngOnInit();
}, 500); }, 500);
for (let i = 0; i < this.selectedlogoupload.length; i++) {
this.mainService.uploadLogoupload(data.id, this.tableName, this.selectedlogoupload[i]).subscribe(uploaddata => {
console.log(uploaddata);
})
}
}, (error) => { }, (error) => {
console.log(error); console.log(error);
if (error.status >= 200 && error.status <= 299) { if (error.status >= 200 && error.status <= 299) {
@ -195,7 +224,9 @@ export class SiteTreeComponent implements OnInit {
}, 500); }, 500);
} }
goToAdd(row) { goToAdd(row) {
this.modalAdd = true; this.submitted = false; console.log('go to add ')
this.modalAdd = true;
this.submitted = false;
} }
@ -218,6 +249,47 @@ export class SiteTreeComponent implements OnInit {
filePreviewlogoupload: string | ArrayBuffer | null = null;
FileDatalogoupload: { uploadedfile_name?: any, filePreview: string | ArrayBuffer | null }[] = []; // Initialize the array
selectedlogoupload: File[] = [];
public onFileChangedlogoupload(event, index) {
const files = event.target.files;
for (let i = 0; i < files.length; i++) {
const file = files[i];
this.FileDatalogoupload[index].uploadedfile_name = files[i].name;
this.selectedlogoupload.push(files[i]);
if (file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = (e) => {
// Set the file preview source
const filePreview = e.target?.result as string;
this.FileDatalogoupload[index] = {
...this.FileDatalogoupload[index], // Preserve existing properties
filePreview: filePreview // Update only the filePreview property
};
};
reader.readAsDataURL(file);
}
}
}
onAddLineslogoupload() {
this.FileDatalogoupload.push({
uploadedfile_name: "",
filePreview: "",
// f3: "",
});
}
deleteRowlogoupload(index, id) {
this.FileDatalogoupload.splice(index, 1);
if (id) {
this.mainService.uploadLogouploaddelete(id).subscribe(data => {
console.log(data);
})
}
}
// updateaction // updateaction
gotositebuilder(id) { gotositebuilder(id) {

View File

@ -10,6 +10,7 @@ export class SiteTreeservice {
private baseURL = "SiteTree/SiteTree"; private baseURL = "SiteTree/SiteTree";
private dlfbaseURL = environment.nodeUrl + "/entityBuilder"; private dlfbaseURL = environment.nodeUrl + "/entityBuilder";
private llmURL = environment.nodeUrl + "/llm"; private llmURL = environment.nodeUrl + "/llm";
private geminiURL = environment.ollamaUrl;
constructor( constructor(
@ -72,20 +73,20 @@ export class SiteTreeservice {
const formattedSiteName = this.formatSiteName(siteName); const formattedSiteName = this.formatSiteName(siteName);
const _http = `${this.baseURL}/deploy?siteId=${siteId}&siteBuilderName=${formattedSiteName}`; const _http = `${this.baseURL}/deploy?siteId=${siteId}&siteBuilderName=${formattedSiteName}`;
return this.apiRequest.post(_http, data); return this.apiRequest.post(_http, data);
} }
createHtmlfile(siteId: number, siteName: string, data: any): Observable<any> { createHtmlfile(siteId: number, siteName: string, data: any): Observable<any> {
const formattedSiteName = this.formatSiteName(siteName); const formattedSiteName = this.formatSiteName(siteName);
const _http = `${this.baseURL}/createFile?siteId=${siteId}&siteBuilderName=${formattedSiteName}`; const _http = `${this.baseURL}/createFile?siteId=${siteId}&siteBuilderName=${formattedSiteName}`;
return this.apiRequest.post(_http, data); return this.apiRequest.post(_http, data);
} }
readPages( siteName: string, pageName: string): Observable<any> { readPages(siteName: string, pageName: string): Observable<any> {
const formattedSite = this.formatSiteName(siteName); const formattedSite = this.formatSiteName(siteName);
const _http = `${this.baseURL}/read?siteBuilderName=${formattedSite}&filename=${pageName}`; const _http = `${this.baseURL}/read?siteBuilderName=${formattedSite}&filename=${pageName}`;
return this.apiRequest.get(_http, undefined, 'text'); return this.apiRequest.get(_http, undefined, 'text');
} }
@ -98,7 +99,7 @@ readPages( siteName: string, pageName: string): Observable<any> {
.replace(/([a-z])([A-Z])/g, '$1_$2') // Convert camelCase to snake_case .replace(/([a-z])([A-Z])/g, '$1_$2') // Convert camelCase to snake_case
.replace(/\s+/g, '_') // Replace spaces with underscores .replace(/\s+/g, '_') // Replace spaces with underscores
.toLowerCase(); .toLowerCase();
} }
// readPages(siteNmae: String, pageNmae: String): Observable<any> { // readPages(siteNmae: String, pageNmae: String): Observable<any> {
@ -110,5 +111,22 @@ readPages( siteName: string, pageName: string): Observable<any> {
return this.http.post(`${this.llmURL}/api/gemini`, data); return this.http.post(`${this.llmURL}/api/gemini`, data);
} }
uploadLogoupload(ref: any, Sitebuilder: any, file: any): Observable<any> {
const formData = new FormData();
formData.append('file', file);
return this.apiRequest.postFormData(`FileUpload/Uploadeddocs/${ref}/${Sitebuilder}`, formData);
}
uploadLogouploadgetById(ref: any, Sitebuilder: any,): Observable<any> {
return this.apiRequest.get(`FileUpload/Uploadeddocs/${ref}/${Sitebuilder}`);
}
uploadLogouploaddelete(id: number): Observable<any> {
return this.apiRequest.delete(`FileUpload/Uploadeddocs/${id}`);
}
// updateactionƒ // updateactionƒ
} }

View File

@ -1,4 +1,6 @@
export const SiteTreecardvariable = { export const SiteTreecardvariable = {
"cardButton": false, "cardButton": false,
// "cardmodeldata": ``
"cardmodeldata": `` "cardmodeldata": ``
} }

View File

@ -0,0 +1,376 @@
<ol class="breadcrumb breadcrumb-arrow font-trirong">
<li><a href="javascript://"> Tag</a></li>
</ol>
<div class="dg-wrapper">
<div class="clr-row">
<div class="clr-col-8">
<h3>Tag </h3>
</div>
<div class="clr-col-4" style="text-align: right;">
<button *ngIf="cardButton" id="add" class="btn btn-primary btn-icon" (click)="changeView()" >
<clr-icon *ngIf="!isCardview" shape="grid-view"></clr-icon> <clr-icon *ngIf="isCardview" shape="bars"></clr-icon>
</button>
<!-- button -->
<button id="add" class="btn btn-primary" (click)="goToAdd(product)" >
<clr-icon shape="plus"></clr-icon>ADD
</button>
</div></div>
<ng-container *ngIf="!isCardview"> <!-- GET ALL --> <clr-datagrid [clrDgLoading]="loading" [(clrDgSelected)]="selected">
<clr-dg-placeholder>
<ng-template #loadingSpinner>
<clr-spinner>Loading ... </clr-spinner>
</ng-template>
<div *ngIf="error;else loadingSpinner">{{error}}</div>
</clr-dg-placeholder>
<clr-dg-column [clrDgField]="' name'"> <ng-container *clrDgHideableColumn="{hidden: false}"> Name
</ng-container></clr-dg-column>
<clr-dg-column [clrDgField]="' description'"> <ng-container *clrDgHideableColumn="{hidden: false}"> Description
</ng-container></clr-dg-column>
<clr-dg-column [clrDgField]="' active'"> <ng-container *clrDgHideableColumn="{hidden: false}"> Active
</ng-container></clr-dg-column>
<!-- who column -->
<clr-dg-column> <ng-container *clrDgHideableColumn="{hidden: false}">
<clr-icon shape="bars"></clr-icon> Action
</ng-container></clr-dg-column>
<!-- end -->
<clr-dg-row *clrDgItems="let user of product" [clrDgItem]="user">
<clr-dg-cell>{{user. name }}</clr-dg-cell>
<clr-dg-cell (click)="goToReplaceStringdescription (user.description)" style="cursor: pointer; align-items: center;"><clr-icon shape="details"></clr-icon>
</clr-dg-cell>
<clr-dg-cell>{{user. active }}</clr-dg-cell>
<!-- who column -->
<clr-dg-cell>
<clr-signpost>
<span style="cursor: pointer;" clrSignpostTrigger><clr-icon shape="help" class="success" style="color: rgb(0, 130, 236);"></clr-icon></span>
<clr-signpost-content [clrPosition]="'left-middle'" *clrIfOpen>
<h5 style="margin-top: 0">Who Column</h5>
<div>Account ID: <code class="clr-code">{{user.accountId}}</code></div>
<div>Created At: <code class="clr-code">{{user.createdAt| date}}</code></div>
<div>Created By: <code class="clr-code">{{user.createdBy}}</code></div>
<div>Updated At: <code class="clr-code">{{user.updatedAt | date}}</code></div>
<div>Updated By: <code class="clr-code">{{user.updatedBy}}</code></div>
</clr-signpost-content>
</clr-signpost>
</clr-dg-cell>
<!-- who colmn -->
<clr-dg-action-overflow>
<button class="action-item" (click)="onEdit(user)">Edit</button>
<button class="action-item" (click)="onDelete(user)">Delete</button>
</clr-dg-action-overflow>
</clr-dg-row>
<clr-dg-footer>
<clr-dg-pagination #pagination [clrDgPageSize]="10">
<clr-dg-page-size [clrPageSizeOptions]="[10,20,50,100]">Users per page</clr-dg-page-size>
{{pagination.firstItem + 1}} - {{pagination.lastItem + 1}}
of {{pagination.totalItems}} users
</clr-dg-pagination>
</clr-dg-footer>
</clr-datagrid> </ng-container>
<ng-template #showInfo>
<div class="alert alert-info" role="alert">
<div class="alert-items">
<div class="alert-item static">
<span class="alert-text">
<clr-icon class="alert-icon" shape="info-circle"></clr-icon>
Data could be found. Loading..
<clr-spinner [clrMedium]="true">Loading ...</clr-spinner>
</span>
</div>
</div>
</div>
</ng-template><ng-container *ngIf="isCardview">
<div *ngIf="product; else showInfo" class="clr-row clr-align-items-start clr-justify-content-start">
<div *ngFor="let app of product| filter:search; let index = i" class="clr-col-auto" >
<div class="clr-row">
<div class="clr-col-lg-12 clr-col-md-4 clr-col-sm-4 clr-col-12" style="width: 410px;">
<div class="card" style="padding: 10px; "[style.background-color]="cardmodal.cardColor !== '' ? cardmodal.cardColor : 'white'">
<div class="card-body" style="display: grid; grid-template-columns: repeat(13, 1fr); grid-template-rows: repeat(7, 1fr); gap: 5px;">
<ng-container *ngFor="let item of dashboardArray">
<div [style.gridColumn]="item.x + 1" [style.gridRow]="item.y + 1" [style.gridColumnEnd]="item.x + item.cols + 1"
[style.gridRowEnd]="item.y + item.rows + 1">
<div *ngIf="item.name === 'textField'" class="title-card card-title"
[style.text-align]="item.alignment !== '' ? item.alignment : 'left'"
[style.line-height]="item.textlineheight !== '' ? item.textlineheight : '1'"
[style.font-family]="item.fontName !== '' ? item.fontName : 'Metropolis'"
[style.font-size]="item.fontSize !== '' ? item.fontSize : '100%'"
[style.font-style]="item.italic == true ? 'Italic' : 'normal'"
[style.font-weight]="item.bold == true ? 'bold' : 'normal'" [style.text-decoration]="(item.underline && item.strikethough) ? 'underline line-through' :
(item.underline ? 'underline' : (item.strikethough ? 'line-through' : 'none'))"
[style.background-color]="item.backgroundcolor !== '' ? item.backgroundcolor : 'white'"
[style.color]="item.textcolor !== '' ? item.textcolor : 'black'" [style.background-color]="item.conditionValue == app[transform(item.fieldtext) ] ? item.conditionbackgroundcolor : item.backgroundcolor"
[style.color]="item.conditionValue == app[transform(item.fieldtext) ] ? item.conditiontextcolor : item.textcolor">
{{beforeText(item.fieldtext)}}
{{ app[transform(item.fieldtext) ] }}
{{afterText(item.fieldtext)}}
</div>
<div *ngIf="item.name === 'dateField'" class="title-card card-title"
[style.text-align]="item.alignment !== '' ? item.alignment : 'left'"
[style.line-height]="item.textlineheight !== '' ? item.textlineheight : '1'"
[style.font-family]="item.fontName !== '' ? item.fontName : 'Metropolis'"
[style.font-size]="item.fontSize !== '' ? item.fontSize : '100%'"
[style.font-style]="item.italic == true ? 'Italic' : 'normal'"
[style.font-weight]="item.bold == true ? 'bold' : 'normal'" [style.text-decoration]="(item.underline && item.strikethough) ? 'underline line-through' :
(item.underline ? 'underline' : (item.strikethough ? 'line-through' : 'none'))"
[style.background-color]="item.backgroundcolor !== '' ? item.backgroundcolor : 'white'"
[style.color]="item.textcolor !== '' ? item.textcolor : 'black'" [style.background-color]="item.conditionValue == app[transform(item.fieldtext) ] ? item.conditionbackgroundcolor : item.backgroundcolor"
[style.color]="item.conditionValue == app[transform(item.fieldtext) ] ? item.conditiontextcolor : item.textcolor">
{{beforeText(item.fieldtext)}}
{{ app[transform(item.fieldtext) ] | date}}
{{afterText(item.fieldtext)}}
</div>
<div *ngIf="item.name === 'numberField'" class="title-card card-title"
[style.text-align]="item.alignment !== '' ? item.alignment : 'left'"
[style.line-height]="item.textlineheight !== '' ? item.textlineheight : '1'"
[style.font-family]="item.fontName !== '' ? item.fontName : 'Metropolis'"
[style.font-size]="item.fontSize !== '' ? item.fontSize : '100%'"
[style.font-style]="item.italic == true ? 'Italic' : 'normal'"
[style.font-weight]="item.bold == true ? 'bold' : 'normal'" [style.text-decoration]="(item.underline && item.strikethough) ? 'underline line-through' :
(item.underline ? 'underline' : (item.strikethough ? 'line-through' : 'none'))"
[style.background-color]="item.backgroundcolor !== '' ? item.backgroundcolor : 'white'"
[style.color]="item.textcolor !== '' ? item.textcolor : 'black'" [style.background-color]="item.conditionValue == app[transform(item.fieldtext) ] ? item.conditionbackgroundcolor : item.backgroundcolor"
[style.color]="item.conditionValue == app[transform(item.fieldtext) ] ? item.conditiontextcolor : item.textcolor">
{{beforeText(item.fieldtext)}}
{{ app[transform(item.fieldtext) ]}}
{{afterText(item.fieldtext)}}
</div>
<div *ngIf="item.name === 'Line'" class="title-card card-title"
[style.text-align]="item.alignment !== '' ? item.alignment : 'left'"
[style.line-height]="item.textlineheight !== '' ? item.textlineheight : '1'"
[style.font-family]="item.fontName !== '' ? item.fontName : 'Metropolis'"
[style.font-size]="item.fontSize !== '' ? item.fontSize : '100%'"
[style.font-style]="item.italic == true ? 'Italic' : 'normal'"
[style.font-weight]="item.bold == true ? 'bold' : 'normal'" [style.text-decoration]="(item.underline && item.strikethough) ? 'underline line-through' :
(item.underline ? 'underline' : (item.strikethough ? 'line-through' : 'none'))"
[style.background-color]="item.backgroundcolor !== '' ? item.backgroundcolor : 'white'"
[style.color]="item.textcolor !== '' ? item.textcolor : 'black'">
<hr>
</div>
<div *ngIf="item.name === 'Icon'" class="icon-card"
[style.text-align]="item.alignment !== '' ? item.alignment : 'left'"
[style.line-height]="item.textlineheight !== '' ? item.textlineheight : '1'"
[style.font-family]="item.fontName !== '' ? item.fontName : 'Metropolis'"
[style.font-size]="item.fontSize !== '' ? item.fontSize : '100%'"
[style.font-style]="item.italic == true ? 'Italic' : 'normal'"
[style.font-weight]="item.bold == true ? 'bold' : 'normal'" [style.text-decoration]="(item.underline && item.strikethough) ? 'underline line-through' :
(item.underline ? 'underline' : (item.strikethough ? 'line-through' : 'none'))"
[style.background-color]="item.backgroundcolor !== '' ? item.backgroundcolor : 'white'"
[style.color]="item.textcolor !== '' ? item.textcolor : 'black'"
>
<clr-icon [attr.shape]="item.iconName"></clr-icon>
</div>
<div *ngIf="item.name == 'Image'"
[style.text-align]="item.alignment !== '' ? item.alignment : 'left'"
[style.line-height]="item.textlineheight !== '' ? item.textlineheight : '1'"
[style.font-family]="item.fontName !== '' ? item.fontName : 'Metropolis'"
[style.font-size]="item.fontSize !== '' ? item.fontSize : '100%'"
[style.font-style]="item.italic == true ? 'Italic' : 'normal'"
[style.font-weight]="item.bold == true ? 'bold' : 'normal'" [style.text-decoration]="(item.underline && item.strikethough) ? 'underline line-through' :
(item.underline ? 'underline' : (item.strikethough ? 'line-through' : 'none'))"
[style.background-color]="item.backgroundcolor !== '' ? item.backgroundcolor : 'white'"
[style.color]="item.textcolor !== '' ? item.textcolor : 'black'"
[style.background-color]="item.conditionValue == app[transform(item.fieldtext) ] ? item.conditionbackgroundcolor : item.backgroundcolor"
[style.color]="item.conditionValue == app[transform(item.fieldtext) ] ? item.conditiontextcolor : item.textcolor"> <img id="filePreview" [src]="item.imageURL" alt="File Preview"
[style.width]="item.imagewidth !== '' ? item.imagewidth + 'px' : '100px'"
[style.height]="item.imagewidth !== '' ? item.imagewidth + 'px' : '100px'"></div>
</div>
</ng-container>
</div>
</div>
</div>
</div>
</div>
</div>
</ng-container>
</div>
<clr-modal [(clrModalOpen)]="rsModaldescription" [clrModalSize]="'xl'" [clrModalStaticBackdrop]="true">
<div class="modal-body">
<textarea class="form-control" style="width:100%; height: 400px;" readonly>{{rowSelected}}</textarea>
</div></clr-modal>
<!-- // EDIT DATA......... -->
<clr-modal [(clrModalOpen)]="modalEdit" [clrModalSize]="'lg'" [clrModalStaticBackdrop]="true">
<h3 class="modal-title">Update Tag
<!--update button -->
</h3>
<div class="modal-body" *ngIf="rowSelected.id">
<h2 class="heading">{{rowSelected.id}}</h2>
<!-- button -->
<form >
<div class="clr-row">
<div class="clr-col-sm-12">
<label>Name</label>
<input class="clr-input" type="text" [(ngModel)]="rowSelected.name" name="name" />
</div>
<div class="clr-col-sm-12">
<label> Description</label>
<textarea cols="10" rows="2"[(ngModel)]="rowSelected.description" name="description " placeholder="Textarea"> </textarea>
</div>
<div class="clr-col-sm-12">
<label> Active</label>
<input type="checkbox" name="active" clrToggle [(ngModel)]="rowSelected.active" /> </div>
</div>
<!-- form code start -->
<div *ngIf="checkFormCode">
<h4 style="font-weight: 300;display: inline;">Extension</h4>
<br>
<hr>
<div class="clr-row">
<div class="clr-col-4" *ngFor="let field of additionalFieldsFromBackend">
<ng-container *ngIf="field.formCode === formcode" [ngSwitch]="field.fieldType">
<!-- Text Input --> <label *ngSwitchCase="'text'">{{ field.fieldName }}</label>
<input *ngSwitchCase="'text'" [type]="field.fieldType" name="{{ field.extValue }}" [(ngModel)]="rowSelected[field.extValue]" class="clr-input" />
<!-- Date Input --> <label *ngSwitchCase="'date'">{{ field.fieldName }}</label>
<input *ngSwitchCase="'date'" [type]="field.fieldType" name="{{ field.extValue }}" [(ngModel)]="rowSelected[field.extValue]" class="clr-input" />
<!-- Textarea --> <label *ngSwitchCase="'textarea'">{{ field.fieldName }}</label>
<textarea *ngSwitchCase="'textarea'" name="{{ field.extValue }}" [(ngModel)]="rowSelected[field.extValue]" col="10" row="2"></textarea>
<!-- Checkbox --> <label *ngSwitchCase="'checkbox'">{{ field.fieldName }}</label><br>
<input *ngSwitchCase="'checkbox'" [type]="field.fieldType" name="{{ field.extValue }}" [(ngModel)]="rowSelected[field.extValue]" class="clr-checkbox" />
</ng-container>
</div>
</div>
</div>
<!-- form code end --> <div class="modal-footer">
<button type="button" class="btn btn-outline" (click)="modalEdit = false">Cancel</button>
<button type="submit" class="btn btn-primary" (click)="onUpdate(rowSelected.id)">Update</button>
</div>
</form>
</div>
</clr-modal>
<clr-modal [(clrModalOpen)]="modaldelete" [clrModalSize]="'lg'" [clrModalStaticBackdrop]="true">
<div class="modal-body" *ngIf="rowSelected.id">
<h1 class="delete">Are You Sure Want to delete?</h1>
<h2 class="heading">{{rowSelected.id}}</h2>
<div class="modal-footer">
<button type="button" class="btn btn-outline" (click)="modaldelete = false">Cancel</button>
<button type="button" (click)="delete(rowSelected.id)" class="btn btn-primary" >Delete</button>
</div>
</div>
</clr-modal>
<!-- ADD FORM ..... -->
<clr-modal [(clrModalOpen)]="modalAdd" [clrModalSize]="'lg'" [clrModalStaticBackdrop]="true">
<h3 class="modal-title">Add Tag
<!-- aeroplane icon -->
&nbsp; &nbsp; &nbsp; &nbsp;
<a *ngIf="userrole.includes('ADMIN')" style="float: right;" href="javascript:void(0)" role="tooltip" aria-haspopup="true"
class="tooltip tooltip-sm tooltip-bottom-left">
<a id="build_extension" [routerLink]="['../extension/all']" [queryParams]="{ formCode: 'Tag_formCode' }">
<clr-icon shape="airplane" size="32"></clr-icon>
</a>
<span class="tooltip-content">Form Extension</span>
</a> </h3>
<div class="modal-body">
<form [formGroup]="entryForm" >
<div class="clr-row" style="height: fit-content;">
<div class="clr-col-sm-12">
<label> Name</label>
<input class="clr-input" type="text" formControlName="name" />
</div>
<div class="clr-col-sm-12">
<label> Description</label>
<textarea cols="10" rows="2" formControlName="description" placeholder="Textarea"> </textarea>
</div>
<div class="clr-col-sm-12">
<label> Active</label>
<input type="checkbox" formControlName="active" clrToggle/> </div>
</div>
<!-- form code start -->
<div *ngIf="checkFormCode">
<h4 style="font-weight: 300;display: inline;">Extension</h4>
<br>
<hr>
<div class="clr-row">
<div class="clr-col-4" *ngFor="let field of additionalFieldsFromBackend">
<ng-container *ngIf="field.formCode === formcode" [ngSwitch]="field.fieldType">
<!-- Text Input --> <label *ngSwitchCase="'text'">{{ field.fieldName }}</label>
<input *ngSwitchCase="'text'" [type]="field.fieldType" [formControlName]="field.extValue"
class="clr-input" />
<!-- Date Input --> <label *ngSwitchCase="'date'">{{ field.fieldName }}</label>
<input *ngSwitchCase="'date'" [type]="field.fieldType" [formControlName]="field.extValue"
class="clr-input" />
<!-- Textarea --> <label *ngSwitchCase="'textarea'">{{ field.fieldName }}</label>
<textarea *ngSwitchCase="'textarea'" [formControlName]="field.extValue" col="10" row="2"></textarea>
<!-- Checkbox --> <label *ngSwitchCase="'checkbox'">{{ field.fieldName }}</label><br>
<input *ngSwitchCase="'checkbox'" [type]="field.fieldType" [formControlName]="field.extValue"
class="clr-checkbox" />
</ng-container>
</div>
</div>
</div>
<!-- form code end --> <div class="modal-footer">
<button type="button" class="btn btn-outline" (click)="modalAdd = false">Cancel</button>
<button type="submit" class="btn btn-primary" (click)="onSubmit()">ADD</button>
</div>
</form>
</div>
</clr-modal>
<!-- htmlpopup -->

View File

@ -0,0 +1,78 @@
//@import "../../../../assets/scss/var";
.s-info-bar {
display: flex;
flex-direction: row;
justify-content: space-between;
button {
outline: none;
}
}
.delete,.heading{
text-align: center;
color: red;
}
.entry-pg {
width: 750px;
}
.button1::after {
content: none;
}
.button1:hover::after {
content: "ADD ROWS";
}
.section {
background-color: #dddddd;
height: 40px;
}
.section p {
//color: white;
padding: 10px;
font-size: 18px;
}
.clr-input {
color: #212529;
border: 1px solid #ced4da;
border-radius: 0.25rem;
padding: 0.75rem 0.75rem;
margin-top: 3px;
width: 100%;
margin-bottom: 10px;
}
.clr-file {
color: #212529;
border: 1px solid #ced4da;
border-radius: 0.25rem;
//padding: 0.6rem 0.75rem;
margin-top: 3px;
width: 100%;
margin-bottom: 10px;
}
.center {
text-align: center;
}
select{
width: 100%;
margin-top: 3px;
padding: 5px 5px;
border: 1px solid #ccc;
border-radius: 4px;
}
input[type=text],[type=date],[type=number],textarea {
width: 100%;
padding: 15px 15px;
background-color:rgb(255, 255, 255);
// margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
.error_mess {
color: red;
}

View File

@ -0,0 +1,244 @@
import { Component, OnInit } from '@angular/core';
import { ToastrService } from 'ngx-toastr';
import { AlertService } from 'src/app/services/alert.service';
import { Tagservice } from './Tag.service';
import { AbstractControl, FormArray, FormBuilder, FormGroup, Validators, ValidationErrors } from '@angular/forms';
import { ExtensionService } from 'src/app/services/fnd/extension.service';
import { DashboardContentModel2 } from 'src/app/models/builder/dashboard';
import { Tagcardvariable } from './Tag_cardvariable';
import { UserInfoService } from 'src/app/services/user-info.service';
declare var JsBarcode: any;
@Component({
selector: 'app-Tag',
templateUrl: './Tag.component.html',
styleUrls: ['./Tag.component.scss']
})
export class TagComponent implements OnInit {
cardButton = Tagcardvariable.cardButton;
cardmodeldata = Tagcardvariable.cardmodeldata;
public dashboardArray: DashboardContentModel2[];
isCardview = Tagcardvariable.cardButton;
cardmodal; changeView() {
this.isCardview = !this.isCardview;
}
beforeText(fieldtext: string): string { // Extract the text before the first '<'
const index = fieldtext.indexOf('<');
return index !== -1 ? fieldtext.substring(0, index) : fieldtext;
}
afterText(fieldtext: string): string { // Extract the text after the last '>'
const index = fieldtext.lastIndexOf('>');
return index !== -1 ? fieldtext.substring(index + 1) : '';
}
transform(fieldtext: string): string {
const match = fieldtext.match(/<([^>]*)>/);
return match ? match[1] : ''; // Extract the text between '<' and '>'
}
userrole;
rowSelected: any = {};
modaldelete = false;
modalEdit = false;
modalAdd = false;
public entryForm: FormGroup;
loading = false;
product;
modalOpenedforNewLine = false;
newLine: any;
additionalFieldsFromBackend: any[] = [];
formcode = 'Tag_formCode'
tableName = 'Tag'; checkFormCode; selected: any[] = []; constructor(
private extensionService: ExtensionService,
private userInfoService: UserInfoService,
private mainService: Tagservice,
private alertService: AlertService,
private toastr: ToastrService,
private _fb: FormBuilder,
) { }
// component button
ngOnInit(): void {
if (this.cardmodeldata !== '') {
this.cardmodal = JSON.parse(this.cardmodeldata);
this.dashboardArray = this.cardmodal.dashboard.slice();
console.log(this.dashboardArray)
}
this.userrole = this.userInfoService.getRoles();
this.getData();
this.entryForm = this._fb.group({
name: [null],
description: [null],
active: [false],
}); // component_button200
// form code start
this.extensionService.getJsonObjectsByFormCodeList(this.formcode).subscribe(data => {
console.log(data);
const jsonArray = data.map((str) => JSON.parse(str));
this.additionalFieldsFromBackend = jsonArray;
this.checkFormCode = this.additionalFieldsFromBackend.some(field => field.formCode === "Tag_formCode");
console.log(this.checkFormCode);
console.log(this.additionalFieldsFromBackend);
if (this.additionalFieldsFromBackend && this.additionalFieldsFromBackend.length > 0) {
this.additionalFieldsFromBackend.forEach(field => {
if (field.formCode === this.formcode) {
if (!this.entryForm.contains(field.extValue)) {
// Add the control only if it doesn't exist in the form
this.entryForm.addControl(field.extValue, this._fb.control(field.fieldValue));
}
}
});
}
});
console.log(this.entryForm.value);
// form code end
}
error;
getData() {
this.mainService.getAll().subscribe((data) => {
console.log(data);
this.product = data;
if (this.product.length == 0) {
this.error = "No Data Available"
}
}, (error) => {
console.log(error);
if (error) {
this.error = "Server Error";
}
});
}
onEdit(row) {
this.rowSelected = row;
this.modalEdit = true;
}
onDelete(row) {
this.rowSelected = row;
this.modaldelete = true;
}
delete(id) {
this.modaldelete = false;
console.log("in delete " + id);
this.mainService.delete(id).subscribe(
(data) => {
console.log(data);
this.ngOnInit();
if (data) { this.toastr.success('Deleted successfully'); }
});
}
onUpdate(id) {
this.modalEdit = false;
//console.log("in update");
console.log("id " + id);
console.log(this.rowSelected);
//console.log("out update");
this.mainService.update(id, this.rowSelected).subscribe(
(data) => {
console.log(data);
if (data || data.status >= 200 && data.status <= 299) {
this.toastr.success("Update Successfully");
}
setTimeout(() => {
this.ngOnInit();
}, 500);
}, (error) => {
console.log(error);
if (error.status >= 200 && error.status <= 299) {
// this.toastr.success("update Succesfully");
}
if (error.status >= 400 && error.status <= 499) {
this.toastr.error("Not Updated");
}
if (error.status >= 500 && error.status <= 599) {
this.toastr.error("Not Updated");
}
});
setTimeout(() => {
this.ngOnInit();
}, 500);
}
onCreate() {
this.modalAdd = false;
this.mainService.create(this.entryForm.value).subscribe(
(data) => {
console.log(data);
if (data || data.status >= 200 && data.status <= 299) {
this.toastr.success("Added Successfully");
}
setTimeout(() => {
this.ngOnInit();
}, 500);
}, (error) => {
console.log(error);
if (error.status >= 200 && error.status <= 299) {
// this.toastr.success("Added Succesfully");
}
if (error.status >= 400 && error.status <= 499) {
this.toastr.error("Not Added");
}
if (error.status >= 500 && error.status <= 599) {
this.toastr.error("Not Added");
}
});
setTimeout(() => {
this.ngOnInit();
}, 500);
}
goToAdd(row) {
this.modalAdd = true; this.submitted = false;
}
submitted = false;
onSubmit() {
console.log(this.entryForm.value);
this.submitted = true;
if (this.entryForm.invalid) {
return;
} this.onCreate();
}
rsModaldescription = false;
goToReplaceStringdescription(row) {
this.rowSelected = row; this.rsModaldescription = true;
}
// updateaction
}

View File

@ -0,0 +1,39 @@
import { Injectable } from '@angular/core';
import { Observable } from "rxjs";
import { HttpClient, HttpHeaders, HttpParams, } from "@angular/common/http";
import { ApiRequestService } from "src/app/services/api/api-request.service";
import { environment } from 'src/environments/environment';
@Injectable({
providedIn: 'root'
})
export class Tagservice{
private baseURL = "Tag/Tag" ; constructor(
private http: HttpClient,
private apiRequest: ApiRequestService,
) { }
getAll(page?: number, size?: number): Observable<any> {
return this.apiRequest.get(this.baseURL);
}
getById(id: number): Observable<any> {
const _http = this.baseURL + "/" + id;
return this.apiRequest.get(_http);
}
create(data: any): Observable<any> {
return this.apiRequest.post(this.baseURL, data);
}
update(id: number, data: any): Observable<any> {
const _http = this.baseURL + "/" + id;
return this.apiRequest.put(_http, data);
}
delete(id: number): Observable<any> {
const _http = this.baseURL + "/" + id;
return this.apiRequest.delete(_http);
}
// updateaction
}

View File

@ -0,0 +1,4 @@
export const Tagcardvariable = {
"cardButton": false,
"cardmodeldata": ``
}

View File

@ -132,9 +132,7 @@
</div> </div>
<!-- Fixed Right Sidebar --> <!-- Fixed Right Sidebar -->
<div class="wireframe-controls-sidebar" <div class="wireframe-controls-sidebar" [class.collapsed]="sidebarCollapsed" [class.mobile-open]="sidebarOpen"
[class.collapsed]="sidebarCollapsed"
[class.mobile-open]="sidebarOpen"
[class.visible]="sidebarOpen || !isMobile"> [class.visible]="sidebarOpen || !isMobile">
<!-- Loading Overlay --> <!-- Loading Overlay -->
@ -145,10 +143,7 @@
<!-- Updated Close Button --> <!-- Updated Close Button -->
<div class="sidebar-header"> <div class="sidebar-header">
<button <button (click)="toggleSidebar()" class="close-btn" style="
(click)="toggleSidebar()"
class="close-btn"
style="
background: none; background: none;
border: none; border: none;
color: #060606; color: #060606;
@ -157,8 +152,7 @@
border-radius: 50%; border-radius: 50%;
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
font-size: 16px; font-size: 16px;
" ">
>
<i class="fas" [ngClass]="sidebarCollapsed ? 'fa-chevron-left' : 'fa-chevron-right'"></i> <i class="fas" [ngClass]="sidebarCollapsed ? 'fa-chevron-left' : 'fa-chevron-right'"></i>
</button> </button>
<h2>Wireframe Controls</h2> <h2>Wireframe Controls</h2>
@ -174,14 +168,10 @@
</h3> </h3>
<div class="search-container"> <div class="search-container">
<input <input type="text" class="search-input" [(ngModel)]="searchTerm" (input)="onSearchChange()"
type="text" placeholder="Search sections...">
class="search-input" </div>
[(ngModel)]="searchTerm" </div>
(input)="onSearchChange()"
placeholder="Search sections..."
> </div>
</div>
@ -196,8 +186,7 @@
</h3> </h3>
<div class="wf-section-list" *ngIf="getFilteredSections(globalSections).length"> <div class="wf-section-list" *ngIf="getFilteredSections(globalSections).length">
<div class="wf-section-item" <div class="wf-section-item" *ngFor="let section of getFilteredSections(globalSections)"
*ngFor="let section of getFilteredSections(globalSections)"
(click)="addSectionFromTemplate(section)"> (click)="addSectionFromTemplate(section)">
<div class="section-icon"> <div class="section-icon">
<i [class]="section.icon"></i> <i [class]="section.icon"></i>
@ -211,15 +200,14 @@
</div> </div>
<!-- Standard Sections --> <!-- Standard Sections -->
<div class="control-section fade-in-left" [@fadeIn]> <div class="control-section fade-in-left" [@fadeIn]>
<h3> <h3>
<i class="fas fa-th-large" style="margin-right: 6px; color: #fd7e14;"></i> <i class="fas fa-th-large" style="margin-right: 6px; color: #fd7e14;"></i>
Standard Sections Standard Sections
</h3> </h3>
<div class="wf-section-list" *ngIf="getFilteredSections(standardSections).length"> <div class="wf-section-list" *ngIf="getFilteredSections(standardSections).length">
<div class="wf-section-item" <div class="wf-section-item" *ngFor="let section of getFilteredSections(standardSections)"
*ngFor="let section of getFilteredSections(standardSections)"
(click)="addSectionFromTemplate(section)"> (click)="addSectionFromTemplate(section)">
<div class="section-icon"> <div class="section-icon">
<i [class]="section.icon"></i> <i [class]="section.icon"></i>
@ -233,15 +221,14 @@
</div> </div>
<!-- Custom Sections --> <!-- Custom Sections -->
<div class="control-section fade-in-left" [@fadeIn]> <div class="control-section fade-in-left" [@fadeIn]>
<h3> <h3>
<i class="fas fa-puzzle-piece" style="margin-right: 6px; color: #e83e8c;"></i> <i class="fas fa-puzzle-piece" style="margin-right: 6px; color: #e83e8c;"></i>
Custom Sections Custom Sections
</h3> </h3>
<div class="wf-section-list" *ngIf="getFilteredSections(customSections).length"> <div class="wf-section-list" *ngIf="getFilteredSections(customSections).length">
<div class="wf-section-item" <div class="wf-section-item" *ngFor="let section of getFilteredSections(customSections)"
*ngFor="let section of getFilteredSections(customSections)"
(click)="addSectionFromTemplate(section)"> (click)="addSectionFromTemplate(section)">
<div class="section-icon"> <div class="section-icon">
<i [class]="section.icon"></i> <i [class]="section.icon"></i>
@ -293,6 +280,11 @@
Build Wireframe Build Wireframe
</button> </button>
<button class="action-btn secondary" (click)="buildSiteBuilder()" [@buttonHover]>
<i class="fas fa-hammer"></i>
Build Site Builder
</button>
<button class="action-btn primary" (click)="goToWireFrameEdit()"> <button class="action-btn primary" (click)="goToWireFrameEdit()">
<i class="fas fa-sync-alt"></i> <i class="fas fa-sync-alt"></i>
Edit WireFrame Edit WireFrame
@ -410,15 +402,13 @@
</div> </div>
--> -->
</div> </div>
</div> </div>
<!-- Main Canvas Area --> <!-- Main Canvas Area -->
<div class="canvas-main-area" [class.sidebar-collapsed]="sidebarCollapsed"> <div class="canvas-main-area" [class.sidebar-collapsed]="sidebarCollapsed">
<div class="wireframe-controls-sidebar-overlay" <div class="wireframe-controls-sidebar-overlay" *ngIf="sidebarOpen && !isMobile" (click)="sidebarOpen = false">
*ngIf="sidebarOpen && !isMobile"
(click)="sidebarOpen = false">
</div> </div>
<!-- Infinite Grid Background --> <!-- Infinite Grid Background -->
@ -427,17 +417,12 @@
<!-- Zoom Controls --> <!-- Zoom Controls -->
<!-- Canvas Container --> <!-- Canvas Container -->
<div class="canvas-container" <div class="canvas-container" [class.panning]="isPanning" (mousedown)="startPan($event)" (mousemove)="doPan($event)"
[class.panning]="isPanning" (mouseup)="endPan()" (mouseleave)="endPan()" (wheel)="onWheel($event)">
(mousedown)="startPan($event)"
(mousemove)="doPan($event)"
(mouseup)="endPan()"
(mouseleave)="endPan()"
(wheel)="onWheel($event)">
<!-- Loading Overlay --> <!-- Loading Overlay -->
<!-- Updated Loading Overlay --> <!-- Updated Loading Overlay -->
<div *ngIf="isLoading" class="loading-overlay" [@fadeIn]> <div *ngIf="isLoading" class="loading-overlay" [@fadeIn]>
<div class="loading-container"> <div class="loading-container">
<mat-spinner diameter="50" color="accent"></mat-spinner> <mat-spinner diameter="50" color="accent"></mat-spinner>
<div class="loading-text">Building Interface...</div> <div class="loading-text">Building Interface...</div>
@ -446,33 +431,27 @@
<div class="progress-fill" [style.width.%]="loadProgress"></div> <div class="progress-fill" [style.width.%]="loadProgress"></div>
</div> </div>
</div> </div>
</div> </div>
<!-- Updated single page container with minimal header and full height --> <!-- Updated single page container with minimal header and full height -->
<!-- Replace your current "all-pages-grid-container" section with this --> <!-- Replace your current "all-pages-grid-container" section with this -->
<div *ngIf="!isLoading" class="single-page-container" [style.transform]="getPageTransform()"> <div *ngIf="!isLoading" class="single-page-container" [style.transform]="getPageTransform()">
<div class="page-info"> <div class="page-info">
<h2 class="current-page-title">{{ getCurrentPageName() }}</h2> <h2 class="current-page-title">{{ getCurrentPageName() }}</h2>
<span class="page-counter">Page {{ currentPageIndex + 1 }} of {{ pageRenderOrder.length }}</span> <span class="page-counter">Page {{ currentPageIndex + 1 }} of {{ pageRenderOrder.length }}</span>
</div> </div>
<div class="single-page-wrapper"> <div class="single-page-wrapper">
<div *ngIf="pageRenderOrder.length > 0" <div *ngIf="pageRenderOrder.length > 0" class="current-page-card">
class="current-page-card">
<!-- Page Content --> <!-- Page Content -->
<div class="page-content-area"> <div class="page-content-area">
<!-- Sections for current page --> <!-- Sections for current page -->
<div class="connected-sections" <div class="connected-sections" cdkDropList [cdkDropListData]="getPageSections(getCurrentPageName())"
cdkDropList
[cdkDropListData]="getPageSections(getCurrentPageName())"
[cdkDropListConnectedTo]="allConnectedLists" [cdkDropListConnectedTo]="allConnectedLists"
(cdkDropListDropped)="onSectionDrop($event, getCurrentPageName())"> (cdkDropListDropped)="onSectionDrop($event, getCurrentPageName())">
<div *ngFor="let sectionKey of getPageSections(getCurrentPageName())" <div *ngFor="let sectionKey of getPageSections(getCurrentPageName())" cdkDrag [cdkDragData]="sectionKey"
cdkDrag class="section-container" [class.editing]="isCurrentSectionEditing(sectionKey)">
[cdkDragData]="sectionKey"
class="section-container"
[class.editing]="isCurrentSectionEditing(sectionKey)">
<!-- Drag Handle --> <!-- Drag Handle -->
<div class="drag-handle" cdkDragHandle> <div class="drag-handle" cdkDragHandle>
@ -480,8 +459,7 @@
</div> </div>
<!-- Section Content --> <!-- Section Content -->
<div class="section-content" <div class="section-content" [innerHTML]="getSectionHtml(getCurrentPageName(), sectionKey)"
[innerHTML]="getSectionHtml(getCurrentPageName(), sectionKey)"
[attr.contenteditable]="isCurrentSectionEditing(sectionKey)" [attr.contenteditable]="isCurrentSectionEditing(sectionKey)"
(blur)="handleDirectContentEdit($event, getCurrentPageName(), sectionKey)"> (blur)="handleDirectContentEdit($event, getCurrentPageName(), sectionKey)">
</div> </div>
@ -517,13 +495,16 @@
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<div class="page-actions"> <div class="page-actions">
<!-- Show Code Button -->
<button class="action-btn-modern copy-btn" (click)="showCode()">
<i class="fas fa-code"></i>
Show Code
</button>
<button class="action-btn-modern copy-btn" (click)="copyPageToClipboard()"> <button class="action-btn-modern copy-btn" (click)="copyPageToClipboard()">
<i class="fas fa-copy"></i> <i class="fas fa-copy"></i>
Copy Page Copy Page
@ -533,15 +514,30 @@
<i class="fas fa-download"></i> <i class="fas fa-download"></i>
Download Page Download Page
</button> </button>
</div> </div>
<!-- Show Code Modal -->
<!-- Code Edit Modal -->
<div *ngIf="showCodeModal" class="code-modal-overlay">
<div class="code-modal">
<div class="code-modal-header">
<h3>Edit Code {{ currentEditingPage }}</h3>
<button class="close-btn" (click)="cancelEdit()">×</button>
</div>
<textarea [(ngModel)]="editableHtml" class="code-textarea"></textarea>
<div class="code-modal-footer">
<button class="action-btn-modern" (click)="saveEditedCode()">Save</button>
<button class="action-btn-modern" (click)="cancelEdit()">Cancel</button>
</div>
</div>
</div>
<!-- Page Navigation Controls --> <!-- Page Navigation Controls -->
<div *ngIf="!isLoading && pageRenderOrder.length > 0" class="page-navigation"> <div *ngIf="!isLoading && pageRenderOrder.length > 0" class="page-navigation">
<button class="nav-btn" <button class="nav-btn" (click)="previousPage()" [disabled]="currentPageIndex <= 0" title="Previous Page">
(click)="previousPage()"
[disabled]="currentPageIndex <= 0"
title="Previous Page">
<i class="fas fa-chevron-left"></i> <i class="fas fa-chevron-left"></i>
Previous Previous
</button> </button>
@ -553,9 +549,7 @@
<div class="page-title">{{ getCurrentPageName() }}</div> <div class="page-title">{{ getCurrentPageName() }}</div>
</div> </div>
<button class="nav-btn" <button class="nav-btn" (click)="nextPage()" [disabled]="currentPageIndex >= pageRenderOrder.length - 1"
(click)="nextPage()"
[disabled]="currentPageIndex >= pageRenderOrder.length - 1"
title="Next Page"> title="Next Page">
Next Next
<i class="fas fa-chevron-right"></i> <i class="fas fa-chevron-right"></i>
@ -564,9 +558,7 @@
</div> </div>
<!-- Mobile Sidebar Toggle (Hidden on Desktop) --> <!-- Mobile Sidebar Toggle (Hidden on Desktop) -->
<button class="mobile-sidebar-toggle" <button class="mobile-sidebar-toggle" (click)="toggleMobileSidebar()" [class.active]="sidebarOpen"
(click)="toggleMobileSidebar()"
[class.active]="sidebarOpen"
style="display: none; position: fixed; top: 20px; right: 20px; z-index: 1600; background: #212529; color: white; border: none; padding: 12px; border-radius: 50%; font-size: 16px;" style="display: none; position: fixed; top: 20px; right: 20px; z-index: 1600; background: #212529; color: white; border: none; padding: 12px; border-radius: 50%; font-size: 16px;"
*ngIf="isMobile"> *ngIf="isMobile">
<i class="fas" [ngClass]="sidebarOpen ? 'fa-times' : 'fa-bars'"></i> <i class="fas" [ngClass]="sidebarOpen ? 'fa-times' : 'fa-bars'"></i>
@ -574,8 +566,8 @@
<!-- Navbar Editor Modal --> <!-- Navbar Editor Modal -->
<!-- Updated Navbar Editor Modal --> <!-- Updated Navbar Editor Modal -->
<div class="modal-overlay" *ngIf="showNavbarEditorModal" [@fadeIn] (click)="closeNavbarEditorModal()"> <div class="modal-overlay" *ngIf="showNavbarEditorModal" [@fadeIn] (click)="closeNavbarEditorModal()">
<div class="modal-content navbar-editor-modal" (click)="$event.stopPropagation()" [@slideIn]> <div class="modal-content navbar-editor-modal" (click)="$event.stopPropagation()" [@slideIn]>
<div class="modal-header"> <div class="modal-header">
@ -593,8 +585,7 @@
<div class="form-group"> <div class="form-group">
<label for="navbarPageSelect">Select Page:</label> <label for="navbarPageSelect">Select Page:</label>
<select id="navbarPageSelect" class="form-control" [(ngModel)]="selectedNavbarPage" <select id="navbarPageSelect" class="form-control" [(ngModel)]="selectedNavbarPage"
(change)="onNavbarPageChange()" (change)="onNavbarPageChange()" [@focusBorder]>
[@focusBorder]>
<option value="">Choose a page...</option> <option value="">Choose a page...</option>
<option *ngFor="let page of pageRenderOrder" [value]="page"> <option *ngFor="let page of pageRenderOrder" [value]="page">
<i class="fas fa-file-alt"></i> {{ page }} <i class="fas fa-file-alt"></i> {{ page }}
@ -645,10 +636,10 @@
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<!-- Add Custom Section Modal --> <!-- Add Custom Section Modal -->
<div class="modal-overlay" *ngIf="showAddCustomModal" [@fadeIn] (click)="closeAddCustomModal()"> <div class="modal-overlay" *ngIf="showAddCustomModal" [@fadeIn] (click)="closeAddCustomModal()">
<div class="modal-content" (click)="$event.stopPropagation()" [@slideIn]> <div class="modal-content" (click)="$event.stopPropagation()" [@slideIn]>
<div class="modal-header"> <div class="modal-header">
@ -667,11 +658,8 @@
<i class="fas fa-tag" style="margin-right: 4px;"></i> <i class="fas fa-tag" style="margin-right: 4px;"></i>
Section Name: Section Name:
</label> </label>
<input id="customSectionName" <input id="customSectionName" type="text" [(ngModel)]="newCustomSectionName"
type="text" placeholder="Enter section name (e.g., Custom Header, Special CTA)" class="form-control">
[(ngModel)]="newCustomSectionName"
placeholder="Enter section name (e.g., Custom Header, Special CTA)"
class="form-control">
</div> </div>
<div class="form-group"> <div class="form-group">
@ -679,11 +667,8 @@
<i class="fas fa-align-left" style="margin-right: 4px;"></i> <i class="fas fa-align-left" style="margin-right: 4px;"></i>
Section Description: Section Description:
</label> </label>
<textarea id="customSectionDesc" <textarea id="customSectionDesc" [(ngModel)]="newCustomSectionDesc" rows="4"
[(ngModel)]="newCustomSectionDesc" placeholder="Describe the content and purpose of this custom section..." class="form-control"></textarea>
rows="4"
placeholder="Describe the content and purpose of this custom section..."
class="form-control"></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
@ -691,11 +676,8 @@
<i class="fas fa-icons" style="margin-right: 4px;"></i> <i class="fas fa-icons" style="margin-right: 4px;"></i>
Icon Class: Icon Class:
</label> </label>
<input id="customSectionIcon" <input id="customSectionIcon" type="text" [(ngModel)]="newCustomSectionIcon"
type="text" placeholder="e.g., fas fa-star, fas fa-rocket" class="form-control">
[(ngModel)]="newCustomSectionIcon"
placeholder="e.g., fas fa-star, fas fa-rocket"
class="form-control">
</div> </div>
</div> </div>
@ -704,15 +686,14 @@
<i class="fas fa-times" style="margin-right: 5px;"></i> <i class="fas fa-times" style="margin-right: 5px;"></i>
Cancel Cancel
</button> </button>
<button class="action-btn primary" <button class="action-btn primary" [disabled]="!newCustomSectionName || !newCustomSectionDesc"
[disabled]="!newCustomSectionName || !newCustomSectionDesc"
(click)="confirmAddCustomSection()"> (click)="confirmAddCustomSection()">
<i class="fas fa-plus" style="margin-right: 5px;"></i> <i class="fas fa-plus" style="margin-right: 5px;"></i>
Add Custom Section Add Custom Section
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<!-- Modal for Adding New Page --> <!-- Modal for Adding New Page -->
<div class="modal-overlay" *ngIf="showNewPageModal" [@fadeIn] (click)="closeNewPageModal()"> <div class="modal-overlay" *ngIf="showNewPageModal" [@fadeIn] (click)="closeNewPageModal()">
<div class="modal-content" (click)="$event.stopPropagation()" [@slideIn]> <div class="modal-content" (click)="$event.stopPropagation()" [@slideIn]>
@ -733,11 +714,8 @@
<i class="fas fa-file-alt" style="margin-right: 4px;"></i> <i class="fas fa-file-alt" style="margin-right: 4px;"></i>
Page Name: Page Name:
</label> </label>
<input id="pageName" <input id="pageName" type="text" [(ngModel)]="newPageName"
type="text" placeholder="Enter page name (e.g., Home, About, Contact)" class="form-control">
[(ngModel)]="newPageName"
placeholder="Enter page name (e.g., Home, About, Contact)"
class="form-control">
</div> </div>
<div class="form-group"> <div class="form-group">
@ -745,11 +723,8 @@
<i class="fas fa-align-left" style="margin-right: 4px;"></i> <i class="fas fa-align-left" style="margin-right: 4px;"></i>
Page Description: Page Description:
</label> </label>
<textarea id="pageDescription" <textarea id="pageDescription" [(ngModel)]="newPageDescription" rows="3"
[(ngModel)]="newPageDescription" placeholder="Describe the purpose and content of this page..." class="form-control"></textarea>
rows="3"
placeholder="Describe the purpose and content of this page..."
class="form-control"></textarea>
</div> </div>
</div> </div>
@ -758,9 +733,7 @@
<i class="fas fa-times" style="margin-right: 5px;"></i> <i class="fas fa-times" style="margin-right: 5px;"></i>
Cancel Cancel
</button> </button>
<button class="action-btn primary" <button class="action-btn primary" [disabled]="!newPageName.trim()" (click)="confirmAddPage()">
[disabled]="!newPageName.trim()"
(click)="confirmAddPage()">
<i class="fas fa-plus" style="margin-right: 5px;"></i> <i class="fas fa-plus" style="margin-right: 5px;"></i>
Add Page Add Page
</button> </button>
@ -768,4 +741,4 @@
</div> </div>
</div> </div>
</div> </div>

View File

@ -9,8 +9,12 @@ import * as sha256 from 'crypto-js/sha256';
import SHA256 from 'crypto-js/sha256'; import SHA256 from 'crypto-js/sha256';
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop'; import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
import { trigger, transition, style, animate, state } from '@angular/animations'; import { trigger, transition, style, animate, state } from '@angular/animations';
import * as e from 'express';
import { json } from 'stream/consumers';
interface GeneratedSectionContent {
json: string;
css: string;
}
@Component({ @Component({
selector: 'app-wireframe-renderer', selector: 'app-wireframe-renderer',
@ -50,6 +54,8 @@ import { json } from 'stream/consumers';
] ]
}) })
export class WireframeRendererComponent implements OnInit { export class WireframeRendererComponent implements OnInit {
globalSections = [ globalSections = [
@ -177,6 +183,8 @@ export class WireframeRendererComponent implements OnInit {
initialPrompt = ''; initialPrompt = '';
id: number; id: number;
allPagePrompts: Record<string, Record<string, string>> = {}; allPagePrompts: Record<string, Record<string, string>> = {};
allPageCss: Record<string, Record<string, string>> = {};
initialGeneratedPrompts: Record<string, Record<string, string>> = {}; initialGeneratedPrompts: Record<string, Record<string, string>> = {};
promptHashCache: Record<string, string> = {}; promptHashCache: Record<string, string> = {};
pageSections: Record<string, { FullPage: SafeHtml }> = {}; pageSections: Record<string, { FullPage: SafeHtml }> = {};
@ -186,12 +194,14 @@ export class WireframeRendererComponent implements OnInit {
sidebarCollapsed: boolean = false; sidebarCollapsed: boolean = false;
newlyGeneratedPages: string[] = []; newlyGeneratedPages: string[] = [];
// Add toggle method // Add toggle method
processedCssSections: string[] = [];
finalCssBundle: string = '';
deployedUrl: string | null = null; deployedUrl: string | null = null;
// Added properties for grid and drag functionality // Added properties for grid and drag functionality
hoveredPage: string | null = null; hoveredPage: string | null = null;
hoveredSection: string | null = null; hoveredSection: string | null = null;
@ -202,7 +212,7 @@ deployedUrl: string | null = null;
lastX: number = 0; lastX: number = 0;
lastY: number = 0; lastY: number = 0;
isDragging = false; isDragging = false;
startPanPosition = { x: 0, y: 0 }; startPanPosition = { x: 0, y: 0 };
// Edit mode properties // Edit mode properties
editMode: boolean = false; editMode: boolean = false;
editingSection: { page: string, section: string } | null = null; editingSection: { page: string, section: string } | null = null;
@ -320,6 +330,7 @@ private async checkAllExistingFilesEnhanced(siteName: string, expectedPages: str
// Only create new HTML structure if the original doesn't have proper HTML tags // Only create new HTML structure if the original doesn't have proper HTML tags
if (!rawHtml.includes('<!DOCTYPE') || !rawHtml.includes('<html')) { if (!rawHtml.includes('<!DOCTYPE') || !rawHtml.includes('<html')) {
completeHtml = this.createCompleteHtml(pageName, parsed.css, parsed.bodyHtml); completeHtml = this.createCompleteHtml(pageName, parsed.css, parsed.bodyHtml);
} }
@ -867,7 +878,9 @@ fetchTreeById(id: number) {
this.dividePagesToExistingOrNew(this.jsonInput, this.sitename); this.dividePagesToExistingOrNew(this.jsonInput, this.sitename);
this.updateLoadingProgress(20, 'Model data loaded successfully'); this.updateLoadingProgress(20, 'Model data loaded successfully');
await this.generateMissingPagesWithAI(this.missingPages, this.jsonInput); await this.generateMissingPagesWithAI(this.missingPages, this.jsonInput);
console.log("Printing Final Map of Html ", this.missingHtmlPages) console.log("Printing Final Map of Html ", this.mapofPageAndHtmlBody)
// Start the enhanced processing flow // Start the enhanced processing flow
// await this.processAllPagesWithExistingCheck(this.jsonInput); // await this.processAllPagesWithExistingCheck(this.jsonInput);
} catch (err) { } catch (err) {
@ -887,11 +900,11 @@ fetchTreeById(id: number) {
} }
}); });
} }
goToWireFrameEdit() {
goToWireFrameEdit(){ localStorage.setItem('mapOfHtml',JSON.stringify(this.mapofPageAndHtmlBody));
let mapOfHtml:any; this.router.navigate(['/cns-portal/WireFrameEdit']);
this.router.navigate(["../WireFrameEdit/",{ mapOfHtml: this.mapofPageAndHtmlBody }])
} }
/* Step 2: Process all pages with existing file checking /* Step 2: Process all pages with existing file checking
*/ */
async processAllPagesWithExistingCheck(treeJsonString: string) { async processAllPagesWithExistingCheck(treeJsonString: string) {
@ -1037,8 +1050,25 @@ private async generatePromptsForMissingPage(pageName: string, sections: any) {
this.sectionOrderMap[pageName].push(sectionName); this.sectionOrderMap[pageName].push(sectionName);
const prompt = await this.generatePromptFromSection(sectionName, sectionDescription as string); const prompt = await this.generatePromptFromSection(sectionName, sectionDescription as string);
sectionPrompts[sectionName] = prompt; sectionPrompts[sectionName] = prompt.json;
// ✅ Store section-wise CSS externally
if (!this.allPageCss[pageName]) {
this.allPageCss[pageName] = {};
} }
this.allPageCss[pageName][sectionName] = prompt.css;
// store for unique css
const templateKey = sectionName.toLowerCase().replace(/section$/, '').trim();
if (!this.processedCssSections.includes(templateKey)) {
this.processedCssSections.push(templateKey);
this.finalCssBundle += prompt.css + '\n';
}
}
this.allPagePrompts[pageName] = sectionPrompts; this.allPagePrompts[pageName] = sectionPrompts;
this.initialGeneratedPrompts[pageName] = { ...sectionPrompts }; this.initialGeneratedPrompts[pageName] = { ...sectionPrompts };
@ -1449,8 +1479,26 @@ private async processMissingPagesEnhanced(treeJson: any, missingPages: string[])
this.sectionOrderMap[pageName].push(sectionName); this.sectionOrderMap[pageName].push(sectionName);
const prompt = await this.generatePromptFromSection(sectionName, sectionDescription as string); const prompt = await this.generatePromptFromSection(sectionName, sectionDescription as string);
sectionPrompts[sectionName] = prompt; sectionPrompts[sectionName] = prompt.json;
// ✅ Store section-wise CSS externally
if (!this.allPageCss[pageName]) {
this.allPageCss[pageName] = {};
} }
this.allPageCss[pageName][sectionName] = prompt.css;
// store for unique css
const templateKey = sectionName.toLowerCase().replace(/section$/, '').trim();
if (!this.processedCssSections.includes(templateKey)) {
this.processedCssSections.push(templateKey);
this.finalCssBundle += prompt.css + '\n';
}
}
this.allPagePrompts[pageName] = sectionPrompts; this.allPagePrompts[pageName] = sectionPrompts;
this.initialGeneratedPrompts[pageName] = { ...sectionPrompts }; this.initialGeneratedPrompts[pageName] = { ...sectionPrompts };
@ -1501,7 +1549,21 @@ private async processAllPagesEnhanced(treeJson: any) {
this.sectionOrderMap[pageName].push(sectionName); this.sectionOrderMap[pageName].push(sectionName);
const prompt = await this.generatePromptFromSection(sectionName, sectionDescription); const prompt = await this.generatePromptFromSection(sectionName, sectionDescription);
sectionPrompts[sectionName] = prompt; sectionPrompts[sectionName] = prompt.json;
// ✅ Store section-wise CSS externally
if (!this.allPageCss[pageName]) {
this.allPageCss[pageName] = {};
}
this.allPageCss[pageName][sectionName] = prompt.css;
// store for unique css
const templateKey = sectionName.toLowerCase().replace(/section$/, '').trim();
if (!this.processedCssSections.includes(templateKey)) {
this.processedCssSections.push(templateKey);
this.finalCssBundle += prompt.css + '\n';
}
} }
this.allPagePrompts[pageName] = sectionPrompts; this.allPagePrompts[pageName] = sectionPrompts;
@ -1579,7 +1641,10 @@ async processPageSectionsEnhanced(pageName: string, sectionMap: Record<string, s
await Promise.all(htmlTasks); await Promise.all(htmlTasks);
// Create complete HTML structure for the page // Create complete HTML structure for the page
const completeHtml = this.createCompleteHtml(pageName, COMMON_CSS, sectionHtmls.join('\n'));
const css = this.getCombinedSectionCss(pageName);
const completeHtml = this.createCompleteHtml(pageName, css, sectionHtmls.join('\n'));
const safeHtml = completeHtml; const safeHtml = completeHtml;
this.pageSections[pageName] = { FullPage: safeHtml }; this.pageSections[pageName] = { FullPage: safeHtml };
@ -1622,13 +1687,14 @@ HTML Only. No CSS.
Focus on layout that matches a modern UI semantic, responsive, and readable. Focus on layout that matches a modern UI semantic, responsive, and readable.
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>)`;
// Generate prompt from section // Generate prompt from section
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<GeneratedSectionContent> {
return new Promise((resolve) => { return new Promise((resolve) => {
const fieldType = sectionName.toLowerCase().replace(/section$/i, '').trim(); const fieldType = sectionName.toLowerCase().replace(/section$/i, '').trim();
@ -1639,8 +1705,11 @@ HTML Only. No CSS.
try { try {
// const jsonBlock = res?.javacode; // const jsonBlock = res?.javacode;
const jsonBlock = res?.htmljson; const jsonBlock = res?.htmljson;
const sectionCss = res?.css || '';
// if (!jsonBlock) return resolve('{}');
if (!jsonBlock) return resolve({ json: '{}', css: '' });
if (!jsonBlock) return resolve('{}');
console.log(' base json is ...',jsonBlock); console.log(' base json is ...',jsonBlock);
const baseJson = typeof jsonBlock === 'string' ? JSON.parse(jsonBlock) : jsonBlock; const baseJson = typeof jsonBlock === 'string' ? JSON.parse(jsonBlock) : jsonBlock;
@ -1673,7 +1742,9 @@ HTML Only. No CSS.
const hash = sha256(enhancedPrompt).toString(); const hash = sha256(enhancedPrompt).toString();
if (this.promptHashCache[hash]) { if (this.promptHashCache[hash]) {
return resolve(this.promptHashCache[hash]); // return resolve(this.promptHashCache[hash]);
return resolve({ json: this.promptHashCache[hash], css: sectionCss });
} }
const enhanced = await this.callAi(enhancedPrompt); const enhanced = await this.callAi(enhancedPrompt);
@ -1682,16 +1753,27 @@ HTML Only. No CSS.
this.promptHashCache[hash] = enhanced; this.promptHashCache[hash] = enhanced;
// resolve(baseJsonString); // resolve(baseJsonString);
resolve(this.promptHashCache[hash]); // resolve(this.promptHashCache[hash]);
resolve({ json: this.promptHashCache[hash], css: sectionCss });
} catch (err) { } catch (err) {
console.error('❌ JSON parse error:', err); console.error('❌ JSON parse error:', err);
resolve('{}'); // resolve('{}');
resolve({ json: '{}', css: '' });
} }
}, },
error: () => resolve('{}') error: () => resolve({ json: '{}', css: '' })
// error: () => resolve('{}')
}); });
}); });
} }
private getCombinedSectionCss(pageName: string): string {
const sectionCssMap = this.allPageCss[pageName] || {};
return Object.values(sectionCssMap).join('\n');
}
// Process all pages live update // Process all pages live update
async processAllPagesLiveUpdate() { async processAllPagesLiveUpdate() {
const htmlGenerationTasks: Promise<void>[] = []; const htmlGenerationTasks: Promise<void>[] = [];
@ -1828,8 +1910,6 @@ private createCompleteHtml(pageName: string, css: string, bodyHtml: string): str
<style> <style>
${css} ${css}
/* Additional common styles */
${COMMON_CSS}
html, body { html, body {
margin: 0 !important; margin: 0 !important;
@ -1905,7 +1985,8 @@ createHtmlFiles() {
// Ensure we have valid HTML // Ensure we have valid HTML
if (!html.includes('<!DOCTYPE') && !html.includes('<html')) { if (!html.includes('<!DOCTYPE') && !html.includes('<html')) {
// If it's just body content, wrap it properly // If it's just body content, wrap it properly
html = this.createCompleteHtml(pageName, COMMON_CSS, html); const css = this.getCombinedSectionCss(pageName);
html = this.createCompleteHtml(pageName, css, html);
} }
const sanitizedPageName = this.sanitizeFilename(pageName); const sanitizedPageName = this.sanitizeFilename(pageName);
@ -1933,9 +2014,9 @@ async generateJson(data: { jsonStructure: any, sectionType: string }): Promise<s
return new Promise((resolve) => { return new Promise((resolve) => {
try { try {
const parsedJson = const parsedJson =
typeof data.jsonStructure === 'string' typeof data.jsonStructure.json === 'string'
? JSON.parse(data.jsonStructure) ? JSON.parse(data.jsonStructure.json)
: data.jsonStructure; : data.jsonStructure.json;
// Check for empty or invalid parsed JSON // Check for empty or invalid parsed JSON
const isEmpty = !parsedJson || Object.keys(parsedJson).length === 0; const isEmpty = !parsedJson || Object.keys(parsedJson).length === 0;
@ -2060,6 +2141,64 @@ downloadHtml(pageName: string) {
} }
buildSiteBuilder() {
const pageHtmlMap: Record<string, string> = {};
for (const [pageName, section] of Object.entries(this.pageSections)) {
const html = section.FullPage?.toString() || '';
pageHtmlMap[pageName] = html;
}
const payload = {
css: this.finalCssBundle,
pageHtmlMap: pageHtmlMap
};
this.siteTreeService.deploySiteBuilder(this.siteId,this.sitename,payload).subscribe(
(data) => {
console.log(data);
if (data || data.status >= 200 && data.status <= 299) {
this.siteTreeService.getById(this.siteId).subscribe({
next: async (res) => {
console.log('📥 Fetched from getById again :', res);
if (res ) {
this.deployedUrl = res.deployedUrl;
console.log('deployed url is ', this.deployedUrl)
} else {
console.warn('⚠️ Deployed Url Not found');
}
},
error: (err) => {
console.error('❌ Error in getById:', err);
}
});
this.toastr.success("Site builder Deploying Start..");
}
// setTimeout(() => {
// this.ngOnInit();
// }, 500);
}, (error) => {
console.log(error);
if (error.status >= 200 && error.status <= 299) {
this.toastr.success("deployed Files Created Successfully");
}
if (error.status >= 400 && error.status <= 499) {
this.toastr.error(" deployed Files Not Created");
}
if (error.status >= 500 && error.status <= 599) {
this.toastr.error("deployed Server Error");
}
});
}
// Update your helper methods // Update your helper methods
@ -2568,6 +2707,42 @@ copyPageToClipboard(pageName?: string): void {
} }
} }
// this is for show code
showCodeModal = false;
editableHtml = '';
currentEditingPage = '';
showCode(pageName?: string): void {
const pageToSelect = pageName || this.getCurrentPageName();
const html = this.mapofPageAndHtmlBody[pageToSelect];
if (html) {
this.currentEditingPage = pageToSelect;
this.editableHtml = html;
this.showCodeModal = true;
} else {
this.toastr.error('No code found for this page');
}
}
saveEditedCode(): void {
if (this.currentEditingPage && this.editableHtml) {
this.mapofPageAndHtmlBody[this.currentEditingPage] = this.editableHtml;
this.toastr.success(`${this.currentEditingPage} HTML updated`);
this.showCodeModal = false;
} else {
this.toastr.error('Failed to save. Missing page or HTML.');
}
}
cancelEdit(): void {
this.showCodeModal = false;
this.editableHtml = '';
this.currentEditingPage = '';
}
// show code end
@ -2899,9 +3074,9 @@ downloadCurrentPage(): void {
// Add this to initialize the current page // Add this to initialize the current page
getPageTransform(): string { getPageTransform(): string {
return `scale(${this.scale})`; return `scale(${this.scale})`;
} }
refreshAllSectionCSS(): void { refreshAllSectionCSS(): void {
// Refresh CSS in all section previews // Refresh CSS in all section previews
@ -3363,6 +3538,8 @@ async mapOfExistingPagesWithHtmlCss(existingPages: string[]): Promise<void> {
try { try {
await Promise.all(pagePromises); await Promise.all(pagePromises);
console.log('All existing pages loaded:', this.mapofPageAndHtmlBody); console.log('All existing pages loaded:', this.mapofPageAndHtmlBody);
console.log("Start The Deployment! ")
await this.deployAllPages()
} catch (error) { } catch (error) {
console.error('Error loading some pages:', error); console.error('Error loading some pages:', error);
} }
@ -3393,7 +3570,9 @@ calculateSectionHtmlsForExistingPage(pageName: string, htmlContent: string): voi
this.sectionHtmls[pageName]['FullPage'] = this.sanitizer.bypassSecurityTrustHtml(htmlContent); this.sectionHtmls[pageName]['FullPage'] = this.sanitizer.bypassSecurityTrustHtml(htmlContent);
} }
} }
async generateMissingPagesWithAI(missingPages: string[], jsonInput: string): Promise<void> {
async generateMissingPagesWithAI(missingPages: string[], jsonInput: string): Promise<void> {
if (!missingPages.length) { if (!missingPages.length) {
this.toastr.info('No missing pages to generate'); this.toastr.info('No missing pages to generate');
return; return;
@ -3447,7 +3626,22 @@ calculateSectionHtmlsForExistingPage(pageName: string, htmlContent: string): voi
for (const [sectionName, sectionDescription] of sectionEntries) { for (const [sectionName, sectionDescription] of sectionEntries) {
// Generate prompt for section, passing the full jsonInput as context // Generate prompt for section, passing the full jsonInput as context
const prompt = await this.generatePromptFromSection(sectionName, sectionDescription as string); const prompt = await this.generatePromptFromSection(sectionName, sectionDescription as string);
this.allPagePrompts[pageName][sectionName] = prompt; this.allPagePrompts[pageName][sectionName] = prompt.json;
// ✅ Store section-wise CSS externally
if (!this.allPageCss[pageName]) {
this.allPageCss[pageName] = {};
}
this.allPageCss[pageName][sectionName] = prompt.css;
// store for unique css
const templateKey = sectionName.toLowerCase().replace(/section$/, '').trim();
if (!this.processedCssSections.includes(templateKey)) {
this.processedCssSections.push(templateKey);
this.finalCssBundle += prompt.css + '\n';
}
// Generate HTML for section // Generate HTML for section
const html = await this.generateJson({ sectionType: sectionName, jsonStructure: prompt }); const html = await this.generateJson({ sectionType: sectionName, jsonStructure: prompt });
@ -3458,7 +3652,9 @@ calculateSectionHtmlsForExistingPage(pageName: string, htmlContent: string): voi
sanitizedPageName = this.sanitizeFilename(pageName); sanitizedPageName = this.sanitizeFilename(pageName);
// Combine all section HTMLs and CSS for the page // Combine all section HTMLs and CSS for the page
const finalHtml = this.createCompleteHtml(sanitizedPageName, COMMON_CSS, sectionHtmls.join('\n')); const css = this.getCombinedSectionCss(pageName);
const finalHtml = this.createCompleteHtml(sanitizedPageName, css, sectionHtmls.join('\n'));
this.pageSections[pageName] = { FullPage: finalHtml }; this.pageSections[pageName] = { FullPage: finalHtml };
this.mapofPageAndHtmlBody[pageName] = finalHtml; this.mapofPageAndHtmlBody[pageName] = finalHtml;
@ -3472,17 +3668,22 @@ calculateSectionHtmlsForExistingPage(pageName: string, htmlContent: string): voi
for (const [pageName, html] of pagesToSave.entries()) { for (const [pageName, html] of pagesToSave.entries()) {
const pageObj: Record<string, string> = { [pageName]: html }; const pageObj: Record<string, string> = { [pageName]: html };
const payload = {
css: this.finalCssBundle,
pageHtmlMap: pageObj
};
// Ensure the page name is sanitized // Ensure the page name is sanitized
await new Promise<void>((resolve) => { await new Promise<void>((resolve) => {
this.siteTreeService.createHtmlfile(this.siteId, this.sitename, pageObj).subscribe({ this.siteTreeService.createHtmlfile(this.siteId, this.sitename, payload).subscribe({
next: (response) => { next: (response) => {
console.log(`Page "${pageName}" created successfully.`); console.log(`Page "${pageName}" created successfully.`);
this.toastr.success(`Generated and saved page: ${pageName}`); // this.toastr.success(`Generated and saved page: ${pageName}`);
resolve(); resolve();
}, },
error: (error) => { error: (error) => {
console.error(`Error creating page "${pageName}":`, error); console.error(`Error creating page "${pageName}":`, error);
this.toastr.error(`Failed to save generated page: ${pageName}`); // this.toastr.error(`Failed to save generated page: ${pageName}`);
resolve(); resolve();
} }
}); });
@ -3506,7 +3707,9 @@ calculateSectionHtmlsForExistingPage(pageName: string, htmlContent: string): voi
// } // }
console.log('Map of All Pages with HTML:', this.mapofPageAndHtmlBody); console.log('Map of All Pages with HTML:', this.mapofPageAndHtmlBody);
this.toastr.success('Generated all missing pages with AI.'); console.log('Generated all missing pages with AI...');
// this.toastr.success('Generated all missing pages with AI.');
this.cdr.detectChanges(); this.cdr.detectChanges();
} }
@ -3519,6 +3722,26 @@ calculateSectionHtmlsForExistingPage(pageName: string, htmlContent: string): voi
// Add this property to your component // Add this property to your component
isGridView: boolean = false; // Set to true for grid, false for single page isGridView: boolean = false; // Set to true for grid, false for single page
async deployAllPages() {
// this.toastr.info("Deploying all pages...");
try {
console.log("SITE ID ",this.siteId)
console.log("SITE NAME FORMATTED ",this.formatSiteName(this.sitename));
this.siteTreeService.deploySiteBuilder(+this.siteId,
this.formatSiteName(this.sitename).trim(),
this.mapofPageAndHtmlBody
)
// this.toastr.success("All pages deployed successfully!");
} catch (error) {
console.error(`Error deploy}:`, error);
this.toastr.error(`Failed to deploy page: `);
}
}
} }

View File

@ -146,7 +146,7 @@
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
background: rgba(0,0,0,0.75); background: rgba(0, 0, 0, 0.75);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -155,17 +155,27 @@
animation: fadeIn 0.3s ease-out; animation: fadeIn 0.3s ease-out;
} }
/* Main Popup Content */
/* Main Popup Content */ /* Main Popup Content */
.popup-content { .popup-content {
width: 600px; width: 900px;
max-height: none; /* ⬅️ Increased from 600px to 900px */
max-width: 95vw;
/* ⬅️ Prevent overflow on smaller screens */
max-height: 90vh;
/* ⬅️ Avoid overflowing vertically */
padding: 24px; padding: 24px;
box-shadow: 0 8px 24px rgba(0,0,0,0.25); /* ⬅️ More spacing */
border-radius: 8px; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);
border-radius: 12px;
/* ⬅️ Slightly larger corners */
background-color: snow; background-color: snow;
animation: slideIn 0.4s ease-out; animation: slideIn 0.4s ease-out;
overflow-y: auto;
/* ⬅️ Scroll if content overflows vertically */
} }
.close-btn { .close-btn {
background: transparent; background: transparent;
border: none; border: none;
@ -193,7 +203,7 @@
font-family: inherit; font-family: inherit;
resize: vertical; resize: vertical;
transition: border 0.3s ease; transition: border 0.3s ease;
box-shadow: 0 2px 4px rgba(0,0,0,0.05); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
padding: 12px; padding: 12px;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 6px; border-radius: 6px;
@ -240,13 +250,13 @@
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
box-shadow: 0 2px 4px rgba(0,0,0,0.2); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
} }
.generate-btn:hover { .generate-btn:hover {
background: #1565c0; background: #1565c0;
transform: translateY(-1px); transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(0,0,0,0.3); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
} }
/* Loading Container */ /* Loading Container */
@ -255,7 +265,7 @@
padding: 40px; padding: 40px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-radius: 16px; border-radius: 16px;
box-shadow: 0 20px 40px rgba(0,0,0,0.3); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
text-align: center; text-align: center;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
@ -269,13 +279,11 @@
right: 0; right: 0;
bottom: 0; bottom: 0;
opacity: 0.1; opacity: 0.1;
background-image: repeating-linear-gradient( background-image: repeating-linear-gradient(45deg,
45deg,
transparent, transparent,
transparent 10px, transparent 10px,
rgba(255,255,255,0.1) 10px, rgba(255, 255, 255, 0.1) 10px,
rgba(255,255,255,0.1) 20px rgba(255, 255, 255, 0.1) 20px);
);
} }
.loader-content { .loader-content {
@ -287,12 +295,12 @@
width: 80px; width: 80px;
height: 80px; height: 80px;
margin: 0 auto 24px; margin: 0 auto 24px;
background: rgba(255,255,255,0.15); background: rgba(255, 255, 255, 0.15);
border-radius: 50%; border-radius: 50%;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 8px 32px rgba(0,0,0,0.2); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
animation: spinPulse 2s ease-in-out infinite; animation: spinPulse 2s ease-in-out infinite;
} }
@ -306,7 +314,7 @@
font-size: 28px; font-size: 28px;
font-weight: 600; font-weight: 600;
margin-bottom: 16px; margin-bottom: 16px;
text-shadow: 0 2px 4px rgba(0,0,0,0.3); text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
} }
.dots { .dots {
@ -314,7 +322,7 @@
} }
.thinking-subtitle { .thinking-subtitle {
color: rgba(255,255,255,0.9); color: rgba(255, 255, 255, 0.9);
font-size: 16px; font-size: 16px;
margin-bottom: 32px; margin-bottom: 32px;
} }
@ -330,15 +338,29 @@
width: 12px; width: 12px;
height: 12px; height: 12px;
border-radius: 50%; border-radius: 50%;
background: rgba(255,255,255,0.4); background: rgba(255, 255, 255, 0.4);
animation: dotPulse 1.4s infinite ease-in-out; animation: dotPulse 1.4s infinite ease-in-out;
} }
.dot-1 { animation-delay: 0s; } .dot-1 {
.dot-2 { animation-delay: 0.2s; } animation-delay: 0s;
.dot-3 { animation-delay: 0.4s; } }
.dot-4 { animation-delay: 0.6s; }
.dot-5 { animation-delay: 0.8s; } .dot-2 {
animation-delay: 0.2s;
}
.dot-3 {
animation-delay: 0.4s;
}
.dot-4 {
animation-delay: 0.6s;
}
.dot-5 {
animation-delay: 0.8s;
}
.particles { .particles {
position: absolute; position: absolute;
@ -352,7 +374,7 @@
.particle { .particle {
position: absolute; position: absolute;
border-radius: 50%; border-radius: 50%;
background: rgba(255,255,255,0.6); background: rgba(255, 255, 255, 0.6);
animation: float 3s infinite ease-in-out; animation: float 3s infinite ease-in-out;
} }
@ -367,7 +389,7 @@
.particle-2 { .particle-2 {
width: 6px; width: 6px;
height: 6px; height: 6px;
background: rgba(255,255,255,0.4); background: rgba(255, 255, 255, 0.4);
top: 60%; top: 60%;
right: 20%; right: 20%;
animation-duration: 4s; animation-duration: 4s;
@ -377,7 +399,7 @@
.particle-3 { .particle-3 {
width: 3px; width: 3px;
height: 3px; height: 3px;
background: rgba(255,255,255,0.7); background: rgba(255, 255, 255, 0.7);
bottom: 30%; bottom: 30%;
left: 25%; left: 25%;
animation-duration: 2.5s; animation-duration: 2.5s;
@ -386,7 +408,7 @@
.particle-4 { .particle-4 {
width: 5px; width: 5px;
height: 5px; height: 5px;
background: rgba(255,255,255,0.5); background: rgba(255, 255, 255, 0.5);
top: 40%; top: 40%;
right: 15%; right: 15%;
animation-duration: 3.5s; animation-duration: 3.5s;
@ -399,7 +421,7 @@
padding: 32px; padding: 32px;
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%); background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
border-radius: 16px; border-radius: 16px;
box-shadow: 0 20px 40px rgba(0,0,0,0.3); box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
text-align: center; text-align: center;
position: relative; position: relative;
animation: slideIn 0.4s ease-out; animation: slideIn 0.4s ease-out;
@ -409,7 +431,7 @@
width: 80px; width: 80px;
height: 80px; height: 80px;
margin: 0 auto 24px; margin: 0 auto 24px;
background: rgba(255,255,255,0.15); background: rgba(255, 255, 255, 0.15);
border-radius: 50%; border-radius: 50%;
display: flex; display: flex;
align-items: center; align-items: center;
@ -422,11 +444,11 @@
font-size: 24px; font-size: 24px;
font-weight: 600; font-weight: 600;
margin-bottom: 12px; margin-bottom: 12px;
text-shadow: 0 2px 4px rgba(0,0,0,0.3); text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
} }
.error-message { .error-message {
color: rgba(255,255,255,0.9); color: rgba(255, 255, 255, 0.9);
font-size: 16px; font-size: 16px;
margin-bottom: 32px; margin-bottom: 32px;
line-height: 1.5; line-height: 1.5;
@ -434,9 +456,9 @@
.retry-btn { .retry-btn {
padding: 12px 20px; padding: 12px 20px;
background: rgba(255,255,255,0.2); background: rgba(255, 255, 255, 0.2);
color: white; color: white;
border: 1px solid rgba(255,255,255,0.3); border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 8px; border-radius: 8px;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease; transition: all 0.2s ease;
@ -444,7 +466,7 @@
} }
.retry-btn:hover { .retry-btn:hover {
background: rgba(255,255,255,0.3); background: rgba(255, 255, 255, 0.3);
transform: translateY(-1px); transform: translateY(-1px);
} }
@ -469,6 +491,7 @@
from { from {
opacity: 0; opacity: 0;
} }
to { to {
opacity: 1; opacity: 1;
} }
@ -479,6 +502,7 @@
opacity: 0; opacity: 0;
transform: translateY(30px) scale(0.95); transform: translateY(30px) scale(0.95);
} }
to { to {
opacity: 1; opacity: 1;
transform: translateY(0) scale(1); transform: translateY(0) scale(1);
@ -486,44 +510,76 @@
} }
@keyframes spinPulse { @keyframes spinPulse {
0%, 100% {
0%,
100% {
transform: rotate(0deg) scale(1); transform: rotate(0deg) scale(1);
box-shadow: 0 8px 32px rgba(0,0,0,0.2); box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
} }
50% { 50% {
transform: rotate(180deg) scale(1.1); transform: rotate(180deg) scale(1.1);
box-shadow: 0 12px 48px rgba(0,0,0,0.3); box-shadow: 0 12px 48px rgba(0, 0, 0, 0.3);
} }
} }
@keyframes brainThink { @keyframes brainThink {
0%, 100% { transform: scale(1) rotate(0deg); }
25% { transform: scale(1.1) rotate(-5deg); } 0%,
75% { transform: scale(0.95) rotate(5deg); } 100% {
transform: scale(1) rotate(0deg);
}
25% {
transform: scale(1.1) rotate(-5deg);
}
75% {
transform: scale(0.95) rotate(5deg);
}
} }
@keyframes typewriter { @keyframes typewriter {
0%, 20% { opacity: 1; }
50% { opacity: 0; } 0%,
80%, 100% { opacity: 1; } 20% {
opacity: 1;
}
50% {
opacity: 0;
}
80%,
100% {
opacity: 1;
}
} }
@keyframes dotPulse { @keyframes dotPulse {
0%, 20%, 80%, 100% {
0%,
20%,
80%,
100% {
transform: scale(1); transform: scale(1);
background: rgba(255,255,255,0.4); background: rgba(255, 255, 255, 0.4);
} }
40% { 40% {
transform: scale(1.5); transform: scale(1.5);
background: rgba(255,255,255,0.9); background: rgba(255, 255, 255, 0.9);
} }
} }
@keyframes float { @keyframes float {
0%, 100% {
0%,
100% {
transform: translateY(0px) rotate(0deg); transform: translateY(0px) rotate(0deg);
opacity: 0.6; opacity: 0.6;
} }
50% { 50% {
transform: translateY(-20px) rotate(180deg); transform: translateY(-20px) rotate(180deg);
opacity: 1; opacity: 1;
@ -531,14 +587,27 @@
} }
@keyframes errorShake { @keyframes errorShake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-10px); } 0%,
75% { transform: translateX(10px); } 100% {
transform: translateX(0);
}
25% {
transform: translateX(-10px);
}
75% {
transform: translateX(10px);
}
} }
/* Responsive Design */ /* Responsive Design */
@media (max-width: 768px) { @media (max-width: 768px) {
.popup-content, .loading-container, .error-container {
.popup-content,
.loading-container,
.error-container {
width: 90%; width: 90%;
margin: 0 20px; margin: 0 20px;
} }

View File

@ -145,11 +145,11 @@ export class TreeVisualizerComponent {
} }
// Add these properties to your component class // Add these properties to your component class
isLoading = false; isLoading = false;
showError = false; showError = false;
// Method to handle the enhanced generate flow // Method to handle the enhanced generate flow
generateJsonWithLoading() { generateJsonWithLoading() {
this.isLoading = true; this.isLoading = true;
this.showError = false; this.showError = false;
@ -157,6 +157,7 @@ showError = false;
console.log('🔄 Starting generateJsonWithLoading...'); console.log('🔄 Starting generateJsonWithLoading...');
// Call the actual generateJson method // Call the actual generateJson method
const [minPages, maxPages] = this.selectedPageRange.split("-").map(Number);
const prompt = ` const prompt = `
You are a JSON structure generator for website UI and sitemap hierarchy. You are a JSON structure generator for website UI and sitemap hierarchy.
@ -165,19 +166,20 @@ showError = false;
Each page must contain: Each page must contain:
- 4 to 5 meaningful UI sections (e.g., "Header Section", "Form Section", "Feature Section", etc.) - Each page MUST contain at least 6 meaningful UI sections (including "Navbar" and "Footer"). These sections should be clearly named and described (e.g., "Header Section", "Hero Section", "Testimonial Section", etc.). You are NOT allowed to include fewer than 6 sections on any page.
- A "Navbar" and a "Footer" section (always included on every page) - A "Navbar" and a "Footer" section (always included on every page)
- A short, clear description for each section (to support frontend development) - A short, clear description for each section (to support frontend development)
Constraints:
- Total number of pages (including nested children) must be between ${this.selectedPageRange}
- Do NOT create unnecessary or generic pages (e.g., no "Blog", "FAQ", etc.) unless explicitly present in the user flow
- Pages that appear after user actions (e.g., clicking a card or after login) must be nested under the relevant parent using a "Children" key
- DO NOT include any standalone section like "FAQ" or "Blog" as top-level pages unless mentioned
📘 Website Context: 📘 Website Context:
${this.rawInputText} ${this.rawInputText}
🔒 Strict Constraints:
- You MUST generate at least ${minPages} and not more than ${maxPages} unique pages in total (including nested children), be strict on this
- Each page MUST contain at least 6 meaningful UI sections (including "Navbar" and "Footer")
- Do NOT create unnecessary or generic pages (e.g., no "Blog", "FAQ", etc.) unless explicitly present in the user flow
- Pages that appear after user actions (e.g., clicking a card or after login) must be nested under the relevant parent using a "Children" key
- DO NOT include any standalone section like "FAQ" or "Blog" as top-level pages unless mentioned
--- Reference Format (DO NOT COPY; for structure only) --- --- Reference Format (DO NOT COPY; for structure only) ---
@ -202,7 +204,6 @@ showError = false;
} }
} }
--- ---
🚫 DO NOT: 🚫 DO NOT:
- Include any explanation, notes, comments, or formatting (like \`\`\` or \`json\`) - Include any explanation, notes, comments, or formatting (like \`\`\` or \`json\`)
- Do NOT return escaped or markdown-formatted JSON - Do NOT return escaped or markdown-formatted JSON
@ -290,15 +291,15 @@ showError = false;
}); });
} }
// Helper method to check if all calls are complete // Helper method to check if all calls are complete
private checkAndCompleteGeneration(parsedJson: any, pendingCalls: number) { private checkAndCompleteGeneration(parsedJson: any, pendingCalls: number) {
if (pendingCalls === 0) { if (pendingCalls === 0) {
this.completeGeneration(parsedJson); this.completeGeneration(parsedJson);
} }
} }
// Helper method to complete the generation process // Helper method to complete the generation process
private completeGeneration(parsedJson: any) { private completeGeneration(parsedJson: any) {
this.inputJson = JSON.stringify(parsedJson); this.inputJson = JSON.stringify(parsedJson);
const updatePayload = { const updatePayload = {
@ -327,29 +328,29 @@ private completeGeneration(parsedJson: any) {
this.handleGenerationError('Failed to save site structure'); this.handleGenerationError('Failed to save site structure');
} }
}); });
} }
// Helper method to handle errors // Helper method to handle errors
private handleGenerationError(message: string) { private handleGenerationError(message: string) {
console.error('❌ Generation failed:', message); console.error('❌ Generation failed:', message);
this.isLoading = false; this.isLoading = false;
this.showError = true; this.showError = true;
// Don't close popup so user can retry // Don't close popup so user can retry
} }
// Enhanced close method // Enhanced close method
closePopup() { closePopup() {
this.showPopup = false; this.showPopup = false;
this.isLoading = false; this.isLoading = false;
this.showError = false; this.showError = false;
} }
// Retry method for error state // Retry method for error state
retryGeneration() { retryGeneration() {
this.showError = false; this.showError = false;
this.generateJsonWithLoading(); this.generateJsonWithLoading();
} }
convertJson() { convertJson() {
try { try {
const parsed = JSON.parse(this.inputJson); const parsed = JSON.parse(this.inputJson);
@ -645,6 +646,7 @@ retryGeneration() {
alert('Model data is not valid JSON format'); alert('Model data is not valid JSON format');
} }
} else { } else {
this.openPopup();
console.warn('⚠️ Model key not found or empty, keeping inputJson as is.'); console.warn('⚠️ Model key not found or empty, keeping inputJson as is.');
} }
}, },

View File

@ -1 +1,34 @@
<p>wire-frame-edit works!</p> <div class="wireframe-container">
<!-- GrapesJS Editor + Sidebar -->
<div class="app-container" *ngIf="currentPageHtml">
<div class="canvas-container">
<div #gjsContainer class="page-canvas"></div>
</div>
</div>
<!-- No content message -->
<div class="no-content" *ngIf="!currentPageHtml">
<p *ngIf="totalPages === 0">No HTML pages found in localStorage.</p>
<p *ngIf="totalPages > 0 && !currentPageHtml">Current page has no HTML content.</p>
</div>
<!-- Sticky Navigation buttons at bottom center -->
<div class="sticky-navigation" *ngIf="totalPages > 1">
<button
class="nav-btn prev-btn"
[disabled]="!hasPrevPage()"
(click)="prevPage()">
← Previous
</button>
<span class="page-indicator">
{{ getCurrentPageNumber() }} / {{ totalPages }}
</span>
<button
class="nav-btn next-btn"
[disabled]="!hasNextPage()"
(click)="nextPage()">
Next →
</button>
</div>
</div>

View File

@ -0,0 +1,161 @@
// Hide GrapesJS outlines/highlights - IMPORTANT: This must be global
:host ::ng-deep .gjs-dashed *[data-gjs-highlightable] {
display: none !important;
}
:host ::ng-deep .gjs-cv-canvas {
.gjs-dashed *[data-gjs-highlightable] {
display: none !important;
}
// Hide any other GrapesJS visual indicators
.gjs-hovered,
.gjs-selected {
outline: none !important;
border: none !important;
}
}
.wireframe-container {
padding: 0;
margin: 0;
width: 100%;
height: 100vh;
position: relative;
.app-container {
display: flex;
height: 100vh;
width: 100%;
.canvas-container {
flex: 1;
height: 100%;
overflow: hidden;
.page-canvas {
width: 100%;
height: 100%;
}
}
}
.no-content {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #f9f9f9;
color: #666;
p {
font-size: 18px;
margin: 0;
}
}
.page-list {
position: fixed;
top: 20px;
right: 20px;
background: rgba(255, 255, 255, 0.95);
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
z-index: 999;
h4 {
margin: 0 0 10px 0;
font-size: 14px;
color: #333;
}
.page-buttons {
display: flex;
flex-direction: column;
gap: 5px;
.page-btn {
padding: 8px 12px;
border: 1px solid #ddd;
background: white;
cursor: pointer;
font-size: 12px;
border-radius: 4px;
transition: all 0.2s ease;
&:hover {
background: #f8f9fa;
}
&.active {
background: #007bff;
color: white;
border-color: #007bff;
}
}
}
}
// Sticky navigation at bottom center
.sticky-navigation {
position: fixed;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
background-color: rgba(255, 255, 255, 0.95);
padding: 15px 25px;
border-radius: 50px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
z-index: 1000;
.nav-btn {
padding: 10px 20px;
border: none;
border-radius: 25px;
background-color: #2196F3;
color: white;
cursor: pointer;
font-size: 14px;
font-weight: 500;
transition: all 0.3s ease;
&:hover:not(:disabled) {
background-color: #1976D2;
transform: translateY(-2px);
}
&:disabled {
background-color: #cccccc;
cursor: not-allowed;
transform: none;
}
&.prev-btn {
background-color: #FF9800;
&:hover:not(:disabled) {
background-color: #F57C00;
}
}
}
.page-indicator {
padding: 8px 16px;
background-color: rgba(33, 150, 243, 0.1);
border-radius: 20px;
font-weight: bold;
color: #333;
border: 2px solid #2196F3;
font-size: 14px;
}
}
}

View File

@ -1,10 +1,142 @@
import { Component } from '@angular/core'; import { Component, OnInit, ViewChild, ElementRef, OnDestroy } from '@angular/core';
import grapesjs from 'grapesjs';
import presetWebpage from 'grapesjs-preset-webpage';
const editor = grapesjs.init({
container: '#editor',
plugins: [presetWebpage],
});
import { COMMON_CSS } from './common-css';
@Component({ @Component({
selector: 'app-wire-frame-edit', selector: 'app-wire-frame-edit',
templateUrl: './wire-frame-edit.component.html', templateUrl: './wire-frame-edit.component.html',
styleUrls: ['./wire-frame-edit.component.scss'] styleUrls: ['./wire-frame-edit.component.scss'] // use your CSS here
}) })
export class WireFrameEditComponent { export class WireFrameEditComponent implements OnInit, OnDestroy {
@ViewChild('gjsContainer', { static: false }) gjsContainer!: ElementRef<HTMLDivElement>;
mapOfAllHtmlPages: { [key: string]: string } = {};
pageKeys: string[] = [];
currentPageIndex: number = 0;
currentPageName: string = '';
currentPageHtml: string = '';
totalPages: number = 0;
sidebarOpen = true;
private editor: any = null;
ngOnInit(): void {
this.mapOfAllHtmlPages = JSON.parse(localStorage.getItem('mapOfHtml') || '{}');
this.pageKeys = Object.keys(this.mapOfAllHtmlPages);
this.totalPages = this.pageKeys.length;
if (this.totalPages > 0) {
this.loadPage(0);
}
}
ngAfterViewInit() {
// Initialize GrapesJS after view is ready
if (this.gjsContainer && this.currentPageHtml) {
this.initGrapesJs();
}
}
ngOnDestroy() {
this.editor?.destroy();
}
loadPage(index: number): void {
if (index >= 0 && index < this.totalPages) {
this.currentPageIndex = index;
this.currentPageName = this.pageKeys[index];
this.currentPageHtml = this.mapOfAllHtmlPages[this.currentPageName];
// If GrapesJS already initialized, update its content
if (this.editor) {
this.editor.setComponents(this.currentPageHtml, { keepScripts: true });
}
}
}
nextPage(): void {
if (this.currentPageIndex < this.totalPages - 1) {
this.loadPage(this.currentPageIndex + 1);
}
}
prevPage(): void {
if (this.currentPageIndex > 0) {
this.loadPage(this.currentPageIndex - 1);
}
}
hasNextPage(): boolean {
return this.currentPageIndex < this.totalPages - 1;
}
hasPrevPage(): boolean {
return this.currentPageIndex > 0;
}
getCurrentPageNumber(): number {
return this.currentPageIndex + 1;
}
toggleSidebar() {
this.sidebarOpen = !this.sidebarOpen;
}
downloadHtml() {
const blob = new Blob([this.currentPageHtml], { type: 'text/html' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = `${this.currentPageName || 'exported-page'}.html`;
a.click();
URL.revokeObjectURL(a.href);
}
private initGrapesJs() {
// If already initialized, destroy and re-init
if (this.editor) {
this.editor.destroy();
}
this.editor = grapesjs.init({
container: this.gjsContainer.nativeElement,
fromElement: false,
storageManager: false,
plugins: ['gjs-preset-webpage'],
allowScripts: 1,
} as any);
this.editor.setComponents(this.currentPageHtml, { keepScripts: true });
this.editor.on('component:update', this.updateCurrentPageHtml.bind(this));
this.editor.on('style:change', this.updateCurrentPageHtml.bind(this));
}
private updateCurrentPageHtml() {
if (!this.editor) return;
const html = this.editor.getHtml();
const css = this.editor.getCss();
this.currentPageHtml = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>${this.currentPageName}</title>
<style>${css }</style>
<style>${COMMON_CSS }</style>
</head>
<body>
${html}
</body>
</html>
`;
// Optionally, update your map and localStorage here if you want autosave
// this.mapOfAllHtmlPages[this.currentPageName] = this.currentPageHtml;
// localStorage.setItem('mapOfHtml', JSON.stringify(this.mapOfAllHtmlPages));
}
} }

View File

@ -101,6 +101,7 @@ import { EditstepperComponent } from './BuilderComponents/vpspack/Visa_applicati
import { Design_lbraryComponent } from './fnd/SiteTreeBuilder/Design_lbrary/Design_lbrary.component'; import { Design_lbraryComponent } from './fnd/SiteTreeBuilder/Design_lbrary/Design_lbrary.component';
import { Dlf_headerComponent } from './fnd/SiteTreeBuilder/Dlf_header/Dlf_header.component'; import { Dlf_headerComponent } from './fnd/SiteTreeBuilder/Dlf_header/Dlf_header.component';
import { WireFrameEditComponent } from './fnd/SiteTreeBuilder/wire-frame-edit/wire-frame-edit.component'; import { WireFrameEditComponent } from './fnd/SiteTreeBuilder/wire-frame-edit/wire-frame-edit.component';
import { TagComponent } from './fnd/SiteTreeBuilder/Tag/Tag.component';
@ -272,10 +273,14 @@ const routes: Routes = [
// buildercomponents // buildercomponents
{ path: 'Tag', component: TagComponent },
{ path: 'Dlf_header', component: Dlf_headerComponent }, { path: 'Dlf_header', component: Dlf_headerComponent },
// { path: 'Design_lbrary', component: Design_lbraryComponent }, // { path: 'Design_lbrary', component: Design_lbraryComponent },
{ path: 'Design_lbrary/:id', component: Design_lbraryComponent }, { path: 'Design_lbrary/:id', component: Design_lbraryComponent },
{ path: 'WireFrameEdit', component: WireFrameEditComponent },
{ path: 'sitetree', component: SiteTreeComponent, }, { path: 'sitetree', component: SiteTreeComponent, },

View File

@ -129,6 +129,7 @@ import { Design_lbraryComponent } from './fnd/SiteTreeBuilder/Design_lbrary/Desi
import { Dlf_headerComponent } from './fnd/SiteTreeBuilder/Dlf_header/Dlf_header.component'; import { Dlf_headerComponent } from './fnd/SiteTreeBuilder/Dlf_header/Dlf_header.component';
import { EditstepperTfComponent } from './fnd/Visa_application/VisaOrderWorkflow/editstepperTf.component'; import { EditstepperTfComponent } from './fnd/Visa_application/VisaOrderWorkflow/editstepperTf.component';
import { WireFrameEditComponent } from './fnd/SiteTreeBuilder/wire-frame-edit/wire-frame-edit.component'; import { WireFrameEditComponent } from './fnd/SiteTreeBuilder/wire-frame-edit/wire-frame-edit.component';
import { TagComponent } from './fnd/SiteTreeBuilder/Tag/Tag.component';
@NgModule({ @NgModule({
@ -152,6 +153,8 @@ import { WireFrameEditComponent } from './fnd/SiteTreeBuilder/wire-frame-edit/wi
// buildercomponents // buildercomponents
WireFrameEditComponent,
TagComponent,
EditstepperTfComponent, EditstepperTfComponent,
Dlf_headerComponent, Dlf_headerComponent,
Design_lbraryComponent, Design_lbraryComponent,