From 77519e6d523bcd8f784edc06e3d376b8301afc91 Mon Sep 17 00:00:00 2001 From: William Mantly Date: Sat, 6 Jan 2024 18:09:23 -0500 Subject: [PATCH] first --- app.js | 2 +- public/js/app.js | 443 ++++--------------------------------- public/js/app/api.js | 91 ++++++++ public/js/app/auth.js | 87 ++++++++ public/js/app/group.js | 15 ++ public/js/app/pubsub.js | 41 ++++ public/js/app/socket.js | 28 +++ public/js/app/torrent.js | 122 ++++++++++ public/js/app/user.js | 44 ++++ public/js/app/utils.js | 96 ++++++++ public/partial/header.html | 131 +---------- routes/transmission.js | 6 +- 12 files changed, 576 insertions(+), 530 deletions(-) create mode 100644 public/js/app/api.js create mode 100644 public/js/app/auth.js create mode 100644 public/js/app/group.js create mode 100644 public/js/app/pubsub.js create mode 100644 public/js/app/socket.js create mode 100644 public/js/app/torrent.js create mode 100644 public/js/app/user.js create mode 100644 public/js/app/utils.js diff --git a/app.js b/app.js index e35eb68..0bbf448 100644 --- a/app.js +++ b/app.js @@ -39,7 +39,7 @@ app.onListen.push(function(){ app.contollers.pubsub.subscribe(/./g, function(data, topic){ app.io.emit('P2PSub', { topic, data }); - }); + }); app.io.on('connection', (socket) => { // console.log('socket', socket) diff --git a/public/js/app.js b/public/js/app.js index 915c35f..2e11bf3 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,419 +1,56 @@ -var app = {}; +// socket -app.pubsub = (function(){ - app.topics = {}; +// api - app.subscribe = function(topic, listener) { - if(topic instanceof RegExp){ - listener.match = topic; - topic = "__REGEX__"; - } +// auth - // create the topic if not yet created - if(!app.topics[topic]) app.topics[topic] = []; +// user - // add the listener - app.topics[topic].push(listener); - } +// group - app.matchTopics = function(topic){ - topic = topic || ''; - var matches = [... app.topics[topic] ? app.topics[topic] : []]; +"use strict"; +/* globals jQuery, Mustache, XRegExp, $, app */ +var app = app || {}; - if(!app.topics['__REGEX__']) return matches; +( function($){ - for(var listener of app.topics['__REGEX__']){ - if(topic.match(listener.match)) matches.push(listener); - } + /* + delay calling document.ready until app is loaded. + */ + jQuery.holdReady(true); - return matches; - } + app.includeScrip = function(path, base){ + path = (base || JQapp_BASE_PATH || '') + path; - app.publish = function(topic, data) { - - // send the event to all listeners - app.matchTopics(topic).forEach(function(listener) { - setTimeout(function(data, topic){ - listener(data || {}, topic); - }, 0, data, topic); + jQuery.ajax({ + url: path, + dataType: 'script', + async: false }); - } - - return this; -})(app); - -app.socket = (function(app){ - // $.getScript('/socket.io/socket.io.js') - // - - var socket; - $(document).ready(function(){ - socket = io({ - auth: { - token: app.auth.getToken() - } - }); - // socket.emit('chat message', $('#m').val()); - socket.on('P2PSub', function(msg){ - msg.data.__noSocket = true; - app.publish(msg.topic, msg.data); - }); - - app.subscribe(/./g, function(data, topic){ - // console.log('local_pubs', data, topic) - if(data.__noSocket) return; - // console.log('local_pubs 2', data, topic) - - socket.emit('P2PSub', { topic, data }); - }); - }) - - return socket; - -})(app); - -app.api = (function(app){ - var baseURL = '/__api/' - - - $( document ).on( "ajaxError", function(event, res, req) { - console.log('bad!', `app:api:error:`, res.status); - app.publish(`app:api:error:${res.status}`, {res, res}); - } ); - - function post(url, data, callback){ - callback = callback || app.util.emptyFuction; - $.ajax({ - type: 'POST', - url: baseURL+url, - headers:{ - 'auth-token': app.auth.getToken() - }, - data: JSON.stringify(data), - contentType: "application/json; charset=utf-8", - dataType: "json", - complete: function(res, text){ - callback( - text !== 'success' ? res.statusText : null, - JSON.parse(res.responseText), - res.status - ) - } - }); - } - - function put(url, data, callback){ - $.ajax({ - type: 'PUT', - url: baseURL+url, - headers:{ - 'auth-token': app.auth.getToken() - }, - data: JSON.stringify(data), - contentType: "application/json; charset=utf-8", - dataType: "json", - complete: function(res, text){ - callback( - text !== 'success' ? res.statusText : null, - JSON.parse(res.responseText), - res.status - ) - } - }); - } - - function remove(url, callback, callback2){ - if(!$.isFunction(callback)) callback = callback2; - $.ajax({ - type: 'delete', - url: baseURL+url, - headers:{ - 'auth-token': app.auth.getToken() - }, - contentType: "application/json; charset=utf-8", - dataType: "json", - complete: function(res, text){ - callback( - text !== 'success' ? res.statusText : null, - JSON.parse(res.responseText), - res.status - ) - } - }); - } - - function get(url, callback){ - $.ajax({ - type: 'GET', - url: baseURL+url, - headers:{ - 'auth-token': app.auth.getToken() - }, - contentType: "application/json; charset=utf-8", - dataType: "json", - complete: function(res, text){ - callback( - text !== 'success' ? res.statusText : null, - JSON.parse(res.responseText), - res.status - ) - } - }); - } - - return {post: post, get: get, put: put, delete: remove} -})(app) - -app.auth = (function(app) { - var user = {} - function setToken(token){ - localStorage.setItem('APIToken', token); - } - - function getToken(){ - return localStorage.getItem('APIToken'); - } - - function isLoggedIn(callback){ - if(getToken()){ - return app.api.get('user/me', function(error, data){ - if(error === 'Unauthorized') logOut(); - if(!error) app.auth.user = data; - return callback(error, data); - }); - }else{ - callback(null, false); - } - } - - function logIn(args, callback){ - app.api.post('auth/login', args, function(error, data){ - if(data.login){ - setToken(data.token); - } - callback(error, !!data.token); - }); - } - - function logOut(callback){ - callback = callback || app.util.emptyFuction; - localStorage.removeItem('APIToken'); - callback(); - } - - function makeUserFromInvite(args, callback){ - app.api.post('auth/invite/'+ args.token, args, function(error, data){ - if(data.login){ - callback(null, data); - setToken(data.token); - } - callback(error, !!data.token); - }); - } - - function forceLogin(){ - $.holdReady( true ); - app.auth.isLoggedIn(function(error, isLoggedIn){ - if(error || !isLoggedIn){ - app.auth.logOut(function(){}) - location.replace(`/login${location.href.replace(location.origin, '')}`); - }else{ - $.holdReady( false ); - } - }); - } - - function logInRedirect(){ - window.location.href = location.href.replace(location.origin+'/login', '') || '/' - } - - - $( document ).ready( function(){ - isLoggedIn(function(error, isLoggedIn){ - if(!error && isLoggedIn){ - $('.tbp_proxy_is_authed').show(); - $('.tbp_proxy_not_authed').hide(); - }else{ - $('.tbp_proxy_is_authed').hide(); - $('.tbp_proxy_not_authed').show(); - } - }); - }); - - return { - getToken: getToken, - setToken: setToken, - isLoggedIn: isLoggedIn, - logIn: logIn, - logOut: logOut, - makeUserFromInvite: makeUserFromInvite, - forceLogin, - logInRedirect, - } - -})(app); - -app.util = (function(app){ - - function getUrlParameter(name) { - name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); - var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); - var results = regex.exec(location.search); - return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); }; - function actionMessage(message, $target, type, callback){ - message = message || ''; - $target = $target.closest('div.card').find('.actionMessage'); - type = type || 'info'; - callback = callback || function(){}; - - if($target.html() === message) return; - - if($target.html()){ - $target.slideUp('fast', function(){ - $target.html('') - $target.removeClass (function (index, className) { - return (className.match (/(^|\s)ui-\S+/g) || []).join(' '); - }); - if(message) return actionMessage(message, $target, type, callback); - $target.hide() - }) - }else{ - if(type) $target.addClass('ui-' + type); - $target.html(message).slideDown('fast'); + app.include = function(scripts, base){ + scripts = $.isArray(scripts) ? scripts : [scripts]; + for(let script of scripts){ + app.includeScrip(script, base) } - setTimeout(callback,10) } +})(jQuery); - $.fn.serializeObject = function() { - var - arr = $(this).serializeArray(), - obj = {}; - - for(var i = 0; i < arr.length; i++) { - if(obj[arr[i].name] === undefined) { - obj[arr[i].name] = arr[i].value; - } else { - if(!(obj[arr[i].name] instanceof Array)) { - obj[arr[i].name] = [obj[arr[i].name]]; - } - obj[arr[i].name].push(arr[i].value); - } - } - return obj; - }; +app.include([ + '/utils.js', + '/pubsub.js', + '/api.js', + '/socket.js', + '/user.js', + '/group.js', + '/auth.js', +], JQapp_BASE_PATH) - return { - getUrlParameter: getUrlParameter, - actionMessage: actionMessage, - emptyFuction: function(){}, - - } -})(app); - - -app.user = (function(app){ - function list(callback){ - app.api.get('user/?detail=true', function(error, data){ - callback(error, data); - }) - } - - function add(args, callback){ - app.api.post('user/', args, function(error, data){ - callback(error, data); - }); - } - - function remove(args, callback){ - if(!confirm('Delete '+ args.uid+ 'user?')) return false; - app.api.delete('user/'+ args.uid, function(error, data){ - callback(error, data); - }); - } - - function changePassword(args, callback){ - app.api.put('users/'+ arg.uid || '', args, function(error, data){ - callback(error, data); - }); - } - - function createInvite(callback){ - app.api.post('user/invite', {}, function(error, data, status){ - callback(error, data); - }); - } - - function consumeInvite(args){ - app.api.post('/auth/invite/'+args.token, args, function(error, data){ - if(data.token){ - app.auth.setToken(data.token) - return callback(null, true) - } - callback(error) - }); - } - - return {list, remove, createInvite}; - -})(app); - -app.group = (function(app){ - function list(callback){ - app.api.get('group?detail=true', function(error, data){ - callback(error, data); - }); - } - - function remove(args, callback){ - app.api.delete('group/'+args.cn, function(error, data){ - callback(error, data); - }); - } - - return {list, remove} -})(app); - -$( document ).ready( function () { - - $( 'div.row' ).fadeIn( 'slow' ); //show the page - - //panel button's - $( '.fa-arrows-v' ).click( function () { - $( this ).closest( '.card' ).find( '.card-body' ).slideToggle( 'fast' ); - }); - - $('.actionMessage').on('click', 'button.action-close', function(event){ - app.util.actionMessage(null, $(this)); - }) - -}); - -//ajax form submit -function formAJAX( btn, del ) { - event.preventDefault(); // avoid to execute the actual submit of the form. - var $form = $(btn).closest( '[action]' ); // gets the 'form' parent - var formData = $form.find( '[name]' ).serializeObject(); // builds query formDataing - var method = $form.attr('method') || 'post'; - - // if( !$form.validate()) { - // app.util.actionMessage('Please fix the form errors.', $form, 'danger') - // return false; - // } - - app.util.actionMessage( - '
Loading...
', - $form, - 'state-highlight' - ); - - app.api[method]($form.attr('action'), formData, function(error, data){ - app.util.actionMessage(data.message, $form, error ? 'state-error' : 'priority-primary'); //re-populate table - if(!error){ - $form.trigger("reset"); - eval($form.attr('evalAJAX')); //gets JS to run after completion - } - }); - -} +/* + when the DOM is finished, start the app +*/ +jQuery(document).on("DOMContentLoaded", function(event) { + app.publish("__dom-content-loaded-start"); + app.publish("__dom-content-loaded-end"); +}); \ No newline at end of file diff --git a/public/js/app/api.js b/public/js/app/api.js new file mode 100644 index 0000000..17be2e4 --- /dev/null +++ b/public/js/app/api.js @@ -0,0 +1,91 @@ +app.api = (function(app){ + var baseURL = '/__api/' + + + $( document ).on( "ajaxError", function(event, res, req) { + console.log('bad!', `app:api:error:`, res.status); + app.publish(`app:api:error:${res.status}`, {res, res}); + } ); + + function post(url, data, callback){ + callback = callback || app.util.emptyFuction; + $.ajax({ + type: 'POST', + url: baseURL+url, + headers:{ + 'auth-token': app.auth.getToken() + }, + data: JSON.stringify(data), + contentType: "application/json; charset=utf-8", + dataType: "json", + complete: function(res, text){ + callback( + text !== 'success' ? res.statusText : null, + JSON.parse(res.responseText), + res.status + ) + } + }); + } + + function put(url, data, callback){ + $.ajax({ + type: 'PUT', + url: baseURL+url, + headers:{ + 'auth-token': app.auth.getToken() + }, + data: JSON.stringify(data), + contentType: "application/json; charset=utf-8", + dataType: "json", + complete: function(res, text){ + callback( + text !== 'success' ? res.statusText : null, + JSON.parse(res.responseText), + res.status + ) + } + }); + } + + function remove(url, callback, callback2){ + if(!$.isFunction(callback)) callback = callback2; + $.ajax({ + type: 'delete', + url: baseURL+url, + headers:{ + 'auth-token': app.auth.getToken() + }, + contentType: "application/json; charset=utf-8", + dataType: "json", + complete: function(res, text){ + callback( + text !== 'success' ? res.statusText : null, + JSON.parse(res.responseText), + res.status + ) + } + }); + } + + function get(url, callback){ + $.ajax({ + type: 'GET', + url: baseURL+url, + headers:{ + 'auth-token': app.auth.getToken() + }, + contentType: "application/json; charset=utf-8", + dataType: "json", + complete: function(res, text){ + callback( + text !== 'success' ? res.statusText : null, + JSON.parse(res.responseText), + res.status + ) + } + }); + } + + return {post: post, get: get, put: put, delete: remove} +})(app); \ No newline at end of file diff --git a/public/js/app/auth.js b/public/js/app/auth.js new file mode 100644 index 0000000..01772f4 --- /dev/null +++ b/public/js/app/auth.js @@ -0,0 +1,87 @@ +app.auth = (function(app) { + var user = {} + function setToken(token){ + localStorage.setItem('APIToken', token); + } + + function getToken(){ + return localStorage.getItem('APIToken'); + } + + function isLoggedIn(callback){ + if(getToken()){ + return app.api.get('user/me', function(error, data){ + if(error === 'Unauthorized') logOut(); + if(!error) app.auth.user = data; + return callback(error, data); + }); + }else{ + callback(null, false); + } + } + + function logIn(args, callback){ + app.api.post('auth/login', args, function(error, data){ + if(data.login){ + setToken(data.token); + } + callback(error, !!data.token); + }); + } + + function logOut(callback){ + callback = callback || app.util.emptyFuction; + localStorage.removeItem('APIToken'); + callback(); + } + + function makeUserFromInvite(args, callback){ + app.api.post('auth/invite/'+ args.token, args, function(error, data){ + if(data.login){ + callback(null, data); + setToken(data.token); + } + callback(error, !!data.token); + }); + } + + function forceLogin(){ + $.holdReady( true ); + app.auth.isLoggedIn(function(error, isLoggedIn){ + if(error || !isLoggedIn){ + app.auth.logOut(function(){}) + location.replace(`/login${location.href.replace(location.origin, '')}`); + }else{ + $.holdReady( false ); + } + }); + } + + function logInRedirect(){ + window.location.href = location.href.replace(location.origin+'/login', '') || '/' + } + + + $( document ).ready( function(){ + isLoggedIn(function(error, isLoggedIn){ + if(!error && isLoggedIn){ + $('.tbp_proxy_is_authed').show(); + $('.tbp_proxy_not_authed').hide(); + }else{ + $('.tbp_proxy_is_authed').hide(); + $('.tbp_proxy_not_authed').show(); + } + }); + }); + + return { + getToken: getToken, + setToken: setToken, + isLoggedIn: isLoggedIn, + logIn: logIn, + logOut: logOut, + makeUserFromInvite: makeUserFromInvite, + forceLogin, + logInRedirect, + } +})(app); \ No newline at end of file diff --git a/public/js/app/group.js b/public/js/app/group.js new file mode 100644 index 0000000..e706ca6 --- /dev/null +++ b/public/js/app/group.js @@ -0,0 +1,15 @@ +app.group = (function(app){ + function list(callback){ + app.api.get('group?detail=true', function(error, data){ + callback(error, data); + }); + } + + function remove(args, callback){ + app.api.delete('group/'+args.cn, function(error, data){ + callback(error, data); + }); + } + + return {list, remove} +})(app); \ No newline at end of file diff --git a/public/js/app/pubsub.js b/public/js/app/pubsub.js new file mode 100644 index 0000000..d58e7f0 --- /dev/null +++ b/public/js/app/pubsub.js @@ -0,0 +1,41 @@ +app.pubsub = (function(){ + app.topics = {}; + + app.subscribe = function(topic, listener) { + if(topic instanceof RegExp){ + listener.match = topic; + topic = "__REGEX__"; + } + + // create the topic if not yet created + if(!app.topics[topic]) app.topics[topic] = []; + + // add the listener + app.topics[topic].push(listener); + } + + app.matchTopics = function(topic){ + topic = topic || ''; + var matches = [... app.topics[topic] ? app.topics[topic] : []]; + + if(!app.topics['__REGEX__']) return matches; + + for(var listener of app.topics['__REGEX__']){ + if(topic.match(listener.match)) matches.push(listener); + } + + return matches; + } + + app.publish = function(topic, data) { + + // send the event to all listeners + app.matchTopics(topic).forEach(function(listener) { + setTimeout(function(data, topic){ + listener(data || {}, topic); + }, 0, data, topic); + }); + } + + return this; +})(app); \ No newline at end of file diff --git a/public/js/app/socket.js b/public/js/app/socket.js new file mode 100644 index 0000000..26875d1 --- /dev/null +++ b/public/js/app/socket.js @@ -0,0 +1,28 @@ +app.socket = (function(app){ + // $.getScript('/socket.io/socket.io.js') + // + + var socket; + $(document).ready(function(){ + socket = io({ + auth: { + token: app.auth.getToken() + } + }); + // socket.emit('chat message', $('#m').val()); + socket.on('P2PSub', function(msg){ + msg.data.__noSocket = true; + app.publish(msg.topic, msg.data); + }); + + app.subscribe(/./g, function(data, topic){ + // console.log('local_pubs', data, topic) + if(data.__noSocket) return; + // console.log('local_pubs 2', data, topic) + + socket.emit('P2PSub', { topic, data }); + }); + }) + + return socket; +})(app); \ No newline at end of file diff --git a/public/js/app/torrent.js b/public/js/app/torrent.js new file mode 100644 index 0000000..08c318a --- /dev/null +++ b/public/js/app/torrent.js @@ -0,0 +1,122 @@ +app.torrent = (function(app){ + let isDown = false; + + $( document ).on( "ajaxSend", function(event, ajax, res, ...args) { + console.log('right?', res.url, res.url.startsWith('/__api/torrent'), app.torrent.isDown) + if(res.url.startsWith('/__api/torrent') && isDown){ + ajax.abort() + } + // $( ".log" ).text( "Triggered ajaxStart handler." ); + // throw new Error('go') + } ); + + statusMap = [ + 'Inactive', // 0 + 'CHECK_WAIT', // 1 + 'Verifying', // 2 + 'DOWNLOAD_WAIT', // 3 + 'Downloading', // 4 + 'SEED_WAIT', // 5 + 'Seeding', // 6 + 'ISOLATED', // 7 + 'Unknown', // 8 + ]; + + function list(callback, username) { + app.api.get('torrent', function(error, data){ + if(error) return; + callback(null, data) + }); + } + + function get(callback, id, forceUpdate){ + app.api.get(`torrent/${id}?${forceUpdate ? 'latest': '' }`, function(error, data){ + if(error) return; + callback(null, data) + }); + } + + function start(id, callback){ + app.api.post(`torrent/${id}/start`, function(error, data){ + if(error) return; + callback(null, data) + }); + } + + function stop(id, callback){ + app.api.post(`torrent/${id}/stop`, function(error, data){ + if(error) return; + callback(null, data) + }); + } + + function destroy(id, callback){ + app.api.delete(`torrent/${id}`, function(error, data){ + if(error) return; + callback(null, data) + }); + } + + function parseServerStatus(data){ + return { + ...data, + "downloadSpeed": humanFileSize(data.downloadSpeed)+'/s', + "uploadSpeed": humanFileSize(data.uploadSpeed)+'/s', +/* "activeTorrentCount": 11, + "cumulative-stats": { + "downloadedBytes": 2925927098021, + "filesAdded": 80609, + "secondsActive": 12136579, + "sessionCount": 21, + "uploadedBytes": 107123787853 + }, + "current-stats": { + "downloadedBytes": 48440590262, + "filesAdded": 544, + "secondsActive": 111907, + "sessionCount": 1, + "uploadedBytes": 461874022 + }, + "pausedTorrentCount": 462, + "torrentCount": 473, + "__noSocket": true*/ + } + } + + function parseTorrnetItem(torrent){ + let percentDone = (torrent.percentDone || 0)*100; + return { + ...torrent, + "eta": torrent.eta > 0 ? moment().seconds(torrent.eta).fromNow() : 'Unknown', + "rateDownload": `${humanFileSize(torrent.rateDownload)}/s`, + "sizeWhenDone": humanFileSize(torrent.sizeWhenDone), + "percentDone": percentDone, + "statusText": statusMap[torrent.status], + "isActive": [3, 4, 5, 6].includes(torrent.status), // DOWNLOAD_WAIT ,DOWNLOAD, SEED_WAIT, SEED + "isFinished": torrent.isFinished || percentDone === 100, + "createdAtString": moment(torrent.createdAt).fromNow(), + + // "isFinished": false, + // "isStalled": false, + // "name": "reacher.s02e06.1080p.web.h264-successfulcrab[EZTVx.to].mkv", + // "hashString": "4794a0915cada6c491eb5c910e1f4a0da727cac8", + // "status": 4, + // "id": 1, + + // "peersConnected": 50, + // "added_by": "wmantly", + // "errorString": "", + + // "downloadDir": "/media/torrents", + // "files": [], + // "peers": [], + // "magnetLink": "magnet:?xt=urn:btih:4794A0915CADA6C491EB5C910E1F4A0DA727CAC8&dn=Reacher+S02E06+1080p+WEB+H264-SuccessfulCrab&tr=http%3A%2F%2Fp4p.arenabg.com%3A1337%2Fannounce&tr=udp%3A%2F%2F47.ip-51-68-199.eu%3A6969%2Fannounce&tr=udp%3A%2F%2F9.rarbg.me%3A2780%2Fannounce&tr=udp%3A%2F%2F9.rarbg.to%3A2710%2Fannounce&tr=udp%3A%2F%2F9.rarbg.to%3A2730%2Fannounce&tr=udp%3A%2F%2F9.rarbg.to%3A2920%2Fannounce&tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&tr=udp%3A%2F%2Fopentracker.i2p.rocks%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.cyberia.is%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.dler.org%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.internetwarriors.net%3A1337%2Fannounce&tr=udp%3A%2F%2Ftracker.leechers-paradise.org%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337&tr=udp%3A%2F%2Ftracker.pirateparty.gr%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.tiny-vps.com%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce", + // "isPrivate": false, + // "createdAt": "2024-01-05T21:18:30.607Z", + // "updatedAt": "2024-01-05T21:32:54.493Z" + // "torrent_id": "454", + } + } + + return {list, get, start, stop, destroy, parseTorrnetItem, parseServerStatus, isDown}; +})(app); \ No newline at end of file diff --git a/public/js/app/user.js b/public/js/app/user.js new file mode 100644 index 0000000..26c0232 --- /dev/null +++ b/public/js/app/user.js @@ -0,0 +1,44 @@ +app.user = (function(app){ + function list(callback){ + app.api.get('user/?detail=true', function(error, data){ + callback(error, data); + }) + } + + function add(args, callback){ + app.api.post('user/', args, function(error, data){ + callback(error, data); + }); + } + + function remove(args, callback){ + if(!confirm('Delete '+ args.uid+ 'user?')) return false; + app.api.delete('user/'+ args.uid, function(error, data){ + callback(error, data); + }); + } + + function changePassword(args, callback){ + app.api.put('users/'+ arg.uid || '', args, function(error, data){ + callback(error, data); + }); + } + + function createInvite(callback){ + app.api.post('user/invite', {}, function(error, data, status){ + callback(error, data); + }); + } + + function consumeInvite(args){ + app.api.post('/auth/invite/'+args.token, args, function(error, data){ + if(data.token){ + app.auth.setToken(data.token) + return callback(null, true) + } + callback(error) + }); + } + + return {list, remove, createInvite}; +})(app); \ No newline at end of file diff --git a/public/js/app/utils.js b/public/js/app/utils.js new file mode 100644 index 0000000..306c3dc --- /dev/null +++ b/public/js/app/utils.js @@ -0,0 +1,96 @@ +app.util = (function(app){ + + function getUrlParameter(name) { + name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); + var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); + var results = regex.exec(location.search); + return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); + }; + + function actionMessage(message, $target, type, callback){ + message = message || ''; + $target = $target.closest('div.card').find('.actionMessage'); + type = type || 'info'; + callback = callback || function(){}; + + if($target.html() === message) return; + + if($target.html()){ + $target.slideUp('fast', function(){ + $target.html('') + $target.removeClass (function (index, className) { + return (className.match (/(^|\s)ui-\S+/g) || []).join(' '); + }); + if(message) return actionMessage(message, $target, type, callback); + $target.hide() + }) + }else{ + if(type) $target.addClass('ui-' + type); + $target.html(message).slideDown('fast'); + } + setTimeout(callback,10) + } + + $( document ).ready( function () { + $('.actionMessage').on('click', 'button.action-close', function(event){ + app.util.actionMessage(null, $(this)); + }); + }); + + $.fn.serializeObject = function() { + var + arr = $(this).serializeArray(), + obj = {}; + + for(var i = 0; i < arr.length; i++) { + if(obj[arr[i].name] === undefined) { + obj[arr[i].name] = arr[i].value; + } else { + if(!(obj[arr[i].name] instanceof Array)) { + obj[arr[i].name] = [obj[arr[i].name]]; + } + obj[arr[i].name].push(arr[i].value); + } + } + return obj; + }; + + function formAJAX( btn, del ) { + event.preventDefault(); // avoid to execute the actual submit of the form. + var $form = $(btn).closest( '[action]' ); // gets the 'form' parent + var formData = $form.find( '[name]' ).serializeObject(); // builds query formDataing + var method = $form.attr('method') || 'post'; + + // if( !$form.validate()) { + // app.util.actionMessage('Please fix the form errors.', $form, 'danger') + // return false; + // } + + app.util.actionMessage( + '
Loading...
', + $form, + 'state-highlight' + ); + + app.api[method]($form.attr('action'), formData, function(error, data){ + app.util.actionMessage(data.message, $form, error ? 'state-error' : 'priority-primary'); //re-populate table + if(!error){ + $form.trigger("reset"); + eval($form.attr('evalAJAX')); //gets JS to run after completion + } + }); + } + + function humanFileSize(size) { + var i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024)); + return (size / Math.pow(1024, i)).toFixed(2) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; + } + + return { + emptyFuction: function(){}, + getUrlParameter, + actionMessage, + humanFileSize, + formAJAX, + } +})(app); diff --git a/public/partial/header.html b/public/partial/header.html index 2730ad2..17f89b4 100644 --- a/public/partial/header.html +++ b/public/partial/header.html @@ -1,3 +1,6 @@ + @@ -6,6 +9,10 @@ +