directus-extension-flow-manager 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,9 +6,11 @@ You can install it via ``npm install directus-extension-flow-manager``
6
6
  - [x] Duplicate flow
7
7
  - [x] Export and import flow
8
8
  - [x] Add flow validation when Restore
9
+ - [x] Feature for keeping original flow id when restore
10
+ - [ ] Add flow grouping
9
11
 
10
12
  Screenshoots
11
- ![Alt text](screenshoots/image.png)
13
+ ![Alt text](https://raw.githubusercontent.com/baguse/directus-extension-flow-manager/634b5085908e9fc33133a78c7578276d1a08e888/screenshoots/image.png)
12
14
 
13
15
  Changelogs:
14
16
  - 1.0.0: (13 July 2023)
@@ -18,5 +20,8 @@ Changelogs:
18
20
  * Allow user to click the flow row and bring to flow detail page
19
21
  - 1.1.1: (02 August 2023)
20
22
  * Add flow validation on restore
23
+ - 1.2.1: (14 September 2023)
24
+ * Add feature for keeping original flow id when restore
25
+ * Add New flow name textfield on restore confirmation dialog
21
26
 
22
27
  If you want to contribute kindly to create a PR and if you want to request a feature or report of a bug kindly create the Issue
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{useStores as e,useApi as t,defineModule as o}from"@directus/extensions-sdk";import{defineComponent as n,ref as i,unref as a,resolveComponent as l,resolveDirective as r,openBlock as s,createBlock as c,withCtx as u,withDirectives as d,createVNode as p,createCommentVNode as f,normalizeClass as v,createTextVNode as m,toDisplayString as g,createElementVNode as y,createElementBlock as h,Fragment as _,renderList as w,pushScopeId as k,popScopeId as C}from"vue";import{useRouter as b}from"vue-router";var x=n({setup(){const{useFlowsStore:o,useNotificationsStore:n,useCollectionsStore:l}=e(),r=o(),s=n(),c=l(),u=t(),d=b(),p=i(r.flows),{allCollections:f}=c,v=f.reduce(((e,t)=>(e[t.collection]=!0,e)),{}),m=i(null),g=i({}),y=i(!1),h=i([]);return{headers:i([{text:"",value:"icon",width:50,sortable:!1},{text:"Status",value:"status"},{text:"Name",value:"name",width:400}]),flows:p,restoredFile:m,restoreConfirmationDialog:y,errors:h,duplicate:_,backup:async function(e){const t={name:e.name,icon:e.icon,color:e.color,description:e.description,trigger:e.trigger,options:e.options,operation:e.operation,operations:e.operations.map((e=>({id:e.id,name:e.name,key:e.key,type:e.type,position_x:e.position_x,position_y:e.position_y,options:e.options,resolve:e.resolve,reject:e.reject})))},o=new Blob([JSON.stringify(t,null,2)],{type:"application/json"});var n=window.URL.createObjectURL(o),i=document.createElement("a");i.href=n,i.setAttribute("download",`${function(){const e=new Date,t=e.getFullYear(),o=(e.getMonth()+1).toString().padStart(2,"0"),n=e.getDate().toString().padStart(2,"0"),i=e.getHours().toString().padStart(2,"0"),a=e.getMinutes().toString().padStart(2,"0"),l=e.getSeconds().toString().padStart(2,"0");return`${t}${o}${n}${i}${a}${l}`}()}-${e.name}.json`),document.body.appendChild(i),i.click()},onRestoredFileChanged:function(e){var t;const o=null==(t=null==e?void 0:e.target)?void 0:t.files[0];if(!o)return;const n=new FileReader;n.onload=async e=>{var t;try{const o=null==(t=e.target)?void 0:t.result,n=JSON.parse(o);if(h.value=[],(null==n?void 0:n.trigger)||h.value.push("Trigger is required"),(null==n?void 0:n.options)||h.value.push("Flow Options are required"),null==n?void 0:n.operations)for(const e of n.operations)["item-read","item-create","item-update","item-delete"].includes(e.type)&&(v[e.options.collection]||h.value.push(`Collection "${e.options.collection}"" does not exist on ${e.name} operation`));h.value.length?(y.value=!0,g.value=n):await _(n,!1)}catch(e){console.log(e)}},n.readAsText(o)},onRestoreButtonClicked:function(){var e;console.log("restore button clicked"),null==(e=m.value)||e.click()},goToFlow:function({item:e}){console.log("go to flow",e),d.push(`/settings/flows/${e.id}`)},onConfirmRestore:function(){_(g.value,!1),y.value=!1}};async function _(e,t=!0){try{let o=function(t){const o={};function i(e){return t.find((t=>t.id===e))}function a(e){if(!e)return null;return{name:e.name,position_x:e.position_x,position_y:e.position_y,key:e.key,type:e.type,options:e.options,flow:n.data.data.id,resolve:a(i(e.resolve)),reject:a(i(e.reject))}}const l=i(e.operation);return o.name=null==l?void 0:l.name,o.position_x=null==l?void 0:l.position_x,o.position_y=null==l?void 0:l.position_y,o.key=null==l?void 0:l.key,o.type=null==l?void 0:l.type,o.options=null==l?void 0:l.options,o.flow=n.data.data.id,o.resolve=a(i((null==l?void 0:l.resolve)||null)),o.reject=a(i((null==l?void 0:l.reject)||null)),o};const n=await u.post("/flows",{name:t?`${e.name} - Copy`:e.name,status:"inactive",icon:e.icon,accountability:e.accountability,description:e.description,trigger:e.trigger,options:e.options}),i=o(e.operations);await u.patch(`/flows/${n.data.data.id}`,{operation:e.operation?i:null}),await r.hydrate(),p.value=a(r.flows),s.add({type:"success",title:t?"Flow Duplicated successfully":`Flow ${e.name} restored successfully`,closeable:!0,persist:!0})}catch(e){console.log(e)}}}});const S=e=>(k("data-v-b52a34f6"),e=e(),C(),e),F=S((()=>y("div",{style:{"margin-top":"15px"}}," There are some errors in the file you are trying to restore. Do you want to continue? ",-1)));var $=[],j=[];!function(e,t){if(e&&"undefined"!=typeof document){var o,n=!0===t.prepend?"prepend":"append",i=!0===t.singleTag,a="string"==typeof t.container?document.querySelector(t.container):document.getElementsByTagName("head")[0];if(i){var l=$.indexOf(a);-1===l&&(l=$.push(a)-1,j[l]={}),o=j[l]&&j[l][n]?j[l][n]:j[l][n]=r()}else o=r();65279===e.charCodeAt(0)&&(e=e.substring(1)),o.styleSheet?o.styleSheet.cssText+=e:o.appendChild(document.createTextNode(e))}function r(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),t.attributes)for(var o=Object.keys(t.attributes),i=0;i<o.length;i++)e.setAttribute(o[i],t.attributes[o[i]]);var l="prepend"===n?"afterbegin":"beforeend";return a.insertAdjacentElement(l,e),e}}(".active-chip[data-v-b52a34f6] {\n background-color: var(--primary);\n}\n.inactive-chip[data-v-b52a34f6] {\n background-color: var(--foreground-subdued);\n}",{}),x.render=function(e,t,o,n,i,a){const k=l("v-icon"),C=l("v-chip"),b=l("v-list-item-icon"),x=l("v-list-item-content"),S=l("v-list-item"),$=l("v-list"),j=l("v-menu"),R=l("v-table"),D=l("v-button"),T=l("v-card-title"),A=l("v-error"),N=l("v-card-text"),O=l("v-card-actions"),B=l("v-card"),E=l("v-dialog"),M=l("private-view"),U=r("tooltip");return s(),c(M,{title:"Flow Manager"},{actions:u((()=>[d((s(),c(D,{rounded:"",icon:"",onClick:e.onRestoreButtonClicked},{default:u((()=>[p(k,{name:"file_upload"})])),_:1},8,["onClick"])),[[U,"Restore",void 0,{bottom:!0}]])])),default:u((()=>[p(R,{items:e.flows,headers:e.headers,"onUpdate:headers":t[0]||(t[0]=t=>e.headers=t),"onClick:row":e.goToFlow},{"item.icon":u((({item:e})=>[e.icon?(s(),c(k,{key:0,name:e.icon},null,8,["name"])):f("v-if",!0)])),"item.status":u((({item:e})=>[p(C,{rounded:"",class:v("active"===e.status?"active-chip":"inactive-chip")},{default:u((()=>[m(g(e.status),1)])),_:2},1032,["class"])])),"item-append":u((({item:t})=>[p(j,{placement:"bottom-end","show-arrow":"","close-on-content-click":!0},{activator:u((({toggle:e})=>[p(k,{name:"more_vert",class:"ctx-toggle",onClick:e},null,8,["onClick"])])),default:u((()=>[p($,null,{default:u((()=>[p(S,{clickable:"",onClick:o=>e.duplicate(t)},{default:u((()=>[p(b,null,{default:u((()=>[p(k,{name:"content_copy"})])),_:1}),p(x,null,{default:u((()=>[m(" Duplicate ")])),_:1})])),_:2},1032,["onClick"]),p(S,{clickable:"",onClick:o=>e.backup(t)},{default:u((()=>[p(b,null,{default:u((()=>[p(k,{name:"file_download"})])),_:1}),p(x,null,{default:u((()=>[m(" Backup ")])),_:1})])),_:2},1032,["onClick"])])),_:2},1024)])),_:2},1024)])),_:2},1032,["items","headers","onClick:row"]),y("input",{ref:"restoredFile",type:"file",accept:"application/json",onChange:t[1]||(t[1]=(...t)=>e.onRestoredFileChanged&&e.onRestoredFileChanged(...t)),style:{display:"none"}},null,544),p(E,{"model-value":e.restoreConfirmationDialog,persistent:!0,"onUpdate:modelValue":t[3]||(t[3]=t=>e.restoreConfirmationDialog=!1)},{default:u((()=>[p(B,null,{default:u((()=>[p(T,null,{default:u((()=>[m("Confirmation Dialog")])),_:1}),p(N,null,{default:u((()=>[(s(!0),h(_,null,w(e.errors,((e,t)=>(s(),c(A,{key:`errorIndex-${t}`,error:{extensions:{code:"Error"},message:e}},null,8,["error"])))),128)),F])),_:1}),p(O,null,{default:u((()=>[p(D,{secondary:"",onClick:t[2]||(t[2]=t=>e.restoreConfirmationDialog=!1)},{default:u((()=>[m(" Cancel ")])),_:1}),p(D,{onClick:e.onConfirmRestore},{default:u((()=>[m(" Continue ")])),_:1},8,["onClick"])])),_:1})])),_:1})])),_:1},8,["model-value"])])),_:1})},x.__scopeId="data-v-b52a34f6",x.__file="src/module.vue";var R=o({id:"flow-manager",name:"Flow Manager",icon:"bolt",routes:[{path:"",component:x}]});export{R as default};
1
+ import{useStores as e,useApi as t,defineModule as o}from"@directus/extensions-sdk";import{defineComponent as n,ref as i,unref as l,resolveComponent as a,resolveDirective as r,openBlock as s,createBlock as d,withCtx as u,withDirectives as c,createVNode as p,createCommentVNode as v,normalizeClass as m,createTextVNode as f,toDisplayString as g,createElementVNode as y,createElementBlock as w,Fragment as h,renderList as b,pushScopeId as _,popScopeId as k}from"vue";import{useRouter as C}from"vue-router";var x=n({setup(){const{useFlowsStore:o,useNotificationsStore:n,useCollectionsStore:a}=e(),r=o(),s=n(),d=a(),u=t(),c=C(),p=i(r.flows),{allCollections:v}=d,m=v.reduce(((e,t)=>(e[t.collection]=!0,e)),{}),f=i(null),g=i({}),y=i(!1),w=i([]),h=i([{text:"",value:"icon",width:50,sortable:!1},{text:"Status",value:"status"},{text:"Name",value:"name",width:400}]),b=i(""),_=i(!1);return{headers:h,flows:p,restoredFile:f,restoreConfirmationDialog:y,errors:w,duplicate:k,backup:async function(e){const t={id:e.id,name:e.name,icon:e.icon,color:e.color,description:e.description,trigger:e.trigger,options:e.options,operation:e.operation,operations:e.operations.map((e=>({id:e.id,name:e.name,key:e.key,type:e.type,position_x:e.position_x,position_y:e.position_y,options:e.options,resolve:e.resolve,reject:e.reject})))},o=new Blob([JSON.stringify(t,null,2)],{type:"application/json"});var n=window.URL.createObjectURL(o),i=document.createElement("a");i.href=n,i.setAttribute("download",`${function(){const e=new Date,t=e.getFullYear(),o=(e.getMonth()+1).toString().padStart(2,"0"),n=e.getDate().toString().padStart(2,"0"),i=e.getHours().toString().padStart(2,"0"),l=e.getMinutes().toString().padStart(2,"0"),a=e.getSeconds().toString().padStart(2,"0");return`${t}${o}${n}${i}${l}${a}`}()}-${e.name}.json`),document.body.appendChild(i),i.click()},onRestoredFileChanged:function(e){var t;const o=null==(t=null==e?void 0:e.target)?void 0:t.files[0];if(!o)return;const n=new FileReader;n.onload=async e=>{var t;try{const o=null==(t=e.target)?void 0:t.result,n=JSON.parse(o);if(w.value=[],(null==n?void 0:n.trigger)||w.value.push("Trigger is required"),(null==n?void 0:n.options)||w.value.push("Flow Options are required"),null==n?void 0:n.operations)for(const e of n.operations)["item-read","item-create","item-update","item-delete"].includes(e.type)&&(m[e.options.collection]||w.value.push(`Collection "${e.options.collection}"" does not exist on ${e.name} operation`));y.value=!0,g.value=n,b.value=`${n.name} - Copy`,n.id?_.value=!0:_.value=!1}catch(e){console.log(e)}},n.readAsText(o)},onRestoreButtonClicked:function(){var e;null==(e=f.value)||e.click()},goToFlow:function({item:e}){c.push(`/settings/flows/${e.id}`)},onConfirmRestore:function(){k(g.value,!1),y.value=!1},flowDuplicatedName:b,isPreviousIdPersisted:_,restoredFileObj:g};async function k(e,t=!0){try{let o=function(t){const o={};function i(e){return t.find((t=>t.id===e))}function l(e){if(!e)return null;return{name:e.name,position_x:e.position_x,position_y:e.position_y,key:e.key,type:e.type,options:e.options,flow:n.data.data.id,resolve:l(i(e.resolve)),reject:l(i(e.reject))}}const a=i(e.operation);return o.name=null==a?void 0:a.name,o.position_x=null==a?void 0:a.position_x,o.position_y=null==a?void 0:a.position_y,o.key=null==a?void 0:a.key,o.type=null==a?void 0:a.type,o.options=null==a?void 0:a.options,o.flow=n.data.data.id,o.resolve=l(i((null==a?void 0:a.resolve)||null)),o.reject=l(i((null==a?void 0:a.reject)||null)),o};const n=await u.post("/flows",{id:!t&&_.value?e.id:void 0,name:t?e.name:b.value,status:"inactive",icon:e.icon,accountability:e.accountability,description:e.description,trigger:e.trigger,options:e.options}),i=o(e.operations);await u.patch(`/flows/${n.data.data.id}`,{operation:e.operation?i:null}),await r.hydrate(),p.value=l(r.flows),_.value=!1,s.add({type:"success",title:t?"Flow Duplicated successfully":`Flow "${e.name}" restored successfully`,closeable:!0,persist:!0})}catch(o){s.add({type:"error",title:t?"Flow Duplication failed":`Failed to restore Flow "${e.name}"`,closeable:!0,persist:!0})}finally{f.value&&(f.value.value=null)}}}});const F=e=>(_("data-v-b52a34f6"),e=e(),k(),e),S={key:0},$=F((()=>y("div",{style:{"margin-top":"15px"}},"There are some errors in the file you are trying to restore. Do you want to continue?",-1))),D={key:1},j=[F((()=>y("div",{style:{"margin-top":"15px"}},"Do you want to continue?",-1)))];var N=[],R=[];!function(e,t){if(e&&"undefined"!=typeof document){var o,n=!0===t.prepend?"prepend":"append",i=!0===t.singleTag,l="string"==typeof t.container?document.querySelector(t.container):document.getElementsByTagName("head")[0];if(i){var a=N.indexOf(l);-1===a&&(a=N.push(l)-1,R[a]={}),o=R[a]&&R[a][n]?R[a][n]:R[a][n]=r()}else o=r();65279===e.charCodeAt(0)&&(e=e.substring(1)),o.styleSheet?o.styleSheet.cssText+=e:o.appendChild(document.createTextNode(e))}function r(){var e=document.createElement("style");if(e.setAttribute("type","text/css"),t.attributes)for(var o=Object.keys(t.attributes),i=0;i<o.length;i++)e.setAttribute(o[i],t.attributes[o[i]]);var a="prepend"===n?"afterbegin":"beforeend";return l.insertAdjacentElement(a,e),e}}(".active-chip[data-v-b52a34f6] {\n background-color: var(--primary);\n}\n.inactive-chip[data-v-b52a34f6] {\n background-color: var(--foreground-subdued);\n}",{}),x.render=function(e,t,o,n,i,l){const _=a("v-icon"),k=a("v-chip"),C=a("v-list-item-icon"),x=a("v-list-item-content"),F=a("v-list-item"),N=a("v-list"),R=a("v-menu"),T=a("v-table"),O=a("v-button"),A=a("v-card-title"),P=a("v-input"),U=a("v-checkbox"),B=a("v-error"),E=a("v-card-text"),I=a("v-card-actions"),V=a("v-card"),M=a("v-dialog"),q=a("private-view"),J=r("tooltip");return s(),d(q,{title:"Flow Manager"},{actions:u((()=>[c((s(),d(O,{rounded:"",icon:"",onClick:e.onRestoreButtonClicked},{default:u((()=>[p(_,{name:"file_upload"})])),_:1},8,["onClick"])),[[J,"Restore",void 0,{bottom:!0}]])])),default:u((()=>[p(T,{items:e.flows,headers:e.headers,"onUpdate:headers":t[0]||(t[0]=t=>e.headers=t),"onClick:row":e.goToFlow},{"item.icon":u((({item:e})=>[e.icon?(s(),d(_,{key:0,name:e.icon},null,8,["name"])):v("v-if",!0)])),"item.status":u((({item:e})=>[p(k,{rounded:"",class:m("active"===e.status?"active-chip":"inactive-chip")},{default:u((()=>[f(g(e.status),1)])),_:2},1032,["class"])])),"item-append":u((({item:t})=>[p(R,{placement:"bottom-end","show-arrow":"","close-on-content-click":!0},{activator:u((({toggle:e})=>[p(_,{name:"more_vert",class:"ctx-toggle",onClick:e},null,8,["onClick"])])),default:u((()=>[p(N,null,{default:u((()=>[p(F,{clickable:"",onClick:o=>e.duplicate(t)},{default:u((()=>[p(C,null,{default:u((()=>[p(_,{name:"content_copy"})])),_:1}),p(x,null,{default:u((()=>[f(" Duplicate ")])),_:1})])),_:2},1032,["onClick"]),p(F,{clickable:"",onClick:o=>e.backup(t)},{default:u((()=>[p(C,null,{default:u((()=>[p(_,{name:"file_download"})])),_:1}),p(x,null,{default:u((()=>[f(" Backup ")])),_:1})])),_:2},1032,["onClick"])])),_:2},1024)])),_:2},1024)])),_:2},1032,["items","headers","onClick:row"]),y("input",{ref:"restoredFile",type:"file",accept:"application/json",onChange:t[1]||(t[1]=(...t)=>e.onRestoredFileChanged&&e.onRestoredFileChanged(...t)),style:{display:"none"}},null,544),p(M,{"model-value":e.restoreConfirmationDialog,persistent:!0,"onUpdate:modelValue":t[5]||(t[5]=t=>e.restoreConfirmationDialog=!1)},{default:u((()=>[p(V,null,{default:u((()=>[p(A,null,{default:u((()=>[f("Confirmation Dialog")])),_:1}),p(E,null,{default:u((()=>[c(p(P,{placeholder:"Flow Name",modelValue:e.flowDuplicatedName,"onUpdate:modelValue":t[2]||(t[2]=t=>e.flowDuplicatedName=t)},null,8,["modelValue"]),[[J,"Flow Name",void 0,{bottom:!0}]]),p(U,{style:{"margin-top":"4px"},label:"Keep the same flow id as the original flow","model-value":e.isPreviousIdPersisted,disabled:!e.restoredFileObj.id,"onUpdate:modelValue":t[3]||(t[3]=t=>e.isPreviousIdPersisted=t)},null,8,["model-value","disabled"]),e.errors.length?(s(),w("div",S,[(s(!0),w(h,null,b(e.errors,((e,t)=>(s(),d(B,{key:`errorIndex-${t}`,error:{extensions:{code:"Error"},message:e}},null,8,["error"])))),128)),$])):(s(),w("div",D,j))])),_:1}),p(I,null,{default:u((()=>[p(O,{secondary:"",onClick:t[4]||(t[4]=t=>e.restoreConfirmationDialog=!1)},{default:u((()=>[f(" Cancel ")])),_:1}),p(O,{onClick:e.onConfirmRestore},{default:u((()=>[f(" Continue ")])),_:1},8,["onClick"])])),_:1})])),_:1})])),_:1},8,["model-value"])])),_:1})},x.__scopeId="data-v-b52a34f6",x.__file="src/module.vue";var T=o({id:"flow-manager",name:"Flow Manager",icon:"bolt",routes:[{path:"",component:x}]});export{T as default};
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "directus-extension-flow-manager",
3
3
  "description": "This is a custom module for managing Flow",
