mirror of https://github.com/status-im/codimd.git
refactor
This commit is contained in:
parent
e4855cdb3c
commit
f83b4b77fd
|
@ -3973,6 +3973,21 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz",
|
||||||
"integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ=="
|
"integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ=="
|
||||||
},
|
},
|
||||||
|
"@types/jquery": {
|
||||||
|
"version": "3.5.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.6.tgz",
|
||||||
|
"integrity": "sha512-SmgCQRzGPId4MZQKDj9Hqc6kSXFNWZFHpELkyK8AQhf8Zr6HKfCzFv9ZC1Fv3FyQttJZOlap3qYb12h61iZAIg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/sizzle": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/js-cookie": {
|
||||||
|
"version": "2.2.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz",
|
||||||
|
"integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/json-schema": {
|
"@types/json-schema": {
|
||||||
"version": "7.0.7",
|
"version": "7.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
|
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
|
||||||
|
@ -4014,6 +4029,12 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/list.js": {
|
||||||
|
"version": "2.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/list.js/-/list.js-2.3.1.tgz",
|
||||||
|
"integrity": "sha512-yKwk95g7K5mKl9i5/rrkrbwoXvRtiC/gd4b1qU8mbfxanSkPsCSqAvmgaXS+tdj66+l5BMvdargh57pdOH+yBg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/lodash": {
|
"@types/lodash": {
|
||||||
"version": "4.14.170",
|
"version": "4.14.170",
|
||||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz",
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz",
|
||||||
|
@ -4118,6 +4139,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
|
||||||
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
|
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
|
||||||
},
|
},
|
||||||
|
"@types/select2": {
|
||||||
|
"version": "4.0.54",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/select2/-/select2-4.0.54.tgz",
|
||||||
|
"integrity": "sha512-xq8c3zsKktym2b9XbDLUWBDyX0WyWjKzeFsDQHkM9p6NfxJza4g2Ud1bheTKNXpHNyVPUrfGwDEMN7JBe3gQbw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/jquery": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/serve-static": {
|
"@types/serve-static": {
|
||||||
"version": "1.13.9",
|
"version": "1.13.9",
|
||||||
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz",
|
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz",
|
||||||
|
@ -4127,6 +4157,12 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/sizzle": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/socket.io": {
|
"@types/socket.io": {
|
||||||
"version": "2.1.13",
|
"version": "2.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/@types/socket.io/-/socket.io-2.1.13.tgz",
|
||||||
|
@ -4147,6 +4183,12 @@
|
||||||
"socket.io-parser": "*"
|
"socket.io-parser": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/store": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/store/-/store-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-ZPHnXkzmGMfk+pHqAGzTSpA9CbsHmJLgkvOl5w52LZ0XTxB1ZIHWZzQ7lEtjTNWScBbsQekg8TjApMXkMe4nkw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@types/validator": {
|
"@types/validator": {
|
||||||
"version": "13.1.4",
|
"version": "13.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.1.4.tgz",
|
||||||
|
@ -19059,13 +19101,21 @@
|
||||||
"integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM="
|
"integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM="
|
||||||
},
|
},
|
||||||
"xss": {
|
"xss": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.9.tgz",
|
||||||
"integrity": "sha512-6Q9TPBeNyoTRxgZFk5Ggaepk/4vUOYdOsIUYvLehcsIZTFjaavbVnsuAkLA5lIFuug5hw8zxcB9tm01gsjph2A==",
|
"integrity": "sha512-2t7FahYnGJys6DpHLhajusId7R0Pm2yTmuL0GV9+mV0ZlaLSnb2toBmppATfg5sWIhZQGlsTLoecSzya+l4EAQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"commander": "^2.9.0",
|
"commander": "^2.20.3",
|
||||||
"cssfilter": "0.0.10"
|
"cssfilter": "0.0.10"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"commander": {
|
||||||
|
"version": "2.20.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||||
|
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"xtend": {
|
"xtend": {
|
||||||
|
|
|
@ -119,6 +119,9 @@
|
||||||
"@types/express": "4.17.9",
|
"@types/express": "4.17.9",
|
||||||
"@types/express-flash": "0.0.2",
|
"@types/express-flash": "0.0.2",
|
||||||
"@types/express-session": "^1.17.3",
|
"@types/express-session": "^1.17.3",
|
||||||
|
"@types/jquery": "^3.5.6",
|
||||||
|
"@types/js-cookie": "^2.2.7",
|
||||||
|
"@types/list.js": "^2.3.1",
|
||||||
"@types/lodash": "^4.14.170",
|
"@types/lodash": "^4.14.170",
|
||||||
"@types/markdown-pdf": "^9.0.0",
|
"@types/markdown-pdf": "^9.0.0",
|
||||||
"@types/mime-types": "^2.1.0",
|
"@types/mime-types": "^2.1.0",
|
||||||
|
@ -128,7 +131,9 @@
|
||||||
"@types/passport.socketio": "^3.7.5",
|
"@types/passport.socketio": "^3.7.5",
|
||||||
"@types/qs": "^6.9.6",
|
"@types/qs": "^6.9.6",
|
||||||
"@types/randomcolor": "^0.5.5",
|
"@types/randomcolor": "^0.5.5",
|
||||||
|
"@types/select2": "^4.0.54",
|
||||||
"@types/socket.io": "^2.1.13",
|
"@types/socket.io": "^2.1.13",
|
||||||
|
"@types/store": "^2.0.2",
|
||||||
"@types/validator": "^13.1.4",
|
"@types/validator": "^13.1.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.26.1",
|
"@typescript-eslint/eslint-plugin": "^4.26.1",
|
||||||
"@typescript-eslint/parser": "^4.26.1",
|
"@typescript-eslint/parser": "^4.26.1",
|
||||||
|
@ -222,7 +227,7 @@
|
||||||
"webpack-cli": "~4.7.2",
|
"webpack-cli": "~4.7.2",
|
||||||
"webpack-merge": "~5.8.0",
|
"webpack-merge": "~5.8.0",
|
||||||
"wurl": "~2.5.3",
|
"wurl": "~2.5.3",
|
||||||
"xss": "~1.0.6"
|
"xss": "~1.0.9"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"bufferutil": "~4.0.0",
|
"bufferutil": "~4.0.0",
|
||||||
|
|
|
@ -1,38 +1,115 @@
|
||||||
/* eslint-env browser, jquery */
|
import {saveAs} from 'file-saver'
|
||||||
/* global moment, serverurl */
|
import $ from 'jquery'
|
||||||
|
import List from 'list.js'
|
||||||
|
import unescapeHTML from 'lodash/unescape'
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
import {
|
import '../css/cover.css'
|
||||||
checkIfAuth,
|
import '../css/site.css'
|
||||||
clearLoginState,
|
|
||||||
getLoginState,
|
|
||||||
resetCheckAuth,
|
|
||||||
setloginStateChangeEvent
|
|
||||||
} from './lib/common/login'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
clearDuplicatedHistory,
|
clearDuplicatedHistory,
|
||||||
deleteServerHistory,
|
clearServerHistoryAsync,
|
||||||
|
deleteServerHistoryAsync,
|
||||||
getHistory,
|
getHistory,
|
||||||
|
getHistoryAsync,
|
||||||
getStorageHistory,
|
getStorageHistory,
|
||||||
|
NoteHistory,
|
||||||
parseHistory,
|
parseHistory,
|
||||||
parseServerToHistory,
|
parseServerToHistory,
|
||||||
parseStorageToHistory,
|
parseStorageToHistory,
|
||||||
postHistoryToServer,
|
postHistoryToServerAsync,
|
||||||
removeHistory,
|
removeHistory,
|
||||||
saveHistory,
|
saveHistory,
|
||||||
saveStorageHistoryToServer
|
saveStorageHistoryToServer
|
||||||
} from './history'
|
} from './history'
|
||||||
|
|
||||||
import { saveAs } from 'file-saver'
|
import {
|
||||||
import List from 'list.js'
|
checkIfAuth,
|
||||||
import unescapeHTML from 'lodash/unescape'
|
clearLoginState,
|
||||||
|
getLoginState,
|
||||||
|
getLoginUserProfile, isLogin,
|
||||||
|
resetCheckAuth,
|
||||||
|
setLoginStateChangeEvent
|
||||||
|
} from './lib/common/login'
|
||||||
|
import {serverurl} from "./lib/config";
|
||||||
|
|
||||||
require('./locale')
|
import {initializeLocaleDropdown} from "./locale";
|
||||||
|
|
||||||
require('../css/cover.css')
|
initializeLocaleDropdown()
|
||||||
require('../css/site.css')
|
|
||||||
|
|
||||||
const options = {
|
setLoginStateChangeEvent(pageInit)
|
||||||
|
|
||||||
|
void pageInit()
|
||||||
|
|
||||||
|
async function pageInit() {
|
||||||
|
try {
|
||||||
|
const profile = await getLoginUserProfile()
|
||||||
|
$('.ui-signin').hide()
|
||||||
|
$('.ui-or').hide()
|
||||||
|
$('.ui-welcome').show()
|
||||||
|
if (profile.photo) $('.ui-avatar').prop('src', profile.photo).show()
|
||||||
|
else $('.ui-avatar').prop('src', '').hide()
|
||||||
|
$('.ui-name').html(profile.name)
|
||||||
|
$('.ui-signout').show()
|
||||||
|
navSection.historyPageBtn.trigger('click')
|
||||||
|
parseServerToHistory(historyList, parseHistoryCallback)
|
||||||
|
} catch (err) {
|
||||||
|
$('.ui-signin').show()
|
||||||
|
$('.ui-or').show()
|
||||||
|
$('.ui-welcome').hide()
|
||||||
|
$('.ui-avatar').prop('src', '').hide()
|
||||||
|
$('.ui-name').html('')
|
||||||
|
$('.ui-signout').hide()
|
||||||
|
parseStorageToHistory(historyList, parseHistoryCallback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent empty link change hash
|
||||||
|
$('a[href="#"]').on('click', function (e) {
|
||||||
|
e.preventDefault()
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* masthead nav section
|
||||||
|
*/
|
||||||
|
const navSection = {
|
||||||
|
introPageBtn: $('.ui-home'),
|
||||||
|
historyPageBtn: $('.ui-history'),
|
||||||
|
deleteUserModalCancel: $('.ui-delete-user-modal-cancel'),
|
||||||
|
logoutBtn: $('.ui-logout')
|
||||||
|
}
|
||||||
|
const introSection = $('#home')
|
||||||
|
const historySection = $('#history')
|
||||||
|
|
||||||
|
navSection.introPageBtn.on('click', function (e) {
|
||||||
|
if (!introSection.is(':visible')) {
|
||||||
|
$('.section:visible').hide()
|
||||||
|
introSection.fadeIn()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
navSection.historyPageBtn.on('click', () => {
|
||||||
|
if (!historySection.is(':visible')) {
|
||||||
|
$('.section:visible').hide()
|
||||||
|
historySection.fadeIn()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
navSection.deleteUserModalCancel.on('click', () => {
|
||||||
|
$('.ui-delete-user').parent().removeClass('active')
|
||||||
|
})
|
||||||
|
|
||||||
|
navSection.logoutBtn.on('click', () => {
|
||||||
|
clearLoginState()
|
||||||
|
location.href = `${serverurl}/logout`
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* History Section
|
||||||
|
*/
|
||||||
|
|
||||||
|
const options: List.ListOptions = {
|
||||||
valueNames: ['id', 'text', 'timestamp', 'fromNow', 'time', 'tags', 'pinned'],
|
valueNames: ['id', 'text', 'timestamp', 'fromNow', 'time', 'tags', 'pinned'],
|
||||||
item: `<li class="col-xs-12 col-sm-6 col-md-6 col-lg-4">
|
item: `<li class="col-xs-12 col-sm-6 col-md-6 col-lg-4">
|
||||||
<span class="id" style="display:none;"></span>
|
<span class="id" style="display:none;"></span>
|
||||||
|
@ -54,87 +131,169 @@ const options = {
|
||||||
</a>
|
</a>
|
||||||
</li>`,
|
</li>`,
|
||||||
page: 18,
|
page: 18,
|
||||||
pagination: [{
|
pagination: {
|
||||||
outerWindow: 1
|
outerWindow: 1
|
||||||
}]
|
}
|
||||||
}
|
}
|
||||||
const historyList = new List('history', options)
|
const historyList = new List('history', options)
|
||||||
|
|
||||||
window.migrateHistoryFromTempCallback = pageInit
|
/**
|
||||||
setloginStateChangeEvent(pageInit)
|
* History Tool Bar
|
||||||
|
*/
|
||||||
pageInit()
|
const historyListContainer = $('#history-list')
|
||||||
|
const historyPagination = $('.pagination')
|
||||||
function pageInit () {
|
const historyToolbar = {
|
||||||
checkIfAuth(
|
importFromBrowserBtn: $('.ui-import-from-browser'),
|
||||||
data => {
|
clearHistoryBtn: $('.ui-clear-history'),
|
||||||
$('.ui-signin').hide()
|
saveHistoryBtn: $('.ui-save-history'),
|
||||||
$('.ui-or').hide()
|
openHistoryFile: $('.ui-open-history'),
|
||||||
$('.ui-welcome').show()
|
tagFilter: $('.ui-use-tags')
|
||||||
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')
|
* clear all history
|
||||||
$(this).addClass('active')
|
*/
|
||||||
|
historyToolbar.clearHistoryBtn.on('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.')
|
||||||
|
isClearAllHistory = true
|
||||||
|
deleteHistoryModalTargetId = null
|
||||||
})
|
})
|
||||||
|
|
||||||
// prevent empty link change hash
|
historyToolbar.importFromBrowserBtn.on('click', () => {
|
||||||
$('a[href="#"]').click(function (e) {
|
saveStorageHistoryToServer(() => {
|
||||||
e.preventDefault()
|
parseStorageToHistory(historyList, parseHistoryCallback)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
$('.ui-home').click(function (e) {
|
historyToolbar.saveHistoryBtn.on('click', async function () {
|
||||||
if (!$('#home').is(':visible')) {
|
const history = JSON.stringify(await getHistoryAsync())
|
||||||
$('.section:visible').hide()
|
const blob = new Blob([history], {
|
||||||
$('#home').fadeIn()
|
type: 'application/json;charset=utf-8'
|
||||||
}
|
})
|
||||||
|
saveAs(blob, `codimd_history_${moment().format('YYYYMMDDHHmmss')}`, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
$('.ui-history').click(() => {
|
historyToolbar.openHistoryFile.on('change', function (e) {
|
||||||
if (!$('#history').is(':visible')) {
|
const files = e.target.files || e.dataTransfer.files
|
||||||
$('.section:visible').hide()
|
const file = files[0]
|
||||||
$('#history').fadeIn()
|
const reader = new FileReader()
|
||||||
}
|
reader.onload = () => {
|
||||||
})
|
const notehistory = JSON.parse(reader.result)
|
||||||
|
// console.log(notehistory);
|
||||||
function checkHistoryList () {
|
if (!reader.result) return
|
||||||
if ($('#history-list').children().length > 0) {
|
getHistory(data => {
|
||||||
$('.pagination').show()
|
let mergedata = data.concat(notehistory)
|
||||||
$('.ui-nohistory').hide()
|
mergedata = clearDuplicatedHistory(mergedata)
|
||||||
$('.ui-import-from-browser').hide()
|
saveHistory(mergedata)
|
||||||
} else if ($('#history-list').children().length === 0) {
|
parseHistory(historyList, parseHistoryCallback)
|
||||||
$('.pagination').hide()
|
|
||||||
$('.ui-nohistory').slideDown()
|
|
||||||
getStorageHistory(data => {
|
|
||||||
if (data && data.length > 0 && getLoginState() && historyList.items.length === 0) {
|
|
||||||
$('.ui-import-from-browser').slideDown()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
historyToolbar.openHistoryFile.replaceWith(historyToolbar.openHistoryFile.val('').clone(true))
|
||||||
}
|
}
|
||||||
|
reader.readAsText(file)
|
||||||
|
})
|
||||||
|
|
||||||
|
$('.ui-refresh-history').on('click', () => {
|
||||||
|
const lastTags = historyToolbar.tagFilter.select2('val')
|
||||||
|
historyToolbar.tagFilter.select2('val', '')
|
||||||
|
historyList.filter()
|
||||||
|
const lastKeyword = $('.search').val()
|
||||||
|
$('.search').val('')
|
||||||
|
historyList.search()
|
||||||
|
historyListContainer.slideUp('fast')
|
||||||
|
historyPagination.hide()
|
||||||
|
|
||||||
|
resetCheckAuth()
|
||||||
|
historyList.clear()
|
||||||
|
parseHistory(historyList, (list, notehistory) => {
|
||||||
|
parseHistoryCallback(list, notehistory)
|
||||||
|
historyToolbar.tagFilter.select2('val', lastTags)
|
||||||
|
historyToolbar.tagFilter.trigger('change')
|
||||||
|
historyList.search(lastKeyword)
|
||||||
|
$('.search').val(lastKeyword)
|
||||||
|
refreshHistoryUIElementVisibility()
|
||||||
|
historyListContainer.slideDown('fast')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
let filtertags = []
|
||||||
|
historyToolbar.tagFilter.select2({
|
||||||
|
placeholder: historyToolbar.tagFilter.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: unescapeHTML(tags[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filtertags = tags
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseHistoryCallback (list, notehistory) {
|
|
||||||
checkHistoryList()
|
historyToolbar.tagFilter.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()
|
||||||
|
}
|
||||||
|
refreshHistoryUIElementVisibility()
|
||||||
|
})
|
||||||
|
|
||||||
|
$('.search').on('keyup', () => {
|
||||||
|
refreshHistoryUIElementVisibility()
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
function refreshHistoryUIElementVisibility() {
|
||||||
|
if (historyListContainer.children().length > 0) {
|
||||||
|
historyPagination.show()
|
||||||
|
$('.ui-nohistory').hide()
|
||||||
|
historyToolbar.importFromBrowserBtn.hide()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
historyPagination.hide()
|
||||||
|
$('.ui-nohistory').slideDown()
|
||||||
|
getStorageHistory(data => {
|
||||||
|
if (data && data.length > 0 && getLoginState() && historyList.items.length === 0) {
|
||||||
|
historyToolbar.importFromBrowserBtn.slideDown()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseHistoryCallback(list, notehistory) {
|
||||||
|
refreshHistoryUIElementVisibility()
|
||||||
// sort by pinned then timestamp
|
// sort by pinned then timestamp
|
||||||
list.sort('', {
|
list.sort('', {
|
||||||
sortFunction (a, b) {
|
sortFunction(a, b) {
|
||||||
const notea = a.values()
|
const notea = a.values()
|
||||||
const noteb = b.values()
|
const noteb = b.values()
|
||||||
if (notea.pinned && !noteb.pinned) {
|
if (notea.pinned && !noteb.pinned) {
|
||||||
|
@ -160,8 +319,12 @@ function parseHistoryCallback (list, notehistory) {
|
||||||
for (let j = 0; j < tags.length; j++) {
|
for (let j = 0; j < tags.length; j++) {
|
||||||
// push info filtertags if not found
|
// push info filtertags if not found
|
||||||
let found = false
|
let found = false
|
||||||
if (filtertags.includes(tags[j])) { found = true }
|
if (filtertags.includes(tags[j])) {
|
||||||
if (!found) { filtertags.push(tags[j]) }
|
found = true
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
filtertags.push(tags[j])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,7 +332,7 @@ function parseHistoryCallback (list, notehistory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// update items whenever list updated
|
// update items whenever list updated
|
||||||
historyList.on('updated', e => {
|
historyList.on('updated', function (e) {
|
||||||
for (let i = 0, l = e.items.length; i < l; i++) {
|
for (let i = 0, l = e.items.length; i < l; i++) {
|
||||||
const item = e.items[i]
|
const item = e.items[i]
|
||||||
if (item.visible()) {
|
if (item.visible()) {
|
||||||
|
@ -189,7 +352,7 @@ historyList.on('updated', e => {
|
||||||
// parse tags
|
// parse tags
|
||||||
const tags = values.tags
|
const tags = values.tags
|
||||||
if (tags && tags.length > 0 && tagsEl.children().length <= 0) {
|
if (tags && tags.length > 0 && tagsEl.children().length <= 0) {
|
||||||
const labels = []
|
const labels: string[] = []
|
||||||
for (let j = 0; j < tags.length; j++) {
|
for (let j = 0; j < tags.length; j++) {
|
||||||
// push into the item label
|
// push into the item label
|
||||||
labels.push(`<span class='label label-default'>${tags[j]}</span>`)
|
labels.push(`<span class='label label-default'>${tags[j]}</span>`)
|
||||||
|
@ -199,22 +362,66 @@ historyList.on('updated', e => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$('.ui-history-close').off('click')
|
$('.ui-history-close').off('click')
|
||||||
$('.ui-history-close').on('click', historyCloseClick)
|
$('.ui-history-close').on('click', onHistoryCloseClick)
|
||||||
$('.ui-history-pin').off('click')
|
$('.ui-history-pin').off('click')
|
||||||
$('.ui-history-pin').on('click', historyPinClick)
|
$('.ui-history-pin').on('click', historyPinClick)
|
||||||
})
|
})
|
||||||
|
|
||||||
function historyCloseClick (e) {
|
/**
|
||||||
|
* Delete History Modal
|
||||||
|
*/
|
||||||
|
let isClearAllHistory: boolean = false
|
||||||
|
let deleteHistoryModalTargetId: string | null = null
|
||||||
|
|
||||||
|
function onHistoryCloseClick(this: HTMLElement, e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const id = $(this).closest('a').siblings('span').html()
|
const id: string = $(this).closest('a').siblings('span').html()
|
||||||
const value = historyList.get('id', id)[0]._values
|
const value: NoteHistory = historyList.get('id', id)[0].values()
|
||||||
$('.ui-delete-history-modal-msg').text('Do you really want to delete below history?')
|
$('.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}`)
|
$('.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
|
isClearAllHistory = false
|
||||||
deleteId = id
|
deleteHistoryModalTargetId = id
|
||||||
}
|
}
|
||||||
|
|
||||||
function historyPinClick (e) {
|
$('.ui-delete-history-modal-confirm').on('click', async function () {
|
||||||
|
if (await isLogin()) {
|
||||||
|
if (isClearAllHistory) {
|
||||||
|
await clearServerHistoryAsync()
|
||||||
|
} else {
|
||||||
|
if (deleteHistoryModalTargetId) {
|
||||||
|
await deleteServerHistoryAsync(deleteHistoryModalTargetId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refreshHistoryUIElementVisibility()
|
||||||
|
$('.delete-history-modal').modal('hide')
|
||||||
|
deleteHistoryModalTargetId = null
|
||||||
|
isClearAllHistory = false
|
||||||
|
} else {
|
||||||
|
if (isClearAllHistory) {
|
||||||
|
saveHistory([])
|
||||||
|
historyList.clear()
|
||||||
|
refreshHistoryUIElementVisibility()
|
||||||
|
deleteHistoryModalTargetId = null
|
||||||
|
} else {
|
||||||
|
if (!deleteHistoryModalTargetId) return
|
||||||
|
getHistory(notehistory => {
|
||||||
|
const newnotehistory = removeHistory(deleteHistoryModalTargetId, notehistory)
|
||||||
|
saveHistory(newnotehistory)
|
||||||
|
historyList.remove('id', deleteHistoryModalTargetId)
|
||||||
|
refreshHistoryUIElementVisibility()
|
||||||
|
deleteHistoryModalTargetId = null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
$('.delete-history-modal').modal('hide')
|
||||||
|
isClearAllHistory = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pin History
|
||||||
|
*/
|
||||||
|
|
||||||
|
function historyPinClick(e) {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const $this = $(this)
|
const $this = $(this)
|
||||||
const id = $this.closest('a').siblings('span').html()
|
const id = $this.closest('a').siblings('span').html()
|
||||||
|
@ -229,13 +436,17 @@ function historyPinClick (e) {
|
||||||
item._values.pinned = false
|
item._values.pinned = false
|
||||||
}
|
}
|
||||||
checkIfAuth(() => {
|
checkIfAuth(() => {
|
||||||
postHistoryToServer(id, {
|
postHistoryToServerAsync(id, {pinned})
|
||||||
pinned
|
.then(() => {
|
||||||
}, (err, result) => {
|
if (pinned) {
|
||||||
if (!err) {
|
$this.addClass('active')
|
||||||
if (pinned) { $this.addClass('active') } else { $this.removeClass('active') }
|
} else {
|
||||||
}
|
$this.removeClass('active')
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err)
|
||||||
|
})
|
||||||
}, () => {
|
}, () => {
|
||||||
getHistory(notehistory => {
|
getHistory(notehistory => {
|
||||||
for (let i = 0; i < notehistory.length; i++) {
|
for (let i = 0; i < notehistory.length; i++) {
|
||||||
|
@ -245,7 +456,11 @@ function historyPinClick (e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveHistory(notehistory)
|
saveHistory(notehistory)
|
||||||
if (pinned) { $this.addClass('active') } else { $this.removeClass('active') }
|
if (pinned) {
|
||||||
|
$this.addClass('active')
|
||||||
|
} else {
|
||||||
|
$this.removeClass('active')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -253,7 +468,7 @@ function historyPinClick (e) {
|
||||||
// auto update item fromNow every minutes
|
// auto update item fromNow every minutes
|
||||||
setInterval(updateItemFromNow, 60000)
|
setInterval(updateItemFromNow, 60000)
|
||||||
|
|
||||||
function updateItemFromNow () {
|
function updateItemFromNow() {
|
||||||
const items = $('.item').toArray()
|
const items = $('.item').toArray()
|
||||||
for (let i = 0; i < items.length; i++) {
|
for (let i = 0; i < items.length; i++) {
|
||||||
const item = $(items[i])
|
const item = $(items[i])
|
||||||
|
@ -261,170 +476,3 @@ function updateItemFromNow () {
|
||||||
item.find('.fromNow').text(moment(timestamp).fromNow())
|
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, `codimd_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: unescapeHTML(tags[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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()
|
|
||||||
})
|
|
||||||
|
|
|
@ -44,6 +44,8 @@ require('prismjs/components/prism-gherkin')
|
||||||
|
|
||||||
require('./lib/common/login')
|
require('./lib/common/login')
|
||||||
require('../vendor/md-toc')
|
require('../vendor/md-toc')
|
||||||
|
|
||||||
|
|
||||||
let viz = new window.Viz()
|
let viz = new window.Viz()
|
||||||
const plantumlEncoder = require('plantuml-encoder')
|
const plantumlEncoder = require('plantuml-encoder')
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
/* eslint-env browser, jquery */
|
/* eslint-env browser, jquery */
|
||||||
/* global serverurl, moment */
|
/* global serverurl, moment */
|
||||||
|
|
||||||
|
import $ from 'jquery'
|
||||||
import store from 'store'
|
import store from 'store'
|
||||||
import LZString from '@hackmd/lz-string'
|
import LZString from '@hackmd/lz-string'
|
||||||
|
import {serverurl} from "./lib/config";
|
||||||
import escapeHTML from 'lodash/escape'
|
import escapeHTML from 'lodash/escape'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -11,13 +12,11 @@ import {
|
||||||
encodeNoteId
|
encodeNoteId
|
||||||
} from './utils'
|
} from './utils'
|
||||||
|
|
||||||
import { checkIfAuth } from './lib/common/login'
|
import {checkIfAuth, isLogin} from './lib/common/login'
|
||||||
|
|
||||||
import { urlpath } from './lib/config'
|
import {urlpath} from './lib/config'
|
||||||
|
|
||||||
window.migrateHistoryFromTempCallback = null
|
export function saveHistory(notehistory) {
|
||||||
|
|
||||||
export function saveHistory (notehistory) {
|
|
||||||
checkIfAuth(
|
checkIfAuth(
|
||||||
() => {
|
() => {
|
||||||
saveHistoryToServer(notehistory)
|
saveHistoryToServer(notehistory)
|
||||||
|
@ -28,17 +27,17 @@ export function saveHistory (notehistory) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveHistoryToStorage (notehistory) {
|
function saveHistoryToStorage(notehistory) {
|
||||||
store.set('notehistory', JSON.stringify(notehistory))
|
store.set('notehistory', JSON.stringify(notehistory))
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveHistoryToServer (notehistory) {
|
function saveHistoryToServer(notehistory) {
|
||||||
$.post(`${serverurl}/history`, {
|
$.post(`${serverurl}/history`, {
|
||||||
history: JSON.stringify(notehistory)
|
history: JSON.stringify(notehistory)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function saveStorageHistoryToServer (callback) {
|
export function saveStorageHistoryToServer(callback) {
|
||||||
const data = store.get('notehistory')
|
const data = store.get('notehistory')
|
||||||
if (data) {
|
if (data) {
|
||||||
$.post(`${serverurl}/history`, {
|
$.post(`${serverurl}/history`, {
|
||||||
|
@ -50,7 +49,7 @@ export function saveStorageHistoryToServer (callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clearDuplicatedHistory (notehistory) {
|
export function clearDuplicatedHistory(notehistory) {
|
||||||
const newnotehistory = []
|
const newnotehistory = []
|
||||||
for (let i = 0; i < notehistory.length; i++) {
|
for (let i = 0; i < notehistory.length; i++) {
|
||||||
let found = false
|
let found = false
|
||||||
|
@ -67,12 +66,14 @@ export function clearDuplicatedHistory (notehistory) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) { newnotehistory.push(notehistory[i]) }
|
if (!found) {
|
||||||
|
newnotehistory.push(notehistory[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return newnotehistory
|
return newnotehistory
|
||||||
}
|
}
|
||||||
|
|
||||||
function addHistory (id, text, time, tags, pinned, notehistory) {
|
function addHistory(id, text, time, tags, pinned, notehistory) {
|
||||||
// only add when note id exists
|
// only add when note id exists
|
||||||
if (id) {
|
if (id) {
|
||||||
notehistory.push({
|
notehistory.push({
|
||||||
|
@ -86,7 +87,7 @@ function addHistory (id, text, time, tags, pinned, notehistory) {
|
||||||
return notehistory
|
return notehistory
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeHistory (id, notehistory) {
|
export function removeHistory(id, notehistory) {
|
||||||
for (let i = 0; i < notehistory.length; i++) {
|
for (let i = 0; i < notehistory.length; i++) {
|
||||||
if (notehistory[i].id === id) {
|
if (notehistory[i].id === id) {
|
||||||
notehistory.splice(i, 1)
|
notehistory.splice(i, 1)
|
||||||
|
@ -97,7 +98,7 @@ export function removeHistory (id, notehistory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// used for inner
|
// used for inner
|
||||||
export function writeHistory (title, tags) {
|
export function writeHistory(title, tags) {
|
||||||
checkIfAuth(
|
checkIfAuth(
|
||||||
() => {
|
() => {
|
||||||
// no need to do this anymore, this will count from server-side
|
// no need to do this anymore, this will count from server-side
|
||||||
|
@ -109,7 +110,7 @@ export function writeHistory (title, tags) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeHistoryToStorage (title, tags) {
|
function writeHistoryToStorage(title, tags) {
|
||||||
const data = store.get('notehistory')
|
const data = store.get('notehistory')
|
||||||
let notehistory
|
let notehistory
|
||||||
if (data && typeof data === 'string') {
|
if (data && typeof data === 'string') {
|
||||||
|
@ -126,7 +127,7 @@ if (!Array.isArray) {
|
||||||
Array.isArray = arg => Object.prototype.toString.call(arg) === '[object Array]'
|
Array.isArray = arg => Object.prototype.toString.call(arg) === '[object Array]'
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderHistory (title, tags) {
|
function renderHistory(title, tags) {
|
||||||
// console.debug(tags);
|
// console.debug(tags);
|
||||||
const id = urlpath ? location.pathname.slice(urlpath.length + 1, location.pathname.length).split('/')[1] : location.pathname.split('/')[1]
|
const id = urlpath ? location.pathname.slice(urlpath.length + 1, location.pathname.length).split('/')[1] : location.pathname.split('/')[1]
|
||||||
return {
|
return {
|
||||||
|
@ -137,7 +138,7 @@ function renderHistory (title, tags) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateHistory (title, tags, notehistory) {
|
function generateHistory(title, tags, notehistory) {
|
||||||
const info = renderHistory(title, tags)
|
const info = renderHistory(title, tags)
|
||||||
// keep any pinned data
|
// keep any pinned data
|
||||||
let pinned = false
|
let pinned = false
|
||||||
|
@ -154,22 +155,42 @@ function generateHistory (title, tags, notehistory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// used for outer
|
// used for outer
|
||||||
export function getHistory (callback) {
|
|
||||||
checkIfAuth(
|
export async function getHistoryAsync(): Promise<NoteHistory[]> {
|
||||||
() => {
|
if (await isLogin()) {
|
||||||
getServerHistory(callback)
|
return await getServerHistoryAsync()
|
||||||
},
|
}
|
||||||
() => {
|
return getStorageHistoryAsync();
|
||||||
getStorageHistory(callback)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getServerHistory (callback) {
|
export function getHistory(callback: (_: NoteHistory[]) => void) {
|
||||||
|
getHistoryAsync()
|
||||||
|
.then((data) => {
|
||||||
|
callback(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NoteHistory {
|
||||||
|
id?: string
|
||||||
|
text?: string
|
||||||
|
time?: Date | number
|
||||||
|
tags?: string[]
|
||||||
|
pinned?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
function getServerHistoryAsync(): Promise<NoteHistory[]> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
getServerHistory(function (data: NoteHistory[]) {
|
||||||
|
resolve(data)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getServerHistory(callback) {
|
||||||
$.get(`${serverurl}/history`)
|
$.get(`${serverurl}/history`)
|
||||||
.done(data => {
|
.done(data => {
|
||||||
if (data.history) {
|
if (data.history) {
|
||||||
callback(data.history)
|
callback(data.history as NoteHistory[])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.fail((xhr, status, error) => {
|
.fail((xhr, status, error) => {
|
||||||
|
@ -177,17 +198,30 @@ function getServerHistory (callback) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getStorageHistory (callback) {
|
function getStorageHistoryAsync(): NoteHistory[] {
|
||||||
let data = store.get('notehistory')
|
let data = store.get('notehistory')
|
||||||
if (data) {
|
if (data) {
|
||||||
if (typeof data === 'string') { data = JSON.parse(data) }
|
if (typeof data === 'string') {
|
||||||
|
data = JSON.parse(data)
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStorageHistory(callback) {
|
||||||
|
let data = store.get('notehistory')
|
||||||
|
if (data) {
|
||||||
|
if (typeof data === 'string') {
|
||||||
|
data = JSON.parse(data)
|
||||||
|
}
|
||||||
callback(data)
|
callback(data)
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line standard/no-callback-literal
|
// eslint-disable-next-line standard/no-callback-literal
|
||||||
callback([])
|
callback([])
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseHistory (list, callback) {
|
export function parseHistory(list, callback) {
|
||||||
checkIfAuth(
|
checkIfAuth(
|
||||||
() => {
|
() => {
|
||||||
parseServerToHistory(list, callback)
|
parseServerToHistory(list, callback)
|
||||||
|
@ -198,7 +232,7 @@ export function parseHistory (list, callback) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseServerToHistory (list, callback) {
|
export function parseServerToHistory(list, callback) {
|
||||||
$.get(`${serverurl}/history`)
|
$.get(`${serverurl}/history`)
|
||||||
.done(data => {
|
.done(data => {
|
||||||
if (data.history) {
|
if (data.history) {
|
||||||
|
@ -210,16 +244,18 @@ export function parseServerToHistory (list, callback) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseStorageToHistory (list, callback) {
|
export function parseStorageToHistory(list, callback) {
|
||||||
let data = store.get('notehistory')
|
let data = store.get('notehistory')
|
||||||
if (data) {
|
if (data) {
|
||||||
if (typeof data === 'string') { data = JSON.parse(data) }
|
if (typeof data === 'string') {
|
||||||
|
data = JSON.parse(data)
|
||||||
|
}
|
||||||
parseToHistory(list, data, callback)
|
parseToHistory(list, data, callback)
|
||||||
}
|
}
|
||||||
parseToHistory(list, [], callback)
|
parseToHistory(list, [], callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseToHistory (list, notehistory, callback) {
|
function parseToHistory(list, notehistory, callback) {
|
||||||
if (!callback) return
|
if (!callback) return
|
||||||
else if (!list || !notehistory) callback(list, notehistory)
|
else if (!list || !notehistory) callback(list, notehistory)
|
||||||
else if (notehistory && notehistory.length > 0) {
|
else if (notehistory && notehistory.length > 0) {
|
||||||
|
@ -242,29 +278,53 @@ function parseToHistory (list, notehistory, callback) {
|
||||||
notehistory[i].text = escapeHTML(notehistory[i].text)
|
notehistory[i].text = escapeHTML(notehistory[i].text)
|
||||||
notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? escapeHTML(notehistory[i].tags).split(',') : []
|
notehistory[i].tags = (notehistory[i].tags && notehistory[i].tags.length > 0) ? escapeHTML(notehistory[i].tags).split(',') : []
|
||||||
// add to list
|
// add to list
|
||||||
if (notehistory[i].id && list.get('id', notehistory[i].id).length === 0) { list.add(notehistory[i]) }
|
if (notehistory[i].id && list.get('id', notehistory[i].id).length === 0) {
|
||||||
|
list.add(notehistory[i])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
callback(list, notehistory)
|
callback(list, notehistory)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function postHistoryToServer (noteId, data, callback) {
|
interface HistoryUpdatePayload {
|
||||||
$.post(`${serverurl}/history/${noteId}`, data)
|
pinned: boolean
|
||||||
.done(result => callback(null, result))
|
|
||||||
.fail((xhr, status, error) => {
|
|
||||||
console.error(xhr.responseText)
|
|
||||||
return callback(error, null)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteServerHistory (noteId, callback) {
|
export function postHistoryToServerAsync(noteId: string, data ?: HistoryUpdatePayload) {
|
||||||
$.ajax({
|
return new Promise((resolve, reject) => {
|
||||||
url: `${serverurl}/history${noteId ? '/' + noteId : ''}`,
|
$.post(`${serverurl}/history/${noteId}`, data as any)
|
||||||
type: 'DELETE'
|
.done(result => resolve(result))
|
||||||
|
.fail((xhr, status, error) => {
|
||||||
|
console.error(xhr.responseText)
|
||||||
|
return reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deleteServerHistoryAsync(noteId: string) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
$.ajax({
|
||||||
|
url: `${serverurl}/history/${noteId}`,
|
||||||
|
type: 'DELETE'
|
||||||
|
})
|
||||||
|
.done(result => resolve(result))
|
||||||
|
.fail((xhr, status, error) => {
|
||||||
|
console.error(xhr.responseText)
|
||||||
|
return reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearServerHistoryAsync() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
$.ajax({
|
||||||
|
url: `${serverurl}/history`,
|
||||||
|
type: 'DELETE'
|
||||||
|
})
|
||||||
|
.done(result => resolve(result))
|
||||||
|
.fail((xhr, status, error) => {
|
||||||
|
console.error(xhr.responseText)
|
||||||
|
return reject(error)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.done(result => callback(null, result))
|
|
||||||
.fail((xhr, status, error) => {
|
|
||||||
console.error(xhr.responseText)
|
|
||||||
return callback(error, null)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,14 @@ import { Spinner } from 'spin.js'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
checkLoginStateChanged,
|
checkLoginStateChanged,
|
||||||
setloginStateChangeEvent
|
setLoginStateChangeEvent
|
||||||
} from './lib/common/login'
|
} from './lib/common/login'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
debug,
|
debug,
|
||||||
DROPBOX_APP_KEY,
|
DROPBOX_APP_KEY,
|
||||||
noteid,
|
noteid,
|
||||||
noteurl,
|
noteurl, serverurl,
|
||||||
urlpath,
|
urlpath,
|
||||||
version
|
version
|
||||||
} from './lib/config'
|
} from './lib/config'
|
||||||
|
@ -66,10 +66,9 @@ import {
|
||||||
|
|
||||||
import {
|
import {
|
||||||
writeHistory,
|
writeHistory,
|
||||||
deleteServerHistory,
|
|
||||||
getHistory,
|
getHistory,
|
||||||
saveHistory,
|
saveHistory,
|
||||||
removeHistory
|
removeHistory, deleteServerHistoryAsync
|
||||||
} from './history'
|
} from './history'
|
||||||
|
|
||||||
import { preventXSS } from './render'
|
import { preventXSS } from './render'
|
||||||
|
@ -396,7 +395,7 @@ function setNeedRefresh () {
|
||||||
showStatus(statusType.offline)
|
showStatus(statusType.offline)
|
||||||
}
|
}
|
||||||
|
|
||||||
setloginStateChangeEvent(function () {
|
setLoginStateChangeEvent(function () {
|
||||||
setRefreshModal('user-state-changed')
|
setRefreshModal('user-state-changed')
|
||||||
setNeedRefresh()
|
setNeedRefresh()
|
||||||
})
|
})
|
||||||
|
@ -1752,11 +1751,14 @@ socket.on('error', function (data) {
|
||||||
console.error(data)
|
console.error(data)
|
||||||
if (data.message && data.message.indexOf('AUTH failed') === 0) { location.href = serverurl + '/403' }
|
if (data.message && data.message.indexOf('AUTH failed') === 0) { location.href = serverurl + '/403' }
|
||||||
})
|
})
|
||||||
socket.on('delete', function () {
|
socket.on('delete', async function () {
|
||||||
if (personalInfo.login) {
|
if (personalInfo.login) {
|
||||||
deleteServerHistory(noteid, function (err, data) {
|
try {
|
||||||
if (!err) location.href = serverurl
|
await deleteServerHistoryAsync(noteid)
|
||||||
})
|
location.href = serverurl
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
getHistory(function (notehistory) {
|
getHistory(function (notehistory) {
|
||||||
var newnotehistory = removeHistory(noteid, notehistory)
|
var newnotehistory = removeHistory(noteid, notehistory)
|
||||||
|
|
|
@ -1,24 +1,28 @@
|
||||||
/* eslint-env browser, jquery */
|
/* eslint-env browser, jquery */
|
||||||
/* global Cookies */
|
/* global Cookies */
|
||||||
|
|
||||||
import { serverurl } from '../config'
|
import Cookies from 'js-cookie'
|
||||||
|
|
||||||
let checkAuth = false
|
import {serverurl} from '../config'
|
||||||
|
|
||||||
|
type PureFunction = () => void
|
||||||
|
|
||||||
|
let checkAuth: boolean = false
|
||||||
let profile = null
|
let profile = null
|
||||||
let lastLoginState = getLoginState()
|
let lastLoginState = getLoginState()
|
||||||
let lastUserId = getUserId()
|
let lastUserId: string | null = getUserId()
|
||||||
let loginStateChangeEvent = null
|
let loginStateChangeEvent: PureFunction | null = null
|
||||||
|
|
||||||
export function setloginStateChangeEvent (func) {
|
export function setLoginStateChangeEvent(func: PureFunction): void {
|
||||||
loginStateChangeEvent = func
|
loginStateChangeEvent = func
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetCheckAuth () {
|
export function resetCheckAuth(): void {
|
||||||
checkAuth = false
|
checkAuth = false
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setLoginState (bool, id) {
|
function setLoginState(bool: boolean, id?: string) {
|
||||||
Cookies.set('loginstate', bool, {
|
Cookies.set('loginstate', String(bool), {
|
||||||
expires: 365
|
expires: 365
|
||||||
})
|
})
|
||||||
if (id) {
|
if (id) {
|
||||||
|
@ -29,64 +33,81 @@ export function setLoginState (bool, id) {
|
||||||
Cookies.remove('userid')
|
Cookies.remove('userid')
|
||||||
}
|
}
|
||||||
lastLoginState = bool
|
lastLoginState = bool
|
||||||
lastUserId = id
|
lastUserId = id || null
|
||||||
checkLoginStateChanged()
|
checkLoginStateChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkLoginStateChanged () {
|
export function checkLoginStateChanged(): boolean {
|
||||||
if (getLoginState() !== lastLoginState || getUserId() !== lastUserId) {
|
if (getLoginState() !== lastLoginState || getUserId() !== lastUserId) {
|
||||||
if (loginStateChangeEvent) setTimeout(loginStateChangeEvent, 100)
|
if (loginStateChangeEvent) setTimeout(loginStateChangeEvent, 100)
|
||||||
return true
|
return true
|
||||||
} else {
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLoginState(): boolean {
|
||||||
|
const state = Cookies.get('loginstate')
|
||||||
|
return state === 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUserId(): string {
|
||||||
|
return Cookies.get('userid') || ""
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearLoginState(): void {
|
||||||
|
Cookies.remove('loginstate')
|
||||||
|
}
|
||||||
|
|
||||||
|
type YesCallbackFunc = (profile: any) => void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getLoginUserProfile
|
||||||
|
* @throws Error when user not login
|
||||||
|
* @return profile user profile
|
||||||
|
*/
|
||||||
|
export async function getLoginUserProfile(): Promise<any> {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
const cookieLoginState = getLoginState()
|
||||||
|
if (checkLoginStateChanged()) checkAuth = false
|
||||||
|
if (!checkAuth || typeof cookieLoginState === 'undefined') {
|
||||||
|
$.get(`${serverurl}/me`)
|
||||||
|
.done(data => {
|
||||||
|
if (data && data.status === 'ok') {
|
||||||
|
profile = data
|
||||||
|
setLoginState(true, data.id)
|
||||||
|
return resolve(profile)
|
||||||
|
} else {
|
||||||
|
setLoginState(false)
|
||||||
|
return reject(new Error('user not login'))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.fail(() => {
|
||||||
|
return reject(new Error('user not login'))
|
||||||
|
})
|
||||||
|
.always(() => {
|
||||||
|
checkAuth = true
|
||||||
|
})
|
||||||
|
} else if (cookieLoginState) {
|
||||||
|
return resolve(profile)
|
||||||
|
} else {
|
||||||
|
return reject(new Error('user not login'))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function isLogin(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await getLoginUserProfile()
|
||||||
|
return true
|
||||||
|
} catch (e) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLoginState () {
|
export function checkIfAuth(yesCallback: YesCallbackFunc, noCallback: PureFunction) {
|
||||||
const state = Cookies.get('loginstate')
|
getLoginUserProfile().then((profile) => {
|
||||||
return state === 'true' || state === true
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getUserId () {
|
|
||||||
return Cookies.get('userid')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function clearLoginState () {
|
|
||||||
Cookies.remove('loginstate')
|
|
||||||
}
|
|
||||||
|
|
||||||
export function checkIfAuth (yesCallback, noCallback) {
|
|
||||||
const cookieLoginState = getLoginState()
|
|
||||||
if (checkLoginStateChanged()) checkAuth = false
|
|
||||||
if (!checkAuth || typeof cookieLoginState === 'undefined') {
|
|
||||||
$.get(`${serverurl}/me`)
|
|
||||||
.done(data => {
|
|
||||||
if (data && data.status === 'ok') {
|
|
||||||
profile = data
|
|
||||||
yesCallback(profile)
|
|
||||||
setLoginState(true, data.id)
|
|
||||||
} else {
|
|
||||||
noCallback()
|
|
||||||
setLoginState(false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.fail(() => {
|
|
||||||
noCallback()
|
|
||||||
})
|
|
||||||
.always(() => {
|
|
||||||
checkAuth = true
|
|
||||||
})
|
|
||||||
} else if (cookieLoginState) {
|
|
||||||
yesCallback(profile)
|
yesCallback(profile)
|
||||||
} else {
|
}).catch(() => {
|
||||||
noCallback()
|
noCallback()
|
||||||
}
|
})
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
checkAuth,
|
|
||||||
profile,
|
|
||||||
lastLoginState,
|
|
||||||
lastUserId,
|
|
||||||
loginStateChangeEvent
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
declare interface Window {
|
|
||||||
DROPBOX_APP_KEY: string,
|
|
||||||
domain: string,
|
|
||||||
urlpath: string,
|
|
||||||
debug: boolean,
|
|
||||||
serverurl: string,
|
|
||||||
version: string
|
|
||||||
USE_CDN: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DROPBOX_APP_KEY = window.DROPBOX_APP_KEY || ''
|
export const DROPBOX_APP_KEY = window.DROPBOX_APP_KEY || ''
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,48 @@
|
||||||
/* eslint-env browser, jquery */
|
/* eslint-env browser, jquery */
|
||||||
/* global Cookies */
|
/* global Cookies */
|
||||||
|
|
||||||
var lang = 'en'
|
import $ from 'jquery'
|
||||||
var userLang = navigator.language || navigator.userLanguage
|
import Cookies from 'js-cookie'
|
||||||
var userLangCode = userLang.split('-')[0]
|
|
||||||
var locale = $('.ui-locale')
|
const userLang = navigator.language || navigator.userLanguage
|
||||||
var supportLangs = []
|
const userLangCode = userLang.split('-')[0]
|
||||||
$('.ui-locale option').each(function () {
|
|
||||||
supportLangs.push($(this).val())
|
let lang = 'en'
|
||||||
})
|
let supportLangs: string[] = []
|
||||||
if (Cookies.get('locale')) {
|
|
||||||
lang = Cookies.get('locale')
|
function reloadLanguageFromCookie () {
|
||||||
if (lang === 'zh') {
|
if (Cookies.get('locale')) {
|
||||||
lang = 'zh-TW'
|
lang = Cookies.get('locale') as string
|
||||||
|
if (lang === 'zh') {
|
||||||
|
lang = 'zh-TW'
|
||||||
|
}
|
||||||
|
} else if (supportLangs.indexOf(userLang) !== -1) {
|
||||||
|
lang = supportLangs[supportLangs.indexOf(userLang)]
|
||||||
|
} else if (supportLangs.indexOf(userLangCode) !== -1) {
|
||||||
|
lang = supportLangs[supportLangs.indexOf(userLangCode)]
|
||||||
}
|
}
|
||||||
} else if (supportLangs.indexOf(userLang) !== -1) {
|
|
||||||
lang = supportLangs[supportLangs.indexOf(userLang)]
|
|
||||||
} else if (supportLangs.indexOf(userLangCode) !== -1) {
|
|
||||||
lang = supportLangs[supportLangs.indexOf(userLangCode)]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
locale.val(lang)
|
function fillSupportLanguageArrayFromDropdownOptions () {
|
||||||
$('select.ui-locale option[value="' + lang + '"]').attr('selected', 'selected')
|
const $langOptions = $('.ui-locale option');
|
||||||
|
$langOptions.each(function () {
|
||||||
locale.change(function () {
|
supportLangs.push($(this).val() as string)
|
||||||
Cookies.set('locale', $(this).val(), {
|
|
||||||
expires: 365
|
|
||||||
})
|
})
|
||||||
window.location.reload()
|
}
|
||||||
})
|
|
||||||
|
export function initializeLocaleDropdown() {
|
||||||
|
const $locale = $('.ui-locale')
|
||||||
|
|
||||||
|
fillSupportLanguageArrayFromDropdownOptions()
|
||||||
|
reloadLanguageFromCookie()
|
||||||
|
|
||||||
|
$locale.val(lang)
|
||||||
|
$('select.ui-locale option[value="' + lang + '"]').attr('selected', 'selected')
|
||||||
|
|
||||||
|
$locale.on('change', function () {
|
||||||
|
Cookies.set('locale', $(this).val() as string, {
|
||||||
|
expires: 365
|
||||||
|
})
|
||||||
|
window.location.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
/* eslint-env browser, jquery */
|
/* eslint-env browser, jquery */
|
||||||
// allow some attributes
|
// allow some attributes
|
||||||
|
|
||||||
var filterXSS = require('xss')
|
import {filterXSS, escapeAttrValue, whiteList} from 'xss'
|
||||||
|
|
||||||
var whiteListAttr = ['id', 'class', 'style']
|
const whiteListAttr = ['id', 'class', 'style']
|
||||||
window.whiteListAttr = whiteListAttr
|
window.whiteListAttr = whiteListAttr
|
||||||
// allow link starts with '.', '/' and custom protocol with '://', exclude link starts with javascript://
|
// allow link starts with '.', '/' and custom protocol with '://', exclude link starts with javascript://
|
||||||
var linkRegex = /^(?!javascript:\/\/)([\w|-]+:\/\/)|^([.|/])+/i
|
const linkRegex = /^(?!javascript:\/\/)([\w|-]+:\/\/)|^([.|/])+/i
|
||||||
// allow data uri, from https://gist.github.com/bgrins/6194623
|
// allow data uri, from https://gist.github.com/bgrins/6194623
|
||||||
var dataUriRegex = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)\s*$/i
|
const dataUriRegex = /^\s*data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)?)?(;base64)?,([a-z0-9!$&',()*+;=\-._~:@/?%\s]*)\s*$/i
|
||||||
// custom white list
|
// custom white list
|
||||||
var whiteList = filterXSS.whiteList
|
|
||||||
// allow ol specify start number
|
// allow ol specify start number
|
||||||
whiteList.ol = ['start']
|
whiteList.ol = ['start']
|
||||||
// allow li specify value number
|
// allow li specify value number
|
||||||
|
@ -34,7 +33,7 @@ whiteList.figure = []
|
||||||
// allow figcaption tag
|
// allow figcaption tag
|
||||||
whiteList.figcaption = []
|
whiteList.figcaption = []
|
||||||
|
|
||||||
var filterXSSOptions = {
|
const filterXSSOptions = {
|
||||||
allowCommentTag: true,
|
allowCommentTag: true,
|
||||||
whiteList: whiteList,
|
whiteList: whiteList,
|
||||||
escapeHtml: function (html) {
|
escapeHtml: function (html) {
|
||||||
|
@ -51,28 +50,25 @@ var filterXSSOptions = {
|
||||||
onTagAttr: function (tag, name, value, isWhiteAttr) {
|
onTagAttr: function (tag, name, value, isWhiteAttr) {
|
||||||
// allow href and src that match linkRegex
|
// allow href and src that match linkRegex
|
||||||
if (isWhiteAttr && (name === 'href' || name === 'src') && linkRegex.test(value)) {
|
if (isWhiteAttr && (name === 'href' || name === 'src') && linkRegex.test(value)) {
|
||||||
return name + '="' + filterXSS.escapeAttrValue(value) + '"'
|
return name + '="' + escapeAttrValue(value) + '"'
|
||||||
}
|
}
|
||||||
// allow data uri in img src
|
// allow data uri in img src
|
||||||
if (isWhiteAttr && (tag === 'img' && name === 'src') && dataUriRegex.test(value)) {
|
if (isWhiteAttr && (tag === 'img' && name === 'src') && dataUriRegex.test(value)) {
|
||||||
return name + '="' + filterXSS.escapeAttrValue(value) + '"'
|
return name + '="' + escapeAttrValue(value) + '"'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {
|
onIgnoreTagAttr: function (tag, name, value, isWhiteAttr) {
|
||||||
// allow attr start with 'data-' or in the whiteListAttr
|
// allow attr start with 'data-' or in the whiteListAttr
|
||||||
if (name.substr(0, 5) === 'data-' || window.whiteListAttr.indexOf(name) !== -1) {
|
if (name.substr(0, 5) === 'data-' || window.whiteListAttr.indexOf(name) !== -1) {
|
||||||
// escape its value using built-in escapeAttrValue function
|
// escape its value using built-in escapeAttrValue function
|
||||||
return name + '="' + filterXSS.escapeAttrValue(value) + '"'
|
return name + '="' + escapeAttrValue(value) + '"'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function preventXSS (html) {
|
export function preventXSS (html) {
|
||||||
return filterXSS(html, filterXSSOptions)
|
return filterXSS(html, filterXSSOptions)
|
||||||
}
|
}
|
||||||
window.preventXSS = preventXSS
|
window.preventXSS = preventXSS
|
||||||
|
|
||||||
module.exports = {
|
export {escapeAttrValue} from 'xss'
|
||||||
preventXSS: preventXSS,
|
|
||||||
escapeAttrValue: filterXSS.escapeAttrValue
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"module": "ESNext",
|
||||||
|
"lib": ["DOM", "ESNext"],
|
||||||
|
"sourceMap": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"allowJs": true,
|
||||||
|
"strict": false,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"strictBindCallApply": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"alwaysStrict": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
|
||||||
|
"typeRoots": ["../../node_modules/@types",
|
||||||
|
"./typings"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"./"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
Viz: any
|
||||||
|
createtime: any
|
||||||
|
lastchangetime: any
|
||||||
|
lastchangeui: any
|
||||||
|
owner: any
|
||||||
|
ownerprofile: any
|
||||||
|
whiteListAttr: any
|
||||||
|
preventXSS: any
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,23 +2,23 @@ import base64url from 'base64url'
|
||||||
|
|
||||||
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
||||||
|
|
||||||
export function checkNoteIdValid (id) {
|
export function checkNoteIdValid (id: string) {
|
||||||
const result = id.match(uuidRegex)
|
const result = id.match(uuidRegex)
|
||||||
return !!(result && result.length === 1)
|
return !!(result && result.length === 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encodeNoteId (id) {
|
export function encodeNoteId (id: string) {
|
||||||
// remove dashes in UUID and encode in url-safe base64
|
// remove dashes in UUID and encode in url-safe base64
|
||||||
const str = id.replace(/-/g, '')
|
const str = id.replace(/-/g, '')
|
||||||
const hexStr = Buffer.from(str, 'hex')
|
const hexStr = Buffer.from(str, 'hex')
|
||||||
return base64url.encode(hexStr)
|
return base64url.encode(hexStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function decodeNoteId (encodedId) {
|
export function decodeNoteId (encodedId: string) {
|
||||||
// decode from url-safe base64
|
// decode from url-safe base64
|
||||||
const id = base64url.toBuffer(encodedId).toString('hex')
|
const id = base64url.toBuffer(encodedId).toString('hex')
|
||||||
// add dashes between the UUID string parts
|
// add dashes between the UUID string parts
|
||||||
const idParts = []
|
const idParts: string[] = []
|
||||||
idParts.push(id.substr(0, 8))
|
idParts.push(id.substr(0, 8))
|
||||||
idParts.push(id.substr(8, 4))
|
idParts.push(id.substr(8, 4))
|
||||||
idParts.push(id.substr(12, 4))
|
idParts.push(id.substr(12, 4))
|
||||||
|
|
Loading…
Reference in New Issue