Report more errors to the user (#8623)

This commit is contained in:
Michael Mauderer 2024-01-04 14:12:03 +01:00 committed by GitHub
parent bf8dd1888c
commit cd30815c05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 36 deletions

View File

@ -29,12 +29,12 @@ import { colorFromString } from '@/util/colors'
import { Rect } from '@/util/data/rect' import { Rect } from '@/util/data/rect'
import { Vec2 } from '@/util/data/vec2' import { Vec2 } from '@/util/data/vec2'
import * as set from 'lib0/set' import * as set from 'lib0/set'
import { toast } from 'react-toastify'
import type { ExprId, NodeMetadata } from 'shared/yjsModel' import type { ExprId, NodeMetadata } from 'shared/yjsModel'
import { computed, onMounted, onScopeDispose, ref, watch } from 'vue' import { computed, onMounted, onScopeDispose, onUnmounted, ref, watch } from 'vue'
import { toast, type Id as ToastId } from 'vue3-toastify' import { ProjectManagerEvents } from '../../../ide-desktop/lib/dashboard/src/authentication/src/dashboard/projectManager'
import { type Usage } from './ComponentBrowser/input' import { type Usage } from './ComponentBrowser/input'
const STARTUP_TOAST_DELAY_MS = 100
const EXECUTION_MODES = ['design', 'live'] const EXECUTION_MODES = ['design', 'live']
// Assumed size of a newly created node. This is used to place the component browser. // Assumed size of a newly created node. This is used to place the component browser.
const DEFAULT_NODE_SIZE = new Vec2(0, 24) const DEFAULT_NODE_SIZE = new Vec2(0, 24)
@ -52,18 +52,52 @@ const componentBrowserUsage = ref<Usage>({ type: 'newNode' })
const suggestionDb = useSuggestionDbStore() const suggestionDb = useSuggestionDbStore()
const interaction = provideInteractionHandler() const interaction = provideInteractionHandler()
/// === UI Messages and Errors ===
function initStartupToast() { function initStartupToast() {
let startupToast = toast.info('Initializing the project. This can take up to one minute.', { let startupToast = toast.info('Initializing the project. This can take up to one minute.', {
autoClose: false, autoClose: false,
}) })
const removeToast = () => toast.remove(startupToast) const removeToast = () => toast.dismiss(startupToast)
projectStore.firstExecution.then(removeToast) projectStore.firstExecution.then(removeToast)
onScopeDispose(removeToast) onScopeDispose(removeToast)
} }
function initConnectionLostToast() {
let connectionLostToast = 'connectionLostToast'
document.addEventListener(
ProjectManagerEvents.loadingFailed,
() => {
toast.error('Lost connection to Language Server.', {
autoClose: false,
toastId: connectionLostToast,
})
},
{ once: true },
)
onUnmounted(() => {
toast.dismiss(connectionLostToast)
})
}
projectStore.lsRpcConnection.then(
(ls) => {
ls.client.onError((err) => {
toast.error(`Language server error: ${err}`)
})
},
(err) => {
toast.error(`Connection to language server failed: ${err}`)
},
)
projectStore.executionContext.on('executionFailed', (err) => {
toast.error(`Execution Failed: ${err}`, {})
})
onMounted(() => { onMounted(() => {
initStartupToast() initStartupToast()
initConnectionLostToast()
}) })
const nodeSelection = provideGraphSelection(graphNavigator, graphStore.nodeRects, { const nodeSelection = provideGraphSelection(graphNavigator, graphStore.nodeRects, {

View File

@ -3,7 +3,6 @@ import '@/assets/main.css'
import type { ApplicationConfig } from '@/util/config' import type { ApplicationConfig } from '@/util/config'
import { createPinia } from 'pinia' import { createPinia } from 'pinia'
import { createApp } from 'vue' import { createApp } from 'vue'
import Vue3Toastify, { type ToastContainerOptions } from 'vue3-toastify'
export function mountProjectApp(rootProps: { export function mountProjectApp(rootProps: {
config: ApplicationConfig config: ApplicationConfig
@ -13,13 +12,6 @@ export function mountProjectApp(rootProps: {
}) { }) {
const app = createApp(App, rootProps) const app = createApp(App, rootProps)
app.use(createPinia()) app.use(createPinia())
app.use(Vue3Toastify, {
position: 'top-center',
theme: 'light',
closeOnClick: false,
draggable: false,
toastClassName: 'text-sm leading-170 bg-frame-selected rounded-2xl backdrop-blur-3xl',
} as ToastContainerOptions)
app.mount('#app') app.mount('#app')
return app return app
} }

View File

@ -1,8 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { reactive, ref } from 'vue'
import GraphEditor from '@/components/GraphEditor.vue' import GraphEditor from '@/components/GraphEditor.vue'
import { useSuggestionDbStore } from '@/stores/suggestionDatabase' import { useSuggestionDbStore } from '@/stores/suggestionDatabase'
import { ToastContainer } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.css'
import { createReactWrapper } from 'vue-react-wrapper'
import MockProjectStoreWrapper from './MockProjectStoreWrapper.vue' import MockProjectStoreWrapper from './MockProjectStoreWrapper.vue'
import HstCode from './histoire/HstCode.vue' import HstCode from './histoire/HstCode.vue'
@ -32,6 +35,22 @@ main =
result = run_main benches result = run_main benches
third_node = 2 + 2 third_node = 2 + 2
`) `)
/**
* Note: These props should be synced with the props in
* `app/ide-desktop/lib/dashboard/src/authentication/src/components/app.tsx`.
* We need this here, as the react component is not part of the dashboard and not usually available in the demo scenes.
* Using this wrapper enables us to see toasts in the absence of the dashboard/React.
*/
const toastProps = reactive({
position: 'top-center',
theme: 'light',
closeOnClick: false,
draggable: false,
toastClassName: 'text-sm leading-170 bg-frame-selected rounded-2xl backdrop-blur-3xl',
limit: 3,
})
const WrappedToastContainer = createReactWrapper(ToastContainer, toastProps)
</script> </script>
<template> <template>
@ -47,6 +66,7 @@ main =
responsiveDisabled responsiveDisabled
autoPropsDisabled autoPropsDisabled
> >
<WrappedToastContainer />t
<MockProjectStoreWrapper v-model="text"> <MockProjectStoreWrapper v-model="text">
<Suspense><GraphEditor /></Suspense> <Suspense><GraphEditor /></Suspense>
</MockProjectStoreWrapper> </MockProjectStoreWrapper>

View File

@ -143,6 +143,7 @@ export default function App(props: AppProps) {
draggable={false} draggable={false}
toastClassName="text-sm leading-170 bg-frame-selected rounded-2xl backdrop-blur-3xl" toastClassName="text-sm leading-170 bg-frame-selected rounded-2xl backdrop-blur-3xl"
transition={toastify.Zoom} transition={toastify.Zoom}
limit={3}
/> />
<Router basename={getMainPageUrl().pathname}> <Router basename={getMainPageUrl().pathname}>
<AppRouter {...props} /> <AppRouter {...props} />

53
package-lock.json generated
View File

@ -14,12 +14,12 @@
], ],
"dependencies": { "dependencies": {
"chromedriver": "^106.0.1", "chromedriver": "^106.0.1",
"tslib": "^2.6.2", "tslib": "^2.6.2"
"vue3-toastify": "^0.1.14"
}, },
"devDependencies": { "devDependencies": {
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.0.0" "prettier": "^3.0.0",
"vue-react-wrapper": "^0.3.1"
} }
}, },
"app/gui2": { "app/gui2": {
@ -17678,6 +17678,36 @@
"eslint": ">=6.0.0" "eslint": ">=6.0.0"
} }
}, },
"node_modules/vue-react-wrapper": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/vue-react-wrapper/-/vue-react-wrapper-0.3.1.tgz",
"integrity": "sha512-kvG3A+fua1GkSiwO24Dp/i67KTz1yTH55HjxVmfnKtVA91sWoAlx2MZ728ooV4PKDt7LCapyPdJesoylPmHkUg==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
"@types/react": "./src/react-types/react",
"@types/react-dom": "18.0.3",
"@types/scheduler": "*",
"csstype": "^3.0.2",
"react": "^18.1.0",
"react-dom": "^18.1.0"
},
"engines": {
"pnpm": ">=7"
},
"peerDependencies": {
"vue": "^3"
}
},
"node_modules/vue-react-wrapper/node_modules/@types/react-dom": {
"version": "18.0.3",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.3.tgz",
"integrity": "sha512-1RRW9kst+67gveJRYPxGmVy8eVJ05O43hg77G2j5m76/RFJtMbcfAs2viQ2UNsvvDg8F7OfQZx8qQcl6ymygaQ==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/vue-resize": { "node_modules/vue-resize": {
"version": "2.0.0-alpha.1", "version": "2.0.0-alpha.1",
"resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz", "resolved": "https://registry.npmjs.org/vue-resize/-/vue-resize-2.0.0-alpha.1.tgz",
@ -17712,23 +17742,6 @@
"typescript": "*" "typescript": "*"
} }
}, },
"node_modules/vue3-toastify": {
"version": "0.1.14",
"resolved": "https://registry.npmjs.org/vue3-toastify/-/vue3-toastify-0.1.14.tgz",
"integrity": "sha512-2wyzMhWq8IjTclL25tqKWknDFdFI1vPueMGZpHNlPWf6TBfxBycBANS+2n4W1xD7tHhX4G6HhCe31sle6OpwYQ==",
"engines": {
"node": ">=16",
"npm": ">=7"
},
"peerDependencies": {
"vue": ">=3.2.0"
},
"peerDependenciesMeta": {
"vue": {
"optional": true
}
}
},
"node_modules/w3c-keyname": { "node_modules/w3c-keyname": {
"version": "2.2.8", "version": "2.2.8",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",

View File

@ -1,12 +1,12 @@
{ {
"devDependencies": { "devDependencies": {
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.0.0" "prettier": "^3.0.0",
"vue-react-wrapper": "^0.3.1"
}, },
"dependencies": { "dependencies": {
"chromedriver": "^106.0.1", "chromedriver": "^106.0.1",
"tslib": "^2.6.2", "tslib": "^2.6.2"
"vue3-toastify": "^0.1.14"
}, },
"name": "root", "name": "root",
"scripts": { "scripts": {