Display warnings on components (#9108)

Closes #8678

[Peek 2024-02-20 12-45.webm](https://github.com/enso-org/enso/assets/1428930/6bb6c4ad-5507-4b11-b2c9-b295bf10c745)
This commit is contained in:
Michael Mauderer 2024-02-21 11:40:07 +00:00 committed by GitHub
parent 9daca288f4
commit 6c4c791d87
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 75 additions and 26 deletions

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { nodeEditBindings } from '@/bindings' import { nodeEditBindings } from '@/bindings'
import CircularMenu from '@/components/CircularMenu.vue' import CircularMenu from '@/components/CircularMenu.vue'
import GraphNodeError from '@/components/GraphEditor/GraphNodeError.vue' import GraphNodeError from '@/components/GraphEditor/GraphNodeMessage.vue'
import GraphVisualization from '@/components/GraphEditor/GraphVisualization.vue' import GraphVisualization from '@/components/GraphEditor/GraphVisualization.vue'
import NodeWidgetTree from '@/components/GraphEditor/NodeWidgetTree.vue' import NodeWidgetTree from '@/components/GraphEditor/NodeWidgetTree.vue'
import SvgIcon from '@/components/SvgIcon.vue' import SvgIcon from '@/components/SvgIcon.vue'
@ -107,6 +107,15 @@ const error = computed(() => {
} }
}) })
const warning = computed(() => {
const externalId = graph.db.idToExternal(nodeId.value)
if (!externalId) return
const info = projectStore.computedValueRegistry.db.get(externalId)
const warning = info?.payload.type === 'Value' ? info.payload.warnings?.value : undefined
if (!warning) return
return '⚠ Warning: ' + warning!
})
const isSelected = computed(() => nodeSelection?.isSelected(nodeId.value) ?? false) const isSelected = computed(() => nodeSelection?.isSelected(nodeId.value) ?? false)
watch(isSelected, (selected) => { watch(isSelected, (selected) => {
if (!selected) { if (!selected) {
@ -331,6 +340,8 @@ watchEffect(() => {
} }
}) })
const nodeHovered = ref(false)
function portGroupStyle(port: PortData) { function portGroupStyle(port: PortData) {
const [start, end] = port.clipRange const [start, end] = port.clipRange
return { return {
@ -368,6 +379,8 @@ function openFullMenu() {
['executionState-' + executionState]: true, ['executionState-' + executionState]: true,
}" }"
:data-node-id="nodeId" :data-node-id="nodeId"
@pointerenter="nodeHovered = true"
@pointerleave="nodeHovered = false"
> >
<div class="selection" v-on="dragPointer.events"></div> <div class="selection" v-on="dragPointer.events"></div>
<div class="binding" @pointerdown.stop> <div class="binding" @pointerdown.stop>
@ -409,7 +422,14 @@ function openFullMenu() {
<NodeWidgetTree :ast="displayedExpression" :nodeId="nodeId" /> <NodeWidgetTree :ast="displayedExpression" :nodeId="nodeId" />
</div> </div>
</div> </div>
<GraphNodeError v-if="error" class="error" :error="error" /> <GraphNodeError v-if="error" class="message" :message="error" type="error" />
<GraphNodeError
v-if="warning && (nodeHovered || isSelected)"
class="message warning"
:class="menuVisible === MenuState.Off ? '' : 'messageWithMenu'"
:message="warning"
type="warning"
/>
<svg class="bgPaths" :style="bgStyleVariables"> <svg class="bgPaths" :style="bgStyleVariables">
<rect class="bgFill" /> <rect class="bgFill" />
<template v-for="port of outputPorts" :key="port.portId"> <template v-for="port of outputPorts" :key="port.portId">
@ -631,9 +651,17 @@ function openFullMenu() {
z-index: 1; z-index: 1;
} }
.error { .message {
position: absolute; position: absolute;
top: 100%; top: 100%;
margin-top: 4px; margin-top: 4px;
} }
.messageWithMenu {
left: 40px;
}
.warning {
top: 35px;
}
</style> </style>

View File

@ -1,23 +0,0 @@
<script setup lang="ts">
const props = defineProps<{ error: string }>()
</script>
<template>
<div class="GraphNodeError" v-text="props.error"></div>
</template>
<style scoped>
.GraphNodeError {
display: flex;
height: 24px;
padding: 1px 8px;
align-items: flex-start;
gap: 10px;
font-weight: 800;
white-space: nowrap;
border-radius: var(--radius-full);
background-color: #e85252;
color: var(--color-text-inversed);
line-height: 20px;
}
</style>

View File

@ -0,0 +1,44 @@
<script setup lang="ts">
/// types of messages
export type GraphNodeMessageType = 'error' | 'warning'
const props = defineProps<{ message: string; type: GraphNodeMessageType }>()
function styleClassForType(type: GraphNodeMessageType) {
switch (type) {
case 'error':
return 'GraphNodeError'
case 'warning':
return 'GraphNodeWarning'
default:
return ''
}
}
</script>
<template>
<div class="GraphNodeMessage" :class="styleClassForType(props.type)" v-text="props.message"></div>
</template>
<style scoped>
.GraphNodeMessage {
display: flex;
height: 24px;
padding: 1px 8px;
align-items: flex-start;
gap: 10px;
font-weight: 800;
white-space: nowrap;
border-radius: var(--radius-full);
color: var(--color-text-inversed);
line-height: 20px;
}
.GraphNodeWarning {
background-color: #faa212;
}
.GraphNodeError {
background-color: #e85252;
}
</style>