Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change "Override Execution Context" button to "Record" button on nodes #9188

Merged
merged 28 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f62663c
Use new icon for overridding output context; prevent overriding the o…
somebody1234 Feb 26, 2024
ce58d66
Always show button to disable recording if recording is enabled
somebody1234 Feb 26, 2024
0bf492b
Fix appearance of Record/Record Once button in top bar
somebody1234 Feb 26, 2024
c3796fb
Fix bugs
somebody1234 Feb 26, 2024
432533d
WIP: does it work?
somebody1234 Feb 26, 2024
81c357f
Rename `OutputContext` to `Recording`
somebody1234 Feb 27, 2024
bdb9095
WIP: Attempt to fix
somebody1234 Feb 28, 2024
c533142
Merge branch 'develop' into wip/sb/toggle-recording-on-nodes
somebody1234 Feb 28, 2024
ba64a44
Minor fixes
somebody1234 Feb 28, 2024
0b88e82
Fix icon for nodes that are recording
somebody1234 Feb 28, 2024
3c3d168
Fix self argument detection
somebody1234 Feb 28, 2024
0a86911
Remove debug log
somebody1234 Feb 28, 2024
fa95176
Attempt (and fail) to fix bug
somebody1234 Feb 28, 2024
1856cd2
Fix obsolete FIXME
somebody1234 Feb 28, 2024
81a26c9
Merge branch 'develop' into wip/sb/toggle-recording-on-nodes
somebody1234 Feb 29, 2024
3f03d53
Address review
somebody1234 Feb 29, 2024
0eabbb2
Merge branch 'develop' into wip/sb/toggle-recording-on-nodes
somebody1234 Feb 29, 2024
e817f45
Fix tests
somebody1234 Feb 29, 2024
1a8cad3
Fix tests?
somebody1234 Feb 29, 2024
834dddd
Merge branch 'develop' into wip/sb/toggle-recording-on-nodes
somebody1234 Mar 6, 2024
3d02abd
Merge branch 'develop' into wip/sb/toggle-recording-on-nodes
mergify[bot] Mar 6, 2024
5dc3765
Use .. to identify autoscoped constructors (#9285)
JaroslavTulach Mar 6, 2024
5bb6c91
Extract tests to their own files (#9229)
somebody1234 Mar 6, 2024
9101626
Fix tests
somebody1234 Mar 6, 2024
c1ad57b
Restore whenReady, as I do not see the freeze (#9262)
farmaazon Mar 6, 2024
6bf8153
Merge branch 'develop' into wip/sb/toggle-recording-on-nodes
somebody1234 Mar 7, 2024
324c92f
Merge branch 'develop' into wip/sb/toggle-recording-on-nodes
somebody1234 Mar 8, 2024
64b3611
Fix E2E tests
somebody1234 Mar 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 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.
22 changes: 9 additions & 13 deletions app/gui2/src/components/CircularMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import SvgIcon from '@/components/SvgIcon.vue'
import ToggleIcon from '@/components/ToggleIcon.vue'

const props = defineProps<{
isOutputContextEnabledGlobally: boolean
isOutputContextOverridden: boolean
isRecordingEnabledGlobally: boolean
isRecordingOverridden: boolean
isDocsVisible: boolean
isVisualizationVisible: boolean
isFullMenuVisible: boolean
}>()
const emit = defineEmits<{
'update:isOutputContextOverridden': [isOutputContextOverridden: boolean]
'update:isRecordingOverridden': [isRecordingOverridden: boolean]
'update:isDocsVisible': [isDocsVisible: boolean]
'update:isVisualizationVisible': [isVisualizationVisible: boolean]
startEditing: []
Expand Down Expand Up @@ -38,16 +38,12 @@ const emit = defineEmits<{
@click.stop="emit('startEditing')"
/>
<ToggleIcon
:icon="props.isOutputContextEnabledGlobally ? 'no_auto_replay' : 'auto_replay'"
icon="record"
class="icon-container button slot7"
:class="{ 'output-context-overridden': props.isOutputContextOverridden }"
:alt="`${
props.isOutputContextEnabledGlobally != props.isOutputContextOverridden
? 'Disable'
: 'Enable'
} output context`"
:modelValue="props.isOutputContextOverridden"
@update:modelValue="emit('update:isOutputContextOverridden', $event)"
:class="{ 'output-context-overridden': props.isRecordingOverridden }"
:alt="`${props.isRecordingOverridden ? 'Disable' : 'Enable'} recording`"
:modelValue="props.isRecordingOverridden"
@update:modelValue="emit('update:isRecordingOverridden', $event)"
/>
</div>
</template>
Expand Down Expand Up @@ -187,7 +183,7 @@ const emit = defineEmits<{
.slot7 {
position: absolute;
top: 44px;
left: 9px;
left: 8px;
}

.slot8 {
Expand Down
2 changes: 1 addition & 1 deletion app/gui2/src/components/ComponentBrowser/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ export function useComponentBrowserInput(
}
break
case 'editNode':
code.value = graphDb.nodeIdToNode.get(usage.node)?.rootSpan.code() ?? ''
code.value = graphDb.nodeIdToNode.get(usage.node)?.innerExpr.code() ?? ''
selection.value = { start: usage.cursorPos, end: usage.cursorPos }
break
}
Expand Down
2 changes: 1 addition & 1 deletion app/gui2/src/components/GraphEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ function copyNodeContent() {
const id = nodeSelection.selected.values().next().value
const node = graphStore.db.nodeIdToNode.get(id)
if (!node) return
const content = node.rootSpan.code()
const content = node.innerExpr.code()
const nodeMetadata = node.rootSpan.nodeMetadata
const metadata = {
position: nodeMetadata.get('position'),
Expand Down
111 changes: 46 additions & 65 deletions app/gui2/src/components/GraphEditor/GraphNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import CircularMenu from '@/components/CircularMenu.vue'
import GraphNodeError from '@/components/GraphEditor/GraphNodeMessage.vue'
import GraphVisualization from '@/components/GraphEditor/GraphVisualization.vue'
import NodeWidgetTree from '@/components/GraphEditor/NodeWidgetTree.vue'
import SvgIcon from '@/components/SvgIcon.vue'
import { useApproach } from '@/composables/animation'
import { useDoubleClick } from '@/composables/doubleClick'
import { usePointer, useResizeObserver } from '@/composables/events'
Expand All @@ -14,7 +15,7 @@ import { asNodeId } from '@/stores/graph/graphDatabase'
import { useProjectStore } from '@/stores/project'
import { Ast } from '@/util/ast'
import type { AstId } from '@/util/ast/abstract'
import { Prefixes } from '@/util/ast/prefixes'
import { prefixes } from '@/util/ast/node'
import type { Opt } from '@/util/data/opt'
import { Rect } from '@/util/data/rect'
import { Vec2 } from '@/util/data/vec2'
Expand All @@ -26,16 +27,6 @@ import { computed, onUnmounted, ref, watch, watchEffect } from 'vue'
const MAXIMUM_CLICK_LENGTH_MS = 300
const MAXIMUM_CLICK_DISTANCE_SQ = 50

const prefixes = Prefixes.FromLines({
enableOutputContext:
'Standard.Base.Runtime.with_enabled_context Standard.Base.Runtime.Context.Output __ <| __',
disableOutputContext:
'Standard.Base.Runtime.with_disabled_context Standard.Base.Runtime.Context.Output __ <| __',
// Currently unused; included as PoC.
skip: 'SKIP __',
freeze: 'FREEZE __',
})

const props = defineProps<{
node: Node
edited: boolean
Expand Down Expand Up @@ -69,11 +60,10 @@ const outputPortsSet = computed(() => {

const widthOverridePx = ref<number>()
const nodeId = computed(() => asNodeId(props.node.rootSpan.id))
const externalId = computed(() => props.node.rootSpan.externalId)
const potentialSelfArgumentId = computed(() => props.node.primarySubject)
const connectedSelfArgumentId = computed(() =>
props.node.primarySubject && graph.isConnectedTarget(props.node.primarySubject)
? props.node.primarySubject
potentialSelfArgumentId.value && graph.isConnectedTarget(potentialSelfArgumentId.value)
? potentialSelfArgumentId.value
: undefined,
)

Expand All @@ -84,7 +74,7 @@ const contentNode = ref<HTMLElement>()
const nodeSize = useResizeObserver(rootNode)
const baseNodeSize = computed(() => new Vec2(contentNode.value?.scrollWidth ?? 0, nodeSize.value.y))

/// Menu can be full, partial or off
/** The menu can be full, partial or off */
enum MenuState {
Full,
Partial,
Expand Down Expand Up @@ -135,15 +125,16 @@ watchEffect(() => {
})

const bgStyleVariables = computed(() => {
const { x: width, y: height } = nodeSize.value
return {
'--node-width': `${nodeSize.value.x}px`,
'--node-height': `${nodeSize.value.y}px`,
'--node-width': `${width}px`,
'--node-height': `${height}px`,
}
})

const transform = computed(() => {
let pos = props.node.position
return `translate(${pos.x}px, ${pos.y}px)`
const { x, y } = props.node.position
return `translate(${x}px, ${y}px)`
})

const startEpochMs = ref(0)
Expand Down Expand Up @@ -183,62 +174,30 @@ const dragPointer = usePointer((pos, event, type) => {
}
})

const matches = computed(() => prefixes.extractMatches(props.node.rootSpan))
const displayedExpression = computed(() => props.node.rootSpan.module.get(matches.value.innerExpr))

const isOutputContextOverridden = computed({
const isRecordingOverridden = computed({
get() {
const override =
matches.value.matches.enableOutputContext ?? matches.value.matches.disableOutputContext
const overrideEnabled = matches.value.matches.enableOutputContext != null
// An override is only counted as enabled if it is currently in effect. This requires:
// - that an override exists
if (!override) return false
// - that it is setting the "enabled" value to a non-default value
else if (overrideEnabled === projectStore.isOutputContextEnabled) return false
// - and that it applies to the current execution context.
else {
const module = props.node.rootSpan.module
const contextWithoutQuotes = module
.get(override[0])
?.code()
.replace(/^['"]|['"]$/g, '')
return contextWithoutQuotes === projectStore.executionMode
}
return props.node.prefixes.enableRecording != null
},
set(shouldOverride) {
const module = projectStore.module
if (!module) return
const edit = props.node.rootSpan.module.edit()
const replacementText = shouldOverride
? [Ast.TextLiteral.new(projectStore.executionMode, edit)]
: undefined
const replacements = projectStore.isOutputContextEnabled
? {
enableOutputContext: undefined,
disableOutputContext: replacementText,
}
: {
enableOutputContext: replacementText,
disableOutputContext: undefined,
}
prefixes.modify(edit.getVersion(props.node.rootSpan), replacements)
const replacement =
shouldOverride && !projectStore.isRecordingEnabled
? [Ast.TextLiteral.new(projectStore.executionMode, edit)]
: undefined
prefixes.modify(edit.getVersion(props.node.rootSpan), { enableRecording: replacement })
graph.commitEdit(edit)
},
})

// FIXME [sb]: https://github.com/enso-org/enso/issues/8442
// This does not take into account `displayedExpression`.
const expressionInfo = computed(() => graph.db.getExpressionInfo(externalId.value))
const expressionInfo = computed(() => graph.db.getExpressionInfo(props.node.innerExpr.externalId))
const outputPortLabel = computed(() => expressionInfo.value?.typename ?? 'Unknown')
const executionState = computed(() => expressionInfo.value?.payload.type ?? 'Unknown')
const suggestionEntry = computed(() => graph.db.nodeMainSuggestion.lookup(nodeId.value))
const color = computed(() => graph.db.getNodeColorStyle(nodeId.value))
const icon = computed(() => {
const expressionInfo = graph.db.getExpressionInfo(externalId.value)
return displayedIconOf(
suggestionEntry.value,
expressionInfo?.methodCall?.methodPointer,
expressionInfo.value?.methodCall?.methodPointer,
outputPortLabel.value,
)
})
Expand Down Expand Up @@ -391,11 +350,18 @@ function openFullMenu() {
<div class="binding" @pointerdown.stop>
{{ node.pattern?.code() ?? '' }}
</div>
<button
v-if="menuVisible === MenuState.Off && isRecordingOverridden"
class="overrideRecordButton"
@click="isRecordingOverridden = false"
>
<SvgIcon name="record" />
</button>
<CircularMenu
v-if="menuVisible === MenuState.Full || menuVisible === MenuState.Partial"
v-model:isOutputContextOverridden="isOutputContextOverridden"
v-model:isRecordingOverridden="isRecordingOverridden"
v-model:isDocsVisible="isDocsVisible"
:isOutputContextEnabledGlobally="projectStore.isOutputContextEnabled"
:isRecordingEnabledGlobally="projectStore.isRecordingEnabled"
:isVisualizationVisible="isVisualizationVisible"
:isFullMenuVisible="menuVisible === MenuState.Full"
@update:isVisualizationVisible="emit('update:visualizationVisible', $event)"
Expand All @@ -407,8 +373,8 @@ function openFullMenu() {
:scale="navigator?.scale ?? 1"
:nodePosition="props.node.position"
:isCircularMenuVisible="menuVisible === MenuState.Full || menuVisible === MenuState.Partial"
:currentType="node.vis?.identifier"
:dataSource="{ type: 'node', nodeId: externalId }"
:currentType="props.node.vis?.identifier"
:dataSource="{ type: 'node', nodeId: props.node.rootSpan.externalId }"
:typename="expressionInfo?.typename"
@update:rect="
emit('update:visualizationRect', $event),
Expand All @@ -426,7 +392,7 @@ function openFullMenu() {
@pointerup.stop
>
<NodeWidgetTree
:ast="displayedExpression"
:ast="props.node.innerExpr"
:nodeId="nodeId"
:icon="icon"
:connectedSelfArgumentId="connectedSelfArgumentId"
Expand Down Expand Up @@ -671,4 +637,19 @@ function openFullMenu() {
.warning {
top: 35px;
}

.overrideRecordButton {
position: absolute;
cursor: pointer;
display: flex;
align-items: center;
backdrop-filter: var(--blur-app-bg);
background: var(--color-app-bg);
border-radius: var(--radius-full);
color: red;
padding: 8px;
height: 100%;
right: 100%;
margin-right: 4px;
}
</style>
2 changes: 1 addition & 1 deletion app/gui2/src/components/GraphEditor/collapsing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ if (import.meta.vitest) {
const nodePatternToId = new Map<string, NodeId>()
for (const code of testCase.initialNodes) {
const [pattern, expr] = code.split(/\s*=\s*/)
const [id, _] = nodes.find(([_id, node]) => node.rootSpan.code() == expr)!
const [id, _] = nodes.find(([_id, node]) => node.innerExpr.code() == expr)!
nodeCodeToId.set(code, id)
if (pattern != null) nodePatternToId.set(pattern, id)
}
Expand Down
24 changes: 15 additions & 9 deletions app/gui2/src/components/RecordControl.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const emit = defineEmits<{ recordOnce: []; 'update:recordMode': [enabled: boolea

<template>
<div class="RecordControl" @pointerdown.stop @pointerup.stop @click.stop>
<div class="control left-end">
<div class="control left-end" @click.stop="() => emit('update:recordMode', !props.recordMode)">
<ToggleIcon
icon="record"
class="button"
Expand All @@ -17,14 +17,8 @@ const emit = defineEmits<{ recordOnce: []; 'update:recordMode': [enabled: boolea
@update:modelValue="emit('update:recordMode', $event)"
/>
</div>
<div class="control right-end">
<SvgIcon
alt="Record once"
class="button"
name="record_once"
draggable="false"
@click.stop="() => emit('recordOnce')"
/>
<div class="control right-end" @click.stop="() => emit('recordOnce')">
<SvgIcon alt="Record once" class="button" name="record_once" draggable="false" :scale="1.5" />
</div>
</div>
</template>
Expand All @@ -41,14 +35,26 @@ const emit = defineEmits<{ recordOnce: []; 'update:recordMode': [enabled: boolea
background: var(--color-frame-bg);
backdrop-filter: var(--blur-app-bg);
padding: 8px 8px;
width: 42px;
cursor: pointer;
}

.left-end {
border-radius: var(--radius-full) 0 0 var(--radius-full);

.button {
margin: 0 4px 0 auto;
}
}

.right-end {
border-radius: 0 var(--radius-full) var(--radius-full) 0;

.button {
position: relative;
top: -4px;
margin: 0 auto 0 0;
}
}

.toggledOn {
Expand Down
17 changes: 15 additions & 2 deletions app/gui2/src/components/SvgIcon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,22 @@ import icons from '@/assets/icons.svg'
import type { URLString } from '@/util/data/urlString'
import type { Icon } from '@/util/iconName'

const props = defineProps<{ name: Icon | URLString; width?: number; height?: number }>()
const props = defineProps<{
name: Icon | URLString
width?: number
height?: number
scale?: number
}>()
</script>

<template>
<svg :style="{ '--width': `${width ?? 16}px`, '--height': `${height ?? 16}px` }">
<svg
:style="{
'--width': `${props.width ?? 16}px`,
'--height': `${props.height ?? 16}px`,
'--scale': props.scale ?? 1,
}"
>
<use :href="props.name.includes(':') ? props.name : `${icons}#${props.name}`"></use>
</svg>
</template>
Expand All @@ -23,5 +34,7 @@ svg {
min-width: var(--width);
height: var(--height);
min-height: var(--height);
transform: scale(var(--scale));
transform-origin: top left;
}
</style>
Loading
Loading