From 20d68a540063f2a07a3095875f1b9525d7378d09 Mon Sep 17 00:00:00 2001 From: Arkadiusz Sygulski Date: Fri, 26 Jun 2020 22:06:10 +0200 Subject: [PATCH 01/11] Start working on using swagger documentation instead of obsolete endpoints --- package-lock.json | 133 +++++++++++++++++++++- package.json | 1 + src/components/ConfigEditor.vue | 40 +++---- src/components/ConfigFields/Input.vue | 2 +- src/components/ConfigFields/InputEnum.vue | 11 +- src/components/ConfigFields/InputList.vue | 21 ++-- src/components/ConfigFields/InputTag.vue | 9 +- src/utils/swagger/dereference.js | 23 ++++ src/utils/swagger/parse.js | 16 +++ src/views/GlobalConfig.vue | 27 ++--- webpack.config.js | 3 +- 11 files changed, 219 insertions(+), 67 deletions(-) create mode 100644 src/utils/swagger/dereference.js create mode 100644 src/utils/swagger/parse.js diff --git a/package-lock.json b/package-lock.json index 6b7d9b2bb..bf7daca6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3020,6 +3020,16 @@ "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", "dev": true }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -3405,6 +3415,11 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, "check-types": { "version": "8.0.3", "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz", @@ -3589,6 +3604,11 @@ } } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, "clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", @@ -4204,6 +4224,11 @@ "which": "^1.2.9" } }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, "crypto-browserify": { "version": "3.12.0", "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", @@ -4353,6 +4378,11 @@ "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", "dev": true }, + "dag-map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/dag-map/-/dag-map-1.0.2.tgz", + "integrity": "sha1-6DefBBAA7VYfxRVHXB7SyF7s6Nc=" + }, "de-indent": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", @@ -5688,6 +5718,13 @@ } } }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, "filesize": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", @@ -6634,8 +6671,7 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-builtin-module": { "version": "1.0.0", @@ -6724,6 +6760,29 @@ "is-extglob": "^2.1.1" } }, + "is-invalid-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz", + "integrity": "sha1-MHqFWzzxqTi0TqcNLGEQYFNxTzQ=", + "requires": { + "is-glob": "^2.0.0" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "^1.0.0" + } + } + } + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -6813,6 +6872,14 @@ "has-symbols": "^1.0.0" } }, + "is-valid-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz", + "integrity": "sha1-EQ+f90w39mPh7HkV60UfLbk6yd8=", + "requires": { + "is-invalid-path": "^0.1.0" + } + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -6871,6 +6938,21 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-schema-deref-sync": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/json-schema-deref-sync/-/json-schema-deref-sync-0.13.0.tgz", + "integrity": "sha512-YBOEogm5w9Op337yb6pAT6ZXDqlxAsQCanM3grid8lMWNxRJO/zWEJi3ZzqDL8boWfwhTFym5EFrNgWwpqcBRg==", + "requires": { + "clone": "^2.1.2", + "dag-map": "~1.0.0", + "is-valid-path": "^0.1.1", + "lodash": "^4.17.13", + "md5": "~2.2.0", + "memory-cache": "~0.2.0", + "traverse": "~0.6.6", + "valid-url": "~1.0.9" + } + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6981,8 +7063,7 @@ "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, "lodash-es": { "version": "4.17.15", @@ -7053,6 +7134,16 @@ "object-visit": "^1.0.0" } }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "requires": { + "charenc": "~0.0.1", + "crypt": "~0.0.1", + "is-buffer": "~1.1.1" + } + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -7070,6 +7161,11 @@ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, + "memory-cache": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz", + "integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo=" + }, "memory-fs": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", @@ -7357,6 +7453,13 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true, + "optional": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -9700,6 +9803,11 @@ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", "dev": true }, + "traverse": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz", + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=" + }, "tryer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz", @@ -10084,6 +10192,11 @@ "integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==", "dev": true }, + "valid-url": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", + "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -10426,7 +10539,11 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } }, "glob-parent": { "version": "3.1.0", @@ -10844,7 +10961,11 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } }, "glob-parent": { "version": "3.1.0", diff --git a/package.json b/package.json index 418ca4061..d1bcd38d9 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "copy-to-clipboard": "^3.3.1", "flat": "^5.0.0", "humanize-duration": "^3.23.1", + "json-schema-deref-sync": "^0.13.0", "lodash-es": "^4.17.15", "plurals-cldr": "^1.0.4", "svg-country-flags": "^1.2.7", diff --git a/src/components/ConfigEditor.vue b/src/components/ConfigEditor.vue index 30ad0bcd3..f7d5641f6 100644 --- a/src/components/ConfigEditor.vue +++ b/src/components/ConfigEditor.vue @@ -44,14 +44,14 @@ required: true }, categories: Array, - descriptions: Object, extendedFields: Object }, computed: { uncategorizedFields() { if (!this.categories) return this.fields; - const categorizedFields = this.categories.map(category => category.fields).reduce((categorizedFields, categoryFields) => [...categorizedFields, ...categoryFields], []); + const categorizedFields = this.categories.map(category => category.fields) + .reduce((categorizedFields, categoryFields) => [...categorizedFields, ...categoryFields], []); return this.fields.filter(field => !categorizedFields.includes(field.param)); }, @@ -60,7 +60,8 @@ if (!this.categories) return []; const category = this.categories.find(({ name }) => name === categoryName); if (!category) return []; - return this.getFields(category.fields).sort((a, b) => category.fields.indexOf(a.paramName) - category.fields.indexOf(b.paramName)); + return this.getFields(category.fields) + .sort((a, b) => category.fields.indexOf(a.paramName) - category.fields.indexOf(b.paramName)); }; }, isValid() { @@ -76,27 +77,24 @@ }, methods: { componentFromField(field) { + console.log({ ...field }); + switch (field.type) { case 'string': - case 'uint64': + if (field.enum) { + if (field.format === 'flags') return InputFlag; + return InputEnum; + } + return InputString; case 'boolean': return InputBoolean; - case 'uint32': - case 'uint16': - case 'byte': + case 'integer': + if (field.format === 'int64') return InputString; return InputNumber; - case 'flag': - return InputFlag; - case 'enum': - return InputEnum; - case 'hashSet': - case 'list': - if (['enum'].includes(field.values.type)) return field.type === 'list' ? InputList : InputSet; - if (['byte', 'uint16', 'uint32', 'uint64', 'string'].includes(field.values.type)) return InputTag; - return InputUnknown; - case 'dictionary': - return InputDictionary; + case 'array': + if (field.items.type === 'enum') return InputSet; + return InputTag; default: return InputUnknown; } @@ -129,7 +127,8 @@ case 'list': return a.length === b.length && a.every((item, index) => item === b[index]); case 'dictionary': - return Object.keys(a).length === Object.keys(b).length && Object.keys(a).every(key => a[key] === b[key]); + return Object.keys(a).length === Object.keys(b).length && Object.keys(a) + .every(key => a[key] === b[key]); } return false; @@ -141,7 +140,8 @@ this.$el.style.setProperty('--label-width', 'auto'); this.$nextTick(() => { - const labelWidth = Math.max(...Array.from(this.$el.querySelectorAll('.form-item__label')).map(el => Math.ceil(parseFloat(getComputedStyle(el).width)))); + const labelWidth = Math.max(...Array.from(this.$el.querySelectorAll('.form-item__label')) + .map(el => Math.ceil(parseFloat(getComputedStyle(el).width)))); this.$el.style.setProperty('--label-width', `${labelWidth}px`); }); } diff --git a/src/components/ConfigFields/Input.vue b/src/components/ConfigFields/Input.vue index e547762ec..e7b5b2f43 100644 --- a/src/components/ConfigFields/Input.vue +++ b/src/components/ConfigFields/Input.vue @@ -13,7 +13,7 @@ currentValue: true }, data() { - const initialValue = typeof this.currentValue !== 'undefined' ? this.currentValue : this.schema.defaultValue; + const initialValue = typeof this.currentValue !== 'undefined' ? this.currentValue : null; return { value: typeof initialValue === 'object' ? JSON.parse(JSON.stringify(initialValue)) : initialValue, diff --git a/src/components/ConfigFields/InputEnum.vue b/src/components/ConfigFields/InputEnum.vue index 89c180638..30bc27baf 100644 --- a/src/components/ConfigFields/InputEnum.vue +++ b/src/components/ConfigFields/InputEnum.vue @@ -4,9 +4,7 @@
@@ -22,12 +20,7 @@ mixins: [Input], computed: { values() { - return this.schema.values; - } - }, - methods: { - isLastValue(value) { - return value === Math.max(...Object.values(this.values)); + return this.schema.enum; } } }; diff --git a/src/components/ConfigFields/InputList.vue b/src/components/ConfigFields/InputList.vue index d15628cc7..86ecfd980 100644 --- a/src/components/ConfigFields/InputList.vue +++ b/src/components/ConfigFields/InputList.vue @@ -5,12 +5,8 @@
@@ -44,15 +40,15 @@ availableEnumValues() { const availableEnumValues = []; - for (const key of Object.keys(this.enumValues)) { - if (this.value.includes(this.enumValues[key])) continue; - availableEnumValues.push(this.enumValues[key]); + for (const value of this.enumValues) { + if (this.value.includes(value)) continue; + availableEnumValues.push(value); } return availableEnumValues; }, enumValues() { - return this.schema.values.values; + return this.schema.enum; } }, created() { @@ -72,9 +68,6 @@ removeElement(index) { this.value.splice(index, 1); this.element = this.getDefaultElement(); - }, - resolveOption(value) { - return Object.keys(this.enumValues).find(key => this.enumValues[key] === value); } } }; diff --git a/src/components/ConfigFields/InputTag.vue b/src/components/ConfigFields/InputTag.vue index 7f8b1a45e..247021b6e 100644 --- a/src/components/ConfigFields/InputTag.vue +++ b/src/components/ConfigFields/InputTag.vue @@ -9,12 +9,15 @@ {{ item }} + + + {{ errorText }} @@ -37,13 +40,13 @@ }, computed: { isString() { - return ['string', 'uint64'].includes(this.schema.values.type); + return ['string'].includes(this.schema.items.type); }, isNumber() { - return ['uint32', 'uint16'].includes(this.schema.values.type); + return ['uint32', 'uint16'].includes(this.schema.items.type); }, errors() { - if (validator.hasOwnProperty(this.schema.values.type)) return validator[this.schema.values.type](this.element); + if (validator.hasOwnProperty(this.schema.items.type)) return validator[this.schema.items.type](this.element); return []; }, isValid() { diff --git a/src/utils/swagger/dereference.js b/src/utils/swagger/dereference.js new file mode 100644 index 000000000..c1a9286c4 --- /dev/null +++ b/src/utils/swagger/dereference.js @@ -0,0 +1,23 @@ +import { cloneDeep, get, isObject } from 'lodash-es'; + +function isRef(node) { + return node.$ref; +} + +function resolveRef(path, schema) { + const lodashPath = path.substr(2).replace(/\//g, '.'); + return get(schema, lodashPath); +} + +function resolve(tree, schema) { + for (const key of Object.keys(tree)) { + if (isRef(tree[key])) tree[key] = resolveRef(tree[key].$ref, schema); + if (isObject(tree[key])) resolve(tree[key], schema); + } +} + +export function dereference(schema) { + const localSchema = cloneDeep(schema); + resolve(localSchema, localSchema); + return localSchema; +} diff --git a/src/utils/swagger/parse.js b/src/utils/swagger/parse.js new file mode 100644 index 000000000..b1e2dccda --- /dev/null +++ b/src/utils/swagger/parse.js @@ -0,0 +1,16 @@ +import { dereference } from './dereference'; +import axios from 'axios'; + +const endpoint = 'http://localhost:8080/swagger/ASF/swagger.json'; + +export async function getTypes() { + return await axios.get(endpoint) + .then(response => response.data) + .then(schema => dereference(schema)) + .then(schema => schema.components.schemas); +} + +export async function getType(name) { + const { [name]: type } = await getTypes(); + return type.properties; +} diff --git a/src/views/GlobalConfig.vue b/src/views/GlobalConfig.vue index 4205b2d55..daec48bb2 100644 --- a/src/views/GlobalConfig.vue +++ b/src/views/GlobalConfig.vue @@ -7,8 +7,7 @@