Skip to content

Commit

Permalink
feat: auto select components created by mgmt fns
Browse files Browse the repository at this point in the history
If you create a bunch of components via a management function, (say, via
a template func), we will now replace the selection with them when the
components are created.
  • Loading branch information
zacharyhamm committed Dec 19, 2024
1 parent 8aff0d2 commit c79c600
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 66 deletions.
22 changes: 0 additions & 22 deletions app/web/src/components/ManagementRunPrototype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
<script lang="ts" setup>
import { ref, computed, onMounted, watch } from "vue";
import clsx from "clsx";
import { useToast } from "vue-toastification";
import {
DropdownMenu,
DropdownMenuItem,
Expand Down Expand Up @@ -69,7 +68,6 @@ import FuncRunTabDropdown from "./FuncRunTabDropdown.vue";
const funcStore = useFuncStore();
const viewStore = useViewsStore();
const router = useRouter();
const toast = useToast();
const managementRunsStore = useManagementRunsStore();
const viewsStore = useViewsStore();
Expand Down Expand Up @@ -129,27 +127,7 @@ const runPrototype = async (viewId: ViewId) => {
);
if (result.result.success) {
// TODO(WENDY) - for template functions, select the returned componentIds
// modelingEventBus.emit("setSelection", componentIds);
lastExecution.value = result.result.data;
if (result.result.data.message) {
const toastOptions = {
pauseOnHover: true,
timeout: 5000,
};
if (result.result.data.status === "ok") {
toast.success(
`${props.prototype.label}: ${result.result.data.message}`,
toastOptions,
);
} else {
toast.warning(
`${props.prototype.label}: ${result.result.data.message}`,
toastOptions,
);
}
}
}
};
Expand Down
22 changes: 1 addition & 21 deletions app/web/src/components/ModelingView/ModelingRightClickMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import { storeToRefs } from "pinia";
import { computed, ref } from "vue";
// import plur from "plur";
import { RouteLocationRaw } from "vue-router";
import { useToast } from "vue-toastification";
import { IRect } from "konva/lib/types";
import { ComponentType } from "@/api/sdf/dal/schema";
import { useComponentsStore } from "@/store/components.store";
Expand All @@ -68,7 +67,6 @@ import {
const contextMenuRef = ref<InstanceType<typeof DropdownMenu>>();
const toast = useToast();
const changeSetsStore = useChangeSetsStore();
const componentsStore = useComponentsStore();
const funcStore = useFuncStore();
Expand Down Expand Up @@ -519,29 +517,11 @@ const runManagementFunc = async (prototype: MgmtPrototype) => {
if (!selectedComponent.value) return;
if (!viewStore.selectedViewId) return;
const result = await funcStore.RUN_MGMT_PROTOTYPE(
await funcStore.RUN_MGMT_PROTOTYPE(
prototype.managementPrototypeId,
selectedComponent.value.def.id,
viewStore.selectedViewId,
);
if (result.result.success && result.result.data.message) {
const toastOptions = {
pauseOnHover: true,
timeout: 5000,
};
if (result.result.data.status === "ok") {
toast.success(
`${prototype.label}: ${result.result.data.message}`,
toastOptions,
);
} else {
toast.warning(
`${prototype.label}: ${result.result.data.message}`,
toastOptions,
);
}
}
};
function triggerCopySelection() {
Expand Down
48 changes: 42 additions & 6 deletions app/web/src/store/func/funcs.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as _ from "lodash-es";
import { defineStore } from "pinia";
import { addStoreHooks, ApiRequest, URLPattern } from "@si/vue-lib/pinia";
import { ulid } from "ulid";
import { useToast } from "vue-toastification";
import { Visibility } from "@/api/sdf/dal/visibility";
import {
FuncArgument,
Expand Down Expand Up @@ -41,6 +42,7 @@ import { useRealtimeStore } from "../realtime/realtime.store";

import { FuncRunId } from "../func_runs.store";
import { useViewsStore } from "../views.store";
import { useComponentsStore } from "../components.store";

type FuncExecutionState =
| "Create"
Expand Down Expand Up @@ -83,6 +85,7 @@ export type MgmtPrototype = {
export type MgmtPrototypeResult = {
message?: string;
status: "ok" | "error";
createdComponentIds?: ComponentId[];
};

export function actionBindingsForVariant(
Expand Down Expand Up @@ -207,6 +210,7 @@ export const useFuncStore = () => {
executingPrompt: false,
// So we can ignore websocket update originated by this client
clientUlid: ulid(),
pendingManagementRunRequestUlid: undefined as string | undefined,
}),
getters: {
selectedFuncSummary(state): FuncSummary | undefined {
Expand All @@ -231,7 +235,7 @@ export const useFuncStore = () => {

const variant =
useAssetStore().variantFromListById[
viewStore.selectedComponent?.def.schemaVariantId || ""
viewStore.selectedComponent?.def.schemaVariantId || ""
];
if (!variant) return [];
variant.funcIds.forEach((funcId) => {
Expand Down Expand Up @@ -260,7 +264,7 @@ export const useFuncStore = () => {
return [];
const variant =
useAssetStore().variantFromListById[
viewStore.selectedComponent?.def.schemaVariantId || ""
viewStore.selectedComponent?.def.schemaVariantId || ""
];
if (!variant) return [];
const summaries: Record<FuncId, FuncSummary> = {};
Expand Down Expand Up @@ -318,6 +322,9 @@ export const useFuncStore = () => {
{ componentId },
{ viewId },
]),
optimistic: (requestUlid) => {
this.pendingManagementRunRequestUlid = requestUlid;
},
});
},

Expand Down Expand Up @@ -431,7 +438,7 @@ export const useFuncStore = () => {
clientUlid: this.clientUlid,
},
optimistic: () => {
if (isHead) return () => {};
if (isHead) return () => { };

const current = _.cloneDeep(this.funcsById[func.funcId]);
const editing = this.funcsById[func.funcId];
Expand Down Expand Up @@ -481,7 +488,7 @@ export const useFuncStore = () => {
if (
b.attributePrototypeId &&
b.attributePrototypeId ===
binding.attributePrototypeId
binding.attributePrototypeId
)
return true;
}
Expand All @@ -498,7 +505,7 @@ export const useFuncStore = () => {
if (
b.managementPrototypeId &&
b.managementPrototypeId ===
binding.managementPrototypeId
binding.managementPrototypeId
)
return true;
}
Expand Down Expand Up @@ -931,7 +938,7 @@ export const useFuncStore = () => {
if (data.funcId === this.selectedFuncId) {
if (
typeof this.funcCodeById[this.selectedFuncId] ===
"undefined" ||
"undefined" ||
changeSetsStore.headSelected
) {
this.FETCH_CODE(this.selectedFuncId);
Expand All @@ -940,6 +947,35 @@ export const useFuncStore = () => {
}
},
},
{
eventType: "ManagementOperationsComplete",
callback: (
{ requestUlid, status, message, createdComponentIds, funcName },
_metadata,
) => {
if (
requestUlid &&
requestUlid === this.pendingManagementRunRequestUlid &&
createdComponentIds?.length
) {
viewStore.setSelectedComponentId(createdComponentIds);
this.pendingManagementRunRequestUlid = undefined;
}

const toast = useToast();
const toastOptions = {
timeout: 5000,
};
const toastMessage = message?.length
? `Ran ${funcName}: ${message}`
: `Ran ${funcName}`;
if (status === "ok") {
toast.success(toastMessage, toastOptions);
} else {
toast.warning(toastMessage, toastOptions);
}
},
},
]);
return () => {
realtimeStore.unsubscribe(this.$id);
Expand Down
9 changes: 9 additions & 0 deletions app/web/src/store/realtime/realtime_events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,12 +215,21 @@ export type WsEventPayloadMap = {
fromComponentId: string;
toComponentId: string;
};

ManagementFuncExecuted: {
managerComponentId: string;
prototypeId: string;
funcRunId: FuncRunId;
changeSetId: string;
};
ManagementOperationsComplete: {
requestUlid?: string;
funcName: string;
status: "ok" | "error";
message?: string;
createdComponentIds?: ComponentId[];
};

ModuleImported: SchemaVariant[];
WorkspaceImportBeginApprovalProcess: {
workspacePk: WorkspacePk;
Expand Down
7 changes: 5 additions & 2 deletions lib/dal/src/management/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@ impl<'a> ManagementOperator<'a> {
Ok(())
}

pub async fn operate(&mut self) -> ManagementResult<()> {
pub async fn operate(&mut self) -> ManagementResult<Option<Vec<ComponentId>>> {
let mut pending_operations = self.creates().await?;
let mut component_graph = DependencyGraph::new();
pending_operations.extend(self.updates().await?);
Expand All @@ -1029,6 +1029,9 @@ impl<'a> ManagementOperator<'a> {
component_graph.id_depends_on(pending_parent.child_component_id, parent_id);
}

let created_component_ids = (!self.created_components.is_empty())
.then_some(self.created_components.iter().copied().collect());

self.send_component_ws_events(component_graph).await?;

// Now, the rest of the pending ops can be executed, which need to have
Expand Down Expand Up @@ -1061,7 +1064,7 @@ impl<'a> ManagementOperator<'a> {

self.actions().await?;

Ok(())
Ok(created_component_ids)
}
}

Expand Down
37 changes: 34 additions & 3 deletions lib/dal/src/management/prototype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{
use serde::{Deserialize, Serialize};
use si_events::FuncRunId;
use thiserror::Error;
use veritech_client::ManagementResultSuccess;
use veritech_client::{ManagementFuncStatus, ManagementResultSuccess};

use crate::{
cached_module::{CachedModule, CachedModuleError},
Expand All @@ -24,7 +24,7 @@ use crate::{
Component, ComponentError, ComponentId, DalContext, EdgeWeightKind,
EdgeWeightKindDiscriminants, FuncId, HelperError, NodeWeightDiscriminants, Schema, SchemaError,
SchemaId, SchemaVariant, SchemaVariantError, SchemaVariantId, TransactionsError,
WorkspaceSnapshotError, WsEvent, WsEventError, WsEventResult,
WorkspaceSnapshotError, WsEvent, WsEventError, WsEventResult, WsPayload,
};

use super::ManagementGeometry;
Expand Down Expand Up @@ -660,6 +660,16 @@ pub struct ManagementFuncExecutedPayload {
func_run_id: FuncRunId,
}

#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct ManagementOperationsCompletePayload {
request_ulid: Option<ulid::Ulid>,
func_name: String,
status: ManagementFuncStatus,
message: Option<String>,
created_component_ids: Option<Vec<ComponentId>>,
}

impl WsEvent {
pub async fn management_func_executed(
ctx: &DalContext,
Expand All @@ -669,12 +679,33 @@ impl WsEvent {
) -> WsEventResult<Self> {
WsEvent::new(
ctx,
crate::WsPayload::ManagementFuncExecuted(ManagementFuncExecutedPayload {
WsPayload::ManagementFuncExecuted(ManagementFuncExecutedPayload {
prototype_id,
manager_component_id,
func_run_id,
}),
)
.await
}

pub async fn management_operations_complete(
ctx: &DalContext,
request_ulid: Option<ulid::Ulid>,
func_name: String,
message: Option<String>,
status: ManagementFuncStatus,
created_component_ids: Option<Vec<ComponentId>>,
) -> WsEventResult<Self> {
WsEvent::new(
ctx,
WsPayload::ManagementOperationsComplete(ManagementOperationsCompletePayload {
request_ulid,
func_name,
status,
message,
created_component_ids,
}),
)
.await
}
}
5 changes: 4 additions & 1 deletion lib/dal/src/ws_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ use crate::func::runner::FuncRunLogUpdatedPayload;
use crate::func::{
FuncWsEventCodeSaved, FuncWsEventFuncSummary, FuncWsEventGenerating, FuncWsEventPayload,
};
use crate::management::prototype::ManagementFuncExecutedPayload;
use crate::management::prototype::{
ManagementFuncExecutedPayload, ManagementOperationsCompletePayload,
};
use crate::pkg::{
ImportWorkspaceVotePayload, WorkspaceActorPayload, WorkspaceImportApprovalActorPayload,
};
Expand Down Expand Up @@ -113,6 +115,7 @@ pub enum WsPayload {
InferredEdgeRemove(InferredEdgeRemovePayload),
InferredEdgeUpsert(InferredEdgeUpsertPayload),
ManagementFuncExecuted(ManagementFuncExecutedPayload),
ManagementOperationsComplete(ManagementOperationsCompletePayload),
ModuleImported(Vec<si_frontend_types::SchemaVariant>),
Online(OnlinePayload),
PromptUpdated(PromptUpdatedPayload),
Expand Down
Loading

0 comments on commit c79c600

Please sign in to comment.