nightly commit
This commit is contained in:
@@ -3,6 +3,7 @@ import sqlite3
|
|||||||
import json
|
import json
|
||||||
import utils
|
import utils
|
||||||
import threading
|
import threading
|
||||||
|
import logging
|
||||||
|
|
||||||
def SafeDatabaseOperation(func):
|
def SafeDatabaseOperation(func):
|
||||||
def wrapper(self, *args, **kwargs):
|
def wrapper(self, *args, **kwargs):
|
||||||
@@ -11,22 +12,31 @@ def SafeDatabaseOperation(func):
|
|||||||
try:
|
try:
|
||||||
self.check_database()
|
self.check_database()
|
||||||
self.cursor = self.db.cursor()
|
self.cursor = self.db.cursor()
|
||||||
except:
|
except Exception as e:
|
||||||
self.cursor = None
|
self.cursor = None
|
||||||
return (False, None)
|
if config.CustomConfig['debug']:
|
||||||
|
logging.exception(e)
|
||||||
|
return (False, str(e), None)
|
||||||
|
|
||||||
# do real data work
|
# do real data work
|
||||||
try:
|
try:
|
||||||
result = (True, func(self, *args, **kwargs))
|
if self.isFirstRun:
|
||||||
|
self.isFirstRun = False
|
||||||
|
print('Cleaning outdated token...')
|
||||||
|
self.tokenOper_clean()
|
||||||
|
|
||||||
|
result = (True, '', func(self, *args, **kwargs))
|
||||||
self.cursor.close()
|
self.cursor.close()
|
||||||
self.cursor = None
|
self.cursor = None
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
return result
|
return result
|
||||||
except:
|
except Exception as e:
|
||||||
self.cursor.close()
|
self.cursor.close()
|
||||||
self.cursor = None
|
self.cursor = None
|
||||||
self.db.rollback()
|
self.db.rollback()
|
||||||
return (False, None)
|
if config.CustomConfig['debug']:
|
||||||
|
logging.exception(e)
|
||||||
|
return (False, str(e), None)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
@@ -35,6 +45,7 @@ class CalendarDatabase(object):
|
|||||||
self.db = None
|
self.db = None
|
||||||
self.cursor = None
|
self.cursor = None
|
||||||
self.mutex = threading.Lock()
|
self.mutex = threading.Lock()
|
||||||
|
self.isFirstRun = True
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
if (self.is_database_valid()):
|
if (self.is_database_valid()):
|
||||||
@@ -49,7 +60,7 @@ class CalendarDatabase(object):
|
|||||||
|
|
||||||
def init(self, username, password):
|
def init(self, username, password):
|
||||||
if (self.is_database_valid()):
|
if (self.is_database_valid()):
|
||||||
raise Exception('Databade is opened')
|
raise Exception('Database is opened')
|
||||||
|
|
||||||
# establish tables
|
# establish tables
|
||||||
self.open()
|
self.open()
|
||||||
@@ -58,13 +69,11 @@ class CalendarDatabase(object):
|
|||||||
cursor.executescript(fsql.read())
|
cursor.executescript(fsql.read())
|
||||||
|
|
||||||
# finish init
|
# finish init
|
||||||
cursor.execute('INSERT INTO user VALUES (?, ?, ?, ?, ?, ?);', (
|
cursor.execute('INSERT INTO user VALUES (?, ?, ?, ?);', (
|
||||||
username,
|
username,
|
||||||
utils.ComputePasswordHash(password),
|
utils.ComputePasswordHash(password),
|
||||||
1,
|
1,
|
||||||
utils.GenerateSalt(),
|
utils.GenerateSalt()
|
||||||
utils.GenerateToken(username),
|
|
||||||
0
|
|
||||||
))
|
))
|
||||||
cursor.close()
|
cursor.close()
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
@@ -81,8 +90,27 @@ class CalendarDatabase(object):
|
|||||||
def is_database_valid(self):
|
def is_database_valid(self):
|
||||||
return not (self.db == None)
|
return not (self.db == None)
|
||||||
|
|
||||||
def get_username_from_token(self, token):
|
# ======================= token related internal operation
|
||||||
self.cursor.execute('SELECT [ccn_name] FROM user WHERE [ccn_token] = ? AND [ccn_tokenExpireOn] > ?;',(
|
def tokenOper_clean(self):
|
||||||
|
# remove outdated token
|
||||||
|
self.cursor.execute('DELETE FROM token WHERE [ccn_tokenExpireOn] <= ?',(utils.GetCurrentTimestamp(), ))
|
||||||
|
|
||||||
|
def tokenOper_postpone_expireOn(self, token):
|
||||||
|
self.cursor.execute('UPDATE token SET [ccn_tokenExpireOn] = ? WHERE [ccn_token] = ?;', (
|
||||||
|
utils.GetTokenExpireOn(),
|
||||||
|
token
|
||||||
|
))
|
||||||
|
|
||||||
|
def tokenOper_check_valid(self, token):
|
||||||
|
self.tokenOper_get_username(token)
|
||||||
|
|
||||||
|
def tokenOper_is_admin(self, username):
|
||||||
|
self.cursor.execute('SELECT [ccn_isAdmin] FROM user WHERE [ccn_name] = ?;',(username, ))
|
||||||
|
cache = self.cursor.fetchone()[0]
|
||||||
|
return True if cache == 1 else False
|
||||||
|
|
||||||
|
def tokenOper_get_username(self, token):
|
||||||
|
self.cursor.execute('SELECT [ccn_user] FROM token WHERE [ccn_token] = ? AND [ccn_tokenExpireOn] > ?;',(
|
||||||
token,
|
token,
|
||||||
utils.GetCurrentTimestamp()
|
utils.GetCurrentTimestamp()
|
||||||
))
|
))
|
||||||
@@ -106,16 +134,19 @@ class CalendarDatabase(object):
|
|||||||
|
|
||||||
if password == utils.ComputePasswordHashWithSalt(gotten_password, gotten_salt):
|
if password == utils.ComputePasswordHashWithSalt(gotten_password, gotten_salt):
|
||||||
token = utils.GenerateToken(username)
|
token = utils.GenerateToken(username)
|
||||||
self.cursor.execute('UPDATE user SET [ccn_token] = ?, [ccn_tokenExpireOn] = ?, [ccn_salt] = ? WHERE [ccn_name] = ?;', (
|
self.cursor.execute('UPDATE user SET [ccn_salt] = ? WHERE [ccn_name] = ?;', (
|
||||||
token,
|
|
||||||
utils.GetCurrentTimestamp() + 60 * 60 * 24 * 2, # add 2 day from now
|
|
||||||
utils.GenerateSalt(), # regenerate a new slat to prevent re-login try
|
utils.GenerateSalt(), # regenerate a new slat to prevent re-login try
|
||||||
username
|
username
|
||||||
))
|
))
|
||||||
|
self.cursor.execute('INSERT INTO token VALUES (?, ?, ?);', (
|
||||||
|
username,
|
||||||
|
token,
|
||||||
|
utils.GetTokenExpireOn(), # add 2 day from now
|
||||||
|
))
|
||||||
return token
|
return token
|
||||||
else:
|
else:
|
||||||
# throw a exception to indicate fail to login
|
# throw a exception to indicate fail to login
|
||||||
raise Exception()
|
raise Exception('Login authentication failed')
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def common_webLogin(self, username, password):
|
def common_webLogin(self, username, password):
|
||||||
@@ -123,38 +154,35 @@ class CalendarDatabase(object):
|
|||||||
|
|
||||||
if len(self.cursor.fetchall()) != 0:
|
if len(self.cursor.fetchall()) != 0:
|
||||||
token = utils.GenerateToken(username)
|
token = utils.GenerateToken(username)
|
||||||
self.cursor.execute('UPDATE user SET [ccn_token] = ?, [ccn_tokenExpireOn] = ? WHERE [ccn_name] = ?;', (
|
self.cursor.execute('INSERT INTO token VALUES (?, ?, ?);', (
|
||||||
|
username,
|
||||||
token,
|
token,
|
||||||
utils.GetCurrentTimestamp() + 60 * 60 * 24 * 2, # add 2 day from now
|
utils.GetTokenExpireOn(), # add 2 day from now
|
||||||
username
|
|
||||||
))
|
))
|
||||||
return token
|
return token
|
||||||
else:
|
else:
|
||||||
# throw a exception to indicate fail to login
|
# throw a exception to indicate fail to login
|
||||||
raise Exception()
|
raise Exception('Login authentication failed')
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def common_logout(self, token):
|
def common_logout(self, token):
|
||||||
username = self.get_username_from_token(token)
|
self.tokenOper_check_valid(token)
|
||||||
self.cursor.execute('UPDATE user SET [ccn_tokenExpireOn] = 0 WHERE [ccn_name] = ?;', (username, ))
|
self.cursor.execute('DELETE FROM token WHERE [ccn_token] = ?;', (token, ))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def common_tokenValid(self, token):
|
def common_tokenValid(self, token):
|
||||||
# get user name have check the validation, don't do anything more.
|
self.tokenOper_check_valid(token)
|
||||||
self.get_username_from_token(token)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def common_isAdmin(self, token):
|
def common_isAdmin(self, token):
|
||||||
username = self.get_username_from_token(token)
|
username = self.tokenOper_get_username(token)
|
||||||
self.cursor.execute('SELECT [ccn_isAdmin] FROM user WHERE [ccn_name] = ?;', (username, ))
|
return self.tokenOper_is_admin(username)
|
||||||
result = self.cursor.fetchone()[0] == 1
|
|
||||||
return result
|
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def common_changePassword(self, token, newpassword):
|
def common_changePassword(self, token, newpassword):
|
||||||
username = self.get_username_from_token(token)
|
username = self.tokenOper_get_username(token)
|
||||||
self.cursor.execute('UPDATE user SET [ccn_password] = ? WHERE [ccn_name] = ?;', (
|
self.cursor.execute('UPDATE user SET [ccn_password] = ? WHERE [ccn_name] = ?;', (
|
||||||
newpassword,
|
newpassword,
|
||||||
username
|
username
|
||||||
@@ -170,25 +198,25 @@ class CalendarDatabase(object):
|
|||||||
# =============================== todo
|
# =============================== todo
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def todo_getFull(self, token):
|
def todo_getFull(self, token):
|
||||||
username = self.get_username_from_token(token)
|
username = self.tokenOper_get_username(token)
|
||||||
self.cursor.execute('SELECT * FROM todo WHERE [ccn_belongTo] = ?;', (username, ))
|
self.cursor.execute('SELECT * FROM todo WHERE [ccn_belongTo] = ?;', (username, ))
|
||||||
return self.cursor.fetchall()
|
return self.cursor.fetchall()
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def todo_getList(self, token):
|
def todo_getList(self, token):
|
||||||
username = self.get_username_from_token(token)
|
username = self.tokenOper_get_username(token)
|
||||||
self.cursor.execute('SELECT [ccn_uuid] FROM todo WHERE [ccn_belongTo] = ?;', (username, ))
|
self.cursor.execute('SELECT [ccn_uuid] FROM todo WHERE [ccn_belongTo] = ?;', (username, ))
|
||||||
return tuple(map(lambda x: x[0], self.cursor.fetchall()))
|
return tuple(map(lambda x: x[0], self.cursor.fetchall()))
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def todo_getDetail(self, token, uuid):
|
def todo_getDetail(self, token, uuid):
|
||||||
username = self.get_username_from_token(token)
|
username = self.tokenOper_get_username(token)
|
||||||
self.cursor.execute('SELECT * FROM todo WHERE [ccn_belongTo] = ? AND [ccn_uuid] = ?;', (username, uuid))
|
self.cursor.execute('SELECT * FROM todo WHERE [ccn_belongTo] = ? AND [ccn_uuid] = ?;', (username, uuid))
|
||||||
return self.cursor.fetchone()
|
return self.cursor.fetchone()
|
||||||
|
|
||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def todo_add(self, token):
|
def todo_add(self, token):
|
||||||
username = self.get_username_from_token(token)
|
username = self.tokenOper_get_username(token)
|
||||||
newuuid = utils.GenerateUUID()
|
newuuid = utils.GenerateUUID()
|
||||||
lastupdate = utils.GenerateUUID()
|
lastupdate = utils.GenerateUUID()
|
||||||
returnedData = (
|
returnedData = (
|
||||||
@@ -203,7 +231,7 @@ class CalendarDatabase(object):
|
|||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def todo_update(self, token, uuid, data, lastChange):
|
def todo_update(self, token, uuid, data, lastChange):
|
||||||
# check valid token
|
# check valid token
|
||||||
self.get_username_from_token(token)
|
self.tokenOper_check_valid(token)
|
||||||
# check sync conflict
|
# check sync conflict
|
||||||
self.cursor.execute('SELECT [ccn_uuid] FROM todo WHERE [ccn_uuid] = ? AND [ccn_lastChange] = ?;', (
|
self.cursor.execute('SELECT [ccn_uuid] FROM todo WHERE [ccn_uuid] = ? AND [ccn_lastChange] = ?;', (
|
||||||
uuid,
|
uuid,
|
||||||
@@ -224,7 +252,7 @@ class CalendarDatabase(object):
|
|||||||
@SafeDatabaseOperation
|
@SafeDatabaseOperation
|
||||||
def todo_delete(self, token, uuid, lastChange):
|
def todo_delete(self, token, uuid, lastChange):
|
||||||
# check valid token
|
# check valid token
|
||||||
self.get_username_from_token(token)
|
self.tokenOper_check_valid(token)
|
||||||
# check sync conflict
|
# check sync conflict
|
||||||
self.cursor.execute('SELECT [ccn_uuid] FROM todo WHERE [ccn_uuid] = ? AND [ccn_lastChange] = ?;', (
|
self.cursor.execute('SELECT [ccn_uuid] FROM todo WHERE [ccn_uuid] = ? AND [ccn_lastChange] = ?;', (
|
||||||
uuid,
|
uuid,
|
||||||
|
|||||||
@@ -302,8 +302,8 @@ def CheckParameter(paramList):
|
|||||||
def ConstructResponseBody(returnedTuple):
|
def ConstructResponseBody(returnedTuple):
|
||||||
return {
|
return {
|
||||||
'success': returnedTuple[0],
|
'success': returnedTuple[0],
|
||||||
'error': '',
|
'error': returnedTuple[1],
|
||||||
'data': returnedTuple[1]
|
'data': returnedTuple[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
def run():
|
def run():
|
||||||
|
|||||||
@@ -6,10 +6,16 @@ CREATE TABLE user(
|
|||||||
[ccn_password] TEXT NOT NULL,
|
[ccn_password] TEXT NOT NULL,
|
||||||
[ccn_isAdmin] TINYINT NOT NULL CHECK(ccn_isAdmin = 1 OR ccn_isAdmin = 0),
|
[ccn_isAdmin] TINYINT NOT NULL CHECK(ccn_isAdmin = 1 OR ccn_isAdmin = 0),
|
||||||
[ccn_salt] INTEGER NOT NULL,
|
[ccn_salt] INTEGER NOT NULL,
|
||||||
|
|
||||||
|
PRIMARY KEY (ccn_name)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE token(
|
||||||
|
[ccn_user] TEXT NOT NULL,
|
||||||
[ccn_token] TEXT UNIQUE NOT NULL,
|
[ccn_token] TEXT UNIQUE NOT NULL,
|
||||||
[ccn_tokenExpireOn] BIGINT NOT NULL,
|
[ccn_tokenExpireOn] BIGINT NOT NULL,
|
||||||
|
|
||||||
PRIMARY KEY (ccn_name)
|
FOREIGN KEY (ccn_user) REFERENCES user(ccn_name) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE collection(
|
CREATE TABLE collection(
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ ccn-login-form-login=Login
|
|||||||
|
|
||||||
ccn-todo-todoList=Todo list
|
ccn-todo-todoList=Todo list
|
||||||
|
|
||||||
ccn-calendar-jump=Jump
|
ccn-calendar-calendar-jump=Jump
|
||||||
ccn-calendar-today=Today
|
ccn-calendar-calendar-today=Today
|
||||||
ccn-calendar-add=Add...
|
ccn-calendar-calendar-add=Add...
|
||||||
ccn-calendar-scheduleList=Schedule
|
ccn-calendar-calendar-scheduleList=Schedule
|
||||||
ccn-calendar-tabcontrol-tabCalendar=Calendar
|
ccn-calendar-tabcontrol-tabCalendar=Calendar
|
||||||
ccn-calendar-tabcontrol-tabShared=Shared
|
ccn-calendar-tabcontrol-tabShared=Shared
|
||||||
ccn-calendar-tabcontrol-tabSharing=Sharing
|
ccn-calendar-tabcontrol-tabSharing=Sharing
|
||||||
@@ -38,3 +38,7 @@ ccn-calendar-week-thursday=Thursday
|
|||||||
ccn-calendar-week-friday=Friday
|
ccn-calendar-week-friday=Friday
|
||||||
ccn-calendar-week-saturday=Saturday
|
ccn-calendar-week-saturday=Saturday
|
||||||
ccn-calendar-week-sunday=Sunday
|
ccn-calendar-week-sunday=Sunday
|
||||||
|
ccn-calendar-shared-list=Shared
|
||||||
|
ccn-calendar-sharing-ownedList=Owned
|
||||||
|
ccn-calendar-sharing-sharingTargetList=Sharing target
|
||||||
|
ccn-calendar-sharing-sharingTargetEditing=Editing:
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ ccn-login-form-login=登录
|
|||||||
|
|
||||||
ccn-todo-todoList=待办列表
|
ccn-todo-todoList=待办列表
|
||||||
|
|
||||||
ccn-calendar-jump=转到
|
ccn-calendar-calendar-jump=转到
|
||||||
ccn-calendar-today=今天
|
ccn-calendar-calendar-today=今天
|
||||||
ccn-calendar-add=添加...
|
ccn-calendar-calendar-add=添加...
|
||||||
ccn-calendar-scheduleList=日程安排
|
ccn-calendar-calendar-scheduleList=日程安排
|
||||||
ccn-calendar-tabcontrol-tabCalendar=日历
|
ccn-calendar-tabcontrol-tabCalendar=日历
|
||||||
ccn-calendar-tabcontrol-tabShared=被共享的
|
ccn-calendar-tabcontrol-tabShared=被共享的
|
||||||
ccn-calendar-tabcontrol-tabSharing=共享给其他人
|
ccn-calendar-tabcontrol-tabSharing=共享给其他人
|
||||||
@@ -38,3 +38,7 @@ ccn-calendar-week-thursday=星期四
|
|||||||
ccn-calendar-week-friday=星期五
|
ccn-calendar-week-friday=星期五
|
||||||
ccn-calendar-week-saturday=星期六
|
ccn-calendar-week-saturday=星期六
|
||||||
ccn-calendar-week-sunday=星期日
|
ccn-calendar-week-sunday=星期日
|
||||||
|
ccn-calendar-shared-list=被共享的集合
|
||||||
|
ccn-calendar-sharing-ownedList=我的集合
|
||||||
|
ccn-calendar-sharing-sharingTargetList=分享目标
|
||||||
|
ccn-calendar-sharing-sharingTargetEditing=正在编辑集合:
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
function cnn_headerNav_Insert() {
|
function cnn_headerNav_Insert() {
|
||||||
$.ajax({
|
$('body').prepend(ccn_template_headerNav.render());
|
||||||
url: $("#jsrender-tmpl-headerNav").attr('src'),
|
|
||||||
type: "GET",
|
|
||||||
async: false,
|
|
||||||
success: function (data) {
|
|
||||||
var tmpl = $.templates(data);
|
|
||||||
$('body').prepend(tmpl.render());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cnn_headerNav_LoggedRefresh() {
|
function cnn_headerNav_LoggedRefresh() {
|
||||||
@@ -57,10 +49,10 @@ function cnn_headerNav_BindEvents() {
|
|||||||
// Check for click events on the navbar burger icon
|
// Check for click events on the navbar burger icon
|
||||||
$(".navbar-burger").click(function() {
|
$(".navbar-burger").click(function() {
|
||||||
|
|
||||||
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
|
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
|
||||||
$(".navbar-burger").toggleClass("is-active");
|
$(".navbar-burger").toggleClass("is-active");
|
||||||
$(".navbar-menu").toggleClass("is-active");
|
$(".navbar-menu").toggleClass("is-active");
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,19 +43,19 @@ function ccn_i18n_ApplyLanguage() {
|
|||||||
//set title
|
//set title
|
||||||
switch(ccn_pages_currentPage) {
|
switch(ccn_pages_currentPage) {
|
||||||
case ccn_pages_enumPages.home:
|
case ccn_pages_enumPages.home:
|
||||||
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-home'))
|
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-home'));
|
||||||
break;
|
break;
|
||||||
case ccn_pages_enumPages.calendar:
|
case ccn_pages_enumPages.calendar:
|
||||||
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-calendar'))
|
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-calendar'));
|
||||||
break;
|
break;
|
||||||
case ccn_pages_enumPages.todo:
|
case ccn_pages_enumPages.todo:
|
||||||
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-todo'))
|
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-todo'));
|
||||||
break;
|
break;
|
||||||
case ccn_pages_enumPages.admin:
|
case ccn_pages_enumPages.admin:
|
||||||
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-admin'))
|
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-admin'));
|
||||||
break;
|
break;
|
||||||
case ccn_pages_enumPages.login:
|
case ccn_pages_enumPages.login:
|
||||||
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-login'))
|
$('#ccn-pageName').html($.i18n.prop('ccn-pageName-login'));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
$(document).ready(function() {
|
||||||
|
ccn_pages_currentPage = ccn_pages_enumPages.admin;
|
||||||
|
|
||||||
|
// template process
|
||||||
|
ccn_template_Load();
|
||||||
|
|
||||||
|
// nav process
|
||||||
|
cnn_headerNav_Insert();
|
||||||
|
cnn_headerNav_BindEvents();
|
||||||
|
cnn_headerNav_LoggedRefresh();
|
||||||
|
|
||||||
|
// apply i18n
|
||||||
|
ccn_i18n_ApplyLanguage();
|
||||||
|
});
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// nav process
|
|
||||||
ccn_pages_currentPage = ccn_pages_enumPages.calendar;
|
ccn_pages_currentPage = ccn_pages_enumPages.calendar;
|
||||||
|
|
||||||
|
// template process
|
||||||
|
ccn_template_Load();
|
||||||
|
|
||||||
|
// nav process
|
||||||
cnn_headerNav_Insert();
|
cnn_headerNav_Insert();
|
||||||
cnn_headerNav_BindEvents();
|
cnn_headerNav_BindEvents();
|
||||||
cnn_headerNav_LoggedRefresh();
|
cnn_headerNav_LoggedRefresh();
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// nav process
|
|
||||||
ccn_pages_currentPage = ccn_pages_enumPages.home;
|
ccn_pages_currentPage = ccn_pages_enumPages.home;
|
||||||
|
|
||||||
|
// template process
|
||||||
|
ccn_template_Load();
|
||||||
|
|
||||||
|
// nav process
|
||||||
cnn_headerNav_Insert();
|
cnn_headerNav_Insert();
|
||||||
cnn_headerNav_BindEvents();
|
cnn_headerNav_BindEvents();
|
||||||
cnn_headerNav_LoggedRefresh();
|
cnn_headerNav_LoggedRefresh();
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// nav process
|
|
||||||
ccn_pages_currentPage = ccn_pages_enumPages.login;
|
ccn_pages_currentPage = ccn_pages_enumPages.login;
|
||||||
|
|
||||||
|
// template process
|
||||||
|
ccn_template_Load();
|
||||||
|
|
||||||
|
// nav process
|
||||||
cnn_headerNav_Insert();
|
cnn_headerNav_Insert();
|
||||||
cnn_headerNav_BindEvents();
|
cnn_headerNav_BindEvents();
|
||||||
cnn_headerNav_LoggedRefresh();
|
cnn_headerNav_LoggedRefresh();
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
var ccn_todo_todoListCache = [];
|
var ccn_todo_todoListCache = [];
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
ccn_pages_currentPage = ccn_pages_enumPages.todo;
|
||||||
|
|
||||||
|
// template process
|
||||||
|
ccn_template_Load();
|
||||||
|
|
||||||
// nav process
|
// nav process
|
||||||
ccn_pages_currentPage = ccn_pages_enumPages.login;
|
|
||||||
cnn_headerNav_Insert();
|
cnn_headerNav_Insert();
|
||||||
cnn_headerNav_BindEvents();
|
cnn_headerNav_BindEvents();
|
||||||
cnn_headerNav_LoggedRefresh();
|
cnn_headerNav_LoggedRefresh();
|
||||||
@@ -40,25 +44,15 @@ function ccn_todo_RenderCacheList() {
|
|||||||
data: undefined
|
data: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
var templates = undefined;
|
|
||||||
$.ajax({
|
|
||||||
url: $("#jsrender-tmpl-todoItem").attr('src'),
|
|
||||||
type: "GET",
|
|
||||||
async: false,
|
|
||||||
success: function (data) {
|
|
||||||
templates = $.templates(data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var listDOM = $("#ccn-todo-todoList");
|
var listDOM = $("#ccn-todo-todoList");
|
||||||
for(var index in ccn_todo_todoListCache) {
|
for(var index in ccn_todo_todoListCache) {
|
||||||
// update render data
|
// update render data
|
||||||
var item = ccn_todo_todoListCache[index];
|
var item = ccn_todo_todoListCache[index];
|
||||||
renderdata.uuid = item[0];
|
renderdata.uuid = item[0];
|
||||||
renderdata.data = item[2];
|
renderdata.data = LineBreaker2Br(item[2]);
|
||||||
|
|
||||||
// render
|
// render
|
||||||
listDOM.append(templates.render(renderdata));
|
listDOM.append(ccn_template_todoItem.render(renderdata));
|
||||||
|
|
||||||
// set mode
|
// set mode
|
||||||
var uuid = renderdata.uuid;
|
var uuid = renderdata.uuid;
|
||||||
@@ -110,22 +104,11 @@ function ccn_todo_Add() {
|
|||||||
// add into cache
|
// add into cache
|
||||||
ccn_todo_todoListCache[result[0]] = result;
|
ccn_todo_todoListCache[result[0]] = result;
|
||||||
|
|
||||||
// render
|
|
||||||
var templates = undefined;
|
|
||||||
$.ajax({
|
|
||||||
url: $("#jsrender-tmpl-todoItem").attr('src'),
|
|
||||||
type: "GET",
|
|
||||||
async: false,
|
|
||||||
success: function (data) {
|
|
||||||
templates = $.templates(data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// render
|
// render
|
||||||
var listDOM = $("#ccn-todo-todoList");
|
var listDOM = $("#ccn-todo-todoList");
|
||||||
listDOM.append(templates.render({
|
listDOM.append(ccn_template_todoItem.render({
|
||||||
uuid: result[0],
|
uuid: result[0],
|
||||||
data: result[2]
|
data: LineBreaker2Br(result[2])
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// set mode
|
// set mode
|
||||||
@@ -145,7 +128,7 @@ function ccn_todo_ItemEdit() {
|
|||||||
|
|
||||||
// copy current data to textarea
|
// copy current data to textarea
|
||||||
$("#ccn-todo-todoItem-textarea-" + uuid).val(
|
$("#ccn-todo-todoItem-textarea-" + uuid).val(
|
||||||
$("#ccn-todo-todoItem-p-" + uuid).text()
|
ccn_todo_todoListCache[uuid][2]
|
||||||
);
|
);
|
||||||
|
|
||||||
// switch to edit mode
|
// switch to edit mode
|
||||||
@@ -186,7 +169,7 @@ function ccn_todo_ItemUpdate() {
|
|||||||
// safely update data & lastChanged and control
|
// safely update data & lastChanged and control
|
||||||
ccn_todo_todoListCache[uuid][2] = newData;
|
ccn_todo_todoListCache[uuid][2] = newData;
|
||||||
ccn_todo_todoListCache[uuid][3] = result;
|
ccn_todo_todoListCache[uuid][3] = result;
|
||||||
$("#ccn-todo-todoItem-p-" + uuid).text(newData);
|
$("#ccn-todo-todoItem-p-" + uuid).html(LineBreaker2Br(newData));
|
||||||
|
|
||||||
// switch to normal mode
|
// switch to normal mode
|
||||||
ccn_todo_ChangeDisplayMode(uuid, false);
|
ccn_todo_ChangeDisplayMode(uuid, false);
|
||||||
|
|||||||
61
src/static/js/template.js
Normal file
61
src/static/js/template.js
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
var ccn_template_headerNav = undefined;
|
||||||
|
var ccn_template_calendarItem = undefined;
|
||||||
|
var ccn_template_scheduleItem = undefined;
|
||||||
|
var ccn_template_userItem = undefined;
|
||||||
|
var ccn_template_todoItem = undefined;
|
||||||
|
|
||||||
|
function ccn_template_Load() {
|
||||||
|
$.ajax({
|
||||||
|
url: $("#jsrender-tmpl-headerNav").attr('src'),
|
||||||
|
type: "GET",
|
||||||
|
async: false,
|
||||||
|
success: function (data) {
|
||||||
|
ccn_template_headerNav = $.templates(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
switch(ccn_pages_currentPage) {
|
||||||
|
case ccn_pages_enumPages.home:
|
||||||
|
break;
|
||||||
|
case ccn_pages_enumPages.calendar:
|
||||||
|
$.ajax({
|
||||||
|
url: $("#jsrender-tmpl-calendarItem").attr('src'),
|
||||||
|
type: "GET",
|
||||||
|
async: false,
|
||||||
|
success: function (data) {
|
||||||
|
ccn_template_calendarItem = $.templates(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$.ajax({
|
||||||
|
url: $("#jsrender-tmpl-scheduleItem").attr('src'),
|
||||||
|
type: "GET",
|
||||||
|
async: false,
|
||||||
|
success: function (data) {
|
||||||
|
ccn_template_scheduleItem = $.templates(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ccn_pages_enumPages.todo:
|
||||||
|
$.ajax({
|
||||||
|
url: $("#jsrender-tmpl-todoItem").attr('src'),
|
||||||
|
type: "GET",
|
||||||
|
async: false,
|
||||||
|
success: function (data) {
|
||||||
|
ccn_template_todoItem = $.templates(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ccn_pages_enumPages.admin:
|
||||||
|
$.ajax({
|
||||||
|
url: $("#jsrender-tmpl-userItem").attr('src'),
|
||||||
|
type: "GET",
|
||||||
|
async: false,
|
||||||
|
success: function (data) {
|
||||||
|
ccn_template_userItem = $.templates(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ccn_pages_enumPages.login:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,3 +36,7 @@ function GetApiToken() {
|
|||||||
function SetApiToken(value) {
|
function SetApiToken(value) {
|
||||||
ccn_localstorageAssist_Set('ccn-token', value);
|
ccn_localstorageAssist_Set('ccn-token', value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function LineBreaker2Br(strl) {
|
||||||
|
return $('<div>').text(strl).html().replace(/\n/g,'<br />');
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<div id="ccn-todo-todoItem-{{:uuid}}" class="todo-item card">
|
<div id="ccn-todo-todoItem-{{:uuid}}" class="todo-item card">
|
||||||
<div class="todo-item-words">
|
<div class="todo-item-words">
|
||||||
<p id="ccn-todo-todoItem-p-{{:uuid}}">{{>data}}</p>
|
<p id="ccn-todo-todoItem-p-{{:uuid}}">{{:data}}</p>
|
||||||
<textarea id="ccn-todo-todoItem-textarea-{{:uuid}}" class="textarea"></textarea>
|
<textarea id="ccn-todo-todoItem-textarea-{{:uuid}}" class="textarea"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/utils.js"></script>
|
<script type="text/javascript" src="/static/js/utils.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/api.js"></script>
|
<script type="text/javascript" src="/static/js/api.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/js/template.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/page/admin.js"></script>
|
<script type="text/javascript" src="/static/js/page/admin.js"></script>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/utils.js"></script>
|
<script type="text/javascript" src="/static/js/utils.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/api.js"></script>
|
<script type="text/javascript" src="/static/js/api.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/js/template.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/tabcontrol.js"></script>
|
<script type="text/javascript" src="/static/js/tabcontrol.js"></script>
|
||||||
|
|
||||||
@@ -46,16 +47,16 @@
|
|||||||
<input class="input" type="date">
|
<input class="input" type="date">
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button i18n-name="ccn-calendar-jump" class="button is-info"></button>
|
<button i18n-name="ccn-calendar-calendar-jump" class="button is-info"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="level-item control">
|
<div class="level-item control">
|
||||||
<a i18n-name="ccn-calendar-today" class="button is-info"></a>
|
<a i18n-name="ccn-calendar-calendar-today" class="button is-info"></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="level-item control">
|
<div class="level-item control">
|
||||||
<a i18n-name="ccn-calendar-add" class="button is-primary"></a>
|
<a i18n-name="ccn-calendar-calendar-add" class="button is-primary"></a>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container" style="padding: 1.25rem; display: flex; flex-flow: column; margin-top: 1.25rem;">
|
<div class="container" style="padding: 1.25rem; display: flex; flex-flow: column; margin-top: 1.25rem;">
|
||||||
<h1 i18n-name="ccn-calendar-scheduleList" class="title"></h1>
|
<h1 i18n-name="ccn-calendar-calendar-scheduleList" class="title"></h1>
|
||||||
|
|
||||||
<div id="schedule-list">
|
<div id="schedule-list">
|
||||||
<div class="schedule-day container">
|
<div class="schedule-day container">
|
||||||
@@ -174,7 +175,7 @@
|
|||||||
<div id="tabcontrol-panel-1-2" class="container tabcontrol-panel-1" style="margin-top: 20px;">
|
<div id="tabcontrol-panel-1-2" class="container tabcontrol-panel-1" style="margin-top: 20px;">
|
||||||
|
|
||||||
<div class="container" style="display: flex; flex-flow: column;">
|
<div class="container" style="display: flex; flex-flow: column;">
|
||||||
<h1 class="title">Shared</h1>
|
<h1 i18n-name="ccn-calendar-shared-list" class="title"></h1>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<a class="button is-primary">
|
<a class="button is-primary">
|
||||||
@@ -215,7 +216,7 @@
|
|||||||
<div id="tabcontrol-panel-1-3" class="container tabcontrol-panel-1" style="margin-top: 20px;">
|
<div id="tabcontrol-panel-1-3" class="container tabcontrol-panel-1" style="margin-top: 20px;">
|
||||||
|
|
||||||
<div class="container" style="display: flex; flex-flow: column;">
|
<div class="container" style="display: flex; flex-flow: column;">
|
||||||
<h1 class="title">Owned</h1>
|
<h1 i18n-name="ccn-calendar-sharing-ownedList" class="title"></h1>
|
||||||
<div class="control-list">
|
<div class="control-list">
|
||||||
<div class="field has-addons">
|
<div class="field has-addons">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
@@ -272,8 +273,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container" style="display: flex; flex-flow: column;">
|
<div class="container" style="display: flex; flex-flow: column;">
|
||||||
<h1 class="title">Sharing target</h1>
|
<h1 i18n-name="ccn-calendar-sharing-sharingTargetList" class="title"></h1>
|
||||||
<label class="label"><span>Editing: </span><span>xxx</span></label>
|
<label class="label"><span i18n-name="ccn-calendar-sharing-sharingTargetEditing"></span><span>xxx</span></label>
|
||||||
|
|
||||||
<div class="control-list">
|
<div class="control-list">
|
||||||
<div class="field has-addons">
|
<div class="field has-addons">
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/utils.js"></script>
|
<script type="text/javascript" src="/static/js/utils.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/api.js"></script>
|
<script type="text/javascript" src="/static/js/api.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/js/template.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/page/home.js"></script>
|
<script type="text/javascript" src="/static/js/page/home.js"></script>
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/utils.js"></script>
|
<script type="text/javascript" src="/static/js/utils.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/api.js"></script>
|
<script type="text/javascript" src="/static/js/api.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/js/template.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/page/login.js"></script>
|
<script type="text/javascript" src="/static/js/page/login.js"></script>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
<script type="text/javascript" src="/static/js/i18n.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/utils.js"></script>
|
<script type="text/javascript" src="/static/js/utils.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/api.js"></script>
|
<script type="text/javascript" src="/static/js/api.js"></script>
|
||||||
|
<script type="text/javascript" src="/static/js/template.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
<script type="text/javascript" src="/static/js/headerNav.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/page/todo.js"></script>
|
<script type="text/javascript" src="/static/js/page/todo.js"></script>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ def GenerateUUID():
|
|||||||
def GenerateToken(username):
|
def GenerateToken(username):
|
||||||
s = hashlib.sha256()
|
s = hashlib.sha256()
|
||||||
s.update(username.encode('utf-8'))
|
s.update(username.encode('utf-8'))
|
||||||
s.update((str(GenerateSalt())).encode('utf-8'))
|
s.update(GenerateUUID().encode('utf-8'))
|
||||||
return s.hexdigest()
|
return s.hexdigest()
|
||||||
|
|
||||||
def GenerateSalt():
|
def GenerateSalt():
|
||||||
@@ -36,3 +36,6 @@ def ComputePasswordHashWithSalt(passwordHashed, salt):
|
|||||||
|
|
||||||
def GetCurrentTimestamp():
|
def GetCurrentTimestamp():
|
||||||
return int(time.time())
|
return int(time.time())
|
||||||
|
|
||||||
|
def GetTokenExpireOn():
|
||||||
|
return GetCurrentTimestamp() + 60 * 60 * 24 * 2 # add 2 day from now
|
||||||
Reference in New Issue
Block a user