diff --git a/client/web/admin/src/app.js b/client/web/admin/src/app.js index 55cf3dfa5f..c4c42e0c1a 100644 --- a/client/web/admin/src/app.js +++ b/client/web/admin/src/app.js @@ -148,7 +148,7 @@ export default (options = {}) => { break case 'error': - console.error('websocket message with error', msg['@value']) + this.toastDanger('Websocket message with error', msg['@value']) } }) }, diff --git a/client/web/compose/src/app.js b/client/web/compose/src/app.js index 444e681ffc..e5ea4c4b1c 100644 --- a/client/web/compose/src/app.js +++ b/client/web/compose/src/app.js @@ -154,7 +154,7 @@ export default (options = {}) => { break case 'error': - console.error('websocket message with error', msg['@value']) + this.toastDanger('Websocket message with error', msg['@value']) } }) }, diff --git a/client/web/one/src/app.js b/client/web/one/src/app.js index e3e15822ce..adba2bee1d 100644 --- a/client/web/one/src/app.js +++ b/client/web/one/src/app.js @@ -96,7 +96,7 @@ export default (options = {}) => { break case 'error': - console.error('websocket message with error', msg['@value']) + this.toastDanger('Websocket message with error', msg['@value']) } }) }, diff --git a/client/web/workflow/src/components/Configurator/Function.vue b/client/web/workflow/src/components/Configurator/Function.vue index a5887c7d4c..fe316c1454 100644 --- a/client/web/workflow/src/components/Configurator/Function.vue +++ b/client/web/workflow/src/components/Configurator/Function.vue @@ -132,7 +132,7 @@ @input="$root.$emit('change-detected')" @search="searchWorkflows" /> - + @@ -520,7 +521,7 @@ export default { target: param.name, type: arg.type || this.paramTypes[func.ref][param.name][0], valueType: this.getValueType(arg, arg.type || this.paramTypes[func.ref][param.name][0], input), - value: arg.value || null, + value: arg.value || input.default || null, expr: arg.expr || arg.source || null, required: param.required || false, input, diff --git a/lib/vue/src/components/prompts/definitions.ts b/lib/vue/src/components/prompts/definitions.ts index 0935eb8319..a0cc90e492 100644 --- a/lib/vue/src/components/prompts/definitions.ts +++ b/lib/vue/src/components/prompts/definitions.ts @@ -11,6 +11,11 @@ const variants = [ { value: 'dark', text: 'Dark' }, ] +const openModeVariants = [ + { value: 'newTab', text: 'Open link in a new tab' }, + { value: 'sameTab', text: 'Open link in the same tab' }, +] + export const prompts = Object.freeze([ { ref: 'redirect', @@ -19,6 +24,7 @@ export const prompts = Object.freeze([ { name: 'owner', types: ['User', 'ID'], required: false }, { name: 'url', types: ['String'], required: true }, { name: 'delay', types: ['Integer'], meta: { description: 'Redirection delay in seconds' } }, + { name: 'openMode', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: openModeVariants }, default: 'sameTab' } } } }, ], }, { @@ -30,6 +36,7 @@ export const prompts = Object.freeze([ { name: 'params', types: ['KV'] }, { name: 'query', types: ['KV'] }, { name: 'delay', types: ['Integer'], meta: { description: 'Redirection delay in seconds' } }, + { name: 'openMode', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: openModeVariants }, default: 'sameTab' } } } }, ], }, { @@ -45,6 +52,7 @@ export const prompts = Object.freeze([ { name: 'record', types: ['ID', 'ComposeRecord'] }, { name: 'edit', types: ['Boolean'] }, { name: 'delay', types: ['Integer'], meta: { description: 'Redirection delay in seconds' } }, + { name: 'openMode', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: [...openModeVariants, { value: 'modal', text: 'Open in a modal' }] }, default: 'sameTab' } } } }, ], }, { @@ -58,7 +66,7 @@ export const prompts = Object.freeze([ { name: 'owner', types: ['User', 'ID'], required: false }, { name: 'title', types: ['String'] }, { name: 'message', types: ['String'], required: true }, - { name: 'variant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants } } } } }, + { name: 'variant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants }, default: 'primary' } } } }, { name: 'timeout', types: ['Integer'], meta: { description: 'How long do we show the notification in seconds' } }, ], }, @@ -70,7 +78,7 @@ export const prompts = Object.freeze([ { name: 'title', types: ['String'] }, { name: 'message', types: ['String'], required: true }, { name: 'buttonLabel', types: ['String'] }, - { name: 'buttonVariant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants } } } } }, + { name: 'buttonVariant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants }, default: 'primary' } } } }, { name: 'buttonValue', types: ['Any'] }, ], }, @@ -82,10 +90,10 @@ export const prompts = Object.freeze([ { name: 'title', types: ['String'] }, { name: 'message', types: ['String'], required: true }, { name: 'confirmButtonLabel', types: ['String'] }, - { name: 'confirmButtonVariant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants } } } } }, + { name: 'confirmButtonVariant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants }, default: 'primary' } } } }, { name: 'confirmButtonValue', types: ['Any'] }, { name: 'rejectButtonLabel', types: ['String'] }, - { name: 'rejectButtonVariant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants } } } } }, + { name: 'rejectButtonVariant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants }, default: 'danger' } } } }, { name: 'rejectButtonValue', types: ['Any'] }, ], results: [ @@ -147,7 +155,7 @@ export const prompts = Object.freeze([ parameters: [ { name: 'owner', types: ['User', 'ID'], required: false }, { name: 'title', types: ['String'] }, - { name: 'variant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants } } } } }, + { name: 'variant', types: ['String'], meta: { visual: { input: { type: 'select', properties: { options: variants }, default: 'primary' } } } }, { name: 'message', types: ['String'], required: true }, { name: 'label', types: ['String'] }, { diff --git a/lib/vue/src/components/prompts/kinds/index.ts b/lib/vue/src/components/prompts/kinds/index.ts index 4b25033394..d806592637 100644 --- a/lib/vue/src/components/prompts/kinds/index.ts +++ b/lib/vue/src/components/prompts/kinds/index.ts @@ -6,7 +6,7 @@ import notification from './CPromptNotification.vue' import options from './CPromptOptions.vue' import { Component } from 'vue' import { pType, pVal } from '../utils' -import { automation } from '@cortezaproject/corteza-js' +import { automation, NoID } from '@cortezaproject/corteza-js' import { KV } from '@cortezaproject/corteza-js/dist/compose/types/chart/util' interface Handler { @@ -61,11 +61,18 @@ const definitions: Record = { handler: function (v): void { const url = pVal(v, 'url') const delay = (pVal(v, 'delay') || 0) as number + const openMode = pVal(v, 'openMode') + if (url !== undefined) { console.debug('redirect to %s via prompt in %d sec', url, delay) setTimeout(() => { - // @ts-ignore - window.location = url + if (openMode === 'newTab') { + // @ts-ignore + window.open(url, '_blank') + } else { + // @ts-ignore + window.location = url + } }, delay * 1000) } }, @@ -77,11 +84,20 @@ const definitions: Record = { const params = pVal(v, 'params') const query = pVal(v, 'query') const delay = (pVal(v, 'delay') || 0) as number + const openMode = pVal(v, 'openMode') if (name !== undefined) { console.debug('reroute to %s via prompt in %d sec', name, delay, { params, query }) setTimeout(() => { - // @ts-ignore - this.$router.push({ name, params, query }) + const routeParams = { name, params, query } + if (openMode === 'newTab') { + // @ts-ignore + const url = this.$router.resolve(routeParams).href + // @ts-ignore + window.open(url, '_blank') + } else { + // @ts-ignore + this.$router.push(routeParams) + } }, delay * 1000) } }, @@ -94,6 +110,7 @@ const definitions: Record = { const record = pVal(v, 'record') const edit = !!pVal(v, 'edit') const delay = (pVal(v, 'delay') || 0) as number + const openMode = pVal(v, 'openMode') let namespaceID = '' let slug = '' @@ -122,7 +139,9 @@ const definitions: Record = { // @ts-ignore const { set: nn } = await this.$ComposeAPI.namespaceList({ slug: namespace as string }) if (!nn || nn.length !== 1) { - throw new Error('namespace not resolved') + // @ts-ignore + this.toastDanger('Namespace not resolved', 'Prompt error') + return } namespaceID = nn[0].namespaceID @@ -138,7 +157,9 @@ const definitions: Record = { // @ts-ignore const { set: mm } = await this.$ComposeAPI.moduleList({ handle: module as string, namespaceID }) if (!mm || mm.length !== 1) { - throw new Error('module not resolved') + // @ts-ignore + this.toastDanger('Module not resolved', 'Prompt error') + return } moduleID = mm[0].moduleID @@ -155,19 +176,17 @@ const definitions: Record = { // @ts-ignore const { set: pp } = await this.$ComposeAPI.pageList({ moduleID, namespaceID }) if (!pp || pp.length !== 1) { - throw new Error('record page not resolved') + // @ts-ignore + this.toastDanger('Record page not resolved', 'Prompt error') + return } pageID = pp[0].pageID // @ts-ignore if (this.$root.$options.name === 'compose') { - if (!edit && !recordID) { - throw new Error('invalid record page prompt configuration') - } - let name = 'page.record' - if (edit) { - name += recordID ? '.edit' : '.create' + if (edit || !recordID || recordID === NoID) { + name += recordID && recordID !== NoID ? '.edit' : '.create' } // If name and params match, make sure to refresh page instead of push @@ -176,11 +195,24 @@ const definitions: Record = { setTimeout(() => { console.debug('reroute to %s via prompt in %d sec', name, delay, { namespaceID, slug, moduleID, recordID }) + + const routeParams = { name, params: { recordID, pageID, slug } } if (reloadPage) { window.location.reload() + } else if (openMode === 'modal') { + // @ts-ignore + this.$root.$emit('show-record-modal', { + recordID: !recordID ? NoID : recordID, + recordPageID: pageID, + }) + } else if (openMode === 'newTab') { + // @ts-ignore + const url = this.$router.resolve(routeParams).href + // @ts-ignore + window.open(url, '_blank') } else { // @ts-ignore - this.$router.push({ name, params: { recordID, pageID, slug } }) + this.$router.push(routeParams) } }, delay * 1000) } else {