mirror of https://github.com/Fabio286/antares.git
feat: ability to edit notes
This commit is contained in:
parent
eaaf1b756a
commit
08e5a13f72
|
@ -0,0 +1,116 @@
|
||||||
|
<template>
|
||||||
|
<ConfirmModal
|
||||||
|
size="medium"
|
||||||
|
:disable-autofocus="true"
|
||||||
|
:close-on-confirm="!!localNote.note.length"
|
||||||
|
:confirm-text="t('general.save')"
|
||||||
|
@confirm="updateNote"
|
||||||
|
@hide="$emit('hide')"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="d-flex">
|
||||||
|
<BaseIcon
|
||||||
|
icon-name="mdiNoteEditOutline"
|
||||||
|
class="mr-1"
|
||||||
|
:size="24"
|
||||||
|
/> {{ t('application.editNote') }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #body>
|
||||||
|
<form class="form">
|
||||||
|
<div class="form-group columns">
|
||||||
|
<div class="column col-8">
|
||||||
|
<label class="form-label">{{ t('connection.connection') }}</label>
|
||||||
|
<BaseSelect
|
||||||
|
v-model="localNote.cUid"
|
||||||
|
class="form-select"
|
||||||
|
:options="connectionOptions"
|
||||||
|
option-track-by="code"
|
||||||
|
option-label="name"
|
||||||
|
@change="null"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="column col-4">
|
||||||
|
<label class="form-label">{{ t('application.tag') }}</label>
|
||||||
|
<BaseSelect
|
||||||
|
v-model="localNote.type"
|
||||||
|
class="form-select"
|
||||||
|
:options="noteTags"
|
||||||
|
option-track-by="code"
|
||||||
|
option-label="name"
|
||||||
|
@change="null"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">{{ t('general.content') }}</label>
|
||||||
|
<BaseTextEditor
|
||||||
|
v-model="localNote.note"
|
||||||
|
:mode="editorMode"
|
||||||
|
:show-line-numbers="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
</ConfirmModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { inject, onBeforeMount, PropType, Ref, ref, watch } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
||||||
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||||||
|
import BaseSelect from '@/components/BaseSelect.vue';
|
||||||
|
import BaseTextEditor from '@/components/BaseTextEditor.vue';
|
||||||
|
import { ConnectionNote, TagCode, useScratchpadStore } from '@/stores/scratchpad';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const { editNote } = useScratchpadStore();
|
||||||
|
|
||||||
|
const emit = defineEmits(['hide']);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
note: {
|
||||||
|
type: Object as PropType<ConnectionNote>,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const noteTags = inject<{code: TagCode; name: string}[]>('noteTags');
|
||||||
|
const connectionOptions = inject<{code: string; name: string}[]>('connectionOptions');
|
||||||
|
|
||||||
|
const editorMode = ref('markdown');
|
||||||
|
const localNote: Ref<ConnectionNote> = ref({
|
||||||
|
uid: 'dummy',
|
||||||
|
cUid: null,
|
||||||
|
title: undefined,
|
||||||
|
note: '',
|
||||||
|
date: new Date(),
|
||||||
|
type: 'note',
|
||||||
|
isArchived: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateNote = () => {
|
||||||
|
if (localNote.value.note) {
|
||||||
|
if (!localNote.value.title)// Set a default title
|
||||||
|
localNote.value.title = `${localNote.value.type.toLocaleUpperCase()}: ${localNote.value.uid}`;
|
||||||
|
|
||||||
|
localNote.value.date = new Date();
|
||||||
|
editNote(localNote.value);
|
||||||
|
emit('hide');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(() => localNote.value.type, () => {
|
||||||
|
if (localNote.value.type === 'query')
|
||||||
|
editorMode.value = 'sql';
|
||||||
|
else
|
||||||
|
editorMode.value = 'markdown';
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
localNote.value = props.note;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
|
@ -3,6 +3,7 @@
|
||||||
size="medium"
|
size="medium"
|
||||||
:disable-autofocus="true"
|
:disable-autofocus="true"
|
||||||
:close-on-confirm="!!newNote.note.length"
|
:close-on-confirm="!!newNote.note.length"
|
||||||
|
:confirm-text="t('general.save')"
|
||||||
@confirm="createNote"
|
@confirm="createNote"
|
||||||
@hide="$emit('hide')"
|
@hide="$emit('hide')"
|
||||||
>
|
>
|
|
@ -30,7 +30,8 @@
|
||||||
<div class="tile-content-message" :class="[{'opened': isSelected}]">
|
<div class="tile-content-message" :class="[{'opened': isSelected}]">
|
||||||
<code
|
<code
|
||||||
v-if="note.type === 'query'"
|
v-if="note.type === 'query'"
|
||||||
class="cut-text"
|
ref="noteParagraph"
|
||||||
|
class="tile-paragraph"
|
||||||
v-html="highlightWord(note.note)"
|
v-html="highlightWord(note.note)"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
@ -47,7 +48,7 @@
|
||||||
<button
|
<button
|
||||||
v-if="note.type === 'todo' && !note.isArchived"
|
v-if="note.type === 'todo' && !note.isArchived"
|
||||||
class="btn btn-link pl-1"
|
class="btn btn-link pl-1"
|
||||||
@click="$emit('archive-note', note.uid)"
|
@click.stop="$emit('archive-note', note.uid)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
icon-name="mdiCheck"
|
icon-name="mdiCheck"
|
||||||
|
@ -58,7 +59,7 @@
|
||||||
<button
|
<button
|
||||||
v-if="note.type === 'todo' && note.isArchived"
|
v-if="note.type === 'todo' && note.isArchived"
|
||||||
class="btn btn-link pl-1"
|
class="btn btn-link pl-1"
|
||||||
@click="$emit('restore-note', note.uid)"
|
@click.stop="$emit('restore-note', note.uid)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
icon-name="mdiRestore"
|
icon-name="mdiRestore"
|
||||||
|
@ -69,7 +70,7 @@
|
||||||
<button
|
<button
|
||||||
v-if="note.type === 'query'"
|
v-if="note.type === 'query'"
|
||||||
class="btn btn-link pl-1"
|
class="btn btn-link pl-1"
|
||||||
@click="copyText(note.note)"
|
@click.stop="copyText(note.note)"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
icon-name="mdiContentCopy"
|
icon-name="mdiContentCopy"
|
||||||
|
@ -80,7 +81,7 @@
|
||||||
<button
|
<button
|
||||||
v-if=" !note.isArchived"
|
v-if=" !note.isArchived"
|
||||||
class="btn btn-link pl-1"
|
class="btn btn-link pl-1"
|
||||||
@click="null"
|
@click.stop="$emit('edit-note')"
|
||||||
>
|
>
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
icon-name="mdiPencil"
|
icon-name="mdiPencil"
|
||||||
|
@ -88,7 +89,7 @@
|
||||||
:size="22"
|
:size="22"
|
||||||
/> {{ t('general.edit') }}
|
/> {{ t('general.edit') }}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-link pl-1" @click="$emit('delete-note', note.uid)">
|
<button class="btn btn-link pl-1" @click.stop="$emit('delete-note', note.uid)">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
icon-name="mdiDeleteForever"
|
icon-name="mdiDeleteForever"
|
||||||
class="pr-1"
|
class="pr-1"
|
||||||
|
@ -131,7 +132,14 @@ const { t } = useI18n();
|
||||||
const { formatDate } = useFilters();
|
const { formatDate } = useFilters();
|
||||||
const { getConnectionName } = useConnectionsStore();
|
const { getConnectionName } = useConnectionsStore();
|
||||||
|
|
||||||
defineEmits(['delete-note', 'select-note', 'toggle-note', 'archive-note', 'restore-note']);
|
defineEmits([
|
||||||
|
'edit-note',
|
||||||
|
'delete-note',
|
||||||
|
'select-note',
|
||||||
|
'toggle-note',
|
||||||
|
'archive-note',
|
||||||
|
'restore-note'
|
||||||
|
]);
|
||||||
|
|
||||||
const noteParagraph: Ref<HTMLDivElement> = ref(null);
|
const noteParagraph: Ref<HTMLDivElement> = ref(null);
|
||||||
const noteHeight = ref(useElementBounding(noteParagraph)?.height);
|
const noteHeight = ref(useElementBounding(noteParagraph)?.height);
|
||||||
|
@ -188,7 +196,7 @@ const highlightWord = (string: string) => {
|
||||||
right: 2px;
|
right: 2px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
opacity: .7;
|
opacity: .7;
|
||||||
z-index: 9;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tile-icon {
|
.tile-icon {
|
||||||
|
@ -233,13 +241,14 @@ const highlightWord = (string: string) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code, pre {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 100%;
|
font-size: 100%;
|
||||||
// color: $primary-color;
|
// color: $primary-color;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
white-space: break-spaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tile-subtitle {
|
.tile-subtitle {
|
||||||
|
|
|
@ -109,6 +109,7 @@
|
||||||
:selected-note="selectedNote"
|
:selected-note="selectedNote"
|
||||||
@select-note="selectedNote = note.uid"
|
@select-note="selectedNote = note.uid"
|
||||||
@toggle-note="toggleNote"
|
@toggle-note="toggleNote"
|
||||||
|
@edit-note="startEditNote(note)"
|
||||||
@delete-note="deleteNote"
|
@delete-note="deleteNote"
|
||||||
@archive-note="archiveNote"
|
@archive-note="archiveNote"
|
||||||
@restore-note="restoreNote"
|
@restore-note="restoreNote"
|
||||||
|
@ -139,7 +140,12 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
<ModalNewNote v-if="isAddModal" @hide="isAddModal = false" />
|
<ModalNoteNew v-if="isAddModal" @hide="isAddModal = false" />
|
||||||
|
<ModalNoteEdit
|
||||||
|
v-if="isEditModal"
|
||||||
|
:note="noteToEdit"
|
||||||
|
@hide="closeEditModal"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -161,11 +167,12 @@ import { useI18n } from 'vue-i18n';
|
||||||
import BaseIcon from '@/components/BaseIcon.vue';
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||||||
import BaseSelect from '@/components/BaseSelect.vue';
|
import BaseSelect from '@/components/BaseSelect.vue';
|
||||||
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
|
import BaseVirtualScroll from '@/components/BaseVirtualScroll.vue';
|
||||||
import ModalNewNote from '@/components/ModalNewNote.vue';
|
import ModalNoteEdit from '@/components/ModalNoteEdit.vue';
|
||||||
|
import ModalNoteNew from '@/components/ModalNoteNew.vue';
|
||||||
import ScratchpadNote from '@/components/ScratchpadNote.vue';
|
import ScratchpadNote from '@/components/ScratchpadNote.vue';
|
||||||
import { useApplicationStore } from '@/stores/application';
|
import { useApplicationStore } from '@/stores/application';
|
||||||
import { useConnectionsStore } from '@/stores/connections';
|
import { useConnectionsStore } from '@/stores/connections';
|
||||||
import { TagCode, useScratchpadStore } from '@/stores/scratchpad';
|
import { ConnectionNote, TagCode, useScratchpadStore } from '@/stores/scratchpad';
|
||||||
import { useWorkspacesStore } from '@/stores/workspaces';
|
import { useWorkspacesStore } from '@/stores/workspaces';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -194,6 +201,7 @@ const localSearchTerm = ref('');
|
||||||
const showArchived = ref(false);
|
const showArchived = ref(false);
|
||||||
const isAddModal = ref(false);
|
const isAddModal = ref(false);
|
||||||
const isEditModal = ref(false);
|
const isEditModal = ref(false);
|
||||||
|
const noteToEdit: Ref<ConnectionNote> = ref(null);
|
||||||
const selectedTag = ref('all');
|
const selectedTag = ref('all');
|
||||||
const selectedNote = ref(null);
|
const selectedNote = ref(null);
|
||||||
|
|
||||||
|
@ -241,6 +249,11 @@ const toggleNote = (uid: string) => {
|
||||||
selectedNote.value = selectedNote.value !== uid ? uid : null;
|
selectedNote.value = selectedNote.value !== uid ? uid : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const startEditNote = (note: ConnectionNote) => {
|
||||||
|
isEditModal.value = true;
|
||||||
|
noteToEdit.value = note;
|
||||||
|
};
|
||||||
|
|
||||||
const archiveNote = (uid: string) => {
|
const archiveNote = (uid: string) => {
|
||||||
const remappedNotes = connectionNotes.value.map(n => {
|
const remappedNotes = connectionNotes.value.map(n => {
|
||||||
if (n.uid === uid)
|
if (n.uid === uid)
|
||||||
|
@ -264,6 +277,11 @@ const deleteNote = (uid: string) => {
|
||||||
changeNotes(otherNotes);
|
changeNotes(otherNotes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const closeEditModal = () => {
|
||||||
|
isEditModal.value = false;
|
||||||
|
noteToEdit.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
watch(searchTerm, () => {
|
watch(searchTerm, () => {
|
||||||
clearTimeout(searchTermInterval.value);
|
clearTimeout(searchTermInterval.value);
|
||||||
|
|
||||||
|
@ -310,6 +328,7 @@ onBeforeUnmount(() => {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
margin-top: -40px;
|
margin-top: -40px;
|
||||||
margin-left: 580px;
|
margin-left: 580px;
|
||||||
|
z-index: 9;
|
||||||
}
|
}
|
||||||
.archived-button {
|
.archived-button {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
|
@ -391,6 +391,7 @@ export const enUS = {
|
||||||
note: 'Note | Notes',
|
note: 'Note | Notes',
|
||||||
thereAreNoNotesYet: 'There are no notes yet',
|
thereAreNoNotesYet: 'There are no notes yet',
|
||||||
addNote: 'Add note',
|
addNote: 'Add note',
|
||||||
|
editNote: 'Edit note',
|
||||||
showArchivedNotes: 'Show archived notes',
|
showArchivedNotes: 'Show archived notes',
|
||||||
hideArchivedNotes: 'Hide archived notes',
|
hideArchivedNotes: 'Hide archived notes',
|
||||||
tag: 'Tag' // Note tag
|
tag: 'Tag' // Note tag
|
||||||
|
|
|
@ -32,6 +32,15 @@ export const useScratchpadStore = defineStore('scratchpad', {
|
||||||
...this.connectionNotes
|
...this.connectionNotes
|
||||||
];
|
];
|
||||||
persistentStore.set('connectionNotes', this.connectionNotes);
|
persistentStore.set('connectionNotes', this.connectionNotes);
|
||||||
|
},
|
||||||
|
editNote (note: ConnectionNote) {
|
||||||
|
this.connectionNotes = (this.connectionNotes as ConnectionNote[]).map(n => {
|
||||||
|
if (n.uid === note.uid)
|
||||||
|
n = note;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
});
|
||||||
|
persistentStore.set('connectionNotes', this.connectionNotes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue