multi-connections and basic settings

This commit is contained in:
Gabriel Pastori 2023-11-06 18:44:35 -03:00
parent 687d9a1402
commit 6a9e1c54d4
7 changed files with 363 additions and 26 deletions

View File

@ -21,6 +21,7 @@
</template>
<script>
import Options from "./settings/Options.vue";
import Webhook from "./settings/Webhook.vue";
import Websocket from "./settings/Websocket.vue";
import Rabbitmq from "./settings/Rabbitmq.vue";
@ -32,6 +33,7 @@ import MyChats from "./message/MyChats.vue";
import HasWhatsapp from "./message/HasWhatsapp.vue";
export default {
components: {
Options,
Webhook,
Websocket,
Rabbitmq,
@ -48,7 +50,7 @@ export default {
id: "settings",
icon: "mdi-cog",
title: "Configurações",
components: ["Webhook", "Websocket", "Rabbitmq", "Chatwoot", "Typebot"],
components: ["Options","Webhook", "Websocket", "Rabbitmq", "Chatwoot", "Typebot"],
},
{
id: "message",

View File

@ -0,0 +1,187 @@
<template>
<v-card variant="outlined" :loading="loading">
<v-card-title class="d-flex align-center">
<v-icon start>mdi-cellphone-cog</v-icon>
Comportamento
<v-spacer></v-spacer>
<v-btn
size="small"
icon
:disabled="loading"
variant="tonal"
@click="expanded = !expanded"
:style="{ transform: expanded ? 'rotate(180deg)' : '' }"
>
<v-icon>mdi-chevron-down</v-icon>
</v-btn>
</v-card-title>
<v-card-text v-if="expanded">
<v-alert v-if="error" type="error" class="mb-3">
{{ error }}
</v-alert>
<v-form v-model="valid">
<div class="d-flex align-center gap-4 flex-wrap">
<v-checkbox
class="flex-grow-0 flex-shrink-0"
v-model="optionsData.reject_call"
:disabled="loading"
label="Rejeitar chamadas"
hide-details
density="compact"
></v-checkbox>
<v-text-field
class="flex-grow-1 flex-shrink-0"
v-model="optionsData.msg_call"
:disabled="loading || !optionsData.reject_call"
label="Mensagem de rejeição"
hide-details
style="min-width: 200px"
></v-text-field>
</div>
<div class="d-flex gap-x-4 flex-wrap">
<v-checkbox
class="flex-grow-0"
v-model="optionsData.groups_ignore"
:disabled="loading"
label="Ignorar grupos"
hide-details
density="compact"
></v-checkbox>
<v-checkbox
class="flex-grow-0"
v-model="optionsData.always_online"
:disabled="loading"
label="Sempre online"
hide-details
density="compact"
></v-checkbox>
<v-checkbox
class="flex-grow-0"
v-model="optionsData.read_messages"
:disabled="loading"
label="Marcar mensagens como lidas"
hide-details
density="compact"
></v-checkbox>
<v-checkbox
class="flex-grow-0"
v-model="optionsData.read_status"
:disabled="loading"
label="Marcar status como visto"
hide-details
density="compact"
></v-checkbox>
</div>
</v-form>
</v-card-text>
<v-card-actions v-if="expanded">
<v-spacer></v-spacer>
<v-btn
:disabled="
!valid ||
JSON.stringify(optionsData) === JSON.stringify(defaultOptionsData)
"
:loading="loading"
color="primary"
@click="saveOptions"
variant="tonal"
>
Salvar
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
import instanceController from "@/services/instanceController";
const defaultOptions = () => ({
reject_call: false,
msg_call: "",
groups_ignore: false,
always_online: false,
read_messages: false,
read_status: false,
})
export default {
name: "InstanceOptions",
props: {
instance: {
type: Object,
required: true,
},
},
data: () => ({
expanded: false,
loading: false,
error: false,
valid: false,
optionsData: {
reject_call: false,
msg_call: "",
groups_ignore: false,
always_online: false,
read_messages: false,
read_status: false,
},
defaultOptionsData: {
reject_call: false,
msg_call: "",
groups_ignore: false,
always_online: false,
read_messages: false,
read_status: false,
},
}),
methods: {
async saveOptions() {
try {
this.loading = true;
this.error = false;
await instanceController.options.set(
this.instance.instance.instanceName,
this.optionsData
);
this.defaultOptionsData = Object.assign(defaultOptions(), this.optionsData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
async loadOptions() {
try {
this.loading = true;
this.error = false;
const optionsData = await instanceController.options.get(
this.instance.instance.instanceName
);
this.optionsData = Object.assign(defaultOptions(), optionsData);
this.defaultOptionsData = Object.assign(defaultOptions(), optionsData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
},
watch: {
expanded(val) {
if (val) this.loadOptions();
},
},
};
</script>
<style></style>

View File

@ -2,7 +2,6 @@
<v-dialog
v-model="dialog"
max-width="500px"
:persistent="!AppStore.validConnection"
>
<v-card>
<v-card-text class="d-flex flex-column gap-4">
@ -48,7 +47,6 @@
<v-card-actions>
<v-spacer></v-spacer>
<v-btn
v-if="AppStore.validConnection"
text
@click="dialog = false"
:disabled="loading"

View File

@ -1,5 +1,9 @@
<template>
<v-dialog v-model="dialog" max-width="500px" :persistent="!AppStore.validConnection">
<v-dialog
v-model="dialog"
max-width="500px"
:persistent="!AppStore.validConnection"
>
<v-card>
<v-card-text>
<v-form v-model="valid">
@ -31,12 +35,27 @@
</v-alert>
</v-card-text>
<v-card-actions>
<v-btn
v-if="!AppStore.connection.host === connection.host"
text
@click="dialog = false"
>
Cancel
</v-btn>
<v-spacer></v-spacer>
<v-btn v-if="AppStore.validConnection" text @click="dialog = false" :disabled="loading">Cancel</v-btn>
<v-btn
v-if="AppStore.validConnection"
text
@click="dialog = false"
:disabled="loading"
>
Cancel
</v-btn>
<v-btn
color="success"
variant="tonal"
@click="save"
@click="save()"
:disabled="!valid"
:loading="loading"
>
@ -44,6 +63,60 @@
</v-btn>
</v-card-actions>
</v-card>
<v-card class="mt-2" v-if="connectionsList && connectionsList.length > 1">
<v-card-text>
<h3 class="mb-4">Conexões salvas</h3>
<v-list>
<v-list-item
v-for="conect in connectionsList"
:key="conect.host"
:disabled="
loading ||
(conect.host === AppStore.connection.host &&
AppStore.validConnection)
"
@click="save(conect)"
>
<v-list-item-content>
<v-list-item-title>{{
conect.host.replace(/https?:\/\//, "")
}}</v-list-item-title>
<!-- <v-list-item-subtitle>
{{ connection.globalApiKey.slice(0, 10) }}...
</v-list-item-subtitle> -->
</v-list-item-content>
<template v-slot:append>
<v-btn
@click.stop="removeConnection(conect)"
icon
v-if="
conect.host !== AppStore.connection.host ||
!AppStore.validConnection
"
size="x-small"
variant="tonal"
color="error"
:disabled="loading"
>
<v-icon>mdi-delete</v-icon>
</v-btn>
<v-btn
icon
v-else
size="x-small"
variant="tonal"
color="success"
:disabled="loading"
>
<v-icon>mdi-check</v-icon>
</v-btn>
</template>
</v-list-item>
</v-list>
</v-card-text>
</v-card>
</v-dialog>
</template>
@ -65,12 +138,15 @@ export default {
AppStore: useAppStore(),
}),
methods: {
async save() {
removeConnection(connection) {
this.AppStore.removeConnection(connection);
},
async save(connection) {
try {
this.loading = true;
this.error = false;
await this.AppStore.setConnection(this.connection);
await this.AppStore.setConnection(connection || this.connection);
this.dialog = false;
} catch (e) {
this.error = e.message?.message || e.message || e;
@ -80,10 +156,15 @@ export default {
},
open() {
this.dialog = true;
this.connection = this.AppStore.connection;
this.connection = Object.assign({}, this.AppStore.connection);
},
},
computed: {
connectionsList() {
return this.AppStore.connectionsList;
},
},
emits: ["close"],
};
</script>

View File

@ -1,6 +1,32 @@
import http from "../http-common";
const findOptions = async (instanceName) => {
return await http
.get("/settings/find/:instance", {
params: {
instance: instanceName
}
})
.then((r) => r.data)
.catch((error) => {
throw error.response?.data || error.response || error;
});
}
const setOptions = async (instanceName, data) => {
return await http
.post("/settings/set/:instance", data, {
params: {
instance: instanceName
}
})
.then((r) => r.data)
.catch((error) => {
throw error.response?.data || error.response || error;
});
}
const findWebhook = async (instanceName) => {
return await http
.get("/webhook/find/:instance", {
@ -115,7 +141,14 @@ const setTypebot = async (instanceName, data) => {
});
}
export default {
options: {
get: findOptions,
set: setOptions,
},
webhook: {
get: findWebhook,
set: setWebhook,

View File

@ -23,6 +23,9 @@ export const useAppStore = defineStore('app', {
},
instancesKeys: {},
instancesList: [],
// lista de "contatos" de conexoes
connectionsList: [],
}),
actions: {
@ -51,16 +54,16 @@ export const useAppStore = defineStore('app', {
async loadInstance(instanceName) {
try {
const { host, globalApiKey } = this.connection;
const response = await axios({
method: 'GET',
baseURL: host,
headers: {
'Content-Type': 'application/json',
'apikey': globalApiKey
},
url: `/instance/fetchInstances?instanceName=${instanceName}`
})
return this.reconnect()
// const response = await axios({
// method: 'GET',
// baseURL: host,
// headers: {
// 'Content-Type': 'application/json',
// 'apikey': globalApiKey
// },
// url: `/instance/fetchInstances?instanceName=${instanceName}`
// })
} catch (e) {
this.connection.valid = false
@ -71,6 +74,9 @@ export const useAppStore = defineStore('app', {
async reconnect() {
try {
const { host, globalApiKey } = this.connection
if (!host || !globalApiKey) {
throw new Error('Invalid connection')
}
const response = await axios({
method: 'GET',
baseURL: host,
@ -101,28 +107,54 @@ export const useAppStore = defineStore('app', {
this.instancesKeys[instance] = key
},
removeConnection({ host }) {
const currentKey = this.connectionsList.findIndex(
(item) => item.host === host
)
if (currentKey !== -1)
this.connectionsList.splice(currentKey, 1)
this.saveLocalStorage()
},
saveConnection({ host, globalApiKey }) {
this.connection = {
valid: true,
host,
globalApiKey,
}
const currentKey = this.connectionsList.findIndex(
(item) => item.host === host
)
if (currentKey === -1) {
this.connectionsList.push({ host, globalApiKey })
} else {
this.connectionsList[currentKey] = { host, globalApiKey }
}
this.saveLocalStorage()
},
saveLocalStorage() {
if (typeof window !== 'undefined') {
window.localStorage.setItem('connection', JSON.stringify({
host,
globalApiKey,
}))
window.localStorage.setItem('connection', JSON.stringify(this.connection))
window.localStorage.setItem('connectionsList', JSON.stringify(this.connectionsList))
}
},
async loadConnection() {
if (typeof window !== 'undefined') {
const connectionsList = window.localStorage.getItem('connectionsList')
if (connectionsList) {
this.connectionsList = JSON.parse(connectionsList || '[]')
}
const connection = window.localStorage.getItem('connection')
if (connection) {
this.connection = JSON.parse(connection)
this.connection = JSON.parse(connection || '{}')
return this.reconnect()
}
}
}
},
}
})

View File

@ -39,7 +39,11 @@ export default {
}
},
},
watch: {},
watch: {
instance(val, oldVal) {
if (!val && oldVal) this.$router.push("/");
},
},
computed: {
instance() {