Added some realtime events to the app
* When a user gets a new shared message, it will popup instantly * When a new website is scraped, it will update in real time * Various other little bug fixes and improvements * Sharing displays correct notes and handles shared notes correctly * Tags were not displaying on notes, they do now. They better.
This commit is contained in:
@@ -22,6 +22,18 @@ io.on('connection', function(socket){
|
||||
|
||||
// console.log('New user ', socket.id)
|
||||
|
||||
//When a user connects, add them to their own room
|
||||
// This allows the server to emit events to that specific user
|
||||
// access socket.io in the controller with req.io
|
||||
socket.on('user_connect', token => {
|
||||
Auth.decodeToken(token)
|
||||
.then(userData => {
|
||||
socket.join(userData.id)
|
||||
}).catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
})
|
||||
|
||||
socket.on('join_room', roomId => {
|
||||
// console.log('Join room ', roomId)
|
||||
socket.join(roomId)
|
||||
|
@@ -226,7 +226,7 @@ Attachment.generateThumbnail = (fileName) => {
|
||||
}
|
||||
|
||||
//Scans text for websites, returns all attachments
|
||||
Attachment.scanTextForWebsites = (userId, noteId, noteText) => {
|
||||
Attachment.scanTextForWebsites = (io, userId, noteId, noteText) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let solrAttachmentText = '' //Final searchable scrape text for note
|
||||
@@ -244,7 +244,7 @@ Attachment.scanTextForWebsites = (userId, noteId, noteText) => {
|
||||
allUrls = []
|
||||
}
|
||||
|
||||
//Every URL needs HTTPS
|
||||
//Every URL needs HTTPS!!!
|
||||
let foundUrls = []
|
||||
allUrls.forEach( (item, index) => {
|
||||
//Every URL should have HTTPS
|
||||
@@ -279,12 +279,17 @@ Attachment.scanTextForWebsites = (userId, noteId, noteText) => {
|
||||
|
||||
//No newly scraped URLs, resolve with looked up attachment text
|
||||
if(foundUrls == null || foundUrls.length == 0){
|
||||
resolve(solrAttachmentText)
|
||||
return resolve(solrAttachmentText)
|
||||
}
|
||||
|
||||
//Process the remaining URLs into attachments
|
||||
Attachment.scrapeUrlsCreateAttachments(userId, noteId, foundUrls).then( freshlyScrapedText => {
|
||||
|
||||
//Once everything is done being scraped, emit new attachment events
|
||||
if(io){
|
||||
io.to(userId).emit('update_counts')
|
||||
}
|
||||
|
||||
solrAttachmentText += freshlyScrapedText
|
||||
resolve(solrAttachmentText)
|
||||
})
|
||||
|
@@ -2,6 +2,7 @@ let db = require('@config/database')
|
||||
|
||||
let Tags = require('@models/Tag')
|
||||
let Attachment = require('@models/Attachment')
|
||||
let ShareNote = require('@models/ShareNote')
|
||||
|
||||
let ProcessText = require('@helpers/ProcessText')
|
||||
|
||||
@@ -157,7 +158,7 @@ Note.reindex = (userId, noteId) => {
|
||||
})
|
||||
}
|
||||
|
||||
Note.update = (userId, noteId, noteText, color, pinned, archived) => {
|
||||
Note.update = (io, userId, noteId, noteText, color, pinned, archived) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
//Prevent note loss if it saves with empty text
|
||||
@@ -192,7 +193,7 @@ Note.update = (userId, noteId, noteText, color, pinned, archived) => {
|
||||
Note.reindex(userId, noteId)
|
||||
|
||||
//Async attachment reindex
|
||||
Attachment.scanTextForWebsites(userId, noteId, noteText)
|
||||
Attachment.scanTextForWebsites(io, userId, noteId, noteText)
|
||||
|
||||
//Send back updated response
|
||||
resolve(rows[0])
|
||||
@@ -258,6 +259,15 @@ Note.delete = (userId, noteId) => {
|
||||
.query('DELETE FROM note_tag WHERE note_tag.note_id = ? AND note_tag.user_id = ?', [noteId,userId])
|
||||
})
|
||||
.then((rows, fields) => {
|
||||
|
||||
//IF there are nots with a matching raw text id, we want to under their share status
|
||||
db.promise().query('SELECT id FROM note WHERE note_raw_text_id = ?',[rawTextId])
|
||||
.then((rows, fields) => {
|
||||
if(rows[0].length == 1){
|
||||
db.promise().query('UPDATE note SET shared = 0 WHERE id = ?', [rows[0][0]['id']])
|
||||
}
|
||||
})
|
||||
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
@@ -325,8 +335,7 @@ Note.get = (userId, noteId) => {
|
||||
note.archived,
|
||||
note.color,
|
||||
count(distinct attachment.id) as attachment_count,
|
||||
note.note_raw_text_id as rawTextId,
|
||||
user.username as shareUsername
|
||||
note.note_raw_text_id as rawTextId
|
||||
FROM note
|
||||
JOIN note_raw_text ON (note_raw_text.id = note.note_raw_text_id)
|
||||
LEFT JOIN attachment ON (note.id = attachment.note_id)
|
||||
@@ -450,7 +459,8 @@ Note.search = (userId, searchQuery, searchTags, fastFilters) => {
|
||||
note.archived,
|
||||
GROUP_CONCAT(DISTINCT tag.text) as tags,
|
||||
GROUP_CONCAT(DISTINCT attachment.file_location) as thumbs,
|
||||
shareUser.username as username
|
||||
shareUser.username as shareUsername,
|
||||
note.shared
|
||||
FROM note
|
||||
JOIN note_raw_text ON (note_raw_text.id = note.note_raw_text_id)
|
||||
LEFT JOIN note_tag ON (note.id = note_tag.note_id)
|
||||
@@ -462,7 +472,10 @@ Note.search = (userId, searchQuery, searchTags, fastFilters) => {
|
||||
|
||||
//Show shared notes
|
||||
if(fastFilters.onlyShowSharedNotes == 1){
|
||||
noteSearchQuery += ' AND note.share_user_id IS NOT NULL' //Show Archived
|
||||
//share_user_id means your shared them, a note with a shared user id filled in means it was shared
|
||||
noteSearchQuery += ` AND share_user_id IS NOT NULL OR (note.shared = 2 AND note.user_id = ?)`
|
||||
searchParams.push(userId)
|
||||
//Show notes shared with you
|
||||
} else {
|
||||
noteSearchQuery += ' AND note.share_user_id IS NULL'
|
||||
}
|
||||
|
@@ -71,7 +71,7 @@ QuickNote.update = (userId, pushText) => {
|
||||
let newText = broken +''+ d.text
|
||||
|
||||
//Save that, then return the new text
|
||||
Note.update(userId, d.id, newText, d.color, d.pinned, d.archived)
|
||||
Note.update(null, userId, d.id, newText, d.color, d.pinned, d.archived)
|
||||
.then( saveResults => {
|
||||
resolve({
|
||||
id:d.id,
|
||||
|
@@ -15,9 +15,10 @@ ShareNote.addUser = (userId, noteId, rawTextId, username) => {
|
||||
|
||||
let shareUserId = null
|
||||
let newNoteShare = null
|
||||
const cleanUser = username.toLowerCase().trim()
|
||||
|
||||
//Check that user actually exists
|
||||
db.promise().query(`SELECT id FROM user WHERE username = ?`, [username])
|
||||
db.promise().query(`SELECT id FROM user WHERE LOWER(username) = ?`, [cleanUser])
|
||||
.then((rows, fields) => {
|
||||
|
||||
if(rows[0].length == 0){
|
||||
@@ -69,11 +70,17 @@ ShareNote.addUser = (userId, noteId, rawTextId, username) => {
|
||||
})
|
||||
.then((rows, fields) => {
|
||||
|
||||
//Update note share status to 2
|
||||
return db.promise()
|
||||
.query('UPDATE note SET shared = 2 WHERE id = ?', [noteId])
|
||||
|
||||
})
|
||||
.then((rows, fields) => {
|
||||
//Success!
|
||||
return resolve(true)
|
||||
return resolve({'success':true, shareUserId})
|
||||
})
|
||||
.catch(error => {
|
||||
// console.log(error)
|
||||
console.log(error)
|
||||
resolve(false)
|
||||
})
|
||||
})
|
||||
@@ -102,25 +109,38 @@ ShareNote.getUsers = (userId, rawTextId) => {
|
||||
// Remove a user from a shared note
|
||||
ShareNote.removeUser = (userId, noteId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
const Note = require('@models/Note')
|
||||
|
||||
let rawTextId = null
|
||||
let removeUserId = null
|
||||
|
||||
//note.id = noteId, share_user_id = userId
|
||||
db.promise()
|
||||
.query('SELECT user_id FROM note WHERE id = ? AND share_user_id = ?', [noteId, userId])
|
||||
.query('SELECT note_raw_text_id, user_id FROM note WHERE id = ? AND share_user_id = ?', [noteId, userId])
|
||||
.then( (rows, fields) => {
|
||||
|
||||
//User has shared this note, with this user
|
||||
if(rows[0].length == 1 && Number.isInteger(rows[0][0]['user_id'])){
|
||||
rawTextId = rows[0][0]['note_raw_text_id']
|
||||
removeUserId = rows[0][0]['user_id']
|
||||
|
||||
Note.delete(rows[0][0]['user_id'], noteId)
|
||||
.then( result => {
|
||||
resolve(result)
|
||||
})
|
||||
//Delete note entry for other user - remove users access
|
||||
if(removeUserId && Number.isInteger(removeUserId)){
|
||||
//Delete this users access to the note
|
||||
return Note.delete(removeUserId, noteId)
|
||||
|
||||
} else {
|
||||
return resolve(false)
|
||||
|
||||
return new Promise((resolve, reject) => { resolve(true) })
|
||||
}
|
||||
|
||||
})
|
||||
.then(stuff => {
|
||||
resolve(true)
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error)
|
||||
resolve(false)
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
|
@@ -17,21 +17,21 @@ Tag.userTags = (userId, searchQuery, searchTags, fastFilters) => {
|
||||
`
|
||||
|
||||
//Show shared notes
|
||||
if(fastFilters.onlyShowSharedNotes == 1){
|
||||
if(fastFilters && fastFilters.onlyShowSharedNotes == 1){
|
||||
query += ' AND note.share_user_id IS NOT NULL' //Show Archived
|
||||
} else {
|
||||
query += ' AND note.share_user_id IS NULL'
|
||||
}
|
||||
|
||||
//Show archived notes, only if fast filter is set, default to not archived
|
||||
if(fastFilters.onlyArchived == 1){
|
||||
if(fastFilters && fastFilters.onlyArchived == 1){
|
||||
query += ' AND note.archived = 1' //Show Archived
|
||||
} else {
|
||||
query += ' AND note.archived = 0' //Exclude archived
|
||||
}
|
||||
|
||||
query += ` GROUP BY tag.id
|
||||
ORDER BY id DESC`
|
||||
ORDER BY usages DESC, text ASC`
|
||||
|
||||
|
||||
db.promise()
|
||||
|
@@ -123,7 +123,7 @@ User.getCounts = (userId) => {
|
||||
db.promise().query(
|
||||
`SELECT
|
||||
SUM(pinned = 1 && archived = 0 && share_user_id IS NULL) AS pinnedNotes,
|
||||
SUM(pinned = 0 && archived = 1 && share_user_id IS NULL) AS archivedNotes,
|
||||
SUM(archived = 1 && share_user_id IS NULL) AS archivedNotes,
|
||||
SUM(share_user_id IS NULL) AS totalNotes,
|
||||
SUM(share_user_id != ?) AS sharedToNotes,
|
||||
SUM( (share_user_id != ? && opened IS null) || (share_user_id != ? && updated > opened) ) AS unreadNotes
|
||||
|
@@ -54,7 +54,7 @@ router.post('/upload', upload.single('file'), function (req, res, next) {
|
||||
.then( uploadResults => {
|
||||
//Reindex note, attachment may have had text
|
||||
Note.reindex(userId, noteId)
|
||||
.then( data => res.send(uploadResults) )
|
||||
.then( data => {res.send(uploadResults)})
|
||||
})
|
||||
|
||||
})
|
||||
|
@@ -23,7 +23,7 @@ router.use(function setUserId (req, res, next) {
|
||||
// Note actions
|
||||
//
|
||||
router.post('/get', function (req, res) {
|
||||
req.io.emit('welcome_homie', 'Welcome, dont poop from excitement')
|
||||
// req.io.emit('welcome_homie', 'Welcome, dont poop from excitement')
|
||||
Notes.get(userId, req.body.noteId)
|
||||
.then( data => {
|
||||
//Join room when user opens note
|
||||
@@ -43,7 +43,7 @@ router.post('/create', function (req, res) {
|
||||
})
|
||||
|
||||
router.post('/update', function (req, res) {
|
||||
Notes.update(userId, req.body.noteId, req.body.text, req.body.color, req.body.pinned, req.body.archived)
|
||||
Notes.update(req.io, userId, req.body.noteId, req.body.text, req.body.color, req.body.pinned, req.body.archived)
|
||||
.then( id => res.send({id}) )
|
||||
})
|
||||
|
||||
@@ -72,7 +72,13 @@ router.post('/getshareusers', function (req, res) {
|
||||
|
||||
router.post('/shareadduser', function (req, res) {
|
||||
ShareNote.addUser(userId, req.body.noteId, req.body.rawTextId, req.body.username)
|
||||
.then(results => res.send(results))
|
||||
.then( ({success, shareUserId}) => {
|
||||
|
||||
//Emit update count event to user shared with - so they see the note in real time
|
||||
req.io.to(shareUserId).emit('update_counts')
|
||||
|
||||
res.send(success)
|
||||
})
|
||||
})
|
||||
|
||||
router.post('/shareremoveuser', function (req, res) {
|
||||
|
Reference in New Issue
Block a user