@snteam/amplify-angular-core 1.0.42 → 1.0.43

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.
@@ -5156,6 +5156,7 @@ class ConfigurationsComponent {
5156
5156
  hasFormView = false;
5157
5157
  hasListView = false;
5158
5158
  hasFieldConfig = false;
5159
+ hasRelationshipConfig = false;
5159
5160
  // Relationship configuration management
5160
5161
  relationshipConfigs = [];
5161
5162
  showAddRelationshipConfig = false;
@@ -5190,11 +5191,13 @@ class ConfigurationsComponent {
5190
5191
  this.hasFormView = 'FormView' in models;
5191
5192
  this.hasListView = 'ListView' in models;
5192
5193
  this.hasFieldConfig = 'FieldConfig' in models;
5194
+ this.hasRelationshipConfig = 'RelationshipConfig' in models;
5193
5195
  console.log('ConfigurationsComponent: Model availability:', {
5194
5196
  TableConfig: this.hasTableConfig,
5195
5197
  FormView: this.hasFormView,
5196
5198
  ListView: this.hasListView,
5197
- FieldConfig: this.hasFieldConfig
5199
+ FieldConfig: this.hasFieldConfig,
5200
+ RelationshipConfig: this.hasRelationshipConfig
5198
5201
  });
5199
5202
  }
5200
5203
  async populateDefaultFieldConfigs() {
@@ -5507,7 +5510,41 @@ return fields;
5507
5510
  console.log('ConfigurationsComponent: Available relationship fields for', modelName, ':', this.availableFields);
5508
5511
  }
5509
5512
  loadRelationshipConfigs() {
5510
- // Load from localStorage for now (could be extended to use Amplify model later)
5513
+ if (!this.hasRelationshipConfig) {
5514
+ console.warn('ConfigurationsComponent: RelationshipConfig model not available, falling back to localStorage');
5515
+ this.loadRelationshipConfigsFromLocalStorage();
5516
+ return;
5517
+ }
5518
+ // Load from Amplify RelationshipConfig model
5519
+ const observable = this.ams.listItemsForModel('RelationshipConfig');
5520
+ if (!observable) {
5521
+ console.error('ConfigurationsComponent: Failed to get RelationshipConfig observable');
5522
+ this.loadRelationshipConfigsFromLocalStorage();
5523
+ return;
5524
+ }
5525
+ observable.subscribe({
5526
+ next: ({ items }) => {
5527
+ this.relationshipConfigs = items
5528
+ .filter((item) => item.isActive !== false)
5529
+ .map((item) => ({
5530
+ id: item.id,
5531
+ relationshipModel: item.relationshipModel,
5532
+ fieldName: item.fieldName,
5533
+ selectionSet: item.selectionSet || [],
5534
+ description: item.description
5535
+ }));
5536
+ console.log('ConfigurationsComponent: Loaded relationship configs from Amplify:', this.relationshipConfigs);
5537
+ // Update the AmplifyModelService with loaded configurations
5538
+ this.updateAmplifyModelService();
5539
+ },
5540
+ error: (error) => {
5541
+ console.error('ConfigurationsComponent: Error loading relationship configs from Amplify:', error);
5542
+ this.loadRelationshipConfigsFromLocalStorage();
5543
+ }
5544
+ });
5545
+ }
5546
+ loadRelationshipConfigsFromLocalStorage() {
5547
+ // Fallback to localStorage for backward compatibility
5511
5548
  const stored = localStorage.getItem('snteam-relationship-configs');
5512
5549
  if (stored) {
5513
5550
  try {
@@ -5516,10 +5553,10 @@ return fields;
5516
5553
  ...rel,
5517
5554
  id: rel.id || this.generateId()
5518
5555
  }));
5519
- console.log('ConfigurationsComponent: Loaded relationship configs:', this.relationshipConfigs);
5556
+ console.log('ConfigurationsComponent: Loaded relationship configs from localStorage:', this.relationshipConfigs);
5520
5557
  }
5521
5558
  catch (error) {
5522
- console.error('ConfigurationsComponent: Error loading relationship configs:', error);
5559
+ console.error('ConfigurationsComponent: Error loading relationship configs from localStorage:', error);
5523
5560
  this.relationshipConfigs = [];
5524
5561
  }
5525
5562
  }
@@ -5528,6 +5565,7 @@ return fields;
5528
5565
  }
5529
5566
  }
