1
0
Fork 0
mirror of synced 2024-07-31 19:01:57 +12:00

Adding in main portal page automation error notification.

This commit is contained in:
mike12345567 2022-06-21 00:02:22 +01:00
parent e9d3a1e92f
commit 2ff853c917
8 changed files with 114 additions and 18 deletions

View file

@ -1,15 +1,20 @@
<script>
import { ActionButton } from "../"
import { createEventDispatcher } from "svelte"
export let type = "info"
export let icon = "Info"
export let message = ""
export let dismissable = false
export let actionMessage = null
export let action = null
export let wide = false
const dispatch = createEventDispatcher()
</script>
<div class="spectrum-Toast spectrum-Toast--{type}">
<div class="spectrum-Toast spectrum-Toast--{type}" class:wide>
{#if icon}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Toast-typeIcon"
@ -19,8 +24,13 @@
<use xlink:href="#spectrum-icon-18-{icon}" />
</svg>
{/if}
<div class="spectrum-Toast-body">
<div class="spectrum-Toast-body" class:actionBody={!!action}>
<div class="spectrum-Toast-content">{message || ""}</div>
{#if action}
<ActionButton quiet emphasized on:click={action}>
<div style="color: white; font-weight: 600;">{actionMessage}</div>
</ActionButton>
{/if}
</div>
{#if dismissable}
<div class="spectrum-Toast-buttons">
@ -46,4 +56,15 @@
.spectrum-Toast {
pointer-events: all;
}
.wide {
width: 100%;
}
.actionBody {
justify-content: space-between;
display: flex;
width: 100%;
align-items: center;
}
</style>

View file

@ -8,13 +8,15 @@
<Portal target=".modal-container">
<div class="notifications">
{#each $notifications as { type, icon, message, id, dismissable } (id)}
{#each $notifications as { type, icon, message, id, dismissable, action, wide } (id)}
<div transition:fly={{ y: -30 }}>
<Notification
{type}
{icon}
{message}
{dismissable}
{action}
{wide}
on:dismiss={() => notifications.dismiss(id)}
/>
</div>

View file

@ -20,7 +20,16 @@ export const createNotificationStore = () => {
setTimeout(() => (block = false), timeout)
}
const send = (message, type = "default", icon = "", autoDismiss = true) => {
const send = (
message,
{
type = "default",
icon = "",
autoDismiss = true,
action = null,
wide = false,
}
) => {
if (block) {
return
}
@ -28,7 +37,15 @@ export const createNotificationStore = () => {
_notifications.update(state => {
return [
...state,
{ id: _id, type, message, icon, dismissable: !autoDismiss },
{
id: _id,
type,
message,
icon,
dismissable: !autoDismiss,
action,
wide,
},
]
})
if (autoDismiss) {
@ -50,10 +67,11 @@ export const createNotificationStore = () => {
return {
subscribe,
send,
info: msg => send(msg, "info", "Info"),
error: msg => send(msg, "error", "Alert", false),
warning: msg => send(msg, "warning", "Alert"),
success: msg => send(msg, "success", "CheckmarkCircle"),
info: msg => send(msg, { type: "info", icon: "Info" }),
error: msg =>
send(msg, { type: "error", icon: "Alert", autoDismiss: false }),
warning: msg => send(msg, { type: "warning", icon: "Alert" }),
success: msg => send(msg, { type: "success", icon: "CheckmarkCircle" }),
blockNotifications,
dismiss: dismissNotification,
}

View file

@ -129,6 +129,7 @@ const automationActions = store => ({
page,
})
},
clearLogErrors: async () => {},
addTestDataToAutomation: data => {
store.update(state => {
state.selectedAutomation.addTestData(data)

View file

@ -4,10 +4,15 @@
import DateTimeRenderer from "components/common/renderers/DateTimeRenderer.svelte"
import TestDisplay from "components/automation/AutomationBuilder/TestDisplay.svelte"
import { goto } from "@roxi/routify"
import { automationStore } from "builderStore"
export let history
export let appId
export let close
$: exists = $automationStore.automations?.find(
auto => auto._id === history?.automationId
)
</script>
{#if history}
@ -28,13 +33,15 @@
<div>{history.automationName}</div>
</div>
<div>
<ActionButton
icon="Edit"
fullWidth={false}
on:click={() =>
$goto(`../../../app/${appId}/automate/${history.automationId}`)}
>Edit automation</ActionButton
>
{#if exists}
<ActionButton
icon="Edit"
fullWidth={false}
on:click={() =>
$goto(`../../../app/${appId}/automate/${history.automationId}`)}
>Edit automation</ActionButton
>
{/if}
</div>
</Layout>
<div class="bottom">

View file

@ -126,7 +126,7 @@
/>
</div>
</div>
{#if runHistory}
{#if runHistory && runHistory.length}
<Table
on:click={viewDetails}
schema={runHistorySchema}

View file

@ -7,6 +7,7 @@
Modal,
Page,
notifications,
Notification,
Body,
Search,
} from "@budibase/bbui"
@ -37,6 +38,7 @@
let searchTerm = ""
let cloud = $admin.cloud
let creatingFromTemplate = false
let automationErrors
const resolveWelcomeMessage = (auth, apps) => {
const userWelcome = auth?.user?.firstName
@ -59,7 +61,8 @@
)
$: lockedApps = filteredApps.filter(app => app?.lockedYou || app?.lockedOther)
$: unlocked = lockedApps?.length == 0
$: unlocked = lockedApps?.length === 0
$: automationErrors = getAutomationErrors(enrichedApps)
const enrichApps = (apps, user, sortBy) => {
const enrichedApps = apps.map(app => ({
@ -89,6 +92,33 @@
}
}
const getAutomationErrors = apps => {
const automationErrors = {}
for (let app of apps) {
if (app.automationErrors) {
automationErrors[app.devId] = app.automationErrors
}
}
return automationErrors
}
const goToAutomationError = appId => {
const params = new URLSearchParams({ tab: "Automation History" })
$goto(`../overview/${appId}?${params.toString()}`)
}
const errorCount = appId => {
return Object.values(automationErrors[appId]).reduce(
(prev, next) => prev + next,
0
)
}
const automationErrorMessage = appId => {
const app = enrichedApps.find(app => app.devId === appId)
return `${app.name} - Automation error (${errorCount(appId)})`
}
const initiateAppCreation = () => {
if ($apps?.length) {
$goto("/builder/portal/apps/create")
@ -208,6 +238,19 @@
<Page wide>
<Layout noPadding gap="M">
{#if loaded}
{#if automationErrors}
{#each Object.keys(automationErrors) as appId}
<Notification
wide
dismissable
action={() => goToAutomationError(appId)}
type="error"
icon="Alert"
actionMessage={errorCount(appId) > 1 ? "View errors" : "View error"}
message={automationErrorMessage(appId)}
/>
{/each}
{/if}
<div class="title">
<div class="welcome">
<Layout noPadding gap="XS">

View file

@ -188,6 +188,10 @@
})
onMount(async () => {
const params = new URLSearchParams(window.location.search)
if (params.get("tab")) {
selectedTab = params.get("tab")
}
try {
if (!apps.length) {
await apps.load()