var t = ` ↗ Title Linked notes count Title Link count Labels tree Labels tree Labels panel Title Modified Created Linked notes count Compact view Detailed view Dark mode ↗ · {{ filteredNotes.length }}/{{ notesLength }} matches for "" Full text search → ` import Icon from './icon.js' import Pane from './pane.js' import Preview from './preview.js' import { formatDate } from './dateutils.js'; export default { props: ['lastSave'], emits: ['note-open', 'note-new', 'finder-open'], components: { Pane, Icon, Preview }, data() { return { query: '', notes: [], notesLength: 0, newLabel: '', previewFilename: '', } }, methods: { fetchNotes() { fetch("/api/notes") .then(r => r.ok ? r.json() : r.json().then(e => Promise.reject(e))) .then(response => { const notes = Object.values(response); this.notesLength = notes.length; this.notes = notes.map(note => { const linkedNotes = [...new Map( [...(note.IncomingLinks || []), ...(note.OutgoingLinks || [])].map(link => [link.Filename, { Filename: link.Filename, Title: link.Title }]) ).values()].sort((a, b) => a.Title.localeCompare(b.Title)); const linkedLabels = linkedNotes.filter(link => link.Title && !link.Title.includes(' ')).map(link => link.Title); const mtime = new Date(note.Mtime); const ctime = new Date(note.Ctime); return { Filename: note.Filename, Title: note.Title, Mtime: mtime, Ctime: ctime, MtimeRelative: this.formatRelativeDate(mtime), CtimeRelative: this.formatRelativeDate(ctime), IsLabel: note.IsLabel, LinkedLabels: linkedLabels, LinkedNotes: linkedNotes, LinkedNotesCount: linkedNotes.length, SearchStr: (note.Title + ' ' + linkedLabels.join(' ')).toLowerCase(), }; }) }) .catch(e => { console.error(e); }); }, formatRelativeDate(date) { const now = new Date(); const nowTime = now.getTime(); const dateTime = date.getTime(); const diff = nowTime - dateTime; const minutes = Math.floor(diff / 60000); // 60 * 1000 const hours = Math.floor(diff / 3600000); // 60 * 60 * 1000 if (minutes < 0) { // future date } else if (minutes < 1) { return 'Just now'; } else if (minutes < 60) { return `${minutes}m ago`; } else if (hours < 24) { return `${hours}h ago`; } else if (hours < 48) { return `Yesterday`; } const format = now.getFullYear() === date.getFullYear() ? '%b %d' : '%b %d, %Y'; return formatDate(date, format); }, createNewLabelNote() { if (this.newLabelStatus.isValid) { const content = `# ${this.newLabel}\n`; this.$emit('note-new', null, content); this.$refs.newLabelInput.blur(); this.newLabel=''; } }, }, computed: { newLabelStatus() { if (!this.newLabel) return { isValid: false, error: '' }; if (this.newLabel.includes(' ')) return { isValid: false, error: 'not 1-word' }; if (this.sortedLabelNotes.some(label => label.Title.toLowerCase() === this.newLabel.toLowerCase())) return { isValid: false, error: 'exists' }; return { isValid: true, error: '' }; }, sortedNotes() { switch(this.$notesiumState.sidePanelSortNotes) { case 'title': return this.notes.sort((a, b) => a.Title.localeCompare(b.Title)); case 'links': return this.notes.sort((a, b) => b.LinkedNotesCount - a.LinkedNotesCount); case 'mtime': return this.notes.sort((a, b) => b.Mtime - a.Mtime); case 'ctime': return this.notes.sort((a, b) => b.Ctime - a.Ctime); } }, sortedLabelNotes() { switch(this.$notesiumState.sidePanelSortLabels) { case 'title': return this.notes.filter(note => note.IsLabel).sort((a, b) => a.Title.localeCompare(b.Title)); case 'links': return this.notes.filter(note => note.IsLabel).sort((a, b) => b.LinkedNotesCount - a.LinkedNotesCount); } }, filteredNotes() { const maxNotes = 300; const { query, sortedNotes } = this; if (!query) return sortedNotes.slice(0, maxNotes); const queryWords = query.toLowerCase().split(' '); const labelQuery = queryWords.find(word => word.startsWith('label:')); if (labelQuery) { const label = labelQuery.slice(6); if (!label) return sortedNotes.filter(note => note.IsLabel).slice(0, maxNotes); const notesSubset = sortedNotes.filter(note => note.LinkedLabels.some(l => l.toLowerCase() === label) || note.Title.toLowerCase() === label); const remainingQueryWords = queryWords.filter(word => word !== labelQuery); return notesSubset.filter(note => remainingQueryWords.every(queryWord => note.SearchStr.includes(queryWord))).slice(0, maxNotes); } return sortedNotes.filter(note => queryWords.every(queryWord => note.SearchStr.includes(queryWord))).slice(0, maxNotes); }, filteredLabelNotes() { const { query, sortedLabelNotes } = this; if (!query) return sortedLabelNotes; const queryWords = query.toLowerCase().split(' '); return sortedLabelNotes.filter(note => queryWords.every(queryWord => note.SearchStr.includes(queryWord))); }, }, created() { this.fetchNotes(); }, watch: { 'lastSave': function() { this.fetchNotes(); }, }, template: t }