9fd09a8dfb
This provides the UI for the delete user feature introduced in
4229084c62
Placing of the user delete button is not perfect, but can be moved to an
own user tab later on.
Signed-off-by: Sheogorath <sheogorath@shivering-isles.com>
430 lines
12 KiB
JavaScript
430 lines
12 KiB
JavaScript
/* eslint-env browser, jquery */
|
|
/* global moment, serverurl */
|
|
|
|
require('./locale')
|
|
|
|
require('../css/cover.css')
|
|
require('../css/site.css')
|
|
|
|
import {
|
|
checkIfAuth,
|
|
clearLoginState,
|
|
getLoginState,
|
|
resetCheckAuth,
|
|
setloginStateChangeEvent
|
|
} from './lib/common/login'
|
|
|
|
import {
|
|
clearDuplicatedHistory,
|
|
deleteServerHistory,
|
|
getHistory,
|
|
getStorageHistory,
|
|
parseHistory,
|
|
parseServerToHistory,
|
|
parseStorageToHistory,
|
|
postHistoryToServer,
|
|
removeHistory,
|
|
saveHistory,
|
|
saveStorageHistoryToServer
|
|
} from './history'
|
|
|
|
import { saveAs } from 'file-saver'
|
|
import List from 'list.js'
|
|
import S from 'string'
|
|
|
|
const options = {
|
|
valueNames: ['id', 'text', 'timestamp', 'fromNow', 'time', 'tags', 'pinned'],
|
|
item: '<li class="col-xs-12 col-sm-6 col-md-6 col-lg-4">' +
|
|
'<span class="id" style="display:none;"></span>' +
|
|
'<a href="#">' +
|
|
'<div class="item">' +
|
|
'<div class="ui-history-pin fa fa-thumb-tack fa-fw"></div>' +
|
|
'<div class="ui-history-close fa fa-close fa-fw" data-toggle="modal" data-target=".delete-history-modal"></div>' +
|
|
'<div class="content">' +
|
|
'<h4 class="text"></h4>' +
|
|
'<p>' +
|
|
'<i><i class="fa fa-clock-o"></i> visited </i><i class="fromNow"></i>' +
|
|
'<br>' +
|
|
'<i class="timestamp" style="display:none;"></i>' +
|
|
'<i class="time"></i>' +
|
|
'</p>' +
|
|
'<p class="tags"></p>' +
|
|
'</div>' +
|
|
'</div>' +
|
|
'</a>' +
|
|
'</li>',
|
|
page: 18,
|
|
pagination: [{
|
|
outerWindow: 1
|
|
}]
|
|
}
|
|
const historyList = new List('history', options)
|
|
|
|
window.migrateHistoryFromTempCallback = pageInit
|
|
setloginStateChangeEvent(pageInit)
|
|
|
|
pageInit()
|
|
|
|
function pageInit () {
|
|
checkIfAuth(
|
|
data => {
|
|
$('.ui-signin').hide()
|
|
$('.ui-or').hide()
|
|
$('.ui-welcome').show()
|
|
if (data.photo) $('.ui-avatar').prop('src', data.photo).show()
|
|
else $('.ui-avatar').prop('src', '').hide()
|
|
$('.ui-name').html(data.name)
|
|
$('.ui-signout').show()
|
|
$('.ui-history').click()
|
|
parseServerToHistory(historyList, parseHistoryCallback)
|
|
},
|
|
() => {
|
|
$('.ui-signin').show()
|
|
$('.ui-or').show()
|
|
$('.ui-welcome').hide()
|
|
$('.ui-avatar').prop('src', '').hide()
|
|
$('.ui-name').html('')
|
|
$('.ui-signout').hide()
|
|
parseStorageToHistory(historyList, parseHistoryCallback)
|
|
}
|
|
)
|
|
}
|
|
|
|
$('.masthead-nav li').click(function () {
|
|
$(this).siblings().removeClass('active')
|
|
$(this).addClass('active')
|
|
})
|
|
|
|
// prevent empty link change hash
|
|
$('a[href="#"]').click(function (e) {
|
|
e.preventDefault()
|
|
})
|
|
|
|
$('.ui-home').click(function (e) {
|
|
if (!$('#home').is(':visible')) {
|
|
$('.section:visible').hide()
|
|
$('#home').fadeIn()
|
|
}
|
|
})
|
|
|
|
$('.ui-history').click(() => {
|
|
if (!$('#history').is(':visible')) {
|
|
$('.section:visible').hide()
|
|
$('#history').fadeIn()
|
|
}
|
|
})
|
|
|
|
function checkHistoryList () {
|
|
if ($('#history-list').children().length > 0) {
|
|
$('.pagination').show()
|
|
$('.ui-nohistory').hide()
|
|
$('.ui-import-from-browser').hide()
|
|
} else if ($('#history-list').children().length === 0) {
|
|
$('.pagination').hide()
|
|
$('.ui-nohistory').slideDown()
|
|
getStorageHistory(data => {
|
|
if (data && data.length > 0 && getLoginState() && historyList.items.length === 0) {
|
|
$('.ui-import-from-browser').slideDown()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
function parseHistoryCallback (list, notehistory) {
|
|
checkHistoryList()
|
|
// sort by pinned then timestamp
|
|
list.sort('', {
|
|
sortFunction (a, b) {
|
|
const notea = a.values()
|
|
const noteb = b.values()
|
|
if (notea.pinned && !noteb.pinned) {
|
|
return -1
|
|
} else if (!notea.pinned && noteb.pinned) {
|
|
return 1
|
|
} else {
|
|
if (notea.timestamp > noteb.timestamp) {
|
|
return -1
|
|
} else if (notea.timestamp < noteb.timestamp) {
|
|
return 1
|
|
} else {
|
|
return 0
|
|
}
|
|
}
|
|
}
|
|
})
|
|
// parse filter tags
|
|
const filtertags = []
|
|
for (let i = 0, l = list.items.length; i < l; i++) {
|
|
const tags = list.items[i]._values.tags
|
|
if (tags && tags.length > 0) {
|
|
for (let j = 0; j < tags.length; j++) {
|
|
// push info filtertags if not found
|
|
let found = false
|
|
if (filtertags.includes(tags[j])) { found = true }
|
|
if (!found) { filtertags.push(tags[j]) }
|
|
}
|
|
}
|
|
}
|
|
buildTagsFilter(filtertags)
|
|
}
|
|
|
|
// update items whenever list updated
|
|
historyList.on('updated', e => {
|
|
for (let i = 0, l = e.items.length; i < l; i++) {
|
|
const item = e.items[i]
|
|
if (item.visible()) {
|
|
const itemEl = $(item.elm)
|
|
const values = item._values
|
|
const a = itemEl.find('a')
|
|
const pin = itemEl.find('.ui-history-pin')
|
|
const tagsEl = itemEl.find('.tags')
|
|
// parse link to element a
|
|
a.attr('href', `${serverurl}/${values.id}`)
|
|
// parse pinned
|
|
if (values.pinned) {
|
|
pin.addClass('active')
|
|
} else {
|
|
pin.removeClass('active')
|
|
}
|
|
// parse tags
|
|
const tags = values.tags
|
|
if (tags && tags.length > 0 && tagsEl.children().length <= 0) {
|
|
const labels = []
|
|
for (let j = 0; j < tags.length; j++) {
|
|
// push into the item label
|
|
labels.push(`<span class='label label-default'>${tags[j]}</span>`)
|
|
}
|
|
tagsEl.html(labels.join(' '))
|
|
}
|
|
}
|
|
}
|
|
$('.ui-history-close').off('click')
|
|
$('.ui-history-close').on('click', historyCloseClick)
|
|
$('.ui-history-pin').off('click')
|
|
$('.ui-history-pin').on('click', historyPinClick)
|
|
})
|
|
|
|
function historyCloseClick (e) {
|
|
e.preventDefault()
|
|
const id = $(this).closest('a').siblings('span').html()
|
|
const value = historyList.get('id', id)[0]._values
|
|
$('.ui-delete-history-modal-msg').text('Do you really want to delete below history?')
|
|
$('.ui-delete-history-modal-item').html(`<i class="fa fa-file-text"></i> ${value.text}<br><i class="fa fa-clock-o"></i> ${value.time}`)
|
|
clearHistory = false
|
|
deleteId = id
|
|
}
|
|
|
|
function historyPinClick (e) {
|
|
e.preventDefault()
|
|
const $this = $(this)
|
|
const id = $this.closest('a').siblings('span').html()
|
|
const item = historyList.get('id', id)[0]
|
|
const values = item._values
|
|
let pinned = values.pinned
|
|
if (!values.pinned) {
|
|
pinned = true
|
|
item._values.pinned = true
|
|
} else {
|
|
pinned = false
|
|
item._values.pinned = false
|
|
}
|
|
checkIfAuth(() => {
|
|
postHistoryToServer(id, {
|
|
pinned
|
|
}, (err, result) => {
|
|
if (!err) {
|
|
if (pinned) { $this.addClass('active') } else { $this.removeClass('active') }
|
|
}
|
|
})
|
|
}, () => {
|
|
getHistory(notehistory => {
|
|
for (let i = 0; i < notehistory.length; i++) {
|
|
if (notehistory[i].id === id) {
|
|
notehistory[i].pinned = pinned
|
|
break
|
|
}
|
|
}
|
|
saveHistory(notehistory)
|
|
if (pinned) { $this.addClass('active') } else { $this.removeClass('active') }
|
|
})
|
|
})
|
|
}
|
|
|
|
// auto update item fromNow every minutes
|
|
setInterval(updateItemFromNow, 60000)
|
|
|
|
function updateItemFromNow () {
|
|
const items = $('.item').toArray()
|
|
for (let i = 0; i < items.length; i++) {
|
|
const item = $(items[i])
|
|
const timestamp = parseInt(item.find('.timestamp').text())
|
|
item.find('.fromNow').text(moment(timestamp).fromNow())
|
|
}
|
|
}
|
|
|
|
var clearHistory = false
|
|
var deleteId = null
|
|
|
|
function deleteHistory () {
|
|
checkIfAuth(() => {
|
|
deleteServerHistory(deleteId, (err, result) => {
|
|
if (!err) {
|
|
if (clearHistory) {
|
|
historyList.clear()
|
|
checkHistoryList()
|
|
} else {
|
|
historyList.remove('id', deleteId)
|
|
checkHistoryList()
|
|
}
|
|
}
|
|
$('.delete-history-modal').modal('hide')
|
|
deleteId = null
|
|
clearHistory = false
|
|
})
|
|
}, () => {
|
|
if (clearHistory) {
|
|
saveHistory([])
|
|
historyList.clear()
|
|
checkHistoryList()
|
|
deleteId = null
|
|
} else {
|
|
if (!deleteId) return
|
|
getHistory(notehistory => {
|
|
const newnotehistory = removeHistory(deleteId, notehistory)
|
|
saveHistory(newnotehistory)
|
|
historyList.remove('id', deleteId)
|
|
checkHistoryList()
|
|
deleteId = null
|
|
})
|
|
}
|
|
$('.delete-history-modal').modal('hide')
|
|
clearHistory = false
|
|
})
|
|
}
|
|
|
|
$('.ui-delete-history-modal-confirm').click(() => {
|
|
deleteHistory()
|
|
})
|
|
|
|
$('.ui-import-from-browser').click(() => {
|
|
saveStorageHistoryToServer(() => {
|
|
parseStorageToHistory(historyList, parseHistoryCallback)
|
|
})
|
|
})
|
|
|
|
$('.ui-save-history').click(() => {
|
|
getHistory(data => {
|
|
const history = JSON.stringify(data)
|
|
const blob = new Blob([history], {
|
|
type: 'application/json;charset=utf-8'
|
|
})
|
|
saveAs(blob, `hackmd_history_${moment().format('YYYYMMDDHHmmss')}`, true)
|
|
})
|
|
})
|
|
|
|
$('.ui-open-history').bind('change', e => {
|
|
const files = e.target.files || e.dataTransfer.files
|
|
const file = files[0]
|
|
const reader = new FileReader()
|
|
reader.onload = () => {
|
|
const notehistory = JSON.parse(reader.result)
|
|
// console.log(notehistory);
|
|
if (!reader.result) return
|
|
getHistory(data => {
|
|
let mergedata = data.concat(notehistory)
|
|
mergedata = clearDuplicatedHistory(mergedata)
|
|
saveHistory(mergedata)
|
|
parseHistory(historyList, parseHistoryCallback)
|
|
})
|
|
$('.ui-open-history').replaceWith($('.ui-open-history').val('').clone(true))
|
|
}
|
|
reader.readAsText(file)
|
|
})
|
|
|
|
$('.ui-clear-history').click(() => {
|
|
$('.ui-delete-history-modal-msg').text('Do you really want to clear all history?')
|
|
$('.ui-delete-history-modal-item').html('There is no turning back.')
|
|
clearHistory = true
|
|
deleteId = null
|
|
})
|
|
|
|
$('.ui-refresh-history').click(() => {
|
|
const lastTags = $('.ui-use-tags').select2('val')
|
|
$('.ui-use-tags').select2('val', '')
|
|
historyList.filter()
|
|
const lastKeyword = $('.search').val()
|
|
$('.search').val('')
|
|
historyList.search()
|
|
$('#history-list').slideUp('fast')
|
|
$('.pagination').hide()
|
|
|
|
resetCheckAuth()
|
|
historyList.clear()
|
|
parseHistory(historyList, (list, notehistory) => {
|
|
parseHistoryCallback(list, notehistory)
|
|
$('.ui-use-tags').select2('val', lastTags)
|
|
$('.ui-use-tags').trigger('change')
|
|
historyList.search(lastKeyword)
|
|
$('.search').val(lastKeyword)
|
|
checkHistoryList()
|
|
$('#history-list').slideDown('fast')
|
|
})
|
|
})
|
|
|
|
$('.ui-delete-user-modal-cancel').click(() => {
|
|
$('.ui-delete-user').parent().removeClass('active')
|
|
})
|
|
|
|
$('.ui-logout').click(() => {
|
|
clearLoginState()
|
|
location.href = `${serverurl}/logout`
|
|
})
|
|
|
|
let filtertags = []
|
|
$('.ui-use-tags').select2({
|
|
placeholder: $('.ui-use-tags').attr('placeholder'),
|
|
multiple: true,
|
|
data () {
|
|
return {
|
|
results: filtertags
|
|
}
|
|
}
|
|
})
|
|
$('.select2-input').css('width', 'inherit')
|
|
buildTagsFilter([])
|
|
|
|
function buildTagsFilter (tags) {
|
|
for (let i = 0; i < tags.length; i++) {
|
|
tags[i] = {
|
|
id: i,
|
|
text: S(tags[i]).unescapeHTML().s
|
|
}
|
|
}
|
|
filtertags = tags
|
|
}
|
|
$('.ui-use-tags').on('change', function () {
|
|
const tags = []
|
|
const data = $(this).select2('data')
|
|
for (let i = 0; i < data.length; i++) { tags.push(data[i].text) }
|
|
if (tags.length > 0) {
|
|
historyList.filter(item => {
|
|
const values = item.values()
|
|
if (!values.tags) return false
|
|
let found = false
|
|
for (let i = 0; i < tags.length; i++) {
|
|
if (values.tags.includes(tags[i])) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
return found
|
|
})
|
|
} else {
|
|
historyList.filter()
|
|
}
|
|
checkHistoryList()
|
|
})
|
|
|
|
$('.search').keyup(() => {
|
|
checkHistoryList()
|
|
})
|