Skip to content

Commit

Permalink
Merge branch 'develop' into wip/jtulach/ChainedOperator_7904
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Dec 1, 2023
2 parents 472b9a7 + 2707262 commit fee11f7
Show file tree
Hide file tree
Showing 115 changed files with 2,695 additions and 739 deletions.
4 changes: 3 additions & 1 deletion app/gui2/shared/languageServerTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,9 @@ export function methodPointerEquals(left: MethodPointer, right: MethodPointer):
)
}

export type ProfilingInfo = ExecutionTime
export interface ProfilingInfo {
ExecutionTime: ExecutionTime
}

export interface ExecutionTime {
/** The time elapsed during the expression's evaluation, in nanoseconds */
Expand Down
6 changes: 5 additions & 1 deletion app/gui2/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
<script setup lang="ts">
import { provideAppClassSet } from '@/providers/appClass'
import { provideGuiConfig, type GuiConfig } from '@/providers/guiConfig'
import { useSuggestionDbStore } from '@/stores/suggestionDatabase'
import ProjectView from '@/views/ProjectView.vue'
import { onMounted, toRef } from 'vue'
const props = defineProps<{
config: GuiConfig
metadata: object
}>()
const classSet = provideAppClassSet()
provideGuiConfig(toRef(props, 'config'))
// Initialize suggestion db immediately, so it will be ready when user needs it.
onMounted(() => useSuggestionDbStore())
</script>

<template>
<ProjectView class="App flex" />
<ProjectView class="App flex" :class="[...classSet.keys()]" />
</template>

<style scoped>
Expand Down
17 changes: 9 additions & 8 deletions app/gui2/src/assets/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@

--vt-c-indigo: #2c3e50;

--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-divider-light-1: rgba(60 60 60 / 0.29);
--vt-c-divider-light-2: rgba(60 60 60 / 0.12);
--vt-c-divider-dark-1: rgba(84 84 84 / 0.65);
--vt-c-divider-dark-2: rgba(84 84 84 / 0.48);

--vt-c-text-light-1: rgba(118, 118, 118, 1);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-light-1: rgba(118 118 118);
--vt-c-text-light-2: rgba(60 60 60 / 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
--vt-c-text-dark-2: rgba(235 235 235 / 0.64);
}

/* semantic color variables for this project */
Expand All @@ -36,7 +36,8 @@
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);

