Browse Source

mapping editor wip

Martin Kunz 1 year ago
parent
commit
2bd11d720c
6 changed files with 194 additions and 0 deletions
  1. 103 0
      package-lock.json
  2. 1 0
      package.json
  3. 4 0
      src/App.vue
  4. 72 0
      src/components/TheEditor.vue
  5. 7 0
      src/main.ts
  6. 7 0
      src/util/store.ts

+ 103 - 0
package-lock.json

@@ -8,6 +8,7 @@
       "name": "modtool",
       "version": "0.0.0",
       "dependencies": {
+        "@guolao/vue-monaco-editor": "^1.3.0",
         "bootstrap": "^5.3.2",
         "fast-xml-parser": "^4.3.1",
         "jszip": "^3.10.1",
@@ -457,6 +458,50 @@
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
       }
     },
+    "node_modules/@guolao/vue-monaco-editor": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/@guolao/vue-monaco-editor/-/vue-monaco-editor-1.3.0.tgz",
+      "integrity": "sha512-gMrPZUlwwA0AKE7/q2UYKTrdZBYoJ1In0i4bNSAgyFLlSDqzrHi4Stjfi+RIprJrNWJ/j4STifPNKcldr8EaJw==",
+      "dependencies": {
+        "@monaco-editor/loader": "^1.3.3",
+        "vue-demi": "latest"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.7.1",
+        "monaco-editor": "^0.38.0",
+        "vue": "^2.6.14 || >=3.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@guolao/vue-monaco-editor/node_modules/vue-demi": {
+      "version": "0.14.6",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
+      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
+      "hasInstallScript": true,
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/@humanwhocodes/config-array": {
       "version": "0.11.11",
       "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
@@ -495,6 +540,17 @@
       "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
       "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
     },
+    "node_modules/@monaco-editor/loader": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz",
+      "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==",
+      "dependencies": {
+        "state-local": "^1.0.6"
+      },
+      "peerDependencies": {
+        "monaco-editor": ">= 0.21.0 < 1"
+      }
+    },
     "node_modules/@nodelib/fs.scandir": {
       "version": "2.1.5",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -2579,6 +2635,12 @@
         "node": "*"
       }
     },
+    "node_modules/monaco-editor": {
+      "version": "0.38.0",
+      "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.38.0.tgz",
+      "integrity": "sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A==",
+      "peer": true
+    },
     "node_modules/ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -3453,6 +3515,11 @@
       "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==",
       "dev": true
     },
+    "node_modules/state-local": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
+      "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
+    },
     "node_modules/string_decoder": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@@ -4187,6 +4254,23 @@
       "integrity": "sha512-NCC3zz2+nvYd+Ckfh87rA47zfu2QsQpvc6k1yzTk+b9KzRj0wkGa8LSoGOXN6Zv4lRf/EIoZ80biDh9HOI+RNQ==",
       "dev": true
     },
+    "@guolao/vue-monaco-editor": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/@guolao/vue-monaco-editor/-/vue-monaco-editor-1.3.0.tgz",
+      "integrity": "sha512-gMrPZUlwwA0AKE7/q2UYKTrdZBYoJ1In0i4bNSAgyFLlSDqzrHi4Stjfi+RIprJrNWJ/j4STifPNKcldr8EaJw==",
+      "requires": {
+        "@monaco-editor/loader": "^1.3.3",
+        "vue-demi": "latest"
+      },
+      "dependencies": {
+        "vue-demi": {
+          "version": "0.14.6",
+          "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
+          "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
+          "requires": {}
+        }
+      }
+    },
     "@humanwhocodes/config-array": {
       "version": "0.11.11",
       "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz",
@@ -4215,6 +4299,14 @@
       "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
       "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
     },
+    "@monaco-editor/loader": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz",
+      "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==",
+      "requires": {
+        "state-local": "^1.0.6"
+      }
+    },
     "@nodelib/fs.scandir": {
       "version": "2.1.5",
       "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -5743,6 +5835,12 @@
         "brace-expansion": "^1.1.7"
       }
     },
+    "monaco-editor": {
+      "version": "0.38.0",
+      "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.38.0.tgz",
+      "integrity": "sha512-11Fkh6yzEmwx7O0YoLxeae0qEGFwmyPRlVxpg7oF9czOOCB/iCjdJrG5I67da5WiXK3YJCxoz9TJFE8Tfq/v9A==",
+      "peer": true
+    },
     "ms": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -6348,6 +6446,11 @@
       "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==",
       "dev": true
     },
+    "state-local": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
+      "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
+    },
     "string_decoder": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",

+ 1 - 0
package.json