4
4
  "icon": "extension",
5
- "version": "1.1.1",
5
+ "version": "1.2.0",
6
6
  "author": "Bagus Andreanto<andreanto.bagus@gmail.com>",
7
7
  "homepage": "https://github.com/baguse/directus-extension-flow-manager",
8
8
  "license": "MIT",
@@ -13,7 +13,7 @@
13
13
  ],
14
14
  "directus:extension": {
15
15
  "type": "module",
16
- "path": "dist/index.js",
16
+ "path": "/myproject/project/freelance/directus/latest/extensions/modules/flow-manager/index.js",
17
17
  "source": "src/index.ts",
18
18
  "host": "^9.26.0"
19
19
  },
@@ -24,9 +24,11 @@
24
24
  },
25
25
  "devDependencies": {
26
26
  "@directus/extensions-sdk": "9.26.0",
27
+ "@vue-flow/core": "^1.22.2",
28
+ "sass": "^1.63.6",
27
29
  "typescript": "^5.1.6",
28
30
  "vue": "^3.3.4",
29
- "sass": "^1.63.6",
30
- "vue-router": "^4.2.4"
31
+ "vue-router": "^4.2.4",
32
+ "vue3-html2pdf": "^1.1.2"
31
33
  }
32
34
  }
package/src/module.vue CHANGED
@@ -43,9 +43,24 @@
43
43
  <v-card>
