Switched to spaces
This commit is contained in:
parent
79df9b56d3
commit
2702518e31
265 changed files with 14902 additions and 14902 deletions
|
@ -2,130 +2,130 @@ var App = App || {};
|
|||
|
||||
App.API = function(_, jQuery, promise, appState) {
|
||||
|
||||
var baseUrl = '/api/';
|
||||
var AJAX_UNSENT = 0;
|
||||
var AJAX_OPENED = 1;
|
||||
var AJAX_HEADERS_RECEIVED = 2;
|
||||
var AJAX_LOADING = 3;
|
||||
var AJAX_DONE = 4;
|
||||
var baseUrl = '/api/';
|
||||
var AJAX_UNSENT = 0;
|
||||
var AJAX_OPENED = 1;
|
||||
var AJAX_HEADERS_RECEIVED = 2;
|
||||
var AJAX_LOADING = 3;
|
||||
var AJAX_DONE = 4;
|
||||
|
||||
var cache = {};
|
||||
var cache = {};
|
||||
|
||||
function get(url, data) {
|
||||
return request('GET', url, data);
|
||||
}
|
||||
function get(url, data) {
|
||||
return request('GET', url, data);
|
||||
}
|
||||
|
||||
function post(url, data) {
|
||||
return request('POST', url, data);
|
||||
}
|
||||
function post(url, data) {
|
||||
return request('POST', url, data);
|
||||
}
|
||||
|
||||
function put(url, data) {
|
||||
return request('PUT', url, data);
|
||||
}
|
||||
function put(url, data) {
|
||||
return request('PUT', url, data);
|
||||
}
|
||||
|
||||
function _delete(url, data) {
|
||||
return request('DELETE', url, data);
|
||||
}
|
||||
function _delete(url, data) {
|
||||
return request('DELETE', url, data);
|
||||
}
|
||||
|
||||
function getCacheKey(method, url, data) {
|
||||
return JSON.stringify({method: method, url: url, data: data});
|
||||
}
|
||||
function getCacheKey(method, url, data) {
|
||||
return JSON.stringify({method: method, url: url, data: data});
|
||||
}
|
||||
|
||||
function clearCache() {
|
||||
cache = {};
|
||||
}
|
||||
function clearCache() {
|
||||
cache = {};
|
||||
}
|
||||
|
||||
function request(method, url, data) {
|
||||
if (method === 'GET') {
|
||||
return requestWithCache(method, url, data);
|
||||
}
|
||||
clearCache();
|
||||
return requestWithAjax(method, url, data);
|
||||
}
|
||||
function request(method, url, data) {
|
||||
if (method === 'GET') {
|
||||
return requestWithCache(method, url, data);
|
||||
}
|
||||
clearCache();
|
||||
return requestWithAjax(method, url, data);
|
||||
}
|
||||
|
||||
function requestWithCache(method, url, data) {
|
||||
var cacheKey = getCacheKey(method, url, data);
|
||||
if (_.has(cache, cacheKey)) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
resolve(cache[cacheKey]);
|
||||
});
|
||||
}
|
||||
function requestWithCache(method, url, data) {
|
||||
var cacheKey = getCacheKey(method, url, data);
|
||||
if (_.has(cache, cacheKey)) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
resolve(cache[cacheKey]);
|
||||
});
|
||||
}
|
||||
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(requestWithAjax(method, url, data))
|
||||
.then(function(response) {
|
||||
setCache(method, url, data, response);
|
||||
resolve(response);
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(requestWithAjax(method, url, data))
|
||||
.then(function(response) {
|
||||
setCache(method, url, data, response);
|
||||
resolve(response);
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setCache(method, url, data, response) {
|
||||
var cacheKey = getCacheKey(method, url, data);
|
||||
cache[cacheKey] = response;
|
||||
}
|
||||
function setCache(method, url, data, response) {
|
||||
var cacheKey = getCacheKey(method, url, data);
|
||||
cache[cacheKey] = response;
|
||||
}
|
||||
|
||||
function requestWithAjax(method, url, data) {
|
||||
var fullUrl = baseUrl + '/' + url;
|
||||
fullUrl = fullUrl.replace(/\/{2,}/, '/');
|
||||
function requestWithAjax(method, url, data) {
|
||||
var fullUrl = baseUrl + '/' + url;
|
||||
fullUrl = fullUrl.replace(/\/{2,}/, '/');
|
||||
|
||||
var xhr = null;
|
||||
var apiPromise = promise.make(function(resolve, reject) {
|
||||
var options = {
|
||||
headers: {
|
||||
'X-Authorization-Token': appState.get('loginToken') || '',
|
||||
},
|
||||
success: function(data, textStatus, xhr) {
|
||||
resolve({
|
||||
status: xhr.status,
|
||||
json: stripMeta(data)});
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
reject({
|
||||
status: xhr.status,
|
||||
json: xhr.responseJSON ?
|
||||
stripMeta(xhr.responseJSON) :
|
||||
{error: errorThrown}});
|
||||
},
|
||||
type: method,
|
||||
url: fullUrl,
|
||||
data: data,
|
||||
cache: false,
|
||||
};
|
||||
if (data instanceof FormData) {
|
||||
options.processData = false;
|
||||
options.contentType = false;
|
||||
}
|
||||
xhr = jQuery.ajax(options);
|
||||
});
|
||||
apiPromise.xhr = xhr;
|
||||
return apiPromise;
|
||||
}
|
||||
var xhr = null;
|
||||
var apiPromise = promise.make(function(resolve, reject) {
|
||||
var options = {
|
||||
headers: {
|
||||
'X-Authorization-Token': appState.get('loginToken') || '',
|
||||
},
|
||||
success: function(data, textStatus, xhr) {
|
||||
resolve({
|
||||
status: xhr.status,
|
||||
json: stripMeta(data)});
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
reject({
|
||||
status: xhr.status,
|
||||
json: xhr.responseJSON ?
|
||||
stripMeta(xhr.responseJSON) :
|
||||
{error: errorThrown}});
|
||||
},
|
||||
type: method,
|
||||
url: fullUrl,
|
||||
data: data,
|
||||
cache: false,
|
||||
};
|
||||
if (data instanceof FormData) {
|
||||
options.processData = false;
|
||||
options.contentType = false;
|
||||
}
|
||||
xhr = jQuery.ajax(options);
|
||||
});
|
||||
apiPromise.xhr = xhr;
|
||||
return apiPromise;
|
||||
}
|
||||
|
||||
function stripMeta(data) {
|
||||
var result = {};
|
||||
_.each(data, function(v, k) {
|
||||
if (!k.match(/^__/)) {
|
||||
result[k] = v;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function stripMeta(data) {
|
||||
var result = {};
|
||||
_.each(data, function(v, k) {
|
||||
if (!k.match(/^__/)) {
|
||||
result[k] = v;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
return {
|
||||
get: get,
|
||||
post: post,
|
||||
put: put,
|
||||
delete: _delete,
|
||||
return {
|
||||
get: get,
|
||||
post: post,
|
||||
put: put,
|
||||
delete: _delete,
|
||||
|
||||
AJAX_UNSENT: AJAX_UNSENT,
|
||||
AJAX_OPENED: AJAX_OPENED,
|
||||
AJAX_HEADERS_RECEIVED: AJAX_HEADERS_RECEIVED,
|
||||
AJAX_LOADING: AJAX_LOADING,
|
||||
AJAX_DONE: AJAX_DONE,
|
||||
};
|
||||
AJAX_UNSENT: AJAX_UNSENT,
|
||||
AJAX_OPENED: AJAX_OPENED,
|
||||
AJAX_HEADERS_RECEIVED: AJAX_HEADERS_RECEIVED,
|
||||
AJAX_LOADING: AJAX_LOADING,
|
||||
AJAX_DONE: AJAX_DONE,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,198 +2,198 @@ var App = App || {};
|
|||
|
||||
App.Auth = function(_, jQuery, util, api, appState, promise) {
|
||||
|
||||
var privileges = {
|
||||
register: 'register',
|
||||
listUsers: 'listUsers',
|
||||
viewUsers: 'viewUsers',
|
||||
viewAllAccessRanks: 'viewAllAccessRanks',
|
||||
viewAllEmailAddresses: 'viewAllEmailAddresses',
|
||||
changeAccessRank: 'changeAccessRank',
|
||||
changeOwnAvatarStyle: 'changeOwnAvatarStyle',
|
||||
changeOwnEmailAddress: 'changeOwnEmailAddress',
|
||||
changeOwnName: 'changeOwnName',
|
||||
changeOwnPassword: 'changeOwnPassword',
|
||||
changeAllAvatarStyles: 'changeAllAvatarStyles',
|
||||
changeAllEmailAddresses: 'changeAllEmailAddresses',
|
||||
changeAllNames: 'changeAllNames',
|
||||
changeAllPasswords: 'changeAllPasswords',
|
||||
deleteOwnAccount: 'deleteOwnAccount',
|
||||
deleteAllAccounts: 'deleteAllAccounts',
|
||||
banUsers: 'banUsers',
|
||||
var privileges = {
|
||||
register: 'register',
|
||||
listUsers: 'listUsers',
|
||||
viewUsers: 'viewUsers',
|
||||
viewAllAccessRanks: 'viewAllAccessRanks',
|
||||
viewAllEmailAddresses: 'viewAllEmailAddresses',
|
||||
changeAccessRank: 'changeAccessRank',
|
||||
changeOwnAvatarStyle: 'changeOwnAvatarStyle',
|
||||
changeOwnEmailAddress: 'changeOwnEmailAddress',
|
||||
changeOwnName: 'changeOwnName',
|
||||
changeOwnPassword: 'changeOwnPassword',
|
||||
changeAllAvatarStyles: 'changeAllAvatarStyles',
|
||||
changeAllEmailAddresses: 'changeAllEmailAddresses',
|
||||
changeAllNames: 'changeAllNames',
|
||||
changeAllPasswords: 'changeAllPasswords',
|
||||
deleteOwnAccount: 'deleteOwnAccount',
|
||||
deleteAllAccounts: 'deleteAllAccounts',
|
||||
banUsers: 'banUsers',
|
||||
|
||||
listPosts: 'listPosts',
|
||||
viewPosts: 'viewPosts',
|
||||
uploadPosts: 'uploadPosts',
|
||||
uploadPostsAnonymously: 'uploadPostsAnonymously',
|
||||
deletePosts: 'deletePosts',
|
||||
featurePosts: 'featurePosts',
|
||||
changePostSafety: 'changePostSafety',
|
||||
changePostSource: 'changePostSource',
|
||||
changePostTags: 'changePostTags',
|
||||
changePostContent: 'changePostContent',
|
||||
changePostThumbnail: 'changePostThumbnail',
|
||||
changePostRelations: 'changePostRelations',
|
||||
changePostFlags: 'changePostFlags',
|
||||
listPosts: 'listPosts',
|
||||
viewPosts: 'viewPosts',
|
||||
uploadPosts: 'uploadPosts',
|
||||
uploadPostsAnonymously: 'uploadPostsAnonymously',
|
||||
deletePosts: 'deletePosts',
|
||||
featurePosts: 'featurePosts',
|
||||
changePostSafety: 'changePostSafety',
|
||||
changePostSource: 'changePostSource',
|
||||
changePostTags: 'changePostTags',
|
||||
changePostContent: 'changePostContent',
|
||||
changePostThumbnail: 'changePostThumbnail',
|
||||
changePostRelations: 'changePostRelations',
|
||||
changePostFlags: 'changePostFlags',
|
||||
|
||||
addPostNotes: 'addPostNotes',
|
||||
editPostNotes: 'editPostNotes',
|
||||
deletePostNotes: 'deletePostNotes',
|
||||
addPostNotes: 'addPostNotes',
|
||||
editPostNotes: 'editPostNotes',
|
||||
deletePostNotes: 'deletePostNotes',
|
||||
|
||||
listComments: 'listComments',
|
||||
addComments: 'addComments',
|
||||
editOwnComments: 'editOwnComments',
|
||||
editAllComments: 'editAllComments',
|
||||
deleteOwnComments: 'deleteOwnComments',
|
||||
deleteAllComments: 'deleteAllComments',
|
||||
deleteTags: 'deleteTags',
|
||||
mergeTags: 'mergeTags',
|
||||
listComments: 'listComments',
|
||||
addComments: 'addComments',
|
||||
editOwnComments: 'editOwnComments',
|
||||
editAllComments: 'editAllComments',
|
||||
deleteOwnComments: 'deleteOwnComments',
|
||||
deleteAllComments: 'deleteAllComments',
|
||||
deleteTags: 'deleteTags',
|
||||
mergeTags: 'mergeTags',
|
||||
|
||||
listTags: 'listTags',
|
||||
massTag: 'massTag',
|
||||
changeTagName: 'changeTagName',
|
||||
changeTagCategory: 'changeTagCategory',
|
||||
changeTagImplications: 'changeTagImplications',
|
||||
changeTagSuggestions: 'changeTagSuggestions',
|
||||
banTags: 'banTags',
|
||||
listTags: 'listTags',
|
||||
massTag: 'massTag',
|
||||
changeTagName: 'changeTagName',
|
||||
changeTagCategory: 'changeTagCategory',
|
||||
changeTagImplications: 'changeTagImplications',
|
||||
changeTagSuggestions: 'changeTagSuggestions',
|
||||
banTags: 'banTags',
|
||||
|
||||
viewHistory: 'viewHistory',
|
||||
};
|
||||
viewHistory: 'viewHistory',
|
||||
};
|
||||
|
||||
function loginFromCredentials(userNameOrEmail, password, remember) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.post('/login', {userNameOrEmail: userNameOrEmail, password: password}))
|
||||
.then(function(response) {
|
||||
updateAppState(response);
|
||||
jQuery.cookie(
|
||||
'auth',
|
||||
response.json.token.name,
|
||||
remember ? { expires: 365 } : {});
|
||||
resolve(response);
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
function loginFromCredentials(userNameOrEmail, password, remember) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.post('/login', {userNameOrEmail: userNameOrEmail, password: password}))
|
||||
.then(function(response) {
|
||||
updateAppState(response);
|
||||
jQuery.cookie(
|
||||
'auth',
|
||||
response.json.token.name,
|
||||
remember ? { expires: 365 } : {});
|
||||
resolve(response);
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function loginFromToken(token, isFromCookie) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
var fd = {
|
||||
token: token,
|
||||
isFromCookie: isFromCookie
|
||||
};
|
||||
promise.wait(api.post('/login', fd))
|
||||
.then(function(response) {
|
||||
updateAppState(response);
|
||||
resolve(response);
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
function loginFromToken(token, isFromCookie) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
var fd = {
|
||||
token: token,
|
||||
isFromCookie: isFromCookie
|
||||
};
|
||||
promise.wait(api.post('/login', fd))
|
||||
.then(function(response) {
|
||||
updateAppState(response);
|
||||
resolve(response);
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function loginAnonymous() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.post('/login'))
|
||||
.then(function(response) {
|
||||
updateAppState(response);
|
||||
resolve(response);
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
function loginAnonymous() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.post('/login'))
|
||||
.then(function(response) {
|
||||
updateAppState(response);
|
||||
resolve(response);
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function logout() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
jQuery.removeCookie('auth');
|
||||
appState.set('loginToken', null);
|
||||
return promise.wait(loginAnonymous())
|
||||
.then(resolve)
|
||||
.fail(reject);
|
||||
});
|
||||
}
|
||||
function logout() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
jQuery.removeCookie('auth');
|
||||
appState.set('loginToken', null);
|
||||
return promise.wait(loginAnonymous())
|
||||
.then(resolve)
|
||||
.fail(reject);
|
||||
});
|
||||
}
|
||||
|
||||
function tryLoginFromCookie() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
if (isLoggedIn()) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
function tryLoginFromCookie() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
if (isLoggedIn()) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
var authCookie = jQuery.cookie('auth');
|
||||
if (!authCookie) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
var authCookie = jQuery.cookie('auth');
|
||||
if (!authCookie) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
|
||||
promise.wait(loginFromToken(authCookie, true))
|
||||
.then(function(response) {
|
||||
resolve();
|
||||
}).fail(function(response) {
|
||||
jQuery.removeCookie('auth');
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
promise.wait(loginFromToken(authCookie, true))
|
||||
.then(function(response) {
|
||||
resolve();
|
||||
}).fail(function(response) {
|
||||
jQuery.removeCookie('auth');
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function updateAppState(response) {
|
||||
appState.set('privileges', response.json.privileges || []);
|
||||
appState.set('loginToken', response.json.token && response.json.token.name);
|
||||
appState.set('loggedIn', response.json.user && !!response.json.user.id);
|
||||
appState.set('loggedInUser', response.json.user);
|
||||
}
|
||||
function updateAppState(response) {
|
||||
appState.set('privileges', response.json.privileges || []);
|
||||
appState.set('loginToken', response.json.token && response.json.token.name);
|
||||
appState.set('loggedIn', response.json.user && !!response.json.user.id);
|
||||
appState.set('loggedInUser', response.json.user);
|
||||
}
|
||||
|
||||
function isLoggedIn(userName) {
|
||||
if (!appState.get('loggedIn')) {
|
||||
return false;
|
||||
}
|
||||
if (typeof(userName) !== 'undefined') {
|
||||
if (getCurrentUser().name !== userName) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
function isLoggedIn(userName) {
|
||||
if (!appState.get('loggedIn')) {
|
||||
return false;
|
||||
}
|
||||
if (typeof(userName) !== 'undefined') {
|
||||
if (getCurrentUser().name !== userName) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getCurrentUser() {
|
||||
return appState.get('loggedInUser');
|
||||
}
|
||||
function getCurrentUser() {
|
||||
return appState.get('loggedInUser');
|
||||
}
|
||||
|
||||
function getCurrentPrivileges() {
|
||||
return appState.get('privileges');
|
||||
}
|
||||
function getCurrentPrivileges() {
|
||||
return appState.get('privileges');
|
||||
}
|
||||
|
||||
function updateCurrentUser(user) {
|
||||
if (user.id !== getCurrentUser().id) {
|
||||
throw new Error('Cannot set current user to other user this way.');
|
||||
}
|
||||
appState.set('loggedInUser', user);
|
||||
}
|
||||
function updateCurrentUser(user) {
|
||||
if (user.id !== getCurrentUser().id) {
|
||||
throw new Error('Cannot set current user to other user this way.');
|
||||
}
|
||||
appState.set('loggedInUser', user);
|
||||
}
|
||||
|
||||
function hasPrivilege(privilege) {
|
||||
return _.contains(getCurrentPrivileges(), privilege);
|
||||
}
|
||||
function hasPrivilege(privilege) {
|
||||
return _.contains(getCurrentPrivileges(), privilege);
|
||||
}
|
||||
|
||||
function startObservingLoginChanges(listenerName, callback) {
|
||||
appState.startObserving('loggedInUser', listenerName, callback);
|
||||
}
|
||||
function startObservingLoginChanges(listenerName, callback) {
|
||||
appState.startObserving('loggedInUser', listenerName, callback);
|
||||
}
|
||||
|
||||
return {
|
||||
loginFromCredentials: loginFromCredentials,
|
||||
loginFromToken: loginFromToken,
|
||||
loginAnonymous: loginAnonymous,
|
||||
tryLoginFromCookie: tryLoginFromCookie,
|
||||
logout: logout,
|
||||
return {
|
||||
loginFromCredentials: loginFromCredentials,
|
||||
loginFromToken: loginFromToken,
|
||||
loginAnonymous: loginAnonymous,
|
||||
tryLoginFromCookie: tryLoginFromCookie,
|
||||
logout: logout,
|
||||
|
||||
startObservingLoginChanges: startObservingLoginChanges,
|
||||
isLoggedIn: isLoggedIn,
|
||||
getCurrentUser: getCurrentUser,
|
||||
updateCurrentUser: updateCurrentUser,
|
||||
getCurrentPrivileges: getCurrentPrivileges,
|
||||
hasPrivilege: hasPrivilege,
|
||||
startObservingLoginChanges: startObservingLoginChanges,
|
||||
isLoggedIn: isLoggedIn,
|
||||
getCurrentUser: getCurrentUser,
|
||||
updateCurrentUser: updateCurrentUser,
|
||||
getCurrentPrivileges: getCurrentPrivileges,
|
||||
hasPrivilege: hasPrivilege,
|
||||
|
||||
privileges: privileges,
|
||||
};
|
||||
privileges: privileges,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,29 +2,29 @@ var App = App || {};
|
|||
|
||||
App.Bootstrap = function(auth, router, promise, presenterManager) {
|
||||
|
||||
promise.wait(presenterManager.init())
|
||||
.then(function() {
|
||||
promise.wait(auth.tryLoginFromCookie())
|
||||
.then(startRouting)
|
||||
.fail(function(error) {
|
||||
promise.wait(auth.loginAnonymous())
|
||||
.then(startRouting)
|
||||
.fail(function() {
|
||||
console.log(arguments);
|
||||
window.alert('Fatal authentication error');
|
||||
});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
});
|
||||
promise.wait(presenterManager.init())
|
||||
.then(function() {
|
||||
promise.wait(auth.tryLoginFromCookie())
|
||||
.then(startRouting)
|
||||
.fail(function(error) {
|
||||
promise.wait(auth.loginAnonymous())
|
||||
.then(startRouting)
|
||||
.fail(function() {
|
||||
console.log(arguments);
|
||||
window.alert('Fatal authentication error');
|
||||
});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
});
|
||||
|
||||
function startRouting() {
|
||||
try {
|
||||
router.start();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
function startRouting() {
|
||||
try {
|
||||
router.start();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1,96 +1,96 @@
|
|||
var App = App || {};
|
||||
|
||||
App.BrowsingSettings = function(
|
||||
promise,
|
||||
auth,
|
||||
api) {
|
||||
promise,
|
||||
auth,
|
||||
api) {
|
||||
|
||||
var settings = getDefaultSettings();
|
||||
var settings = getDefaultSettings();
|
||||
|
||||
auth.startObservingLoginChanges('browsing-settings', loginStateChanged);
|
||||
auth.startObservingLoginChanges('browsing-settings', loginStateChanged);
|
||||
|
||||
readFromLocalStorage();
|
||||
if (auth.isLoggedIn()) {
|
||||
loginStateChanged();
|
||||
}
|
||||
readFromLocalStorage();
|
||||
if (auth.isLoggedIn()) {
|
||||
loginStateChanged();
|
||||
}
|
||||
|
||||
function setSettings(newSettings) {
|
||||
settings = newSettings;
|
||||
return save();
|
||||
}
|
||||
function setSettings(newSettings) {
|
||||
settings = newSettings;
|
||||
return save();
|
||||
}
|
||||
|
||||
function getSettings() {
|
||||
return settings;
|
||||
}
|
||||
function getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
function getDefaultSettings() {
|
||||
return {
|
||||
hideDownvoted: true,
|
||||
endlessScroll: false,
|
||||
listPosts: {
|
||||
safe: true,
|
||||
sketchy: true,
|
||||
unsafe: true,
|
||||
},
|
||||
keyboardShortcuts: true,
|
||||
};
|
||||
}
|
||||
function getDefaultSettings() {
|
||||
return {
|
||||
hideDownvoted: true,
|
||||
endlessScroll: false,
|
||||
listPosts: {
|
||||
safe: true,
|
||||
sketchy: true,
|
||||
unsafe: true,
|
||||
},
|
||||
keyboardShortcuts: true,
|
||||
};
|
||||
}
|
||||
|
||||
function loginStateChanged() {
|
||||
readFromUser(auth.getCurrentUser());
|
||||
}
|
||||
function loginStateChanged() {
|
||||
readFromUser(auth.getCurrentUser());
|
||||
}
|
||||
|
||||
function readFromLocalStorage() {
|
||||
readFromString(localStorage.getItem('browsingSettings'));
|
||||
}
|
||||
function readFromLocalStorage() {
|
||||
readFromString(localStorage.getItem('browsingSettings'));
|
||||
}
|
||||
|
||||
function readFromUser(user) {
|
||||
readFromString(user.browsingSettings);
|
||||
}
|
||||
function readFromUser(user) {
|
||||
readFromString(user.browsingSettings);
|
||||
}
|
||||
|
||||
function readFromString(string) {
|
||||
if (!string) {
|
||||
return;
|
||||
}
|
||||
function readFromString(string) {
|
||||
if (!string) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof(string) === 'string' || string instanceof String) {
|
||||
settings = JSON.parse(string);
|
||||
} else {
|
||||
settings = string;
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (typeof(string) === 'string' || string instanceof String) {
|
||||
settings = JSON.parse(string);
|
||||
} else {
|
||||
settings = string;
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
function saveToLocalStorage() {
|
||||
localStorage.setItem('browsingSettings', JSON.stringify(settings));
|
||||
}
|
||||
function saveToLocalStorage() {
|
||||
localStorage.setItem('browsingSettings', JSON.stringify(settings));
|
||||
}
|
||||
|
||||
function saveToUser(user) {
|
||||
var formData = {
|
||||
browsingSettings: JSON.stringify(settings),
|
||||
};
|
||||
return api.post('/users/' + user.name, formData);
|
||||
}
|
||||
function saveToUser(user) {
|
||||
var formData = {
|
||||
browsingSettings: JSON.stringify(settings),
|
||||
};
|
||||
return api.post('/users/' + user.name, formData);
|
||||
}
|
||||
|
||||
function save() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
saveToLocalStorage();
|
||||
if (auth.isLoggedIn()) {
|
||||
promise.wait(saveToUser(auth.getCurrentUser()))
|
||||
.then(resolve)
|
||||
.fail(reject);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
function save() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
saveToLocalStorage();
|
||||
if (auth.isLoggedIn()) {
|
||||
promise.wait(saveToUser(auth.getCurrentUser()))
|
||||
.then(resolve)
|
||||
.fail(reject);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getSettings: getSettings,
|
||||
setSettings: setSettings,
|
||||
};
|
||||
return {
|
||||
getSettings: getSettings,
|
||||
setSettings: setSettings,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,273 +2,273 @@ var App = App || {};
|
|||
App.Controls = App.Controls || {};
|
||||
|
||||
App.Controls.AutoCompleteInput = function($input) {
|
||||
var _ = App.DI.get('_');
|
||||
var jQuery = App.DI.get('jQuery');
|
||||
var tagList = App.DI.get('tagList');
|
||||
var _ = App.DI.get('_');
|
||||
var jQuery = App.DI.get('jQuery');
|
||||
var tagList = App.DI.get('tagList');
|
||||
|
||||
var KEY_TAB = 9;
|
||||
var KEY_RETURN = 13;
|
||||
var KEY_DELETE = 46;
|
||||
var KEY_ESCAPE = 27;
|
||||
var KEY_UP = 38;
|
||||
var KEY_DOWN = 40;
|
||||
var KEY_TAB = 9;
|
||||
var KEY_RETURN = 13;
|
||||
var KEY_DELETE = 46;
|
||||
var KEY_ESCAPE = 27;
|
||||
var KEY_UP = 38;
|
||||
var KEY_DOWN = 40;
|
||||
|
||||
var options = {
|
||||
caseSensitive: false,
|
||||
source: null,
|
||||
maxResults: 15,
|
||||
minLengthToArbitrarySearch: 3,
|
||||
onApply: null,
|
||||
onDelete: null,
|
||||
onRender: null,
|
||||
additionalFilter: null,
|
||||
};
|
||||
var showTimeout = null;
|
||||
var cachedSource = null;
|
||||
var results = [];
|
||||
var activeResult = -1;
|
||||
var monitorInputHidingInterval = null;
|
||||
var options = {
|
||||
caseSensitive: false,
|
||||
source: null,
|
||||
maxResults: 15,
|
||||
minLengthToArbitrarySearch: 3,
|
||||
onApply: null,
|
||||
onDelete: null,
|
||||
onRender: null,
|
||||
additionalFilter: null,
|
||||
};
|
||||
var showTimeout = null;
|
||||
var cachedSource = null;
|
||||
var results = [];
|
||||
var activeResult = -1;
|
||||
var monitorInputHidingInterval = null;
|
||||
|
||||
if ($input.length === 0) {
|
||||
throw new Error('Input element was not found');
|
||||
}
|
||||
if ($input.length > 1) {
|
||||
throw new Error('Cannot add autocompletion to more than one element at once');
|
||||
}
|
||||
if ($input.attr('data-autocomplete')) {
|
||||
throw new Error('Autocompletion was already added for this element');
|
||||
}
|
||||
$input.attr('data-autocomplete', true);
|
||||
$input.attr('autocomplete', 'off');
|
||||
if ($input.length === 0) {
|
||||
throw new Error('Input element was not found');
|
||||
}
|
||||
if ($input.length > 1) {
|
||||
throw new Error('Cannot add autocompletion to more than one element at once');
|
||||
}
|
||||
if ($input.attr('data-autocomplete')) {
|
||||
throw new Error('Autocompletion was already added for this element');
|
||||
}
|
||||
$input.attr('data-autocomplete', true);
|
||||
$input.attr('autocomplete', 'off');
|
||||
|
||||
var $div = jQuery('<div>');
|
||||
var $list = jQuery('<ul>');
|
||||
$div.addClass('autocomplete');
|
||||
$div.append($list);
|
||||
jQuery(document.body).append($div);
|
||||
var $div = jQuery('<div>');
|
||||
var $list = jQuery('<ul>');
|
||||
$div.addClass('autocomplete');
|
||||
$div.append($list);
|
||||
jQuery(document.body).append($div);
|
||||
|
||||
function getSource() {
|
||||
if (cachedSource) {
|
||||
return cachedSource;
|
||||
} else {
|
||||
var source = tagList.getTags();
|
||||
source = _.sortBy(source, function(a) { return -a.usages; });
|
||||
source = _.filter(source, function(a) { return a.usages >= 0; });
|
||||
source = _.map(source, function(a) {
|
||||
return {
|
||||
tag: a.name,
|
||||
caption: a.name + ' (' + a.usages + ')',
|
||||
};
|
||||
});
|
||||
cachedSource = source;
|
||||
return source;
|
||||
}
|
||||
}
|
||||
function getSource() {
|
||||
if (cachedSource) {
|
||||
return cachedSource;
|
||||
} else {
|
||||
var source = tagList.getTags();
|
||||
source = _.sortBy(source, function(a) { return -a.usages; });
|
||||
source = _.filter(source, function(a) { return a.usages >= 0; });
|
||||
source = _.map(source, function(a) {
|
||||
return {
|
||||
tag: a.name,
|
||||
caption: a.name + ' (' + a.usages + ')',
|
||||
};
|
||||
});
|
||||
cachedSource = source;
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
$input.bind('keydown', function(e) {
|
||||
var func = null;
|
||||
if (isShown() && e.which === KEY_ESCAPE) {
|
||||
func = hide;
|
||||
} else if (isShown() && e.which === KEY_TAB) {
|
||||
if (e.shiftKey) {
|
||||
func = selectPrevious;
|
||||
} else {
|
||||
func = selectNext;
|
||||
}
|
||||
} else if (isShown() && e.which === KEY_DOWN) {
|
||||
func = selectNext;
|
||||
} else if (isShown() && e.which === KEY_UP) {
|
||||
func = selectPrevious;
|
||||
} else if (isShown() && e.which === KEY_RETURN && activeResult >= 0) {
|
||||
func = function() { applyAutocomplete(); hide(); };
|
||||
} else if (isShown() && e.which === KEY_DELETE && activeResult >= 0) {
|
||||
func = function() { applyDelete(); hide(); };
|
||||
}
|
||||
$input.bind('keydown', function(e) {
|
||||
var func = null;
|
||||
if (isShown() && e.which === KEY_ESCAPE) {
|
||||
func = hide;
|
||||
} else if (isShown() && e.which === KEY_TAB) {
|
||||
if (e.shiftKey) {
|
||||
func = selectPrevious;
|
||||
} else {
|
||||
func = selectNext;
|
||||
}
|
||||
} else if (isShown() && e.which === KEY_DOWN) {
|
||||
func = selectNext;
|
||||
} else if (isShown() && e.which === KEY_UP) {
|
||||
func = selectPrevious;
|
||||
} else if (isShown() && e.which === KEY_RETURN && activeResult >= 0) {
|
||||
func = function() { applyAutocomplete(); hide(); };
|
||||
} else if (isShown() && e.which === KEY_DELETE && activeResult >= 0) {
|
||||
func = function() { applyDelete(); hide(); };
|
||||
}
|
||||
|
||||
if (func !== null) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
func();
|
||||
} else {
|
||||
window.clearTimeout(showTimeout);
|
||||
showTimeout = window.setTimeout(showOrHide, 250);
|
||||
}
|
||||
});
|
||||
if (func !== null) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
func();
|
||||
} else {
|
||||
window.clearTimeout(showTimeout);
|
||||
showTimeout = window.setTimeout(showOrHide, 250);
|
||||
}
|
||||
});
|
||||
|
||||
$input.blur(function(e) {
|
||||
window.clearTimeout(showTimeout);
|
||||
window.setTimeout(function() { hide(); }, 50);
|
||||
});
|
||||
$input.blur(function(e) {
|
||||
window.clearTimeout(showTimeout);
|
||||
window.setTimeout(function() { hide(); }, 50);
|
||||
});
|
||||
|
||||
function getSelectionStart(){
|
||||
var input = $input.get(0);
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
if ('selectionStart' in input) {
|
||||
return input.selectionStart;
|
||||
} else if (document.selection) {
|
||||
input.focus();
|
||||
var sel = document.selection.createRange();
|
||||
var selLen = document.selection.createRange().text.length;
|
||||
sel.moveStart('character', -input.value.length);
|
||||
return sel.text.length - selLen;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
function getSelectionStart(){
|
||||
var input = $input.get(0);
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
if ('selectionStart' in input) {
|
||||
return input.selectionStart;
|
||||
} else if (document.selection) {
|
||||
input.focus();
|
||||
var sel = document.selection.createRange();
|
||||
var selLen = document.selection.createRange().text.length;
|
||||
sel.moveStart('character', -input.value.length);
|
||||
return sel.text.length - selLen;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
function getTextToFind() {
|
||||
var val = $input.val();
|
||||
var start = getSelectionStart();
|
||||
return val.substring(0, start).replace(/.*\s/, '');
|
||||
}
|
||||
function getTextToFind() {
|
||||
var val = $input.val();
|
||||
var start = getSelectionStart();
|
||||
return val.substring(0, start).replace(/.*\s/, '');
|
||||
}
|
||||
|
||||
function showOrHide() {
|
||||
var textToFind = getTextToFind();
|
||||
if (textToFind.length === 0) {
|
||||
hide();
|
||||
} else {
|
||||
updateResults(textToFind);
|
||||
refreshList();
|
||||
}
|
||||
}
|
||||
function showOrHide() {
|
||||
var textToFind = getTextToFind();
|
||||
if (textToFind.length === 0) {
|
||||
hide();
|
||||
} else {
|
||||
updateResults(textToFind);
|
||||
refreshList();
|
||||
}
|
||||
}
|
||||
|
||||
function isShown() {
|
||||
return $div.is(':visible');
|
||||
}
|
||||
function isShown() {
|
||||
return $div.is(':visible');
|
||||
}
|
||||
|
||||
function hide() {
|
||||
$div.hide();
|
||||
window.clearInterval(monitorInputHidingInterval);
|
||||
}
|
||||
function hide() {
|
||||
$div.hide();
|
||||
window.clearInterval(monitorInputHidingInterval);
|
||||
}
|
||||
|
||||
function selectPrevious() {
|
||||
select(activeResult === -1 ? results.length - 1 : activeResult - 1);
|
||||
}
|
||||
function selectPrevious() {
|
||||
select(activeResult === -1 ? results.length - 1 : activeResult - 1);
|
||||
}
|
||||
|
||||
function selectNext() {
|
||||
select(activeResult === -1 ? 0 : activeResult + 1);
|
||||
}
|
||||
function selectNext() {
|
||||
select(activeResult === -1 ? 0 : activeResult + 1);
|
||||
}
|
||||
|
||||
function select(newActiveResult) {
|
||||
if (newActiveResult >= 0 && newActiveResult < results.length) {
|
||||
activeResult = newActiveResult;
|
||||
refreshActiveResult();
|
||||
} else {
|
||||
activeResult = - 1;
|
||||
refreshActiveResult();
|
||||
}
|
||||
}
|
||||
function select(newActiveResult) {
|
||||
if (newActiveResult >= 0 && newActiveResult < results.length) {
|
||||
activeResult = newActiveResult;
|
||||
refreshActiveResult();
|
||||
} else {
|
||||
activeResult = - 1;
|
||||
refreshActiveResult();
|
||||
}
|
||||
}
|
||||
|
||||
function getResultsFilter(textToFind) {
|
||||
if (textToFind.length < options.minLengthToArbitrarySearch) {
|
||||
return options.caseSensitive ?
|
||||
function(resultItem) { return resultItem.tag.indexOf(textToFind) === 0; } :
|
||||
function(resultItem) { return resultItem.tag.toLowerCase().indexOf(textToFind.toLowerCase()) === 0; };
|
||||
} else {
|
||||
return options.caseSensitive ?
|
||||
function(resultItem) { return resultItem.tag.indexOf(textToFind) >= 0; } :
|
||||
function(resultItem) { return resultItem.tag.toLowerCase().indexOf(textToFind.toLowerCase()) >= 0; };
|
||||
}
|
||||
}
|
||||
function getResultsFilter(textToFind) {
|
||||
if (textToFind.length < options.minLengthToArbitrarySearch) {
|
||||
return options.caseSensitive ?
|
||||
function(resultItem) { return resultItem.tag.indexOf(textToFind) === 0; } :
|
||||
function(resultItem) { return resultItem.tag.toLowerCase().indexOf(textToFind.toLowerCase()) === 0; };
|
||||
} else {
|
||||
return options.caseSensitive ?
|
||||
function(resultItem) { return resultItem.tag.indexOf(textToFind) >= 0; } :
|
||||
function(resultItem) { return resultItem.tag.toLowerCase().indexOf(textToFind.toLowerCase()) >= 0; };
|
||||
}
|
||||
}
|
||||
|
||||
function updateResults(textToFind) {
|
||||
var oldResults = results.slice();
|
||||
var source = getSource();
|
||||
var filter = getResultsFilter(textToFind);
|
||||
results = _.filter(source, filter);
|
||||
if (options.additionalFilter) {
|
||||
results = options.additionalFilter(results);
|
||||
}
|
||||
results = results.slice(0, options.maxResults);
|
||||
if (!_.isEqual(oldResults, results)) {
|
||||
activeResult = -1;
|
||||
}
|
||||
}
|
||||
function updateResults(textToFind) {
|
||||
var oldResults = results.slice();
|
||||
var source = getSource();
|
||||
var filter = getResultsFilter(textToFind);
|
||||
results = _.filter(source, filter);
|
||||
if (options.additionalFilter) {
|
||||
results = options.additionalFilter(results);
|
||||
}
|
||||
results = results.slice(0, options.maxResults);
|
||||
if (!_.isEqual(oldResults, results)) {
|
||||
activeResult = -1;
|
||||
}
|
||||
}
|
||||
|
||||
function applyDelete() {
|
||||
if (options.onDelete) {
|
||||
options.onDelete(results[activeResult].tag);
|
||||
}
|
||||
}
|
||||
function applyDelete() {
|
||||
if (options.onDelete) {
|
||||
options.onDelete(results[activeResult].tag);
|
||||
}
|
||||
}
|
||||
|
||||
function applyAutocomplete() {
|
||||
if (options.onApply) {
|
||||
options.onApply(results[activeResult].tag);
|
||||
} else {
|
||||
var val = $input.val();
|
||||
var start = getSelectionStart();
|
||||
var prefix = '';
|
||||
var suffix = val.substring(start);
|
||||
var middle = val.substring(0, start);
|
||||
var index = middle.lastIndexOf(' ');
|
||||
if (index !== -1) {
|
||||
prefix = val.substring(0, index + 1);
|
||||
middle = val.substring(index + 1);
|
||||
}
|
||||
$input.val(prefix + results[activeResult].tag + ' ' + suffix.trimLeft());
|
||||
$input.focus();
|
||||
}
|
||||
}
|
||||
function applyAutocomplete() {
|
||||
if (options.onApply) {
|
||||
options.onApply(results[activeResult].tag);
|
||||
} else {
|
||||
var val = $input.val();
|
||||
var start = getSelectionStart();
|
||||
var prefix = '';
|
||||
var suffix = val.substring(start);
|
||||
var middle = val.substring(0, start);
|
||||
var index = middle.lastIndexOf(' ');
|
||||
if (index !== -1) {
|
||||
prefix = val.substring(0, index + 1);
|
||||
middle = val.substring(index + 1);
|
||||
}
|
||||
$input.val(prefix + results[activeResult].tag + ' ' + suffix.trimLeft());
|
||||
$input.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function refreshList() {
|
||||
if (results.length === 0) {
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
function refreshList() {
|
||||
if (results.length === 0) {
|
||||
hide();
|
||||
return;
|
||||
}
|
||||
|
||||
$list.empty();
|
||||
_.each(results, function(resultItem, resultIndex) {
|
||||
var $listItem = jQuery('<li/>');
|
||||
$listItem.text(resultItem.caption);
|
||||
$listItem.attr('data-key', resultItem.tag);
|
||||
$listItem.hover(function(e) {
|
||||
e.preventDefault();
|
||||
activeResult = resultIndex;
|
||||
refreshActiveResult();
|
||||
});
|
||||
$listItem.mousedown(function(e) {
|
||||
e.preventDefault();
|
||||
activeResult = resultIndex;
|
||||
applyAutocomplete();
|
||||
hide();
|
||||
});
|
||||
$list.append($listItem);
|
||||
});
|
||||
if (options.onRender) {
|
||||
options.onRender($list);
|
||||
}
|
||||
refreshActiveResult();
|
||||
$list.empty();
|
||||
_.each(results, function(resultItem, resultIndex) {
|
||||
var $listItem = jQuery('<li/>');
|
||||
$listItem.text(resultItem.caption);
|
||||
$listItem.attr('data-key', resultItem.tag);
|
||||
$listItem.hover(function(e) {
|
||||
e.preventDefault();
|
||||
activeResult = resultIndex;
|
||||
refreshActiveResult();
|
||||
});
|
||||
$listItem.mousedown(function(e) {
|
||||
e.preventDefault();
|
||||
activeResult = resultIndex;
|
||||
applyAutocomplete();
|
||||
hide();
|
||||
});
|
||||
$list.append($listItem);
|
||||
});
|
||||
if (options.onRender) {
|
||||
options.onRender($list);
|
||||
}
|
||||
refreshActiveResult();
|
||||
|
||||
var x = $input.offset().left;
|
||||
var y = $input.offset().top + $input.outerHeight() - 2;
|
||||
if (y + $div.height() > window.innerHeight) {
|
||||
y = $input.offset().top - $div.height();
|
||||
}
|
||||
$div.css({
|
||||
left: x + 'px',
|
||||
top: y + 'px',
|
||||
});
|
||||
$div.show();
|
||||
monitorInputHiding();
|
||||
}
|
||||
var x = $input.offset().left;
|
||||
var y = $input.offset().top + $input.outerHeight() - 2;
|
||||
if (y + $div.height() > window.innerHeight) {
|
||||
y = $input.offset().top - $div.height();
|
||||
}
|
||||
$div.css({
|
||||
left: x + 'px',
|
||||
top: y + 'px',
|
||||
});
|
||||
$div.show();
|
||||
monitorInputHiding();
|
||||
}
|
||||
|
||||
function refreshActiveResult() {
|
||||
$list.find('li.active').removeClass('active');
|
||||
if (activeResult >= 0) {
|
||||
$list.find('li').eq(activeResult).addClass('active');
|
||||
}
|
||||
}
|
||||
function refreshActiveResult() {
|
||||
$list.find('li.active').removeClass('active');
|
||||
if (activeResult >= 0) {
|
||||
$list.find('li').eq(activeResult).addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
function monitorInputHiding() {
|
||||
monitorInputHidingInterval = window.setInterval(function() {
|
||||
if (!$input.is(':visible')) {
|
||||
hide();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
function monitorInputHiding() {
|
||||
monitorInputHidingInterval = window.setInterval(function() {
|
||||
if (!$input.is(':visible')) {
|
||||
hide();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
return options;
|
||||
return options;
|
||||
};
|
||||
|
|
|
@ -2,64 +2,64 @@ var App = App || {};
|
|||
App.Controls = App.Controls || {};
|
||||
|
||||
App.Controls.FileDropper = function($fileInput) {
|
||||
var _ = App.DI.get('_');
|
||||
var jQuery = App.DI.get('jQuery');
|
||||
var _ = App.DI.get('_');
|
||||
var jQuery = App.DI.get('jQuery');
|
||||
|
||||
var options = {
|
||||
onChange: null,
|
||||
setNames: false,
|
||||
};
|
||||
var options = {
|
||||
onChange: null,
|
||||
setNames: false,
|
||||
};
|
||||
|
||||
var $dropDiv = jQuery('<button type="button" class="file-handler"></button>');
|
||||
var allowMultiple = $fileInput.attr('multiple');
|
||||
$dropDiv.html((allowMultiple ? 'Drop files here!' : 'Drop file here!') + '<br/>Or just click on this box.');
|
||||
$dropDiv.insertBefore($fileInput);
|
||||
$fileInput.attr('multiple', allowMultiple);
|
||||
$fileInput.hide();
|
||||
var $dropDiv = jQuery('<button type="button" class="file-handler"></button>');
|
||||
var allowMultiple = $fileInput.attr('multiple');
|
||||
$dropDiv.html((allowMultiple ? 'Drop files here!' : 'Drop file here!') + '<br/>Or just click on this box.');
|
||||
$dropDiv.insertBefore($fileInput);
|
||||
$fileInput.attr('multiple', allowMultiple);
|
||||
$fileInput.hide();
|
||||
|
||||
$fileInput.change(function(e) {
|
||||
addFiles(this.files);
|
||||
});
|
||||
$fileInput.change(function(e) {
|
||||
addFiles(this.files);
|
||||
});
|
||||
|
||||
$dropDiv.on('dragenter', function(e) {
|
||||
$dropDiv.addClass('active');
|
||||
}).on('dragleave', function(e) {
|
||||
$dropDiv.removeClass('active');
|
||||
}).on('dragover', function(e) {
|
||||
e.preventDefault();
|
||||
}).on('drop', function(e) {
|
||||
e.preventDefault();
|
||||
addFiles(e.originalEvent.dataTransfer.files);
|
||||
}).on('click', function(e) {
|
||||
$fileInput.show().focus().trigger('click').hide();
|
||||
$dropDiv.addClass('active');
|
||||
});
|
||||
$dropDiv.on('dragenter', function(e) {
|
||||
$dropDiv.addClass('active');
|
||||
}).on('dragleave', function(e) {
|
||||
$dropDiv.removeClass('active');
|
||||
}).on('dragover', function(e) {
|
||||
e.preventDefault();
|
||||
}).on('drop', function(e) {
|
||||
e.preventDefault();
|
||||
addFiles(e.originalEvent.dataTransfer.files);
|
||||
}).on('click', function(e) {
|
||||
$fileInput.show().focus().trigger('click').hide();
|
||||
$dropDiv.addClass('active');
|
||||
});
|
||||
|
||||
function addFiles(files) {
|
||||
$dropDiv.removeClass('active');
|
||||
if (!allowMultiple && files.length > 1) {
|
||||
window.alert('Cannot select multiple files.');
|
||||
return;
|
||||
}
|
||||
if (typeof(options.onChange) !== 'undefined') {
|
||||
options.onChange(files);
|
||||
}
|
||||
if (options.setNames && !allowMultiple) {
|
||||
$dropDiv.text(files[0].name);
|
||||
}
|
||||
}
|
||||
function addFiles(files) {
|
||||
$dropDiv.removeClass('active');
|
||||
if (!allowMultiple && files.length > 1) {
|
||||
window.alert('Cannot select multiple files.');
|
||||
return;
|
||||
}
|
||||
if (typeof(options.onChange) !== 'undefined') {
|
||||
options.onChange(files);
|
||||
}
|
||||
if (options.setNames && !allowMultiple) {
|
||||
$dropDiv.text(files[0].name);
|
||||
}
|
||||
}
|
||||
|
||||
function readAsDataURL(file, callback) {
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = function() {
|
||||
callback(reader.result);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
function readAsDataURL(file, callback) {
|
||||
var reader = new FileReader();
|
||||
reader.onloadend = function() {
|
||||
callback(reader.result);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
_.extend(options, {
|
||||
readAsDataURL: readAsDataURL,
|
||||
});
|
||||
_.extend(options, {
|
||||
readAsDataURL: readAsDataURL,
|
||||
});
|
||||
|
||||
return options;
|
||||
return options;
|
||||
};
|
||||
|
|
|
@ -2,419 +2,419 @@ var App = App || {};
|
|||
App.Controls = App.Controls || {};
|
||||
|
||||
App.Controls.TagInput = function($underlyingInput) {
|
||||
var _ = App.DI.get('_');
|
||||
var jQuery = App.DI.get('jQuery');
|
||||
var promise = App.DI.get('promise');
|
||||
var api = App.DI.get('api');
|
||||
var tagList = App.DI.get('tagList');
|
||||
var _ = App.DI.get('_');
|
||||
var jQuery = App.DI.get('jQuery');
|
||||
var promise = App.DI.get('promise');
|
||||
var api = App.DI.get('api');
|
||||
var tagList = App.DI.get('tagList');
|
||||
|
||||
var KEY_RETURN = 13;
|
||||
var KEY_SPACE = 32;
|
||||
var KEY_BACKSPACE = 8;
|
||||
var tagConfirmKeys = [KEY_RETURN, KEY_SPACE];
|
||||
var inputConfirmKeys = [KEY_RETURN];
|
||||
var KEY_RETURN = 13;
|
||||
var KEY_SPACE = 32;
|
||||
var KEY_BACKSPACE = 8;
|
||||
var tagConfirmKeys = [KEY_RETURN, KEY_SPACE];
|
||||
var inputConfirmKeys = [KEY_RETURN];
|
||||
|
||||
var SOURCE_INITIAL_TEXT = 1;
|
||||
var SOURCE_AUTOCOMPLETION = 2;
|
||||
var SOURCE_PASTE = 3;
|
||||
var SOURCE_IMPLICATIONS = 4;
|
||||
var SOURCE_INPUT_BLUR = 5;
|
||||
var SOURCE_INPUT_ENTER = 6;
|
||||
var SOURCE_SUGGESTIONS = 7;
|
||||
var SOURCE_INITIAL_TEXT = 1;
|
||||
var SOURCE_AUTOCOMPLETION = 2;
|
||||
var SOURCE_PASTE = 3;
|
||||
var SOURCE_IMPLICATIONS = 4;
|
||||
var SOURCE_INPUT_BLUR = 5;
|
||||
var SOURCE_INPUT_ENTER = 6;
|
||||
var SOURCE_SUGGESTIONS = 7;
|
||||
|
||||
var tags = [];
|
||||
var options = {
|
||||
beforeTagAdded: null,
|
||||
beforeTagRemoved: null,
|
||||
inputConfirmed: null,
|
||||
};
|
||||
var tags = [];
|
||||
var options = {
|
||||
beforeTagAdded: null,
|
||||
beforeTagRemoved: null,
|
||||
inputConfirmed: null,
|
||||
};
|
||||
|
||||
var $wrapper = jQuery('<div class="tag-input">');
|
||||
var $tagList = jQuery('<ul class="tags">');
|
||||
var tagInputId = 'tags' + Math.random();
|
||||
var $label = jQuery('<label for="' + tagInputId + '" style="display: none">Tags:</label>');
|
||||
var $input = jQuery('<input class="tag-real-input" type="text" id="' + tagInputId + '"/>');
|
||||
var $siblings = jQuery('<div class="related-tags"><span>Sibling tags:</span><ul>');
|
||||
var $suggestions = jQuery('<div class="related-tags"><span>Suggested tags:</span><ul>');
|
||||
init();
|
||||
render();
|
||||
initAutoComplete();
|
||||
var $wrapper = jQuery('<div class="tag-input">');
|
||||
var $tagList = jQuery('<ul class="tags">');
|
||||
var tagInputId = 'tags' + Math.random();
|
||||
var $label = jQuery('<label for="' + tagInputId + '" style="display: none">Tags:</label>');
|
||||
var $input = jQuery('<input class="tag-real-input" type="text" id="' + tagInputId + '"/>');
|
||||
var $siblings = jQuery('<div class="related-tags"><span>Sibling tags:</span><ul>');
|
||||
var $suggestions = jQuery('<div class="related-tags"><span>Suggested tags:</span><ul>');
|
||||
init();
|
||||
render();
|
||||
initAutoComplete();
|
||||
|
||||
function init() {
|
||||
if ($underlyingInput.length === 0) {
|
||||
throw new Error('Tag input element was not found');
|
||||
}
|
||||
if ($underlyingInput.length > 1) {
|
||||
throw new Error('Cannot set tag input to more than one element at once');
|
||||
}
|
||||
if ($underlyingInput.attr('data-tagged')) {
|
||||
throw new Error('Tag input was already initialized for this element');
|
||||
}
|
||||
$underlyingInput.attr('data-tagged', true);
|
||||
}
|
||||
function init() {
|
||||
if ($underlyingInput.length === 0) {
|
||||
throw new Error('Tag input element was not found');
|
||||
}
|
||||
if ($underlyingInput.length > 1) {
|
||||
throw new Error('Cannot set tag input to more than one element at once');
|
||||
}
|
||||
if ($underlyingInput.attr('data-tagged')) {
|
||||
throw new Error('Tag input was already initialized for this element');
|
||||
}
|
||||
$underlyingInput.attr('data-tagged', true);
|
||||
}
|
||||
|
||||
function render() {
|
||||
$underlyingInput.hide();
|
||||
$wrapper.append($tagList);
|
||||
$wrapper.append($label);
|
||||
$wrapper.append($input);
|
||||
$wrapper.insertAfter($underlyingInput);
|
||||
$wrapper.click(function(e) {
|
||||
if (e.target.nodeName === 'LI') {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
$input.focus();
|
||||
});
|
||||
$input.attr('placeholder', $underlyingInput.attr('placeholder'));
|
||||
$siblings.insertAfter($wrapper);
|
||||
$suggestions.insertAfter($wrapper);
|
||||
function render() {
|
||||
$underlyingInput.hide();
|
||||
$wrapper.append($tagList);
|
||||
$wrapper.append($label);
|
||||
$wrapper.append($input);
|
||||
$wrapper.insertAfter($underlyingInput);
|
||||
$wrapper.click(function(e) {
|
||||
if (e.target.nodeName === 'LI') {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
$input.focus();
|
||||
});
|
||||
$input.attr('placeholder', $underlyingInput.attr('placeholder'));
|
||||
$siblings.insertAfter($wrapper);
|
||||
$suggestions.insertAfter($wrapper);
|
||||
|
||||
processText($underlyingInput.val(), SOURCE_INITIAL_TEXT);
|
||||
processText($underlyingInput.val(), SOURCE_INITIAL_TEXT);
|
||||
|
||||
$underlyingInput.val('');
|
||||
}
|
||||
$underlyingInput.val('');
|
||||
}
|
||||
|
||||
function initAutoComplete() {
|
||||
var autoComplete = new App.Controls.AutoCompleteInput($input);
|
||||
autoComplete.onDelete = function(text) {
|
||||
removeTag(text);
|
||||
$input.val('');
|
||||
};
|
||||
autoComplete.onApply = function(text) {
|
||||
processText(text, SOURCE_AUTOCOMPLETION);
|
||||
$input.val('');
|
||||
};
|
||||
autoComplete.additionalFilter = function(results) {
|
||||
return _.filter(results, function(resultItem) {
|
||||
return !_.contains(getTags(), resultItem[0]);
|
||||
});
|
||||
};
|
||||
autoComplete.onRender = function($list) {
|
||||
$list.find('li').each(function() {
|
||||
var $li = jQuery(this);
|
||||
if (isTaggedWith($li.attr('data-key'))) {
|
||||
$li.css('opacity', '0.5');
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
function initAutoComplete() {
|
||||
var autoComplete = new App.Controls.AutoCompleteInput($input);
|
||||
autoComplete.onDelete = function(text) {
|
||||
removeTag(text);
|
||||
$input.val('');
|
||||
};
|
||||
autoComplete.onApply = function(text) {
|
||||
processText(text, SOURCE_AUTOCOMPLETION);
|
||||
$input.val('');
|
||||
};
|
||||
autoComplete.additionalFilter = function(results) {
|
||||
return _.filter(results, function(resultItem) {
|
||||
return !_.contains(getTags(), resultItem[0]);
|
||||
});
|
||||
};
|
||||
autoComplete.onRender = function($list) {
|
||||
$list.find('li').each(function() {
|
||||
var $li = jQuery(this);
|
||||
if (isTaggedWith($li.attr('data-key'))) {
|
||||
$li.css('opacity', '0.5');
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
$input.bind('focus', function(e) {
|
||||
$wrapper.addClass('focused');
|
||||
});
|
||||
$input.bind('blur', function(e) {
|
||||
$wrapper.removeClass('focused');
|
||||
var tagName = $input.val();
|
||||
addTag(tagName, SOURCE_INPUT_BLUR);
|
||||
$input.val('');
|
||||
});
|
||||
$input.bind('focus', function(e) {
|
||||
$wrapper.addClass('focused');
|
||||
});
|
||||
$input.bind('blur', function(e) {
|
||||
$wrapper.removeClass('focused');
|
||||
var tagName = $input.val();
|
||||
addTag(tagName, SOURCE_INPUT_BLUR);
|
||||
$input.val('');
|
||||
});
|
||||
|
||||
$input.bind('paste', function(e) {
|
||||
e.preventDefault();
|
||||
var pastedText;
|
||||
if (window.clipboardData) {
|
||||
pastedText = window.clipboardData.getData('Text');
|
||||
} else {
|
||||
pastedText = (e.originalEvent || e).clipboardData.getData('text/plain');
|
||||
}
|
||||
$input.bind('paste', function(e) {
|
||||
e.preventDefault();
|
||||
var pastedText;
|
||||
if (window.clipboardData) {
|
||||
pastedText = window.clipboardData.getData('Text');
|
||||
} else {
|
||||
pastedText = (e.originalEvent || e).clipboardData.getData('text/plain');
|
||||
}
|
||||
|
||||
if (pastedText.length > 2000) {
|
||||
window.alert('Pasted text is too long.');
|
||||
return;
|
||||
}
|
||||
if (pastedText.length > 2000) {
|
||||
window.alert('Pasted text is too long.');
|
||||
return;
|
||||
}
|
||||
|
||||
processTextWithoutLast(pastedText, SOURCE_PASTE);
|
||||
});
|
||||
processTextWithoutLast(pastedText, SOURCE_PASTE);
|
||||
});
|
||||
|
||||
$input.bind('keydown', function(e) {
|
||||
if (_.contains(inputConfirmKeys, e.which) && !$input.val()) {
|
||||
e.preventDefault();
|
||||
if (typeof(options.inputConfirmed) !== 'undefined') {
|
||||
options.inputConfirmed();
|
||||
}
|
||||
} else if (_.contains(tagConfirmKeys, e.which)) {
|
||||
var tagName = $input.val();
|
||||
e.preventDefault();
|
||||
$input.val('');
|
||||
addTag(tagName, SOURCE_INPUT_ENTER);
|
||||
} else if (e.which === KEY_BACKSPACE && jQuery(this).val().length === 0) {
|
||||
e.preventDefault();
|
||||
removeLastTag();
|
||||
}
|
||||
});
|
||||
$input.bind('keydown', function(e) {
|
||||
if (_.contains(inputConfirmKeys, e.which) && !$input.val()) {
|
||||
e.preventDefault();
|
||||
if (typeof(options.inputConfirmed) !== 'undefined') {
|
||||
options.inputConfirmed();
|
||||
}
|
||||
} else if (_.contains(tagConfirmKeys, e.which)) {
|
||||
var tagName = $input.val();
|
||||
e.preventDefault();
|
||||
$input.val('');
|
||||
addTag(tagName, SOURCE_INPUT_ENTER);
|
||||
} else if (e.which === KEY_BACKSPACE && jQuery(this).val().length === 0) {
|
||||
e.preventDefault();
|
||||
removeLastTag();
|
||||
}
|
||||
});
|
||||
|
||||
function explodeText(text) {
|
||||
return _.filter(text.trim().split(/\s+/), function(item) {
|
||||
return item.length > 0;
|
||||
});
|
||||
}
|
||||
function explodeText(text) {
|
||||
return _.filter(text.trim().split(/\s+/), function(item) {
|
||||
return item.length > 0;
|
||||
});
|
||||
}
|
||||
|
||||
function processText(text, source) {
|
||||
var tagNamesToAdd = explodeText(text);
|
||||
_.map(tagNamesToAdd, function(tagName) { addTag(tagName, source); });
|
||||
}
|
||||
function processText(text, source) {
|
||||
var tagNamesToAdd = explodeText(text);
|
||||
_.map(tagNamesToAdd, function(tagName) { addTag(tagName, source); });
|
||||
}
|
||||
|
||||
function processTextWithoutLast(text, source) {
|
||||
var tagNamesToAdd = explodeText(text);
|
||||
var lastTagName = tagNamesToAdd.pop();
|
||||
_.map(tagNamesToAdd, function(tagName) { addTag(tagName, source); });
|
||||
$input.val(lastTagName);
|
||||
}
|
||||
function processTextWithoutLast(text, source) {
|
||||
var tagNamesToAdd = explodeText(text);
|
||||
var lastTagName = tagNamesToAdd.pop();
|
||||
_.map(tagNamesToAdd, function(tagName) { addTag(tagName, source); });
|
||||
$input.val(lastTagName);
|
||||
}
|
||||
|
||||
function addTag(tagName, source) {
|
||||
tagName = tagName.trim();
|
||||
if (tagName.length === 0) {
|
||||
return;
|
||||
}
|
||||
function addTag(tagName, source) {
|
||||
tagName = tagName.trim();
|
||||
if (tagName.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tagName.length > 64) {
|
||||
//showing alert inside keydown event leads to mysterious behaviors
|
||||
//in some browsers, hence the timeout
|
||||
window.setTimeout(function() {
|
||||
window.alert('Tag is too long.');
|
||||
}, 10);
|
||||
return;
|
||||
}
|
||||
if (tagName.length > 64) {
|
||||
//showing alert inside keydown event leads to mysterious behaviors
|
||||
//in some browsers, hence the timeout
|
||||
window.setTimeout(function() {
|
||||
window.alert('Tag is too long.');
|
||||
}, 10);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isTaggedWith(tagName)) {
|
||||
flashTagRed(tagName);
|
||||
} else {
|
||||
beforeTagAdded(tagName, source);
|
||||
if (isTaggedWith(tagName)) {
|
||||
flashTagRed(tagName);
|
||||
} else {
|
||||
beforeTagAdded(tagName, source);
|
||||
|
||||
var exportedTag = getExportedTag(tagName);
|
||||
if (!exportedTag || !exportedTag.banned) {
|
||||
tags.push(tagName);
|
||||
var $elem = createListElement(tagName);
|
||||
$tagList.append($elem);
|
||||
}
|
||||
var exportedTag = getExportedTag(tagName);
|
||||
if (!exportedTag || !exportedTag.banned) {
|
||||
tags.push(tagName);
|
||||
var $elem = createListElement(tagName);
|
||||
$tagList.append($elem);
|
||||
}
|
||||
|
||||
afterTagAdded(tagName, source);
|
||||
}
|
||||
}
|
||||
afterTagAdded(tagName, source);
|
||||
}
|
||||
}
|
||||
|
||||
function beforeTagRemoved(tagName) {
|
||||
if (typeof(options.beforeTagRemoved) === 'function') {
|
||||
options.beforeTagRemoved(tagName);
|
||||
}
|
||||
}
|
||||
function beforeTagRemoved(tagName) {
|
||||
if (typeof(options.beforeTagRemoved) === 'function') {
|
||||
options.beforeTagRemoved(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
function afterTagRemoved(tagName) {
|
||||
refreshShownSiblings();
|
||||
}
|
||||
function afterTagRemoved(tagName) {
|
||||
refreshShownSiblings();
|
||||
}
|
||||
|
||||
function beforeTagAdded(tagName, source) {
|
||||
if (typeof(options.beforeTagAdded) === 'function') {
|
||||
options.beforeTagAdded(tagName);
|
||||
}
|
||||
}
|
||||
function beforeTagAdded(tagName, source) {
|
||||
if (typeof(options.beforeTagAdded) === 'function') {
|
||||
options.beforeTagAdded(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
function afterTagAdded(tagName, source) {
|
||||
if (source === SOURCE_IMPLICATIONS) {
|
||||
flashTagYellow(tagName);
|
||||
} else if (source !== SOURCE_INITIAL_TEXT) {
|
||||
var tag = getExportedTag(tagName);
|
||||
if (tag) {
|
||||
_.each(tag.implications, function(impliedTagName) {
|
||||
if (!isTaggedWith(impliedTagName)) {
|
||||
addTag(impliedTagName, SOURCE_IMPLICATIONS);
|
||||
}
|
||||
});
|
||||
if (source !== SOURCE_IMPLICATIONS && source !== SOURCE_SUGGESTIONS) {
|
||||
showOrHideSuggestions(tagName);
|
||||
refreshShownSiblings();
|
||||
}
|
||||
} else {
|
||||
flashTagGreen(tagName);
|
||||
}
|
||||
}
|
||||
}
|
||||
function afterTagAdded(tagName, source) {
|
||||
if (source === SOURCE_IMPLICATIONS) {
|
||||
flashTagYellow(tagName);
|
||||
} else if (source !== SOURCE_INITIAL_TEXT) {
|
||||
var tag = getExportedTag(tagName);
|
||||
if (tag) {
|
||||
_.each(tag.implications, function(impliedTagName) {
|
||||
if (!isTaggedWith(impliedTagName)) {
|
||||
addTag(impliedTagName, SOURCE_IMPLICATIONS);
|
||||
}
|
||||
});
|
||||
if (source !== SOURCE_IMPLICATIONS && source !== SOURCE_SUGGESTIONS) {
|
||||
showOrHideSuggestions(tagName);
|
||||
refreshShownSiblings();
|
||||
}
|
||||
} else {
|
||||
flashTagGreen(tagName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getExportedTag(tagName) {
|
||||
return _.first(_.filter(
|
||||
tagList.getTags(),
|
||||
function(t) {
|
||||
return t.name.toLowerCase() === tagName.toLowerCase();
|
||||
}));
|
||||
}
|
||||
function getExportedTag(tagName) {
|
||||
return _.first(_.filter(
|
||||
tagList.getTags(),
|
||||
function(t) {
|
||||
return t.name.toLowerCase() === tagName.toLowerCase();
|
||||
}));
|
||||
}
|
||||
|
||||
function removeTag(tagName) {
|
||||
var oldTagNames = getTags();
|
||||
var newTagNames = _.without(oldTagNames, tagName);
|
||||
if (newTagNames.length !== oldTagNames.length) {
|
||||
beforeTagRemoved(tagName);
|
||||
setTags(newTagNames);
|
||||
afterTagRemoved(tagName);
|
||||
}
|
||||
}
|
||||
function removeTag(tagName) {
|
||||
var oldTagNames = getTags();
|
||||
var newTagNames = _.without(oldTagNames, tagName);
|
||||
if (newTagNames.length !== oldTagNames.length) {
|
||||
beforeTagRemoved(tagName);
|
||||
setTags(newTagNames);
|
||||
afterTagRemoved(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
function isTaggedWith(tagName) {
|
||||
var tagNames = _.map(getTags(), function(tagName) {
|
||||
return tagName.toLowerCase();
|
||||
});
|
||||
return _.contains(tagNames, tagName.toLowerCase());
|
||||
}
|
||||
function isTaggedWith(tagName) {
|
||||
var tagNames = _.map(getTags(), function(tagName) {
|
||||
return tagName.toLowerCase();
|
||||
});
|
||||
return _.contains(tagNames, tagName.toLowerCase());
|
||||
}
|
||||
|
||||
function removeLastTag() {
|
||||
removeTag(_.last(getTags()));
|
||||
}
|
||||
function removeLastTag() {
|
||||
removeTag(_.last(getTags()));
|
||||
}
|
||||
|
||||
function flashTagRed(tagName) {
|
||||
flashTag(tagName, 'rgba(255, 200, 200, 1)');
|
||||
}
|
||||
function flashTagRed(tagName) {
|
||||
flashTag(tagName, 'rgba(255, 200, 200, 1)');
|
||||
}
|
||||
|
||||
function flashTagYellow(tagName) {
|
||||
flashTag(tagName, 'rgba(255, 255, 200, 1)');
|
||||
}
|
||||
function flashTagYellow(tagName) {
|
||||
flashTag(tagName, 'rgba(255, 255, 200, 1)');
|
||||
}
|
||||
|
||||
function flashTagGreen(tagName) {
|
||||
flashTag(tagName, 'rgba(200, 255, 200, 1)');
|
||||
}
|
||||
function flashTagGreen(tagName) {
|
||||
flashTag(tagName, 'rgba(200, 255, 200, 1)');
|
||||
}
|
||||
|
||||
function flashTag(tagName, color) {
|
||||
var $elem = getListElement(tagName);
|
||||
$elem.css({backgroundColor: color});
|
||||
}
|
||||
function flashTag(tagName, color) {
|
||||
var $elem = getListElement(tagName);
|
||||
$elem.css({backgroundColor: color});
|
||||
}
|
||||
|
||||
function getListElement(tagName) {
|
||||
return $tagList.find('li[data-tag="' + tagName.toLowerCase() + '"]');
|
||||
}
|
||||
function getListElement(tagName) {
|
||||
return $tagList.find('li[data-tag="' + tagName.toLowerCase() + '"]');
|
||||
}
|
||||
|
||||
function setTags(newTagNames) {
|
||||
tags = newTagNames.slice();
|
||||
$tagList.empty();
|
||||
$underlyingInput.val(newTagNames.join(' '));
|
||||
_.each(newTagNames, function(tagName) {
|
||||
var $elem = createListElement(tagName);
|
||||
$tagList.append($elem);
|
||||
});
|
||||
}
|
||||
function setTags(newTagNames) {
|
||||
tags = newTagNames.slice();
|
||||
$tagList.empty();
|
||||
$underlyingInput.val(newTagNames.join(' '));
|
||||
_.each(newTagNames, function(tagName) {
|
||||
var $elem = createListElement(tagName);
|
||||
$tagList.append($elem);
|
||||
});
|
||||
}
|
||||
|
||||
function createListElement(tagName) {
|
||||
var $elem = jQuery('<li/>');
|
||||
$elem.attr('data-tag', tagName.toLowerCase());
|
||||
function createListElement(tagName) {
|
||||
var $elem = jQuery('<li/>');
|
||||
$elem.attr('data-tag', tagName.toLowerCase());
|
||||
|
||||
var $tagLink = jQuery('<a class="tag">');
|
||||
$tagLink.text(tagName + ' ' /* for easy copying */);
|
||||
$tagLink.click(function(e) {
|
||||
e.preventDefault();
|
||||
showOrHideSiblings(tagName);
|
||||
showOrHideSuggestions(tagName);
|
||||
});
|
||||
$elem.append($tagLink);
|
||||
var $tagLink = jQuery('<a class="tag">');
|
||||
$tagLink.text(tagName + ' ' /* for easy copying */);
|
||||
$tagLink.click(function(e) {
|
||||
e.preventDefault();
|
||||
showOrHideSiblings(tagName);
|
||||
showOrHideSuggestions(tagName);
|
||||
});
|
||||
$elem.append($tagLink);
|
||||
|
||||
var $deleteButton = jQuery('<a class="close"><i class="fa fa-remove"></i></a>');
|
||||
$deleteButton.click(function(e) {
|
||||
e.preventDefault();
|
||||
removeTag(tagName);
|
||||
$input.focus();
|
||||
});
|
||||
$elem.append($deleteButton);
|
||||
return $elem;
|
||||
}
|
||||
var $deleteButton = jQuery('<a class="close"><i class="fa fa-remove"></i></a>');
|
||||
$deleteButton.click(function(e) {
|
||||
e.preventDefault();
|
||||
removeTag(tagName);
|
||||
$input.focus();
|
||||
});
|
||||
$elem.append($deleteButton);
|
||||
return $elem;
|
||||
}
|
||||
|
||||
function showOrHideSuggestions(tagName) {
|
||||
var tag = getExportedTag(tagName);
|
||||
var suggestions = tag ? tag.suggestions : [];
|
||||
updateSuggestions($suggestions, suggestions);
|
||||
}
|
||||
function showOrHideSuggestions(tagName) {
|
||||
var tag = getExportedTag(tagName);
|
||||
var suggestions = tag ? tag.suggestions : [];
|
||||
updateSuggestions($suggestions, suggestions);
|
||||
}
|
||||
|
||||
function showOrHideSiblings(tagName) {
|
||||
if ($siblings.data('lastTag') === tagName && $siblings.is(':visible')) {
|
||||
$siblings.slideUp('fast');
|
||||
$siblings.data('lastTag', null);
|
||||
return;
|
||||
}
|
||||
function showOrHideSiblings(tagName) {
|
||||
if ($siblings.data('lastTag') === tagName && $siblings.is(':visible')) {
|
||||
$siblings.slideUp('fast');
|
||||
$siblings.data('lastTag', null);
|
||||
return;
|
||||
}
|
||||
|
||||
promise.wait(getSiblings(tagName), promise.make(function(resolve, reject) {
|
||||
$siblings.slideUp('fast', resolve);
|
||||
})).then(function(siblings) {
|
||||
siblings = _.pluck(siblings, 'name');
|
||||
$siblings.data('lastTag', tagName);
|
||||
$siblings.data('siblings', siblings);
|
||||
updateSuggestions($siblings, siblings);
|
||||
}).fail(function() {
|
||||
});
|
||||
}
|
||||
promise.wait(getSiblings(tagName), promise.make(function(resolve, reject) {
|
||||
$siblings.slideUp('fast', resolve);
|
||||
})).then(function(siblings) {
|
||||
siblings = _.pluck(siblings, 'name');
|
||||
$siblings.data('lastTag', tagName);
|
||||
$siblings.data('siblings', siblings);
|
||||
updateSuggestions($siblings, siblings);
|
||||
}).fail(function() {
|
||||
});
|
||||
}
|
||||
|
||||
function refreshShownSiblings() {
|
||||
updateSuggestions($siblings, $siblings.data('siblings'));
|
||||
}
|
||||
function refreshShownSiblings() {
|
||||
updateSuggestions($siblings, $siblings.data('siblings'));
|
||||
}
|
||||
|
||||
function updateSuggestions($target, suggestedTagNames) {
|
||||
function filterSuggestions(sourceTagNames) {
|
||||
if (!sourceTagNames) {
|
||||
return [];
|
||||
}
|
||||
var tagNames = _.filter(sourceTagNames.slice(), function(tagName) {
|
||||
return !isTaggedWith(tagName);
|
||||
});
|
||||
tagNames = tagNames.slice(0, 20);
|
||||
return tagNames;
|
||||
}
|
||||
function updateSuggestions($target, suggestedTagNames) {
|
||||
function filterSuggestions(sourceTagNames) {
|
||||
if (!sourceTagNames) {
|
||||
return [];
|
||||
}
|
||||
var tagNames = _.filter(sourceTagNames.slice(), function(tagName) {
|
||||
return !isTaggedWith(tagName);
|
||||
});
|
||||
tagNames = tagNames.slice(0, 20);
|
||||
return tagNames;
|
||||
}
|
||||
|
||||
function attachTagsToSuggestionList($list, tagNames) {
|
||||
$list.empty();
|
||||
_.each(tagNames, function(tagName) {
|
||||
var $li = jQuery('<li>');
|
||||
var $a = jQuery('<a href="#/posts/query=' + tagName + '">');
|
||||
$a.text(tagName);
|
||||
$a.click(function(e) {
|
||||
e.preventDefault();
|
||||
addTag(tagName, SOURCE_SUGGESTIONS);
|
||||
$li.fadeOut('fast', function() {
|
||||
$li.remove();
|
||||
if ($list.children().length === 0) {
|
||||
$list.parent('div').slideUp('fast');
|
||||
}
|
||||
});
|
||||
});
|
||||
$li.append($a);
|
||||
$list.append($li);
|
||||
});
|
||||
}
|
||||
function attachTagsToSuggestionList($list, tagNames) {
|
||||
$list.empty();
|
||||
_.each(tagNames, function(tagName) {
|
||||
var $li = jQuery('<li>');
|
||||
var $a = jQuery('<a href="#/posts/query=' + tagName + '">');
|
||||
$a.text(tagName);
|
||||
$a.click(function(e) {
|
||||
e.preventDefault();
|
||||
addTag(tagName, SOURCE_SUGGESTIONS);
|
||||
$li.fadeOut('fast', function() {
|
||||
$li.remove();
|
||||
if ($list.children().length === 0) {
|
||||
$list.parent('div').slideUp('fast');
|
||||
}
|
||||
});
|
||||
});
|
||||
$li.append($a);
|
||||
$list.append($li);
|
||||
});
|
||||
}
|
||||
|
||||
var suggestions = filterSuggestions(suggestedTagNames);
|
||||
if (suggestions.length > 0) {
|
||||
attachTagsToSuggestionList($target.find('ul'), suggestions);
|
||||
$target.slideDown('fast');
|
||||
} else {
|
||||
$target.slideUp('fast');
|
||||
}
|
||||
}
|
||||
var suggestions = filterSuggestions(suggestedTagNames);
|
||||
if (suggestions.length > 0) {
|
||||
attachTagsToSuggestionList($target.find('ul'), suggestions);
|
||||
$target.slideDown('fast');
|
||||
} else {
|
||||
$target.slideUp('fast');
|
||||
}
|
||||
}
|
||||
|
||||
function getSiblings(tagName) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.get('/tags/' + tagName + '/siblings'))
|
||||
.then(function(response) {
|
||||
resolve(response.json.data);
|
||||
}).fail(function() {
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
function getSiblings(tagName) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.get('/tags/' + tagName + '/siblings'))
|
||||
.then(function(response) {
|
||||
resolve(response.json.data);
|
||||
}).fail(function() {
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getTags() {
|
||||
return tags;
|
||||
}
|
||||
function getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
function focus() {
|
||||
$input.focus();
|
||||
}
|
||||
function focus() {
|
||||
$input.focus();
|
||||
}
|
||||
|
||||
function hideSuggestions() {
|
||||
$siblings.hide();
|
||||
$suggestions.hide();
|
||||
$siblings.data('siblings', []);
|
||||
}
|
||||
function hideSuggestions() {
|
||||
$siblings.hide();
|
||||
$suggestions.hide();
|
||||
$siblings.data('siblings', []);
|
||||
}
|
||||
|
||||
_.extend(options, {
|
||||
setTags: setTags,
|
||||
getTags: getTags,
|
||||
removeTag: removeTag,
|
||||
addTag: addTag,
|
||||
focus: focus,
|
||||
hideSuggestions: hideSuggestions,
|
||||
});
|
||||
return options;
|
||||
_.extend(options, {
|
||||
setTags: setTags,
|
||||
getTags: getTags,
|
||||
removeTag: removeTag,
|
||||
addTag: addTag,
|
||||
focus: focus,
|
||||
hideSuggestions: hideSuggestions,
|
||||
});
|
||||
return options;
|
||||
};
|
||||
|
|
|
@ -2,53 +2,53 @@ var App = App || {};
|
|||
|
||||
App.DI = (function() {
|
||||
|
||||
var factories = {};
|
||||
var instances = {};
|
||||
var factories = {};
|
||||
var instances = {};
|
||||
|
||||
function get(key) {
|
||||
var instance = instances[key];
|
||||
if (!instance) {
|
||||
var factory = factories[key];
|
||||
if (!factory) {
|
||||
throw new Error('Unregistered key: ' + key);
|
||||
}
|
||||
var objectInitializer = factory.initializer;
|
||||
var singleton = factory.singleton;
|
||||
var deps = resolveDependencies(objectInitializer, factory.dependencies);
|
||||
instance = {};
|
||||
instance = objectInitializer.apply(instance, deps);
|
||||
if (singleton) {
|
||||
instances[key] = instance;
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
function get(key) {
|
||||
var instance = instances[key];
|
||||
if (!instance) {
|
||||
var factory = factories[key];
|
||||
if (!factory) {
|
||||
throw new Error('Unregistered key: ' + key);
|
||||
}
|
||||
var objectInitializer = factory.initializer;
|
||||
var singleton = factory.singleton;
|
||||
var deps = resolveDependencies(objectInitializer, factory.dependencies);
|
||||
instance = {};
|
||||
instance = objectInitializer.apply(instance, deps);
|
||||
if (singleton) {
|
||||
instances[key] = instance;
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
function resolveDependencies(objectIntializer, depKeys) {
|
||||
var deps = [];
|
||||
for (var i = 0; i < depKeys.length; i ++) {
|
||||
deps[i] = get(depKeys[i]);
|
||||
}
|
||||
return deps;
|
||||
}
|
||||
function resolveDependencies(objectIntializer, depKeys) {
|
||||
var deps = [];
|
||||
for (var i = 0; i < depKeys.length; i ++) {
|
||||
deps[i] = get(depKeys[i]);
|
||||
}
|
||||
return deps;
|
||||
}
|
||||
|
||||
function register(key, dependencies, objectInitializer) {
|
||||
factories[key] = {initializer: objectInitializer, singleton: false, dependencies: dependencies};
|
||||
}
|
||||
function register(key, dependencies, objectInitializer) {
|
||||
factories[key] = {initializer: objectInitializer, singleton: false, dependencies: dependencies};
|
||||
}
|
||||
|
||||
function registerSingleton(key, dependencies, objectInitializer) {
|
||||
factories[key] = {initializer: objectInitializer, singleton: true, dependencies: dependencies};
|
||||
}
|
||||
function registerSingleton(key, dependencies, objectInitializer) {
|
||||
factories[key] = {initializer: objectInitializer, singleton: true, dependencies: dependencies};
|
||||
}
|
||||
|
||||
function registerManual(key, objectInitializer) {
|
||||
instances[key] = objectInitializer();
|
||||
}
|
||||
function registerManual(key, objectInitializer) {
|
||||
instances[key] = objectInitializer();
|
||||
}
|
||||
|
||||
return {
|
||||
get: get,
|
||||
register: register,
|
||||
registerManual: registerManual,
|
||||
registerSingleton: registerSingleton,
|
||||
};
|
||||
return {
|
||||
get: get,
|
||||
register: register,
|
||||
registerManual: registerManual,
|
||||
registerSingleton: registerSingleton,
|
||||
};
|
||||
|
||||
})();
|
||||
|
|
|
@ -2,60 +2,60 @@ var App = App || {};
|
|||
|
||||
App.Keyboard = function(jQuery, mousetrap, browsingSettings) {
|
||||
|
||||
var enabled = browsingSettings.getSettings().keyboardShortcuts;
|
||||
var oldStopCallback = mousetrap.stopCallback;
|
||||
mousetrap.stopCallback = function(e, element, combo, sequence) {
|
||||
if (combo.indexOf('ctrl') === -1 && e.ctrlKey) {
|
||||
return true;
|
||||
}
|
||||
if (combo.indexOf('alt') === -1 && e.altKey) {
|
||||
return true;
|
||||
}
|
||||
if (combo.indexOf('ctrl') !== -1) {
|
||||
return false;
|
||||
}
|
||||
var $focused = jQuery(':focus').eq(0);
|
||||
if ($focused.length) {
|
||||
if ($focused.prop('tagName').match(/embed|object/i)) {
|
||||
return true;
|
||||
}
|
||||
if ($focused.prop('tagName').toLowerCase() === 'input' &&
|
||||
$focused.attr('type').match(/checkbox|radio/i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return oldStopCallback.apply(mousetrap, arguments);
|
||||
};
|
||||
var enabled = browsingSettings.getSettings().keyboardShortcuts;
|
||||
var oldStopCallback = mousetrap.stopCallback;
|
||||
mousetrap.stopCallback = function(e, element, combo, sequence) {
|
||||
if (combo.indexOf('ctrl') === -1 && e.ctrlKey) {
|
||||
return true;
|
||||
}
|
||||
if (combo.indexOf('alt') === -1 && e.altKey) {
|
||||
return true;
|
||||
}
|
||||
if (combo.indexOf('ctrl') !== -1) {
|
||||
return false;
|
||||
}
|
||||
var $focused = jQuery(':focus').eq(0);
|
||||
if ($focused.length) {
|
||||
if ($focused.prop('tagName').match(/embed|object/i)) {
|
||||
return true;
|
||||
}
|
||||
if ($focused.prop('tagName').toLowerCase() === 'input' &&
|
||||
$focused.attr('type').match(/checkbox|radio/i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return oldStopCallback.apply(mousetrap, arguments);
|
||||
};
|
||||
|
||||
function keyup(key, callback) {
|
||||
unbind(key);
|
||||
if (enabled) {
|
||||
mousetrap.bind(key, callback, 'keyup');
|
||||
}
|
||||
}
|
||||
function keyup(key, callback) {
|
||||
unbind(key);
|
||||
if (enabled) {
|
||||
mousetrap.bind(key, callback, 'keyup');
|
||||
}
|
||||
}
|
||||
|
||||
function keydown(key, callback) {
|
||||
unbind(key);
|
||||
if (enabled) {
|
||||
mousetrap.bind(key, callback);
|
||||
}
|
||||
}
|
||||
function keydown(key, callback) {
|
||||
unbind(key);
|
||||
if (enabled) {
|
||||
mousetrap.bind(key, callback);
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
mousetrap.reset();
|
||||
}
|
||||
function reset() {
|
||||
mousetrap.reset();
|
||||
}
|
||||
|
||||
function unbind(key) {
|
||||
mousetrap.unbind(key, 'keyup');
|
||||
mousetrap.unbind(key);
|
||||
}
|
||||
function unbind(key) {
|
||||
mousetrap.unbind(key, 'keyup');
|
||||
mousetrap.unbind(key);
|
||||
}
|
||||
|
||||
return {
|
||||
keydown: keydown,
|
||||
keyup: keyup,
|
||||
reset: reset,
|
||||
unbind: unbind,
|
||||
};
|
||||
return {
|
||||
keydown: keydown,
|
||||
keyup: keyup,
|
||||
reset: reset,
|
||||
unbind: unbind,
|
||||
};
|
||||
};
|
||||
|
||||
App.DI.register('keyboard', ['jQuery', 'mousetrap', 'browsingSettings'], App.Keyboard);
|
||||
|
|
|
@ -1,142 +1,142 @@
|
|||
var App = App || {};
|
||||
|
||||
App.Pager = function(
|
||||
_,
|
||||
promise,
|
||||
api) {
|
||||
_,
|
||||
promise,
|
||||
api) {
|
||||
|
||||
var totalPages;
|
||||
var pageNumber;
|
||||
var searchParams;
|
||||
var url;
|
||||
var cache = {};
|
||||
var totalPages;
|
||||
var pageNumber;
|
||||
var searchParams;
|
||||
var url;
|
||||
var cache = {};
|
||||
|
||||
function init(args) {
|
||||
url = args.url;
|
||||
function init(args) {
|
||||
url = args.url;
|
||||
|
||||
setSearchParams(args.searchParams);
|
||||
if (typeof(args.page) !== 'undefined') {
|
||||
setPage(args.page);
|
||||
} else {
|
||||
setPage(1);
|
||||
}
|
||||
}
|
||||
setSearchParams(args.searchParams);
|
||||
if (typeof(args.page) !== 'undefined') {
|
||||
setPage(args.page);
|
||||
} else {
|
||||
setPage(1);
|
||||
}
|
||||
}
|
||||
|
||||
function getPage() {
|
||||
return pageNumber;
|
||||
}
|
||||
function getPage() {
|
||||
return pageNumber;
|
||||
}
|
||||
|
||||
function getTotalPages() {
|
||||
return totalPages;
|
||||
}
|
||||
function getTotalPages() {
|
||||
return totalPages;
|
||||
}
|
||||
|
||||
function prevPage() {
|
||||
if (pageNumber > 1) {
|
||||
setPage(pageNumber - 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function prevPage() {
|
||||
if (pageNumber > 1) {
|
||||
setPage(pageNumber - 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
if (pageNumber < totalPages) {
|
||||
setPage(pageNumber + 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function nextPage() {
|
||||
if (pageNumber < totalPages) {
|
||||
setPage(pageNumber + 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function setPage(newPageNumber) {
|
||||
pageNumber = parseInt(newPageNumber);
|
||||
if (!pageNumber || isNaN(pageNumber)) {
|
||||
throw new Error('Trying to set page to a non-number (' + newPageNumber + ')');
|
||||
}
|
||||
}
|
||||
function setPage(newPageNumber) {
|
||||
pageNumber = parseInt(newPageNumber);
|
||||
if (!pageNumber || isNaN(pageNumber)) {
|
||||
throw new Error('Trying to set page to a non-number (' + newPageNumber + ')');
|
||||
}
|
||||
}
|
||||
|
||||
function getSearchParams() {
|
||||
return searchParams;
|
||||
}
|
||||
function getSearchParams() {
|
||||
return searchParams;
|
||||
}
|
||||
|
||||
function setSearchParams(newSearchParams) {
|
||||
setPage(1);
|
||||
searchParams = _.extend({}, newSearchParams);
|
||||
delete searchParams.page;
|
||||
}
|
||||
function setSearchParams(newSearchParams) {
|
||||
setPage(1);
|
||||
searchParams = _.extend({}, newSearchParams);
|
||||
delete searchParams.page;
|
||||
}
|
||||
|
||||
function retrieve() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.get(url, _.extend({}, searchParams, {page: pageNumber})))
|
||||
.then(function(response) {
|
||||
var pageSize = response.json.pageSize;
|
||||
var totalRecords = response.json.totalRecords;
|
||||
totalPages = Math.ceil(totalRecords / pageSize);
|
||||
function retrieve() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.get(url, _.extend({}, searchParams, {page: pageNumber})))
|
||||
.then(function(response) {
|
||||
var pageSize = response.json.pageSize;
|
||||
var totalRecords = response.json.totalRecords;
|
||||
totalPages = Math.ceil(totalRecords / pageSize);
|
||||
|
||||
resolve({
|
||||
entities: response.json.data,
|
||||
totalRecords: totalRecords,
|
||||
totalPages: totalPages});
|
||||
resolve({
|
||||
entities: response.json.data,
|
||||
totalRecords: totalRecords,
|
||||
totalPages: totalPages});
|
||||
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
}).fail(function(response) {
|
||||
reject(response);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function retrieveCached() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
var cacheKey = JSON.stringify(_.extend({}, searchParams, {url: url, page: getPage()}));
|
||||
if (cacheKey in cache) {
|
||||
resolve.apply(this, cache[cacheKey]);
|
||||
} else {
|
||||
promise.wait(retrieve())
|
||||
.then(function() {
|
||||
cache[cacheKey] = arguments;
|
||||
resolve.apply(this, arguments);
|
||||
}).fail(function() {
|
||||
reject.apply(this, arguments);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function retrieveCached() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
var cacheKey = JSON.stringify(_.extend({}, searchParams, {url: url, page: getPage()}));
|
||||
if (cacheKey in cache) {
|
||||
resolve.apply(this, cache[cacheKey]);
|
||||
} else {
|
||||
promise.wait(retrieve())
|
||||
.then(function() {
|
||||
cache[cacheKey] = arguments;
|
||||
resolve.apply(this, arguments);
|
||||
}).fail(function() {
|
||||
reject.apply(this, arguments);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function resetCache() {
|
||||
cache = {};
|
||||
}
|
||||
function resetCache() {
|
||||
cache = {};
|
||||
}
|
||||
|
||||
function getVisiblePages() {
|
||||
var pages = [1, totalPages || 1];
|
||||
var pagesAroundCurrent = 2;
|
||||
for (var i = -pagesAroundCurrent; i <= pagesAroundCurrent; i ++) {
|
||||
if (pageNumber + i >= 1 && pageNumber + i <= totalPages) {
|
||||
pages.push(pageNumber + i);
|
||||
}
|
||||
}
|
||||
if (pageNumber - pagesAroundCurrent - 1 === 2) {
|
||||
pages.push(2);
|
||||
}
|
||||
if (pageNumber + pagesAroundCurrent + 1 === totalPages - 1) {
|
||||
pages.push(totalPages - 1);
|
||||
}
|
||||
function getVisiblePages() {
|
||||
var pages = [1, totalPages || 1];
|
||||
var pagesAroundCurrent = 2;
|
||||
for (var i = -pagesAroundCurrent; i <= pagesAroundCurrent; i ++) {
|
||||
if (pageNumber + i >= 1 && pageNumber + i <= totalPages) {
|
||||
pages.push(pageNumber + i);
|
||||
}
|
||||
}
|
||||
if (pageNumber - pagesAroundCurrent - 1 === 2) {
|
||||
pages.push(2);
|
||||
}
|
||||
if (pageNumber + pagesAroundCurrent + 1 === totalPages - 1) {
|
||||
pages.push(totalPages - 1);
|
||||
}
|
||||
|
||||
return pages.sort(function(a, b) { return a - b; }).filter(function(item, pos) {
|
||||
return !pos || item !== pages[pos - 1];
|
||||
});
|
||||
}
|
||||
return pages.sort(function(a, b) { return a - b; }).filter(function(item, pos) {
|
||||
return !pos || item !== pages[pos - 1];
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
getPage: getPage,
|
||||
getTotalPages: getTotalPages,
|
||||
prevPage: prevPage,
|
||||
nextPage: nextPage,
|
||||
setPage: setPage,
|
||||
getSearchParams: getSearchParams,
|
||||
setSearchParams: setSearchParams,
|
||||
retrieve: retrieve,
|
||||
retrieveCached: retrieveCached,
|
||||
getVisiblePages: getVisiblePages,
|
||||
resetCache: resetCache,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
getPage: getPage,
|
||||
getTotalPages: getTotalPages,
|
||||
prevPage: prevPage,
|
||||
nextPage: nextPage,
|
||||
setPage: setPage,
|
||||
getSearchParams: getSearchParams,
|
||||
setSearchParams: setSearchParams,
|
||||
retrieve: retrieve,
|
||||
retrieveCached: retrieveCached,
|
||||
getVisiblePages: getVisiblePages,
|
||||
resetCache: resetCache,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,53 +2,53 @@ var App = App || {};
|
|||
|
||||
App.PresenterManager = function(jQuery, promise, topNavigationPresenter, keyboard) {
|
||||
|
||||
var lastContentPresenter = null;
|
||||
var lastContentPresenter = null;
|
||||
|
||||
function init() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
initPresenter(topNavigationPresenter, [], resolve);
|
||||
});
|
||||
}
|
||||
function init() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
initPresenter(topNavigationPresenter, [], resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function initPresenter(presenter, args, loaded) {
|
||||
presenter.init.call(presenter, args, loaded);
|
||||
}
|
||||
function initPresenter(presenter, args, loaded) {
|
||||
presenter.init.call(presenter, args, loaded);
|
||||
}
|
||||
|
||||
function switchContentPresenter(presenter, args) {
|
||||
if (lastContentPresenter === null || lastContentPresenter.name !== presenter.name) {
|
||||
if (lastContentPresenter !== null && lastContentPresenter.deinit) {
|
||||
lastContentPresenter.deinit();
|
||||
}
|
||||
keyboard.reset();
|
||||
topNavigationPresenter.changeTitle(null);
|
||||
topNavigationPresenter.focus();
|
||||
presenter.init.call(presenter, args, function() {});
|
||||
lastContentPresenter = presenter;
|
||||
} else if (lastContentPresenter.reinit) {
|
||||
lastContentPresenter.reinit.call(lastContentPresenter, args, function() {});
|
||||
}
|
||||
}
|
||||
function switchContentPresenter(presenter, args) {
|
||||
if (lastContentPresenter === null || lastContentPresenter.name !== presenter.name) {
|
||||
if (lastContentPresenter !== null && lastContentPresenter.deinit) {
|
||||
lastContentPresenter.deinit();
|
||||
}
|
||||
keyboard.reset();
|
||||
topNavigationPresenter.changeTitle(null);
|
||||
topNavigationPresenter.focus();
|
||||
presenter.init.call(presenter, args, function() {});
|
||||
lastContentPresenter = presenter;
|
||||
} else if (lastContentPresenter.reinit) {
|
||||
lastContentPresenter.reinit.call(lastContentPresenter, args, function() {});
|
||||
}
|
||||
}
|
||||
|
||||
function initPresenters(options, loaded) {
|
||||
var count = 0;
|
||||
var subPresenterLoaded = function() {
|
||||
count ++;
|
||||
if (count === options.length) {
|
||||
loaded();
|
||||
}
|
||||
};
|
||||
function initPresenters(options, loaded) {
|
||||
var count = 0;
|
||||
var subPresenterLoaded = function() {
|
||||
count ++;
|
||||
if (count === options.length) {
|
||||
loaded();
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < options.length; i ++) {
|
||||
initPresenter(options[i][0], options[i][1], subPresenterLoaded);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < options.length; i ++) {
|
||||
initPresenter(options[i][0], options[i][1], subPresenterLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
initPresenter: initPresenter,
|
||||
initPresenters: initPresenters,
|
||||
switchContentPresenter: switchContentPresenter,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
initPresenter: initPresenter,
|
||||
initPresenters: initPresenters,
|
||||
switchContentPresenter: switchContentPresenter,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,230 +2,230 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.CommentListPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $el;
|
||||
var privileges;
|
||||
var templates = {};
|
||||
var $el;
|
||||
var privileges;
|
||||
var templates = {};
|
||||
|
||||
var post;
|
||||
var comments = [];
|
||||
var post;
|
||||
var comments = [];
|
||||
|
||||
function init(params, loaded) {
|
||||
$el = params.$target;
|
||||
post = params.post;
|
||||
comments = params.comments || [];
|
||||
function init(params, loaded) {
|
||||
$el = params.$target;
|
||||
post = params.post;
|
||||
comments = params.comments || [];
|
||||
|
||||
privileges = {
|
||||
canListComments: auth.hasPrivilege(auth.privileges.listComments),
|
||||
canAddComments: auth.hasPrivilege(auth.privileges.addComments),
|
||||
canEditOwnComments: auth.hasPrivilege(auth.privileges.editOwnComments),
|
||||
canEditAllComments: auth.hasPrivilege(auth.privileges.editAllComments),
|
||||
canDeleteOwnComments: auth.hasPrivilege(auth.privileges.deleteOwnComments),
|
||||
canDeleteAllComments: auth.hasPrivilege(auth.privileges.deleteAllComments),
|
||||
canViewUsers: auth.hasPrivilege(auth.privileges.viewUsers),
|
||||
canViewPosts: auth.hasPrivilege(auth.privileges.viewPosts),
|
||||
};
|
||||
privileges = {
|
||||
canListComments: auth.hasPrivilege(auth.privileges.listComments),
|
||||
canAddComments: auth.hasPrivilege(auth.privileges.addComments),
|
||||
canEditOwnComments: auth.hasPrivilege(auth.privileges.editOwnComments),
|
||||
canEditAllComments: auth.hasPrivilege(auth.privileges.editAllComments),
|
||||
canDeleteOwnComments: auth.hasPrivilege(auth.privileges.deleteOwnComments),
|
||||
canDeleteAllComments: auth.hasPrivilege(auth.privileges.deleteAllComments),
|
||||
canViewUsers: auth.hasPrivilege(auth.privileges.viewUsers),
|
||||
canViewPosts: auth.hasPrivilege(auth.privileges.viewPosts),
|
||||
};
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('comment-list'),
|
||||
util.promiseTemplate('comment-list-item'),
|
||||
util.promiseTemplate('comment-form'))
|
||||
.then(function(
|
||||
commentListTemplate,
|
||||
commentListItemTemplate,
|
||||
commentFormTemplate)
|
||||
{
|
||||
templates.commentList = commentListTemplate;
|
||||
templates.commentListItem = commentListItemTemplate;
|
||||
templates.commentForm = commentFormTemplate;
|
||||
promise.wait(
|
||||
util.promiseTemplate('comment-list'),
|
||||
util.promiseTemplate('comment-list-item'),
|
||||
util.promiseTemplate('comment-form'))
|
||||
.then(function(
|
||||
commentListTemplate,
|
||||
commentListItemTemplate,
|
||||
commentFormTemplate)
|
||||
{
|
||||
templates.commentList = commentListTemplate;
|
||||
templates.commentListItem = commentListItemTemplate;
|
||||
templates.commentForm = commentFormTemplate;
|
||||
|
||||
render();
|
||||
loaded();
|
||||
render();
|
||||
loaded();
|
||||
|
||||
if (comments.length === 0) {
|
||||
promise.wait(api.get('/comments/' + params.post.id))
|
||||
.then(function(response) {
|
||||
comments = response.json.data;
|
||||
render();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
});
|
||||
}
|
||||
})
|
||||
.fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
if (comments.length === 0) {
|
||||
promise.wait(api.get('/comments/' + params.post.id))
|
||||
.then(function(response) {
|
||||
comments = response.json.data;
|
||||
render();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
});
|
||||
}
|
||||
})
|
||||
.fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.commentList(
|
||||
_.extend(
|
||||
{
|
||||
commentListItemTemplate: templates.commentListItem,
|
||||
commentFormTemplate: templates.commentForm,
|
||||
util: util,
|
||||
comments: comments,
|
||||
post: post,
|
||||
},
|
||||
privileges)));
|
||||
function render() {
|
||||
$el.html(templates.commentList(
|
||||
_.extend(
|
||||
{
|
||||
commentListItemTemplate: templates.commentListItem,
|
||||
commentFormTemplate: templates.commentForm,
|
||||
util: util,
|
||||
comments: comments,
|
||||
post: post,
|
||||
},
|
||||
privileges)));
|
||||
|
||||
$el.find('.comment-add form button[type=submit]').click(function(e) { commentFormSubmitted(e, null); });
|
||||
renderComments(comments);
|
||||
}
|
||||
$el.find('.comment-add form button[type=submit]').click(function(e) { commentFormSubmitted(e, null); });
|
||||
renderComments(comments);
|
||||
}
|
||||
|
||||
function renderComments(comments) {
|
||||
var $target = $el.find('.comments');
|
||||
var $targetList = $el.find('ul');
|
||||
function renderComments(comments) {
|
||||
var $target = $el.find('.comments');
|
||||
var $targetList = $el.find('ul');
|
||||
|
||||
if (comments.length > 0) {
|
||||
$target.show();
|
||||
} else {
|
||||
$target.hide();
|
||||
}
|
||||
if (comments.length > 0) {
|
||||
$target.show();
|
||||
} else {
|
||||
$target.hide();
|
||||
}
|
||||
|
||||
$targetList.empty();
|
||||
_.each(comments, function(comment) {
|
||||
renderComment($targetList, comment);
|
||||
});
|
||||
}
|
||||
$targetList.empty();
|
||||
_.each(comments, function(comment) {
|
||||
renderComment($targetList, comment);
|
||||
});
|
||||
}
|
||||
|
||||
function renderComment($targetList, comment) {
|
||||
var $item = jQuery('<li>' + templates.commentListItem({
|
||||
comment: comment,
|
||||
util: util,
|
||||
canVote: auth.isLoggedIn(),
|
||||
canEditComment: auth.isLoggedIn(comment.user.name) ? privileges.canEditOwnComments : privileges.canEditAllComments,
|
||||
canDeleteComment: auth.isLoggedIn(comment.user.name) ? privileges.canDeleteOwnComments : privileges.canDeleteAllComments,
|
||||
canViewUsers: privileges.canViewUsers,
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
util.loadImagesNicely($item.find('img'));
|
||||
$targetList.append($item);
|
||||
function renderComment($targetList, comment) {
|
||||
var $item = jQuery('<li>' + templates.commentListItem({
|
||||
comment: comment,
|
||||
util: util,
|
||||
canVote: auth.isLoggedIn(),
|
||||
canEditComment: auth.isLoggedIn(comment.user.name) ? privileges.canEditOwnComments : privileges.canEditAllComments,
|
||||
canDeleteComment: auth.isLoggedIn(comment.user.name) ? privileges.canDeleteOwnComments : privileges.canDeleteAllComments,
|
||||
canViewUsers: privileges.canViewUsers,
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
util.loadImagesNicely($item.find('img'));
|
||||
$targetList.append($item);
|
||||
|
||||
$item.find('a.edit').click(function(e) {
|
||||
e.preventDefault();
|
||||
editCommentStart($item, comment);
|
||||
});
|
||||
$item.find('a.edit').click(function(e) {
|
||||
e.preventDefault();
|
||||
editCommentStart($item, comment);
|
||||
});
|
||||
|
||||
$item.find('a.delete').click(function(e) {
|
||||
e.preventDefault();
|
||||
deleteComment(comment);
|
||||
});
|
||||
$item.find('a.delete').click(function(e) {
|
||||
e.preventDefault();
|
||||
deleteComment(comment);
|
||||
});
|
||||
|
||||
$item.find('a.score-up').click(function(e) {
|
||||
e.preventDefault();
|
||||
score(comment, jQuery(this).hasClass('active') ? 0 : 1);
|
||||
});
|
||||
$item.find('a.score-up').click(function(e) {
|
||||
e.preventDefault();
|
||||
score(comment, jQuery(this).hasClass('active') ? 0 : 1);
|
||||
});
|
||||
|
||||
$item.find('a.score-down').click(function(e) {
|
||||
e.preventDefault();
|
||||
score(comment, jQuery(this).hasClass('active') ? 0 : -1);
|
||||
});
|
||||
}
|
||||
$item.find('a.score-down').click(function(e) {
|
||||
e.preventDefault();
|
||||
score(comment, jQuery(this).hasClass('active') ? 0 : -1);
|
||||
});
|
||||
}
|
||||
|
||||
function commentFormSubmitted(e, comment) {
|
||||
e.preventDefault();
|
||||
var $button = jQuery(e.target);
|
||||
var $form = $button.parents('form');
|
||||
var sender = $button.val();
|
||||
if (sender === 'preview') {
|
||||
previewComment($form);
|
||||
} else {
|
||||
submitComment($form, comment);
|
||||
}
|
||||
}
|
||||
function commentFormSubmitted(e, comment) {
|
||||
e.preventDefault();
|
||||
var $button = jQuery(e.target);
|
||||
var $form = $button.parents('form');
|
||||
var sender = $button.val();
|
||||
if (sender === 'preview') {
|
||||
previewComment($form);
|
||||
} else {
|
||||
submitComment($form, comment);
|
||||
}
|
||||
}
|
||||
|
||||
function previewComment($form) {
|
||||
var $preview = $form.find('.preview');
|
||||
$preview.slideUp('fast', function() {
|
||||
$preview.html(util.formatMarkdown($form.find('textarea').val()));
|
||||
$preview.slideDown('fast');
|
||||
});
|
||||
}
|
||||
function previewComment($form) {
|
||||
var $preview = $form.find('.preview');
|
||||
$preview.slideUp('fast', function() {
|
||||
$preview.html(util.formatMarkdown($form.find('textarea').val()));
|
||||
$preview.slideDown('fast');
|
||||
});
|
||||
}
|
||||
|
||||
function updateComment(comment) {
|
||||
comments = _.map(comments, function(c) { return c.id === comment.id ? comment : c; });
|
||||
render();
|
||||
}
|
||||
function updateComment(comment) {
|
||||
comments = _.map(comments, function(c) { return c.id === comment.id ? comment : c; });
|
||||
render();
|
||||
}
|
||||
|
||||
function addComment(comment) {
|
||||
comments.push(comment);
|
||||
render();
|
||||
}
|
||||
function addComment(comment) {
|
||||
comments.push(comment);
|
||||
render();
|
||||
}
|
||||
|
||||
function submitComment($form, commentToEdit) {
|
||||
$form.find('.preview').slideUp();
|
||||
var $textarea = $form.find('textarea');
|
||||
function submitComment($form, commentToEdit) {
|
||||
$form.find('.preview').slideUp();
|
||||
var $textarea = $form.find('textarea');
|
||||
|
||||
var data = {text: $textarea.val()};
|
||||
var p;
|
||||
if (commentToEdit) {
|
||||
p = promise.wait(api.put('/comments/' + commentToEdit.id, data));
|
||||
} else {
|
||||
p = promise.wait(api.post('/comments/' + post.id, data));
|
||||
}
|
||||
var data = {text: $textarea.val()};
|
||||
var p;
|
||||
if (commentToEdit) {
|
||||
p = promise.wait(api.put('/comments/' + commentToEdit.id, data));
|
||||
} else {
|
||||
p = promise.wait(api.post('/comments/' + post.id, data));
|
||||
}
|
||||
|
||||
p.then(function(response) {
|
||||
$textarea.val('');
|
||||
var comment = response.json;
|
||||
p.then(function(response) {
|
||||
$textarea.val('');
|
||||
var comment = response.json;
|
||||
|
||||
if (commentToEdit) {
|
||||
$form.slideUp(function() {
|
||||
$form.remove();
|
||||
});
|
||||
updateComment(comment);
|
||||
} else {
|
||||
addComment(comment);
|
||||
}
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
if (commentToEdit) {
|
||||
$form.slideUp(function() {
|
||||
$form.remove();
|
||||
});
|
||||
updateComment(comment);
|
||||
} else {
|
||||
addComment(comment);
|
||||
}
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
|
||||
function editCommentStart($item, comment) {
|
||||
if ($item.find('.comment-form').length > 0) {
|
||||
return;
|
||||
}
|
||||
var $form = jQuery(templates.commentForm({title: 'Edit comment', text: comment.text}));
|
||||
$item.find('.body').append($form);
|
||||
$item.find('form button[type=submit]').click(function(e) { commentFormSubmitted(e, comment); });
|
||||
}
|
||||
function editCommentStart($item, comment) {
|
||||
if ($item.find('.comment-form').length > 0) {
|
||||
return;
|
||||
}
|
||||
var $form = jQuery(templates.commentForm({title: 'Edit comment', text: comment.text}));
|
||||
$item.find('.body').append($form);
|
||||
$item.find('form button[type=submit]').click(function(e) { commentFormSubmitted(e, comment); });
|
||||
}
|
||||
|
||||
function deleteComment(comment) {
|
||||
if (!window.confirm('Are you sure you want to delete this comment?')) {
|
||||
return;
|
||||
}
|
||||
promise.wait(api.delete('/comments/' + comment.id))
|
||||
.then(function(response) {
|
||||
comments = _.filter(comments, function(c) { return c.id !== comment.id; });
|
||||
renderComments(comments);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
function deleteComment(comment) {
|
||||
if (!window.confirm('Are you sure you want to delete this comment?')) {
|
||||
return;
|
||||
}
|
||||
promise.wait(api.delete('/comments/' + comment.id))
|
||||
.then(function(response) {
|
||||
comments = _.filter(comments, function(c) { return c.id !== comment.id; });
|
||||
renderComments(comments);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
|
||||
function score(comment, scoreValue) {
|
||||
promise.wait(api.post('/comments/' + comment.id + '/score', {score: scoreValue}))
|
||||
.then(function(response) {
|
||||
comment.score = parseInt(response.json.score);
|
||||
comment.ownScore = parseInt(response.json.ownScore);
|
||||
updateComment(comment);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
function score(comment, scoreValue) {
|
||||
promise.wait(api.post('/comments/' + comment.id + '/score', {score: scoreValue}))
|
||||
.then(function(response) {
|
||||
comment.score = parseInt(response.json.score);
|
||||
comment.ownScore = parseInt(response.json.ownScore);
|
||||
updateComment(comment);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
|
||||
function showGenericError(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
}
|
||||
function showGenericError(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,103 +2,103 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.GlobalCommentListPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
auth,
|
||||
promise,
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
auth,
|
||||
promise,
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var $el;
|
||||
var privileges;
|
||||
var templates = {};
|
||||
var $el;
|
||||
var privileges;
|
||||
var templates = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
$el = jQuery('#content');
|
||||
topNavigationPresenter.select('comments');
|
||||
function init(params, loaded) {
|
||||
$el = jQuery('#content');
|
||||
topNavigationPresenter.select('comments');
|
||||
|
||||
privileges = {
|
||||
canViewPosts: auth.hasPrivilege(auth.privileges.viewPosts),
|
||||
};
|
||||
privileges = {
|
||||
canViewPosts: auth.hasPrivilege(auth.privileges.viewPosts),
|
||||
};
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('global-comment-list'),
|
||||
util.promiseTemplate('global-comment-list-item'),
|
||||
util.promiseTemplate('post-list-item'))
|
||||
.then(function(listTemplate, listItemTemplate, postTemplate) {
|
||||
templates.list = listTemplate;
|
||||
templates.listItem = listItemTemplate;
|
||||
templates.post = postTemplate;
|
||||
promise.wait(
|
||||
util.promiseTemplate('global-comment-list'),
|
||||
util.promiseTemplate('global-comment-list-item'),
|
||||
util.promiseTemplate('post-list-item'))
|
||||
.then(function(listTemplate, listItemTemplate, postTemplate) {
|
||||
templates.list = listTemplate;
|
||||
templates.listItem = listItemTemplate;
|
||||
templates.post = postTemplate;
|
||||
|
||||
render();
|
||||
loaded();
|
||||
render();
|
||||
loaded();
|
||||
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/comments',
|
||||
backendUri: '/comments',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderComments($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/comments',
|
||||
backendUri: '/comments',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderComments($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function reinit(params, loaded) {
|
||||
pagerPresenter.reinit({query: params.query || {}});
|
||||
loaded();
|
||||
}
|
||||
function reinit(params, loaded) {
|
||||
pagerPresenter.reinit({query: params.query || {}});
|
||||
loaded();
|
||||
}
|
||||
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
}
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.list());
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.list());
|
||||
}
|
||||
|
||||
function renderComments($page, data) {
|
||||
var $target = $page.find('.posts');
|
||||
_.each(data, function(data) {
|
||||
var post = data.post;
|
||||
var comments = data.comments;
|
||||
function renderComments($page, data) {
|
||||
var $target = $page.find('.posts');
|
||||
_.each(data, function(data) {
|
||||
var post = data.post;
|
||||
var comments = data.comments;
|
||||
|
||||
var $post = jQuery('<li>' + templates.listItem({
|
||||
util: util,
|
||||
post: post,
|
||||
postTemplate: templates.post,
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
var $post = jQuery('<li>' + templates.listItem({
|
||||
util: util,
|
||||
post: post,
|
||||
postTemplate: templates.post,
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
|
||||
util.loadImagesNicely($post.find('img'));
|
||||
var presenter = App.DI.get('commentListPresenter');
|
||||
util.loadImagesNicely($post.find('img'));
|
||||
var presenter = App.DI.get('commentListPresenter');
|
||||
|
||||
presenter.init({
|
||||
post: post,
|
||||
comments: comments,
|
||||
$target: $post.find('.post-comments-target'),
|
||||
}, function() {
|
||||
presenter.render();
|
||||
});
|
||||
presenter.init({
|
||||
post: post,
|
||||
comments: comments,
|
||||
$target: $post.find('.post-comments-target'),
|
||||
}, function() {
|
||||
presenter.render();
|
||||
});
|
||||
|
||||
$target.append($post);
|
||||
});
|
||||
}
|
||||
$target.append($post);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,48 +2,48 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.HelpPresenter = function(
|
||||
jQuery,
|
||||
promise,
|
||||
util,
|
||||
topNavigationPresenter) {
|
||||
jQuery,
|
||||
promise,
|
||||
util,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var activeTab;
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var activeTab;
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('help');
|
||||
topNavigationPresenter.changeTitle('Help');
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('help');
|
||||
topNavigationPresenter.changeTitle('Help');
|
||||
|
||||
promise.wait(util.promiseTemplate('help'))
|
||||
.then(function(template) {
|
||||
templates.help = template;
|
||||
reinit(params, loaded);
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
promise.wait(util.promiseTemplate('help'))
|
||||
.then(function(template) {
|
||||
templates.help = template;
|
||||
reinit(params, loaded);
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function reinit(params, loaded) {
|
||||
activeTab = params.tab || 'about';
|
||||
render();
|
||||
loaded();
|
||||
}
|
||||
function reinit(params, loaded) {
|
||||
activeTab = params.tab || 'about';
|
||||
render();
|
||||
loaded();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.help({title: topNavigationPresenter.getBaseTitle() }));
|
||||
$el.find('.big-button').removeClass('active');
|
||||
$el.find('.big-button[href*="' + activeTab + '"]').addClass('active');
|
||||
$el.find('div[data-tab]').hide();
|
||||
$el.find('div[data-tab*="' + activeTab + '"]').show();
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.help({title: topNavigationPresenter.getBaseTitle() }));
|
||||
$el.find('.big-button').removeClass('active');
|
||||
$el.find('.big-button[href*="' + activeTab + '"]').addClass('active');
|
||||
$el.find('div[data-tab]').hide();
|
||||
$el.find('div[data-tab*="' + activeTab + '"]').show();
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,76 +2,76 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.HistoryPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var params;
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var params;
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.changeTitle('History');
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.changeTitle('History');
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('global-history'),
|
||||
util.promiseTemplate('history'))
|
||||
.then(function(historyWrapperTemplate, historyTemplate) {
|
||||
templates.historyWrapper = historyWrapperTemplate;
|
||||
templates.history = historyTemplate;
|
||||
promise.wait(
|
||||
util.promiseTemplate('global-history'),
|
||||
util.promiseTemplate('history'))
|
||||
.then(function(historyWrapperTemplate, historyTemplate) {
|
||||
templates.historyWrapper = historyWrapperTemplate;
|
||||
templates.history = historyTemplate;
|
||||
|
||||
render();
|
||||
loaded();
|
||||
render();
|
||||
loaded();
|
||||
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/history',
|
||||
backendUri: '/history',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderHistory($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/history',
|
||||
backendUri: '/history',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderHistory($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
|
||||
pagerPresenter.reinit({query: params.query});
|
||||
loaded();
|
||||
}
|
||||
pagerPresenter.reinit({query: params.query});
|
||||
loaded();
|
||||
}
|
||||
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
}
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.historyWrapper());
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.historyWrapper());
|
||||
}
|
||||
|
||||
function renderHistory($page, historyItems) {
|
||||
$page.append(templates.history({
|
||||
util: util,
|
||||
history: historyItems}));
|
||||
}
|
||||
function renderHistory($page, historyItems) {
|
||||
$page.append(templates.history({
|
||||
util: util,
|
||||
history: historyItems}));
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,90 +2,90 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.HomePresenter = function(
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
presenterManager,
|
||||
postContentPresenter,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
presenterManager,
|
||||
postContentPresenter,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var globals;
|
||||
var post;
|
||||
var user;
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var globals;
|
||||
var post;
|
||||
var user;
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('home');
|
||||
topNavigationPresenter.changeTitle('Home');
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('home');
|
||||
topNavigationPresenter.changeTitle('Home');
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('home'),
|
||||
api.get('/globals'),
|
||||
api.get('/posts/featured'))
|
||||
.then(function(
|
||||
homeTemplate,
|
||||
globalsResponse,
|
||||
featuredPostResponse) {
|
||||
templates.home = homeTemplate;
|
||||
promise.wait(
|
||||
util.promiseTemplate('home'),
|
||||
api.get('/globals'),
|
||||
api.get('/posts/featured'))
|
||||
.then(function(
|
||||
homeTemplate,
|
||||
globalsResponse,
|
||||
featuredPostResponse) {
|
||||
templates.home = homeTemplate;
|
||||
|
||||
globals = globalsResponse.json;
|
||||
post = featuredPostResponse.json.post;
|
||||
user = featuredPostResponse.json.user;
|
||||
render();
|
||||
loaded();
|
||||
globals = globalsResponse.json;
|
||||
post = featuredPostResponse.json.post;
|
||||
user = featuredPostResponse.json.user;
|
||||
render();
|
||||
loaded();
|
||||
|
||||
if ($el.find('#post-content-target').length > 0) {
|
||||
presenterManager.initPresenters([
|
||||
[postContentPresenter, {post: post, $target: $el.find('#post-content-target')}]],
|
||||
function() {
|
||||
var $wrapper = $el.find('.object-wrapper');
|
||||
$wrapper.css({
|
||||
maxWidth: $wrapper.attr('data-width') + 'px',
|
||||
width: 'auto',
|
||||
margin: '0 auto'});
|
||||
postContentPresenter.updatePostNotesSize();
|
||||
});
|
||||
}
|
||||
if ($el.find('#post-content-target').length > 0) {
|
||||
presenterManager.initPresenters([
|
||||
[postContentPresenter, {post: post, $target: $el.find('#post-content-target')}]],
|
||||
function() {
|
||||
var $wrapper = $el.find('.object-wrapper');
|
||||
$wrapper.css({
|
||||
maxWidth: $wrapper.attr('data-width') + 'px',
|
||||
width: 'auto',
|
||||
margin: '0 auto'});
|
||||
postContentPresenter.updatePostNotesSize();
|
||||
});
|
||||
}
|
||||
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($el, response.json && response.json.error || response);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($el, response.json && response.json.error || response);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.home({
|
||||
post: post,
|
||||
user: user,
|
||||
globals: globals,
|
||||
title: topNavigationPresenter.getBaseTitle(),
|
||||
canViewUsers: auth.hasPrivilege(auth.privileges.viewUsers),
|
||||
canViewPosts: auth.hasPrivilege(auth.privileges.viewPosts),
|
||||
util: util,
|
||||
version: jQuery('head').attr('data-version'),
|
||||
buildTime: jQuery('head').attr('data-build-time'),
|
||||
}));
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.home({
|
||||
post: post,
|
||||
user: user,
|
||||
globals: globals,
|
||||
title: topNavigationPresenter.getBaseTitle(),
|
||||
canViewUsers: auth.hasPrivilege(auth.privileges.viewUsers),
|
||||
canViewPosts: auth.hasPrivilege(auth.privileges.viewPosts),
|
||||
util: util,
|
||||
version: jQuery('head').attr('data-version'),
|
||||
buildTime: jQuery('head').attr('data-build-time'),
|
||||
}));
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
App.DI.register('homePresenter', [
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'api',
|
||||
'auth',
|
||||
'presenterManager',
|
||||
'postContentPresenter',
|
||||
'topNavigationPresenter',
|
||||
'messagePresenter'],
|
||||
App.Presenters.HomePresenter);
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'api',
|
||||
'auth',
|
||||
'presenterManager',
|
||||
'postContentPresenter',
|
||||
'topNavigationPresenter',
|
||||
'messagePresenter'],
|
||||
App.Presenters.HomePresenter);
|
||||
|
|
|
@ -2,46 +2,46 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.HttpErrorPresenter = function(
|
||||
jQuery,
|
||||
promise,
|
||||
util,
|
||||
topNavigationPresenter) {
|
||||
jQuery,
|
||||
promise,
|
||||
util,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.changeTitle('Error ' + params.error);
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.changeTitle('Error ' + params.error);
|
||||
|
||||
if (params.error === 404) {
|
||||
promise.wait(util.promiseTemplate('404'))
|
||||
.then(function(template) {
|
||||
templates.errorPage = template;
|
||||
reinit(params, loaded);
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
} else {
|
||||
console.log('Not supported.');
|
||||
loaded();
|
||||
}
|
||||
}
|
||||
if (params.error === 404) {
|
||||
promise.wait(util.promiseTemplate('404'))
|
||||
.then(function(template) {
|
||||
templates.errorPage = template;
|
||||
reinit(params, loaded);
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
} else {
|
||||
console.log('Not supported.');
|
||||
loaded();
|
||||
}
|
||||
}
|
||||
|
||||
function reinit(params, loaded) {
|
||||
render();
|
||||
loaded();
|
||||
}
|
||||
function reinit(params, loaded) {
|
||||
render();
|
||||
loaded();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.errorPage());
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.errorPage());
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,84 +2,84 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.LoginPresenter = function(
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
router,
|
||||
auth,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
router,
|
||||
auth,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var $messages;
|
||||
var templates = {};
|
||||
var previousLocation;
|
||||
var $el = jQuery('#content');
|
||||
var $messages;
|
||||
var templates = {};
|
||||
var previousLocation;
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('login');
|
||||
topNavigationPresenter.changeTitle('Login');
|
||||
previousLocation = params.previousLocation;
|
||||
promise.wait(util.promiseTemplate('login-form'))
|
||||
.then(function(template) {
|
||||
templates.login = template;
|
||||
if (auth.isLoggedIn()) {
|
||||
finishLogin();
|
||||
} else {
|
||||
render();
|
||||
$el.find('input:eq(0)').focus();
|
||||
}
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('login');
|
||||
topNavigationPresenter.changeTitle('Login');
|
||||
previousLocation = params.previousLocation;
|
||||
promise.wait(util.promiseTemplate('login-form'))
|
||||
.then(function(template) {
|
||||
templates.login = template;
|
||||
if (auth.isLoggedIn()) {
|
||||
finishLogin();
|
||||
} else {
|
||||
render();
|
||||
$el.find('input:eq(0)').focus();
|
||||
}
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.login());
|
||||
$el.find('form').submit(loginFormSubmitted);
|
||||
$messages = $el.find('.messages');
|
||||
$messages.width($el.find('form').width());
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.login());
|
||||
$el.find('form').submit(loginFormSubmitted);
|
||||
$messages = $el.find('.messages');
|
||||
$messages.width($el.find('form').width());
|
||||
}
|
||||
|
||||
function loginFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
function loginFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
|
||||
var userNameOrEmail = $el.find('[name=user]').val();
|
||||
var password = $el.find('[name=password]').val();
|
||||
var remember = $el.find('[name=remember]').is(':checked');
|
||||
var userNameOrEmail = $el.find('[name=user]').val();
|
||||
var password = $el.find('[name=password]').val();
|
||||
var remember = $el.find('[name=remember]').is(':checked');
|
||||
|
||||
if (userNameOrEmail.length === 0) {
|
||||
messagePresenter.showError($messages, 'User name cannot be empty.');
|
||||
return false;
|
||||
}
|
||||
if (userNameOrEmail.length === 0) {
|
||||
messagePresenter.showError($messages, 'User name cannot be empty.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (password.length === 0) {
|
||||
messagePresenter.showError($messages, 'Password cannot be empty.');
|
||||
return false;
|
||||
}
|
||||
if (password.length === 0) {
|
||||
messagePresenter.showError($messages, 'Password cannot be empty.');
|
||||
return false;
|
||||
}
|
||||
|
||||
promise.wait(auth.loginFromCredentials(userNameOrEmail, password, remember))
|
||||
.then(function(response) {
|
||||
finishLogin();
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
promise.wait(auth.loginFromCredentials(userNameOrEmail, password, remember))
|
||||
.then(function(response) {
|
||||
finishLogin();
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
|
||||
function finishLogin() {
|
||||
if (previousLocation && !previousLocation.match(/logout|password-reset|activate|register/)) {
|
||||
router.navigate(previousLocation);
|
||||
} else {
|
||||
router.navigateToMainPage();
|
||||
}
|
||||
}
|
||||
function finishLogin() {
|
||||
if (previousLocation && !previousLocation.match(/logout|password-reset|activate|register/)) {
|
||||
router.navigate(previousLocation);
|
||||
} else {
|
||||
router.navigateToMainPage();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,38 +2,38 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.LogoutPresenter = function(
|
||||
jQuery,
|
||||
promise,
|
||||
router,
|
||||
auth,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
jQuery,
|
||||
promise,
|
||||
router,
|
||||
auth,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $messages = jQuery('#content');
|
||||
var $messages = jQuery('#content');
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('logout');
|
||||
topNavigationPresenter.changeTitle('Logout');
|
||||
promise.wait(auth.logout())
|
||||
.then(function() {
|
||||
loaded();
|
||||
$messages.empty();
|
||||
var $messageDiv = messagePresenter.showInfo($messages, 'Logged out. <a href="">Back to main page</a>');
|
||||
$messageDiv.find('a').click(mainPageLinkClicked);
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError(($messages, response.json && response.json.error || response) + '<br/>Reload the page to continue.');
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('logout');
|
||||
topNavigationPresenter.changeTitle('Logout');
|
||||
promise.wait(auth.logout())
|
||||
.then(function() {
|
||||
loaded();
|
||||
$messages.empty();
|
||||
var $messageDiv = messagePresenter.showInfo($messages, 'Logged out. <a href="">Back to main page</a>');
|
||||
$messageDiv.find('a').click(mainPageLinkClicked);
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError(($messages, response.json && response.json.error || response) + '<br/>Reload the page to continue.');
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function mainPageLinkClicked(e) {
|
||||
e.preventDefault();
|
||||
router.navigateToMainPage();
|
||||
}
|
||||
function mainPageLinkClicked(e) {
|
||||
e.preventDefault();
|
||||
router.navigateToMainPage();
|
||||
}
|
||||
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
return {
|
||||
init: init
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -3,51 +3,51 @@ App.Presenters = App.Presenters || {};
|
|||
|
||||
App.Presenters.MessagePresenter = function(_, jQuery) {
|
||||
|
||||
var options = {
|
||||
instant: false
|
||||
};
|
||||
var options = {
|
||||
instant: false
|
||||
};
|
||||
|
||||
function showInfo($el, message) {
|
||||
return showMessage($el, 'info', message);
|
||||
}
|
||||
function showInfo($el, message) {
|
||||
return showMessage($el, 'info', message);
|
||||
}
|
||||
|
||||
function showError($el, message) {
|
||||
return showMessage($el, 'error', message);
|
||||
}
|
||||
function showError($el, message) {
|
||||
return showMessage($el, 'error', message);
|
||||
}
|
||||
|
||||
function hideMessages($el) {
|
||||
var $messages = $el.children('.message');
|
||||
if (options.instant) {
|
||||
$messages.each(function() {
|
||||
jQuery(this).slideUp('fast', function() {
|
||||
jQuery(this).remove();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$messages.remove();
|
||||
}
|
||||
}
|
||||
function hideMessages($el) {
|
||||
var $messages = $el.children('.message');
|
||||
if (options.instant) {
|
||||
$messages.each(function() {
|
||||
jQuery(this).slideUp('fast', function() {
|
||||
jQuery(this).remove();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$messages.remove();
|
||||
}
|
||||
}
|
||||
|
||||
function showMessage($el, className, message) {
|
||||
var $messageDiv = jQuery('<div>');
|
||||
$messageDiv.addClass('message');
|
||||
$messageDiv.addClass(className);
|
||||
$messageDiv.html(message);
|
||||
if (!options.instant) {
|
||||
$messageDiv.hide();
|
||||
}
|
||||
$el.append($messageDiv);
|
||||
if (!options.instant) {
|
||||
$messageDiv.slideDown('fast');
|
||||
}
|
||||
return $messageDiv;
|
||||
}
|
||||
function showMessage($el, className, message) {
|
||||
var $messageDiv = jQuery('<div>');
|
||||
$messageDiv.addClass('message');
|
||||
$messageDiv.addClass(className);
|
||||
$messageDiv.html(message);
|
||||
if (!options.instant) {
|
||||
$messageDiv.hide();
|
||||
}
|
||||
$el.append($messageDiv);
|
||||
if (!options.instant) {
|
||||
$messageDiv.slideDown('fast');
|
||||
}
|
||||
return $messageDiv;
|
||||
}
|
||||
|
||||
return _.extend(options, {
|
||||
showInfo: showInfo,
|
||||
showError: showError,
|
||||
hideMessages: hideMessages,
|
||||
});
|
||||
return _.extend(options, {
|
||||
showInfo: showInfo,
|
||||
showError: showError,
|
||||
hideMessages: hideMessages,
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,267 +2,267 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.PagerPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
keyboard,
|
||||
router,
|
||||
pager,
|
||||
messagePresenter,
|
||||
browsingSettings,
|
||||
progress) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
keyboard,
|
||||
router,
|
||||
pager,
|
||||
messagePresenter,
|
||||
browsingSettings,
|
||||
progress) {
|
||||
|
||||
var $target;
|
||||
var $pageList;
|
||||
var $messages;
|
||||
var targetContent;
|
||||
var endlessScroll = browsingSettings.getSettings().endlessScroll;
|
||||
var scrollInterval;
|
||||
var templates = {};
|
||||
var forceClear = !endlessScroll;
|
||||
var $target;
|
||||
var $pageList;
|
||||
var $messages;
|
||||
var targetContent;
|
||||
var endlessScroll = browsingSettings.getSettings().endlessScroll;
|
||||
var scrollInterval;
|
||||
var templates = {};
|
||||
var forceClear = !endlessScroll;
|
||||
|
||||
var baseUri;
|
||||
var updateCallback;
|
||||
var baseUri;
|
||||
var updateCallback;
|
||||
|
||||
function init(params, loaded) {
|
||||
baseUri = params.baseUri;
|
||||
updateCallback = params.updateCallback;
|
||||
function init(params, loaded) {
|
||||
baseUri = params.baseUri;
|
||||
updateCallback = params.updateCallback;
|
||||
|
||||
messagePresenter.instant = true;
|
||||
messagePresenter.instant = true;
|
||||
|
||||
$target = params.$target;
|
||||
targetContent = jQuery(params.$target).html();
|
||||
$target = params.$target;
|
||||
targetContent = jQuery(params.$target).html();
|
||||
|
||||
pager.init({url: params.backendUri});
|
||||
setQuery(params.query);
|
||||
if (forceClear) {
|
||||
clearContent();
|
||||
}
|
||||
pager.init({url: params.backendUri});
|
||||
setQuery(params.query);
|
||||
if (forceClear) {
|
||||
clearContent();
|
||||
}
|
||||
|
||||
promise.wait(util.promiseTemplate('pager'))
|
||||
.then(function(template) {
|
||||
templates.pager = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
promise.wait(util.promiseTemplate('pager'))
|
||||
.then(function(template) {
|
||||
templates.pager = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function reinit(params, loaded) {
|
||||
setQuery(params.query);
|
||||
if (forceClear) {
|
||||
clearContent();
|
||||
}
|
||||
function reinit(params, loaded) {
|
||||
setQuery(params.query);
|
||||
if (forceClear) {
|
||||
clearContent();
|
||||
}
|
||||
|
||||
promise.wait(retrieve())
|
||||
.then(loaded)
|
||||
.fail(loaded);
|
||||
promise.wait(retrieve())
|
||||
.then(loaded)
|
||||
.fail(loaded);
|
||||
|
||||
if (!endlessScroll) {
|
||||
keyboard.keydown('a', navigateToPrevPage);
|
||||
keyboard.keydown('d', navigateToNextPage);
|
||||
}
|
||||
}
|
||||
if (!endlessScroll) {
|
||||
keyboard.keydown('a', navigateToPrevPage);
|
||||
keyboard.keydown('d', navigateToNextPage);
|
||||
}
|
||||
}
|
||||
|
||||
function deinit() {
|
||||
detachNextPageLoader();
|
||||
}
|
||||
function deinit() {
|
||||
detachNextPageLoader();
|
||||
}
|
||||
|
||||
function getUrl(options) {
|
||||
return util.appendComplexRouteParam(
|
||||
baseUri,
|
||||
util.simplifySearchQuery(
|
||||
_.extend(
|
||||
{},
|
||||
pager.getSearchParams(),
|
||||
{page: pager.getPage()},
|
||||
options)));
|
||||
}
|
||||
function getUrl(options) {
|
||||
return util.appendComplexRouteParam(
|
||||
baseUri,
|
||||
util.simplifySearchQuery(
|
||||
_.extend(
|
||||
{},
|
||||
pager.getSearchParams(),
|
||||
{page: pager.getPage()},
|
||||
options)));
|
||||
}
|
||||
|
||||
function syncUrl(options) {
|
||||
router.navigate(getUrl(options));
|
||||
}
|
||||
function syncUrl(options) {
|
||||
router.navigate(getUrl(options));
|
||||
}
|
||||
|
||||
function syncUrlInplace(options) {
|
||||
router.navigateInplace(getUrl(options));
|
||||
}
|
||||
function syncUrlInplace(options) {
|
||||
router.navigateInplace(getUrl(options));
|
||||
}
|
||||
|
||||
function retrieve() {
|
||||
messagePresenter.hideMessages($messages);
|
||||
progress.start();
|
||||
function retrieve() {
|
||||
messagePresenter.hideMessages($messages);
|
||||
progress.start();
|
||||
|
||||
return promise.make(function(resolve, reject) {
|
||||
hidePageList();
|
||||
return promise.make(function(resolve, reject) {
|
||||
hidePageList();
|
||||
|
||||
promise.wait(pager.retrieve())
|
||||
.then(function(response) {
|
||||
progress.done();
|
||||
promise.wait(pager.retrieve())
|
||||
.then(function(response) {
|
||||
progress.done();
|
||||
|
||||
if (forceClear) {
|
||||
clearContent();
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
var $page = jQuery('<div class="page">');
|
||||
if (endlessScroll && pager.getTotalPages() > 1) {
|
||||
$page.append('<p>Page ' + pager.getPage() + ' of ' + pager.getTotalPages() + '</p>');
|
||||
}
|
||||
$page.append(targetContent);
|
||||
$target.find('.pagination-content').append($page);
|
||||
updateCallback($page, response);
|
||||
if (forceClear) {
|
||||
clearContent();
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
var $page = jQuery('<div class="page">');
|
||||
if (endlessScroll && pager.getTotalPages() > 1) {
|
||||
$page.append('<p>Page ' + pager.getPage() + ' of ' + pager.getTotalPages() + '</p>');
|
||||
}
|
||||
$page.append(targetContent);
|
||||
$target.find('.pagination-content').append($page);
|
||||
updateCallback($page, response);
|
||||
|
||||
refreshPageList();
|
||||
if (!response.entities.length) {
|
||||
messagePresenter.showInfo($messages, 'No data to show');
|
||||
if (pager.getVisiblePages().length === 1) {
|
||||
hidePageList();
|
||||
} else {
|
||||
showPageList();
|
||||
}
|
||||
} else {
|
||||
showPageList();
|
||||
}
|
||||
refreshPageList();
|
||||
if (!response.entities.length) {
|
||||
messagePresenter.showInfo($messages, 'No data to show');
|
||||
if (pager.getVisiblePages().length === 1) {
|
||||
hidePageList();
|
||||
} else {
|
||||
showPageList();
|
||||
}
|
||||
} else {
|
||||
showPageList();
|
||||
}
|
||||
|
||||
if (pager.getPage() < response.totalPages) {
|
||||
attachNextPageLoader();
|
||||
}
|
||||
if (pager.getPage() < response.totalPages) {
|
||||
attachNextPageLoader();
|
||||
}
|
||||
|
||||
resolve();
|
||||
}).fail(function(response) {
|
||||
progress.done();
|
||||
clearContent();
|
||||
hidePageList();
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
resolve();
|
||||
}).fail(function(response) {
|
||||
progress.done();
|
||||
clearContent();
|
||||
hidePageList();
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function clearContent() {
|
||||
detachNextPageLoader();
|
||||
$target.find('.pagination-content').empty();
|
||||
}
|
||||
function clearContent() {
|
||||
detachNextPageLoader();
|
||||
$target.find('.pagination-content').empty();
|
||||
}
|
||||
|
||||
function attachNextPageLoader() {
|
||||
if (!endlessScroll) {
|
||||
return;
|
||||
}
|
||||
function attachNextPageLoader() {
|
||||
if (!endlessScroll) {
|
||||
return;
|
||||
}
|
||||
|
||||
detachNextPageLoader();
|
||||
scrollInterval = window.setInterval(function() {
|
||||
var myScrollInterval = scrollInterval;
|
||||
var baseLine = $target.offset().top + $target.innerHeight();
|
||||
var scrollY = jQuery(window).scrollTop() + jQuery(window).height();
|
||||
if (scrollY > baseLine) {
|
||||
syncUrlInplace({page: pager.getPage() + 1});
|
||||
window.clearInterval(myScrollInterval);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
detachNextPageLoader();
|
||||
scrollInterval = window.setInterval(function() {
|
||||
var myScrollInterval = scrollInterval;
|
||||
var baseLine = $target.offset().top + $target.innerHeight();
|
||||
var scrollY = jQuery(window).scrollTop() + jQuery(window).height();
|
||||
if (scrollY > baseLine) {
|
||||
syncUrlInplace({page: pager.getPage() + 1});
|
||||
window.clearInterval(myScrollInterval);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function detachNextPageLoader() {
|
||||
window.clearInterval(scrollInterval);
|
||||
}
|
||||
function detachNextPageLoader() {
|
||||
window.clearInterval(scrollInterval);
|
||||
}
|
||||
|
||||
function showPageList() {
|
||||
$pageList.show();
|
||||
}
|
||||
function showPageList() {
|
||||
$pageList.show();
|
||||
}
|
||||
|
||||
function hidePageList() {
|
||||
$pageList.hide();
|
||||
}
|
||||
function hidePageList() {
|
||||
$pageList.hide();
|
||||
}
|
||||
|
||||
function navigateToPrevPage() {
|
||||
console.log('!');
|
||||
if (pager.prevPage()) {
|
||||
syncUrl({page: pager.getPage()});
|
||||
}
|
||||
}
|
||||
function navigateToPrevPage() {
|
||||
console.log('!');
|
||||
if (pager.prevPage()) {
|
||||
syncUrl({page: pager.getPage()});
|
||||
}
|
||||
}
|
||||
|
||||
function navigateToNextPage() {
|
||||
if (pager.nextPage()) {
|
||||
syncUrl({page: pager.getPage()});
|
||||
}
|
||||
}
|
||||
function navigateToNextPage() {
|
||||
if (pager.nextPage()) {
|
||||
syncUrl({page: pager.getPage()});
|
||||
}
|
||||
}
|
||||
|
||||
function refreshPageList() {
|
||||
var $lastItem = $pageList.find('li:last-child');
|
||||
var currentPage = pager.getPage();
|
||||
var pages = pager.getVisiblePages();
|
||||
$pageList.find('li.page').remove();
|
||||
var lastPage = 0;
|
||||
_.each(pages, function(page) {
|
||||
if (page - lastPage > 1) {
|
||||
jQuery('<li class="page ellipsis"><a>…</a></li>').insertBefore($lastItem);
|
||||
}
|
||||
lastPage = page;
|
||||
function refreshPageList() {
|
||||
var $lastItem = $pageList.find('li:last-child');
|
||||
var currentPage = pager.getPage();
|
||||
var pages = pager.getVisiblePages();
|
||||
$pageList.find('li.page').remove();
|
||||
var lastPage = 0;
|
||||
_.each(pages, function(page) {
|
||||
if (page - lastPage > 1) {
|
||||
jQuery('<li class="page ellipsis"><a>…</a></li>').insertBefore($lastItem);
|
||||
}
|
||||
lastPage = page;
|
||||
|
||||
var $a = jQuery('<a href="#"/>');
|
||||
$a.click(function(e) {
|
||||
e.preventDefault();
|
||||
syncUrl({page: page});
|
||||
});
|
||||
$a.addClass('big-button');
|
||||
$a.text(page);
|
||||
if (page === currentPage) {
|
||||
$a.addClass('active');
|
||||
}
|
||||
jQuery('<li class="page"/>').append($a).insertBefore($lastItem);
|
||||
});
|
||||
var $a = jQuery('<a href="#"/>');
|
||||
$a.click(function(e) {
|
||||
e.preventDefault();
|
||||
syncUrl({page: page});
|
||||
});
|
||||
$a.addClass('big-button');
|
||||
$a.text(page);
|
||||
if (page === currentPage) {
|
||||
$a.addClass('active');
|
||||
}
|
||||
jQuery('<li class="page"/>').append($a).insertBefore($lastItem);
|
||||
});
|
||||
|
||||
$pageList.find('li.next a').unbind('click').bind('click', function(e) {
|
||||
e.preventDefault();
|
||||
navigateToNextPage();
|
||||
});
|
||||
$pageList.find('li.prev a').unbind('click').bind('click', function(e) {
|
||||
e.preventDefault();
|
||||
navigateToPrevPage();
|
||||
});
|
||||
}
|
||||
$pageList.find('li.next a').unbind('click').bind('click', function(e) {
|
||||
e.preventDefault();
|
||||
navigateToNextPage();
|
||||
});
|
||||
$pageList.find('li.prev a').unbind('click').bind('click', function(e) {
|
||||
e.preventDefault();
|
||||
navigateToPrevPage();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$target.html(templates.pager());
|
||||
$messages = $target.find('.pagination-content');
|
||||
$pageList = $target.find('.page-list');
|
||||
if (endlessScroll) {
|
||||
$pageList.remove();
|
||||
} else {
|
||||
refreshPageList();
|
||||
}
|
||||
}
|
||||
function render() {
|
||||
$target.html(templates.pager());
|
||||
$messages = $target.find('.pagination-content');
|
||||
$pageList = $target.find('.page-list');
|
||||
if (endlessScroll) {
|
||||
$pageList.remove();
|
||||
} else {
|
||||
refreshPageList();
|
||||
}
|
||||
}
|
||||
|
||||
function setQuery(query) {
|
||||
if (!query) {
|
||||
return;
|
||||
}
|
||||
query.page = parseInt(query.page) || 1;
|
||||
var page = query.page;
|
||||
query = _.extend({}, query);
|
||||
delete query.page;
|
||||
forceClear =
|
||||
query.query !== pager.getSearchParams().query ||
|
||||
query.order !== pager.getSearchParams().order ||
|
||||
parseInt(page) !== pager.getPage() + 1 ||
|
||||
!endlessScroll;
|
||||
pager.setSearchParams(query);
|
||||
pager.setPage(page);
|
||||
}
|
||||
function setQuery(query) {
|
||||
if (!query) {
|
||||
return;
|
||||
}
|
||||
query.page = parseInt(query.page) || 1;
|
||||
var page = query.page;
|
||||
query = _.extend({}, query);
|
||||
delete query.page;
|
||||
forceClear =
|
||||
query.query !== pager.getSearchParams().query ||
|
||||
query.order !== pager.getSearchParams().order ||
|
||||
parseInt(page) !== pager.getPage() + 1 ||
|
||||
!endlessScroll;
|
||||
pager.setSearchParams(query);
|
||||
pager.setPage(page);
|
||||
}
|
||||
|
||||
function setQueryAndSyncUrl(query) {
|
||||
setQuery(query);
|
||||
syncUrl();
|
||||
}
|
||||
function setQueryAndSyncUrl(query) {
|
||||
setQuery(query);
|
||||
syncUrl();
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
syncUrl: syncUrl,
|
||||
setQuery: setQueryAndSyncUrl,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
syncUrl: syncUrl,
|
||||
setQuery: setQueryAndSyncUrl,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,76 +2,76 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.PostContentPresenter = function(
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
presenterManager,
|
||||
postNotesPresenter) {
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
presenterManager,
|
||||
postNotesPresenter) {
|
||||
|
||||
var post;
|
||||
var templates = {};
|
||||
var $target;
|
||||
var post;
|
||||
var templates = {};
|
||||
var $target;
|
||||
|
||||
function init(params, loaded) {
|
||||
$target = params.$target;
|
||||
post = params.post;
|
||||
function init(params, loaded) {
|
||||
$target = params.$target;
|
||||
post = params.post;
|
||||
|
||||
promise.wait(util.promiseTemplate('post-content'))
|
||||
.then(function(postContentTemplate) {
|
||||
templates.postContent = postContentTemplate;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
promise.wait(util.promiseTemplate('post-content'))
|
||||
.then(function(postContentTemplate) {
|
||||
templates.postContent = postContentTemplate;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$target.html(templates.postContent({post: post}));
|
||||
function render() {
|
||||
$target.html(templates.postContent({post: post}));
|
||||
|
||||
if (post.contentType === 'image') {
|
||||
loadPostNotes();
|
||||
updatePostNotesSize();
|
||||
}
|
||||
if (post.contentType === 'image') {
|
||||
loadPostNotes();
|
||||
updatePostNotesSize();
|
||||
}
|
||||
|
||||
jQuery(window).resize(updatePostNotesSize);
|
||||
}
|
||||
jQuery(window).resize(updatePostNotesSize);
|
||||
}
|
||||
|
||||
function loadPostNotes() {
|
||||
presenterManager.initPresenters([
|
||||
[postNotesPresenter, {post: post, notes: post.notes, $target: $target.find('.post-notes-target')}]],
|
||||
function() {});
|
||||
}
|
||||
function loadPostNotes() {
|
||||
presenterManager.initPresenters([
|
||||
[postNotesPresenter, {post: post, notes: post.notes, $target: $target.find('.post-notes-target')}]],
|
||||
function() {});
|
||||
}
|
||||
|
||||
function updatePostNotesSize() {
|
||||
var $postNotes = $target.find('.post-notes-target');
|
||||
var $objectWrapper = $target.find('.object-wrapper');
|
||||
$postNotes.css({
|
||||
width: $objectWrapper.outerWidth() + 'px',
|
||||
height: $objectWrapper.outerHeight() + 'px',
|
||||
left: ($objectWrapper.offset().left - $objectWrapper.parent().offset().left) + 'px',
|
||||
top: ($objectWrapper.offset().top - $objectWrapper.parent().offset().top) + 'px',
|
||||
});
|
||||
}
|
||||
function updatePostNotesSize() {
|
||||
var $postNotes = $target.find('.post-notes-target');
|
||||
var $objectWrapper = $target.find('.object-wrapper');
|
||||
$postNotes.css({
|
||||
width: $objectWrapper.outerWidth() + 'px',
|
||||
height: $objectWrapper.outerHeight() + 'px',
|
||||
left: ($objectWrapper.offset().left - $objectWrapper.parent().offset().left) + 'px',
|
||||
top: ($objectWrapper.offset().top - $objectWrapper.parent().offset().top) + 'px',
|
||||
});
|
||||
}
|
||||
|
||||
function addNewPostNote() {
|
||||
postNotesPresenter.addNewPostNote();
|
||||
}
|
||||
function addNewPostNote() {
|
||||
postNotesPresenter.addNewPostNote();
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
addNewPostNote: addNewPostNote,
|
||||
updatePostNotesSize: updatePostNotesSize,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
addNewPostNote: addNewPostNote,
|
||||
updatePostNotesSize: updatePostNotesSize,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
App.DI.register('postContentPresenter', [
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'presenterManager',
|
||||
'postNotesPresenter'],
|
||||
App.Presenters.PostContentPresenter);
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'presenterManager',
|
||||
'postNotesPresenter'],
|
||||
App.Presenters.PostContentPresenter);
|
||||
|
|
|
@ -2,154 +2,154 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.PostEditPresenter = function(
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
tagList) {
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
tagList) {
|
||||
|
||||
var $target;
|
||||
var post;
|
||||
var updateCallback;
|
||||
var privileges = {};
|
||||
var templates = {};
|
||||
var $target;
|
||||
var post;
|
||||
var updateCallback;
|
||||
var privileges = {};
|
||||
var templates = {};
|
||||
|
||||
var tagInput;
|
||||
var postContentFileDropper;
|
||||
var postThumbnailFileDropper;
|
||||
var postContent;
|
||||
var postThumbnail;
|
||||
var tagInput;
|
||||
var postContentFileDropper;
|
||||
var postThumbnailFileDropper;
|
||||
var postContent;
|
||||
var postThumbnail;
|
||||
|
||||
privileges.canChangeSafety = auth.hasPrivilege(auth.privileges.changePostSafety);
|
||||
privileges.canChangeSource = auth.hasPrivilege(auth.privileges.changePostSource);
|
||||
privileges.canChangeTags = auth.hasPrivilege(auth.privileges.changePostTags);
|
||||
privileges.canChangeContent = auth.hasPrivilege(auth.privileges.changePostContent);
|
||||
privileges.canChangeThumbnail = auth.hasPrivilege(auth.privileges.changePostThumbnail);
|
||||
privileges.canChangeRelations = auth.hasPrivilege(auth.privileges.changePostRelations);
|
||||
privileges.canChangeFlags = auth.hasPrivilege(auth.privileges.changePostFlags);
|
||||
privileges.canChangeSafety = auth.hasPrivilege(auth.privileges.changePostSafety);
|
||||
privileges.canChangeSource = auth.hasPrivilege(auth.privileges.changePostSource);
|
||||
privileges.canChangeTags = auth.hasPrivilege(auth.privileges.changePostTags);
|
||||
privileges.canChangeContent = auth.hasPrivilege(auth.privileges.changePostContent);
|
||||
privileges.canChangeThumbnail = auth.hasPrivilege(auth.privileges.changePostThumbnail);
|
||||
privileges.canChangeRelations = auth.hasPrivilege(auth.privileges.changePostRelations);
|
||||
privileges.canChangeFlags = auth.hasPrivilege(auth.privileges.changePostFlags);
|
||||
|
||||
function init(params, loaded) {
|
||||
post = params.post;
|
||||
function init(params, loaded) {
|
||||
post = params.post;
|
||||
|
||||
updateCallback = params.updateCallback;
|
||||
$target = params.$target;
|
||||
updateCallback = params.updateCallback;
|
||||
$target = params.$target;
|
||||
|
||||
promise.wait(util.promiseTemplate('post-edit'))
|
||||
.then(function(postEditTemplate) {
|
||||
templates.postEdit = postEditTemplate;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
promise.wait(util.promiseTemplate('post-edit'))
|
||||
.then(function(postEditTemplate) {
|
||||
templates.postEdit = postEditTemplate;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$target.html(templates.postEdit({post: post, privileges: privileges}));
|
||||
function render() {
|
||||
$target.html(templates.postEdit({post: post, privileges: privileges}));
|
||||
|
||||
postContentFileDropper = new App.Controls.FileDropper($target.find('form [name=content]'));
|
||||
postContentFileDropper.onChange = postContentChanged;
|
||||
postContentFileDropper.setNames = true;
|
||||
postThumbnailFileDropper = new App.Controls.FileDropper($target.find('form [name=thumbnail]'));
|
||||
postThumbnailFileDropper.onChange = postThumbnailChanged;
|
||||
postThumbnailFileDropper.setNames = true;
|
||||
postContentFileDropper = new App.Controls.FileDropper($target.find('form [name=content]'));
|
||||
postContentFileDropper.onChange = postContentChanged;
|
||||
postContentFileDropper.setNames = true;
|
||||
postThumbnailFileDropper = new App.Controls.FileDropper($target.find('form [name=thumbnail]'));
|
||||
postThumbnailFileDropper.onChange = postThumbnailChanged;
|
||||
postThumbnailFileDropper.setNames = true;
|
||||
|
||||
if (privileges.canChangeTags) {
|
||||
tagInput = new App.Controls.TagInput($target.find('form [name=tags]'));
|
||||
tagInput.inputConfirmed = editPost;
|
||||
}
|
||||
if (privileges.canChangeTags) {
|
||||
tagInput = new App.Controls.TagInput($target.find('form [name=tags]'));
|
||||
tagInput.inputConfirmed = editPost;
|
||||
}
|
||||
|
||||
$target.find('form').submit(editFormSubmitted);
|
||||
}
|
||||
$target.find('form').submit(editFormSubmitted);
|
||||
}
|
||||
|
||||
function focus() {
|
||||
if (tagInput) {
|
||||
tagInput.focus();
|
||||
}
|
||||
}
|
||||
function focus() {
|
||||
if (tagInput) {
|
||||
tagInput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function editFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
editPost();
|
||||
}
|
||||
function editFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
editPost();
|
||||
}
|
||||
|
||||
function postContentChanged(files) {
|
||||
postContent = files[0];
|
||||
}
|
||||
function postContentChanged(files) {
|
||||
postContent = files[0];
|
||||
}
|
||||
|
||||
function postThumbnailChanged(files) {
|
||||
postThumbnail = files[0];
|
||||
}
|
||||
function postThumbnailChanged(files) {
|
||||
postThumbnail = files[0];
|
||||
}
|
||||
|
||||
function getPrivileges() {
|
||||
return privileges;
|
||||
}
|
||||
function getPrivileges() {
|
||||
return privileges;
|
||||
}
|
||||
|
||||
function editPost() {
|
||||
var $form = $target.find('form');
|
||||
var formData = new FormData();
|
||||
formData.append('seenEditTime', post.lastEditTime);
|
||||
function editPost() {
|
||||
var $form = $target.find('form');
|
||||
var formData = new FormData();
|
||||
formData.append('seenEditTime', post.lastEditTime);
|
||||
|
||||
if (privileges.canChangeContent && postContent) {
|
||||
formData.append('content', postContent);
|
||||
}
|
||||
if (privileges.canChangeContent && postContent) {
|
||||
formData.append('content', postContent);
|
||||
}
|
||||
|
||||
if (privileges.canChangeThumbnail && postThumbnail) {
|
||||
formData.append('thumbnail', postThumbnail);
|
||||
}
|
||||
if (privileges.canChangeThumbnail && postThumbnail) {
|
||||
formData.append('thumbnail', postThumbnail);
|
||||
}
|
||||
|
||||
if (privileges.canChangeSource) {
|
||||
formData.append('source', $form.find('[name=source]').val());
|
||||
}
|
||||
if (privileges.canChangeSource) {
|
||||
formData.append('source', $form.find('[name=source]').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangeSafety) {
|
||||
formData.append('safety', $form.find('[name=safety]:checked').val());
|
||||
}
|
||||
if (privileges.canChangeSafety) {
|
||||
formData.append('safety', $form.find('[name=safety]:checked').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangeTags) {
|
||||
formData.append('tags', tagInput.getTags().join(' '));
|
||||
}
|
||||
if (privileges.canChangeTags) {
|
||||
formData.append('tags', tagInput.getTags().join(' '));
|
||||
}
|
||||
|
||||
if (privileges.canChangeRelations) {
|
||||
formData.append('relations', $form.find('[name=relations]').val());
|
||||
}
|
||||
if (privileges.canChangeRelations) {
|
||||
formData.append('relations', $form.find('[name=relations]').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangeFlags) {
|
||||
if (post.contentType === 'video') {
|
||||
formData.append('loop', $form.find('[name=loop]').is(':checked') ? 1 : 0);
|
||||
}
|
||||
}
|
||||
if (privileges.canChangeFlags) {
|
||||
if (post.contentType === 'video') {
|
||||
formData.append('loop', $form.find('[name=loop]').is(':checked') ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (post.tags.length === 0) {
|
||||
showEditError('No tags set.');
|
||||
return;
|
||||
}
|
||||
if (post.tags.length === 0) {
|
||||
showEditError('No tags set.');
|
||||
return;
|
||||
}
|
||||
|
||||
jQuery(document.activeElement).blur();
|
||||
jQuery(document.activeElement).blur();
|
||||
|
||||
promise.wait(api.post('/posts/' + post.id, formData))
|
||||
.then(function(response) {
|
||||
tagList.refreshTags();
|
||||
if (typeof(updateCallback) !== 'undefined') {
|
||||
updateCallback(post = response.json);
|
||||
}
|
||||
}).fail(function(response) {
|
||||
showEditError(response);
|
||||
});
|
||||
}
|
||||
promise.wait(api.post('/posts/' + post.id, formData))
|
||||
.then(function(response) {
|
||||
tagList.refreshTags();
|
||||
if (typeof(updateCallback) !== 'undefined') {
|
||||
updateCallback(post = response.json);
|
||||
}
|
||||
}).fail(function(response) {
|
||||
showEditError(response);
|
||||
});
|
||||
}
|
||||
|
||||
function showEditError(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
}
|
||||
function showEditError(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
getPrivileges: getPrivileges,
|
||||
focus: focus,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
getPrivileges: getPrivileges,
|
||||
focus: focus,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,264 +2,264 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.PostListPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
api,
|
||||
keyboard,
|
||||
pagerPresenter,
|
||||
browsingSettings,
|
||||
topNavigationPresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
api,
|
||||
keyboard,
|
||||
pagerPresenter,
|
||||
browsingSettings,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var KEY_RETURN = 13;
|
||||
var KEY_RETURN = 13;
|
||||
|
||||
var templates = {};
|
||||
var $el = jQuery('#content');
|
||||
var $searchInput;
|
||||
var privileges = {};
|
||||
var templates = {};
|
||||
var $el = jQuery('#content');
|
||||
var $searchInput;
|
||||
var privileges = {};
|
||||
|
||||
var params;
|
||||
var params;
|
||||
|
||||
function init(_params, loaded) {
|
||||
topNavigationPresenter.select('posts');
|
||||
topNavigationPresenter.changeTitle('Posts');
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
function init(_params, loaded) {
|
||||
topNavigationPresenter.select('posts');
|
||||
topNavigationPresenter.changeTitle('Posts');
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
|
||||
privileges.canMassTag = auth.hasPrivilege(auth.privileges.massTag);
|
||||
privileges.canViewPosts = auth.hasPrivilege(auth.privileges.viewPosts);
|
||||
privileges.canMassTag = auth.hasPrivilege(auth.privileges.massTag);
|
||||
privileges.canViewPosts = auth.hasPrivilege(auth.privileges.viewPosts);
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('post-list'),
|
||||
util.promiseTemplate('post-list-item'))
|
||||
.then(function(listTemplate, listItemTemplate) {
|
||||
templates.list = listTemplate;
|
||||
templates.listItem = listItemTemplate;
|
||||
promise.wait(
|
||||
util.promiseTemplate('post-list'),
|
||||
util.promiseTemplate('post-list-item'))
|
||||
.then(function(listTemplate, listItemTemplate) {
|
||||
templates.list = listTemplate;
|
||||
templates.listItem = listItemTemplate;
|
||||
|
||||
render();
|
||||
loaded();
|
||||
render();
|
||||
loaded();
|
||||
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/posts',
|
||||
backendUri: '/posts',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderPosts($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/posts',
|
||||
backendUri: '/posts',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderPosts($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
|
||||
jQuery(window).on('resize', windowResized);
|
||||
}
|
||||
jQuery(window).on('resize', windowResized);
|
||||
}
|
||||
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
pagerPresenter.reinit({query: params.query});
|
||||
loaded();
|
||||
softRender();
|
||||
}
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
pagerPresenter.reinit({query: params.query});
|
||||
loaded();
|
||||
softRender();
|
||||
}
|
||||
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
jQuery(window).off('resize', windowResized);
|
||||
}
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
jQuery(window).off('resize', windowResized);
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.list({
|
||||
massTag: params.query.massTag,
|
||||
privileges: privileges,
|
||||
browsingSettings: browsingSettings.getSettings()}));
|
||||
$searchInput = $el.find('input[name=query]');
|
||||
App.Controls.AutoCompleteInput($searchInput);
|
||||
function render() {
|
||||
$el.html(templates.list({
|
||||
massTag: params.query.massTag,
|
||||
privileges: privileges,
|
||||
browsingSettings: browsingSettings.getSettings()}));
|
||||
$searchInput = $el.find('input[name=query]');
|
||||
App.Controls.AutoCompleteInput($searchInput);
|
||||
|
||||
$searchInput.val(params.query.query);
|
||||
$searchInput.keydown(searchInputKeyPressed);
|
||||
$el.find('form').submit(searchFormSubmitted);
|
||||
$el.find('[name=mass-tag]').click(massTagButtonClicked);
|
||||
$el.find('.safety button').click(safetyButtonClicked);
|
||||
$searchInput.val(params.query.query);
|
||||
$searchInput.keydown(searchInputKeyPressed);
|
||||
$el.find('form').submit(searchFormSubmitted);
|
||||
$el.find('[name=mass-tag]').click(massTagButtonClicked);
|
||||
$el.find('.safety button').click(safetyButtonClicked);
|
||||
|
||||
keyboard.keyup('p', function() {
|
||||
$el.find('.posts li a').eq(0).focus();
|
||||
});
|
||||
keyboard.keyup('p', function() {
|
||||
$el.find('.posts li a').eq(0).focus();
|
||||
});
|
||||
|
||||
keyboard.keyup('q', function() {
|
||||
$searchInput.eq(0).focus().select();
|
||||
});
|
||||
keyboard.keyup('q', function() {
|
||||
$searchInput.eq(0).focus().select();
|
||||
});
|
||||
|
||||
windowResized();
|
||||
}
|
||||
windowResized();
|
||||
}
|
||||
|
||||
function safetyButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var settings = browsingSettings.getSettings();
|
||||
var buttonClass = jQuery(e.currentTarget).attr('class').split(' ')[0];
|
||||
var enabled = jQuery(e.currentTarget).hasClass('disabled');
|
||||
jQuery(e.currentTarget).toggleClass('disabled');
|
||||
if (buttonClass === 'safety-unsafe') {
|
||||
settings.listPosts.unsafe = enabled;
|
||||
} else if (buttonClass === 'safety-sketchy') {
|
||||
settings.listPosts.sketchy = enabled;
|
||||
} else if (buttonClass === 'safety-safe') {
|
||||
settings.listPosts.safe = enabled;
|
||||
}
|
||||
promise.wait(browsingSettings.setSettings(settings))
|
||||
.then(function() {
|
||||
reinit(params, function() {});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
});
|
||||
}
|
||||
function safetyButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var settings = browsingSettings.getSettings();
|
||||
var buttonClass = jQuery(e.currentTarget).attr('class').split(' ')[0];
|
||||
var enabled = jQuery(e.currentTarget).hasClass('disabled');
|
||||
jQuery(e.currentTarget).toggleClass('disabled');
|
||||
if (buttonClass === 'safety-unsafe') {
|
||||
settings.listPosts.unsafe = enabled;
|
||||
} else if (buttonClass === 'safety-sketchy') {
|
||||
settings.listPosts.sketchy = enabled;
|
||||
} else if (buttonClass === 'safety-safe') {
|
||||
settings.listPosts.safe = enabled;
|
||||
}
|
||||
promise.wait(browsingSettings.setSettings(settings))
|
||||
.then(function() {
|
||||
reinit(params, function() {});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
});
|
||||
}
|
||||
|
||||
function softRender() {
|
||||
$searchInput.val(params.query.query);
|
||||
function softRender() {
|
||||
$searchInput.val(params.query.query);
|
||||
|
||||
var $massTagInfo = $el.find('.mass-tag-info');
|
||||
if (params.query.massTag) {
|
||||
$massTagInfo.show();
|
||||
$massTagInfo.find('span').text(params.query.massTag);
|
||||
} else {
|
||||
$massTagInfo.hide();
|
||||
}
|
||||
_.map($el.find('.posts .post-small'), function(postNode) { softRenderPost(jQuery(postNode).parents('li')); });
|
||||
}
|
||||
var $massTagInfo = $el.find('.mass-tag-info');
|
||||
if (params.query.massTag) {
|
||||
$massTagInfo.show();
|
||||
$massTagInfo.find('span').text(params.query.massTag);
|
||||
} else {
|
||||
$massTagInfo.hide();
|
||||
}
|
||||
_.map($el.find('.posts .post-small'), function(postNode) { softRenderPost(jQuery(postNode).parents('li')); });
|
||||
}
|
||||
|
||||
function renderPosts($page, posts) {
|
||||
var $target = $page.find('.posts');
|
||||
_.each(posts, function(post) {
|
||||
if (!shouldSkipPost(post)) {
|
||||
var $post = renderPost(post);
|
||||
softRenderPost($post);
|
||||
$target.append($post);
|
||||
}
|
||||
});
|
||||
windowResized();
|
||||
}
|
||||
function renderPosts($page, posts) {
|
||||
var $target = $page.find('.posts');
|
||||
_.each(posts, function(post) {
|
||||
if (!shouldSkipPost(post)) {
|
||||
var $post = renderPost(post);
|
||||
softRenderPost($post);
|
||||
$target.append($post);
|
||||
}
|
||||
});
|
||||
windowResized();
|
||||
}
|
||||
|
||||
function shouldSkipPost(post) {
|
||||
var settings = browsingSettings.getSettings();
|
||||
if (post.ownScore < 0 && settings.hideDownvoted) {
|
||||
return true;
|
||||
}
|
||||
if (settings.listPosts) {
|
||||
if (post.safety === 'safe' && !settings.listPosts.safe) {
|
||||
return true;
|
||||
} else if (post.safety === 'sketchy' && !settings.listPosts.sketchy) {
|
||||
return true;
|
||||
} else if (post.safety === 'unsafe' && !settings.listPosts.unsafe) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function shouldSkipPost(post) {
|
||||
var settings = browsingSettings.getSettings();
|
||||
if (post.ownScore < 0 && settings.hideDownvoted) {
|
||||
return true;
|
||||
}
|
||||
if (settings.listPosts) {
|
||||
if (post.safety === 'safe' && !settings.listPosts.safe) {
|
||||
return true;
|
||||
} else if (post.safety === 'sketchy' && !settings.listPosts.sketchy) {
|
||||
return true;
|
||||
} else if (post.safety === 'unsafe' && !settings.listPosts.unsafe) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function renderPost(post) {
|
||||
var $post = jQuery('<li>' + templates.listItem({
|
||||
util: util,
|
||||
query: params.query,
|
||||
post: post,
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
$post.data('post', post);
|
||||
util.loadImagesNicely($post.find('img'));
|
||||
return $post;
|
||||
}
|
||||
function renderPost(post) {
|
||||
var $post = jQuery('<li>' + templates.listItem({
|
||||
util: util,
|
||||
query: params.query,
|
||||
post: post,
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
$post.data('post', post);
|
||||
util.loadImagesNicely($post.find('img'));
|
||||
return $post;
|
||||
}
|
||||
|
||||
function softRenderPost($post) {
|
||||
var classes = [];
|
||||
if (params.query.massTag) {
|
||||
var post = $post.data('post');
|
||||
if (_.contains(_.map(post.tags, function(tag) { return tag.name.toLowerCase(); }), params.query.massTag.toLowerCase())) {
|
||||
classes.push('tagged');
|
||||
} else {
|
||||
classes.push('untagged');
|
||||
}
|
||||
}
|
||||
$post.toggleClass('tagged', _.contains(classes, 'tagged'));
|
||||
$post.toggleClass('untagged', _.contains(classes, 'untagged'));
|
||||
$post.find('.action').toggle(_.any(classes));
|
||||
$post.find('.action button').text(_.contains(classes, 'tagged') ? 'Tagged' : 'Untagged').unbind('click').click(postTagButtonClicked);
|
||||
}
|
||||
function softRenderPost($post) {
|
||||
var classes = [];
|
||||
if (params.query.massTag) {
|
||||
var post = $post.data('post');
|
||||
if (_.contains(_.map(post.tags, function(tag) { return tag.name.toLowerCase(); }), params.query.massTag.toLowerCase())) {
|
||||
classes.push('tagged');
|
||||
} else {
|
||||
classes.push('untagged');
|
||||
}
|
||||
}
|
||||
$post.toggleClass('tagged', _.contains(classes, 'tagged'));
|
||||
$post.toggleClass('untagged', _.contains(classes, 'untagged'));
|
||||
$post.find('.action').toggle(_.any(classes));
|
||||
$post.find('.action button').text(_.contains(classes, 'tagged') ? 'Tagged' : 'Untagged').unbind('click').click(postTagButtonClicked);
|
||||
}
|
||||
|
||||
function windowResized() {
|
||||
var $list = $el.find('ul.posts');
|
||||
var $posts = $list.find('.post-small');
|
||||
var $firstPost = $posts.eq(0);
|
||||
var $lastPost = $firstPost;
|
||||
for (var i = 1; i < $posts.length; i ++) {
|
||||
$lastPost = $posts.eq(i-1);
|
||||
if ($posts.eq(i).offset().left < $lastPost.offset().left) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($firstPost.length === 0) {
|
||||
return;
|
||||
}
|
||||
$el.find('.search').width($lastPost.offset().left + $lastPost.width() - $firstPost.offset().left);
|
||||
}
|
||||
function windowResized() {
|
||||
var $list = $el.find('ul.posts');
|
||||
var $posts = $list.find('.post-small');
|
||||
var $firstPost = $posts.eq(0);
|
||||
var $lastPost = $firstPost;
|
||||
for (var i = 1; i < $posts.length; i ++) {
|
||||
$lastPost = $posts.eq(i-1);
|
||||
if ($posts.eq(i).offset().left < $lastPost.offset().left) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($firstPost.length === 0) {
|
||||
return;
|
||||
}
|
||||
$el.find('.search').width($lastPost.offset().left + $lastPost.width() - $firstPost.offset().left);
|
||||
}
|
||||
|
||||
function postTagButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var $post = jQuery(e.target).parents('li');
|
||||
var post = $post.data('post');
|
||||
var tags = _.pluck(post.tags, 'name');
|
||||
if (_.contains(_.map(tags, function(tag) { return tag.toLowerCase(); }), params.query.massTag.toLowerCase())) {
|
||||
tags = _.filter(tags, function(tag) { return tag.toLowerCase() !== params.query.massTag.toLowerCase(); });
|
||||
} else {
|
||||
tags.push(params.query.massTag);
|
||||
}
|
||||
var formData = {};
|
||||
formData.seenEditTime = post.lastEditTime;
|
||||
formData.tags = tags.join(' ');
|
||||
promise.wait(api.post('/posts/' + post.id, formData))
|
||||
.then(function(response) {
|
||||
post = response.json;
|
||||
$post.data('post', post);
|
||||
softRenderPost($post);
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
function postTagButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var $post = jQuery(e.target).parents('li');
|
||||
var post = $post.data('post');
|
||||
var tags = _.pluck(post.tags, 'name');
|
||||
if (_.contains(_.map(tags, function(tag) { return tag.toLowerCase(); }), params.query.massTag.toLowerCase())) {
|
||||
tags = _.filter(tags, function(tag) { return tag.toLowerCase() !== params.query.massTag.toLowerCase(); });
|
||||
} else {
|
||||
tags.push(params.query.massTag);
|
||||
}
|
||||
var formData = {};
|
||||
formData.seenEditTime = post.lastEditTime;
|
||||
formData.tags = tags.join(' ');
|
||||
promise.wait(api.post('/posts/' + post.id, formData))
|
||||
.then(function(response) {
|
||||
post = response.json;
|
||||
$post.data('post', post);
|
||||
softRenderPost($post);
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
|
||||
function searchInputKeyPressed(e) {
|
||||
if (e.which !== KEY_RETURN) {
|
||||
return;
|
||||
}
|
||||
updateSearch();
|
||||
}
|
||||
function searchInputKeyPressed(e) {
|
||||
if (e.which !== KEY_RETURN) {
|
||||
return;
|
||||
}
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
function massTagButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
params.query.massTag = window.prompt('Enter tag to tag with:');
|
||||
pagerPresenter.setQuery(params.query);
|
||||
}
|
||||
function massTagButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
params.query.massTag = window.prompt('Enter tag to tag with:');
|
||||
pagerPresenter.setQuery(params.query);
|
||||
}
|
||||
|
||||
function searchFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
updateSearch();
|
||||
}
|
||||
function searchFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
function updateSearch() {
|
||||
$searchInput.blur();
|
||||
params.query.query = $searchInput.val().trim();
|
||||
params.query.page = 1;
|
||||
pagerPresenter.setQuery(params.query);
|
||||
}
|
||||
function updateSearch() {
|
||||
$searchInput.blur();
|
||||
params.query.query = $searchInput.val().trim();
|
||||
params.query.page = 1;
|
||||
pagerPresenter.setQuery(params.query);
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,192 +2,192 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.PostNotesPresenter = function(
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
draggable,
|
||||
resizable) {
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
draggable,
|
||||
resizable) {
|
||||
|
||||
var post;
|
||||
var notes;
|
||||
var templates = {};
|
||||
var $target;
|
||||
var $form;
|
||||
var privileges = {};
|
||||
var post;
|
||||
var notes;
|
||||
var templates = {};
|
||||
var $target;
|
||||
var $form;
|
||||
var privileges = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
$target = params.$target;
|
||||
post = params.post;
|
||||
notes = params.notes || [];
|
||||
function init(params, loaded) {
|
||||
$target = params.$target;
|
||||
post = params.post;
|
||||
notes = params.notes || [];
|
||||
|
||||
privileges.canDeletePostNotes = auth.hasPrivilege(auth.privileges.deletePostNotes);
|
||||
privileges.canEditPostNotes = auth.hasPrivilege(auth.privileges.editPostNotes);
|
||||
privileges.canDeletePostNotes = auth.hasPrivilege(auth.privileges.deletePostNotes);
|
||||
privileges.canEditPostNotes = auth.hasPrivilege(auth.privileges.editPostNotes);
|
||||
|
||||
promise.wait(util.promiseTemplate('post-notes'))
|
||||
.then(function(postNotesTemplate) {
|
||||
templates.postNotes = postNotesTemplate;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
promise.wait(util.promiseTemplate('post-notes'))
|
||||
.then(function(postNotesTemplate) {
|
||||
templates.postNotes = postNotesTemplate;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function addNewPostNote() {
|
||||
notes.push({left: 10.0, top: 10.0, width: 10.0, height: 10.0, text: '…'});
|
||||
}
|
||||
function addNewPostNote() {
|
||||
notes.push({left: 10.0, top: 10.0, width: 10.0, height: 10.0, text: '…'});
|
||||
}
|
||||
|
||||
function addNewPostNoteAndRender() {
|
||||
addNewPostNote();
|
||||
render();
|
||||
}
|
||||
function addNewPostNoteAndRender() {
|
||||
addNewPostNote();
|
||||
render();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$target.html(templates.postNotes({
|
||||
privileges: privileges,
|
||||
post: post,
|
||||
notes: notes,
|
||||
util: util}));
|
||||
function render() {
|
||||
$target.html(templates.postNotes({
|
||||
privileges: privileges,
|
||||
post: post,
|
||||
notes: notes,
|
||||
util: util}));
|
||||
|
||||
$form = $target.find('.post-note-edit');
|
||||
var $postNotes = $target.find('.post-note');
|
||||
$form = $target.find('.post-note-edit');
|
||||
var $postNotes = $target.find('.post-note');
|
||||
|
||||
$postNotes.each(function(i) {
|
||||
var postNote = notes[i];
|
||||
var $postNote = jQuery(this);
|
||||
$postNote.data('postNote', postNote);
|
||||
$postNote.find('.text-wrapper').click(postNoteClicked);
|
||||
postNote.$element = $postNote;
|
||||
draggable.makeDraggable($postNote, draggable.relativeDragStrategy, true);
|
||||
resizable.makeResizable($postNote, true);
|
||||
});
|
||||
$postNotes.each(function(i) {
|
||||
var postNote = notes[i];
|
||||
var $postNote = jQuery(this);
|
||||
$postNote.data('postNote', postNote);
|
||||
$postNote.find('.text-wrapper').click(postNoteClicked);
|
||||
postNote.$element = $postNote;
|
||||
draggable.makeDraggable($postNote, draggable.relativeDragStrategy, true);
|
||||
resizable.makeResizable($postNote, true);
|
||||
});
|
||||
|
||||
$form.find('button').click(formSubmitted);
|
||||
}
|
||||
$form.find('button').click(formSubmitted);
|
||||
}
|
||||
|
||||
function formSubmitted(e) {
|
||||
e.preventDefault();
|
||||
var $button = jQuery(e.target);
|
||||
var sender = $button.val();
|
||||
function formSubmitted(e) {
|
||||
e.preventDefault();
|
||||
var $button = jQuery(e.target);
|
||||
var sender = $button.val();
|
||||
|
||||
var postNote = $form.data('postNote');
|
||||
postNote.left = (postNote.$element.offset().left - $target.offset().left) * 100.0 / $target.outerWidth();
|
||||
postNote.top = (postNote.$element.offset().top - $target.offset().top) * 100.0 / $target.outerHeight();
|
||||
postNote.width = postNote.$element.width() * 100.0 / $target.outerWidth();
|
||||
postNote.height = postNote.$element.height() * 100.0 / $target.outerHeight();
|
||||
postNote.text = $form.find('textarea').val();
|
||||
var postNote = $form.data('postNote');
|
||||
postNote.left = (postNote.$element.offset().left - $target.offset().left) * 100.0 / $target.outerWidth();
|
||||
postNote.top = (postNote.$element.offset().top - $target.offset().top) * 100.0 / $target.outerHeight();
|
||||
postNote.width = postNote.$element.width() * 100.0 / $target.outerWidth();
|
||||
postNote.height = postNote.$element.height() * 100.0 / $target.outerHeight();
|
||||
postNote.text = $form.find('textarea').val();
|
||||
|
||||
if (sender === 'cancel') {
|
||||
hideForm();
|
||||
} else if (sender === 'remove') {
|
||||
removePostNote(postNote);
|
||||
} else if (sender === 'save') {
|
||||
savePostNote(postNote);
|
||||
} else if (sender === 'preview') {
|
||||
previewPostNote(postNote);
|
||||
}
|
||||
}
|
||||
if (sender === 'cancel') {
|
||||
hideForm();
|
||||
} else if (sender === 'remove') {
|
||||
removePostNote(postNote);
|
||||
} else if (sender === 'save') {
|
||||
savePostNote(postNote);
|
||||
} else if (sender === 'preview') {
|
||||
previewPostNote(postNote);
|
||||
}
|
||||
}
|
||||
|
||||
function removePostNote(postNote) {
|
||||
if (postNote.id) {
|
||||
if (window.confirm('Are you sure you want to delete this note?')) {
|
||||
promise.wait(api.delete('/notes/' + postNote.id))
|
||||
.then(function() {
|
||||
hideForm();
|
||||
postNote.$element.remove();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
postNote.$element.remove();
|
||||
hideForm();
|
||||
}
|
||||
}
|
||||
function removePostNote(postNote) {
|
||||
if (postNote.id) {
|
||||
if (window.confirm('Are you sure you want to delete this note?')) {
|
||||
promise.wait(api.delete('/notes/' + postNote.id))
|
||||
.then(function() {
|
||||
hideForm();
|
||||
postNote.$element.remove();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
postNote.$element.remove();
|
||||
hideForm();
|
||||
}
|
||||
}
|
||||
|
||||
function savePostNote(postNote) {
|
||||
if (window.confirm('Are you sure you want to save this note?')) {
|
||||
var formData = {
|
||||
left: postNote.left,
|
||||
top: postNote.top,
|
||||
width: postNote.width,
|
||||
height: postNote.height,
|
||||
text: postNote.text,
|
||||
};
|
||||
function savePostNote(postNote) {
|
||||
if (window.confirm('Are you sure you want to save this note?')) {
|
||||
var formData = {
|
||||
left: postNote.left,
|
||||
top: postNote.top,
|
||||
width: postNote.width,
|
||||
height: postNote.height,
|
||||
text: postNote.text,
|
||||
};
|
||||
|
||||
var p = postNote.id ?
|
||||
api.put('/notes/' + postNote.id, formData) :
|
||||
api.post('/notes/' + post.id, formData);
|
||||
var p = postNote.id ?
|
||||
api.put('/notes/' + postNote.id, formData) :
|
||||
api.post('/notes/' + post.id, formData);
|
||||
|
||||
promise.wait(p)
|
||||
.then(function(response) {
|
||||
hideForm();
|
||||
postNote.id = response.json.id;
|
||||
postNote.$element.data('postNote', postNote);
|
||||
render();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
}
|
||||
promise.wait(p)
|
||||
.then(function(response) {
|
||||
hideForm();
|
||||
postNote.id = response.json.id;
|
||||
postNote.$element.data('postNote', postNote);
|
||||
render();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function previewPostNote(postNote) {
|
||||
var previewText = $form.find('textarea').val();
|
||||
postNote.$element.find('.text').html(util.formatMarkdown(previewText));
|
||||
showPostNoteText(postNote);
|
||||
}
|
||||
function previewPostNote(postNote) {
|
||||
var previewText = $form.find('textarea').val();
|
||||
postNote.$element.find('.text').html(util.formatMarkdown(previewText));
|
||||
showPostNoteText(postNote);
|
||||
}
|
||||
|
||||
function showPostNoteText(postNote) {
|
||||
postNote.$element.find('.text-wrapper').show();
|
||||
}
|
||||
function showPostNoteText(postNote) {
|
||||
postNote.$element.find('.text-wrapper').show();
|
||||
}
|
||||
|
||||
function hidePostNoteText(postNote) {
|
||||
postNote.$element.find('.text-wrapper').css('display', '');
|
||||
}
|
||||
function hidePostNoteText(postNote) {
|
||||
postNote.$element.find('.text-wrapper').css('display', '');
|
||||
}
|
||||
|
||||
function postNoteClicked(e) {
|
||||
e.preventDefault();
|
||||
var $postNote = jQuery(e.currentTarget).parents('.post-note');
|
||||
if ($postNote.hasClass('resizing') || $postNote.hasClass('dragging')) {
|
||||
return;
|
||||
}
|
||||
showFormForPostNote($postNote);
|
||||
}
|
||||
function postNoteClicked(e) {
|
||||
e.preventDefault();
|
||||
var $postNote = jQuery(e.currentTarget).parents('.post-note');
|
||||
if ($postNote.hasClass('resizing') || $postNote.hasClass('dragging')) {
|
||||
return;
|
||||
}
|
||||
showFormForPostNote($postNote);
|
||||
}
|
||||
|
||||
function showFormForPostNote($postNote) {
|
||||
hideForm();
|
||||
var postNote = $postNote.data('postNote');
|
||||
$form.data('postNote', postNote);
|
||||
$form.find('textarea').val(postNote.text);
|
||||
$form.show();
|
||||
draggable.makeDraggable($form, draggable.absoluteDragStrategy, false);
|
||||
}
|
||||
function showFormForPostNote($postNote) {
|
||||
hideForm();
|
||||
var postNote = $postNote.data('postNote');
|
||||
$form.data('postNote', postNote);
|
||||
$form.find('textarea').val(postNote.text);
|
||||
$form.show();
|
||||
draggable.makeDraggable($form, draggable.absoluteDragStrategy, false);
|
||||
}
|
||||
|
||||
function hideForm() {
|
||||
var previousPostNote = $form.data('post-note');
|
||||
if (previousPostNote) {
|
||||
hidePostNoteText(previousPostNote);
|
||||
}
|
||||
$form.hide();
|
||||
}
|
||||
function hideForm() {
|
||||
var previousPostNote = $form.data('post-note');
|
||||
if (previousPostNote) {
|
||||
hidePostNoteText(previousPostNote);
|
||||
}
|
||||
$form.hide();
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
addNewPostNote: addNewPostNoteAndRender,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
addNewPostNote: addNewPostNoteAndRender,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
App.DI.register('postNotesPresenter', [
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'api',
|
||||
'auth',
|
||||
'draggable',
|
||||
'resizable'],
|
||||
App.Presenters.PostNotesPresenter);
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'api',
|
||||
'auth',
|
||||
'draggable',
|
||||
'resizable'],
|
||||
App.Presenters.PostNotesPresenter);
|
||||
|
|
|
@ -2,349 +2,349 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.PostPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
router,
|
||||
keyboard,
|
||||
presenterManager,
|
||||
postsAroundCalculator,
|
||||
postEditPresenter,
|
||||
postContentPresenter,
|
||||
commentListPresenter,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
router,
|
||||
keyboard,
|
||||
presenterManager,
|
||||
postsAroundCalculator,
|
||||
postEditPresenter,
|
||||
postContentPresenter,
|
||||
commentListPresenter,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var $messages = $el;
|
||||
var $el = jQuery('#content');
|
||||
var $messages = $el;
|
||||
|
||||
var templates = {};
|
||||
var params;
|
||||
var templates = {};
|
||||
var params;
|
||||
|
||||
var postNameOrId;
|
||||
var post;
|
||||
var postNameOrId;
|
||||
var post;
|
||||
|
||||
var privileges = {};
|
||||
var privileges = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('posts');
|
||||
postsAroundCalculator.resetCache();
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('posts');
|
||||
postsAroundCalculator.resetCache();
|
||||
|
||||
privileges.canDeletePosts = auth.hasPrivilege(auth.privileges.deletePosts);
|
||||
privileges.canFeaturePosts = auth.hasPrivilege(auth.privileges.featurePosts);
|
||||
privileges.canViewHistory = auth.hasPrivilege(auth.privileges.viewHistory);
|
||||
privileges.canAddPostNotes = auth.hasPrivilege(auth.privileges.addPostNotes);
|
||||
privileges.canDeletePosts = auth.hasPrivilege(auth.privileges.deletePosts);
|
||||
privileges.canFeaturePosts = auth.hasPrivilege(auth.privileges.featurePosts);
|
||||
privileges.canViewHistory = auth.hasPrivilege(auth.privileges.viewHistory);
|
||||
privileges.canAddPostNotes = auth.hasPrivilege(auth.privileges.addPostNotes);
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('post'),
|
||||
util.promiseTemplate('history'))
|
||||
.then(function(
|
||||
postTemplate,
|
||||
historyTemplate) {
|
||||
templates.post = postTemplate;
|
||||
templates.history = historyTemplate;
|
||||
promise.wait(
|
||||
util.promiseTemplate('post'),
|
||||
util.promiseTemplate('history'))
|
||||
.then(function(
|
||||
postTemplate,
|
||||
historyTemplate) {
|
||||
templates.post = postTemplate;
|
||||
templates.history = historyTemplate;
|
||||
|
||||
reinit(params, loaded);
|
||||
}).fail(function(response) {
|
||||
showGenericError(response);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
reinit(params, loaded);
|
||||
}).fail(function(response) {
|
||||
showGenericError(response);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
params.query.page = parseInt(params.query.page) || 1;
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
params.query.page = parseInt(params.query.page) || 1;
|
||||
|
||||
postNameOrId = params.postNameOrId;
|
||||
postNameOrId = params.postNameOrId;
|
||||
|
||||
promise.wait(refreshPost())
|
||||
.then(function() {
|
||||
topNavigationPresenter.changeTitle('@' + post.id);
|
||||
render();
|
||||
loaded();
|
||||
promise.wait(refreshPost())
|
||||
.then(function() {
|
||||
topNavigationPresenter.changeTitle('@' + post.id);
|
||||
render();
|
||||
loaded();
|
||||
|
||||
presenterManager.initPresenters([
|
||||
[postContentPresenter, {post: post, $target: $el.find('#post-content-target')}],
|
||||
[postEditPresenter, {post: post, $target: $el.find('#post-edit-target'), updateCallback: postEdited}],
|
||||
[commentListPresenter, {post: post, $target: $el.find('#post-comments-target')}]],
|
||||
function() { });
|
||||
presenterManager.initPresenters([
|
||||
[postContentPresenter, {post: post, $target: $el.find('#post-content-target')}],
|
||||
[postEditPresenter, {post: post, $target: $el.find('#post-edit-target'), updateCallback: postEdited}],
|
||||
[commentListPresenter, {post: post, $target: $el.find('#post-comments-target')}]],
|
||||
function() { });
|
||||
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function attachLinksToPostsAround() {
|
||||
promise.wait(postsAroundCalculator.getLinksToPostsAround(params.query, post.id))
|
||||
.then(function(nextPostUrl, prevPostUrl) {
|
||||
var $prevPost = $el.find('#post-current-search .right a');
|
||||
var $nextPost = $el.find('#post-current-search .left a');
|
||||
function attachLinksToPostsAround() {
|
||||
promise.wait(postsAroundCalculator.getLinksToPostsAround(params.query, post.id))
|
||||
.then(function(nextPostUrl, prevPostUrl) {
|
||||
var $prevPost = $el.find('#post-current-search .right a');
|
||||
var $nextPost = $el.find('#post-current-search .left a');
|
||||
|
||||
if (nextPostUrl) {
|
||||
$nextPost.addClass('enabled');
|
||||
$nextPost.attr('href', nextPostUrl);
|
||||
keyboard.keyup('a', function() {
|
||||
router.navigate(nextPostUrl);
|
||||
});
|
||||
} else {
|
||||
$nextPost.removeClass('enabled');
|
||||
$nextPost.removeAttr('href');
|
||||
keyboard.unbind('a');
|
||||
}
|
||||
if (nextPostUrl) {
|
||||
$nextPost.addClass('enabled');
|
||||
$nextPost.attr('href', nextPostUrl);
|
||||
keyboard.keyup('a', function() {
|
||||
router.navigate(nextPostUrl);
|
||||
});
|
||||
} else {
|
||||
$nextPost.removeClass('enabled');
|
||||
$nextPost.removeAttr('href');
|
||||
keyboard.unbind('a');
|
||||
}
|
||||
|
||||
if (prevPostUrl) {
|
||||
$prevPost.addClass('enabled');
|
||||
$prevPost.attr('href', prevPostUrl);
|
||||
keyboard.keyup('d', function() {
|
||||
router.navigate(prevPostUrl);
|
||||
});
|
||||
} else {
|
||||
$prevPost.removeClass('enabled');
|
||||
$prevPost.removeAttr('href');
|
||||
keyboard.unbind('d');
|
||||
}
|
||||
}).fail(function() {
|
||||
});
|
||||
}
|
||||
if (prevPostUrl) {
|
||||
$prevPost.addClass('enabled');
|
||||
$prevPost.attr('href', prevPostUrl);
|
||||
keyboard.keyup('d', function() {
|
||||
router.navigate(prevPostUrl);
|
||||
});
|
||||
} else {
|
||||
$prevPost.removeClass('enabled');
|
||||
$prevPost.removeAttr('href');
|
||||
keyboard.unbind('d');
|
||||
}
|
||||
}).fail(function() {
|
||||
});
|
||||
}
|
||||
|
||||
function refreshPost() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.get('/posts/' + postNameOrId))
|
||||
.then(function(postResponse) {
|
||||
post = postResponse.json;
|
||||
resolve();
|
||||
}).fail(function(response) {
|
||||
showGenericError(response);
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
function refreshPost() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
promise.wait(api.get('/posts/' + postNameOrId))
|
||||
.then(function(postResponse) {
|
||||
post = postResponse.json;
|
||||
resolve();
|
||||
}).fail(function(response) {
|
||||
showGenericError(response);
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(renderPostTemplate());
|
||||
$messages = $el.find('.messages');
|
||||
function render() {
|
||||
$el.html(renderPostTemplate());
|
||||
$messages = $el.find('.messages');
|
||||
|
||||
keyboard.keyup('e', function() {
|
||||
editButtonClicked(null);
|
||||
});
|
||||
keyboard.keyup('e', function() {
|
||||
editButtonClicked(null);
|
||||
});
|
||||
|
||||
keyboard.keyup('f', function() {
|
||||
var $wrapper = $el.find('.object-wrapper');
|
||||
if ($wrapper.data('full')) {
|
||||
$wrapper.css({maxWidth: $wrapper.attr('data-width') + 'px', width: 'auto'});
|
||||
$wrapper.data('full', false);
|
||||
} else {
|
||||
$wrapper.css({maxWidth: null, width: $wrapper.attr('data-width')});
|
||||
$wrapper.data('full', true);
|
||||
}
|
||||
postContentPresenter.updatePostNotesSize();
|
||||
});
|
||||
keyboard.keyup('f', function() {
|
||||
var $wrapper = $el.find('.object-wrapper');
|
||||
if ($wrapper.data('full')) {
|
||||
$wrapper.css({maxWidth: $wrapper.attr('data-width') + 'px', width: 'auto'});
|
||||
$wrapper.data('full', false);
|
||||
} else {
|
||||
$wrapper.css({maxWidth: null, width: $wrapper.attr('data-width')});
|
||||
$wrapper.data('full', true);
|
||||
}
|
||||
postContentPresenter.updatePostNotesSize();
|
||||
});
|
||||
|
||||
attachSidebarEvents();
|
||||
attachSidebarEvents();
|
||||
|
||||
attachLinksToPostsAround();
|
||||
}
|
||||
attachLinksToPostsAround();
|
||||
}
|
||||
|
||||
function postEdited(newPost) {
|
||||
post = newPost;
|
||||
hideEditForm();
|
||||
softRender();
|
||||
}
|
||||
function postEdited(newPost) {
|
||||
post = newPost;
|
||||
hideEditForm();
|
||||
softRender();
|
||||
}
|
||||
|
||||
function softRender() {
|
||||
renderSidebar();
|
||||
$el.find('video').prop('loop', post.flags.loop);
|
||||
}
|
||||
function softRender() {
|
||||
renderSidebar();
|
||||
$el.find('video').prop('loop', post.flags.loop);
|
||||
}
|
||||
|
||||
function renderSidebar() {
|
||||
$el.find('#sidebar').html(jQuery(renderPostTemplate()).find('#sidebar').html());
|
||||
attachSidebarEvents();
|
||||
}
|
||||
function renderSidebar() {
|
||||
$el.find('#sidebar').html(jQuery(renderPostTemplate()).find('#sidebar').html());
|
||||
attachSidebarEvents();
|
||||
}
|
||||
|
||||
function renderPostTemplate() {
|
||||
return templates.post({
|
||||
query: params.query,
|
||||
post: post,
|
||||
ownScore: post.ownScore,
|
||||
postFavorites: post.favorites,
|
||||
postHistory: post.history,
|
||||
function renderPostTemplate() {
|
||||
return templates.post({
|
||||
query: params.query,
|
||||
post: post,
|
||||
ownScore: post.ownScore,
|
||||
postFavorites: post.favorites,
|
||||
postHistory: post.history,
|
||||
|
||||
util: util,
|
||||
util: util,
|
||||
|
||||
historyTemplate: templates.history,
|
||||
historyTemplate: templates.history,
|
||||
|
||||
hasFav: _.any(post.favorites, function(favUser) { return favUser.id === auth.getCurrentUser().id; }),
|
||||
isLoggedIn: auth.isLoggedIn(),
|
||||
privileges: privileges,
|
||||
editPrivileges: postEditPresenter.getPrivileges(),
|
||||
});
|
||||
}
|
||||
hasFav: _.any(post.favorites, function(favUser) { return favUser.id === auth.getCurrentUser().id; }),
|
||||
isLoggedIn: auth.isLoggedIn(),
|
||||
privileges: privileges,
|
||||
editPrivileges: postEditPresenter.getPrivileges(),
|
||||
});
|
||||
}
|
||||
|
||||
function attachSidebarEvents() {
|
||||
$el.find('#sidebar .delete').click(deleteButtonClicked);
|
||||
$el.find('#sidebar .feature').click(featureButtonClicked);
|
||||
$el.find('#sidebar .edit').click(editButtonClicked);
|
||||
$el.find('#sidebar .history').click(historyButtonClicked);
|
||||
$el.find('#sidebar .add-favorite').click(addFavoriteButtonClicked);
|
||||
$el.find('#sidebar .delete-favorite').click(deleteFavoriteButtonClicked);
|
||||
$el.find('#sidebar .score-up').click(scoreUpButtonClicked);
|
||||
$el.find('#sidebar .score-down').click(scoreDownButtonClicked);
|
||||
$el.find('#sidebar .add-note').click(addNoteButtonClicked);
|
||||
}
|
||||
function attachSidebarEvents() {
|
||||
$el.find('#sidebar .delete').click(deleteButtonClicked);
|
||||
$el.find('#sidebar .feature').click(featureButtonClicked);
|
||||
$el.find('#sidebar .edit').click(editButtonClicked);
|
||||
$el.find('#sidebar .history').click(historyButtonClicked);
|
||||
$el.find('#sidebar .add-favorite').click(addFavoriteButtonClicked);
|
||||
$el.find('#sidebar .delete-favorite').click(deleteFavoriteButtonClicked);
|
||||
$el.find('#sidebar .score-up').click(scoreUpButtonClicked);
|
||||
$el.find('#sidebar .score-down').click(scoreDownButtonClicked);
|
||||
$el.find('#sidebar .add-note').click(addNoteButtonClicked);
|
||||
}
|
||||
|
||||
function addNoteButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
postContentPresenter.addNewPostNote();
|
||||
}
|
||||
function addNoteButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
postContentPresenter.addNewPostNote();
|
||||
}
|
||||
|
||||
function deleteButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
if (window.confirm('Do you really want to delete this post?')) {
|
||||
deletePost();
|
||||
}
|
||||
}
|
||||
function deleteButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
if (window.confirm('Do you really want to delete this post?')) {
|
||||
deletePost();
|
||||
}
|
||||
}
|
||||
|
||||
function deletePost() {
|
||||
promise.wait(api.delete('/posts/' + post.id))
|
||||
.then(function(response) {
|
||||
router.navigate('#/posts');
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
function deletePost() {
|
||||
promise.wait(api.delete('/posts/' + post.id))
|
||||
.then(function(response) {
|
||||
router.navigate('#/posts');
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
|
||||
function featureButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
if (window.confirm('Do you want to feature this post on the front page?')) {
|
||||
featurePost();
|
||||
}
|
||||
}
|
||||
function featureButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
if (window.confirm('Do you want to feature this post on the front page?')) {
|
||||
featurePost();
|
||||
}
|
||||
}
|
||||
|
||||
function featurePost() {
|
||||
promise.wait(api.post('/posts/' + post.id + '/feature'))
|
||||
.then(function(response) {
|
||||
router.navigate('#/home');
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
function featurePost() {
|
||||
promise.wait(api.post('/posts/' + post.id + '/feature'))
|
||||
.then(function(response) {
|
||||
router.navigate('#/home');
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
|
||||
function editButtonClicked(e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
messagePresenter.hideMessages($messages);
|
||||
if ($el.find('#post-edit-target').is(':visible')) {
|
||||
hideEditForm();
|
||||
} else {
|
||||
showEditForm();
|
||||
}
|
||||
}
|
||||
function editButtonClicked(e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
messagePresenter.hideMessages($messages);
|
||||
if ($el.find('#post-edit-target').is(':visible')) {
|
||||
hideEditForm();
|
||||
} else {
|
||||
showEditForm();
|
||||
}
|
||||
}
|
||||
|
||||
function showEditForm() {
|
||||
$el.find('#post-edit-target').slideDown('fast');
|
||||
util.enableExitConfirmation();
|
||||
postEditPresenter.focus();
|
||||
}
|
||||
function showEditForm() {
|
||||
$el.find('#post-edit-target').slideDown('fast');
|
||||
util.enableExitConfirmation();
|
||||
postEditPresenter.focus();
|
||||
}
|
||||
|
||||
function hideEditForm() {
|
||||
$el.find('#post-edit-target').slideUp('fast');
|
||||
util.disableExitConfirmation();
|
||||
}
|
||||
function hideEditForm() {
|
||||
$el.find('#post-edit-target').slideUp('fast');
|
||||
util.disableExitConfirmation();
|
||||
}
|
||||
|
||||
function historyButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
if ($el.find('.post-history-wrapper').is(':visible')) {
|
||||
hideHistory();
|
||||
} else {
|
||||
showHistory();
|
||||
}
|
||||
}
|
||||
function historyButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
if ($el.find('.post-history-wrapper').is(':visible')) {
|
||||
hideHistory();
|
||||
} else {
|
||||
showHistory();
|
||||
}
|
||||
}
|
||||
|
||||
function hideHistory() {
|
||||
$el.find('.post-history-wrapper').slideUp('slow');
|
||||
}
|
||||
function hideHistory() {
|
||||
$el.find('.post-history-wrapper').slideUp('slow');
|
||||
}
|
||||
|
||||
function showHistory() {
|
||||
$el.find('.post-history-wrapper').slideDown('slow');
|
||||
}
|
||||
function showHistory() {
|
||||
$el.find('.post-history-wrapper').slideDown('slow');
|
||||
}
|
||||
|
||||
function addFavoriteButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
addFavorite();
|
||||
}
|
||||
function addFavoriteButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
addFavorite();
|
||||
}
|
||||
|
||||
function deleteFavoriteButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
deleteFavorite();
|
||||
}
|
||||
function deleteFavoriteButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
deleteFavorite();
|
||||
}
|
||||
|
||||
function addFavorite() {
|
||||
promise.wait(api.post('/posts/' + post.id + '/favorites'))
|
||||
.then(function(response) {
|
||||
promise.wait(refreshPost()).then(softRender);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
function addFavorite() {
|
||||
promise.wait(api.post('/posts/' + post.id + '/favorites'))
|
||||
.then(function(response) {
|
||||
promise.wait(refreshPost()).then(softRender);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
|
||||
function deleteFavorite() {
|
||||
promise.wait(api.delete('/posts/' + post.id + '/favorites'))
|
||||
.then(function(response) {
|
||||
promise.wait(refreshPost()).then(softRender);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
function deleteFavorite() {
|
||||
promise.wait(api.delete('/posts/' + post.id + '/favorites'))
|
||||
.then(function(response) {
|
||||
promise.wait(refreshPost()).then(softRender);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
|
||||
function scoreUpButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var $target = jQuery(this);
|
||||
score($target.hasClass('active') ? 0 : 1);
|
||||
}
|
||||
function scoreUpButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var $target = jQuery(this);
|
||||
score($target.hasClass('active') ? 0 : 1);
|
||||
}
|
||||
|
||||
function scoreDownButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var $target = jQuery(this);
|
||||
score($target.hasClass('active') ? 0 : -1);
|
||||
}
|
||||
function scoreDownButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var $target = jQuery(this);
|
||||
score($target.hasClass('active') ? 0 : -1);
|
||||
}
|
||||
|
||||
function score(scoreValue) {
|
||||
promise.wait(api.post('/posts/' + post.id + '/score', {score: scoreValue}))
|
||||
.then(function() {
|
||||
promise.wait(refreshPost()).then(softRender);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
function score(scoreValue) {
|
||||
promise.wait(api.post('/posts/' + post.id + '/score', {score: scoreValue}))
|
||||
.then(function() {
|
||||
promise.wait(refreshPost()).then(softRender);
|
||||
}).fail(showGenericError);
|
||||
}
|
||||
|
||||
function showGenericError(response) {
|
||||
if ($messages === $el) {
|
||||
$el.empty();
|
||||
}
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
}
|
||||
function showGenericError(response) {
|
||||
if ($messages === $el) {
|
||||
$el.empty();
|
||||
}
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
App.DI.register('postPresenter', [
|
||||
'_',
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'api',
|
||||
'auth',
|
||||
'router',
|
||||
'keyboard',
|
||||
'presenterManager',
|
||||
'postsAroundCalculator',
|
||||
'postEditPresenter',
|
||||
'postContentPresenter',
|
||||
'commentListPresenter',
|
||||
'topNavigationPresenter',
|
||||
'messagePresenter'],
|
||||
App.Presenters.PostPresenter);
|
||||
'_',
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'api',
|
||||
'auth',
|
||||
'router',
|
||||
'keyboard',
|
||||
'presenterManager',
|
||||
'postsAroundCalculator',
|
||||
'postEditPresenter',
|
||||
'postContentPresenter',
|
||||
'commentListPresenter',
|
||||
'topNavigationPresenter',
|
||||
'messagePresenter'],
|
||||
App.Presenters.PostPresenter);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -2,43 +2,43 @@ var App = App || {};
|
|||
App.Controls = App.Controls || {};
|
||||
|
||||
App.Presenters.ProgressPresenter = function(nprogress) {
|
||||
var nesting = 0;
|
||||
var nesting = 0;
|
||||
|
||||
function start() {
|
||||
nesting ++;
|
||||
function start() {
|
||||
nesting ++;
|
||||
|
||||
if (nesting === 1) {
|
||||
nprogress.start();
|
||||
}
|
||||
}
|
||||
if (nesting === 1) {
|
||||
nprogress.start();
|
||||
}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
nesting = 0;
|
||||
}
|
||||
function reset() {
|
||||
nesting = 0;
|
||||
}
|
||||
|
||||
function done() {
|
||||
if (nesting) {
|
||||
nesting --;
|
||||
}
|
||||
function done() {
|
||||
if (nesting) {
|
||||
nesting --;
|
||||
}
|
||||
|
||||
if (nesting <= 0) {
|
||||
nprogress.done();
|
||||
} else {
|
||||
nprogress.inc();
|
||||
}
|
||||
}
|
||||
if (nesting <= 0) {
|
||||
nprogress.done();
|
||||
} else {
|
||||
nprogress.inc();
|
||||
}
|
||||
}
|
||||
|
||||
window.setInterval(function() {
|
||||
if (nesting <= 0) {
|
||||
nprogress.done();
|
||||
}
|
||||
}, 1000);
|
||||
window.setInterval(function() {
|
||||
if (nesting <= 0) {
|
||||
nprogress.done();
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
return {
|
||||
start: start,
|
||||
done: done,
|
||||
reset: reset,
|
||||
};
|
||||
return {
|
||||
start: start,
|
||||
done: done,
|
||||
reset: reset,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,100 +2,100 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.RegistrationPresenter = function(
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var $messages;
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var $messages;
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('register');
|
||||
topNavigationPresenter.changeTitle('Registration');
|
||||
promise.wait(util.promiseTemplate('registration-form'))
|
||||
.then(function(template) {
|
||||
templates.registration = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('register');
|
||||
topNavigationPresenter.changeTitle('Registration');
|
||||
promise.wait(util.promiseTemplate('registration-form'))
|
||||
.then(function(template) {
|
||||
templates.registration = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.registration());
|
||||
$el.find('form').submit(registrationFormSubmitted);
|
||||
$messages = $el.find('.messages');
|
||||
$messages.width($el.find('form').width());
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.registration());
|
||||
$el.find('form').submit(registrationFormSubmitted);
|
||||
$messages = $el.find('.messages');
|
||||
$messages.width($el.find('form').width());
|
||||
}
|
||||
|
||||
function registrationFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
function registrationFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
|
||||
var formData = {
|
||||
userName: $el.find('[name=userName]').val(),
|
||||
password: $el.find('[name=password]').val(),
|
||||
passwordConfirmation: $el.find('[name=passwordConfirmation]').val(),
|
||||
email: $el.find('[name=email]').val(),
|
||||
};
|
||||
var formData = {
|
||||
userName: $el.find('[name=userName]').val(),
|
||||
password: $el.find('[name=password]').val(),
|
||||
passwordConfirmation: $el.find('[name=passwordConfirmation]').val(),
|
||||
email: $el.find('[name=email]').val(),
|
||||
};
|
||||
|
||||
if (!validateRegistrationFormData(formData)) {
|
||||
return;
|
||||
}
|
||||
if (!validateRegistrationFormData(formData)) {
|
||||
return;
|
||||
}
|
||||
|
||||
promise.wait(api.post('/users', formData))
|
||||
.then(function(response) {
|
||||
registrationSuccess(response);
|
||||
}).fail(function(response) {
|
||||
registrationFailure(response);
|
||||
});
|
||||
}
|
||||
promise.wait(api.post('/users', formData))
|
||||
.then(function(response) {
|
||||
registrationSuccess(response);
|
||||
}).fail(function(response) {
|
||||
registrationFailure(response);
|
||||
});
|
||||
}
|
||||
|
||||
function registrationSuccess(apiResponse) {
|
||||
$el.find('form').slideUp(function() {
|
||||
var message = 'Registration complete! ';
|
||||
if (!apiResponse.json.confirmed) {
|
||||
message += '<br/>Check your inbox for activation e-mail.<br/>If e-mail doesn\'t show up, check your spam folder.';
|
||||
} else {
|
||||
message += '<a href="#/login">Click here</a> to login.';
|
||||
}
|
||||
messagePresenter.showInfo($messages, message);
|
||||
});
|
||||
}
|
||||
function registrationSuccess(apiResponse) {
|
||||
$el.find('form').slideUp(function() {
|
||||
var message = 'Registration complete! ';
|
||||
if (!apiResponse.json.confirmed) {
|
||||
message += '<br/>Check your inbox for activation e-mail.<br/>If e-mail doesn\'t show up, check your spam folder.';
|
||||
} else {
|
||||
message += '<a href="#/login">Click here</a> to login.';
|
||||
}
|
||||
messagePresenter.showInfo($messages, message);
|
||||
});
|
||||
}
|
||||
|
||||
function registrationFailure(apiResponse) {
|
||||
messagePresenter.showError($messages, apiResponse.json && apiResponse.json.error || apiResponse);
|
||||
}
|
||||
function registrationFailure(apiResponse) {
|
||||
messagePresenter.showError($messages, apiResponse.json && apiResponse.json.error || apiResponse);
|
||||
}
|
||||
|
||||
function validateRegistrationFormData(formData) {
|
||||
if (formData.userName.length === 0) {
|
||||
messagePresenter.showError($messages, 'User name cannot be empty.');
|
||||
return false;
|
||||
}
|
||||
function validateRegistrationFormData(formData) {
|
||||
if (formData.userName.length === 0) {
|
||||
messagePresenter.showError($messages, 'User name cannot be empty.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (formData.password.length === 0) {
|
||||
messagePresenter.showError($messages, 'Password cannot be empty.');
|
||||
return false;
|
||||
}
|
||||
if (formData.password.length === 0) {
|
||||
messagePresenter.showError($messages, 'Password cannot be empty.');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (formData.password !== formData.passwordConfirmation) {
|
||||
messagePresenter.showError($messages, 'Passwords must be the same.');
|
||||
return false;
|
||||
}
|
||||
if (formData.password !== formData.passwordConfirmation) {
|
||||
messagePresenter.showError($messages, 'Passwords must be the same.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,124 +2,124 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.TagListPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
keyboard,
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
keyboard,
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var $searchInput;
|
||||
var templates = {};
|
||||
var $el = jQuery('#content');
|
||||
var $searchInput;
|
||||
var templates = {};
|
||||
|
||||
var params;
|
||||
var params;
|
||||
|
||||
function init(_params, loaded) {
|
||||
topNavigationPresenter.select('tags');
|
||||
topNavigationPresenter.changeTitle('Tags');
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
function init(_params, loaded) {
|
||||
topNavigationPresenter.select('tags');
|
||||
topNavigationPresenter.changeTitle('Tags');
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('tag-list'),
|
||||
util.promiseTemplate('tag-list-item'))
|
||||
.then(function(listTemplate, listItemTemplate) {
|
||||
templates.list = listTemplate;
|
||||
templates.listItem = listItemTemplate;
|
||||
promise.wait(
|
||||
util.promiseTemplate('tag-list'),
|
||||
util.promiseTemplate('tag-list-item'))
|
||||
.then(function(listTemplate, listItemTemplate) {
|
||||
templates.list = listTemplate;
|
||||
templates.listItem = listItemTemplate;
|
||||
|
||||
render();
|
||||
loaded();
|
||||
render();
|
||||
loaded();
|
||||
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/tags',
|
||||
backendUri: '/tags',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderTags($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/tags',
|
||||
backendUri: '/tags',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderTags($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
params.query.order = params.query.order || 'name,asc';
|
||||
updateActiveOrder(params.query.order);
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
params.query.order = params.query.order || 'name,asc';
|
||||
updateActiveOrder(params.query.order);
|
||||
|
||||
pagerPresenter.reinit({query: params.query});
|
||||
pagerPresenter.reinit({query: params.query});
|
||||
|
||||
keyboard.keyup('p', function() {
|
||||
$el.find('table a').eq(0).focus();
|
||||
});
|
||||
keyboard.keyup('p', function() {
|
||||
$el.find('table a').eq(0).focus();
|
||||
});
|
||||
|
||||
keyboard.keyup('q', function() {
|
||||
$searchInput.eq(0).focus().select();
|
||||
});
|
||||
keyboard.keyup('q', function() {
|
||||
$searchInput.eq(0).focus().select();
|
||||
});
|
||||
|
||||
loaded();
|
||||
softRender();
|
||||
}
|
||||
loaded();
|
||||
softRender();
|
||||
}
|
||||
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
}
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.list());
|
||||
$searchInput = $el.find('input[name=query]');
|
||||
$el.find('form').submit(searchFormSubmitted);
|
||||
App.Controls.AutoCompleteInput($searchInput);
|
||||
softRender();
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.list());
|
||||
$searchInput = $el.find('input[name=query]');
|
||||
$el.find('form').submit(searchFormSubmitted);
|
||||
App.Controls.AutoCompleteInput($searchInput);
|
||||
softRender();
|
||||
}
|
||||
|
||||
function softRender() {
|
||||
$searchInput.val(params.query.query);
|
||||
}
|
||||
function softRender() {
|
||||
$searchInput.val(params.query.query);
|
||||
}
|
||||
|
||||
|
||||
function searchFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
updateSearch();
|
||||
}
|
||||
function searchFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
updateSearch();
|
||||
}
|
||||
|
||||
function updateSearch() {
|
||||
$searchInput.blur();
|
||||
params.query.query = $searchInput.val().trim();
|
||||
params.query.page = 1;
|
||||
pagerPresenter.setQuery(params.query);
|
||||
}
|
||||
function updateSearch() {
|
||||
$searchInput.blur();
|
||||
params.query.query = $searchInput.val().trim();
|
||||
params.query.page = 1;
|
||||
pagerPresenter.setQuery(params.query);
|
||||
}
|
||||
|
||||
function updateActiveOrder(activeOrder) {
|
||||
$el.find('.order li a.active').removeClass('active');
|
||||
$el.find('.order [href*="' + activeOrder + '"]').addClass('active');
|
||||
}
|
||||
function updateActiveOrder(activeOrder) {
|
||||
$el.find('.order li a.active').removeClass('active');
|
||||
$el.find('.order [href*="' + activeOrder + '"]').addClass('active');
|
||||
}
|
||||
|
||||
function renderTags($page, tags) {
|
||||
var $target = $page.find('tbody');
|
||||
_.each(tags, function(tag) {
|
||||
var $item = jQuery(templates.listItem({
|
||||
tag: tag,
|
||||
util: util,
|
||||
}));
|
||||
$target.append($item);
|
||||
});
|
||||
}
|
||||
function renderTags($page, tags) {
|
||||
var $target = $page.find('tbody');
|
||||
_.each(tags, function(tag) {
|
||||
var $item = jQuery(templates.listItem({
|
||||
tag: tag,
|
||||
util: util,
|
||||
}));
|
||||
$target.append($item);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,199 +2,199 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.TagPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
api,
|
||||
tagList,
|
||||
router,
|
||||
keyboard,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
api,
|
||||
tagList,
|
||||
router,
|
||||
keyboard,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var $messages = $el;
|
||||
var templates = {};
|
||||
var implicationsTagInput;
|
||||
var suggestionsTagInput;
|
||||
var $el = jQuery('#content');
|
||||
var $messages = $el;
|
||||
var templates = {};
|
||||
var implicationsTagInput;
|
||||
var suggestionsTagInput;
|
||||
|
||||
var tag;
|
||||
var posts;
|
||||
var siblings;
|
||||
var tag;
|
||||
var posts;
|
||||
var siblings;
|
||||
|
||||
var privileges = {};
|
||||
var privileges = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('tags');
|
||||
topNavigationPresenter.changeTitle('Tags');
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('tags');
|
||||
topNavigationPresenter.changeTitle('Tags');
|
||||
|
||||
privileges.canChangeName = auth.hasPrivilege(auth.privileges.changeTagName);
|
||||
privileges.canChangeCategory = auth.hasPrivilege(auth.privileges.changeTagCategory);
|
||||
privileges.canChangeImplications = auth.hasPrivilege(auth.privileges.changeTagImplications);
|
||||
privileges.canChangeSuggestions = auth.hasPrivilege(auth.privileges.changeTagSuggestions);
|
||||
privileges.canBan = auth.hasPrivilege(auth.privileges.banTags);
|
||||
privileges.canViewHistory = auth.hasPrivilege(auth.privileges.viewHistory);
|
||||
privileges.canDelete = auth.hasPrivilege(auth.privileges.deleteTags);
|
||||
privileges.canMerge = auth.hasPrivilege(auth.privileges.mergeTags);
|
||||
privileges.canViewPosts = auth.hasPrivilege(auth.privileges.viewPosts);
|
||||
privileges.canChangeName = auth.hasPrivilege(auth.privileges.changeTagName);
|
||||
privileges.canChangeCategory = auth.hasPrivilege(auth.privileges.changeTagCategory);
|
||||
privileges.canChangeImplications = auth.hasPrivilege(auth.privileges.changeTagImplications);
|
||||
privileges.canChangeSuggestions = auth.hasPrivilege(auth.privileges.changeTagSuggestions);
|
||||
privileges.canBan = auth.hasPrivilege(auth.privileges.banTags);
|
||||
privileges.canViewHistory = auth.hasPrivilege(auth.privileges.viewHistory);
|
||||
privileges.canDelete = auth.hasPrivilege(auth.privileges.deleteTags);
|
||||
privileges.canMerge = auth.hasPrivilege(auth.privileges.mergeTags);
|
||||
privileges.canViewPosts = auth.hasPrivilege(auth.privileges.viewPosts);
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('tag'),
|
||||
util.promiseTemplate('post-list-item'),
|
||||
util.promiseTemplate('history'))
|
||||
.then(function(tagTemplate, postListItemTemplate, historyTemplate) {
|
||||
templates.tag = tagTemplate;
|
||||
templates.postListItem = postListItemTemplate;
|
||||
templates.history = historyTemplate;
|
||||
promise.wait(
|
||||
util.promiseTemplate('tag'),
|
||||
util.promiseTemplate('post-list-item'),
|
||||
util.promiseTemplate('history'))
|
||||
.then(function(tagTemplate, postListItemTemplate, historyTemplate) {
|
||||
templates.tag = tagTemplate;
|
||||
templates.postListItem = postListItemTemplate;
|
||||
templates.history = historyTemplate;
|
||||
|
||||
reinit(params, loaded);
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
reinit(params, loaded);
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function reinit(params, loaded) {
|
||||
var tagName = params.tagName;
|
||||
function reinit(params, loaded) {
|
||||
var tagName = params.tagName;
|
||||
|
||||
messagePresenter.hideMessages($messages);
|
||||
messagePresenter.hideMessages($messages);
|
||||
|
||||
promise.wait(
|
||||
api.get('tags/' + tagName),
|
||||
api.get('tags/' + tagName + '/siblings'),
|
||||
api.get('posts', {query: tagName}))
|
||||
.then(function(tagResponse, siblingsResponse, postsResponse) {
|
||||
tag = tagResponse.json;
|
||||
siblings = siblingsResponse.json.data;
|
||||
posts = postsResponse.json.data;
|
||||
posts = posts.slice(0, 8);
|
||||
promise.wait(
|
||||
api.get('tags/' + tagName),
|
||||
api.get('tags/' + tagName + '/siblings'),
|
||||
api.get('posts', {query: tagName}))
|
||||
.then(function(tagResponse, siblingsResponse, postsResponse) {
|
||||
tag = tagResponse.json;
|
||||
siblings = siblingsResponse.json.data;
|
||||
posts = postsResponse.json.data;
|
||||
posts = posts.slice(0, 8);
|
||||
|
||||
render();
|
||||
loaded();
|
||||
render();
|
||||
loaded();
|
||||
|
||||
renderPosts(posts);
|
||||
}).fail(function(tagResponse, siblingsResponse, postsResponse) {
|
||||
messagePresenter.showError($messages, tagResponse.json.error || siblingsResponse.json.error || postsResponse.json.error);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
renderPosts(posts);
|
||||
}).fail(function(tagResponse, siblingsResponse, postsResponse) {
|
||||
messagePresenter.showError($messages, tagResponse.json.error || siblingsResponse.json.error || postsResponse.json.error);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.tag({
|
||||
privileges: privileges,
|
||||
tag: tag,
|
||||
siblings: siblings,
|
||||
tagCategories: JSON.parse(jQuery('head').attr('data-tag-categories')),
|
||||
util: util,
|
||||
historyTemplate: templates.history,
|
||||
}));
|
||||
$el.find('.post-list').hide();
|
||||
$el.find('form').submit(function(e) { e.preventDefault(); });
|
||||
$el.find('form button[name=update]').click(updateButtonClicked);
|
||||
$el.find('form button[name=delete]').click(deleteButtonClicked);
|
||||
$el.find('form button[name=merge]').click(mergeButtonClicked);
|
||||
implicationsTagInput = App.Controls.TagInput($el.find('[name=implications]'));
|
||||
suggestionsTagInput = App.Controls.TagInput($el.find('[name=suggestions]'));
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.tag({
|
||||
privileges: privileges,
|
||||
tag: tag,
|
||||
siblings: siblings,
|
||||
tagCategories: JSON.parse(jQuery('head').attr('data-tag-categories')),
|
||||
util: util,
|
||||
historyTemplate: templates.history,
|
||||
}));
|
||||
$el.find('.post-list').hide();
|
||||
$el.find('form').submit(function(e) { e.preventDefault(); });
|
||||
$el.find('form button[name=update]').click(updateButtonClicked);
|
||||
$el.find('form button[name=delete]').click(deleteButtonClicked);
|
||||
$el.find('form button[name=merge]').click(mergeButtonClicked);
|
||||
implicationsTagInput = App.Controls.TagInput($el.find('[name=implications]'));
|
||||
suggestionsTagInput = App.Controls.TagInput($el.find('[name=suggestions]'));
|
||||
}
|
||||
|
||||
function updateButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var $form = $el.find('form');
|
||||
var formData = {};
|
||||
function updateButtonClicked(e) {
|
||||
e.preventDefault();
|
||||
var $form = $el.find('form');
|
||||
var formData = {};
|
||||
|
||||
if (privileges.canChangeName) {
|
||||
formData.name = $form.find('[name=name]').val();
|
||||
}
|
||||
if (privileges.canChangeName) {
|
||||
formData.name = $form.find('[name=name]').val();
|
||||
}
|
||||
|
||||
if (privileges.canChangeCategory) {
|
||||
formData.category = $form.find('[name=category]:checked').val();
|
||||
}
|
||||
if (privileges.canChangeCategory) {
|
||||
formData.category = $form.find('[name=category]:checked').val();
|
||||
}
|
||||
|
||||
if (privileges.canBan) {
|
||||
formData.banned = $form.find('[name=ban]').is(':checked') ? 1 : 0;
|
||||
}
|
||||
if (privileges.canBan) {
|
||||
formData.banned = $form.find('[name=ban]').is(':checked') ? 1 : 0;
|
||||
}
|
||||
|
||||
if (privileges.canChangeImplications) {
|
||||
formData.implications = implicationsTagInput.getTags().join(' ');
|
||||
}
|
||||
if (privileges.canChangeImplications) {
|
||||
formData.implications = implicationsTagInput.getTags().join(' ');
|
||||
}
|
||||
|
||||
if (privileges.canChangeSuggestions) {
|
||||
formData.suggestions = suggestionsTagInput.getTags().join(' ');
|
||||
}
|
||||
if (privileges.canChangeSuggestions) {
|
||||
formData.suggestions = suggestionsTagInput.getTags().join(' ');
|
||||
}
|
||||
|
||||
promise.wait(api.put('/tags/' + tag.name, formData))
|
||||
.then(function(response) {
|
||||
router.navigateInplace('#/tag/' + response.json.name);
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
}
|
||||
promise.wait(api.put('/tags/' + tag.name, formData))
|
||||
.then(function(response) {
|
||||
router.navigateInplace('#/tag/' + response.json.name);
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
}
|
||||
|
||||
function deleteButtonClicked(e) {
|
||||
if (!window.confirm('Are you sure you want to delete this tag?')) {
|
||||
return;
|
||||
}
|
||||
promise.wait(api.delete('/tags/' + tag.name))
|
||||
.then(function(response) {
|
||||
router.navigate('#/tags');
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
}
|
||||
function deleteButtonClicked(e) {
|
||||
if (!window.confirm('Are you sure you want to delete this tag?')) {
|
||||
return;
|
||||
}
|
||||
promise.wait(api.delete('/tags/' + tag.name))
|
||||
.then(function(response) {
|
||||
router.navigate('#/tags');
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
}
|
||||
|
||||
function mergeButtonClicked(e) {
|
||||
var targetTag = window.prompt('What tag should this be merged to?');
|
||||
if (targetTag) {
|
||||
promise.wait(api.put('/tags/' + tag.name + '/merge', {targetTag: targetTag}))
|
||||
.then(function(response) {
|
||||
router.navigate('#/tags');
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
}
|
||||
}
|
||||
function mergeButtonClicked(e) {
|
||||
var targetTag = window.prompt('What tag should this be merged to?');
|
||||
if (targetTag) {
|
||||
promise.wait(api.put('/tags/' + tag.name + '/merge', {targetTag: targetTag}))
|
||||
.then(function(response) {
|
||||
router.navigate('#/tags');
|
||||
tagList.refreshTags();
|
||||
}).fail(function(response) {
|
||||
window.alert(response.json && response.json.error || 'An error occured.');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function renderPosts(posts) {
|
||||
var $target = $el.find('.post-list ul');
|
||||
_.each(posts, function(post) {
|
||||
var $post = jQuery('<li>' + templates.postListItem({
|
||||
util: util,
|
||||
post: post,
|
||||
query: {query: tag.name},
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
$target.append($post);
|
||||
});
|
||||
if (posts.length > 0) {
|
||||
$el.find('.post-list').fadeIn();
|
||||
keyboard.keyup('p', function() {
|
||||
$el.find('.post-list a').eq(0).focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
function renderPosts(posts) {
|
||||
var $target = $el.find('.post-list ul');
|
||||
_.each(posts, function(post) {
|
||||
var $post = jQuery('<li>' + templates.postListItem({
|
||||
util: util,
|
||||
post: post,
|
||||
query: {query: tag.name},
|
||||
canViewPosts: privileges.canViewPosts,
|
||||
}) + '</li>');
|
||||
$target.append($post);
|
||||
});
|
||||
if (posts.length > 0) {
|
||||
$el.find('.post-list').fadeIn();
|
||||
keyboard.keyup('p', function() {
|
||||
$el.find('.post-list a').eq(0).focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
App.DI.register('tagPresenter', [
|
||||
'_',
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'auth',
|
||||
'api',
|
||||
'tagList',
|
||||
'router',
|
||||
'keyboard',
|
||||
'topNavigationPresenter',
|
||||
'messagePresenter'],
|
||||
'_',
|
||||
'jQuery',
|
||||
'util',
|
||||
'promise',
|
||||
'auth',
|
||||
'api',
|
||||
'tagList',
|
||||
'router',
|
||||
'keyboard',
|
||||
'topNavigationPresenter',
|
||||
'messagePresenter'],
|
||||
App.Presenters.TagPresenter);
|
||||
|
|
|
@ -2,78 +2,78 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.TopNavigationPresenter = function(
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth) {
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth) {
|
||||
|
||||
var selectedElement = null;
|
||||
var $el = jQuery('#top-navigation');
|
||||
var templates = {};
|
||||
var baseTitle = document.title;
|
||||
var selectedElement = null;
|
||||
var $el = jQuery('#top-navigation');
|
||||
var templates = {};
|
||||
var baseTitle = document.title;
|
||||
|
||||
function init(params, loaded) {
|
||||
promise.wait(util.promiseTemplate('top-navigation'))
|
||||
.then(function(template) {
|
||||
templates.topNavigation = template;
|
||||
render();
|
||||
loaded();
|
||||
auth.startObservingLoginChanges('top-navigation', loginStateChanged);
|
||||
}).fail(function() {
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
function init(params, loaded) {
|
||||
promise.wait(util.promiseTemplate('top-navigation'))
|
||||
.then(function(template) {
|
||||
templates.topNavigation = template;
|
||||
render();
|
||||
loaded();
|
||||
auth.startObservingLoginChanges('top-navigation', loginStateChanged);
|
||||
}).fail(function() {
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function select(newSelectedElement) {
|
||||
selectedElement = newSelectedElement;
|
||||
$el.find('li a').removeClass('active');
|
||||
$el.find('li.' + selectedElement).find('a').addClass('active');
|
||||
}
|
||||
function select(newSelectedElement) {
|
||||
selectedElement = newSelectedElement;
|
||||
$el.find('li a').removeClass('active');
|
||||
$el.find('li.' + selectedElement).find('a').addClass('active');
|
||||
}
|
||||
|
||||
function loginStateChanged() {
|
||||
render();
|
||||
}
|
||||
function loginStateChanged() {
|
||||
render();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.topNavigation({
|
||||
loggedIn: auth.isLoggedIn(),
|
||||
user: auth.getCurrentUser(),
|
||||
canListUsers: auth.hasPrivilege(auth.privileges.listUsers),
|
||||
canListPosts: auth.hasPrivilege(auth.privileges.listPosts),
|
||||
canListComments: auth.hasPrivilege(auth.privileges.listComments),
|
||||
canListTags: auth.hasPrivilege(auth.privileges.listTags),
|
||||
canUploadPosts: auth.hasPrivilege(auth.privileges.uploadPosts),
|
||||
}));
|
||||
$el.find('li.' + selectedElement).find('a').addClass('active');
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.topNavigation({
|
||||
loggedIn: auth.isLoggedIn(),
|
||||
user: auth.getCurrentUser(),
|
||||
canListUsers: auth.hasPrivilege(auth.privileges.listUsers),
|
||||
canListPosts: auth.hasPrivilege(auth.privileges.listPosts),
|
||||
canListComments: auth.hasPrivilege(auth.privileges.listComments),
|
||||
canListTags: auth.hasPrivilege(auth.privileges.listTags),
|
||||
canUploadPosts: auth.hasPrivilege(auth.privileges.uploadPosts),
|
||||
}));
|
||||
$el.find('li.' + selectedElement).find('a').addClass('active');
|
||||
}
|
||||
|
||||
function focus() {
|
||||
var $tmp = jQuery('<a href="#"> </a>');
|
||||
$el.prepend($tmp);
|
||||
$tmp.focus();
|
||||
$tmp.remove();
|
||||
}
|
||||
function focus() {
|
||||
var $tmp = jQuery('<a href="#"> </a>');
|
||||
$el.prepend($tmp);
|
||||
$tmp.focus();
|
||||
$tmp.remove();
|
||||
}
|
||||
|
||||
function getBaseTitle() {
|
||||
return baseTitle;
|
||||
}
|
||||
function getBaseTitle() {
|
||||
return baseTitle;
|
||||
}
|
||||
|
||||
function changeTitle(subTitle) {
|
||||
var newTitle = baseTitle;
|
||||
if (subTitle) {
|
||||
newTitle += ' - ' + subTitle;
|
||||
}
|
||||
document.title = newTitle;
|
||||
}
|
||||
function changeTitle(subTitle) {
|
||||
var newTitle = baseTitle;
|
||||
if (subTitle) {
|
||||
newTitle += ' - ' + subTitle;
|
||||
}
|
||||
document.title = newTitle;
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
select: select,
|
||||
focus: focus,
|
||||
getBaseTitle: getBaseTitle,
|
||||
changeTitle: changeTitle,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
select: select,
|
||||
focus: focus,
|
||||
getBaseTitle: getBaseTitle,
|
||||
changeTitle: changeTitle,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,80 +2,80 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.UserAccountRemovalPresenter = function(
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
router,
|
||||
messagePresenter) {
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
router,
|
||||
messagePresenter) {
|
||||
|
||||
var target;
|
||||
var templates = {};
|
||||
var user;
|
||||
var privileges = {};
|
||||
var target;
|
||||
var templates = {};
|
||||
var user;
|
||||
var privileges = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
user = params.user;
|
||||
target = params.target;
|
||||
function init(params, loaded) {
|
||||
user = params.user;
|
||||
target = params.target;
|
||||
|
||||
privileges.canDeleteAccount =
|
||||
auth.hasPrivilege(auth.privileges.deleteAllAccounts) ||
|
||||
(auth.hasPrivilege(auth.privileges.deleteOwnAccount) && auth.isLoggedIn(user.name));
|
||||
privileges.canDeleteAccount =
|
||||
auth.hasPrivilege(auth.privileges.deleteAllAccounts) ||
|
||||
(auth.hasPrivilege(auth.privileges.deleteOwnAccount) && auth.isLoggedIn(user.name));
|
||||
|
||||
promise.wait(util.promiseTemplate('account-removal'))
|
||||
.then(function(template) {
|
||||
templates.accountRemoval = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
promise.wait(util.promiseTemplate('account-removal'))
|
||||
.then(function(template) {
|
||||
templates.accountRemoval = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
var $el = jQuery(target);
|
||||
$el.html(templates.accountRemoval({
|
||||
user: user,
|
||||
canDeleteAccount: privileges.canDeleteAccount}));
|
||||
function render() {
|
||||
var $el = jQuery(target);
|
||||
$el.html(templates.accountRemoval({
|
||||
user: user,
|
||||
canDeleteAccount: privileges.canDeleteAccount}));
|
||||
|
||||
$el.find('form').submit(accountRemovalFormSubmitted);
|
||||
}
|
||||
$el.find('form').submit(accountRemovalFormSubmitted);
|
||||
}
|
||||
|
||||
function getPrivileges() {
|
||||
return privileges;
|
||||
}
|
||||
function getPrivileges() {
|
||||
return privileges;
|
||||
}
|
||||
|
||||
function accountRemovalFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
var $el = jQuery(target);
|
||||
var $messages = $el.find('.messages');
|
||||
messagePresenter.hideMessages($messages);
|
||||
if (!$el.find('input[name=confirmation]:visible').prop('checked')) {
|
||||
messagePresenter.showError($messages, 'Must confirm to proceed.');
|
||||
return;
|
||||
}
|
||||
promise.wait(api.delete('/users/' + user.name))
|
||||
.then(function() {
|
||||
auth.logout();
|
||||
var $messageDiv = messagePresenter.showInfo($messages, 'Account deleted. <a href="">Back to main page</a>');
|
||||
$messageDiv.find('a').click(mainPageLinkClicked);
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
function accountRemovalFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
var $el = jQuery(target);
|
||||
var $messages = $el.find('.messages');
|
||||
messagePresenter.hideMessages($messages);
|
||||
if (!$el.find('input[name=confirmation]:visible').prop('checked')) {
|
||||
messagePresenter.showError($messages, 'Must confirm to proceed.');
|
||||
return;
|
||||
}
|
||||
promise.wait(api.delete('/users/' + user.name))
|
||||
.then(function() {
|
||||
auth.logout();
|
||||
var $messageDiv = messagePresenter.showInfo($messages, 'Account deleted. <a href="">Back to main page</a>');
|
||||
$messageDiv.find('a').click(mainPageLinkClicked);
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
|
||||
function mainPageLinkClicked(e) {
|
||||
e.preventDefault();
|
||||
router.navigateToMainPage();
|
||||
}
|
||||
function mainPageLinkClicked(e) {
|
||||
e.preventDefault();
|
||||
router.navigateToMainPage();
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
getPrivileges: getPrivileges
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
getPrivileges: getPrivileges
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,162 +2,162 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.UserAccountSettingsPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
messagePresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
messagePresenter) {
|
||||
|
||||
var target;
|
||||
var templates = {};
|
||||
var user;
|
||||
var privileges;
|
||||
var avatarContent;
|
||||
var fileDropper;
|
||||
var target;
|
||||
var templates = {};
|
||||
var user;
|
||||
var privileges;
|
||||
var avatarContent;
|
||||
var fileDropper;
|
||||
|
||||
function init(params, loaded) {
|
||||
user = params.user;
|
||||
target = params.target;
|
||||
function init(params, loaded) {
|
||||
user = params.user;
|
||||
target = params.target;
|
||||
|
||||
privileges = {
|
||||
canBan:
|
||||
auth.hasPrivilege(auth.privileges.banUsers),
|
||||
canChangeAccessRank:
|
||||
auth.hasPrivilege(auth.privileges.changeAccessRank),
|
||||
canChangeAvatarStyle:
|
||||
auth.hasPrivilege(auth.privileges.changeAllAvatarStyles) ||
|
||||
(auth.hasPrivilege(auth.privileges.changeOwnAvatarStyle) && auth.isLoggedIn(user.name)),
|
||||
canChangeName:
|
||||
auth.hasPrivilege(auth.privileges.changeAllNames) ||
|
||||
(auth.hasPrivilege(auth.privileges.changeOwnName) && auth.isLoggedIn(user.name)),
|
||||
canChangeEmailAddress:
|
||||
auth.hasPrivilege(auth.privileges.changeAllEmailAddresses) ||
|
||||
(auth.hasPrivilege(auth.privileges.changeOwnEmailAddress) && auth.isLoggedIn(user.name)),
|
||||
canChangePassword:
|
||||
auth.hasPrivilege(auth.privileges.changeAllPasswords) ||
|
||||
(auth.hasPrivilege(auth.privileges.changeOwnPassword) && auth.isLoggedIn(user.name)),
|
||||
};
|
||||
privileges = {
|
||||
canBan:
|
||||
auth.hasPrivilege(auth.privileges.banUsers),
|
||||
canChangeAccessRank:
|
||||
auth.hasPrivilege(auth.privileges.changeAccessRank),
|
||||
canChangeAvatarStyle:
|
||||
auth.hasPrivilege(auth.privileges.changeAllAvatarStyles) ||
|
||||
(auth.hasPrivilege(auth.privileges.changeOwnAvatarStyle) && auth.isLoggedIn(user.name)),
|
||||
canChangeName:
|
||||
auth.hasPrivilege(auth.privileges.changeAllNames) ||
|
||||
(auth.hasPrivilege(auth.privileges.changeOwnName) && auth.isLoggedIn(user.name)),
|
||||
canChangeEmailAddress:
|
||||
auth.hasPrivilege(auth.privileges.changeAllEmailAddresses) ||
|
||||
(auth.hasPrivilege(auth.privileges.changeOwnEmailAddress) && auth.isLoggedIn(user.name)),
|
||||
canChangePassword:
|
||||
auth.hasPrivilege(auth.privileges.changeAllPasswords) ||
|
||||
(auth.hasPrivilege(auth.privileges.changeOwnPassword) && auth.isLoggedIn(user.name)),
|
||||
};
|
||||
|
||||
promise.wait(util.promiseTemplate('account-settings'))
|
||||
.then(function(template) {
|
||||
templates.accountRemoval = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
promise.wait(util.promiseTemplate('account-settings'))
|
||||
.then(function(template) {
|
||||
templates.accountRemoval = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
var $el = jQuery(target);
|
||||
$el.html(templates.accountRemoval(_.extend({user: user}, privileges)));
|
||||
$el.find('form').submit(accountSettingsFormSubmitted);
|
||||
$el.find('form [name=avatar-style]').change(avatarStyleChanged);
|
||||
avatarStyleChanged();
|
||||
fileDropper = new App.Controls.FileDropper($el.find('[name=avatar-content]'));
|
||||
fileDropper.onChange = avatarContentChanged;
|
||||
fileDropper.setNames = true;
|
||||
}
|
||||
function render() {
|
||||
var $el = jQuery(target);
|
||||
$el.html(templates.accountRemoval(_.extend({user: user}, privileges)));
|
||||
$el.find('form').submit(accountSettingsFormSubmitted);
|
||||
$el.find('form [name=avatar-style]').change(avatarStyleChanged);
|
||||
avatarStyleChanged();
|
||||
fileDropper = new App.Controls.FileDropper($el.find('[name=avatar-content]'));
|
||||
fileDropper.onChange = avatarContentChanged;
|
||||
fileDropper.setNames = true;
|
||||
}
|
||||
|
||||
function getPrivileges() {
|
||||
return privileges;
|
||||
}
|
||||
function getPrivileges() {
|
||||
return privileges;
|
||||
}
|
||||
|
||||
function avatarStyleChanged(e) {
|
||||
var $el = jQuery(target);
|
||||
var $target = $el.find('.avatar-content .file-handler');
|
||||
if ($el.find('[name=avatar-style]:checked').val() === 'manual') {
|
||||
$target.show();
|
||||
} else {
|
||||
$target.hide();
|
||||
}
|
||||
}
|
||||
function avatarStyleChanged(e) {
|
||||
var $el = jQuery(target);
|
||||
var $target = $el.find('.avatar-content .file-handler');
|
||||
if ($el.find('[name=avatar-style]:checked').val() === 'manual') {
|
||||
$target.show();
|
||||
} else {
|
||||
$target.hide();
|
||||
}
|
||||
}
|
||||
|
||||
function avatarContentChanged(files) {
|
||||
avatarContent = files[0];
|
||||
}
|
||||
function avatarContentChanged(files) {
|
||||
avatarContent = files[0];
|
||||
}
|
||||
|
||||
function accountSettingsFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
var $el = jQuery(target);
|
||||
var $messages = jQuery(target).find('.messages');
|
||||
messagePresenter.hideMessages($messages);
|
||||
var formData = new FormData();
|
||||
function accountSettingsFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
var $el = jQuery(target);
|
||||
var $messages = jQuery(target).find('.messages');
|
||||
messagePresenter.hideMessages($messages);
|
||||
var formData = new FormData();
|
||||
|
||||
if (privileges.canChangeAvatarStyle) {
|
||||
formData.append('avatarStyle', $el.find('[name=avatar-style]:checked').val());
|
||||
if (avatarContent) {
|
||||
formData.append('avatarContent', avatarContent);
|
||||
}
|
||||
}
|
||||
if (privileges.canChangeName) {
|
||||
formData.append('userName', $el.find('[name=userName]').val());
|
||||
}
|
||||
if (privileges.canChangeAvatarStyle) {
|
||||
formData.append('avatarStyle', $el.find('[name=avatar-style]:checked').val());
|
||||
if (avatarContent) {
|
||||
formData.append('avatarContent', avatarContent);
|
||||
}
|
||||
}
|
||||
if (privileges.canChangeName) {
|
||||
formData.append('userName', $el.find('[name=userName]').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangeEmailAddress) {
|
||||
formData.append('email', $el.find('[name=email]').val());
|
||||
}
|
||||
if (privileges.canChangeEmailAddress) {
|
||||
formData.append('email', $el.find('[name=email]').val());
|
||||
}
|
||||
|
||||
if (privileges.canChangePassword) {
|
||||
var password = $el.find('[name=password]').val();
|
||||
var passwordConfirmation = $el.find('[name=passwordConfirmation]').val();
|
||||
if (privileges.canChangePassword) {
|
||||
var password = $el.find('[name=password]').val();
|
||||
var passwordConfirmation = $el.find('[name=passwordConfirmation]').val();
|
||||
|
||||
if (password) {
|
||||
if (password !== passwordConfirmation) {
|
||||
messagePresenter.showError($messages, 'Passwords must be the same.');
|
||||
return;
|
||||
}
|
||||
if (password) {
|
||||
if (password !== passwordConfirmation) {
|
||||
messagePresenter.showError($messages, 'Passwords must be the same.');
|
||||
return;
|
||||
}
|
||||
|
||||
formData.append('password', password);
|
||||
}
|
||||
}
|
||||
formData.append('password', password);
|
||||
}
|
||||
}
|
||||
|
||||
if (privileges.canChangeAccessRank) {
|
||||
formData.append('accessRank', $el.find('[name=access-rank]:checked').val());
|
||||
}
|
||||
if (privileges.canChangeAccessRank) {
|
||||
formData.append('accessRank', $el.find('[name=access-rank]:checked').val());
|
||||
}
|
||||
|
||||
if (privileges.canBan) {
|
||||
formData.append('banned', $el.find('[name=ban]').is(':checked') ? 1 : 0);
|
||||
}
|
||||
if (privileges.canBan) {
|
||||
formData.append('banned', $el.find('[name=ban]').is(':checked') ? 1 : 0);
|
||||
}
|
||||
|
||||
promise.wait(api.post('/users/' + user.name, formData))
|
||||
.then(function(response) {
|
||||
editSuccess(response);
|
||||
}).fail(function(response) {
|
||||
editFailure(response);
|
||||
});
|
||||
}
|
||||
promise.wait(api.post('/users/' + user.name, formData))
|
||||
.then(function(response) {
|
||||
editSuccess(response);
|
||||
}).fail(function(response) {
|
||||
editFailure(response);
|
||||
});
|
||||
}
|
||||
|
||||
function editSuccess(apiResponse) {
|
||||
var wasLoggedIn = auth.isLoggedIn(user.name);
|
||||
user = apiResponse.json;
|
||||
if (wasLoggedIn) {
|
||||
auth.updateCurrentUser(user);
|
||||
}
|
||||
function editSuccess(apiResponse) {
|
||||
var wasLoggedIn = auth.isLoggedIn(user.name);
|
||||
user = apiResponse.json;
|
||||
if (wasLoggedIn) {
|
||||
auth.updateCurrentUser(user);
|
||||
}
|
||||
|
||||
render();
|
||||
render();
|
||||
|
||||
var $messages = jQuery(target).find('.messages');
|
||||
var message = 'Account settings updated!';
|
||||
if (!apiResponse.json.confirmed) {
|
||||
message += '<br/>Check your inbox for activation e-mail.<br/>If e-mail doesn\'t show up, check your spam folder.';
|
||||
}
|
||||
messagePresenter.showInfo($messages, message);
|
||||
}
|
||||
var $messages = jQuery(target).find('.messages');
|
||||
var message = 'Account settings updated!';
|
||||
if (!apiResponse.json.confirmed) {
|
||||
message += '<br/>Check your inbox for activation e-mail.<br/>If e-mail doesn\'t show up, check your spam folder.';
|
||||
}
|
||||
messagePresenter.showInfo($messages, message);
|
||||
}
|
||||
|
||||
function editFailure(apiResponse) {
|
||||
var $messages = jQuery(target).find('.messages');
|
||||
messagePresenter.showError($messages, apiResponse.json && apiResponse.json.error || apiResponse);
|
||||
}
|
||||
function editFailure(apiResponse) {
|
||||
var $messages = jQuery(target).find('.messages');
|
||||
messagePresenter.showError($messages, apiResponse.json && apiResponse.json.error || apiResponse);
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
getPrivileges: getPrivileges,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
getPrivileges: getPrivileges,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,117 +2,117 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.UserActivationPresenter = function(
|
||||
jQuery,
|
||||
promise,
|
||||
util,
|
||||
auth,
|
||||
api,
|
||||
router,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
jQuery,
|
||||
promise,
|
||||
util,
|
||||
auth,
|
||||
api,
|
||||
router,
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var $messages = $el;
|
||||
var templates = {};
|
||||
var formHidden = false;
|
||||
var operation;
|
||||
var $el = jQuery('#content');
|
||||
var $messages = $el;
|
||||
var templates = {};
|
||||
var formHidden = false;
|
||||
var operation;
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('login');
|
||||
topNavigationPresenter.changeTitle('Account recovery');
|
||||
reinit(params, loaded);
|
||||
}
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('login');
|
||||
topNavigationPresenter.changeTitle('Account recovery');
|
||||
reinit(params, loaded);
|
||||
}
|
||||
|
||||
function reinit(params, loaded) {
|
||||
operation = params.operation;
|
||||
promise.wait(util.promiseTemplate('user-query-form'))
|
||||
.then(function(template) {
|
||||
templates.userQuery = template;
|
||||
if (params.token) {
|
||||
hideForm();
|
||||
confirmToken(params.token);
|
||||
} else {
|
||||
showForm();
|
||||
}
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
function reinit(params, loaded) {
|
||||
operation = params.operation;
|
||||
promise.wait(util.promiseTemplate('user-query-form'))
|
||||
.then(function(template) {
|
||||
templates.userQuery = template;
|
||||
if (params.token) {
|
||||
hideForm();
|
||||
confirmToken(params.token);
|
||||
} else {
|
||||
showForm();
|
||||
}
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.userQuery());
|
||||
$messages = $el.find('.messages');
|
||||
if (formHidden) {
|
||||
$el.find('form').hide();
|
||||
}
|
||||
$el.find('form').submit(userQueryFormSubmitted);
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.userQuery());
|
||||
$messages = $el.find('.messages');
|
||||
if (formHidden) {
|
||||
$el.find('form').hide();
|
||||
}
|
||||
$el.find('form').submit(userQueryFormSubmitted);
|
||||
}
|
||||
|
||||
function hideForm() {
|
||||
formHidden = true;
|
||||
}
|
||||
function hideForm() {
|
||||
formHidden = true;
|
||||
}
|
||||
|
||||
function showForm() {
|
||||
formHidden = false;
|
||||
}
|
||||
function showForm() {
|
||||
formHidden = false;
|
||||
}
|
||||
|
||||
function userQueryFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
function userQueryFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
messagePresenter.hideMessages($messages);
|
||||
|
||||
var userNameOrEmail = $el.find('form input[name=user]').val();
|
||||
if (userNameOrEmail.length === 0) {
|
||||
messagePresenter.showError($messages, 'Field cannot be blank.');
|
||||
return;
|
||||
}
|
||||
var url = operation === 'passwordReset' ?
|
||||
'/password-reset/' + userNameOrEmail :
|
||||
'/activation/' + userNameOrEmail;
|
||||
var userNameOrEmail = $el.find('form input[name=user]').val();
|
||||
if (userNameOrEmail.length === 0) {
|
||||
messagePresenter.showError($messages, 'Field cannot be blank.');
|
||||
return;
|
||||
}
|
||||
var url = operation === 'passwordReset' ?
|
||||
'/password-reset/' + userNameOrEmail :
|
||||
'/activation/' + userNameOrEmail;
|
||||
|
||||
promise.wait(api.post(url))
|
||||
.then(function(response) {
|
||||
var message = operation === 'passwordReset' ?
|
||||
'Password reset request sent.' :
|
||||
'Activation e-mail resent.';
|
||||
message += ' Check your inbox.<br/>If e-mail doesn\'t show up, check your spam folder.';
|
||||
promise.wait(api.post(url))
|
||||
.then(function(response) {
|
||||
var message = operation === 'passwordReset' ?
|
||||
'Password reset request sent.' :
|
||||
'Activation e-mail resent.';
|
||||
message += ' Check your inbox.<br/>If e-mail doesn\'t show up, check your spam folder.';
|
||||
|
||||
$el.find('#user-query-form').slideUp(function() {
|
||||
messagePresenter.showInfo($messages, message);
|
||||
});
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
$el.find('#user-query-form').slideUp(function() {
|
||||
messagePresenter.showInfo($messages, message);
|
||||
});
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
|
||||
function confirmToken(token) {
|
||||
messagePresenter.hideMessages($messages);
|
||||
function confirmToken(token) {
|
||||
messagePresenter.hideMessages($messages);
|
||||
|
||||
var url = operation === 'passwordReset' ?
|
||||
'/finish-password-reset/' + token :
|
||||
'/finish-activation/' + token;
|
||||
var url = operation === 'passwordReset' ?
|
||||
'/finish-password-reset/' + token :
|
||||
'/finish-activation/' + token;
|
||||
|
||||
promise.wait(api.post(url))
|
||||
.then(function(response) {
|
||||
var message = operation === 'passwordReset' ?
|
||||
'Your new password is <strong>' + response.json.newPassword + '</strong>.' :
|
||||
'E-mail activation successful.';
|
||||
promise.wait(api.post(url))
|
||||
.then(function(response) {
|
||||
var message = operation === 'passwordReset' ?
|
||||
'Your new password is <strong>' + response.json.newPassword + '</strong>.' :
|
||||
'E-mail activation successful.';
|
||||
|
||||
$el.find('#user-query-form').slideUp(function() {
|
||||
messagePresenter.showInfo($messages, message);
|
||||
});
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
$el.find('#user-query-form').slideUp(function() {
|
||||
messagePresenter.showInfo($messages, message);
|
||||
});
|
||||
}).fail(function(response) {
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,75 +2,75 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.UserBrowsingSettingsPresenter = function(
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
browsingSettings,
|
||||
messagePresenter) {
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
browsingSettings,
|
||||
messagePresenter) {
|
||||
|
||||
var target;
|
||||
var templates = {};
|
||||
var user;
|
||||
var privileges = {};
|
||||
var target;
|
||||
var templates = {};
|
||||
var user;
|
||||
var privileges = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
user = params.user;
|
||||
target = params.target;
|
||||
function init(params, loaded) {
|
||||
user = params.user;
|
||||
target = params.target;
|
||||
|
||||
privileges.canChangeBrowsingSettings = auth.isLoggedIn(user.name) && user.name === auth.getCurrentUser().name;
|
||||
privileges.canChangeBrowsingSettings = auth.isLoggedIn(user.name) && user.name === auth.getCurrentUser().name;
|
||||
|
||||
promise.wait(util.promiseTemplate('browsing-settings'))
|
||||
.then(function(template) {
|
||||
templates.browsingSettings = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
promise.wait(util.promiseTemplate('browsing-settings'))
|
||||
.then(function(template) {
|
||||
templates.browsingSettings = template;
|
||||
render();
|
||||
loaded();
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
var $el = jQuery(target);
|
||||
$el.html(templates.browsingSettings({user: user, settings: browsingSettings.getSettings()}));
|
||||
$el.find('form').submit(browsingSettingsFormSubmitted);
|
||||
}
|
||||
function render() {
|
||||
var $el = jQuery(target);
|
||||
$el.html(templates.browsingSettings({user: user, settings: browsingSettings.getSettings()}));
|
||||
$el.find('form').submit(browsingSettingsFormSubmitted);
|
||||
}
|
||||
|
||||
function browsingSettingsFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
var $el = jQuery(target);
|
||||
var $messages = $el.find('.messages');
|
||||
messagePresenter.hideMessages($messages);
|
||||
function browsingSettingsFormSubmitted(e) {
|
||||
e.preventDefault();
|
||||
var $el = jQuery(target);
|
||||
var $messages = $el.find('.messages');
|
||||
messagePresenter.hideMessages($messages);
|
||||
|
||||
var newSettings = {
|
||||
endlessScroll: $el.find('[name=endlessScroll]').is(':checked'),
|
||||
hideDownvoted: $el.find('[name=hideDownvoted]').is(':checked'),
|
||||
listPosts: {
|
||||
safe: $el.find('[name=listSafePosts]').is(':checked'),
|
||||
sketchy: $el.find('[name=listSketchyPosts]').is(':checked'),
|
||||
unsafe: $el.find('[name=listUnsafePosts]').is(':checked'),
|
||||
},
|
||||
keyboardShortcuts: $el.find('[name=keyboardShortcuts]').is(':checked'),
|
||||
};
|
||||
var newSettings = {
|
||||
endlessScroll: $el.find('[name=endlessScroll]').is(':checked'),
|
||||
hideDownvoted: $el.find('[name=hideDownvoted]').is(':checked'),
|
||||
listPosts: {
|
||||
safe: $el.find('[name=listSafePosts]').is(':checked'),
|
||||
sketchy: $el.find('[name=listSketchyPosts]').is(':checked'),
|
||||
unsafe: $el.find('[name=listUnsafePosts]').is(':checked'),
|
||||
},
|
||||
keyboardShortcuts: $el.find('[name=keyboardShortcuts]').is(':checked'),
|
||||
};
|
||||
|
||||
promise.wait(browsingSettings.setSettings(newSettings))
|
||||
.then(function() {
|
||||
messagePresenter.showInfo($messages, 'Browsing settings updated!');
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
});
|
||||
}
|
||||
promise.wait(browsingSettings.setSettings(newSettings))
|
||||
.then(function() {
|
||||
messagePresenter.showInfo($messages, 'Browsing settings updated!');
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
});
|
||||
}
|
||||
|
||||
function getPrivileges() {
|
||||
return privileges;
|
||||
}
|
||||
function getPrivileges() {
|
||||
return privileges;
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
getPrivileges: getPrivileges,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
render: render,
|
||||
getPrivileges: getPrivileges,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,93 +2,93 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.UserListPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
auth,
|
||||
pagerPresenter,
|
||||
topNavigationPresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var params;
|
||||
var privileges = {};
|
||||
var $el = jQuery('#content');
|
||||
var templates = {};
|
||||
var params;
|
||||
var privileges = {};
|
||||
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('users');
|
||||
topNavigationPresenter.changeTitle('Users');
|
||||
function init(params, loaded) {
|
||||
topNavigationPresenter.select('users');
|
||||
topNavigationPresenter.changeTitle('Users');
|
||||
|
||||
privileges.canViewUsers = auth.hasPrivilege(auth.privileges.viewUsers);
|
||||
privileges.canViewUsers = auth.hasPrivilege(auth.privileges.viewUsers);
|
||||
|
||||
promise.wait(
|
||||
util.promiseTemplate('user-list'),
|
||||
util.promiseTemplate('user-list-item'))
|
||||
.then(function(listTemplate, listItemTemplate) {
|
||||
templates.list = listTemplate;
|
||||
templates.listItem = listItemTemplate;
|
||||
promise.wait(
|
||||
util.promiseTemplate('user-list'),
|
||||
util.promiseTemplate('user-list-item'))
|
||||
.then(function(listTemplate, listItemTemplate) {
|
||||
templates.list = listTemplate;
|
||||
templates.listItem = listItemTemplate;
|
||||
|
||||
render();
|
||||
loaded();
|
||||
render();
|
||||
loaded();
|
||||
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/users',
|
||||
backendUri: '/users',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderUsers($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
pagerPresenter.init({
|
||||
baseUri: '#/users',
|
||||
backendUri: '/users',
|
||||
$target: $el.find('.pagination-target'),
|
||||
updateCallback: function($page, data) {
|
||||
renderUsers($page, data.entities);
|
||||
},
|
||||
},
|
||||
function() {
|
||||
reinit(params, function() {});
|
||||
});
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
params.query.order = params.query.order || 'name,asc';
|
||||
updateActiveOrder(params.query.order);
|
||||
function reinit(_params, loaded) {
|
||||
params = _params;
|
||||
params.query = params.query || {};
|
||||
params.query.order = params.query.order || 'name,asc';
|
||||
updateActiveOrder(params.query.order);
|
||||
|
||||
pagerPresenter.reinit({query: params.query});
|
||||
loaded();
|
||||
}
|
||||
pagerPresenter.reinit({query: params.query});
|
||||
loaded();
|
||||
}
|
||||
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
}
|
||||
function deinit() {
|
||||
pagerPresenter.deinit();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.list(privileges));
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.list(privileges));
|
||||
}
|
||||
|
||||
function updateActiveOrder(activeOrder) {
|
||||
$el.find('.order li a.active').removeClass('active');
|
||||
$el.find('.order [href*="' + activeOrder + '"]').addClass('active');
|
||||
}
|
||||
function updateActiveOrder(activeOrder) {
|
||||
$el.find('.order li a.active').removeClass('active');
|
||||
$el.find('.order [href*="' + activeOrder + '"]').addClass('active');
|
||||
}
|
||||
|
||||
function renderUsers($page, users) {
|
||||
var $target = $page.find('.users');
|
||||
_.each(users, function(user) {
|
||||
var $item = jQuery('<li>' + templates.listItem(_.extend({
|
||||
user: user,
|
||||
util: util,
|
||||
}, privileges)) + '</li>');
|
||||
$target.append($item);
|
||||
});
|
||||
_.map(_.map($target.find('img'), jQuery), util.loadImagesNicely);
|
||||
}
|
||||
function renderUsers($page, users) {
|
||||
var $target = $page.find('.users');
|
||||
_.each(users, function(user) {
|
||||
var $item = jQuery('<li>' + templates.listItem(_.extend({
|
||||
user: user,
|
||||
util: util,
|
||||
}, privileges)) + '</li>');
|
||||
$target.append($item);
|
||||
});
|
||||
_.map(_.map($target.find('img'), jQuery), util.loadImagesNicely);
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
deinit: deinit,
|
||||
render: render,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,105 +2,105 @@ var App = App || {};
|
|||
App.Presenters = App.Presenters || {};
|
||||
|
||||
App.Presenters.UserPresenter = function(
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
topNavigationPresenter,
|
||||
presenterManager,
|
||||
userBrowsingSettingsPresenter,
|
||||
userAccountSettingsPresenter,
|
||||
userAccountRemovalPresenter,
|
||||
messagePresenter) {
|
||||
_,
|
||||
jQuery,
|
||||
util,
|
||||
promise,
|
||||
api,
|
||||
auth,
|
||||
topNavigationPresenter,
|
||||
presenterManager,
|
||||
userBrowsingSettingsPresenter,
|
||||
userAccountSettingsPresenter,
|
||||
userAccountRemovalPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var $messages = $el;
|
||||
var templates = {};
|
||||
var user;
|
||||
var userName = null;
|
||||
var activeTab;
|
||||
var $el = jQuery('#content');
|
||||
var $messages = $el;
|
||||
var templates = {};
|
||||
var user;
|
||||
var userName = null;
|
||||
var activeTab;
|
||||
|
||||
function init(params, loaded) {
|
||||
promise.wait(util.promiseTemplate('user'))
|
||||
.then(function(template) {
|
||||
templates.user = template;
|
||||
reinit(params, loaded);
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
function init(params, loaded) {
|
||||
promise.wait(util.promiseTemplate('user'))
|
||||
.then(function(template) {
|
||||
templates.user = template;
|
||||
reinit(params, loaded);
|
||||
}).fail(function() {
|
||||
console.log(arguments);
|
||||
loaded();
|
||||
});
|
||||
}
|
||||
|
||||
function reinit(params, loaded) {
|
||||
if (params.userName !== userName) {
|
||||
userName = params.userName;
|
||||
topNavigationPresenter.select(auth.isLoggedIn(userName) ? 'my-account' : 'users');
|
||||
topNavigationPresenter.changeTitle(userName);
|
||||
function reinit(params, loaded) {
|
||||
if (params.userName !== userName) {
|
||||
userName = params.userName;
|
||||
topNavigationPresenter.select(auth.isLoggedIn(userName) ? 'my-account' : 'users');
|
||||
topNavigationPresenter.changeTitle(userName);
|
||||
|
||||
promise.wait(api.get('/users/' + userName))
|
||||
.then(function(response) {
|
||||
user = response.json;
|
||||
var extendedContext = _.extend(params, {user: user});
|
||||
promise.wait(api.get('/users/' + userName))
|
||||
.then(function(response) {
|
||||
user = response.json;
|
||||
var extendedContext = _.extend(params, {user: user});
|
||||
|
||||
presenterManager.initPresenters([
|
||||
[userBrowsingSettingsPresenter, _.extend({}, extendedContext, {target: '#browsing-settings-target'})],
|
||||
[userAccountSettingsPresenter, _.extend({}, extendedContext, {target: '#account-settings-target'})],
|
||||
[userAccountRemovalPresenter, _.extend({}, extendedContext, {target: '#account-removal-target'})]],
|
||||
function() {
|
||||
initTabs(params);
|
||||
loaded();
|
||||
});
|
||||
presenterManager.initPresenters([
|
||||
[userBrowsingSettingsPresenter, _.extend({}, extendedContext, {target: '#browsing-settings-target'})],
|
||||
[userAccountSettingsPresenter, _.extend({}, extendedContext, {target: '#account-settings-target'})],
|
||||
[userAccountRemovalPresenter, _.extend({}, extendedContext, {target: '#account-removal-target'})]],
|
||||
function() {
|
||||
initTabs(params);
|
||||
loaded();
|
||||
});
|
||||
|
||||
}).fail(function(response) {
|
||||
$el.empty();
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
loaded();
|
||||
});
|
||||
}).fail(function(response) {
|
||||
$el.empty();
|
||||
messagePresenter.showError($messages, response.json && response.json.error || response);
|
||||
loaded();
|
||||
});
|
||||
|
||||
} else {
|
||||
initTabs(params);
|
||||
loaded();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
initTabs(params);
|
||||
loaded();
|
||||
}
|
||||
}
|
||||
|
||||
function initTabs(params) {
|
||||
activeTab = params.tab || 'basic-info';
|
||||
render();
|
||||
}
|
||||
function initTabs(params) {
|
||||
activeTab = params.tab || 'basic-info';
|
||||
render();
|
||||
}
|
||||
|
||||
function render() {
|
||||
$el.html(templates.user({
|
||||
user: user,
|
||||
isLoggedIn: auth.isLoggedIn(user.name),
|
||||
util: util,
|
||||
canChangeBrowsingSettings: userBrowsingSettingsPresenter.getPrivileges().canChangeBrowsingSettings,
|
||||
canChangeAccountSettings: _.any(userAccountSettingsPresenter.getPrivileges()),
|
||||
canDeleteAccount: userAccountRemovalPresenter.getPrivileges().canDeleteAccount}));
|
||||
$messages = $el.find('.messages');
|
||||
util.loadImagesNicely($el.find('img'));
|
||||
userBrowsingSettingsPresenter.render();
|
||||
userAccountSettingsPresenter.render();
|
||||
userAccountRemovalPresenter.render();
|
||||
changeTab(activeTab);
|
||||
}
|
||||
function render() {
|
||||
$el.html(templates.user({
|
||||
user: user,
|
||||
isLoggedIn: auth.isLoggedIn(user.name),
|
||||
util: util,
|
||||
canChangeBrowsingSettings: userBrowsingSettingsPresenter.getPrivileges().canChangeBrowsingSettings,
|
||||
canChangeAccountSettings: _.any(userAccountSettingsPresenter.getPrivileges()),
|
||||
canDeleteAccount: userAccountRemovalPresenter.getPrivileges().canDeleteAccount}));
|
||||
$messages = $el.find('.messages');
|
||||
util.loadImagesNicely($el.find('img'));
|
||||
userBrowsingSettingsPresenter.render();
|
||||
userAccountSettingsPresenter.render();
|
||||
userAccountRemovalPresenter.render();
|
||||
changeTab(activeTab);
|
||||
}
|
||||
|
||||
function changeTab(targetTab) {
|
||||
var $link = $el.find('a[data-tab=' + targetTab + ']');
|
||||
var $links = $link.closest('ul').find('a[data-tab]');
|
||||
var $tabs = $el.find('.tab-wrapper').find('.tab');
|
||||
$links.removeClass('active');
|
||||
$link.addClass('active');
|
||||
$tabs.removeClass('active');
|
||||
$tabs.filter('[data-tab=' + targetTab + ']').addClass('active');
|
||||
}
|
||||
function changeTab(targetTab) {
|
||||
var $link = $el.find('a[data-tab=' + targetTab + ']');
|
||||
var $links = $link.closest('ul').find('a[data-tab]');
|
||||
var $tabs = $el.find('.tab-wrapper').find('.tab');
|
||||
$links.removeClass('active');
|
||||
$link.addClass('active');
|
||||
$tabs.removeClass('active');
|
||||
$tabs.filter('[data-tab=' + targetTab + ']').addClass('active');
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render
|
||||
};
|
||||
return {
|
||||
init: init,
|
||||
reinit: reinit,
|
||||
render: render
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,84 +2,84 @@ var App = App || {};
|
|||
|
||||
App.Promise = function(_, jQuery, progress) {
|
||||
|
||||
function BrokenPromiseError(promiseId) {
|
||||
this.name = 'BrokenPromiseError';
|
||||
this.message = 'Broken promise (promise ID: ' + promiseId + ')';
|
||||
}
|
||||
BrokenPromiseError.prototype = new Error();
|
||||
function BrokenPromiseError(promiseId) {
|
||||
this.name = 'BrokenPromiseError';
|
||||
this.message = 'Broken promise (promise ID: ' + promiseId + ')';
|
||||
}
|
||||
BrokenPromiseError.prototype = new Error();
|
||||
|
||||
var active = [];
|
||||
var promiseId = 0;
|
||||
var active = [];
|
||||
var promiseId = 0;
|
||||
|
||||
function make(callback, useProgress) {
|
||||
var deferred = jQuery.Deferred();
|
||||
var promise = deferred.promise();
|
||||
promise.promiseId = ++ promiseId;
|
||||
function make(callback, useProgress) {
|
||||
var deferred = jQuery.Deferred();
|
||||
var promise = deferred.promise();
|
||||
promise.promiseId = ++ promiseId;
|
||||
|
||||
if (useProgress === true) {
|
||||
progress.start();
|
||||
}
|
||||
callback(function() {
|
||||
try {
|
||||
deferred.resolve.apply(deferred, arguments);
|
||||
active = _.without(active, promise.promiseId);
|
||||
progress.done();
|
||||
} catch (e) {
|
||||
if (!(e instanceof BrokenPromiseError)) {
|
||||
console.log(e);
|
||||
}
|
||||
progress.reset();
|
||||
}
|
||||
}, function() {
|
||||
try {
|
||||
deferred.reject.apply(deferred, arguments);
|
||||
active = _.without(active, promise.promiseId);
|
||||
progress.done();
|
||||
} catch (e) {
|
||||
if (!(e instanceof BrokenPromiseError)) {
|
||||
console.log(e);
|
||||
}
|
||||
progress.reset();
|
||||
}
|
||||
});
|
||||
if (useProgress === true) {
|
||||
progress.start();
|
||||
}
|
||||
callback(function() {
|
||||
try {
|
||||
deferred.resolve.apply(deferred, arguments);
|
||||
active = _.without(active, promise.promiseId);
|
||||
progress.done();
|
||||
} catch (e) {
|
||||
if (!(e instanceof BrokenPromiseError)) {
|
||||
console.log(e);
|
||||
}
|
||||
progress.reset();
|
||||
}
|
||||
}, function() {
|
||||
try {
|
||||
deferred.reject.apply(deferred, arguments);
|
||||
active = _.without(active, promise.promiseId);
|
||||
progress.done();
|
||||
} catch (e) {
|
||||
if (!(e instanceof BrokenPromiseError)) {
|
||||
console.log(e);
|
||||
}
|
||||
progress.reset();
|
||||
}
|
||||
});
|
||||
|
||||
active.push(promise.promiseId);
|
||||
active.push(promise.promiseId);
|
||||
|
||||
promise.always(function() {
|
||||
if (!_.contains(active, promise.promiseId)) {
|
||||
throw new BrokenPromiseError(promise.promiseId);
|
||||
}
|
||||
});
|
||||
promise.always(function() {
|
||||
if (!_.contains(active, promise.promiseId)) {
|
||||
throw new BrokenPromiseError(promise.promiseId);
|
||||
}
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
function wait() {
|
||||
var promises = arguments;
|
||||
var deferred = jQuery.Deferred();
|
||||
return jQuery.when.apply(jQuery, promises)
|
||||
.then(function() {
|
||||
return deferred.resolve.apply(deferred, arguments);
|
||||
}).fail(function() {
|
||||
return deferred.reject.apply(deferred, arguments);
|
||||
});
|
||||
}
|
||||
function wait() {
|
||||
var promises = arguments;
|
||||
var deferred = jQuery.Deferred();
|
||||
return jQuery.when.apply(jQuery, promises)
|
||||
.then(function() {
|
||||
return deferred.resolve.apply(deferred, arguments);
|
||||
}).fail(function() {
|
||||
return deferred.reject.apply(deferred, arguments);
|
||||
});
|
||||
}
|
||||
|
||||
function abortAll() {
|
||||
active = [];
|
||||
}
|
||||
function abortAll() {
|
||||
active = [];
|
||||
}
|
||||
|
||||
function getActive() {
|
||||
return active.length;
|
||||
}
|
||||
function getActive() {
|
||||
return active.length;
|
||||
}
|
||||
|
||||
return {
|
||||
make: function(callback) { return make(callback, true); },
|
||||
makeSilent: function(callback) { return make(callback, false); },
|
||||
wait: wait,
|
||||
getActive: getActive,
|
||||
abortAll: abortAll,
|
||||
};
|
||||
return {
|
||||
make: function(callback) { return make(callback, true); },
|
||||
makeSilent: function(callback) { return make(callback, false); },
|
||||
wait: wait,
|
||||
getActive: getActive,
|
||||
abortAll: abortAll,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,184 +2,184 @@ var App = App || {};
|
|||
|
||||
App.Router = function(_, jQuery, promise, util, appState, presenterManager) {
|
||||
|
||||
var root = '#/';
|
||||
var previousLocation = window.location.href;
|
||||
var routes = [];
|
||||
var root = '#/';
|
||||
var previousLocation = window.location.href;
|
||||
var routes = [];
|
||||
|
||||
injectRoutes();
|
||||
injectRoutes();
|
||||
|
||||
function injectRoutes() {
|
||||
inject('', 'homePresenter');
|
||||
inject('#/', 'homePresenter');
|
||||
inject('#/404', 'httpErrorPresenter', {error: 404});
|
||||
inject('#/home', 'homePresenter');
|
||||
inject('#/login', 'loginPresenter');
|
||||
inject('#/logout', 'logoutPresenter');
|
||||
inject('#/register', 'registrationPresenter');
|
||||
inject('#/upload', 'postUploadPresenter');
|
||||
inject('#/password-reset(/:token)', 'userActivationPresenter', {operation: 'passwordReset'});
|
||||
inject('#/activate(/:token)', 'userActivationPresenter', {operation: 'activation'});
|
||||
inject('#/users(/:!query)', 'userListPresenter');
|
||||
inject('#/user/:userName(/:tab)', 'userPresenter');
|
||||
inject('#/posts(/:!query)', 'postListPresenter');
|
||||
inject('#/post/:postNameOrId(/:!query)', 'postPresenter');
|
||||
inject('#/comments(/:!query)', 'globalCommentListPresenter');
|
||||
inject('#/tags(/:!query)', 'tagListPresenter');
|
||||
inject('#/tag/:tagName', 'tagPresenter');
|
||||
inject('#/help(/:tab)', 'helpPresenter');
|
||||
inject('#/history(/:!query)', 'historyPresenter');
|
||||
}
|
||||
function injectRoutes() {
|
||||
inject('', 'homePresenter');
|
||||
inject('#/', 'homePresenter');
|
||||
inject('#/404', 'httpErrorPresenter', {error: 404});
|
||||
inject('#/home', 'homePresenter');
|
||||
inject('#/login', 'loginPresenter');
|
||||
inject('#/logout', 'logoutPresenter');
|
||||
inject('#/register', 'registrationPresenter');
|
||||
inject('#/upload', 'postUploadPresenter');
|
||||
inject('#/password-reset(/:token)', 'userActivationPresenter', {operation: 'passwordReset'});
|
||||
inject('#/activate(/:token)', 'userActivationPresenter', {operation: 'activation'});
|
||||
inject('#/users(/:!query)', 'userListPresenter');
|
||||
inject('#/user/:userName(/:tab)', 'userPresenter');
|
||||
inject('#/posts(/:!query)', 'postListPresenter');
|
||||
inject('#/post/:postNameOrId(/:!query)', 'postPresenter');
|
||||
inject('#/comments(/:!query)', 'globalCommentListPresenter');
|
||||
inject('#/tags(/:!query)', 'tagListPresenter');
|
||||
inject('#/tag/:tagName', 'tagPresenter');
|
||||
inject('#/help(/:tab)', 'helpPresenter');
|
||||
inject('#/history(/:!query)', 'historyPresenter');
|
||||
}
|
||||
|
||||
function navigate(url, useBrowserDispatcher) {
|
||||
if (('pushState' in history) && !useBrowserDispatcher) {
|
||||
history.pushState('', '', url);
|
||||
dispatch();
|
||||
} else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
function navigate(url, useBrowserDispatcher) {
|
||||
if (('pushState' in history) && !useBrowserDispatcher) {
|
||||
history.pushState('', '', url);
|
||||
dispatch();
|
||||
} else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
|
||||
function navigateToMainPage() {
|
||||
navigate(root);
|
||||
}
|
||||
function navigateToMainPage() {
|
||||
navigate(root);
|
||||
}
|
||||
|
||||
function navigateInplace(url, useBrowserDispatcher) {
|
||||
if ('replaceState' in history) {
|
||||
history.replaceState('', '', url);
|
||||
if (!useBrowserDispatcher) {
|
||||
dispatch();
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
} else {
|
||||
navigate(url, useBrowserDispatcher);
|
||||
}
|
||||
}
|
||||
function navigateInplace(url, useBrowserDispatcher) {
|
||||
if ('replaceState' in history) {
|
||||
history.replaceState('', '', url);
|
||||
if (!useBrowserDispatcher) {
|
||||
dispatch();
|
||||
} else {
|
||||
location.reload();
|
||||
}
|
||||
} else {
|
||||
navigate(url, useBrowserDispatcher);
|
||||
}
|
||||
}
|
||||
|
||||
function start() {
|
||||
if ('onhashchange' in window) {
|
||||
window.onhashchange = dispatch;
|
||||
} else {
|
||||
window.onpopstate = dispatch;
|
||||
}
|
||||
dispatch();
|
||||
}
|
||||
function start() {
|
||||
if ('onhashchange' in window) {
|
||||
window.onhashchange = dispatch;
|
||||
} else {
|
||||
window.onpopstate = dispatch;
|
||||
}
|
||||
dispatch();
|
||||
}
|
||||
|
||||
function inject(definition, presenterName, additionalParams) {
|
||||
routes.push(new Route(definition, function(params) {
|
||||
if (util.isExitConfirmationEnabled()) {
|
||||
if (window.location.href === previousLocation) {
|
||||
return;
|
||||
} else {
|
||||
if (window.confirm('Are you sure you want to leave this page? Data will be lost.')) {
|
||||
util.disableExitConfirmation();
|
||||
} else {
|
||||
window.location.href = previousLocation;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
function inject(definition, presenterName, additionalParams) {
|
||||
routes.push(new Route(definition, function(params) {
|
||||
if (util.isExitConfirmationEnabled()) {
|
||||
if (window.location.href === previousLocation) {
|
||||
return;
|
||||
} else {
|
||||
if (window.confirm('Are you sure you want to leave this page? Data will be lost.')) {
|
||||
util.disableExitConfirmation();
|
||||
} else {
|
||||
window.location.href = previousLocation;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params = _.extend({}, params, additionalParams, {previousLocation: previousLocation});
|
||||
params = _.extend({}, params, additionalParams, {previousLocation: previousLocation});
|
||||
|
||||
//abort every operation that can be executed
|
||||
promise.abortAll();
|
||||
previousLocation = window.location.href;
|
||||
//abort every operation that can be executed
|
||||
promise.abortAll();
|
||||
previousLocation = window.location.href;
|
||||
|
||||
var presenter = App.DI.get(presenterName);
|
||||
presenter.name = presenterName;
|
||||
presenterManager.switchContentPresenter(presenter, params);
|
||||
}));
|
||||
}
|
||||
var presenter = App.DI.get(presenterName);
|
||||
presenter.name = presenterName;
|
||||
presenterManager.switchContentPresenter(presenter, params);
|
||||
}));
|
||||
}
|
||||
|
||||
function dispatch() {
|
||||
var url = document.location.hash;
|
||||
for (var i = 0; i < routes.length; i ++) {
|
||||
var route = routes[i];
|
||||
if (route.match(url)) {
|
||||
route.callback(route.params);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
navigateInplace('#/404', true);
|
||||
return false;
|
||||
}
|
||||
function dispatch() {
|
||||
var url = document.location.hash;
|
||||
for (var i = 0; i < routes.length; i ++) {
|
||||
var route = routes[i];
|
||||
if (route.match(url)) {
|
||||
route.callback(route.params);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
navigateInplace('#/404', true);
|
||||
return false;
|
||||
}
|
||||
|
||||
function parseComplexParamValue(value) {
|
||||
var result = {};
|
||||
var params = (value || '').split(/;/);
|
||||
for (var i = 0; i < params.length; i ++) {
|
||||
var param = params[i];
|
||||
if (!param) {
|
||||
continue;
|
||||
}
|
||||
var kv = param.split(/=/);
|
||||
result[kv[0]] = kv[1];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function parseComplexParamValue(value) {
|
||||
var result = {};
|
||||
var params = (value || '').split(/;/);
|
||||
for (var i = 0; i < params.length; i ++) {
|
||||
var param = params[i];
|
||||
if (!param) {
|
||||
continue;
|
||||
}
|
||||
var kv = param.split(/=/);
|
||||
result[kv[0]] = kv[1];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function Route(definition, callback) {
|
||||
var possibleRoutes = getPossibleRoutes(definition);
|
||||
function Route(definition, callback) {
|
||||
var possibleRoutes = getPossibleRoutes(definition);
|
||||
|
||||
function getPossibleRoutes(routeDefinition) {
|
||||
var parts = [];
|
||||
var re = new RegExp('\\(([^}]+?)\\)', 'g');
|
||||
while (true) {
|
||||
var text = re.exec(routeDefinition);
|
||||
if (!text) {
|
||||
break;
|
||||
}
|
||||
parts.push(text[1]);
|
||||
}
|
||||
var possibleRoutes = [routeDefinition.split('(')[0]];
|
||||
for (var i = 0; i < parts.length; i ++) {
|
||||
possibleRoutes.push(possibleRoutes[possibleRoutes.length - 1] + parts[i]);
|
||||
}
|
||||
return possibleRoutes;
|
||||
}
|
||||
function getPossibleRoutes(routeDefinition) {
|
||||
var parts = [];
|
||||
var re = new RegExp('\\(([^}]+?)\\)', 'g');
|
||||
while (true) {
|
||||
var text = re.exec(routeDefinition);
|
||||
if (!text) {
|
||||
break;
|
||||
}
|
||||
parts.push(text[1]);
|
||||
}
|
||||
var possibleRoutes = [routeDefinition.split('(')[0]];
|
||||
for (var i = 0; i < parts.length; i ++) {
|
||||
possibleRoutes.push(possibleRoutes[possibleRoutes.length - 1] + parts[i]);
|
||||
}
|
||||
return possibleRoutes;
|
||||
}
|
||||
|
||||
function match(url) {
|
||||
var params = {};
|
||||
for (var i = 0; i < possibleRoutes.length; i ++) {
|
||||
var possibleRoute = possibleRoutes[i];
|
||||
var compare = url;
|
||||
var possibleRouteParts = possibleRoute.split('/');
|
||||
var compareParts = compare.split('/');
|
||||
if (possibleRoute.search(':') > 0) {
|
||||
for (var j = 0; j < possibleRouteParts.length; j ++) {
|
||||
if ((j < compareParts.length) && (possibleRouteParts[j].charAt(0) === ':')) {
|
||||
var key = possibleRouteParts[j].substring(1);
|
||||
var value = compareParts[j];
|
||||
if (key.charAt(0) === '!') {
|
||||
key = key.substring(1);
|
||||
value = parseComplexParamValue(value);
|
||||
}
|
||||
params[key] = value;
|
||||
compareParts[j] = possibleRouteParts[j];
|
||||
compare = compareParts.join('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (possibleRoute === compare) {
|
||||
this.params = params;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function match(url) {
|
||||
var params = {};
|
||||
for (var i = 0; i < possibleRoutes.length; i ++) {
|
||||
var possibleRoute = possibleRoutes[i];
|
||||
var compare = url;
|
||||
var possibleRouteParts = possibleRoute.split('/');
|
||||
var compareParts = compare.split('/');
|
||||
if (possibleRoute.search(':') > 0) {
|
||||
for (var j = 0; j < possibleRouteParts.length; j ++) {
|
||||
if ((j < compareParts.length) && (possibleRouteParts[j].charAt(0) === ':')) {
|
||||
var key = possibleRouteParts[j].substring(1);
|
||||
var value = compareParts[j];
|
||||
if (key.charAt(0) === '!') {
|
||||
key = key.substring(1);
|
||||
value = parseComplexParamValue(value);
|
||||
}
|
||||
params[key] = value;
|
||||
compareParts[j] = possibleRouteParts[j];
|
||||
compare = compareParts.join('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (possibleRoute === compare) {
|
||||
this.params = params;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.match = match;
|
||||
this.callback = callback;
|
||||
}
|
||||
this.match = match;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
start: start,
|
||||
navigate: navigate,
|
||||
navigateInplace: navigateInplace,
|
||||
navigateToMainPage: navigateToMainPage,
|
||||
};
|
||||
return {
|
||||
start: start,
|
||||
navigate: navigate,
|
||||
navigateInplace: navigateInplace,
|
||||
navigateToMainPage: navigateToMainPage,
|
||||
};
|
||||
};
|
||||
|
||||
App.DI.registerSingleton('router', ['_', 'jQuery', 'promise', 'util', 'appState', 'presenterManager'], App.Router);
|
||||
|
|
|
@ -3,83 +3,83 @@ App.Services = App.Services || {};
|
|||
|
||||
App.Services.PostsAroundCalculator = function(_, promise, util, pager) {
|
||||
|
||||
pager.init({url: '/posts'});
|
||||
pager.init({url: '/posts'});
|
||||
|
||||
function resetCache() {
|
||||
pager.resetCache();
|
||||
}
|
||||
function resetCache() {
|
||||
pager.resetCache();
|
||||
}
|
||||
|
||||
function getLinksToPostsAround(query, postId) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
pager.setSearchParams(query);
|
||||
pager.setPage(query.page);
|
||||
promise.wait(pager.retrieveCached())
|
||||
.then(function(response) {
|
||||
var postIds = _.pluck(response.entities, 'id');
|
||||
var position = _.indexOf(postIds, postId);
|
||||
function getLinksToPostsAround(query, postId) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
pager.setSearchParams(query);
|
||||
pager.setPage(query.page);
|
||||
promise.wait(pager.retrieveCached())
|
||||
.then(function(response) {
|
||||
var postIds = _.pluck(response.entities, 'id');
|
||||
var position = _.indexOf(postIds, postId);
|
||||
|
||||
if (position === -1) {
|
||||
resolve(null, null);
|
||||
}
|
||||
if (position === -1) {
|
||||
resolve(null, null);
|
||||
}
|
||||
|
||||
promise.wait(
|
||||
getLinkToPostAround(postIds, position, query.page, -1),
|
||||
getLinkToPostAround(postIds, position, query.page, 1))
|
||||
.then(function(nextPostUrl, prevPostUrl) {
|
||||
resolve(nextPostUrl, prevPostUrl);
|
||||
}).fail(function() {
|
||||
reject();
|
||||
});
|
||||
}).fail(function() {
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
promise.wait(
|
||||
getLinkToPostAround(postIds, position, query.page, -1),
|
||||
getLinkToPostAround(postIds, position, query.page, 1))
|
||||
.then(function(nextPostUrl, prevPostUrl) {
|
||||
resolve(nextPostUrl, prevPostUrl);
|
||||
}).fail(function() {
|
||||
reject();
|
||||
});
|
||||
}).fail(function() {
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getLinkToPostAround(postIds, position, page, direction) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
if (position + direction >= 0 && position + direction < postIds.length) {
|
||||
var url = util.appendComplexRouteParam(
|
||||
'#/post/' + postIds[position + direction],
|
||||
util.simplifySearchQuery(
|
||||
_.extend(
|
||||
{page: page},
|
||||
pager.getSearchParams())));
|
||||
function getLinkToPostAround(postIds, position, page, direction) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
if (position + direction >= 0 && position + direction < postIds.length) {
|
||||
var url = util.appendComplexRouteParam(
|
||||
'#/post/' + postIds[position + direction],
|
||||
util.simplifySearchQuery(
|
||||
_.extend(
|
||||
{page: page},
|
||||
pager.getSearchParams())));
|
||||
|
||||
resolve(url);
|
||||
} else if (page + direction >= 1) {
|
||||
pager.setPage(page + direction);
|
||||
promise.wait(pager.retrieveCached())
|
||||
.then(function(response) {
|
||||
if (response.entities.length) {
|
||||
var post = direction === - 1 ?
|
||||
_.last(response.entities) :
|
||||
_.first(response.entities);
|
||||
resolve(url);
|
||||
} else if (page + direction >= 1) {
|
||||
pager.setPage(page + direction);
|
||||
promise.wait(pager.retrieveCached())
|
||||
.then(function(response) {
|
||||
if (response.entities.length) {
|
||||
var post = direction === - 1 ?
|
||||
_.last(response.entities) :
|
||||
_.first(response.entities);
|
||||
|
||||
var url = util.appendComplexRouteParam(
|
||||
'#/post/' + post.id,
|
||||
util.simplifySearchQuery(
|
||||
_.extend(
|
||||
{page: page + direction},
|
||||
pager.getSearchParams())));
|
||||
var url = util.appendComplexRouteParam(
|
||||
'#/post/' + post.id,
|
||||
util.simplifySearchQuery(
|
||||
_.extend(
|
||||
{page: page + direction},
|
||||
pager.getSearchParams())));
|
||||
|
||||
resolve(url);
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
}).fail(function() {
|
||||
reject();
|
||||
});
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
resolve(url);
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
}).fail(function() {
|
||||
reject();
|
||||
});
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
resetCache: resetCache,
|
||||
getLinksToPostsAround: getLinksToPostsAround,
|
||||
};
|
||||
return {
|
||||
resetCache: resetCache,
|
||||
getLinksToPostsAround: getLinksToPostsAround,
|
||||
};
|
||||
};
|
||||
|
||||
App.DI.register('postsAroundCalculator', ['_', 'promise', 'util', 'pager'], App.Services.PostsAroundCalculator);
|
||||
|
|
|
@ -2,31 +2,31 @@ var App = App || {};
|
|||
App.Services = App.Services || {};
|
||||
|
||||
App.Services.TagList = function(jQuery) {
|
||||
var tags = [];
|
||||
var tags = [];
|
||||
|
||||
function refreshTags() {
|
||||
jQuery.ajax({
|
||||
success: function(data, textStatus, xhr) {
|
||||
tags = data;
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
console.log(new Error(errorThrown));
|
||||
},
|
||||
type: 'GET',
|
||||
url: '/data/tags.json',
|
||||
});
|
||||
}
|
||||
function refreshTags() {
|
||||
jQuery.ajax({
|
||||
success: function(data, textStatus, xhr) {
|
||||
tags = data;
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
console.log(new Error(errorThrown));
|
||||
},
|
||||
type: 'GET',
|
||||
url: '/data/tags.json',
|
||||
});
|
||||
}
|
||||
|
||||
function getTags() {
|
||||
return tags;
|
||||
}
|
||||
function getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
refreshTags();
|
||||
refreshTags();
|
||||
|
||||
return {
|
||||
refreshTags: refreshTags,
|
||||
getTags: getTags,
|
||||
};
|
||||
return {
|
||||
refreshTags: refreshTags,
|
||||
getTags: getTags,
|
||||
};
|
||||
};
|
||||
|
||||
App.DI.registerSingleton('tagList', ['jQuery'], App.Services.TagList);
|
||||
|
|
|
@ -2,50 +2,50 @@ var App = App || {};
|
|||
|
||||
App.State = function() {
|
||||
|
||||
var properties = {};
|
||||
var observers = {};
|
||||
var properties = {};
|
||||
var observers = {};
|
||||
|
||||
function get(key) {
|
||||
return properties[key];
|
||||
}
|
||||
function get(key) {
|
||||
return properties[key];
|
||||
}
|
||||
|
||||
function set(key, value) {
|
||||
properties[key] = value;
|
||||
if (key in observers) {
|
||||
for (var observerName in observers[key]) {
|
||||
if (observers[key].hasOwnProperty(observerName)) {
|
||||
observers[key][observerName](key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function set(key, value) {
|
||||
properties[key] = value;
|
||||
if (key in observers) {
|
||||
for (var observerName in observers[key]) {
|
||||
if (observers[key].hasOwnProperty(observerName)) {
|
||||
observers[key][observerName](key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function startObserving(key, observerName, callback) {
|
||||
if (!(key in observers)) {
|
||||
observers[key] = {};
|
||||
}
|
||||
if (!(observerName in observers[key])) {
|
||||
observers[key][observerName] = {};
|
||||
}
|
||||
observers[key][observerName] = callback;
|
||||
}
|
||||
function startObserving(key, observerName, callback) {
|
||||
if (!(key in observers)) {
|
||||
observers[key] = {};
|
||||
}
|
||||
if (!(observerName in observers[key])) {
|
||||
observers[key][observerName] = {};
|
||||
}
|
||||
observers[key][observerName] = callback;
|
||||
}
|
||||
|
||||
function stopObserving(key, observerName) {
|
||||
if (!(key in observers)) {
|
||||
return;
|
||||
}
|
||||
if (!(observerName in observers[key])) {
|
||||
return;
|
||||
}
|
||||
delete observers[key][observerName];
|
||||
}
|
||||
function stopObserving(key, observerName) {
|
||||
if (!(key in observers)) {
|
||||
return;
|
||||
}
|
||||
if (!(observerName in observers[key])) {
|
||||
return;
|
||||
}
|
||||
delete observers[key][observerName];
|
||||
}
|
||||
|
||||
return {
|
||||
get: get,
|
||||
set: set,
|
||||
startObserving: startObserving,
|
||||
stopObserving: stopObserving,
|
||||
};
|
||||
return {
|
||||
get: get,
|
||||
set: set,
|
||||
startObserving: startObserving,
|
||||
stopObserving: stopObserving,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,146 +2,146 @@ var App = App || {};
|
|||
App.Util = App.Util || {};
|
||||
|
||||
App.Util.Draggable = function(jQuery) {
|
||||
var KEY_LEFT = 37;
|
||||
var KEY_UP = 38;
|
||||
var KEY_RIGHT = 39;
|
||||
var KEY_DOWN = 40;
|
||||
var KEY_LEFT = 37;
|
||||
var KEY_UP = 38;
|
||||
var KEY_RIGHT = 39;
|
||||
var KEY_DOWN = 40;
|
||||
|
||||
function relativeDragStrategy($element) {
|
||||
var $parent = $element.parent();
|
||||
var delta;
|
||||
var x = $element.offset().left - $parent.offset().left;
|
||||
var y = $element.offset().top - $parent.offset().top;
|
||||
function relativeDragStrategy($element) {
|
||||
var $parent = $element.parent();
|
||||
var delta;
|
||||
var x = $element.offset().left - $parent.offset().left;
|
||||
var y = $element.offset().top - $parent.offset().top;
|
||||
|
||||
var getPosition = function() {
|
||||
return {x: x, y: y};
|
||||
};
|
||||
var getPosition = function() {
|
||||
return {x: x, y: y};
|
||||
};
|
||||
|
||||
var setPosition = function(newX, newY) {
|
||||
x = newX;
|
||||
y = newY;
|
||||
var screenX = Math.min(Math.max(newX, 0), $parent.outerWidth() - $element.outerWidth());
|
||||
var screenY = Math.min(Math.max(newY, 0), $parent.outerHeight() - $element.outerHeight());
|
||||
screenX *= 100.0 / $parent.outerWidth();
|
||||
screenY *= 100.0 / $parent.outerHeight();
|
||||
$element.css({
|
||||
left: screenX + '%',
|
||||
top: screenY + '%'});
|
||||
};
|
||||
var setPosition = function(newX, newY) {
|
||||
x = newX;
|
||||
y = newY;
|
||||
var screenX = Math.min(Math.max(newX, 0), $parent.outerWidth() - $element.outerWidth());
|
||||
var screenY = Math.min(Math.max(newY, 0), $parent.outerHeight() - $element.outerHeight());
|
||||
screenX *= 100.0 / $parent.outerWidth();
|
||||
screenY *= 100.0 / $parent.outerHeight();
|
||||
$element.css({
|
||||
left: screenX + '%',
|
||||
top: screenY + '%'});
|
||||
};
|
||||
|
||||
return {
|
||||
mouseClicked: function(e) {
|
||||
delta = {
|
||||
x: $element.offset().left - e.clientX,
|
||||
y: $element.offset().top - e.clientY,
|
||||
};
|
||||
},
|
||||
return {
|
||||
mouseClicked: function(e) {
|
||||
delta = {
|
||||
x: $element.offset().left - e.clientX,
|
||||
y: $element.offset().top - e.clientY,
|
||||
};
|
||||
},
|
||||
|
||||
mouseMoved: function(e) {
|
||||
setPosition(
|
||||
e.clientX + delta.x - $parent.offset().left,
|
||||
e.clientY + delta.y - $parent.offset().top);
|
||||
},
|
||||
mouseMoved: function(e) {
|
||||
setPosition(
|
||||
e.clientX + delta.x - $parent.offset().left,
|
||||
e.clientY + delta.y - $parent.offset().top);
|
||||
},
|
||||
|
||||
getPosition: getPosition,
|
||||
setPosition: setPosition,
|
||||
};
|
||||
}
|
||||
getPosition: getPosition,
|
||||
setPosition: setPosition,
|
||||
};
|
||||
}
|
||||
|
||||
function absoluteDragStrategy($element) {
|
||||
var delta;
|
||||
var x = $element.offset().left;
|
||||
var y = $element.offset().top;
|
||||
function absoluteDragStrategy($element) {
|
||||
var delta;
|
||||
var x = $element.offset().left;
|
||||
var y = $element.offset().top;
|
||||
|
||||
var getPosition = function() {
|
||||
return {x: x, y: y};
|
||||
};
|
||||
var getPosition = function() {
|
||||
return {x: x, y: y};
|
||||
};
|
||||
|
||||
var setPosition = function(newX, newY) {
|
||||
x = newX;
|
||||
y = newY;
|
||||
$element.css({
|
||||
left: x + 'px',
|
||||
top: y + 'px'});
|
||||
};
|
||||
var setPosition = function(newX, newY) {
|
||||
x = newX;
|
||||
y = newY;
|
||||
$element.css({
|
||||
left: x + 'px',
|
||||
top: y + 'px'});
|
||||
};
|
||||
|
||||
return {
|
||||
mouseClicked: function(e) {
|
||||
delta = {
|
||||
x: $element.position().left - e.clientX,
|
||||
y: $element.position().top - e.clientY,
|
||||
};
|
||||
},
|
||||
return {
|
||||
mouseClicked: function(e) {
|
||||
delta = {
|
||||
x: $element.position().left - e.clientX,
|
||||
y: $element.position().top - e.clientY,
|
||||
};
|
||||
},
|
||||
|
||||
mouseMoved: function(e) {
|
||||
setPosition(e.clientX + delta.x, e.clientY + delta.y);
|
||||
},
|
||||
mouseMoved: function(e) {
|
||||
setPosition(e.clientX + delta.x, e.clientY + delta.y);
|
||||
},
|
||||
|
||||
getPosition: getPosition,
|
||||
setPosition: setPosition,
|
||||
};
|
||||
}
|
||||
getPosition: getPosition,
|
||||
setPosition: setPosition,
|
||||
};
|
||||
}
|
||||
|
||||
function makeDraggable($element, dragStrategy, enableHotkeys) {
|
||||
var strategy = dragStrategy($element);
|
||||
$element.data('drag-strategy', strategy);
|
||||
function makeDraggable($element, dragStrategy, enableHotkeys) {
|
||||
var strategy = dragStrategy($element);
|
||||
$element.data('drag-strategy', strategy);
|
||||
|
||||
$element.addClass('draggable');
|
||||
$element.addClass('draggable');
|
||||
|
||||
$element.mousedown(function(e) {
|
||||
if (e.target !== $element.get(0)) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
$element.focus();
|
||||
$element.addClass('dragging');
|
||||
$element.mousedown(function(e) {
|
||||
if (e.target !== $element.get(0)) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
$element.focus();
|
||||
$element.addClass('dragging');
|
||||
|
||||
strategy.mouseClicked(e);
|
||||
jQuery(window).bind('mousemove.elemmove', function(e) {
|
||||
strategy.mouseMoved(e);
|
||||
}).bind('mouseup.elemmove', function(e) {
|
||||
e.preventDefault();
|
||||
strategy.mouseMoved(e);
|
||||
$element.removeClass('dragging');
|
||||
jQuery(window).unbind('mousemove.elemmove');
|
||||
jQuery(window).unbind('mouseup.elemmove');
|
||||
});
|
||||
});
|
||||
strategy.mouseClicked(e);
|
||||
jQuery(window).bind('mousemove.elemmove', function(e) {
|
||||
strategy.mouseMoved(e);
|
||||
}).bind('mouseup.elemmove', function(e) {
|
||||
e.preventDefault();
|
||||
strategy.mouseMoved(e);
|
||||
$element.removeClass('dragging');
|
||||
jQuery(window).unbind('mousemove.elemmove');
|
||||
jQuery(window).unbind('mouseup.elemmove');
|
||||
});
|
||||
});
|
||||
|
||||
if (enableHotkeys) {
|
||||
$element.keydown(function(e) {
|
||||
var position = strategy.getPosition();
|
||||
var oldPosition = {x: position.x, y: position.y};
|
||||
if (e.shiftKey) {
|
||||
return;
|
||||
}
|
||||
if (enableHotkeys) {
|
||||
$element.keydown(function(e) {
|
||||
var position = strategy.getPosition();
|
||||
var oldPosition = {x: position.x, y: position.y};
|
||||
if (e.shiftKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
var delta = e.ctrlKey ? 10 : 1;
|
||||
if (e.which === KEY_LEFT) {
|
||||
position.x -= delta;
|
||||
} else if (e.which === KEY_RIGHT) {
|
||||
position.x += delta;
|
||||
} else if (e.which === KEY_UP) {
|
||||
position.y -= delta;
|
||||
} else if (e.which === KEY_DOWN) {
|
||||
position.y += delta;
|
||||
}
|
||||
var delta = e.ctrlKey ? 10 : 1;
|
||||
if (e.which === KEY_LEFT) {
|
||||
position.x -= delta;
|
||||
} else if (e.which === KEY_RIGHT) {
|
||||
position.x += delta;
|
||||
} else if (e.which === KEY_UP) {
|
||||
position.y -= delta;
|
||||
} else if (e.which === KEY_DOWN) {
|
||||
position.y += delta;
|
||||
}
|
||||
|
||||
if (position.x !== oldPosition.x || position.y !== oldPosition.y) {
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
strategy.setPosition(position.x, position.y);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (position.x !== oldPosition.x || position.y !== oldPosition.y) {
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
strategy.setPosition(position.x, position.y);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
makeDraggable: makeDraggable,
|
||||
absoluteDragStrategy: absoluteDragStrategy,
|
||||
relativeDragStrategy: relativeDragStrategy,
|
||||
};
|
||||
return {
|
||||
makeDraggable: makeDraggable,
|
||||
absoluteDragStrategy: absoluteDragStrategy,
|
||||
relativeDragStrategy: relativeDragStrategy,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -3,265 +3,265 @@ App.Util = App.Util || {};
|
|||
|
||||
App.Util.Misc = function(_, jQuery, marked, promise) {
|
||||
|
||||
var exitConfirmationEnabled = false;
|
||||
var exitConfirmationEnabled = false;
|
||||
|
||||
function transparentPixel() {
|
||||
return 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
||||
}
|
||||
function transparentPixel() {
|
||||
return 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7';
|
||||
}
|
||||
|
||||
function enableExitConfirmation() {
|
||||
exitConfirmationEnabled = true;
|
||||
jQuery(window).bind('beforeunload', function(e) {
|
||||
return 'There are unsaved changes.';
|
||||
});
|
||||
}
|
||||
function enableExitConfirmation() {
|
||||
exitConfirmationEnabled = true;
|
||||
jQuery(window).bind('beforeunload', function(e) {
|
||||
return 'There are unsaved changes.';
|
||||
});
|
||||
}
|
||||
|
||||
function disableExitConfirmation() {
|
||||
exitConfirmationEnabled = false;
|
||||
jQuery(window).unbind('beforeunload');
|
||||
}
|
||||
function disableExitConfirmation() {
|
||||
exitConfirmationEnabled = false;
|
||||
jQuery(window).unbind('beforeunload');
|
||||
}
|
||||
|
||||
function isExitConfirmationEnabled() {
|
||||
return exitConfirmationEnabled;
|
||||
}
|
||||
function isExitConfirmationEnabled() {
|
||||
return exitConfirmationEnabled;
|
||||
}
|
||||
|
||||
function loadImagesNicely($img) {
|
||||
if (!$img.get(0).complete) {
|
||||
$img.addClass('loading');
|
||||
$img.css({opacity: 0});
|
||||
var $div = jQuery('<div>Loading ' + $img.attr('alt') + '…</div>');
|
||||
var width = $img.width();
|
||||
var height = $img.height();
|
||||
if (width > 50 && height > 50) {
|
||||
$div.css({
|
||||
position: 'absolute',
|
||||
width: width + 'px',
|
||||
height: height + 'px',
|
||||
color: 'rgba(0, 0, 0, 0.15)',
|
||||
zIndex: -1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center'});
|
||||
$div.insertBefore($img);
|
||||
$div.offset($img.offset());
|
||||
}
|
||||
$img.bind('load', function() {
|
||||
$img.animate({opacity: 1}, 'fast');
|
||||
$img.removeClass('loading');
|
||||
$div.fadeOut($div.remove);
|
||||
});
|
||||
}
|
||||
}
|
||||
function loadImagesNicely($img) {
|
||||
if (!$img.get(0).complete) {
|
||||
$img.addClass('loading');
|
||||
$img.css({opacity: 0});
|
||||
var $div = jQuery('<div>Loading ' + $img.attr('alt') + '…</div>');
|
||||
var width = $img.width();
|
||||
var height = $img.height();
|
||||
if (width > 50 && height > 50) {
|
||||
$div.css({
|
||||
position: 'absolute',
|
||||
width: width + 'px',
|
||||
height: height + 'px',
|
||||
color: 'rgba(0, 0, 0, 0.15)',
|
||||
zIndex: -1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center'});
|
||||
$div.insertBefore($img);
|
||||
$div.offset($img.offset());
|
||||
}
|
||||
$img.bind('load', function() {
|
||||
$img.animate({opacity: 1}, 'fast');
|
||||
$img.removeClass('loading');
|
||||
$div.fadeOut($div.remove);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function promiseTemplate(templateName) {
|
||||
return promiseTemplateFromDOM(templateName) ||
|
||||
promiseTemplateWithAJAX(templateName);
|
||||
}
|
||||
function promiseTemplate(templateName) {
|
||||
return promiseTemplateFromDOM(templateName) ||
|
||||
promiseTemplateWithAJAX(templateName);
|
||||
}
|
||||
|
||||
function promiseTemplateFromDOM(templateName) {
|
||||
var $template = jQuery('#' + templateName + '-template');
|
||||
if ($template.length) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
resolve(_.template($template.html()));
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function promiseTemplateFromDOM(templateName) {
|
||||
var $template = jQuery('#' + templateName + '-template');
|
||||
if ($template.length) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
resolve(_.template($template.html()));
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function promiseTemplateWithAJAX(templateName) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
var templatesDir = '/templates';
|
||||
var templateUrl = templatesDir + '/' + templateName + '.tpl';
|
||||
function promiseTemplateWithAJAX(templateName) {
|
||||
return promise.make(function(resolve, reject) {
|
||||
var templatesDir = '/templates';
|
||||
var templateUrl = templatesDir + '/' + templateName + '.tpl';
|
||||
|
||||
jQuery.ajax({
|
||||
url: templateUrl,
|
||||
method: 'GET',
|
||||
success: function(data, textStatus, xhr) {
|
||||
resolve(_.template(data));
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
console.log(new Error('Error while loading template ' + templateName + ': ' + errorThrown));
|
||||
reject();
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
jQuery.ajax({
|
||||
url: templateUrl,
|
||||
method: 'GET',
|
||||
success: function(data, textStatus, xhr) {
|
||||
resolve(_.template(data));
|
||||
},
|
||||
error: function(xhr, textStatus, errorThrown) {
|
||||
console.log(new Error('Error while loading template ' + templateName + ': ' + errorThrown));
|
||||
reject();
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function formatRelativeTime(timeString) {
|
||||
if (!timeString) {
|
||||
return 'never';
|
||||
}
|
||||
function formatRelativeTime(timeString) {
|
||||
if (!timeString) {
|
||||
return 'never';
|
||||
}
|
||||
|
||||
var then = Date.parse(timeString);
|
||||
var now = Date.now();
|
||||
var difference = Math.abs(now - then);
|
||||
var future = now < then;
|
||||
var then = Date.parse(timeString);
|
||||
var now = Date.now();
|
||||
var difference = Math.abs(now - then);
|
||||
var future = now < then;
|
||||
|
||||
var text = (function(difference) {
|
||||
var mul = 1000;
|
||||
var prevMul;
|
||||
var text = (function(difference) {
|
||||
var mul = 1000;
|
||||
var prevMul;
|
||||
|
||||
mul *= 60;
|
||||
if (difference < mul) {
|
||||
return 'a few seconds';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'a minute';
|
||||
}
|
||||
mul *= 60;
|
||||
if (difference < mul) {
|
||||
return 'a few seconds';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'a minute';
|
||||
}
|
||||
|
||||
prevMul = mul; mul *= 60;
|
||||
if (difference < mul) {
|
||||
return Math.round(difference / prevMul) + ' minutes';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'an hour';
|
||||
}
|
||||
prevMul = mul; mul *= 60;
|
||||
if (difference < mul) {
|
||||
return Math.round(difference / prevMul) + ' minutes';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'an hour';
|
||||
}
|
||||
|
||||
prevMul = mul; mul *= 24;
|
||||
if (difference < mul) {
|
||||
return Math.round(difference / prevMul) + ' hours';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'a day';
|
||||
}
|
||||
prevMul = mul; mul *= 24;
|
||||
if (difference < mul) {
|
||||
return Math.round(difference / prevMul) + ' hours';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'a day';
|
||||
}
|
||||
|
||||
prevMul = mul; mul *= 30.42;
|
||||
if (difference < mul) {
|
||||
return Math.round(difference / prevMul) + ' days';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'a month';
|
||||
}
|
||||
prevMul = mul; mul *= 30.42;
|
||||
if (difference < mul) {
|
||||
return Math.round(difference / prevMul) + ' days';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'a month';
|
||||
}
|
||||
|
||||
prevMul = mul; mul *= 12;
|
||||
if (difference < mul) {
|
||||
return Math.round(difference / prevMul) + ' months';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'a year';
|
||||
}
|
||||
prevMul = mul; mul *= 12;
|
||||
if (difference < mul) {
|
||||
return Math.round(difference / prevMul) + ' months';
|
||||
} else if (difference < mul * 2) {
|
||||
return 'a year';
|
||||
}
|
||||
|
||||
return Math.round(difference / mul) + ' years';
|
||||
})(difference);
|
||||
return Math.round(difference / mul) + ' years';
|
||||
})(difference);
|
||||
|
||||
if (text === 'a day') {
|
||||
return future ? 'tomorrow' : 'yesterday';
|
||||
}
|
||||
return future ? 'in ' + text : text + ' ago';
|
||||
}
|
||||
if (text === 'a day') {
|
||||
return future ? 'tomorrow' : 'yesterday';
|
||||
}
|
||||
return future ? 'in ' + text : text + ' ago';
|
||||
}
|
||||
|
||||
function formatAbsoluteTime(timeString) {
|
||||
var time = new Date(Date.parse(timeString));
|
||||
return time.toString();
|
||||
}
|
||||
function formatAbsoluteTime(timeString) {
|
||||
var time = new Date(Date.parse(timeString));
|
||||
return time.toString();
|
||||
}
|
||||
|
||||
function formatUnits(number, base, suffixes, callback) {
|
||||
if (!number && number !== 0) {
|
||||
return NaN;
|
||||
}
|
||||
number *= 1.0;
|
||||
function formatUnits(number, base, suffixes, callback) {
|
||||
if (!number && number !== 0) {
|
||||
return NaN;
|
||||
}
|
||||
number *= 1.0;
|
||||
|
||||
var suffix = suffixes.shift();
|
||||
while (number >= base && suffixes.length > 0) {
|
||||
suffix = suffixes.shift();
|
||||
number /= base;
|
||||
}
|
||||
var suffix = suffixes.shift();
|
||||
while (number >= base && suffixes.length > 0) {
|
||||
suffix = suffixes.shift();
|
||||
number /= base;
|
||||
}
|
||||
|
||||
if (typeof(callback) === 'undefined') {
|
||||
callback = function(number, suffix) {
|
||||
return suffix ? number.toFixed(1) + suffix : number;
|
||||
};
|
||||
}
|
||||
if (typeof(callback) === 'undefined') {
|
||||
callback = function(number, suffix) {
|
||||
return suffix ? number.toFixed(1) + suffix : number;
|
||||
};
|
||||
}
|
||||
|
||||
return callback(number, suffix);
|
||||
}
|
||||
return callback(number, suffix);
|
||||
}
|
||||
|
||||
function formatFileSize(fileSize) {
|
||||
return formatUnits(
|
||||
fileSize,
|
||||
1024,
|
||||
['B', 'K', 'M', 'G'],
|
||||
function(number, suffix) {
|
||||
var decimalPlaces = number < 20 && suffix !== 'B' ? 1 : 0;
|
||||
return number.toFixed(decimalPlaces) + suffix;
|
||||
});
|
||||
}
|
||||
function formatFileSize(fileSize) {
|
||||
return formatUnits(
|
||||
fileSize,
|
||||
1024,
|
||||
['B', 'K', 'M', 'G'],
|
||||
function(number, suffix) {
|
||||
var decimalPlaces = number < 20 && suffix !== 'B' ? 1 : 0;
|
||||
return number.toFixed(decimalPlaces) + suffix;
|
||||
});
|
||||
}
|
||||
|
||||
function formatMarkdown(text) {
|
||||
var renderer = new marked.Renderer();
|
||||
function formatMarkdown(text) {
|
||||
var renderer = new marked.Renderer();
|
||||
|
||||
var options = {
|
||||
renderer: renderer,
|
||||
breaks: true,
|
||||
sanitize: true,
|
||||
smartypants: true,
|
||||
};
|
||||
var options = {
|
||||
renderer: renderer,
|
||||
breaks: true,
|
||||
sanitize: true,
|
||||
smartypants: true,
|
||||
};
|
||||
|
||||
var preDecorator = function(text) {
|
||||
//prevent ^#... from being treated as headers, due to tag permalinks
|
||||
text = text.replace(/^#/g, '%%%#');
|
||||
//fix \ before ~ being stripped away
|
||||
text = text.replace(/\\~/g, '%%%T');
|
||||
return text;
|
||||
};
|
||||
var preDecorator = function(text) {
|
||||
//prevent ^#... from being treated as headers, due to tag permalinks
|
||||
text = text.replace(/^#/g, '%%%#');
|
||||
//fix \ before ~ being stripped away
|
||||
text = text.replace(/\\~/g, '%%%T');
|
||||
return text;
|
||||
};
|
||||
|
||||
var postDecorator = function(text) {
|
||||
//restore fixes
|
||||
text = text.replace(/%%%T/g, '\\~');
|
||||
text = text.replace(/%%%#/g, '#');
|
||||
var postDecorator = function(text) {
|
||||
//restore fixes
|
||||
text = text.replace(/%%%T/g, '\\~');
|
||||
text = text.replace(/%%%#/g, '#');
|
||||
|
||||
//search permalinks
|
||||
text = text.replace(/\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]/ig, '<a href="#/posts/query=$1"><code>$1</code></a>');
|
||||
//spoilers
|
||||
text = text.replace(/\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/ig, '<span class="spoiler">$1</span>');
|
||||
//[small]
|
||||
text = text.replace(/\[small\]((?:[^\[]|\[(?!\/?small\]))+)\[\/small\]/ig, '<small>$1</small>');
|
||||
//strike-through
|
||||
text = text.replace(/(^|[^\\])(~~|~)([^~]+)\2/g, '$1<del>$3</del>');
|
||||
text = text.replace(/\\~/g, '~');
|
||||
//post premalinks
|
||||
text = text.replace(/(^|[\s<>\(\)\[\]])@(\d+)/g, '$1<a href="#/post/$2"><code>@$2</code></a>');
|
||||
//user permalinks
|
||||
text = text.replace(/(^|[\s<>\(\)\[\]])\+([a-zA-Z0-9_-]+)/g, '$1<a href="#/user/$2"><code>+$2</code></a>');
|
||||
//tag permalinks
|
||||
text = text.replace(/(^|[\s<>\(\)\[\]])\#([^\s<>/\\]+)/g, '$1<a href="#/posts/query=$2"><code>#$2</code></a>');
|
||||
return text;
|
||||
};
|
||||
//search permalinks
|
||||
text = text.replace(/\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]/ig, '<a href="#/posts/query=$1"><code>$1</code></a>');
|
||||
//spoilers
|
||||
text = text.replace(/\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/ig, '<span class="spoiler">$1</span>');
|
||||
//[small]
|
||||
text = text.replace(/\[small\]((?:[^\[]|\[(?!\/?small\]))+)\[\/small\]/ig, '<small>$1</small>');
|
||||
//strike-through
|
||||
text = text.replace(/(^|[^\\])(~~|~)([^~]+)\2/g, '$1<del>$3</del>');
|
||||
text = text.replace(/\\~/g, '~');
|
||||
//post premalinks
|
||||
text = text.replace(/(^|[\s<>\(\)\[\]])@(\d+)/g, '$1<a href="#/post/$2"><code>@$2</code></a>');
|
||||
//user permalinks
|
||||
text = text.replace(/(^|[\s<>\(\)\[\]])\+([a-zA-Z0-9_-]+)/g, '$1<a href="#/user/$2"><code>+$2</code></a>');
|
||||
//tag permalinks
|
||||
text = text.replace(/(^|[\s<>\(\)\[\]])\#([^\s<>/\\]+)/g, '$1<a href="#/posts/query=$2"><code>#$2</code></a>');
|
||||
return text;
|
||||
};
|
||||
|
||||
return postDecorator(marked(preDecorator(text), options));
|
||||
}
|
||||
return postDecorator(marked(preDecorator(text), options));
|
||||
}
|
||||
|
||||
function appendComplexRouteParam(baseUri, params) {
|
||||
var result = baseUri + '/';
|
||||
_.each(params, function(v, k) {
|
||||
if (typeof(v) !== 'undefined') {
|
||||
result += k + '=' + v + ';';
|
||||
}
|
||||
});
|
||||
return result.slice(0, -1);
|
||||
}
|
||||
function appendComplexRouteParam(baseUri, params) {
|
||||
var result = baseUri + '/';
|
||||
_.each(params, function(v, k) {
|
||||
if (typeof(v) !== 'undefined') {
|
||||
result += k + '=' + v + ';';
|
||||
}
|
||||
});
|
||||
return result.slice(0, -1);
|
||||
}
|
||||
|
||||
function simplifySearchQuery(query) {
|
||||
if (typeof(query) === 'undefined') {
|
||||
return {};
|
||||
}
|
||||
if (query.page === 1) {
|
||||
delete query.page;
|
||||
}
|
||||
query = _.pick(query, _.identity); //remove falsy values
|
||||
return query;
|
||||
}
|
||||
function simplifySearchQuery(query) {
|
||||
if (typeof(query) === 'undefined') {
|
||||
return {};
|
||||
}
|
||||
if (query.page === 1) {
|
||||
delete query.page;
|
||||
}
|
||||
query = _.pick(query, _.identity); //remove falsy values
|
||||
return query;
|
||||
}
|
||||
|
||||
return {
|
||||
promiseTemplate: promiseTemplate,
|
||||
formatRelativeTime: formatRelativeTime,
|
||||
formatAbsoluteTime: formatAbsoluteTime,
|
||||
formatFileSize: formatFileSize,
|
||||
formatMarkdown: formatMarkdown,
|
||||
enableExitConfirmation: enableExitConfirmation,
|
||||
disableExitConfirmation: disableExitConfirmation,
|
||||
isExitConfirmationEnabled: isExitConfirmationEnabled,
|
||||
transparentPixel: transparentPixel,
|
||||
loadImagesNicely: loadImagesNicely,
|
||||
appendComplexRouteParam: appendComplexRouteParam,
|
||||
simplifySearchQuery: simplifySearchQuery,
|
||||
};
|
||||
return {
|
||||
promiseTemplate: promiseTemplate,
|
||||
formatRelativeTime: formatRelativeTime,
|
||||
formatAbsoluteTime: formatAbsoluteTime,
|
||||
formatFileSize: formatFileSize,
|
||||
formatMarkdown: formatMarkdown,
|
||||
enableExitConfirmation: enableExitConfirmation,
|
||||
disableExitConfirmation: disableExitConfirmation,
|
||||
isExitConfirmationEnabled: isExitConfirmationEnabled,
|
||||
transparentPixel: transparentPixel,
|
||||
loadImagesNicely: loadImagesNicely,
|
||||
appendComplexRouteParam: appendComplexRouteParam,
|
||||
simplifySearchQuery: simplifySearchQuery,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -2,108 +2,108 @@ var App = App || {};
|
|||
App.Util = App.Util || {};
|
||||
|
||||
App.Util.Resizable = function(jQuery) {
|
||||
var KEY_LEFT = 37;
|
||||
var KEY_UP = 38;
|
||||
var KEY_RIGHT = 39;
|
||||
var KEY_DOWN = 40;
|
||||
var KEY_LEFT = 37;
|
||||
var KEY_UP = 38;
|
||||
var KEY_RIGHT = 39;
|
||||
var KEY_DOWN = 40;
|
||||
|
||||
function relativeResizeStrategy($element) {
|
||||
var $parent = $element.parent();
|
||||
var delta;
|
||||
var width = $element.width();
|
||||
var height = $element.height();
|
||||
function relativeResizeStrategy($element) {
|
||||
var $parent = $element.parent();
|
||||
var delta;
|
||||
var width = $element.width();
|
||||
var height = $element.height();
|
||||
|
||||
var getSize = function() {
|
||||
return {width: width, height: height};
|
||||
};
|
||||
var getSize = function() {
|
||||
return {width: width, height: height};
|
||||
};
|
||||
|
||||
var setSize = function(newWidth, newHeight) {
|
||||
width = newWidth;
|
||||
height = newHeight;
|
||||
var screenWidth = Math.min(Math.max(width, 20), $parent.outerWidth() + $parent.offset().left - $element.offset().left);
|
||||
var screenHeight = Math.min(Math.max(height, 20), $parent.outerHeight() + $parent.offset().top - $element.offset().top);
|
||||
screenWidth *= 100.0 / $parent.outerWidth();
|
||||
screenHeight *= 100.0 / $parent.outerHeight();
|
||||
$element.css({
|
||||
width: screenWidth + '%',
|
||||
height: screenHeight + '%'});
|
||||
};
|
||||
var setSize = function(newWidth, newHeight) {
|
||||
width = newWidth;
|
||||
height = newHeight;
|
||||
var screenWidth = Math.min(Math.max(width, 20), $parent.outerWidth() + $parent.offset().left - $element.offset().left);
|
||||
var screenHeight = Math.min(Math.max(height, 20), $parent.outerHeight() + $parent.offset().top - $element.offset().top);
|
||||
screenWidth *= 100.0 / $parent.outerWidth();
|
||||
screenHeight *= 100.0 / $parent.outerHeight();
|
||||
$element.css({
|
||||
width: screenWidth + '%',
|
||||
height: screenHeight + '%'});
|
||||
};
|
||||
|
||||
return {
|
||||
mouseClicked: function(e) {
|
||||
delta = {
|
||||
x: $element.width() - e.clientX,
|
||||
y: $element.height() - e.clientY,
|
||||
};
|
||||
},
|
||||
return {
|
||||
mouseClicked: function(e) {
|
||||
delta = {
|
||||
x: $element.width() - e.clientX,
|
||||
y: $element.height() - e.clientY,
|
||||
};
|
||||
},
|
||||
|
||||
mouseMoved: function(e) {
|
||||
setSize(
|
||||
e.clientX + delta.x,
|
||||
e.clientY + delta.y);
|
||||
},
|
||||
mouseMoved: function(e) {
|
||||
setSize(
|
||||
e.clientX + delta.x,
|
||||
e.clientY + delta.y);
|
||||
},
|
||||
|
||||
getSize: getSize,
|
||||
setSize: setSize,
|
||||
};
|
||||
}
|
||||
getSize: getSize,
|
||||
setSize: setSize,
|
||||
};
|
||||
}
|
||||
|
||||
function makeResizable($element, enableHotkeys) {
|
||||
var $resizer = jQuery('<div class="resizer"></div>');
|
||||
var strategy = relativeResizeStrategy($element);
|
||||
$element.append($resizer);
|
||||
function makeResizable($element, enableHotkeys) {
|
||||
var $resizer = jQuery('<div class="resizer"></div>');
|
||||
var strategy = relativeResizeStrategy($element);
|
||||
$element.append($resizer);
|
||||
|
||||
$resizer.mousedown(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
$element.focus();
|
||||
$element.addClass('resizing');
|
||||
$resizer.mousedown(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
$element.focus();
|
||||
$element.addClass('resizing');
|
||||
|
||||
strategy.mouseClicked(e);
|
||||
strategy.mouseClicked(e);
|
||||
|
||||
jQuery(window).bind('mousemove.elemsize', function(e) {
|
||||
strategy.mouseMoved(e);
|
||||
}).bind('mouseup.elemsize', function(e) {
|
||||
e.preventDefault();
|
||||
strategy.mouseMoved(e);
|
||||
$element.removeClass('resizing');
|
||||
jQuery(window).unbind('mousemove.elemsize');
|
||||
jQuery(window).unbind('mouseup.elemsize');
|
||||
});
|
||||
});
|
||||
jQuery(window).bind('mousemove.elemsize', function(e) {
|
||||
strategy.mouseMoved(e);
|
||||
}).bind('mouseup.elemsize', function(e) {
|
||||
e.preventDefault();
|
||||
strategy.mouseMoved(e);
|
||||
$element.removeClass('resizing');
|
||||
jQuery(window).unbind('mousemove.elemsize');
|
||||
jQuery(window).unbind('mouseup.elemsize');
|
||||
});
|
||||
});
|
||||
|
||||
if (enableHotkeys) {
|
||||
$element.keydown(function(e) {
|
||||
var size = strategy.getSize();
|
||||
var oldSize = {width: size.width, height: size.height};
|
||||
if (!e.shiftKey) {
|
||||
return;
|
||||
}
|
||||
if (enableHotkeys) {
|
||||
$element.keydown(function(e) {
|
||||
var size = strategy.getSize();
|
||||
var oldSize = {width: size.width, height: size.height};
|
||||
if (!e.shiftKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
var delta = e.ctrlKey ? 10 : 1;
|
||||
if (e.which === KEY_LEFT) {
|
||||
size.width -= delta;
|
||||
} else if (e.which === KEY_RIGHT) {
|
||||
size.width += delta;
|
||||
} else if (e.which === KEY_UP) {
|
||||
size.height -= delta;
|
||||
} else if (e.which === KEY_DOWN) {
|
||||
size.height += delta;
|
||||
}
|
||||
var delta = e.ctrlKey ? 10 : 1;
|
||||
if (e.which === KEY_LEFT) {
|
||||
size.width -= delta;
|
||||
} else if (e.which === KEY_RIGHT) {
|
||||
size.width += delta;
|
||||
} else if (e.which === KEY_UP) {
|
||||
size.height -= delta;
|
||||
} else if (e.which === KEY_DOWN) {
|
||||
size.height += delta;
|
||||
}
|
||||
|
||||
if (size.width !== oldSize.width || size.height !== oldSize.height) {
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
strategy.setSize(size.width, size.height);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (size.width !== oldSize.width || size.height !== oldSize.height) {
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
strategy.setSize(size.width, size.height);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
makeResizable: makeResizable,
|
||||
};
|
||||
return {
|
||||
makeResizable: makeResizable,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -5,42 +5,42 @@ $startTime = microtime(true);
|
|||
|
||||
final class Bootstrap
|
||||
{
|
||||
private static $startTime;
|
||||
private static $startTime;
|
||||
|
||||
public static function init($startTime)
|
||||
{
|
||||
self::$startTime = $startTime;
|
||||
self::setTimezone();
|
||||
self::turnErrorsIntoExceptions();
|
||||
self::initAutoloader();
|
||||
}
|
||||
public static function init($startTime)
|
||||
{
|
||||
self::$startTime = $startTime;
|
||||
self::setTimezone();
|
||||
self::turnErrorsIntoExceptions();
|
||||
self::initAutoloader();
|
||||
}
|
||||
|
||||
public static function getStartTime()
|
||||
{
|
||||
return self::$startTime;
|
||||
}
|
||||
public static function getStartTime()
|
||||
{
|
||||
return self::$startTime;
|
||||
}
|
||||
|
||||
private static function setTimezone()
|
||||
{
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
private static function setTimezone()
|
||||
{
|
||||
date_default_timezone_set('UTC');
|
||||
}
|
||||
|
||||
private static function initAutoloader()
|
||||
{
|
||||
require(__DIR__
|
||||
. DIRECTORY_SEPARATOR . '..'
|
||||
. DIRECTORY_SEPARATOR . 'vendor'
|
||||
. DIRECTORY_SEPARATOR . 'autoload.php');
|
||||
}
|
||||
private static function initAutoloader()
|
||||
{
|
||||
require(__DIR__
|
||||
. DIRECTORY_SEPARATOR . '..'
|
||||
. DIRECTORY_SEPARATOR . 'vendor'
|
||||
. DIRECTORY_SEPARATOR . 'autoload.php');
|
||||
}
|
||||
|
||||
private static function turnErrorsIntoExceptions()
|
||||
{
|
||||
set_error_handler(
|
||||
function($errno, $errstr, $errfile, $errline, array $errcontext)
|
||||
{
|
||||
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||
});
|
||||
}
|
||||
private static function turnErrorsIntoExceptions()
|
||||
{
|
||||
set_error_handler(
|
||||
function($errno, $errstr, $errfile, $errline, array $errcontext)
|
||||
{
|
||||
throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Bootstrap::init($startTime);
|
||||
|
|
126
src/Config.php
126
src/Config.php
|
@ -3,79 +3,79 @@ namespace Szurubooru;
|
|||
|
||||
class Config extends \ArrayObject
|
||||
{
|
||||
private $dataDirectory;
|
||||
private $publicDataDirectory;
|
||||
private $dataDirectory;
|
||||
private $publicDataDirectory;
|
||||
|
||||
public function __construct($dataDirectory, $publicDataDirectory)
|
||||
{
|
||||
$this->setFlags($this->getArrayObjectFlags());
|
||||
$this->dataDirectory = $dataDirectory;
|
||||
$this->publicDataDirectory = $publicDataDirectory;
|
||||
$this->tryLoadFromIni([
|
||||
$dataDirectory . DIRECTORY_SEPARATOR . 'config.ini',
|
||||
$dataDirectory . DIRECTORY_SEPARATOR . 'local.ini']);
|
||||
}
|
||||
public function __construct($dataDirectory, $publicDataDirectory)
|
||||
{
|
||||
$this->setFlags($this->getArrayObjectFlags());
|
||||
$this->dataDirectory = $dataDirectory;
|
||||
$this->publicDataDirectory = $publicDataDirectory;
|
||||
$this->tryLoadFromIni([
|
||||
$dataDirectory . DIRECTORY_SEPARATOR . 'config.ini',
|
||||
$dataDirectory . DIRECTORY_SEPARATOR . 'local.ini']);
|
||||
}
|
||||
|
||||
public function tryLoadFromIni($configPaths)
|
||||
{
|
||||
if (!is_array($configPaths))
|
||||
$configPaths = [$configPaths];
|
||||
public function tryLoadFromIni($configPaths)
|
||||
{
|
||||
if (!is_array($configPaths))
|
||||
$configPaths = [$configPaths];
|
||||
|
||||
foreach ($configPaths as $configPath)
|
||||
{
|
||||
if (file_exists($configPath))
|
||||
$this->loadFromIni($configPath);
|
||||
}
|
||||
}
|
||||
foreach ($configPaths as $configPath)
|
||||
{
|
||||
if (file_exists($configPath))
|
||||
$this->loadFromIni($configPath);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDataDirectory()
|
||||
{
|
||||
return $this->dataDirectory;
|
||||
}
|
||||
public function getDataDirectory()
|
||||
{
|
||||
return $this->dataDirectory;
|
||||
}
|
||||
|
||||
public function getPublicDataDirectory()
|
||||
{
|
||||
return $this->publicDataDirectory;
|
||||
}
|
||||
public function getPublicDataDirectory()
|
||||
{
|
||||
return $this->publicDataDirectory;
|
||||
}
|
||||
|
||||
public function offsetGet($index)
|
||||
{
|
||||
if (!parent::offsetExists($index))
|
||||
return null;
|
||||
return parent::offsetGet($index);
|
||||
}
|
||||
public function offsetGet($index)
|
||||
{
|
||||
if (!parent::offsetExists($index))
|
||||
return null;
|
||||
return parent::offsetGet($index);
|
||||
}
|
||||
|
||||
public function loadFromIni($configPath)
|
||||
{
|
||||
$array = parse_ini_file($configPath, true, INI_SCANNER_RAW);
|
||||
public function loadFromIni($configPath)
|
||||
{
|
||||
$array = parse_ini_file($configPath, true, INI_SCANNER_RAW);
|
||||
|
||||
foreach ($array as $key => $value)
|
||||
{
|
||||
if (!is_array($value))
|
||||
{
|
||||
$this->offsetSet($key, $value);
|
||||
}
|
||||
else
|
||||
{
|
||||
$section = $key;
|
||||
$ptr = $this;
|
||||
foreach ($array as $key => $value)
|
||||
{
|
||||
if (!is_array($value))
|
||||
{
|
||||
$this->offsetSet($key, $value);
|
||||
}
|
||||
else
|
||||
{
|
||||
$section = $key;
|
||||
$ptr = $this;
|
||||
|
||||
foreach (explode('.', $section) as $subSection)
|
||||
{
|
||||
if (!$ptr->offsetExists($subSection))
|
||||
$ptr->offsetSet($subSection, new \ArrayObject([], $this->getArrayObjectFlags()));
|
||||
foreach (explode('.', $section) as $subSection)
|
||||
{
|
||||
if (!$ptr->offsetExists($subSection))
|
||||
$ptr->offsetSet($subSection, new \ArrayObject([], $this->getArrayObjectFlags()));
|
||||
|
||||
$ptr = $ptr->$subSection;
|
||||
}
|
||||
$ptr = $ptr->$subSection;
|
||||
}
|
||||
|
||||
foreach ($value as $sectionKey => $sectionValue)
|
||||
$ptr->offsetSet($sectionKey, $sectionValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($value as $sectionKey => $sectionValue)
|
||||
$ptr->offsetSet($sectionKey, $sectionValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getArrayObjectFlags()
|
||||
{
|
||||
return parent::ARRAY_AS_PROPS | parent::STD_PROP_LIST;
|
||||
}
|
||||
private function getArrayObjectFlags()
|
||||
{
|
||||
return parent::ARRAY_AS_PROPS | parent::STD_PROP_LIST;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,300 +12,300 @@ use Szurubooru\Search\Result;
|
|||
|
||||
abstract class AbstractDao implements ICrudDao, IBatchDao
|
||||
{
|
||||
protected $pdo;
|
||||
protected $tableName;
|
||||
protected $entityConverter;
|
||||
protected $driver;
|
||||
protected $pdo;
|
||||
protected $tableName;
|
||||
protected $entityConverter;
|
||||
protected $driver;
|
||||
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
$tableName,
|
||||
IEntityConverter $entityConverter)
|
||||
{
|
||||
$this->setDatabaseConnection($databaseConnection);
|
||||
$this->tableName = $tableName;
|
||||
$this->entityConverter = $entityConverter;
|
||||
$this->entityConverter->setEntityDecorator(function($entity)
|
||||
{
|
||||
$this->afterLoad($entity);
|
||||
});
|
||||
}
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
$tableName,
|
||||
IEntityConverter $entityConverter)
|
||||
{
|
||||
$this->setDatabaseConnection($databaseConnection);
|
||||
$this->tableName = $tableName;
|
||||
$this->entityConverter = $entityConverter;
|
||||
$this->entityConverter->setEntityDecorator(function($entity)
|
||||
{
|
||||
$this->afterLoad($entity);
|
||||
});
|
||||
}
|
||||
|
||||
public function getTableName()
|
||||
{
|
||||
return $this->tableName;
|
||||
}
|
||||
public function getTableName()
|
||||
{
|
||||
return $this->tableName;
|
||||
}
|
||||
|
||||
public function getEntityConverter()
|
||||
{
|
||||
return $this->entityConverter;
|
||||
}
|
||||
public function getEntityConverter()
|
||||
{
|
||||
return $this->entityConverter;
|
||||
}
|
||||
|
||||
public function save(&$entity)
|
||||
{
|
||||
$entity = $this->upsert($entity);
|
||||
$this->afterSave($entity);
|
||||
$this->afterBatchSave([$entity]);
|
||||
return $entity;
|
||||
}
|
||||
public function save(&$entity)
|
||||
{
|
||||
$entity = $this->upsert($entity);
|
||||
$this->afterSave($entity);
|
||||
$this->afterBatchSave([$entity]);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
public function batchSave(array $entities)
|
||||
{
|
||||
foreach ($entities as $key => $entity)
|
||||
{
|
||||
$entities[$key] = $this->upsert($entity);
|
||||
$this->afterSave($entity);
|
||||
}
|
||||
if (count($entities) > 0)
|
||||
$this->afterBatchSave([$entity]);
|
||||
return $entities;
|
||||
}
|
||||
public function batchSave(array $entities)
|
||||
{
|
||||
foreach ($entities as $key => $entity)
|
||||
{
|
||||
$entities[$key] = $this->upsert($entity);
|
||||
$this->afterSave($entity);
|
||||
}
|
||||
if (count($entities) > 0)
|
||||
$this->afterBatchSave([$entity]);
|
||||
return $entities;
|
||||
}
|
||||
|
||||
public function findAll()
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName);
|
||||
return $this->arrayToEntities($query);
|
||||
}
|
||||
public function findAll()
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName);
|
||||
return $this->arrayToEntities($query);
|
||||
}
|
||||
|
||||
public function findById($entityId)
|
||||
{
|
||||
return $this->findOneBy($this->getIdColumn(), $entityId);
|
||||
}
|
||||
public function findById($entityId)
|
||||
{
|
||||
return $this->findOneBy($this->getIdColumn(), $entityId);
|
||||
}
|
||||
|
||||
public function findByIds($entityIds)
|
||||
{
|
||||
return $this->findBy($this->getIdColumn(), $entityIds);
|
||||
}
|
||||
public function findByIds($entityIds)
|
||||
{
|
||||
return $this->findBy($this->getIdColumn(), $entityIds);
|
||||
}
|
||||
|
||||
public function findFiltered(IFilter $searchFilter)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName);
|
||||
public function findFiltered(IFilter $searchFilter)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName);
|
||||
|
||||
$orderByString = self::compileOrderBy($searchFilter->getOrder());
|
||||
if ($orderByString)
|
||||
$query->orderBy($orderByString);
|
||||
$orderByString = self::compileOrderBy($searchFilter->getOrder());
|
||||
if ($orderByString)
|
||||
$query->orderBy($orderByString);
|
||||
|
||||
$this->decorateQueryFromFilter($query, $searchFilter);
|
||||
if ($searchFilter->getPageSize() > 0)
|
||||
{
|
||||
$query->limit($searchFilter->getPageSize());
|
||||
$query->offset($searchFilter->getPageSize() * max(0, $searchFilter->getPageNumber() - 1));
|
||||
}
|
||||
$entities = $this->arrayToEntities(iterator_to_array($query));
|
||||
$this->decorateQueryFromFilter($query, $searchFilter);
|
||||
if ($searchFilter->getPageSize() > 0)
|
||||
{
|
||||
$query->limit($searchFilter->getPageSize());
|
||||
$query->offset($searchFilter->getPageSize() * max(0, $searchFilter->getPageNumber() - 1));
|
||||
}
|
||||
$entities = $this->arrayToEntities(iterator_to_array($query));
|
||||
|
||||
$query = $this->pdo->from($this->tableName);
|
||||
$this->decorateQueryFromFilter($query, $searchFilter);
|
||||
$totalRecords = count($query);
|
||||
$query = $this->pdo->from($this->tableName);
|
||||
$this->decorateQueryFromFilter($query, $searchFilter);
|
||||
$totalRecords = count($query);
|
||||
|
||||
$searchResult = new Result();
|
||||
$searchResult->setSearchFilter($searchFilter);
|
||||
$searchResult->setEntities($entities);
|
||||
$searchResult->setTotalRecords($totalRecords);
|
||||
$searchResult->setPageNumber($searchFilter->getPageNumber());
|
||||
$searchResult->setPageSize($searchFilter->getPageSize());
|
||||
return $searchResult;
|
||||
}
|
||||
$searchResult = new Result();
|
||||
$searchResult->setSearchFilter($searchFilter);
|
||||
$searchResult->setEntities($entities);
|
||||
$searchResult->setTotalRecords($totalRecords);
|
||||
$searchResult->setPageNumber($searchFilter->getPageNumber());
|
||||
$searchResult->setPageSize($searchFilter->getPageSize());
|
||||
return $searchResult;
|
||||
}
|
||||
|
||||
public function deleteAll()
|
||||
{
|
||||
foreach ($this->findAll() as $entity)
|
||||
{
|
||||
$this->beforeDelete($entity);
|
||||
}
|
||||
$this->pdo->deleteFrom($this->tableName)->execute();
|
||||
}
|
||||
public function deleteAll()
|
||||
{
|
||||
foreach ($this->findAll() as $entity)
|
||||
{
|
||||
$this->beforeDelete($entity);
|
||||
}
|
||||
$this->pdo->deleteFrom($this->tableName)->execute();
|
||||
}
|
||||
|
||||
public function deleteById($entityId)
|
||||
{
|
||||
return $this->deleteBy($this->getIdColumn(), $entityId);
|
||||
}
|
||||
public function deleteById($entityId)
|
||||
{
|
||||
return $this->deleteBy($this->getIdColumn(), $entityId);
|
||||
}
|
||||
|
||||
public function update(Entity $entity)
|
||||
{
|
||||
$arrayEntity = $this->entityConverter->toArray($entity);
|
||||
unset($arrayEntity['id']);
|
||||
$this->pdo->update($this->tableName)->set($arrayEntity)->where($this->getIdColumn(), $entity->getId())->execute();
|
||||
return $entity;
|
||||
}
|
||||
public function update(Entity $entity)
|
||||
{
|
||||
$arrayEntity = $this->entityConverter->toArray($entity);
|
||||
unset($arrayEntity['id']);
|
||||
$this->pdo->update($this->tableName)->set($arrayEntity)->where($this->getIdColumn(), $entity->getId())->execute();
|
||||
return $entity;
|
||||
}
|
||||
|
||||
public function create(Entity $entity)
|
||||
{
|
||||
$sql = 'UPDATE sequencer SET lastUsedId = (@lastUsedId := (lastUsedId + 1)) WHERE tableName = :tableName';
|
||||
$query = $this->pdo->prepare($sql);
|
||||
$query->bindValue(':tableName', $this->tableName);
|
||||
$query->execute();
|
||||
$lastUsedId = $this->pdo->query('SELECT @lastUsedId')->fetchColumn();
|
||||
public function create(Entity $entity)
|
||||
{
|
||||
$sql = 'UPDATE sequencer SET lastUsedId = (@lastUsedId := (lastUsedId + 1)) WHERE tableName = :tableName';
|
||||
$query = $this->pdo->prepare($sql);
|
||||
$query->bindValue(':tableName', $this->tableName);
|
||||
$query->execute();
|
||||
$lastUsedId = $this->pdo->query('SELECT @lastUsedId')->fetchColumn();
|
||||
|
||||
$entity->setId(intval($lastUsedId));
|
||||
$arrayEntity = $this->entityConverter->toArray($entity);
|
||||
$this->pdo->insertInto($this->tableName)->values($arrayEntity)->execute();
|
||||
return $entity;
|
||||
}
|
||||
$entity->setId(intval($lastUsedId));
|
||||
$arrayEntity = $this->entityConverter->toArray($entity);
|
||||
$this->pdo->insertInto($this->tableName)->values($arrayEntity)->execute();
|
||||
return $entity;
|
||||
}
|
||||
|
||||
protected function getIdColumn()
|
||||
{
|
||||
return 'id';
|
||||
}
|
||||
protected function getIdColumn()
|
||||
{
|
||||
return 'id';
|
||||
}
|
||||
|
||||
protected function hasAnyRecords()
|
||||
{
|
||||
return count(iterator_to_array($this->pdo->from($this->tableName)->limit(1))) > 0;
|
||||
}
|
||||
protected function hasAnyRecords()
|
||||
{
|
||||
return count(iterator_to_array($this->pdo->from($this->tableName)->limit(1))) > 0;
|
||||
}
|
||||
|
||||
protected function findBy($columnName, $value)
|
||||
{
|
||||
if (is_array($value) && empty($value))
|
||||
return [];
|
||||
$query = $this->pdo->from($this->tableName)->where($columnName, $value);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
protected function findBy($columnName, $value)
|
||||
{
|
||||
if (is_array($value) && empty($value))
|
||||
return [];
|
||||
$query = $this->pdo->from($this->tableName)->where($columnName, $value);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
|
||||
protected function findOneBy($columnName, $value)
|
||||
{
|
||||
$entities = $this->findBy($columnName, $value);
|
||||
if (!$entities)
|
||||
return null;
|
||||
return array_shift($entities);
|
||||
}
|
||||
protected function findOneBy($columnName, $value)
|
||||
{
|
||||
$entities = $this->findBy($columnName, $value);
|
||||
if (!$entities)
|
||||
return null;
|
||||
return array_shift($entities);
|
||||
}
|
||||
|
||||
protected function deleteBy($columnName, $value)
|
||||
{
|
||||
foreach ($this->findBy($columnName, $value) as $entity)
|
||||
{
|
||||
$this->beforeDelete($entity);
|
||||
}
|
||||
$this->pdo->deleteFrom($this->tableName)->where($columnName, $value)->execute();
|
||||
}
|
||||
protected function deleteBy($columnName, $value)
|
||||
{
|
||||
foreach ($this->findBy($columnName, $value) as $entity)
|
||||
{
|
||||
$this->beforeDelete($entity);
|
||||
}
|
||||
$this->pdo->deleteFrom($this->tableName)->where($columnName, $value)->execute();
|
||||
}
|
||||
|
||||
protected function afterLoad(Entity $entity)
|
||||
{
|
||||
}
|
||||
protected function afterLoad(Entity $entity)
|
||||
{
|
||||
}
|
||||
|
||||
protected function afterSave(Entity $entity)
|
||||
{
|
||||
}
|
||||
protected function afterSave(Entity $entity)
|
||||
{
|
||||
}
|
||||
|
||||
protected function afterBatchSave(array $entities)
|
||||
{
|
||||
}
|
||||
protected function afterBatchSave(array $entities)
|
||||
{
|
||||
}
|
||||
|
||||
protected function beforeDelete(Entity $entity)
|
||||
{
|
||||
}
|
||||
protected function beforeDelete(Entity $entity)
|
||||
{
|
||||
}
|
||||
|
||||
protected function decorateQueryFromRequirement($query, Requirement $requirement)
|
||||
{
|
||||
$value = $requirement->getValue();
|
||||
$sqlColumn = $requirement->getType();
|
||||
protected function decorateQueryFromRequirement($query, Requirement $requirement)
|
||||
{
|
||||
$value = $requirement->getValue();
|
||||
$sqlColumn = $requirement->getType();
|
||||
|
||||
if ($value instanceof RequirementCompositeValue)
|
||||
{
|
||||
$sql = $sqlColumn;
|
||||
$bindings = $value->getValues();
|
||||
if ($value instanceof RequirementCompositeValue)
|
||||
{
|
||||
$sql = $sqlColumn;
|
||||
$bindings = $value->getValues();
|
||||
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
}
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
}
|
||||
|
||||
else if ($value instanceof RequirementRangedValue)
|
||||
{
|
||||
if ($value->getMinValue() && $value->getMaxValue())
|
||||
{
|
||||
$sql = $sqlColumn . ' >= ? AND ' . $sqlColumn . ' <= ?';
|
||||
$bindings = [$value->getMinValue(), $value->getMaxValue()];
|
||||
}
|
||||
elseif ($value->getMinValue())
|
||||
{
|
||||
$sql = $sqlColumn . ' >= ?';
|
||||
$bindings = [$value->getMinValue()];
|
||||
}
|
||||
elseif ($value->getMaxValue())
|
||||
{
|
||||
$sql = $sqlColumn . ' <= ?';
|
||||
$bindings = [$value->getMaxValue()];
|
||||
}
|
||||
else
|
||||
throw new \RuntimeException('Neither min or max value was supplied');
|
||||
else if ($value instanceof RequirementRangedValue)
|
||||
{
|
||||
if ($value->getMinValue() && $value->getMaxValue())
|
||||
{
|
||||
$sql = $sqlColumn . ' >= ? AND ' . $sqlColumn . ' <= ?';
|
||||
$bindings = [$value->getMinValue(), $value->getMaxValue()];
|
||||
}
|
||||
elseif ($value->getMinValue())
|
||||
{
|
||||
$sql = $sqlColumn . ' >= ?';
|
||||
$bindings = [$value->getMinValue()];
|
||||
}
|
||||
elseif ($value->getMaxValue())
|
||||
{
|
||||
$sql = $sqlColumn . ' <= ?';
|
||||
$bindings = [$value->getMaxValue()];
|
||||
}
|
||||
else
|
||||
throw new \RuntimeException('Neither min or max value was supplied');
|
||||
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT (' . $sql . ')';
|
||||
}
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT (' . $sql . ')';
|
||||
}
|
||||
|
||||
else if ($value instanceof RequirementSingleValue)
|
||||
{
|
||||
$sql = $sqlColumn;
|
||||
$bindings = [$value->getValue()];
|
||||
else if ($value instanceof RequirementSingleValue)
|
||||
{
|
||||
$sql = $sqlColumn;
|
||||
$bindings = [$value->getValue()];
|
||||
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
}
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
}
|
||||
|
||||
else
|
||||
throw new \Exception('Bad value: ' . get_class($value));
|
||||
else
|
||||
throw new \Exception('Bad value: ' . get_class($value));
|
||||
|
||||
$query->where($sql, $bindings);
|
||||
}
|
||||
$query->where($sql, $bindings);
|
||||
}
|
||||
|
||||
protected function arrayToEntities($arrayEntities, $entityConverter = null)
|
||||
{
|
||||
if ($entityConverter === null)
|
||||
$entityConverter = $this->entityConverter;
|
||||
protected function arrayToEntities($arrayEntities, $entityConverter = null)
|
||||
{
|
||||
if ($entityConverter === null)
|
||||
$entityConverter = $this->entityConverter;
|
||||
|
||||
$entities = [];
|
||||
foreach ($arrayEntities as $arrayEntity)
|
||||
{
|
||||
$entity = $entityConverter->toEntity($arrayEntity);
|
||||
$entities[$entity->getId()] = $entity;
|
||||
}
|
||||
return $entities;
|
||||
}
|
||||
$entities = [];
|
||||
foreach ($arrayEntities as $arrayEntity)
|
||||
{
|
||||
$entity = $entityConverter->toEntity($arrayEntity);
|
||||
$entities[$entity->getId()] = $entity;
|
||||
}
|
||||
return $entities;
|
||||
}
|
||||
|
||||
private function setDatabaseConnection(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
$this->pdo = $databaseConnection->getPDO();
|
||||
$this->driver = $databaseConnection->getDriver();
|
||||
}
|
||||
private function setDatabaseConnection(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
$this->pdo = $databaseConnection->getPDO();
|
||||
$this->driver = $databaseConnection->getDriver();
|
||||
}
|
||||
|
||||
private function decorateQueryFromFilter($query, IFilter $filter)
|
||||
{
|
||||
foreach ($filter->getRequirements() as $requirement)
|
||||
{
|
||||
$this->decorateQueryFromRequirement($query, $requirement);
|
||||
}
|
||||
}
|
||||
private function decorateQueryFromFilter($query, IFilter $filter)
|
||||
{
|
||||
foreach ($filter->getRequirements() as $requirement)
|
||||
{
|
||||
$this->decorateQueryFromRequirement($query, $requirement);
|
||||
}
|
||||
}
|
||||
|
||||
private function compileOrderBy($order)
|
||||
{
|
||||
$orderByString = '';
|
||||
foreach ($order as $orderColumn => $orderDir)
|
||||
{
|
||||
if ($orderColumn === IFilter::ORDER_RANDOM)
|
||||
{
|
||||
$driver = $this->driver;
|
||||
if ($driver === 'sqlite')
|
||||
{
|
||||
$orderColumn = 'RANDOM()';
|
||||
}
|
||||
else
|
||||
{
|
||||
$orderColumn = 'RAND()';
|
||||
}
|
||||
}
|
||||
$orderByString .= $orderColumn . ' ' . ($orderDir === IFilter::ORDER_DESC ? 'DESC' : 'ASC') . ', ';
|
||||
}
|
||||
return substr($orderByString, 0, -2);
|
||||
}
|
||||
private function compileOrderBy($order)
|
||||
{
|
||||
$orderByString = '';
|
||||
foreach ($order as $orderColumn => $orderDir)
|
||||
{
|
||||
if ($orderColumn === IFilter::ORDER_RANDOM)
|
||||
{
|
||||
$driver = $this->driver;
|
||||
if ($driver === 'sqlite')
|
||||
{
|
||||
$orderColumn = 'RANDOM()';
|
||||
}
|
||||
else
|
||||
{
|
||||
$orderColumn = 'RAND()';
|
||||
}
|
||||
}
|
||||
$orderByString .= $orderColumn . ' ' . ($orderDir === IFilter::ORDER_DESC ? 'DESC' : 'ASC') . ', ';
|
||||
}
|
||||
return substr($orderByString, 0, -2);
|
||||
}
|
||||
|
||||
private function upsert(Entity $entity)
|
||||
{
|
||||
if ($entity->getId())
|
||||
{
|
||||
return $this->update($entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->create($entity);
|
||||
}
|
||||
}
|
||||
private function upsert(Entity $entity)
|
||||
{
|
||||
if ($entity->getId())
|
||||
{
|
||||
return $this->update($entity);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->create($entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,42 +10,42 @@ use Szurubooru\Entities\Post;
|
|||
|
||||
class CommentDao extends AbstractDao implements ICrudDao
|
||||
{
|
||||
private $userDao;
|
||||
private $postDao;
|
||||
private $userDao;
|
||||
private $postDao;
|
||||
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
UserDao $userDao,
|
||||
PostDao $postDao)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'comments',
|
||||
new CommentEntityConverter());
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
UserDao $userDao,
|
||||
PostDao $postDao)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'comments',
|
||||
new CommentEntityConverter());
|
||||
|
||||
$this->userDao = $userDao;
|
||||
$this->postDao = $postDao;
|
||||
}
|
||||
$this->userDao = $userDao;
|
||||
$this->postDao = $postDao;
|
||||
}
|
||||
|
||||
public function findByPost(Post $post)
|
||||
{
|
||||
return $this->findBy('postId', $post->getId());
|
||||
}
|
||||
public function findByPost(Post $post)
|
||||
{
|
||||
return $this->findBy('postId', $post->getId());
|
||||
}
|
||||
|
||||
protected function afterLoad(Entity $comment)
|
||||
{
|
||||
$comment->setLazyLoader(
|
||||
Comment::LAZY_LOADER_USER,
|
||||
function (Comment $comment)
|
||||
{
|
||||
return $this->userDao->findById($comment->getUserId());
|
||||
});
|
||||
protected function afterLoad(Entity $comment)
|
||||
{
|
||||
$comment->setLazyLoader(
|
||||
Comment::LAZY_LOADER_USER,
|
||||
function (Comment $comment)
|
||||
{
|
||||
return $this->userDao->findById($comment->getUserId());
|
||||
});
|
||||
|
||||
$comment->setLazyLoader(
|
||||
Comment::LAZY_LOADER_POST,
|
||||
function (Comment $comment)
|
||||
{
|
||||
return $this->postDao->findById($comment->getPostId());
|
||||
});
|
||||
}
|
||||
$comment->setLazyLoader(
|
||||
Comment::LAZY_LOADER_POST,
|
||||
function (Comment $comment)
|
||||
{
|
||||
return $this->postDao->findById($comment->getPostId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,43 +5,43 @@ use Szurubooru\Entities\Entity;
|
|||
|
||||
abstract class AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
private $entityDecorator = null;
|
||||
private $entityDecorator = null;
|
||||
|
||||
public function setEntityDecorator(callable $entityDecorator)
|
||||
{
|
||||
$this->entityDecorator = $entityDecorator;
|
||||
}
|
||||
public function setEntityDecorator(callable $entityDecorator)
|
||||
{
|
||||
$this->entityDecorator = $entityDecorator;
|
||||
}
|
||||
|
||||
public function toEntity(array $array)
|
||||
{
|
||||
$entity = $this->toBasicEntity($array);
|
||||
$func = $this->entityDecorator;
|
||||
if ($func !== null)
|
||||
$func($entity);
|
||||
return $entity;
|
||||
}
|
||||
public function toEntity(array $array)
|
||||
{
|
||||
$entity = $this->toBasicEntity($array);
|
||||
$func = $this->entityDecorator;
|
||||
if ($func !== null)
|
||||
$func($entity);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
public function toArray(Entity $entity)
|
||||
{
|
||||
$array = $this->toBasicArray($entity);
|
||||
if ($entity->getId() !== null)
|
||||
$array['id'] = $entity->getId();
|
||||
return $array;
|
||||
}
|
||||
public function toArray(Entity $entity)
|
||||
{
|
||||
$array = $this->toBasicArray($entity);
|
||||
if ($entity->getId() !== null)
|
||||
$array['id'] = $entity->getId();
|
||||
return $array;
|
||||
}
|
||||
|
||||
protected abstract function toBasicEntity(array $array);
|
||||
protected abstract function toBasicEntity(array $array);
|
||||
|
||||
protected abstract function toBasicArray(Entity $entity);
|
||||
protected abstract function toBasicArray(Entity $entity);
|
||||
|
||||
protected function dbTimeToEntityTime($time)
|
||||
{
|
||||
if ($time === null)
|
||||
return null;
|
||||
return date('c', strtotime($time));
|
||||
}
|
||||
protected function dbTimeToEntityTime($time)
|
||||
{
|
||||
if ($time === null)
|
||||
return null;
|
||||
return date('c', strtotime($time));
|
||||
}
|
||||
|
||||
protected function entityTimeToDbTime($time)
|
||||
{
|
||||
return $time === null ? null : date('Y-m-d H:i:s', strtotime($time));
|
||||
}
|
||||
protected function entityTimeToDbTime($time)
|
||||
{
|
||||
return $time === null ? null : date('Y-m-d H:i:s', strtotime($time));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,27 +5,27 @@ use Szurubooru\Entities\Entity;
|
|||
|
||||
class CommentEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'userId' => $entity->getUserId(),
|
||||
'postId' => $entity->getPostId(),
|
||||
'text' => $entity->getText(),
|
||||
'creationTime' => $this->entityTimeToDbTime($entity->getCreationTime()),
|
||||
'lastEditTime' => $this->entityTimeToDbTime($entity->getLastEditTime()),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'userId' => $entity->getUserId(),
|
||||
'postId' => $entity->getPostId(),
|
||||
'text' => $entity->getText(),
|
||||
'creationTime' => $this->entityTimeToDbTime($entity->getCreationTime()),
|
||||
'lastEditTime' => $this->entityTimeToDbTime($entity->getLastEditTime()),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Comment(intval($array['id']));
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setText($array['text']);
|
||||
$entity->setCreationTime($this->dbTimeToEntityTime($array['creationTime']));
|
||||
$entity->setLastEditTime($this->dbTimeToEntityTime($array['lastEditTime']));
|
||||
$entity->setMeta(Comment::META_SCORE, intval($array['score']));
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Comment(intval($array['id']));
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setText($array['text']);
|
||||
$entity->setCreationTime($this->dbTimeToEntityTime($array['creationTime']));
|
||||
$entity->setLastEditTime($this->dbTimeToEntityTime($array['lastEditTime']));
|
||||
$entity->setMeta(Comment::META_SCORE, intval($array['score']));
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,22 +5,22 @@ use Szurubooru\Entities\Favorite;
|
|||
|
||||
class FavoriteEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'userId' => $entity->getUserId(),
|
||||
'postId' => $entity->getPostId(),
|
||||
'time' => $this->entityTimeToDbTime($entity->getTime()),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'userId' => $entity->getUserId(),
|
||||
'postId' => $entity->getPostId(),
|
||||
'time' => $this->entityTimeToDbTime($entity->getTime()),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Favorite(intval($array['id']));
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setTime($this->dbTimeToEntityTime($array['time']));
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Favorite(intval($array['id']));
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setTime($this->dbTimeToEntityTime($array['time']));
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,20 +5,20 @@ use Szurubooru\Entities\GlobalParam;
|
|||
|
||||
class GlobalParamEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'dataKey' => $entity->getKey(),
|
||||
'dataValue' => $entity->getValue(),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'dataKey' => $entity->getKey(),
|
||||
'dataValue' => $entity->getValue(),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new GlobalParam(intval($array['id']));
|
||||
$entity->setKey($array['dataKey']);
|
||||
$entity->setValue($array['dataValue']);
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new GlobalParam(intval($array['id']));
|
||||
$entity->setKey($array['dataKey']);
|
||||
$entity->setValue($array['dataValue']);
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use Szurubooru\Entities\Entity;
|
|||
|
||||
interface IEntityConverter
|
||||
{
|
||||
public function toArray(Entity $entity);
|
||||
public function toArray(Entity $entity);
|
||||
|
||||
public function toEntity(array $array);
|
||||
public function toEntity(array $array);
|
||||
}
|
||||
|
|
|
@ -5,52 +5,52 @@ use Szurubooru\Entities\Post;
|
|||
|
||||
class PostEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'name' => $entity->getName(),
|
||||
'userId' => $entity->getUserId(),
|
||||
'uploadTime' => $this->entityTimeToDbTime($entity->getUploadTime()),
|
||||
'lastEditTime' => $this->entityTimeToDbTime($entity->getLastEditTime()),
|
||||
'safety' => $entity->getSafety(),
|
||||
'contentType' => $entity->getContentType(),
|
||||
'contentChecksum' => $entity->getContentChecksum(),
|
||||
'contentMimeType' => $entity->getContentMimeType(),
|
||||
'source' => $entity->getSource(),
|
||||
'imageWidth' => $entity->getImageWidth(),
|
||||
'imageHeight' => $entity->getImageHeight(),
|
||||
'originalFileSize' => $entity->getOriginalFileSize(),
|
||||
'originalFileName' => $entity->getOriginalFileName(),
|
||||
'featureCount' => $entity->getFeatureCount(),
|
||||
'lastFeatureTime' => $this->entityTimeToDbTime($entity->getLastFeatureTime()),
|
||||
'flags' => $entity->getFlags(),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'name' => $entity->getName(),
|
||||
'userId' => $entity->getUserId(),
|
||||
'uploadTime' => $this->entityTimeToDbTime($entity->getUploadTime()),
|
||||
'lastEditTime' => $this->entityTimeToDbTime($entity->getLastEditTime()),
|
||||
'safety' => $entity->getSafety(),
|
||||
'contentType' => $entity->getContentType(),
|
||||
'contentChecksum' => $entity->getContentChecksum(),
|
||||
'contentMimeType' => $entity->getContentMimeType(),
|
||||
'source' => $entity->getSource(),
|
||||
'imageWidth' => $entity->getImageWidth(),
|
||||
'imageHeight' => $entity->getImageHeight(),
|
||||
'originalFileSize' => $entity->getOriginalFileSize(),
|
||||
'originalFileName' => $entity->getOriginalFileName(),
|
||||
'featureCount' => $entity->getFeatureCount(),
|
||||
'lastFeatureTime' => $this->entityTimeToDbTime($entity->getLastFeatureTime()),
|
||||
'flags' => $entity->getFlags(),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Post(intval($array['id']));
|
||||
$entity->setName($array['name']);
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setUploadTime($this->dbTimeToEntityTime($array['uploadTime']));
|
||||
$entity->setLastEditTime($this->dbTimeToEntityTime($array['lastEditTime']));
|
||||
$entity->setSafety(intval($array['safety']));
|
||||
$entity->setContentType(intval($array['contentType']));
|
||||
$entity->setContentChecksum($array['contentChecksum']);
|
||||
$entity->setContentMimeType($array['contentMimeType']);
|
||||
$entity->setSource($array['source']);
|
||||
$entity->setImageWidth($array['imageWidth']);
|
||||
$entity->setImageHeight($array['imageHeight']);
|
||||
$entity->setOriginalFileSize($array['originalFileSize']);
|
||||
$entity->setOriginalFileName($array['originalFileName']);
|
||||
$entity->setFeatureCount(intval($array['featureCount']));
|
||||
$entity->setLastFeatureTime($this->dbTimeToEntityTime($array['lastFeatureTime']));
|
||||
$entity->setFlags(intval($array['flags']));
|
||||
$entity->setMeta(Post::META_TAG_COUNT, intval($array['tagCount']));
|
||||
$entity->setMeta(Post::META_FAV_COUNT, intval($array['favCount']));
|
||||
$entity->setMeta(Post::META_COMMENT_COUNT, intval($array['commentCount']));
|
||||
$entity->setMeta(Post::META_SCORE, intval($array['score']));
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Post(intval($array['id']));
|
||||
$entity->setName($array['name']);
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setUploadTime($this->dbTimeToEntityTime($array['uploadTime']));
|
||||
$entity->setLastEditTime($this->dbTimeToEntityTime($array['lastEditTime']));
|
||||
$entity->setSafety(intval($array['safety']));
|
||||
$entity->setContentType(intval($array['contentType']));
|
||||
$entity->setContentChecksum($array['contentChecksum']);
|
||||
$entity->setContentMimeType($array['contentMimeType']);
|
||||
$entity->setSource($array['source']);
|
||||
$entity->setImageWidth($array['imageWidth']);
|
||||
$entity->setImageHeight($array['imageHeight']);
|
||||
$entity->setOriginalFileSize($array['originalFileSize']);
|
||||
$entity->setOriginalFileName($array['originalFileName']);
|
||||
$entity->setFeatureCount(intval($array['featureCount']));
|
||||
$entity->setLastFeatureTime($this->dbTimeToEntityTime($array['lastFeatureTime']));
|
||||
$entity->setFlags(intval($array['flags']));
|
||||
$entity->setMeta(Post::META_TAG_COUNT, intval($array['tagCount']));
|
||||
$entity->setMeta(Post::META_FAV_COUNT, intval($array['favCount']));
|
||||
$entity->setMeta(Post::META_COMMENT_COUNT, intval($array['commentCount']));
|
||||
$entity->setMeta(Post::META_SCORE, intval($array['score']));
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,28 +5,28 @@ use Szurubooru\Entities\PostNote;
|
|||
|
||||
class PostNoteEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'postId' => $entity->getPostId(),
|
||||
'x' => $entity->getLeft(),
|
||||
'y' => $entity->getTop(),
|
||||
'width' => $entity->getWidth(),
|
||||
'height' => $entity->getHeight(),
|
||||
'text' => $entity->getText(),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'postId' => $entity->getPostId(),
|
||||
'x' => $entity->getLeft(),
|
||||
'y' => $entity->getTop(),
|
||||
'width' => $entity->getWidth(),
|
||||
'height' => $entity->getHeight(),
|
||||
'text' => $entity->getText(),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new PostNote(intval($array['id']));
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setLeft(floatval($array['x']));
|
||||
$entity->setTop(floatval($array['y']));
|
||||
$entity->setWidth(floatval($array['width']));
|
||||
$entity->setHeight(floatval($array['height']));
|
||||
$entity->setText($array['text']);
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new PostNote(intval($array['id']));
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setLeft(floatval($array['x']));
|
||||
$entity->setTop(floatval($array['y']));
|
||||
$entity->setWidth(floatval($array['width']));
|
||||
$entity->setHeight(floatval($array['height']));
|
||||
$entity->setText($array['text']);
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,26 +5,26 @@ use Szurubooru\Entities\Score;
|
|||
|
||||
class ScoreEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'userId' => $entity->getUserId(),
|
||||
'postId' => $entity->getPostId(),
|
||||
'commentId' => $entity->getCommentId(),
|
||||
'time' => $this->entityTimeToDbTime($entity->getTime()),
|
||||
'score' => $entity->getScore(),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'userId' => $entity->getUserId(),
|
||||
'postId' => $entity->getPostId(),
|
||||
'commentId' => $entity->getCommentId(),
|
||||
'time' => $this->entityTimeToDbTime($entity->getTime()),
|
||||
'score' => $entity->getScore(),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Score(intval($array['id']));
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setCommentId($array['commentId']);
|
||||
$entity->setTime($this->dbTimeToEntityTime($array['time']));
|
||||
$entity->setScore(intval($array['score']));
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Score(intval($array['id']));
|
||||
$entity->setUserId($array['userId']);
|
||||
$entity->setPostId($array['postId']);
|
||||
$entity->setCommentId($array['commentId']);
|
||||
$entity->setTime($this->dbTimeToEntityTime($array['time']));
|
||||
$entity->setScore(intval($array['score']));
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,30 +5,30 @@ use Szurubooru\Entities\Snapshot;
|
|||
|
||||
class SnapshotEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'time' => $this->entityTimeToDbTime($entity->getTime()),
|
||||
'type' => $entity->getType(),
|
||||
'primaryKey' => $entity->getPrimaryKey(),
|
||||
'userId' => $entity->getUserId(),
|
||||
'operation' => $entity->getOperation(),
|
||||
'data' => gzdeflate(json_encode($entity->getData())),
|
||||
'dataDifference' => gzdeflate(json_encode($entity->getDataDifference())),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'time' => $this->entityTimeToDbTime($entity->getTime()),
|
||||
'type' => $entity->getType(),
|
||||
'primaryKey' => $entity->getPrimaryKey(),
|
||||
'userId' => $entity->getUserId(),
|
||||
'operation' => $entity->getOperation(),
|
||||
'data' => gzdeflate(json_encode($entity->getData())),
|
||||
'dataDifference' => gzdeflate(json_encode($entity->getDataDifference())),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Snapshot(intval($array['id']));
|
||||
$entity->setTime($this->dbTimeToEntityTime($array['time']));
|
||||
$entity->setType(intval($array['type']));
|
||||
$entity->setPrimaryKey($array['primaryKey']);
|
||||
$entity->setUserId(intval($array['userId']));
|
||||
$entity->setOperation($array['operation']);
|
||||
$entity->setData(json_decode(gzinflate($array['data']), true));
|
||||
$entity->setDataDifference(json_decode(gzinflate($array['dataDifference']), true));
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Snapshot(intval($array['id']));
|
||||
$entity->setTime($this->dbTimeToEntityTime($array['time']));
|
||||
$entity->setType(intval($array['type']));
|
||||
$entity->setPrimaryKey($array['primaryKey']);
|
||||
$entity->setUserId(intval($array['userId']));
|
||||
$entity->setOperation($array['operation']);
|
||||
$entity->setData(json_decode(gzinflate($array['data']), true));
|
||||
$entity->setDataDifference(json_decode(gzinflate($array['dataDifference']), true));
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,25 +5,25 @@ use Szurubooru\Entities\Tag;
|
|||
|
||||
class TagEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'name' => $entity->getName(),
|
||||
'creationTime' => $this->entityTimeToDbTime($entity->getCreationTime()),
|
||||
'banned' => intval($entity->isBanned()),
|
||||
'category' => $entity->getCategory(),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'name' => $entity->getName(),
|
||||
'creationTime' => $this->entityTimeToDbTime($entity->getCreationTime()),
|
||||
'banned' => intval($entity->isBanned()),
|
||||
'category' => $entity->getCategory(),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Tag(intval($array['id']));
|
||||
$entity->setName($array['name']);
|
||||
$entity->setCreationTime($this->dbTimeToEntityTime($array['creationTime']));
|
||||
$entity->setMeta(Tag::META_USAGES, intval($array['usages']));
|
||||
$entity->setBanned($array['banned']);
|
||||
$entity->setCategory($array['category']);
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Tag(intval($array['id']));
|
||||
$entity->setName($array['name']);
|
||||
$entity->setCreationTime($this->dbTimeToEntityTime($array['creationTime']));
|
||||
$entity->setMeta(Tag::META_USAGES, intval($array['usages']));
|
||||
$entity->setBanned($array['banned']);
|
||||
$entity->setCategory($array['category']);
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,22 +5,22 @@ use Szurubooru\Entities\Token;
|
|||
|
||||
class TokenEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'name' => $entity->getName(),
|
||||
'purpose' => $entity->getPurpose(),
|
||||
'additionalData' => $entity->getAdditionalData(),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'name' => $entity->getName(),
|
||||
'purpose' => $entity->getPurpose(),
|
||||
'additionalData' => $entity->getAdditionalData(),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Token(intval($array['id']));
|
||||
$entity->setName($array['name']);
|
||||
$entity->setPurpose($array['purpose']);
|
||||
$entity->setAdditionalData($array['additionalData']);
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new Token(intval($array['id']));
|
||||
$entity->setName($array['name']);
|
||||
$entity->setPurpose($array['purpose']);
|
||||
$entity->setAdditionalData($array['additionalData']);
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,40 +5,40 @@ use Szurubooru\Entities\User;
|
|||
|
||||
class UserEntityConverter extends AbstractEntityConverter implements IEntityConverter
|
||||
{
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'name' => $entity->getName(),
|
||||
'email' => $entity->getEmail(),
|
||||
'emailUnconfirmed' => $entity->getEmailUnconfirmed(),
|
||||
'passwordHash' => $entity->getPasswordHash(),
|
||||
'passwordSalt' => $entity->getPasswordSalt(),
|
||||
'accessRank' => $entity->getAccessRank(),
|
||||
'registrationTime' => $this->entityTimeToDbTime($entity->getRegistrationTime()),
|
||||
'lastLoginTime' => $this->entityTimeToDbTime($entity->getLastLoginTime()),
|
||||
'avatarStyle' => $entity->getAvatarStyle(),
|
||||
'browsingSettings' => json_encode($entity->getBrowsingSettings()),
|
||||
'accountConfirmed' => intval($entity->isAccountConfirmed()),
|
||||
'banned' => intval($entity->isBanned()),
|
||||
];
|
||||
}
|
||||
public function toBasicArray(Entity $entity)
|
||||
{
|
||||
return
|
||||
[
|
||||
'name' => $entity->getName(),
|
||||
'email' => $entity->getEmail(),
|
||||
'emailUnconfirmed' => $entity->getEmailUnconfirmed(),
|
||||
'passwordHash' => $entity->getPasswordHash(),
|
||||
'passwordSalt' => $entity->getPasswordSalt(),
|
||||
'accessRank' => $entity->getAccessRank(),
|
||||
'registrationTime' => $this->entityTimeToDbTime($entity->getRegistrationTime()),
|
||||
'lastLoginTime' => $this->entityTimeToDbTime($entity->getLastLoginTime()),
|
||||
'avatarStyle' => $entity->getAvatarStyle(),
|
||||
'browsingSettings' => json_encode($entity->getBrowsingSettings()),
|
||||
'accountConfirmed' => intval($entity->isAccountConfirmed()),
|
||||
'banned' => intval($entity->isBanned()),
|
||||
];
|
||||
}
|
||||
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new User(intval($array['id']));
|
||||
$entity->setName($array['name']);
|
||||
$entity->setEmail($array['email']);
|
||||
$entity->setEmailUnconfirmed($array['emailUnconfirmed']);
|
||||
$entity->setPasswordHash($array['passwordHash']);
|
||||
$entity->setPasswordSalt($array['passwordSalt']);
|
||||
$entity->setAccessRank(intval($array['accessRank']));
|
||||
$entity->setRegistrationTime($this->dbTimeToEntityTime($array['registrationTime']));
|
||||
$entity->setLastLoginTime($this->dbTimeToEntityTime($array['lastLoginTime']));
|
||||
$entity->setAvatarStyle(intval($array['avatarStyle']));
|
||||
$entity->setBrowsingSettings(json_decode($array['browsingSettings']));
|
||||
$entity->setAccountConfirmed($array['accountConfirmed']);
|
||||
$entity->setBanned($array['banned']);
|
||||
return $entity;
|
||||
}
|
||||
public function toBasicEntity(array $array)
|
||||
{
|
||||
$entity = new User(intval($array['id']));
|
||||
$entity->setName($array['name']);
|
||||
$entity->setEmail($array['email']);
|
||||
$entity->setEmailUnconfirmed($array['emailUnconfirmed']);
|
||||
$entity->setPasswordHash($array['passwordHash']);
|
||||
$entity->setPasswordSalt($array['passwordSalt']);
|
||||
$entity->setAccessRank(intval($array['accessRank']));
|
||||
$entity->setRegistrationTime($this->dbTimeToEntityTime($array['registrationTime']));
|
||||
$entity->setLastLoginTime($this->dbTimeToEntityTime($array['lastLoginTime']));
|
||||
$entity->setAvatarStyle(intval($array['avatarStyle']));
|
||||
$entity->setBrowsingSettings(json_decode($array['browsingSettings']));
|
||||
$entity->setAccountConfirmed($array['accountConfirmed']);
|
||||
$entity->setBanned($array['banned']);
|
||||
return $entity;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,65 +10,65 @@ use Szurubooru\Services\TimeService;
|
|||
|
||||
class FavoritesDao extends AbstractDao implements ICrudDao
|
||||
{
|
||||
private $timeService;
|
||||
private $timeService;
|
||||
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
TimeService $timeService)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'favorites',
|
||||
new FavoriteEntityConverter());
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
TimeService $timeService)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'favorites',
|
||||
new FavoriteEntityConverter());
|
||||
|
||||
$this->timeService = $timeService;
|
||||
}
|
||||
$this->timeService = $timeService;
|
||||
}
|
||||
|
||||
public function findByEntity(Entity $entity)
|
||||
{
|
||||
if ($entity instanceof Post)
|
||||
return $this->findBy('postId', $entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
public function findByEntity(Entity $entity)
|
||||
{
|
||||
if ($entity instanceof Post)
|
||||
return $this->findBy('postId', $entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
|
||||
public function set(User $user, Entity $entity)
|
||||
{
|
||||
$favorite = $this->get($user, $entity);
|
||||
if (!$favorite)
|
||||
{
|
||||
$favorite = new Favorite();
|
||||
$favorite->setTime($this->timeService->getCurrentTime());
|
||||
$favorite->setUserId($user->getId());
|
||||
public function set(User $user, Entity $entity)
|
||||
{
|
||||
$favorite = $this->get($user, $entity);
|
||||
if (!$favorite)
|
||||
{
|
||||
$favorite = new Favorite();
|
||||
$favorite->setTime($this->timeService->getCurrentTime());
|
||||
$favorite->setUserId($user->getId());
|
||||
|
||||
if ($entity instanceof Post)
|
||||
$favorite->setPostId($entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
if ($entity instanceof Post)
|
||||
$favorite->setPostId($entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
|
||||
$this->save($favorite);
|
||||
}
|
||||
return $favorite;
|
||||
}
|
||||
$this->save($favorite);
|
||||
}
|
||||
return $favorite;
|
||||
}
|
||||
|
||||
public function delete(User $user, Entity $entity)
|
||||
{
|
||||
$favorite = $this->get($user, $entity);
|
||||
if ($favorite)
|
||||
$this->deleteById($favorite->getId());
|
||||
}
|
||||
public function delete(User $user, Entity $entity)
|
||||
{
|
||||
$favorite = $this->get($user, $entity);
|
||||
if ($favorite)
|
||||
$this->deleteById($favorite->getId());
|
||||
}
|
||||
|
||||
private function get(User $user, Entity $entity)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName)->where('userId', $user->getId());
|
||||
private function get(User $user, Entity $entity)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName)->where('userId', $user->getId());
|
||||
|
||||
if ($entity instanceof Post)
|
||||
$query->where('postId', $entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
if ($entity instanceof Post)
|
||||
$query->where('postId', $entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
$entities = $this->arrayToEntities($arrayEntities);
|
||||
return array_shift($entities);
|
||||
}
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
$entities = $this->arrayToEntities($arrayEntities);
|
||||
return array_shift($entities);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,93 +4,93 @@ use Szurubooru\Dao\IFileDao;
|
|||
|
||||
class FileDao implements IFileDao
|
||||
{
|
||||
private $directory;
|
||||
private $directory;
|
||||
|
||||
public function __construct($directory)
|
||||
{
|
||||
$this->directory = $directory;
|
||||
}
|
||||
public function __construct($directory)
|
||||
{
|
||||
$this->directory = $directory;
|
||||
}
|
||||
|
||||
public function load($fileName)
|
||||
{
|
||||
$fullPath = $this->getFullPath($fileName);
|
||||
return file_exists($fullPath)
|
||||
? file_get_contents($fullPath)
|
||||
: null;
|
||||
}
|
||||
public function load($fileName)
|
||||
{
|
||||
$fullPath = $this->getFullPath($fileName);
|
||||
return file_exists($fullPath)
|
||||
? file_get_contents($fullPath)
|
||||
: null;
|
||||
}
|
||||
|
||||
public function save($fileName, $data)
|
||||
{
|
||||
$fullPath = $this->getFullPath($fileName);
|
||||
$this->createFolders($fileName);
|
||||
file_put_contents($fullPath, $data);
|
||||
}
|
||||
public function save($fileName, $data)
|
||||
{
|
||||
$fullPath = $this->getFullPath($fileName);
|
||||
$this->createFolders($fileName);
|
||||
file_put_contents($fullPath, $data);
|
||||
}
|
||||
|
||||
public function delete($fileName)
|
||||
{
|
||||
$fullPath = $this->getFullPath($fileName);
|
||||
if (file_exists($fullPath))
|
||||
unlink($fullPath);
|
||||
}
|
||||
public function delete($fileName)
|
||||
{
|
||||
$fullPath = $this->getFullPath($fileName);
|
||||
if (file_exists($fullPath))
|
||||
unlink($fullPath);
|
||||
}
|
||||
|
||||
public function exists($fileName)
|
||||
{
|
||||
$fullPath = $this->getFullPath($fileName);
|
||||
return file_exists($fullPath);
|
||||
}
|
||||
public function exists($fileName)
|
||||
{
|
||||
$fullPath = $this->getFullPath($fileName);
|
||||
return file_exists($fullPath);
|
||||
}
|
||||
|
||||
public function getFullPath($fileName)
|
||||
{
|
||||
return $this->directory . DIRECTORY_SEPARATOR . $fileName;
|
||||
}
|
||||
public function getFullPath($fileName)
|
||||
{
|
||||
return $this->directory . DIRECTORY_SEPARATOR . $fileName;
|
||||
}
|
||||
|
||||
public function listAll()
|
||||
{
|
||||
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory));
|
||||
$files = [];
|
||||
foreach ($iterator as $path)
|
||||
{
|
||||
if (!$path->isDir())
|
||||
$files[] = $this->getRelativePath($this->directory, $path->getPathName());
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
public function listAll()
|
||||
{
|
||||
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory));
|
||||
$files = [];
|
||||
foreach ($iterator as $path)
|
||||
{
|
||||
if (!$path->isDir())
|
||||
$files[] = $this->getRelativePath($this->directory, $path->getPathName());
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
|
||||
private function createFolders($fileName)
|
||||
{
|
||||
$fullPath = dirname($this->getFullPath($fileName));
|
||||
if (!file_exists($fullPath))
|
||||
mkdir($fullPath, 0777, true);
|
||||
}
|
||||
private function createFolders($fileName)
|
||||
{
|
||||
$fullPath = dirname($this->getFullPath($fileName));
|
||||
if (!file_exists($fullPath))
|
||||
mkdir($fullPath, 0777, true);
|
||||
}
|
||||
|
||||
private function getRelativePath($from, $to)
|
||||
{
|
||||
$from = is_dir($from) ? rtrim($from, '\/') . '/' : $from;
|
||||
$to = is_dir($to) ? rtrim($to, '\/') . '/' : $to;
|
||||
$from = explode('/', str_replace('\\', '/', $from));
|
||||
$to = explode('/', str_replace('\\', '/', $to));
|
||||
$relPath = $to;
|
||||
foreach($from as $depth => $dir)
|
||||
{
|
||||
if($dir === $to[$depth])
|
||||
{
|
||||
array_shift($relPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
$remaining = count($from) - $depth;
|
||||
if ($remaining > 1)
|
||||
{
|
||||
$padLength = (count($relPath) + $remaining - 1) * -1;
|
||||
$relPath = array_pad($relPath, $padLength, '..');
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$relPath[0] = $relPath[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode('/', $relPath);
|
||||
}
|
||||
private function getRelativePath($from, $to)
|
||||
{
|
||||
$from = is_dir($from) ? rtrim($from, '\/') . '/' : $from;
|
||||
$to = is_dir($to) ? rtrim($to, '\/') . '/' : $to;
|
||||
$from = explode('/', str_replace('\\', '/', $from));
|
||||
$to = explode('/', str_replace('\\', '/', $to));
|
||||
$relPath = $to;
|
||||
foreach($from as $depth => $dir)
|
||||
{
|
||||
if($dir === $to[$depth])
|
||||
{
|
||||
array_shift($relPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
$remaining = count($from) - $depth;
|
||||
if ($remaining > 1)
|
||||
{
|
||||
$padLength = (count($relPath) + $remaining - 1) * -1;
|
||||
$relPath = array_pad($relPath, $padLength, '..');
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$relPath[0] = $relPath[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode('/', $relPath);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,32 +5,32 @@ use Szurubooru\DatabaseConnection;
|
|||
|
||||
class GlobalParamDao extends AbstractDao implements ICrudDao
|
||||
{
|
||||
public function __construct(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'globals',
|
||||
new GlobalParamEntityConverter());
|
||||
}
|
||||
public function __construct(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'globals',
|
||||
new GlobalParamEntityConverter());
|
||||
}
|
||||
|
||||
public function save(&$entity)
|
||||
{
|
||||
if (!$entity->getId())
|
||||
{
|
||||
$otherEntityWithThisKey = $this->findByKey($entity->getKey());
|
||||
if ($otherEntityWithThisKey)
|
||||
$entity->setId($otherEntityWithThisKey->getId());
|
||||
}
|
||||
parent::save($entity);
|
||||
}
|
||||
public function save(&$entity)
|
||||
{
|
||||
if (!$entity->getId())
|
||||
{
|
||||
$otherEntityWithThisKey = $this->findByKey($entity->getKey());
|
||||
if ($otherEntityWithThisKey)
|
||||
$entity->setId($otherEntityWithThisKey->getId());
|
||||
}
|
||||
parent::save($entity);
|
||||
}
|
||||
|
||||
public function findByKey($key)
|
||||
{
|
||||
return $this->findOneBy('dataKey', $key);
|
||||
}
|
||||
public function findByKey($key)
|
||||
{
|
||||
return $this->findOneBy('dataKey', $key);
|
||||
}
|
||||
|
||||
public function deleteByKey($key)
|
||||
{
|
||||
return $this->deleteBy('dataKey', $key);
|
||||
}
|
||||
public function deleteByKey($key)
|
||||
{
|
||||
return $this->deleteBy('dataKey', $key);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ namespace Szurubooru\Dao;
|
|||
|
||||
interface IBatchDao
|
||||
{
|
||||
public function findAll();
|
||||
public function findAll();
|
||||
|
||||
public function deleteAll();
|
||||
public function deleteAll();
|
||||
|
||||
public function batchSave(array $objects);
|
||||
public function batchSave(array $objects);
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ namespace Szurubooru\Dao;
|
|||
|
||||
interface ICrudDao
|
||||
{
|
||||
public function findById($objectId);
|
||||
public function findById($objectId);
|
||||
|
||||
public function save(&$object);
|
||||
public function save(&$object);
|
||||
|
||||
public function deleteById($objectId);
|
||||
public function deleteById($objectId);
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@ namespace Szurubooru\Dao;
|
|||
|
||||
interface IFileDao
|
||||
{
|
||||
public function load($fileName);
|
||||
public function load($fileName);
|
||||
|
||||
public function save($fileName, $contents);
|
||||
public function save($fileName, $contents);
|
||||
|
||||
public function delete($fileName);
|
||||
public function delete($fileName);
|
||||
|
||||
public function exists($fileName);
|
||||
public function exists($fileName);
|
||||
}
|
||||
|
|
|
@ -13,295 +13,295 @@ use Szurubooru\Services\ThumbnailService;
|
|||
|
||||
class PostDao extends AbstractDao implements ICrudDao
|
||||
{
|
||||
private $tagDao;
|
||||
private $userDao;
|
||||
private $fileDao;
|
||||
private $thumbnailService;
|
||||
private $tagDao;
|
||||
private $userDao;
|
||||
private $fileDao;
|
||||
private $thumbnailService;
|
||||
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
TagDao $tagDao,
|
||||
UserDao $userDao,
|
||||
PublicFileDao $fileDao,
|
||||
ThumbnailService $thumbnailService)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'posts',
|
||||
new PostEntityConverter());
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
TagDao $tagDao,
|
||||
UserDao $userDao,
|
||||
PublicFileDao $fileDao,
|
||||
ThumbnailService $thumbnailService)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'posts',
|
||||
new PostEntityConverter());
|
||||
|
||||
$this->tagDao = $tagDao;
|
||||
$this->userDao = $userDao;
|
||||
$this->fileDao = $fileDao;
|
||||
$this->thumbnailService = $thumbnailService;
|
||||
}
|
||||
$this->tagDao = $tagDao;
|
||||
$this->userDao = $userDao;
|
||||
$this->fileDao = $fileDao;
|
||||
$this->thumbnailService = $thumbnailService;
|
||||
}
|
||||
|
||||
public function getCount()
|
||||
{
|
||||
return count($this->pdo->from($this->tableName));
|
||||
}
|
||||
public function getCount()
|
||||
{
|
||||
return count($this->pdo->from($this->tableName));
|
||||
}
|
||||
|
||||
public function getTotalFileSize()
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName)->select('SUM(originalFileSize) AS __sum');
|
||||
return iterator_to_array($query)[0]['__sum'];
|
||||
}
|
||||
public function getTotalFileSize()
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName)->select('SUM(originalFileSize) AS __sum');
|
||||
return iterator_to_array($query)[0]['__sum'];
|
||||
}
|
||||
|
||||
public function findByName($name)
|
||||
{
|
||||
return $this->findOneBy('name', $name);
|
||||
}
|
||||
public function findByName($name)
|
||||
{
|
||||
return $this->findOneBy('name', $name);
|
||||
}
|
||||
|
||||
public function findByTagName($tagName)
|
||||
{
|
||||
$query = $this->pdo->from('posts')
|
||||
->innerJoin('postTags', 'postTags.postId = posts.id')
|
||||
->innerJoin('tags', 'postTags.tagId = tags.id')
|
||||
->where('tags.name', $tagName);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
public function findByTagName($tagName)
|
||||
{
|
||||
$query = $this->pdo->from('posts')
|
||||
->innerJoin('postTags', 'postTags.postId = posts.id')
|
||||
->innerJoin('tags', 'postTags.tagId = tags.id')
|
||||
->where('tags.name', $tagName);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
|
||||
public function findByContentChecksum($checksum)
|
||||
{
|
||||
return $this->findOneBy('contentChecksum', $checksum);
|
||||
}
|
||||
public function findByContentChecksum($checksum)
|
||||
{
|
||||
return $this->findOneBy('contentChecksum', $checksum);
|
||||
}
|
||||
|
||||
protected function afterLoad(Entity $post)
|
||||
{
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_CONTENT,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->fileDao->load($post->getContentPath());
|
||||
});
|
||||
protected function afterLoad(Entity $post)
|
||||
{
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_CONTENT,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->fileDao->load($post->getContentPath());
|
||||
});
|
||||
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_THUMBNAIL_SOURCE_CONTENT,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->fileDao->load($post->getThumbnailSourceContentPath());
|
||||
});
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_THUMBNAIL_SOURCE_CONTENT,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->fileDao->load($post->getThumbnailSourceContentPath());
|
||||
});
|
||||
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_USER,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->getUser($post);
|
||||
});
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_USER,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->getUser($post);
|
||||
});
|
||||
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_TAGS,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->getTags($post);
|
||||
});
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_TAGS,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->getTags($post);
|
||||
});
|
||||
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_RELATED_POSTS,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->getRelatedPosts($post);
|
||||
});
|
||||
}
|
||||
$post->setLazyLoader(
|
||||
Post::LAZY_LOADER_RELATED_POSTS,
|
||||
function (Post $post)
|
||||
{
|
||||
return $this->getRelatedPosts($post);
|
||||
});
|
||||
}
|
||||
|
||||
protected function afterSave(Entity $post)
|
||||
{
|
||||
$this->syncContent($post);
|
||||
$this->syncThumbnailSourceContent($post);
|
||||
$this->syncTags($post);
|
||||
$this->syncPostRelations($post);
|
||||
}
|
||||
protected function afterSave(Entity $post)
|
||||
{
|
||||
$this->syncContent($post);
|
||||
$this->syncThumbnailSourceContent($post);
|
||||
$this->syncTags($post);
|
||||
$this->syncPostRelations($post);
|
||||
}
|
||||
|
||||
protected function decorateQueryFromRequirement($query, Requirement $requirement)
|
||||
{
|
||||
if ($requirement->getType() === PostFilter::REQUIREMENT_TAG)
|
||||
{
|
||||
$tagName = $requirement->getValue()->getValue();
|
||||
$tag = $this->tagDao->findByName($tagName);
|
||||
if (!$tag)
|
||||
throw new \DomainException('Invalid tag: "' . $tagName . '"');
|
||||
protected function decorateQueryFromRequirement($query, Requirement $requirement)
|
||||
{
|
||||
if ($requirement->getType() === PostFilter::REQUIREMENT_TAG)
|
||||
{
|
||||
$tagName = $requirement->getValue()->getValue();
|
||||
$tag = $this->tagDao->findByName($tagName);
|
||||
if (!$tag)
|
||||
throw new \DomainException('Invalid tag: "' . $tagName . '"');
|
||||
|
||||
$sql = 'EXISTS (
|
||||
SELECT 1 FROM postTags
|
||||
WHERE postTags.postId = posts.id
|
||||
AND postTags.tagId = ?)';
|
||||
$sql = 'EXISTS (
|
||||
SELECT 1 FROM postTags
|
||||
WHERE postTags.postId = posts.id
|
||||
AND postTags.tagId = ?)';
|
||||
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
|
||||
$query->where($sql, $tag->getId());
|
||||
return;
|
||||
}
|
||||
$query->where($sql, $tag->getId());
|
||||
return;
|
||||
}
|
||||
|
||||
elseif ($requirement->getType() === PostFilter::REQUIREMENT_FAVORITE)
|
||||
{
|
||||
foreach ($requirement->getValue()->getValues() as $userName)
|
||||
{
|
||||
$sql = 'EXISTS (
|
||||
SELECT 1 FROM favorites f
|
||||
WHERE f.postId = posts.id
|
||||
AND f.userId = (SELECT id FROM users WHERE name = ?))';
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
$query->where($sql, [$userName]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
elseif ($requirement->getType() === PostFilter::REQUIREMENT_FAVORITE)
|
||||
{
|
||||
foreach ($requirement->getValue()->getValues() as $userName)
|
||||
{
|
||||
$sql = 'EXISTS (
|
||||
SELECT 1 FROM favorites f
|
||||
WHERE f.postId = posts.id
|
||||
AND f.userId = (SELECT id FROM users WHERE name = ?))';
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
$query->where($sql, [$userName]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
elseif ($requirement->getType() === PostFilter::REQUIREMENT_COMMENT_AUTHOR)
|
||||
{
|
||||
foreach ($requirement->getValue()->getValues() as $userName)
|
||||
{
|
||||
$sql = 'EXISTS (
|
||||
SELECT 1 FROM comments c
|
||||
WHERE c.postId = posts.id
|
||||
AND c.userId = (SELECT id FROM users WHERE name = ?))';
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
$query->where($sql, [$userName]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
elseif ($requirement->getType() === PostFilter::REQUIREMENT_COMMENT_AUTHOR)
|
||||
{
|
||||
foreach ($requirement->getValue()->getValues() as $userName)
|
||||
{
|
||||
$sql = 'EXISTS (
|
||||
SELECT 1 FROM comments c
|
||||
WHERE c.postId = posts.id
|
||||
AND c.userId = (SELECT id FROM users WHERE name = ?))';
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
$query->where($sql, [$userName]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
elseif ($requirement->getType() === PostFilter::REQUIREMENT_UPLOADER)
|
||||
{
|
||||
foreach ($requirement->getValue()->getValues() as $userName)
|
||||
{
|
||||
$alias = 'u' . uniqid();
|
||||
$query->innerJoin('users ' . $alias, $alias . '.id = posts.userId');
|
||||
$sql = $alias . '.name = ?';
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
$query->where($sql, [$userName]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
elseif ($requirement->getType() === PostFilter::REQUIREMENT_UPLOADER)
|
||||
{
|
||||
foreach ($requirement->getValue()->getValues() as $userName)
|
||||
{
|
||||
$alias = 'u' . uniqid();
|
||||
$query->innerJoin('users ' . $alias, $alias . '.id = posts.userId');
|
||||
$sql = $alias . '.name = ?';
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
$query->where($sql, [$userName]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
elseif ($requirement->getType() === PostFilter::REQUIREMENT_USER_SCORE)
|
||||
{
|
||||
$values = $requirement->getValue()->getValues();
|
||||
$userName = $values[0];
|
||||
$score = $values[1];
|
||||
$sql = 'EXISTS (
|
||||
SELECT 1 FROM scores
|
||||
WHERE scores.postId = posts.id
|
||||
AND scores.userId = (SELECT id FROM users WHERE name = ?)
|
||||
AND scores.score = ?)';
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
$query->where($sql, [$userName, $score]);
|
||||
return;
|
||||
}
|
||||
elseif ($requirement->getType() === PostFilter::REQUIREMENT_USER_SCORE)
|
||||
{
|
||||
$values = $requirement->getValue()->getValues();
|
||||
$userName = $values[0];
|
||||
$score = $values[1];
|
||||
$sql = 'EXISTS (
|
||||
SELECT 1 FROM scores
|
||||
WHERE scores.postId = posts.id
|
||||
AND scores.userId = (SELECT id FROM users WHERE name = ?)
|
||||
AND scores.score = ?)';
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
$query->where($sql, [$userName, $score]);
|
||||
return;
|
||||
}
|
||||
|
||||
parent::decorateQueryFromRequirement($query, $requirement);
|
||||
}
|
||||
parent::decorateQueryFromRequirement($query, $requirement);
|
||||
}
|
||||
|
||||
private function getTags(Post $post)
|
||||
{
|
||||
return $this->tagDao->findByPostId($post->getId());
|
||||
}
|
||||
private function getTags(Post $post)
|
||||
{
|
||||
return $this->tagDao->findByPostId($post->getId());
|
||||
}
|
||||
|
||||
private function getUser(Post $post)
|
||||
{
|
||||
return $this->userDao->findById($post->getUserId());
|
||||
}
|
||||
private function getUser(Post $post)
|
||||
{
|
||||
return $this->userDao->findById($post->getUserId());
|
||||
}
|
||||
|
||||
private function getRelatedPosts(Post $post)
|
||||
{
|
||||
$relatedPostIds = [];
|
||||
private function getRelatedPosts(Post $post)
|
||||
{
|
||||
$relatedPostIds = [];
|
||||
|
||||
foreach ($this->pdo->from('postRelations')->where('post1id', $post->getId()) as $arrayEntity)
|
||||
{
|
||||
$postId = intval($arrayEntity['post2id']);
|
||||
if ($postId !== $post->getId())
|
||||
$relatedPostIds[] = $postId;
|
||||
}
|
||||
foreach ($this->pdo->from('postRelations')->where('post1id', $post->getId()) as $arrayEntity)
|
||||
{
|
||||
$postId = intval($arrayEntity['post2id']);
|
||||
if ($postId !== $post->getId())
|
||||
$relatedPostIds[] = $postId;
|
||||
}
|
||||
|
||||
foreach ($this->pdo->from('postRelations')->where('post2id', $post->getId()) as $arrayEntity)
|
||||
{
|
||||
$postId = intval($arrayEntity['post1id']);
|
||||
if ($postId !== $post->getId())
|
||||
$relatedPostIds[] = $postId;
|
||||
}
|
||||
foreach ($this->pdo->from('postRelations')->where('post2id', $post->getId()) as $arrayEntity)
|
||||
{
|
||||
$postId = intval($arrayEntity['post1id']);
|
||||
if ($postId !== $post->getId())
|
||||
$relatedPostIds[] = $postId;
|
||||
}
|
||||
|
||||
return $this->findByIds($relatedPostIds);
|
||||
}
|
||||
return $this->findByIds($relatedPostIds);
|
||||
}
|
||||
|
||||
private function syncContent(Post $post)
|
||||
{
|
||||
$targetPath = $post->getContentPath();
|
||||
$content = $post->getContent();
|
||||
if ($content)
|
||||
$this->fileDao->save($targetPath, $content);
|
||||
else
|
||||
$this->fileDao->delete($targetPath, $content);
|
||||
$this->thumbnailService->deleteUsedThumbnails($targetPath);
|
||||
}
|
||||
private function syncContent(Post $post)
|
||||
{
|
||||
$targetPath = $post->getContentPath();
|
||||
$content = $post->getContent();
|
||||
if ($content)
|
||||
$this->fileDao->save($targetPath, $content);
|
||||
else
|
||||
$this->fileDao->delete($targetPath, $content);
|
||||
$this->thumbnailService->deleteUsedThumbnails($targetPath);
|
||||
}
|
||||
|
||||
private function syncThumbnailSourceContent(Post $post)
|
||||
{
|
||||
$targetPath = $post->getThumbnailSourceContentPath();
|
||||
$content = $post->getThumbnailSourceContent();
|
||||
if ($content)
|
||||
$this->fileDao->save($targetPath, $content);
|
||||
else
|
||||
$this->fileDao->delete($targetPath);
|
||||
$this->thumbnailService->deleteUsedThumbnails($targetPath);
|
||||
}
|
||||
private function syncThumbnailSourceContent(Post $post)
|
||||
{
|
||||
$targetPath = $post->getThumbnailSourceContentPath();
|
||||
$content = $post->getThumbnailSourceContent();
|
||||
if ($content)
|
||||
$this->fileDao->save($targetPath, $content);
|
||||
else
|
||||
$this->fileDao->delete($targetPath);
|
||||
$this->thumbnailService->deleteUsedThumbnails($targetPath);
|
||||
}
|
||||
|
||||
private function syncTags(Post $post)
|
||||
{
|
||||
$tagIds = array_map(
|
||||
function ($tag)
|
||||
{
|
||||
if (!$tag->getId())
|
||||
throw new \RuntimeException('Unsaved entities found');
|
||||
return $tag->getId();
|
||||
},
|
||||
$post->getTags());
|
||||
private function syncTags(Post $post)
|
||||
{
|
||||
$tagIds = array_map(
|
||||
function ($tag)
|
||||
{
|
||||
if (!$tag->getId())
|
||||
throw new \RuntimeException('Unsaved entities found');
|
||||
return $tag->getId();
|
||||
},
|
||||
$post->getTags());
|
||||
|
||||
$existingTagRelationIds = array_map(
|
||||
function ($arrayEntity)
|
||||
{
|
||||
return $arrayEntity['tagId'];
|
||||
},
|
||||
iterator_to_array($this->pdo->from('postTags')->where('postId', $post->getId())));
|
||||
$existingTagRelationIds = array_map(
|
||||
function ($arrayEntity)
|
||||
{
|
||||
return $arrayEntity['tagId'];
|
||||
},
|
||||
iterator_to_array($this->pdo->from('postTags')->where('postId', $post->getId())));
|
||||
|
||||
$tagRelationsToInsert = array_diff($tagIds, $existingTagRelationIds);
|
||||
$tagRelationsToDelete = array_diff($existingTagRelationIds, $tagIds);
|
||||
$tagRelationsToInsert = array_diff($tagIds, $existingTagRelationIds);
|
||||
$tagRelationsToDelete = array_diff($existingTagRelationIds, $tagIds);
|
||||
|
||||
foreach ($tagRelationsToInsert as $tagId)
|
||||
{
|
||||
$this->pdo->insertInto('postTags')->values(['postId' => $post->getId(), 'tagId' => $tagId])->execute();
|
||||
}
|
||||
foreach ($tagRelationsToDelete as $tagId)
|
||||
{
|
||||
$this->pdo->deleteFrom('postTags')->where('postId', $post->getId())->where('tagId', $tagId)->execute();
|
||||
}
|
||||
}
|
||||
foreach ($tagRelationsToInsert as $tagId)
|
||||
{
|
||||
$this->pdo->insertInto('postTags')->values(['postId' => $post->getId(), 'tagId' => $tagId])->execute();
|
||||
}
|
||||
foreach ($tagRelationsToDelete as $tagId)
|
||||
{
|
||||
$this->pdo->deleteFrom('postTags')->where('postId', $post->getId())->where('tagId', $tagId)->execute();
|
||||
}
|
||||
}
|
||||
|
||||
private function syncPostRelations(Post $post)
|
||||
{
|
||||
$relatedPostIds = array_filter(array_unique(array_map(
|
||||
function ($post)
|
||||
{
|
||||
if (!$post->getId())
|
||||
throw new \RuntimeException('Unsaved entities found');
|
||||
return $post->getId();
|
||||
},
|
||||
$post->getRelatedPosts())));
|
||||
private function syncPostRelations(Post $post)
|
||||
{
|
||||
$relatedPostIds = array_filter(array_unique(array_map(
|
||||
function ($post)
|
||||
{
|
||||
if (!$post->getId())
|
||||
throw new \RuntimeException('Unsaved entities found');
|
||||
return $post->getId();
|
||||
},
|
||||
$post->getRelatedPosts())));
|
||||
|
||||
$this->pdo->deleteFrom('postRelations')->where('post1id', $post->getId())->execute();
|
||||
$this->pdo->deleteFrom('postRelations')->where('post2id', $post->getId())->execute();
|
||||
foreach ($relatedPostIds as $postId)
|
||||
{
|
||||
$this->pdo
|
||||
->insertInto('postRelations')
|
||||
->values([
|
||||
'post1id' => $post->getId(),
|
||||
'post2id' => $postId])
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
$this->pdo->deleteFrom('postRelations')->where('post1id', $post->getId())->execute();
|
||||
$this->pdo->deleteFrom('postRelations')->where('post2id', $post->getId())->execute();
|
||||
foreach ($relatedPostIds as $postId)
|
||||
{
|
||||
$this->pdo
|
||||
->insertInto('postRelations')
|
||||
->values([
|
||||
'post1id' => $post->getId(),
|
||||
'post2id' => $postId])
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,32 +8,32 @@ use Szurubooru\Entities\PostNote;
|
|||
|
||||
class PostNoteDao extends AbstractDao implements ICrudDao
|
||||
{
|
||||
private $postDao;
|
||||
private $postDao;
|
||||
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
PostDao $postDao)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'postNotes',
|
||||
new PostNoteEntityConverter());
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
PostDao $postDao)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'postNotes',
|
||||
new PostNoteEntityConverter());
|
||||
|
||||
$this->postDao = $postDao;
|
||||
}
|
||||
$this->postDao = $postDao;
|
||||
}
|
||||
|
||||
public function findByPostId($postId)
|
||||
{
|
||||
return $this->findBy('postId', $postId);
|
||||
}
|
||||
public function findByPostId($postId)
|
||||
{
|
||||
return $this->findBy('postId', $postId);
|
||||
}
|
||||
|
||||
protected function afterLoad(Entity $postNote)
|
||||
{
|
||||
$postNote->setLazyLoader(
|
||||
PostNote::LAZY_LOADER_POST,
|
||||
function (PostNote $postNote)
|
||||
{
|
||||
return $this->postDao->findById($postNote->getPostId());
|
||||
});
|
||||
}
|
||||
protected function afterLoad(Entity $postNote)
|
||||
{
|
||||
$postNote->setLazyLoader(
|
||||
PostNote::LAZY_LOADER_POST,
|
||||
function (PostNote $postNote)
|
||||
{
|
||||
return $this->postDao->findById($postNote->getPostId());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ use Szurubooru\Dao\IFileDao;
|
|||
|
||||
class PublicFileDao extends FileDao implements IFileDao
|
||||
{
|
||||
public function __construct(Config $config)
|
||||
{
|
||||
parent::__construct($config->getPublicDataDirectory());
|
||||
}
|
||||
public function __construct(Config $config)
|
||||
{
|
||||
parent::__construct($config->getPublicDataDirectory());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,70 +11,70 @@ use Szurubooru\Services\TimeService;
|
|||
|
||||
class ScoreDao extends AbstractDao implements ICrudDao
|
||||
{
|
||||
private $timeService;
|
||||
private $timeService;
|
||||
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
TimeService $timeService)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'scores',
|
||||
new ScoreEntityConverter());
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
TimeService $timeService)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'scores',
|
||||
new ScoreEntityConverter());
|
||||
|
||||
$this->timeService = $timeService;
|
||||
}
|
||||
$this->timeService = $timeService;
|
||||
}
|
||||
|
||||
public function getScoreValue(Entity $entity)
|
||||
{
|
||||
$query = $this->getBaseQuery($entity);
|
||||
$query->select(null);
|
||||
$query->select('SUM(score) AS score');
|
||||
return iterator_to_array($query)[0]['score'];
|
||||
}
|
||||
public function getScoreValue(Entity $entity)
|
||||
{
|
||||
$query = $this->getBaseQuery($entity);
|
||||
$query->select(null);
|
||||
$query->select('SUM(score) AS score');
|
||||
return iterator_to_array($query)[0]['score'];
|
||||
}
|
||||
|
||||
public function getUserScore(User $user, Entity $entity)
|
||||
{
|
||||
$query = $this->getBaseQuery($entity);
|
||||
$query->where('userId', $user->getId());
|
||||
public function getUserScore(User $user, Entity $entity)
|
||||
{
|
||||
$query = $this->getBaseQuery($entity);
|
||||
$query->where('userId', $user->getId());
|
||||
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
$entities = $this->arrayToEntities($arrayEntities);
|
||||
return array_shift($entities);
|
||||
}
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
$entities = $this->arrayToEntities($arrayEntities);
|
||||
return array_shift($entities);
|
||||
}
|
||||
|
||||
public function setUserScore(User $user, Entity $entity, $scoreValue)
|
||||
{
|
||||
$score = $this->getUserScore($user, $entity);
|
||||
if (!$score)
|
||||
{
|
||||
$score = new Score();
|
||||
$score->setTime($this->timeService->getCurrentTime());
|
||||
$score->setUserId($user->getId());
|
||||
public function setUserScore(User $user, Entity $entity, $scoreValue)
|
||||
{
|
||||
$score = $this->getUserScore($user, $entity);
|
||||
if (!$score)
|
||||
{
|
||||
$score = new Score();
|
||||
$score->setTime($this->timeService->getCurrentTime());
|
||||
$score->setUserId($user->getId());
|
||||
|
||||
if ($entity instanceof Post)
|
||||
$score->setPostId($entity->getId());
|
||||
elseif ($entity instanceof Comment)
|
||||
$score->setCommentId($entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
$score->setScore($scoreValue);
|
||||
$this->save($score);
|
||||
return $score;
|
||||
}
|
||||
if ($entity instanceof Post)
|
||||
$score->setPostId($entity->getId());
|
||||
elseif ($entity instanceof Comment)
|
||||
$score->setCommentId($entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
}
|
||||
$score->setScore($scoreValue);
|
||||
$this->save($score);
|
||||
return $score;
|
||||
}
|
||||
|
||||
private function getBaseQuery($entity)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName);
|
||||
private function getBaseQuery($entity)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName);
|
||||
|
||||
if ($entity instanceof Post)
|
||||
$query->where('postId', $entity->getId());
|
||||
elseif ($entity instanceof Comment)
|
||||
$query->where('commentId', $entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
if ($entity instanceof Post)
|
||||
$query->where('postId', $entity->getId());
|
||||
elseif ($entity instanceof Comment)
|
||||
$query->where('commentId', $entity->getId());
|
||||
else
|
||||
throw new \InvalidArgumentException();
|
||||
|
||||
return $query;
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,47 +8,47 @@ use Szurubooru\Entities\Snapshot;
|
|||
|
||||
class SnapshotDao extends AbstractDao
|
||||
{
|
||||
private $userDao;
|
||||
private $userDao;
|
||||
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
UserDao $userDao)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'snapshots',
|
||||
new SnapshotEntityConverter());
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
UserDao $userDao)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'snapshots',
|
||||
new SnapshotEntityConverter());
|
||||
|
||||
$this->userDao = $userDao;
|
||||
}
|
||||
$this->userDao = $userDao;
|
||||
}
|
||||
|
||||
public function findEarlierSnapshots(Snapshot $snapshot)
|
||||
{
|
||||
$query = $this->pdo
|
||||
->from($this->tableName)
|
||||
->where('type', $snapshot->getType())
|
||||
->where('primaryKey', $snapshot->getPrimaryKey())
|
||||
->orderBy('time DESC');
|
||||
public function findEarlierSnapshots(Snapshot $snapshot)
|
||||
{
|
||||
$query = $this->pdo
|
||||
->from($this->tableName)
|
||||
->where('type', $snapshot->getType())
|
||||
->where('primaryKey', $snapshot->getPrimaryKey())
|
||||
->orderBy('time DESC');
|
||||
|
||||
if ($snapshot->getId())
|
||||
$query->where('id < ?', $snapshot->getId());
|
||||
if ($snapshot->getId())
|
||||
$query->where('id < ?', $snapshot->getId());
|
||||
|
||||
return $this->arrayToEntities(iterator_to_array($query));
|
||||
}
|
||||
return $this->arrayToEntities(iterator_to_array($query));
|
||||
}
|
||||
|
||||
public function afterLoad(Entity $snapshot)
|
||||
{
|
||||
$snapshot->setLazyLoader(
|
||||
Snapshot::LAZY_LOADER_USER,
|
||||
function (Snapshot $snapshot)
|
||||
{
|
||||
return $this->getUser($snapshot);
|
||||
});
|
||||
}
|
||||
public function afterLoad(Entity $snapshot)
|
||||
{
|
||||
$snapshot->setLazyLoader(
|
||||
Snapshot::LAZY_LOADER_USER,
|
||||
function (Snapshot $snapshot)
|
||||
{
|
||||
return $this->getUser($snapshot);
|
||||
});
|
||||
}
|
||||
|
||||
private function getUser(Snapshot $snapshot)
|
||||
{
|
||||
$userId = $snapshot->getUserId();
|
||||
return $this->userDao->findById($userId);
|
||||
}
|
||||
private function getUser(Snapshot $snapshot)
|
||||
{
|
||||
$userId = $snapshot->getUserId();
|
||||
return $this->userDao->findById($userId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,213 +10,213 @@ use Szurubooru\Search\Requirements\Requirement;
|
|||
|
||||
class TagDao extends AbstractDao implements ICrudDao
|
||||
{
|
||||
const TAG_RELATION_IMPLICATION = 1;
|
||||
const TAG_RELATION_SUGGESTION = 2;
|
||||
const TAG_RELATION_IMPLICATION = 1;
|
||||
const TAG_RELATION_SUGGESTION = 2;
|
||||
|
||||
public function __construct(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'tags',
|
||||
new TagEntityConverter());
|
||||
}
|
||||
public function __construct(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'tags',
|
||||
new TagEntityConverter());
|
||||
}
|
||||
|
||||
public function findByName($tagName)
|
||||
{
|
||||
return $this->findOneBy('name', $tagName);
|
||||
}
|
||||
public function findByName($tagName)
|
||||
{
|
||||
return $this->findOneBy('name', $tagName);
|
||||
}
|
||||
|
||||
public function findByNames($tagNames)
|
||||
{
|
||||
return $this->findBy('name', $tagNames);
|
||||
}
|
||||
public function findByNames($tagNames)
|
||||
{
|
||||
return $this->findBy('name', $tagNames);
|
||||
}
|
||||
|
||||
public function findByPostId($postId)
|
||||
{
|
||||
return $this->findByPostIds([$postId]);
|
||||
}
|
||||
public function findByPostId($postId)
|
||||
{
|
||||
return $this->findByPostIds([$postId]);
|
||||
}
|
||||
|
||||
public function findByPostIds($postIds)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName)
|
||||
->innerJoin('postTags', 'postTags.tagId = tags.id')
|
||||
->where('postTags.postId', $postIds);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
public function findByPostIds($postIds)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName)
|
||||
->innerJoin('postTags', 'postTags.tagId = tags.id')
|
||||
->where('postTags.postId', $postIds);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
|
||||
public function findSiblings($tagName)
|
||||
{
|
||||
$tag = $this->findByName($tagName);
|
||||
if (!$tag)
|
||||
return [];
|
||||
$tagId = $tag->getId();
|
||||
$query = $this->pdo->from($this->tableName)
|
||||
->select('COUNT(pt2.postId) AS postCount')
|
||||
->innerJoin('postTags pt1', 'pt1.tagId = tags.id')
|
||||
->innerJoin('postTags pt2', 'pt2.postId = pt1.postId')
|
||||
->where('pt2.tagId', $tagId)
|
||||
->groupBy('tags.id')
|
||||
->orderBy('postCount DESC, name ASC');
|
||||
public function findSiblings($tagName)
|
||||
{
|
||||
$tag = $this->findByName($tagName);
|
||||
if (!$tag)
|
||||
return [];
|
||||
$tagId = $tag->getId();
|
||||
$query = $this->pdo->from($this->tableName)
|
||||
->select('COUNT(pt2.postId) AS postCount')
|
||||
->innerJoin('postTags pt1', 'pt1.tagId = tags.id')
|
||||
->innerJoin('postTags pt2', 'pt2.postId = pt1.postId')
|
||||
->where('pt2.tagId', $tagId)
|
||||
->groupBy('tags.id')
|
||||
->orderBy('postCount DESC, name ASC');
|
||||
|
||||
$arrayEntities = array_filter(
|
||||
iterator_to_array($query),
|
||||
function($arrayEntity) use ($tagName)
|
||||
{
|
||||
return strcasecmp($arrayEntity['name'], $tagName) !== 0;
|
||||
});
|
||||
$arrayEntities = array_filter(
|
||||
iterator_to_array($query),
|
||||
function($arrayEntity) use ($tagName)
|
||||
{
|
||||
return strcasecmp($arrayEntity['name'], $tagName) !== 0;
|
||||
});
|
||||
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
|
||||
public function export()
|
||||
{
|
||||
$exported = [];
|
||||
foreach ($this->pdo->from($this->tableName) as $arrayEntity)
|
||||
{
|
||||
$exported[$arrayEntity['id']] = [
|
||||
'name' => $arrayEntity['name'],
|
||||
'usages' => intval($arrayEntity['usages']),
|
||||
'banned' => boolval($arrayEntity['banned'])
|
||||
];
|
||||
}
|
||||
public function export()
|
||||
{
|
||||
$exported = [];
|
||||
foreach ($this->pdo->from($this->tableName) as $arrayEntity)
|
||||
{
|
||||
$exported[$arrayEntity['id']] = [
|
||||
'name' => $arrayEntity['name'],
|
||||
'usages' => intval($arrayEntity['usages']),
|
||||
'banned' => boolval($arrayEntity['banned'])
|
||||
];
|
||||
}
|
||||
|
||||
//upgrades on old databases
|
||||
try
|
||||
{
|
||||
$relations = iterator_to_array($this->pdo->from('tagRelations'));
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$relations = [];
|
||||
}
|
||||
//upgrades on old databases
|
||||
try
|
||||
{
|
||||
$relations = iterator_to_array($this->pdo->from('tagRelations'));
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$relations = [];
|
||||
}
|
||||
|
||||
foreach ($relations as $arrayEntity)
|
||||
{
|
||||
$key1 = $arrayEntity['tag1id'];
|
||||
$key2 = $arrayEntity['tag2id'];
|
||||
$type = intval($arrayEntity['type']);
|
||||
if ($type === self::TAG_RELATION_IMPLICATION)
|
||||
$target = 'implications';
|
||||
elseif ($type === self::TAG_RELATION_SUGGESTION)
|
||||
$target = 'suggestions';
|
||||
else
|
||||
continue;
|
||||
foreach ($relations as $arrayEntity)
|
||||
{
|
||||
$key1 = $arrayEntity['tag1id'];
|
||||
$key2 = $arrayEntity['tag2id'];
|
||||
$type = intval($arrayEntity['type']);
|
||||
if ($type === self::TAG_RELATION_IMPLICATION)
|
||||
$target = 'implications';
|
||||
elseif ($type === self::TAG_RELATION_SUGGESTION)
|
||||
$target = 'suggestions';
|
||||
else
|
||||
continue;
|
||||
|
||||
if (!isset($exported[$key1]) || !isset($exported[$key2]))
|
||||
continue;
|
||||
if (!isset($exported[$key1]) || !isset($exported[$key2]))
|
||||
continue;
|
||||
|
||||
if (!isset($exported[$key1][$target]))
|
||||
$exported[$key1][$target] = [];
|
||||
if (!isset($exported[$key1][$target]))
|
||||
$exported[$key1][$target] = [];
|
||||
|
||||
$exported[$key1][$target][] = $exported[$key2]['name'];
|
||||
}
|
||||
$exported[$key1][$target][] = $exported[$key2]['name'];
|
||||
}
|
||||
|
||||
return array_values($exported);
|
||||
}
|
||||
return array_values($exported);
|
||||
}
|
||||
|
||||
protected function afterLoad(Entity $tag)
|
||||
{
|
||||
$tag->setLazyLoader(
|
||||
Tag::LAZY_LOADER_IMPLIED_TAGS,
|
||||
function (Tag $tag)
|
||||
{
|
||||
return $this->findImpliedTags($tag);
|
||||
});
|
||||
protected function afterLoad(Entity $tag)
|
||||
{
|
||||
$tag->setLazyLoader(
|
||||
Tag::LAZY_LOADER_IMPLIED_TAGS,
|
||||
function (Tag $tag)
|
||||
{
|
||||
return $this->findImpliedTags($tag);
|
||||
});
|
||||
|
||||
$tag->setLazyLoader(
|
||||
Tag::LAZY_LOADER_SUGGESTED_TAGS,
|
||||
function (Tag $tag)
|
||||
{
|
||||
return $this->findSuggested($tag);
|
||||
});
|
||||
}
|
||||
$tag->setLazyLoader(
|
||||
Tag::LAZY_LOADER_SUGGESTED_TAGS,
|
||||
function (Tag $tag)
|
||||
{
|
||||
return $this->findSuggested($tag);
|
||||
});
|
||||
}
|
||||
|
||||
protected function afterSave(Entity $tag)
|
||||
{
|
||||
$this->syncImpliedTags($tag);
|
||||
$this->syncSuggestedTags($tag);
|
||||
}
|
||||
protected function afterSave(Entity $tag)
|
||||
{
|
||||
$this->syncImpliedTags($tag);
|
||||
$this->syncSuggestedTags($tag);
|
||||
}
|
||||
|
||||
protected function decorateQueryFromRequirement($query, Requirement $requirement)
|
||||
{
|
||||
if ($requirement->getType() === TagFilter::REQUIREMENT_PARTIAL_TAG_NAME)
|
||||
{
|
||||
$sql = 'INSTR(LOWER(tags.name), LOWER(?)) > 0';
|
||||
protected function decorateQueryFromRequirement($query, Requirement $requirement)
|
||||
{
|
||||
if ($requirement->getType() === TagFilter::REQUIREMENT_PARTIAL_TAG_NAME)
|
||||
{
|
||||
$sql = 'INSTR(LOWER(tags.name), LOWER(?)) > 0';
|
||||
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
if ($requirement->isNegated())
|
||||
$sql = 'NOT ' . $sql;
|
||||
|
||||
$query->where($sql, $requirement->getValue()->getValue());
|
||||
return;
|
||||
}
|
||||
$query->where($sql, $requirement->getValue()->getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
elseif ($requirement->getType() === TagFilter::REQUIREMENT_CATEGORY)
|
||||
{
|
||||
$sql = 'IFNULL(category, \'default\')';
|
||||
$requirement->setType($sql);
|
||||
return parent::decorateQueryFromRequirement($query, $requirement);
|
||||
}
|
||||
elseif ($requirement->getType() === TagFilter::REQUIREMENT_CATEGORY)
|
||||
{
|
||||
$sql = 'IFNULL(category, \'default\')';
|
||||
$requirement->setType($sql);
|
||||
return parent::decorateQueryFromRequirement($query, $requirement);
|
||||
}
|
||||
|
||||
parent::decorateQueryFromRequirement($query, $requirement);
|
||||
}
|
||||
parent::decorateQueryFromRequirement($query, $requirement);
|
||||
}
|
||||
|
||||
private function findImpliedTags(Tag $tag)
|
||||
{
|
||||
return $this->findRelatedTagsByType($tag, self::TAG_RELATION_IMPLICATION);
|
||||
}
|
||||
private function findImpliedTags(Tag $tag)
|
||||
{
|
||||
return $this->findRelatedTagsByType($tag, self::TAG_RELATION_IMPLICATION);
|
||||
}
|
||||
|
||||
private function findSuggested(Tag $tag)
|
||||
{
|
||||
return $this->findRelatedTagsByType($tag, self::TAG_RELATION_SUGGESTION);
|
||||
}
|
||||
private function findSuggested(Tag $tag)
|
||||
{
|
||||
return $this->findRelatedTagsByType($tag, self::TAG_RELATION_SUGGESTION);
|
||||
}
|
||||
|
||||
private function syncImpliedTags($tag)
|
||||
{
|
||||
$this->syncRelatedTagsByType($tag, $tag->getImpliedTags(), self::TAG_RELATION_IMPLICATION);
|
||||
}
|
||||
private function syncImpliedTags($tag)
|
||||
{
|
||||
$this->syncRelatedTagsByType($tag, $tag->getImpliedTags(), self::TAG_RELATION_IMPLICATION);
|
||||
}
|
||||
|
||||
private function syncSuggestedTags($tag)
|
||||
{
|
||||
$this->syncRelatedTagsByType($tag, $tag->getSuggestedTags(), self::TAG_RELATION_SUGGESTION);
|
||||
}
|
||||
private function syncSuggestedTags($tag)
|
||||
{
|
||||
$this->syncRelatedTagsByType($tag, $tag->getSuggestedTags(), self::TAG_RELATION_SUGGESTION);
|
||||
}
|
||||
|
||||
private function syncRelatedTagsByType(Tag $tag, array $relatedTags, $type)
|
||||
{
|
||||
$relatedTagIds = array_filter(array_unique(array_map(
|
||||
function ($tag)
|
||||
{
|
||||
if (!$tag->getId())
|
||||
throw new \RuntimeException('Unsaved entities found');
|
||||
return $tag->getId();
|
||||
},
|
||||
$relatedTags)));
|
||||
private function syncRelatedTagsByType(Tag $tag, array $relatedTags, $type)
|
||||
{
|
||||
$relatedTagIds = array_filter(array_unique(array_map(
|
||||
function ($tag)
|
||||
{
|
||||
if (!$tag->getId())
|
||||
throw new \RuntimeException('Unsaved entities found');
|
||||
return $tag->getId();
|
||||
},
|
||||
$relatedTags)));
|
||||
|
||||
$this->pdo->deleteFrom('tagRelations')
|
||||
->where('tag1id', $tag->getId())
|
||||
->where('type', $type)
|
||||
->execute();
|
||||
$this->pdo->deleteFrom('tagRelations')
|
||||
->where('tag1id', $tag->getId())
|
||||
->where('type', $type)
|
||||
->execute();
|
||||
|
||||
foreach ($relatedTagIds as $tagId)
|
||||
{
|
||||
$this->pdo
|
||||
->insertInto('tagRelations')
|
||||
->values([
|
||||
'tag1id' => $tag->getId(),
|
||||
'tag2id' => $tagId,
|
||||
'type' => $type])
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
foreach ($relatedTagIds as $tagId)
|
||||
{
|
||||
$this->pdo
|
||||
->insertInto('tagRelations')
|
||||
->values([
|
||||
'tag1id' => $tag->getId(),
|
||||
'tag2id' => $tagId,
|
||||
'type' => $type])
|
||||
->execute();
|
||||
}
|
||||
}
|
||||
|
||||
private function findRelatedTagsByType(Tag $tag, $type)
|
||||
{
|
||||
$tagId = $tag->getId();
|
||||
$query = $this->pdo->from($this->tableName)
|
||||
->innerJoin('tagRelations tr', 'tags.id = tr.tag2id')
|
||||
->where('tr.type', $type)
|
||||
->where('tr.tag1id', $tagId);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
private function findRelatedTagsByType(Tag $tag, $type)
|
||||
{
|
||||
$tagId = $tag->getId();
|
||||
$query = $this->pdo->from($this->tableName)
|
||||
->innerJoin('tagRelations tr', 'tags.id = tr.tag2id')
|
||||
->where('tr.type', $type)
|
||||
->where('tr.tag1id', $tagId);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
return $this->arrayToEntities($arrayEntities);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,39 +5,39 @@ use Szurubooru\DatabaseConnection;
|
|||
|
||||
class TokenDao extends AbstractDao
|
||||
{
|
||||
public function __construct(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'tokens',
|
||||
new TokenEntityConverter());
|
||||
}
|
||||
public function __construct(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'tokens',
|
||||
new TokenEntityConverter());
|
||||
}
|
||||
|
||||
public function findByName($tokenName)
|
||||
{
|
||||
return $this->findOneBy('name', $tokenName);
|
||||
}
|
||||
public function findByName($tokenName)
|
||||
{
|
||||
return $this->findOneBy('name', $tokenName);
|
||||
}
|
||||
|
||||
public function findByAdditionalDataAndPurpose($additionalData, $purpose)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName)
|
||||
->where('additionalData', $additionalData)
|
||||
->where('purpose', $purpose);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
$entities = $this->arrayToEntities($arrayEntities);
|
||||
if (!$entities || !count($entities))
|
||||
return null;
|
||||
$entity = array_shift($entities);
|
||||
return $entity;
|
||||
}
|
||||
public function findByAdditionalDataAndPurpose($additionalData, $purpose)
|
||||
{
|
||||
$query = $this->pdo->from($this->tableName)
|
||||
->where('additionalData', $additionalData)
|
||||
->where('purpose', $purpose);
|
||||
$arrayEntities = iterator_to_array($query);
|
||||
$entities = $this->arrayToEntities($arrayEntities);
|
||||
if (!$entities || !count($entities))
|
||||
return null;
|
||||
$entity = array_shift($entities);
|
||||
return $entity;
|
||||
}
|
||||
|
||||
public function deleteByName($tokenName)
|
||||
{
|
||||
return $this->deleteBy('name', $tokenName);
|
||||
}
|
||||
public function deleteByName($tokenName)
|
||||
{
|
||||
return $this->deleteBy('name', $tokenName);
|
||||
}
|
||||
|
||||
public function deleteByAdditionalData($additionalData)
|
||||
{
|
||||
return $this->deleteBy('additionalData', $additionalData);
|
||||
}
|
||||
public function deleteByAdditionalData($additionalData)
|
||||
{
|
||||
return $this->deleteBy('additionalData', $additionalData);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,40 +4,40 @@ use Szurubooru\DatabaseConnection;
|
|||
|
||||
class TransactionManager
|
||||
{
|
||||
private $databaseConnection;
|
||||
private $databaseConnection;
|
||||
|
||||
public function __construct(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
$this->databaseConnection = $databaseConnection;
|
||||
}
|
||||
public function __construct(DatabaseConnection $databaseConnection)
|
||||
{
|
||||
$this->databaseConnection = $databaseConnection;
|
||||
}
|
||||
|
||||
public function commit($callback)
|
||||
{
|
||||
return $this->doInTransaction($callback, 'commit');
|
||||
}
|
||||
public function commit($callback)
|
||||
{
|
||||
return $this->doInTransaction($callback, 'commit');
|
||||
}
|
||||
|
||||
public function rollback($callback)
|
||||
{
|
||||
return $this->doInTransaction($callback, 'rollBack');
|
||||
}
|
||||
public function rollback($callback)
|
||||
{
|
||||
return $this->doInTransaction($callback, 'rollBack');
|
||||
}
|
||||
|
||||
public function doInTransaction($callback, $operation)
|
||||
{
|
||||
$pdo = $this->databaseConnection->getPDO();
|
||||
if ($pdo->inTransaction())
|
||||
return $callback();
|
||||
public function doInTransaction($callback, $operation)
|
||||
{
|
||||
$pdo = $this->databaseConnection->getPDO();
|
||||
if ($pdo->inTransaction())
|
||||
return $callback();
|
||||
|
||||
$pdo->beginTransaction();
|
||||
try
|
||||
{
|
||||
$ret = $callback();
|
||||
$pdo->$operation();
|
||||
return $ret;
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$pdo->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
$pdo->beginTransaction();
|
||||
try
|
||||
{
|
||||
$ret = $callback();
|
||||
$pdo->$operation();
|
||||
return $ret;
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$pdo->rollBack();
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,78 +9,78 @@ use Szurubooru\Services\ThumbnailService;
|
|||
|
||||
class UserDao extends AbstractDao implements ICrudDao
|
||||
{
|
||||
const ORDER_NAME = 'name';
|
||||
const ORDER_REGISTRATION_TIME = 'registrationTime';
|
||||
const ORDER_NAME = 'name';
|
||||
const ORDER_REGISTRATION_TIME = 'registrationTime';
|
||||
|
||||
private $fileDao;
|
||||
private $thumbnailService;
|
||||
private $fileDao;
|
||||
private $thumbnailService;
|
||||
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
PublicFileDao $fileDao,
|
||||
ThumbnailService $thumbnailService)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'users',
|
||||
new UserEntityConverter());
|
||||
public function __construct(
|
||||
DatabaseConnection $databaseConnection,
|
||||
PublicFileDao $fileDao,
|
||||
ThumbnailService $thumbnailService)
|
||||
{
|
||||
parent::__construct(
|
||||
$databaseConnection,
|
||||
'users',
|
||||
new UserEntityConverter());
|
||||
|
||||
$this->fileDao = $fileDao;
|
||||
$this->thumbnailService = $thumbnailService;
|
||||
}
|
||||
$this->fileDao = $fileDao;
|
||||
$this->thumbnailService = $thumbnailService;
|
||||
}
|
||||
|
||||
public function findByName($userName)
|
||||
{
|
||||
return $this->findOneBy('name', $userName);
|
||||
}
|
||||
public function findByName($userName)
|
||||
{
|
||||
return $this->findOneBy('name', $userName);
|
||||
}
|
||||
|
||||
public function findByEmail($userEmail, $allowUnconfirmed = false)
|
||||
{
|
||||
$result = $this->findOneBy('email', $userEmail);
|
||||
if (!$result && $allowUnconfirmed)
|
||||
{
|
||||
$result = $this->findOneBy('emailUnconfirmed', $userEmail);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function findByEmail($userEmail, $allowUnconfirmed = false)
|
||||
{
|
||||
$result = $this->findOneBy('email', $userEmail);
|
||||
if (!$result && $allowUnconfirmed)
|
||||
{
|
||||
$result = $this->findOneBy('emailUnconfirmed', $userEmail);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function hasAnyUsers()
|
||||
{
|
||||
return $this->hasAnyRecords();
|
||||
}
|
||||
public function hasAnyUsers()
|
||||
{
|
||||
return $this->hasAnyRecords();
|
||||
}
|
||||
|
||||
public function deleteByName($userName)
|
||||
{
|
||||
$this->deleteBy('name', $userName);
|
||||
$this->pdo->deleteFrom('tokens')->where('additionalData', $userName);
|
||||
}
|
||||
public function deleteByName($userName)
|
||||
{
|
||||
$this->deleteBy('name', $userName);
|
||||
$this->pdo->deleteFrom('tokens')->where('additionalData', $userName);
|
||||
}
|
||||
|
||||
protected function afterLoad(Entity $user)
|
||||
{
|
||||
$user->setLazyLoader(
|
||||
User::LAZY_LOADER_CUSTOM_AVATAR_SOURCE_CONTENT,
|
||||
function(User $user)
|
||||
{
|
||||
$avatarSource = $user->getCustomAvatarSourceContentPath();
|
||||
return $this->fileDao->load($avatarSource);
|
||||
});
|
||||
}
|
||||
protected function afterLoad(Entity $user)
|
||||
{
|
||||
$user->setLazyLoader(
|
||||
User::LAZY_LOADER_CUSTOM_AVATAR_SOURCE_CONTENT,
|
||||
function(User $user)
|
||||
{
|
||||
$avatarSource = $user->getCustomAvatarSourceContentPath();
|
||||
return $this->fileDao->load($avatarSource);
|
||||
});
|
||||
}
|
||||
|
||||
protected function afterSave(Entity $user)
|
||||
{
|
||||
$targetPath = $user->getCustomAvatarSourceContentPath();
|
||||
$content = $user->getCustomAvatarSourceContent();
|
||||
if ($content)
|
||||
$this->fileDao->save($targetPath, $content);
|
||||
else
|
||||
$this->fileDao->delete($targetPath);
|
||||
$this->thumbnailService->deleteUsedThumbnails($targetPath);
|
||||
}
|
||||
protected function afterSave(Entity $user)
|
||||
{
|
||||
$targetPath = $user->getCustomAvatarSourceContentPath();
|
||||
$content = $user->getCustomAvatarSourceContent();
|
||||
if ($content)
|
||||
$this->fileDao->save($targetPath, $content);
|
||||
else
|
||||
$this->fileDao->delete($targetPath);
|
||||
$this->thumbnailService->deleteUsedThumbnails($targetPath);
|
||||
}
|
||||
|
||||
protected function afterDelete(Entity $user)
|
||||
{
|
||||
$avatarSource = $user->getCustomAvatarSourceContentPath();
|
||||
$this->fileDao->delete($avatarSource);
|
||||
$this->thumbnailService->deleteUsedThumbnails($avatarSource);
|
||||
}
|
||||
protected function afterDelete(Entity $user)
|
||||
{
|
||||
$avatarSource = $user->getCustomAvatarSourceContentPath();
|
||||
$this->fileDao->delete($avatarSource);
|
||||
$this->thumbnailService->deleteUsedThumbnails($avatarSource);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,45 +5,45 @@ use Szurubooru\PDOEx\PDOEx;
|
|||
|
||||
class DatabaseConnection
|
||||
{
|
||||
private $pdo;
|
||||
private $config;
|
||||
private $pdo;
|
||||
private $config;
|
||||
|
||||
public function __construct(Config $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
public function __construct(Config $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
public function getPDO()
|
||||
{
|
||||
if (!$this->pdo)
|
||||
{
|
||||
$this->createPDO();
|
||||
}
|
||||
return $this->pdo;
|
||||
}
|
||||
public function getPDO()
|
||||
{
|
||||
if (!$this->pdo)
|
||||
{
|
||||
$this->createPDO();
|
||||
}
|
||||
return $this->pdo;
|
||||
}
|
||||
|
||||
public function getDriver()
|
||||
{
|
||||
return $this->getPDO()->getAttribute(\PDO::ATTR_DRIVER_NAME);
|
||||
}
|
||||
public function getDriver()
|
||||
{
|
||||
return $this->getPDO()->getAttribute(\PDO::ATTR_DRIVER_NAME);
|
||||
}
|
||||
|
||||
public function close()
|
||||
{
|
||||
$this->pdo = null;
|
||||
}
|
||||
public function close()
|
||||
{
|
||||
$this->pdo = null;
|
||||
}
|
||||
|
||||
private function createPDO()
|
||||
{
|
||||
$cwd = getcwd();
|
||||
if ($this->config->getDataDirectory())
|
||||
chdir($this->config->getDataDirectory());
|
||||
private function createPDO()
|
||||
{
|
||||
$cwd = getcwd();
|
||||
if ($this->config->getDataDirectory())
|
||||
chdir($this->config->getDataDirectory());
|
||||
|
||||
$this->pdo = new PDOEx(
|
||||
$this->config->database->dsn,
|
||||
$this->config->database->user,
|
||||
$this->config->database->password);
|
||||
$this->pdo = new PDOEx(
|
||||
$this->config->database->dsn,
|
||||
$this->config->database->user,
|
||||
$this->config->database->password);
|
||||
|
||||
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
chdir($cwd);
|
||||
}
|
||||
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||
chdir($cwd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,78 +10,78 @@ use Szurubooru\Services\TokenService;
|
|||
|
||||
final class Dispatcher
|
||||
{
|
||||
private $router;
|
||||
private $config;
|
||||
private $databaseConnection;
|
||||
private $authService;
|
||||
private $tokenService;
|
||||
private $router;
|
||||
private $config;
|
||||
private $databaseConnection;
|
||||
private $authService;
|
||||
private $tokenService;
|
||||
|
||||
public function __construct(
|
||||
Router $router,
|
||||
Config $config,
|
||||
DatabaseConnection $databaseConnection,
|
||||
HttpHelper $httpHelper,
|
||||
AuthService $authService,
|
||||
TokenService $tokenService,
|
||||
RouteRepository $routeRepository)
|
||||
{
|
||||
$this->router = $router;
|
||||
$this->config = $config;
|
||||
$this->databaseConnection = $databaseConnection;
|
||||
$this->httpHelper = $httpHelper;
|
||||
$this->authService = $authService;
|
||||
$this->tokenService = $tokenService;
|
||||
public function __construct(
|
||||
Router $router,
|
||||
Config $config,
|
||||
DatabaseConnection $databaseConnection,
|
||||
HttpHelper $httpHelper,
|
||||
AuthService $authService,
|
||||
TokenService $tokenService,
|
||||
RouteRepository $routeRepository)
|
||||
{
|
||||
$this->router = $router;
|
||||
$this->config = $config;
|
||||
$this->databaseConnection = $databaseConnection;
|
||||
$this->httpHelper = $httpHelper;
|
||||
$this->authService = $authService;
|
||||
$this->tokenService = $tokenService;
|
||||
|
||||
//if script fails prematurely, mark it as fail from advance
|
||||
$this->httpHelper->setResponseCode(500);
|
||||
//if script fails prematurely, mark it as fail from advance
|
||||
$this->httpHelper->setResponseCode(500);
|
||||
|
||||
$routeRepository->injectRoutes($router);
|
||||
}
|
||||
$routeRepository->injectRoutes($router);
|
||||
}
|
||||
|
||||
public function run($requestMethod, $requestUri)
|
||||
{
|
||||
try
|
||||
{
|
||||
$code = 200;
|
||||
$this->authorizeFromRequestHeader();
|
||||
$json = (array) $this->router->handle($requestMethod, $requestUri);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$code = 400;
|
||||
$trace = $e->getTrace();
|
||||
foreach ($trace as &$item)
|
||||
unset($item['args']);
|
||||
$json = [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $trace,
|
||||
];
|
||||
}
|
||||
$end = microtime(true);
|
||||
$json['__time'] = $end - Bootstrap::getStartTime();
|
||||
if ($this->config->misc->dumpSqlIntoQueries)
|
||||
{
|
||||
$json['__queries'] = $this->databaseConnection->getPDO()->getQueryCount();
|
||||
$json['__statements'] = $this->databaseConnection->getPDO()->getStatements();
|
||||
}
|
||||
public function run($requestMethod, $requestUri)
|
||||
{
|
||||
try
|
||||
{
|
||||
$code = 200;
|
||||
$this->authorizeFromRequestHeader();
|
||||
$json = (array) $this->router->handle($requestMethod, $requestUri);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$code = 400;
|
||||
$trace = $e->getTrace();
|
||||
foreach ($trace as &$item)
|
||||
unset($item['args']);
|
||||
$json = [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $trace,
|
||||
];
|
||||
}
|
||||
$end = microtime(true);
|
||||
$json['__time'] = $end - Bootstrap::getStartTime();
|
||||
if ($this->config->misc->dumpSqlIntoQueries)
|
||||
{
|
||||
$json['__queries'] = $this->databaseConnection->getPDO()->getQueryCount();
|
||||
$json['__statements'] = $this->databaseConnection->getPDO()->getStatements();
|
||||
}
|
||||
|
||||
if (!$this->httpHelper->isRedirecting())
|
||||
{
|
||||
$this->httpHelper->setResponseCode($code);
|
||||
$this->httpHelper->setHeader('Content-Type', 'application/json');
|
||||
$this->httpHelper->outputJSON($json);
|
||||
}
|
||||
if (!$this->httpHelper->isRedirecting())
|
||||
{
|
||||
$this->httpHelper->setResponseCode($code);
|
||||
$this->httpHelper->setHeader('Content-Type', 'application/json');
|
||||
$this->httpHelper->outputJSON($json);
|
||||
}
|
||||
|
||||
return $json;
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
|
||||
private function authorizeFromRequestHeader()
|
||||
{
|
||||
$loginTokenName = $this->httpHelper->getRequestHeader('X-Authorization-Token');
|
||||
if ($loginTokenName)
|
||||
{
|
||||
$token = $this->tokenService->getByName($loginTokenName);
|
||||
$this->authService->loginFromToken($token);
|
||||
}
|
||||
}
|
||||
private function authorizeFromRequestHeader()
|
||||
{
|
||||
$loginTokenName = $this->httpHelper->getRequestHeader('X-Authorization-Token');
|
||||
if ($loginTokenName)
|
||||
{
|
||||
$token = $this->tokenService->getByName($loginTokenName);
|
||||
$this->authService->loginFromToken($token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,91 +5,91 @@ use Szurubooru\Entities\User;
|
|||
|
||||
final class Comment extends Entity
|
||||
{
|
||||
private $postId;
|
||||
private $userId;
|
||||
private $creationTime;
|
||||
private $lastEditTime;
|
||||
private $text;
|
||||
private $postId;
|
||||
private $userId;
|
||||
private $creationTime;
|
||||
private $lastEditTime;
|
||||
private $text;
|
||||
|
||||
const LAZY_LOADER_USER = 'user';
|
||||
const LAZY_LOADER_POST = 'post';
|
||||
const LAZY_LOADER_USER = 'user';
|
||||
const LAZY_LOADER_POST = 'post';
|
||||
|
||||
const META_SCORE = 'score';
|
||||
const META_SCORE = 'score';
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
public function getPostId()
|
||||
{
|
||||
return $this->postId;
|
||||
}
|
||||
public function getPostId()
|
||||
{
|
||||
return $this->postId;
|
||||
}
|
||||
|
||||
public function setPostId($postId)
|
||||
{
|
||||
$this->postId = $postId;
|
||||
}
|
||||
public function setPostId($postId)
|
||||
{
|
||||
$this->postId = $postId;
|
||||
}
|
||||
|
||||
public function getCreationTime()
|
||||
{
|
||||
return $this->creationTime;
|
||||
}
|
||||
public function getCreationTime()
|
||||
{
|
||||
return $this->creationTime;
|
||||
}
|
||||
|
||||
public function setCreationTime($creationTime)
|
||||
{
|
||||
$this->creationTime = $creationTime;
|
||||
}
|
||||
public function setCreationTime($creationTime)
|
||||
{
|
||||
$this->creationTime = $creationTime;
|
||||
}
|
||||
|
||||
public function getLastEditTime()
|
||||
{
|
||||
return $this->lastEditTime;
|
||||
}
|
||||
public function getLastEditTime()
|
||||
{
|
||||
return $this->lastEditTime;
|
||||
}
|
||||
|
||||
public function setLastEditTime($lastEditTime)
|
||||
{
|
||||
$this->lastEditTime = $lastEditTime;
|
||||
}
|
||||
public function setLastEditTime($lastEditTime)
|
||||
{
|
||||
$this->lastEditTime = $lastEditTime;
|
||||
}
|
||||
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
public function setText($text)
|
||||
{
|
||||
$this->text = $text;
|
||||
}
|
||||
public function setText($text)
|
||||
{
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_USER, null);
|
||||
}
|
||||
public function getUser()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_USER, null);
|
||||
}
|
||||
|
||||
public function setUser(User $user = null)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_USER, $user);
|
||||
$this->userId = $user ? $user->getId() : null;
|
||||
}
|
||||
public function setUser(User $user = null)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_USER, $user);
|
||||
$this->userId = $user ? $user->getId() : null;
|
||||
}
|
||||
|
||||
public function getPost()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_POST, null);
|
||||
}
|
||||
public function getPost()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_POST, null);
|
||||
}
|
||||
|
||||
public function setPost(Post $post)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_POST, $post);
|
||||
$this->postId = $post->getId();
|
||||
}
|
||||
public function setPost(Post $post)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_POST, $post);
|
||||
$this->postId = $post->getId();
|
||||
}
|
||||
|
||||
public function getScore()
|
||||
{
|
||||
return $this->getMeta(self::META_SCORE, 0);
|
||||
}
|
||||
public function getScore()
|
||||
{
|
||||
return $this->getMeta(self::META_SCORE, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,74 +3,74 @@ namespace Szurubooru\Entities;
|
|||
|
||||
abstract class Entity
|
||||
{
|
||||
protected $id = null;
|
||||
private $lazyLoaders = [];
|
||||
private $lazyContainers = [];
|
||||
private $meta;
|
||||
protected $id = null;
|
||||
private $lazyLoaders = [];
|
||||
private $lazyContainers = [];
|
||||
private $meta;
|
||||
|
||||
public function __construct($id = null)
|
||||
{
|
||||
$this->id = $id === null ? null : intval($id);
|
||||
}
|
||||
public function __construct($id = null)
|
||||
{
|
||||
$this->id = $id === null ? null : intval($id);
|
||||
}
|
||||
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
public function setId($id)
|
||||
{
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function getMeta($metaName, $default = null)
|
||||
{
|
||||
if (!isset($this->meta[$metaName]))
|
||||
return $default;
|
||||
return $this->meta[$metaName];
|
||||
}
|
||||
public function getMeta($metaName, $default = null)
|
||||
{
|
||||
if (!isset($this->meta[$metaName]))
|
||||
return $default;
|
||||
return $this->meta[$metaName];
|
||||
}
|
||||
|
||||
public function setMeta($metaName, $value)
|
||||
{
|
||||
$this->meta[$metaName] = $value;
|
||||
}
|
||||
public function setMeta($metaName, $value)
|
||||
{
|
||||
$this->meta[$metaName] = $value;
|
||||
}
|
||||
|
||||
public function resetMeta()
|
||||
{
|
||||
$this->meta = [];
|
||||
}
|
||||
public function resetMeta()
|
||||
{
|
||||
$this->meta = [];
|
||||
}
|
||||
|
||||
public function resetLazyLoaders()
|
||||
{
|
||||
$this->lazyLoaders = [];
|
||||
$this->lazyContainers = [];
|
||||
}
|
||||
public function resetLazyLoaders()
|
||||
{
|
||||
$this->lazyLoaders = [];
|
||||
$this->lazyContainers = [];
|
||||
}
|
||||
|
||||
public function setLazyLoader($lazyContainerName, $getter)
|
||||
{
|
||||
$this->lazyLoaders[$lazyContainerName] = $getter;
|
||||
}
|
||||
public function setLazyLoader($lazyContainerName, $getter)
|
||||
{
|
||||
$this->lazyLoaders[$lazyContainerName] = $getter;
|
||||
}
|
||||
|
||||
protected function lazyLoad($lazyContainerName, $defaultValue)
|
||||
{
|
||||
if (!isset($this->lazyContainers[$lazyContainerName]))
|
||||
{
|
||||
if (!isset($this->lazyLoaders[$lazyContainerName]))
|
||||
{
|
||||
return $defaultValue;
|
||||
}
|
||||
$result = $this->lazyLoaders[$lazyContainerName]($this);
|
||||
$this->lazySave($lazyContainerName, $result);
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = $this->lazyContainers[$lazyContainerName];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
protected function lazyLoad($lazyContainerName, $defaultValue)
|
||||
{
|
||||
if (!isset($this->lazyContainers[$lazyContainerName]))
|
||||
{
|
||||
if (!isset($this->lazyLoaders[$lazyContainerName]))
|
||||
{
|
||||
return $defaultValue;
|
||||
}
|
||||
$result = $this->lazyLoaders[$lazyContainerName]($this);
|
||||
$this->lazySave($lazyContainerName, $result);
|
||||
}
|
||||
else
|
||||
{
|
||||
$result = $this->lazyContainers[$lazyContainerName];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function lazySave($lazyContainerName, $value)
|
||||
{
|
||||
$this->lazyContainers[$lazyContainerName] = $value;
|
||||
}
|
||||
protected function lazySave($lazyContainerName, $value)
|
||||
{
|
||||
$this->lazyContainers[$lazyContainerName] = $value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,62 +5,62 @@ use Szurubooru\Entities\User;
|
|||
|
||||
final class Favorite extends Entity
|
||||
{
|
||||
private $postId;
|
||||
private $userId;
|
||||
private $time;
|
||||
private $postId;
|
||||
private $userId;
|
||||
private $time;
|
||||
|
||||
const LAZY_LOADER_USER = 'user';
|
||||
const LAZY_LOADER_POST = 'post';
|
||||
const LAZY_LOADER_USER = 'user';
|
||||
const LAZY_LOADER_POST = 'post';
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
public function getPostId()
|
||||
{
|
||||
return $this->postId;
|
||||
}
|
||||
public function getPostId()
|
||||
{
|
||||
return $this->postId;
|
||||
}
|
||||
|
||||
public function setPostId($postId)
|
||||
{
|
||||
$this->postId = $postId;
|
||||
}
|
||||
public function setPostId($postId)
|
||||
{
|
||||
$this->postId = $postId;
|
||||
}
|
||||
|
||||
public function getTime()
|
||||
{
|
||||
return $this->time;
|
||||
}
|
||||
public function getTime()
|
||||
{
|
||||
return $this->time;
|
||||
}
|
||||
|
||||
public function setTime($time)
|
||||
{
|
||||
$this->time = $time;
|
||||
}
|
||||
public function setTime($time)
|
||||
{
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_USER, null);
|
||||
}
|
||||
public function getUser()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_USER, null);
|
||||
}
|
||||
|
||||
public function setUser(User $user)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_USER, $user);
|
||||
$this->userId = $user->getId();
|
||||
}
|
||||
public function setUser(User $user)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_USER, $user);
|
||||
$this->userId = $user->getId();
|
||||
}
|
||||
|
||||
public function getPost()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_POST, null);
|
||||
}
|
||||
public function getPost()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_POST, null);
|
||||
}
|
||||
|
||||
public function setPost(Post $post)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_POST, $post);
|
||||
$this->postId = $post->getId();
|
||||
}
|
||||
public function setPost(Post $post)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_POST, $post);
|
||||
$this->postId = $post->getId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,31 +3,31 @@ namespace Szurubooru\Entities;
|
|||
|
||||
final class GlobalParam extends Entity
|
||||
{
|
||||
const KEY_FEATURED_POST_USER = 'featuredPostUser';
|
||||
const KEY_FEATURED_POST = 'featuredPost';
|
||||
const KEY_POST_SIZE = 'postSize';
|
||||
const KEY_POST_COUNT = 'postCount';
|
||||
const KEY_FEATURED_POST_USER = 'featuredPostUser';
|
||||
const KEY_FEATURED_POST = 'featuredPost';
|
||||
const KEY_POST_SIZE = 'postSize';
|
||||
const KEY_POST_COUNT = 'postCount';
|
||||
|
||||
private $key;
|
||||
private $value;
|
||||
private $key;
|
||||
private $value;
|
||||
|
||||
public function getKey()
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
public function getKey()
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public function setKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
}
|
||||
public function setKey($key)
|
||||
{
|
||||
$this->key = $key;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
public function setValue($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,290 +4,290 @@ use Szurubooru\Entities\User;
|
|||
|
||||
final class Post extends Entity
|
||||
{
|
||||
const POST_SAFETY_SAFE = 1;
|
||||
const POST_SAFETY_SKETCHY = 2;
|
||||
const POST_SAFETY_UNSAFE = 3;
|
||||
const POST_SAFETY_SAFE = 1;
|
||||
const POST_SAFETY_SKETCHY = 2;
|
||||
const POST_SAFETY_UNSAFE = 3;
|
||||
|
||||
const POST_TYPE_IMAGE = 1;
|
||||
const POST_TYPE_FLASH = 2;
|
||||
const POST_TYPE_VIDEO = 3;
|
||||
const POST_TYPE_YOUTUBE = 4;
|
||||
const POST_TYPE_ANIMATED_IMAGE = 5;
|
||||
const POST_TYPE_IMAGE = 1;
|
||||
const POST_TYPE_FLASH = 2;
|
||||
const POST_TYPE_VIDEO = 3;
|
||||
const POST_TYPE_YOUTUBE = 4;
|
||||
const POST_TYPE_ANIMATED_IMAGE = 5;
|
||||
|
||||
const FLAG_LOOP = 1;
|
||||
const FLAG_LOOP = 1;
|
||||
|
||||
const LAZY_LOADER_USER = 'user';
|
||||
const LAZY_LOADER_TAGS = 'tags';
|
||||
const LAZY_LOADER_CONTENT = 'content';
|
||||
const LAZY_LOADER_THUMBNAIL_SOURCE_CONTENT = 'thumbnailSourceContent';
|
||||
const LAZY_LOADER_RELATED_POSTS = 'relatedPosts';
|
||||
const LAZY_LOADER_USER = 'user';
|
||||
const LAZY_LOADER_TAGS = 'tags';
|
||||
const LAZY_LOADER_CONTENT = 'content';
|
||||
const LAZY_LOADER_THUMBNAIL_SOURCE_CONTENT = 'thumbnailSourceContent';
|
||||
const LAZY_LOADER_RELATED_POSTS = 'relatedPosts';
|
||||
|
||||
const META_TAG_COUNT = 'tagCount';
|
||||
const META_FAV_COUNT = 'favCount';
|
||||
const META_COMMENT_COUNT = 'commentCount';
|
||||
const META_SCORE = 'score';
|
||||
const META_TAG_COUNT = 'tagCount';
|
||||
const META_FAV_COUNT = 'favCount';
|
||||
const META_COMMENT_COUNT = 'commentCount';
|
||||
const META_SCORE = 'score';
|
||||
|
||||
private $name;
|
||||
private $userId;
|
||||
private $uploadTime;
|
||||
private $lastEditTime;
|
||||
private $safety;
|
||||
private $contentType;
|
||||
private $contentChecksum;
|
||||
private $contentMimeType;
|
||||
private $source;
|
||||
private $imageWidth;
|
||||
private $imageHeight;
|
||||
private $originalFileSize;
|
||||
private $originalFileName;
|
||||
private $featureCount = 0;
|
||||
private $lastFeatureTime;
|
||||
private $flags = 0;
|
||||
private $name;
|
||||
private $userId;
|
||||
private $uploadTime;
|
||||
private $lastEditTime;
|
||||
private $safety;
|
||||
private $contentType;
|
||||
private $contentChecksum;
|
||||
private $contentMimeType;
|
||||
private $source;
|
||||
private $imageWidth;
|
||||
private $imageHeight;
|
||||
private $originalFileSize;
|
||||
private $originalFileName;
|
||||
private $featureCount = 0;
|
||||
private $lastFeatureTime;
|
||||
private $flags = 0;
|
||||
|
||||
public function getIdMarkdown()
|
||||
{
|
||||
return '@' . $this->id;
|
||||
}
|
||||
public function getIdMarkdown()
|
||||
{
|
||||
return '@' . $this->id;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
public function getSafety()
|
||||
{
|
||||
return $this->safety;
|
||||
}
|
||||
public function getSafety()
|
||||
{
|
||||
return $this->safety;
|
||||
}
|
||||
|
||||
public function setSafety($safety)
|
||||
{
|
||||
$this->safety = $safety;
|
||||
}
|
||||
public function setSafety($safety)
|
||||
{
|
||||
$this->safety = $safety;
|
||||
}
|
||||
|
||||
public function getUploadTime()
|
||||
{
|
||||
return $this->uploadTime;
|
||||
}
|
||||
public function getUploadTime()
|
||||
{
|
||||
return $this->uploadTime;
|
||||
}
|
||||
|
||||
public function setUploadTime($uploadTime)
|
||||
{
|
||||
$this->uploadTime = $uploadTime;
|
||||
}
|
||||
public function setUploadTime($uploadTime)
|
||||
{
|
||||
$this->uploadTime = $uploadTime;
|
||||
}
|
||||
|
||||
public function getLastEditTime()
|
||||
{
|
||||
return $this->lastEditTime;
|
||||
}
|
||||
public function getLastEditTime()
|
||||
{
|
||||
return $this->lastEditTime;
|
||||
}
|
||||
|
||||
public function setLastEditTime($lastEditTime)
|
||||
{
|
||||
$this->lastEditTime = $lastEditTime;
|
||||
}
|
||||
public function setLastEditTime($lastEditTime)
|
||||
{
|
||||
$this->lastEditTime = $lastEditTime;
|
||||
}
|
||||
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->contentType;
|
||||
}
|
||||
public function getContentType()
|
||||
{
|
||||
return $this->contentType;
|
||||
}
|
||||
|
||||
public function setContentType($contentType)
|
||||
{
|
||||
$this->contentType = $contentType;
|
||||
}
|
||||
public function setContentType($contentType)
|
||||
{
|
||||
$this->contentType = $contentType;
|
||||
}
|
||||
|
||||
public function getContentChecksum()
|
||||
{
|
||||
return $this->contentChecksum;
|
||||
}
|
||||
public function getContentChecksum()
|
||||
{
|
||||
return $this->contentChecksum;
|
||||
}
|
||||
|
||||
public function setContentChecksum($contentChecksum)
|
||||
{
|
||||
$this->contentChecksum = $contentChecksum;
|
||||
}
|
||||
public function setContentChecksum($contentChecksum)
|
||||
{
|
||||
$this->contentChecksum = $contentChecksum;
|
||||
}
|
||||
|
||||
public function getContentMimeType()
|
||||
{
|
||||
return $this->contentMimeType;
|
||||
}
|
||||
public function getContentMimeType()
|
||||
{
|
||||
return $this->contentMimeType;
|
||||
}
|
||||
|
||||
public function setContentMimeType($contentMimeType)
|
||||
{
|
||||
$this->contentMimeType = $contentMimeType;
|
||||
}
|
||||
public function setContentMimeType($contentMimeType)
|
||||
{
|
||||
$this->contentMimeType = $contentMimeType;
|
||||
}
|
||||
|
||||
public function getSource()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
public function getSource()
|
||||
{
|
||||
return $this->source;
|
||||
}
|
||||
|
||||
public function setSource($source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
public function setSource($source)
|
||||
{
|
||||
$this->source = $source;
|
||||
}
|
||||
|
||||
public function getImageWidth()
|
||||
{
|
||||
return $this->imageWidth;
|
||||
}
|
||||
public function getImageWidth()
|
||||
{
|
||||
return $this->imageWidth;
|
||||
}
|
||||
|
||||
public function setImageWidth($imageWidth)
|
||||
{
|
||||
$this->imageWidth = $imageWidth;
|
||||
}
|
||||
public function setImageWidth($imageWidth)
|
||||
{
|
||||
$this->imageWidth = $imageWidth;
|
||||
}
|
||||
|
||||
public function getImageHeight()
|
||||
{
|
||||
return $this->imageHeight;
|
||||
}
|
||||
public function getImageHeight()
|
||||
{
|
||||
return $this->imageHeight;
|
||||
}
|
||||
|
||||
public function setImageHeight($imageHeight)
|
||||
{
|
||||
$this->imageHeight = $imageHeight;
|
||||
}
|
||||
public function setImageHeight($imageHeight)
|
||||
{
|
||||
$this->imageHeight = $imageHeight;
|
||||
}
|
||||
|
||||
public function getOriginalFileSize()
|
||||
{
|
||||
return $this->originalFileSize;
|
||||
}
|
||||
public function getOriginalFileSize()
|
||||
{
|
||||
return $this->originalFileSize;
|
||||
}
|
||||
|
||||
public function setOriginalFileSize($originalFileSize)
|
||||
{
|
||||
$this->originalFileSize = $originalFileSize;
|
||||
}
|
||||
public function setOriginalFileSize($originalFileSize)
|
||||
{
|
||||
$this->originalFileSize = $originalFileSize;
|
||||
}
|
||||
|
||||
public function getOriginalFileName()
|
||||
{
|
||||
return $this->originalFileName;
|
||||
}
|
||||
public function getOriginalFileName()
|
||||
{
|
||||
return $this->originalFileName;
|
||||
}
|
||||
|
||||
public function setOriginalFileName($originalFileName)
|
||||
{
|
||||
$this->originalFileName = $originalFileName;
|
||||
}
|
||||
public function setOriginalFileName($originalFileName)
|
||||
{
|
||||
$this->originalFileName = $originalFileName;
|
||||
}
|
||||
|
||||
public function getFeatureCount()
|
||||
{
|
||||
return $this->featureCount;
|
||||
}
|
||||
public function getFeatureCount()
|
||||
{
|
||||
return $this->featureCount;
|
||||
}
|
||||
|
||||
public function setFeatureCount($featureCount)
|
||||
{
|
||||
$this->featureCount = $featureCount;
|
||||
}
|
||||
public function setFeatureCount($featureCount)
|
||||
{
|
||||
$this->featureCount = $featureCount;
|
||||
}
|
||||
|
||||
public function getLastFeatureTime()
|
||||
{
|
||||
return $this->lastFeatureTime;
|
||||
}
|
||||
public function getLastFeatureTime()
|
||||
{
|
||||
return $this->lastFeatureTime;
|
||||
}
|
||||
|
||||
public function setLastFeatureTime($lastFeatureTime)
|
||||
{
|
||||
$this->lastFeatureTime = $lastFeatureTime;
|
||||
}
|
||||
public function setLastFeatureTime($lastFeatureTime)
|
||||
{
|
||||
$this->lastFeatureTime = $lastFeatureTime;
|
||||
}
|
||||
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->flags;
|
||||
}
|
||||
|
||||
public function setFlags($flags)
|
||||
{
|
||||
$this->flags = $flags;
|
||||
}
|
||||
public function setFlags($flags)
|
||||
{
|
||||
$this->flags = $flags;
|
||||
}
|
||||
|
||||
public function getTags()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_TAGS, []);
|
||||
}
|
||||
public function getTags()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_TAGS, []);
|
||||
}
|
||||
|
||||
public function setTags(array $tags)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_TAGS, $tags);
|
||||
$this->setMeta(self::META_TAG_COUNT, count($tags));
|
||||
}
|
||||
public function setTags(array $tags)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_TAGS, $tags);
|
||||
$this->setMeta(self::META_TAG_COUNT, count($tags));
|
||||
}
|
||||
|
||||
public function getRelatedPosts()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_RELATED_POSTS, []);
|
||||
}
|
||||
public function getRelatedPosts()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_RELATED_POSTS, []);
|
||||
}
|
||||
|
||||
public function setRelatedPosts(array $relatedPosts)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_RELATED_POSTS, $relatedPosts);
|
||||
}
|
||||
public function setRelatedPosts(array $relatedPosts)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_RELATED_POSTS, $relatedPosts);
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_USER, null);
|
||||
}
|
||||
public function getUser()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_USER, null);
|
||||
}
|
||||
|
||||
public function setUser(User $user = null)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_USER, $user);
|
||||
$this->userId = $user ? $user->getId() : null;
|
||||
}
|
||||
public function setUser(User $user = null)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_USER, $user);
|
||||
$this->userId = $user ? $user->getId() : null;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_CONTENT, null);
|
||||
}
|
||||
public function getContent()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_CONTENT, null);
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_CONTENT, $content);
|
||||
}
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_CONTENT, $content);
|
||||
}
|
||||
|
||||
public function getThumbnailSourceContent()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_THUMBNAIL_SOURCE_CONTENT, null);
|
||||
}
|
||||
public function getThumbnailSourceContent()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_THUMBNAIL_SOURCE_CONTENT, null);
|
||||
}
|
||||
|
||||
public function setThumbnailSourceContent($content)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_THUMBNAIL_SOURCE_CONTENT, $content);
|
||||
}
|
||||
public function setThumbnailSourceContent($content)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_THUMBNAIL_SOURCE_CONTENT, $content);
|
||||
}
|
||||
|
||||
public function getContentPath()
|
||||
{
|
||||
return 'posts' . DIRECTORY_SEPARATOR . $this->getName();
|
||||
}
|
||||
public function getContentPath()
|
||||
{
|
||||
return 'posts' . DIRECTORY_SEPARATOR . $this->getName();
|
||||
}
|
||||
|
||||
public function getThumbnailSourceContentPath()
|
||||
{
|
||||
return 'posts' . DIRECTORY_SEPARATOR . $this->getName() . '-custom-thumb';
|
||||
}
|
||||
public function getThumbnailSourceContentPath()
|
||||
{
|
||||
return 'posts' . DIRECTORY_SEPARATOR . $this->getName() . '-custom-thumb';
|
||||
}
|
||||
|
||||
public function getTagCount()
|
||||
{
|
||||
return $this->getMeta(self::META_TAG_COUNT, 0);
|
||||
}
|
||||
public function getTagCount()
|
||||
{
|
||||
return $this->getMeta(self::META_TAG_COUNT, 0);
|
||||
}
|
||||
|
||||
public function getFavoriteCount()
|
||||
{
|
||||
return $this->getMeta(self::META_FAV_COUNT, 0);
|
||||
}
|
||||
public function getFavoriteCount()
|
||||
{
|
||||
return $this->getMeta(self::META_FAV_COUNT, 0);
|
||||
}
|
||||
|
||||
public function getCommentCount()
|
||||
{
|
||||
return $this->getMeta(self::META_COMMENT_COUNT, 0);
|
||||
}
|
||||
public function getCommentCount()
|
||||
{
|
||||
return $this->getMeta(self::META_COMMENT_COUNT, 0);
|
||||
}
|
||||
|
||||
public function getScore()
|
||||
{
|
||||
return $this->getMeta(self::META_SCORE, 0);
|
||||
}
|
||||
public function getScore()
|
||||
{
|
||||
return $this->getMeta(self::META_SCORE, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,83 +3,83 @@ namespace Szurubooru\Entities;
|
|||
|
||||
final class PostNote extends Entity
|
||||
{
|
||||
private $postId;
|
||||
private $left;
|
||||
private $top;
|
||||
private $width;
|
||||
private $height;
|
||||
private $text;
|
||||
private $postId;
|
||||
private $left;
|
||||
private $top;
|
||||
private $width;
|
||||
private $height;
|
||||
private $text;
|
||||
|
||||
const LAZY_LOADER_POST = 'post';
|
||||
const LAZY_LOADER_POST = 'post';
|
||||
|
||||
public function getPostId()
|
||||
{
|
||||
return $this->postId;
|
||||
}
|
||||
public function getPostId()
|
||||
{
|
||||
return $this->postId;
|
||||
}
|
||||
|
||||
public function setPostId($postId)
|
||||
{
|
||||
$this->postId = $postId;
|
||||
}
|
||||
public function setPostId($postId)
|
||||
{
|
||||
$this->postId = $postId;
|
||||
}
|
||||
|
||||
public function getLeft()
|
||||
{
|
||||
return $this->left;
|
||||
}
|
||||
public function getLeft()
|
||||
{
|
||||
return $this->left;
|
||||
}
|
||||
|
||||
public function setLeft($left)
|
||||
{
|
||||
$this->left = $left;
|
||||
}
|
||||
public function setLeft($left)
|
||||
{
|
||||
$this->left = $left;
|
||||
}
|
||||
|
||||
public function getTop()
|
||||
{
|
||||
return $this->top;
|
||||
}
|
||||
public function getTop()
|
||||
{
|
||||
return $this->top;
|
||||
}
|
||||
|
||||
public function setTop($top)
|
||||
{
|
||||
$this->top = $top;
|
||||
}
|
||||
public function setTop($top)
|
||||
{
|
||||
$this->top = $top;
|
||||
}
|
||||
|
||||
public function getWidth()
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
public function getWidth()
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
public function setWidth($width)
|
||||
{
|
||||
$this->width = $width;
|
||||
}
|
||||
public function setWidth($width)
|
||||
{
|
||||
$this->width = $width;
|
||||
}
|
||||
|
||||
public function getHeight()
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
public function getHeight()
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
public function setHeight($height)
|
||||
{
|
||||
$this->height = $height;
|
||||
}
|
||||
public function setHeight($height)
|
||||
{
|
||||
$this->height = $height;
|
||||
}
|
||||
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
public function getText()
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
public function setText($text)
|
||||
{
|
||||
$this->text = $text;
|
||||
}
|
||||
public function setText($text)
|
||||
{
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
public function getPost()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_POST, null);
|
||||
}
|
||||
public function getPost()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_POST, null);
|
||||
}
|
||||
|
||||
public function setPost(Post $post)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_POST, $post);
|
||||
$this->postId = $post->getId();
|
||||
}
|
||||
public function setPost(Post $post)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_POST, $post);
|
||||
$this->postId = $post->getId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,59 +3,59 @@ namespace Szurubooru\Entities;
|
|||
|
||||
final class Score extends Entity
|
||||
{
|
||||
private $postId;
|
||||
private $commentId;
|
||||
private $score;
|
||||
private $time;
|
||||
private $userId;
|
||||
private $postId;
|
||||
private $commentId;
|
||||
private $score;
|
||||
private $time;
|
||||
private $userId;
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
public function getPostId()
|
||||
{
|
||||
return $this->postId;
|
||||
}
|
||||
public function getPostId()
|
||||
{
|
||||
return $this->postId;
|
||||
}
|
||||
|
||||
public function setPostId($postId)
|
||||
{
|
||||
$this->postId = $postId;
|
||||
}
|
||||
public function setPostId($postId)
|
||||
{
|
||||
$this->postId = $postId;
|
||||
}
|
||||
|
||||
public function getCommentId()
|
||||
{
|
||||
return $this->commentId;
|
||||
}
|
||||
public function getCommentId()
|
||||
{
|
||||
return $this->commentId;
|
||||
}
|
||||
|
||||
public function setCommentId($commentId)
|
||||
{
|
||||
$this->commentId = $commentId;
|
||||
}
|
||||
public function setCommentId($commentId)
|
||||
{
|
||||
$this->commentId = $commentId;
|
||||
}
|
||||
|
||||
public function getTime()
|
||||
{
|
||||
return $this->time;
|
||||
}
|
||||
public function getTime()
|
||||
{
|
||||
return $this->time;
|
||||
}
|
||||
|
||||
public function setTime($time)
|
||||
{
|
||||
$this->time = $time;
|
||||
}
|
||||
public function setTime($time)
|
||||
{
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
public function getScore()
|
||||
{
|
||||
return $this->score;
|
||||
}
|
||||
public function getScore()
|
||||
{
|
||||
return $this->score;
|
||||
}
|
||||
|
||||
public function setScore($score)
|
||||
{
|
||||
$this->score = $score;
|
||||
}
|
||||
public function setScore($score)
|
||||
{
|
||||
$this->score = $score;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,101 +4,101 @@ use Szurubooru\Entities\User;
|
|||
|
||||
final class Snapshot extends Entity
|
||||
{
|
||||
const TYPE_POST = 0;
|
||||
const TYPE_TAG = 1;
|
||||
const TYPE_POST = 0;
|
||||
const TYPE_TAG = 1;
|
||||
|
||||
const OPERATION_CREATION = 0;
|
||||
const OPERATION_CHANGE = 1;
|
||||
const OPERATION_DELETE = 2;
|
||||
const OPERATION_CREATION = 0;
|
||||
const OPERATION_CHANGE = 1;
|
||||
const OPERATION_DELETE = 2;
|
||||
|
||||
const LAZY_LOADER_USER = 'user';
|
||||
const LAZY_LOADER_USER = 'user';
|
||||
|
||||
private $time;
|
||||
private $type;
|
||||
private $primaryKey;
|
||||
private $operation;
|
||||
private $userId;
|
||||
private $data;
|
||||
private $dataDifference;
|
||||
private $time;
|
||||
private $type;
|
||||
private $primaryKey;
|
||||
private $operation;
|
||||
private $userId;
|
||||
private $data;
|
||||
private $dataDifference;
|
||||
|
||||
public function getTime()
|
||||
{
|
||||
return $this->time;
|
||||
}
|
||||
public function getTime()
|
||||
{
|
||||
return $this->time;
|
||||
}
|
||||
|
||||
public function setTime($time)
|
||||
{
|
||||
$this->time = $time;
|
||||
}
|
||||
public function setTime($time)
|
||||
{
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function getPrimaryKey()
|
||||
{
|
||||
return $this->primaryKey;
|
||||
}
|
||||
public function getPrimaryKey()
|
||||
{
|
||||
return $this->primaryKey;
|
||||
}
|
||||
|
||||
public function setPrimaryKey($primaryKey)
|
||||
{
|
||||
$this->primaryKey = $primaryKey;
|
||||
}
|
||||
public function setPrimaryKey($primaryKey)
|
||||
{
|
||||
$this->primaryKey = $primaryKey;
|
||||
}
|
||||
|
||||
public function getOperation()
|
||||
{
|
||||
return $this->operation;
|
||||
}
|
||||
public function getOperation()
|
||||
{
|
||||
return $this->operation;
|
||||
}
|
||||
|
||||
public function setOperation($operation)
|
||||
{
|
||||
$this->operation = $operation;
|
||||
}
|
||||
public function setOperation($operation)
|
||||
{
|
||||
$this->operation = $operation;
|
||||
}
|
||||
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
public function setUserId($userId)
|
||||
{
|
||||
$this->userId = $userId;
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function setData($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
public function setData($data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function getDataDifference()
|
||||
{
|
||||
return $this->dataDifference;
|
||||
}
|
||||
public function getDataDifference()
|
||||
{
|
||||
return $this->dataDifference;
|
||||
}
|
||||
|
||||
public function setDataDifference($dataDifference)
|
||||
{
|
||||
$this->dataDifference = $dataDifference;
|
||||
}
|
||||
public function setDataDifference($dataDifference)
|
||||
{
|
||||
$this->dataDifference = $dataDifference;
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_USER, null);
|
||||
}
|
||||
public function getUser()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_USER, null);
|
||||
}
|
||||
|
||||
public function setUser(User $user = null)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_USER, $user);
|
||||
$this->userId = $user ? $user->getId() : null;
|
||||
}
|
||||
public function setUser(User $user = null)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_USER, $user);
|
||||
$this->userId = $user ? $user->getId() : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,78 +3,78 @@ namespace Szurubooru\Entities;
|
|||
|
||||
final class Tag extends Entity
|
||||
{
|
||||
private $name;
|
||||
private $creationTime;
|
||||
private $banned = false;
|
||||
private $category = 'default';
|
||||
private $name;
|
||||
private $creationTime;
|
||||
private $banned = false;
|
||||
private $category = 'default';
|
||||
|
||||
const LAZY_LOADER_IMPLIED_TAGS = 'implications';
|
||||
const LAZY_LOADER_SUGGESTED_TAGS = 'suggestions';
|
||||
const LAZY_LOADER_IMPLIED_TAGS = 'implications';
|
||||
const LAZY_LOADER_SUGGESTED_TAGS = 'suggestions';
|
||||
|
||||
const META_USAGES = 'usages';
|
||||
const META_USAGES = 'usages';
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getCreationTime()
|
||||
{
|
||||
return $this->creationTime;
|
||||
}
|
||||
public function getCreationTime()
|
||||
{
|
||||
return $this->creationTime;
|
||||
}
|
||||
|
||||
public function setCreationTime($creationTime)
|
||||
{
|
||||
$this->creationTime = $creationTime;
|
||||
}
|
||||
public function setCreationTime($creationTime)
|
||||
{
|
||||
$this->creationTime = $creationTime;
|
||||
}
|
||||
|
||||
public function isBanned()
|
||||
{
|
||||
return $this->banned;
|
||||
}
|
||||
public function isBanned()
|
||||
{
|
||||
return $this->banned;
|
||||
}
|
||||
|
||||
public function setBanned($banned)
|
||||
{
|
||||
$this->banned = boolval($banned);
|
||||
}
|
||||
public function setBanned($banned)
|
||||
{
|
||||
$this->banned = boolval($banned);
|
||||
}
|
||||
|
||||
public function getCategory()
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
public function getCategory()
|
||||
{
|
||||
return $this->category;
|
||||
}
|
||||
|
||||
public function setCategory($category)
|
||||
{
|
||||
$this->category = $category;
|
||||
}
|
||||
public function setCategory($category)
|
||||
{
|
||||
$this->category = $category;
|
||||
}
|
||||
|
||||
public function getUsages()
|
||||
{
|
||||
return $this->getMeta(self::META_USAGES);
|
||||
}
|
||||
public function getUsages()
|
||||
{
|
||||
return $this->getMeta(self::META_USAGES);
|
||||
}
|
||||
|
||||
public function getImpliedTags()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_IMPLIED_TAGS, []);
|
||||
}
|
||||
public function getImpliedTags()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_IMPLIED_TAGS, []);
|
||||
}
|
||||
|
||||
public function setImpliedTags(array $impliedTags)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_IMPLIED_TAGS, $impliedTags);
|
||||
}
|
||||
public function setImpliedTags(array $impliedTags)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_IMPLIED_TAGS, $impliedTags);
|
||||
}
|
||||
|
||||
public function getSuggestedTags()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_SUGGESTED_TAGS, []);
|
||||
}
|
||||
public function getSuggestedTags()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_SUGGESTED_TAGS, []);
|
||||
}
|
||||
|
||||
public function setSuggestedTags(array $suggestedTags)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_SUGGESTED_TAGS, $suggestedTags);
|
||||
}
|
||||
public function setSuggestedTags(array $suggestedTags)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_SUGGESTED_TAGS, $suggestedTags);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,41 +3,41 @@ namespace Szurubooru\Entities;
|
|||
|
||||
final class Token extends Entity
|
||||
{
|
||||
const PURPOSE_LOGIN = 1;
|
||||
const PURPOSE_ACTIVATE = 2;
|
||||
const PURPOSE_PASSWORD_RESET = 3;
|
||||
const PURPOSE_LOGIN = 1;
|
||||
const PURPOSE_ACTIVATE = 2;
|
||||
const PURPOSE_PASSWORD_RESET = 3;
|
||||
|
||||
private $name;
|
||||
private $purpose;
|
||||
private $additionalData;
|
||||
private $name;
|
||||
private $purpose;
|
||||
private $additionalData;
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getPurpose()
|
||||
{
|
||||
return $this->purpose;
|
||||
}
|
||||
public function getPurpose()
|
||||
{
|
||||
return $this->purpose;
|
||||
}
|
||||
|
||||
public function setPurpose($purpose)
|
||||
{
|
||||
$this->purpose = intval($purpose);
|
||||
}
|
||||
public function setPurpose($purpose)
|
||||
{
|
||||
$this->purpose = intval($purpose);
|
||||
}
|
||||
|
||||
public function getAdditionalData()
|
||||
{
|
||||
return $this->additionalData;
|
||||
}
|
||||
public function getAdditionalData()
|
||||
{
|
||||
return $this->additionalData;
|
||||
}
|
||||
|
||||
public function setAdditionalData($additionalData)
|
||||
{
|
||||
$this->additionalData = $additionalData;
|
||||
}
|
||||
public function setAdditionalData($additionalData)
|
||||
{
|
||||
$this->additionalData = $additionalData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,165 +3,165 @@ namespace Szurubooru\Entities;
|
|||
|
||||
final class User extends Entity
|
||||
{
|
||||
const ACCESS_RANK_NOBODY = 0;
|
||||
const ACCESS_RANK_ANONYMOUS = 1;
|
||||
const ACCESS_RANK_RESTRICTED_USER = 2;
|
||||
const ACCESS_RANK_REGULAR_USER = 3;
|
||||
const ACCESS_RANK_POWER_USER = 4;
|
||||
const ACCESS_RANK_MODERATOR = 5;
|
||||
const ACCESS_RANK_ADMINISTRATOR = 6;
|
||||
const ACCESS_RANK_NOBODY = 0;
|
||||
const ACCESS_RANK_ANONYMOUS = 1;
|
||||
const ACCESS_RANK_RESTRICTED_USER = 2;
|
||||
const ACCESS_RANK_REGULAR_USER = 3;
|
||||
const ACCESS_RANK_POWER_USER = 4;
|
||||
const ACCESS_RANK_MODERATOR = 5;
|
||||
const ACCESS_RANK_ADMINISTRATOR = 6;
|
||||
|
||||
const AVATAR_STYLE_GRAVATAR = 1;
|
||||
const AVATAR_STYLE_MANUAL = 2;
|
||||
const AVATAR_STYLE_BLANK = 3;
|
||||
const AVATAR_STYLE_GRAVATAR = 1;
|
||||
const AVATAR_STYLE_MANUAL = 2;
|
||||
const AVATAR_STYLE_BLANK = 3;
|
||||
|
||||
const LAZY_LOADER_CUSTOM_AVATAR_SOURCE_CONTENT = 'customAvatarContent';
|
||||
const LAZY_LOADER_CUSTOM_AVATAR_SOURCE_CONTENT = 'customAvatarContent';
|
||||
|
||||
private $name;
|
||||
private $email;
|
||||
private $emailUnconfirmed;
|
||||
private $passwordHash;
|
||||
private $passwordSalt;
|
||||
private $accessRank;
|
||||
private $registrationTime;
|
||||
private $lastLoginTime;
|
||||
private $avatarStyle;
|
||||
private $browsingSettings;
|
||||
private $accountConfirmed = false;
|
||||
private $banned = false;
|
||||
private $name;
|
||||
private $email;
|
||||
private $emailUnconfirmed;
|
||||
private $passwordHash;
|
||||
private $passwordSalt;
|
||||
private $accessRank;
|
||||
private $registrationTime;
|
||||
private $lastLoginTime;
|
||||
private $avatarStyle;
|
||||
private $browsingSettings;
|
||||
private $accountConfirmed = false;
|
||||
private $banned = false;
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getEmail()
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
public function getEmail()
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail($email)
|
||||
{
|
||||
$this->email = $email;
|
||||
}
|
||||
public function setEmail($email)
|
||||
{
|
||||
$this->email = $email;
|
||||
}
|
||||
|
||||
public function getEmailUnconfirmed()
|
||||
{
|
||||
return $this->emailUnconfirmed;
|
||||
}
|
||||
public function getEmailUnconfirmed()
|
||||
{
|
||||
return $this->emailUnconfirmed;
|
||||
}
|
||||
|
||||
public function setEmailUnconfirmed($emailUnconfirmed)
|
||||
{
|
||||
$this->emailUnconfirmed = $emailUnconfirmed;
|
||||
}
|
||||
public function setEmailUnconfirmed($emailUnconfirmed)
|
||||
{
|
||||
$this->emailUnconfirmed = $emailUnconfirmed;
|
||||
}
|
||||
|
||||
public function isBanned()
|
||||
{
|
||||
return $this->banned;
|
||||
}
|
||||
public function isBanned()
|
||||
{
|
||||
return $this->banned;
|
||||
}
|
||||
|
||||
public function setBanned($banned)
|
||||
{
|
||||
$this->banned = boolval($banned);
|
||||
}
|
||||
public function setBanned($banned)
|
||||
{
|
||||
$this->banned = boolval($banned);
|
||||
}
|
||||
|
||||
public function isAccountConfirmed()
|
||||
{
|
||||
return $this->accountConfirmed;
|
||||
}
|
||||
public function isAccountConfirmed()
|
||||
{
|
||||
return $this->accountConfirmed;
|
||||
}
|
||||
|
||||
public function setAccountConfirmed($accountConfirmed)
|
||||
{
|
||||
$this->accountConfirmed = boolval($accountConfirmed);
|
||||
}
|
||||
public function setAccountConfirmed($accountConfirmed)
|
||||
{
|
||||
$this->accountConfirmed = boolval($accountConfirmed);
|
||||
}
|
||||
|
||||
public function getPasswordHash()
|
||||
{
|
||||
return $this->passwordHash;
|
||||
}
|
||||
public function getPasswordHash()
|
||||
{
|
||||
return $this->passwordHash;
|
||||
}
|
||||
|
||||
public function setPasswordHash($passwordHash)
|
||||
{
|
||||
$this->passwordHash = $passwordHash;
|
||||
}
|
||||
public function setPasswordHash($passwordHash)
|
||||
{
|
||||
$this->passwordHash = $passwordHash;
|
||||
}
|
||||
|
||||
public function getPasswordSalt()
|
||||
{
|
||||
return $this->passwordSalt;
|
||||
}
|
||||
public function getPasswordSalt()
|
||||
{
|
||||
return $this->passwordSalt;
|
||||
}
|
||||
|
||||
public function setPasswordSalt($passwordSalt)
|
||||
{
|
||||
$this->passwordSalt = $passwordSalt;
|
||||
}
|
||||
public function setPasswordSalt($passwordSalt)
|
||||
{
|
||||
$this->passwordSalt = $passwordSalt;
|
||||
}
|
||||
|
||||
public function getAccessRank()
|
||||
{
|
||||
return $this->accessRank;
|
||||
}
|
||||
public function getAccessRank()
|
||||
{
|
||||
return $this->accessRank;
|
||||
}
|
||||
|
||||
public function setAccessRank($accessRank)
|
||||
{
|
||||
$this->accessRank = $accessRank;
|
||||
}
|
||||
public function setAccessRank($accessRank)
|
||||
{
|
||||
$this->accessRank = $accessRank;
|
||||
}
|
||||
|
||||
public function getRegistrationTime()
|
||||
{
|
||||
return $this->registrationTime;
|
||||
}
|
||||
public function getRegistrationTime()
|
||||
{
|
||||
return $this->registrationTime;
|
||||
}
|
||||
|
||||
public function setRegistrationTime($registrationTime)
|
||||
{
|
||||
$this->registrationTime = $registrationTime;
|
||||
}
|
||||
public function setRegistrationTime($registrationTime)
|
||||
{
|
||||
$this->registrationTime = $registrationTime;
|
||||
}
|
||||
|
||||
public function getLastLoginTime()
|
||||
{
|
||||
return $this->lastLoginTime;
|
||||
}
|
||||
public function getLastLoginTime()
|
||||
{
|
||||
return $this->lastLoginTime;
|
||||
}
|
||||
|
||||
public function setLastLoginTime($lastLoginTime)
|
||||
{
|
||||
$this->lastLoginTime = $lastLoginTime;
|
||||
}
|
||||
public function setLastLoginTime($lastLoginTime)
|
||||
{
|
||||
$this->lastLoginTime = $lastLoginTime;
|
||||
}
|
||||
|
||||
public function getAvatarStyle()
|
||||
{
|
||||
return $this->avatarStyle;
|
||||
}
|
||||
public function getAvatarStyle()
|
||||
{
|
||||
return $this->avatarStyle;
|
||||
}
|
||||
|
||||
public function setAvatarStyle($avatarStyle)
|
||||
{
|
||||
$this->avatarStyle = $avatarStyle;
|
||||
}
|
||||
public function setAvatarStyle($avatarStyle)
|
||||
{
|
||||
$this->avatarStyle = $avatarStyle;
|
||||
}
|
||||
|
||||
public function getBrowsingSettings()
|
||||
{
|
||||
return $this->browsingSettings;
|
||||
}
|
||||
public function getBrowsingSettings()
|
||||
{
|
||||
return $this->browsingSettings;
|
||||
}
|
||||
|
||||
public function setBrowsingSettings($browsingSettings)
|
||||
{
|
||||
$this->browsingSettings = $browsingSettings;
|
||||
}
|
||||
public function setBrowsingSettings($browsingSettings)
|
||||
{
|
||||
$this->browsingSettings = $browsingSettings;
|
||||
}
|
||||
|
||||
public function getCustomAvatarSourceContent()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_CUSTOM_AVATAR_SOURCE_CONTENT, null);
|
||||
}
|
||||
public function getCustomAvatarSourceContent()
|
||||
{
|
||||
return $this->lazyLoad(self::LAZY_LOADER_CUSTOM_AVATAR_SOURCE_CONTENT, null);
|
||||
}
|
||||
|
||||
public function setCustomAvatarSourceContent($content)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_CUSTOM_AVATAR_SOURCE_CONTENT, $content);
|
||||
}
|
||||
public function setCustomAvatarSourceContent($content)
|
||||
{
|
||||
$this->lazySave(self::LAZY_LOADER_CUSTOM_AVATAR_SOURCE_CONTENT, $content);
|
||||
}
|
||||
|
||||
public function getCustomAvatarSourceContentPath()
|
||||
{
|
||||
return 'avatars' . DIRECTORY_SEPARATOR . $this->getId();
|
||||
}
|
||||
public function getCustomAvatarSourceContentPath()
|
||||
{
|
||||
return 'avatars' . DIRECTORY_SEPARATOR . $this->getId();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,19 +5,19 @@ use Szurubooru\Validator;
|
|||
|
||||
class LoginFormData implements IValidatable
|
||||
{
|
||||
public $userNameOrEmail;
|
||||
public $password;
|
||||
public $userNameOrEmail;
|
||||
public $password;
|
||||
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->userNameOrEmail = trim($inputReader->userNameOrEmail);
|
||||
$this->password = $inputReader->password;
|
||||
}
|
||||
}
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->userNameOrEmail = trim($inputReader->userNameOrEmail);
|
||||
$this->password = $inputReader->password;
|
||||
}
|
||||
}
|
||||
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
}
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,46 +6,46 @@ use Szurubooru\Validator;
|
|||
|
||||
class PostEditFormData implements IValidatable
|
||||
{
|
||||
public $content;
|
||||
public $thumbnail;
|
||||
public $safety;
|
||||
public $source;
|
||||
public $tags;
|
||||
public $relations;
|
||||
public $flags;
|
||||
public $content;
|
||||
public $thumbnail;
|
||||
public $safety;
|
||||
public $source;
|
||||
public $tags;
|
||||
public $relations;
|
||||
public $flags;
|
||||
|
||||
public $seenEditTime;
|
||||
public $seenEditTime;
|
||||
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->content = $inputReader->readFile('content');
|
||||
$this->thumbnail = $inputReader->readFile('thumbnail');
|
||||
if ($inputReader->safety)
|
||||
$this->safety = EnumHelper::postSafetyFromString($inputReader->safety);
|
||||
if ($inputReader->source !== null)
|
||||
$this->source = $inputReader->source;
|
||||
$this->tags = preg_split('/[\s+]/', $inputReader->tags);
|
||||
if ($inputReader->relations !== null)
|
||||
$this->relations = array_filter(preg_split('/[\s+]/', $inputReader->relations));
|
||||
$this->seenEditTime = $inputReader->seenEditTime;
|
||||
$this->flags = new \StdClass;
|
||||
$this->flags->loop = !empty($inputReader->loop);
|
||||
}
|
||||
}
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->content = $inputReader->readFile('content');
|
||||
$this->thumbnail = $inputReader->readFile('thumbnail');
|
||||
if ($inputReader->safety)
|
||||
$this->safety = EnumHelper::postSafetyFromString($inputReader->safety);
|
||||
if ($inputReader->source !== null)
|
||||
$this->source = $inputReader->source;
|
||||
$this->tags = preg_split('/[\s+]/', $inputReader->tags);
|
||||
if ($inputReader->relations !== null)
|
||||
$this->relations = array_filter(preg_split('/[\s+]/', $inputReader->relations));
|
||||
$this->seenEditTime = $inputReader->seenEditTime;
|
||||
$this->flags = new \StdClass;
|
||||
$this->flags->loop = !empty($inputReader->loop);
|
||||
}
|
||||
}
|
||||
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
$validator->validatePostTags($this->tags);
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
$validator->validatePostTags($this->tags);
|
||||
|
||||
if ($this->source !== null)
|
||||
$validator->validatePostSource($this->source);
|
||||
if ($this->source !== null)
|
||||
$validator->validatePostSource($this->source);
|
||||
|
||||
if ($this->relations)
|
||||
{
|
||||
foreach ($this->relations as $relatedPostId)
|
||||
$validator->validateNumber($relatedPostId);
|
||||
}
|
||||
}
|
||||
if ($this->relations)
|
||||
{
|
||||
foreach ($this->relations as $relatedPostId)
|
||||
$validator->validateNumber($relatedPostId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,26 +5,26 @@ use Szurubooru\Validator;
|
|||
|
||||
class PostNoteFormData implements IValidatable
|
||||
{
|
||||
public $left;
|
||||
public $top;
|
||||
public $width;
|
||||
public $height;
|
||||
public $text;
|
||||
public $left;
|
||||
public $top;
|
||||
public $width;
|
||||
public $height;
|
||||
public $text;
|
||||
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->left = floatval($inputReader->left);
|
||||
$this->top = floatval($inputReader->top);
|
||||
$this->width = floatval($inputReader->width);
|
||||
$this->height = floatval($inputReader->height);
|
||||
$this->text = trim($inputReader->text);
|
||||
}
|
||||
}
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->left = floatval($inputReader->left);
|
||||
$this->top = floatval($inputReader->top);
|
||||
$this->width = floatval($inputReader->width);
|
||||
$this->height = floatval($inputReader->height);
|
||||
$this->text = trim($inputReader->text);
|
||||
}
|
||||
}
|
||||
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
$validator->validateMinLength($this->text, 3, 'Post note content');
|
||||
}
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
$validator->validateMinLength($this->text, 3, 'Post note content');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,24 +5,24 @@ use Szurubooru\Validator;
|
|||
|
||||
class RegistrationFormData implements IValidatable
|
||||
{
|
||||
public $userName;
|
||||
public $password;
|
||||
public $email;
|
||||
public $userName;
|
||||
public $password;
|
||||
public $email;
|
||||
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->userName = trim($inputReader->userName);
|
||||
$this->password = $inputReader->password;
|
||||
$this->email = trim($inputReader->email);
|
||||
}
|
||||
}
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->userName = trim($inputReader->userName);
|
||||
$this->password = $inputReader->password;
|
||||
$this->email = trim($inputReader->email);
|
||||
}
|
||||
}
|
||||
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
$validator->validateUserName($this->userName);
|
||||
$validator->validatePassword($this->password);
|
||||
$validator->validateEmail($this->email);
|
||||
}
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
$validator->validateUserName($this->userName);
|
||||
$validator->validatePassword($this->password);
|
||||
$validator->validateEmail($this->email);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,40 +5,40 @@ use Szurubooru\Validator;
|
|||
|
||||
class TagEditFormData implements IValidatable
|
||||
{
|
||||
public $name;
|
||||
public $banned;
|
||||
public $category;
|
||||
public $implications;
|
||||
public $suggestions;
|
||||
public $name;
|
||||
public $banned;
|
||||
public $category;
|
||||
public $implications;
|
||||
public $suggestions;
|
||||
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->name = trim($inputReader->name);
|
||||
$this->category = strtolower(trim($inputReader->category));
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->name = trim($inputReader->name);
|
||||
$this->category = strtolower(trim($inputReader->category));
|
||||
|
||||
if ($inputReader->banned !== null)
|
||||
$this->banned = boolval($inputReader->banned);
|
||||
if ($inputReader->banned !== null)
|
||||
$this->banned = boolval($inputReader->banned);
|
||||
|
||||
$this->implications = array_filter(array_unique(preg_split('/[\s+]/', $inputReader->implications)));
|
||||
$this->suggestions = array_filter(array_unique(preg_split('/[\s+]/', $inputReader->suggestions)));
|
||||
}
|
||||
}
|
||||
$this->implications = array_filter(array_unique(preg_split('/[\s+]/', $inputReader->implications)));
|
||||
$this->suggestions = array_filter(array_unique(preg_split('/[\s+]/', $inputReader->suggestions)));
|
||||
}
|
||||
}
|
||||
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
if ($this->category !== null)
|
||||
$validator->validateLength($this->category, 1, 25, 'Tag category');
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
if ($this->category !== null)
|
||||
$validator->validateLength($this->category, 1, 25, 'Tag category');
|
||||
|
||||
if ($this->name !== null)
|
||||
$validator->validatePostTags([$this->name]);
|
||||
if ($this->name !== null)
|
||||
$validator->validatePostTags([$this->name]);
|
||||
|
||||
if (!empty($this->implications))
|
||||
$validator->validatePostTags($this->implications);
|
||||
if (!empty($this->implications))
|
||||
$validator->validatePostTags($this->implications);
|
||||
|
||||
if (!empty($this->suggestions))
|
||||
$validator->validatePostTags($this->suggestions);
|
||||
}
|
||||
if (!empty($this->suggestions))
|
||||
$validator->validatePostTags($this->suggestions);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,37 +6,37 @@ use Szurubooru\Validator;
|
|||
|
||||
class UploadFormData implements IValidatable
|
||||
{
|
||||
public $contentFileName;
|
||||
public $content;
|
||||
public $url;
|
||||
public $anonymous;
|
||||
public $safety;
|
||||
public $source;
|
||||
public $tags;
|
||||
public $contentFileName;
|
||||
public $content;
|
||||
public $url;
|
||||
public $anonymous;
|
||||
public $safety;
|
||||
public $source;
|
||||
public $tags;
|
||||
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->contentFileName = $inputReader->contentFileName;
|
||||
$this->content = $inputReader->readFile('content');
|
||||
$this->url = $inputReader->url;
|
||||
$this->anonymous = $inputReader->anonymous;
|
||||
$this->safety = EnumHelper::postSafetyFromString($inputReader->safety);
|
||||
$this->source = $inputReader->source;
|
||||
$this->tags = preg_split('/[\s+]/', $inputReader->tags);
|
||||
}
|
||||
}
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->contentFileName = $inputReader->contentFileName;
|
||||
$this->content = $inputReader->readFile('content');
|
||||
$this->url = $inputReader->url;
|
||||
$this->anonymous = $inputReader->anonymous;
|
||||
$this->safety = EnumHelper::postSafetyFromString($inputReader->safety);
|
||||
$this->source = $inputReader->source;
|
||||
$this->tags = preg_split('/[\s+]/', $inputReader->tags);
|
||||
}
|
||||
}
|
||||
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
if ($this->content === null && $this->url === null)
|
||||
throw new \DomainException('Neither data or URL provided.');
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
if ($this->content === null && $this->url === null)
|
||||
throw new \DomainException('Neither data or URL provided.');
|
||||
|
||||
$validator->validatePostTags($this->tags);
|
||||
$validator->validatePostTags($this->tags);
|
||||
|
||||
if ($this->source !== null)
|
||||
$validator->validatePostSource($this->source);
|
||||
}
|
||||
if ($this->source !== null)
|
||||
$validator->validatePostSource($this->source);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,60 +7,60 @@ use Szurubooru\Validator;
|
|||
|
||||
class UserEditFormData implements IValidatable
|
||||
{
|
||||
public $userName;
|
||||
public $email;
|
||||
public $password;
|
||||
public $accessRank;
|
||||
public $avatarStyle;
|
||||
public $avatarContent;
|
||||
public $browsingSettings;
|
||||
public $banned;
|
||||
public $userName;
|
||||
public $email;
|
||||
public $password;
|
||||
public $accessRank;
|
||||
public $avatarStyle;
|
||||
public $avatarContent;
|
||||
public $browsingSettings;
|
||||
public $banned;
|
||||
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->userName = $inputReader->userName;
|
||||
$this->email = $inputReader->email;
|
||||
$this->password = $inputReader->password;
|
||||
if ($inputReader->accessRank !== null)
|
||||
$this->accessRank = EnumHelper::accessRankFromString($inputReader->accessRank);
|
||||
if ($inputReader->avatarStyle !== null)
|
||||
$this->avatarStyle = EnumHelper::avatarStyleFromString($inputReader->avatarStyle);
|
||||
$this->avatarContent = $inputReader->readFile('avatarContent');
|
||||
$this->browsingSettings = json_decode($inputReader->browsingSettings);
|
||||
if ($inputReader->banned !== null)
|
||||
$this->banned = boolval($inputReader->banned);
|
||||
}
|
||||
}
|
||||
public function __construct($inputReader = null)
|
||||
{
|
||||
if ($inputReader !== null)
|
||||
{
|
||||
$this->userName = $inputReader->userName;
|
||||
$this->email = $inputReader->email;
|
||||
$this->password = $inputReader->password;
|
||||
if ($inputReader->accessRank !== null)
|
||||
$this->accessRank = EnumHelper::accessRankFromString($inputReader->accessRank);
|
||||
if ($inputReader->avatarStyle !== null)
|
||||
$this->avatarStyle = EnumHelper::avatarStyleFromString($inputReader->avatarStyle);
|
||||
$this->avatarContent = $inputReader->readFile('avatarContent');
|
||||
$this->browsingSettings = json_decode($inputReader->browsingSettings);
|
||||
if ($inputReader->banned !== null)
|
||||
$this->banned = boolval($inputReader->banned);
|
||||
}
|
||||
}
|
||||
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
if ($this->userName !== null)
|
||||
$validator->validateUserName($this->userName);
|
||||
public function validate(Validator $validator)
|
||||
{
|
||||
if ($this->userName !== null)
|
||||
$validator->validateUserName($this->userName);
|
||||
|
||||
if ($this->password !== null)
|
||||
$validator->validatePassword($this->password);
|
||||
if ($this->password !== null)
|
||||
$validator->validatePassword($this->password);
|
||||
|
||||
if ($this->email !== null)
|
||||
$validator->validateEmail($this->email);
|
||||
if ($this->email !== null)
|
||||
$validator->validateEmail($this->email);
|
||||
|
||||
if (strlen($this->avatarContent) > 1024 * 512)
|
||||
throw new \DomainException('Avatar content must have at most 512 kilobytes.');
|
||||
if (strlen($this->avatarContent) > 1024 * 512)
|
||||
throw new \DomainException('Avatar content must have at most 512 kilobytes.');
|
||||
|
||||
if ($this->avatarContent)
|
||||
{
|
||||
$avatarContentMimeType = MimeHelper::getMimeTypeFromBuffer($this->avatarContent);
|
||||
if (!MimeHelper::isImage($avatarContentMimeType))
|
||||
throw new \DomainException('Avatar must be an image (detected: ' . $avatarContentMimeType . ').');
|
||||
}
|
||||
if ($this->avatarContent)
|
||||
{
|
||||
$avatarContentMimeType = MimeHelper::getMimeTypeFromBuffer($this->avatarContent);
|
||||
if (!MimeHelper::isImage($avatarContentMimeType))
|
||||
throw new \DomainException('Avatar must be an image (detected: ' . $avatarContentMimeType . ').');
|
||||
}
|
||||
|
||||
if ($this->browsingSettings !== null)
|
||||
{
|
||||
if (!is_object($this->browsingSettings))
|
||||
throw new \InvalidArgumentException('Browsing settings must be valid JSON.');
|
||||
else if (strlen(json_encode($this->browsingSettings)) > 300)
|
||||
throw new \InvalidArgumentException('Stringified browsing settings can have at most 300 characters.');
|
||||
}
|
||||
}
|
||||
if ($this->browsingSettings !== null)
|
||||
{
|
||||
if (!is_object($this->browsingSettings))
|
||||
throw new \InvalidArgumentException('Browsing settings must be valid JSON.');
|
||||
else if (strlen(json_encode($this->browsingSettings)) > 300)
|
||||
throw new \InvalidArgumentException('Stringified browsing settings can have at most 300 characters.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,111 +6,111 @@ use Szurubooru\Entities\User;
|
|||
|
||||
class EnumHelper
|
||||
{
|
||||
private static $accessRankMap =
|
||||
[
|
||||
'anonymous' => User::ACCESS_RANK_ANONYMOUS,
|
||||
'restrictedUser' => User::ACCESS_RANK_RESTRICTED_USER,
|
||||
'regularUser' => User::ACCESS_RANK_REGULAR_USER,
|
||||
'powerUser' => User::ACCESS_RANK_POWER_USER,
|
||||
'moderator' => User::ACCESS_RANK_MODERATOR,
|
||||
'administrator' => User::ACCESS_RANK_ADMINISTRATOR,
|
||||
];
|
||||
private static $accessRankMap =
|
||||
[
|
||||
'anonymous' => User::ACCESS_RANK_ANONYMOUS,
|
||||
'restrictedUser' => User::ACCESS_RANK_RESTRICTED_USER,
|
||||
'regularUser' => User::ACCESS_RANK_REGULAR_USER,
|
||||
'powerUser' => User::ACCESS_RANK_POWER_USER,
|
||||
'moderator' => User::ACCESS_RANK_MODERATOR,
|
||||
'administrator' => User::ACCESS_RANK_ADMINISTRATOR,
|
||||
];
|
||||
|
||||
private static $avatarStyleMap =
|
||||
[
|
||||
'gravatar' => User::AVATAR_STYLE_GRAVATAR,
|
||||
'manual' => User::AVATAR_STYLE_MANUAL,
|
||||
'none' => User::AVATAR_STYLE_BLANK,
|
||||
'blank' => User::AVATAR_STYLE_BLANK,
|
||||
];
|
||||
private static $avatarStyleMap =
|
||||
[
|
||||
'gravatar' => User::AVATAR_STYLE_GRAVATAR,
|
||||
'manual' => User::AVATAR_STYLE_MANUAL,
|
||||
'none' => User::AVATAR_STYLE_BLANK,
|
||||
'blank' => User::AVATAR_STYLE_BLANK,
|
||||
];
|
||||
|
||||
private static $postSafetyMap =
|
||||
[
|
||||
'safe' => Post::POST_SAFETY_SAFE,
|
||||
'sketchy' => Post::POST_SAFETY_SKETCHY,
|
||||
'unsafe' => Post::POST_SAFETY_UNSAFE,
|
||||
];
|
||||
private static $postSafetyMap =
|
||||
[
|
||||
'safe' => Post::POST_SAFETY_SAFE,
|
||||
'sketchy' => Post::POST_SAFETY_SKETCHY,
|
||||
'unsafe' => Post::POST_SAFETY_UNSAFE,
|
||||
];
|
||||
|
||||
private static $postTypeMap =
|
||||
[
|
||||
'image' => Post::POST_TYPE_IMAGE,
|
||||
'video' => Post::POST_TYPE_VIDEO,
|
||||
'flash' => Post::POST_TYPE_FLASH,
|
||||
'youtube' => Post::POST_TYPE_YOUTUBE,
|
||||
'animation' => Post::POST_TYPE_ANIMATED_IMAGE,
|
||||
];
|
||||
private static $postTypeMap =
|
||||
[
|
||||
'image' => Post::POST_TYPE_IMAGE,
|
||||
'video' => Post::POST_TYPE_VIDEO,
|
||||
'flash' => Post::POST_TYPE_FLASH,
|
||||
'youtube' => Post::POST_TYPE_YOUTUBE,
|
||||
'animation' => Post::POST_TYPE_ANIMATED_IMAGE,
|
||||
];
|
||||
|
||||
private static $snapshotTypeMap =
|
||||
[
|
||||
'post' => Snapshot::TYPE_POST,
|
||||
];
|
||||
private static $snapshotTypeMap =
|
||||
[
|
||||
'post' => Snapshot::TYPE_POST,
|
||||
];
|
||||
|
||||
public static function accessRankToString($accessRank)
|
||||
{
|
||||
return self::enumToString(self::$accessRankMap, $accessRank);
|
||||
}
|
||||
public static function accessRankToString($accessRank)
|
||||
{
|
||||
return self::enumToString(self::$accessRankMap, $accessRank);
|
||||
}
|
||||
|
||||
public static function accessRankFromString($accessRankString)
|
||||
{
|
||||
return self::stringToEnum(self::$accessRankMap, $accessRankString);
|
||||
}
|
||||
public static function accessRankFromString($accessRankString)
|
||||
{
|
||||
return self::stringToEnum(self::$accessRankMap, $accessRankString);
|
||||
}
|
||||
|
||||
public static function avatarStyleToString($avatarStyle)
|
||||
{
|
||||
return self::enumToString(self::$avatarStyleMap, $avatarStyle);
|
||||
}
|
||||
public static function avatarStyleToString($avatarStyle)
|
||||
{
|
||||
return self::enumToString(self::$avatarStyleMap, $avatarStyle);
|
||||
}
|
||||
|
||||
public static function avatarStyleFromString($avatarStyleString)
|
||||
{
|
||||
return self::stringToEnum(self::$avatarStyleMap, $avatarStyleString);
|
||||
}
|
||||
public static function avatarStyleFromString($avatarStyleString)
|
||||
{
|
||||
return self::stringToEnum(self::$avatarStyleMap, $avatarStyleString);
|
||||
}
|
||||
|
||||
public static function postSafetyToString($postSafety)
|
||||
{
|
||||
return self::enumToString(self::$postSafetyMap, $postSafety);
|
||||
}
|
||||
public static function postSafetyToString($postSafety)
|
||||
{
|
||||
return self::enumToString(self::$postSafetyMap, $postSafety);
|
||||
}
|
||||
|
||||
public static function postSafetyFromString($postSafetyString)
|
||||
{
|
||||
return self::stringToEnum(self::$postSafetyMap, $postSafetyString);
|
||||
}
|
||||
public static function postSafetyFromString($postSafetyString)
|
||||
{
|
||||
return self::stringToEnum(self::$postSafetyMap, $postSafetyString);
|
||||
}
|
||||
|
||||
public static function postTypeToString($postType)
|
||||
{
|
||||
return self::enumToString(self::$postTypeMap, $postType);
|
||||
}
|
||||
public static function postTypeToString($postType)
|
||||
{
|
||||
return self::enumToString(self::$postTypeMap, $postType);
|
||||
}
|
||||
|
||||
public static function postTypeFromString($postTypeString)
|
||||
{
|
||||
return self::stringToEnum(self::$postTypeMap, $postTypeString);
|
||||
}
|
||||
public static function postTypeFromString($postTypeString)
|
||||
{
|
||||
return self::stringToEnum(self::$postTypeMap, $postTypeString);
|
||||
}
|
||||
|
||||
public static function snapshotTypeFromString($snapshotTypeString)
|
||||
{
|
||||
return self::stringToEnum(self::$snapshotTypeMap, $snapshotTypeString);
|
||||
}
|
||||
public static function snapshotTypeFromString($snapshotTypeString)
|
||||
{
|
||||
return self::stringToEnum(self::$snapshotTypeMap, $snapshotTypeString);
|
||||
}
|
||||
|
||||
private static function enumToString($enumMap, $enumValue)
|
||||
{
|
||||
$reverseMap = array_flip($enumMap);
|
||||
if (!isset($reverseMap[$enumValue]))
|
||||
throw new \RuntimeException('Invalid value!');
|
||||
private static function enumToString($enumMap, $enumValue)
|
||||
{
|
||||
$reverseMap = array_flip($enumMap);
|
||||
if (!isset($reverseMap[$enumValue]))
|
||||
throw new \RuntimeException('Invalid value!');
|
||||
|
||||
return $reverseMap[$enumValue];
|
||||
}
|
||||
return $reverseMap[$enumValue];
|
||||
}
|
||||
|
||||
private static function stringToEnum($enumMap, $enumString)
|
||||
{
|
||||
$key = trim(strtolower($enumString));
|
||||
$lowerEnumMap = array_change_key_case($enumMap, \CASE_LOWER);
|
||||
if (!isset($lowerEnumMap[$key]))
|
||||
{
|
||||
throw new \DomainException(sprintf(
|
||||
'Unrecognized value: %s.' . PHP_EOL . 'Possible values: %s',
|
||||
$enumString,
|
||||
join(', ', array_keys($lowerEnumMap))));
|
||||
}
|
||||
private static function stringToEnum($enumMap, $enumString)
|
||||
{
|
||||
$key = trim(strtolower($enumString));
|
||||
$lowerEnumMap = array_change_key_case($enumMap, \CASE_LOWER);
|
||||
if (!isset($lowerEnumMap[$key]))
|
||||
{
|
||||
throw new \DomainException(sprintf(
|
||||
'Unrecognized value: %s.' . PHP_EOL . 'Possible values: %s',
|
||||
$enumString,
|
||||
join(', ', array_keys($lowerEnumMap))));
|
||||
}
|
||||
|
||||
return $lowerEnumMap[$key];
|
||||
}
|
||||
return $lowerEnumMap[$key];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,89 +3,89 @@ namespace Szurubooru\Helpers;
|
|||
|
||||
class HttpHelper
|
||||
{
|
||||
private $redirected = false;
|
||||
private $redirected = false;
|
||||
|
||||
public function setResponseCode($code)
|
||||
{
|
||||
http_response_code($code);
|
||||
}
|
||||
public function setResponseCode($code)
|
||||
{
|
||||
http_response_code($code);
|
||||
}
|
||||
|
||||
public function setHeader($key, $value)
|
||||
{
|
||||
header($key . ': ' . $value);
|
||||
}
|
||||
public function setHeader($key, $value)
|
||||
{
|
||||
header($key . ': ' . $value);
|
||||
}
|
||||
|
||||
public function outputJSON($data)
|
||||
{
|
||||
$encodedJson = json_encode((array) $data);
|
||||
$lastError = json_last_error();
|
||||
if ($lastError !== JSON_ERROR_NONE)
|
||||
$this->output('Fatal error while encoding JSON: ' . $lastError . PHP_EOL . PHP_EOL . print_r($data, true));
|
||||
else
|
||||
$this->output($encodedJson);
|
||||
}
|
||||
public function outputJSON($data)
|
||||
{
|
||||
$encodedJson = json_encode((array) $data);
|
||||
$lastError = json_last_error();
|
||||
if ($lastError !== JSON_ERROR_NONE)
|
||||
$this->output('Fatal error while encoding JSON: ' . $lastError . PHP_EOL . PHP_EOL . print_r($data, true));
|
||||
else
|
||||
$this->output($encodedJson);
|
||||
}
|
||||
|
||||
public function output($data)
|
||||
{
|
||||
echo $data;
|
||||
}
|
||||
public function output($data)
|
||||
{
|
||||
echo $data;
|
||||
}
|
||||
|
||||
public function getRequestHeaders()
|
||||
{
|
||||
if (function_exists('getallheaders'))
|
||||
{
|
||||
return getallheaders();
|
||||
}
|
||||
$result = [];
|
||||
foreach ($_SERVER as $key => $value)
|
||||
{
|
||||
if (substr($key, 0, 5) == "HTTP_")
|
||||
{
|
||||
$key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
|
||||
$result[$key] = $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
$result[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function getRequestHeaders()
|
||||
{
|
||||
if (function_exists('getallheaders'))
|
||||
{
|
||||
return getallheaders();
|
||||
}
|
||||
$result = [];
|
||||
foreach ($_SERVER as $key => $value)
|
||||
{
|
||||
if (substr($key, 0, 5) == "HTTP_")
|
||||
{
|
||||
$key = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))));
|
||||
$result[$key] = $value;
|
||||
}
|
||||
else
|
||||
{
|
||||
$result[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getRequestHeader($key)
|
||||
{
|
||||
$headers = $this->getRequestHeaders();
|
||||
return isset($headers[$key]) ? $headers[$key] : null;
|
||||
}
|
||||
public function getRequestHeader($key)
|
||||
{
|
||||
$headers = $this->getRequestHeaders();
|
||||
return isset($headers[$key]) ? $headers[$key] : null;
|
||||
}
|
||||
|
||||
public function getRequestMethod()
|
||||
{
|
||||
return $_SERVER['REQUEST_METHOD'];
|
||||
}
|
||||
public function getRequestMethod()
|
||||
{
|
||||
return $_SERVER['REQUEST_METHOD'];
|
||||
}
|
||||
|
||||
public function getRequestUri()
|
||||
{
|
||||
$requestUri = $_SERVER['REQUEST_URI'];
|
||||
$requestUri = preg_replace('/\?.*$/', '', $requestUri);
|
||||
return $requestUri;
|
||||
}
|
||||
public function getRequestUri()
|
||||
{
|
||||
$requestUri = $_SERVER['REQUEST_URI'];
|
||||
$requestUri = preg_replace('/\?.*$/', '', $requestUri);
|
||||
return $requestUri;
|
||||
}
|
||||
|
||||
public function redirect($destination)
|
||||
{
|
||||
$this->setResponseCode(307);
|
||||
$this->setHeader('Location', $destination);
|
||||
$this->redirected = true;
|
||||
}
|
||||
public function redirect($destination)
|
||||
{
|
||||
$this->setResponseCode(307);
|
||||
$this->setHeader('Location', $destination);
|
||||
$this->redirected = true;
|
||||
}
|
||||
|
||||
public function nonCachedRedirect($destination)
|
||||
{
|
||||
$this->setResponseCode(303);
|
||||
$this->setHeader('Location', $destination);
|
||||
$this->redirected = true;
|
||||
}
|
||||
public function nonCachedRedirect($destination)
|
||||
{
|
||||
$this->setResponseCode(303);
|
||||
$this->setHeader('Location', $destination);
|
||||
$this->redirected = true;
|
||||
}
|
||||
|
||||
public function isRedirecting()
|
||||
{
|
||||
return $this->redirected;
|
||||
}
|
||||
public function isRedirecting()
|
||||
{
|
||||
return $this->redirected;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,36 +3,36 @@ namespace Szurubooru\Helpers;
|
|||
|
||||
final class InputReader extends \ArrayObject
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::setFlags(parent::ARRAY_AS_PROPS | parent::STD_PROP_LIST);
|
||||
public function __construct()
|
||||
{
|
||||
parent::setFlags(parent::ARRAY_AS_PROPS | parent::STD_PROP_LIST);
|
||||
|
||||
$_PUT = [];
|
||||
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT')
|
||||
parse_str(file_get_contents('php://input'), $_PUT);
|
||||
$_PUT = [];
|
||||
if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'PUT')
|
||||
parse_str(file_get_contents('php://input'), $_PUT);
|
||||
|
||||
foreach ([$_GET, $_POST, $_PUT] as $source)
|
||||
{
|
||||
foreach ($source as $key => $value)
|
||||
$this->offsetSet($key, $value);
|
||||
}
|
||||
}
|
||||
foreach ([$_GET, $_POST, $_PUT] as $source)
|
||||
{
|
||||
foreach ($source as $key => $value)
|
||||
$this->offsetSet($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function offsetGet($index)
|
||||
{
|
||||
if (!parent::offsetExists($index))
|
||||
return null;
|
||||
return parent::offsetGet($index);
|
||||
}
|
||||
public function offsetGet($index)
|
||||
{
|
||||
if (!parent::offsetExists($index))
|
||||
return null;
|
||||
return parent::offsetGet($index);
|
||||
}
|
||||
|
||||
public function readFile($fileName)
|
||||
{
|
||||
if (!isset($_FILES[$fileName]))
|
||||
return null;
|
||||
public function readFile($fileName)
|
||||
{
|
||||
if (!isset($_FILES[$fileName]))
|
||||
return null;
|
||||
|
||||
if (!$_FILES[$fileName]['tmp_name'])
|
||||
throw new \Exception('File is probably too big.');
|
||||
if (!$_FILES[$fileName]['tmp_name'])
|
||||
throw new \Exception('File is probably too big.');
|
||||
|
||||
return file_get_contents($_FILES[$fileName]['tmp_name']);
|
||||
}
|
||||
return file_get_contents($_FILES[$fileName]['tmp_name']);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue