@gravitee/ui-components 3.25.3-typescript-fdacf14 → 3.25.3-typescript-493e1dd

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.
Files changed (183) hide show
  1. package/package.json +5 -13
  2. package/src/atoms/gv-autocomplete.js +422 -1
  3. package/src/atoms/gv-button.js +397 -1
  4. package/src/atoms/gv-checkbox.js +178 -1
  5. package/src/atoms/gv-date-picker-calendar.js +812 -1
  6. package/src/atoms/gv-date-picker-cell.js +174 -1
  7. package/src/atoms/gv-date-picker.js +638 -1
  8. package/src/atoms/gv-file-upload.js +348 -1
  9. package/src/atoms/gv-icon.js +93 -1
  10. package/src/atoms/gv-image.js +135 -1
  11. package/src/atoms/gv-input-message.js +78 -1
  12. package/src/atoms/gv-input.js +508 -1
  13. package/src/atoms/gv-link.js +204 -1
  14. package/src/atoms/gv-message.js +133 -1
  15. package/src/atoms/gv-metric.js +112 -1
  16. package/src/atoms/gv-relative-time.js +143 -1
  17. package/src/atoms/gv-select-native.js +363 -1
  18. package/src/atoms/gv-select.js +413 -1
  19. package/src/atoms/gv-spinner.js +54 -1
  20. package/src/atoms/gv-state.js +125 -1
  21. package/src/atoms/gv-switch.js +235 -1
  22. package/src/atoms/gv-tag.js +162 -1
  23. package/src/atoms/gv-text.js +160 -1
  24. package/src/charts/gv-chart-bar.js +101 -1
  25. package/src/charts/gv-chart-gauge.js +92 -1
  26. package/src/charts/gv-chart-histogram.js +78 -1
  27. package/src/charts/gv-chart-line.js +218 -1
  28. package/src/charts/gv-chart-map.js +111 -1
  29. package/src/charts/gv-chart-pie.js +89 -1
  30. package/src/index.js +77 -1
  31. package/src/lib/cron-expression.js +176 -1
  32. package/src/lib/date.js +43 -1
  33. package/src/lib/events.js +26 -1
  34. package/src/lib/http-client-schema-form.js +67 -1
  35. package/src/lib/http.js +237 -1
  36. package/src/lib/i18n.js +93 -1
  37. package/src/lib/item.js +110 -1
  38. package/src/lib/properties.js +171 -1
  39. package/src/lib/schema-form.js +39 -1
  40. package/src/lib/studio.js +144 -1
  41. package/src/lib/style.js +39 -1
  42. package/src/lib/text-format.js +65 -1
  43. package/src/lib/theme.js +60 -1
  44. package/src/lib/utils.js +106 -1
  45. package/src/mixins/chart-element.js +153 -1
  46. package/src/mixins/input-element.js +136 -1
  47. package/src/mixins/item-resource.js +102 -1
  48. package/src/mixins/keyboard-element.js +62 -1
  49. package/src/mixins/update-after-browser.js +30 -1
  50. package/src/mixins/with-resize-observer.js +62 -1
  51. package/src/mixins/with-skeleton-attribute.js +109 -1
  52. package/src/molecules/gv-card-full.js +209 -1
  53. package/src/molecules/gv-card-list.js +101 -1
  54. package/src/molecules/gv-card.js +130 -1
  55. package/src/molecules/gv-category-list.js +56 -1
  56. package/src/molecules/gv-category.js +163 -1
  57. package/src/molecules/gv-code.js +334 -1
  58. package/src/molecules/gv-confirm.js +175 -1
  59. package/src/molecules/gv-cron-editor.js +685 -1
  60. package/src/molecules/gv-dropdown-menu.js +108 -1
  61. package/src/molecules/gv-expandable.js +116 -1
  62. package/src/molecules/gv-expression-language.js +263 -1
  63. package/src/molecules/gv-identity-picture.js +139 -1
  64. package/src/molecules/gv-list.js +214 -1
  65. package/src/molecules/gv-metrics.js +147 -1
  66. package/src/molecules/gv-modal.js +203 -1
  67. package/src/molecules/gv-nav.js +180 -1
  68. package/src/molecules/gv-option.js +230 -1
  69. package/src/molecules/gv-plans.js +400 -1
  70. package/src/molecules/gv-popover.js +323 -1
  71. package/src/molecules/gv-promote.js +203 -1
  72. package/src/molecules/gv-rating-list.js +341 -1
  73. package/src/molecules/gv-rating.js +234 -1
  74. package/src/molecules/gv-row-expandable.js +42 -1
  75. package/src/molecules/gv-row.js +205 -1
  76. package/src/molecules/gv-stats.js +110 -1
  77. package/src/molecules/gv-stepper.js +274 -1
  78. package/src/molecules/gv-table.js +644 -1
  79. package/src/molecules/gv-tree.js +238 -1
  80. package/src/organisms/gv-documentation.js +205 -1
  81. package/src/organisms/gv-header.js +276 -1
  82. package/src/organisms/gv-http-client.js +258 -1
  83. package/src/organisms/gv-menu.js +258 -1
  84. package/src/organisms/gv-newsletter-subscription.js +258 -1
  85. package/src/organisms/gv-pagination.js +179 -1
  86. package/src/organisms/gv-properties.js +860 -1
  87. package/src/organisms/gv-resizable-views.js +371 -1
  88. package/src/organisms/gv-resources.js +496 -1
  89. package/src/organisms/gv-schema-form-array.js +237 -1
  90. package/src/organisms/gv-schema-form-control-object.js +141 -1
  91. package/src/organisms/gv-schema-form-control.js +419 -1
  92. package/src/organisms/gv-schema-form.js +700 -1
  93. package/src/organisms/gv-tabs.js +201 -1
  94. package/src/organisms/gv-user-menu.js +298 -1
  95. package/src/organisms/gv-vertical-menu.js +119 -1
  96. package/src/policy-studio/gv-flow-step.js +443 -1
  97. package/src/policy-studio/gv-flow.js +595 -1
  98. package/src/policy-studio/gv-policy-studio-menu.js +689 -1
  99. package/src/policy-studio/gv-policy-studio.js +1712 -1
  100. package/src/styles/empty.js +35 -1
  101. package/src/styles/input.js +262 -1
  102. package/src/styles/link.js +31 -1
  103. package/src/styles/shapes.js +17 -1
  104. package/src/styles/skeleton.js +52 -1
  105. package/src/styles/zoom.js +39 -1
  106. package/src/theme/gv-theme.js +197 -1
  107. package/wc/gv-autocomplete.js +1 -1
  108. package/wc/gv-button.js +1 -1
  109. package/wc/gv-card-full.js +1 -1
  110. package/wc/gv-card-list.js +1 -1
  111. package/wc/gv-card.js +1 -1
  112. package/wc/gv-category-list.js +1 -1
  113. package/wc/gv-category.js +1 -1
  114. package/wc/gv-chart-bar.js +1 -1
  115. package/wc/gv-chart-gauge.js +1 -1
  116. package/wc/gv-chart-histogram.js +1 -1
  117. package/wc/gv-chart-line.js +1 -1
  118. package/wc/gv-chart-map.js +1 -1
  119. package/wc/gv-chart-pie.js +1 -1
  120. package/wc/gv-checkbox.js +1 -1
  121. package/wc/gv-code.js +1 -1
  122. package/wc/gv-confirm.js +1 -1
  123. package/wc/gv-cron-editor.js +1 -1
  124. package/wc/gv-date-picker-calendar.js +1 -1
  125. package/wc/gv-date-picker-cell.js +1 -1
  126. package/wc/gv-date-picker.js +1 -1
  127. package/wc/gv-documentation.js +1 -1
  128. package/wc/gv-dropdown-menu.js +1 -1
  129. package/wc/gv-expandable.js +1 -1
  130. package/wc/gv-expression-language.js +1 -1
  131. package/wc/gv-file-upload.js +1 -1
  132. package/wc/gv-flow-step.js +1 -1
  133. package/wc/gv-flow.js +1 -1
  134. package/wc/gv-header.js +1 -1
  135. package/wc/gv-http-client.js +1 -1
  136. package/wc/gv-icon.js +1 -1
  137. package/wc/gv-identity-picture.js +1 -1
  138. package/wc/gv-image.js +1 -1
  139. package/wc/gv-input-message.js +1 -1
  140. package/wc/gv-input.js +1 -1
  141. package/wc/gv-link.js +1 -1
  142. package/wc/gv-list.js +1 -1
  143. package/wc/gv-menu.js +1 -1
  144. package/wc/gv-message.js +1 -1
  145. package/wc/gv-metric.js +1 -1
  146. package/wc/gv-metrics.js +1 -1
  147. package/wc/gv-modal.js +1 -1
  148. package/wc/gv-nav.js +1 -1
  149. package/wc/gv-newsletter-subscription.js +1 -1
  150. package/wc/gv-option.js +1 -1
  151. package/wc/gv-pagination.js +1 -1
  152. package/wc/gv-plans.js +1 -1
  153. package/wc/gv-policy-studio-menu.js +1 -1
  154. package/wc/gv-policy-studio.js +1 -1
  155. package/wc/gv-popover.js +1 -1
  156. package/wc/gv-promote.js +1 -1
  157. package/wc/gv-properties.js +1 -1
  158. package/wc/gv-rating-list.js +1 -1
  159. package/wc/gv-rating.js +1 -1
  160. package/wc/gv-relative-time.js +1 -1
  161. package/wc/gv-resizable-views.js +1 -1
  162. package/wc/gv-resources.js +1 -1
  163. package/wc/gv-row-expandable.js +1 -1
  164. package/wc/gv-row.js +1 -1
  165. package/wc/gv-schema-form-array.js +1 -1
  166. package/wc/gv-schema-form-control-object.js +1 -1
  167. package/wc/gv-schema-form-control.js +1 -1
  168. package/wc/gv-schema-form.js +1 -1
  169. package/wc/gv-select-native.js +1 -1
  170. package/wc/gv-select.js +1 -1
  171. package/wc/gv-spinner.js +1 -1
  172. package/wc/gv-state.js +1 -1
  173. package/wc/gv-stats.js +1 -1
  174. package/wc/gv-stepper.js +1 -1
  175. package/wc/gv-switch.js +1 -1
  176. package/wc/gv-table.js +1 -1
  177. package/wc/gv-tabs.js +1 -1
  178. package/wc/gv-tag.js +1 -1
  179. package/wc/gv-text.js +1 -1
  180. package/wc/gv-theme.js +1 -1
  181. package/wc/gv-tree.js +1 -1
  182. package/wc/gv-user-menu.js +1 -1
  183. package/wc/gv-vertical-menu.js +1 -1
