add search and fix chatwoot save

This commit is contained in:
Gabriel Pastori 2023-12-12 11:03:45 -03:00
parent f99b865f47
commit d2056aec52
3 changed files with 118 additions and 76 deletions

View File

@ -1,7 +1,7 @@
{ {
"name": "evolution-manager", "name": "evolution-manager",
"description": "Evolution Manager is an open-source interface for managing the Evolution API, simplifying the creation and administration of API instances with advanced features and diverse integrations.", "description": "Evolution Manager is an open-source interface for managing the Evolution API, simplifying the creation and administration of API instances with advanced features and diverse integrations.",
"version": "0.4.2", "version": "0.4.3",
"main": "dist", "main": "dist",
"engines": { "engines": {
"node": ">=16.0.0" "node": ">=16.0.0"

View File

@ -139,11 +139,12 @@
v-model="chatwootData.auto_create" v-model="chatwootData.auto_create"
label="Conversa pendente" label="Conversa pendente"
:disabled="loading || !AppStore.versionSatisfies('>=1.6.0')" :disabled="loading || !AppStore.versionSatisfies('>=1.6.0')"
:error-messages="[ :hint="[
!AppStore.versionSatisfies('>=1.6.0') !AppStore.versionSatisfies('>=1.6.0')
? 'Disponível a partir da versão 1.6.0' ? 'Disponível a partir da versão 1.6.0'
: undefined, : undefined,
]" ]"
:persistent-hint="!AppStore.versionSatisfies('>=1.6.0')"
hide-details="auto" hide-details="auto"
class="mb-3" class="mb-3"
density="compact" density="compact"

View File

@ -25,77 +25,111 @@
</div> </div>
<v-row dense> <v-row dense>
<v-col cols="12" v-if="instances.length === 0 || loading"> <v-col cols="12" v-if="loading">
<v-progress-linear v-if="loading" indeterminate color="info" /> <v-progress-linear v-if="loading" indeterminate color="info" />
<v-alert type="info" class="mb-4" v-else :loading="loading" outlined> <v-alert type="info" class="mb-4" v-else :loading="loading" outlined>
{{ loading ? "Carregando..." : "Nenhuma instância encontrada" }} Carregando...
</v-alert> </v-alert>
</v-col> </v-col>
<v-col v-else cols="12">
<v-col <div class="d-flex gap-2 flex-wrap">
cols="12" <v-text-field
sm="6" v-model="search"
lg="4" label="Pesquisar"
v-for="{ instance } in instances" density="comfortable"
:key="instance.instanceName" variant="outlined"
> hide-details
<v-card />
@click="goToInstance(instance)" <v-btn-toggle
class="pa-2 rounded-lg" v-model="statusFilter"
variant="outlined" variant="outlined"
:disabled="loading" divided
mandatory
>
<v-btn
:value="false"
:disabled="loading"
:loading="loading"
variant="outlined"
size="x-small"
>
Todos
</v-btn>
<v-btn
v-for="[key, item] in Object.entries(statusMapper)"
:key="item.text"
:value="key"
:color="item.color"
:disabled="loading"
:loading="loading"
variant="outlined"
size="x-small"
>
{{ item.text }}
</v-btn>
</v-btn-toggle>
</div>
</v-col>
<template v-if="filteredInstances.length !== 0">
<v-col
cols="12"
sm="6"
lg="4"
v-for="{ instance } in filteredInstances"
:key="instance.instanceName"
> >
<div class="d-flex align-center gap-2"> <v-card
<v-avatar size="50"> @click="goToInstance(instance)"
<v-img class="pa-2 rounded-lg"
v-if="instance.profilePictureUrl" variant="outlined"
:src="instance.profilePictureUrl" :disabled="loading"
/> >
<v-icon v-else>{{ statusMapper[instance.status].icon }}</v-icon> <div class="d-flex align-center gap-2">
</v-avatar> <v-avatar size="50">
<div class="flex-shrink-1"> <v-img
<v-chip v-if="instance.profilePictureUrl"
:color="statusMapper[instance.status].color" :src="instance.profilePictureUrl"
size="x-small" />
label <v-icon v-else>{{ statusMapper[instance.status].icon }}</v-icon>
> </v-avatar>
<v-icon <div class="flex-shrink-1">
v-if="statusMapper[instance.status].icon" <v-chip
start :color="statusMapper[instance.status].color"
size="x-small"
label
>
<v-icon
v-if="statusMapper[instance.status].icon"
start
size="x-small"
>
{{ statusMapper[instance.status].icon }}
</v-icon>
{{ statusMapper[instance.status].text }}
</v-chip>
<h5>{{ instance.instanceName }}</h5>
</div>
<div class="ml-auto flex-shrink-0">
<v-btn
:disabled="loading || !!loadingDelete"
:loading="loadingDelete === instance.instanceName"
@click.stop="deleteInstance(instance.instanceName)"
icon
variant="tonal"
color="error"
size="x-small" size="x-small"
> >
{{ statusMapper[instance.status].icon }} <v-icon>mdi-delete</v-icon>
</v-icon> </v-btn>
{{ statusMapper[instance.status].text }} </div>
</v-chip>
<h5>{{ instance.instanceName }}</h5>
</div> </div>
<div class="ml-auto flex-shrink-0"> </v-card>
<!-- <v-btn </v-col>
:disabled="loading" </template>
:to="`/${instance.instanceName}`" <v-col v-else cols="12">
icon <v-alert type="info" class="mb-4" outlined>
size="x-small" Nenhuma instância encontrada
class="mr-1" </v-alert>
variant="tonal"
color="info"
>
<v-icon>mdi-cog</v-icon>
</v-btn> -->
<v-btn
:disabled="loading || !!loadingDelete"
:loading="loadingDelete === instance.instanceName"
@click.stop="deleteInstance(instance.instanceName)"
icon
variant="tonal"
color="error"
size="x-small"
>
<v-icon>mdi-delete</v-icon>
</v-btn>
</div>
</div>
</v-card>
</v-col> </v-col>
</v-row> </v-row>
<v-alert v-if="error" type="error"> <v-alert v-if="error" type="error">
@ -122,16 +156,8 @@ export default {
loadingDelete: false, loadingDelete: false,
error: false, error: false,
statusMapper: statusMapper, statusMapper: statusMapper,
headers: [ statusFilter: false,
{ search: "",
title: "Nome",
align: "start",
sortable: true,
key: "instance.instanceName",
},
{ title: "Status", key: "instance.status" },
{ title: "Ações", key: "actions", sortable: false, align: "center" },
],
}), }),
methods: { methods: {
addInstance() { addInstance() {
@ -176,10 +202,25 @@ export default {
loading() { loading() {
return this.loadingInner || this.AppStore.connecting; return this.loadingInner || this.AppStore.connecting;
}, },
instances() { instances() {
return this.AppStore.instances; return this.AppStore.instances;
}, },
filteredInstances() {
const instances = this.instances.filter((instance) => {
if (!this.statusFilter) return true;
return instance.instance.status === this.statusFilter;
});
if (!this.search) return instances;
return instances.filter((instance) => {
const search = this.search.trim().toLowerCase();
return (
instance.instance.instanceName.toLowerCase().includes(search) ||
instance.instance.owner.toLowerCase().includes(search)
);
});
},
}, },
mounted() {}, mounted() {},
}; };