muita coisa

This commit is contained in:
Gabriel Pastori
2023-11-05 00:41:04 -03:00
parent e0f6d28a88
commit 558545e469
23 changed files with 3005 additions and 2824 deletions

View File

@@ -0,0 +1,59 @@
<template>
<v-tabs>
<v-tab v-for="tab in tabs" :key="tab.id" :value="tab.id">
<v-icon start>{{ tab.icon }}</v-icon>
{{ tab.title }}
</v-tab>
</v-tabs>
<v-window v-model="tab">
<v-window-item v-for="tab in tabs" :key="tab.id" :value="tab.id" >
<div class="d-flex flex-column gap-8">
<component
v-for="component in tab.components"
:key="component"
:is="component"
:instance="instance"
/>
</div>
</v-window-item>
</v-window>
</template>
<script>
import Webhook from "./settings/webhook.vue";
import Websocket from "./settings/Websocket.vue";
import Rabbitmq from "./settings/Rabbitmq.vue";
import Chatwoot from "./settings/Chatwoot.vue";
import Typebot from "./settings/Typebot.vue";
export default {
components: {
Webhook,
Websocket,
Rabbitmq,
Chatwoot,
Typebot,
},
data: () => ({
tab: "settings",
tabs: [
{
id: "settings",
icon: "mdi-cog",
title: "Configurações",
components: ["Webhook", "Websocket", "Rabbitmq", "Chatwoot", "Typebot"],
},
],
}),
props: {
instance: {
type: Object,
required: true,
},
},
};
</script>
<style></style>

View File

@@ -0,0 +1,99 @@
<template>
<v-card
variant="outlined"
class="d-flex align-center gap-4 pa-2"
rounded="xl"
>
<v-avatar size="100" rounded="xl">
<v-icon
v-if="
instance.instance.status != 'open' &&
statusMapper[instance.instance.status].icon
"
size="70"
>
{{ statusMapper[instance.instance.status].icon }}
</v-icon>
<v-img
v-else
:src="
instance.instance.profilePictureUrl ||
'https://cdn.vuetifyjs.com/images/lists/1.jpg'
"
/>
</v-avatar>
<div class="d-flex flex-column">
<span class="text-overline" style="line-height: 1em">
{{ owner }}
</span>
<h2 class="mb-0">{{ instance.instance.instanceName }}</h2>
<small>{{ instance.instance.profileStatus }}</small>
</div>
<v-spacer></v-spacer>
<v-btn
@click="disconnectInstance"
:disabled="instance.instance.status === 'close'"
:loading="disconnect.loading"
variant="tonal"
color="error"
size="small"
>
<v-icon start>mdi-cellphone-nfc-off</v-icon>
{{ disconnect.confirm ? "Tem Certeza?" : "Desconectar" }}
</v-btn>
</v-card>
</template>
<script>
import { useAppStore } from "@/store/app";
import statusMapper from "@/helpers/mappers/status";
import instanceController from "@/services/instanceController";
export default {
name: "InstanceHeader",
data: () => ({
disconnect: {
confirm: false,
loading: false,
},
statusMapper: statusMapper,
AppStore: useAppStore(),
}),
methods: {
async disconnectInstance() {
if (!this.disconnect.confirm) return (this.disconnect.confirm = true);
this.disconnect.loading = true;
try {
this.disconnect.confirm = false;
await instanceController.logout(this.instance.instance.instanceName);
await this.AppStore.reconnect();
} catch (e) {
console.log(e);
alert(e.message || e.error || "Erro desconhecido");
} finally {
this.disconnect.loading = false;
}
},
},
computed: {
owner() {
if (!this.instance?.instance?.owner)
return (
this.statusMapper[this.instance.instance.status]?.text ||
"Desconhecido"
);
return (this.instance?.instance?.owner || "").split("@")[0];
},
},
props: {
instance: {
type: Object,
required: true,
},
},
};
</script>
<style></style>

View File