@@ -1 +1,1712 @@
1
- var e=Object.create?function(e,t,i,o){void 0===o&&(o=i),Object.defineProperty(e,o,{enumerable:!0,get:function(){return t[i]}})}:function(e,t,i,o){void 0===o&&(o=i),e[o]=t[i]},t=Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t},i=function(i){if(i&&i.__esModule)return i;var o={};if(null!=i)for(var s in i)"default"!==s&&Object.prototype.hasOwnProperty.call(i,s)&&e(o,i,s);return t(o,i),o};Object.defineProperty(exports,"__esModule",{value:!0}),exports.GvPolicyStudio=void 0;const o=require("lit"),s=require("../lib/studio"),n=require("../lib/events"),r=require("../lib/i18n");require("../atoms/gv-button"),require("../atoms/gv-icon"),require("../molecules/gv-option"),require("../organisms/gv-documentation"),require("../organisms/gv-resizable-views"),require("../organisms/gv-schema-form"),require("../organisms/gv-http-client"),require("../organisms/gv-tabs"),require("../molecules/gv-row"),require("./gv-flow"),require("./gv-flow-step"),require("./gv-policy-studio-menu");const l=require("../styles/empty"),a=require("lit/directives/cache"),d=require("../lib/utils"),c=require("../mixins/keyboard-element");class h extends((0,c.KeyboardElement)(o.LitElement)){static get properties(){return{policies:{type:Array},services:{type:Object},resourceTypes:{type:Array,attribute:"resource-types"},propertyProviders:{type:Array,attribute:"property-providers"},dynamicPropertySchema:{type:Object,attribute:"dynamic-property-schema"},tabId:{type:String,attribute:"tab-id"},_tabId:{type:String,attribute:!1},definition:{type:Object},_definition:{type:Object,attribute:!1},documentation:{type:Object},flowSchema:{type:Object,attribute:"flow-schema"},configurationSchema:{type:Object,attribute:"configuration-schema"},_configurationSchema:{type:Object,attribute:!1},configurationInformation:{type:String,attribute:"configuration-information"},isDirty:{type:Boolean,attribute:"dirty",reflect:!0},_dragPolicy:{type:Object,attribute:!1},_dropPolicy:{type:Object,attribute:!1},selectedFlowsId:{type:Array,attribute:"selected-flows-id"},_selectedFlowsId:{type:Array,attribute:!1},_currentPolicyId:{type:String,attribute:!1},_searchPolicyQuery:{type:String,attribute:!1},_searchFlowQuery:{type:String,attribute:!1},_flowStepSchema:{type:Object,attribute:!1},_currentFlowStep:{type:Object,attribute:!1},_policyFilter:{type:Array,attribute:!1},_flowFilter:{type:Array,attribute:!1},_currentAskConfirmation:{type:Boolean,attribute:!1},hasProperties:{type:Boolean,attribute:"has-properties"},_hasProperties:{type:Boolean,attribute:!1},hasResources:{type:Boolean,attribute:"has-resources"},hasPolicyFilter:{type:Boolean,attribute:"has-policy-filter"},flowsTitle:{type:String,attribute:"flows-title"},sortable:{type:Boolean},canAdd:{type:Boolean,attribute:"can-add"},readonly:{type:Boolean},readonlyPlans:{type:Boolean,attribute:"readonly-plans"},canDebug:{type:Boolean,attribute:"can-debug"},_canDebug:{type:Boolean,attribute:!1},debugResponse:{type:Object,attribute:"debug-response"},hasConditionalSteps:{type:Boolean,attribute:"has-conditional-steps"}}}static get styles(){return[l.empty,s.methods,o.css`:host{box-sizing:border-box;--height:var(--gv-policy-studio--h, calc(100vh - 32px));height:var(--height);--height-in-tabs:calc(var(--height) - 25px)}.box{height:var(--height);display:flex}.design,.properties{display:flex}gv-resizable-views{width:100%}.editable-name{padding:.5rem 1rem;font-size:16px}.editable-name span{color:#bfbfbf;font-size:12px}.form__control{margin:.5rem}gv-input{width:100%}.flow-name{display:flex;align-items:center}.flow-name.dirty{font-style:italic;opacity:.8}.flow-name gv-icon{--gv-icon--s:24px;margin-right:.2rem}.flow-path{margin-left:.2rem}.title_methods{margin-left:.5rem}.two-cols{display:flex;width:100%;height:100%}.two-cols>*{flex:1}.left-menu{border-left:1px solid #d9d9d9;height:var(--height-in-tabs)}.right-menu{border-right:1px solid #d9d9d9;height:var(--height-in-tabs)}.two-cols>:first-child{border-right:1px solid #d9d9d9}.flow-step__container{overflow:hidden;position:relative;overflow:hidden;height:99%}.flow-step__form{padding:0 .5rem;overflow:auto}.flow-step__form-title{text-transform:uppercase;letter-spacing:.2rem}gv-tabs{width:100%;height:100%;display:inline-block}gv-properties,gv-resizable-views,gv-resources{height:var(--height-in-tabs)}gv-properties,gv-resources{width:100%}gv-properties.properties{--gv-properties-table--colmg:10px}.api-settings{display:flex;flex-direction:column;border-left:1px solid #bfbfbf;height:var(--height-in-tabs)}.debug{display:flex;flex-direction:column;border-left:1px solid #bfbfbf;height:var(--height-in-tabs)}.api-settings-information{display:flex;align-items:center}.api-settings-information__icon{--gv-icon--c:var(--gv-theme-color, #5a7684);--gv-icon-opacity--c:var(--gv-theme-color-info-light, #64b5f6)}.api-settings-information__blockquote,.debug-information__blockquote{border-left:1px solid var(--gv-theme-color,#5a7684);margin:15px;padding-left:15px;font-size:14px}.flow-settings gv-schema-form{flex:1;padding:.5rem}.search{display:flex;justify-content:stretch}gv-input{margin:.2rem 0;width:100%}.header-actions,.search-policies{display:flex;flex-direction:column;align-items:center;margin:.5rem}.search-policies{margin:1.5rem .5rem .5rem}.footer-actions>gv-button.btn-large,.footer-actions>gv-option{width:100%}.footer-actions{display:flex;flex-direction:column;align-items:center;padding:.5rem 0;margin:.5rem 15px;border-top:1px solid #bfbfbf}.header-actions .title{text-transform:uppercase;text-align:center;letter-spacing:.3rem;color:#bfbfbf;font-size:18px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;width:240px;min-height:25px}.header-actions>*,.search-policies>*{margin-bottom:1rem}`]}constructor(){super(),this.isDirty=!1,this.policies=[],this.resourceTypes=[],this.tabId="design",this.selectedFlowsId=[],this.flowsTitle="Flows",this.sortable=!1,this.services={},this._definition={flows:[]},this._tabs=[{id:"design",title:"Design",icon:"navigation:exchange"}],this._policyFilter=[],this._flowFilter=[]}set hasProperties(e){e&&Promise.resolve().then((()=>i(require("../organisms/gv-properties")))).then((()=>{this._tabs=[...this._tabs,{id:"properties",title:"Properties",icon:"general:settings#1"}],this.requestUpdate()})),this._hasProperties=e}get hasProperties(){return this._hasProperties}set hasResources(e){e&&Promise.resolve().then((()=>i(require("../organisms/gv-resources")))).then((()=>{this._tabs=[...this._tabs,{id:"resources",title:"Resources",icon:"general:settings#5"}],this.requestUpdate()}))}set canDebug(e){e&&(this._tabs=[...this._tabs,{id:"debug",title:"Try it",icon:"content:send"}])}get _flowFilterOptions(){if(this.definedPlans.length>0)return[{id:"api",title:"Api",icon:"shopping:box#3"},{id:"plan",title:"Plans",icon:"shopping:sale#2"}]}set hasPolicyFilter(e){e&&(this._policyFilterOptions=[{id:"onRequest",title:"Request",icon:"navigation:arrow-from-left"},{id:"onResponse",title:"Response",icon:"navigation:arrow-from-right"}])}set configurationSchema(e){e&&this._tabs.splice(1,0,{id:"settings",title:"Configuration",icon:"general:settings#2"}),this._configurationSchema=e}get configurationSchema(){return this._configurationSchema}onKeyboard(){if(null==this._currentAskConfirmation)if(this.isPressed(c.KEYS.Shift,c.KEYS.Ctrl,c.KEYS.Space)){const e=this.shadowRoot.querySelector("#search-policy");e&&e.focus()}else if(this.isPressed(c.KEYS.Ctrl,c.KEYS.Space)){const e=this.shadowRoot.querySelector("#search-flow");e&&e.focus()}}set tabId(e){null!=e&&["design","settings","properties","resources","debug"].includes(e)?this._tabId=e:this._tabId="design"}get tabId(){return this._tabId}set definition(e){if(e){const t=this._generateFlowsId(e.flows),i=this._generateId("resource-",e.resources),o=null==e.plans?[]:e.plans.map((e=>({...e,flows:this._generatePlanFlowsId(e)})));this._initialDefinition={...e,flows:t,resources:i,plans:o},this._definition=(0,d.deepClone)(this._initialDefinition),this.isDirty=!1,this._selectFirstFlow()}}get definition(){return this._definition}set selectedFlowsId(e){null!=e&&Array.isArray(e)&&(this._selectedFlowsId=e.filter((e=>null!=this._findFlowById(e))),e.length!==this._selectedFlowsId.length&&this._selectFirstFlow(!0))}get selectedFlowsId(){return this._selectedFlowsId.filter((e=>null!=this._findFlowById(e)))}_updateSelectedFlows(e){this.selectedFlowsId=e,(0,n.dispatchCustomEvent)(this,"select-flows",{flows:this.selectedFlowsId})}_selectFirstFlow(e=!1){if(0===this.selectedFlowsId.length){let t=null;if(this.definedFlows.length>0&&null!=this.definedFlows[0]._id)t=this.definedFlows[0];else if(this.definedPlans.length>0){const e=this.definedPlans.find((e=>null!=e.flows&&e.flows.length>0&&null!=e.flows[0]._id));e&&(t=e.flows[0])}null!=t&&(e?this._updateSelectedFlows([t._id]):this.selectedFlowsId=[t._id])}}_getFlowElement(e){return this.shadowRoot.querySelector(`[id="${e}"]`)}_onDragEndPolicy(){this.shadowRoot.querySelectorAll("gv-flow").forEach((e=>e.onDragEnd()))}async _onDropPolicy({detail:e}){try{await this._askToValidateForms();const t=e.policy,i=this._findFlowById(e.flowId);let o,s=t.name,n="",r="",l={},a=!1;e.flowStep?(o=e.flowStep._id,s=e.flowStep.name,n=e.flowStep.description||"",r=e.flowStep.condition||"",l=e.flowStep.configuration):(o=this._generateFlowStepId(i._id,e.flowKey,e.position),a=!0);const d={_id:o,_new:a,name:s,policy:t.id,description:n,condition:r,enabled:!0,configuration:l},c=null!=e.sourceFlowId?this._findFlowById(e.sourceFlowId):i;if(null!=e.sourcePosition){if(e.sourceFlowKey&&e.sourceFlowKey!==e.flowKey){if(c[e.sourceFlowKey].splice(e.sourcePosition,1),i[e.flowKey].splice(e.position,0,d),null!=this._currentFlowStep&&this._currentFlowStep.step._id===o){this._currentFlowStep.group=e.flowKey;const t=this.buildSchema(this._currentFlowStep.policy);await this._setCurrentFlowStep(this._currentFlowStep,t,!0),this._getFlowElement(i._id).requestUpdate()}}else e.position>e.sourcePosition?(i[e.flowKey].splice(e.position,0,d),c[e.flowKey].splice(e.sourcePosition,1)):(c[e.flowKey].splice(e.sourcePosition,1),i[e.flowKey].splice(e.position,0,d));i._id!==c._id&&this._getFlowElement(i._id).requestUpdate()}else{i[e.flowKey].splice(e.position,0,d);const o=this._getFlowStepForm();if(null==o||!0!==o.dirty){let o=i[e.flowKey][e.position];null==o&&(o=i[e.flowKey][e.position-1]),!0!==e.cancelEdit&&setTimeout((async()=>{await this._editFlowStep({step:o,policy:t,flow:i,group:e.flowKey}),this.updateComplete.then((()=>{const e=this._getFlowElement(i._id);e.selectedStepId=o._id,e.requestUpdate()}))}))}}i._dirty=!0,c._dirty=!0,this.isDirty=!0,this.shadowRoot.querySelectorAll("gv-flow").forEach((e=>e.removeCandidate())),setTimeout((()=>{this._dragPolicy=null,this._dropPolicy=null}),0)}catch(e){this._currentAskConfirmation=null}}_onDeletePolicy({detail:e}){const t=this._findFlowById(e.flowId);t[e.flowKey].splice(e.position,1),t._dirty=!0,this.isDirty=!0,e.target.editing&&this._closeFlowStepForm(!0),this._getFlowElement(e.flowId).requestUpdate()}_onDesign(){this._changeTab("design"),this._splitMainViews()}buildSchema({schema:e}){const t={title:"Description",description:"Description of flow step",type:"string"},i={title:"Condition",description:"Condition the execution of the flow step (support EL)",type:"string","x-schema-form":{"expression-language":!0}};if(e){const o="string"==typeof e?JSON.parse(e):e,s={commonDescription:t,...this.hasConditionalSteps?{commonCondition:i}:{},...o.properties};return{...o,properties:s}}return{properties:{commonDescription:t,...this.hasConditionalSteps?{commonCondition:i}:{}}}}async _editFlowStep({step:e,flow:t,policy:i,group:o}){if(e){this._currentPolicyId=i.id;const s={flow:t,step:e,policy:i,group:o},n=this.buildSchema(i);try{await this._setCurrentFlowStep(s,n),this._updateSelectedFlows([t._id]),this._splitMainViews(),null==localStorage.getItem("gv-policy-studio:keep-documentation-close")&&this._onOpenDocumentation()}catch(e){this._currentAskConfirmation=null}}else await this._closeFlowStepForm(),this._maximizeTopView()}async _onEditFlowStep({detail:{step:e,flow:t,policy:i,group:o}}){return this._editFlowStep({step:e,flow:t,policy:i,group:o})}_getResizableViews(){return this.shadowRoot.querySelector("gv-resizable-views")}_maximizeTopView(){this.selectedFlowsId.length<=1&&this._getResizableViews().maximizeTop()}_maximizeBottomView(){this._getResizableViews().maximizeBottom()}_splitMainViews(){this._getResizableViews().split()}_onChangeFlowStepState({detail:e}){const t=this._findFlowById(e.flowId);t[e.flowKey][e.position].enabled=e.enabled,t._dirty=!0,this.isDirty=!0}async _onCloseFlowStepForm(){try{await this._closeFlowStepForm()}catch(e){this._currentAskConfirmation=null}}async _closeFlowStepForm(e=!1){await this._setCurrentFlowStep(null,null,e)}async _askToValidateForms(){if(null==this._currentAskConfirmation)return this._currentAskConfirmation=!0,Promise.all(this._submitOrConfirmForms()).then((e=>e.filter((e=>null!=e)).length>0?(this._definition=this._buildDefinitionToSave(),this.getChildren().forEach((e=>e.requestUpdate())),this._checkCurrentFlowStep().then((()=>(this.getChildren().forEach((e=>e.requestUpdate())),this.updateComplete.then((()=>(this._currentAskConfirmation=null,e))))))):(this._currentAskConfirmation=null,e)));throw new Error("ask already waiting")}async _setCurrentFlowStep(e,t,i=!1){i||await this._askToValidateForms();const o=(0,d.deepClone)(t);if(null!=e){const i="string"==typeof e.step.configuration?JSON.parse(e.step.configuration):e.step.configuration,s={...e.step,configuration:i},n={...s.configuration,commonDescription:s.description,commonCondition:s.condition};if(this._currentFlowStep={...e,step:s,_initialValues:n},t&&t.properties.scope){const e=o.properties.scope.enum;if(null!=e.find((e=>["REQUEST","REQUEST_CONTENT","RESPONSE","RESPONSE_CONTENT"].includes(e)))){const t="pre"===this._currentFlowStep.group?["REQUEST","REQUEST_CONTENT"]:["RESPONSE","RESPONSE_CONTENT"];o.properties.scope.enum=e.filter((e=>t.includes(e)));const i=this._currentFlowStep.step.configuration.scope;null!=i&&o.properties.scope.enum.includes(i)||(o.properties.scope.default=o.properties.scope.enum[0],this._currentFlowStep.step.configuration.scope=o.properties.scope.enum[0],this._currentFlowStep._initialValues.scope=o.properties.scope.enum[0],this._currentFlowStep._values&&(this._currentFlowStep._values.scope=o.properties.scope.enum[0]))}}}else this._currentFlowStep=null;this._flowStepSchema=o}_refresh(e=!0){e&&this._closeFlowStepForm(!0),this._definition=(0,d.deepClone)(this._definition)}async _onSelectFlows({detail:e}){try{await this._closeFlowStepForm(),this._onCloseDocumentation(),this._updateSelectedFlows(e.flows),this._onDesign()}catch(e){this._currentAskConfirmation=null}}async _onOpenDocumentationFromMenu({detail:{policy:e}}){try{null!=this.documentation&&this.documentation.id===e.id||(await this._closeFlowStepForm(),this._currentPolicyId=e.id,this.getSelectedFlow()?this._splitMainViews():this._maximizeBottomView(),(0,n.dispatchCustomEvent)(this,"fetch-documentation",{policy:e}))}catch(e){}}_fetchDocumentation(e){null!=this.documentation&&this.documentation.id===e.id||(0,n.dispatchCustomEvent)(this,"fetch-documentation",{policy:e})}_onOpenDocumentation(){this._currentFlowStep&&this._currentFlowStep.policy&&this._fetchDocumentation(this._currentFlowStep.policy)}_onOpenDocumentationFromForm(){localStorage.removeItem("gv-policy-studio:keep-documentation-close"),this._onOpenDocumentation()}_findFlowCollection(e){const t=this.definedPlans.find((t=>null!=t.flows.find((t=>t._id===e))));return{plan:t,flows:null!=t?t.flows:this.definedFlows}}_findFlowById(e){let t=this.definedFlows.find((t=>t._id===e));if(null==t){t=this.definedPlans.map((e=>e.flows)).reduce(((e,t)=>e.concat(t)),[]).find((t=>t._id===e))}return t}getSelectedFlow(e=0){const t=this.selectedFlowsId[e];return this._findFlowById(t)}_onTargetPolicy({detail:e}){null==this._currentAskConfirmation&&(this._dragPolicy=e)}_onChangeFlowStep({detail:e}){this._currentFlowStep._values=e.values}_writeFlowStep(e){const{commonDescription:t,commonCondition:i,...o}=e;if(this._currentFlowStep.step._new||this._currentFlowStep.step.description!==t||this._currentFlowStep.step.condition!==i||!(0,d.deepEqual)(this._currentFlowStep.step.configuration,o)){const e=this._findFlowById(this._currentFlowStep.flow._id),s=e[this._currentFlowStep.group].findIndex((e=>e._id===this._currentFlowStep.step._id));e[this._currentFlowStep.group][s].description=t,e[this._currentFlowStep.group][s].condition=i,e[this._currentFlowStep.group][s].configuration=(0,d.deepClone)(o),delete e[this._currentFlowStep.group][s]._new,e[this._currentFlowStep.group][s]._dirty=!0,e._dirty=!0,this.isDirty=!0,this._currentFlowStep.flow=e,this._currentFlowStep.step=e[this._currentFlowStep.group][s]}}async _onSubmitFlowStep({detail:e}){this._writeFlowStep(e.values),await this.requestUpdate("_definition"),this.getChildren().forEach((e=>e.requestUpdate()))}_onCancelFlow(){this._onDesign()}_onSubmitFlow({detail:{values:e}}){const t=this.getSelectedFlow(),i=Object.assign({},this._createFlowFromSchema(),e),o=Object.assign({},t,i);(0,d.deepEqual)(t,o)||(Object.assign(t,o,{_dirty:!0}),this.isDirty=!0,this._refresh())}_onCancelFlowMode(){this._onDesign()}_onSubmitFlowMode({detail:{values:e}}){this._definition["flow-mode"]=e["flow-mode"]||"DEFAULT",this.isDirty=!0,this._refresh()}_onChangeTab({detail:e}){this._changeTab(e.value)}async _changeTabValidator({from:e,to:t}){if("properties"===e){const e=this.shadowRoot.querySelector("gv-properties");if(e.dirty)return e.confirm()}else if("resources"===e){const e=this.shadowRoot.querySelector("gv-resources");if(e.dirty)return e.confirm()}else try{return await this._askToValidateForms()}catch(e){throw this._currentAskConfirmation=null,e}return Promise.resolve()}_changeTab(e){null==this._currentAskConfirmation&&(this.tabId=e,(0,n.dispatchCustomEvent)(this,"change-tab",this.tabId))}_onDragStartFlowStep(e,{detail:t}){null==this._currentAskConfirmation&&(this._dropPolicy=t,this._dragPolicy=t)}_renderFlowEmptyState(e){return o.html`<div slot="content" class="empty"><div>Select a flow ${!0!==e?o.html`or<gv-button @gv-button:click="${this._onAddFlow}" outlined icon="code:plus" large>design new one</gv-button>`:""}</div></div>`}_renderFlow(e=0,t=!0,i){const s=this.getSelectedFlow(e);if(s){const{plan:e}=this._findFlowCollection(s._id),t=this._currentFlowStep?this._currentFlowStep.step._id:null;return o.html`<gv-flow style="height:100%" .id="${s._id}" .flow="${s}" .plan="${e}" .policies="${this.policies}" slot="content" ?disabled="${this._currentAskConfirmation}" .dragPolicy="${this._dragPolicy}" .dropPolicy="${this._dropPolicy}" .selectedStepId="${t}" ?readonly="${i}" ?has-policy-filter="${null!=this._policyFilterOptions}" flows-title="${this.flowsTitle}" @gv-flow:drag-start="${this._onDragStartFlowStep.bind(this,s)}" @gv-flow:edit="${this._onEditFlowStep}" @gv-flow:change-state="${this._onChangeFlowStepState}" @gv-flow:drop="${this._onDropPolicy}" @gv-flow:delete="${this._onDeletePolicy}"></gv-flow>`}return t?this._renderFlowEmptyState(i):o.html``}_onFetchResources(e){const{currentTarget:t,regexTypes:i}=e.detail,o=this.definedResources.filter((e=>null==i||new RegExp(i).test(e.type))).map(((e,t)=>{const i=this.resourceTypes.find((t=>t.id===e.type)),o=document.createElement("gv-row"),s=i.icon?i.icon:null;return o.item={picture:s,name:e.name},{element:o,value:e.name,id:e.type}}));t.options=o}_renderPolicy(e){return this._flowStepSchema&&this.documentation?o.html`<gv-resizable-views direction="horizontal" no-overflow><div slot="top">${this._renderFlowStepForm(e)}</div><div slot="bottom"><gv-documentation .text="${this.documentation.content}" .image="${this.documentation.image}" ?disabled="${this._currentAskConfirmation}" @gv-documentation:close="${this._onCloseDocumentation}"></gv-documentation></div></gv-resizable-views>`:this.documentation?o.html`<gv-documentation .text="${this.documentation.content}" .image="${this.documentation.image}" ?disabled="${this._currentAskConfirmation}" @gv-documentation:close="${this._onCloseDocumentation}"></gv-documentation>`:this._flowStepSchema?this._renderFlowStepForm(e):o.html``}_getFlowStepForm(){return this.shadowRoot.querySelector("#flow-step-form")}_onResetFlowStep(){this._currentFlowStep&&(delete this._currentFlowStep._values,this._getFlowStepForm().reset())}_generateFlowsId(e,t=!1){return this._generateId("f",e,t,!0)}_generatePlanFlowsId(e,t=!1){return this._generateId(e.id,e.flows,t,!0)}_generateFlowStepId(e,t,i){return`${e}_${t}_${i}`}_generateId(e,t,i=!1,o=!1){return t?t.map(((t,s)=>{const n=`${e}_${s}`;return o&&(t.pre&&t.pre.forEach(((e,t)=>e._id=this._generateFlowStepId(n,"pre",t))),t.post&&t.post.forEach(((e,t)=>e._id=this._generateFlowStepId(n,"post",t)))),i||null==t._id?{...t,_id:n}:t})):t}getChildren(){return[...Array.from(this.shadowRoot.querySelectorAll("gv-flow")),...Array.from(this.shadowRoot.querySelectorAll("gv-resizable-views"))]}async getUpdateComplete(){await super.getUpdateComplete(),await Promise.all(this.getChildren().map((e=>e.updateComplete)))}shouldUpdate(e){return e.has("_dragPolicy")?(this.shadowRoot.querySelectorAll("gv-flow").forEach((e=>e.dragPolicy=this._dragPolicy)),!1):e.has("_dropPolicy")?(this.shadowRoot.querySelectorAll("gv-flow").forEach((e=>e.dropPolicy=this._dropPolicy)),!1):super.shouldUpdate(e)}updated(e){e.has("documentation")&&null!=this.documentation&&this.selectedFlowsId.length>1&&this._updateSelectedFlows([this.selectedFlowsId[0]])}_renderFlowStepForm(e){const t=this._currentFlowStep._values||this._currentFlowStep._initialValues,i=[{items:["commonDescription","commonCondition"]},{name:(0,r.i18n)("gv-policy-studio.policy-settings"),default:!0}];return o.html`${(0,a.cache)(this._flowStepSchema&&this._currentFlowStep?o.html`<div class="flow-step__container"><div class="flow-step__form"><gv-schema-form .id="${"flow-step-form"}" .schema="${this._flowStepSchema}" .icon="design:edit" has-header validate-on-render .values="${t}" .dirty="${null!=this._currentFlowStep._values}" ?readonly="${e}" scrollable .groups="${i}" @gv-schema-form:change="${this._onChangeFlowStep}" @gv-schema-form:reset="${this._onResetFlowStep}" @gv-schema-form:fetch-resources="${this._onFetchResources}" @gv-schema-form:submit="${this._onSubmitFlowStep}"><div slot="title" class="flow-step__form-title">${this._currentFlowStep.step.name}</div><gv-button slot="header-left" icon="general:close" outlined small @gv-button:click="${this._onCloseFlowStepForm}" title="Close"></gv-button><gv-button slot="header-left" icon="home:book" ?disabled="${null!=this.documentation}" outlined small @gv-button:click="${this._onOpenDocumentationFromForm}" title="Open documentation"></gv-button></gv-schema-form></div></div>`:"")}`}_onCloseDocumentation(){this.documentation=null,null==this._currentFlowStep?this._maximizeTopView():localStorage.setItem("gv-policy-studio:keep-documentation-close",!0)}_onDeleteFlow({detail:e}){const t=e.content._id,{flows:i}=this._findFlowCollection(t),o=i.find((e=>e._id===t));this._deleteFlow(i,o)}get definedFlows(){return this._definition&&this._definition.flows?this._definition.flows:[]}get definedPlans(){return this._definition&&this._definition.plans?this._definition.plans:[]}get definedResources(){return this._definition&&this._definition.resources?this._definition.resources:[]}get definedProperties(){return this._definition&&this._definition.properties?this._definition.properties:[]}async _onDuplicateFlow({detail:e}){try{await this._askToValidateForms();const t=e.content._id,{plan:i,flows:o}=this._findFlowCollection(t);if(this._addFlow(o,this._findFlowById(t)),null!=i){let e=null;this.definedPlans.find(((t,o)=>t.id===i.id&&(e=o,!0))),i.flows=o,this.definedPlans[e].flows=this._generatePlanFlowsId(i,!0),this._updateSelectedFlows([this.definedPlans[e].flows[o.length-1]._id])}else this._definition.flows=this._generateFlowsId(this._definition.flows),this._updateSelectedFlows([this._definition.flows[this._definition.flows.length-1]._id])}catch(e){this._currentAskConfirmation=null}}_onChangeFlowState({detail:e}){const t=this._findFlowById(e.content._id);t.enabled=e.enabled,t._dirty=!0,this.isDirty=!0}async _onAddFlowPlan({detail:e}){try{await this._askToValidateForms(),this._addFlow(this.definedPlans[e.planIndex].flows),this.definedPlans[e.planIndex].flows=this._generatePlanFlowsId(this.definedPlans[e.planIndex]),this._updateSelectedFlows([this.definedPlans[e.planIndex].flows[this.definedPlans[e.planIndex].flows.length-1]._id])}catch(e){this._currentAskConfirmation=null}}async _onAddFlow(){try{await this._askToValidateForms(),this._addFlow(this._definition.flows),this._definition.flows=this._generateFlowsId(this._definition.flows),this._updateSelectedFlows([this._definition.flows[this._definition.flows.length-1]._id])}catch(e){this._currentAskConfirmation=null}}_addFlow(e,t=null){const i=null==t?this._createFlowFromSchema():{...t,_id:null,id:null,_dirty:!0};return e.push(i),this.isDirty=!0,e}_createFlowFromSchema(){return this._instantiate(this.flowSchema.properties,{name:"",pre:[],post:[],_dirty:!0})}_instantiate(e,t={}){const i={...t};if(e)for(const o of Object.keys(e)){const s=e[o];"object"===s.type&&(i[o]=this._instantiate(s.properties,t={})),void 0!==s.default?i[o]=s.default:"string"===s.type&&(i[o]="")}return i}_deleteFlow(e,t){const i=e.indexOf(t);e.splice(i,1);const o=this.selectedFlowsId.filter((e=>e!==t._id));1===o.length?this._updateSelectedFlows(o):this._selectFirstFlow(!0),this._changeTab("design"),this._refresh(),this.isDirty=!0}_findFlowIndex(e,t){let i=null;return e.find(((e,o)=>e._id===t&&(i=o,!0))),i}async _onReorderFlows({detail:{plan:e}}){try{if(await this._askToValidateForms(),this.isDirty=!0,null!=e){const t=this._generatePlanFlowsId(e,!0);this.selectedFlowsId&&this._updateSelectedFlows(this.selectedFlowsId.map((i=>{const o=this._findFlowIndex(e.flows,i);return null!=o?t[o]._id:i}))),e.flows=t}else{const e=this._generateFlowsId(this._definition.flows,!0);this.selectedFlowsId&&this._updateSelectedFlows(this.selectedFlowsId.map((t=>{const i=this._findFlowIndex(this._definition.flows,t);return null!=i?e[i]._id:t}))),this._definition.flows=e}}catch(e){this._currentAskConfirmation=!1}}_onSearchPolicy({detail:e}){this._searchPolicyQuery=e}_onClearPolicy(){this._searchPolicyQuery=null}_onSearchFlows({detail:e}){this._searchFlowQuery=e}_onClearFlows(){this._searchFlowQuery=null}async _onResetAll(){try{await this._closeFlowStepForm(),this.definition=(0,d.deepClone)(this._initialDefinition)}catch(e){this._currentAskConfirmation=null}}_filterNotValidStep(e){return!0!==e._new}_removePrivateProperties(e){const t={...e};return Object.keys(e).filter((e=>e.startsWith("_"))).forEach((e=>{delete t[e]})),t}_submitOrConfirmForms(){return[...this.shadowRoot.querySelectorAll("gv-schema-form")].filter((e=>{const t=e.isValid();return t?e.submit():e.dirty=!0,!t})).map((e=>e.confirm()))}getPropertiesElement(){return this.shadowRoot.querySelector("gv-properties")}async _checkCurrentFlowStep(){if(this._currentFlowStep&&this.selectedFlowsId){const e=this.selectedFlowsId.map((e=>{const t=this._findFlowById(e);return null==[...t.pre,...t.post].find((e=>e._id===this._currentFlowStep.step._id))?this._closeFlowStepForm(!0):null})).filter((e=>null!==e));return Promise.all(e)}return Promise.resolve()}saved(){this.isDirty&&(this._initialDefinition=(0,d.deepClone)(this._definitionSaved),this._definition=(0,d.deepClone)(this._definitionSaved),this._definitionSaved=null,this.isDirty=!1,this._checkCurrentFlowStep(),this.definedPlans.forEach((e=>{e.flows.forEach((e=>e._dirty=!1))})),this.definedFlows.forEach((e=>e._dirty=!1)),this.getChildren().forEach((e=>e.requestUpdate())))}_buildDefinitionToSave(){const e=this._definition.flows.map((e=>(e.pre=e.pre.filter(this._filterNotValidStep),e.post=e.post.filter(this._filterNotValidStep),e)));let t={...this._definition,flows:e};if(null!=this._definition.plans){const e=this._definition.plans.map((e=>{const t=e.flows.map((e=>(e.pre=e.pre.filter(this._filterNotValidStep),e.post=e.post.filter(this._filterNotValidStep),e)));return{...e,flows:t}}));t={...t,plans:e}}return t}_buildDefinitionToSend(e){const t=e.flows.map((e=>{const t=this._removePrivateProperties(e);return t.pre=t.pre.map(this._removePrivateProperties),t.post=t.post.map(this._removePrivateProperties),t}));let i={...this._definition,flows:t};if(null!=this._definition.plans){const t=e.plans.map((e=>{const t=e.flows.map((e=>{const t=this._removePrivateProperties(e);return t.pre=t.pre.map(this._removePrivateProperties),t.post=t.post.map(this._removePrivateProperties),t}));return{...e,flows:t}}));i={...i,plans:t}}if(null!=this._definition.properties){const e=this._definition.properties.map(this._removePrivateProperties);i={...i,properties:e}}if(null!=this._definition.resources){const e=this._definition.resources.map(this._removePrivateProperties);i={...i,resources:e}}return i}_onSaveAll(){this.hasProperties&&this.getPropertiesElement().submit(),Promise.all(this._submitOrConfirmForms()).then((()=>{this._definitionSaved=this._buildDefinitionToSave();const e=this._buildDefinitionToSend(this._definitionSaved);(0,n.dispatchCustomEvent)(this,"save",{definition:e,services:this.services})})).catch((e=>{console.error("[policy-studio] Error on save",e)}))}_onDebug(e){this.hasProperties&&this.getPropertiesElement().submit(),Promise.all(this._submitOrConfirmForms()).then((()=>{const t=this._buildDefinitionToSend(this._buildDefinitionToSave());(0,n.dispatchCustomEvent)(this,"debug",{definition:t,services:this.services,request:e.detail.request})})).catch((e=>{console.error("[policy-studio] Error on debug",e)}))}get filteredFlows(){return 0===this._flowFilter.length||this._flowFilter.includes("api")?this.definedFlows:null}get filteredPlans(){return 0===this._flowFilter.length||this._flowFilter.includes("plan")?this.definedPlans:null}_onFilterFlows({detail:e}){this._flowFilter.includes(e.id)?this._flowFilter=[]:this._flowFilter=[e.id]}_getFilteredPolicies(){return this._policyFilter.length>0?this.policies.filter((e=>e.onRequest&&this._policyFilter.includes("onRequest")||e.onResponse&&this._policyFilter.includes("onResponse"))):this.policies}_onFilterPolicies({detail:e}){this._policyFilter.includes(e.id)?this._policyFilter=[]:this._policyFilter=[e.id]}_renderDesign(e){return o.html`<div id="design" slot="content" class="design"><gv-resizable-views no-overflow><div slot="top">${this._renderFlow(0,!0,e)}</div><div slot="bottom">${this._renderFlow(1,!1,e)} ${this._renderPolicy(e)} ${this._renderFlowForm(e)}</div></gv-resizable-views>${!0!==e?o.html`<gv-policy-studio-menu class="right-menu" ?disabled="${this._currentAskConfirmation}" .policies="${this._getFilteredPolicies()}" .selectedIds="${[this._currentPolicyId]}" .query="${this._searchPolicyQuery}" ?has-policy-filter="${null!=this._policyFilterOptions}" ?readonly="${e}" @gv-policy-studio-menu:target-policy="${this._onTargetPolicy}" @gv-policy-studio-menu:fetch-documentation="${this._onOpenDocumentationFromMenu}" @gv-policy-studio-menu:dragend-policy="${this._onDragEndPolicy}"><div slot="header" class="search-policies">${null!=this._policyFilterOptions?o.html`<gv-option ?disabled="${this._currentAskConfirmation}" .options="${this._policyFilterOptions}" multiple="multiple" outlined .value="${this._policyFilter}" small @gv-option:select="${this._onFilterPolicies}"></gv-option>`:""}<gv-input id="search-policy" ?disabled="${this._currentAskConfirmation}" placeholder="Filter policies (Shift + Ctrl + Space)" type="search" small @gv-input:input="${this._onSearchPolicy}" @gv-input:clear="${this._onClearPolicy}"></gv-input></div></gv-policy-studio-menu>`:""}</div>`}_renderDebug(){const e=this.debugResponse?this.debugResponse.response:void 0,t=this.debugResponse?this.debugResponse.isLoading:void 0,i=this.debugResponse&&this.debugResponse.request?this.debugResponse.request.path:void 0,s=this.debugResponse&&this.debugResponse.request?this.debugResponse.request.method:void 0;return o.html`<gv-http-client id="debug" slot="content" class="debug" @gv-http-client:send="${this._onDebug}" .response="${e}" .path="${i}" .method="${s}" ?loading="${t}"></gv-http-client>`}_renderConfigurationForm(e){if(this.configurationSchema){const t=(0,d.deepClone)(this._definition);return o.html`<div id="settings" slot="content" class="api-settings" @dragover="${this._onDesign}"><gv-schema-form .schema="${this.configurationSchema}" id="api-settings-form" .values="${t}" has-header has-footer scrollable ?readonly="${e}" @gv-schema-form:cancel="${this._onCancelFlowMode}" @gv-schema-form:submit="${this._onSubmitFlowMode}">${this.configurationInformation?o.html`<div class="api-settings-information" slot="title"><gv-icon class="api-settings-information__icon" title="Info" shape="code:info"></gv-icon><blockquote class="api-settings-information__blockquote">${this.configurationInformation}</blockquote></div>`:""}</gv-schema-form></div>`}return o.html``}_renderFlowForm(e){if(this.flowSchema&&null==this._flowStepSchema&&null==this.documentation&&1===this.selectedFlowsId.length){const t=this.getSelectedFlow();if(t){const i=(0,d.deepClone)(t);return o.html`<div slot="content" class="flow-settings"><gv-schema-form .schema="${this.flowSchema}" id="settings-form" .values="${i}" has-header scrollable ?readonly="${e}" @gv-schema-form:cancel="${this._onCancelFlow}" @gv-schema-form:submit="${this._onSubmitFlow}"><div slot="title" class="flow-step__form-title">Flow configuration</div></gv-schema-form></div>`}}}_onResourcesChange({detail:e}){this.definition.resources=e.resources,this.isDirty=!0}_onPropertiesChange({detail:e}){this.definition.properties=e.properties,this.isDirty=!0}_onSaveProvider({detail:e}){this.services["dynamic-property"]=e.provider,this.isDirty=!0}_onSwitchEncryptedProperty({detail:e}){this.isDirty=!0}render(){const e=this._getReadonlyModeForDesign();return o.html`<div class="box"><gv-policy-studio-menu class="left-menu" .api-name="${this._definition.name}" .flows="${this.filteredFlows}" .plans="${this.filteredPlans}" .selectedIds="${this.selectedFlowsId}" ?disabled="${this._currentAskConfirmation}" ?sortable="${this.sortable&&!0!==this.readonly}" ?readonly="${this.readonly}" ?readonlyPlans="${this.readonlyPlans}" flows-title="${this.flowsTitle}" .query="${this._searchFlowQuery}" ?can-add="${this.canAdd&&!this.readonly}" @gv-policy-studio-menu:reorder-flows="${this._onReorderFlows}" @gv-policy-studio-menu:change-flow-state="${this._onChangeFlowState}" @gv-policy-studio-menu:add-flow="${this._onAddFlow}" @gv-policy-studio-menu:add-flow-plan="${this._onAddFlowPlan}" @gv-policy-studio-menu:delete-flow="${this._onDeleteFlow}" @gv-policy-studio-menu:duplicate-flow="${this._onDuplicateFlow}" @gv-policy-studio-menu:select-flows="${this._onSelectFlows}"><div slot="header" class="header-actions"><div class="title">${this._definition.name}</div>${null!=this._flowFilterOptions?o.html`<gv-option ?disabled="${this._currentAskConfirmation}" .options="${this._flowFilterOptions}" multiple="multiple" outlined .value="${this._flowFilter}" small @gv-option:select="${this._onFilterFlows}"></gv-option>`:""}<gv-input ?disabled="${this._currentAskConfirmation}" id="search-flow" placeholder="Filter flows (Ctrl + Space)" type="search" small @gv-input:input="${this._onSearchFlows}" @gv-input:clear="${this._onClearFlows}"></gv-input></div>${!0!==this.readonly?o.html`<div slot="footer" class="footer-actions"><gv-button class="btn-large" .disabled="${!this.isDirty||this._currentAskConfirmation}" @gv-button:click="${this._onSaveAll}">Save</gv-button><gv-button link .disabled="${!this.isDirty||this._currentAskConfirmation}" @gv-button:click="${this._onResetAll}">Reset</gv-button></div>`:""}</gv-policy-studio-menu><gv-tabs .value="${this.tabId}" .options="${this._tabs}" .disabled="${this._currentAskConfirmation}" @gv-tabs:change="${this._onChangeTab}" .validator="${this._changeTabValidator.bind(this)}">${this._renderDesign(e)} ${this._renderConfigurationForm(e)} ${this._renderDebug()}<gv-properties id="properties" slot="content" class="properties" .provider="${this.services["dynamic-property"]}" @gv-properties:change="${this._onPropertiesChange}" @gv-properties:save-provider="${this._onSaveProvider}" @gv-properties:switch-encrypted="${this._onSwitchEncryptedProperty}" ?readonly="${e}" encryptable="true" .properties="${this.definedProperties}" .providers="${this.propertyProviders}" .dynamicPropertySchema="${this.dynamicPropertySchema}"></gv-properties><gv-resources id="resources" slot="content" class="resources" @gv-resources:change="${this._onResourcesChange}" ?readonly="${e}" .resources="${this.definedResources}" .types="${this.resourceTypes}"></gv-resources></gv-tabs></div>`}_getReadonlyModeForDesign(){if(this.readonly)return!0;const e=this.getSelectedFlow(0);if(!e)return!1;const{plan:t}=this._findFlowCollection(e._id);if(t&&this.readonlyPlans)return!0;const i=this.getSelectedFlow(1);if(!i)return!1;const{plan:o}=this._findFlowCollection(i._id);return o&&this.readonlyPlans}}exports.GvPolicyStudio=h,window.customElements.define("gv-policy-studio",h);
1
+ /*
2
+ * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { css, html, LitElement } from 'lit';
17
+ import { methods } from '../lib/studio';
18
+ import { dispatchCustomEvent } from '../lib/events';
19
+ import { i18n } from '../lib/i18n';
20
+ import '../atoms/gv-button';
21
+ import '../atoms/gv-icon';
22
+ import '../molecules/gv-option';
23
+ import '../organisms/gv-documentation';
24
+ import '../organisms/gv-resizable-views';
25
+ import '../organisms/gv-schema-form';
26
+ import '../organisms/gv-http-client';
27
+ import '../organisms/gv-tabs';
28
+ import '../molecules/gv-row';
29
+ import './gv-flow';
30
+ import './gv-flow-step';
31
+ import './gv-policy-studio-menu';
32
+ import { empty } from '../styles/empty';
33
+ import { cache } from 'lit/directives/cache';
34
+ import { deepClone, deepEqual } from '../lib/utils';
35
+ import { KeyboardElement, KEYS } from '../mixins/keyboard-element';
36
+ const FLOW_STEP_FORM_ID = 'flow-step-form';
37
+ /**
38
+ * Studio Policy component
39
+ *
40
+ * ⚠️ This component is based on `asciidoctor`, `highlight.js` and `asciidoctor-highlight.js`.
41
+ * To use this component in your project be sure the dependencies are installed or
42
+ * install them with: `npm install asciidoctor highlight.js asciidoctor-highlight.js --save`
43
+ *
44
+ * @fires gv-policy-studio:select-policy - Select policy event
45
+ * @fires gv-policy-studio:save - Event sent when "Save" button is clicked, it contains the whole definition of the API
46
+ * @fires gv-policy-studio:debug - Event sent when validation button of the 'Try it' tab is clicked, it contains the whole definition of the API and the information about the try it request.
47
+ *
48
+ * @attr {Array} policies - Policies available
49
+ * @attr {Array} services - Services available
50
+ * @attr {Array} resourceTypes - Resources types available
51
+ * @attr {Array} propertyProviders - Providers of properties
52
+ * @attr {Array} dynamicPropertySchema - Schema for the dynamic property form
53
+ * @attr {String} tabId - Current tabId to display (design, settings, properties or resources)
54
+ * @attr {Object} definition - The definition of flows
55
+ * @attr {Object} documentation - The documentation to display
56
+ * @attr {Object} flowSchema - The flow form configuration to display in gv-schema-form component
57
+ * @attr {Object} configurationSchema - The form configuration to display in gv-schema-form component
58
+ * @attr {Object} configurationInformation - The information related to api configuration tab
59
+ * @attr {Boolean} isDirty - true if component is dirty
60
+ * @attr {Array} selectedFlowsId - The selected flows id
61
+ * @attr {Boolean} sortable - true if flows are sortable
62
+ * @attr {Boolean} readonly - true if readonly
63
+ * @attr {Boolean} readonly-plans - true if plans' flows can't be modified
64
+ * @attr {Boolean} can-add - true if user can add flow
65
+ * @attr {String} flowsTitle - flows menu title
66
+ * @attr {Boolean} has-policy-filter - true if policies have onRequest/onResponse properties
67
+ * @attr {Boolean} can-debug - true if debug tab should be displayed
68
+ * @attr {Object} debugResponse - true if debug tab should be displayed
69
+ * @attr {Boolean} has-conditional-steps - true if steps can be conditioned
70
+ */
71
+ export class GvPolicyStudio extends KeyboardElement(LitElement) {
72
+ static get properties() {
73
+ return {
74
+ policies: { type: Array },
75
+ services: { type: Object },
76
+ resourceTypes: { type: Array, attribute: 'resource-types' },
77
+ propertyProviders: { type: Array, attribute: 'property-providers' },
78
+ dynamicPropertySchema: { type: Object, attribute: 'dynamic-property-schema' },
79
+ tabId: { type: String, attribute: 'tab-id' },
80
+ _tabId: { type: String, attribute: false },
81
+ definition: { type: Object },
82
+ _definition: { type: Object, attribute: false },
83
+ documentation: { type: Object },
84
+ flowSchema: { type: Object, attribute: 'flow-schema' },
85
+ configurationSchema: { type: Object, attribute: 'configuration-schema' },
86
+ _configurationSchema: { type: Object, attribute: false },
87
+ configurationInformation: { type: String, attribute: 'configuration-information' },
88
+ isDirty: { type: Boolean, attribute: 'dirty', reflect: true },
89
+ _dragPolicy: { type: Object, attribute: false },
90
+ _dropPolicy: { type: Object, attribute: false },
91
+ selectedFlowsId: { type: Array, attribute: 'selected-flows-id' },
92
+ _selectedFlowsId: { type: Array, attribute: false },
93
+ _currentPolicyId: { type: String, attribute: false },
94
+ _searchPolicyQuery: { type: String, attribute: false },
95
+ _searchFlowQuery: { type: String, attribute: false },
96
+ _flowStepSchema: { type: Object, attribute: false },
97
+ _currentFlowStep: { type: Object, attribute: false },
98
+ _policyFilter: { type: Array, attribute: false },
99
+ _flowFilter: { type: Array, attribute: false },
100
+ _currentAskConfirmation: { type: Boolean, attribute: false },
101
+ hasProperties: { type: Boolean, attribute: 'has-properties' },
102
+ _hasProperties: { type: Boolean, attribute: false },
103
+ hasResources: { type: Boolean, attribute: 'has-resources' },
104
+ hasPolicyFilter: { type: Boolean, attribute: 'has-policy-filter' },
105
+ flowsTitle: { type: String, attribute: 'flows-title' },
106
+ sortable: { type: Boolean },
107
+ canAdd: { type: Boolean, attribute: 'can-add' },
108
+ readonly: { type: Boolean },
109
+ readonlyPlans: { type: Boolean, attribute: 'readonly-plans' },
110
+ canDebug: { type: Boolean, attribute: 'can-debug' },
111
+ _canDebug: { type: Boolean, attribute: false },
112
+ debugResponse: { type: Object, attribute: 'debug-response' },
113
+ hasConditionalSteps: { type: Boolean, attribute: 'has-conditional-steps' },
114
+ };
115
+ }
116
+ static get styles() {
117
+ return [
118
+ empty,
119
+ methods,
120
+ // language=CSS
121
+ css `
122
+ :host {
123
+ box-sizing: border-box;
124
+ --height: var(--gv-policy-studio--h, calc(100vh - 32px));
125
+ height: var(--height);
126
+ --height-in-tabs: calc(var(--height) - 25px);
127
+ }
128
+
129
+ .box {
130
+ height: var(--height);
131
+ display: flex;
132
+ }
133
+
134
+ .design,
135
+ .properties {
136
+ display: flex;
137
+ }
138
+
139
+ gv-resizable-views {
140
+ width: 100%;
141
+ }
142
+
143
+ .editable-name {
144
+ padding: 0.5rem 1rem;
145
+ font-size: 16px;
146
+ }
147
+
148
+ .editable-name span {
149
+ color: #bfbfbf;
150
+ font-size: 12px;
151
+ }
152
+
153
+ .form__control {
154
+ margin: 0.5rem;
155
+ }
156
+
157
+ gv-input {
158
+ width: 100%;
159
+ }
160
+
161
+ .flow-name {
162
+ display: flex;
163
+ align-items: center;
164
+ }
165
+
166
+ .flow-name.dirty {
167
+ font-style: italic;
168
+ opacity: 0.8;
169
+ }
170
+
171
+ .flow-name gv-icon {
172
+ --gv-icon--s: 24px;
173
+ margin-right: 0.2rem;
174
+ }
175
+
176
+ .flow-path {
177
+ margin-left: 0.2rem;
178
+ }
179
+
180
+ .title_methods {
181
+ margin-left: 0.5rem;
182
+ }
183
+
184
+ .two-cols {
185
+ display: flex;
186
+ width: 100%;
187
+ height: 100%;
188
+ }
189
+
190
+ .two-cols > * {
191
+ flex: 1;
192
+ }
193
+
194
+ .left-menu {
195
+ border-left: 1px solid #d9d9d9;
196
+ height: var(--height-in-tabs);
197
+ }
198
+
199
+ .right-menu {
200
+ border-right: 1px solid #d9d9d9;
201
+ height: var(--height-in-tabs);
202
+ }
203
+
204
+ .two-cols > *:first-child {
205
+ border-right: 1px solid #d9d9d9;
206
+ }
207
+
208
+ .flow-step__container {
209
+ overflow: hidden;
210
+ position: relative;
211
+ overflow: hidden;
212
+ height: 99%;
213
+ }
214
+
215
+ .flow-step__form {
216
+ padding: 0 0.5rem;
217
+ overflow: auto;
218
+ }
219
+
220
+ .flow-step__form-title {
221
+ text-transform: uppercase;
222
+ letter-spacing: 0.2rem;
223
+ }
224
+
225
+ gv-tabs {
226
+ width: 100%;
227
+ height: 100%;
228
+ display: inline-block;
229
+ }
230
+
231
+ gv-resizable-views,
232
+ gv-properties,
233
+ gv-resources {
234
+ height: var(--height-in-tabs);
235
+ }
236
+
237
+ gv-properties,
238
+ gv-resources {
239
+ width: 100%;
240
+ }
241
+
242
+ gv-properties.properties {
243
+ --gv-properties-table--colmg: 10px;
244
+ }
245
+
246
+ .api-settings {
247
+ display: flex;
248
+ flex-direction: column;
249
+ border-left: 1px solid #bfbfbf;
250
+ height: var(--height-in-tabs);
251
+ }
252
+
253
+ .debug {
254
+ display: flex;
255
+ flex-direction: column;
256
+ border-left: 1px solid #bfbfbf;
257
+ height: var(--height-in-tabs);
258
+ }
259
+
260
+ .api-settings-information {
261
+ display: flex;
262
+ align-items: center;
263
+ }
264
+
265
+ .api-settings-information__icon {
266
+ --gv-icon--c: var(--gv-theme-color, #5a7684);
267
+ --gv-icon-opacity--c: var(--gv-theme-color-info-light, #64b5f6);
268
+ }
269
+
270
+ .api-settings-information__blockquote,
271
+ .debug-information__blockquote {
272
+ border-left: 1px solid var(--gv-theme-color, #5a7684);
273
+ margin: 15px;
274
+ padding-left: 15px;
275
+ font-size: 14px;
276
+ }
277
+
278
+ .flow-settings gv-schema-form {
279
+ flex: 1;
280
+ padding: 0.5rem;
281
+ }
282
+
283
+ .search {
284
+ display: flex;
285
+ justify-content: stretch;
286
+ }
287
+
288
+ gv-input {
289
+ margin: 0.2rem 0;
290
+ width: 100%;
291
+ }
292
+
293
+ .header-actions,
294
+ .search-policies {
295
+ display: flex;
296
+ flex-direction: column;
297
+ align-items: center;
298
+ margin: 0.5rem;
299
+ }
300
+
301
+ .search-policies {
302
+ margin: 1.5rem 0.5rem 0.5rem;
303
+ }
304
+
305
+ .footer-actions > gv-button.btn-large,
306
+ .footer-actions > gv-option {
307
+ width: 100%;
308
+ }
309
+
310
+ .footer-actions {
311
+ display: flex;
312
+ flex-direction: column;
313
+ align-items: center;
314
+ padding: 0.5rem 0;
315
+ margin: 0.5rem 15px;
316
+ border-top: 1px solid #bfbfbf;
317
+ }
318
+
319
+ .header-actions .title {
320
+ text-transform: uppercase;
321
+ text-align: center;
322
+ letter-spacing: 0.3rem;
323
+ color: #bfbfbf;
324
+ font-size: 18px;
325
+ white-space: nowrap;
326
+ overflow: hidden;
327
+ text-overflow: ellipsis;
328
+ width: 240px;
329
+ min-height: 25px;
330
+ }
331
+
332
+ .header-actions > *,
333
+ .search-policies > * {
334
+ margin-bottom: 1rem;
335
+ }
336
+ `,
337
+ ];
338
+ }
339
+ constructor() {
340
+ super();
341
+ this.isDirty = false;
342
+ this.policies = [];
343
+ this.resourceTypes = [];
344
+ this.tabId = 'design';
345
+ this.selectedFlowsId = [];
346
+ this.flowsTitle = 'Flows';
347
+ this.sortable = false;
348
+ this.services = {};
349
+ this._definition = {
350
+ flows: [],
351
+ };
352
+ this._tabs = [{ id: 'design', title: 'Design', icon: 'navigation:exchange' }];
353
+ this._policyFilter = [];
354
+ this._flowFilter = [];
355
+ }
356
+ set hasProperties(value) {
357
+ if (value) {
358
+ import('../organisms/gv-properties').then(() => {
359
+ this._tabs = [...this._tabs, { id: 'properties', title: 'Properties', icon: 'general:settings#1' }];
360
+ this.requestUpdate();
361
+ });
362
+ }
363
+ this._hasProperties = value;
364
+ }
365
+ get hasProperties() {
366
+ return this._hasProperties;
367
+ }
368
+ set hasResources(value) {
369
+ if (value) {
370
+ import('../organisms/gv-resources').then(() => {
371
+ this._tabs = [...this._tabs, { id: 'resources', title: 'Resources', icon: 'general:settings#5' }];
372
+ this.requestUpdate();
373
+ });
374
+ }
375
+ }
376
+ set canDebug(value) {
377
+ if (value) {
378
+ this._tabs = [...this._tabs, { id: 'debug', title: 'Try it', icon: 'content:send' }];
379
+ }
380
+ }
381
+ get _flowFilterOptions() {
382
+ if (this.definedPlans.length > 0) {
383
+ return [
384
+ { id: 'api', title: 'Api', icon: 'shopping:box#3' },
385
+ { id: 'plan', title: 'Plans', icon: 'shopping:sale#2' },
386
+ ];
387
+ }
388
+ }
389
+ set hasPolicyFilter(value) {
390
+ if (value) {
391
+ this._policyFilterOptions = [
392
+ { id: 'onRequest', title: 'Request', icon: 'navigation:arrow-from-left' },
393
+ { id: 'onResponse', title: 'Response', icon: 'navigation:arrow-from-right' },
394
+ ];
395
+ }
396
+ }
397
+ set configurationSchema(value) {
398
+ if (value) {
399
+ this._tabs.splice(1, 0, { id: 'settings', title: 'Configuration', icon: 'general:settings#2' });
400
+ }
401
+ this._configurationSchema = value;
402
+ }
403
+ get configurationSchema() {
404
+ return this._configurationSchema;
405
+ }
406
+ onKeyboard() {
407
+ if (this._currentAskConfirmation == null) {
408
+ if (this.isPressed(KEYS.Shift, KEYS.Ctrl, KEYS.Space)) {
409
+ const search = this.shadowRoot.querySelector('#search-policy');
410
+ if (search) {
411
+ search.focus();
412
+ }
413
+ }
414
+ else if (this.isPressed(KEYS.Ctrl, KEYS.Space)) {
415
+ const search = this.shadowRoot.querySelector('#search-flow');
416
+ if (search) {
417
+ search.focus();
418
+ }
419
+ }
420
+ }
421
+ }
422
+ set tabId(tabId) {
423
+ if (tabId != null && ['design', 'settings', 'properties', 'resources', 'debug'].includes(tabId)) {
424
+ this._tabId = tabId;
425
+ }
426
+ else {
427
+ this._tabId = 'design';
428
+ }
429
+ }
430
+ get tabId() {
431
+ return this._tabId;
432
+ }
433
+ set definition(definition) {
434
+ if (definition) {
435
+ const flows = this._generateFlowsId(definition.flows);
436
+ const resources = this._generateId('resource-', definition.resources);
437
+ const plans = definition.plans == null
438
+ ? []
439
+ : definition.plans.map((plan) => {
440
+ return { ...plan, flows: this._generatePlanFlowsId(plan) };
441
+ });
442
+ this._initialDefinition = { ...definition, flows, resources, plans };
443
+ this._definition = deepClone(this._initialDefinition);
444
+ this.isDirty = false;
445
+ this._selectFirstFlow();
446
+ }
447
+ }
448
+ get definition() {
449
+ return this._definition;
450
+ }
451
+ set selectedFlowsId(selectedFlowsId) {
452
+ if (selectedFlowsId != null && Array.isArray(selectedFlowsId)) {
453
+ this._selectedFlowsId = selectedFlowsId.filter((id) => this._findFlowById(id) != null);
454
+ if (selectedFlowsId.length !== this._selectedFlowsId.length) {
455
+ this._selectFirstFlow(true);
456
+ }
457
+ }
458
+ }
459
+ get selectedFlowsId() {
460
+ return this._selectedFlowsId.filter((id) => this._findFlowById(id) != null);
461
+ }
462
+ _updateSelectedFlows(selectedFlowsId) {
463
+ this.selectedFlowsId = selectedFlowsId;
464
+ dispatchCustomEvent(this, 'select-flows', { flows: this.selectedFlowsId });
465
+ }
466
+ _selectFirstFlow(dispatch = false) {
467
+ if (this.selectedFlowsId.length === 0) {
468
+ let candidate = null;
469
+ if (this.definedFlows.length > 0 && this.definedFlows[0]._id != null) {
470
+ candidate = this.definedFlows[0];
471
+ }
472
+ else if (this.definedPlans.length > 0) {
473
+ const plan = this.definedPlans.find((plan) => plan.flows != null && plan.flows.length > 0 && plan.flows[0]._id != null);
474
+ if (plan) {
475
+ candidate = plan.flows[0];
476
+ }
477
+ }
478
+ if (candidate != null) {
479
+ if (dispatch) {
480
+ this._updateSelectedFlows([candidate._id]);
481
+ }
482
+ else {
483
+ this.selectedFlowsId = [candidate._id];
484
+ }
485
+ }
486
+ }
487
+ }
488
+ _getFlowElement(flowId) {
489
+ return this.shadowRoot.querySelector(`[id="${flowId}"]`);
490
+ }
491
+ _onDragEndPolicy() {
492
+ this.shadowRoot.querySelectorAll('gv-flow').forEach((e) => e.onDragEnd());
493
+ }
494
+ async _onDropPolicy({ detail }) {
495
+ try {
496
+ await this._askToValidateForms();
497
+ const policy = detail.policy;
498
+ const targetFlow = this._findFlowById(detail.flowId);
499
+ let name = policy.name;
500
+ let description = '';
501
+ let condition = '';
502
+ let configuration = {};
503
+ let _id;
504
+ let _new = false;
505
+ if (detail.flowStep) {
506
+ _id = detail.flowStep._id;
507
+ name = detail.flowStep.name;
508
+ description = detail.flowStep.description || '';
509
+ condition = detail.flowStep.condition || '';
510
+ configuration = detail.flowStep.configuration;
511
+ }
512
+ else {
513
+ _id = this._generateFlowStepId(targetFlow._id, detail.flowKey, detail.position);
514
+ _new = true;
515
+ }
516
+ const flowStep = { _id, _new, name, policy: policy.id, description, condition, enabled: true, configuration };
517
+ const sourceFlow = detail.sourceFlowId != null ? this._findFlowById(detail.sourceFlowId) : targetFlow;
518
+ if (detail.sourcePosition != null) {
519
+ if (detail.sourceFlowKey && detail.sourceFlowKey !== detail.flowKey) {
520
+ sourceFlow[detail.sourceFlowKey].splice(detail.sourcePosition, 1);
521
+ targetFlow[detail.flowKey].splice(detail.position, 0, flowStep);
522
+ if (this._currentFlowStep != null && this._currentFlowStep.step._id === _id) {
523
+ this._currentFlowStep.group = detail.flowKey;
524
+ // Special case for update schema after change request to response or inverse
525
+ const schema = this.buildSchema(this._currentFlowStep.policy);
526
+ await this._setCurrentFlowStep(this._currentFlowStep, schema, true);
527
+ this._getFlowElement(targetFlow._id).requestUpdate();
528
+ }
529
+ }
530
+ else {
531
+ if (detail.position > detail.sourcePosition) {
532
+ targetFlow[detail.flowKey].splice(detail.position, 0, flowStep);
533
+ sourceFlow[detail.flowKey].splice(detail.sourcePosition, 1);
534
+ }
535
+ else {
536
+ sourceFlow[detail.flowKey].splice(detail.sourcePosition, 1);
537
+ targetFlow[detail.flowKey].splice(detail.position, 0, flowStep);
538
+ }
539
+ }
540
+ // Force Refresh source flow element when move to other flow
541
+ if (targetFlow._id !== sourceFlow._id) {
542
+ this._getFlowElement(targetFlow._id).requestUpdate();
543
+ }
544
+ }
545
+ else {
546
+ targetFlow[detail.flowKey].splice(detail.position, 0, flowStep);
547
+ const currentFlowForm = this._getFlowStepForm();
548
+ if (currentFlowForm == null || currentFlowForm.dirty !== true) {
549
+ let step = targetFlow[detail.flowKey][detail.position];
550
+ if (step == null) {
551
+ // When confirm lose change after drop policy
552
+ step = targetFlow[detail.flowKey][detail.position - 1];
553
+ }
554
+ if (detail.cancelEdit !== true) {
555
+ setTimeout(async () => {
556
+ await this._editFlowStep({ step, policy, flow: targetFlow, group: detail.flowKey });
557
+ this.updateComplete.then(() => {
558
+ const flowElement = this._getFlowElement(targetFlow._id);
559
+ flowElement.selectedStepId = step._id;
560
+ flowElement.requestUpdate();
561
+ });
562
+ });
563
+ }
564
+ }
565
+ }
566
+ targetFlow._dirty = true;
567
+ sourceFlow._dirty = true;
568
+ this.isDirty = true;
569
+ this.shadowRoot.querySelectorAll('gv-flow').forEach((gvFlow) => gvFlow.removeCandidate());
570
+ setTimeout(() => {
571
+ this._dragPolicy = null;
572
+ this._dropPolicy = null;
573
+ }, 0);
574
+ }
575
+ catch (e) {
576
+ this._currentAskConfirmation = null;
577
+ }
578
+ }
579
+ _onDeletePolicy({ detail }) {
580
+ const targetFlow = this._findFlowById(detail.flowId);
581
+ targetFlow[detail.flowKey].splice(detail.position, 1);
582
+ targetFlow._dirty = true;
583
+ this.isDirty = true;
584
+ if (detail.target.editing) {
585
+ this._closeFlowStepForm(true);
586
+ }
587
+ this._getFlowElement(detail.flowId).requestUpdate();
588
+ }
589
+ _onDesign() {
590
+ this._changeTab('design');
591
+ this._splitMainViews();
592
+ }
593
+ buildSchema({ schema }) {
594
+ const commonDescription = {
595
+ title: 'Description',
596
+ description: 'Description of flow step',
597
+ type: 'string',
598
+ };
599
+ const commonCondition = {
600
+ title: 'Condition',
601
+ description: 'Condition the execution of the flow step (support EL)',
602
+ type: 'string',
603
+ 'x-schema-form': {
604
+ 'expression-language': true,
605
+ },
606
+ };
607
+ if (schema) {
608
+ const jsonSchema = typeof schema === 'string' ? JSON.parse(schema) : schema;
609
+ const properties = { commonDescription, ...(this.hasConditionalSteps ? { commonCondition } : {}), ...jsonSchema.properties };
610
+ return { ...jsonSchema, properties };
611
+ }
612
+ return { properties: { commonDescription, ...(this.hasConditionalSteps ? { commonCondition } : {}) } };
613
+ }
614
+ async _editFlowStep({ step, flow, policy, group }) {
615
+ if (step) {
616
+ this._currentPolicyId = policy.id;
617
+ const currentFlowStep = { flow, step, policy, group };
618
+ const schema = this.buildSchema(policy);
619
+ try {
620
+ await this._setCurrentFlowStep(currentFlowStep, schema);
621
+ this._updateSelectedFlows([flow._id]);
622
+ this._splitMainViews();
623
+ if (localStorage.getItem('gv-policy-studio:keep-documentation-close') == null) {
624
+ this._onOpenDocumentation();
625
+ }
626
+ }
627
+ catch (e) {
628
+ this._currentAskConfirmation = null;
629
+ }
630
+ }
631
+ else {
632
+ await this._closeFlowStepForm();
633
+ this._maximizeTopView();
634
+ }
635
+ }
636
+ async _onEditFlowStep({ detail: { step, flow, policy, group } }) {
637
+ return this._editFlowStep({ step, flow, policy, group });
638
+ }
639
+ _getResizableViews() {
640
+ return this.shadowRoot.querySelector('gv-resizable-views');
641
+ }
642
+ _maximizeTopView() {
643
+ if (this.selectedFlowsId.length <= 1) {
644
+ this._getResizableViews().maximizeTop();
645
+ }
646
+ }
647
+ _maximizeBottomView() {
648
+ this._getResizableViews().maximizeBottom();
649
+ }
650
+ _splitMainViews() {
651
+ this._getResizableViews().split();
652
+ }
653
+ _onChangeFlowStepState({ detail }) {
654
+ const targetFlow = this._findFlowById(detail.flowId);
655
+ const step = targetFlow[detail.flowKey][detail.position];
656
+ step.enabled = detail.enabled;
657
+ targetFlow._dirty = true;
658
+ this.isDirty = true;
659
+ }
660
+ async _onCloseFlowStepForm() {
661
+ try {
662
+ await this._closeFlowStepForm();
663
+ }
664
+ catch (err) {
665
+ this._currentAskConfirmation = null;
666
+ }
667
+ }
668
+ async _closeFlowStepForm(force = false) {
669
+ await this._setCurrentFlowStep(null, null, force);
670
+ }
671
+ async _askToValidateForms() {
672
+ if (this._currentAskConfirmation == null) {
673
+ this._currentAskConfirmation = true;
674
+ return Promise.all(this._submitOrConfirmForms()).then((forms) => {
675
+ if (forms.filter((r) => r != null).length > 0) {
676
+ this._definition = this._buildDefinitionToSave();
677
+ this.getChildren().forEach((e) => e.requestUpdate());
678
+ // Refresh if lose changes lost current step selection
679
+ return this._checkCurrentFlowStep().then(() => {
680
+ this.getChildren().forEach((e) => e.requestUpdate());
681
+ return this.updateComplete.then(() => {
682
+ this._currentAskConfirmation = null;
683
+ return forms;
684
+ });
685
+ });
686
+ }
687
+ else {
688
+ this._currentAskConfirmation = null;
689
+ return forms;
690
+ }
691
+ });
692
+ }
693
+ throw new Error('ask already waiting');
694
+ }
695
+ async _setCurrentFlowStep(currentFlowStep, flowStepSchema, force = false) {
696
+ if (!force) {
697
+ await this._askToValidateForms();
698
+ }
699
+ const schema = deepClone(flowStepSchema);
700
+ if (currentFlowStep != null) {
701
+ const configuration = typeof currentFlowStep.step.configuration === 'string'
702
+ ? JSON.parse(currentFlowStep.step.configuration)
703
+ : currentFlowStep.step.configuration;
704
+ const step = { ...currentFlowStep.step, configuration };
705
+ const _initialValues = { ...step.configuration, commonDescription: step.description, commonCondition: step.condition };
706
+ this._currentFlowStep = { ...currentFlowStep, step, _initialValues };
707
+ if (flowStepSchema && flowStepSchema.properties.scope) {
708
+ const _enum = schema.properties.scope.enum;
709
+ if (_enum.find((scope) => ['REQUEST', 'REQUEST_CONTENT', 'RESPONSE', 'RESPONSE_CONTENT'].includes(scope)) != null) {
710
+ const filtered = this._currentFlowStep.group === 'pre' ? ['REQUEST', 'REQUEST_CONTENT'] : ['RESPONSE', 'RESPONSE_CONTENT'];
711
+ schema.properties.scope.enum = _enum.filter((scope) => filtered.includes(scope));
712
+ const scope = this._currentFlowStep.step.configuration.scope;
713
+ if (scope == null || !schema.properties.scope.enum.includes(scope)) {
714
+ schema.properties.scope.default = schema.properties.scope.enum[0];
715
+ this._currentFlowStep.step.configuration.scope = schema.properties.scope.enum[0];
716
+ this._currentFlowStep._initialValues.scope = schema.properties.scope.enum[0];
717
+ if (this._currentFlowStep._values) {
718
+ this._currentFlowStep._values.scope = schema.properties.scope.enum[0];
719
+ }
720
+ }
721
+ }
722
+ }
723
+ }
724
+ else {
725
+ this._currentFlowStep = null;
726
+ }
727
+ this._flowStepSchema = schema;
728
+ }
729
+ _refresh(closeStepForm = true) {
730
+ if (closeStepForm) {
731
+ this._closeFlowStepForm(true);
732
+ }
733
+ this._definition = deepClone(this._definition);
734
+ }
735
+ async _onSelectFlows({ detail }) {
736
+ try {
737
+ await this._closeFlowStepForm();
738
+ this._onCloseDocumentation();
739
+ this._updateSelectedFlows(detail.flows);
740
+ this._onDesign();
741
+ }
742
+ catch (e) {
743
+ this._currentAskConfirmation = null;
744
+ }
745
+ }
746
+ async _onOpenDocumentationFromMenu({ detail: { policy } }) {
747
+ try {
748
+ if (this.documentation == null || this.documentation.id !== policy.id) {
749
+ await this._closeFlowStepForm();
750
+ this._currentPolicyId = policy.id;
751
+ if (this.getSelectedFlow()) {
752
+ this._splitMainViews();
753
+ }
754
+ else {
755
+ this._maximizeBottomView();
756
+ }
757
+ dispatchCustomEvent(this, 'fetch-documentation', { policy });
758
+ }
759
+ }
760
+ catch (e) { }
761
+ }
762
+ _fetchDocumentation(policy) {
763
+ if (this.documentation == null || this.documentation.id !== policy.id) {
764
+ dispatchCustomEvent(this, 'fetch-documentation', { policy });
765
+ }
766
+ }
767
+ _onOpenDocumentation() {
768
+ if (this._currentFlowStep && this._currentFlowStep.policy) {
769
+ this._fetchDocumentation(this._currentFlowStep.policy);
770
+ }
771
+ }
772
+ _onOpenDocumentationFromForm() {
773
+ localStorage.removeItem('gv-policy-studio:keep-documentation-close');
774
+ this._onOpenDocumentation();
775
+ }
776
+ _findFlowCollection(flowId) {
777
+ const plan = this.definedPlans.find((plan) => plan.flows.find((flow) => flow._id === flowId) != null);
778
+ return { plan, flows: plan != null ? plan.flows : this.definedFlows };
779
+ }
780
+ _findFlowById(flowId) {
781
+ let flow = this.definedFlows.find((flow) => flow._id === flowId);
782
+ if (flow == null) {
783
+ const plansFlows = this.definedPlans.map((plan) => plan.flows).reduce((acc, val) => acc.concat(val), []);
784
+ flow = plansFlows.find((flow) => flow._id === flowId);
785
+ }
786
+ return flow;
787
+ }
788
+ getSelectedFlow(index = 0) {
789
+ const selectedFlowId = this.selectedFlowsId[index];
790
+ return this._findFlowById(selectedFlowId);
791
+ }
792
+ _onTargetPolicy({ detail }) {
793
+ if (this._currentAskConfirmation == null) {
794
+ this._dragPolicy = detail;
795
+ }
796
+ }
797
+ _onChangeFlowStep({ detail }) {
798
+ this._currentFlowStep._values = detail.values;
799
+ }
800
+ _writeFlowStep(values) {
801
+ const { commonDescription, commonCondition, ...configuration } = values;
802
+ if (this._currentFlowStep.step._new ||
803
+ this._currentFlowStep.step.description !== commonDescription ||
804
+ this._currentFlowStep.step.condition !== commonCondition ||
805
+ !deepEqual(this._currentFlowStep.step.configuration, configuration)) {
806
+ const flow = this._findFlowById(this._currentFlowStep.flow._id);
807
+ const position = flow[this._currentFlowStep.group].findIndex((step) => step._id === this._currentFlowStep.step._id);
808
+ flow[this._currentFlowStep.group][position].description = commonDescription;
809
+ flow[this._currentFlowStep.group][position].condition = commonCondition;
810
+ flow[this._currentFlowStep.group][position].configuration = deepClone(configuration);
811
+ delete flow[this._currentFlowStep.group][position]._new;
812
+ flow[this._currentFlowStep.group][position]._dirty = true;
813
+ flow._dirty = true;
814
+ this.isDirty = true;
815
+ this._currentFlowStep.flow = flow;
816
+ this._currentFlowStep.step = flow[this._currentFlowStep.group][position];
817
+ }
818
+ }
819
+ async _onSubmitFlowStep({ detail }) {
820
+ this._writeFlowStep(detail.values);
821
+ await this.requestUpdate('_definition');
822
+ this.getChildren().forEach((c) => c.requestUpdate());
823
+ }
824
+ _onCancelFlow() {
825
+ this._onDesign();
826
+ }
827
+ _onSubmitFlow({ detail: { values } }) {
828
+ const selectedFlow = this.getSelectedFlow();
829
+ const _values = Object.assign({}, this._createFlowFromSchema(), values);
830
+ const selectedFlowUpdated = Object.assign({}, selectedFlow, _values);
831
+ if (!deepEqual(selectedFlow, selectedFlowUpdated)) {
832
+ Object.assign(selectedFlow, selectedFlowUpdated, { _dirty: true });
833
+ this.isDirty = true;
834
+ this._refresh();
835
+ }
836
+ }
837
+ _onCancelFlowMode() {
838
+ this._onDesign();
839
+ }
840
+ _onSubmitFlowMode({ detail: { values } }) {
841
+ this._definition['flow-mode'] = values['flow-mode'] || 'DEFAULT';
842
+ this.isDirty = true;
843
+ this._refresh();
844
+ }
845
+ _onChangeTab({ detail }) {
846
+ this._changeTab(detail.value);
847
+ }
848
+ async _changeTabValidator({ from, to }) {
849
+ if (from === 'properties') {
850
+ const component = this.shadowRoot.querySelector('gv-properties');
851
+ if (component.dirty) {
852
+ return component.confirm();
853
+ }
854
+ }
855
+ else if (from === 'resources') {
856
+ const component = this.shadowRoot.querySelector('gv-resources');
857
+ if (component.dirty) {
858
+ return component.confirm();
859
+ }
860
+ }
861
+ else {
862
+ try {
863
+ return await this._askToValidateForms();
864
+ }
865
+ catch (e) {
866
+ this._currentAskConfirmation = null;
867
+ throw e;
868
+ }
869
+ }
870
+ return Promise.resolve();
871
+ }
872
+ _changeTab(tabId) {
873
+ if (this._currentAskConfirmation == null) {
874
+ this.tabId = tabId;
875
+ dispatchCustomEvent(this, 'change-tab', this.tabId);
876
+ }
877
+ }
878
+ _onDragStartFlowStep(flow, { detail }) {
879
+ if (this._currentAskConfirmation == null) {
880
+ this._dropPolicy = detail;
881
+ this._dragPolicy = detail;
882
+ }
883
+ }
884
+ _renderFlowEmptyState(readonlyMode) {
885
+ return html `<div slot="content" class="empty">
886
+ <div>
887
+ Select a flow
888
+ ${readonlyMode !== true
889
+ ? html `or <gv-button @gv-button:click="${this._onAddFlow}" outlined icon="code:plus" large>design new one</gv-button>`
890
+ : ''}
891
+ </div>
892
+ </div>`;
893
+ }
894
+ _renderFlow(index = 0, hasEmptyState = true, readonlyMode) {
895
+ const flow = this.getSelectedFlow(index);
896
+ if (flow) {
897
+ const { plan } = this._findFlowCollection(flow._id);
898
+ const selectedStepId = this._currentFlowStep ? this._currentFlowStep.step._id : null;
899
+ return html ` <gv-flow
900
+ style="height: 100%"
901
+ .id="${flow._id}"
902
+ .flow="${flow}"
903
+ .plan="${plan}"
904
+ .policies="${this.policies}"
905
+ slot="content"
906
+ ?disabled="${this._currentAskConfirmation}"
907
+ .dragPolicy="${this._dragPolicy}"
908
+ .dropPolicy="${this._dropPolicy}"
909
+ .selectedStepId="${selectedStepId}"
910
+ ?readonly="${readonlyMode}"
911
+ ?has-policy-filter="${this._policyFilterOptions != null}"
912
+ flows-title="${this.flowsTitle}"
913
+ @gv-flow:drag-start="${this._onDragStartFlowStep.bind(this, flow)}"
914
+ @gv-flow:edit="${this._onEditFlowStep}"
915
+ @gv-flow:change-state="${this._onChangeFlowStepState}"
916
+ @gv-flow:drop="${this._onDropPolicy}"
917
+ @gv-flow:delete="${this._onDeletePolicy}"
918
+ ></gv-flow>`;
919
+ }
920
+ else if (hasEmptyState) {
921
+ return this._renderFlowEmptyState(readonlyMode);
922
+ }
923
+ return html ``;
924
+ }
925
+ _onFetchResources(event) {
926
+ const { currentTarget, regexTypes } = event.detail;
927
+ const options = this.definedResources
928
+ .filter((resource) => regexTypes == null || new RegExp(regexTypes).test(resource.type))
929
+ .map((resource, index) => {
930
+ const resourceType = this.resourceTypes.find((type) => type.id === resource.type);
931
+ const row = document.createElement('gv-row');
932
+ const picture = resourceType.icon ? resourceType.icon : null;
933
+ row.item = { picture, name: resource.name };
934
+ return {
935
+ element: row,
936
+ value: resource.name,
937
+ id: resource.type,
938
+ };
939
+ });
940
+ currentTarget.options = options;
941
+ }
942
+ _renderPolicy(readonlyMode) {
943
+ if (this._flowStepSchema && this.documentation) {
944
+ return html `<gv-resizable-views direction="horizontal" no-overflow>
945
+ <div slot="top">${this._renderFlowStepForm(readonlyMode)}</div>
946
+ <div slot="bottom">
947
+ <gv-documentation
948
+ .text="${this.documentation.content}"
949
+ .image="${this.documentation.image}"
950
+ ?disabled="${this._currentAskConfirmation}"
951
+ @gv-documentation:close="${this._onCloseDocumentation}"
952
+ ></gv-documentation>
953
+ </div>
954
+ </gv-resizable-views>`;
955
+ }
956
+ else if (this.documentation) {
957
+ return html `<gv-documentation
958
+ .text="${this.documentation.content}"
959
+ .image="${this.documentation.image}"
960
+ ?disabled="${this._currentAskConfirmation}"
961
+ @gv-documentation:close="${this._onCloseDocumentation}"
962
+ ></gv-documentation>`;
963
+ }
964
+ else if (this._flowStepSchema) {
965
+ return this._renderFlowStepForm(readonlyMode);
966
+ }
967
+ return html ``;
968
+ }
969
+ _getFlowStepForm() {
970
+ return this.shadowRoot.querySelector(`#${FLOW_STEP_FORM_ID}`);
971
+ }
972
+ _onResetFlowStep() {
973
+ if (this._currentFlowStep) {
974
+ delete this._currentFlowStep._values;
975
+ this._getFlowStepForm().reset();
976
+ }
977
+ }
978
+ _generateFlowsId(list, force = false) {
979
+ return this._generateId('f', list, force, true);
980
+ }
981
+ _generatePlanFlowsId(plan, force = false) {
982
+ return this._generateId(plan.id, plan.flows, force, true);
983
+ }
984
+ _generateFlowStepId(flowId, flowKey, position) {
985
+ return `${flowId}_${flowKey}_${position}`;
986
+ }
987
+ _generateId(prefix, list, force = false, isFlow = false) {
988
+ if (list) {
989
+ return list.map((e, index) => {
990
+ const _id = `${prefix}_${index}`;
991
+ if (isFlow) {
992
+ if (e.pre) {
993
+ e.pre.forEach((step, stepIndex) => (step._id = this._generateFlowStepId(_id, 'pre', stepIndex)));
994
+ }
995
+ if (e.post) {
996
+ e.post.forEach((step, stepIndex) => (step._id = this._generateFlowStepId(_id, 'post', stepIndex)));
997
+ }
998
+ }
999
+ if (force || e._id == null) {
1000
+ return { ...e, _id };
1001
+ }
1002
+ return e;
1003
+ });
1004
+ }
1005
+ return list;
1006
+ }
1007
+ getChildren() {
1008
+ return [
1009
+ ...Array.from(this.shadowRoot.querySelectorAll('gv-flow')),
1010
+ ...Array.from(this.shadowRoot.querySelectorAll('gv-resizable-views')),
1011
+ ];
1012
+ }
1013
+ async getUpdateComplete() {
1014
+ await super.getUpdateComplete();
1015
+ await Promise.all(this.getChildren().map((e) => e.updateComplete));
1016
+ }
1017
+ shouldUpdate(changedProperties) {
1018
+ // Just refresh gv-flow components
1019
+ if (changedProperties.has('_dragPolicy')) {
1020
+ this.shadowRoot.querySelectorAll('gv-flow').forEach((flow) => (flow.dragPolicy = this._dragPolicy));
1021
+ return false;
1022
+ }
1023
+ if (changedProperties.has('_dropPolicy')) {
1024
+ this.shadowRoot.querySelectorAll('gv-flow').forEach((flow) => (flow.dropPolicy = this._dropPolicy));
1025
+ return false;
1026
+ }
1027
+ return super.shouldUpdate(changedProperties);
1028
+ }
1029
+ updated(props) {
1030
+ if (props.has('documentation') && this.documentation != null && this.selectedFlowsId.length > 1) {
1031
+ this._updateSelectedFlows([this.selectedFlowsId[0]]);
1032
+ }
1033
+ }
1034
+ _renderFlowStepForm(readonlyMode) {
1035
+ const values = this._currentFlowStep._values || this._currentFlowStep._initialValues;
1036
+ const groups = [{ items: ['commonDescription', 'commonCondition'] }, { name: i18n('gv-policy-studio.policy-settings'), default: true }];
1037
+ return html `${cache(this._flowStepSchema && this._currentFlowStep
1038
+ ? html `<div class="flow-step__container">
1039
+ <div class="flow-step__form">
1040
+ <gv-schema-form
1041
+ .id="${FLOW_STEP_FORM_ID}"
1042
+ .schema="${this._flowStepSchema}"
1043
+ .icon="design:edit"
1044
+ has-header
1045
+ validate-on-render
1046
+ .values="${values}"
1047
+ .dirty="${this._currentFlowStep._values != null}"
1048
+ ?readonly="${readonlyMode}"
1049
+ scrollable
1050
+ .groups="${groups}"
1051
+ @gv-schema-form:change="${this._onChangeFlowStep}"
1052
+ @gv-schema-form:reset="${this._onResetFlowStep}"
1053
+ @gv-schema-form:fetch-resources="${this._onFetchResources}"
1054
+ @gv-schema-form:submit="${this._onSubmitFlowStep}"
1055
+ >
1056
+ <div slot="title" class="flow-step__form-title">${this._currentFlowStep.step.name}</div>
1057
+ <gv-button
1058
+ slot="header-left"
1059
+ icon="general:close"
1060
+ outlined
1061
+ small
1062
+ @gv-button:click="${this._onCloseFlowStepForm}"
1063
+ title="Close"
1064
+ ></gv-button>
1065
+ <gv-button
1066
+ slot="header-left"
1067
+ icon="home:book"
1068
+ ?disabled="${this.documentation != null}"
1069
+ outlined
1070
+ small
1071
+ @gv-button:click="${this._onOpenDocumentationFromForm}"
1072
+ title="Open documentation"
1073
+ ></gv-button>
1074
+ </gv-schema-form>
1075
+ </div>
1076
+ </div>`
1077
+ : '')}`;
1078
+ }
1079
+ _onCloseDocumentation() {
1080
+ this.documentation = null;
1081
+ if (this._currentFlowStep == null) {
1082
+ this._maximizeTopView();
1083
+ }
1084
+ else {
1085
+ localStorage.setItem('gv-policy-studio:keep-documentation-close', true);
1086
+ }
1087
+ }
1088
+ _onDeleteFlow({ detail }) {
1089
+ const flowId = detail.content._id;
1090
+ const { flows } = this._findFlowCollection(flowId);
1091
+ const flow = flows.find((flow) => flow._id === flowId);
1092
+ this._deleteFlow(flows, flow);
1093
+ }
1094
+ get definedFlows() {
1095
+ return this._definition && this._definition.flows ? this._definition.flows : [];
1096
+ }
1097
+ get definedPlans() {
1098
+ return this._definition && this._definition.plans ? this._definition.plans : [];
1099
+ }
1100
+ get definedResources() {
1101
+ return this._definition && this._definition.resources ? this._definition.resources : [];
1102
+ }
1103
+ get definedProperties() {
1104
+ return this._definition && this._definition.properties ? this._definition.properties : [];
1105
+ }
1106
+ async _onDuplicateFlow({ detail }) {
1107
+ try {
1108
+ await this._askToValidateForms();
1109
+ const flowId = detail.content._id;
1110
+ const { plan, flows } = this._findFlowCollection(flowId);
1111
+ this._addFlow(flows, this._findFlowById(flowId));
1112
+ if (plan != null) {
1113
+ let planIndex = null;
1114
+ this.definedPlans.find((p, i) => {
1115
+ if (p.id === plan.id) {
1116
+ planIndex = i;
1117
+ return true;
1118
+ }
1119
+ return false;
1120
+ });
1121
+ plan.flows = flows;
1122
+ this.definedPlans[planIndex].flows = this._generatePlanFlowsId(plan, true);
1123
+ this._updateSelectedFlows([this.definedPlans[planIndex].flows[flows.length - 1]._id]);
1124
+ }
1125
+ else {
1126
+ this._definition.flows = this._generateFlowsId(this._definition.flows);
1127
+ this._updateSelectedFlows([this._definition.flows[this._definition.flows.length - 1]._id]);
1128
+ }
1129
+ }
1130
+ catch (err) {
1131
+ this._currentAskConfirmation = null;
1132
+ }
1133
+ }
1134
+ _onChangeFlowState({ detail }) {
1135
+ const flow = this._findFlowById(detail.content._id);
1136
+ flow.enabled = detail.enabled;
1137
+ flow._dirty = true;
1138
+ this.isDirty = true;
1139
+ }
1140
+ async _onAddFlowPlan({ detail }) {
1141
+ try {
1142
+ await this._askToValidateForms();
1143
+ this._addFlow(this.definedPlans[detail.planIndex].flows);
1144
+ this.definedPlans[detail.planIndex].flows = this._generatePlanFlowsId(this.definedPlans[detail.planIndex]);
1145
+ this._updateSelectedFlows([this.definedPlans[detail.planIndex].flows[this.definedPlans[detail.planIndex].flows.length - 1]._id]);
1146
+ }
1147
+ catch (err) {
1148
+ this._currentAskConfirmation = null;
1149
+ }
1150
+ }
1151
+ async _onAddFlow() {
1152
+ try {
1153
+ await this._askToValidateForms();
1154
+ this._addFlow(this._definition.flows);
1155
+ this._definition.flows = this._generateFlowsId(this._definition.flows);
1156
+ this._updateSelectedFlows([this._definition.flows[this._definition.flows.length - 1]._id]);
1157
+ }
1158
+ catch (err) {
1159
+ this._currentAskConfirmation = null;
1160
+ }
1161
+ }
1162
+ _addFlow(collection, duplicate = null) {
1163
+ const flow = duplicate == null
1164
+ ? this._createFlowFromSchema()
1165
+ : {
1166
+ ...duplicate,
1167
+ _id: null,
1168
+ // reset the id to avoid issue with AM that persists the ID
1169
+ id: null,
1170
+ _dirty: true,
1171
+ };
1172
+ collection.push(flow);
1173
+ this.isDirty = true;
1174
+ return collection;
1175
+ }
1176
+ _createFlowFromSchema() {
1177
+ const newFlow = {
1178
+ name: '',
1179
+ pre: [],
1180
+ post: [],
1181
+ _dirty: true,
1182
+ };
1183
+ return this._instantiate(this.flowSchema.properties, newFlow);
1184
+ }
1185
+ _instantiate(propertiesDefinition, initiator = {}) {
1186
+ const property = { ...initiator };
1187
+ if (propertiesDefinition) {
1188
+ for (const key of Object.keys(propertiesDefinition)) {
1189
+ const entry = propertiesDefinition[key];
1190
+ if (entry.type === 'object') {
1191
+ property[key] = this._instantiate(entry.properties, (initiator = {}));
1192
+ }
1193
+ if (entry.default !== undefined) {
1194
+ property[key] = entry.default;
1195
+ }
1196
+ else if (entry.type === 'string') {
1197
+ property[key] = '';
1198
+ }
1199
+ }
1200
+ }
1201
+ return property;
1202
+ }
1203
+ _deleteFlow(collection, flow) {
1204
+ const index = collection.indexOf(flow);
1205
+ collection.splice(index, 1);
1206
+ const selectedFlows = this.selectedFlowsId.filter((flowId) => flowId !== flow._id);
1207
+ if (selectedFlows.length === 1) {
1208
+ this._updateSelectedFlows(selectedFlows);
1209
+ }
1210
+ else {
1211
+ this._selectFirstFlow(true);
1212
+ }
1213
+ this._changeTab('design');
1214
+ this._refresh();
1215
+ this.isDirty = true;
1216
+ }
1217
+ _findFlowIndex(list, id) {
1218
+ let index = null;
1219
+ list.find((f, i) => {
1220
+ if (f._id === id) {
1221
+ index = i;
1222
+ return true;
1223
+ }
1224
+ return false;
1225
+ });
1226
+ return index;
1227
+ }
1228
+ async _onReorderFlows({ detail: { plan } }) {
1229
+ try {
1230
+ await this._askToValidateForms();
1231
+ this.isDirty = true;
1232
+ if (plan != null) {
1233
+ const newOrder = this._generatePlanFlowsId(plan, true);
1234
+ if (this.selectedFlowsId) {
1235
+ this._updateSelectedFlows(this.selectedFlowsId.map((flowId) => {
1236
+ const index = this._findFlowIndex(plan.flows, flowId);
1237
+ return index != null ? newOrder[index]._id : flowId;
1238
+ }));
1239
+ }
1240
+ plan.flows = newOrder;
1241
+ }
1242
+ else {
1243
+ const newOrder = this._generateFlowsId(this._definition.flows, true);
1244
+ if (this.selectedFlowsId) {
1245
+ this._updateSelectedFlows(this.selectedFlowsId.map((flowId) => {
1246
+ const index = this._findFlowIndex(this._definition.flows, flowId);
1247
+ return index != null ? newOrder[index]._id : flowId;
1248
+ }));
1249
+ }
1250
+ this._definition.flows = newOrder;
1251
+ }
1252
+ }
1253
+ catch (err) {
1254
+ this._currentAskConfirmation = false;
1255
+ }
1256
+ }
1257
+ _onSearchPolicy({ detail }) {
1258
+ this._searchPolicyQuery = detail;
1259
+ }
1260
+ _onClearPolicy() {
1261
+ this._searchPolicyQuery = null;
1262
+ }
1263
+ _onSearchFlows({ detail }) {
1264
+ this._searchFlowQuery = detail;
1265
+ }
1266
+ _onClearFlows() {
1267
+ this._searchFlowQuery = null;
1268
+ }
1269
+ async _onResetAll() {
1270
+ try {
1271
+ await this._closeFlowStepForm();
1272
+ this.definition = deepClone(this._initialDefinition);
1273
+ }
1274
+ catch (e) {
1275
+ this._currentAskConfirmation = null;
1276
+ }
1277
+ }
1278
+ _filterNotValidStep(step) {
1279
+ return step._new !== true;
1280
+ }
1281
+ _removePrivateProperties(o) {
1282
+ const copy = { ...o };
1283
+ Object.keys(o)
1284
+ .filter((key) => key.startsWith('_'))
1285
+ .forEach((key) => {
1286
+ delete copy[key];
1287
+ });
1288
+ return copy;
1289
+ }
1290
+ _submitOrConfirmForms() {
1291
+ return [...this.shadowRoot.querySelectorAll('gv-schema-form')]
1292
+ .filter((form) => {
1293
+ const isValid = form.isValid();
1294
+ if (isValid) {
1295
+ form.submit();
1296
+ }
1297
+ else {
1298
+ form.dirty = true;
1299
+ }
1300
+ return !isValid;
1301
+ })
1302
+ .map((form) => form.confirm());
1303
+ }
1304
+ getPropertiesElement() {
1305
+ return this.shadowRoot.querySelector('gv-properties');
1306
+ }
1307
+ async _checkCurrentFlowStep() {
1308
+ if (this._currentFlowStep && this.selectedFlowsId) {
1309
+ const closePromises = this.selectedFlowsId
1310
+ .map((flowId) => {
1311
+ const flow = this._findFlowById(flowId);
1312
+ const currentStep = [...flow.pre, ...flow.post].find((step) => step._id === this._currentFlowStep.step._id);
1313
+ if (currentStep == null) {
1314
+ return this._closeFlowStepForm(true);
1315
+ }
1316
+ return null;
1317
+ })
1318
+ .filter((p) => p !== null);
1319
+ return Promise.all(closePromises);
1320
+ }
1321
+ return Promise.resolve();
1322
+ }
1323
+ saved() {
1324
+ if (this.isDirty) {
1325
+ this._initialDefinition = deepClone(this._definitionSaved);
1326
+ this._definition = deepClone(this._definitionSaved);
1327
+ this._definitionSaved = null;
1328
+ this.isDirty = false;
1329
+ this._checkCurrentFlowStep();
1330
+ this.definedPlans.forEach((plan) => {
1331
+ plan.flows.forEach((flow) => (flow._dirty = false));
1332
+ });
1333
+ this.definedFlows.forEach((flow) => (flow._dirty = false));
1334
+ this.getChildren().forEach((e) => e.requestUpdate());
1335
+ }
1336
+ }
1337
+ _buildDefinitionToSave() {
1338
+ // Copy definition and remove invalid step
1339
+ // Keep private properties like _id and others stuff useful for render
1340
+ const flows = this._definition.flows.map((flow) => {
1341
+ flow.pre = flow.pre.filter(this._filterNotValidStep);
1342
+ flow.post = flow.post.filter(this._filterNotValidStep);
1343
+ return flow;
1344
+ });
1345
+ let definition = { ...this._definition, flows };
1346
+ if (this._definition.plans != null) {
1347
+ const plans = this._definition.plans.map((plan) => {
1348
+ const flows = plan.flows.map((flow) => {
1349
+ flow.pre = flow.pre.filter(this._filterNotValidStep);
1350
+ flow.post = flow.post.filter(this._filterNotValidStep);
1351
+ return flow;
1352
+ });
1353
+ return { ...plan, flows };
1354
+ });
1355
+ definition = { ...definition, plans };
1356
+ }
1357
+ return definition;
1358
+ }
1359
+ _buildDefinitionToSend(definitionToSave) {
1360
+ // Copy definition and remove all private properties
1361
+ const flows = definitionToSave.flows.map((f) => {
1362
+ const flow = this._removePrivateProperties(f);
1363
+ flow.pre = flow.pre.map(this._removePrivateProperties);
1364
+ flow.post = flow.post.map(this._removePrivateProperties);
1365
+ return flow;
1366
+ });
1367
+ let definition = { ...this._definition, flows };
1368
+ if (this._definition.plans != null) {
1369
+ const plans = definitionToSave.plans.map((plan) => {
1370
+ const flows = plan.flows.map((f) => {
1371
+ const flow = this._removePrivateProperties(f);
1372
+ flow.pre = flow.pre.map(this._removePrivateProperties);
1373
+ flow.post = flow.post.map(this._removePrivateProperties);
1374
+ return flow;
1375
+ });
1376
+ return { ...plan, flows };
1377
+ });
1378
+ definition = { ...definition, plans };
1379
+ }
1380
+ if (this._definition.properties != null) {
1381
+ const properties = this._definition.properties.map(this._removePrivateProperties);
1382
+ definition = { ...definition, properties };
1383
+ }
1384
+ if (this._definition.resources != null) {
1385
+ const resources = this._definition.resources.map(this._removePrivateProperties);
1386
+ definition = { ...definition, resources };
1387
+ }
1388
+ return definition;
1389
+ }
1390
+ _onSaveAll() {
1391
+ if (this.hasProperties) {
1392
+ this.getPropertiesElement().submit();
1393
+ }
1394
+ Promise.all(this._submitOrConfirmForms())
1395
+ .then(() => {
1396
+ this._definitionSaved = this._buildDefinitionToSave();
1397
+ const definition = this._buildDefinitionToSend(this._definitionSaved);
1398
+ dispatchCustomEvent(this, 'save', { definition, services: this.services });
1399
+ })
1400
+ .catch((err) => {
1401
+ console.error(`[policy-studio] Error on save`, err);
1402
+ });
1403
+ }
1404
+ _onDebug(requestEvent) {
1405
+ if (this.hasProperties) {
1406
+ this.getPropertiesElement().submit();
1407
+ }
1408
+ Promise.all(this._submitOrConfirmForms())
1409
+ .then(() => {
1410
+ const definition = this._buildDefinitionToSend(this._buildDefinitionToSave());
1411
+ dispatchCustomEvent(this, 'debug', { definition, services: this.services, request: requestEvent.detail.request });
1412
+ })
1413
+ .catch((err) => {
1414
+ console.error(`[policy-studio] Error on debug`, err);
1415
+ });
1416
+ }
1417
+ get filteredFlows() {
1418
+ if (this._flowFilter.length === 0 || this._flowFilter.includes('api')) {
1419
+ return this.definedFlows;
1420
+ }
1421
+ return null;
1422
+ }
1423
+ get filteredPlans() {
1424
+ if (this._flowFilter.length === 0 || this._flowFilter.includes('plan')) {
1425
+ return this.definedPlans;
1426
+ }
1427
+ return null;
1428
+ }
1429
+ _onFilterFlows({ detail }) {
1430
+ if (this._flowFilter.includes(detail.id)) {
1431
+ this._flowFilter = [];
1432
+ }
1433
+ else {
1434
+ this._flowFilter = [detail.id];
1435
+ }
1436
+ }
1437
+ _getFilteredPolicies() {
1438
+ if (this._policyFilter.length > 0) {
1439
+ return this.policies.filter((policy) => {
1440
+ return ((policy.onRequest && this._policyFilter.includes('onRequest')) || (policy.onResponse && this._policyFilter.includes('onResponse')));
1441
+ });
1442
+ }
1443
+ return this.policies;
1444
+ }
1445
+ _onFilterPolicies({ detail }) {
1446
+ if (this._policyFilter.includes(detail.id)) {
1447
+ this._policyFilter = [];
1448
+ }
1449
+ else {
1450
+ this._policyFilter = [detail.id];
1451
+ }
1452
+ }
1453
+ _renderDesign(readonlyMode) {
1454
+ return html ` <div id="design" slot="content" class="design">
1455
+ <gv-resizable-views no-overflow>
1456
+ <div slot="top">${this._renderFlow(0, true, readonlyMode)}</div>
1457
+
1458
+ <div slot="bottom">
1459
+ ${this._renderFlow(1, false, readonlyMode)} ${this._renderPolicy(readonlyMode)} ${this._renderFlowForm(readonlyMode)}
1460
+ </div>
1461
+ </gv-resizable-views>
1462
+ ${readonlyMode !== true
1463
+ ? html `<gv-policy-studio-menu
1464
+ class="right-menu"
1465
+ ?disabled="${this._currentAskConfirmation}"
1466
+ .policies="${this._getFilteredPolicies()}"
1467
+ .selectedIds="${[this._currentPolicyId]}"
1468
+ .query="${this._searchPolicyQuery}"
1469
+ ?has-policy-filter="${this._policyFilterOptions != null}"
1470
+ ?readonly="${readonlyMode}"
1471
+ @gv-policy-studio-menu:target-policy="${this._onTargetPolicy}"
1472
+ @gv-policy-studio-menu:fetch-documentation="${this._onOpenDocumentationFromMenu}"
1473
+ @gv-policy-studio-menu:dragend-policy="${this._onDragEndPolicy}"
1474
+ >
1475
+ <div slot="header" class="search-policies">
1476
+ ${this._policyFilterOptions != null
1477
+ ? html `<gv-option
1478
+ ?disabled="${this._currentAskConfirmation}"
1479
+ .options="${this._policyFilterOptions}"
1480
+ multiple
1481
+ outlined
1482
+ .value="${this._policyFilter}"
1483
+ small
1484
+ @gv-option:select="${this._onFilterPolicies}"
1485
+ ></gv-option>`
1486
+ : ''}
1487
+ <gv-input
1488
+ id="search-policy"
1489
+ ?disabled="${this._currentAskConfirmation}"
1490
+ placeholder="Filter policies (Shift + Ctrl + Space)"
1491
+ type="search"
1492
+ small
1493
+ @gv-input:input="${this._onSearchPolicy}"
1494
+ @gv-input:clear="${this._onClearPolicy}"
1495
+ ></gv-input>
1496
+ </div>
1497
+ </gv-policy-studio-menu>`
1498
+ : ''}
1499
+ </div>`;
1500
+ }
1501
+ _renderDebug() {
1502
+ const response = this.debugResponse ? this.debugResponse.response : undefined;
1503
+ const isLoading = this.debugResponse ? this.debugResponse.isLoading : undefined;
1504
+ const path = this.debugResponse && this.debugResponse.request ? this.debugResponse.request.path : undefined;
1505
+ const method = this.debugResponse && this.debugResponse.request ? this.debugResponse.request.method : undefined;
1506
+ return html `<gv-http-client
1507
+ id="debug"
1508
+ slot="content"
1509
+ class="debug"
1510
+ @gv-http-client:send="${this._onDebug}"
1511
+ .response="${response}"
1512
+ .path="${path}"
1513
+ .method="${method}"
1514
+ ?loading="${isLoading}"
1515
+ >
1516
+ </gv-http-client>`;
1517
+ }
1518
+ _renderConfigurationForm(readonlyMode) {
1519
+ if (this.configurationSchema) {
1520
+ const values = deepClone(this._definition);
1521
+ return html ` <div id="settings" slot="content" class="api-settings" @dragover="${this._onDesign}">
1522
+ <gv-schema-form
1523
+ .schema="${this.configurationSchema}"
1524
+ id="api-settings-form"
1525
+ .values="${values}"
1526
+ has-header
1527
+ has-footer
1528
+ scrollable
1529
+ ?readonly="${readonlyMode}"
1530
+ @gv-schema-form:cancel="${this._onCancelFlowMode}"
1531
+ @gv-schema-form:submit="${this._onSubmitFlowMode}"
1532
+ >
1533
+ ${!this.configurationInformation
1534
+ ? ''
1535
+ : html `
1536
+ <div class="api-settings-information" slot="title">
1537
+ <gv-icon class="api-settings-information__icon" title="Info" shape="code:info"></gv-icon>
1538
+ <blockquote class="api-settings-information__blockquote">${this.configurationInformation}</blockquote>
1539
+ </div>
1540
+ `}
1541
+ </gv-schema-form>
1542
+ </div>`;
1543
+ }
1544
+ return html ``;
1545
+ }
1546
+ _renderFlowForm(readonlyMode) {
1547
+ if (this.flowSchema && this._flowStepSchema == null && this.documentation == null && this.selectedFlowsId.length === 1) {
1548
+ const flow = this.getSelectedFlow();
1549
+ if (flow) {
1550
+ const values = deepClone(flow);
1551
+ return html `<div slot="content" class="flow-settings">
1552
+ <gv-schema-form
1553
+ .schema="${this.flowSchema}"
1554
+ id="settings-form"
1555
+ .values="${values}"
1556
+ has-header
1557
+ scrollable
1558
+ ?readonly="${readonlyMode}"
1559
+ @gv-schema-form:cancel="${this._onCancelFlow}"
1560
+ @gv-schema-form:submit="${this._onSubmitFlow}"
1561
+ >
1562
+ <div slot="title" class="flow-step__form-title">Flow configuration</div>
1563
+ </gv-schema-form>
1564
+ </div>`;
1565
+ }
1566
+ }
1567
+ }
1568
+ _onResourcesChange({ detail }) {
1569
+ this.definition.resources = detail.resources;
1570
+ this.isDirty = true;
1571
+ }
1572
+ _onPropertiesChange({ detail }) {
1573
+ this.definition.properties = detail.properties;
1574
+ this.isDirty = true;
1575
+ }
1576
+ _onSaveProvider({ detail }) {
1577
+ this.services['dynamic-property'] = detail.provider;
1578
+ this.isDirty = true;
1579
+ }
1580
+ _onSwitchEncryptedProperty({ detail }) {
1581
+ this.isDirty = true;
1582
+ }
1583
+ render() {
1584
+ const readonlyMode = this._getReadonlyModeForDesign();
1585
+ return html `<div class="box">
1586
+ <gv-policy-studio-menu
1587
+ class="left-menu"
1588
+ .api-name="${this._definition.name}"
1589
+ .flows="${this.filteredFlows}"
1590
+ .plans="${this.filteredPlans}"
1591
+ .selectedIds="${this.selectedFlowsId}"
1592
+ ?disabled="${this._currentAskConfirmation}"
1593
+ ?sortable="${this.sortable && this.readonly !== true}"
1594
+ ?readonly="${this.readonly}"
1595
+ ?readonlyPlans="${this.readonlyPlans}"
1596
+ flows-title="${this.flowsTitle}"
1597
+ .query="${this._searchFlowQuery}"
1598
+ ?can-add="${this.canAdd && !this.readonly}"
1599
+ @gv-policy-studio-menu:reorder-flows="${this._onReorderFlows}"
1600
+ @gv-policy-studio-menu:change-flow-state="${this._onChangeFlowState}"
1601
+ @gv-policy-studio-menu:add-flow="${this._onAddFlow}"
1602
+ @gv-policy-studio-menu:add-flow-plan="${this._onAddFlowPlan}"
1603
+ @gv-policy-studio-menu:delete-flow="${this._onDeleteFlow}"
1604
+ @gv-policy-studio-menu:duplicate-flow="${this._onDuplicateFlow}"
1605
+ @gv-policy-studio-menu:select-flows="${this._onSelectFlows}"
1606
+ >
1607
+ <div slot="header" class="header-actions">
1608
+ <div class="title">${this._definition.name}</div>
1609
+ ${this._flowFilterOptions != null
1610
+ ? html `<gv-option
1611
+ ?disabled="${this._currentAskConfirmation}"
1612
+ .options="${this._flowFilterOptions}"
1613
+ multiple
1614
+ outlined
1615
+ .value="${this._flowFilter}"
1616
+ small
1617
+ @gv-option:select="${this._onFilterFlows}"
1618
+ ></gv-option>`
1619
+ : ''}
1620
+ <gv-input
1621
+ ?disabled="${this._currentAskConfirmation}"
1622
+ id="search-flow"
1623
+ placeholder="Filter flows (Ctrl + Space)"
1624
+ type="search"
1625
+ small
1626
+ @gv-input:input="${this._onSearchFlows}"
1627
+ @gv-input:clear="${this._onClearFlows}"
1628
+ ></gv-input>
1629
+ </div>
1630
+
1631
+ ${this.readonly !== true
1632
+ ? html ` <div slot="footer" class="footer-actions">
1633
+ <gv-button
1634
+ class="btn-large"
1635
+ .disabled="${!this.isDirty || this._currentAskConfirmation}"
1636
+ @gv-button:click="${this._onSaveAll}"
1637
+ >Save</gv-button
1638
+ >
1639
+ <gv-button link .disabled="${!this.isDirty || this._currentAskConfirmation}" @gv-button:click="${this._onResetAll}"
1640
+ >Reset</gv-button
1641
+ >
1642
+ </div>`
1643
+ : ''}
1644
+ </gv-policy-studio-menu>
1645
+
1646
+ <gv-tabs
1647
+ .value="${this.tabId}"
1648
+ .options="${this._tabs}"
1649
+ .disabled="${this._currentAskConfirmation}"
1650
+ @gv-tabs:change="${this._onChangeTab}"
1651
+ .validator="${this._changeTabValidator.bind(this)}"
1652
+ >
1653
+ ${this._renderDesign(readonlyMode)} ${this._renderConfigurationForm(readonlyMode)} ${this._renderDebug()}
1654
+ <gv-properties
1655
+ id="properties"
1656
+ slot="content"
1657
+ class="properties"
1658
+ .provider="${this.services['dynamic-property']}"
1659
+ @gv-properties:change="${this._onPropertiesChange}"
1660
+ @gv-properties:save-provider="${this._onSaveProvider}"
1661
+ @gv-properties:switch-encrypted="${this._onSwitchEncryptedProperty}"
1662
+ ?readonly="${readonlyMode}"
1663
+ encryptable="true"
1664
+ .properties="${this.definedProperties}"
1665
+ .providers="${this.propertyProviders}"
1666
+ .dynamicPropertySchema="${this.dynamicPropertySchema}"
1667
+ ></gv-properties>
1668
+ <gv-resources
1669
+ id="resources"
1670
+ slot="content"
1671
+ class="resources"
1672
+ @gv-resources:change="${this._onResourcesChange}"
1673
+ ?readonly="${readonlyMode}"
1674
+ .resources="${this.definedResources}"
1675
+ .types="${this.resourceTypes}"
1676
+ ></gv-resources>
1677
+ </gv-tabs>
1678
+ </div>`;
1679
+ }
1680
+ /**
1681
+ * Determine if the design view should be in readonly mode or not
1682
+ * It is in readonly mode if:
1683
+ * the readonly attribute is set to true
1684
+ * OR
1685
+ * the main selected flow belongs to a plan and the readonly-plans attribute is set to true
1686
+ * OR
1687
+ * the second flow for comparison belongs to a plan and the readonly-plans attribute is set to true
1688
+ * @returns {boolean|*|{type: BooleanConstructor}|{attribute: string, type: BooleanConstructor}|{type: *}|{attribute: string, type: *}}
1689
+ * @private
1690
+ */
1691
+ _getReadonlyModeForDesign() {
1692
+ if (this.readonly) {
1693
+ return true;
1694
+ }
1695
+ const flow = this.getSelectedFlow(0);
1696
+ if (!flow) {
1697
+ return false;
1698
+ }
1699
+ const { plan: flowPlan } = this._findFlowCollection(flow._id);
1700
+ const readonlyMode = flowPlan && this.readonlyPlans;
1701
+ if (readonlyMode) {
1702
+ return true;
1703
+ }
1704
+ const comparedFlow = this.getSelectedFlow(1);
1705
+ if (!comparedFlow) {
1706
+ return false;
1707
+ }
1708
+ const { plan: comparedFlowPlan } = this._findFlowCollection(comparedFlow._id);
1709
+ return comparedFlowPlan && this.readonlyPlans;
1710
+ }
1711
+ }
1712
+ window.customElements.define('gv-policy-studio', GvPolicyStudio);