5530
5567
  saveRelationshipConfigsToStorage() {
5568
+ // Always update localStorage for backward compatibility
5531
5569
  const config = {
5532
5570
  relationships: this.relationshipConfigs.map(({ id, ...config }) => config),
5533
5571
  defaultSelectionSet: ['id'],
@@ -5535,10 +5573,19 @@ return fields;
5535
5573
  };
5536
5574
  localStorage.setItem('snteam-relationship-configs', JSON.stringify(config));
5537
5575
  // Update the AmplifyModelService with the new configuration
5538
- this.ams.setRelationshipConfig(config);
5576
+ this.updateAmplifyModelService();
5539
5577
  console.log('ConfigurationsComponent: Saved relationship configs to storage and updated service');
5540
5578
  }
5541
- saveRelationshipConfig() {
5579
+ updateAmplifyModelService() {
5580
+ const config = {
5581
+ relationships: this.relationshipConfigs.map(({ id, ...config }) => config),
5582
+ defaultSelectionSet: ['id'],
5583
+ enableFallback: true
5584
+ };
5585
+ this.ams.setRelationshipConfig(config);
5586
+ console.log('ConfigurationsComponent: Updated AmplifyModelService with relationship configs');
5587
+ }
5588
+ async saveRelationshipConfig() {
5542
5589
  if (!this.relationshipConfigForm.valid) {
5543
5590
  this.snackBar.open('Please fill in all required fields', 'Dismiss', { duration: 3000 });
5544
5591
  return;
@@ -5549,35 +5596,98 @@ return fields;
5549
5596
  .split('\n')
5550
5597
  .map((line) => line.trim())
5551
5598
  .filter((line) => line.length > 0);
5552
- const config = {
5553
- relationshipModel: formValue.relationshipModel,
5554
- fieldName: formValue.fieldName,
5555
- selectionSet: selectionSet,
5556
- description: formValue.description || undefined,
5557
- id: this.editingRelationshipConfig?.id || this.generateId()
5558
- };
5559
- if (this.editingRelationshipConfig) {
5560
- // Update existing configuration
5561
- const index = this.relationshipConfigs.findIndex(c => c.id === this.editingRelationshipConfig.id);
5562
- if (index >= 0) {
5563
- this.relationshipConfigs[index] = config;
5599
+ try {
5600
+ if (this.editingRelationshipConfig) {
5601
+ // Update existing configuration
5602
+ await this.updateRelationshipConfig(this.editingRelationshipConfig.id, {
5603
+ relationshipModel: formValue.relationshipModel,
5604
+ fieldName: formValue.fieldName,
5605
+ selectionSet: selectionSet,
5606
+ description: formValue.description || undefined
5607
+ });
5564
5608
  this.snackBar.open('Relationship configuration updated successfully', 'Dismiss', { duration: 3000 });
5565
5609
  }
5610
+ else {
5611
+ // Check for duplicate configuration
5612
+ const existing = this.relationshipConfigs.find(c => c.relationshipModel === formValue.relationshipModel &&
5613
+ c.fieldName === formValue.fieldName);
5614
+ if (existing) {
5615
+ this.snackBar.open('Configuration for this relationship already exists', 'Dismiss', { duration: 3000 });
5616
+ return;
5617
+ }
5618
+ // Create new configuration
5619
+ await this.createRelationshipConfig({
5620
+ relationshipModel: formValue.relationshipModel,
5621
+ fieldName: formValue.fieldName,
5622
+ selectionSet: selectionSet,
5623
+ description: formValue.description || undefined
5624
+ });
5625
+ this.snackBar.open('Relationship configuration added successfully', 'Dismiss', { duration: 3000 });
5626
+ }
5627
+ this.cancelRelationshipConfigEdit();
5628
+ }
5629
+ catch (error) {
5630
+ console.error('ConfigurationsComponent: Error saving relationship config:', error);
5631
+ this.snackBar.open('Error saving configuration: ' + error, 'Dismiss', { duration: 5000 });
5632
+ }
5633
+ }
5634
+ async createRelationshipConfig(config) {
5635
+ if (!this.hasRelationshipConfig) {
5636
+ // Fallback to localStorage if model not available
5637
+ const newConfig = {
5638
+ ...config,
5639
+ id: this.generateId()
5640
+ };
5641
+ this.relationshipConfigs.push(newConfig);
5642
+ this.saveRelationshipConfigsToStorage();
5643
+ return;
5644
+ }
5645
+ const amplifyConfig = {
5646
+ relationshipModel: config.relationshipModel,
5647
+ fieldName: config.fieldName,
5648
+ selectionSet: config.selectionSet,
5649
+ description: config.description,
5650
+ isActive: true,
5651
+ createdAt: new Date().toISOString(),
5652
+ updatedAt: new Date().toISOString()
5653
+ };
5654
+ const result = await this.ams.createItemPromise('RelationshipConfig', amplifyConfig);
5655
+ if (result && result.data) {
5656
+ console.log('ConfigurationsComponent: Created RelationshipConfig in Amplify:', result.data);
5657
+ // Reload configurations to get the updated list
5658
+ this.loadRelationshipConfigs();
5566
5659
  }
5567
5660
  else {
5568
- // Check for duplicate configuration
5569
- const existing = this.relationshipConfigs.find(c => c.relationshipModel === config.relationshipModel &&
5570
- c.fieldName === config.fieldName);
5571
- if (existing) {
5572
- this.snackBar.open('Configuration for this relationship already exists', 'Dismiss', { duration: 3000 });
5573
- return;
5661
+ throw new Error('Failed to create RelationshipConfig in Amplify');
5662
+ }
5663
+ }
5664
+ async updateRelationshipConfig(id, config) {
5665
+ if (!this.hasRelationshipConfig) {
5666
+ // Fallback to localStorage if model not available
5667
+ const index = this.relationshipConfigs.findIndex(c => c.id === id);
5668
+ if (index >= 0) {
5669
+ this.relationshipConfigs[index] = { ...config, id };
5670
+ this.saveRelationshipConfigsToStorage();
5574
5671
  }
5575
- // Add new configuration
5576
- this.relationshipConfigs.push(config);
5577
- this.snackBar.open('Relationship configuration added successfully', 'Dismiss', { duration: 3000 });
5672
+ return;
5673
+ }
5674
+ const amplifyConfig = {
5675
+ id: id,
5676
+ relationshipModel: config.relationshipModel,
5677
+ fieldName: config.fieldName,
5678
+ selectionSet: config.selectionSet,
5679
+ description: config.description,
5680
+ updatedAt: new Date().toISOString()
5681
+ };
5682
+ const result = await this.ams.updateItemForModel('RelationshipConfig', amplifyConfig);
5683
+ if (result && result.data) {
5684
+ console.log('ConfigurationsComponent: Updated RelationshipConfig in Amplify:', result.data);
5685
+ // Reload configurations to get the updated list
5686
+ this.loadRelationshipConfigs();
5687
+ }
5688
+ else {
5689
+ throw new Error('Failed to update RelationshipConfig in Amplify');
5578
5690
  }
5579
- this.saveRelationshipConfigsToStorage();
5580
- this.cancelRelationshipConfigEdit();
5581
5691
  }
5582
5692
  editRelationshipConfig(config) {
5583
5693
  this.editingRelationshipConfig = config;
@@ -5592,12 +5702,32 @@ return fields;
5592
5702
  description: config.description || ''
5593
5703
  });
5594
5704
  }
5595
- deleteRelationshipConfig(config) {
5596
- const index = this.relationshipConfigs.findIndex(c => c.id === config.id);
5597
- if (index >= 0) {
5598
- this.relationshipConfigs.splice(index, 1);
5599
- this.saveRelationshipConfigsToStorage();
5600
- this.snackBar.open('Relationship configuration deleted', 'Dismiss', { duration: 3000 });
5705
+ async deleteRelationshipConfig(config) {
5706
+ try {
5707
+ if (!this.hasRelationshipConfig) {
5708
+ // Fallback to localStorage if model not available
5709
+ const index = this.relationshipConfigs.findIndex(c => c.id === config.id);
5710
+ if (index >= 0) {
5711
+ this.relationshipConfigs.splice(index, 1);
5712
+ this.saveRelationshipConfigsToStorage();
5713
+ this.snackBar.open('Relationship configuration deleted', 'Dismiss', { duration: 3000 });
5714
+ }
5715
+ return;
5716
+ }
5717
+ const result = await this.ams.deleteItemForModel('RelationshipConfig', config.id);
5718
+ if (result && result.data) {
5719
+ console.log('ConfigurationsComponent: Deleted RelationshipConfig from Amplify:', result.data);
5720
+ // Reload configurations to get the updated list
5721
+ this.loadRelationshipConfigs();
5722
+ this.snackBar.open('Relationship configuration deleted', 'Dismiss', { duration: 3000 });
5723
+ }
5724
+ else {
5725
+ throw new Error('Failed to delete RelationshipConfig from Amplify');
5726
+ }
5727
+ }
5728
+ catch (error) {
5729
+ console.error('ConfigurationsComponent: Error deleting relationship config:', error);
5730
+ this.snackBar.open('Error deleting configuration: ' + error, 'Dismiss', { duration: 5000 });
5601
5731
  }
5602
5732
  }
5603
5733
  generateId() {
@@ -5609,11 +5739,10 @@ return fields;
5609
5739
  this.relationshipConfigForm.reset();
5610
5740
  this.availableFields = [];
5611
5741
  }
5612
- loadDefaultRelationshipConfigs() {
5742
+ async loadDefaultRelationshipConfigs() {
5613
5743
  // Load some sensible default configurations
5614
5744
  const defaultConfigs = [
5615
5745
  {
5616
- id: this.generateId(),
5617
5746
  relationshipModel: 'ListView',
5618
5747
  fieldName: 'table',
5619
5748
  selectionSet: [
@@ -5627,7 +5756,6 @@ return fields;
5627
5756
  description: 'Configuration for ListView -> Table relationship'
5628
5757
  },
5629
5758
  {
5630
- id: this.generateId(),
5631
5759
  relationshipModel: 'FormViewField',
5632
5760
  fieldName: 'formView',
5633
5761
  selectionSet: [
@@ -5641,7 +5769,6 @@ return fields;
5641
5769
  description: 'Configuration for FormViewField -> FormView relationship'
5642
5770
  },
5643
5771
  {
5644
- id: this.generateId(),
5645
5772
  relationshipModel: 'ServiceCustomer',
5646
5773
  fieldName: 'service',
5647
5774
  selectionSet: [
@@ -5655,7 +5782,6 @@ return fields;
5655
5782
  description: 'Configuration for ServiceCustomer -> Service relationship'
5656
5783
  },
5657
5784
  {
5658
- id: this.generateId(),
5659
5785
  relationshipModel: 'ServiceCustomer',
5660
5786
  fieldName: 'customer',
5661
5787
  selectionSet: [
@@ -5668,32 +5794,53 @@ return fields;
5668
5794
  description: 'Configuration for ServiceCustomer -> Customer relationship'
5669
5795
  }
5670
5796
  ];
5671
- // Only add configs that don't already exist
5672
- let addedCount = 0;
5673
- for (const defaultConfig of defaultConfigs) {
5674
- const existing = this.relationshipConfigs.find(c => c.relationshipModel === defaultConfig.relationshipModel &&
5675
- c.fieldName === defaultConfig.fieldName);
5676
- if (!existing) {
5677
- this.relationshipConfigs.push(defaultConfig);
5678
- addedCount++;
5797
+ try {
5798
+ // Only add configs that don't already exist
5799
+ let addedCount = 0;
5800
+ for (const defaultConfig of defaultConfigs) {
5801
+ const existing = this.relationshipConfigs.find(c => c.relationshipModel === defaultConfig.relationshipModel &&
5802
+ c.fieldName === defaultConfig.fieldName);
5803
+ if (!existing) {
5804
+ await this.createRelationshipConfig(defaultConfig);
5805
+ addedCount++;
5806
+ }
5807
+ }
5808
+ if (addedCount > 0) {
5809
+ this.snackBar.open(`Added ${addedCount} default relationship configurations`, 'Dismiss', { duration: 3000 });
5810
+ }
5811
+ else {
5812
+ this.snackBar.open('All default configurations already exist', 'Dismiss', { duration: 3000 });
5679
5813
  }
5680
5814
  }
5681
- if (addedCount > 0) {
5682
- this.saveRelationshipConfigsToStorage();
5683
- this.snackBar.open(`Added ${addedCount} default relationship configurations`, 'Dismiss', { duration: 3000 });
5684
- }
5685
- else {
5686
- this.snackBar.open('All default configurations already exist', 'Dismiss', { duration: 3000 });
5815
+ catch (error) {
5816
+ console.error('ConfigurationsComponent: Error loading default relationship configs:', error);
5817
+ this.snackBar.open('Error loading default configurations: ' + error, 'Dismiss', { duration: 5000 });
5687
5818
  }
5688
5819
  }
5689
- clearAllRelationshipConfigs() {
5820
+ async clearAllRelationshipConfigs() {
5690
5821
  if (this.relationshipConfigs.length === 0) {
5691
5822
  this.snackBar.open('No relationship configurations to clear', 'Dismiss', { duration: 3000 });
5692
5823
  return;
5693
5824
  }
5694
- this.relationshipConfigs = [];
5695
- this.saveRelationshipConfigsToStorage();
5696
- this.snackBar.open('All relationship configurations cleared', 'Dismiss', { duration: 3000 });
5825
+ try {
5826
+ if (!this.hasRelationshipConfig) {
5827
+ // Fallback to localStorage if model not available
5828
+ this.relationshipConfigs = [];
5829
+ this.saveRelationshipConfigsToStorage();
5830
+ this.snackBar.open('All relationship configurations cleared', 'Dismiss', { duration: 3000 });
5831
+ return;
5832
+ }
5833
+ // Delete all configurations from Amplify
5834
+ const deletePromises = this.relationshipConfigs.map(config => this.ams.deleteItemForModel('RelationshipConfig', config.id));
5835
+ await Promise.all(deletePromises);
5836
+ // Reload configurations to get the updated (empty) list
5837
+ this.loadRelationshipConfigs();
5838
+ this.snackBar.open('All relationship configurations cleared', 'Dismiss', { duration: 3000 });
5839
+ }
5840
+ catch (error) {
5841
+ console.error('ConfigurationsComponent: Error clearing relationship configs:', error);
5842
+ this.snackBar.open('Error clearing configurations: ' + error, 'Dismiss', { duration: 5000 });
5843
+ }
5697
5844
  }
5698
5845
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: ConfigurationsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5699
5846
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: ConfigurationsComponent, isStandalone: true, selector: "snteam-configurations", inputs: { amplifyOutputs: "amplifyOutputs" }, ngImport: i0, template: "<div class=\"configurations-container\">\n <h2>System Configurations</h2>\n \n <mat-accordion multi=\"true\">\n \n <!-- Table Configs Section -->\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title>\n <mat-icon>table_chart</mat-icon>\n <span class=\"panel-title\">Table Configs</span>\n </mat-panel-title>\n <mat-panel-description>\n Manage table configurations and settings\n </mat-panel-description>\n </mat-expansion-panel-header>\n \n <div class=\"panel-content\">\n @if (hasTableConfig) {\n <div class=\"section-actions\">\n <button mat-raised-button color=\"accent\" (click)=\"populateDefaultTableConfigs()\" class=\"populate-button\">\n <mat-icon>auto_fix_high</mat-icon>\n Populate Default Table Configs\n </button>\n <button mat-raised-button color=\"warn\" (click)=\"deleteTableConfigs()\" class=\"delete-button\">\n <mat-icon>delete</mat-icon>\n Delete All Table Configs\n </button>\n </div>\n <snteam-list-view \n [modelName]=\"'TableConfig'\"\n [useRouter]=\"true\"\n [showDeleteAction]=\"true\">\n </snteam-list-view>\n } @else {\n <mat-card class=\"error-card\">\n <mat-card-content>\n <mat-icon class=\"error-icon\">error_outline</mat-icon>\n <h3>TableConfig Model Not Found</h3>\n <p>The TableConfig model is not available in your Amplify schema. Please add it to your data model to manage table configurations.</p>\n <button mat-raised-button color=\"primary\" class=\"help-button\">\n <mat-icon>help</mat-icon>\n View Documentation\n </button>\n </mat-card-content>\n </mat-card>\n }\n </div>\n </mat-expansion-panel>\n\n <!-- Form Views Section -->\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title>\n <mat-icon>dynamic_form</mat-icon>\n <span class=\"panel-title\">Form Views</span>\n </mat-panel-title>\n <mat-panel-description>\n Configure custom form layouts and field selections\n </mat-panel-description>\n </mat-expansion-panel-header>\n \n <div class=\"panel-content\">\n @if (hasFormView) {\n <div class=\"section-actions\">\n <button mat-raised-button color=\"warn\" (click)=\"deleteFormViews()\" class=\"delete-button\">\n <mat-icon>delete</mat-icon>\n Delete All Form Views\n </button>\n </div>\n <snteam-list-view \n [modelName]=\"'FormView'\"\n [useRouter]=\"true\"\n [showDeleteAction]=\"true\">\n </snteam-list-view>\n } @else {\n <mat-card class=\"error-card\">\n <mat-card-content>\n <mat-icon class=\"error-icon\">error_outline</mat-icon>\n <h3>FormView Model Not Found</h3>\n <p>The FormView model is not available in your Amplify schema. Please add it to your data model to create custom form configurations.</p>\n <button mat-raised-button color=\"primary\" class=\"help-button\">\n <mat-icon>help</mat-icon>\n View Documentation\n </button>\n </mat-card-content>\n </mat-card>\n }\n </div>\n </mat-expansion-panel>\n\n <!-- List Views Section -->\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title>\n <mat-icon>view_list</mat-icon>\n <span class=\"panel-title\">List Views</span>\n </mat-panel-title>\n <mat-panel-description>\n Customize list displays and column configurations\n </mat-panel-description>\n </mat-expansion-panel-header>\n \n <div class=\"panel-content\">\n @if (hasListView) {\n <div class=\"section-actions\">\n <button mat-raised-button color=\"warn\" (click)=\"deleteListViews()\" class=\"delete-button\">\n <mat-icon>delete</mat-icon>\n Delete All List Views\n </button>\n </div>\n <snteam-list-view \n [modelName]=\"'ListView'\"\n [useRouter]=\"true\"\n [showDeleteAction]=\"true\">\n </snteam-list-view>\n } @else {\n <mat-card class=\"error-card\">\n <mat-card-content>\n <mat-icon class=\"error-icon\">error_outline</mat-icon>\n <h3>ListView Model Not Found</h3>\n <p>The ListView model is not available in your Amplify schema. Please add it to your data model to create custom list view configurations.</p>\n <button mat-raised-button color=\"primary\" class=\"help-button\">\n <mat-icon>help</mat-icon>\n View Documentation\n </button>\n </mat-card-content>\n </mat-card>\n }\n </div>\n </mat-expansion-panel>\n\n <!-- Field Configs Section -->\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title>\n <mat-icon>settings</mat-icon>\n <span class=\"panel-title\">Field Configs</span>\n </mat-panel-title>\n <mat-panel-description>\n Configure field behavior, validation, and choices\n </mat-panel-description>\n </mat-expansion-panel-header>\n \n <div class=\"panel-content\">\n @if (hasFieldConfig) {\n <div class=\"section-actions\">\n <button mat-raised-button color=\"accent\" (click)=\"populateDefaultFieldConfigs()\" class=\"populate-button\">\n <mat-icon>auto_fix_high</mat-icon>\n Populate Default Field Configs\n </button>\n <button mat-raised-button color=\"warn\" (click)=\"deleteFieldConfigs()\" class=\"delete-button\">\n <mat-icon>delete</mat-icon>\n Delete All Field Configs\n </button>\n </div>\n <snteam-list-view \n [modelName]=\"'FieldConfig'\"\n [useRouter]=\"true\"\n [showDeleteAction]=\"true\">\n </snteam-list-view>\n } @else {\n <mat-card class=\"error-card\">\n <mat-card-content>\n <mat-icon class=\"error-icon\">error_outline</mat-icon>\n <h3>FieldConfig Model Not Found</h3>\n <p>The FieldConfig model is not available in your Amplify schema. Please add it to your data model to configure field behavior and validation.</p>\n <button mat-raised-button color=\"primary\" class=\"help-button\">\n <mat-icon>help</mat-icon>\n View Documentation\n </button>\n </mat-card-content>\n </mat-card>\n }\n </div>\n </mat-expansion-panel>\n\n <!-- Relationship Configs Section -->\n <mat-expansion-panel>\n <mat-expansion-panel-header>\n <mat-panel-title>\n <mat-icon>link</mat-icon>\n <span class=\"panel-title\">Relationship Configs</span>\n </mat-panel-title>\n <mat-panel-description>\n Configure GraphQL selection sets for relationship queries\n </mat-panel-description>\n </mat-expansion-panel-header>\n \n <div class=\"panel-content\">\n <div class=\"section-actions\">\n <button mat-raised-button color=\"primary\" (click)=\"showAddRelationshipConfig = !showAddRelationshipConfig\" class=\"add-button\">\n <mat-icon>{{ showAddRelationshipConfig ? 'close' : 'add' }}</mat-icon>\n {{ showAddRelationshipConfig ? 'Cancel' : 'Add Relationship Config' }}\n </button>\n <button mat-raised-button color=\"accent\" (click)=\"loadDefaultRelationshipConfigs()\" class=\"populate-button\">\n <mat-icon>auto_fix_high</mat-icon>\n Load Default Configs\n </button>\n <button mat-raised-button color=\"warn\" (click)=\"clearAllRelationshipConfigs()\" class=\"delete-button\">\n <mat-icon>delete</mat-icon>\n Clear All Configs\n </button>\n </div>\n\n <!-- Add/Edit Relationship Config Form -->\n @if (showAddRelationshipConfig) {\n <mat-card class=\"config-form-card\">\n <mat-card-header>\n <mat-card-title>\n <mat-icon>{{ editingRelationshipConfig ? 'edit' : 'add' }}</mat-icon>\n {{ editingRelationshipConfig ? 'Edit' : 'Add' }} Relationship Configuration\n </mat-card-title>\n </mat-card-header>\n <mat-card-content>\n <form [formGroup]=\"relationshipConfigForm\" (ngSubmit)=\"saveRelationshipConfig()\">\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Relationship Model</mat-label>\n <mat-select formControlName=\"relationshipModel\" (selectionChange)=\"onRelationshipModelChange($event)\">\n @for (model of availableModels; track model) {\n <mat-option [value]=\"model\">{{ model }}</mat-option>\n }\n </mat-select>\n <mat-hint>The model that contains the relationship field</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Field Name</mat-label>\n <mat-select formControlName=\"fieldName\">\n @for (field of availableFields; track field.name) {\n <mat-option [value]=\"field.name\">{{ field.label }}</mat-option>\n }\n </mat-select>\n <mat-hint>The relationship field in the selected model</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Selection Set</mat-label>\n <textarea \n matInput \n formControlName=\"selectionSet\" \n rows=\"6\"\n placeholder=\"Enter GraphQL selection fields, one per line:&#10;id&#10;table&#10;table.id&#10;table.name&#10;table.title\">\n </textarea>\n <mat-hint>GraphQL fields to select for this relationship (one per line)</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"form-row\">\n <mat-form-field appearance=\"outline\" class=\"full-width\">\n <mat-label>Description</mat-label>\n <input matInput formControlName=\"description\" placeholder=\"Optional description for this configuration\">\n <mat-hint>Optional description to document this configuration</mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"form-actions\">\n <button mat-raised-button color=\"primary\" type=\"submit\" [disabled]=\"!relationshipConfigForm.valid\">\n <mat-icon>save</mat-icon>\n {{ editingRelationshipConfig ? 'Update' : 'Save' }} Configuration\n </button>\n <button mat-button type=\"button\" (click)=\"cancelRelationshipConfigEdit()\">\n <mat-icon>cancel</mat-icon>\n Cancel\n </button>\n </div>\n </form>\n </mat-card-content>\n </mat-card>\n }\n\n <!-- Current Relationship Configurations -->\n <div class=\"current-configs\">\n <h3>Current Relationship Configurations</h3>\n @if (relationshipConfigs.length === 0) {\n <mat-card class=\"empty-state-card\">\n <mat-card-content>\n <mat-icon class=\"empty-icon\">link_off</mat-icon>\n <h4>No Relationship Configurations</h4>\n <p>Add relationship configurations to control GraphQL selection sets for relationship queries.</p>\n </mat-card-content>\n </mat-card>\n } @else {\n <div class=\"configs-list\">\n @for (config of relationshipConfigs; track config.id) {\n <mat-card class=\"config-card\">\n <mat-card-header>\n <mat-card-title>{{ config.relationshipModel }} \u2192 {{ config.fieldName }}</mat-card-title>\n <mat-card-subtitle>{{ config.description || 'No description' }}</mat-card-subtitle>\n <div class=\"card-actions\">\n <button mat-icon-button (click)=\"editRelationshipConfig(config)\" matTooltip=\"Edit Configuration\">\n <mat-icon>edit</mat-icon>\n </button>\n <button mat-icon-button color=\"warn\" (click)=\"deleteRelationshipConfig(config)\" matTooltip=\"Delete Configuration\">\n <mat-icon>delete</mat-icon>\n </button>\n </div>\n </mat-card-header>\n <mat-card-content>\n <div class=\"selection-set\">\n <strong>Selection Set:</strong>\n <div class=\"selection-fields\">\n @for (field of config.selectionSet; track field) {\n <span class=\"field-chip\">{{ field }}</span>\n }\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n }\n </div>\n }\n </div>\n\n <!-- Configuration Status -->\n <div class=\"config-status\">\n <mat-card class=\"status-card\">\n <mat-card-content>\n <div class=\"status-info\">\n <mat-icon class=\"status-icon\">info</mat-icon>\n <div class=\"status-text\">\n <strong>Active Configurations: {{ relationshipConfigs.length }}</strong>\n <p>These configurations control how relationship data is queried from your GraphQL API.</p>\n </div>\n </div>\n </mat-card-content>\n </mat-card>\n </div>\n </div>\n </mat-expansion-panel>\n\n </mat-accordion>\n</div>", styles: [".configurations-container{padding:20px;max-width:1200px;margin:0 auto}.configurations-container h2{margin-bottom:24px;color:#333;font-weight:500}.mat-expansion-panel{margin-bottom:16px;border-radius:8px;box-shadow:0 2px 4px #0000001a}.mat-expansion-panel-header{padding:16px 24px}.panel-title{margin-left:12px;font-weight:500;font-size:16px}.mat-panel-description{color:#666;font-size:14px}.panel-content{padding:16px 24px 24px;background-color:#fafafa}.error-card{text-align:center;padding:24px;background-color:#fff;border:2px dashed #ddd;border-radius:8px}.error-card mat-card-content{padding:0}.error-icon{font-size:48px;width:48px;height:48px;color:#ff9800;margin-bottom:16px}.error-card h3{margin:0 0 12px;color:#333;font-weight:500}.error-card p{color:#666;line-height:1.5;max-width:500px;margin:0 auto 20px}.help-button{margin-top:8px}.help-button mat-icon{margin-right:8px}.section-actions{margin-bottom:16px;padding-bottom:16px;border-bottom:1px solid #e0e0e0;display:flex;gap:12px;flex-wrap:wrap}.generate-button{background-color:#2196f3;color:#fff}.generate-button mat-icon{margin-right:8px}.delete-button{background-color:#f44336;color:#fff}.delete-button mat-icon{margin-right:8px}.populate-button mat-icon{margin-right:8px}@media (max-width: 768px){.configurations-container{padding:16px}.panel-content{padding:12px 16px 16px}.error-card{padding:16px}.error-icon{font-size:36px;width:36px;height:36px}}.add-button{background-color:#4caf50;color:#fff}.add-button mat-icon{margin-right:8px}.config-form-card{margin:16px 0;background-color:#fff;border-radius:8px;box-shadow:0 2px 8px #0000001a}.config-form-card mat-card-header{background-color:#f5f5f5;border-radius:8px 8px 0 0;padding:16px 24px}.config-form-card mat-card-title{display:flex;align-items:center;font-size:18px;font-weight:500;color:#333}.config-form-card mat-card-title mat-icon{margin-right:12px;color:#2196f3}.config-form-card mat-card-content{padding:24px}.form-row{margin-bottom:20px}.full-width{width:100%}.form-actions{display:flex;gap:12px;margin-top:24px;padding-top:16px;border-top:1px solid #e0e0e0}.form-actions button mat-icon{margin-right:8px}.current-configs{margin-top:24px}.current-configs h3{margin-bottom:16px;color:#333;font-weight:500}.empty-state-card{text-align:center;padding:32px;background-color:#fff;border:2px dashed #ddd;border-radius:8px}.empty-state-card mat-card-content{padding:0}.empty-icon{font-size:48px;width:48px;height:48px;color:#bbb;margin-bottom:16px}.empty-state-card h4{margin:0 0 12px;color:#333;font-weight:500}.empty-state-card p{margin:0;color:#666;line-height:1.5}.configs-list{display:grid;gap:16px}.config-card{background-color:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a;transition:box-shadow .2s ease}.config-card:hover{box-shadow:0 4px 8px #00000026}.config-card mat-card-header{padding:16px 20px;border-bottom:1px solid #f0f0f0;display:flex;align-items:center;justify-content:space-between}.config-card mat-card-title{font-size:16px;font-weight:500;color:#333;margin:0}.config-card mat-card-subtitle{font-size:14px;color:#666;margin:4px 0 0}.card-actions{display:flex;gap:4px}.config-card mat-card-content{padding:16px 20px}.selection-set{margin:0}.selection-set strong{display:block;margin-bottom:8px;color:#333;font-size:14px}.selection-fields{display:flex;flex-wrap:wrap;gap:6px}.field-chip{display:inline-block;padding:4px 8px;background-color:#e3f2fd;color:#1976d2;border-radius:12px;font-size:12px;font-family:Roboto Mono,monospace;border:1px solid #bbdefb}.config-status{margin-top:24px}.status-card{background-color:#fff;border-radius:8px;box-shadow:0 2px 4px #0000001a}.status-card mat-card-content{padding:16px 20px}.status-info{display:flex;align-items:flex-start;gap:12px}.status-icon{color:#2196f3;margin-top:2px}.status-text strong{display:block;margin-bottom:4px;color:#333;font-size:16px}.status-text p{margin:0;color:#666;font-size:14px;line-height:1.5}@media (max-width: 768px){.config-form-card mat-card-content{padding:16px}.form-actions{flex-direction:column}.form-actions button{width:100%}.config-card mat-card-header{flex-direction:column;align-items:flex-start;gap:8px}.card-actions{align-self:flex-end}.selection-fields{gap:4px}.field-chip{font-size:11px;padding:3px 6px}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i2.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i2.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i2.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i2.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i2.MatExpansionPanelDescription, selector: "mat-panel-description" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i4$2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i4$2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i4$2.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i4$2.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "directive", type: i4$2.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i3$3.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "component", type: ListViewComponent, selector: "snteam-list-view", inputs: ["modelName", "customItemTemplate", "hideNewButton", "title", "useRouter", "showRowActions", "showDeleteAction", "customRowActions"], outputs: ["itemClick", "newClick", "itemsLoaded", "itemDeleted"] }] });