tree
This commit is contained in:
parent
32c8b6acd4
commit
0b8f762a63
@ -57,8 +57,8 @@ export class EditstepperComponent implements OnInit {
|
|||||||
rowSelected: any = {};
|
rowSelected: any = {};
|
||||||
modalcomplete = false;
|
modalcomplete = false;
|
||||||
|
|
||||||
constructor(private mainService: Visa_applicationservice,
|
constructor(
|
||||||
|
private mainService: Visa_applicationservice,
|
||||||
private _fb: FormBuilder,
|
private _fb: FormBuilder,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
|
|||||||
Binary file not shown.
@ -73,7 +73,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="offcanvas-body">
|
<div class="offcanvas-body">
|
||||||
<div class="section-templates-container">
|
<div class="section-templates-container">
|
||||||
<!-- Default Sections -->
|
<!-- Default Sections -->
|
||||||
<h4>Default Sections</h4>
|
<h4>Default Sections</h4>
|
||||||
<div class="section-template" *ngFor="let template of sectionTemplates"
|
<div class="section-template" *ngFor="let template of sectionTemplates"
|
||||||
@ -92,7 +92,7 @@
|
|||||||
|
|
||||||
<!-- Message when no custom sections -->
|
<!-- Message when no custom sections -->
|
||||||
<div *ngIf="customSections.length === 0" class="no-custom-sections"
|
<div *ngIf="customSections.length === 0" class="no-custom-sections"
|
||||||
style="padding: 15px; text-align: center; color: #666; font-style: italic; border: 1px dashed #ccc; border-radius: 4px;">
|
style="padding: 15px; text-align: center; color: #666; font-style: italic; border: 1px dashed #ccc; border-radius: 4px;">
|
||||||
No custom sections created yet. Create one below!
|
No custom sections created yet. Create one below!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -115,31 +115,38 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Edit Section Offcanvas -->
|
<!-- Edit Section Offcanvas -->
|
||||||
<div class="offcanvas edit-section" [class.show]="showEditSectionOffcanvas">
|
<div class="offcanvas edit-section" [class.show]="showEditSectionOffcanvas">
|
||||||
<div class="offcanvas-header">
|
<div class="offcanvas-header">
|
||||||
<div class="offcanvas-title">Edit Section: {{ selectedSection?.type }}</div>
|
<div class="offcanvas-title">Edit Section: {{ selectedSection?.type }}</div>
|
||||||
<button class="close-btn" (click)="closeEditSectionOffcanvas()">
|
<button class="close-btn" (click)="closeEditSectionOffcanvas()">
|
||||||
<i class="fas fa-times"></i>
|
<i class="fas fa-times"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
|
||||||
<div class="offcanvas-body">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="form-label">Section Type</label>
|
|
||||||
<input type="text" class="form-control" [(ngModel)]="selectedSection.type" *ngIf="selectedSection"
|
|
||||||
placeholder="Section type">
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group mt-3">
|
<div class="offcanvas-body">
|
||||||
<label class="form-label">Content</label>
|
<div class="form-group">
|
||||||
<!-- Fixed binding here -->
|
<label class="form-label">Section Type</label>
|
||||||
<textarea class="form-control" [(ngModel)]="selectedSection.content" *ngIf="selectedSection" rows="8"
|
<input type="text" class="form-control" [(ngModel)]="selectedSection.type" *ngIf="selectedSection"
|
||||||
placeholder="Enter content"></textarea>
|
placeholder="Section type">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-actions mt-4">
|
<div class="form-group mt-3">
|
||||||
<button class="btn btn-secondary" (click)="closeEditSectionOffcanvas()">Cancel</button>
|
<label class="form-label">Content</label>
|
||||||
<button class="btn btn-primary" (click)="saveSection()">Save Changes</button>
|
<!-- Fixed binding here -->
|
||||||
|
<textarea class="form-control" [(ngModel)]="selectedSection.content" *ngIf="selectedSection" rows="8"
|
||||||
|
placeholder="Enter content"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group mt-3">
|
||||||
|
<label class="form-label">Keywords (comma separated)</label>
|
||||||
|
<input type="text" class="form-control" [(ngModel)]="selectedSection.keywords"
|
||||||
|
placeholder="e.g. technology, business" *ngIf="selectedSection">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-actions mt-4">
|
||||||
|
<button class="btn btn-secondary" (click)="closeEditSectionOffcanvas()">Cancel</button>
|
||||||
|
<button class="btn btn-primary" (click)="saveSection()">Save Changes</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal" [class.show]="showAddChildModal">
|
<div class="modal" [class.show]="showAddChildModal">
|
||||||
<div class="modal-backdrop" *ngIf="showAddChildModal" (click)="closeAddChildModal()"></div>
|
<div class="modal-backdrop" *ngIf="showAddChildModal" (click)="closeAddChildModal()"></div>
|
||||||
@ -167,98 +174,96 @@
|
|||||||
<div class="spinner"></div>
|
<div class="spinner"></div>
|
||||||
<div class="loading-text">Processing...</div>
|
<div class="loading-text">Processing...</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Updated page template with proper connector lines -->
|
<!-- Updated page template with proper connector lines -->
|
||||||
<ng-template #pageTemplate let-page>
|
<ng-template #pageTemplate let-page>
|
||||||
<div class="node-container drop-zone"
|
<div class="node-container drop-zone" draggable="true" (dragstart)="onPageDragStart(page, $event)"
|
||||||
draggable="true"
|
(dragend)="onPageDragEnd($event)" (dragover)="onPageDragOver($event)" (dragleave)="onPageDragLeave($event)"
|
||||||
(dragstart)="onPageDragStart(page, $event)"
|
(drop)="onPageDrop(page, $event)" style="position: relative; margin: 20px 0;">
|
||||||
(dragend)="onPageDragEnd($event)"
|
|
||||||
(dragover)="onPageDragOver($event)"
|
|
||||||
(dragleave)="onPageDragLeave($event)"
|
|
||||||
(drop)="onPageDrop(page, $event)"
|
|
||||||
style="position: relative; margin: 20px 0;">
|
|
||||||
|
|
||||||
<!-- Single consistent connector line from parent -->
|
<!-- Single consistent connector line from parent -->
|
||||||
<div *ngIf="page.parent && page.parent !== rootPage"
|
<div *ngIf="page.parent && page.parent !== rootPage"
|
||||||
style="position: absolute; top: -20px; left: 50%; width: 2px; height: 20px; background-color: #6c757d !important; z-index: 1; transform: translateX(-50%);"></div>
|
style="position: absolute; top: -20px; left: 50%; width: 2px; height: 20px; background-color: #6c757d !important; z-index: 1; transform: translateX(-50%);">
|
||||||
|
|
||||||
<div class="node-card" [class.selected]="selectedPage === page" (click)="selectPage(page)">
|
|
||||||
<div class="node-header">
|
|
||||||
<i class="node-icon" [class]="getNodeIcon(page)"></i>
|
|
||||||
<span class="node-title">{{ page.name }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sections-container" cdkDropList [cdkDropListData]="page.sections"
|
<div class="node-card" [class.selected]="selectedPage === page" (click)="selectPage(page)">
|
||||||
(cdkDropListDropped)="onSectionDrop($event)">
|
<div class="node-header">
|
||||||
|
<i class="node-icon" [class]="getNodeIcon(page)"></i>
|
||||||
|
<span class="node-title">{{ page.name }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Show message and add button for empty pages -->
|
<div class="sections-container" cdkDropList [cdkDropListData]="page.sections"
|
||||||
<div *ngIf="page.sections.length === 0" class="empty-page-container"
|
(cdkDropListDropped)="onSectionDrop($event)">
|
||||||
style="padding: 20px; text-align: center; border: 2px dashed #ccc; margin: 10px 0; border-radius: 8px;">
|
|
||||||
<p style="color: #666; margin: 0 0 10px 0; font-style: italic;">No sections added yet</p>
|
<!-- Show message and add button for empty pages -->
|
||||||
<button class="btn btn-primary btn-sm" (click)="showAddSectionForEmptyPage(page, $event)"
|
<div *ngIf="page.sections.length === 0" class="empty-page-container"
|
||||||
style="background-color: #007bff !important; border: none; padding: 8px 16px; border-radius: 4px; color: white;">
|
style="padding: 20px; text-align: center; border: 2px dashed #ccc; margin: 10px 0; border-radius: 8px;">
|
||||||
<i class="fas fa-plus"></i> Add First Section
|
<p style="color: #666; margin: 0 0 10px 0; font-style: italic;">No sections added yet</p>
|
||||||
|
<button class="btn btn-primary btn-sm" (click)="showAddSectionForEmptyPage(page, $event)"
|
||||||
|
style="background-color: #007bff !important; border: none; padding: 8px 16px; border-radius: 4px; color: white;">
|
||||||
|
<i class="fas fa-plus"></i> Add First Section
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Existing sections -->
|
||||||
|
<div class="section-card" *ngFor="let section of page.sections; let i = index" cdkDrag [cdkDragData]="section"
|
||||||
|
(click)="selectSection(section); $event.stopPropagation()">
|
||||||
|
<div class="section-title">{{ section.type }}</div>
|
||||||
|
<div class="section-content" [innerHTML]="getSectionContentHtml(section.content)"></div>
|
||||||
|
<div class="section-actions">
|
||||||
|
<button class="section-action-btn" title="Edit Section" (click)="editSection(section, $event)">
|
||||||
|
<i class="fas fa-pencil-alt"></i>
|
||||||
|
</button>
|
||||||
|
<button class="section-action-btn" title="Delete Section" (click)="deleteSection(section, page, $event)">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="add-section-hover-btn" (click)="openAddSectionOffcanvas(page, i, $event)" title="Add Section">
|
||||||
|
<i class="fas fa-plus"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Add section button for pages with existing sections -->
|
||||||
|
<div *ngIf="page.sections.length > 0" class="add-section-btn"
|
||||||
|
(click)="openAddSectionOffcanvas(page, -1, $event)"
|
||||||
|
style="padding: 10px; text-align: center; border: 1px dashed #007bff; margin-top: 10px; border-radius: 4px; cursor: pointer; color: #007bff;">
|
||||||
|
<i class="fas fa-plus"></i> Add Section
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="node-actions">
|
||||||
|
<button class="node-action-btn" title="Add Child Page"
|
||||||
|
(click)="showAddChildPageModal(page); $event.stopPropagation()">
|
||||||
|
<i class="fas fa-plus"></i>
|
||||||
|
</button>
|
||||||
|
<button class="node-action-btn" title="Delete Page" (click)="deletePage(page, $event)">
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="add-child-hover-btn" (click)="showAddChildPageModal(page); $event.stopPropagation()">
|
||||||
<!-- Existing sections -->
|
|
||||||
<div class="section-card" *ngFor="let section of page.sections; let i = index" cdkDrag [cdkDragData]="section"
|
|
||||||
(click)="selectSection(section); $event.stopPropagation()">
|
|
||||||
<div class="section-title">{{ section.type }}</div>
|
|
||||||
<div class="section-content" [innerHTML]="getSectionContentHtml(section.content)"></div>
|
|
||||||
<div class="section-actions">
|
|
||||||
<button class="section-action-btn" title="Edit Section" (click)="editSection(section, $event)">
|
|
||||||
<i class="fas fa-pencil-alt"></i>
|
|
||||||
</button>
|
|
||||||
<button class="section-action-btn" title="Delete Section" (click)="deleteSection(section, page, $event)">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="add-section-hover-btn" (click)="openAddSectionOffcanvas(page, i, $event)" title="Add Section">
|
|
||||||
<i class="fas fa-plus"></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Add section button for pages with existing sections -->
|
|
||||||
<div *ngIf="page.sections.length > 0" class="add-section-btn"
|
|
||||||
(click)="openAddSectionOffcanvas(page, -1, $event)"
|
|
||||||
style="padding: 10px; text-align: center; border: 1px dashed #007bff; margin-top: 10px; border-radius: 4px; cursor: pointer; color: #007bff;">
|
|
||||||
<i class="fas fa-plus"></i> Add Section
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="node-actions">
|
|
||||||
<button class="node-action-btn" title="Add Child Page"
|
|
||||||
(click)="showAddChildPageModal(page); $event.stopPropagation()">
|
|
||||||
<i class="fas fa-plus"></i>
|
<i class="fas fa-plus"></i>
|
||||||
</button>
|
</div>
|
||||||
<button class="node-action-btn" title="Delete Page" (click)="deletePage(page, $event)">
|
|
||||||
<i class="fas fa-trash"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="add-child-hover-btn" (click)="showAddChildPageModal(page); $event.stopPropagation()">
|
|
||||||
<i class="fas fa-plus"></i>
|
<!-- Connector to children - only show if has children -->
|
||||||
|
<div *ngIf="page.children && page.children.length > 0">
|
||||||
|
<!-- Vertical line down from current node -->
|
||||||
|
<div
|
||||||
|
style="position: absolute; bottom: -20px; left: 50%; width: 2px; height: 20px; background-color: #6c757d !important; z-index: 1; transform: translateX(-50%);">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Horizontal line connecting all children (only if more than 1 child) -->
|
||||||
|
<div *ngIf="page.children.length > 1" class="horizontal-connector"
|
||||||
|
style="position: absolute; bottom: -20px; height: 2px; background-color: #6c757d !important; z-index: 1;"
|
||||||
|
[style.left.px]="getHorizontalConnectorLeft(page.children.length)"
|
||||||
|
[style.width.px]="getHorizontalConnectorWidth(page.children.length)"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Children container -->
|
||||||
|
<div class="children-container" *ngIf="page.children && page.children.length > 0"
|
||||||
|
style="display: flex; justify-content: center; gap: 40px; margin-top: 40px;">
|
||||||
|
<ng-container *ngFor="let childPage of page.children">
|
||||||
|
<ng-container *ngTemplateOutlet="pageTemplate; context: { $implicit: childPage }"></ng-container>
|
||||||
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ng-template>
|
||||||
<!-- Connector to children - only show if has children -->
|
|
||||||
<div *ngIf="page.children && page.children.length > 0">
|
|
||||||
<!-- Vertical line down from current node -->
|
|
||||||
<div style="position: absolute; bottom: -20px; left: 50%; width: 2px; height: 20px; background-color: #6c757d !important; z-index: 1; transform: translateX(-50%);"></div>
|
|
||||||
|
|
||||||
<!-- Horizontal line connecting all children (only if more than 1 child) -->
|
|
||||||
<div *ngIf="page.children.length > 1" class="horizontal-connector"
|
|
||||||
style="position: absolute; bottom: -20px; height: 2px; background-color: #6c757d !important; z-index: 1;"
|
|
||||||
[style.left.px]="getHorizontalConnectorLeft(page.children.length)"
|
|
||||||
[style.width.px]="getHorizontalConnectorWidth(page.children.length)"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Children container -->
|
|
||||||
<div class="children-container" *ngIf="page.children && page.children.length > 0"
|
|
||||||
style="display: flex; justify-content: center; gap: 40px; margin-top: 40px;">
|
|
||||||
<ng-container *ngFor="let childPage of page.children">
|
|
||||||
<ng-container *ngTemplateOutlet="pageTemplate; context: { $implicit: childPage }"></ng-container>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</ng-template>
|
|
||||||
@ -9,6 +9,8 @@ import { ToastrService } from 'ngx-toastr';
|
|||||||
interface Section {
|
interface Section {
|
||||||
type: string;
|
type: string;
|
||||||
content: string;
|
content: string;
|
||||||
|
keywords?: string; // <-- Add this line
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Page {
|
interface Page {
|
||||||
@ -140,17 +142,17 @@ export class TreeNodeComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
|
|
||||||
|
|
||||||
customSections = [
|
customSections = [
|
||||||
{
|
{
|
||||||
type: 'Visa Application',
|
type: 'Visa Application',
|
||||||
description: 'Visa application form and process',
|
description: 'Visa application form and process',
|
||||||
content: 'Complete visa application with required documents and processing information.'
|
content: 'Complete visa application with required documents and processing information.'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'Visa Application 2',
|
type: 'Visa Application 2',
|
||||||
description: 'Alternative visa application layout',
|
description: 'Alternative visa application layout',
|
||||||
content: 'Alternative visa application design with step-by-step guidance.'
|
content: 'Alternative visa application design with step-by-step guidance.'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -538,6 +540,18 @@ export class TreeNodeComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
// If parsing fails, use the raw content
|
// If parsing fails, use the raw content
|
||||||
pageObj[section.type] = section.content;
|
pageObj[section.type] = section.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ✅ Save keywords if present
|
||||||
|
if (section.keywords) {
|
||||||
|
if (typeof pageObj[section.type] === 'object') {
|
||||||
|
pageObj[section.type].keywords = section.keywords;
|
||||||
|
} else {
|
||||||
|
pageObj[section.type] = {
|
||||||
|
text: pageObj[section.type],
|
||||||
|
keywords: section.keywords
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add children
|
// Add children
|
||||||
@ -709,19 +723,19 @@ export class TreeNodeComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
|
|
||||||
// Save section changes
|
// Save section changes
|
||||||
saveSection(): void {
|
saveSection(): void {
|
||||||
if (this.selectedSection && this.currentParentPage) {
|
if (this.selectedSection && this.currentParentPage) {
|
||||||
// Find the original section in the parent page by reference
|
// Find the original section in the parent page by reference
|
||||||
const originalSection = this.currentParentPage.sections.find(s => s === this.selectedSection);
|
const originalSection = this.currentParentPage.sections.find(s => s === this.selectedSection);
|
||||||
|
|
||||||
if (originalSection) {
|
if (originalSection) {
|
||||||
// Update the original section directly
|
// Update the original section directly
|
||||||
originalSection.type = this.selectedSection.type;
|
originalSection.type = this.selectedSection.type;
|
||||||
originalSection.content = this.selectedSection.content;
|
originalSection.content = this.selectedSection.content;
|
||||||
this.hasUnsavedChanges = true;
|
this.hasUnsavedChanges = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
this.closeEditSectionOffcanvas();
|
||||||
}
|
}
|
||||||
this.closeEditSectionOffcanvas();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add section from a template
|
// Add section from a template
|
||||||
addSectionFromTemplate(template: any): void {
|
addSectionFromTemplate(template: any): void {
|
||||||
@ -751,79 +765,79 @@ export class TreeNodeComponent implements OnInit, OnDestroy, AfterViewInit {
|
|||||||
|
|
||||||
// Similar update for addCustomSection
|
// Similar update for addCustomSection
|
||||||
addCustomSection(): void {
|
addCustomSection(): void {
|
||||||
if (this.currentParentPage && this.customSectionType) {
|
if (this.currentParentPage && this.customSectionType) {
|
||||||
const newSection: Section = {
|
const newSection: Section = {
|
||||||
type: this.customSectionType,
|
|
||||||
content: this.customSectionContent || ''
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add to current page
|
|
||||||
if (this.currentSectionIndex >= 0) {
|
|
||||||
this.currentParentPage.sections.splice(this.currentSectionIndex + 1, 0, newSection);
|
|
||||||
} else {
|
|
||||||
this.currentParentPage.sections.push(newSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to custom sections list if it doesn't exist
|
|
||||||
const existingCustomSection = this.customSections.find(cs => cs.type === this.customSectionType);
|
|
||||||
if (!existingCustomSection) {
|
|
||||||
this.customSections.push({
|
|
||||||
type: this.customSectionType,
|
type: this.customSectionType,
|
||||||
description: 'Custom section',
|
|
||||||
content: this.customSectionContent || ''
|
content: this.customSectionContent || ''
|
||||||
});
|
};
|
||||||
|
|
||||||
|
// Add to current page
|
||||||
|
if (this.currentSectionIndex >= 0) {
|
||||||
|
this.currentParentPage.sections.splice(this.currentSectionIndex + 1, 0, newSection);
|
||||||
|
} else {
|
||||||
|
this.currentParentPage.sections.push(newSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to custom sections list if it doesn't exist
|
||||||
|
const existingCustomSection = this.customSections.find(cs => cs.type === this.customSectionType);
|
||||||
|
if (!existingCustomSection) {
|
||||||
|
this.customSections.push({
|
||||||
|
type: this.customSectionType,
|
||||||
|
description: 'Custom section',
|
||||||
|
content: this.customSectionContent || ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to available section types
|
||||||
|
if (!this.availableSectionTypes.includes(this.customSectionType)) {
|
||||||
|
this.availableSectionTypes.push(this.customSectionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hasUnsavedChanges = true;
|
||||||
|
this.closeAddSectionOffcanvas();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to available section types
|
|
||||||
if (!this.availableSectionTypes.includes(this.customSectionType)) {
|
|
||||||
this.availableSectionTypes.push(this.customSectionType);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.hasUnsavedChanges = true;
|
|
||||||
this.closeAddSectionOffcanvas();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addCustomSectionFromList(customSection: any): void {
|
||||||
|
if (this.currentParentPage) {
|
||||||
|
const newSection: Section = {
|
||||||
|
type: customSection.type,
|
||||||
|
content: customSection.content
|
||||||
|
};
|
||||||
|
|
||||||
}
|
// Insert at specific position if provided, otherwise add to end
|
||||||
|
if (this.currentSectionIndex >= 0) {
|
||||||
|
this.currentParentPage.sections.splice(this.currentSectionIndex + 1, 0, newSection);
|
||||||
|
} else {
|
||||||
|
this.currentParentPage.sections.push(newSection);
|
||||||
|
}
|
||||||
|
|
||||||
addCustomSectionFromList(customSection: any): void {
|
if (!this.availableSectionTypes.includes(customSection.type)) {
|
||||||
if (this.currentParentPage) {
|
this.availableSectionTypes.push(customSection.type);
|
||||||
const newSection: Section = {
|
}
|
||||||
type: customSection.type,
|
|
||||||
content: customSection.content
|
|
||||||
};
|
|
||||||
|
|
||||||
// Insert at specific position if provided, otherwise add to end
|
this.hasUnsavedChanges = true;
|
||||||
if (this.currentSectionIndex >= 0) {
|
this.closeAddSectionOffcanvas();
|
||||||
this.currentParentPage.sections.splice(this.currentSectionIndex + 1, 0, newSection);
|
|
||||||
} else {
|
|
||||||
this.currentParentPage.sections.push(newSection);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.availableSectionTypes.includes(customSection.type)) {
|
|
||||||
this.availableSectionTypes.push(customSection.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.hasUnsavedChanges = true;
|
|
||||||
this.closeAddSectionOffcanvas();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Edit section
|
// Edit section
|
||||||
// Edit section - modify this function
|
// Edit section - modify this function
|
||||||
editSection(section: Section, event: Event): void {
|
editSection(section: Section, event: Event): void {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
// Store reference to the original section
|
// Store reference to the original section
|
||||||
this.selectedSection = section; // Don't clone, use direct reference
|
this.selectedSection = section; // Don't clone, use direct reference
|
||||||
this.currentParentPage = this.selectedPage;
|
this.currentParentPage = this.selectedPage;
|
||||||
this.editMode = 'section';
|
this.editMode = 'section';
|
||||||
this.showEditSectionOffcanvas = true;
|
this.showEditSectionOffcanvas = true;
|
||||||
|
|
||||||
// Listen for clicks outside offcanvas
|
// Listen for clicks outside offcanvas
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.addEventListener('click', this.handleOutsideClick);
|
document.addEventListener('click', this.handleOutsideClick);
|
||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel edit
|
// Cancel edit
|
||||||
cancelEdit(): void {
|
cancelEdit(): void {
|
||||||
@ -860,112 +874,112 @@ addCustomSectionFromList(customSection: any): void {
|
|||||||
|
|
||||||
// Handle page drag start
|
// Handle page drag start
|
||||||
onPageDragStart(page: Page, event: DragEvent): void {
|
onPageDragStart(page: Page, event: DragEvent): void {
|
||||||
this.draggedPage = page;
|
this.draggedPage = page;
|
||||||
if (event.dataTransfer) {
|
if (event.dataTransfer) {
|
||||||
event.dataTransfer.effectAllowed = 'move';
|
event.dataTransfer.effectAllowed = 'move';
|
||||||
event.dataTransfer.setData('text/html', page.name);
|
event.dataTransfer.setData('text/html', page.name);
|
||||||
}
|
|
||||||
|
|
||||||
// Add visual feedback
|
|
||||||
setTimeout(() => {
|
|
||||||
const draggedElement = event.target as HTMLElement;
|
|
||||||
if (draggedElement) {
|
|
||||||
draggedElement.classList.add('dragging');
|
|
||||||
}
|
}
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
onPageDragOver(event: DragEvent): void {
|
// Add visual feedback
|
||||||
event.preventDefault();
|
setTimeout(() => {
|
||||||
event.stopPropagation();
|
const draggedElement = event.target as HTMLElement;
|
||||||
|
if (draggedElement) {
|
||||||
if (event.dataTransfer) {
|
draggedElement.classList.add('dragging');
|
||||||
event.dataTransfer.dropEffect = 'move';
|
}
|
||||||
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add visual feedback
|
onPageDragOver(event: DragEvent): void {
|
||||||
const dropZone = event.currentTarget as HTMLElement;
|
event.preventDefault();
|
||||||
if (dropZone) {
|
event.stopPropagation();
|
||||||
dropZone.classList.add('drag-over');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onPageDragLeave(event: DragEvent): void {
|
if (event.dataTransfer) {
|
||||||
const dropZone = event.currentTarget as HTMLElement;
|
event.dataTransfer.dropEffect = 'move';
|
||||||
if (dropZone) {
|
}
|
||||||
dropZone.classList.remove('drag-over');
|
|
||||||
|
// Add visual feedback
|
||||||
|
const dropZone = event.currentTarget as HTMLElement;
|
||||||
|
if (dropZone) {
|
||||||
|
dropZone.classList.add('drag-over');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onPageDragLeave(event: DragEvent): void {
|
||||||
|
const dropZone = event.currentTarget as HTMLElement;
|
||||||
|
if (dropZone) {
|
||||||
|
dropZone.classList.remove('drag-over');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Handle page drag end
|
// Handle page drag end
|
||||||
onPageDragEnd(event: DragEvent): void {
|
onPageDragEnd(event: DragEvent): void {
|
||||||
// Remove visual feedback
|
// Remove visual feedback
|
||||||
const draggedElement = event.target as HTMLElement;
|
const draggedElement = event.target as HTMLElement;
|
||||||
if (draggedElement) {
|
if (draggedElement) {
|
||||||
draggedElement.classList.remove('dragging');
|
draggedElement.classList.remove('dragging');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all drop zone highlights
|
||||||
|
document.querySelectorAll('.drop-zone').forEach(el => {
|
||||||
|
el.classList.remove('drag-over');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.draggedPage = null;
|
||||||
|
this.dropTargetPage = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all drop zone highlights
|
|
||||||
document.querySelectorAll('.drop-zone').forEach(el => {
|
|
||||||
el.classList.remove('drag-over');
|
|
||||||
});
|
|
||||||
|
|
||||||
this.draggedPage = null;
|
|
||||||
this.dropTargetPage = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle page drop
|
// Handle page drop
|
||||||
onPageDrop(targetPage: Page, event: DragEvent): void {
|
onPageDrop(targetPage: Page, event: DragEvent): void {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
// Remove visual feedback
|
// Remove visual feedback
|
||||||
const dropZone = event.currentTarget as HTMLElement;
|
const dropZone = event.currentTarget as HTMLElement;
|
||||||
if (dropZone) {
|
if (dropZone) {
|
||||||
dropZone.classList.remove('drag-over');
|
dropZone.classList.remove('drag-over');
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.draggedPage || this.draggedPage === targetPage) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prevent dropping a parent into its own child
|
|
||||||
if (this.isDescendant(targetPage, this.draggedPage)) {
|
|
||||||
console.warn('Cannot drop a parent into its own descendant');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove from current parent
|
|
||||||
if (this.draggedPage.parent && this.draggedPage.parent.children) {
|
|
||||||
const sourceIndex = this.draggedPage.parent.children.indexOf(this.draggedPage);
|
|
||||||
if (sourceIndex > -1) {
|
|
||||||
this.draggedPage.parent.children.splice(sourceIndex, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.draggedPage || this.draggedPage === targetPage) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent dropping a parent into its own child
|
||||||
|
if (this.isDescendant(targetPage, this.draggedPage)) {
|
||||||
|
console.warn('Cannot drop a parent into its own descendant');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove from current parent
|
||||||
|
if (this.draggedPage.parent && this.draggedPage.parent.children) {
|
||||||
|
const sourceIndex = this.draggedPage.parent.children.indexOf(this.draggedPage);
|
||||||
|
if (sourceIndex > -1) {
|
||||||
|
this.draggedPage.parent.children.splice(sourceIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to new parent
|
||||||
|
if (!targetPage.children) {
|
||||||
|
targetPage.children = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update parent reference
|
||||||
|
this.draggedPage.parent = targetPage;
|
||||||
|
targetPage.children.push(this.draggedPage);
|
||||||
|
|
||||||
|
this.hasUnsavedChanges = true;
|
||||||
|
console.log(`Moved "${this.draggedPage.name}" to "${targetPage.name}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to new parent
|
private isDescendant(possibleDescendant: Page, ancestor: Page): boolean {
|
||||||
if (!targetPage.children) {
|
if (!ancestor.children) return false;
|
||||||
targetPage.children = [];
|
|
||||||
|
for (const child of ancestor.children) {
|
||||||
|
if (child === possibleDescendant) return true;
|
||||||
|
if (this.isDescendant(possibleDescendant, child)) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update parent reference
|
|
||||||
this.draggedPage.parent = targetPage;
|
|
||||||
targetPage.children.push(this.draggedPage);
|
|
||||||
|
|
||||||
this.hasUnsavedChanges = true;
|
|
||||||
console.log(`Moved "${this.draggedPage.name}" to "${targetPage.name}"`);
|
|
||||||
}
|
|
||||||
|
|
||||||
private isDescendant(possibleDescendant: Page, ancestor: Page): boolean {
|
|
||||||
if (!ancestor.children) return false;
|
|
||||||
|
|
||||||
for (const child of ancestor.children) {
|
|
||||||
if (child === possibleDescendant) return true;
|
|
||||||
if (this.isDescendant(possibleDescendant, child)) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Handle section drag drop
|
// Handle section drag drop
|
||||||
onSectionDrop(event: CdkDragDrop<Section[]>): void {
|
onSectionDrop(event: CdkDragDrop<Section[]>): void {
|
||||||
if (event.previousContainer === event.container) {
|
if (event.previousContainer === event.container) {
|
||||||
@ -999,26 +1013,26 @@ private isDescendant(possibleDescendant: Page, ancestor: Page): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
showAddSectionForEmptyPage(page: Page, event: Event): void {
|
showAddSectionForEmptyPage(page: Page, event: Event): void {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
this.openAddSectionOffcanvas(page, -1, event);
|
this.openAddSectionOffcanvas(page, -1, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add these helper methods to your component for proper connector positioning
|
// Add these helper methods to your component for proper connector positioning
|
||||||
|
|
||||||
getHorizontalConnectorLeft(childrenCount: number): number {
|
getHorizontalConnectorLeft(childrenCount: number): number {
|
||||||
// Calculate left position for horizontal connector
|
// Calculate left position for horizontal connector
|
||||||
const nodeWidth = 250; // Approximate node width
|
const nodeWidth = 250; // Approximate node width
|
||||||
const gap = 40; // Gap between nodes
|
const gap = 40; // Gap between nodes
|
||||||
const totalWidth = (childrenCount * nodeWidth) + ((childrenCount - 1) * gap);
|
const totalWidth = (childrenCount * nodeWidth) + ((childrenCount - 1) * gap);
|
||||||
return (totalWidth / 2) - (totalWidth / childrenCount / 2);
|
return (totalWidth / 2) - (totalWidth / childrenCount / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
getHorizontalConnectorWidth(childrenCount: number): number {
|
getHorizontalConnectorWidth(childrenCount: number): number {
|
||||||
// Calculate width of horizontal connector
|
// Calculate width of horizontal connector
|
||||||
const nodeWidth = 250; // Approximate node width
|
const nodeWidth = 250; // Approximate node width
|
||||||
const gap = 40; // Gap between nodes
|
const gap = 40; // Gap between nodes
|
||||||
return (childrenCount - 1) * (nodeWidth + gap);
|
return (childrenCount - 1) * (nodeWidth + gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save tree data
|
// Save tree data
|
||||||
saveTreeData(silent: boolean = false): void {
|
saveTreeData(silent: boolean = false): void {
|
||||||
|
|||||||
@ -451,7 +451,8 @@
|
|||||||
(cdkDropListDropped)="onSectionDrop($event, getCurrentPageName())">
|
(cdkDropListDropped)="onSectionDrop($event, getCurrentPageName())">
|
||||||
|
|
||||||
<div *ngFor="let sectionKey of getPageSections(getCurrentPageName())" cdkDrag [cdkDragData]="sectionKey"
|
<div *ngFor="let sectionKey of getPageSections(getCurrentPageName())" cdkDrag [cdkDragData]="sectionKey"
|
||||||
class="section-container" [class.editing]="isCurrentSectionEditing(sectionKey)">
|
class="section-container" [class.editing]="isCurrentSectionEditing(sectionKey)"
|
||||||
|
(click)="openCssEditor(getCurrentPageName(), sectionKey)">
|
||||||
|
|
||||||
<!-- Drag Handle -->
|
<!-- Drag Handle -->
|
||||||
<div class="drag-handle" cdkDragHandle>
|
<div class="drag-handle" cdkDragHandle>
|
||||||
@ -483,6 +484,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- CSS Editor Modal -->
|
||||||
|
<div *ngIf="showCssEditorModal" class="css-editor-modal">
|
||||||
|
<h3>Edit CSS for Section: {{ selectedSection?.section }}</h3>
|
||||||
|
|
||||||
|
<div *ngFor="let className of objectKeys(classCssMap)">
|
||||||
|
<h4>.{{ className }}</h4>
|
||||||
|
<div *ngFor="let prop of objectKeys(classCssMap[className])">
|
||||||
|
<label>{{ prop }}</label>
|
||||||
|
<input [(ngModel)]="classCssMap[className][prop]" />
|
||||||
|
<button (click)="removeCssProp(className, prop)">🗑️</button>
|
||||||
|
</div>
|
||||||
|
<button (click)="addCssProp(className)">➕ Add Property</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button (click)="saveClassCss()">💾 Save</button>
|
||||||
|
<button (click)="closeCssEditor()">Cancel</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Empty State for No Pages -->
|
<!-- Empty State for No Pages -->
|
||||||
<div *ngIf="pageRenderOrder.length === 0" class="empty-pages-modern">
|
<div *ngIf="pageRenderOrder.length === 0" class="empty-pages-modern">
|
||||||
<div class="empty-state-modern">
|
<div class="empty-state-modern">
|
||||||
|
|||||||
@ -1920,6 +1920,73 @@ $shadow-heavy: 0 8px 25px rgba(0, 0, 0, 0.15);
|
|||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.css-editor-modal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
z-index: 1000;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
// css editor
|
||||||
|
.css-editor-modal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-editor-modal {
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
width: 600px;
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-editor-modal input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 6px 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-editor-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-editor-header .close-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
font-size: 18px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.css-editor-footer {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// chow code css end
|
// chow code css end
|
||||||
}
|
}
|
||||||
@ -3741,9 +3741,105 @@ async deployAllPages() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// css editor
|
||||||
|
showCssEditorModal = false;
|
||||||
|
cssEditorStyles: any = {};
|
||||||
|
selectedSection: { page: string; section: string } | null = null;
|
||||||
|
|
||||||
|
closeCssEditor(): void {
|
||||||
|
this.showCssEditorModal = false;
|
||||||
|
this.selectedSection = null;
|
||||||
|
this.cssEditorStyles = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// new
|
||||||
|
|
||||||
|
openCssEditor(page: string, section: string): void {
|
||||||
|
const rawHtml = this.sectionHtmls[page]?.[section]?.toString() || '';
|
||||||
|
|
||||||
|
// ✅ Step 1: Parse all class names recursively
|
||||||
|
const tempDiv = document.createElement('div');
|
||||||
|
tempDiv.innerHTML = rawHtml;
|
||||||
|
|
||||||
|
const classSet = new Set<string>();
|
||||||
|
|
||||||
|
// Traverse all elements recursively and extract classList
|
||||||
|
const elements = tempDiv.querySelectorAll('*');
|
||||||
|
elements.forEach(el => {
|
||||||
|
const classList = Array.from(el.classList);
|
||||||
|
classList.forEach(cls => classSet.add(cls));
|
||||||
|
});
|
||||||
|
|
||||||
|
const allClasses = Array.from(classSet);
|
||||||
|
|
||||||
|
// ✅ Step 2: Extract CSS rules for all these classes
|
||||||
|
const cssMap: Record<string, Record<string, string>> = {};
|
||||||
|
allClasses.forEach(cls => {
|
||||||
|
const rules = this.extractCssForClass(cls, this.finalCssBundle); // use your full css bundle
|
||||||
|
cssMap[cls] = rules;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ✅ Step 3: Store in modal
|
||||||
|
this.selectedSection = { page, section };
|
||||||
|
this.classCssMap = cssMap;
|
||||||
|
this.showCssEditorModal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
extractClassesFromHtml(html: string): string[] {
|
||||||
|
const match = html.match(/class=["']([^"']+)["']/);
|
||||||
|
if (!match) return [];
|
||||||
|
return match[1].split(/\s+/).filter(cls => cls.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
extractCssForClass(className: string, cssText: string): Record<string, string> {
|
||||||
|
const result: Record<string, string> = {};
|
||||||
|
const regex = new RegExp(`\\.${className}\\s*{([^}]*)}`, 'g');
|
||||||
|
let match;
|
||||||
|
|
||||||
|
while ((match = regex.exec(cssText)) !== null) {
|
||||||
|
const props = match[1].split(';').map(p => p.trim()).filter(Boolean);
|
||||||
|
props.forEach(prop => {
|
||||||
|
const [key, val] = prop.split(':');
|
||||||
|
if (key && val) result[key.trim()] = val.trim();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
classCssMap: Record<string, Record<string, string>> = {};
|
||||||
|
|
||||||
|
saveClassCss(): void {
|
||||||
|
let cssBundle = '';
|
||||||
|
|
||||||
|
for (const [className, props] of Object.entries(this.classCssMap)) {
|
||||||
|
const block = Object.entries(props)
|
||||||
|
.map(([k, v]) => ` ${k}: ${v};`)
|
||||||
|
.join('\n');
|
||||||
|
cssBundle += `.${className} {\n${block}\n}\n\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { page, section } = this.selectedSection!;
|
||||||
|
this.allPageCss[page] = this.allPageCss[page] || {};
|
||||||
|
this.allPageCss[page][section] = cssBundle;
|
||||||
|
|
||||||
|
this.updateFullPageHtml(page);
|
||||||
|
this.toastr.success(`CSS updated for ${section}`);
|
||||||
|
this.closeCssEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
addCssProp(className: string): void {
|
||||||
|
this.classCssMap[className]['new-property'] = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
removeCssProp(className: string, prop: string): void {
|
||||||
|
delete this.classCssMap[className][prop];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user