diff --git a/app/web/src/api/sdf/dal/property_editor.ts b/app/web/src/api/sdf/dal/property_editor.ts index fad55a15e1..62c9ab4b9c 100644 --- a/app/web/src/api/sdf/dal/property_editor.ts +++ b/app/web/src/api/sdf/dal/property_editor.ts @@ -23,6 +23,14 @@ export interface PropertyEditorPropWidgetKindArray { kind: "array"; } +export interface PropertyEditorpropWidgetKindRequirement { + kind: "requirement"; +} + +export interface PropertyEditorPropWidgetKindUsers { + kind: "users"; +} + export interface PropertyEditorPropWidgetKindCheckBox { kind: "checkbox"; } @@ -85,6 +93,8 @@ export type PropertyEditorPropWidgetKind = | PropertyEditorPropWidgetKindInteger | PropertyEditorPropWidgetKindHeader | PropertyEditorPropWidgetKindArray + | PropertyEditorpropWidgetKindRequirement + | PropertyEditorPropWidgetKindUsers | PropertyEditorPropWidgetKindCodeEditor | PropertyEditorPropWidgetKindComboBox | PropertyEditorPropWidgetKindSelect diff --git a/app/web/src/api/sdf/dal/views.ts b/app/web/src/api/sdf/dal/views.ts index d9ab67817c..d9b1399d52 100644 --- a/app/web/src/api/sdf/dal/views.ts +++ b/app/web/src/api/sdf/dal/views.ts @@ -5,9 +5,11 @@ import { DiagramViewData, SocketLocationInfo, } from "@/components/ModelingDiagram/diagram_types"; +import { UserId } from "@/store/auth.store"; import { ComponentType } from "./schema"; export type ViewId = string; +export type EntityId = string; // TODO - "entity" can refer to most things in the system, currently we use this mostly just for views export type Components = Record; export type Groups = Record< @@ -39,3 +41,13 @@ export interface StringGeometry { width: string; height: string; } + +// Approval Requirement Definition types +export type ApprovalRequirementDefinitionId = string; +export interface ViewApprovalRequirementDefinition { + id: ApprovalRequirementDefinitionId; + entityId: ViewId; + requiredCount: number; + approverGroups: Record; + approverIndividuals: UserId[]; +} diff --git a/app/web/src/components/Actions/ActionsList.vue b/app/web/src/components/Actions/ActionsList.vue index b3ea9f7e85..ab22d54be5 100644 --- a/app/web/src/components/Actions/ActionsList.vue +++ b/app/web/src/components/Actions/ActionsList.vue @@ -33,7 +33,7 @@
- {{ displayActions.length }} Actions + {{ displayActions.length }} Action(s)
+ + @@ -938,6 +1005,7 @@ import SecretsModal from "../SecretsModal.vue"; import SourceIconWithTooltip from "./SourceIconWithTooltip.vue"; import CodeViewer from "../CodeViewer.vue"; import { TreeFormContext } from "./TreeForm.vue"; +import UserSelectMenu from "../UserSelectMenu.vue"; export type TreeFormProp = { id: string; @@ -1052,7 +1120,13 @@ const viewsStore = useViewsStore(); const componentId = viewsStore.selectedComponentId!; const changeSetsStore = useChangeSetsStore(); -const attributesStore = useComponentAttributesStore(componentId); +const attributesStore = computed(() => { + if (props.attributesPanel) { + return useComponentAttributesStore(componentId); + } else { + return undefined; + } +}); const secretsStore = useSecretsStore(); const fullPropDef = computed(() => props.treeDef.propDef); @@ -1239,10 +1313,12 @@ const propSource = computed(() => { }); const setSource = (source: AttributeValueSource) => { + if (!attributesStore.value) return; + if (source === AttributeValueSource.Manual) { const value = props.treeDef.value?.value ?? null; - attributesStore.UPDATE_PROPERTY_VALUE({ + attributesStore.value.UPDATE_PROPERTY_VALUE({ update: { attributeValueId: props.treeDef.valueId, parentAttributeValueId: props.treeDef.parentValueId, @@ -1253,7 +1329,7 @@ const setSource = (source: AttributeValueSource) => { }, }); } else { - attributesStore.RESET_PROPERTY_VALUE({ + attributesStore.value.RESET_PROPERTY_VALUE({ attributeValueId: props.treeDef.valueId, }); } @@ -1334,8 +1410,8 @@ const newMapChildKeyIsValid = computed(() => { function removeChildHandler() { if (!isChildOfArray.value && !isChildOfMap.value) return; - if (props.attributesPanel) { - attributesStore.REMOVE_PROPERTY_VALUE({ + if (props.attributesPanel && attributesStore.value) { + attributesStore.value.REMOVE_PROPERTY_VALUE({ attributeValueId: props.treeDef.valueId, propId: props.treeDef.propId, componentId, @@ -1371,8 +1447,8 @@ function addChildHandler() { return; } - if (props.attributesPanel) { - attributesStore.UPDATE_PROPERTY_VALUE({ + if (props.attributesPanel && attributesStore.value) { + attributesStore.value.UPDATE_PROPERTY_VALUE({ insert: { parentAttributeValueId: props.treeDef.valueId, propId: props.treeDef.propId, @@ -1391,8 +1467,8 @@ function unsetHandler(value?: string) { newValueBoolean.value = false; newValueString.value = ""; - if (props.attributesPanel) { - attributesStore.RESET_PROPERTY_VALUE({ + if (props.attributesPanel && attributesStore.value) { + attributesStore.value.RESET_PROPERTY_VALUE({ attributeValueId: props.treeDef.valueId, }); } else { @@ -1445,8 +1521,8 @@ function updateValue(maybeNewVal?: unknown) { isForSecret = true; } - if (props.attributesPanel) { - attributesStore.UPDATE_PROPERTY_VALUE({ + if (props.attributesPanel && attributesStore.value) { + attributesStore.value.UPDATE_PROPERTY_VALUE({ update: { attributeValueId: props.treeDef.valueId, parentAttributeValueId: props.treeDef.parentValueId, @@ -1703,6 +1779,35 @@ const socketSearchFilters = computed(() => { return filters; }); + +// APPROVAL REQUIREMENTS STUFF +const usersToFilterOut = computed(() => { + if (props.treeDef.propDef.widgetKind.kind === "users") { + const users = props.treeDef.children.map((user) => user.propId); + return users; + } else return undefined; +}); + +const userSelectMenuRef = ref>(); + +const addUser = async (userId: string) => { + const requirementId = props.treeDef.parentValueId; + await viewsStore.ADD_INDIVIDUAL_APPROVER_TO_REQUIREMENT( + requirementId, + userId, + ); + userSelectMenuRef.value?.clearSelection(); +}; + +const removeUser = (userId: string) => { + const requirementId = props.treeDef.parentValueId; + viewsStore.REMOVE_INDIVIDUAL_APPROVER_FROM_REQUIREMENT(requirementId, userId); +}; + +const deleteRequirement = () => { + const requirementId = props.treeDef.propId; + viewsStore.REMOVE_VIEW_APPROVAL_REQUIREMENT(requirementId); +};