mirror of
https://github.com/EvolutionAPI/evolution-manager.git
synced 2025-12-24 05:07:44 -06:00
first commit
This commit is contained in:
7
src/App.vue
Normal file
7
src/App.vue
Normal file
@@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
//
|
||||
</script>
|
||||
BIN
src/assets/logo.png
Normal file
BIN
src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
6
src/assets/logo.svg
Normal file
6
src/assets/logo.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M261.126 140.65L164.624 307.732L256.001 466L377.028 256.5L498.001 47H315.192L261.126 140.65Z" fill="#1697F6"/>
|
||||
<path d="M135.027 256.5L141.365 267.518L231.64 111.178L268.731 47H256H14L135.027 256.5Z" fill="#AEDDFF"/>
|
||||
<path d="M315.191 47C360.935 197.446 256 466 256 466L164.624 307.732L315.191 47Z" fill="#1867C0"/>
|
||||
<path d="M268.731 47C76.0026 47 141.366 267.518 141.366 267.518L268.731 47Z" fill="#7BC6FF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 526 B |
75
src/components/HelloWorld.vue
Normal file
75
src/components/HelloWorld.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<v-container class="fill-height">
|
||||
<v-responsive class="align-center text-center fill-height">
|
||||
<v-img height="300" src="@/assets/logo.svg" />
|
||||
|
||||
<div class="text-body-2 font-weight-light mb-n1">Welcome to</div>
|
||||
|
||||
<h1 class="text-h2 font-weight-bold">Vuetify</h1>
|
||||
|
||||
<div class="py-14" />
|
||||
|
||||
<v-row class="d-flex align-center justify-center">
|
||||
<v-col cols="auto">
|
||||
<v-btn
|
||||
href="https://vuetifyjs.com/components/all/"
|
||||
min-width="164"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
variant="text"
|
||||
>
|
||||
<v-icon
|
||||
icon="mdi-view-dashboard"
|
||||
size="large"
|
||||
start
|
||||
/>
|
||||
|
||||
Components
|
||||
</v-btn>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="auto">
|
||||
<v-btn
|
||||
color="primary"
|
||||
href="https://vuetifyjs.com/introduction/why-vuetify/#feature-guides"
|
||||
min-width="228"
|
||||
rel="noopener noreferrer"
|
||||
size="x-large"
|
||||
target="_blank"
|
||||
variant="flat"
|
||||
>
|
||||
<v-icon
|
||||
icon="mdi-speedometer"
|
||||
size="large"
|
||||
start
|
||||
/>
|
||||
|
||||
Get Started
|
||||
</v-btn>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="auto">
|
||||
<v-btn
|
||||
href="https://community.vuetifyjs.com/"
|
||||
min-width="164"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
variant="text"
|
||||
>
|
||||
<v-icon
|
||||
icon="mdi-account-group"
|
||||
size="large"
|
||||
start
|
||||
/>
|
||||
|
||||
Community
|
||||
</v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-responsive>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
//
|
||||
</script>
|
||||
116
src/components/modal/CreateInstance.vue
Normal file
116
src/components/modal/CreateInstance.vue
Normal file
@@ -0,0 +1,116 @@
|
||||
<template>
|
||||
<v-dialog
|
||||
v-model="dialog"
|
||||
max-width="500px"
|
||||
:persistent="!AppStore.validConnection"
|
||||
>
|
||||
<v-card>
|
||||
<v-card-text>
|
||||
<v-form v-model="valid">
|
||||
<h3 class="mb-4">Criar instancia</h3>
|
||||
<v-text-field
|
||||
v-model="instance.instanceName"
|
||||
label="Nome"
|
||||
required
|
||||
outlined
|
||||
:rules="[
|
||||
// Verify is not have any caracter except letters, numbers, _ and -
|
||||
(v) =>
|
||||
new RegExp('^[a-zA-Z0-9_-]*$', 'i').test(v) ||
|
||||
'Nome inválido (apenas letras, números, _ e -)',
|
||||
]"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="instance.apiKey"
|
||||
label="API Key"
|
||||
required
|
||||
outlined
|
||||
@click:prepend-inner="generateApiKey"
|
||||
prepend-inner-icon="mdi-lock-reset"
|
||||
:rules="[
|
||||
// Verify is not have any caracter except letters, numbers, _ and -
|
||||
(v) =>
|
||||
new RegExp('^[a-zA-Z0-9_-]*$', 'i').test(v) ||
|
||||
'Nome inválido (apenas letras, números, _ e -)',
|
||||
]"
|
||||
/>
|
||||
</v-form>
|
||||
|
||||
<v-alert type="error" v-if="error">
|
||||
{{ Array.isArray(error) ? error.join(", ") : error }}
|
||||
</v-alert>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
v-if="AppStore.validConnection"
|
||||
text
|
||||
@click="dialog = false"
|
||||
:disabled="loading"
|
||||
>
|
||||
Cancel
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="success"
|
||||
variant="tonal"
|
||||
@click="save"
|
||||
:disabled="!valid"
|
||||
:loading="loading"
|
||||
>
|
||||
Conectar
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import instanceController from "@/services/instanceController";
|
||||
import { useAppStore } from "@/store/app";
|
||||
|
||||
export default {
|
||||
name: "SettingsModal",
|
||||
data: () => ({
|
||||
dialog: false,
|
||||
valid: false,
|
||||
instance: {
|
||||
instanceName: "",
|
||||
apiKey: "",
|
||||
},
|
||||
loading: false,
|
||||
error: false,
|
||||
AppStore: useAppStore(),
|
||||
}),
|
||||
methods: {
|
||||
generateApiKey() {
|
||||
this.instance.apiKey =
|
||||
Math.random().toString(36).substring(2, 15) +
|
||||
Math.random().toString(36).substring(2, 15);
|
||||
},
|
||||
async save() {
|
||||
try {
|
||||
this.loading = true;
|
||||
this.error = false;
|
||||
|
||||
const instance = await instanceController.create(this.instance);
|
||||
|
||||
this.$router.push({
|
||||
name: "instance",
|
||||
params: { id: instance.instance.instanceName },
|
||||
});
|
||||
|
||||
} catch (e) {
|
||||
this.error = e.message?.message || e.message || e;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
open() {
|
||||
this.dialog = true;
|
||||
this.generateApiKey();
|
||||
},
|
||||
},
|
||||
|
||||
emits: ["close"],
|
||||
};
|
||||
</script>
|
||||
89
src/components/modal/Settings.vue
Normal file
89
src/components/modal/Settings.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<v-dialog v-model="dialog" max-width="500px" :persistent="!AppStore.validConnection">
|
||||
<v-card>
|
||||
<v-card-text>
|
||||
<v-form v-model="valid">
|
||||
<h3 class="mb-4">Configurar conexão</h3>
|
||||
<v-text-field
|
||||
v-model="connection.host"
|
||||
label="URL"
|
||||
required
|
||||
outlined
|
||||
:rules="[
|
||||
// regex to verify is has http or https
|
||||
(v) =>
|
||||
new RegExp('^(http|https)://', 'i').test(v) || 'URL inválida',
|
||||
]"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="connection.globalApiKey"
|
||||
label="Global API Key"
|
||||
required
|
||||
outlined
|
||||
:type="revelPassword ? 'text' : 'password'"
|
||||
:append-inner-icon="revelPassword ? 'mdi-eye' : 'mdi-eye-off'"
|
||||
@click:append-inner="revelPassword = !revelPassword"
|
||||
/>
|
||||
</v-form>
|
||||
|
||||
<v-alert type="error" v-if="error">
|
||||
{{ Array.isArray(error) ? error.join(", ") : error }}
|
||||
</v-alert>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn v-if="AppStore.validConnection" text @click="dialog = false" :disabled="loading">Cancel</v-btn>
|
||||
<v-btn
|
||||
color="success"
|
||||
variant="tonal"
|
||||
@click="save"
|
||||
:disabled="!valid"
|
||||
:loading="loading"
|
||||
>
|
||||
Conectar
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useAppStore } from "@/store/app";
|
||||
|
||||
export default {
|
||||
name: "SettingsModal",
|
||||
data: () => ({
|
||||
dialog: false,
|
||||
valid: false,
|
||||
revelPassword: false,
|
||||
connection: {
|
||||
host: "",
|
||||
globalApiKey: "",
|
||||
},
|
||||
loading: false,
|
||||
error: false,
|
||||
AppStore: useAppStore(),
|
||||
}),
|
||||
methods: {
|
||||
async save() {
|
||||
try {
|
||||
this.loading = true;
|
||||
this.error = false;
|
||||
|
||||
await this.AppStore.setConnection(this.connection);
|
||||
this.dialog = false;
|
||||
} catch (e) {
|
||||
this.error = e.message?.message || e.message || e;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
open() {
|
||||
this.dialog = true;
|
||||
this.connection = this.AppStore.connection;
|
||||
},
|
||||
},
|
||||
|
||||
emits: ["close"],
|
||||
};
|
||||
</script>
|
||||
12
src/helpers/mappers/status.js
Normal file
12
src/helpers/mappers/status.js
Normal file
@@ -0,0 +1,12 @@
|
||||
export default {
|
||||
close: {
|
||||
color: "red",
|
||||
text: "Desconectado",
|
||||
icon: "mdi-close-circle",
|
||||
},
|
||||
open: {
|
||||
color: "green",
|
||||
text: "Conectado",
|
||||
icon: "mdi-check-circle",
|
||||
},
|
||||
}
|
||||
23
src/http-common.js
Normal file
23
src/http-common.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import axios from "axios";
|
||||
import { useAppStore } from "@/store/app";
|
||||
const appStore = useAppStore();
|
||||
|
||||
appStore
|
||||
|
||||
const http = axios.create({
|
||||
headers: {
|
||||
"Content-type": "application/json"
|
||||
}
|
||||
});
|
||||
|
||||
http.interceptors.request.use(
|
||||
config => {
|
||||
config.baseURL = appStore.connection.host;
|
||||
config.headers["apikey"] = appStore.connection.globalApiKey;
|
||||
|
||||
return config;
|
||||
},
|
||||
error => Promise.reject(error)
|
||||
);
|
||||
|
||||
export default http;
|
||||
40
src/layouts/default/AppBar.vue
Normal file
40
src/layouts/default/AppBar.vue
Normal file
@@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<v-app-bar flat>
|
||||
<v-app-bar-title>
|
||||
<v-icon icon="mdi-whatsapp" left />
|
||||
Evolution Manager
|
||||
</v-app-bar-title>
|
||||
|
||||
<v-icon v-if="AppStore.validConnection" color="success">
|
||||
mdi-check-circle
|
||||
</v-icon>
|
||||
<v-icon v-else color="error"> mdi-alert-circle </v-icon>
|
||||
<v-btn @click="openSettings" icon>
|
||||
<v-icon>mdi-cog</v-icon>
|
||||
</v-btn>
|
||||
</v-app-bar>
|
||||
<SettingsModal ref="settings" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SettingsModal from "@/components/modal/Settings.vue";
|
||||
import { useAppStore } from "@/store/app";
|
||||
|
||||
export default {
|
||||
name: "AppBar",
|
||||
data: () => ({
|
||||
AppStore: useAppStore(),
|
||||
}),
|
||||
components: {
|
||||
SettingsModal,
|
||||
},
|
||||
methods: {
|
||||
openSettings() {
|
||||
this.$refs.settings.open();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (!this.AppValidConnection) this.openSettings();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
12
src/layouts/default/Default.vue
Normal file
12
src/layouts/default/Default.vue
Normal file
@@ -0,0 +1,12 @@
|
||||
<template>
|
||||
<v-app>
|
||||
<default-bar />
|
||||
|
||||
<default-view />
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import DefaultBar from './AppBar.vue'
|
||||
import DefaultView from './View.vue'
|
||||
</script>
|
||||
11
src/layouts/default/View.vue
Normal file
11
src/layouts/default/View.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<v-main>
|
||||
<v-container>
|
||||
<router-view />
|
||||
</v-container>
|
||||
</v-main>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
//
|
||||
</script>
|
||||
20
src/main.js
Normal file
20
src/main.js
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* main.js
|
||||
*
|
||||
* Bootstraps Vuetify and other plugins then mounts the App`
|
||||
*/
|
||||
|
||||
// Components
|
||||
import App from './App.vue'
|
||||
|
||||
// Composables
|
||||
import { createApp } from 'vue'
|
||||
|
||||
// Plugins
|
||||
import { registerPlugins } from '@/plugins'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
registerPlugins(app)
|
||||
|
||||
app.mount('#app')
|
||||
17
src/plugins/index.js
Normal file
17
src/plugins/index.js
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* plugins/index.js
|
||||
*
|
||||
* Automatically included in `./src/main.js`
|
||||
*/
|
||||
|
||||
// Plugins
|
||||
import vuetify from './vuetify'
|
||||
import pinia from '../store'
|
||||
import router from '../router'
|
||||
|
||||
export function registerPlugins (app) {
|
||||
app
|
||||
.use(vuetify)
|
||||
.use(router)
|
||||
.use(pinia)
|
||||
}
|
||||
39
src/plugins/vuetify.js
Normal file
39
src/plugins/vuetify.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* plugins/vuetify.js
|
||||
*
|
||||
* Framework documentation: https://vuetifyjs.com`
|
||||
*/
|
||||
|
||||
// Styles
|
||||
import '@mdi/font/css/materialdesignicons.css'
|
||||
import 'vuetify/styles'
|
||||
|
||||
// Composables
|
||||
import { createVuetify } from 'vuetify'
|
||||
|
||||
|
||||
// Labs features
|
||||
import {
|
||||
VDataTable,
|
||||
VDataTableServer,
|
||||
VDataTableVirtual,
|
||||
} from "vuetify/labs/VDataTable";
|
||||
|
||||
// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides
|
||||
export default createVuetify({
|
||||
components: {
|
||||
VDataTable,
|
||||
VDataTableServer,
|
||||
VDataTableVirtual,
|
||||
},
|
||||
theme: {
|
||||
themes: {
|
||||
light: {
|
||||
colors: {
|
||||
primary: '#1867C0',
|
||||
secondary: '#5CBBF6',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
29
src/router/index.js
Normal file
29
src/router/index.js
Normal file
@@ -0,0 +1,29 @@
|
||||
// Composables
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('@/layouts/default/Default.vue'),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'instances',
|
||||
component: () => import(/* webpackChunkName: "home" */ '@/views/Home.vue'),
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
name: 'instance',
|
||||
component: () => import('@/views/Instance.vue'),
|
||||
}
|
||||
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(process.env.BASE_URL),
|
||||
routes,
|
||||
})
|
||||
|
||||
export default router
|
||||
26
src/services/instanceController.js
Normal file
26
src/services/instanceController.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import http from "../http-common";
|
||||
|
||||
|
||||
const fetchAll = async () => {
|
||||
return await http
|
||||
.get("/instance/fetchInstances")
|
||||
.then((r) => r.data)
|
||||
.catch((error) => {
|
||||
throw error.response?.data || error.response || error;
|
||||
});
|
||||
};
|
||||
|
||||
const create = async (data) => {
|
||||
return await http
|
||||
.post("/instance/create", data)
|
||||
.then((r) => r.data)
|
||||
.catch((error) => {
|
||||
throw error.response?.data || error.response || error;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
fetchAll,
|
||||
create
|
||||
};
|
||||
65
src/store/app.js
Normal file
65
src/store/app.js
Normal file
@@ -0,0 +1,65 @@
|
||||
// Utilities
|
||||
import axios from 'axios'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useAppStore = defineStore('app', {
|
||||
getters: {
|
||||
validConnection: (state) => state.connection.valid,
|
||||
instances: (state) => state.instancesList,
|
||||
},
|
||||
state: () => ({
|
||||
connection: {
|
||||
valid: false,
|
||||
host: null,
|
||||
globalApiKey: null,
|
||||
},
|
||||
instancesList: [],
|
||||
}),
|
||||
|
||||
actions: {
|
||||
async setConnection({ host, globalApiKey }) {
|
||||
try {
|
||||
const responde = await axios({
|
||||
method: 'GET',
|
||||
baseURL: host,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': globalApiKey
|
||||
},
|
||||
url: '/instance/fetchInstances'
|
||||
})
|
||||
|
||||
this.connection.valid = true
|
||||
this.connection.host = host
|
||||
this.connection.globalApiKey = globalApiKey
|
||||
this.instancesList = responde.data
|
||||
} catch (e) {
|
||||
this.connection.valid = false
|
||||
throw e.response?.data?.response?.message || e.response || e
|
||||
|
||||
}
|
||||
},
|
||||
async reconnect() {
|
||||
try {
|
||||
const { host, globalApiKey } = this.connection
|
||||
const responde = await axios({
|
||||
method: 'GET',
|
||||
baseURL: host,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': globalApiKey
|
||||
},
|
||||
url: '/instance/fetchInstances'
|
||||
})
|
||||
|
||||
this.connection.valid = true
|
||||
this.connection.host = host
|
||||
this.connection.globalApiKey = globalApiKey
|
||||
this.instancesList = responde.data
|
||||
} catch (e) {
|
||||
this.connection.valid = false
|
||||
throw e.response?.data?.response?.message || e.response || e
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
4
src/store/index.js
Normal file
4
src/store/index.js
Normal file
@@ -0,0 +1,4 @@
|
||||
// Utilities
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
export default createPinia()
|
||||
10
src/styles/settings.scss
Normal file
10
src/styles/settings.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* src/styles/settings.scss
|
||||
*
|
||||
* Configures SASS variables and Vuetify overwrites
|
||||
*/
|
||||
|
||||
// https://vuetifyjs.com/features/sass-variables/`
|
||||
// @use 'vuetify/settings' with (
|
||||
// $color-pack: false
|
||||
// );
|
||||
141
src/views/Home.vue
Normal file
141
src/views/Home.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="d-flex mb-4 align-center">
|
||||
<h3>Instancias</h3>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
:disabled="loading"
|
||||
@click="getInstances"
|
||||
icon
|
||||
variant="text"
|
||||
size="small"
|
||||
class="mr-2"
|
||||
>
|
||||
<v-icon>mdi-refresh</v-icon>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="primary"
|
||||
variant="tonal"
|
||||
@click="addInstance"
|
||||
:disabled="loading"
|
||||
>
|
||||
<v-icon>mdi-plus</v-icon>
|
||||
<span class="ml-2">Instancia</span>
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<v-card v-if="!loading && instances?.length === 0" variant="outlined">
|
||||
<v-card-text>
|
||||
<div class="text-center">
|
||||
<v-icon size="70">mdi-server-network-off</v-icon>
|
||||
<h3 class="mt-4">Nenhuma instância encontrada</h3>
|
||||
</div>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
|
||||
<v-data-table
|
||||
v-if="!instances || instances?.length > 0"
|
||||
:headers="headers"
|
||||
:items="instances || []"
|
||||
:loading="loading"
|
||||
:items-per-page="10"
|
||||
>
|
||||
<!-- eslint-disable-next-line vue/valid-v-slot -->
|
||||
<template v-slot:item.instance.status="{ item }">
|
||||
<v-chip
|
||||
:color="statusMapper[item.instance.status].color"
|
||||
:text-color="statusMapper[item.instance.status].textColor"
|
||||
size="small"
|
||||
label
|
||||
>
|
||||
<v-icon
|
||||
v-if="statusMapper[item.instance.status].icon"
|
||||
start
|
||||
size="small"
|
||||
>
|
||||
{{ statusMapper[item.instance.status].icon }}
|
||||
</v-icon>
|
||||
{{ statusMapper[item.instance.status].text }}
|
||||
</v-chip>
|
||||
</template>
|
||||
<template v-slot:item.actions="{ item }">
|
||||
<v-btn
|
||||
:disabled="loading"
|
||||
:to="`/${item.instance.instanceName}`"
|
||||
icon
|
||||
variant="text"
|
||||
size="small"
|
||||
class="mr-2"
|
||||
>
|
||||
<v-icon>mdi-pencil</v-icon>
|
||||
</v-btn>
|
||||
<!-- <v-btn
|
||||
:disabled="loading"
|
||||
@click="AppStore.selectInstance(item.instance)"
|
||||
icon
|
||||
variant="text"
|
||||
size="small"
|
||||
>
|
||||
<v-icon>mdi-delete</v-icon>
|
||||
</v-btn> -->
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
||||
<v-alert v-if="error" type="error">
|
||||
{{ error }}
|
||||
</v-alert>
|
||||
</div>
|
||||
<CreateInstance ref="createInstanceModal" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useAppStore } from "@/store/app";
|
||||
import CreateInstance from "@/components/modal/CreateInstance";
|
||||
import statusMapper from "@/helpers/mappers/status";
|
||||
|
||||
export default {
|
||||
name: "HomeInstance",
|
||||
components: {
|
||||
CreateInstance,
|
||||
},
|
||||
data: () => ({
|
||||
AppStore: useAppStore(),
|
||||
loading: false,
|
||||
error: false,
|
||||
statusMapper: statusMapper,
|
||||
headers: [
|
||||
{
|
||||
title: "Nome",
|
||||
align: "start",
|
||||
sortable: true,
|
||||
key: "instance.instanceName",
|
||||
},
|
||||
{ title: "Status", key: "instance.status" },
|
||||
{ title: "Ações", key: "actions", sortable: false , align: "center"},
|
||||
],
|
||||
}),
|
||||
methods: {
|
||||
addInstance() {
|
||||
this.$refs.createInstanceModal.open();
|
||||
},
|
||||
async getInstances() {
|
||||
try {
|
||||
this.loading = true;
|
||||
this.instances = await this.AppStore.reconnect();
|
||||
} catch (e) {
|
||||
this.error = e.message?.message || e.message || e;
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {},
|
||||
computed: {
|
||||
instances() {
|
||||
return this.AppStore.instances;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
52
src/views/Instance.vue
Normal file
52
src/views/Instance.vue
Normal file
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<v-alert v-if="error" type="error">
|
||||
{{ error }}
|
||||
</v-alert>
|
||||
<div v-else-if="instance">
|
||||
<v-card variant="outlined" class="d-flex align-center">
|
||||
<v-avatar size="100">
|
||||
<v-icon v-if="statusMapper[instance.instance.status].icon" size="70">
|
||||
{{ statusMapper[instance.instance.status].icon }}
|
||||
</v-icon>
|
||||
</v-avatar>
|
||||
<div>
|
||||
<h2>{{ instance.instance.instanceName }}</h2>
|
||||
</div>
|
||||
</v-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useAppStore } from "@/store/app";
|
||||
import statusMapper from "@/helpers/mappers/status";
|
||||
|
||||
export default {
|
||||
name: "HomeInstance",
|
||||
data: () => ({
|
||||
AppStore: useAppStore(),
|
||||
loading: true,
|
||||
error: false,
|
||||
instance: null,
|
||||
statusMapper: statusMapper,
|
||||
}),
|
||||
methods: {
|
||||
async loadInstance() {
|
||||
if (!this.AppStore.instances) await this.AppStore.reconnect();
|
||||
const instances = this.AppStore.instances;
|
||||
const instance = instances.find(
|
||||
(instance) => instance.instance.instanceName === this.$route.params.id
|
||||
);
|
||||
if (!instance) {
|
||||
this.error = "Instância não encontrada";
|
||||
return;
|
||||
}
|
||||
this.instance = instance;
|
||||
},
|
||||
},
|
||||
watch: {},
|
||||
async mounted() {
|
||||
if (this.AppStore.validConnection) this.loadInstance();
|
||||
else this.$router.push({ name: "instances" });
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user