--color-text-light: rgba(255, 255, 255, 0.7);
--color-text-light: rgba(255 255 255 / 0.7);
--color-text-inversed: rgba(255 255 255);
--color-app-bg: rgba(255 255 255 / 0.8);
--color-menu-entry-hover-bg: rgba(0 0 0 / 0.1);
--color-visualization-bg: rgb(255 242 242);
Expand Down
17 changes: 11 additions & 6 deletions app/gui2/src/assets/icons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 12 additions & 1 deletion app/gui2/src/components/CodeEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ const expressionUpdatesDiagnostics = computed(() => {
break
}
case 'DataflowError': {
diagnostics.push({ from, to, message: 'Unknown data flow error', severity: 'error' })
const error = projectStore.dataflowErrors.lookup(id)
if (error?.value?.message) {
diagnostics.push({ from, to, message: error.value.message, severity: 'error' })
}
break
}
}
Expand Down Expand Up @@ -116,6 +119,14 @@ watchEffect(() => {
.appendChild(document.createElement('div'))
.appendChild(document.createTextNode(`Type: ${expressionInfo.typename ?? 'Unknown'}`))
}
if (expressionInfo?.profilingInfo[0] != null) {
const profile = expressionInfo.profilingInfo[0]
const executionTime = (profile.ExecutionTime.nanoTime / 1_000_000).toFixed(3)
const text = `Execution Time: ${executionTime}ms`
dom
.appendChild(document.createElement('div'))
.appendChild(document.createTextNode(text))
}
dom
.appendChild(document.createElement('div'))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { GraphDb } from '@/stores/graph/graphDatabase'
import type { RequiredImport } from '@/stores/graph/imports'
import { ComputedValueRegistry } from '@/stores/project/computedValueRegistry'
import { SuggestionDb } from '@/stores/suggestionDatabase'
import {
makeCon,
Expand All @@ -12,7 +13,6 @@ import {
makeType,
type SuggestionEntry,
} from '@/stores/suggestionDatabase/entry'
import { ComputedValueRegistry } from '@/util/computedValueRegistry'
import { tryIdentifier, tryQualifiedName } from '@/util/qualifiedName'
import { unwrap } from '@/util/result'
import type { ExprId } from 'shared/yjsModel'
Expand Down
22 changes: 9 additions & 13 deletions app/gui2/src/components/GraphEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,23 +65,21 @@ const interactionBindingsHandler = interactionBindings.handler({
// or the node that is being edited when creating from a port double click.
function environmentForNodes(nodeIds: IterableIterator<ExprId>): Environment {
const nodeRects = [...graphStore.nodeRects.values()]
const selectedNodeRects: Iterable<Rect> = [...nodeIds]
const selectedNodeRects = [...nodeIds]
.map((id) => graphStore.nodeRects.get(id))
.filter((item): item is Rect => item !== undefined)
const screenBounds = graphNavigator.viewport
const mousePosition = graphNavigator.sceneMousePos
return { nodeRects, selectedNodeRects, screenBounds, mousePosition } as Environment
}
const placementEnvironment = computed(() => {
return environmentForNodes(nodeSelection.selected.values())
})
const placementEnvironment = computed(() => environmentForNodes(nodeSelection.selected.values()))
// Return the position for a new node, assuming there are currently nodes selected. If there are no nodes
// selected, return undefined.
/** Return the position for a new node, assuming there are currently nodes selected. If there are no nodes
* selected, return `undefined`. */
function placementPositionForSelection() {
const hasNodeSelected = nodeSelection.selected.size > 0
if (!hasNodeSelected) return undefined
if (!hasNodeSelected) return
const gapBetweenNodes = 48.0
return previousNodeDictatedPlacement(DEFAULT_NODE_SIZE, placementEnvironment.value, {
horizontalGap: gapBetweenNodes,
Expand All @@ -98,12 +96,10 @@ function targetComponentBrowserPosition() {
const targetPos = targetNode?.position ?? Vec2.Zero
return targetPos.add(COMPONENT_BROWSER_TO_NODE_OFFSET)
} else {
const targetPos = placementPositionForSelection()
if (targetPos != undefined) {
return targetPos
} else {
return mouseDictatedPlacement(DEFAULT_NODE_SIZE, placementEnvironment.value).position
}
return (
placementPositionForSelection() ??
mouseDictatedPlacement(DEFAULT_NODE_SIZE, placementEnvironment.value).position
)
}
}
Expand Down
79 changes: 60 additions & 19 deletions app/gui2/src/components/GraphEditor/GraphNode.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
<script setup lang="ts">
import { nodeEditBindings } from '@/bindings'
import CircularMenu from '@/components/CircularMenu.vue'
import GraphNodeError from '@/components/GraphEditor/GraphNodeError.vue'
import GraphVisualization from '@/components/GraphEditor/GraphVisualization.vue'
import NodeWidgetTree from '@/components/GraphEditor/NodeWidgetTree.vue'
import SvgIcon from '@/components/SvgIcon.vue'
import { useDoubleClick } from '@/composables/doubleClick'
import { injectGraphNavigator } from '@/providers/graphNavigator'
import { injectGraphSelection } from '@/providers/graphSelection'
import { useGraphStore, type Node } from '@/stores/graph'
import { useProjectStore } from '@/stores/project'
import { useApproach } from '@/util/animation'
import { usePointer, useResizeObserver } from '@/util/events'
import { displayedIconOf } from '@/util/getIconName'
Expand All @@ -19,41 +22,65 @@ import { computed, ref, watch, watchEffect } from 'vue'
const MAXIMUM_CLICK_LENGTH_MS = 300
const MAXIMUM_CLICK_DISTANCE_SQ = 50
/** The width in pixels that is not the widget tree. This includes the icon, and padding. */
const NODE_EXTRA_WIDTH_PX = 30
const props = defineProps<{
node: Node
edited: boolean
}>()
const emit = defineEmits<{
updateRect: [rect: Rect]
updateContent: [updates: [range: ContentRange, content: string][]]
dragging: [offset: Vec2]
draggingCommited: []
setVisualizationId: [id: Opt<VisualizationIdentifier>]
setVisualizationVisible: [visible: boolean]
delete: []
replaceSelection: []
'update:selected': [selected: boolean]
outputPortClick: [portId: ExprId]
outputPortDoubleClick: [portId: ExprId]
'update:content': [updates: [range: ContentRange, content: string][]]
'update:edited': [cursorPosition: number]
'update:rect': [rect: Rect]
'update:selected': [selected: boolean]
'update:visualizationId': [id: Opt<VisualizationIdentifier>]
'update:visualizationRect': [rect: Rect | undefined]
'update:visualizationVisible': [visible: boolean]
}>()
const nodeSelection = injectGraphSelection(true)
const projectStore = useProjectStore()
const graph = useGraphStore()
const navigator = injectGraphNavigator(true)
const outputPortsSet = computed(() => {
const bindings = graph.db.nodeOutputPorts.lookup(nodeId.value)
if (bindings.size === 0) return new Set([nodeId.value])
return bindings
})
const widthOverridePx = ref<number>()
const nodeId = computed(() => props.node.rootSpan.astId)
const rootNode = ref<HTMLElement>()
const contentNode = ref<HTMLElement>()
const nodeSize = useResizeObserver(rootNode)
const baseNodeSize = computed(
() => new Vec2((contentNode.value?.scrollWidth ?? 0) + NODE_EXTRA_WIDTH_PX, nodeSize.value.y),
)
const menuVisible = ref(false)
const error = computed(() => {
const info = projectStore.computedValueRegistry.db.get(nodeId.value)
switch (info?.payload.type) {
case 'Panic': {
return info.payload.message
}
case 'DataflowError': {
return projectStore.dataflowErrors.lookup(nodeId.value)?.value?.message.split(' (at')[0]
}
default:
return undefined
}
})
const isSelected = computed(() => nodeSelection?.isSelected(nodeId.value) ?? false)
watch(isSelected, (selected) => {
menuVisible.value = menuVisible.value && selected
Expand All @@ -66,7 +93,7 @@ const isVisualizationVisible = computed(() => props.node.vis?.visible ?? false)
watchEffect(() => {
const size = nodeSize.value
if (!size.isZero()) {
emit('updateRect', new Rect(props.node.position, nodeSize.value))
emit('update:rect', new Rect(props.node.position, nodeSize.value))
}
})
Expand Down Expand Up @@ -155,14 +182,13 @@ function startEditingNode(position: Vec2 | undefined) {
domOffset = caret?.startOffset
} else {
console.error(
'Neither caretPositionFromPoint nor caretRangeFromPoint are supported by this browser',
'Neither `caretPositionFromPoint` nor `caretRangeFromPoint` are supported by this browser',
)
}
if (domNode != null && domOffset != null) {
sourceOffset = getRelatedSpanOffset(domNode, domOffset)
}
}
emit('update:edited', sourceOffset)
}
Expand Down Expand Up @@ -243,6 +269,10 @@ function portGroupStyle(port: PortData) {
class="GraphNode"
:style="{
transform,
width:
widthOverridePx != null && isVisualizationVisible
? `${Math.max(widthOverridePx, (contentNode?.scrollWidth ?? 0) + NODE_EXTRA_WIDTH_PX)}px`
: undefined,
'--node-group-color': color,
}"
:class="{
Expand All @@ -262,27 +292,31 @@ function portGroupStyle(port: PortData) {
v-model:isAutoEvaluationDisabled="isAutoEvaluationDisabled"
v-model:isDocsVisible="isDocsVisible"
:isVisualizationVisible="isVisualizationVisible"
@update:isVisualizationVisible="emit('setVisualizationVisible', $event)"
@update:isVisualizationVisible="emit('update:visualizationVisible', $event)"
/>
<GraphVisualization
v-if="isVisualizationVisible"
:nodeSize="nodeSize"
:nodeSize="baseNodeSize"
:scale="navigator?.scale ?? 1"
:nodePosition="props.node.position"
:isCircularMenuVisible="menuVisible"
:currentType="props.node.vis"
:expressionId="props.node.rootSpan.astId"
:typename="expressionInfo?.typename"
@setVisualizationId="emit('setVisualizationId', $event)"
@setVisualizationVisible="emit('setVisualizationVisible', $event)"
@update:rect="
emit('update:visualizationRect', $event),
(widthOverridePx = $event && $event.size.x > baseNodeSize.x ? $event.size.x : undefined)
"
@update:id="emit('update:visualizationId', $event)"
@update:visible="emit('update:visualizationVisible', $event)"
/>
<div
class="node"
@pointerdown.capture="nodeEditHandler"
@keydown="nodeEditHandler"
v-on="dragPointer.events"
>
<div class="node" @keydown="nodeEditHandler">
<SvgIcon class="icon grab-handle" :name="icon"></SvgIcon>
<NodeWidgetTree :ast="node.rootSpan" />
<div ref="contentNode" class="widget-tree">
<NodeWidgetTree :ast="node.rootSpan" />
</div>
</div>
<GraphNodeError v-if="error" class="error" :error="error" />
<svg class="bgPaths" :style="bgStyleVariables">
<rect class="bgFill" />
<template v-for="port of outputPorts" :key="port.portId">
Expand Down Expand Up @@ -423,6 +457,7 @@ function portGroupStyle(port: PortData) {
align-items: center;
white-space: nowrap;
padding: 4px;
padding-right: 8px;
z-index: 2;
transition: outline 0.2s ease;
outline: 0px solid transparent;
Expand Down Expand Up @@ -496,4 +531,10 @@ function portGroupStyle(port: PortData) {
.CircularMenu {
z-index: 1;
}
.error {
position: absolute;
top: 100%;
margin-top: 4px;
}
</style>
Loading

0 comments on commit fee11f7

Please sign in to comment.