From 447d7ae10311386c4343ebc689feabf103ce57b9 Mon Sep 17 00:00:00 2001 From: mirkobrombin Date: Thu, 3 Aug 2023 19:22:54 +0200 Subject: [PATCH 1/2] (wip) new Vib manager --- index.html | 1 + package-lock.json | 255 +++++++++++++++++++++++++++++-- package.json | 8 +- public/atlas-logo.svg | 1 + src/App.vue | 50 +++--- src/assets/css/fonts.css | 2 +- src/assets/css/style.css | 245 +++-------------------------- src/components/RecipeDetails.vue | 139 +++++++++++++++++ src/components/RecipeModules.vue | 130 ++++++++++++++++ src/components/RecipeRuns.vue | 18 +++ src/config.ts | 12 +- src/core/manager.ts | 133 ++++++++++++++++ src/core/models.ts | 35 +++++ src/core/registry.ts | 72 --------- src/main.ts | 14 +- src/router/index.ts | 30 ++-- src/views/HomeView.vue | 66 ++++---- src/views/ImageView.vue | 127 --------------- src/views/RecipeView.vue | 79 ++++++++++ 19 files changed, 910 insertions(+), 507 deletions(-) create mode 100644 public/atlas-logo.svg create mode 100644 src/components/RecipeDetails.vue create mode 100644 src/components/RecipeModules.vue create mode 100644 src/components/RecipeRuns.vue create mode 100644 src/core/manager.ts create mode 100644 src/core/models.ts delete mode 100644 src/core/registry.ts delete mode 100644 src/views/ImageView.vue create mode 100644 src/views/RecipeView.vue diff --git a/index.html b/index.html index 5ed1c5b..30f9e3f 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ + Atlas diff --git a/package-lock.json b/package-lock.json index 8bca099..8b0c39e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,11 +8,15 @@ "name": "image-registry", "version": "0.0.0", "dependencies": { + "axios": "^1.4.0", + "js-yaml": "^4.1.0", "vue": "^3.2.47", - "vue-router": "^4.1.6" + "vue-router": "^4.1.6", + "vuetify": "^3.3.11" }, "devDependencies": { - "@types/node": "^18.14.2", + "@types/js-yaml": "^4.0.5", + "@types/node": "^18.17.1", "@vitejs/plugin-vue": "^4.0.0", "@vue/tsconfig": "^0.1.3", "npm-run-all": "^4.1.5", @@ -384,10 +388,16 @@ "node": ">=12" } }, + "node_modules/@types/js-yaml": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", + "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", + "dev": true + }, "node_modules/@types/node": { - "version": "18.15.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", - "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "version": "18.17.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz", + "integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw==", "dev": true }, "node_modules/@vitejs/plugin-vue": { @@ -614,6 +624,11 @@ "node": ">=4" } }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "node_modules/array-buffer-byte-length": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", @@ -627,6 +642,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", @@ -639,6 +659,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -697,6 +727,17 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -746,6 +787,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -885,6 +934,25 @@ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -894,6 +962,19 @@ "is-callable": "^1.1.3" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -1323,6 +1404,17 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -1361,6 +1453,25 @@ "node": ">= 0.10.0" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -1568,6 +1679,11 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -1866,7 +1982,7 @@ "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2007,6 +2123,39 @@ "typescript": "*" } }, + "node_modules/vuetify": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.3.11.tgz", + "integrity": "sha512-hlbSgxXCcEu4VelJMRHKhvLpaitLsruHvdvolbqbCS6Z64XoulUDw3CQ9ay6WGBL7uckmop0bUYidD2d8mN0UQ==", + "engines": { + "node": "^12.20 || >=14.13" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": "^1.0.0-alpha.12", + "vue": "^3.2.0", + "vue-i18n": "^9.0.0", + "webpack-plugin-vuetify": "^2.0.0-alpha.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "vue-i18n": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -2216,10 +2365,16 @@ "dev": true, "optional": true }, + "@types/js-yaml": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", + "integrity": "sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==", + "dev": true + }, "@types/node": { - "version": "18.15.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz", - "integrity": "sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==", + "version": "18.17.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz", + "integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw==", "dev": true }, "@vitejs/plugin-vue": { @@ -2423,6 +2578,11 @@ "color-convert": "^1.9.0" } }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, "array-buffer-byte-length": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", @@ -2433,12 +2593,27 @@ "is-array-buffer": "^3.0.1" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "available-typed-arrays": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", "dev": true }, + "axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2491,6 +2666,14 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -2531,6 +2714,11 @@ "object-keys": "^1.1.1" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2645,6 +2833,11 @@ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -2654,6 +2847,16 @@ "is-callable": "^1.1.3" } }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -2944,6 +3147,14 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "requires": { + "argparse": "^2.0.1" + } + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -2976,6 +3187,19 @@ "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", "dev": true }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, "minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3113,6 +3337,11 @@ "source-map-js": "^1.0.2" } }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", @@ -3331,7 +3560,7 @@ "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true + "devOptional": true }, "unbox-primitive": { "version": "1.0.2", @@ -3407,6 +3636,12 @@ "@volar/vue-typescript": "1.2.0" } }, + "vuetify": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.3.11.tgz", + "integrity": "sha512-hlbSgxXCcEu4VelJMRHKhvLpaitLsruHvdvolbqbCS6Z64XoulUDw3CQ9ay6WGBL7uckmop0bUYidD2d8mN0UQ==", + "requires": {} + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/package.json b/package.json index 61243b8..2897c1d 100644 --- a/package.json +++ b/package.json @@ -10,11 +10,15 @@ "type-check": "vue-tsc --noEmit" }, "dependencies": { + "axios": "^1.4.0", + "js-yaml": "^4.1.0", "vue": "^3.2.47", - "vue-router": "^4.1.6" + "vue-router": "^4.1.6", + "vuetify": "^3.3.11" }, "devDependencies": { - "@types/node": "^18.14.2", + "@types/js-yaml": "^4.0.5", + "@types/node": "^18.17.1", "@vitejs/plugin-vue": "^4.0.0", "@vue/tsconfig": "^0.1.3", "npm-run-all": "^4.1.5", diff --git a/public/atlas-logo.svg b/public/atlas-logo.svg new file mode 100644 index 0000000..508c36c --- /dev/null +++ b/public/atlas-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/App.vue b/src/App.vue index e217eba..6c479b6 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,32 +1,42 @@ \ No newline at end of file diff --git a/src/assets/css/fonts.css b/src/assets/css/fonts.css index 1c9ff7b..b6582a0 100644 --- a/src/assets/css/fonts.css +++ b/src/assets/css/fonts.css @@ -1,3 +1,3 @@ -@import url('https://fonts.googleapis.com/css?family=Material+Icons'); +@import url('https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Two+Tone|Material+Icons+Round|Material+Icons+Sharp'); @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@100;200;300;400;500;600;700;800;900&display=swap'); @import url('https://fonts.googleapis.com/css?family=Pacifico'); \ No newline at end of file diff --git a/src/assets/css/style.css b/src/assets/css/style.css index 70a5563..d59203d 100644 --- a/src/assets/css/style.css +++ b/src/assets/css/style.css @@ -1,248 +1,53 @@ -body { - background-color: #F2F1ED; -} - body, input, button, select, textarea { font-family: 'Outfit', sans-serif; -} - -h1, -h2, -h3, -h4, -h5, -h6 { - font-weight: 600; - margin: 0 0 20px 0; -} - -h1 { - font-size: 32px; -} - -h2 { - font-size: 28px; -} - -h3 { - font-size: 24px; -} - -h4 { - font-size: 20px; -} - -h5 { font-size: 18px; } -h6 { - font-size: 16px; -} - -a { - color: #000; -} - -header { - display: flex; - justify-content: space-between; - align-items: center; -} - -header ul { - display: flex; - gap: 20px; -} - -header ul li a { - font-size: 17px; - text-decoration: none; -} - -.logo { - font-family: "Pacifico", cursive; - font-size: 28px; -} - -.container { - max-width: 1200px; - margin: 0 auto; - padding: 20px; -} - -header a { - text-decoration: none; -} - -header a:hover { - text-decoration: underline; -} - -.container-small { - max-width: 510px; -} - -.v-center { - height: 70vh; - justify-content: center; -} - -.search p { - font-size: 21px; -} - -.search.search-big { - text-align: center; - justify-content: center; - margin: 0 auto; -} - -.search-field { - background: #fff; - padding: 15px 20px 15px 56px; - display: flex; - justify-content: center; - border-radius: 6px; +.card-header-title { gap: 10px; - box-shadow: 0 1px 1px 0px #d1cec5, 0 3px 10px 0 #e1dccc; - border: 0; - outline: none; - font-size: 20px; - flex: 1; -} - -.form-search { - display: flex; - flex-direction: column; - align-items: stretch; -} - -.form-search .form-icon { - position: absolute; - margin: 16px; - pointer-events: none; -} - -.search { - display: flex; - gap: 20px; - flex-direction: column; - align-items: stretch; - margin: 0 0 30px 0; -} - -.table { - background: #fff; - border-radius: 6px; - box-shadow: 0 1px 1px 0px #d1cec5, 0 3px 10px 0 #e1dccc; - border-collapse: collapse; - width: 100%; } -.table td, -.table th, -.fabr-table-search { - border: 1px solid #d1cec5; - padding: 10px; +table.is-bordered tr:last-child td, +.table.is-bordered tr:last-child th, +.table.is-narrow td, +.table.is-narrow th { + padding: 0.6em 0.5em; } -.table th, -.fabr-table-search { - background: #f2f1ed; - font-weight: 600; - text-align: initial; +.table thead th { + font-weight: 500; } -.table tr:nth-child(even) { - background: #f9f8f5; -} - -.table tr:hover { - background: #f2f1ed; -} - -.panel { - background: #fff; - border-radius: 6px; - box-shadow: 0 1px 1px 0px #d1cec5, 0 3px 10px 0 #e1dccc; +pre.block { padding: 20px; + margin: 0 0 10px 0; } -.panel-wrapper { +.bar-chart { display: flex; - gap: 20px; - flex-direction: column; -} - -.fabr-table-search { + border: 1px solid #ccc; + height: 300px; + margin-top: 10px; width: 100%; - border-bottom: 0; - outline: none; } -small { - color: #686761; +.bar-segment:hover { + background-color: #485fc7; } -.panels { +.bar-segment { display: flex; - flex-wrap: wrap; - gap: 10px; - margin: 0 0 10px 0; -} - -.panels .panel { + justify-content: center; + align-items: flex-end; + background-color: #3850b7; + color: #fff; + font-size: 14px; + width: calc(100% / var(--num-segments)); + transition: height 0.2s; + padding: 8px 10px; flex-grow: 1; - overflow: auto; -} - -.panel h2 { - display: flex; - align-items: center; - gap: 10px; - font-size: 23px; -} - -code.hljs { - border-radius: 6px; -} - -pre { - background-color: #282936; - padding: 20px; - color: #e9e9f4; - font-size: 18px; - font-family: monospace; - border-radius: 6px; -} - -b, -strong { - font-weight: 600; -} - -.boxed-list { - display: flex; - flex-direction: column; - gap: 5px; -} - -.boxed-list-item { - display: flex; - align-items: center; - gap: 5px; -} - -.boxed-list-wrapper { - background-color: #f2f1ed; - border-radius: 6px; - padding: 11px; - display: flex; - flex-direction: column; - gap: 5px; } \ No newline at end of file diff --git a/src/components/RecipeDetails.vue b/src/components/RecipeDetails.vue new file mode 100644 index 0000000..1d55cda --- /dev/null +++ b/src/components/RecipeDetails.vue @@ -0,0 +1,139 @@ + + + \ No newline at end of file diff --git a/src/components/RecipeModules.vue b/src/components/RecipeModules.vue new file mode 100644 index 0000000..4dfc66e --- /dev/null +++ b/src/components/RecipeModules.vue @@ -0,0 +1,130 @@ + + + diff --git a/src/components/RecipeRuns.vue b/src/components/RecipeRuns.vue new file mode 100644 index 0000000..044830b --- /dev/null +++ b/src/components/RecipeRuns.vue @@ -0,0 +1,18 @@ + + + diff --git a/src/config.ts b/src/config.ts index 0197de0..76f50b5 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,6 +1,14 @@ class AtlasConfig { - public static readonly registry = 'https://ghcr.io/vanilla-os'; - public static readonly title = 'Vanilla OS Registry'; + public static readonly registry = "https://raw.githubusercontent.com"; + public static readonly title = "Vanilla OS Registry"; + public static readonly repos = [ + "vanilla-os/pico-image", + "vanilla-os/core-image", + "vanilla-os/dev-image", + "vanilla-os/vso-image", + "vanilla-os/desktop-image", + "vanilla-os/nvidia-image", + ]; } export default AtlasConfig; diff --git a/src/core/manager.ts b/src/core/manager.ts new file mode 100644 index 0000000..942cb55 --- /dev/null +++ b/src/core/manager.ts @@ -0,0 +1,133 @@ +import axios from "axios"; +import * as yaml from "js-yaml"; +import type { VibRecipe, Module } from "@/core/models"; +import AtlasConfig from "@/config"; + +class AtlasManager { + private static readonly storageKey = "vibRecipes"; + + private static async fetchRecipeFromRepo( + repo: string + ): Promise { + const url = `${AtlasConfig.registry}/${repo}/main/recipe.yml`; + try { + const response = await axios.get(url); + return response.data; + } catch (error) { + console.error( + `Error fetching recipe.yml from ${repo}: ${(error as Error).message}` + ); + return null; + } + } + + private static async fetchModuleContentFromRepo( + repo: string, + path: string + ): Promise { + const url = `${AtlasConfig.registry}/${repo}/main/${path}.yml`; + try { + const response = await axios.get(url); + return response.data; + } catch (error) { + console.error( + `Error fetching module content from ${url}: ${(error as Error).message}` + ); + return null; + } + } + + private static saveToLocalStorage(recipes: VibRecipe[]): void { + const serializedRecipes = JSON.stringify(recipes); + localStorage.setItem(this.storageKey, serializedRecipes); + } + + private static getFromLocalStorage(): VibRecipe[] | null { + const serializedRecipes = localStorage.getItem(this.storageKey); + if (serializedRecipes) { + return JSON.parse(serializedRecipes) as VibRecipe[]; + } + return null; + } + + public static async getVibRecipes(): Promise { + console.log("Fetching VibRecipes..."); + + const cachedRecipes = this.getFromLocalStorage(); + if (cachedRecipes) { + console.log("Fetched VibRecipes from local storage."); + return cachedRecipes; + } + + const vibRecipes: VibRecipe[] = []; + + for (const repo of AtlasConfig.repos) { + console.log(`Fetching recipe.yml from ${repo}`); + const recipeYaml = await this.fetchRecipeFromRepo(repo); + if (recipeYaml !== null) { + try { + console.log(`Parsing recipe.yml from ${repo}`); + const recipeObject = yaml.load(recipeYaml) as VibRecipe; + const modules: Module[] = []; + + if (recipeObject.modules) { + for (const module of recipeObject.modules) { + if (module.includes) { + console.log( + `Fetching and processing included modules for ${repo}` + ); + for (const includePath of module.includes) { + const moduleContent = await this.fetchModuleContentFromRepo( + repo, + includePath + ); + if (moduleContent) { + try { + const includedModule = yaml.load(moduleContent) as Module; + includedModule.snippet = moduleContent; + modules.push(includedModule); + } catch (error) { + console.error( + `Error parsing included module from ${repo}: ${ + (error as Error).message + }` + ); + } + } + } + } else { + module.snippet = yaml.dump(module); + modules.push(module); + } + } + } + + recipeObject.id = repo.replace("/", "-"); + recipeObject.modules = modules; + vibRecipes.push(recipeObject); + } catch (error) { + console.error( + `Error parsing recipe.yml from ${repo}: ${(error as Error).message}` + ); + } + } + } + + this.saveToLocalStorage(vibRecipes); + + console.log("Finished fetching VibRecipes"); + return vibRecipes; + } + + public static async getVibRecipe(id: string): Promise { + const vibRecipes = await this.getVibRecipes(); + for (const recipe of vibRecipes) { + if (recipe.id === id) { + return recipe; + } + } + return null; + } +} + +export default AtlasManager; diff --git a/src/core/models.ts b/src/core/models.ts new file mode 100644 index 0000000..256ff89 --- /dev/null +++ b/src/core/models.ts @@ -0,0 +1,35 @@ +interface Source { + packages?: string; + path?: string; + url?: string; + type?: string; + tag?: string; + commit?: string; +} + +interface Module { + name: string; + type: string; + path?: string; + source?: Source; + buildflags?: string[]; + buildvars?: string[]; + modules?: { [key: string]: Module }; + includes?: string[]; + commands?: string[]; + snippet?: string; +} + +interface VibRecipe { + id: string; + recipeObject: any; + base: string; + name: string; + singlelayer: boolean; + labels: { [key: string]: string }; + args: { [key: string]: string }; + runs: string[]; + modules: Module[]; +} + +export type { VibRecipe, Module, Source }; diff --git a/src/core/registry.ts b/src/core/registry.ts deleted file mode 100644 index 0991356..0000000 --- a/src/core/registry.ts +++ /dev/null @@ -1,72 +0,0 @@ -import AtlasConfig from '@/config' -import { OciImage } from "@/core/image"; - - -class RegistryManager { - - async get_tags(image: string) { - const r = await fetch(`${AtlasConfig.registry}/v2/${image}/tags/list`); - if (!r.ok) return []; - - const json = await r.json(); - return json.tags as string[]; - } - - async get_manifest(image: string, tag: string) { - const r = await fetch(`${AtlasConfig.registry}/v2/${image}/manifests/${tag}`); - if (!r.ok) return {}; - - return await r.json(); - } - - async get_config(image: string, digest: string) { - const r = await fetch(`${AtlasConfig.registry}/v2/${image}/blobs/${digest}`); - if (!r.ok) return {}; - - return await r.json(); - } - - async get_image(image: string, tag: string) : Promise{ - const manifest = await this.get_manifest(image, tag); - const config = await this.get_config(image, manifest.config.digest); - const ociImage = new OciImage(); - const totalSize = manifest.layers.reduce((a: number, b: any) => a + b.size, 0); - - ociImage.name = image; - ociImage.size = totalSize; - ociImage.create_date = new Date(config.history[0].created); - ociImage.digest = manifest.config.digest; - ociImage.tag = tag; - ociImage.architecture = config.architecture; - ociImage.os = config.os; - ociImage.config = config.config; - ociImage.history = config.history; - ociImage.layers = manifest.layers; - - return ociImage; - } - - - - async get_images() { - const images: OciImage[] = []; - - const r = await fetch(`${AtlasConfig.registry}/v2/_catalog`); - if (!r.ok) return images; - - const json = await r.json(); - const repositories: string[] = json["repositories"]; - - for (const image of repositories) { - const tags = await this.get_tags(image); - - for (const tag of tags) { - images.push(await this.get_image(image, tag)); - } - } - return images; - } - - } - -export { RegistryManager, OciImage }; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 4061701..78c976b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,11 +1,11 @@ -import { createApp } from 'vue' -import App from './App.vue' -import router from './router' +import { createApp } from "vue"; +import App from "./App.vue"; +import router from "./router"; -import './assets/css/index.css' +import "./assets/css/index.css"; -const app = createApp(App) +const app = createApp(App); -app.use(router) +app.use(router); -app.mount('#app') +app.mount("#app"); diff --git a/src/router/index.ts b/src/router/index.ts index e259575..80be006 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,28 +1,28 @@ -import { createRouter, createWebHistory } from 'vue-router' -import HomeView from '../views/HomeView.vue' -import ImageView from '../views/ImageView.vue' -import AtlasConfig from '@/config' +import { createRouter, createWebHistory } from "vue-router"; +import HomeView from "../views/HomeView.vue"; +import RecipeView from "../views/RecipeView.vue"; +import AtlasConfig from "@/config"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { - path: '/', - name: 'Home', - component: HomeView + path: "/", + name: "home", + component: HomeView, }, { - path: '/image/:image/tag/:tag', - name: 'Image', - component: ImageView - } - ] -}) + path: "/recipe/:id", + name: "recipe", + component: RecipeView, + }, + ], +}); router.beforeEach((to, from, next) => { - const suffix = AtlasConfig.title ? ` ${AtlasConfig.title}` : ''; + const suffix = AtlasConfig.title ? ` ${AtlasConfig.title}` : ""; document.title = to.meta.title ? to.meta.title + suffix : suffix; next(); }); -export default router +export default router; diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index c927453..abc916e 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -1,36 +1,40 @@ \ No newline at end of file +export default defineComponent({ + name: 'HomeView', + data() { + return { + recipes: [] as VibRecipe[], + }; + }, + async mounted() { + try { + this.recipes = await AtlasManager.getVibRecipes(); + } catch (error) { + console.error('Error fetching recipes:', error); + } + }, +}); + diff --git a/src/views/ImageView.vue b/src/views/ImageView.vue deleted file mode 100644 index 2650863..0000000 --- a/src/views/ImageView.vue +++ /dev/null @@ -1,127 +0,0 @@ - - - \ No newline at end of file diff --git a/src/views/RecipeView.vue b/src/views/RecipeView.vue new file mode 100644 index 0000000..2409786 --- /dev/null +++ b/src/views/RecipeView.vue @@ -0,0 +1,79 @@ + + + \ No newline at end of file From ea787b1250bd593bc2b282cd0d69c817a9b78a46 Mon Sep 17 00:00:00 2001 From: mirkobrombin Date: Thu, 3 Aug 2023 23:28:36 +0200 Subject: [PATCH 2/2] (wip) new Vib manager --- package-lock.json | 47 ++++++++++++++++++++++++++ package.json | 3 ++ src/assets/css/style.css | 58 ++++++++++++++++++++++++++++++++ src/components/RecipeDetails.vue | 24 +++++++------ src/components/RecipeModules.vue | 49 ++++++++++++++++++++++++--- src/components/RecipeSnippet.vue | 20 +++++++++++ src/core/helpers.ts | 36 ++++++++++++++++++++ src/core/manager.ts | 1 + src/core/models.ts | 1 + src/core/yaml-highlight.ts | 14 ++++++++ src/main.ts | 2 ++ src/views/HomeView.vue | 49 ++++++++++++++++++++------- src/views/RecipeView.vue | 7 ++++ 13 files changed, 284 insertions(+), 27 deletions(-) create mode 100644 src/components/RecipeSnippet.vue create mode 100644 src/core/helpers.ts create mode 100644 src/core/yaml-highlight.ts diff --git a/package-lock.json b/package-lock.json index 8b0c39e..97ae492 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,12 @@ "name": "image-registry", "version": "0.0.0", "dependencies": { + "@highlightjs/vue-plugin": "^2.1.0", "axios": "^1.4.0", + "highlight.js": "^11.8.0", "js-yaml": "^4.1.0", "vue": "^3.2.47", + "vue-highlightjs": "^1.3.3", "vue-router": "^4.1.6", "vuetify": "^3.3.11" }, @@ -388,6 +391,15 @@ "node": ">=12" } }, + "node_modules/@highlightjs/vue-plugin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@highlightjs/vue-plugin/-/vue-plugin-2.1.0.tgz", + "integrity": "sha512-E+bmk4ncca+hBEYRV2a+1aIzIV0VSY/e5ArjpuSN9IO7wBJrzUE2u4ESCwrbQD7sAy+jWQjkV5qCCWgc+pu7CQ==", + "peerDependencies": { + "highlight.js": "^11.0.1", + "vue": "^3" + } + }, "node_modules/@types/js-yaml": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", @@ -1175,6 +1187,14 @@ "he": "bin/he" } }, + "node_modules/highlight.js": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.8.0.tgz", + "integrity": "sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -2083,6 +2103,14 @@ "@vue/shared": "3.2.47" } }, + "node_modules/vue-highlightjs": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/vue-highlightjs/-/vue-highlightjs-1.3.3.tgz", + "integrity": "sha512-NaBfeVVa5rbKw9bNU0ajAcDmKOdzT+XuBZwYKFbEGSGFKGOc5wYerMY3R4WQrnlLD7BkG9tIIusqemKnIgQ7MA==", + "dependencies": { + "highlight.js": "*" + } + }, "node_modules/vue-router": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz", @@ -2365,6 +2393,12 @@ "dev": true, "optional": true }, + "@highlightjs/vue-plugin": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@highlightjs/vue-plugin/-/vue-plugin-2.1.0.tgz", + "integrity": "sha512-E+bmk4ncca+hBEYRV2a+1aIzIV0VSY/e5ArjpuSN9IO7wBJrzUE2u4ESCwrbQD7sAy+jWQjkV5qCCWgc+pu7CQ==", + "requires": {} + }, "@types/js-yaml": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.5.tgz", @@ -2990,6 +3024,11 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "highlight.js": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.8.0.tgz", + "integrity": "sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==" + }, "hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -3608,6 +3647,14 @@ "@vue/shared": "3.2.47" } }, + "vue-highlightjs": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/vue-highlightjs/-/vue-highlightjs-1.3.3.tgz", + "integrity": "sha512-NaBfeVVa5rbKw9bNU0ajAcDmKOdzT+XuBZwYKFbEGSGFKGOc5wYerMY3R4WQrnlLD7BkG9tIIusqemKnIgQ7MA==", + "requires": { + "highlight.js": "*" + } + }, "vue-router": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz", diff --git a/package.json b/package.json index 2897c1d..3afe1a9 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,12 @@ "type-check": "vue-tsc --noEmit" }, "dependencies": { + "@highlightjs/vue-plugin": "^2.1.0", "axios": "^1.4.0", + "highlight.js": "^11.8.0", "js-yaml": "^4.1.0", "vue": "^3.2.47", + "vue-highlightjs": "^1.3.3", "vue-router": "^4.1.6", "vuetify": "^3.3.11" }, diff --git a/src/assets/css/style.css b/src/assets/css/style.css index d59203d..1ffd160 100644 --- a/src/assets/css/style.css +++ b/src/assets/css/style.css @@ -25,6 +25,7 @@ table.is-bordered tr:last-child td, pre.block { padding: 20px; margin: 0 0 10px 0; + line-height: 1.3; } .bar-chart { @@ -33,6 +34,7 @@ pre.block { height: 300px; margin-top: 10px; width: 100%; + overflow: hidden; } .bar-segment:hover { @@ -50,4 +52,60 @@ pre.block { transition: height 0.2s; padding: 8px 10px; flex-grow: 1; +} + +pre.block, +.card, +.bar-chart { + border-radius: 10px; +} + + +.card-header { + box-shadow: none; +} + +.card-content { + padding: 1rem 1.5rem; +} + +.badge { + display: inline-flex; + align-items: center; + gap: 5px; + background-color: #f2f2f2; + padding: 2px 8px; + border-radius: 20px; +} + +p span.badge { + position: relative; + top: 4px; +} + +.flex-list { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 5px; +} + +.badges { + display: flex; + gap: 10px; + align-items: center; +} + +.flex-grid { + display: flex; + flex-wrap: wrap; + gap: 10px; +} + +.flex-grid-item { + flex: 1; +} + +.footer { + background-color: transparent; } \ No newline at end of file diff --git a/src/components/RecipeDetails.vue b/src/components/RecipeDetails.vue index 1d55cda..ccfc292 100644 --- a/src/components/RecipeDetails.vue +++ b/src/components/RecipeDetails.vue @@ -20,7 +20,7 @@ -
+

@@ -39,7 +39,7 @@

-
+

@@ -58,7 +58,7 @@

-
+

@@ -80,15 +80,17 @@

-
-

Modules Usage

-
+
+
+

Modules Usage

+
-
-
-
- {{ moduleType }} ({{ chartData.datasets[0].data[index] }}) +
+
+
+ {{ moduleType }} ({{ chartData.datasets[0].data[index] }}) +
diff --git a/src/components/RecipeModules.vue b/src/components/RecipeModules.vue index 4dfc66e..56fc809 100644 --- a/src/components/RecipeModules.vue +++ b/src/components/RecipeModules.vue @@ -1,5 +1,13 @@ diff --git a/src/components/RecipeSnippet.vue b/src/components/RecipeSnippet.vue new file mode 100644 index 0000000..bab3654 --- /dev/null +++ b/src/components/RecipeSnippet.vue @@ -0,0 +1,20 @@ + + + \ No newline at end of file diff --git a/src/core/helpers.ts b/src/core/helpers.ts new file mode 100644 index 0000000..d25edd1 --- /dev/null +++ b/src/core/helpers.ts @@ -0,0 +1,36 @@ +function getModuleTypeClass(type: string) { + switch (type) { + case "shell": + return "terminal"; + + case "apt": + return "inventory_2"; + case "dpkg": + return "inventory_2"; + case "dnf": + return "inventory_2"; + case "rpm": + return "inventory_2"; + case "yum": + return "inventory_2"; + + case "dpkg-buildpackage": + return "home_repair_service"; + case "rpm-build": + return "home_repair_service"; + + case "cmake": + return "build"; + case "go": + return "build"; + case "meson": + return "build"; + + default: + return "extension"; + } +} + +export default { + getModuleTypeClass +} \ No newline at end of file diff --git a/src/core/manager.ts b/src/core/manager.ts index 942cb55..d6d5063 100644 --- a/src/core/manager.ts +++ b/src/core/manager.ts @@ -68,6 +68,7 @@ class AtlasManager { try { console.log(`Parsing recipe.yml from ${repo}`); const recipeObject = yaml.load(recipeYaml) as VibRecipe; + recipeObject.snippet = recipeYaml; const modules: Module[] = []; if (recipeObject.modules) { diff --git a/src/core/models.ts b/src/core/models.ts index 256ff89..2699aca 100644 --- a/src/core/models.ts +++ b/src/core/models.ts @@ -30,6 +30,7 @@ interface VibRecipe { args: { [key: string]: string }; runs: string[]; modules: Module[]; + snippet: string; } export type { VibRecipe, Module, Source }; diff --git a/src/core/yaml-highlight.ts b/src/core/yaml-highlight.ts new file mode 100644 index 0000000..c1d6868 --- /dev/null +++ b/src/core/yaml-highlight.ts @@ -0,0 +1,14 @@ +import hljs from 'highlight.js/lib/core'; +import yaml from 'highlight.js/lib/languages/yaml'; +import 'highlight.js/styles/atom-one-dark.css'; + +hljs.registerLanguage('yaml', yaml); + +export default { + mounted(el: HTMLElement) { + const code = el.innerText; + const highlightedCode = hljs.highlight('yaml', code).value; + el.innerHTML = highlightedCode; + el.classList.add('hljs'); + }, +}; diff --git a/src/main.ts b/src/main.ts index 78c976b..837da52 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,11 +1,13 @@ import { createApp } from "vue"; import App from "./App.vue"; import router from "./router"; +import yamlHighlight from '@/core//yaml-highlight'; import "./assets/css/index.css"; const app = createApp(App); app.use(router); +app.directive('highlight-yaml', yamlHighlight); app.mount("#app"); diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index abc916e..8b778d4 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -1,20 +1,45 @@