Files
tacticalrmm-web/src/components/agents/NotesTab.vue

268 lines
6.3 KiB
Vue

<template>
<div v-if="!selectedAgent" class="q-pa-sm">No agent selected</div>
<div v-else>
<q-table
grid
class="tabs-tbl-sticky"
:style="{ 'max-height': tabHeight }"
:rows="notes"
:columns="columns"
v-model:pagination="pagination"
row-key="id"
:rows-per-page-options="[0]"
:loading="loading"
hide-bottom
virtual-scroll
no-data-label="No notes"
>
<template v-slot:top>
<q-btn
class="q-mr-sm"
dense
flat
push
@click="getNotes"
icon="refresh"
/>
<q-btn
icon="add"
label="Add Note"
no-caps
dense
flat
push
@click="addNote"
/>
<q-space />
<export-table-btn :data="notes" :columns="columns" />
</template>
<template v-slot:loading>
<q-inner-loading showing color="primary" />
</template>
<template v-slot:item="props">
<q-card class="notes-card q-pa-none q-ma-xs" bordered>
<q-card-section>
<div class="row">
<div class="col">
<div class="text-subtitle2">
{{ formatDate(props.row.entry_time) }}
</div>
<div class="text-caption">{{ props.row.username }}</div>
</div>
<div class="col-auto">
<q-btn color="grey-7" round flat icon="more_vert">
<q-menu cover auto-close>
<q-list dense>
<q-item
clickable
v-close-popup
@click="editNote(props.row)"
>
<q-item-section side>
<q-icon name="edit" />
</q-item-section>
<q-item-section>Edit</q-item-section>
</q-item>
<q-item
clickable
v-close-popup
@click="deleteNote(props.row)"
>
<q-item-section side>
<q-icon name="delete" />
</q-item-section>
<q-item-section>Delete</q-item-section>
</q-item>
</q-list>
</q-menu>
</q-btn>
</div>
</div>
</q-card-section>
<q-card-section style="max-height: 20vh" class="scroll">
<pre>{{ props.row.note }}</pre>
</q-card-section>
</q-card>
</template>
</q-table>
</div>
</template>
<script>
// composition imports
import { ref, computed, watch, onMounted } from "vue";
import { useStore } from "vuex";
import { useQuasar } from "quasar";
import {
fetchAgentNotes,
editAgentNote,
saveAgentNote,
removeAgentNote,
} from "@/api/agents";
import { notifySuccess } from "@/utils/notify";
// ui imports
import ExportTableBtn from "@/components/ui/ExportTableBtn.vue";
// static data
const columns = [
{
name: "entry_time",
label: "Date",
field: "entry_time",
},
{
name: "username",
label: "User",
field: "username",
},
{
name: "note",
label: "Note",
field: "note",
},
];
export default {
name: "NotesTab",
components: {
ExportTableBtn,
},
setup() {
// setup vuex
const store = useStore();
const selectedAgent = computed(() => store.state.selectedRow);
const tabHeight = computed(() => store.state.tabHeight);
const formatDate = computed(() => store.getters.formatDate);
// setup quasar
const $q = useQuasar();
// notes tab logic
const noteText = ref("");
const notes = ref([]);
const loading = ref(false);
const pagination = ref({
rowsPerPage: 0,
sortBy: "id",
descending: false,
});
async function getNotes() {
loading.value = true;
notes.value = await fetchAgentNotes(selectedAgent.value);
loading.value = false;
}
function addNote() {
noteText.value = "";
$q.dialog({
title: "Add Note",
prompt: {
model: noteText,
type: "textarea",
isValid: (val) => !!val,
},
style: "width: 90vw; max-width: 90vw",
ok: { label: "Add" },
cancel: true,
}).onOk(async () => {
loading.value = true;
try {
const result = await saveAgentNote({
agent_id: selectedAgent.value,
note: noteText.value,
});
notifySuccess(result);
await getNotes();
} catch (e) {
console.error(e);
}
loading.value = false;
});
}
function editNote(note) {
$q.dialog({
title: "Edit Note",
prompt: {
model: note.note,
type: "textarea",
isValid: (val) => !!val,
},
style: "width: 90vw; max-width: 90vw",
ok: { label: "Save" },
cancel: true,
}).onOk(async (data) => {
loading.value = true;
try {
const result = await editAgentNote(note.pk, { note: data });
notifySuccess(result);
await getNotes();
} catch (e) {
console.error(e);
}
loading.value = false;
});
}
function deleteNote(note) {
$q.dialog({
title: "Delete note?",
cancel: true,
ok: { label: "Delete", color: "negative" },
}).onOk(async () => {
loading.value = true;
try {
const result = await removeAgentNote(note.pk);
notifySuccess(result);
await getNotes();
} catch (e) {
console.error(e);
}
loading.value = false;
});
}
watch(selectedAgent, (newValue) => {
if (newValue) {
getNotes();
}
});
onMounted(() => {
if (selectedAgent.value) getNotes();
});
return {
// reactive data
notes,
loading,
pagination,
selectedAgent,
tabHeight,
noteText,
// non-reactive data
columns,
// methods
formatDate,
getNotes,
addNote,
editNote,
deleteNote,
};
},
};
</script>
<style lang="sass" scoped>
.notes-card
width: 100%
max-width: 20vw
</style>