Skip to content

Commit

Permalink
Merge pull request #5043 from systeminit/victor/eng-2866-can-change-s…
Browse files Browse the repository at this point in the history
…ocket-connections-to-things-not-in-this-view

feat: Manage socket connections from a form
  • Loading branch information
vbustamante authored Nov 29, 2024
2 parents 53aa84c + 4e4944c commit 03ac579
Show file tree
Hide file tree
Showing 7 changed files with 537 additions and 129 deletions.
9 changes: 8 additions & 1 deletion app/web/src/api/sdf/dal/property_editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ export interface PropertyEditorPropWidgetKindColor {
kind: "color";
}

export interface PropertyEditorPropWidgetKindSocketConnection {
kind: "socketConnection";
options: LabelList<string>;
isSingleArity: boolean;
}

export type PropertyEditorPropWidgetKind =
| PropertyEditorPropWidgetKindText
| PropertyEditorPropWidgetKindTextArea
Expand All @@ -83,7 +89,8 @@ export type PropertyEditorPropWidgetKind =
| PropertyEditorPropWidgetKindComboBox
| PropertyEditorPropWidgetKindSelect
| PropertyEditorPropWidgetKindSecret
| PropertyEditorPropWidgetKindColor;
| PropertyEditorPropWidgetKindColor
| PropertyEditorPropWidgetKindSocketConnection;

