Adding pagination control to the API and to the frontend, as well as getting view working as expected, emitting different key combinations to be able to search by any pattern.
This commit is contained in:
parent
34759c7916
commit
fe84c0f21c
|
@ -122,10 +122,12 @@ const automationActions = store => ({
|
|||
return state
|
||||
})
|
||||
},
|
||||
getLogs: async (automationId, startDate) => {
|
||||
getLogs: async ({ automationId, startDate, status, page } = {}) => {
|
||||
return await API.getAutomationLogs({
|
||||
automationId,
|
||||
startDate,
|
||||
status,
|
||||
page,
|
||||
})
|
||||
},
|
||||
addTestDataToAutomation: data => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { Layout, Table, Select } from "@budibase/bbui"
|
||||
import { Layout, Table, Select, Pagination } from "@budibase/bbui"
|
||||
import DateTimeRenderer from "components/common/renderers/DateTimeRenderer.svelte"
|
||||
import StatusRenderer from "./StatusRenderer.svelte"
|
||||
import HistoryDetailsPanel from "./HistoryDetailsPanel.svelte"
|
||||
|
@ -8,9 +8,24 @@
|
|||
|
||||
export let appId
|
||||
|
||||
let runHistory = []
|
||||
let showPanel = false
|
||||
let selectedHistory = null
|
||||
let runHistory = []
|
||||
let automationOptions = []
|
||||
let automationId = null
|
||||
let status = null
|
||||
let prevPage,
|
||||
nextPage,
|
||||
page,
|
||||
hasNextPage,
|
||||
pageNumber = 1
|
||||
|
||||
$: fetchLogs(automationId, status, page)
|
||||
|
||||
const statusOptions = [
|
||||
{ value: "success", label: "Success" },
|
||||
{ value: "error", label: "Error" },
|
||||
]
|
||||
|
||||
const runHistorySchema = {
|
||||
status: { displayName: "Status" },
|
||||
|
@ -23,7 +38,33 @@
|
|||
{ column: "status", component: StatusRenderer },
|
||||
]
|
||||
|
||||
async function fetchLogs(automationId, status, page) {
|
||||
const response = await automationStore.actions.getLogs({
|
||||
automationId,
|
||||
status,
|
||||
page,
|
||||
})
|
||||
nextPage = response.nextPage
|
||||
hasNextPage = response.hasNextPage
|
||||
runHistory = enrichHistory($automationStore.blockDefinitions, response.data)
|
||||
}
|
||||
|
||||
function goToNextPage() {
|
||||
pageNumber++
|
||||
prevPage = page
|
||||
page = nextPage
|
||||
}
|
||||
|
||||
function goToPrevPage() {
|
||||
pageNumber--
|
||||
nextPage = page
|
||||
page = prevPage
|
||||
}
|
||||
|
||||
function enrichHistory(definitions, runHistory) {
|
||||
if (!definitions) {
|
||||
return []
|
||||
}
|
||||
const finalHistory = []
|
||||
for (let history of runHistory) {
|
||||
if (!history.steps) {
|
||||
|
@ -31,8 +72,8 @@
|
|||
}
|
||||
let notFound = false
|
||||
for (let step of history.steps) {
|
||||
const trigger = definitions.trigger[step.stepId],
|
||||
action = definitions.action[step.stepId]
|
||||
const trigger = definitions.TRIGGER[step.stepId],
|
||||
action = definitions.ACTION[step.stepId]
|
||||
if (!trigger && !action) {
|
||||
notFound = true
|
||||
break
|
||||
|
@ -53,11 +94,12 @@
|
|||
}
|
||||
|
||||
onMount(async () => {
|
||||
let definitions = await automationStore.actions.definitions()
|
||||
runHistory = enrichHistory(
|
||||
definitions,
|
||||
await automationStore.actions.getLogs()
|
||||
)
|
||||
await automationStore.actions.fetch()
|
||||
await fetchLogs()
|
||||
automationOptions = []
|
||||
for (let automation of $automationStore.automations) {
|
||||
automationOptions.push({ value: automation._id, label: automation.name })
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
@ -65,13 +107,23 @@
|
|||
<Layout paddingX="XL" gap="S" alignContent="start">
|
||||
<div class="search">
|
||||
<div class="select">
|
||||
<Select placeholder="All automations" label="Automation" />
|
||||
<Select
|
||||
placeholder="All automations"
|
||||
label="Automation"
|
||||
bind:value={automationId}
|
||||
options={automationOptions}
|
||||
/>
|
||||
</div>
|
||||
<div class="select">
|
||||
<Select placeholder="Past 30 days" label="Date range" />
|
||||
</div>
|
||||
<div class="select">
|
||||
<Select placeholder="All status" label="Status" />
|
||||
<Select
|
||||
placeholder="All status"
|
||||
label="Status"
|
||||
bind:value={status}
|
||||
options={statusOptions}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{#if runHistory}
|
||||
|
@ -95,6 +147,15 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<Pagination
|
||||
page={pageNumber}
|
||||
hasPrevPage={pageNumber > 1}
|
||||
{hasNextPage}
|
||||
{goToPrevPage}
|
||||
{goToNextPage}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.root {
|
||||
|
@ -118,12 +179,11 @@
|
|||
flex-basis: 150px;
|
||||
}
|
||||
|
||||
.separator {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.searchInput {
|
||||
margin-top: auto;
|
||||
.pagination {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
margin-bottom: var(--spacing-xl);
|
||||
margin-left: var(--spacing-l);
|
||||
}
|
||||
|
||||
.panel {
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
|
||||
<div class="cell">
|
||||
<Icon {color} name={isError ? "Alert" : "CheckmarkCircle"} />
|
||||
<div class:green={!isError} class:red={isError}>{value}</div>
|
||||
<div class:green={!isError} class:red={isError}>
|
||||
{isError ? "Error" : "Success"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import CreateAutomationModal from "components/automation/AutomationPanel/CreateAutomationModal.svelte"
|
||||
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
|
||||
import TestPanel from "components/automation/AutomationBuilder/TestPanel.svelte"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
$: automation =
|
||||
$automationStore.selectedAutomation?.automation ||
|
||||
|
@ -12,6 +13,9 @@
|
|||
|
||||
let modal
|
||||
let webhookModal
|
||||
onMount(() => {
|
||||
$automationStore.showTestPanel = false
|
||||
})
|
||||
</script>
|
||||
|
||||
<!-- routify:options index=3 -->
|
||||
|
|
|
@ -79,12 +79,14 @@ export const buildAutomationEndpoints = API => ({
|
|||
* @param automationId The ID of the automation to get logs for.
|
||||
* @param startDate An ISO date string to state the start of the date range.
|
||||
*/
|
||||
getAutomationLogs: async ({ automationId, startDate }) => {
|
||||
getAutomationLogs: async ({ automationId, startDate, status, page }) => {
|
||||
return await API.post({
|
||||
url: "/api/automations/logs/search",
|
||||
body: {
|
||||
automationId,
|
||||
startDate,
|
||||
status,
|
||||
page,
|
||||
},
|
||||
})
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const actions = require("../../automations/actions")
|
||||
const triggers = require("../../automations/triggers")
|
||||
const { getLogs, oneDayAgo } = require("../../automations/history")
|
||||
const { getLogs, oneDayAgo } = require("../../automations/logging")
|
||||
const { getAutomationParams, generateAutomationID } = require("../../db/utils")
|
||||
const {
|
||||
checkForWebhooks,
|
||||
|
@ -152,11 +152,11 @@ exports.destroy = async function (ctx) {
|
|||
}
|
||||
|
||||
exports.logSearch = async function (ctx) {
|
||||
const { automationId } = ctx.request.body
|
||||
const { automationId, status, page } = ctx.request.body
|
||||
// TODO: check if there is a date range in the search params
|
||||
// also check the date range vs their license, see if it is allowed
|
||||
const startDate = oneDayAgo()
|
||||
ctx.body = await getLogs(startDate, automationId)
|
||||
ctx.body = await getLogs(startDate, status, automationId, page)
|
||||
}
|
||||
|
||||
exports.getActionList = async function (ctx) {
|
||||
|
|
|
@ -1,140 +0,0 @@
|
|||
import {
|
||||
AutomationLog,
|
||||
AutomationResults,
|
||||
AutomationStatus,
|
||||
} from "../../definitions/automation"
|
||||
import { getAppDB } from "@budibase/backend-core/context"
|
||||
import {
|
||||
generateAutomationLogID,
|
||||
getAutomationLogParams,
|
||||
getQueryIndex,
|
||||
ViewNames,
|
||||
} from "../../db/utils"
|
||||
import { createLogByAutomationView } from "../../db/views/staticViews"
|
||||
import { Automation } from "../../definitions/common"
|
||||
|
||||
const EARLIEST_DATE = new Date(0).toISOString()
|
||||
const FREE_EXPIRY_SEC = 86400
|
||||
const PRO_EXPIRY_SEC = FREE_EXPIRY_SEC * 30
|
||||
|
||||
function getStatus(results: AutomationResults) {
|
||||
let status = AutomationStatus.SUCCESS
|
||||
let first = true
|
||||
for (let step of results.steps) {
|
||||
// skip the trigger, its always successful if automation ran
|
||||
if (first) {
|
||||
first = false
|
||||
continue
|
||||
}
|
||||
if (!step.outputs?.success) {
|
||||
status = AutomationStatus.ERROR
|
||||
}
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
// export function oneMonthAgo() {
|
||||
// return new Date(
|
||||
// new Date().getTime() - PRO_EXPIRY_SEC * 1000
|
||||
// ).toISOString()
|
||||
// }
|
||||
|
||||
export function oneDayAgo() {
|
||||
return new Date(new Date().getTime() - FREE_EXPIRY_SEC * 1000).toISOString()
|
||||
}
|
||||
|
||||
async function clearOldHistory() {
|
||||
const db = getAppDB()
|
||||
// TODO: handle license lookup for deletion
|
||||
const expiredEnd = oneDayAgo()
|
||||
const results = await getAllLogs(EARLIEST_DATE, expiredEnd, {
|
||||
include_docs: false,
|
||||
})
|
||||
const toDelete = results.map((doc: any) => ({
|
||||
_id: doc.id,
|
||||
_rev: doc.rev,
|
||||
_deleted: true,
|
||||
}))
|
||||
await db.bulkDocs(toDelete)
|
||||
}
|
||||
|
||||
async function getAllLogs(
|
||||
startDate: string,
|
||||
endDate: string,
|
||||
opts: any = { include_docs: true }
|
||||
) {
|
||||
const db = getAppDB()
|
||||
const queryParams: any = {
|
||||
endDate,
|
||||
startDate,
|
||||
}
|
||||
let response = (await db.allDocs(getAutomationLogParams(queryParams, opts)))
|
||||
.rows
|
||||
if (opts?.include_docs) {
|
||||
response = response.map((row: any) => row.doc)
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
async function getLogsByAutomationID(
|
||||
automationId: string,
|
||||
opts: { startDate?: string; endDate?: string } = {}
|
||||
): Promise<AutomationLog[]> {
|
||||
const db = getAppDB()
|
||||
try {
|
||||
const queryParams = {
|
||||
startDate: opts?.startDate,
|
||||
endDate: opts?.startDate,
|
||||
automationId,
|
||||
}
|
||||
return (
|
||||
await db.query(
|
||||
getQueryIndex(ViewNames.LOGS_BY_AUTOMATION),
|
||||
getAutomationLogParams(queryParams, { include_docs: true })
|
||||
)
|
||||
).rows.map((row: any) => row.doc)
|
||||
} catch (err: any) {
|
||||
if (err != null && err.name === "not_found") {
|
||||
await createLogByAutomationView()
|
||||
return getLogsByAutomationID(automationId, opts)
|
||||
}
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
export async function storeLog(
|
||||
automation: Automation,
|
||||
results: AutomationResults
|
||||
) {
|
||||
const automationId = automation._id
|
||||
const name = automation.name
|
||||
const db = getAppDB()
|
||||
const isoDate = new Date().toISOString()
|
||||
const id = generateAutomationLogID(automationId, isoDate)
|
||||
|
||||
await db.put({
|
||||
// results contain automationId and status for view
|
||||
...results,
|
||||
automationId,
|
||||
automationName: name,
|
||||
status: getStatus(results),
|
||||
createdAt: isoDate,
|
||||
_id: id,
|
||||
})
|
||||
// clear up old history for app
|
||||
await clearOldHistory()
|
||||
}
|
||||
|
||||
export async function getLogs(startDate: string, automationId?: string) {
|
||||
let logs: AutomationLog[]
|
||||
let endDate = new Date().toISOString()
|
||||
if (automationId) {
|
||||
logs = await getLogsByAutomationID(automationId, {
|
||||
startDate,
|
||||
endDate,
|
||||
})
|
||||
} else {
|
||||
logs = await getAllLogs(startDate, endDate)
|
||||
}
|
||||
return logs
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
import {
|
||||
AutomationLog,
|
||||
AutomationLogPage,
|
||||
AutomationResults,
|
||||
AutomationStatus,
|
||||
} from "../../definitions/automation"
|
||||
import { getAppDB } from "@budibase/backend-core/context"
|
||||
import {
|
||||
generateAutomationLogID,
|
||||
getAutomationLogParams,
|
||||
getQueryIndex,
|
||||
ViewNames,
|
||||
} from "../../db/utils"
|
||||
import { createLogByAutomationView } from "../../db/views/staticViews"
|
||||
import { Automation } from "../../definitions/common"
|
||||
|
||||
const PAGE_SIZE = 9
|
||||
const EARLIEST_DATE = new Date(0).toISOString()
|
||||
const FREE_EXPIRY_SEC = 86400
|
||||
// const PRO_EXPIRY_SEC = FREE_EXPIRY_SEC * 30
|
||||
|
||||
function getStatus(results: AutomationResults) {
|
||||
let status = AutomationStatus.SUCCESS
|
||||
let first = true
|
||||
for (let step of results.steps) {
|
||||
// skip the trigger, its always successful if automation ran
|
||||
if (first) {
|
||||
first = false
|
||||
continue
|
||||
}
|
||||
if (!step.outputs?.success) {
|
||||
status = AutomationStatus.ERROR
|
||||
}
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
// export function oneMonthAgo() {
|
||||
// return new Date(
|
||||
// new Date().getTime() - PRO_EXPIRY_SEC * 1000
|
||||
// ).toISOString()
|
||||
// }
|
||||
|
||||
export function oneDayAgo() {
|
||||
return new Date(new Date().getTime() - FREE_EXPIRY_SEC * 1000).toISOString()
|
||||
}
|
||||
|
||||
async function clearOldHistory() {
|
||||
const db = getAppDB()
|
||||
// TODO: handle license lookup for deletion
|
||||
const expiredEnd = oneDayAgo()
|
||||
const results = await getAllLogs(EARLIEST_DATE, expiredEnd, {
|
||||
docs: false,
|
||||
})
|
||||
const toDelete = results.data.map((doc: any) => ({
|
||||
_id: doc.id,
|
||||
_rev: doc.rev,
|
||||
_deleted: true,
|
||||
}))
|
||||
await db.bulkDocs(toDelete)
|
||||
}
|
||||
|
||||
function pagination(
|
||||
response: any,
|
||||
paginate: boolean = true
|
||||
): AutomationLogPage {
|
||||
const data = response.rows.map((row: any) => {
|
||||
return row.doc ? row.doc : row
|
||||
})
|
||||
if (!paginate) {
|
||||
return { data, hasNextPage: false }
|
||||
}
|
||||
const hasNextPage = data.length > PAGE_SIZE
|
||||
return {
|
||||
data: data.slice(0, PAGE_SIZE),
|
||||
hasNextPage,
|
||||
nextPage: hasNextPage ? data[PAGE_SIZE]?._id : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
async function getAllLogs(
|
||||
startDate: string,
|
||||
endDate: string,
|
||||
opts: {
|
||||
docs: boolean
|
||||
status?: string
|
||||
paginate?: boolean
|
||||
page?: string
|
||||
} = { docs: true }
|
||||
): Promise<AutomationLogPage> {
|
||||
const db = getAppDB()
|
||||
let optional: any = { status: opts.status }
|
||||
const params = getAutomationLogParams(startDate, endDate, optional, {
|
||||
include_docs: opts.docs,
|
||||
limit: opts?.paginate ? PAGE_SIZE + 1 : undefined,
|
||||
})
|
||||
if (opts?.page) {
|
||||
params.startkey = opts.page
|
||||
}
|
||||
let response = await db.allDocs(params)
|
||||
return pagination(response, opts?.paginate)
|
||||
}
|
||||
|
||||
async function getLogsByView(
|
||||
startDate: string,
|
||||
endDate: string,
|
||||
viewParams: { automationId?: string; status?: string; page?: string } = {}
|
||||
): Promise<AutomationLogPage> {
|
||||
const db = getAppDB()
|
||||
let response
|
||||
try {
|
||||
let optional = {
|
||||
automationId: viewParams?.automationId,
|
||||
status: viewParams?.status,
|
||||
}
|
||||
const params = getAutomationLogParams(startDate, endDate, optional, {
|
||||
include_docs: true,
|
||||
limit: PAGE_SIZE,
|
||||
})
|
||||
if (viewParams?.page) {
|
||||
params.startkey = viewParams.page
|
||||
}
|
||||
response = await db.query(getQueryIndex(ViewNames.AUTO_LOGS), params)
|
||||
} catch (err: any) {
|
||||
if (err != null && err.name === "not_found") {
|
||||
await createLogByAutomationView()
|
||||
return getLogsByView(startDate, endDate, viewParams)
|
||||
}
|
||||
}
|
||||
return pagination(response)
|
||||
}
|
||||
|
||||
export async function storeLog(
|
||||
automation: Automation,
|
||||
results: AutomationResults
|
||||
) {
|
||||
const db = getAppDB()
|
||||
const automationId = automation._id
|
||||
const name = automation.name
|
||||
const status = getStatus(results)
|
||||
const isoDate = new Date().toISOString()
|
||||
const id = generateAutomationLogID(isoDate, status, automationId)
|
||||
|
||||
await db.put({
|
||||
// results contain automationId and status for view
|
||||
...results,
|
||||
automationId,
|
||||
status,
|
||||
automationName: name,
|
||||
createdAt: isoDate,
|
||||
_id: id,
|
||||
})
|
||||
// clear up old logging for app
|
||||
await clearOldHistory()
|
||||
}
|
||||
|
||||
export async function getLogs(
|
||||
startDate: string,
|
||||
status?: string,
|
||||
automationId?: string,
|
||||
page?: string
|
||||
): Promise<AutomationLogPage> {
|
||||
let response: AutomationLogPage
|
||||
let endDate = new Date().toISOString()
|
||||
if (automationId || status) {
|
||||
response = await getLogsByView(startDate, endDate, {
|
||||
automationId,
|
||||
status,
|
||||
page,
|
||||
})
|
||||
} else {
|
||||
response = await getAllLogs(startDate, endDate, {
|
||||
status,
|
||||
page,
|
||||
docs: true,
|
||||
paginate: true,
|
||||
})
|
||||
}
|
||||
return response
|
||||
}
|
|
@ -49,7 +49,13 @@ const DocumentTypes = {
|
|||
const ViewNames = {
|
||||
LINK: "by_link",
|
||||
ROUTING: "screen_routes",
|
||||
LOGS_BY_AUTOMATION: "log_by_auto",
|
||||
AUTO_LOGS: "auto_log",
|
||||
}
|
||||
|
||||
const ViewModes = {
|
||||
ALL: "all",
|
||||
AUTOMATION: "auto",
|
||||
STATUS: "status",
|
||||
}
|
||||
|
||||
const InternalTables = {
|
||||
|
@ -77,6 +83,7 @@ exports.isProdAppID = isProdAppID
|
|||
exports.USER_METDATA_PREFIX = `${DocumentTypes.ROW}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
|
||||
exports.LINK_USER_METADATA_PREFIX = `${DocumentTypes.LINK}${SEPARATOR}${InternalTables.USER_METADATA}${SEPARATOR}`
|
||||
exports.ViewNames = ViewNames
|
||||
exports.ViewModes = ViewModes
|
||||
exports.InternalTables = InternalTables
|
||||
exports.DocumentTypes = DocumentTypes
|
||||
exports.SEPARATOR = SEPARATOR
|
||||
|
@ -364,26 +371,32 @@ exports.getMemoryViewParams = (otherProps = {}) => {
|
|||
return getDocParams(DocumentTypes.MEM_VIEW, null, otherProps)
|
||||
}
|
||||
|
||||
exports.generateAutomationLogID = (automationId, isoDate) => {
|
||||
exports.generateAutomationLogID = (isoDate, status, automationId) => {
|
||||
return `${DocumentTypes.AUTOMATION_LOG}${SEPARATOR}${isoDate}${SEPARATOR}${automationId}`
|
||||
}
|
||||
|
||||
exports.getAutomationLogParams = (
|
||||
{ startDate, endDate, automationId } = {},
|
||||
startDate,
|
||||
endDate,
|
||||
{ status, automationId } = {},
|
||||
otherProps = {}
|
||||
) => {
|
||||
const base = `${DocumentTypes.AUTOMATION_LOG}${SEPARATOR}`
|
||||
let start = startDate || "",
|
||||
end = endDate || ""
|
||||
// reverse for view
|
||||
if (automationId) {
|
||||
start = `${automationId}${SEPARATOR}${start}`
|
||||
end = `${automationId}${SEPARATOR}${end}`
|
||||
const automationBase = automationId ? `${automationId}${SEPARATOR}` : ""
|
||||
const statusBase = status ? `${status}${SEPARATOR}` : ""
|
||||
let base
|
||||
if (status && automationId) {
|
||||
base = `${ViewModes.ALL}${SEPARATOR}${statusBase}${automationBase}`
|
||||
} else if (status) {
|
||||
base = `${ViewModes.STATUS}${SEPARATOR}${statusBase}`
|
||||
} else if (automationId) {
|
||||
base = `${ViewModes.AUTOMATION}${SEPARATOR}${automationBase}`
|
||||
} else {
|
||||
base = `${DocumentTypes.AUTOMATION_LOG}${SEPARATOR}`
|
||||
}
|
||||
return {
|
||||
...otherProps,
|
||||
startkey: `${base}${start}`,
|
||||
endkey: `${base}${end}${UNICODE_MAX}`,
|
||||
startkey: `${base}${startDate}`,
|
||||
endkey: `${base}${endDate}${UNICODE_MAX}`,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ const {
|
|||
DocumentTypes,
|
||||
SEPARATOR,
|
||||
ViewNames,
|
||||
ViewModes,
|
||||
SearchIndexes,
|
||||
} = require("../utils")
|
||||
const SCREEN_PREFIX = DocumentTypes.SCREEN + SEPARATOR
|
||||
|
@ -69,14 +70,20 @@ exports.createLogByAutomationView = async () => {
|
|||
const view = {
|
||||
map: `function(doc) {
|
||||
if (doc._id.startsWith("${LOG_PREFIX}")) {
|
||||
let key = doc.automationId + ${SEPARATOR} + doc.createdAt
|
||||
emit(key, doc._id)
|
||||
let autoId = doc.automationId + "${SEPARATOR}"
|
||||
let status = doc.status + "${SEPARATOR}"
|
||||
let autoKey = "${ViewModes.AUTOMATION}${SEPARATOR}" + autoId + doc.createdAt
|
||||
let statusKey = "${ViewModes.STATUS}${SEPARATOR}" + status + doc.createdAt
|
||||
let allKey = "${ViewModes.ALL}${SEPARATOR}" + status + autoId + doc.createdAt
|
||||
emit(statusKey)
|
||||
emit(autoKey)
|
||||
emit(allKey)
|
||||
}
|
||||
}`,
|
||||
}
|
||||
designDoc.views = {
|
||||
...designDoc.views,
|
||||
[ViewNames.LOGS_BY_AUTOMATION]: view,
|
||||
[ViewNames.AUTO_LOGS]: view,
|
||||
}
|
||||
await db.put(designDoc)
|
||||
}
|
||||
|
|
|
@ -23,3 +23,9 @@ export interface AutomationLog extends AutomationResults {
|
|||
_id: string
|
||||
_rev: string
|
||||
}
|
||||
|
||||
export interface AutomationLogPage {
|
||||
data: AutomationLog[]
|
||||
hasNextPage: boolean
|
||||
nextPage?: string
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ const { doInTenant } = require("@budibase/backend-core/tenancy")
|
|||
const { definitions: triggerDefs } = require("../automations/triggerInfo")
|
||||
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
|
||||
const { AutomationErrors, LoopStepTypes } = require("../constants")
|
||||
const { storeLog } = require("../automations/history")
|
||||
const { storeLog } = require("../automations/logging")
|
||||
const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
|
||||
const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId
|
||||
|
||||
|
@ -326,7 +326,7 @@ class Orchestrator {
|
|||
}
|
||||
}
|
||||
|
||||
// store the history for the automation run
|
||||
// store the logs for the automation run
|
||||
await storeLog(this._automation, this.executionOutput)
|
||||
return this.executionOutput
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue