mirror of https://github.com/Fabio286/antares.git
329 lines
8.4 KiB
Vue
329 lines
8.4 KiB
Vue
|
<template>
|
||
|
<div
|
||
|
class="tile my-2"
|
||
|
tabindex="0"
|
||
|
@click="$emit('select-note', note.uid)"
|
||
|
>
|
||
|
<BaseIcon
|
||
|
v-if="isBig"
|
||
|
class="tile-compress c-hand"
|
||
|
:icon-name="isSelected ? 'mdiChevronUp' : 'mdiChevronDown'"
|
||
|
:size="36"
|
||
|
@click.stop="$emit('toggle-note', note.uid)"
|
||
|
/>
|
||
|
<div class="tile-icon">
|
||
|
<BaseIcon
|
||
|
:icon-name="note.type === 'query'
|
||
|
? 'mdiStarOutline'
|
||
|
: note.type === 'todo'
|
||
|
? note.isArchived
|
||
|
? 'mdiCheckboxMarkedOutline'
|
||
|
: 'mdiCheckboxBlankOutline'
|
||
|
: 'mdiNoteEditOutline'"
|
||
|
:size="36"
|
||
|
/>
|
||
|
<div class="tile-icon-type">
|
||
|
{{ note.type }}
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="tile-content">
|
||
|
<div class="tile-content-message" :class="[{'opened': isSelected}]">
|
||
|
<code
|
||
|
v-if="note.type === 'query'"
|
||
|
class="cut-text"
|
||
|
v-html="highlightWord(note.note)"
|
||
|
/>
|
||
|
<div
|
||
|
v-else
|
||
|
ref="noteParagraph"
|
||
|
class="tile-paragraph"
|
||
|
v-html="parseMarkdown(highlightWord(note.note))"
|
||
|
/>
|
||
|
<div v-if="isBig && !isSelected" class="tile-paragraph-overlay" />
|
||
|
</div>
|
||
|
<div class="tile-bottom-content">
|
||
|
<small class="tile-subtitle">{{ getConnectionName(note.cUid) || t('general.all') }} · {{ formatDate(note.date) }}</small>
|
||
|
<div class="tile-history-buttons">
|
||
|
<button
|
||
|
v-if="note.type === 'todo' && !note.isArchived"
|
||
|
class="btn btn-link pl-1"
|
||
|
@click="$emit('archive-note', note.uid)"
|
||
|
>
|
||
|
<BaseIcon
|
||
|
icon-name="mdiCheck"
|
||
|
class="pr-1"
|
||
|
:size="22"
|
||
|
/> {{ t('general.archive') }}
|
||
|
</button>
|
||
|
<button
|
||
|
v-if="note.type === 'todo' && note.isArchived"
|
||
|
class="btn btn-link pl-1"
|
||
|
@click="$emit('restore-note', note.uid)"
|
||
|
>
|
||
|
<BaseIcon
|
||
|
icon-name="mdiRestore"
|
||
|
class="pr-1"
|
||
|
:size="22"
|
||
|
/> {{ t('general.undo') }}
|
||
|
</button>
|
||
|
<button
|
||
|
v-if="note.type === 'query'"
|
||
|
class="btn btn-link pl-1"
|
||
|
@click="copyText(note.note)"
|
||
|
>
|
||
|
<BaseIcon
|
||
|
icon-name="mdiContentCopy"
|
||
|
class="pr-1"
|
||
|
:size="22"
|
||
|
/> {{ t('general.copy') }}
|
||
|
</button>
|
||
|
<button
|
||
|
v-if=" !note.isArchived"
|
||
|
class="btn btn-link pl-1"
|
||
|
@click="null"
|
||
|
>
|
||
|
<BaseIcon
|
||
|
icon-name="mdiPencil"
|
||
|
class="pr-1"
|
||
|
:size="22"
|
||
|
/> {{ t('general.edit') }}
|
||
|
</button>
|
||
|
<button class="btn btn-link pl-1" @click="$emit('delete-note', note.uid)">
|
||
|
<BaseIcon
|
||
|
icon-name="mdiDeleteForever"
|
||
|
class="pr-1"
|
||
|
:size="22"
|
||
|
/> {{ t('general.delete') }}
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</template>
|
||
|
<script setup lang="ts">
|
||
|
import { useElementBounding } from '@vueuse/core';
|
||
|
import { marked } from 'marked';
|
||
|
import { computed, PropType, Ref, ref } from 'vue';
|
||
|
import { useI18n } from 'vue-i18n';
|
||
|
|
||
|
import BaseIcon from '@/components/BaseIcon.vue';
|
||
|
import { useFilters } from '@/composables/useFilters';
|
||
|
import { copyText } from '@/libs/copyText';
|
||
|
import { useConnectionsStore } from '@/stores/connections';
|
||
|
import { ConnectionNote } from '@/stores/scratchpad';
|
||
|
|
||
|
const props = defineProps({
|
||
|
note: {
|
||
|
type: Object as PropType<ConnectionNote>,
|
||
|
required: true
|
||
|
},
|
||
|
searchTerm: {
|
||
|
type: String,
|
||
|
default: () => ''
|
||
|
},
|
||
|
selectedNote: {
|
||
|
type: String,
|
||
|
default: () => ''
|
||
|
}
|
||
|
});
|
||
|
|
||
|
const { t } = useI18n();
|
||
|
const { formatDate } = useFilters();
|
||
|
const { getConnectionName } = useConnectionsStore();
|
||
|
|
||
|
defineEmits(['delete-note', 'select-note', 'toggle-note', 'archive-note', 'restore-note']);
|
||
|
|
||
|
const noteParagraph: Ref<HTMLDivElement> = ref(null);
|
||
|
const noteHeight = ref(useElementBounding(noteParagraph)?.height);
|
||
|
|
||
|
const isSelected = computed(() => props.selectedNote === props.note.uid);
|
||
|
const isBig = computed(() => noteHeight.value > 75);
|
||
|
|
||
|
const parseMarkdown = (text: string) => {
|
||
|
const renderer = {
|
||
|
listitem (text: string) {
|
||
|
return `<li>${text.replace(/ *\([^)]*\) */g, '')}</li>`;
|
||
|
},
|
||
|
link (href: string, title: string, text: string) {
|
||
|
return `<a>${text}</a>`;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
marked.use({ renderer });
|
||
|
|
||
|
return marked(text);
|
||
|
};
|
||
|
|
||
|
const highlightWord = (string: string) => {
|
||
|
string = string.replaceAll('<', '<').replaceAll('>', '>');
|
||
|
|
||
|
if (props.searchTerm) {
|
||
|
const regexp = new RegExp(`(${props.searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
|
||
|
return string.replace(regexp, '<span class="text-primary text-bold">$1</span>');
|
||
|
}
|
||
|
else
|
||
|
return string;
|
||
|
};
|
||
|
</script>
|
||
|
<style scoped lang="scss">
|
||
|
.tile {
|
||
|
border-radius: $border-radius;
|
||
|
display: flex;
|
||
|
position: relative;
|
||
|
transition: none;
|
||
|
|
||
|
&:hover,
|
||
|
&:focus {
|
||
|
.tile-content {
|
||
|
.tile-bottom-content {
|
||
|
.tile-history-buttons {
|
||
|
opacity: 1;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.tile-compress {
|
||
|
position: absolute;
|
||
|
right: 2px;
|
||
|
top: 0px;
|
||
|
opacity: .7;
|
||
|
z-index: 9;
|
||
|
}
|
||
|
|
||
|
.tile-icon {
|
||
|
font-size: 1.2rem;
|
||
|
margin-left: 0.3rem;
|
||
|
margin-right: 0.3rem;
|
||
|
margin-top: 0.6rem;
|
||
|
width: 40px;
|
||
|
display: flex;
|
||
|
align-items: center;
|
||
|
flex-direction: column;
|
||
|
justify-content: center;
|
||
|
opacity: .8;
|
||
|
|
||
|
.tile-icon-type {
|
||
|
text-transform: uppercase;
|
||
|
font-size: .5rem;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.tile-content {
|
||
|
padding: 0.3rem;
|
||
|
padding-left: 0.1rem;
|
||
|
min-height: 75px;
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
justify-content: space-between;
|
||
|
|
||
|
.tile-content-message{
|
||
|
position: relative;
|
||
|
|
||
|
&:not(.opened) {
|
||
|
max-height: 36px;
|
||
|
overflow: hidden;
|
||
|
}
|
||
|
|
||
|
.tile-paragraph-overlay {
|
||
|
height: 36px;
|
||
|
width: 100%;
|
||
|
position: absolute;
|
||
|
top: 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
code {
|
||
|
max-width: 100%;
|
||
|
display: inline-block;
|
||
|
font-size: 100%;
|
||
|
// color: $primary-color;
|
||
|
opacity: 0.8;
|
||
|
font-weight: 600;
|
||
|
}
|
||
|
|
||
|
.tile-subtitle {
|
||
|
opacity: 0.8;
|
||
|
}
|
||
|
|
||
|
.tile-bottom-content {
|
||
|
display: flex;
|
||
|
justify-content: space-between;
|
||
|
|
||
|
.tile-history-buttons {
|
||
|
opacity: 0;
|
||
|
transition: opacity 0.2s;
|
||
|
|
||
|
button {
|
||
|
font-size: 0.7rem;
|
||
|
height: 1rem;
|
||
|
line-height: 1rem;
|
||
|
display: inline-flex;
|
||
|
align-items: center;
|
||
|
justify-content: center;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.theme-dark {
|
||
|
.tile {
|
||
|
.tile-paragraph-overlay {
|
||
|
background-image: linear-gradient(
|
||
|
to bottom,
|
||
|
rgba(255,0,0,0) 70%,
|
||
|
$body-bg-dark);
|
||
|
}
|
||
|
|
||
|
&:focus {
|
||
|
.tile-paragraph-overlay {
|
||
|
background-image: linear-gradient(
|
||
|
to bottom,
|
||
|
rgba(255,0,0,0)70%,
|
||
|
#323232);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
&:hover{
|
||
|
.tile-paragraph-overlay {
|
||
|
background-image: linear-gradient(
|
||
|
to bottom,
|
||
|
rgba(255,0,0,0) 70%,
|
||
|
$bg-color-light-dark);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.theme-light {
|
||
|
.tile {
|
||
|
.tile-paragraph-overlay {
|
||
|
background-image: linear-gradient(
|
||
|
to bottom,
|
||
|
rgba(255,0,0,0) 70%,
|
||
|
#FFFF);
|
||
|
}
|
||
|
|
||
|
&:hover,
|
||
|
&:focus {
|
||
|
.tile-paragraph-overlay {
|
||
|
background-image: linear-gradient(
|
||
|
to bottom,
|
||
|
rgba(255,0,0,0) 70%,
|
||
|
$bg-color-light-gray);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
</style>
|
||
|
<style lang="scss">
|
||
|
.tile-paragraph {
|
||
|
white-space: initial;
|
||
|
|
||
|
h1, h2, h3, h4, h5, h6, p, li {
|
||
|
margin: 0;
|
||
|
}
|
||
|
}
|
||
|
</style>
|