@meshmakers/octo-ui 3.3.740 → 3.3.760

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.
@@ -2532,6 +2532,11 @@ class CkTypeSelectorInputComponent {
2532
2532
  this.selectCkType(ckType);
2533
2533
  }
2534
2534
  }
2535
+ else if (!value && this.selectedCkType) {
2536
+ this.selectedCkType = null;
2537
+ this.onChange(null);
2538
+ this.ckTypeCleared.emit();
2539
+ }
2535
2540
  }
2536
2541
  onFocus() {
2537
2542
  const currentValue = this.searchFormControl.value;
@@ -9749,15 +9754,13 @@ class CreateEditorComponent {
9749
9754
  return entity;
9750
9755
  }
9751
9756
  /**
9752
- * Resets the form and prepares the state for the selected type.
9753
- * Naming (intentional, not swapped): CkTypeDto has ckTypeId { fullName } and rtCkTypeId.
9757
+ * Handles type selection from the CkTypeSelectorInput.
9758
+ * CkTypeSelectorItem has fullName and rtCkTypeId.
9754
9759
  * - selectedRtCkTypeId = fullName → used as [ckId] for attributes-group (getCkAttributesDetailed expects type id).
9755
- * - selectedCkTypeId = DTO's rtCkTypeId → used in create mutation payload as entity.ckTypeId.
9760
+ * - selectedCkTypeId = rtCkTypeId → used in create mutation payload as entity.ckTypeId.
9756
9761
  */
9757
- onTypeChange(selectedType) {
9758
- if (selectedType === null || selectedType === undefined)
9759
- return;
9760
- const rtCkTypeId = selectedType.ckTypeId.fullName;
9762
+ onCkTypeSelected(selectedType) {
9763
+ const rtCkTypeId = selectedType.fullName;
9761
9764
  const ckTypeId = selectedType.rtCkTypeId;
9762
9765
  if (ckTypeId && rtCkTypeId) {
9763
9766
  this.form.set(this.formBuilder.group({}));
@@ -9770,6 +9773,11 @@ class CreateEditorComponent {
9770
9773
  this.selectedCkTypeId.set(null);
9771
9774
  }
9772
9775
  }
9776
+ onCkTypeCleared() {
9777
+ this.form.set(null);
9778
+ this.selectedRtCkTypeId.set(null);
9779
+ this.selectedCkTypeId.set(null);
9780
+ }
9773
9781
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CreateEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
9774
9782
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: CreateEditorComponent, isStandalone: true, selector: "mm-create-editor-component", inputs: { createInput: { classPropertyName: "createInput", publicName: "createInput", isSignal: true, isRequired: true, transformFunction: null }, messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { createOutput: "createOutput", cancelRequested: "cancelRequested" }, ngImport: i0, template: `
9775
9783
  <div class="entity-editor-container">
@@ -9792,15 +9800,15 @@ class CreateEditorComponent {
9792
9800
 
9793
9801
  <div class="info-item">
9794
9802
  <label>{{ resolvedMessages().entityType }}</label>
9795
- <kendo-dropdownlist
9796
- [data]="createInput()!.ckTypes || []"
9797
- textField="rtCkTypeId"
9798
- valueField="rtCkTypeId"
9799
- [valuePrimitive]="false"
9800
- [attr.placeholder]="resolvedMessages().selectType"
9801
- (valueChange)="onTypeChange($event)"
9803
+ <mm-ck-type-selector-input
9804
+ [placeholder]="resolvedMessages().selectType"
9805
+ [allowAbstract]="false"
9806
+ [derivedFromRtCkTypeId]="createInput()!.derivedFromRtCkTypeId"
9807
+ [dialogTitle]="resolvedMessages().selectType"
9808
+ (ckTypeSelected)="onCkTypeSelected($event)"
9809
+ (ckTypeCleared)="onCkTypeCleared()"
9802
9810
  >
9803
- </kendo-dropdownlist>
9811
+ </mm-ck-type-selector-input>
9804
9812
  </div>
9805
9813
  </kendo-card-body>
9806
9814
  </kendo-card>
@@ -9836,7 +9844,7 @@ class CreateEditorComponent {
9836
9844
  </button>
9837
9845
  </div>
9838
9846
  </div>
9839
- `, isInline: true, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px;text-transform:uppercase}.entity-editor-container .attributes-form-container ::ng-deep kendo-card:not(.basic-info-card) kendo-card-body{display:flex;flex-direction:column;gap:16px}.entity-editor-container .select-type-prompt{grid-column:span 2;text-transform:uppercase;color:var(--kendo-color-primary, #0f6dff);background-color:var(--kendo-color-surface-alt, rgba(0, 0, 0, .05));padding:16px;border-radius:8px;text-align:center;border:1px dashed var(--kendo-color-border, rgba(0, 0, 0, .1))}.entity-editor-container .entity-editor-actions{display:flex;flex-direction:row;gap:16px}.entity-editor-container .entity-editor-actions button:disabled{opacity:.6}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i1$3.CardComponent, selector: "kendo-card", inputs: ["orientation", "width"] }, { kind: "component", type: i1$3.CardBodyComponent, selector: "kendo-card-body" }, { kind: "component", type: i1$3.CardHeaderComponent, selector: "kendo-card-header" }, { kind: "component", type: i5.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: i3$1.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "component", type: i4.DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "adaptiveTitle", "adaptiveSubtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "component", type: AttributesGroupComponent, selector: "mm-attributes-group", inputs: ["ckId", "parentFormGroup", "isRecord", "initialValues"] }] });
9847
+ `, isInline: true, styles: [".entity-editor-container{display:flex;flex-direction:column;gap:16px;width:100%}.entity-editor-container ::ng-deep kendo-card{display:grid;grid-template-rows:auto 1fr;grid-template-columns:1fr 1fr;gap:16px;width:100%!important}.entity-editor-container ::ng-deep kendo-card kendo-card-header{grid-column:span 2;grid-row:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body{grid-row:2;grid-column:span 2;display:grid;grid-template-columns:1fr 1fr;gap:16px}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item{display:flex;flex-direction:column}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :first-child{grid-column:1}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item :nth-child(2){grid-column:2}.entity-editor-container ::ng-deep kendo-card kendo-card-body .info-item label{color:var(--kendo-color-subtle, rgba(0, 0, 0, .7));margin-bottom:8px;text-transform:uppercase}.entity-editor-container .attributes-form-container ::ng-deep kendo-card:not(.basic-info-card) kendo-card-body{display:flex;flex-direction:column;gap:16px}.entity-editor-container .select-type-prompt{grid-column:span 2;text-transform:uppercase;color:var(--kendo-color-primary, #0f6dff);background-color:var(--kendo-color-surface-alt, rgba(0, 0, 0, .05));padding:16px;border-radius:8px;text-align:center;border:1px dashed var(--kendo-color-border, rgba(0, 0, 0, .1))}.entity-editor-container .entity-editor-actions{display:flex;flex-direction:row;gap:16px}.entity-editor-container .entity-editor-actions button:disabled{opacity:.6}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: CardModule }, { kind: "component", type: i1$3.CardComponent, selector: "kendo-card", inputs: ["orientation", "width"] }, { kind: "component", type: i1$3.CardBodyComponent, selector: "kendo-card-body" }, { kind: "component", type: i1$3.CardHeaderComponent, selector: "kendo-card-header" }, { kind: "component", type: i5.TextBoxComponent, selector: "kendo-textbox", inputs: ["focusableId", "title", "type", "disabled", "readonly", "tabindex", "value", "selectOnFocus", "showSuccessIcon", "showErrorIcon", "clearButton", "successIcon", "successSvgIcon", "errorIcon", "errorSvgIcon", "clearButtonIcon", "clearButtonSvgIcon", "size", "rounded", "fillMode", "tabIndex", "placeholder", "maxlength", "inputAttributes"], outputs: ["valueChange", "inputFocus", "inputBlur", "focus", "blur"], exportAs: ["kendoTextBox"] }, { kind: "component", type: i3$1.ButtonComponent, selector: "button[kendoButton]", inputs: ["arrowIcon", "toggleable", "togglable", "selected", "tabIndex", "imageUrl", "iconClass", "icon", "disabled", "size", "rounded", "fillMode", "themeColor", "svgIcon", "primary", "look"], outputs: ["selectedChange", "click"], exportAs: ["kendoButton"] }, { kind: "component", type: CkTypeSelectorInputComponent, selector: "mm-ck-type-selector-input", inputs: ["placeholder", "minSearchLength", "maxResults", "debounceMs", "ckModelIds", "allowAbstract", "dialogTitle", "advancedSearchLabel", "derivedFromRtCkTypeId", "disabled", "required"], outputs: ["ckTypeSelected", "ckTypeCleared"] }, { kind: "component", type: AttributesGroupComponent, selector: "mm-attributes-group", inputs: ["ckId", "parentFormGroup", "isRecord", "initialValues"] }] });
9840
9848
  }
9841
9849
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: CreateEditorComponent, decorators: [{
9842
9850
  type: Component,
@@ -9846,8 +9854,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
9846
9854
  KENDO_INPUTS,
9847
9855
  KENDO_LABEL,
9848
9856
  KENDO_BUTTONS,
9849
- KENDO_DROPDOWNS,
9850
9857
  KENDO_DATEINPUTS,
9858
+ CkTypeSelectorInputComponent,
9851
9859
  AttributesGroupComponent,
9852
9860
  ], template: `
9853
9861
  <div class="entity-editor-container">
@@ -9870,15 +9878,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImpor
9870
9878
 
9871
9879
  <div class="info-item">
9872
9880
  <label>{{ resolvedMessages().entityType }}</label>
9873
- <kendo-dropdownlist
9874
- [data]="createInput()!.ckTypes || []"
9875
- textField="rtCkTypeId"
9876
- valueField="rtCkTypeId"
9877
- [valuePrimitive]="false"
9878
- [attr.placeholder]="resolvedMessages().selectType"
9879
- (valueChange)="onTypeChange($event)"
9881
+ <mm-ck-type-selector-input
9882
+ [placeholder]="resolvedMessages().selectType"
9883
+ [allowAbstract]="false"
9884
+ [derivedFromRtCkTypeId]="createInput()!.derivedFromRtCkTypeId"
9885
+ [dialogTitle]="resolvedMessages().selectType"
9886
+ (ckTypeSelected)="onCkTypeSelected($event)"
9887
+ (ckTypeCleared)="onCkTypeCleared()"
9880
9888
  >
9881
- </kendo-dropdownlist>
9889
+ </mm-ck-type-selector-input>
9882
9890
  </div>
9883
9891
  </kendo-card-body>
9884
9892
  </kendo-card>
@@ -10511,9 +10519,9 @@ class RuntimeBrowserDetailsComponent {
10511
10519
  /**
10512
10520
  * Activates the creation UI and provides necessary data
10513
10521
  * @param parentNode The tree node under which the new entity will be created, or null for root-level creation
10514
- * @param allowedTypes List of compatible entity types for the new node
10522
+ * @param derivedFromRtCkTypeId Base type ID to filter the type selector (e.g. 'Basic/TreeNode' or 'Basic/Tree')
10515
10523
  */
10516
- enterCreateMode(parentNode, allowedTypes) {
10524
+ enterCreateMode(parentNode, derivedFromRtCkTypeId) {
10517
10525
  const rtEntityDto = parentNode;
10518
10526
  this.createInput = {
10519
10527
  parent: {
@@ -10521,7 +10529,7 @@ class RuntimeBrowserDetailsComponent {
10521
10529
  rtId: rtEntityDto?.item.rtId,
10522
10530
  name: parentNode?.text ?? "",
10523
10531
  },
10524
- ckTypes: allowedTypes,
10532
+ derivedFromRtCkTypeId,
10525
10533
  };
10526
10534
  // Toggle the UI state to show the creation form
10527
10535
  this.isCreateModeEnabled = true;
@@ -11507,7 +11515,6 @@ class RuntimeBrowserComponent {
11507
11515
  notificationService = inject(NotificationService);
11508
11516
  isSelectedItemAnRtEntity = false;
11509
11517
  isLoading = false;
11510
- isCreating = false;
11511
11518
  isEditing = false;
11512
11519
  messages = input({}, ...(ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []));
11513
11520
  resolvedMessages = computed(() => ({
@@ -11584,7 +11591,7 @@ class RuntimeBrowserComponent {
11584
11591
  return !this.isLoading;
11585
11592
  }
11586
11593
  get isCreateButtonEnabled() {
11587
- return !this.isLoading && !this.isCreating;
11594
+ return !this.isLoading;
11588
11595
  }
11589
11596
  get isDeleteButtonEnabled() {
11590
11597
  return !this.isLoading && this.isSelectedItemAnRtEntity;
@@ -11991,28 +11998,10 @@ class RuntimeBrowserComponent {
11991
11998
  /**
11992
11999
  * Main action to initiate the creation of a new node
11993
12000
  */
11994
- async onCreate() {
11995
- // Anti-spam validation: prevent multiple clicks
11996
- if (this.isCreating) {
11997
- return;
11998
- }
11999
- try {
12000
- this.isCreating = true;
12001
- // Fetch available Construction Kit types from the API
12002
- const result = await firstValueFrom(this.ckTypesGQL.fetch());
12003
- const allTypes = (result.data?.constructionKit?.types?.items ?? []).filter((type) => type != null);
12004
- const isRootLevel = !this.selectedItem;
12005
- const filteredTypes = this.getCompatibleTreeTypes(allTypes, isRootLevel);
12006
- // Transition the details panel into Create Mode
12007
- // Pass null as parent if no item is selected (creates root-level entity)
12008
- this.detailsPanel?.enterCreateMode(this.selectedItem || null, filteredTypes);
12009
- }
12010
- catch (err) {
12011
- console.error('Failed to load types for creation:', err);
12012
- }
12013
- finally {
12014
- this.isCreating = false;
12015
- }
12001
+ onCreate() {
12002
+ const isRootLevel = !this.selectedItem;
12003
+ const derivedFromRtCkTypeId = isRootLevel ? 'Basic/Tree' : 'Basic/TreeNode';
12004
+ this.detailsPanel?.enterCreateMode(this.selectedItem || null, derivedFromRtCkTypeId);
12016
12005
  }
12017
12006
  async onEdit() {
12018
12007
  // Anti-spam validation: prevent multiple clicks
@@ -12041,60 +12030,6 @@ class RuntimeBrowserComponent {
12041
12030
  this.isEditing = false;
12042
12031
  }
12043
12032
  }
12044
- /**
12045
- * Filters the list of types to find compatible types for entity creation.
12046
- * For root-level creation, only allows Basic/Tree types.
12047
- * For child creation, allows non-abstract TreeNode types.
12048
- *
12049
- * @param types - All available CK types
12050
- * @param isRootLevel - If true, only Basic/Tree types are allowed
12051
- * @returns Filtered list of compatible types
12052
- */
12053
- getCompatibleTreeTypes(types, isRootLevel = false) {
12054
- // For root-level creation, only allow Basic/Tree types
12055
- if (isRootLevel) {
12056
- return types.filter((type) => {
12057
- const isBasicTree = type?.rtCkTypeId === 'Basic/Tree';
12058
- return isBasicTree;
12059
- });
12060
- }
12061
- // For child creation, allow non-abstract TreeNode types
12062
- const filtered = types.filter((type) => {
12063
- const isNotAbstract = type?.isAbstract === false;
12064
- const isTreeNodeFamily = this.isTreeNodeType(type);
12065
- return isNotAbstract && isTreeNodeFamily;
12066
- });
12067
- // If no TreeNode types found, fallback to all non-abstract types
12068
- if (filtered.length === 0) {
12069
- return types.filter((type) => type?.isAbstract === false);
12070
- }
12071
- return filtered;
12072
- }
12073
- /**
12074
- * Checks if a specific type or its base type belongs to the TreeNode hierarchy
12075
- */
12076
- isTreeNodeType(type) {
12077
- const typeFullName = type?.ckTypeId?.fullName || '';
12078
- const baseTypeFullName = type?.baseType?.ckTypeId?.fullName || '';
12079
- const getShortName = (fullName) => {
12080
- if (!fullName) {
12081
- return '';
12082
- }
12083
- // Handle both dot notation (System.Entity) and slash notation (System/Entity)
12084
- const parts = fullName.includes('/')
12085
- ? fullName.split('/')
12086
- : fullName.split('.');
12087
- return parts[parts.length - 1] || '';
12088
- };
12089
- const typeName = getShortName(typeFullName);
12090
- const baseTypeName = getShortName(baseTypeFullName);
12091
- // Check if type name ends with TreeNode or is TreeNode
12092
- const isTreeNode = typeName === 'TreeNode' || baseTypeName === 'TreeNode';
12093
- // Also check if full name contains TreeNode (for cases like Basic/TreeNode)
12094
- const containsTreeNode = typeFullName.includes('TreeNode') ||
12095
- baseTypeFullName.includes('TreeNode');
12096
- return isTreeNode || containsTreeNode;
12097
- }
12098
12033
  /**
12099
12034
  * Handles entitySaved from the details panel: refreshes the tree, then reloads the detail view
12100
12035
  * when the save was an update so the user sees fresh data.