editor.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <template>
  2. <div class="flow-container">
  3. <svg
  4. xmlns="http://www.w3.org/2000/svg"
  5. xmlns:xhtml="http://www.w3.org/1999/xhtml"
  6. xmlns:xlink="http://www.w3.org/1999/xlink"
  7. ref="svg"
  8. class="flow-view view"
  9. :class="viewClasses"
  10. @dragover.prevent
  11. @drop="managerDrop"
  12. @mousedown="viewPointerDown"
  13. @contextmenu.capture.prevent="$refs.menu.open($event,{ctx:'editor'})"
  14. :width="width"
  15. :height="height">
  16. <svg-defs/>
  17. <flow-pan-zoom
  18. ref="panzoom"
  19. v-model="panzoomCTM"
  20. >
  21. <flow-link
  22. v-for="l of nodeData.links"
  23. :key="'link' + l.to + l.in"
  24. :link="l"
  25. @mousedown.middle="LINK_REMOVE(l)"
  26. />
  27. <flow-trigger-link
  28. v-for="(t,i) in nodeData.triggers"
  29. :key="'trigger'+t.to+i"
  30. label="error/finish"
  31. :trigger="t"
  32. @mousedown.middle="TRIGGER_REMOVE(t)"
  33. />
  34. <flow-node
  35. ref="nodes"
  36. v-for="n of nodeData.nodes"
  37. :node="n"
  38. :match="matchHighlight"
  39. :dragging="dragging"
  40. :key="n.id"
  41. @nodePointerDown.prevent="nodePointerDown($event,n.id)"
  42. @socketPointerDown="socketPointerDown(n.id,...arguments)"
  43. @triggerPointerDown="triggerPointerDown(n.id,...arguments)"
  44. @nodeDoubleClick="$emit('nodeDoubleClick',n.id)"
  45. @nodeRightClick="$refs.menu.open($event,{ctx:'node',node:n})"
  46. @activityPointerDown="$emit('activityPointerDown',n.id)"
  47. />
  48. <!-- mouse links-->
  49. <flow-link
  50. v-if="pointerLink.active"
  51. :link="pointerLink"
  52. />
  53. <flow-trigger-link
  54. :pointer="true"
  55. v-if="pointerTriggerLink.active"
  56. :trigger="pointerTriggerLink"
  57. />
  58. </flow-pan-zoom>
  59. <rect
  60. class="flow-selector"
  61. :class="{'flow-selector--selecting':(selector)?true:false}"
  62. v-bind="selector"/>
  63. </svg>
  64. <div class="flow-container__control">
  65. <button disabled>Deploy</button>
  66. <button @click="stickySockets=!stickySockets"> {{ stickySockets? 'Hide':'Show' }} details </button>
  67. <!--
  68. <button @click="stickyTriggers=!stickyTriggers"> {{ stickyTriggers? 'Hide':'Show' }} triggers </button>
  69. <button @click="nodeActivity=!nodeActivity"> {{ nodeActivity? 'Hide':'Show' }} activity </button>-->
  70. <button @click="$emit('documentSave', nodeData)"> Save </button> <!-- should disable until confirmation -->
  71. <button v-if="!panzoomIdentity" @click="panzoomReset"> Reset view </button>
  72. <button v-if="selectionCount>0" @click="nodeSelectionProcess" class="primary-inverse">Process</button>
  73. </div>
  74. <div class="flow-container__info">
  75. {{ nodeData.nodes.length }} nodes
  76. {{ nodeData.links.length }} links
  77. {{ nodeData.triggers.length }} triggers
  78. {{ selectionCount }} selected
  79. </div>
  80. <hx-context-menu ref="menu">
  81. <template slot-scope="d" >
  82. <div v-if="d.userData && d.userData.ctx === 'node'" class="flow-node__context-menu">
  83. <!-- for the selection -->
  84. <div v-if="nodeSelection[d.userData.node.id]">
  85. <div class="hover item" @click="nodeSelectionProcess">Run ({{ selectionCount }})</div>
  86. <div class="hover item" @click="$emit('nodeViewData')">View ({{ selectionCount }})</div>
  87. <hr>
  88. <div class="hover item" @click="NODE_REMOVE(nodeSelection)">Delete ({{ selectionCount }})</div>
  89. </div>
  90. <!-- for the context -->
  91. <div v-else>
  92. <div class="hover item" @click="nodeProcess(d.userData.node.id)">Run</div>
  93. <hr>
  94. <div class="hover item" @click="nodeRemove(d.userData.node.id)">Delete</div>
  95. </div>
  96. <hr>
  97. <div class="hover item" @click="NODE_TRAIN(d.userData.node.id)">Train(temporary)</div>
  98. <hr>
  99. <div class="hover item" @click="nodeInspect(d.userData.node.id,true)">Inspect</div>
  100. </div>
  101. <div v-if="d.userData && d.userData.ctx === 'editor'" class="flow-node__context-menu">
  102. <div v-if="selectionCount>0">
  103. <div class="hover item" @click="nodeSelectionProcess">Run ({{ selectionCount }})</div>
  104. <div class="hover item" @click="$emit('nodeViewData')">View ({{ selectionCount }})</div>
  105. <hr>
  106. <div class="hover item" @click="NODE_REMOVE(nodeSelection)">Delete ({{ selectionCount }})</div>
  107. <hr>
  108. </div>
  109. <!-- editor settings -->
  110. <div>
  111. <div class="hover item" @click="stickySockets=!stickySockets"> {{ stickySockets? 'Hide':'Show' }} details </div>
  112. <div class="hover item" @click="stickyTriggers=!stickyTriggers"> {{ stickyTriggers? 'Hide':'Show' }} triggers </div>
  113. <div class="hover item" @click="nodeActivity=!nodeActivity"> {{ nodeActivity? 'Hide':'Show' }} activity </div>
  114. </div>
  115. </div>
  116. </template>
  117. </hx-context-menu>
  118. </div>
  119. </template>
  120. <script src="./editor.js">
  121. </script>
  122. <style>
  123. .flow-container {
  124. display:flex;
  125. flex-flow:row;
  126. position:relative;
  127. }
  128. .flow-container__control {
  129. position:absolute;
  130. padding:10px;
  131. top: 0;
  132. left: 20px;
  133. display:flex;
  134. flex-flow:row;
  135. justify-content: center;
  136. align-items: center;
  137. color: #fff;
  138. background: var(--background-transparent);
  139. transition: all var(--transition-speed);
  140. }
  141. .flow-container__control button {
  142. display:flex;
  143. justify-content: center;
  144. margin:0;
  145. padding:14px;
  146. /*color:#333;*/
  147. }
  148. .flow-container__info {
  149. position:absolute;
  150. bottom:10px;
  151. left:10px;
  152. padding:2px;
  153. font-size:9px;
  154. }
  155. .flow-view {
  156. border:none;
  157. position:relative;
  158. fill:transparent;
  159. }
  160. .flow-view.activity {
  161. cursor:crosshair;
  162. }
  163. .flow-selector {
  164. pointer-events:none;
  165. opacity:0;
  166. }
  167. .flow-selector.flow-selector--selecting {
  168. opacity:1;
  169. }
  170. .flow-node__context-menu {
  171. box-shadow: 0 1px 4px rgba(0,0,0,0.2);
  172. display:flex;
  173. flex-flow: column;
  174. justify-content: start;
  175. align-items: stretch;
  176. width:180px;
  177. }
  178. .flow-node__context-menu .item {
  179. padding:10px 20px;
  180. cursor: pointer;
  181. width:100%;
  182. }
  183. .flow-node__context-menu hr {
  184. width:90%;
  185. border:none;
  186. border-bottom: solid 1px rgba(150,150,150,0.2);
  187. }
  188. .flow-node__context-menu button {
  189. text-align:left;
  190. }
  191. </style>