@@ -0,0 +1,220 @@
<template>
<v-card variant="outlined" :loading="loading">
<v-card-title class="d-flex align-center">
<v-icon start>mdi-chat</v-icon>
Chatwoot
<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">
<v-text-field
v-model="chatwootData.url"
label="URL"
:disabled="loading"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(url) => {
if (!url) return 'URL é obrigatório';
if (!url.startsWith('http'))
return 'URL deve começar com http ou https';
return true;
},
]"
/>
<div class="d-flex gap-4 flex-wrap">
<div class="flex-grow-1">
<v-text-field
v-model="chatwootData.account_id"
label="ID da conta"
:disabled="loading"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(account_id) => {
if (!account_id) return 'ID da conta é obrigatório';
return true;
},
]"
/>
</div>
<div class="flex-grow-1">
<v-text-field
v-model="chatwootData.token"
label="Token da conta"
:disabled="loading"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(token) => {
if (!token) return 'Token é obrigatório';
return true;
},
]"
/>
</div>
</div>
<div class="d-flex gap-x-4 flex-wrap">
<div>
<v-checkbox
v-model="chatwootData.sign_msg"
label="Assinar mensagens"
:disabled="loading"
hide-details
class="mb-3"
density="compact"
/>
</div>
<div>
<v-checkbox
v-model="chatwootData.reopen_conversation"
label="Reabrir conversa"
:disabled="loading"
hide-details
class="mb-3"
density="compact"
/>
</div>
<div>
<v-checkbox
v-model="chatwootData.conversation_pending"
label="Conversa pendente"
:disabled="loading"
hide-details
class="mb-3"
density="compact"
/>
</div>
</div>
</v-form>
</v-card-text>
<v-card-actions v-if="expanded">
<v-switch
v-model="chatwootData.enabled"
label="Habilitado"
color="primary"
:disabled="loading"
hide-details
></v-switch>
<v-spacer></v-spacer>
<v-btn
:disabled="
!valid ||
JSON.stringify(chatwootData) === JSON.stringify(defaultChatwootData)
"
:loading="loading"
color="primary"
@click="saveChatwoot"
variant="tonal"
>
Salvar
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
import instanceController from "@/services/instanceController";
export default {
name: "InstanceChatwoot",
props: {
instance: {
type: Object,
required: true,
},
},
data: () => ({
expanded: false,
loading: false,
error: false,
valid: false,
chatwootData: {
enabled: false,
url: "",
account_id: "",
token: "",
sign_msg: true,
reopen_conversation: true,
conversation_pending: false,
},
defaultChatwootData: {
enabled: false,
url: "",
account_id: "",
token: "",
sign_msg: true,
reopen_conversation: true,
conversation_pending: false,
},
}),
methods: {
async saveChatwoot() {
try {
this.loading = true;
this.error = false;
await instanceController.chatwoot.set(
this.instance.instance.instanceName,
{
...this.chatwootData,
url: this.chatwootData.url.trim().replace(/\/$/, ""),
}
);
this.defaultChatwootData = Object.assign({}, this.chatwootData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
async loadChatwoot() {
try {
this.loading = true;
this.error = false;
const chatwootData = await instanceController.chatwoot.get(
this.instance.instance.instanceName
);
this.chatwootData = Object.assign({}, chatwootData);
this.defaultChatwootData = Object.assign({}, chatwootData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
},
watch: {
expanded(expanded) {
if (expanded) this.loadChatwoot();
},
},
};
</script>
<style></style>

View File

@@ -0,0 +1,154 @@
<template>
<v-card variant="outlined" :loading="loading">
<v-card-title class="d-flex align-center">
<v-icon start>mdi-rabbit</v-icon>
RabbitMQ
<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">
<v-select
:items="rabbitmqEventsType"
v-model="rabbitmqData.events"
:disabled="loading"
label="Eventos"
hide-details
class="mb-3"
multiple
outlined
dense
chips
/>
</v-form>
</v-card-text>
<v-card-actions v-if="expanded">
<v-switch
v-model="rabbitmqData.enabled"
label="Habilitado"
color="primary"
:disabled="loading"
hide-details
></v-switch>
<v-spacer></v-spacer>
<v-btn
:disabled="
!valid ||
JSON.stringify(rabbitmqData) === JSON.stringify(defaultRabbitmqData)
"
:loading="loading"
color="primary"
@click="saveRabbitmq"
variant="tonal"
>
Salvar
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
import instanceController from "@/services/instanceController";
export default {
name: "InstanceRabbitmq",
props: {
instance: {
type: Object,
required: true,
},
},
data: () => ({
expanded: false,
loading: false,
error: false,
valid: false,
rabbitmqData: {
enabled: false,
events: [],
},
defaultRabbitmqData: {
enabled: false,
events: [],
},
rabbitmqEventsType: [
"APPLICATION_STARTUP",
"QRCODE_UPDATED",
"MESSAGES_SET",
"MESSAGES_UPSERT",
"MESSAGES_UPDATE",
"MESSAGES_DELETE",
"SEND_MESSAGE",
"CONTACTS_SET",
"CONTACTS_UPSERT",
"CONTACTS_UPDATE",
"PRESENCE_UPDATE",
"CHATS_SET",
"CHATS_UPSERT",
"CHATS_UPDATE",
"CHATS_DELETE",
"GROUPS_UPSERT",
"GROUP_UPDATE",
"GROUP_PARTICIPANTS_UPDATE",
"CONNECTION_UPDATE",
"CALL",
"NEW_JWT_TOKEN",
],
}),
methods: {
async saveRabbitmq() {
try {
this.loading = true;
this.error = false;
await instanceController.rabbitmq.set(
this.instance.instance.instanceName,
this.rabbitmqData
);
this.defaultRabbitmqData = Object.assign({}, this.rabbitmqData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
async loadRabbitmq() {
try {
this.loading = true;
this.error = false;
const rabbitmqData = await instanceController.rabbitmq.get(
this.instance.instance.instanceName
);
this.rabbitmqData = Object.assign({}, rabbitmqData);
this.defaultRabbitmqData = Object.assign({}, rabbitmqData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
},
mounted() {
this.loadRabbitmq();
},
};
</script>
<style></style>

View File

@@ -0,0 +1,252 @@
<template>
<v-card variant="outlined" :loading="loading">
<v-card-title class="d-flex align-center">
<v-icon start>mdi-robot-happy</v-icon>
Typebot
<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">
<v-text-field
v-model="typebotData.url"
label="URL"
:disabled="loading"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(url) => {
if (!url) return 'URL é obrigatório';
if (!url.startsWith('http'))
return 'URL deve começar com http ou https';
return true;
},
]"
/>
<div class="d-flex gap-4 flex-wrap">
<div class="flex-grow-1">
<v-text-field
v-model="typebotData.typebot"
label="Typebot"
:disabled="loading"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(account_id) => {
if (!account_id) return 'Typebot é obrigatório';
return true;
},
]"
/>
</div>
<div class="flex-grow-1">
<v-text-field
v-model="typebotData.keyword_finish"
label="Palavra-chave de finalização"
placeholder="#SAIR"
:disabled="loading"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(token) => {
if (!token)
return 'Palavra-chave de finalização é obrigatório';
return true;
},
]"
/>
</div>
</div>
<div class="d-flex gap-4 flex-wrap">
<div class="flex-grow-1">
<v-text-field
v-model="typebotData.expire"
label="Tempo de expiração (em minutos)"
:disabled="loading"
type="number"
min="0"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(v) => {
if (!v) return 'Tempo de expiração é obrigatório';
return true;
},
]"
/>
</div>
<div class="flex-grow-1">
<v-text-field
v-model="typebotData.delay_message"
label="Tempo de atraso da mensagem (em milisegundos)"
type="number"
min="0"
:hint="`${typebotData.delay_message}ms = ${(
typebotData.delay_message / 1000
)
.toFixed(1)
.replace('.0', '')}s`"
:disabled="loading"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(token) => {
if (token == null || token < 0)
return 'Palavra-chave de finalização é obrigatório';
return true;
},
]"
/>
</div>
</div>
<v-text-field
v-model="typebotData.unknown_message"
label="Mensagem de desconhecido"
:disabled="loading"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(token) => {
if (!token) return 'Mensagem de desconhecido é obrigatório';
return true;
},
]"
/>
</v-form>
</v-card-text>
<v-card-actions v-if="expanded">
<v-switch
v-model="typebotData.enabled"
label="Habilitado"
color="primary"
:disabled="loading"
hide-details
></v-switch>
<v-spacer></v-spacer>
<v-btn
:disabled="
!valid ||
JSON.stringify(typebotData) === JSON.stringify(defaultTypebotData)
"
:loading="loading"
color="primary"
@click="saveTypebot"
variant="tonal"
>
Salvar
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
import instanceController from "@/services/instanceController";
export default {
name: "InstanceTypebot",
props: {
instance: {
type: Object,
required: true,
},
},
data: () => ({
expanded: false,
loading: false,
error: false,
valid: false,
typebotData: {
enabled: false,
expire: 0,
sessions: [],
typebot: "",
url: "",
keyword_finish: "",
unknown_message: "",
},
defaultTypebotData: {
enabled: false,
expire: 0,
sessions: [],
typebot: "",
url: "",
keyword_finish: "",
unknown_message: "",
},
}),
methods: {
async saveTypebot() {
try {
this.loading = true;
this.error = false;
await instanceController.typebot.set(
this.instance.instance.instanceName,
{
...this.typebotData,
url: this.typebotData.url.trim().replace(/\/$/, ""),
}
);
this.defaultTypebotData = Object.assign({}, this.typebotData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
async loadTypebot() {
try {
this.loading = true;
this.error = false;
const typebotData = await instanceController.typebot.get(
this.instance.instance.instanceName
);
this.typebotData = Object.assign({}, typebotData);
this.defaultTypebotData = Object.assign({}, typebotData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
},
watch: {
expanded(expanded) {
if (expanded) this.loadTypebot();
},
},
};
</script>
<style></style>

View File

@@ -0,0 +1,204 @@
<template>
<v-card variant="outlined" :loading="loading">
<v-card-title class="d-flex align-center">
<v-icon start>mdi-webhook</v-icon>
Webhook
<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">
<v-text-field
v-model="webhookData.url"
label="URL"
:disabled="loading"
outlined
dense
hide-details="auto"
class="mb-3"
:rules="[
(url) => {
if (!url) return 'URL é obrigatório';
if (!url.startsWith('http'))
return 'URL deve começar com http ou https';
return true;
},
]"
/>
<v-select
:items="webhookEventsType"
v-model="webhookData.events"
:disabled="loading"
label="Eventos"
hide-details
class="mb-3"
multiple
outlined
dense
chips
/>
<div class="d-flex gap-x-4 flex-wrap align-center">
<div>
<v-checkbox
v-model="webhookData.webhook_base64"
:disabled="loading"
label="Webhook base64"
hide-details
class="mb-3"
density="compact"
/>
</div>
<div>
<v-checkbox
v-model="webhookData.webhook_by_events"
:disabled="loading"
label="Webhook por eventos"
hide-details
class="mb-3"
density="compact"
/>
</div>
</div>
</v-form>
</v-card-text>
<v-card-actions v-if="expanded">
<v-switch
v-model="webhookData.enabled"
label="Habilitado"
color="primary"
:disabled="loading"
hide-details
></v-switch>
<v-spacer></v-spacer>
<v-btn
:disabled="
!valid ||
JSON.stringify(webhookData) === JSON.stringify(defaultWebhookData)
"
:loading="loading"
color="primary"
@click="saveWebhook"
variant="tonal"
>
Salvar
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
import instanceController from "@/services/instanceController";
export default {
name: "InstanceWebhook",
props: {
instance: {
type: Object,
required: true,
},
},
data: () => ({
expanded: false,
loading: false,
error: false,
valid: false,
webhookData: {
enabled: false,
events: [],
url: "",
webhook_base64: false,
webhook_by_events: false,
},
defaultWebhookData: {
enabled: false,
events: [],
url: "",
webhook_base64: false,
webhook_by_events: false,
},
webhookEventsType: [
"APPLICATION_STARTUP",
"QRCODE_UPDATED",
"MESSAGES_SET",
"MESSAGES_UPSERT",
"MESSAGES_UPDATE",
"MESSAGES_DELETE",
"SEND_MESSAGE",
"CONTACTS_SET",
"CONTACTS_UPSERT",
"CONTACTS_UPDATE",
"PRESENCE_UPDATE",
"CHATS_SET",
"CHATS_UPSERT",
"CHATS_UPDATE",
"CHATS_DELETE",
"GROUPS_UPSERT",
"GROUP_UPDATE",
"GROUP_PARTICIPANTS_UPDATE",
"CONNECTION_UPDATE",
"CALL",
"NEW_JWT_TOKEN",
],
}),
methods: {
async saveWebhook() {
try {
this.loading = true;
this.error = false;
await instanceController.webhook.set(
this.instance.instance.instanceName,
{
...this.webhookData,
url: this.webhookData.url.trim().replace(/\/$/, ""),
}
);
this.defaultWebhookData = Object.assign({}, this.webhookData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
async loadWebhook() {
try {
this.loading = true;
this.error = false;
const webhookData = await instanceController.webhook.get(
this.instance.instance.instanceName
);
this.webhookData = Object.assign({}, webhookData);
this.defaultWebhookData = Object.assign({}, webhookData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
},
watch: {
expanded(expanded) {
if (expanded) this.loadWebhook();
},
},
};
</script>
<style></style>

View File

@@ -0,0 +1,157 @@
<template>
<v-card variant="outlined" :loading="loading">
<v-card-title class="d-flex align-center">
<v-icon start>mdi-email-fast</v-icon>
Websocket
<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">
<v-select
:items="websocketEventsType"
v-model="websocketData.events"
:disabled="loading"
label="Eventos"
hide-details
class="mb-3"
multiple
outlined
dense
chips
/>
</v-form>
</v-card-text>
<v-card-actions v-if="expanded">
<v-switch
v-model="websocketData.enabled"
label="Habilitado"
color="primary"
:disabled="loading"
hide-details
></v-switch>
<v-spacer></v-spacer>
<v-btn
:disabled="
!valid ||
JSON.stringify(websocketData) === JSON.stringify(defaultWebsocketData)
"
:loading="loading"
color="primary"
@click="saveWebsocket"
variant="tonal"
>
Salvar
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
import instanceController from "@/services/instanceController";
export default {
name: "InstanceWebsocket",
props: {
instance: {
type: Object,
required: true,
},
},
data: () => ({
expanded: false,
loading: false,
error: false,
valid: false,
websocketData: {
enabled: false,
events: [],
},
defaultWebsocketData: {
enabled: false,
events: [],
},
websocketEventsType: [
"APPLICATION_STARTUP",
"QRCODE_UPDATED",
"MESSAGES_SET",
"MESSAGES_UPSERT",
"MESSAGES_UPDATE",
"MESSAGES_DELETE",
"SEND_MESSAGE",
"CONTACTS_SET",
"CONTACTS_UPSERT",
"CONTACTS_UPDATE",
"PRESENCE_UPDATE",
"CHATS_SET",
"CHATS_UPSERT",
"CHATS_UPDATE",
"CHATS_DELETE",
"GROUPS_UPSERT",
"GROUP_UPDATE",
"GROUP_PARTICIPANTS_UPDATE",
"CONNECTION_UPDATE",
"CALL",
"NEW_JWT_TOKEN",
],
}),
methods: {
async saveWebsocket() {
try {
this.loading = true;
this.error = false;
await instanceController.websocket.set(
this.instance.instance.instanceName,
this.websocketData
);
this.defaultWebsocketData = Object.assign({}, this.websocketData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
async loadWebsocket() {
try {
this.loading = true;
this.error = false;
const websocketData = await instanceController.websocket.get(
this.instance.instance.instanceName
);
this.websocketData = Object.assign({}, websocketData);
this.defaultWebsocketData = Object.assign({}, websocketData);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
},
watch: {
expanded: {
handler() {
if (this.expanded) this.loadWebsocket();
},
},
},
};
</script>
<style></style>

View File

@@ -0,0 +1,99 @@
<template>
<v-alert
icon="mdi-qrcode-scan"
v-if="instance.instance?.status != 'open'"
type="warning"
>
<div class="d-flex justify-space-between align-center flex-wrap">
<span>Telefone não conectado</span>
<v-btn @click="startConnect" size="small"> Conectar </v-btn>
</div>
</v-alert>
<v-dialog v-model="dialog" max-width="350px">
<v-card :loading="loading && qrCode">
<v-card-text>
<v-img v-if="qrCode" :src="qrCode" width="300px" height="300px" />
<v-card
v-else
width="300px"
height="300px"
variant="outlined"
elevation="0"
>
<v-card-text class="d-flex justify-center align-center h-100">
<v-progress-circular indeterminate color="primary" />
</v-card-text>
</v-card>
<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 text @click="dialog = false" :disabled="loading"> Cancel </v-btn>
<v-spacer></v-spacer>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
import { useAppStore } from "@/store/app";
import instanceController from "@/services/instanceController";
export default {
name: "SettingsModal",
data: () => ({
dialog: false,
error: false,
loading: false,
qrCode: null,
success: false,
timeout: null,
AppStore: useAppStore(),
}),
methods: {
async loadQr() {
try {
this.loading = true;
this.error = false;
const response = await instanceController.connect(
this.instance.instance.instanceName
);
if (response.base64) this.qrCode = response.base64;
else {
this.dialog = false;
return;
}
this.timeout = setTimeout(this.loadQr, 40000);
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
this.loading = false;
}
},
async startConnect() {
clearTimeout(this.timeout);
this.dialog = true;
this.error = false;
await this.loadQr();
await this.AppStore.reconnect();
},
},
props: {
instance: {
type: Object,
required: true,
},
},
emits: ["close"],
};
</script>

View File

@@ -5,7 +5,7 @@
:persistent="!AppStore.validConnection"
>
<v-card>
<v-card-text>
<v-card-text class="d-flex flex-column gap-4">
<v-form v-model="valid">
<h3 class="mb-4">Criar instancia</h3>
<v-text-field
@@ -21,7 +21,7 @@
]"
/>
<v-text-field
v-model="instance.apiKey"
v-model="instance.token"
label="API Key"
required
outlined
@@ -41,7 +41,7 @@
configurados após a criação da instância.
</v-alert>
<v-alert type="error" v-if="error">
<v-alert type="error" v-if="error" >
{{ Array.isArray(error) ? error.join(", ") : error }}
</v-alert>
</v-card-text>
@@ -62,7 +62,7 @@
:disabled="!valid"
:loading="loading"
>
Conectar
Criar
</v-btn>
</v-card-actions>
</v-card>
@@ -80,7 +80,7 @@ export default {
valid: false,
instance: {
instanceName: "",
apiKey: "",
token: "",
},
loading: false,
error: false,
@@ -88,7 +88,7 @@ export default {
}),
methods: {
generateApiKey() {
this.instance.apiKey =
this.instance.token =
Math.random().toString(36).substring(2, 15) +
Math.random().toString(36).substring(2, 15);
},

View File

@@ -1,25 +1,28 @@
<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">
<h3 class="mb-4">Configurar conexão</h3>
<v-text-field
v-model="apiKey"
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 text to="/" :disabled="loading">Cancel</v-btn>
<v-btn
color="success"
variant="tonal"
@@ -35,13 +38,18 @@
</template>
<script>
import instanceController from "@/services/instanceController";
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(),
@@ -52,13 +60,8 @@ export default {
this.loading = true;
this.error = false;
const instance = await instanceController.create(this.instance);
await this.AppStore.reconnect();
this.$router.push({
name: "instance",
params: { id: instance.instance.instanceName },
});
await this.AppStore.setConnection(this.connection);
this.dialog = false;
} catch (e) {
this.error = e.message?.message || e.message || e;
} finally {
@@ -67,9 +70,6 @@ export default {
},
open() {
this.dialog = true;
this.error = false;
this.instance.instanceName = "";
this.generateApiKey();
},
},