44
44
  <v-card-title>Confirmation Dialog</v-card-title>
45
45
  <v-card-text>
46
- <v-error v-for="(error, indexError) in errors" :key="`errorIndex-${indexError}`" :error="{extensions: {code: 'Error'}, message: error}"></v-error>
47
- <div style="margin-top: 15px;">
48
- There are some errors in the file you are trying to restore. Do you want to continue?
46
+ <v-input placeholder="Flow Name" v-model="flowDuplicatedName" v-tooltip.bottom="'Flow Name'" />
47
+ <v-checkbox
48
+ style="margin-top: 4px"
49
+ label="Keep the same flow id as the original flow"
50
+ :model-value="isPreviousIdPersisted"
51
+ :disabled="restoredFileObj.id ? false : true"
52
+ @update:model-value="isPreviousIdPersisted = $event"
53
+ />
54
+ <div v-if="errors.length">
55
+ <v-error
56
+ v-for="(error, indexError) in errors"
57
+ :key="`errorIndex-${indexError}`"
58
+ :error="{ extensions: { code: 'Error' }, message: error }"
59
+ ></v-error>
60
+ <div style="margin-top: 15px">There are some errors in the file you are trying to restore. Do you want to continue?</div>
61
+ </div>
62
+ <div v-else>
63
+ <div style="margin-top: 15px">Do you want to continue?</div>
49
64
  </div>
