feat: plugin management (#583)
* chore: remove unnecessary files Signed-off-by: Ryan Wang <i@ryanc.cc> * feat: plugin management Signed-off-by: Ryan Wang <i@ryanc.cc> * feat: refine plugin detail page Signed-off-by: Ryan Wang <i@ryanc.cc> * feat: refine plugin detail page Signed-off-by: Ryan Wang <i@ryanc.cc> * fix: theme plugin router link Signed-off-by: Ryan Wang <i@ryanc.cc> * Update src/modules/system/plugins/PluginList.vue Co-authored-by: John Niang <johnniang@fastmail.com> * feat: plugin detail page support start/stop plugin Signed-off-by: Ryan Wang <i@ryanc.cc> Co-authored-by: John Niang <johnniang@fastmail.com>pull/588/head
|
@ -29,6 +29,7 @@
|
|||
"@halo-dev/admin-shared": "workspace:*",
|
||||
"@halo-dev/components": "workspace:*",
|
||||
"@vueuse/core": "^8.6.0",
|
||||
"axios": "^0.27.2",
|
||||
"filepond": "^4.30.4",
|
||||
"filepond-plugin-image-preview": "^4.6.11",
|
||||
"floating-vue": "2.0.0-beta.16",
|
||||
|
|
|
@ -18,7 +18,7 @@ const handleChange = () => {
|
|||
<button
|
||||
:class="{
|
||||
'bg-gray-200': !modelValue,
|
||||
'bg-themeable-primary-600': modelValue,
|
||||
'!bg-themeable-primary-600': modelValue,
|
||||
}"
|
||||
aria-checked="false"
|
||||
class="switch-inner"
|
||||
|
|
|
@ -21,6 +21,7 @@ importers:
|
|||
'@vue/tsconfig': ^0.1.3
|
||||
'@vueuse/core': ^8.6.0
|
||||
autoprefixer: ^10.4.7
|
||||
axios: ^0.27.2
|
||||
c8: ^7.11.3
|
||||
cypress: ^9.7.0
|
||||
eslint: ^8.17.0
|
||||
|
@ -60,6 +61,7 @@ importers:
|
|||
'@halo-dev/admin-shared': link:packages/shared
|
||||
'@halo-dev/components': link:packages/components
|
||||
'@vueuse/core': 8.6.0_vue@3.2.37
|
||||
axios: 0.27.2
|
||||
filepond: 4.30.4
|
||||
filepond-plugin-image-preview: 4.6.11_filepond@4.30.4
|
||||
floating-vue: 2.0.0-beta.16_vue@3.2.37
|
||||
|
@ -2751,6 +2753,15 @@ packages:
|
|||
- debug
|
||||
dev: false
|
||||
|
||||
/axios/0.27.2:
|
||||
resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
|
||||
dependencies:
|
||||
follow-redirects: 1.14.9
|
||||
form-data: 4.0.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/babel-plugin-dynamic-import-node/2.3.3:
|
||||
resolution: {integrity: sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==}
|
||||
dependencies:
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<svg role="img" viewBox="0 0 24 24" fill="#5468FF" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Algolia</title>
|
||||
<path
|
||||
d="M3.16 0A3.156 3.156 0 000 3.152v17.69A3.161 3.161 0 003.16 24h17.68c1.747 0 3.16-1.42 3.16-3.16V3.16C24 1.413 22.58 0 20.84 0H3.16zm7.87 3.494h2.429A1.04 1.04 0 0114.5 4.535v.822a.14.14 0 01-.174.14 7.679 7.647 0 00-2.043-.276 7.564 7.533 0 00-2.113.297c-.095.021-.182-.045-.182-.14v-.843a1.044 1.04 0 011.041-1.04zm-4.35 2.22a1.04 1.035 0 01.75.306l.414.416c.058.065.051.167-.022.21a7.544 7.513 0 00-.941.801 8 7.967 0 00-.793.932c-.058.065-.153.08-.219.016l-.408-.409a1.043 1.04 0 010-1.472l.496-.494a1.04 1.035 0 01.723-.305zm5.597.35a6.774 6.774 0 016.787 6.778 6.784 6.784 0 01-6.787 6.783c-3.748 0-6.789-3.028-6.789-6.777a6.786 6.786 0 016.79-6.784zm0 2.008a4.783 4.783 0 00-4.783 4.776 4.783 4.783 0 004.783 4.775 4.777 4.777 0 004.784-4.775 4.782 4.782 0 00-4.784-4.776zm.145.838a3.935 3.919 0 013.281 1.988c.036.073.015.16-.057.196l-3.166 1.638c-.093.052-.205-.023-.205-.125V9.05h.002c0-.08.072-.139.145-.139Z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.0 KiB |
|
@ -1,5 +0,0 @@
|
|||
<svg role="img" viewBox="0 0 24 24" fill="#ff6a00" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Alibaba Cloud</title>
|
||||
<path
|
||||
d="M3.996 4.517h5.291L8.01 6.324 4.153 7.506a1.668 1.668 0 0 0-1.165 1.601v5.786a1.668 1.668 0 0 0 1.165 1.6l3.857 1.183 1.277 1.807H3.996A3.996 3.996 0 0 1 0 15.487V8.513a3.996 3.996 0 0 1 3.996-3.996m16.008 0h-5.291l1.277 1.807 3.857 1.182c.715.227 1.17.889 1.165 1.601v5.786a1.668 1.668 0 0 1-1.165 1.6l-3.857 1.183-1.277 1.807h5.291A3.996 3.996 0 0 0 24 15.487V8.513a3.996 3.996 0 0 0-3.996-3.996m-4.007 8.345H8.002v-1.804h7.995Z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 574 B |
|
@ -1 +0,0 @@
|
|||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Amazon AWS</title><path d="M6.763 10.036c0 .296.032.535.088.71.064.176.144.368.256.576.04.063.056.127.056.183 0 .08-.048.16-.152.24l-.503.335a.383.383 0 0 1-.208.072c-.08 0-.16-.04-.239-.112a2.47 2.47 0 0 1-.287-.375 6.18 6.18 0 0 1-.248-.471c-.622.734-1.405 1.101-2.347 1.101-.67 0-1.205-.191-1.596-.574-.391-.384-.59-.894-.59-1.533 0-.678.239-1.23.726-1.644.487-.415 1.133-.623 1.955-.623.272 0 .551.024.846.064.296.04.6.104.918.176v-.583c0-.607-.127-1.03-.375-1.277-.255-.248-.686-.367-1.3-.367-.28 0-.568.031-.863.103-.295.072-.583.16-.862.272a2.287 2.287 0 0 1-.28.104.488.488 0 0 1-.127.023c-.112 0-.168-.08-.168-.247v-.391c0-.128.016-.224.056-.28a.597.597 0 0 1 .224-.167c.279-.144.614-.264 1.005-.36a4.84 4.84 0 0 1 1.246-.151c.95 0 1.644.216 2.091.647.439.43.662 1.085.662 1.963v2.586zm-3.24 1.214c.263 0 .534-.048.822-.144.287-.096.543-.271.758-.51.128-.152.224-.32.272-.512.047-.191.08-.423.08-.694v-.335a6.66 6.66 0 0 0-.735-.136 6.02 6.02 0 0 0-.75-.048c-.535 0-.926.104-1.19.32-.263.215-.39.518-.39.917 0 .375.095.655.295.846.191.2.47.296.838.296zm6.41.862c-.144 0-.24-.024-.304-.08-.064-.048-.12-.16-.168-.311L7.586 5.55a1.398 1.398 0 0 1-.072-.32c0-.128.064-.2.191-.2h.783c.151 0 .255.025.31.08.065.048.113.16.16.312l1.342 5.284 1.245-5.284c.04-.16.088-.264.151-.312a.549.549 0 0 1 .32-.08h.638c.152 0 .256.025.32.08.063.048.12.16.151.312l1.261 5.348 1.381-5.348c.048-.16.104-.264.16-.312a.52.52 0 0 1 .311-.08h.743c.127 0 .2.065.2.2 0 .04-.009.08-.017.128a1.137 1.137 0 0 1-.056.2l-1.923 6.17c-.048.16-.104.263-.168.311a.51.51 0 0 1-.303.08h-.687c-.151 0-.255-.024-.32-.08-.063-.056-.119-.16-.15-.32l-1.238-5.148-1.23 5.14c-.04.16-.087.264-.15.32-.065.056-.177.08-.32.08zm10.256.215c-.415 0-.83-.048-1.229-.143-.399-.096-.71-.2-.918-.32-.128-.071-.215-.151-.247-.223a.563.563 0 0 1-.048-.224v-.407c0-.167.064-.247.183-.247.048 0 .096.008.144.024.048.016.12.048.2.08.271.12.566.215.878.279.319.064.63.096.95.096.502 0 .894-.088 1.165-.264a.86.86 0 0 0 .415-.758.777.777 0 0 0-.215-.559c-.144-.151-.416-.287-.807-.415l-1.157-.36c-.583-.183-1.014-.454-1.277-.813a1.902 1.902 0 0 1-.4-1.158c0-.335.073-.63.216-.886.144-.255.335-.479.575-.654.24-.184.51-.32.83-.415.32-.096.655-.136 1.006-.136.175 0 .359.008.535.032.183.024.35.056.518.088.16.04.312.08.455.127.144.048.256.096.336.144a.69.69 0 0 1 .24.2.43.43 0 0 1 .071.263v.375c0 .168-.064.256-.184.256a.83.83 0 0 1-.303-.096 3.652 3.652 0 0 0-1.532-.311c-.455 0-.815.071-1.062.223-.248.152-.375.383-.375.71 0 .224.08.416.24.567.159.152.454.304.877.44l1.134.358c.574.184.99.44 1.237.767.247.327.367.702.367 1.117 0 .343-.072.655-.207.926-.144.272-.336.511-.583.703-.248.2-.543.343-.886.447-.36.111-.734.167-1.142.167zM21.698 16.207c-2.626 1.94-6.442 2.969-9.722 2.969-4.598 0-8.74-1.7-11.87-4.526-.247-.223-.024-.527.272-.351 3.384 1.963 7.559 3.153 11.877 3.153 2.914 0 6.114-.607 9.06-1.852.439-.2.814.287.383.607zM22.792 14.961c-.336-.43-2.22-.207-3.074-.103-.255.032-.295-.192-.063-.36 1.5-1.053 3.967-.75 4.254-.399.287.36-.08 2.826-1.485 4.007-.215.184-.423.088-.327-.151.32-.79 1.03-2.57.695-2.994z"/></svg>
|
Before Width: | Height: | Size: 3.1 KiB |
|
@ -1,5 +0,0 @@
|
|||
<svg role="img" viewBox="0 0 24 24" fill="#005571" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>Elasticsearch</title>
|
||||
<path
|
||||
d="M13.394 0C8.683 0 4.609 2.716 2.644 6.667h15.641a4.77 4.77 0 0 0 3.073-1.11c.446-.375.864-.785 1.247-1.243l.001-.002A11.974 11.974 0 0 0 13.394 0zM1.804 8.889a12.009 12.009 0 0 0 0 6.222h14.7a3.111 3.111 0 1 0 0-6.222zm.84 8.444C4.61 21.283 8.684 24 13.395 24c3.701 0 7.011-1.677 9.212-4.312l-.001-.002a9.958 9.958 0 0 0-1.247-1.243 4.77 4.77 0 0 0-3.073-1.11z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 504 B |
|
@ -1,5 +0,0 @@
|
|||
<svg role="img" viewBox="0 0 24 24" fill="#181717" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>GitHub</title>
|
||||
<path
|
||||
d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 849 B |
Before Width: | Height: | Size: 458 KiB |
|
@ -1 +0,0 @@
|
|||
<svg role="img" viewBox="0 0 24 24" fill="#DC382D" xmlns="http://www.w3.org/2000/svg"><title>Redis</title><path d="M10.5 2.661l.54.997-1.797.644 2.409.218.748 1.246.467-1.121 2.077-.208-1.61-.613.426-1.017-1.578.519zm6.905 2.077L13.76 6.182l3.292 1.298.353-.146 3.293-1.298zm-10.51.312a2.97 1.153 0 0 0-2.97 1.152 2.97 1.153 0 0 0 2.97 1.153 2.97 1.153 0 0 0 2.97-1.153 2.97 1.153 0 0 0-2.97-1.152zM24 6.805s-8.983 4.278-10.395 4.953c-1.226.561-1.901.561-3.261.094C8.318 11.022 0 7.241 0 7.241v1.038c0 .24.332.499.966.8 1.277.613 8.34 3.677 9.45 4.206 1.112.53 1.9.54 3.313-.197 1.412-.738 8.049-3.905 9.326-4.57.654-.342.945-.602.945-.84zm-10.042.602L8.39 8.26l3.884 1.61zM24 10.637s-8.983 4.279-10.395 4.954c-1.226.56-1.901.56-3.261.093C8.318 14.854 0 11.074 0 11.074v1.038c0 .238.332.498.966.8 1.277.612 8.34 3.676 9.45 4.205 1.112.53 1.9.54 3.313-.197 1.412-.737 8.049-3.905 9.326-4.57.654-.332.945-.602.945-.84zm0 3.842l-10.395 4.954c-1.226.56-1.901.56-3.261.094C8.318 18.696 0 14.916 0 14.916v1.038c0 .239.332.499.966.8 1.277.613 8.34 3.676 9.45 4.206 1.112.53 1.9.54 3.313-.198 1.412-.737 8.049-3.904 9.326-4.569.654-.343.945-.613.945-.841z"/></svg>
|
Before Width: | Height: | Size: 1.1 KiB |
|
@ -1 +0,0 @@
|
|||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>W3C</title><path d="M23.642 5.602l-.931 1.858s-.4-.738-.795-1.076c-.377-.322-.864-.62-1.48-.556-.597.062-1.27.587-1.722 1.46-.513.994-.688 2.001-.692 3.112-.005 1.556.57 2.618.57 2.618s-.132-.494-.11-1.33c.014-.52.017-1.089.41-2.261.33-.98 1.084-1.775 1.75-1.912.517-.107.847-.03 1.356.329.603.425.966 1.193.966 1.193l.946-1.81zM0 5.674l3.77 12.723h.156l2.356-7.886 2.357 7.886h.157l3.228-10.895.152-.258h2.655l-2.2 3.802v.754h.629c.806 0 1.398.246 1.775.738.324.42.487 1.011.487 1.776 0 .691-.152 1.283-.455 1.775-.304.492-.676.738-1.116.738-.419 0-.783-.138-1.092-.416-.308-.277-.557-.657-.746-1.139l-1.288.534c.261.796.665 1.427 1.21 1.893.544.466 1.183.699 1.916.699.974 0 1.767-.393 2.38-1.178.613-.785.919-1.754.919-2.906 0-.932-.21-1.743-.628-2.435-.42-.69-1.037-1.167-1.854-1.43l2.326-4.006v-.77h-6.177L8.64 13.419 6.362 5.674h-1.65l.754 2.529-1.54 5.215L1.65 5.674zm17.44 8.88s.233.755.379 1.076c.084.185.342.75.708 1.24.341.46 1.004 1.248 2.011 1.426 1.008.178 1.7-.274 1.871-.384.172-.11.533-.412.761-.657.239-.255.465-.58.59-.775.091-.143.24-.432.24-.432l-.241-1.255s-.418.748-.678 1.036c-.261.288-.727.794-1.302 1.048-.576.253-.877.302-1.446.247-.569-.054-1.097-.383-1.282-.52-.185-.138-.658-.542-.925-.92-.268-.376-.686-1.13-.686-1.13z"/></svg>
|
Before Width: | Height: | Size: 1.3 KiB |
|
@ -1,5 +0,0 @@
|
|||
<svg role="img" viewBox="0 0 24 24" fill="#07C160" xmlns="http://www.w3.org/2000/svg">
|
||||
<title>WeChat</title>
|
||||
<path
|
||||
d="M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 0 1 .213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 0 0 .167-.054l1.903-1.114a.864.864 0 0 1 .717-.098 10.16 10.16 0 0 0 2.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-4.972 1.932-6.446 1.703-1.415 3.882-1.98 5.853-1.838-.576-3.583-4.196-6.348-8.596-6.348zM5.785 5.991c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178A1.17 1.17 0 0 1 4.623 7.17c0-.651.52-1.18 1.162-1.18zm5.813 0c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178 1.17 1.17 0 0 1-1.162-1.178c0-.651.52-1.18 1.162-1.18zm5.34 2.867c-1.797-.052-3.746.512-5.28 1.786-1.72 1.428-2.687 3.72-1.78 6.22.942 2.453 3.666 4.229 6.884 4.229.826 0 1.622-.12 2.361-.336a.722.722 0 0 1 .598.082l1.584.926a.272.272 0 0 0 .14.047c.134 0 .24-.111.24-.247 0-.06-.023-.12-.038-.177l-.327-1.233a.582.582 0 0 1-.023-.156.49.49 0 0 1 .201-.398C23.024 18.48 24 16.82 24 14.98c0-3.21-2.931-5.837-6.656-6.088V8.89c-.135-.01-.27-.027-.407-.03zm-2.53 3.274c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.97-.982zm4.844 0c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.969-.982z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.3 KiB |
37
src/main.ts
|
@ -10,6 +10,9 @@ import { registerMenu } from "@/router/menus.config";
|
|||
|
||||
// core modules
|
||||
import { coreModules } from "./modules";
|
||||
import { useScriptTag } from "@vueuse/core";
|
||||
import { usePluginStore } from "@/stores/plugin";
|
||||
import axiosInstance from "@/utils/api-client";
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
|
@ -58,8 +61,37 @@ function loadCoreModules() {
|
|||
coreModules.forEach(registerModule);
|
||||
}
|
||||
|
||||
const pluginStore = usePluginStore();
|
||||
|
||||
async function loadPluginModules() {
|
||||
// TODO: load plugin modules
|
||||
const response = await axiosInstance.get(
|
||||
`/apis/plugin.halo.run/v1alpha1/plugins`
|
||||
);
|
||||
|
||||
// Get all started plugins
|
||||
const plugins = response.data.filter(
|
||||
(plugin) => plugin.status.phase === "STARTED" && plugin.spec.enabled
|
||||
);
|
||||
|
||||
for (const plugin of plugins) {
|
||||
const { entry } = plugin.status;
|
||||
|
||||
if (entry) {
|
||||
const { load } = useScriptTag(
|
||||
`http://localhost:8090${plugin.status.entry}`
|
||||
);
|
||||
await load();
|
||||
const pluginModule = window[plugin.metadata.name];
|
||||
|
||||
if (pluginModule) {
|
||||
// @ts-ignore
|
||||
plugin.spec.module = pluginModule;
|
||||
registerModule(pluginModule);
|
||||
}
|
||||
}
|
||||
|
||||
pluginStore.registerPlugin(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
(async function () {
|
||||
|
@ -72,7 +104,8 @@ async function initApp() {
|
|||
await loadPluginModules();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
} finally {
|
||||
app.use(router);
|
||||
app.mount("#app");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
} from "@halo-dev/components";
|
||||
import { ref } from "vue";
|
||||
import { users } from "@/modules/system/users/users-mock";
|
||||
import halo from "@/assets/logo-mock/halo.png";
|
||||
import halo from "@/assets/logo.svg";
|
||||
|
||||
const sheetsRef = ref([
|
||||
{
|
||||
|
|
|
@ -249,7 +249,7 @@ const handleChangeTheme = (theme: any) => {
|
|||
<RouterLink
|
||||
:to="{
|
||||
name: 'PluginDetail',
|
||||
params: { id: 'run.halo.plugins.links' },
|
||||
params: { pluginName: 'PluginLinks' },
|
||||
}"
|
||||
class="font-medium text-gray-900 hover:text-blue-400"
|
||||
>
|
||||
|
|
|
@ -5,31 +5,59 @@ import {
|
|||
VInput,
|
||||
VPageHeader,
|
||||
VSpace,
|
||||
VSwitch,
|
||||
VTabbar,
|
||||
VTag,
|
||||
} from "@halo-dev/components";
|
||||
import { useRoute } from "vue-router";
|
||||
import { plugins } from "./plugins-mock";
|
||||
import { ref } from "vue";
|
||||
import { computed, ref } from "vue";
|
||||
import type { Plugin } from "./types";
|
||||
import axiosInstance from "@/utils/api-client";
|
||||
|
||||
const pluginActiveId = ref("detail");
|
||||
const plugin = ref<Plugin>();
|
||||
|
||||
const { params } = useRoute();
|
||||
|
||||
const plugin = plugins.find((item) => {
|
||||
return item.spec.pluginClass === params.id;
|
||||
const handleFetchPlugin = async () => {
|
||||
try {
|
||||
const response = await axiosInstance.get(
|
||||
`/apis/plugin.halo.run/v1alpha1/plugins/${params.pluginName}`
|
||||
);
|
||||
plugin.value = response.data;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
const isStarted = computed(() => {
|
||||
return plugin.value?.status.phase === "STARTED" && plugin.value?.spec.enabled;
|
||||
});
|
||||
|
||||
console.log(plugin);
|
||||
const handleChangePluginStatus = async () => {
|
||||
try {
|
||||
await axiosInstance.put(
|
||||
`/apis/plugin.halo.run/v1alpha1/plugins/${plugin.value?.metadata.name}/${
|
||||
isStarted.value ? "stop" : "startup"
|
||||
}`
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
handleFetchPlugin();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VPageHeader :title="plugin.metadata.name">
|
||||
<VPageHeader :title="plugin?.spec?.displayName">
|
||||
<template #icon>
|
||||
<img :src="plugin.spec.logo" class="mr-2 h-8 w-8" />
|
||||
<img :src="plugin?.spec?.logo" class="mr-2 h-8 w-8" />
|
||||
</template>
|
||||
<template #actions>
|
||||
<VButton class="opacity-0" type="secondary"> 安装</VButton>
|
||||
<VButton class="opacity-0" type="secondary">安装</VButton>
|
||||
</template>
|
||||
</VPageHeader>
|
||||
|
||||
|
@ -48,17 +76,27 @@ console.log(plugin);
|
|||
</template>
|
||||
|
||||
<div v-if="pluginActiveId === 'detail'">
|
||||
<div class="px-4 py-4 sm:px-6">
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900">插件信息</h3>
|
||||
<div class="flex items-center justify-between px-4 py-4 sm:px-6">
|
||||
<div>
|
||||
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
||||
插件信息
|
||||
</h3>
|
||||
<p
|
||||
class="mt-1 flex max-w-2xl items-center gap-2 text-sm text-gray-500"
|
||||
>
|
||||
<span>{{ plugin.spec.version }}</span>
|
||||
<span>{{ plugin?.spec?.version }}</span>
|
||||
<VTag>
|
||||
{{ plugin.metadata.enabled ? "已启用" : "未启用" }}
|
||||
{{ isStarted ? "已启用" : "未启用" }}
|
||||
</VTag>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<VSwitch
|
||||
:model-value="isStarted"
|
||||
@change="handleChangePluginStatus"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="border-t border-gray-200">
|
||||
<dl class="divide-y divide-gray-100">
|
||||
<div
|
||||
|
@ -66,19 +104,7 @@ console.log(plugin);
|
|||
>
|
||||
<dt class="text-sm font-medium text-gray-900">名称</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||
{{ plugin.metadata.name }}
|
||||
</dd>
|
||||
</div>
|
||||
<div
|
||||
class="bg-white px-4 py-5 hover:bg-gray-50 sm:grid sm:grid-cols-6 sm:gap-4 sm:px-6"
|
||||
>
|
||||
<dt class="text-sm font-medium text-gray-900">插件类别</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||
<VTag>
|
||||
extensions.halo.run/category/{{
|
||||
plugin.metadata.labels["extensions.halo.run/category"]
|
||||
}}
|
||||
</VTag>
|
||||
{{ plugin?.spec?.displayName }}
|
||||
</dd>
|
||||
</div>
|
||||
<div
|
||||
|
@ -86,7 +112,7 @@ console.log(plugin);
|
|||
>
|
||||
<dt class="text-sm font-medium text-gray-900">版本</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||
{{ plugin.spec.version }}
|
||||
{{ plugin?.spec?.version }}
|
||||
</dd>
|
||||
</div>
|
||||
<div
|
||||
|
@ -94,7 +120,7 @@ console.log(plugin);
|
|||
>
|
||||
<dt class="text-sm font-medium text-gray-900">Halo 版本要求</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||
{{ plugin.spec.requires }}
|
||||
{{ plugin?.spec?.requires }}
|
||||
</dd>
|
||||
</div>
|
||||
<div
|
||||
|
@ -102,8 +128,8 @@ console.log(plugin);
|
|||
>
|
||||
<dt class="text-sm font-medium text-gray-900">提供方</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||
<a :href="plugin.spec.homepage" target="_blank">
|
||||
@{{ plugin.spec.author }}
|
||||
<a :href="plugin?.spec?.homepage" target="_blank">
|
||||
{{ plugin?.spec?.author }}
|
||||
</a>
|
||||
</dd>
|
||||
</div>
|
||||
|
@ -112,7 +138,22 @@ console.log(plugin);
|
|||
>
|
||||
<dt class="text-sm font-medium text-gray-900">协议</dt>
|
||||
<dd class="mt-1 text-sm text-gray-900 sm:col-span-2 sm:mt-0">
|
||||
{{ plugin.spec.license }}
|
||||
<ul
|
||||
v-if="plugin?.spec?.license && plugin?.spec?.license.length"
|
||||
class="list-inside list-disc"
|
||||
>
|
||||
<li
|
||||
v-for="(license, index) in plugin.spec.license"
|
||||
:key="index"
|
||||
>
|
||||
<a v-if="license.url" :href="license.url" target="_blank">
|
||||
{{ license.name }}
|
||||
</a>
|
||||
<span>
|
||||
{{ license.name }}
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</div>
|
||||
<div
|
||||
|
@ -120,9 +161,9 @@ console.log(plugin);
|
|||
>
|
||||
<dt class="text-sm font-medium text-gray-900">模型定义</dt>
|
||||
<dd class="mt-1 sm:col-span-2 sm:mt-0">
|
||||
<ul v-if="plugin.extensions" class="space-y-2">
|
||||
<ul v-if="plugin?.extensions" class="space-y-2">
|
||||
<li
|
||||
v-for="(extension, index) in plugin.extensions"
|
||||
v-for="(extension, index) in plugin?.extensions"
|
||||
:key="index"
|
||||
>
|
||||
<div
|
||||
|
|
|
@ -9,23 +9,56 @@ import {
|
|||
VInput,
|
||||
VPageHeader,
|
||||
VSpace,
|
||||
VSwitch,
|
||||
VTag,
|
||||
} from "@halo-dev/components";
|
||||
import { ref } from "vue";
|
||||
import { onMounted, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { plugins } from "./plugins-mock";
|
||||
import type { Plugin } from "./types";
|
||||
import axiosInstance from "@/utils/api-client";
|
||||
|
||||
const checkAll = ref(false);
|
||||
const plugins = ref<Plugin[]>([]);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
// eslint-disable-next-line
|
||||
const handleRouteToDetail = (plugin: any) => {
|
||||
const handleRouteToDetail = (plugin: Plugin) => {
|
||||
router.push({
|
||||
name: "PluginDetail",
|
||||
params: { id: plugin.spec.pluginClass },
|
||||
params: { pluginName: plugin.metadata.name },
|
||||
});
|
||||
};
|
||||
|
||||
function isStarted(plugin: Plugin) {
|
||||
return plugin.status.phase === "STARTED" && plugin.spec.enabled;
|
||||
}
|
||||
|
||||
const handleFetchPlugins = async () => {
|
||||
try {
|
||||
const response = await axiosInstance.get(
|
||||
`/apis/plugin.halo.run/v1alpha1/plugins`
|
||||
);
|
||||
plugins.value = response.data;
|
||||
} catch (e) {
|
||||
console.error("Fail to fetch plugins", e);
|
||||
}
|
||||
};
|
||||
|
||||
const handleChangePluginStatus = async (plugin: Plugin) => {
|
||||
try {
|
||||
await axiosInstance.put(
|
||||
`/apis/plugin.halo.run/v1alpha1/plugins/${plugin.metadata.name}/${
|
||||
isStarted(plugin) ? "stop" : "startup"
|
||||
}`
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(handleFetchPlugins);
|
||||
</script>
|
||||
<template>
|
||||
<VPageHeader title="插件">
|
||||
|
@ -187,11 +220,7 @@ const handleRouteToDetail = (plugin: any) => {
|
|||
</div>
|
||||
</template>
|
||||
<ul class="box-border h-full w-full divide-y divide-gray-100" role="list">
|
||||
<li
|
||||
v-for="(plugin, index) in plugins"
|
||||
:key="index"
|
||||
@click.stop="handleRouteToDetail(plugin)"
|
||||
>
|
||||
<li v-for="(plugin, index) in plugins" :key="index">
|
||||
<div
|
||||
:class="{
|
||||
'bg-gray-100': checkAll,
|
||||
|
@ -223,12 +252,15 @@ const handleRouteToDetail = (plugin: any) => {
|
|||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="flex flex-row items-center">
|
||||
<span class="mr-2 truncate text-sm font-medium text-gray-900">
|
||||
{{ plugin.metadata.name }}
|
||||
<span
|
||||
class="mr-2 truncate text-sm font-medium text-gray-900"
|
||||
@click.stop="handleRouteToDetail(plugin)"
|
||||
>
|
||||
{{ plugin.spec.displayName }}
|
||||
</span>
|
||||
<VSpace>
|
||||
<VTag>
|
||||
{{ plugin.metadata.enabled ? "已启用" : "未启用" }}
|
||||
{{ isStarted(plugin) ? "已启用" : "未启用" }}
|
||||
</VTag>
|
||||
</VSpace>
|
||||
</div>
|
||||
|
@ -258,10 +290,16 @@ const handleRouteToDetail = (plugin: any) => {
|
|||
{{ plugin.spec.version }}
|
||||
</span>
|
||||
<time class="text-sm text-gray-500" datetime="2020-01-07">
|
||||
2020-01-07
|
||||
{{ plugin.metadata.creationTimestamp }}
|
||||
</time>
|
||||
<div class="flex items-center">
|
||||
<VSwitch
|
||||
:model-value="isStarted(plugin)"
|
||||
@click="handleChangePluginStatus(plugin)"
|
||||
/>
|
||||
</div>
|
||||
<span class="cursor-pointer">
|
||||
<IconSettings />
|
||||
<IconSettings @click.stop="handleRouteToDetail(plugin)" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -18,7 +18,7 @@ export default definePlugin({
|
|||
component: PluginList,
|
||||
},
|
||||
{
|
||||
path: ":id",
|
||||
path: ":pluginName",
|
||||
name: "PluginDetail",
|
||||
component: PluginDetail,
|
||||
},
|
||||
|
|
|
@ -1,301 +0,0 @@
|
|||
import alibabacloud from "@/assets/logo-mock/alibabacloud.svg";
|
||||
import amazonaws from "@/assets/logo-mock/amazonaws.svg";
|
||||
import w3c from "@/assets/logo-mock/w3c.svg";
|
||||
import halo from "@/assets/logo-mock/halo.png";
|
||||
import wechat from "@/assets/logo-mock/wechat.svg";
|
||||
import github from "@/assets/logo-mock/github.svg";
|
||||
import redis from "@/assets/logo-mock/redis.svg";
|
||||
import elasticsearch from "@/assets/logo-mock/elasticsearch.svg";
|
||||
import algolia from "@/assets/logo-mock/algolia.svg";
|
||||
|
||||
export const plugins = [
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "阿里云 OSS",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "attachment",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: alibabacloud,
|
||||
pluginClass: "run.halo.plugins.OSS",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-oss",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "阿里云 OSS 的上传选项,可同步文件以及上传",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "Amazon S3",
|
||||
enabled: false,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "attachment",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: amazonaws,
|
||||
pluginClass: "run.halo.plugins.s3",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-s3",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "Amazon S3 对象存储的上传选项,可同步文件以及上传",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "OpenGraph Generator",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "common",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "Ryan Wang",
|
||||
logo: w3c,
|
||||
pluginClass: "run.halo.plugins.opengraph-gen",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-opengraph-gen",
|
||||
shortDescription: "this is a test plugin",
|
||||
description:
|
||||
"自动为文章页面添加 OpenGraph 标签,并支持配置生成 OpenGraph 图片",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "富文本编辑器",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "editor",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: halo,
|
||||
pluginClass: "run.halo.plugins.richtext-editor",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-richtext-editor",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "Halo 官方提供的富文本编辑器",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "友情链接",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "page",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: halo,
|
||||
pluginClass: "run.halo.plugins.links",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-links",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "友情链接管理模块",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "图库",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "page",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: halo,
|
||||
pluginClass: "run.halo.plugins.photos",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-photos",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "图库管理模块",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "社区",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "page",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: halo,
|
||||
pluginClass: "run.halo.plugins.forum",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-forum",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "提供一个社区/论坛应有的所有模块",
|
||||
license: "GPL V3",
|
||||
},
|
||||
extensions: [
|
||||
{
|
||||
name: "posts",
|
||||
displayName: "帖子",
|
||||
fields: ["id", "title", "content", "author", "createdAt"],
|
||||
},
|
||||
{
|
||||
name: "discussions",
|
||||
displayName: "评论",
|
||||
fields: ["id", "content", "author", "createdAt"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "微信公众号管理",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "common",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: wechat,
|
||||
pluginClass: "run.halo.plugins.wechat-channel",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-wechatchannel",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "托管微信公众号的管理,支持同步文章和管理媒体",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "GitHub OAuth",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "auth",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: github,
|
||||
pluginClass: "run.halo.plugins.github-oauth",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-github-oauth",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "允许用户通过 GitHub 账号登录",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "Redis Cache",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "cache",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: redis,
|
||||
pluginClass: "run.halo.plugins.redis-cache",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-redis-cache",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "支持使用 Redis 作为缓存",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "ElasticSearch",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "search-engine",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: elasticsearch,
|
||||
pluginClass: "run.halo.plugins.elasticsearch",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-elasticsearch",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "接入 ElasticSearch 作为全文搜索系统",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiVersion: "v1",
|
||||
kind: "Plugin",
|
||||
metadata: {
|
||||
name: "Algolia",
|
||||
enabled: true,
|
||||
labels: {
|
||||
"extensions.halo.run/category": "search-engine",
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
version: "1.0.0",
|
||||
requires: ">=2.0.0",
|
||||
author: "halo-dev",
|
||||
logo: algolia,
|
||||
pluginClass: "run.halo.plugins.algolia",
|
||||
pluginDependencies: {},
|
||||
homepage: "https://github.com/halo-dev/halo-plugin-algolia",
|
||||
shortDescription: "this is a test plugin",
|
||||
description: "接入 Algolia 作为全文搜索系统",
|
||||
license: "GPL V3",
|
||||
},
|
||||
},
|
||||
];
|
|
@ -0,0 +1,47 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface PluginDependencies {}
|
||||
|
||||
export interface License {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export interface Spec {
|
||||
displayName: string;
|
||||
version: string;
|
||||
author: string;
|
||||
logo: string;
|
||||
pluginDependencies: PluginDependencies;
|
||||
homepage: string;
|
||||
description: string;
|
||||
license: License[];
|
||||
requires: string;
|
||||
pluginClass: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface Metadata {
|
||||
name: string;
|
||||
version: number;
|
||||
creationTimestamp: Date;
|
||||
}
|
||||
|
||||
export interface Status {
|
||||
phase: string;
|
||||
entry?: string;
|
||||
stylesheet?: string;
|
||||
}
|
||||
|
||||
export interface Plugin {
|
||||
spec: Spec;
|
||||
apiVersion: string;
|
||||
kind: string;
|
||||
metadata: Metadata;
|
||||
status: Status;
|
||||
extensions: Extension[];
|
||||
}
|
||||
|
||||
export interface Extension {
|
||||
name: string;
|
||||
fields: string[];
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import { defineStore } from "pinia";
|
||||
|
||||
export const usePluginStore = defineStore("plugin", {
|
||||
state: () => ({
|
||||
plugins: [],
|
||||
}),
|
||||
actions: {
|
||||
registerPlugin(plugin) {
|
||||
// @ts-ignore
|
||||
this.plugins.push(plugin);
|
||||
},
|
||||
},
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
import axios from "axios";
|
||||
|
||||
const token =
|
||||
"eyJhbGciOiJSUzUxMiJ9.eyJpc3MiOiJIYWxvIE93bmVyIiwic3ViIjoiYWRtaW4iLCJleHAiOjE2NTU4OTQxNTQsImlhdCI6MTY1NTgwNzc1NCwic2NvcGUiOlsiUk9MRV9zdXBlci1yb2xlIl19.Gnj0rM8DU2bP1KcgKBUVaKf6zs1pDqGxYvii9zxG4lFv4rVZ_uNGXyfhi9V10vRK0GM4v4NEuMtX9-DYnqAV0wR2JcoFevPrJnHHWsvnFrOQm32qeMpew3PsZ5-YAwi9n8Y9GpAcQz_6aWsEuRwm9w5CC3A67CrYPfCK5qwuR5FFLfiMRqPAqNNuZ4r2IfoSZUvXy4HxhUS-01J2BCqP3-hbdN_-tFHCDxtIO637a51EsCmRItY5wSVNmwYPaPOYV7lbHxzBIKXw5RNXg6SrQCSLTVaaJCXsZjwIirk02RQACr6oqTHPbriBVuu-SIgPXS5PJ9i4VaMCn-z8t-oZlQ";
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
baseURL: "http://localhost:8090",
|
||||
});
|
||||
|
||||
export default axiosInstance;
|