fcee24a61d
Tweaked a lot of styles and added some cool animations Added a little to the help text Quickly adding a note, saving and closing no longer causes half formed or empty notes to appear Close Editor animation Display cards text show at the bottom of card Added a delete function, and it works Added browser title attributes More debugging and error checking on scraped links Updated not search to display title and text below the title
278 lines
8.0 KiB
JavaScript
278 lines
8.0 KiB
JavaScript
let db = require('@config/database')
|
|
|
|
let Tags = require('@models/Tags')
|
|
let Attachment = require('@models/Attachment')
|
|
|
|
var rp = require('request-promise');
|
|
var SolrNode = require('solr-node');
|
|
|
|
let Notes = module.exports = {}
|
|
|
|
// Create client
|
|
var client = new SolrNode({
|
|
host: '127.0.0.1',
|
|
port: '8983',
|
|
core: 'note',
|
|
protocol: 'http'
|
|
});
|
|
|
|
Notes.create = (userId, noteText) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if(userId == null || userId < 10){ reject('User Id required to create note') }
|
|
|
|
const created = Math.round((+new Date)/1000)
|
|
|
|
db.promise()
|
|
.query('INSERT INTO notes (user, text, created) VALUES (?,?,?)', [userId, noteText, created])
|
|
.then((rows, fields) => {
|
|
resolve(rows[0].insertId) //Only return the new note ID when creating a new note
|
|
})
|
|
.catch(console.log)
|
|
})
|
|
}
|
|
|
|
Notes.update = (userId, noteId, noteText, fancyInput, color) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const now = Math.round((+new Date)/1000)
|
|
|
|
db.promise()
|
|
.query('UPDATE notes SET text = ?, raw_input = ?, updated = ?, color = ? WHERE id = ? AND user = ? LIMIT 1', [noteText, fancyInput, now, color, noteId, userId])
|
|
.then((rows, fields) => {
|
|
|
|
//Process note text and attachment data
|
|
Attachment.scanTextForWebsites(userId, noteId, noteText).then( attachmentText => {
|
|
//
|
|
// Update Solr index
|
|
//
|
|
Tags.string(userId, noteId).then(tagString => {
|
|
// JSON Data
|
|
var data = {
|
|
'id': noteId,//string - ID of note
|
|
'user_id': userId,//int
|
|
'note_text': noteText,
|
|
'notes_tags': tagString,
|
|
'attachment_text': attachmentText,
|
|
};
|
|
// Update document to Solr server
|
|
client.update(data, function(err, result) {
|
|
if (err) { console.log(err); return; }
|
|
console.log('Note Solr Update, node/solrid ('+noteId+'):');
|
|
console.log(result.responseHeader)
|
|
});
|
|
|
|
})
|
|
})
|
|
|
|
|
|
//Send back updated response
|
|
resolve(rows[0])
|
|
})
|
|
.catch(console.log)
|
|
})
|
|
}
|
|
|
|
Notes.delete = (userId, noteId) => {
|
|
return new Promise((resolve, reject) => {
|
|
// DELETE FROM notes WHERE notes.id = 290 AND notes.user = 61;
|
|
// DELETE FROM attachment WHERE attachment.note_id = 290 AND attachment.user_id = 61;
|
|
// DELETE FROM notes_tags WHERE notes_tags.note_id = 290 AND notes_tags.user_id = 61;
|
|
db.promise().query('DELETE FROM notes WHERE notes.id = ? AND notes.user = ?', [noteId,userId])
|
|
.then((rows, fields) => {
|
|
db.promise().query('DELETE FROM attachment WHERE attachment.note_id = ? AND attachment.user_id = ?', [noteId,userId])
|
|
.then((rows, fields)=> {
|
|
db.promise().query('DELETE FROM notes_tags WHERE notes_tags.note_id = ? AND notes_tags.user_id = ?', [noteId,userId])
|
|
.then((rows, fields)=> {
|
|
console.log('All Deleted')
|
|
resolve(true)
|
|
})
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
Notes.get = (userId, noteId) => {
|
|
return new Promise((resolve, reject) => {
|
|
db.promise()
|
|
.query('SELECT text, updated, raw_input, color FROM notes WHERE user = ? AND id = ? LIMIT 1', [userId,noteId])
|
|
.then((rows, fields) => {
|
|
resolve(rows[0][0])
|
|
})
|
|
.catch(console.log)
|
|
})
|
|
}
|
|
|
|
Notes.getLatest = (userId) => {
|
|
return new Promise((resolve, reject) => {
|
|
db.promise()
|
|
.query('SELECT id, SUBSTRING(text, 1, 100) as text FROM notes WHERE user = ? ORDER BY updated DESC, created DESC', [userId])
|
|
.then((rows, fields) => {
|
|
resolve(rows[0])
|
|
})
|
|
.catch(console.log)
|
|
})
|
|
}
|
|
|
|
Notes.solrQuery = (userId, searchQuery, searchTags) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
|
if(searchQuery != '' && searchQuery != null){
|
|
let urlQuery = `/solr/note/select?hl.fl=note_text&hl=on&q=user_id:${userId} AND note_text:${searchQuery}&wt=json`
|
|
urlQuery = `/solr/note/select?
|
|
hl.fl=note_text,attachment_text,notes_tags&
|
|
hl=on&
|
|
q=user_id:${userId} AND (note_text:${searchQuery} OR attachment_text:${searchQuery} OR notes_tags:${searchQuery})&
|
|
wt=json&
|
|
fl=id&
|
|
hl.fl=note_text,attachment_text,notes_tags&
|
|
hl.snippets=20&
|
|
hl.maxAnalyzedChars=100000`
|
|
|
|
rp('http://127.0.0.1:8983'+urlQuery)
|
|
.then(function (htmlString) {
|
|
let solrResult = JSON.parse(htmlString)
|
|
resolve(solrResult)
|
|
})
|
|
} else {
|
|
resolve([])
|
|
}
|
|
})
|
|
}
|
|
|
|
Notes.search = (userId, searchQuery, searchTags) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
|
|
|
//Define return data objects
|
|
let returnData = {
|
|
'notes':[],
|
|
'tags':[]
|
|
}
|
|
|
|
|
|
Notes.solrQuery(userId, searchQuery, searchTags).then( solrResult => {
|
|
|
|
let highlights = solrResult.highlighting
|
|
|
|
//Parse Note ID's from solr search
|
|
let solrNoteIds = []
|
|
if(solrResult.response){
|
|
solrResult.response.docs.forEach(item => {
|
|
solrNoteIds.push(parseInt(item.id))
|
|
})
|
|
}
|
|
|
|
//Default note lookup gets all notes
|
|
let noteSearchQuery = `
|
|
SELECT notes.id, SUBSTRING(notes.text, 1, 400) as text, updated, color, count(distinct notes_tags.id) as tag_count, count(distinct attachment.id) as attachment_count
|
|
FROM notes
|
|
LEFT JOIN notes_tags ON (notes.id = notes_tags.note_id)
|
|
LEFT JOIN attachment ON (notes.id = attachment.note_id AND attachment.attachment_type = 1)
|
|
WHERE user = ?`
|
|
let searchParams = [userId]
|
|
|
|
if(solrNoteIds.length > 0){
|
|
searchParams.push(solrNoteIds)
|
|
noteSearchQuery += ' AND notes.id IN (?)'
|
|
}
|
|
|
|
// if(searchQuery != ''){
|
|
// //If a search query is defined, search notes for that word
|
|
// searchParams.push('%'+searchQuery+'%')
|
|
// noteSearchQuery += ' AND text LIKE ?'
|
|
// }
|
|
if(searchTags.length > 0){
|
|
//If tags are passed, use those tags in search
|
|
searchParams.push(searchTags)
|
|
noteSearchQuery += ' AND notes_tags.tag_id IN (?)'
|
|
}
|
|
|
|
//Finish up note query
|
|
noteSearchQuery += ' GROUP BY notes.id ORDER BY updated DESC, created DESC, id DESC'
|
|
|
|
db.promise()
|
|
.query(noteSearchQuery, searchParams)
|
|
.then((noteRows, noteFields) => {
|
|
|
|
//Push all notes
|
|
returnData['notes'] = noteRows[0]
|
|
|
|
//pull out all note ids so we can fetch all tags for those notes
|
|
let noteIds = []
|
|
returnData['notes'].forEach(note => {
|
|
|
|
//Grab note ID for finding tags
|
|
noteIds.push(note.id)
|
|
|
|
//Attempt to pull string out of first tag in note
|
|
let reg = note.text.match(/<([\w]+)[^>]*>(.*?)<\/\1>/g)
|
|
|
|
//Pull out first html tag contents, that is the title
|
|
if(reg != null && reg[0]){
|
|
note.title = reg[0] //First line from HTML
|
|
} else {
|
|
note.title = note.text //Entire note
|
|
}
|
|
|
|
//Clean up html title
|
|
note.title = note.title
|
|
.replace(/&[#A-Za-z0-9]+;/g,'') //Rip out all HTML entities
|
|
.replace(/<[^>]+>/g, '') //Rip out all HTML tags
|
|
|
|
//Generate Subtext
|
|
if(note.text != '' && note.title != ''){
|
|
note.subtext = note.text
|
|
.replace(/&[#A-Za-z0-9]+;/g,' ') //Rip out all HTML entities
|
|
.replace(/<[^>]+>/g, ' ') //Rip out all HTML tags
|
|
.replace(/\s+/g, ' ') //Remove all whitespace
|
|
.substring(note.title.length + 2)
|
|
}
|
|
|
|
|
|
note.note_highlights = []
|
|
note.attachment_highlights = []
|
|
note.tag_highlights = []
|
|
|
|
//Push in solr highlights
|
|
if(highlights && highlights[note.id] && highlights[note.id].note_text){
|
|
note['note_highlights'] = highlights[note.id].note_text
|
|
}
|
|
if(highlights && highlights[note.id] && highlights[note.id].attachment_text){
|
|
note['attachment_highlights'] = highlights[note.id].attachment_text
|
|
}
|
|
if(highlights && highlights[note.id] && highlights[note.id].notes_tags){
|
|
note['tag_highlights'] = highlights[note.id].notes_tags
|
|
}
|
|
})
|
|
|
|
//If no notes are returned, there are no tags, return empty
|
|
if(noteIds.length == 0){
|
|
resolve(returnData)
|
|
}
|
|
|
|
//Only show tags of selected notes
|
|
db.promise()
|
|
.query(`SELECT tags.id, tags.text, count(tags.id) as usages FROM notes_tags
|
|
JOIN tags ON (tags.id = notes_tags.tag_id)
|
|
WHERE notes_tags.user_id = ?
|
|
AND note_id IN (?)
|
|
GROUP BY tags.id
|
|
ORDER BY usages DESC;`,[userId, noteIds])
|
|
.then((tagRows, tagFields) => {
|
|
|
|
returnData['tags'] = tagRows[0]
|
|
|
|
resolve(returnData)
|
|
})
|
|
.catch(console.log)
|
|
|
|
})
|
|
.catch(console.log)
|
|
|
|
})
|
|
.catch(console.log)
|
|
|
|
})
|
|
} |