@memberjunction/ng-dashboards 2.48.0 → 2.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +105 -2
- package/dist/AI/ai-dashboard.component.d.ts +2 -0
- package/dist/AI/ai-dashboard.component.d.ts.map +1 -1
- package/dist/AI/ai-dashboard.component.js +66 -43
- package/dist/AI/ai-dashboard.component.js.map +1 -1
- package/dist/AI/components/agents/agent-configuration.component.js +45 -58
- package/dist/AI/components/agents/agent-configuration.component.js.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.d.ts +6 -1
- package/dist/AI/components/agents/agent-editor.component.d.ts.map +1 -1
- package/dist/AI/components/agents/agent-editor.component.js +368 -366
- package/dist/AI/components/agents/agent-editor.component.js.map +1 -1
- package/dist/AI/components/agents/agent-filter-panel.component.js +83 -85
- package/dist/AI/components/agents/agent-filter-panel.component.js.map +1 -1
- package/dist/AI/components/charts/performance-heatmap.component.d.ts +66 -0
- package/dist/AI/components/charts/performance-heatmap.component.d.ts.map +1 -0
- package/dist/AI/components/charts/performance-heatmap.component.js +428 -0
- package/dist/AI/components/charts/performance-heatmap.component.js.map +1 -0
- package/dist/AI/components/charts/time-series-chart.component.d.ts +66 -0
- package/dist/AI/components/charts/time-series-chart.component.d.ts.map +1 -0
- package/dist/AI/components/charts/time-series-chart.component.js +547 -0
- package/dist/AI/components/charts/time-series-chart.component.js.map +1 -0
- package/dist/AI/components/execution-monitoring.component.d.ts +157 -5
- package/dist/AI/components/execution-monitoring.component.d.ts.map +1 -1
- package/dist/AI/components/execution-monitoring.component.js +2032 -20
- package/dist/AI/components/execution-monitoring.component.js.map +1 -1
- package/dist/AI/components/models/model-management.component.js +211 -237
- package/dist/AI/components/models/model-management.component.js.map +1 -1
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js +208 -226
- package/dist/AI/components/prompts/model-prompt-priority-matrix.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-filter-panel.component.js +97 -99
- package/dist/AI/components/prompts/prompt-filter-panel.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-management.component.js +381 -424
- package/dist/AI/components/prompts/prompt-management.component.js.map +1 -1
- package/dist/AI/components/prompts/prompt-version-control.component.js +173 -191
- package/dist/AI/components/prompts/prompt-version-control.component.js.map +1 -1
- package/dist/AI/components/system/system-config-filter-panel.component.js +85 -87
- package/dist/AI/components/system/system-config-filter-panel.component.js.map +1 -1
- package/dist/AI/components/system/system-configuration.component.js +86 -99
- package/dist/AI/components/system/system-configuration.component.js.map +1 -1
- package/dist/AI/components/widgets/kpi-card.component.d.ts +25 -0
- package/dist/AI/components/widgets/kpi-card.component.d.ts.map +1 -0
- package/dist/AI/components/widgets/kpi-card.component.js +163 -0
- package/dist/AI/components/widgets/kpi-card.component.js.map +1 -0
- package/dist/AI/components/widgets/live-execution-widget.component.d.ts +25 -0
- package/dist/AI/components/widgets/live-execution-widget.component.d.ts.map +1 -0
- package/dist/AI/components/widgets/live-execution-widget.component.js +298 -0
- package/dist/AI/components/widgets/live-execution-widget.component.js.map +1 -0
- package/dist/AI/index.d.ts +7 -0
- package/dist/AI/index.d.ts.map +1 -0
- package/dist/AI/index.js +9 -0
- package/dist/AI/index.js.map +1 -0
- package/dist/AI/services/ai-instrumentation.service.d.ts +109 -0
- package/dist/AI/services/ai-instrumentation.service.d.ts.map +1 -0
- package/dist/AI/services/ai-instrumentation.service.js +490 -0
- package/dist/AI/services/ai-instrumentation.service.js.map +1 -0
- package/dist/Actions/actions-management-dashboard.component.js +40 -41
- package/dist/Actions/actions-management-dashboard.component.js.map +1 -1
- package/dist/Actions/components/actions-list-view.component.js +117 -134
- package/dist/Actions/components/actions-list-view.component.js.map +1 -1
- package/dist/Actions/components/actions-overview.component.js +274 -296
- package/dist/Actions/components/actions-overview.component.js.map +1 -1
- package/dist/Actions/components/categories-list-view.component.js +12 -14
- package/dist/Actions/components/categories-list-view.component.js.map +1 -1
- package/dist/Actions/components/code-management.component.js +12 -14
- package/dist/Actions/components/code-management.component.js.map +1 -1
- package/dist/Actions/components/entity-integration.component.js +12 -14
- package/dist/Actions/components/entity-integration.component.js.map +1 -1
- package/dist/Actions/components/execution-monitoring.component.js +238 -256
- package/dist/Actions/components/execution-monitoring.component.js.map +1 -1
- package/dist/Actions/components/executions-list-view.component.js +12 -14
- package/dist/Actions/components/executions-list-view.component.js.map +1 -1
- package/dist/Actions/components/scheduled-actions.component.js +12 -14
- package/dist/Actions/components/scheduled-actions.component.js.map +1 -1
- package/dist/Actions/components/security-permissions.component.js +12 -14
- package/dist/Actions/components/security-permissions.component.js.map +1 -1
- package/dist/EntityAdmin/components/entity-details.component.js +105 -107
- package/dist/EntityAdmin/components/entity-details.component.js.map +1 -1
- package/dist/EntityAdmin/components/entity-filter-panel.component.js +100 -102
- package/dist/EntityAdmin/components/entity-filter-panel.component.js.map +1 -1
- package/dist/EntityAdmin/components/erd-composite.component.js +84 -100
- package/dist/EntityAdmin/components/erd-composite.component.js.map +1 -1
- package/dist/EntityAdmin/components/erd-diagram.component.js +50 -50
- package/dist/EntityAdmin/components/erd-diagram.component.js.map +1 -1
- package/dist/EntityAdmin/entity-admin-dashboard.component.js +45 -49
- package/dist/EntityAdmin/entity-admin-dashboard.component.js.map +1 -1
- package/dist/generic/base-dashboard.js +28 -40
- package/dist/generic/base-dashboard.js.map +1 -1
- package/dist/module.d.ts +16 -12
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +36 -15
- package/dist/module.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { Component, Output, EventEmitter } from '@angular/core';
|
|
11
2
|
import { RunView, Metadata, LogError, LogStatus } from '@memberjunction/core';
|
|
12
3
|
import { Subject, BehaviorSubject, combineLatest } from 'rxjs';
|
|
@@ -686,61 +677,62 @@ function PromptManagementComponent_Conditional_2_Template(rf, ctx) { if (rf & 1)
|
|
|
686
677
|
i0.ɵɵconditional(ctx_r1.isEditing ? 57 : -1);
|
|
687
678
|
} }
|
|
688
679
|
export class PromptManagementComponent {
|
|
680
|
+
mjNotificationsService;
|
|
681
|
+
openEntityRecord = new EventEmitter();
|
|
682
|
+
stateChange = new EventEmitter();
|
|
683
|
+
// Data properties
|
|
684
|
+
prompts = [];
|
|
685
|
+
categories = [];
|
|
686
|
+
types = [];
|
|
687
|
+
templates = [];
|
|
688
|
+
templateContents = [];
|
|
689
|
+
promptsWithTemplates = [];
|
|
690
|
+
filteredPrompts = [];
|
|
691
|
+
// UI state
|
|
692
|
+
isLoading = false;
|
|
693
|
+
loadingMessage = 'Loading prompts...';
|
|
694
|
+
error = null;
|
|
695
|
+
currentView = 'list';
|
|
696
|
+
currentSubView = 'list';
|
|
697
|
+
selectedPrompt = null;
|
|
698
|
+
isEditing = false;
|
|
699
|
+
isDirty = false;
|
|
700
|
+
// Editor state
|
|
701
|
+
editorContent = '';
|
|
702
|
+
editorMode = 'nunjucks';
|
|
703
|
+
showPreview = false;
|
|
704
|
+
supportedLanguages = languages;
|
|
705
|
+
editorLanguage = 'jinja2';
|
|
706
|
+
// Category creation
|
|
707
|
+
newCategoryName = '';
|
|
708
|
+
showNewCategoryInput = false;
|
|
709
|
+
// Splitter panel width
|
|
710
|
+
promptDetailsPanelWidth = 300;
|
|
711
|
+
// Filter panel visibility
|
|
712
|
+
filterPanelVisible = true;
|
|
713
|
+
// Current filters object for the filter panel
|
|
714
|
+
currentFilters = {
|
|
715
|
+
searchTerm: '',
|
|
716
|
+
categoryId: 'all',
|
|
717
|
+
typeId: 'all',
|
|
718
|
+
status: 'all'
|
|
719
|
+
};
|
|
720
|
+
// Filter state
|
|
721
|
+
searchTerm$ = new BehaviorSubject('');
|
|
722
|
+
selectedCategory$ = new BehaviorSubject('all');
|
|
723
|
+
selectedType$ = new BehaviorSubject('all');
|
|
724
|
+
selectedStatus$ = new BehaviorSubject('all');
|
|
725
|
+
categoryOptions = [];
|
|
726
|
+
typeOptions = [];
|
|
727
|
+
statusOptions = [
|
|
728
|
+
{ text: 'All Statuses', value: 'all' },
|
|
729
|
+
{ text: 'Active', value: 'Active' },
|
|
730
|
+
{ text: 'Pending', value: 'Pending' },
|
|
731
|
+
{ text: 'Disabled', value: 'Disabled' }
|
|
732
|
+
];
|
|
733
|
+
destroy$ = new Subject();
|
|
689
734
|
constructor(mjNotificationsService) {
|
|
690
735
|
this.mjNotificationsService = mjNotificationsService;
|
|
691
|
-
this.openEntityRecord = new EventEmitter();
|
|
692
|
-
this.stateChange = new EventEmitter();
|
|
693
|
-
// Data properties
|
|
694
|
-
this.prompts = [];
|
|
695
|
-
this.categories = [];
|
|
696
|
-
this.types = [];
|
|
697
|
-
this.templates = [];
|
|
698
|
-
this.templateContents = [];
|
|
699
|
-
this.promptsWithTemplates = [];
|
|
700
|
-
this.filteredPrompts = [];
|
|
701
|
-
// UI state
|
|
702
|
-
this.isLoading = false;
|
|
703
|
-
this.loadingMessage = 'Loading prompts...';
|
|
704
|
-
this.error = null;
|
|
705
|
-
this.currentView = 'list';
|
|
706
|
-
this.currentSubView = 'list';
|
|
707
|
-
this.selectedPrompt = null;
|
|
708
|
-
this.isEditing = false;
|
|
709
|
-
this.isDirty = false;
|
|
710
|
-
// Editor state
|
|
711
|
-
this.editorContent = '';
|
|
712
|
-
this.editorMode = 'nunjucks';
|
|
713
|
-
this.showPreview = false;
|
|
714
|
-
this.supportedLanguages = languages;
|
|
715
|
-
this.editorLanguage = 'jinja2';
|
|
716
|
-
// Category creation
|
|
717
|
-
this.newCategoryName = '';
|
|
718
|
-
this.showNewCategoryInput = false;
|
|
719
|
-
// Splitter panel width
|
|
720
|
-
this.promptDetailsPanelWidth = 300;
|
|
721
|
-
// Filter panel visibility
|
|
722
|
-
this.filterPanelVisible = true;
|
|
723
|
-
// Current filters object for the filter panel
|
|
724
|
-
this.currentFilters = {
|
|
725
|
-
searchTerm: '',
|
|
726
|
-
categoryId: 'all',
|
|
727
|
-
typeId: 'all',
|
|
728
|
-
status: 'all'
|
|
729
|
-
};
|
|
730
|
-
// Filter state
|
|
731
|
-
this.searchTerm$ = new BehaviorSubject('');
|
|
732
|
-
this.selectedCategory$ = new BehaviorSubject('all');
|
|
733
|
-
this.selectedType$ = new BehaviorSubject('all');
|
|
734
|
-
this.selectedStatus$ = new BehaviorSubject('all');
|
|
735
|
-
this.categoryOptions = [];
|
|
736
|
-
this.typeOptions = [];
|
|
737
|
-
this.statusOptions = [
|
|
738
|
-
{ text: 'All Statuses', value: 'all' },
|
|
739
|
-
{ text: 'Active', value: 'Active' },
|
|
740
|
-
{ text: 'Pending', value: 'Pending' },
|
|
741
|
-
{ text: 'Disabled', value: 'Disabled' }
|
|
742
|
-
];
|
|
743
|
-
this.destroy$ = new Subject();
|
|
744
736
|
}
|
|
745
737
|
toggleFilterPanel() {
|
|
746
738
|
this.filterPanelVisible = !this.filterPanelVisible;
|
|
@@ -751,7 +743,7 @@ export class PromptManagementComponent {
|
|
|
751
743
|
this.emitStateChange();
|
|
752
744
|
}
|
|
753
745
|
onFiltersChange(filters) {
|
|
754
|
-
this.currentFilters =
|
|
746
|
+
this.currentFilters = { ...filters };
|
|
755
747
|
// Update the BehaviorSubjects to match the filter panel
|
|
756
748
|
this.searchTerm$.next(filters.searchTerm);
|
|
757
749
|
this.selectedCategory$.next(filters.categoryId);
|
|
@@ -791,132 +783,120 @@ export class PromptManagementComponent {
|
|
|
791
783
|
this.applyFilters();
|
|
792
784
|
});
|
|
793
785
|
}
|
|
794
|
-
loadData() {
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
}
|
|
824
|
-
});
|
|
786
|
+
async loadData() {
|
|
787
|
+
try {
|
|
788
|
+
this.isLoading = true;
|
|
789
|
+
this.error = null;
|
|
790
|
+
this.loadingMessage = 'Loading prompts and templates...';
|
|
791
|
+
const [prompts, categories, types, templates, templateContents] = await Promise.all([
|
|
792
|
+
this.loadPrompts(),
|
|
793
|
+
this.loadCategories(),
|
|
794
|
+
this.loadTypes(),
|
|
795
|
+
this.loadTemplates(),
|
|
796
|
+
this.loadTemplateContents()
|
|
797
|
+
]);
|
|
798
|
+
this.prompts = prompts;
|
|
799
|
+
this.categories = categories;
|
|
800
|
+
this.types = types;
|
|
801
|
+
this.templates = templates;
|
|
802
|
+
this.templateContents = templateContents;
|
|
803
|
+
this.buildPromptTemplateRelationships();
|
|
804
|
+
this.buildFilterOptions();
|
|
805
|
+
this.applyFilters();
|
|
806
|
+
LogStatus('Prompt management data loaded successfully');
|
|
807
|
+
}
|
|
808
|
+
catch (error) {
|
|
809
|
+
this.error = 'Failed to load prompt data. Please try again.';
|
|
810
|
+
LogError('Error loading prompt management data', undefined, error);
|
|
811
|
+
}
|
|
812
|
+
finally {
|
|
813
|
+
this.isLoading = false;
|
|
814
|
+
}
|
|
825
815
|
}
|
|
826
|
-
loadPrompts() {
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
MaxRows: 1000
|
|
836
|
-
});
|
|
837
|
-
if (result && result.Success && result.Results) {
|
|
838
|
-
return result.Results;
|
|
839
|
-
}
|
|
840
|
-
else {
|
|
841
|
-
throw new Error('Failed to load AI prompts');
|
|
842
|
-
}
|
|
816
|
+
async loadPrompts() {
|
|
817
|
+
const rv = new RunView();
|
|
818
|
+
const result = await rv.RunView({
|
|
819
|
+
EntityName: 'AI Prompts',
|
|
820
|
+
ExtraFilter: '',
|
|
821
|
+
OrderBy: 'Name',
|
|
822
|
+
UserSearchString: '',
|
|
823
|
+
IgnoreMaxRows: false,
|
|
824
|
+
MaxRows: 1000
|
|
843
825
|
});
|
|
826
|
+
if (result && result.Success && result.Results) {
|
|
827
|
+
return result.Results;
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
throw new Error('Failed to load AI prompts');
|
|
831
|
+
}
|
|
844
832
|
}
|
|
845
|
-
loadCategories() {
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
MaxRows: 1000
|
|
855
|
-
});
|
|
856
|
-
if (result && result.Success && result.Results) {
|
|
857
|
-
return result.Results;
|
|
858
|
-
}
|
|
859
|
-
else {
|
|
860
|
-
throw new Error('Failed to load AI prompt categories');
|
|
861
|
-
}
|
|
833
|
+
async loadCategories() {
|
|
834
|
+
const rv = new RunView();
|
|
835
|
+
const result = await rv.RunView({
|
|
836
|
+
EntityName: 'AI Prompt Categories',
|
|
837
|
+
ExtraFilter: '',
|
|
838
|
+
OrderBy: 'Name',
|
|
839
|
+
UserSearchString: '',
|
|
840
|
+
IgnoreMaxRows: false,
|
|
841
|
+
MaxRows: 1000
|
|
862
842
|
});
|
|
843
|
+
if (result && result.Success && result.Results) {
|
|
844
|
+
return result.Results;
|
|
845
|
+
}
|
|
846
|
+
else {
|
|
847
|
+
throw new Error('Failed to load AI prompt categories');
|
|
848
|
+
}
|
|
863
849
|
}
|
|
864
|
-
loadTypes() {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
MaxRows: 1000
|
|
874
|
-
});
|
|
875
|
-
if (result && result.Success && result.Results) {
|
|
876
|
-
return result.Results;
|
|
877
|
-
}
|
|
878
|
-
else {
|
|
879
|
-
throw new Error('Failed to load AI prompt types');
|
|
880
|
-
}
|
|
850
|
+
async loadTypes() {
|
|
851
|
+
const rv = new RunView();
|
|
852
|
+
const result = await rv.RunView({
|
|
853
|
+
EntityName: 'AI Prompt Types',
|
|
854
|
+
ExtraFilter: '',
|
|
855
|
+
OrderBy: 'Name',
|
|
856
|
+
UserSearchString: '',
|
|
857
|
+
IgnoreMaxRows: false,
|
|
858
|
+
MaxRows: 1000
|
|
881
859
|
});
|
|
860
|
+
if (result && result.Success && result.Results) {
|
|
861
|
+
return result.Results;
|
|
862
|
+
}
|
|
863
|
+
else {
|
|
864
|
+
throw new Error('Failed to load AI prompt types');
|
|
865
|
+
}
|
|
882
866
|
}
|
|
883
|
-
loadTemplates() {
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
MaxRows: 1000
|
|
893
|
-
});
|
|
894
|
-
if (result && result.Success && result.Results) {
|
|
895
|
-
return result.Results;
|
|
896
|
-
}
|
|
897
|
-
else {
|
|
898
|
-
throw new Error('Failed to load templates');
|
|
899
|
-
}
|
|
867
|
+
async loadTemplates() {
|
|
868
|
+
const rv = new RunView();
|
|
869
|
+
const result = await rv.RunView({
|
|
870
|
+
EntityName: 'Templates',
|
|
871
|
+
ExtraFilter: '',
|
|
872
|
+
OrderBy: 'Name',
|
|
873
|
+
UserSearchString: '',
|
|
874
|
+
IgnoreMaxRows: false,
|
|
875
|
+
MaxRows: 1000
|
|
900
876
|
});
|
|
877
|
+
if (result && result.Success && result.Results) {
|
|
878
|
+
return result.Results;
|
|
879
|
+
}
|
|
880
|
+
else {
|
|
881
|
+
throw new Error('Failed to load templates');
|
|
882
|
+
}
|
|
901
883
|
}
|
|
902
|
-
loadTemplateContents() {
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
MaxRows: 1000
|
|
912
|
-
});
|
|
913
|
-
if (result && result.Success && result.Results) {
|
|
914
|
-
return result.Results;
|
|
915
|
-
}
|
|
916
|
-
else {
|
|
917
|
-
throw new Error('Failed to load template contents');
|
|
918
|
-
}
|
|
884
|
+
async loadTemplateContents() {
|
|
885
|
+
const rv = new RunView();
|
|
886
|
+
const result = await rv.RunView({
|
|
887
|
+
EntityName: 'Template Contents',
|
|
888
|
+
ExtraFilter: '',
|
|
889
|
+
OrderBy: 'TemplateID',
|
|
890
|
+
UserSearchString: '',
|
|
891
|
+
IgnoreMaxRows: false,
|
|
892
|
+
MaxRows: 1000
|
|
919
893
|
});
|
|
894
|
+
if (result && result.Success && result.Results) {
|
|
895
|
+
return result.Results;
|
|
896
|
+
}
|
|
897
|
+
else {
|
|
898
|
+
throw new Error('Failed to load template contents');
|
|
899
|
+
}
|
|
920
900
|
}
|
|
921
901
|
buildPromptTemplateRelationships() {
|
|
922
902
|
this.promptsWithTemplates = this.prompts.map(prompt => {
|
|
@@ -949,13 +929,10 @@ export class PromptManagementComponent {
|
|
|
949
929
|
// Apply search filter
|
|
950
930
|
const searchTerm = this.searchTerm$.value.toLowerCase();
|
|
951
931
|
if (searchTerm) {
|
|
952
|
-
filtered = filtered.filter(item =>
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
(((_a = item.category) === null || _a === void 0 ? void 0 : _a.Name) || '').toLowerCase().includes(searchTerm) ||
|
|
957
|
-
(((_b = item.template) === null || _b === void 0 ? void 0 : _b.Name) || '').toLowerCase().includes(searchTerm);
|
|
958
|
-
});
|
|
932
|
+
filtered = filtered.filter(item => item.prompt.Name.toLowerCase().includes(searchTerm) ||
|
|
933
|
+
(item.prompt.Description || '').toLowerCase().includes(searchTerm) ||
|
|
934
|
+
(item.category?.Name || '').toLowerCase().includes(searchTerm) ||
|
|
935
|
+
(item.template?.Name || '').toLowerCase().includes(searchTerm));
|
|
959
936
|
}
|
|
960
937
|
// Apply category filter
|
|
961
938
|
const categoryId = this.selectedCategory$.value;
|
|
@@ -989,64 +966,59 @@ export class PromptManagementComponent {
|
|
|
989
966
|
}
|
|
990
967
|
// Navigation methods
|
|
991
968
|
viewPrompt(promptWithTemplate) {
|
|
992
|
-
var _a;
|
|
993
969
|
this.selectedPrompt = promptWithTemplate;
|
|
994
970
|
this.currentView = 'editor';
|
|
995
971
|
this.isEditing = false;
|
|
996
972
|
this.isDirty = false;
|
|
997
|
-
this.editorContent =
|
|
973
|
+
this.editorContent = promptWithTemplate.templateContent?.TemplateText || '';
|
|
998
974
|
this.emitStateChange();
|
|
999
975
|
}
|
|
1000
976
|
editPrompt(promptWithTemplate) {
|
|
1001
|
-
var _a;
|
|
1002
977
|
this.selectedPrompt = promptWithTemplate;
|
|
1003
978
|
this.currentView = 'editor';
|
|
1004
979
|
this.isEditing = true;
|
|
1005
980
|
this.isDirty = false;
|
|
1006
|
-
this.editorContent =
|
|
981
|
+
this.editorContent = promptWithTemplate.templateContent?.TemplateText || '';
|
|
1007
982
|
this.emitStateChange();
|
|
1008
983
|
}
|
|
1009
|
-
createNewCategory() {
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
this.showNewCategoryInput = false;
|
|
1031
|
-
return category.ID;
|
|
1032
|
-
}
|
|
1033
|
-
else {
|
|
1034
|
-
// Handle save failure
|
|
1035
|
-
const errorMessage = ((_a = category.LatestResult) === null || _a === void 0 ? void 0 : _a.Message) || 'Unknown error occurred while saving category';
|
|
1036
|
-
console.error('Category save failed:', category.LatestResult);
|
|
1037
|
-
LogError('Category save failed', undefined, category.LatestResult);
|
|
1038
|
-
this.mjNotificationsService.CreateSimpleNotification(errorMessage, 'error', 3500);
|
|
1039
|
-
this.error = `Failed to create category: ${errorMessage}`;
|
|
1040
|
-
return null;
|
|
1041
|
-
}
|
|
984
|
+
async createNewCategory() {
|
|
985
|
+
if (!this.newCategoryName.trim())
|
|
986
|
+
return null;
|
|
987
|
+
try {
|
|
988
|
+
const md = new Metadata();
|
|
989
|
+
if (!md)
|
|
990
|
+
throw new Error('Metadata provider not available');
|
|
991
|
+
const category = await md.GetEntityObject('AI Prompt Categories', md.CurrentUser);
|
|
992
|
+
category.Name = this.newCategoryName.trim();
|
|
993
|
+
category.Description = 'Category created during prompt editing';
|
|
994
|
+
const result = await category.Save();
|
|
995
|
+
if (result) {
|
|
996
|
+
LogStatus('Category created successfully');
|
|
997
|
+
this.mjNotificationsService.CreateSimpleNotification('Category created successfully', 'success', 2000);
|
|
998
|
+
await this.loadCategories();
|
|
999
|
+
this.buildFilterOptions();
|
|
1000
|
+
// Update filter panel categories
|
|
1001
|
+
this.updateFilterPanelCategories();
|
|
1002
|
+
this.newCategoryName = '';
|
|
1003
|
+
this.showNewCategoryInput = false;
|
|
1004
|
+
return category.ID;
|
|
1042
1005
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1006
|
+
else {
|
|
1007
|
+
// Handle save failure
|
|
1008
|
+
const errorMessage = category.LatestResult?.Message || 'Unknown error occurred while saving category';
|
|
1009
|
+
console.error('Category save failed:', category.LatestResult);
|
|
1010
|
+
LogError('Category save failed', undefined, category.LatestResult);
|
|
1011
|
+
this.mjNotificationsService.CreateSimpleNotification(errorMessage, 'error', 3500);
|
|
1012
|
+
this.error = `Failed to create category: ${errorMessage}`;
|
|
1047
1013
|
return null;
|
|
1048
1014
|
}
|
|
1049
|
-
}
|
|
1015
|
+
}
|
|
1016
|
+
catch (error) {
|
|
1017
|
+
LogError('Error creating category', undefined, error);
|
|
1018
|
+
this.mjNotificationsService.CreateSimpleNotification('Failed to create category. Please try again.', 'error', 3500);
|
|
1019
|
+
this.error = 'Failed to create category. Please try again.';
|
|
1020
|
+
return null;
|
|
1021
|
+
}
|
|
1050
1022
|
}
|
|
1051
1023
|
updateFilterPanelCategories() {
|
|
1052
1024
|
// Trigger update of filter panel categories when new ones are created
|
|
@@ -1062,56 +1034,50 @@ export class PromptManagementComponent {
|
|
|
1062
1034
|
this.isDirty = true;
|
|
1063
1035
|
}
|
|
1064
1036
|
}
|
|
1065
|
-
onCreateNewCategoryKeyup(event) {
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
}
|
|
1074
|
-
});
|
|
1037
|
+
async onCreateNewCategoryKeyup(event) {
|
|
1038
|
+
if (event.key === 'Enter') {
|
|
1039
|
+
await this.createAndSelectNewCategory();
|
|
1040
|
+
}
|
|
1041
|
+
else if (event.key === 'Escape') {
|
|
1042
|
+
this.newCategoryName = '';
|
|
1043
|
+
this.showNewCategoryInput = false;
|
|
1044
|
+
}
|
|
1075
1045
|
}
|
|
1076
1046
|
cancelNewCategory() {
|
|
1077
1047
|
this.newCategoryName = '';
|
|
1078
1048
|
this.showNewCategoryInput = false;
|
|
1079
1049
|
}
|
|
1080
|
-
createAndSelectNewCategory() {
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
}
|
|
1087
|
-
});
|
|
1050
|
+
async createAndSelectNewCategory() {
|
|
1051
|
+
const newCategoryId = await this.createNewCategory();
|
|
1052
|
+
if (newCategoryId && this.selectedPrompt) {
|
|
1053
|
+
this.selectedPrompt.prompt.CategoryID = newCategoryId;
|
|
1054
|
+
this.isDirty = true;
|
|
1055
|
+
}
|
|
1088
1056
|
}
|
|
1089
|
-
createNewPrompt() {
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
this.editorContent = '';
|
|
1114
|
-
});
|
|
1057
|
+
async createNewPrompt() {
|
|
1058
|
+
// Create a new prompt structure
|
|
1059
|
+
const md = new Metadata();
|
|
1060
|
+
if (!md)
|
|
1061
|
+
return;
|
|
1062
|
+
const promptEntity = await md.GetEntityObject('AI Prompts', md.CurrentUser);
|
|
1063
|
+
promptEntity.Name = 'New Prompt';
|
|
1064
|
+
promptEntity.Description = '';
|
|
1065
|
+
promptEntity.CategoryID = '';
|
|
1066
|
+
promptEntity.TypeID = '';
|
|
1067
|
+
promptEntity.Status = 'Pending';
|
|
1068
|
+
promptEntity.TemplateID = '';
|
|
1069
|
+
const newPrompt = {
|
|
1070
|
+
prompt: promptEntity,
|
|
1071
|
+
template: null,
|
|
1072
|
+
templateContent: null,
|
|
1073
|
+
category: null,
|
|
1074
|
+
type: null
|
|
1075
|
+
};
|
|
1076
|
+
this.selectedPrompt = newPrompt;
|
|
1077
|
+
this.currentView = 'editor';
|
|
1078
|
+
this.isEditing = true;
|
|
1079
|
+
this.isDirty = false;
|
|
1080
|
+
this.editorContent = '';
|
|
1115
1081
|
}
|
|
1116
1082
|
backToList() {
|
|
1117
1083
|
if (this.isDirty) {
|
|
@@ -1154,11 +1120,10 @@ export class PromptManagementComponent {
|
|
|
1154
1120
|
}
|
|
1155
1121
|
}
|
|
1156
1122
|
emitStateChange() {
|
|
1157
|
-
var _a;
|
|
1158
1123
|
const state = {
|
|
1159
1124
|
currentView: this.currentView,
|
|
1160
1125
|
currentSubView: this.currentSubView,
|
|
1161
|
-
selectedPromptId:
|
|
1126
|
+
selectedPromptId: this.selectedPrompt?.prompt.ID || null,
|
|
1162
1127
|
isEditing: this.isEditing,
|
|
1163
1128
|
promptDetailsPanelWidth: this.promptDetailsPanelWidth,
|
|
1164
1129
|
filterPanelVisible: this.filterPanelVisible,
|
|
@@ -1169,160 +1134,154 @@ export class PromptManagementComponent {
|
|
|
1169
1134
|
};
|
|
1170
1135
|
this.stateChange.emit(state);
|
|
1171
1136
|
}
|
|
1172
|
-
savePrompt() {
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
templateContent.TemplateID = template.ID;
|
|
1204
|
-
this.selectedPrompt.template = template;
|
|
1205
|
-
}
|
|
1206
|
-
else {
|
|
1207
|
-
// we have an error saving the template
|
|
1208
|
-
const errorMessage = ((_b = template.LatestResult) === null || _b === void 0 ? void 0 : _b.Message) || 'Unknown error occurred while saving template';
|
|
1209
|
-
console.error('Template save failed:', errorMessage);
|
|
1210
|
-
LogError('Template save failed', undefined, errorMessage);
|
|
1211
|
-
this.mjNotificationsService.CreateSimpleNotification(errorMessage, 'error', 3500);
|
|
1212
|
-
this.error = `Failed to save template: ${errorMessage}`;
|
|
1213
|
-
return;
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
else {
|
|
1217
|
-
templateContent.TemplateID = this.selectedPrompt.template.ID;
|
|
1218
|
-
}
|
|
1219
|
-
if (yield templateContent.Save()) {
|
|
1220
|
-
templateContentId = templateContent.ID;
|
|
1221
|
-
this.selectedPrompt.templateContent = templateContent;
|
|
1137
|
+
async savePrompt() {
|
|
1138
|
+
if (!this.selectedPrompt || !this.isEditing)
|
|
1139
|
+
return;
|
|
1140
|
+
try {
|
|
1141
|
+
this.isLoading = true;
|
|
1142
|
+
const md = new Metadata();
|
|
1143
|
+
if (!md)
|
|
1144
|
+
throw new Error('Metadata provider not available');
|
|
1145
|
+
// Save or create template content first
|
|
1146
|
+
let templateContentId = this.selectedPrompt.templateContent?.ID;
|
|
1147
|
+
if (!templateContentId) {
|
|
1148
|
+
// Create new template content
|
|
1149
|
+
const templateContent = await md.GetEntityObject('Template Contents', md.CurrentUser);
|
|
1150
|
+
templateContent.TemplateText = this.editorContent;
|
|
1151
|
+
// make sure the template engine metadata is set correctly
|
|
1152
|
+
await TemplateEngineBase.Instance.Config(false);
|
|
1153
|
+
const tcType = TemplateEngineBase.Instance.TemplateContentTypes.find(tct => tct.Name.trim().toLowerCase() === 'text');
|
|
1154
|
+
if (!tcType) {
|
|
1155
|
+
throw new Error('Template content type "text" not found');
|
|
1156
|
+
}
|
|
1157
|
+
templateContent.TypeID = tcType.ID;
|
|
1158
|
+
templateContent.Priority = 0; // Default priority
|
|
1159
|
+
// We need to link to a template, create one if needed
|
|
1160
|
+
if (!this.selectedPrompt.template) {
|
|
1161
|
+
const template = await md.GetEntityObject('Templates', md.CurrentUser);
|
|
1162
|
+
template.Name = this.selectedPrompt.prompt.Name + ' Template';
|
|
1163
|
+
template.Description = 'Template for ' + this.selectedPrompt.prompt.Name;
|
|
1164
|
+
template.UserID = md.CurrentUser.ID;
|
|
1165
|
+
if (await template.Save()) {
|
|
1166
|
+
templateContent.TemplateID = template.ID;
|
|
1167
|
+
this.selectedPrompt.template = template;
|
|
1222
1168
|
}
|
|
1223
1169
|
else {
|
|
1224
|
-
//
|
|
1225
|
-
const errorMessage =
|
|
1226
|
-
console.error('Template
|
|
1227
|
-
LogError('Template
|
|
1170
|
+
// we have an error saving the template
|
|
1171
|
+
const errorMessage = template.LatestResult?.Message || 'Unknown error occurred while saving template';
|
|
1172
|
+
console.error('Template save failed:', errorMessage);
|
|
1173
|
+
LogError('Template save failed', undefined, errorMessage);
|
|
1228
1174
|
this.mjNotificationsService.CreateSimpleNotification(errorMessage, 'error', 3500);
|
|
1229
|
-
this.error = `Failed to save template
|
|
1175
|
+
this.error = `Failed to save template: ${errorMessage}`;
|
|
1230
1176
|
return;
|
|
1231
1177
|
}
|
|
1232
1178
|
}
|
|
1233
1179
|
else {
|
|
1234
|
-
|
|
1235
|
-
const templateContent = yield md.GetEntityObject('Template Contents');
|
|
1236
|
-
yield templateContent.Load(templateContentId);
|
|
1237
|
-
templateContent.TemplateText = this.editorContent;
|
|
1238
|
-
if (!(yield templateContent.Save())) {
|
|
1239
|
-
// Handle save failure
|
|
1240
|
-
const errorMessage = ((_d = templateContent.LatestResult) === null || _d === void 0 ? void 0 : _d.Message) || 'Unknown error occurred while saving template content';
|
|
1241
|
-
console.error('Template content update failed:', errorMessage);
|
|
1242
|
-
LogError('Template content update failed', undefined, errorMessage);
|
|
1243
|
-
this.mjNotificationsService.CreateSimpleNotification(errorMessage, 'error', 3500);
|
|
1244
|
-
this.error = `Failed to update template content: ${errorMessage}`;
|
|
1245
|
-
return;
|
|
1246
|
-
}
|
|
1180
|
+
templateContent.TemplateID = this.selectedPrompt.template.ID;
|
|
1247
1181
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
// Update existing prompt
|
|
1252
|
-
prompt = yield md.GetEntityObject('AI Prompts', md.CurrentUser);
|
|
1253
|
-
yield prompt.Load(this.selectedPrompt.prompt.ID);
|
|
1182
|
+
if (await templateContent.Save()) {
|
|
1183
|
+
templateContentId = templateContent.ID;
|
|
1184
|
+
this.selectedPrompt.templateContent = templateContent;
|
|
1254
1185
|
}
|
|
1255
1186
|
else {
|
|
1256
|
-
//
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
prompt.TypeID = this.selectedPrompt.prompt.TypeID;
|
|
1264
|
-
prompt.Status = this.selectedPrompt.prompt.Status;
|
|
1265
|
-
prompt.TemplateID = ((_e = this.selectedPrompt.template) === null || _e === void 0 ? void 0 : _e.ID) || '';
|
|
1266
|
-
const promptResult = yield prompt.Save();
|
|
1267
|
-
if (promptResult) {
|
|
1268
|
-
this.isDirty = false;
|
|
1269
|
-
this.isEditing = false;
|
|
1270
|
-
LogStatus('Prompt saved successfully');
|
|
1271
|
-
// Reload data to get the updated state
|
|
1272
|
-
yield this.loadData();
|
|
1273
|
-
// Find and select the updated prompt
|
|
1274
|
-
this.selectedPrompt = this.promptsWithTemplates.find(p => p.prompt.ID === prompt.ID) || null;
|
|
1187
|
+
// Handle save failure
|
|
1188
|
+
const errorMessage = templateContent.LatestResult?.Message || 'Unknown error occurred while saving template content';
|
|
1189
|
+
console.error('Template content save failed:', errorMessage);
|
|
1190
|
+
LogError('Template content save failed', undefined, errorMessage);
|
|
1191
|
+
this.mjNotificationsService.CreateSimpleNotification(errorMessage, 'error', 3500);
|
|
1192
|
+
this.error = `Failed to save template content: ${errorMessage}`;
|
|
1193
|
+
return;
|
|
1275
1194
|
}
|
|
1276
|
-
|
|
1195
|
+
}
|
|
1196
|
+
else {
|
|
1197
|
+
// Update existing template content
|
|
1198
|
+
const templateContent = await md.GetEntityObject('Template Contents');
|
|
1199
|
+
await templateContent.Load(templateContentId);
|
|
1200
|
+
templateContent.TemplateText = this.editorContent;
|
|
1201
|
+
if (!await templateContent.Save()) {
|
|
1277
1202
|
// Handle save failure
|
|
1278
|
-
const errorMessage =
|
|
1279
|
-
console.error('
|
|
1280
|
-
LogError('
|
|
1203
|
+
const errorMessage = templateContent.LatestResult?.Message || 'Unknown error occurred while saving template content';
|
|
1204
|
+
console.error('Template content update failed:', errorMessage);
|
|
1205
|
+
LogError('Template content update failed', undefined, errorMessage);
|
|
1281
1206
|
this.mjNotificationsService.CreateSimpleNotification(errorMessage, 'error', 3500);
|
|
1282
|
-
this.error = `Failed to
|
|
1207
|
+
this.error = `Failed to update template content: ${errorMessage}`;
|
|
1208
|
+
return;
|
|
1283
1209
|
}
|
|
1284
1210
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1211
|
+
// Save the prompt
|
|
1212
|
+
let prompt;
|
|
1213
|
+
if (this.selectedPrompt.prompt.ID) {
|
|
1214
|
+
// Update existing prompt
|
|
1215
|
+
prompt = await md.GetEntityObject('AI Prompts', md.CurrentUser);
|
|
1216
|
+
await prompt.Load(this.selectedPrompt.prompt.ID);
|
|
1288
1217
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1218
|
+
else {
|
|
1219
|
+
// Create new prompt
|
|
1220
|
+
prompt = await md.GetEntityObject('AI Prompts', md.CurrentUser);
|
|
1291
1221
|
}
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
const
|
|
1300
|
-
if (
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
yield prompt.Load(promptWithTemplate.prompt.ID);
|
|
1309
|
-
const result = yield prompt.Delete();
|
|
1310
|
-
if (result) {
|
|
1311
|
-
LogStatus('Prompt deleted successfully');
|
|
1312
|
-
yield this.loadData();
|
|
1313
|
-
if (((_a = this.selectedPrompt) === null || _a === void 0 ? void 0 : _a.prompt.ID) === promptWithTemplate.prompt.ID) {
|
|
1314
|
-
this.backToList();
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1222
|
+
// Update prompt properties
|
|
1223
|
+
prompt.Name = this.selectedPrompt.prompt.Name;
|
|
1224
|
+
prompt.Description = this.selectedPrompt.prompt.Description;
|
|
1225
|
+
prompt.CategoryID = this.selectedPrompt.prompt.CategoryID;
|
|
1226
|
+
prompt.TypeID = this.selectedPrompt.prompt.TypeID;
|
|
1227
|
+
prompt.Status = this.selectedPrompt.prompt.Status;
|
|
1228
|
+
prompt.TemplateID = this.selectedPrompt.template?.ID || '';
|
|
1229
|
+
const promptResult = await prompt.Save();
|
|
1230
|
+
if (promptResult) {
|
|
1231
|
+
this.isDirty = false;
|
|
1232
|
+
this.isEditing = false;
|
|
1233
|
+
LogStatus('Prompt saved successfully');
|
|
1234
|
+
// Reload data to get the updated state
|
|
1235
|
+
await this.loadData();
|
|
1236
|
+
// Find and select the updated prompt
|
|
1237
|
+
this.selectedPrompt = this.promptsWithTemplates.find(p => p.prompt.ID === prompt.ID) || null;
|
|
1317
1238
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1239
|
+
else {
|
|
1240
|
+
// Handle save failure
|
|
1241
|
+
const errorMessage = prompt.LatestResult?.Message || 'Unknown error occurred while saving prompt';
|
|
1242
|
+
console.error('Prompt save failed:', errorMessage);
|
|
1243
|
+
LogError('Prompt save failed', undefined, errorMessage);
|
|
1244
|
+
this.mjNotificationsService.CreateSimpleNotification(errorMessage, 'error', 3500);
|
|
1245
|
+
this.error = `Failed to save prompt: ${errorMessage}`;
|
|
1321
1246
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1247
|
+
}
|
|
1248
|
+
catch (error) {
|
|
1249
|
+
LogError('Error saving prompt', undefined, error);
|
|
1250
|
+
this.error = 'Failed to save prompt. Please try again.';
|
|
1251
|
+
}
|
|
1252
|
+
finally {
|
|
1253
|
+
this.isLoading = false;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
async deletePrompt(promptWithTemplate) {
|
|
1257
|
+
if (!promptWithTemplate.prompt.ID)
|
|
1258
|
+
return;
|
|
1259
|
+
const confirm = window.confirm(`Are you sure you want to delete "${promptWithTemplate.prompt.Name}"?`);
|
|
1260
|
+
if (!confirm)
|
|
1261
|
+
return;
|
|
1262
|
+
try {
|
|
1263
|
+
this.isLoading = true;
|
|
1264
|
+
const md = Metadata.Provider;
|
|
1265
|
+
if (!md)
|
|
1266
|
+
throw new Error('Metadata provider not available');
|
|
1267
|
+
const prompt = await md.GetEntityObject('AI Prompts', md.CurrentUser);
|
|
1268
|
+
await prompt.Load(promptWithTemplate.prompt.ID);
|
|
1269
|
+
const result = await prompt.Delete();
|
|
1270
|
+
if (result) {
|
|
1271
|
+
LogStatus('Prompt deleted successfully');
|
|
1272
|
+
await this.loadData();
|
|
1273
|
+
if (this.selectedPrompt?.prompt.ID === promptWithTemplate.prompt.ID) {
|
|
1274
|
+
this.backToList();
|
|
1275
|
+
}
|
|
1324
1276
|
}
|
|
1325
|
-
}
|
|
1277
|
+
}
|
|
1278
|
+
catch (error) {
|
|
1279
|
+
LogError('Error deleting prompt', undefined, error);
|
|
1280
|
+
this.error = 'Failed to delete prompt. Please try again.';
|
|
1281
|
+
}
|
|
1282
|
+
finally {
|
|
1283
|
+
this.isLoading = false;
|
|
1284
|
+
}
|
|
1326
1285
|
}
|
|
1327
1286
|
// Utility methods
|
|
1328
1287
|
getStatusColor(status) {
|
|
@@ -1337,16 +1296,14 @@ export class PromptManagementComponent {
|
|
|
1337
1296
|
return 'fa-solid fa-comment-dots';
|
|
1338
1297
|
}
|
|
1339
1298
|
getCategoryName(categoryId) {
|
|
1340
|
-
var _a;
|
|
1341
1299
|
if (!categoryId || categoryId === '')
|
|
1342
1300
|
return 'No Category';
|
|
1343
|
-
return
|
|
1301
|
+
return this.categories.find(c => c.ID === categoryId)?.Name || 'Unknown Category';
|
|
1344
1302
|
}
|
|
1345
1303
|
getTypeName(typeId) {
|
|
1346
|
-
var _a;
|
|
1347
1304
|
if (!typeId || typeId === '')
|
|
1348
1305
|
return 'No Type';
|
|
1349
|
-
return
|
|
1306
|
+
return this.types.find(t => t.ID === typeId)?.Name || 'Unknown Type';
|
|
1350
1307
|
}
|
|
1351
1308
|
setSubView(subView) {
|
|
1352
1309
|
this.currentSubView = subView;
|
|
@@ -1369,19 +1326,19 @@ export class PromptManagementComponent {
|
|
|
1369
1326
|
get promptsForMatrix() {
|
|
1370
1327
|
return this.filteredPrompts.map(p => p.prompt);
|
|
1371
1328
|
}
|
|
1329
|
+
static ɵfac = function PromptManagementComponent_Factory(t) { return new (t || PromptManagementComponent)(i0.ɵɵdirectiveInject(i1.MJNotificationService)); };
|
|
1330
|
+
static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PromptManagementComponent, selectors: [["app-prompt-management"]], outputs: { openEntityRecord: "openEntityRecord", stateChange: "stateChange" }, decls: 3, vars: 4, consts: [["newCategoryInput", ""], ["mjFillContainer", "", 1, "prompt-management-container", 3, "rightMargin", "bottomMargin"], [1, "list-view"], [1, "editor-view"], [1, "dashboard-header"], [1, "header-info"], ["type", "button", "title", "Toggle Filters", 1, "filter-toggle-btn", 3, "click"], [1, "fa-solid", "fa-filter"], [1, "prompt-count"], [1, "header-controls"], ["type", "button", 1, "control-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "sub-navigation"], ["type", "button", "title", "List View", 1, "sub-nav-btn", 3, "click"], [1, "fa-solid", "fa-list"], ["type", "button", "title", "Priority Matrix", 1, "sub-nav-btn", 3, "click"], [1, "fa-solid", "fa-th"], ["type", "button", "title", "Version Control", 1, "sub-nav-btn", 3, "click"], [1, "fa-solid", "fa-code-branch"], [1, "main-content"], ["orientation", "horizontal", "mjFillContainer", "", 1, "main-splitter"], ["mjFillContainer", "", 3, "selectedPrompts"], ["mjFillContainer", "", 3, "prompt"], ["orientation", "horizontal", "mjFillContainer", "", 1, "main-splitter", 3, "layoutChange"], [3, "size", "collapsible", "resizable", "scrollable", "hidden"], [3, "filtersChange", "filterChange", "resetFilters", "closePanel", "prompts", "filteredPrompts", "categories", "types", "filters"], [3, "resizable", "scrollable"], [1, "prompts-content"], [1, "loading-container"], [1, "error-container"], [1, "prompts-list"], [1, "loading-content"], [1, "loading-spinner"], [1, "spinner-ring"], [1, "loading-text"], [1, "error-message"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "empty-state"], [1, "prompts-grid"], [1, "fa-solid", "fa-comment-dots"], [1, "prompt-card"], [1, "prompt-card", 3, "click"], [1, "card-header"], [1, "prompt-info"], [1, "prompt-icon"], [1, "prompt-details"], [1, "prompt-name"], [1, "prompt-meta"], [1, "prompt-category"], [1, "prompt-type"], [1, "card-body"], [1, "prompt-description"], [1, "prompt-description", "text-muted"], [1, "template-info"], [1, "template-item", "text-muted"], [1, "card-actions", 3, "click"], ["type", "button", 1, "action-btn", 3, "click"], [1, "fa-solid", "fa-eye"], ["type", "button", 1, "action-btn", "action-btn-primary", 3, "click"], [1, "fa-solid", "fa-edit"], ["type", "button", 1, "action-btn", "action-btn-danger", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "template-item"], [1, "fa-solid", "fa-file-code"], [1, "template-content-info"], ["mjFillContainer", "", 3, "promptSelected", "selectedPrompts"], ["mjFillContainer", "", 3, "versionSelected", "prompt"], [1, "editor-header"], [1, "breadcrumb-section"], ["type", "button", 1, "back-btn", 3, "click"], [1, "fa-solid", "fa-arrow-left"], [1, "editor-title"], [3, "class"], [1, "editor-actions"], ["type", "button", 1, "control-btn"], [1, "editor-content"], ["orientation", "horizontal", "mjFillContainer", "", 1, "editor-splitter", 3, "layoutChange"], [3, "collapsible", "resizable", "scrollable"], [1, "prompt-details-panel"], [1, "form-field"], [1, "field-label"], ["type", "text", "placeholder", "Enter prompt name", 1, "field-input", 3, "ngModel"], [1, "field-value"], ["placeholder", "Enter prompt description", 1, "field-textarea", 3, "ngModel"], [1, "field-select", 3, "ngModel"], [1, "template-info-section"], [1, "template-editor-panel"], [1, "editor-info"], [1, "editor-badge", "editor-badge-secondary"], [1, "editor-container"], [3, "change", "value", "languages", "language", "placeholder", "lineWrapping", "highlightWhitespace", "indentWithTab", "indentUnit", "readonly"], [1, "editor-help"], [1, "fa-solid", "fa-times"], ["type", "button", 1, "control-btn", "control-btn-primary", 3, "click", "disabled"], [1, "loading-spinner-sm"], [1, "fa-solid", "fa-save"], ["type", "text", "placeholder", "Enter prompt name", 1, "field-input", 3, "ngModelChange", "input", "ngModel"], ["placeholder", "Enter prompt description", 1, "field-textarea", 3, "ngModelChange", "input", "ngModel"], [1, "new-category-container"], [1, "field-select", 3, "ngModelChange", "ngModel"], ["value", ""], [3, "value"], ["value", "new", 1, "new-category-option"], ["type", "text", "placeholder", "Enter new category name", 1, "field-input", 3, "ngModelChange", "keyup", "ngModel"], [1, "new-category-actions"], [1, "fa-solid", "fa-check"], [1, "field-select", 3, "ngModelChange", "change", "ngModel"], ["value", "Active"], ["value", "Pending"], ["value", "Disabled"], [1, "template-details"], [1, "editor-badge", "editor-badge-info"], [1, "editor-badge", "editor-badge-warning"], [1, "help-section"], [1, "syntax-examples"], [1, "syntax-item"]], template: function PromptManagementComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1331
|
+
i0.ɵɵelementStart(0, "div", 1);
|
|
1332
|
+
i0.ɵɵtemplate(1, PromptManagementComponent_Conditional_1_Template, 27, 11, "div", 2)(2, PromptManagementComponent_Conditional_2_Template, 58, 25, "div", 3);
|
|
1333
|
+
i0.ɵɵelementEnd();
|
|
1334
|
+
} if (rf & 2) {
|
|
1335
|
+
i0.ɵɵproperty("rightMargin", 8)("bottomMargin", 8);
|
|
1336
|
+
i0.ɵɵadvance();
|
|
1337
|
+
i0.ɵɵconditional(ctx.currentView === "list" ? 1 : -1);
|
|
1338
|
+
i0.ɵɵadvance();
|
|
1339
|
+
i0.ɵɵconditional(ctx.currentView === "editor" && ctx.selectedPrompt ? 2 : -1);
|
|
1340
|
+
} }, dependencies: [i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.SplitterComponent, i3.SplitterPaneComponent, i4.FillContainer, i5.CodeEditorComponent, i6.PromptFilterPanelComponent, i7.ModelPromptPriorityMatrixComponent, i8.PromptVersionControlComponent], styles: [".prompt-management-container[_ngcontent-%COMP%] {\n overflow: hidden;\n padding: 4px;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.dashboard-header[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n \n .header-info {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n \n .filter-toggle-btn {\n padding: 6px 10px;\n border: 1px solid #ddd;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: #555;\n \n &:hover {\n background-color: #f0f0f0;\n border-color: #2196f3;\n color: #2196f3;\n }\n \n .fa-solid {\n font-size: 10px;\n }\n }\n \n .prompt-count {\n font-size: 12px;\n color: #2196f3;\n font-weight: 600;\n background: rgba(33, 150, 243, 0.1);\n padding: 4px 8px;\n border-radius: 4px;\n border: 1px solid rgba(33, 150, 243, 0.2);\n }\n \n .header-controls {\n display: flex;\n gap: 8px;\n \n .control-btn {\n padding: 8px 12px;\n border: 1px solid #ccc;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n \n &:hover {\n background-color: #f0f0f0;\n border-color: #2196f3;\n }\n \n &.active {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n }\n \n &.control-btn-primary {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n }\n }\n \n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n \n &:hover {\n background-color: white;\n border-color: #ccc;\n }\n }\n \n .fa-solid {\n font-size: 14px;\n }\n }\n }\n}\n\n//[_ngcontent-%COMP%] Filters[_ngcontent-%COMP%] now[_ngcontent-%COMP%] handled[_ngcontent-%COMP%] by[_ngcontent-%COMP%] filter[_ngcontent-%COMP%] panel[_ngcontent-%COMP%] component\n\n.loading-container[_ngcontent-%COMP%], .error-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: #fafafa;\n flex: 1;\n \n p {\n color: #666;\n font-size: 14px;\n }\n}\n\n.error-message[_ngcontent-%COMP%] {\n color: #d32f2f;\n font-weight: 500;\n \n .fa-solid {\n margin-right: 8px;\n }\n}\n\n.loading-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n display: inline-block;\n position: relative;\n width: 40px;\n height: 40px;\n \n .spinner-ring {\n box-sizing: border-box;\n display: block;\n position: absolute;\n width: 32px;\n height: 32px;\n margin: 4px;\n border: 3px solid #2196f3;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_loading-spin 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n border-color: #2196f3 transparent transparent transparent;\n \n &:nth-child(1) { animation-delay: -0.45s; }\n &:nth-child(2) { animation-delay: -0.3s; }\n &:nth-child(3) { animation-delay: -0.15s; }\n }\n}\n\n@keyframes _ngcontent-%COMP%_loading-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px 20px;\n color: #666;\n \n .fa-solid {\n font-size: 48px;\n margin-bottom: 16px;\n color: #ccc;\n }\n \n h3 {\n margin: 0 0 8px 0;\n color: #333;\n font-size: 18px;\n font-weight: 500;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n }\n}\n\n.prompts-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));\n gap: 16px;\n flex: 1;\n overflow-y: auto;\n}\n\n.prompt-card[_ngcontent-%COMP%] {\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 16px;\n transition: all 0.2s ease;\n height: fit-content;\n cursor: pointer;\n \n &:hover {\n border-color: #2196f3;\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.1);\n transform: translateY(-1px);\n }\n \n .card-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 12px;\n \n .prompt-info {\n display: flex;\n gap: 12px;\n flex: 1;\n \n .prompt-icon {\n color: #2196f3;\n font-size: 20px;\n margin-top: 2px;\n }\n \n .prompt-details {\n flex: 1;\n \n .prompt-name {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 500;\n color: #333;\n }\n \n .prompt-meta {\n font-size: 12px;\n color: #666;\n \n .prompt-type {\n margin-left: 8px;\n }\n }\n }\n }\n }\n \n .card-body {\n margin-bottom: 12px;\n \n .prompt-description {\n margin-bottom: 12px;\n color: #555;\n font-size: 13px;\n line-height: 1.4;\n }\n \n .template-info {\n .template-item {\n display: flex;\n align-items: center;\n margin-bottom: 4px;\n font-size: 12px;\n color: #666;\n \n .fa-solid {\n margin-right: 6px;\n color: #999;\n }\n }\n \n .template-content-info {\n font-size: 11px;\n color: #999;\n }\n }\n }\n \n .card-actions {\n display: flex;\n gap: 8px;\n border-top: 1px solid #f0f0f0;\n padding-top: 12px;\n \n .action-btn {\n padding: 6px 12px;\n border: 1px solid #ddd;\n border-radius: 3px;\n background: white;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s;\n \n &:hover {\n background-color: #f5f5f5;\n border-color: #bbb;\n }\n \n &.action-btn-primary {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n }\n }\n \n &.action-btn-danger {\n background-color: #f44336;\n border-color: #f44336;\n color: white;\n \n &:hover {\n background-color: #d32f2f;\n }\n }\n \n .fa-solid {\n font-size: 10px;\n }\n }\n }\n}\n\n//[_ngcontent-%COMP%] Editor[_ngcontent-%COMP%] View\n.editor-view[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n}\n\n.editor-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 16px;\n border-bottom: 1px solid #e0e0e0;\n \n .breadcrumb-section {\n .back-btn {\n background: none;\n border: none;\n color: #2196f3;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n \n &:hover {\n text-decoration: underline;\n }\n }\n }\n \n .editor-title {\n flex: 1;\n margin: 0 20px;\n \n h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n }\n}\n\n.editor-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n}\n\n.editor-splitter[_ngcontent-%COMP%] {\n height: 100%;\n \n .k-pane {\n overflow: hidden;\n }\n}\n\n.prompt-details-panel[_ngcontent-%COMP%], .template-editor-panel[_ngcontent-%COMP%] {\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 16px;\n height: 100%;\n overflow-y: auto;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 500;\n color: #333;\n border-bottom: 1px solid #f0f0f0;\n padding-bottom: 8px;\n }\n}\n\n.form-field[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n \n .field-label {\n display: block;\n margin-bottom: 4px;\n font-size: 12px;\n font-weight: 500;\n color: #555;\n }\n \n .field-input, .field-select {\n width: 100%;\n padding: 6px 8px;\n border: 1px solid #ddd;\n border-radius: 3px;\n font-size: 12px;\n \n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n }\n \n .field-textarea {\n width: 100%;\n padding: 6px 8px;\n border: 1px solid #ddd;\n border-radius: 3px;\n font-size: 12px;\n resize: vertical;\n min-height: 60px;\n \n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n }\n \n .field-value {\n padding: 6px 8px;\n background: #f8f9fa;\n border: 1px solid #e0e0e0;\n border-radius: 3px;\n font-size: 12px;\n color: #555;\n }\n}\n\n.template-editor-panel[_ngcontent-%COMP%] {\n .editor-container {\n margin-bottom: 16px;\n \n .code-editor {\n width: 100%;\n min-height: 300px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 12px;\n border: 1px solid #ddd;\n border-radius: 3px;\n padding: 8px;\n background: #f8f9fa;\n \n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n }\n \n .code-display {\n border: 1px solid #e0e0e0;\n border-radius: 3px;\n background: #f8f9fa;\n max-height: 400px;\n overflow-y: auto;\n \n pre {\n margin: 0;\n padding: 12px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 12px;\n line-height: 1.4;\n color: #333;\n \n code {\n background: none;\n padding: 0;\n font-size: inherit;\n color: inherit;\n }\n }\n }\n }\n \n .editor-help {\n .help-section {\n h5 {\n font-size: 13px;\n font-weight: 500;\n margin-bottom: 8px;\n color: #333;\n }\n \n .syntax-examples {\n .syntax-item {\n margin-bottom: 6px;\n padding: 6px 8px;\n background: #f0f0f0;\n border-radius: 3px;\n font-size: 11px;\n \n code {\n background: #e0e0e0;\n padding: 2px 4px;\n border-radius: 2px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n margin-right: 8px;\n }\n }\n }\n }\n }\n}\n\n//[_ngcontent-%COMP%] CodeMirror[_ngcontent-%COMP%] overrides\n.CodeMirror[_ngcontent-%COMP%] {\n border: 1px solid #ddd !important;\n border-radius: 3px !important;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;\n font-size: 12px !important;\n min-height: 300px !important;\n}\n\n.CodeMirror-focused[_ngcontent-%COMP%] {\n border-color: #2196f3 !important;\n}\n\n//[_ngcontent-%COMP%] Status[_ngcontent-%COMP%] badges\n.status-badge[_ngcontent-%COMP%] {\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n text-transform: uppercase;\n \n &.status-active {\n background: #e8f5e8;\n color: #2e7d32;\n }\n \n &.status-pending {\n background: #fff3e0;\n color: #f57c00;\n }\n \n &.status-disabled {\n background: #ffebee;\n color: #c62828;\n }\n}\n\n//[_ngcontent-%COMP%] Editor[_ngcontent-%COMP%] badges\n.editor-badge[_ngcontent-%COMP%] {\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n margin-left: 8px;\n \n &.editor-badge-info {\n background: #e3f2fd;\n color: #1976d2;\n }\n \n &.editor-badge-warning {\n background: #fff3e0;\n color: #f57c00;\n }\n \n &.editor-badge-secondary {\n background: #f5f5f5;\n color: #666;\n }\n}\n\n//[_ngcontent-%COMP%] New[_ngcontent-%COMP%] category[_ngcontent-%COMP%] creation\n.new-category-container[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n align-items: center;\n \n .field-input {\n flex: 1;\n }\n \n .new-category-actions {\n display: flex;\n gap: 2px;\n \n .action-btn {\n padding: 4px 6px;\n border: 1px solid #ddd;\n border-radius: 3px;\n background: white;\n cursor: pointer;\n font-size: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 24px;\n \n &:hover {\n background-color: #f5f5f5;\n }\n \n &.action-btn-primary {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n }\n }\n \n .fa-solid {\n font-size: 10px;\n }\n }\n }\n}\n\n.new-category-option[_ngcontent-%COMP%] {\n color: #2196f3;\n font-style: italic;\n}\n\n//[_ngcontent-%COMP%] CodeMirror[_ngcontent-%COMP%] 6[_ngcontent-%COMP%] styling\nmj-code-editor[_ngcontent-%COMP%] {\n display: block;\n border: 1px solid #ddd;\n border-radius: 3px;\n overflow: hidden;\n min-height: 300px;\n \n .cm-editor {\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;\n font-size: 12px !important;\n min-height: 300px;\n }\n \n .cm-focused {\n outline: none !important;\n }\n \n .cm-editor.cm-focused {\n border-color: #2196f3;\n }\n}\n\n//[_ngcontent-%COMP%] List[_ngcontent-%COMP%] View[_ngcontent-%COMP%] Layout\n.list-view[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n}\n\n.sub-navigation[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n padding: 8px 0;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n\n .sub-nav-btn {\n padding: 8px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: #555;\n font-weight: 500;\n\n &:hover {\n background-color: #f0f0f0;\n border-color: #2196f3;\n color: #2196f3;\n }\n\n &.active {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n box-shadow: 0 2px 4px rgba(33, 150, 243, 0.2);\n }\n\n .fa-solid {\n font-size: 11px;\n }\n }\n}\n\n.main-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n}\n\n.main-splitter[_ngcontent-%COMP%] {\n height: 100%;\n \n .k-pane {\n overflow: hidden;\n }\n}\n\n.prompts-content[_ngcontent-%COMP%] {\n height: 100%;\n overflow-y: auto;\n padding: 0 16px;\n}"] });
|
|
1372
1341
|
}
|
|
1373
|
-
PromptManagementComponent.ɵfac = function PromptManagementComponent_Factory(t) { return new (t || PromptManagementComponent)(i0.ɵɵdirectiveInject(i1.MJNotificationService)); };
|
|
1374
|
-
PromptManagementComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: PromptManagementComponent, selectors: [["app-prompt-management"]], outputs: { openEntityRecord: "openEntityRecord", stateChange: "stateChange" }, decls: 3, vars: 4, consts: [["newCategoryInput", ""], ["mjFillContainer", "", 1, "prompt-management-container", 3, "rightMargin", "bottomMargin"], [1, "list-view"], [1, "editor-view"], [1, "dashboard-header"], [1, "header-info"], ["type", "button", "title", "Toggle Filters", 1, "filter-toggle-btn", 3, "click"], [1, "fa-solid", "fa-filter"], [1, "prompt-count"], [1, "header-controls"], ["type", "button", 1, "control-btn", 3, "click"], [1, "fa-solid", "fa-plus"], [1, "sub-navigation"], ["type", "button", "title", "List View", 1, "sub-nav-btn", 3, "click"], [1, "fa-solid", "fa-list"], ["type", "button", "title", "Priority Matrix", 1, "sub-nav-btn", 3, "click"], [1, "fa-solid", "fa-th"], ["type", "button", "title", "Version Control", 1, "sub-nav-btn", 3, "click"], [1, "fa-solid", "fa-code-branch"], [1, "main-content"], ["orientation", "horizontal", "mjFillContainer", "", 1, "main-splitter"], ["mjFillContainer", "", 3, "selectedPrompts"], ["mjFillContainer", "", 3, "prompt"], ["orientation", "horizontal", "mjFillContainer", "", 1, "main-splitter", 3, "layoutChange"], [3, "size", "collapsible", "resizable", "scrollable", "hidden"], [3, "filtersChange", "filterChange", "resetFilters", "closePanel", "prompts", "filteredPrompts", "categories", "types", "filters"], [3, "resizable", "scrollable"], [1, "prompts-content"], [1, "loading-container"], [1, "error-container"], [1, "prompts-list"], [1, "loading-content"], [1, "loading-spinner"], [1, "spinner-ring"], [1, "loading-text"], [1, "error-message"], [1, "fa-solid", "fa-exclamation-triangle"], [1, "empty-state"], [1, "prompts-grid"], [1, "fa-solid", "fa-comment-dots"], [1, "prompt-card"], [1, "prompt-card", 3, "click"], [1, "card-header"], [1, "prompt-info"], [1, "prompt-icon"], [1, "prompt-details"], [1, "prompt-name"], [1, "prompt-meta"], [1, "prompt-category"], [1, "prompt-type"], [1, "card-body"], [1, "prompt-description"], [1, "prompt-description", "text-muted"], [1, "template-info"], [1, "template-item", "text-muted"], [1, "card-actions", 3, "click"], ["type", "button", 1, "action-btn", 3, "click"], [1, "fa-solid", "fa-eye"], ["type", "button", 1, "action-btn", "action-btn-primary", 3, "click"], [1, "fa-solid", "fa-edit"], ["type", "button", 1, "action-btn", "action-btn-danger", 3, "click"], [1, "fa-solid", "fa-trash"], [1, "template-item"], [1, "fa-solid", "fa-file-code"], [1, "template-content-info"], ["mjFillContainer", "", 3, "promptSelected", "selectedPrompts"], ["mjFillContainer", "", 3, "versionSelected", "prompt"], [1, "editor-header"], [1, "breadcrumb-section"], ["type", "button", 1, "back-btn", 3, "click"], [1, "fa-solid", "fa-arrow-left"], [1, "editor-title"], [3, "class"], [1, "editor-actions"], ["type", "button", 1, "control-btn"], [1, "editor-content"], ["orientation", "horizontal", "mjFillContainer", "", 1, "editor-splitter", 3, "layoutChange"], [3, "collapsible", "resizable", "scrollable"], [1, "prompt-details-panel"], [1, "form-field"], [1, "field-label"], ["type", "text", "placeholder", "Enter prompt name", 1, "field-input", 3, "ngModel"], [1, "field-value"], ["placeholder", "Enter prompt description", 1, "field-textarea", 3, "ngModel"], [1, "field-select", 3, "ngModel"], [1, "template-info-section"], [1, "template-editor-panel"], [1, "editor-info"], [1, "editor-badge", "editor-badge-secondary"], [1, "editor-container"], [3, "change", "value", "languages", "language", "placeholder", "lineWrapping", "highlightWhitespace", "indentWithTab", "indentUnit", "readonly"], [1, "editor-help"], [1, "fa-solid", "fa-times"], ["type", "button", 1, "control-btn", "control-btn-primary", 3, "click", "disabled"], [1, "loading-spinner-sm"], [1, "fa-solid", "fa-save"], ["type", "text", "placeholder", "Enter prompt name", 1, "field-input", 3, "ngModelChange", "input", "ngModel"], ["placeholder", "Enter prompt description", 1, "field-textarea", 3, "ngModelChange", "input", "ngModel"], [1, "new-category-container"], [1, "field-select", 3, "ngModelChange", "ngModel"], ["value", ""], [3, "value"], ["value", "new", 1, "new-category-option"], ["type", "text", "placeholder", "Enter new category name", 1, "field-input", 3, "ngModelChange", "keyup", "ngModel"], [1, "new-category-actions"], [1, "fa-solid", "fa-check"], [1, "field-select", 3, "ngModelChange", "change", "ngModel"], ["value", "Active"], ["value", "Pending"], ["value", "Disabled"], [1, "template-details"], [1, "editor-badge", "editor-badge-info"], [1, "editor-badge", "editor-badge-warning"], [1, "help-section"], [1, "syntax-examples"], [1, "syntax-item"]], template: function PromptManagementComponent_Template(rf, ctx) { if (rf & 1) {
|
|
1375
|
-
i0.ɵɵelementStart(0, "div", 1);
|
|
1376
|
-
i0.ɵɵtemplate(1, PromptManagementComponent_Conditional_1_Template, 27, 11, "div", 2)(2, PromptManagementComponent_Conditional_2_Template, 58, 25, "div", 3);
|
|
1377
|
-
i0.ɵɵelementEnd();
|
|
1378
|
-
} if (rf & 2) {
|
|
1379
|
-
i0.ɵɵproperty("rightMargin", 8)("bottomMargin", 8);
|
|
1380
|
-
i0.ɵɵadvance();
|
|
1381
|
-
i0.ɵɵconditional(ctx.currentView === "list" ? 1 : -1);
|
|
1382
|
-
i0.ɵɵadvance();
|
|
1383
|
-
i0.ɵɵconditional(ctx.currentView === "editor" && ctx.selectedPrompt ? 2 : -1);
|
|
1384
|
-
} }, dependencies: [i2.NgSelectOption, i2.ɵNgSelectMultipleOption, i2.DefaultValueAccessor, i2.SelectControlValueAccessor, i2.NgControlStatus, i2.NgModel, i3.SplitterComponent, i3.SplitterPaneComponent, i4.FillContainer, i5.CodeEditorComponent, i6.PromptFilterPanelComponent, i7.ModelPromptPriorityMatrixComponent, i8.PromptVersionControlComponent], styles: [".prompt-management-container[_ngcontent-%COMP%] {\n overflow: hidden;\n padding: 4px;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.dashboard-header[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n \n .header-info {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n \n .filter-toggle-btn {\n padding: 6px 10px;\n border: 1px solid #ddd;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: #555;\n \n &:hover {\n background-color: #f0f0f0;\n border-color: #2196f3;\n color: #2196f3;\n }\n \n .fa-solid {\n font-size: 10px;\n }\n }\n \n .prompt-count {\n font-size: 12px;\n color: #2196f3;\n font-weight: 600;\n background: rgba(33, 150, 243, 0.1);\n padding: 4px 8px;\n border-radius: 4px;\n border: 1px solid rgba(33, 150, 243, 0.2);\n }\n \n .header-controls {\n display: flex;\n gap: 8px;\n \n .control-btn {\n padding: 8px 12px;\n border: 1px solid #ccc;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n \n &:hover {\n background-color: #f0f0f0;\n border-color: #2196f3;\n }\n \n &.active {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n }\n \n &.control-btn-primary {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n }\n }\n \n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n \n &:hover {\n background-color: white;\n border-color: #ccc;\n }\n }\n \n .fa-solid {\n font-size: 14px;\n }\n }\n }\n}\n\n//[_ngcontent-%COMP%] Filters[_ngcontent-%COMP%] now[_ngcontent-%COMP%] handled[_ngcontent-%COMP%] by[_ngcontent-%COMP%] filter[_ngcontent-%COMP%] panel[_ngcontent-%COMP%] component\n\n.loading-container[_ngcontent-%COMP%], .error-container[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: #fafafa;\n flex: 1;\n \n p {\n color: #666;\n font-size: 14px;\n }\n}\n\n.error-message[_ngcontent-%COMP%] {\n color: #d32f2f;\n font-weight: 500;\n \n .fa-solid {\n margin-right: 8px;\n }\n}\n\n.loading-content[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n}\n\n.loading-spinner[_ngcontent-%COMP%] {\n display: inline-block;\n position: relative;\n width: 40px;\n height: 40px;\n \n .spinner-ring {\n box-sizing: border-box;\n display: block;\n position: absolute;\n width: 32px;\n height: 32px;\n margin: 4px;\n border: 3px solid #2196f3;\n border-radius: 50%;\n animation: _ngcontent-%COMP%_loading-spin 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n border-color: #2196f3 transparent transparent transparent;\n \n &:nth-child(1) { animation-delay: -0.45s; }\n &:nth-child(2) { animation-delay: -0.3s; }\n &:nth-child(3) { animation-delay: -0.15s; }\n }\n}\n\n@keyframes _ngcontent-%COMP%_loading-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.empty-state[_ngcontent-%COMP%] {\n text-align: center;\n padding: 60px 20px;\n color: #666;\n \n .fa-solid {\n font-size: 48px;\n margin-bottom: 16px;\n color: #ccc;\n }\n \n h3 {\n margin: 0 0 8px 0;\n color: #333;\n font-size: 18px;\n font-weight: 500;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n }\n}\n\n.prompts-grid[_ngcontent-%COMP%] {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));\n gap: 16px;\n flex: 1;\n overflow-y: auto;\n}\n\n.prompt-card[_ngcontent-%COMP%] {\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 16px;\n transition: all 0.2s ease;\n height: fit-content;\n cursor: pointer;\n \n &:hover {\n border-color: #2196f3;\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.1);\n transform: translateY(-1px);\n }\n \n .card-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 12px;\n \n .prompt-info {\n display: flex;\n gap: 12px;\n flex: 1;\n \n .prompt-icon {\n color: #2196f3;\n font-size: 20px;\n margin-top: 2px;\n }\n \n .prompt-details {\n flex: 1;\n \n .prompt-name {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 500;\n color: #333;\n }\n \n .prompt-meta {\n font-size: 12px;\n color: #666;\n \n .prompt-type {\n margin-left: 8px;\n }\n }\n }\n }\n }\n \n .card-body {\n margin-bottom: 12px;\n \n .prompt-description {\n margin-bottom: 12px;\n color: #555;\n font-size: 13px;\n line-height: 1.4;\n }\n \n .template-info {\n .template-item {\n display: flex;\n align-items: center;\n margin-bottom: 4px;\n font-size: 12px;\n color: #666;\n \n .fa-solid {\n margin-right: 6px;\n color: #999;\n }\n }\n \n .template-content-info {\n font-size: 11px;\n color: #999;\n }\n }\n }\n \n .card-actions {\n display: flex;\n gap: 8px;\n border-top: 1px solid #f0f0f0;\n padding-top: 12px;\n \n .action-btn {\n padding: 6px 12px;\n border: 1px solid #ddd;\n border-radius: 3px;\n background: white;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s;\n \n &:hover {\n background-color: #f5f5f5;\n border-color: #bbb;\n }\n \n &.action-btn-primary {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n }\n }\n \n &.action-btn-danger {\n background-color: #f44336;\n border-color: #f44336;\n color: white;\n \n &:hover {\n background-color: #d32f2f;\n }\n }\n \n .fa-solid {\n font-size: 10px;\n }\n }\n }\n}\n\n//[_ngcontent-%COMP%] Editor[_ngcontent-%COMP%] View\n.editor-view[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n}\n\n.editor-header[_ngcontent-%COMP%] {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 16px;\n border-bottom: 1px solid #e0e0e0;\n \n .breadcrumb-section {\n .back-btn {\n background: none;\n border: none;\n color: #2196f3;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n \n &:hover {\n text-decoration: underline;\n }\n }\n }\n \n .editor-title {\n flex: 1;\n margin: 0 20px;\n \n h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n }\n}\n\n.editor-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n}\n\n.editor-splitter[_ngcontent-%COMP%] {\n height: 100%;\n \n .k-pane {\n overflow: hidden;\n }\n}\n\n.prompt-details-panel[_ngcontent-%COMP%], .template-editor-panel[_ngcontent-%COMP%] {\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 16px;\n height: 100%;\n overflow-y: auto;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 500;\n color: #333;\n border-bottom: 1px solid #f0f0f0;\n padding-bottom: 8px;\n }\n}\n\n.form-field[_ngcontent-%COMP%] {\n margin-bottom: 16px;\n \n .field-label {\n display: block;\n margin-bottom: 4px;\n font-size: 12px;\n font-weight: 500;\n color: #555;\n }\n \n .field-input, .field-select {\n width: 100%;\n padding: 6px 8px;\n border: 1px solid #ddd;\n border-radius: 3px;\n font-size: 12px;\n \n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n }\n \n .field-textarea {\n width: 100%;\n padding: 6px 8px;\n border: 1px solid #ddd;\n border-radius: 3px;\n font-size: 12px;\n resize: vertical;\n min-height: 60px;\n \n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n }\n \n .field-value {\n padding: 6px 8px;\n background: #f8f9fa;\n border: 1px solid #e0e0e0;\n border-radius: 3px;\n font-size: 12px;\n color: #555;\n }\n}\n\n.template-editor-panel[_ngcontent-%COMP%] {\n .editor-container {\n margin-bottom: 16px;\n \n .code-editor {\n width: 100%;\n min-height: 300px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 12px;\n border: 1px solid #ddd;\n border-radius: 3px;\n padding: 8px;\n background: #f8f9fa;\n \n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n }\n \n .code-display {\n border: 1px solid #e0e0e0;\n border-radius: 3px;\n background: #f8f9fa;\n max-height: 400px;\n overflow-y: auto;\n \n pre {\n margin: 0;\n padding: 12px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 12px;\n line-height: 1.4;\n color: #333;\n \n code {\n background: none;\n padding: 0;\n font-size: inherit;\n color: inherit;\n }\n }\n }\n }\n \n .editor-help {\n .help-section {\n h5 {\n font-size: 13px;\n font-weight: 500;\n margin-bottom: 8px;\n color: #333;\n }\n \n .syntax-examples {\n .syntax-item {\n margin-bottom: 6px;\n padding: 6px 8px;\n background: #f0f0f0;\n border-radius: 3px;\n font-size: 11px;\n \n code {\n background: #e0e0e0;\n padding: 2px 4px;\n border-radius: 2px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n margin-right: 8px;\n }\n }\n }\n }\n }\n}\n\n//[_ngcontent-%COMP%] CodeMirror[_ngcontent-%COMP%] overrides\n.CodeMirror[_ngcontent-%COMP%] {\n border: 1px solid #ddd !important;\n border-radius: 3px !important;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;\n font-size: 12px !important;\n min-height: 300px !important;\n}\n\n.CodeMirror-focused[_ngcontent-%COMP%] {\n border-color: #2196f3 !important;\n}\n\n//[_ngcontent-%COMP%] Status[_ngcontent-%COMP%] badges\n.status-badge[_ngcontent-%COMP%] {\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n text-transform: uppercase;\n \n &.status-active {\n background: #e8f5e8;\n color: #2e7d32;\n }\n \n &.status-pending {\n background: #fff3e0;\n color: #f57c00;\n }\n \n &.status-disabled {\n background: #ffebee;\n color: #c62828;\n }\n}\n\n//[_ngcontent-%COMP%] Editor[_ngcontent-%COMP%] badges\n.editor-badge[_ngcontent-%COMP%] {\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n margin-left: 8px;\n \n &.editor-badge-info {\n background: #e3f2fd;\n color: #1976d2;\n }\n \n &.editor-badge-warning {\n background: #fff3e0;\n color: #f57c00;\n }\n \n &.editor-badge-secondary {\n background: #f5f5f5;\n color: #666;\n }\n}\n\n//[_ngcontent-%COMP%] New[_ngcontent-%COMP%] category[_ngcontent-%COMP%] creation\n.new-category-container[_ngcontent-%COMP%] {\n display: flex;\n gap: 4px;\n align-items: center;\n \n .field-input {\n flex: 1;\n }\n \n .new-category-actions {\n display: flex;\n gap: 2px;\n \n .action-btn {\n padding: 4px 6px;\n border: 1px solid #ddd;\n border-radius: 3px;\n background: white;\n cursor: pointer;\n font-size: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 24px;\n \n &:hover {\n background-color: #f5f5f5;\n }\n \n &.action-btn-primary {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n }\n }\n \n .fa-solid {\n font-size: 10px;\n }\n }\n }\n}\n\n.new-category-option[_ngcontent-%COMP%] {\n color: #2196f3;\n font-style: italic;\n}\n\n//[_ngcontent-%COMP%] CodeMirror[_ngcontent-%COMP%] 6[_ngcontent-%COMP%] styling\nmj-code-editor[_ngcontent-%COMP%] {\n display: block;\n border: 1px solid #ddd;\n border-radius: 3px;\n overflow: hidden;\n min-height: 300px;\n \n .cm-editor {\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;\n font-size: 12px !important;\n min-height: 300px;\n }\n \n .cm-focused {\n outline: none !important;\n }\n \n .cm-editor.cm-focused {\n border-color: #2196f3;\n }\n}\n\n//[_ngcontent-%COMP%] List[_ngcontent-%COMP%] View[_ngcontent-%COMP%] Layout\n.list-view[_ngcontent-%COMP%] {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n}\n\n.sub-navigation[_ngcontent-%COMP%] {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n padding: 8px 0;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n\n .sub-nav-btn {\n padding: 8px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: #555;\n font-weight: 500;\n\n &:hover {\n background-color: #f0f0f0;\n border-color: #2196f3;\n color: #2196f3;\n }\n\n &.active {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n box-shadow: 0 2px 4px rgba(33, 150, 243, 0.2);\n }\n\n .fa-solid {\n font-size: 11px;\n }\n }\n}\n\n.main-content[_ngcontent-%COMP%] {\n flex: 1;\n overflow: hidden;\n}\n\n.main-splitter[_ngcontent-%COMP%] {\n height: 100%;\n \n .k-pane {\n overflow: hidden;\n }\n}\n\n.prompts-content[_ngcontent-%COMP%] {\n height: 100%;\n overflow-y: auto;\n padding: 0 16px;\n}"] });
|
|
1385
1342
|
(() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(PromptManagementComponent, [{
|
|
1386
1343
|
type: Component,
|
|
1387
1344
|
args: [{ selector: 'app-prompt-management', template: "<div class=\"prompt-management-container\" mjFillContainer [rightMargin]=\"8\" [bottomMargin]=\"8\">\n <!-- List View -->\n @if (currentView === 'list') {\n <div class=\"list-view\">\n <!-- Header -->\n <div class=\"dashboard-header\">\n <div class=\"header-info\">\n <button \n type=\"button\" \n class=\"filter-toggle-btn\"\n (click)=\"toggleFilterPanel()\"\n title=\"Toggle Filters\">\n <i class=\"fa-solid fa-filter\"></i>\n @if (filterPanelVisible) {\n Hide Filters\n } @else {\n Show Filters\n }\n </button>\n <span class=\"prompt-count\">{{ filteredPrompts.length }} prompts</span>\n </div>\n \n <div class=\"header-controls\">\n <button \n type=\"button\" \n class=\"control-btn\"\n (click)=\"createNewPrompt()\">\n <i class=\"fa-solid fa-plus\"></i>\n New Prompt\n </button>\n </div>\n </div>\n\n <!-- Sub Navigation -->\n <div class=\"sub-navigation\">\n <button \n type=\"button\" \n class=\"sub-nav-btn\"\n [class.active]=\"currentSubView === 'list'\"\n (click)=\"setSubView('list')\"\n title=\"List View\">\n <i class=\"fa-solid fa-list\"></i>\n List View\n </button>\n <button \n type=\"button\" \n class=\"sub-nav-btn\"\n [class.active]=\"currentSubView === 'priority-matrix'\"\n (click)=\"setSubView('priority-matrix')\"\n title=\"Priority Matrix\">\n <i class=\"fa-solid fa-th\"></i>\n Priority Matrix\n </button>\n <button \n type=\"button\" \n class=\"sub-nav-btn\"\n [class.active]=\"currentSubView === 'version-control'\"\n (click)=\"setSubView('version-control')\"\n title=\"Version Control\">\n <i class=\"fa-solid fa-code-branch\"></i>\n Version Control\n </button>\n </div>\n\n <!-- Main Content with Splitter -->\n <div class=\"main-content\">\n <!-- List View Content -->\n @if (currentSubView === 'list') {\n <kendo-splitter \n class=\"main-splitter\"\n orientation=\"horizontal\"\n (layoutChange)=\"onMainSplitterChange($event)\"\n mjFillContainer>\n \n <!-- Filter Panel (Left) -->\n <kendo-splitter-pane \n [size]=\"filterPanelVisible ? '320px' : '0px'\"\n [collapsible]=\"false\"\n [resizable]=\"filterPanelVisible\"\n [scrollable]=\"false\"\n [hidden]=\"!filterPanelVisible\">\n <mj-prompt-filter-panel\n [prompts]=\"promptsWithTemplates\"\n [filteredPrompts]=\"filteredPrompts\"\n [categories]=\"categories\"\n [types]=\"types\"\n [filters]=\"currentFilters\"\n (filtersChange)=\"onFiltersChange($event)\"\n (filterChange)=\"onFilterChange()\"\n (resetFilters)=\"onResetFilters()\"\n (closePanel)=\"toggleFilterPanel()\">\n </mj-prompt-filter-panel>\n </kendo-splitter-pane>\n \n <!-- Prompts List Panel -->\n <kendo-splitter-pane \n [resizable]=\"true\"\n [scrollable]=\"false\">\n <div class=\"prompts-content\">\n\n <!-- Loading State -->\n @if (isLoading) {\n <div class=\"loading-container\">\n <div class=\"loading-content\">\n <div class=\"loading-spinner\">\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n <div class=\"spinner-ring\"></div>\n </div>\n <div class=\"loading-text\">{{ loadingMessage }}</div>\n </div>\n </div>\n }\n\n <!-- Error State -->\n @if (error) {\n <div class=\"error-container\">\n <p class=\"error-message\">\n <i class=\"fa-solid fa-exclamation-triangle\"></i>\n {{ error }}\n </p>\n </div>\n }\n\n <!-- Prompts List -->\n @if (!isLoading && !error) {\n <div class=\"prompts-list\">\n @if (filteredPrompts.length === 0) {\n <div class=\"empty-state\">\n <i class=\"fa-solid fa-comment-dots\"></i>\n <h3>No prompts found</h3>\n <p>No prompts match your current filters. Try adjusting your search criteria or create a new prompt.</p>\n </div>\n } @else {\n <div class=\"prompts-grid\">\n @for (promptWithTemplate of filteredPrompts; track promptWithTemplate.prompt.ID || $index) {\n <div class=\"prompt-card\" (click)=\"viewPrompt(promptWithTemplate)\">\n <!-- Card Header -->\n <div class=\"card-header\">\n <div class=\"prompt-info\">\n <div class=\"prompt-icon\">\n <i [class]=\"getPromptIcon()\"></i>\n </div>\n <div class=\"prompt-details\">\n <h4 class=\"prompt-name\">{{ promptWithTemplate.prompt.Name }}</h4>\n <div class=\"prompt-meta\">\n <span class=\"prompt-category\">{{ getCategoryName(promptWithTemplate.prompt.CategoryID) }}</span>\n @if (promptWithTemplate.type) {\n <span class=\"prompt-type\">\u2022 {{ promptWithTemplate.type.Name }}</span>\n }\n </div>\n </div>\n </div>\n \n <div class=\"status-badge status-{{ promptWithTemplate.prompt.Status.toLowerCase() }}\">\n {{ promptWithTemplate.prompt.Status }}\n </div>\n </div>\n\n <!-- Card Body -->\n <div class=\"card-body\">\n @if (promptWithTemplate.prompt.Description) {\n <p class=\"prompt-description\">{{ promptWithTemplate.prompt.Description }}</p>\n } @else {\n <p class=\"prompt-description text-muted\">No description provided</p>\n }\n \n <!-- Template Info -->\n <div class=\"template-info\">\n @if (promptWithTemplate.template) {\n <div class=\"template-item\">\n <i class=\"fa-solid fa-file-code\"></i>\n <span>{{ promptWithTemplate.template.Name }}</span>\n </div>\n @if (promptWithTemplate.templateContent) {\n <div class=\"template-content-info\">\n <small>\n Template content: {{ (promptWithTemplate.templateContent.TemplateText || '').length }} characters\n </small>\n </div>\n }\n } @else {\n <div class=\"template-item text-muted\">\n <i class=\"fa-solid fa-file-code\"></i>\n <span>No template assigned</span>\n </div>\n }\n </div>\n </div>\n\n <!-- Card Actions -->\n <div class=\"card-actions\" (click)=\"$event.stopPropagation()\">\n <button \n type=\"button\" \n class=\"action-btn\"\n (click)=\"viewPrompt(promptWithTemplate)\">\n <i class=\"fa-solid fa-eye\"></i>\n View\n </button>\n \n <button \n type=\"button\" \n class=\"action-btn action-btn-primary\"\n (click)=\"editPrompt(promptWithTemplate)\">\n <i class=\"fa-solid fa-edit\"></i>\n Edit\n </button>\n \n <button \n type=\"button\" \n class=\"action-btn action-btn-danger\"\n (click)=\"deletePrompt(promptWithTemplate)\">\n <i class=\"fa-solid fa-trash\"></i>\n Delete\n </button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n }\n\n\n <!-- Priority Matrix View -->\n @if (currentSubView === 'priority-matrix') {\n <app-model-prompt-priority-matrix\n [selectedPrompts]=\"promptsForMatrix\"\n (promptSelected)=\"onPromptSelectedFromMatrix($event)\"\n mjFillContainer>\n </app-model-prompt-priority-matrix>\n }\n\n <!-- Version Control View -->\n @if (currentSubView === 'version-control') {\n <app-prompt-version-control\n [prompt]=\"selectedPrompt?.prompt || null\"\n (versionSelected)=\"onVersionSelected($event)\"\n mjFillContainer>\n </app-prompt-version-control>\n }\n </div>\n </div>\n }\n\n <!-- Editor View -->\n @if (currentView === 'editor' && selectedPrompt) {\n <div class=\"editor-view\">\n <!-- Editor Header -->\n <div class=\"editor-header\">\n <div class=\"breadcrumb-section\">\n <button \n type=\"button\" \n class=\"back-btn\"\n (click)=\"backToList()\">\n <i class=\"fa-solid fa-arrow-left\"></i>\n Back to Prompts\n </button>\n </div>\n \n <div class=\"editor-title\">\n <h2>\n @if (isEditing && !selectedPrompt.prompt.ID) {\n <i class=\"fa-solid fa-plus\"></i>\n Create New Prompt\n } @else if (isEditing) {\n <i class=\"fa-solid fa-edit\"></i>\n Edit Prompt\n } @else {\n <i class=\"fa-solid fa-eye\"></i>\n View Prompt\n }\n </h2>\n \n @if (selectedPrompt.prompt.ID) {\n <div class=\"status-badge status-{{ selectedPrompt.prompt.Status.toLowerCase() }}\">\n {{ selectedPrompt.prompt.Status }}\n </div>\n }\n </div>\n \n <div class=\"editor-actions\">\n @if (!isEditing) {\n <button \n type=\"button\" \n class=\"control-btn\"\n (click)=\"toggleEdit()\">\n <i class=\"fa-solid fa-edit\"></i>\n Edit\n </button>\n } @else {\n <button \n type=\"button\" \n class=\"control-btn\"\n (click)=\"toggleEdit()\">\n <i class=\"fa-solid fa-times\"></i>\n Cancel\n </button>\n \n <button \n type=\"button\" \n class=\"control-btn control-btn-primary\"\n (click)=\"savePrompt()\"\n [disabled]=\"isLoading\">\n @if (isLoading) {\n <span class=\"loading-spinner-sm\"></span>\n } @else {\n <i class=\"fa-solid fa-save\"></i>\n }\n Save\n </button>\n }\n </div>\n </div>\n\n <!-- Editor Content -->\n <div class=\"editor-content\">\n <kendo-splitter \n class=\"editor-splitter\"\n orientation=\"horizontal\"\n (layoutChange)=\"onEditorSplitterChange($event)\"\n mjFillContainer>\n \n <!-- Prompt Details Panel -->\n <kendo-splitter-pane \n [collapsible]=\"false\"\n [resizable]=\"true\"\n [scrollable]=\"true\">\n <div class=\"prompt-details-panel\">\n <h3>Prompt Details</h3>\n \n <!-- Name -->\n <div class=\"form-field\">\n <label class=\"field-label\">Name *</label>\n @if (isEditing) {\n <input \n type=\"text\" \n class=\"field-input\"\n [(ngModel)]=\"selectedPrompt.prompt.Name\"\n placeholder=\"Enter prompt name\"\n (input)=\"isDirty = true\">\n } @else {\n <div class=\"field-value\">{{ selectedPrompt.prompt.Name }}</div>\n }\n </div>\n \n <!-- Description -->\n <div class=\"form-field\">\n <label class=\"field-label\">Description</label>\n @if (isEditing) {\n <textarea \n class=\"field-textarea\"\n [(ngModel)]=\"selectedPrompt.prompt.Description\"\n placeholder=\"Enter prompt description\"\n (input)=\"isDirty = true\"></textarea>\n } @else {\n <div class=\"field-value\">\n {{ selectedPrompt.prompt.Description || 'No description provided' }}\n </div>\n }\n </div>\n \n <!-- Category -->\n <div class=\"form-field\">\n <label class=\"field-label\">Category</label>\n @if (isEditing) {\n @if (!showNewCategoryInput) {\n <select \n class=\"field-select\"\n [(ngModel)]=\"selectedPrompt.prompt.CategoryID\"\n (ngModelChange)=\"onCategoryChange($event)\">\n <option value=\"\">Select category...</option>\n @for (category of categories; track category.ID) {\n <option [value]=\"category.ID\">{{ category.Name }}</option>\n }\n <option value=\"new\" class=\"new-category-option\">+ Create New Category</option>\n </select>\n } @else {\n <div class=\"new-category-container\">\n <input \n type=\"text\" \n class=\"field-input\"\n [(ngModel)]=\"newCategoryName\"\n placeholder=\"Enter new category name\"\n (keyup)=\"onCreateNewCategoryKeyup($event)\"\n #newCategoryInput>\n <div class=\"new-category-actions\">\n <button \n type=\"button\" \n class=\"action-btn action-btn-primary\"\n (click)=\"createAndSelectNewCategory()\">\n <i class=\"fa-solid fa-check\"></i>\n </button>\n <button \n type=\"button\" \n class=\"action-btn\"\n (click)=\"cancelNewCategory()\">\n <i class=\"fa-solid fa-times\"></i>\n </button>\n </div>\n </div>\n }\n } @else {\n <div class=\"field-value\">\n {{ getCategoryName(selectedPrompt.prompt.CategoryID) }}\n </div>\n }\n </div>\n \n <!-- Type -->\n <div class=\"form-field\">\n <label class=\"field-label\">Type</label>\n @if (isEditing) {\n <select \n class=\"field-select\"\n [(ngModel)]=\"selectedPrompt.prompt.TypeID\"\n (change)=\"isDirty = true\">\n <option value=\"\">Select type...</option>\n @for (type of types; track type.ID) {\n <option [value]=\"type.ID\">{{ type.Name }}</option>\n }\n </select>\n } @else {\n <div class=\"field-value\">\n {{ getTypeName(selectedPrompt.prompt.TypeID) }}\n </div>\n }\n </div>\n \n <!-- Status -->\n <div class=\"form-field\">\n <label class=\"field-label\">Status</label>\n @if (isEditing) {\n <select \n class=\"field-select\"\n [(ngModel)]=\"selectedPrompt.prompt.Status\"\n (change)=\"isDirty = true\">\n <option value=\"Active\">Active</option>\n <option value=\"Pending\">Pending</option>\n <option value=\"Disabled\">Disabled</option>\n </select>\n } @else {\n <div class=\"field-value\">\n <span class=\"status-badge status-{{ selectedPrompt.prompt.Status.toLowerCase() }}\">\n {{ selectedPrompt.prompt.Status }}\n </span>\n </div>\n }\n </div>\n \n <!-- Template Info -->\n @if (selectedPrompt.template) {\n <div class=\"template-info-section\">\n <h4>Template Information</h4>\n <div class=\"template-details\">\n <div><strong>Template:</strong> {{ selectedPrompt.template.Name }}</div>\n @if (selectedPrompt.template.Description) {\n <div><strong>Description:</strong> {{ selectedPrompt.template.Description }}</div>\n }\n @if (selectedPrompt.templateContent) {\n <div><strong>Content Length:</strong> {{ (selectedPrompt.templateContent.TemplateText || '').length }} characters</div>\n }\n </div>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n \n <!-- Template Editor Panel -->\n <kendo-splitter-pane \n [resizable]=\"true\"\n [scrollable]=\"true\">\n <div class=\"template-editor-panel\">\n <div class=\"editor-header\">\n <h3>Template Content</h3>\n <div class=\"editor-info\">\n @if (isEditing) {\n <span class=\"editor-badge editor-badge-info\">Nunjucks Template</span>\n @if (isDirty) {\n <span class=\"editor-badge editor-badge-warning\">Unsaved Changes</span>\n }\n } @else {\n <span class=\"editor-badge editor-badge-secondary\">Read Only</span>\n }\n </div>\n </div>\n \n <div class=\"editor-container\">\n <mj-code-editor\n [value]=\"editorContent\"\n [languages]=\"supportedLanguages\"\n [language]=\"editorLanguage\"\n [placeholder]=\"'Enter your Nunjucks template here...'\"\n [lineWrapping]=\"true\"\n [highlightWhitespace]=\"false\"\n [indentWithTab]=\"true\"\n [indentUnit]=\"' '\"\n [readonly]=\"!isEditing\"\n (change)=\"onEditorContentChange($event)\">\n </mj-code-editor>\n </div>\n \n <!-- Editor Help -->\n @if (isEditing) {\n <div class=\"editor-help\">\n <div class=\"help-section\">\n <h5>Nunjucks Template Syntax</h5>\n <div class=\"syntax-examples\">\n <div class=\"syntax-item\">\n <code>{{ \"{{ variable }}\" }}</code> - Variable output\n </div>\n <div class=\"syntax-item\">\n <code>{{ \"{% if condition %} ... {% endif %}\" }}</code> - Conditionals\n </div>\n <div class=\"syntax-item\">\n <code>{{ \"{% for item in items %} ... {% endfor %}\" }}</code> - Loops\n </div>\n </div>\n </div>\n </div>\n }\n </div>\n </kendo-splitter-pane>\n </kendo-splitter>\n </div>\n </div>\n }\n</div>", styles: [".prompt-management-container {\n overflow: hidden;\n padding: 4px;\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n\n.dashboard-header {\n margin-bottom: 16px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n flex-shrink: 0;\n \n .header-info {\n flex: 1;\n display: flex;\n align-items: center;\n gap: 12px;\n }\n \n .filter-toggle-btn {\n padding: 6px 10px;\n border: 1px solid #ddd;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: #555;\n \n &:hover {\n background-color: #f0f0f0;\n border-color: #2196f3;\n color: #2196f3;\n }\n \n .fa-solid {\n font-size: 10px;\n }\n }\n \n .prompt-count {\n font-size: 12px;\n color: #2196f3;\n font-weight: 600;\n background: rgba(33, 150, 243, 0.1);\n padding: 4px 8px;\n border-radius: 4px;\n border: 1px solid rgba(33, 150, 243, 0.2);\n }\n \n .header-controls {\n display: flex;\n gap: 8px;\n \n .control-btn {\n padding: 8px 12px;\n border: 1px solid #ccc;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n \n &:hover {\n background-color: #f0f0f0;\n border-color: #2196f3;\n }\n \n &.active {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n }\n \n &.control-btn-primary {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n }\n }\n \n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n \n &:hover {\n background-color: white;\n border-color: #ccc;\n }\n }\n \n .fa-solid {\n font-size: 14px;\n }\n }\n }\n}\n\n// Filters now handled by filter panel component\n\n.loading-container, .error-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background: #fafafa;\n flex: 1;\n \n p {\n color: #666;\n font-size: 14px;\n }\n}\n\n.error-message {\n color: #d32f2f;\n font-weight: 500;\n \n .fa-solid {\n margin-right: 8px;\n }\n}\n\n.loading-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 16px;\n}\n\n.loading-spinner {\n display: inline-block;\n position: relative;\n width: 40px;\n height: 40px;\n \n .spinner-ring {\n box-sizing: border-box;\n display: block;\n position: absolute;\n width: 32px;\n height: 32px;\n margin: 4px;\n border: 3px solid #2196f3;\n border-radius: 50%;\n animation: loading-spin 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;\n border-color: #2196f3 transparent transparent transparent;\n \n &:nth-child(1) { animation-delay: -0.45s; }\n &:nth-child(2) { animation-delay: -0.3s; }\n &:nth-child(3) { animation-delay: -0.15s; }\n }\n}\n\n@keyframes loading-spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.empty-state {\n text-align: center;\n padding: 60px 20px;\n color: #666;\n \n .fa-solid {\n font-size: 48px;\n margin-bottom: 16px;\n color: #ccc;\n }\n \n h3 {\n margin: 0 0 8px 0;\n color: #333;\n font-size: 18px;\n font-weight: 500;\n }\n \n p {\n margin: 0;\n font-size: 14px;\n }\n}\n\n.prompts-grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));\n gap: 16px;\n flex: 1;\n overflow-y: auto;\n}\n\n.prompt-card {\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 16px;\n transition: all 0.2s ease;\n height: fit-content;\n cursor: pointer;\n \n &:hover {\n border-color: #2196f3;\n box-shadow: 0 2px 8px rgba(33, 150, 243, 0.1);\n transform: translateY(-1px);\n }\n \n .card-header {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n margin-bottom: 12px;\n \n .prompt-info {\n display: flex;\n gap: 12px;\n flex: 1;\n \n .prompt-icon {\n color: #2196f3;\n font-size: 20px;\n margin-top: 2px;\n }\n \n .prompt-details {\n flex: 1;\n \n .prompt-name {\n margin: 0 0 4px 0;\n font-size: 16px;\n font-weight: 500;\n color: #333;\n }\n \n .prompt-meta {\n font-size: 12px;\n color: #666;\n \n .prompt-type {\n margin-left: 8px;\n }\n }\n }\n }\n }\n \n .card-body {\n margin-bottom: 12px;\n \n .prompt-description {\n margin-bottom: 12px;\n color: #555;\n font-size: 13px;\n line-height: 1.4;\n }\n \n .template-info {\n .template-item {\n display: flex;\n align-items: center;\n margin-bottom: 4px;\n font-size: 12px;\n color: #666;\n \n .fa-solid {\n margin-right: 6px;\n color: #999;\n }\n }\n \n .template-content-info {\n font-size: 11px;\n color: #999;\n }\n }\n }\n \n .card-actions {\n display: flex;\n gap: 8px;\n border-top: 1px solid #f0f0f0;\n padding-top: 12px;\n \n .action-btn {\n padding: 6px 12px;\n border: 1px solid #ddd;\n border-radius: 3px;\n background: white;\n cursor: pointer;\n font-size: 11px;\n display: flex;\n align-items: center;\n gap: 4px;\n transition: all 0.2s;\n \n &:hover {\n background-color: #f5f5f5;\n border-color: #bbb;\n }\n \n &.action-btn-primary {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n }\n }\n \n &.action-btn-danger {\n background-color: #f44336;\n border-color: #f44336;\n color: white;\n \n &:hover {\n background-color: #d32f2f;\n }\n }\n \n .fa-solid {\n font-size: 10px;\n }\n }\n }\n}\n\n// Editor View\n.editor-view {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n}\n\n.editor-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 16px;\n padding-bottom: 16px;\n border-bottom: 1px solid #e0e0e0;\n \n .breadcrumb-section {\n .back-btn {\n background: none;\n border: none;\n color: #2196f3;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n \n &:hover {\n text-decoration: underline;\n }\n }\n }\n \n .editor-title {\n flex: 1;\n margin: 0 20px;\n \n h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 500;\n color: #333;\n display: flex;\n align-items: center;\n gap: 8px;\n }\n }\n \n .editor-actions {\n display: flex;\n gap: 8px;\n }\n}\n\n.editor-content {\n flex: 1;\n overflow: hidden;\n}\n\n.editor-splitter {\n height: 100%;\n \n .k-pane {\n overflow: hidden;\n }\n}\n\n.prompt-details-panel, .template-editor-panel {\n background: white;\n border: 1px solid #e0e0e0;\n border-radius: 4px;\n padding: 16px;\n height: 100%;\n overflow-y: auto;\n \n h3 {\n margin: 0 0 16px 0;\n font-size: 16px;\n font-weight: 500;\n color: #333;\n border-bottom: 1px solid #f0f0f0;\n padding-bottom: 8px;\n }\n}\n\n.form-field {\n margin-bottom: 16px;\n \n .field-label {\n display: block;\n margin-bottom: 4px;\n font-size: 12px;\n font-weight: 500;\n color: #555;\n }\n \n .field-input, .field-select {\n width: 100%;\n padding: 6px 8px;\n border: 1px solid #ddd;\n border-radius: 3px;\n font-size: 12px;\n \n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n }\n \n .field-textarea {\n width: 100%;\n padding: 6px 8px;\n border: 1px solid #ddd;\n border-radius: 3px;\n font-size: 12px;\n resize: vertical;\n min-height: 60px;\n \n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n }\n \n .field-value {\n padding: 6px 8px;\n background: #f8f9fa;\n border: 1px solid #e0e0e0;\n border-radius: 3px;\n font-size: 12px;\n color: #555;\n }\n}\n\n.template-editor-panel {\n .editor-container {\n margin-bottom: 16px;\n \n .code-editor {\n width: 100%;\n min-height: 300px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 12px;\n border: 1px solid #ddd;\n border-radius: 3px;\n padding: 8px;\n background: #f8f9fa;\n \n &:focus {\n outline: none;\n border-color: #2196f3;\n }\n }\n \n .code-display {\n border: 1px solid #e0e0e0;\n border-radius: 3px;\n background: #f8f9fa;\n max-height: 400px;\n overflow-y: auto;\n \n pre {\n margin: 0;\n padding: 12px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n font-size: 12px;\n line-height: 1.4;\n color: #333;\n \n code {\n background: none;\n padding: 0;\n font-size: inherit;\n color: inherit;\n }\n }\n }\n }\n \n .editor-help {\n .help-section {\n h5 {\n font-size: 13px;\n font-weight: 500;\n margin-bottom: 8px;\n color: #333;\n }\n \n .syntax-examples {\n .syntax-item {\n margin-bottom: 6px;\n padding: 6px 8px;\n background: #f0f0f0;\n border-radius: 3px;\n font-size: 11px;\n \n code {\n background: #e0e0e0;\n padding: 2px 4px;\n border-radius: 2px;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n margin-right: 8px;\n }\n }\n }\n }\n }\n}\n\n// CodeMirror overrides\n.CodeMirror {\n border: 1px solid #ddd !important;\n border-radius: 3px !important;\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;\n font-size: 12px !important;\n min-height: 300px !important;\n}\n\n.CodeMirror-focused {\n border-color: #2196f3 !important;\n}\n\n// Status badges\n.status-badge {\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n text-transform: uppercase;\n \n &.status-active {\n background: #e8f5e8;\n color: #2e7d32;\n }\n \n &.status-pending {\n background: #fff3e0;\n color: #f57c00;\n }\n \n &.status-disabled {\n background: #ffebee;\n color: #c62828;\n }\n}\n\n// Editor badges\n.editor-badge {\n padding: 2px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n margin-left: 8px;\n \n &.editor-badge-info {\n background: #e3f2fd;\n color: #1976d2;\n }\n \n &.editor-badge-warning {\n background: #fff3e0;\n color: #f57c00;\n }\n \n &.editor-badge-secondary {\n background: #f5f5f5;\n color: #666;\n }\n}\n\n// New category creation\n.new-category-container {\n display: flex;\n gap: 4px;\n align-items: center;\n \n .field-input {\n flex: 1;\n }\n \n .new-category-actions {\n display: flex;\n gap: 2px;\n \n .action-btn {\n padding: 4px 6px;\n border: 1px solid #ddd;\n border-radius: 3px;\n background: white;\n cursor: pointer;\n font-size: 10px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 24px;\n \n &:hover {\n background-color: #f5f5f5;\n }\n \n &.action-btn-primary {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n \n &:hover {\n background-color: #1976d2;\n }\n }\n \n .fa-solid {\n font-size: 10px;\n }\n }\n }\n}\n\n.new-category-option {\n color: #2196f3;\n font-style: italic;\n}\n\n// CodeMirror 6 styling\nmj-code-editor {\n display: block;\n border: 1px solid #ddd;\n border-radius: 3px;\n overflow: hidden;\n min-height: 300px;\n \n .cm-editor {\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;\n font-size: 12px !important;\n min-height: 300px;\n }\n \n .cm-focused {\n outline: none !important;\n }\n \n .cm-editor.cm-focused {\n border-color: #2196f3;\n }\n}\n\n// List View Layout\n.list-view {\n display: flex;\n flex-direction: column;\n flex: 1;\n overflow: hidden;\n}\n\n.sub-navigation {\n display: flex;\n gap: 8px;\n margin-bottom: 16px;\n padding: 8px 0;\n border-bottom: 1px solid #e0e0e0;\n flex-shrink: 0;\n\n .sub-nav-btn {\n padding: 8px 12px;\n border: 1px solid #ddd;\n border-radius: 4px;\n background: white;\n cursor: pointer;\n font-size: 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n transition: all 0.2s;\n color: #555;\n font-weight: 500;\n\n &:hover {\n background-color: #f0f0f0;\n border-color: #2196f3;\n color: #2196f3;\n }\n\n &.active {\n background-color: #2196f3;\n border-color: #2196f3;\n color: white;\n box-shadow: 0 2px 4px rgba(33, 150, 243, 0.2);\n }\n\n .fa-solid {\n font-size: 11px;\n }\n }\n}\n\n.main-content {\n flex: 1;\n overflow: hidden;\n}\n\n.main-splitter {\n height: 100%;\n \n .k-pane {\n overflow: hidden;\n }\n}\n\n.prompts-content {\n height: 100%;\n overflow-y: auto;\n padding: 0 16px;\n}"] }]
|