export interface PropertyEditorProp {
id: string;
Expand Down
14 changes: 7 additions & 7 deletions app/web/src/components/AttributesPanel/TreeForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
<TreeFormItem
v-for="tree in trees"
:key="tree.propId"
:context="useAttributesPanelContext"
:treeDef="tree"
isRootProp
:context="useAttributesPanelContext"
/>
</div>
</div>
Expand All @@ -35,14 +35,14 @@
<script lang="ts">
type EventBusEvents = { toggleAllOpen: boolean };
type ResetFunc = (item: TreeFormData) => void;
type UnsetFunc = (item: TreeFormData, valToUnset?: string) => void;
type SetValueFunc = (item: TreeFormData, newVal: string) => void;
export type TreeFormContext = {
eventBus: Emitter<EventBusEvents>;
hoverSectionValueId: Ref<string | undefined>;
showSectionToggles: Ref<boolean>;
resetValue: ResetFunc;
unsetValue: UnsetFunc;
setValue: SetValueFunc;
};
Expand Down Expand Up @@ -89,15 +89,15 @@ function onMouseLeave() {
}

const emit = defineEmits<{
(e: "reset", item: TreeFormData): void;
(e: "unsetValue", item: TreeFormData, value?: string): void;
(e: "setValue", item: TreeFormData, value: string): void;
}>();

// EXPOSED TO CHILDREN
const eventBus = mitt<EventBusEvents>();
const hoverSectionValueId = ref<string>();
const resetValue = (item: TreeFormData) => {
emit("reset", item);
const unsetValue = (item: TreeFormData, value?: string) => {
emit("unsetValue", item, value);
};
const setValue = (item: TreeFormData, value: string) => {
emit("setValue", item, value);
Expand All @@ -107,7 +107,7 @@ provide(AttributesPanelContextInjectionKey, {
eventBus,
hoverSectionValueId,
showSectionToggles,
resetValue,
unsetValue,
setValue,
});
</script>
122 changes: 101 additions & 21 deletions app/web/src/components/AttributesPanel/TreeFormItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
>
<!-- HEADER -->
<div
:class="
clsx('attributes-panel-item__section-header-wrap', 'sticky h-6')
"
:style="{
top: topPx,
zIndex: headerZIndex,
}"
:class="
clsx('attributes-panel-item__section-header-wrap', 'sticky h-6')
"
>
<div
:class="
Expand All @@ -51,13 +51,12 @@
: 'chevron--right'
: 'none'
"
size="inherit"
class="opacity-80 hover:opacity-100 hover:scale-110"
size="inherit"
/>
</div>

<div
:style="{ marginLeft: indentPx }"
:class="
clsx(
'attributes-panel-item__section-header',
Expand All @@ -71,6 +70,7 @@
themeClasses('text-shade-0 border-shade-0', 'border-neutral-800'),
)
"
:style="{ marginLeft: indentPx }"
@click="toggleOpen(true)"
>
<Icon
Expand Down Expand Up @@ -187,7 +187,6 @@
<!-- LEFT BORDER LINE -->
<div
v-show="isOpen && headerHasContent"
:style="{ marginLeft: indentPx, zIndex: headerZIndex }"
:class="
clsx(
'attributes-panel-item__left-border',
Expand All @@ -198,6 +197,7 @@
),
)
"
:style="{ marginLeft: indentPx, zIndex: headerZIndex }"
/>

<!-- CHILDREN -->
Expand All @@ -208,10 +208,10 @@
<TreeFormItem
v-for="childProp in treeDef.children"
:key="`${propName}/${childProp.propDef?.name}`"
:treeDef="childProp"
:level="level + 1"
:context="context"
:attributesPanel="attributesPanel"
:context="context"
:level="level + 1"
:treeDef="childProp"
/>

<div
Expand Down Expand Up @@ -278,9 +278,9 @@
@click="addChildHandler"
>
<Icon
class="ml-[-2px] w-[14px] h-[14px]"
name="plus"
size="none"
class="ml-[-2px] w-[14px] h-[14px]"
/>
{{ isArray ? "Add array item" : "Add map item" }}
</div>
Expand All @@ -297,17 +297,65 @@
</div>
</div>

<!-- SOCKET WIDGET INSIDE A SECTION -->
<div
v-else-if="widgetKind === 'socketConnection'"
:style="{ paddingLeft: indentPx }"
class="flex flex-col gap-xs"
>
<VormInput
v-if="!socketIsSingleArity || socketConnectionsList.length === 0"
:disabled="widgetOptions.length === 0"
:modelValue="socketDropdownValue"
:options="widgetOptions"
:placeholder="socketDropdownPlaceholder"
class="flex-grow font-bold mb-[-1px]"
noLabel
size="xs"
type="dropdown"
@update:model-value="updateValue"
/>
<div
v-for="peerSocket in socketConnectionsList"
:key="peerSocket.value"
class="flex px-xs"
>
<span
:class="
clsx('flex-grow', peerSocket.isImmutable && 'text-neutral-400')
"
>
{{ peerSocket.label }}
</span>

<IconButton
v-if="!peerSocket.isImmutable"
icon="trash"
size="sm"
@click="unsetHandler(peerSocket.value)"
/>
<IconButton
v-else
disabled
icon="question-circle"
iconTone="neutral"
tooltip="Connection can't be unmade because it's inferred from a parent. You can override it on the diagram"
/>
</div>
</div>

<!-- INDIVIDUAL PROP INSIDE A SECTION -->
<div
v-else
:style="{ paddingLeft: indentPx }"
:class="
clsx(
'attributes-panel-item__item-inner',
'relative flex flex-row items-center w-full pr-xs',
)
"
:style="{ paddingLeft: indentPx }"
>
<!-- Name of prop, to the left -->
<div
class="flex flex-row grow gap-xs relative overflow-hidden items-center"
>
Expand Down Expand Up @@ -375,6 +423,7 @@
</a>
</div>
</div>
<!-- Actual input, to the right -->
<div
:class="
clsx(
Expand Down Expand Up @@ -410,8 +459,6 @@
v-if="
noValue && !iconShouldBeHidden && !isFocus && !propPopulatedBySocket
"
:name="icon"
size="none"
:class="
clsx(
'absolute left-0 top-0 w-7 h-7 p-[3px] z-10 pointer-events-none',
Expand All @@ -420,6 +467,8 @@
: 'opacity-50',
)
"
:name="icon"
size="none"
/>
<Icon
v-if="unsetButtonShow"
Expand All @@ -434,7 +483,7 @@
)
"
name="x-circle"
@click="unsetHandler"
@click="unsetHandler()"
/>
<Icon
v-if="validation"
Expand Down Expand Up @@ -577,9 +626,9 @@
)
"
:disabled="!propIsEditable"
@blur="onBlur"
@change="updateValue"
@focus="onFocus"
@blur="onBlur"
>
<option
v-for="o in widgetOptions"
Expand Down Expand Up @@ -612,7 +661,7 @@
)
"
>
<Icon name="key" size="2xs" class="inline-block align-middle" />
<Icon class="inline-block align-middle" name="key" size="2xs" />
{{ secret.definition }} / {{ secret.name }}
</div>
<div
Expand Down Expand Up @@ -754,8 +803,8 @@
<template v-else-if="widgetKind === 'codeEditor'">
<CodeViewer
:code="newValueString"
disableScroll
class="max-h-[70vh]"
disableScroll
/>
</template>
</div>
Expand Down Expand Up @@ -830,6 +879,8 @@ import {
Modal,
themeClasses,
VButton,
VormInput,
IconButton,
} from "@si/vue-lib/design-system";
import {
AttributeTreeItem,
Expand Down Expand Up @@ -1230,7 +1281,6 @@ const newMapChildKeyIsValid = computed(() => {
function removeChildHandler() {
if (!isChildOfArray.value && !isChildOfMap.value) return;
if (props.attributesPanel) {
attributesStore.REMOVE_PROPERTY_VALUE({
attributeValueId: props.treeDef.valueId,
Expand Down Expand Up @@ -1284,7 +1334,7 @@ function addChildHandler() {
// TODO(Wendy) - make this functional for TreeForm when needed
}
}
function unsetHandler() {
function unsetHandler(value?: string) {
newValueBoolean.value = false;
newValueString.value = "";
Expand All @@ -1294,11 +1344,11 @@ function unsetHandler() {
});
} else {
const treeFormContext = rootCtx as TreeFormContext;
treeFormContext.resetValue(props.treeDef as TreeFormData);
treeFormContext.unsetValue(props.treeDef as TreeFormData, value);
}
}
function updateValue() {
function updateValue(maybeNewVal?: unknown) {
let newVal;
let skipUpdate = false;
let isForSecret = false;
Expand All @@ -1313,6 +1363,13 @@ function updateValue() {
} else {
newVal = newValueNumber.value;
}
} else if (widgetKind.value === "socketConnection") {
if (maybeNewVal && typeof maybeNewVal === "string") {
newVal = maybeNewVal;
socketDropdownValue.value = undefined;
} else {
skipUpdate = true;
}
} else {
// for now, we will always trim, but we need to be smarter about this
// meaning have options, and more generally have some cleaning / coercion logic...
Expand Down Expand Up @@ -1450,6 +1507,29 @@ const confirmEdit = () => {
const editOverride = ref(false);
const sourceSelectMenuRef = ref<InstanceType<typeof DropdownMenu>>();
const socketDropdownValue = ref();
const socketIsSingleArity = computed(() =>
"isSingleArity" in fullPropDef.value.widgetKind
? fullPropDef.value.widgetKind.isSingleArity
: false,
);
const socketDropdownPlaceholder = computed(() =>
widgetOptions.value.length > 0
? "Select to connect..."
: "No new connections available",
);
const socketConnectionsList = computed(() => {
if (!Array.isArray(currentValue.value)) return [];
return currentValue.value.filter(
(socket) =>
"label" in socket &&
typeof socket.label === "string" &&
"value" in socket &&
typeof socket.value === "string",
);
});
</script>

<style lang="less">
Expand Down
Loading

0 comments on commit 03ac579

Please sign in to comment.