Skip to content

Commit

Permalink
Merge pull request #5019 from systeminit/zack/mgmt-funcs-in-views
Browse files Browse the repository at this point in the history
feat: management functions understand views
  • Loading branch information
zacharyhamm authored Nov 22, 2024
2 parents c06ec59 + da601f0 commit 9b47741
Show file tree
Hide file tree
Showing 23 changed files with 597 additions and 278 deletions.
41 changes: 39 additions & 2 deletions app/web/src/components/ManagementRunPrototype.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,18 @@
)
"
>
<IconButton icon="play" :requestStatus="request" @click="runPrototype()" />
<DropdownMenu ref="viewSelectorMenuRef" forceRight>
<DropdownMenuItem header label="RUN IN VIEW" />
<DropdownMenuItem
v-for="viewId in componentViews"
:key="viewId"
:label="viewsStore.viewsById[viewId]?.name ?? 'unknown'"
:onSelect="() => runPrototype(viewId)"
/>
</DropdownMenu>

<IconButton icon="play" :requestStatus="request" @click="runClick" />

<TruncateWithTooltip class="grow">{{
`Run ${props.prototype.label}`
}}</TruncateWithTooltip>
Expand All @@ -31,6 +42,8 @@ import { ref, computed, onMounted, watch } from "vue";
import clsx from "clsx";
import { useToast } from "vue-toastification";
import {
DropdownMenu,
DropdownMenuItem,
IconButton,
themeClasses,
TruncateWithTooltip,
Expand All @@ -44,6 +57,8 @@ import {
import { useComponentsStore } from "@/store/components.store";
import { FuncRunId } from "@/store/func_runs.store";
import { useManagementRunsStore } from "@/store/management_runs.store";
import { useViewsStore } from "@/store/views.store";
import { ViewId } from "@/api/sdf/dal/views";
import {
DiagramGroupData,
DiagramNodeData,
Expand All @@ -56,6 +71,9 @@ const componentsStore = useComponentsStore();
const router = useRouter();
const toast = useToast();
const managementRunsStore = useManagementRunsStore();
const viewsStore = useViewsStore();
const viewSelectorMenuRef = ref<InstanceType<typeof DropdownMenu>>();
const lastExecution = ref<MgmtPrototypeResult | undefined>(undefined);
Expand Down Expand Up @@ -89,16 +107,25 @@ const latestRunId = computed(() =>
),
);
const componentViews = computed(() =>
Object.keys(viewsStore.viewsById).filter(
(viewId) =>
!!viewsStore.viewsById[viewId]?.components[props.component.def.id] ||
!!viewsStore.viewsById[viewId]?.groups[props.component.def.id],
),
);
watch(latestRunId, (latest) => {
if (latest) {
emit("runUpdated", latest);
}
});
const runPrototype = async () => {
const runPrototype = async (viewId: ViewId) => {
const result = await funcStore.RUN_MGMT_PROTOTYPE(
props.prototype.managementPrototypeId,
props.component.def.id,
viewId,
);
if (result.result.success) {
Expand All @@ -123,6 +150,16 @@ const runPrototype = async () => {
}
};
const runClick = async (e?: MouseEvent) => {
if (componentViews.value.length === 1 && componentViews.value[0]) {
await runPrototype(componentViews.value[0]);
} else if (componentViews.value.length > 1) {
viewSelectorMenuRef.value?.open(e, false);
} else if (viewsStore.selectedViewId) {
await runPrototype(viewsStore.selectedViewId);
}
};
function onClickView() {
router.push({
name: "workspace-lab-assets",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,12 @@ const rightClickMenuItems = computed(() => {
const runManagementFunc = async (prototype: MgmtPrototype) => {
if (!selectedComponent.value) return;
if (!viewStore.selectedViewId) return;
const result = await funcStore.RUN_MGMT_PROTOTYPE(
prototype.managementPrototypeId,
selectedComponent.value.def.id,
viewStore.selectedViewId,
);
if (result.result.success && result.result.data.message) {
Expand Down
3 changes: 3 additions & 0 deletions app/web/src/store/func/funcs.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import { useAssetStore } from "@/store/asset.store";
import { SchemaVariant, SchemaVariantId } from "@/api/sdf/dal/schema";
import { DefaultMap } from "@/utils/defaultmap";
import { ComponentId } from "@/api/sdf/dal/component";
import { ViewId } from "@/api/sdf/dal/views";
import { useChangeSetsStore } from "../change_sets.store";
import { useRealtimeStore } from "../realtime/realtime.store";
import { useComponentsStore } from "../components.store";
Expand Down Expand Up @@ -287,6 +288,7 @@ export const useFuncStore = () => {
async RUN_MGMT_PROTOTYPE(
prototypeId: ManagementPrototypeId,
componentId: ComponentId,
viewId: ViewId,
) {
return new ApiRequest<MgmtPrototypeResult>({
method: "post",
Expand All @@ -296,6 +298,7 @@ export const useFuncStore = () => {
"prototype",
{ prototypeId },
{ componentId },
{ viewId },
]),
});
},
Expand Down
6 changes: 3 additions & 3 deletions bin/lang-js/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ export interface Component {
}

export interface Geometry {
x: number;
y: number;
x?: number;
y?: number;
width?: number;
height?: number;
}

export interface ComponentWithGeometry {
properties: Record<string, unknown>;
geometry: Geometry;
geometry: { [key: string]: Geometry };
}
43 changes: 24 additions & 19 deletions bin/lang-js/src/function_kinds/management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ import { RequestCtx } from "../request";
const debug = Debug("langJs:management");

export interface ManagementFunc extends Func {
currentView: string;
thisComponent: ComponentWithGeometry;
components: {
[key: string]: ComponentWithGeometry;
}
}

export type ManagementFuncResult =
| ManagementFuncResultSuccess
| ManagementFuncResultFailure;
| ManagementFuncResultSuccess
| ManagementFuncResultFailure;

export interface ManagmentConnect {
from: string,
Expand All @@ -32,22 +33,26 @@ export interface ManagmentConnect {
}

export interface ManagementOperations {
create?: { [key: string]: {
kind: string;
properties?: object;
geometry?: Geometry;
parent?: string;
connect?: ManagmentConnect[],
} };
update?: { [key: string]: {
properties?: object;
geometry?: Geometry;
parent?: string;
connect: {
add?: ManagmentConnect[],
remove?: ManagmentConnect[],
create?: {
[key: string]: {
kind: string;
properties?: object;
geometry?: Geometry;
parent?: string;
connect?: ManagmentConnect[],
}
} };
};
update?: {
[key: string]: {
properties?: object;
geometry?: { [key: string]: Geometry };
parent?: string;
connect: {
add?: ManagmentConnect[],
remove?: ManagmentConnect[],
}
}
};
actions?: {
[key: string]: {
add?: string[],
Expand All @@ -66,14 +71,14 @@ export interface ManagementFuncResultFailure extends ResultFailure { }
async function execute(
vm: NodeVM,
{ executionId }: RequestCtx,
{ thisComponent, components }: ManagementFunc,
{ thisComponent, components, currentView }: ManagementFunc,
code: string,
): Promise<ManagementFuncResult> {
let managementResult: Record<string, unknown> | undefined | null;
try {
const runner = vm.run(code);
managementResult = await new Promise((resolve) => {
runner({ thisComponent, components }, (resolution: Record<string, unknown>) => resolve(resolution));
runner({ thisComponent, components, currentView }, (resolution: Record<string, unknown>) => resolve(resolution));
});
} catch (err) {
return failureExecution(err as Error, executionId);
Expand Down
2 changes: 2 additions & 0 deletions lib/cyclone-client/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,7 @@ mod tests {
let req = ManagementRequest {
execution_id: "1234".to_string(),
handler: "manage".to_string(),
current_view: "DEFAULT".to_string(),
this_component: ComponentViewWithGeometry {
kind: None,
properties: serde_json::json!({"it": "is", "a": "principle", "of": "music", "to": "repeat the theme"}),
Expand Down Expand Up @@ -1409,6 +1410,7 @@ mod tests {
let req = ManagementRequest {
execution_id: "1234".to_string(),
handler: "manage".to_string(),
current_view: "DEFAULT".to_string(),
this_component: ComponentViewWithGeometry {
kind: None,
properties: serde_json::json!({"it": "is", "a": "principle", "of": "music", "to": "repeat the theme"}),
Expand Down
1 change: 1 addition & 0 deletions lib/cyclone-core/src/management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct ManagementRequest {
pub execution_id: String,
pub handler: String,
pub code_base64: String,
pub current_view: String,
pub this_component: ComponentViewWithGeometry,
pub components: HashMap<String, ComponentViewWithGeometry>,
pub before: Vec<BeforeFunction>,
Expand Down
4 changes: 4 additions & 0 deletions lib/dal-test/src/expected.rs
Original file line number Diff line number Diff line change
Expand Up @@ -880,4 +880,8 @@ impl ExpectView {
let name = generate_fake_name();
View::new(ctx, name).await.expect("create view")
}

pub async fn create_with_name(ctx: &DalContext, name: &str) -> View {
View::new(ctx, name).await.expect("create view")
}
}
48 changes: 48 additions & 0 deletions lib/dal-test/src/test_exclusive_schemas/legos/small.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,44 @@ pub(crate) async fn migrate_test_exclusive_schema_small_odd_lego(
let update_mgmt_func_name = "test:updateManagedComponent";
let update_mgmt_func = build_management_func(update_managed_func_code, update_mgmt_func_name)?;

let update_managed_func_in_view_code = r#"
async function main({ thisComponent, components, currentView }: Input): Promise<Output> {
const thisName = thisComponent.properties?.si?.name ?? "unknown";
const update: { [key: string]: unknown } = {};
for (let [id, component] of Object.entries(components)) {
let name = component.properties?.si?.name ?? "unknown";
update[id] = {
properties: {
...component.properties,
si: {
...component.properties?.si,
name: `${name} managed by ${thisName}`,
}
},
geometry: {
[currentView]: {
x: 1000,
y: 750,
}
}
};
}
return {
status: "ok",
message: currentView,
ops: { update },
}
}
"#;
let update_in_view_mgmt_func_name = "test:updateManagedComponentInView";
let update_in_view_mgmt_func = build_management_func(
update_managed_func_in_view_code,
update_in_view_mgmt_func_name,
)?;

let create_and_connect_from_self_func_code = r#"
async function main({ thisComponent, components }: Input): Promise<Output> {
const thisName = thisComponent.properties?.si?.name ?? "unknown";
Expand Down Expand Up @@ -353,6 +391,15 @@ pub(crate) async fn migrate_test_exclusive_schema_small_odd_lego(
.func_unique_id(&update_mgmt_func.unique_id)
.build()?,
)
.management_func(
ManagementFuncSpec::builder()
.name("Update in View")
.managed_schemas(Some(HashSet::from([
SCHEMA_ID_SMALL_EVEN_LEGO.to_string()
])))
.func_unique_id(&update_in_view_mgmt_func.unique_id)
.build()?,
)
.management_func(
ManagementFuncSpec::builder()
.name("Create and Connect From Self")
Expand Down Expand Up @@ -395,6 +442,7 @@ pub(crate) async fn migrate_test_exclusive_schema_small_odd_lego(
.func(import_management_func)
.func(clone_me_mgmt_func)
.func(update_mgmt_func)
.func(update_in_view_mgmt_func)
.func(create_and_connect_from_self_func)
.func(create_and_connect_to_self_func)
.func(create_and_connect_to_self_as_children_func)
Expand Down
16 changes: 8 additions & 8 deletions lib/dal/src/diagram/geometry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,20 @@ impl Geometry {
self.id
}

pub fn x(&self) -> &isize {
&self.x
pub fn x(&self) -> isize {
self.x
}

pub fn y(&self) -> &isize {
&self.y
pub fn y(&self) -> isize {
self.y
}

pub fn width(&self) -> Option<&isize> {
self.width.as_ref()
pub fn width(&self) -> Option<isize> {
self.width
}

pub fn height(&self) -> Option<&isize> {
self.height.as_ref()
pub fn height(&self) -> Option<isize> {
self.height
}

fn assemble(node_weight: GeometryNodeWeight, content: GeometryContent) -> Self {
Expand Down
2 changes: 2 additions & 0 deletions lib/dal/src/func/backend/management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use super::ExtractPayload;
pub struct FuncBackendManagementArgs {
this_component: ComponentViewWithGeometry,
components: HashMap<String, ComponentViewWithGeometry>,
current_view: String,
}

#[derive(Debug)]
Expand All @@ -41,6 +42,7 @@ impl FuncDispatch for FuncBackendManagement {
code_base64: code_base64.into(),
this_component: args.this_component,
components: args.components,
current_view: args.current_view,
before,
};

Expand Down
Loading

0 comments on commit 9b47741

Please sign in to comment.