50
65
  </v-card-text>
51
66
  <v-card-actions>
@@ -145,6 +160,9 @@ export default defineComponent({
145
160
  },
146
161
  ]);
147
162
 
163
+ const flowDuplicatedName = ref("");
164
+ const isPreviousIdPersisted = ref(false);
165
+
148
166
  return {
149
167
  headers,
150
168
  flows,
@@ -156,13 +174,17 @@ export default defineComponent({
156
174
  onRestoredFileChanged,
157
175
  onRestoreButtonClicked,
158
176
  goToFlow,
159
- onConfirmRestore
177
+ onConfirmRestore,
178
+ flowDuplicatedName,
179
+ isPreviousIdPersisted,
180
+ restoredFileObj,
160
181
  };
161
182
 
162
183
  async function duplicate(item: IFlow, isDuplicate = true) {
163
184
  try {
164
185
  const response = await api.post("/flows", {
165
- name: isDuplicate ? `${item.name} - Copy` : item.name,
186
+ id: !isDuplicate && isPreviousIdPersisted.value ? item.id : undefined,
187
+ name: isDuplicate ? item.name : flowDuplicatedName.value,
166
188
  status: "inactive",
167
189
  icon: item.icon,
168
190
  accountability: item.accountability,
@@ -220,15 +242,24 @@ export default defineComponent({
220
242
 
221
243
  await flowsStore.hydrate();
222
244
  flows.value = unref(flowsStore.flows);
245
+ isPreviousIdPersisted.value = false;
223
246
 
224
247
  notificationsStore.add({
225
248
  type: "success",
226
- title: isDuplicate ? "Flow Duplicated successfully" : `Flow ${item.name} restored successfully`,
249
+ title: isDuplicate ? "Flow Duplicated successfully" : `Flow "${item.name}" restored successfully`,
227
250
  closeable: true,
228
251
  persist: true,
229
252
  });
230
253
  } catch (error) {
231
- console.log(error);
254
+ notificationsStore.add({
255
+ type: "error",
256
+ title: isDuplicate ? "Flow Duplication failed" : `Failed to restore Flow "${item.name}"`,
257
+ closeable: true,
258
+ persist: true,
259
+ });
260
+ } finally {
261
+ if (restoredFile.value)
262
+ restoredFile.value.value = null;
232
263
  }
233
264
  }
234
265
 
@@ -249,6 +280,7 @@ export default defineComponent({
249
280
  operations: Partial<IOperation>[];
250
281
  }
251
282
  const sanitizedFlow: ISanitizedFlow = {
283
+ id: item.id,
252
284
  name: item.name,
253
285
  icon: item.icon,
254
286
  color: item.color,
@@ -307,11 +339,14 @@ export default defineComponent({
307
339
  }
308
340
  }
309
341
 
310
- if (errors.value.length) {
311
- restoreConfirmationDialog.value = true;
312
- restoredFileObj.value = parsedResult;
342
+ restoreConfirmationDialog.value = true;
343
+ restoredFileObj.value = parsedResult;
344
+
345
+ flowDuplicatedName.value = `${parsedResult.name} - Copy`;
346
+ if (parsedResult.id) {
347
+ isPreviousIdPersisted.value = true;
313
348
  } else {
314
- await duplicate(parsedResult, false);
349
+ isPreviousIdPersisted.value = false;
315
350
  }
316
351
  } catch (error) {
317
352
  console.log(error);
@@ -321,12 +356,10 @@ export default defineComponent({
321
356
  }
322
357
 
323
358
  function onRestoreButtonClicked() {
324
- console.log("restore button clicked");
325
359
  restoredFile.value?.click();
326
360
  }
327
361
 
328
362
  function goToFlow({ item }: { item: IFlow }) {
329
- console.log("go to flow", item);
330
363
  router.push(`/settings/flows/${item.id}`);
331
364
  }
332
365