diff --git a/public/css/logo-nav.css b/public/css/logo-nav.css index 2fbcc15bbf7f37c2bc3196ceaec3e6ce1c94f5ae..5074c4b892525df7073861617fee443597ecaac5 100644 --- a/public/css/logo-nav.css +++ b/public/css/logo-nav.css @@ -1,28 +1,3 @@ -/*! - * Start Bootstrap - Logo Nav HTML Template (http://startbootstrap.com) - * Code licensed under the Apache License v2.0. - * For details, see http://www.apache.org/licenses/LICENSE-2.0. - */ - body { - padding-top: 70px; /* Required padding for .navbar-fixed-top. Change if height of navigation changes. */ - padding-bottom: 16px; -} - -.navbar-fixed-top .nav { - padding: 15px 0; -} - -.navbar-fixed-top .navbar-brand { - padding: 0 15px; -} - -@media(min-width:768px) { - body { - padding-top: 100px; /* Required padding for .navbar-fixed-top. Change if height of navigation changes. */ - } - - .navbar-fixed-top .navbar-brand { - padding: 20px 0; - } -} + padding-top: 50px; +} \ No newline at end of file diff --git a/public/index.html b/public/index.html index 31a8e5c6ccb7225cab720ebf3b85e988db4cfde0..cf95f9d968ee8fe6b8fd754cfff03ffdf167ec2b 100644 --- a/public/index.html +++ b/public/index.html @@ -7,12 +7,18 @@ <meta name="viewport" content="width=device-width, initial-scale=1"> <title>AMIV</title> - <link href="bs/css/bootstrap.min.css" rel="stylesheet"> + <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script> - <script src="bs/js/bootstrap.min.js"></script> <script src="https://npmcdn.com/masonry-layout@4.0/dist/masonry.pkgd.min.js"></script> +<!-- Latest compiled and minified CSS --> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous"> + +<!-- Optional theme --> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous"> +<!-- Latest compiled and minified JavaScript --> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script> <link href="css/logo-nav.css" rel="stylesheet"> <link href="css/cards.css" rel="stylesheet"> <link href="css/dynamic.css" rel="stylesheet"> @@ -33,42 +39,44 @@ <body> <!-- Navigation --> - <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> - <div class="container"> - <!-- Brand and toggle get grouped for better mobile display --> - <div class="navbar-header"> - <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> - <span class="sr-only">Toggle navigation</span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </button> - <a class="navbar-brand" href="#"> - <img src="res/AMIV_Logo_150_50.svg" alt="AMIV"> - </a> - </div> - <!-- Collect the nav links, forms, and other content for toggling --> - <div class="collapse navbar-collapse nav-collapse collapse" id="bs-example-navbar-collapse-1"> - <ul class="nav navbar-nav"> - <li> - <a href="#">Home</a> - </li> - <li> - <a href="#">Der AMIV</a> - </li> - <li> - <a href="#">Studium</a> - </li> - <li> - <a href="#">Jobbörse</a> - </li> - </ul> - </div> - <!-- /.navbar-collapse --> - </div> - <!-- /.container --> - </nav> + <div class="navbar navbar-inverse navbar-fixed-top" role="navigation"> + + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" rel="home" href="#" style="padding-bottom: 10px;padding-top: 10px;"> + <img alt="Brand" src="https://www.amiv.ethz.ch/sites/all/themes/amiv15/logo.png" height="30"> + </a> + </div> + + <div class="collapse navbar-collapse"> + + <ul class="nav navbar-nav"> + <li><a href="#">Der AMIV</a></li> + <li><a href="#">Studium</a></li> + <li><a href="#">Jobbörse</a></li> + </ul> + <div class="col-sm-3 col-md-2 pull-right"> + <form class="navbar-form" role="search"> + <div class="input-group"> + <input type="text" class="form-control" placeholder="Search" name="srch-term" id="srch-term"> + <div class="input-group-btn"> + <button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button> + </div> + </div> + </form> + </div> + <ul class="nav navbar-nav navbar-right welcomening"> + <button type="button" class="btn btn-default navbar-btn loglogbutton" data-toggle="modal" data-target="#myModal" style="margin-left:10px;">Login</button> + </ul> + </div> +</div> +<!-- Mainbody --> <div class="container-fluid"> <div class="grid"> <div class="grid-sizer"></div> @@ -96,7 +104,35 @@ <!-- Facebook widget --> </div> </div> + + <!-- Modal --> +<div id="myModal" class="modal fade" role="dialog"> + <div class="modal-dialog modal-sm"> + + <!-- Modal content--> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal">×</button> + <h4 class="modal-title">Herzlich Wilkommen</h4> + </div> + <div class="modal-body"> + <div class="input-group"> + <input type="text" class="form-control" id="loginUsername" name="user" placeholder="user"> + <span class="input-group-addon">@student.ethz.ch</span> + </div> + <br> + <input type="password" class="form-control" id="loginPassword" name="password" placeholder="password"> + </div> + <div class="modal-footer"> + <button type="submit" class="btn btn-primary loginAction" data-dismiss="modal" id="loginSubmit">Login</button> + </div> + </div> + + </div> +</div> + <script src="js/main.js"></script> + <script src="js/amivcore.js"></script> </body> </html> diff --git a/public/js/amivcore.js b/public/js/amivcore.js new file mode 100644 index 0000000000000000000000000000000000000000..43633f82f9b714e6e2340787f26fe3addefa1914 --- /dev/null +++ b/public/js/amivcore.js @@ -0,0 +1,311 @@ +(function(window) { + 'use strict'; + // Library NameSpace + var lns = 'amivcore' + + function libgen() { + // Lib to returned + var lib = {}; + + // Core + var core = { + // Important vars n' stuff + lib: { + //api_url: 'https://amiv-apidev.vsos.ethz.ch', + api_url: 'https://nicco.io/amiv', + spec_url: 'lib/amiv/spec.json', + //spec_url: 'https://nicco.io/amiv/docs/spec.json', + authenticated: false, + ready: false, + req_time_out: 5000, + on_interval: 100, + auth_interval: 5000, + auth_allowed_fails: 5, + auth_fails: 0, + show_errors: false, + }, + // Header Setup + header: { + req: { + 'get': ['Content-Type', 'Authorization'], + 'post': ['Content-Type', 'Authorization'], + 'put': ['Content-Type', 'Authorization', 'If-Match'], + 'patch': ['Content-Type', 'Authorization', 'If-Match'], + 'delete': ['Content-Type', 'Authorization', 'If-Match'], + }, + make: { + 'Content-Type': function() { + return 'application/json' + }, + 'Authorization': function() { + if (get('cur_token') != null) + return 'Basic ' + btoa(get('cur_token') + ':'); + return ''; + }, + 'If-Match': function() { + return null; + } + } + } + } + + // Utility empty function for no callback + function dummy() {}; + + //Save and get into localStorage + function set(cname, cvalue, exdays) { + window.localStorage.setItem('glob-' + cname, cvalue); + } + + function get(cname) { + return window.localStorage.getItem('glob-' + cname); + } + + // Make Request + function req(attr, callback) { + callback = callback || function(msg) { + console.log(msg); + }; + $.ajax({ + url: core.lib.api_url + attr.path, + data: attr.data, + method: attr.method, + dataType: 'json', + timeout: core.lib.req_time_out, + headers: attr.headers, + error: function(res) { + if (core.lib.show_errors) console.log(res); + callback(res); + }, + }).done(function(res) { + callback(res); + }); + } + + function makeFunc(domain, m) { + return function(attr, callback) { + attr = attr || {}; + var curLib = {} + for (var curAttr in attr['data']) + curLib[curAttr] = attr['data'][curAttr]; + + var hdr = {}; + for (var curHdr in attr['header']) + hdr[curHdr] = attr['header'][curHdr]; + + var curPath = '/' + domain; + var curLink = curPath; + if (attr['id'] != undefined) { + curPath += '/' + attr['id']; + curLink += '/{_id}'; + } + + if (get('cur_token') != null) + hdr['Authorization'] = 'Basic ' + btoa(get('cur_token') + ':'); + + if (m != 'GET') { + if (m == 'POST' || m == 'PUT') + for (var param in lib[domain]['methods'][m][curLink]['params']) + if (lib[domain]['methods'][m][curLink]['params'][param]['required'] == true) + if (curLib[lib[domain]['methods'][m][curLink]['params'][param]['name']] == undefined) + return 'Error: Missing ' + lib[domain]['methods'][m][curLink]['params'][param]['name']; + hdr['Content-Type'] = 'application/json'; + curLib = JSON.stringify(curLib); + } + req({ + path: curPath, + method: m, + data: curLib, + headers: hdr, + }, callback); + return true; + }; + } + + $.ajax({ + url: core.lib.spec_url, + dataType: 'json', + timeout: 5000, + success: function(d) { + var data = d['domains']; + for (var domain in data) { + lib[domain] = {}; + lib[domain].methods = []; + for (var p in data[domain]['paths']) { + for (var m in data[domain]['paths'][p]) { + if (lib[domain].methods[m] == undefined) lib[domain].methods[m] = {}; + lib[domain].methods[m][p] = data[domain]['paths'][p][m]; + } + } + for (var m in lib[domain]['methods']) { + lib[domain][m] = makeFunc(domain, m); + } + } + checkAuth(); + }, + error: function(d) { + console.log('Cannot reach initialization spec: ' + core.lib.spec_url); + console.log(d); + } + }); + + function checkAuth() { + if (get('cur_token') != null) { + lib.sessions.GET({ + data: { + where: 'token==["' + get('cur_token') + '"]' + } + }, function(res) { + if (res !== undefined && res.hasOwnProperty('_items') && res['_items'].length > 0) + core.lib.authenticated = true; + else + core.lib.authenticated = false; + core.lib.ready = true; + setTimeout(checkAuth, core.lib.auth_interval); + }); + } else { + core.lib.authenticated = false; + core.lib.ready = true; + setTimeout(checkAuth, core.lib.auth_interval); + } + } + + // Get the etag + lib.getEtag = function(curDomain, curId, callback) { + return lib[curDomain].GET({ + id: curId + }, function(res) { + callback(res['_etag']); + }); + } + + // Returns whether user is logged in + lib.authenticated = function() { + return core.lib.authenticated; + } + + // Login function + lib.login = function(curUser, curPass, callback) { + callback = callback || dummy; + req({ + path: '/sessions/', + method: 'POST', + data: JSON.stringify({ + user: curUser.toLowerCase(), + password: curPass + }), + headers: { + 'Content-Type': 'application/json', + }, + }, function(msg) { + var reqVar = ['token', 'user_id', 'id']; + for (var i in reqVar) { + lib['cur_' + reqVar[i]] = msg[reqVar[i]]; + } + if (msg['_status'] == 'OK') { + set('cur_token_id', msg['id'], 1); + set('cur_token', msg['token'], 1); + set('cur_user_id', parseInt(msg['user_id']), 1); + callback(true); + } else { + set('cur_token_id', null); + set('cur_token', null); + set('cur_user_id', null); + callback(false); + } + }); + } + + // Logout + lib.logout = function() { + // Deleting token from api and unsetting the vars + lib.sessions.DELETE({ + id: get('cur_token_id') + }, function(res) { + set('cur_token', null); + set('cur_token_id', null); + set('cur_user_id', null); + }); + } + + // Get info about the current user + lib.user = function(attr, callback) { + callback = callback || dummy; + lib.users.GET({ + id: get('cur_user_id') + }, function(res) { + if (typeof attr === 'object') { + var ret = {}; + for (var key in attr) + ret[attr[key]] = res[attr[key]]; + callback(ret); + } else { + callback(res[attr]); + } + }); + } + + // Get the necessary field for specific requests + lib.getRequiredFields = function(domain, type, wId) { + var curTree; + var resAttr = {}; + if (wId) + curTree = lib[domain]['methods'][type]['/' + domain + '/{_id}']['params']; + else + curTree = lib[domain]['methods'][type]['/' + domain]['params']; + if (curTree.length == 0) return false; + else { + for (var i = 0; i < curTree.length; i++) + if (curTree[i].required == true) + resAttr[curTree[i].name] = curTree[i]; + } + return resAttr; + } + + //On function + lib.on = function(trigger, callback) { + if (callback) { + lib.on_mem[trigger].callback = callback; + lib.on_mem[trigger].func(); + } + } + lib.on_mem = { + ready: { + func: function() { + if (core.lib.ready) + lib.on_mem.ready.callback(); + else setTimeout(function() { + lib.on_mem.ready.func(); + }, core.lib.on_interval); + } + }, + login: { + func: function() { + if (core.lib.authenticated && !lib.on_mem.login.prev) + lib.on_mem.login.callback(); + lib.on_mem.login.prev = core.lib.authenticated; + setTimeout(lib.on_mem.login.func, core.lib.on_interval); + }, + prev: false, + }, + logout: { + func: function() { + if (!core.lib.authenticated && lib.on_mem.logout.prev) + lib.on_mem.logout.callback(); + lib.on_mem.logout.prev = core.lib.authenticated; + setTimeout(lib.on_mem.logout.func, core.lib.on_interval); + }, + prev: false, + }, + } + + return lib; + } + + if (typeof(window[lns]) === 'undefined') { + window[lns] = libgen(); + } else { + console.log(lns + ' already defined, please solve conflict'); + } + +})(window); diff --git a/public/js/main.js b/public/js/main.js index c79a193f1e0853d32d79b40d5eb3e219eb8f2ec7..677b172865dffe788ae67b32869182863169a64e 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -55,4 +55,22 @@ function getEvents(callback) { addElement('<div class="card"><div class="card-image"><img class="img-responsive" src="'+item.img_banner+'"><date><div class="month">'+month[datenum.getMonth()]+'</div><div class="day">'+datenum.getDate()+'</div><div class="starttime">'+datenum.getHours()+':'+minutes+'</div><date-overlay></date-overlay></date><span class="card-title">'+item.title_de+' @ '+item.location+'</span></div><div class="card-content">'+item.description_de+'</div><div class="card-action"><a href="#" target="new_blank">Info</a><a href="#" target="new_blank">'+register+'</a><a href="#" target="new_blank">Im Kalender speichern</a></div></div>'); }); }); - }); + }); +// Login + $('#loginSubmit').on('click', function(){ + amivcore.login($('#loginUsername').val(), $('#loginPassword').val(), function(ret) { + if (ret == true){ + $('.welcomening').append('<li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">+amivcore.user+<span class="caret"></span></a><ul class="dropdown-menu"><li><a href="#">Logout</a></li><li role="separator" class="divider"></li><li><a href="https://intern.amiv.ethz.ch/wiki/">AMIV-Tools</a></li></ul></li>'); + + $('.loglogbutton').hide(); + } else { + $('.welcomening').append('<p class="navbar-text navbar-right message" style="color:red;margin-right:10px;">LOGIN FAILED</p>'); + setTimeout(function() { + $('.message').remove(); + }, 2000); + } + }); + }); + + +