108 lines
3.6 KiB
Vue
108 lines
3.6 KiB
Vue
<script setup lang="ts">
|
|
import { getNoteReferences, setActiveNote, findNotes, deleteNote } from '@/composables/useNotes'
|
|
import { formatDate } from '@/utils/helpers'
|
|
|
|
const notesWithReferences = computed(() => {
|
|
return findNotes(filter.value).map((note) => ({
|
|
...note,
|
|
references: getNoteReferences(note)
|
|
}))
|
|
})
|
|
|
|
const selectedNotes = ref<{ [key: string]: Boolean }>({})
|
|
const countSelectedNotes = computed<number>(
|
|
() => Object.entries(selectedNotes.value).filter(([, selected]) => Boolean(selected)).length
|
|
)
|
|
|
|
const toggleRow = (note: Note) => {
|
|
if (!note.isRoot) selectedNotes.value[note.id] = !selectedNotes.value[note.id]
|
|
}
|
|
|
|
const filter = ref<string>('')
|
|
|
|
const deleteSelectedNotes = (closeModal: () => void) => {
|
|
closeModal()
|
|
const notesToDelete = Object.entries(selectedNotes.value)
|
|
.filter(([, selected]) => Boolean(selected))
|
|
.map(([id]) => id)
|
|
notesToDelete.forEach((noteId) => deleteNote(noteId))
|
|
selectedNotes.value = {}
|
|
}
|
|
</script>
|
|
<template>
|
|
<div class="flex flex-col gap-2">
|
|
<div class="flex items-center gap-2">
|
|
<div class="flex items-center">
|
|
<span class="whitespace-nowrap">
|
|
{{ notesWithReferences.length }} {{ notesWithReferences.length === 1 ? 'note' : 'notes' }}
|
|
</span>
|
|
<template v-if="countSelectedNotes > 0">
|
|
<span class="mx-1">|</span>
|
|
<div class="whitespace-nowrap font-semibold">{{ countSelectedNotes }} selected</div>
|
|
</template>
|
|
</div>
|
|
<UIModal v-if="countSelectedNotes > 0">
|
|
<template #activator="{ open }">
|
|
<UIButton size="sm" @click="open">Delete</UIButton>
|
|
</template>
|
|
<template #default>Are you sure you want to delete the selected notes?</template>
|
|
<template #actions="{ close }">
|
|
<UIButton size="sm" color="primary" @click="deleteSelectedNotes(close)">
|
|
Delete selected notes
|
|
</UIButton>
|
|
<UIButton size="sm" @click="close">Close</UIButton>
|
|
</template>
|
|
</UIModal>
|
|
<UIInputText
|
|
size="sm"
|
|
v-model="filter"
|
|
placeholder="Start typing to filter"
|
|
class="my-1 ml-auto mr-1 max-w-xs flex-grow"
|
|
></UIInputText>
|
|
</div>
|
|
<div class="overflow-x-auto">
|
|
<UITable density="compact" class="w-full">
|
|
<thead>
|
|
<tr>
|
|
<th class="w-[48px]"></th>
|
|
<th>Note title</th>
|
|
<th class="w-[75px]">Words</th>
|
|
<th class="w-[100px]">References</th>
|
|
<th class="w-[150px]">Modified</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr
|
|
v-for="note in notesWithReferences"
|
|
:key="note.id"
|
|
class="dui-hover hover:cursor-pointer"
|
|
@click="setActiveNote(note.id)"
|
|
>
|
|
<th @click.stop="toggleRow(note)" class="text-center">
|
|
<label>
|
|
<UIInputCheckbox
|
|
color="primary"
|
|
:checked="Boolean(selectedNotes[note.id])"
|
|
:disabled="note.isRoot"
|
|
></UIInputCheckbox>
|
|
</label>
|
|
</th>
|
|
<td>
|
|
<i class="fas fa-fw fa-home mr-1 text-secondary" v-if="note.isRoot" />
|
|
{{ note.title }}
|
|
</td>
|
|
<td>{{ note.wordCount }}</td>
|
|
<td>
|
|
<UIBadge v-if="note.references.length > 0">
|
|
<i data-v-41bbc26f="" class="fas fa-fw fa-sign-out-alt mr-1"></i>
|
|
{{ note.references.length }}
|
|
</UIBadge>
|
|
</td>
|
|
<td>{{ formatDate(note.modified) }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</UITable>
|
|
</div>
|
|
</div>
|
|
</template>
|