@@ -11,6 +11,7 @@
     "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
   },
   "dependencies": {
+    "@guolao/vue-monaco-editor": "^1.3.0",
     "bootstrap": "^5.3.2",
     "fast-xml-parser": "^4.3.1",
     "jszip": "^3.10.1",

+ 4 - 0
src/App.vue

@@ -2,6 +2,8 @@
 import TheModeler from './components/TheModeler.vue'
 import TheDetail from './components/TheDetail.vue'
 import TheParent from './components/TheParent.vue'
+import TheEditor from './components/TheEditor.vue'
+
 
 import TheModels from './components/TheModels.vue'
 import { useStore } from './util/store';
@@ -40,6 +42,8 @@ async function load(): Promise<AddressSpace> {
       <div class="col col-6">
         <TheParent />
         <TheDetail />
+        <TheEditor />
+
       </div>
     </div>
   </div>

+ 72 - 0
src/components/TheEditor.vue

@@ -0,0 +1,72 @@
+<script setup lang="ts">
+import { useStore, type IMappingValue } from '@/util/store'
+const store = useStore()
+import { ref, shallowRef } from 'vue'
+
+//see https://github.com/imguolao/monaco-vue#vite
+import { loader } from "@guolao/vue-monaco-editor"
+import * as monaco from "monaco-editor"
+import editorWorker from "monaco-editor/esm/vs/editor/editor.worker?worker"
+import jsonWorker from "monaco-editor/esm/vs/language/json/json.worker?worker"
+import cssWorker from "monaco-editor/esm/vs/language/css/css.worker?worker"
+import htmlWorker from "monaco-editor/esm/vs/language/html/html.worker?worker"
+import tsWorker from "monaco-editor/esm/vs/language/typescript/ts.worker?worker"
+self.MonacoEnvironment = {
+  getWorker(_, label) {
+    if (label === "json") {
+      return new jsonWorker()
+    }
+    if (label === "css" || label === "scss" || label === "less") {
+      return new cssWorker()
+    }
+    if (label === "html" || label === "handlebars" || label === "razor") {
+      return new htmlWorker()
+    }
+    if (label === "typescript" || label === "javascript") {
+      return new tsWorker()
+    }
+    return new editorWorker()
+  }
+}
+loader.config({ monaco })
+
+
+const MONACO_EDITOR_OPTIONS = {
+  automaticLayout: true,
+  formatOnType: true,
+  formatOnPaste: true,
+}
+
+const code = ref('')
+const editorRef = shallowRef()
+const handleMount = (editor: any) => (editorRef.value = editor)
+
+const onChange = (value: string | undefined, event: monaco.editor.IModelContentChangedEvent) => {
+  if(!store.selectedNode)
+    return;
+  if(!value)
+    return;
+  store.mapping.set(store.selectedNode.nodeId.value.toString(), {read: value, write: ""} as IMappingValue)
+}
+</script>
+
+<template>
+  <div class="card">
+    <div class="card-body" v-if="store.selectedNode != null" :elem="store.selectedNode">
+      <h5 class="card-title">Mapping Editor</h5>
+      <div class="card-text">
+        <vue-monaco-editor
+          v-model:value="code"
+          height= "12em"
+          theme="vs-dark"
+          language="javascript"
+          :options="MONACO_EDITOR_OPTIONS"
+          @mount="handleMount"
+          @change="onChange"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<style scoped></style>

+ 7 - 0
src/main.ts

@@ -3,9 +3,16 @@ import './assets/main.css'
 import { createApp } from 'vue'
 import App from './App.vue'
 import { createPinia } from 'pinia'
+import { install as VueMonacoEditorPlugin } from '@guolao/vue-monaco-editor'
 import 'bootstrap/dist/css/bootstrap.min.css'
 
 const app = createApp(App)
 const pinia = createPinia()
 app.use(pinia)
+app.use(VueMonacoEditorPlugin, {
+    paths: {
+      // The recommended CDN config
+      vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs'
+    },
+  })
 app.mount('#app')

+ 7 - 0
src/util/store.ts

@@ -9,6 +9,7 @@ export const useStore = defineStore('user', {
       addressSpace: null as AddressSpace | null,
       rootNode: null as UABaseNode | null,
       selectedNode: ref<UABaseNode | null>(null),
+      mapping: new Map<string, IMappingValue>()
   }),
   actions: {
     setAddressSpace(as: AddressSpace) {
@@ -22,3 +23,9 @@ export const useStore = defineStore('user', {
     }
   }
 })
+
+export interface IMappingValue {
+  path: string;
+  read: string;
+  write: string;
+}