Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • maspect/amiv-admintool
  • emustafa/amiv-admintool
  • dvruette/amiv-admintool
  • amiv/amiv-admintool
4 results
Show changes
Commits on Source (485)
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-existing-dockerfile
{
"name": "amiv-admintool",
"image": "mcr.microsoft.com/vscode/devcontainers/javascript-node:14",
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [9000],
// Uncomment the next line to run commands after the container is created.
"postCreateCommand": "npm install"
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as an existing user other than the container default. More info: https://aka.ms/dev-containers-non-root.
//"remoteUser": "node"
}
......@@ -7,9 +7,18 @@ module.exports = {
"browser": true,
},
"rules": {
"no-console": 0,
"no-console": 1,
"class-methods-use-this": 0,
"prefer-destructuring": 1,
"no-underscore-dangle": 0,
"linebreak-style": 0,
"import/no-unresolved": [ "error", { "ignore": [ 'networkConfig' ] } ], // hack until resolving import properly
"object-curly-newline": [ "error", {
ObjectExpression: { multiline: true, consistent: true },
ObjectPattern: { multiline: true, consistent: true },
ImportDeclaration: { minProperties: 7, consistent: true },
ExportDeclaration: { minProperties: 7, consistent: true },
}],
"max-len": [ "error", { "code": 100, ignorePattern: ".*<svg.+>" }],
}
};
.ftpconfig
node_modules/
.idea/
dist/
.DS_Store
stages:
- test
- build
- deploy
dev_deploy:
stage: deploy
image: alpine:latest
when: manual
eslint:
stage: test
image: node:latest
before_script:
- npm install
script:
- npm run lint
build_master:
stage: build
image: docker:stable
services:
- docker:dind
before_script:
- 'which ssh-agent || ( apk update -y && apk add openssh-client -y )'
- mkdir -p ~/.ssh
- eval $(ssh-agent -s)
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- echo "$DEPLOY_PRIVATE_KEY" | ssh-add -
- echo "$CI_DOCKER_REGISTRY_TOKEN" | docker login -u "$CI_DOCKER_REGISTRY_USER" --password-stdin
script:
- ssh -p22 amivadmin@amiv-zoidberg.ethz.ch "docker build -t admintools ./amiv-containers/admintools/"
- ssh -p22 amivadmin@amiv-zoidberg.ethz.ch "cd ./amiv-containers/ && docker-compose up -d"
- docker build --build-arg NPM_BUILD_COMMAND=build --pull -t "$CI_REGISTRY_IMAGE:prod" ./
- docker build --build-arg NPM_BUILD_COMMAND=build-staging --pull -t "$CI_REGISTRY_IMAGE:staging" ./
- docker build --build-arg NPM_BUILD_COMMAND=build-local --pull -t "$CI_REGISTRY_IMAGE:local" ./
- docker push "$CI_REGISTRY_IMAGE:prod"
- docker push "$CI_REGISTRY_IMAGE:staging"
- docker push "$CI_REGISTRY_IMAGE:local"
environment:
name: production
url: https://admin.amiv.ethz.ch
only:
- master
build_dev:
stage: build
image: docker:stable
services:
- docker:dind
before_script:
- echo "$CI_DOCKER_REGISTRY_TOKEN_DEV" | docker login -u "$CI_DOCKER_REGISTRY_USER_DEV" --password-stdin
script:
- docker build --build-arg NPM_BUILD_COMMAND=build-dev --pull -t "$CI_REGISTRY_IMAGE_DEV" ./
- docker push "$CI_REGISTRY_IMAGE_DEV"
environment:
name: development
url: https://amiv-admin.amiv.ethz.ch
url: https://admin-dev.amiv.ethz.ch
deploy:
stage: deploy
image: amiveth/ansible-ci-helper
script:
- python /main.py
File moved
# Summary
> Hi! Thanks for contributing to the admintools by reporting a new Bug!
> In order to fix the bug soon, please help us to figure out what causes the
> malfunction!
> describe the issue here
# Steps to Reproduce
> What is the main menu point (left menu bar) where this issue occurs?
> Copy and Paste the url from the window where the issue occured
> Describe in your own words what steps you did before the issue occured
# Additional Debug Information
> Please add information on what browser and operating system you are using
> If possible, can you make a screenshot of the bug?
> Please open the "developer tools" of your browser and copy and paste any
> printouts in the "console"
/label ~bug
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/src/relationlistcontroller.js"
}
]
}
\ No newline at end of file
# First stage: Build project
FROM node:14 as build
ARG NPM_BUILD_COMMAND=build
# Copy files and install dependencies
COPY ./ /
RUN npm install
# Build project
RUN npm run $NPM_BUILD_COMMAND
# Second stage: Server to deliver files
FROM nginx:1.15-alpine
# Copy files from first stage
COPY --from=build /index.html /var/www/
COPY --from=build /dist /var/www/dist
# Copy nginx configuration
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Admintool
### Software:
* ```ubuntu /14.04.1```
* ```nginx /1.4.6```
### Dependecies:
* ```jQuery /2.2.2```
* ```bootstrap /3.3.6```
# Developer Installation
## w/ Docker
Start the dev Container in VS Code
run ```npm run start``` inside the container.
The development server is available under localhost:9000. It refreshes automatically as soon as you save changes in any `.js` file.
## w/o Docker
```
npm install
......@@ -16,17 +17,30 @@ npm install
And now, start developing:
```
npm start
npm run start
```
*Warning*: For installation on Ubuntu 16.04 (and possibly similar), you need to install nodejs from the repos source.
1. Remove nodejs if you already have it (ONLY IF YOU REALLY WANT!):
```
sudo apt remove nodejs
```
2. Add nodejs10 from repo (download): `curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -`
3. Install: `sudo apt install -y nodejs`
4. Clean-up and install the packages for amiv-admintools
```
rm -rf node_modules/
npm install
npm run start
```
This will open up a local server outputting the current version of the admintools. It refreshes automatically as soon as you save changes in any `.js` file.
### File Structure:
* admin (Admintool)
* res (Resources)
* bg (big pictures and backgrounds)
* favicon
* fonts
* logo
* bootstrap
* js
* src
* public (Website)
* res (Resources)
- favicon
- logo
* src
- views (reusable view components, etc for Tables and selection lists)
- `index.js` main file
- `*Tool.js` main file per API resource, e.g. for all user-related UIs.
......@@ -20,8 +20,19 @@
<link rel="icon" type="image/png" sizes="96x96" href="res/favicon/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="res/favicon/favicon-16x16.png">
<link href="res/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="lib/cust/main.css" rel="stylesheet">
<!--link href="lib/cust/main.css" rel="stylesheet"-->
<style>
@keyframes spin {
from { transform:rotate(0deg); }
to { transform:rotate(360deg); }
}
@keyframes popup {
from { opacity: 0; }
90% { opacity: 0; }
to { opacity: 100%; }
}
} </style>
</head>
<body>
......
(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: api_url_config,
spec_url: spec_url_config,
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'],
'patch': ['Content-Type', 'Authorization', 'If-Match'],
'delete': ['Content-Type', 'Authorization', 'If-Match'],
},
make: {
'Content-Type': function() {
return 'application/json'
},
'Authorization': function() {
var token = get('cur_token');
if (token != null)
return token;
return '';
},
'If-Match': function() {
return null;
}
}
},
adapter: {
'none': function(ret) {
return ret;
},
'string': function(strg) {
return String(strg);
},
'integer': function(int) {
return parseInt(int);
},
'boolean': function(bool) {
return (String(bool).trim().toLowerCase() == 'true' || bool === true || bool === 1)
},
'datetime': function(dt) {
var tmp = new Date(dt);
// send an iso string without the milis, thats what the api expects
return new Date(dt).toISOString().split('.')[0]+"Z";
}
}
}
/**
* Utility empty function for no callback
* @constructor
*/
function dummy() {};
/**
* Save and get into localStorage
* @constructor
* @param {string} cname
* @param {string} cvalue
*/
function set(cname, cvalue) {
if (lib.shortSession) {
window.sessionStorage.setItem('glob-' + cname, cvalue);
}
else
window.localStorage.setItem('glob-' + cname, cvalue);
}
/**
* Get from LocalStorage
* @constructor
* @param {string} cname
*/
function get(cname) {
if (lib.shortSession)
return window.sessionStorage.getItem('glob-' + cname);
else
return window.localStorage.getItem('glob-' + cname);
}
/**
* Remove variable in localStorage
* @param {string} cname
*/
function remove(cname) {
if (lib.shortSession) {
if (window.sessionStorage.getItem('glob-' + cname) !== null)
window.sessionStorage.removeItem('glob-' + cname);
}
else {
if (window.localStorage.getItem('glob-' + cname) !== null)
window.localStorage.removeItem('glob-' + cname);
}
}
/**
* Make JSON request with all request parameters in attr
* @constructor
* @param {} attr - all request parameters (attr.path, attr.data, attr.method ...)
* @param {} callback
*/
function req(attr, callback) {
callback = callback || function(msg) {
console.log(msg);
};
$.ajax({
url: core.lib.api_url + attr.path,
data: JSON.stringify(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);
});
}
/**
* Make FormData request with all request parameters in attr
* @constructor
* @param {} attr - all request parameters (attr.path, attr.data, attr.method ...)
* @param {} callback
*/
function reqFormData(attr, callback) {
callback = callback || function(msg) {
console.log(msg);
};
// put the json object into form-data
var form = new FormData();
for (var key in attr['data'])
form.append(key, attr['data'][key]);
$.ajax({
url: core.lib.api_url + attr.path,
data: form,
method: attr.method,
dataType: "json",
contentType: false,
processData: false,
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);
});
}
/**
* Make Function
* @constructor
* @param {string} domain
* @param {string} m - method
*/
function makeFunc(domain, m) {
return function(attr, callback) {
attr = attr || {}; // if attr does not exist use empty object
var curLib = {}
for (var curAttr in attr['data']) {
var curAttrType = lib.getParamType(domain, curAttr);
if (core.adapter.hasOwnProperty(curAttrType))
curLib[curAttr] = core.adapter[lib.getParamType(domain, curAttr)](attr['data'][curAttr]);
else
curLib[curAttr] = attr['data'][curAttr];
}
//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}';
}
// handle where, sort, projection, embedded
var urlParams = "";
var urlTypes = ['where', 'sort', 'projection', 'embedded'];
if (m === 'GET') {
for (var curUrlType of urlTypes) {
if (attr[curUrlType] != undefined) {
urlParams += ((urlParams != "") ? "&" + curUrlType + "=": curUrlType + "=");
if (typeof attr[curUrlType] === 'object')
urlParams += JSON.stringify(attr[curUrlType]);
else
urlParams += attr[curUrlType];
}
}
}
// append urlParams
curPath += "?" + urlParams;
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);
}
if (m != 'POST' && m != 'PATCH') {
req({
path: curPath,
method: m,
data: curLib,
headers: hdr,
}, callback);
}
else {
reqFormData({
path: curPath,
method: m,
data: curLib,
headers: hdr,
}, callback);
}
return true;
};
}
/**
* Read spec.json and set all needed parameters
* @constructor
*/
$.ajax({
url: core.lib.spec_url,
dataType: 'json',
timeout: core.lib.req_time_out,
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.error(d);
}
});
/**
* Check Authentication
* @constructor
* @param {} exec_once
*/
function checkAuth(exec_once) {
exec_once = exec_once || false;
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;
core.lib.auth_fails = 0;
} else {
core.lib.auth_allowed_fails++;
if (core.lib.auth_fails > core.lib.auth_allowed_fails)
core.lib.authenticated = false;
}
core.lib.ready = true;
if (!exec_once)
setTimeout(checkAuth, core.lib.auth_interval);
});
} else {
core.lib.authenticated = false;
core.lib.ready = true;
if (!exec_once)
setTimeout(checkAuth, core.lib.auth_interval);
}
}
/**
* Get parameter type
* @constructor
* @param {string} dom
* @param {string} param
* @example
* // returns type of field "_id" of resource "users"
* amivcore.getParamType("users", "_id")
*/
lib.getParamType = function(dom, param) {
var tmp = 'none';
try {
if (Array.isArray(lib[dom].methods.POST['/' + dom].params))
lib[dom].methods.POST['/' + dom].params.forEach(function(cur) {
if (cur.name == param) {
tmp = cur.type;
}
});
} catch (e) {}
return tmp;
}
/**
* Get the time converted to the format the api understands
* @param {Date} d - date. If none is given then the NOW is used
* @example
* amivcore.getTime() // "2016-12-20T14:12:55Z"
* amivcore.getTime(new Date(2011, 0, 1, 2, 3, 4, 567)) // "2011-01-01T01:03:04Z"
*/
lib.getTime = function(d) {
d = d || new Date();
return core.adapter['datetime'](d.toISOString());
}
/**
* Get the etag
* @constructor
* @param {} curDomain
* @param {} curId
* @param {} callback
* @example
* amivcore.getEtag("users", amivcore.cur_user, function(res) {
* console.log(res);
* });
*/
lib.getEtag = function(curDomain, curId, callback) {
return lib[curDomain].GET({
id: curId
}, function(res) {
callback(res['_etag']);
});
}
/**
* Returns whether user is logged in
* @constructor
*/
lib.authenticated = function() {
return core.lib.authenticated;
}
/**
* Login function
* @constructor
* @param {String} curUser
* @param {String} curPass
* @param {function} callback
* @param {boolean} shortSession - if user is on a public computer
*/
lib.login = function(curUser, curPass, callback, shortSession = false) {
lib.shortSession = shortSession || false;
callback = callback || dummy;
req({
path: '/sessions/',
method: 'POST',
data: {
username: curUser.toLowerCase(),
password: curPass
},
headers: {
'Content-Type': 'application/json',
},
}, function(msg) {
var reqVar = ['token', 'user', '_id'];
for (var i in reqVar) {
lib['cur_' + reqVar[i]] = msg[reqVar[i]];
}
if (msg['_status'] == 'OK') {
set('cur_token_id', msg['_id']);
set('cur_token', msg['token']);
set('cur_user_id', msg['user']);
set('cur_session_etag', msg['_etag']);
callback(true);
} else {
remove('cur_token_id');
remove('cur_token');
remove('cur_user_id');
remove('cur_session_etag');
callback(false);
}
});
}
/**
* Logout
* @constructor
*/
lib.logout = function() {
// Deleting token from api and unsetting the vars
lib.sessions.DELETE({
id: get('cur_token_id'),
header: {"if-match": get('cur_session_etag')}
}, function(res) {
remove('cur_token');
remove('cur_token_id');
remove('cur_user_id');
remove('cur_session_etag');
});
}
/**
* Get info about the current user
* @constructor
* @param {} attr
* @param {} callback
*/
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
* @constructor
* @param {} domain - resource eg. "/users"
* @param {} type - HTTP request type eg. "PATCH"
* @param {boolean} wId - with id eg. "/users/$id"
* @example
* amivcore.getRequiredFields("users", "POST", false)
*/
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
* @constructor
* @param {} trigger
* @param {} callback
*/
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);
{
"domains": {
"purchases": {
"paths": {
"/purchases": {
"POST": {
"params": [
{
"unique": false,
"name": "timestamp",
"nullable": false,
"required": true,
"type": "datetime"
},
{
"not_patchable_unless_admin": true,
"name": "product",
"nullable": false,
"required": true,
"allowed": [
"beer",
"coffee"
],
"unique": false,
"type": "string",
"maxlength": 6
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"name": "user",
"nullable": false,
"required": true,
"data_relation": {
"field": "_id",
"resource": "users",
"embeddable": true
},
"unique": false,
"type": "objectid"
}
],
"label": "Create a Purchase"
},
"GET": {
"params": [],
"label": "Retrieve all purchases"
}
},
"/purchases/{_id}": {
"GET": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Retrieve a Purchase"
}
}
},
"description": {
"fields": {},
"general": "A beer machine or kaffi machine transaction. Users should be able to get beer or kaffi, if their last timestamp is older than one day and they are AMIV members. This resource is used to log their purchases."
}
},
"users": {
"paths": {
"/users/{_id}": {
"PATCH": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
},
{
"not_patchable_unless_admin": true,
"name": "legi",
"nullable": true,
"required": false,
"maxlength": 8,
"unique": true,
"type": "string"
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"not_patchable_unless_admin": true,
"name": "firstname",
"nullable": false,
"required": true,
"maxlength": 50,
"type": "string",
"empty": false
},
{
"not_patchable_unless_admin": true,
"name": "lastname",
"nullable": false,
"required": true,
"maxlength": 50,
"type": "string",
"empty": false
},
{
"name": "rfid",
"nullable": true,
"required": false,
"maxlength": 6,
"unique": true,
"type": "string",
"empty": false
},
{
"nullable": true,
"name": "phone",
"maxlength": 20,
"required": false,
"type": "string",
"empty": false
},
{
"not_patchable_unless_admin": true,
"name": "membership",
"required": true,
"allowed": [
"none",
"regular",
"extraordinary",
"honorary"
],
"unique": false,
"type": "string",
"maxlength": 13
},
{
"not_patchable_unless_admin": true,
"name": "nethz",
"nullable": true,
"default": null,
"required": false,
"maxlength": 30,
"unique": true,
"type": "string",
"empty": false
},
{
"not_patchable_unless_admin": true,
"name": "gender",
"required": true,
"allowed": [
"male",
"female"
],
"unique": false,
"type": "string",
"maxlength": 6
},
{
"nullable": true,
"not_patchable_unless_admin": true,
"name": "department",
"allowed": [
"itet",
"mavt"
],
"required": false,
"type": "string"
},
{
"name": "password",
"nullable": true,
"default": null,
"required": false,
"maxlength": 100,
"type": "string",
"empty": false
},
{
"regex": "^.+@.+$",
"name": "email",
"required": true,
"maxlength": 100,
"unique": true,
"type": "string"
},
{
"required": false,
"type": "boolean",
"name": "send_newsletter",
"nullable": true
}
],
"label": "Update a User"
},
"DELETE": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Delete a User"
},
"GET": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Retrieve a User"
}
},
"/users/{nethz}": {
"GET": {
"params": [
{
"not_patchable_unless_admin": true,
"name": "nethz",
"nullable": true,
"default": null,
"required": false,
"maxlength": 30,
"unique": true,
"type": "string",
"empty": false
}
],
"label": "Retrieve a User"
}
},
"/users": {
"POST": {
"params": [
{
"not_patchable_unless_admin": true,
"name": "legi",
"nullable": true,
"required": false,
"maxlength": 8,
"unique": true,
"type": "string"
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"not_patchable_unless_admin": true,
"name": "firstname",
"nullable": false,
"required": true,
"maxlength": 50,
"type": "string",
"empty": false
},
{
"not_patchable_unless_admin": true,
"name": "lastname",
"nullable": false,
"required": true,
"maxlength": 50,
"type": "string",
"empty": false
},
{
"name": "rfid",
"nullable": true,
"required": false,
"maxlength": 6,
"unique": true,
"type": "string",
"empty": false
},
{
"nullable": true,
"name": "phone",
"maxlength": 20,
"required": false,
"type": "string",
"empty": false
},
{
"not_patchable_unless_admin": true,
"name": "membership",
"required": true,
"allowed": [
"none",
"regular",
"extraordinary",
"honorary"
],
"unique": false,
"type": "string",
"maxlength": 13
},
{
"not_patchable_unless_admin": true,
"name": "nethz",
"nullable": true,
"default": null,
"required": false,
"maxlength": 30,
"unique": true,
"type": "string",
"empty": false
},
{
"not_patchable_unless_admin": true,
"name": "gender",
"required": true,
"allowed": [
"male",
"female"
],
"unique": false,
"type": "string",
"maxlength": 6
},
{
"nullable": true,
"not_patchable_unless_admin": true,
"name": "department",
"allowed": [
"itet",
"mavt"
],
"required": false,
"type": "string"
},
{
"name": "password",
"nullable": true,
"default": null,
"required": false,
"maxlength": 100,
"type": "string",
"empty": false
},
{
"regex": "^.+@.+$",
"name": "email",
"required": true,
"maxlength": 100,
"unique": true,
"type": "string"
},
{
"required": false,
"type": "boolean",
"name": "send_newsletter",
"nullable": true
}
],
"label": "Create a User"
},
"GET": {
"params": [],
"label": "Retrieve all users"
}
}
},
"description": {
"methods": {
"GET": "Authorization is required for most of the fields"
},
"general": "In general, the user data will be generated from LDAP-Data. However, one might change the RFID-Number or the membership-status. Extraordinary members may not have a LDAP-Account and can therefore access all given fields."
}
},
"sessions": {
"paths": {
"/sessions/{_id}": {
"DELETE": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Delete a Session"
},
"GET": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Retrieve a Session"
}
},
"/sessions": {
"POST": {
"params": [
{
"name": "username",
"nullable": false,
"required": true,
"type": "string",
"empty": false
},
{
"readonly": true,
"required": false,
"type": "string",
"name": "token"
},
{
"name": "password",
"nullable": false,
"required": true,
"type": "string",
"empty": false
},
{
"readonly": true,
"name": "user",
"data_relation": {
"field": "_id",
"cascade_delete": true,
"resource": "users",
"embeddable": true
},
"required": false,
"type": "objectid"
},
{
"required": false,
"type": "objectid",
"name": "_id"
}
],
"label": "Create a Session"
},
"GET": {
"params": [],
"label": "Retrieve all sessions"
}
}
},
"description": {
"methods": {
"POST": "Login and aquire a login token. Post the fields 'username' and 'password', the response will contain the token. 'username' can be either nethz, mail, or user_id",
"GET": "Check token(s)."
},
"general": "A session is used to authenticate a user after he provided login data. A POST to /session will return a token you can use in an Authorization header: token <yourtoken>"
}
},
"groupmemberships": {
"paths": {
"/groupmemberships": {
"POST": {
"params": [
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"self_enrollment_required": true,
"name": "group",
"data_relation": {
"field": "_id",
"cascade_delete": true,
"resource": "groups",
"embeddable": true
},
"required": true,
"type": "objectid"
},
{
"name": "user",
"unique_combination": [
"group"
],
"required": true,
"only_self_or_moderator": true,
"data_relation": {
"field": "_id",
"cascade_delete": true,
"resource": "users",
"embeddable": true
},
"type": "objectid"
},
{
"required": false,
"type": "datetime",
"name": "expiry"
}
],
"label": "Create a Groupmembership"
},
"GET": {
"params": [],
"label": "Retrieve all groupmemberships"
}
},
"/groupmemberships/{_id}": {
"DELETE": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Delete a Groupmembership"
},
"GET": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Retrieve a Groupmembership"
}
}
},
"description": {
"general": "Assignment of registered users to groups."
}
},
"joboffers": {
"paths": {
"/joboffers": {
"POST": {
"params": [
{
"dependencies": "description_de",
"name": "title_de",
"required_if_not": "title_en",
"required": false,
"type": "string"
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"required": false,
"type": "string",
"name": "company",
"maxlength": 30
},
{
"dependencies": "description_en",
"name": "title_en",
"required_if_not": "title_de",
"required": false,
"type": "string"
},
{
"required": false,
"type": "datetime",
"name": "time_end"
},
{
"required": false,
"type": "string",
"name": "description_en"
},
{
"name": "logo",
"filetype": [
"png",
"jpeg"
],
"required": true,
"type": "media"
},
{
"default": false,
"required": false,
"type": "boolean",
"name": "show_website"
},
{
"required": false,
"type": "string",
"name": "description_de"
},
{
"name": "pdf",
"filetype": [
"pdf"
],
"required": true,
"type": "media"
}
],
"label": "Create a Joboffer"
},
"GET": {
"params": [],
"label": "Retrieve all joboffers"
}
},
"/joboffers/{_id}": {
"PATCH": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
},
{
"dependencies": "description_de",
"name": "title_de",
"required_if_not": "title_en",
"required": false,
"type": "string"
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"required": false,
"type": "string",
"name": "company",
"maxlength": 30
},
{
"dependencies": "description_en",
"name": "title_en",
"required_if_not": "title_de",
"required": false,
"type": "string"
},
{
"required": false,
"type": "datetime",
"name": "time_end"
},
{
"required": false,
"type": "string",
"name": "description_en"
},
{
"name": "logo",
"filetype": [
"png",
"jpeg"
],
"required": true,
"type": "media"
},
{
"default": false,
"required": false,
"type": "boolean",
"name": "show_website"
},
{
"required": false,
"type": "string",
"name": "description_de"
},
{
"name": "pdf",
"filetype": [
"pdf"
],
"required": true,
"type": "media"
}
],
"label": "Update a Joboffer"
},
"DELETE": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Delete a Joboffer"
},
"GET": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Retrieve a Joboffer"
}
}
},
"description": {
"fields": {},
"general": "A Job Offer posts repositoryUsers can post a job offer with the necessarycontent to fill out a job offer advertisement"
}
},
"eventsignups": {
"paths": {
"/eventsignups/{_id}": {
"PATCH": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
},
{
"required": false,
"type": "json_event_field",
"name": "additional_fields",
"nullable": true
},
{
"readonly": true,
"name": "confirmed",
"nullable": true,
"required": false,
"type": "boolean"
},
{
"signup_requirements": true,
"name": "event",
"unique_combination": [
"user",
"email"
],
"required": true,
"not_patchable": true,
"data_relation": {
"field": "_id",
"resource": "events",
"embeddable": true
},
"type": "objectid"
},
{
"name": "user",
"nullable": false,
"required": false,
"not_patchable": true,
"data_relation": {
"field": "_id",
"resource": "users",
"embeddable": true
},
"only_self_enrollment_for_event": true,
"type": "objectid"
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"regex": "^.+@.+$",
"name": "email",
"email_signup_must_be_allowed": true,
"nullable": false,
"required": false,
"not_patchable": true,
"maxlength": 100,
"type": "string"
}
],
"label": "Update a Eventsignup"
},
"DELETE": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Delete a Eventsignup"
},
"GET": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Retrieve a Eventsignup"
}
},
"/eventsignups": {
"POST": {
"params": [
{
"required": false,
"type": "json_event_field",
"name": "additional_fields",
"nullable": true
},
{
"readonly": true,
"name": "confirmed",
"nullable": true,
"required": false,
"type": "boolean"
},
{
"signup_requirements": true,
"name": "event",
"unique_combination": [
"user",
"email"
],
"required": true,
"not_patchable": true,
"data_relation": {
"field": "_id",
"resource": "events",
"embeddable": true
},
"type": "objectid"
},
{
"name": "user",
"nullable": false,
"required": false,
"not_patchable": true,
"data_relation": {
"field": "_id",
"resource": "users",
"embeddable": true
},
"only_self_enrollment_for_event": true,
"type": "objectid"
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"regex": "^.+@.+$",
"name": "email",
"email_signup_must_be_allowed": true,
"nullable": false,
"required": false,
"not_patchable": true,
"maxlength": 100,
"type": "string"
}
],
"label": "Create a Eventsignup"
},
"GET": {
"params": [],
"label": "Retrieve all eventsignups"
}
}
},
"description": {
"fields": {
"additional_fields": "Data-schema depends on 'additional_fields' from the mapped event. Please provide in json-format.",
"email": "For registered users, this is just a projection of your general email-address. External users need to provide their email here.",
"user": "Provide either user or email."
},
"methods": {
"PATCH": "Only additional_fields can be changed"
},
"general": "You can signup here for an existing event inside of the registration-window. External Users can only sign up to public events."
}
},
"groups": {
"paths": {
"/groups": {
"POST": {
"params": [
{
"name": "name",
"required": true,
"maxlength": 100,
"unique": true,
"type": "string",
"empty": false
},
{
"default": false,
"required": false,
"type": "boolean",
"name": "has_zoidberg_share"
},
{
"default": false,
"required": false,
"type": "boolean",
"name": "allow_self_enrollment"
},
{
"name": "moderator",
"data_relation": {
"field": "_id",
"resource": "users"
},
"nullable": true,
"required": false,
"type": "objectid"
},
{
"name": "forward_to",
"unique_elements": true,
"required": false,
"type": "list",
"schema": {
"regex": "^.+@.+$",
"type": "string",
"maxlength": 100
}
},
{
"name": "receive_from",
"unique_elements": true,
"unique_elements_for_resource": true,
"required": false,
"type": "list",
"schema": {
"regex": "[a-z0-9_\\.-]+",
"type": "string",
"maxlength": 100
}
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"propertyschema": {
"api_resources": true,
"type": "string"
},
"name": "permissions",
"nullable": true,
"required": false,
"type": "dict",
"valueschema": {
"type": "string",
"allowed": [
"read",
"readwrite"
]
}
}
],
"label": "Create a Group"
},
"GET": {
"params": [],
"label": "Retrieve all groups"
}
},
"/groups/{_id}": {
"PATCH": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
},
{
"name": "name",
"required": true,
"maxlength": 100,
"unique": true,
"type": "string",
"empty": false
},
{
"default": false,
"required": false,
"type": "boolean",
"name": "has_zoidberg_share"
},
{
"default": false,
"required": false,
"type": "boolean",
"name": "allow_self_enrollment"
},
{
"name": "moderator",
"data_relation": {
"field": "_id",
"resource": "users"
},
"nullable": true,
"required": false,
"type": "objectid"
},
{
"name": "forward_to",
"unique_elements": true,
"required": false,
"type": "list",
"schema": {
"regex": "^.+@.+$",
"type": "string",
"maxlength": 100
}
},
{
"name": "receive_from",
"unique_elements": true,
"unique_elements_for_resource": true,
"required": false,
"type": "list",
"schema": {
"regex": "[a-z0-9_\\.-]+",
"type": "string",
"maxlength": 100
}
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"propertyschema": {
"api_resources": true,
"type": "string"
},
"name": "permissions",
"nullable": true,
"required": false,
"type": "dict",
"valueschema": {
"type": "string",
"allowed": [
"read",
"readwrite"
]
}
}
],
"label": "Update a Group"
},
"DELETE": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Delete a Group"
},
"GET": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Retrieve a Group"
}
},
"/groups/{name}": {
"GET": {
"params": [
{
"name": "name",
"required": true,
"maxlength": 100,
"unique": true,
"type": "string",
"empty": false
}
],
"label": "Retrieve a Group"
}
}
},
"description": {
"fields": {
"has_zoidberg_share": "If the group has a share in the amiv storage",
"allow_self_enrollment": "If true, the group can be seen by all users and they can subscribe themselves",
"permissions": "permissions the group grants. has to be according to the jsonschema available at /notyetavailable"
},
"general": "This resource describes the different teams in AMIV.A group can grant API permissions and can be reached with several addresses. To see the addresses of this group, see /groupaddressesTo see the members, have a look at '/groupmembers'. To see the addresses messages are forwarded to, see /groupforwards"
}
},
"studydocuments": {
"paths": {
"/studydocuments/{_id}": {
"PATCH": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
},
{
"name": "files",
"required": true,
"type": "list",
"schema": {
"type": "media"
}
},
{
"nullable": true,
"name": "author",
"maxlength": 100,
"required": false,
"type": "string"
},
{
"nullable": true,
"name": "professor",
"maxlength": 100,
"required": false,
"type": "string"
},
{
"name": "title",
"maxlength": 100,
"required": false,
"type": "string",
"empty": false
},
{
"allowed": [
"1",
"2",
"3",
"4",
"5+"
],
"name": "semester",
"nullable": true,
"required": false,
"type": "string"
},
{
"readonly": true,
"name": "uploader",
"data_relation": {
"field": "_id",
"resource": "users"
},
"nullable": true,
"required": false,
"type": "objectid"
},
{
"allowed": [
"itet",
"mavt",
"arch",
"baug",
"bsse",
"infk",
"matl",
"biol",
"chab",
"math",
"phys",
"erdw",
"usys",
"hest",
"mtec",
"gess"
],
"name": "department",
"nullable": true,
"required": false,
"type": "string"
},
{
"nullable": true,
"name": "lecture",
"maxlength": 100,
"required": false,
"type": "string"
},
{
"required": false,
"type": "integer",
"name": "course_year"
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"required": false,
"type": "string",
"name": "type",
"allowed": [
"exams",
"cheat sheets",
"lecture documents",
"exercises"
]
}
],
"label": "Update a Studydocument"
},
"DELETE": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Delete a Studydocument"
},
"GET": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Retrieve a Studydocument"
}
},
"/studydocuments": {
"POST": {
"params": [
{
"name": "files",
"required": true,
"type": "list",
"schema": {
"type": "media"
}
},
{
"nullable": true,
"name": "author",
"maxlength": 100,
"required": false,
"type": "string"
},
{
"nullable": true,
"name": "professor",
"maxlength": 100,
"required": false,
"type": "string"
},
{
"name": "title",
"maxlength": 100,
"required": false,
"type": "string",
"empty": false
},
{
"allowed": [
"1",
"2",
"3",
"4",
"5+"
],
"name": "semester",
"nullable": true,
"required": false,
"type": "string"
},
{
"readonly": true,
"name": "uploader",
"data_relation": {
"field": "_id",
"resource": "users"
},
"nullable": true,
"required": false,
"type": "objectid"
},
{
"allowed": [
"itet",
"mavt",
"arch",
"baug",
"bsse",
"infk",
"matl",
"biol",
"chab",
"math",
"phys",
"erdw",
"usys",
"hest",
"mtec",
"gess"
],
"name": "department",
"nullable": true,
"required": false,
"type": "string"
},
{
"nullable": true,
"name": "lecture",
"maxlength": 100,
"required": false,
"type": "string"
},
{
"required": false,
"type": "integer",
"name": "course_year"
},
{
"required": false,
"type": "objectid",
"name": "_id"
},
{
"required": false,
"type": "string",
"name": "type",
"allowed": [
"exams",
"cheat sheets",
"lecture documents",
"exercises"
]
}
],
"label": "Create a Studydocument"
},
"DELETE": {
"params": [],
"label": "Delete all studydocuments"
},
"GET": {
"params": [],
"label": "Retrieve all studydocuments"
}
}
},
"description": {
"fields": {
"semester": "Study-Semester as an Integer starting with first semester Bachelor.",
"course_year": "Course Year",
"uploader": "Read-only field describing which AMIV member uploaded the files",
"author": "Original author of the uploaded files(Prof, Assistant, copyright owner)"
},
"general": "Study-documents are basically all documents that are connected to a course. All metadata is optional and intended to help finding the file. There are no strict categories, as those do not work well for courses available to many departements and aiming at all levels of experience."
}
},
"events": {
"paths": {
"/events": {
"POST": {
"params": [
{
"name": "title_de",
"required_if_not": "title_en",
"nullable": true,
"required": false,
"dependencies": [
"catchphrase_de",
"description_de"
],
"maxlength": 100,
"type": "string"
},
{
"name": "time_register_start",
"nullable": true,
"only_if_not_null": "spots",
"required": false,
"dependencies": [
"time_register_end"
],
"type": "datetime",
"earlier_than": "time_register_end"
},
{
"readonly": true,
"required": false,
"type": "integer",
"name": "signup_count"
},
{
"filetype": [
"png",
"jpeg"
],
"required": false,
"type": "media",
"name": "img_thumbnail"
},
{
"dependencies": [
"time_start"
],
"name": "time_end",
"nullable": true,
"later_than": "time_start",
"required": false,
"type": "datetime"
},
{
"name": "allow_email_signup",
"nullable": false,
"default": false,
"only_if_not_null": "spots",
"required": false,
"type": "boolean"
},
{
"nullable": true,
"dependencies": [
"time_register_start",
"time_register_end"
],
"name": "spots",
"min": 0,
"required": false,
"type": "integer"
},
{
"name": "description_de",
"nullable": true,
"required": false,
"type": "string",
"maxlength": 10000
},
{
"name": "time_register_end",
"nullable": true,
"later_than": "time_register_start",
"required": false,
"dependencies": [
"time_register_start"
],
"type": "datetime",
"only_if_not_null": "spots"
},
{
"filetype": [
"png",
"jpeg"
],
"required": false,
"type": "media",
"name": "img_banner"
},
{
"dependencies": [
"time_end"
],
"name": "time_start",
"nullable": true,
"required": false,
"type": "datetime",
"earlier_than": "time_end"
},
{
"name": "catchphrase_en",
"nullable": true,
"required": false,
"type": "string",
"maxlength": 500
},
{
"name": "priority",
"min": 0,
"default": 5,
"max": 10,
"required": true,
"type": "integer"
},
{
"nullable": true,
"name": "location",
"maxlength": 50,
"required": false,
"type": "string"
},
{
"name": "show_infoscreen",
"nullable": false,
"default": false,
"required": false,
"type": "boolean"
},
{
"name": "additional_fields",
"nullable": true,
"only_if_not_null": "spots",
"required": false,
"type": "json_schema"
},
{
"filetype": [
"png",
"jpeg"
],
"required": false,
"type": "media",
"name": "img_infoscreen"
},
{
"nullable": true,
"name": "price",
"min": 0,
"required": false,
"type": "integer"
},
{
"name": "title_en",
"required_if_not": "title_de",
"nullable": true,
"required": false,
"dependencies": [
"catchphrase_en",
"description_en"
],
"maxlength": 100,
"type": "string"
},
{
"name": "description_en",
"nullable": true,
"required": false,
"type": "string",
"maxlength": 10000
},
{
"name": "time_advertising_end",
"nullable": false,
"later_than": "time_advertising_start",
"required": true,
"type": "datetime"
},
{
"filetype": [
"png",
"jpeg"
],
"required": false,
"type": "media",
"name": "img_poster"
},
{
"name": "show_announce",
"nullable": false,
"default": false,
"required": false,
"type": "boolean"
},
{
"name": "time_advertising_start",
"nullable": false,
"required": true,
"type": "datetime",
"earlier_than": "time_advertising_end"
},
{
"name": "show_website",
"nullable": false,
"default": false,
"required": false,
"type": "boolean"
},
{
"name": "catchphrase_de",
"nullable": true,
"required": false,
"type": "string",
"maxlength": 500
},
{
"required": false,
"type": "objectid",
"name": "_id"
}
],
"label": "Create a Event"
},
"GET": {
"params": [],
"label": "Retrieve all events"
}
},
"/events/{_id}": {
"PATCH": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
},
{
"name": "title_de",
"required_if_not": "title_en",
"nullable": true,
"required": false,
"dependencies": [
"catchphrase_de",
"description_de"
],
"maxlength": 100,
"type": "string"
},
{
"name": "time_register_start",
"nullable": true,
"only_if_not_null": "spots",
"required": false,
"dependencies": [
"time_register_end"
],
"type": "datetime",
"earlier_than": "time_register_end"
},
{
"readonly": true,
"required": false,
"type": "integer",
"name": "signup_count"
},
{
"filetype": [
"png",
"jpeg"
],
"required": false,
"type": "media",
"name": "img_thumbnail"
},
{
"dependencies": [
"time_start"
],
"name": "time_end",
"nullable": true,
"later_than": "time_start",
"required": false,
"type": "datetime"
},
{
"name": "allow_email_signup",
"nullable": false,
"default": false,
"only_if_not_null": "spots",
"required": false,
"type": "boolean"
},
{
"nullable": true,
"dependencies": [
"time_register_start",
"time_register_end"
],
"name": "spots",
"min": 0,
"required": false,
"type": "integer"
},
{
"name": "description_de",
"nullable": true,
"required": false,
"type": "string",
"maxlength": 10000
},
{
"name": "time_register_end",
"nullable": true,
"later_than": "time_register_start",
"required": false,
"dependencies": [
"time_register_start"
],
"type": "datetime",
"only_if_not_null": "spots"
},
{
"filetype": [
"png",
"jpeg"
],
"required": false,
"type": "media",
"name": "img_banner"
},
{
"dependencies": [
"time_end"
],
"name": "time_start",
"nullable": true,
"required": false,
"type": "datetime",
"earlier_than": "time_end"
},
{
"name": "catchphrase_en",
"nullable": true,
"required": false,
"type": "string",
"maxlength": 500
},
{
"name": "priority",
"min": 0,
"default": 5,
"max": 10,
"required": true,
"type": "integer"
},
{
"nullable": true,
"name": "location",
"maxlength": 50,
"required": false,
"type": "string"
},
{
"name": "show_infoscreen",
"nullable": false,
"default": false,
"required": false,
"type": "boolean"
},
{
"name": "additional_fields",
"nullable": true,
"only_if_not_null": "spots",
"required": false,
"type": "json_schema"
},
{
"filetype": [
"png",
"jpeg"
],
"required": false,
"type": "media",
"name": "img_infoscreen"
},
{
"nullable": true,
"name": "price",
"min": 0,
"required": false,
"type": "integer"
},
{
"name": "title_en",
"required_if_not": "title_de",
"nullable": true,
"required": false,
"dependencies": [
"catchphrase_en",
"description_en"
],
"maxlength": 100,
"type": "string"
},
{
"name": "description_en",
"nullable": true,
"required": false,
"type": "string",
"maxlength": 10000
},
{
"name": "time_advertising_end",
"nullable": false,
"later_than": "time_advertising_start",
"required": true,
"type": "datetime"
},
{
"filetype": [
"png",
"jpeg"
],
"required": false,
"type": "media",
"name": "img_poster"
},
{
"name": "show_announce",
"nullable": false,
"default": false,
"required": false,
"type": "boolean"
},
{
"name": "time_advertising_start",
"nullable": false,
"required": true,
"type": "datetime",
"earlier_than": "time_advertising_end"
},
{
"name": "show_website",
"nullable": false,
"default": false,
"required": false,
"type": "boolean"
},
{
"name": "catchphrase_de",
"nullable": true,
"required": false,
"type": "string",
"maxlength": 500
},
{
"required": false,
"type": "objectid",
"name": "_id"
}
],
"label": "Update a Event"
},
"DELETE": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Delete a Event"
},
"GET": {
"params": [
{
"required": true,
"type": "string",
"name": "_id"
}
],
"label": "Retrieve a Event"
}
}
},
"description": {
"fields": {
"additional_fields": "must be provided in form of a JSON-Schema. You can add here fields you want to know from people signing up going further than their email-address",
"price": "Price of the event as Integer in Rappen.",
"allow_email_signup": "If False, only AMIV-Members can sign up for this event",
"spots": "For no limit, set to '0'. If no signup required, set to '-1'. Otherwise just provide an integer."
},
"methods": {
"GET": "You are always allowed, even without session, to view AMIV-Events"
},
"general": "An Event is basically everything happening in the AMIV. All time fields have the format YYYY-MM-DDThh:mmZ, e.g. 2014-12-20T11:50:06Z"
}
}
},
"api_name": "API",
"base": "http:///",
"server_name": null
}
/*
IMPORTS
*/
@font-face {
font-family: DINPro;
font-weight: normal;
src: url(../../res/fonts/DINPro-Light.ttf);
}
@font-face {
font-family: DINPro;
font-weight: bold;
src: url(../../res/fonts/DINPro-Bold.ttf);
}
/*
GENERAL SETUP
*/
* {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 100%;
}
body {
font-family: DINPro;
overflow: hidden;
}
/*
UTILITY CLASSES
*/
.smooth {
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
[contenteditable=true]:empty:before {
content: attr(placeholder);
display: block; /* For Firefox */
}
/*
LOGIN PANEL
*/
.loginPanel {
width: 100%;
height: 100%;
top: 0%;
left: 0%;
display: flex;
align-items: center;
justify-content: center;
position: fixed;
z-index: 20;
//background: rgba(30,30,30,.9);
background: rgba(31, 45, 84, 1);
}
.loginPanel>div {
box-shadow: 0 0 2em #000;
}
.loginPanel .login-logo {
width: 70%;
}
/*
MAIN FRAMEWORK
*/
.wrapper-main {
height: 100%;
width: 100%;
top: 0;
left: 0;
}
.wrapper-main.toggled {
padding-left: 250px;
}
.wrapper-sidebar {
z-index: 10;
left: 250px;
width: 0px;
height: 100%;
margin-left: -250px;
overflow-y: auto;
position: fixed;
background: #222;
color: #fff;
box-shadow: 0 0 1em rgba(0, 0, 0, 0.5);
}
.wrapper-main.toggled .wrapper-sidebar {
width: 250px;
}
.nav-sidebar .navbar ul {
float: none;
display: block;
}
.wrapper-sidebar .navbar li {
float: none;
display: block;
}
@media(min-width:768px) {
.wrapper-main {
padding-left: 250px;
}
.wrapper-main.toggled {
padding-left: 0px;
}
.wrapper-sidebar {
width: 250px;
}
.wrapper-main.toggled .wrapper-sidebar {
width: 0px;
}
}
.wrapper-sidebar ul li a {
color: inherit;
}
.wrapper-sidebar ul li a:hover, .wrapper-sidebar ul li a:active, .wrapper-sidebar ul li a:focus {
color: #000;
}
.wrapper-sidebar>div {
padding: 1em;
}
.wrapper-sidebar .sidebar-logo {
width: 100%;
}
.wrapper-content {
margin-top: -20px;
//height: calc(100vh - 51px);
background: #eee;
width: 100%;
overflow: auto;
}
/*
MAIN NAVBAR
*/
.navbar-main .container-fluid>ul>li {
float: left;
}
/*
LOG BAR
*/
.alertCont {
position: fixed;
z-index: 10000;
left: 50%;
top: 10px;
transform: translateX(-50%);
}
'use strict';
// Library for all tool actions
var tools = {
//Log Function & Utility Vars
alertElems: [],
alertNum: 0,
alertType: {
's': 'alert-success',
'i': 'alert-info',
'w': 'alert-warning',
'e': 'alert-danger'
},
log: function(msg, type, timeout) {
timeout = timeout || 5000;
tools.alertNum++;
$('.alertCont').append('<div id="alertBox-' + tools.alertNum + '" class="alert ' + tools.alertType[type] + ' alert-dismissible" role="alert"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' + msg + '</div>');
tools.alertElems.push(tools.alertNum);
setTimeout(function() {
$('#alertBox-' + tools.alertElems[0]).alert('close');
tools.alertElems.shift();
}, timeout);
console.log(msg);
},
// Modal function
modalFunc: {
init: 0,
},
modalClose: function() {
$('.modalCont').modal('hide');
},
modal: function(attr) {
attr = attr || {};
if (attr.cancel !== undefined && typeof(attr.cancel) == 'function')
tools.modalFunc.cancel = attr.cancel;
if (!tools.modalFunc.init) {
$('.modalCont').on('hide.bs.modal', tools.modalFunc.cancel);
tools.modalFunc.init = 1;
}
$('.modalCont .modal-title').html(attr.head);
$('.modalCont .modal-body').html(attr.body);
$('.modalCont .modal-footer').html('<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>');
var modalBtnId = 0;
for (var curBtn in attr.button) {
if (attr.button[curBtn].type === undefined || attr.button[curBtn].type == '')
attr.button[curBtn].type = 'primary';
$('.modalCont .modal-footer').append('<button type="button" class="btn btn-' + attr.button[curBtn].type + ' modal-btn-' + modalBtnId + '">' + curBtn + '</button>');
if (attr.button[curBtn].callback !== undefined && typeof(attr.button[curBtn].callback) == 'function')
$('.modal-btn-' + modalBtnId).off('click').on('click', attr.button[curBtn].callback);
if (attr.button[curBtn].close === true)
$('.modal-btn-' + modalBtnId).on('click', tools.modalClose);
modalBtnId++;
}
$('.modalCont').modal('show');
},
// Ajax loading gunction and getting the tools
curTool: '',
getTool: function(tool) {
//Setting home if no other tool is selected
if (window.location.hash == '' || window.location.hash == null)
window.location.hash = 'home';
// If tool is specfied, get it
var nextTool = (tool && typeof tool != 'object') ? tool : window.location.hash.slice(1);
if (tools.curTool == nextTool)
return;
tools.curTool = nextTool;
window.location.hash = tools.curTool;
$('#wheel-logo').css('transform', 'rotate(360deg)');
$('#main-content').fadeOut(100, function() {
// Reset Custom menu
tools.ui.menu();
$.ajax({
url: 'tools/' + tools.curTool + '.tool',
dataType: 'html',
error: function() {
tools.log('Tool not found', 'e');
}
}).done(function(data) {
$('#main-content').html(data);
$('#main-content').fadeIn(250, function() {
$('#wheel-logo').css('transform', 'rotate(0deg)');
});
});
});
},
// UI Stuff
ui: {
//Toggle the sidemenu
toggleSideMenu: function() {
$('.wrapper-main').toggleClass('toggled');
},
login: function() {
$('.loginPanel').css({
'top': '-200%'
});
},
logout: function() {
$('.loginPanel').css({
'top': '0%'
});
},
resizeTool: function() {
$('.wrapper-content').height($(window).height() - $('.navbar-main').height());
},
menuId: 0,
menu: function(attr) {
var custMenu = $('.cust-menu');
custMenu.html('');
for (var cur in attr) {
tools.ui.menuId++;
if (attr[cur].link == '' || attr[cur].link === undefined)
attr[cur].link = 'javascript:void(0);';
custMenu.append('<li><a href="' + attr[cur].link + '" id="cust-menu-link-' + tools.ui.menuId + '">' + cur + '</a></li>');
if (typeof(attr[cur].callback) == 'function')
$('#cust-menu-link-' + tools.ui.menuId).on('click', attr[cur].callback);
}
}
},
// Memory to store stuff
memStore: function(type, name, val) {
window[type].setItem(name, val);
},
memGet: function(type, name) {
return window[type].getItem(name);
},
mem: {
local: {
set: function(name, val) {
tools.memStore('localStorage', tools.curTool + name, val);
},
get: function(name) {
return tools.memGet('localStorage', tools.curTool + name);
},
},
session: {
set: function(name, val) {
tools.memStore('sessionStorage', tools.curTool + name, val);
},
get: function(name) {
return tools.memGet('sessionStorage', tools.curTool + name);
},
}
}
}
/*
Initialization of page
*/
//Turning off cache for ajax on dev stage
$.ajaxSetup({
cache: false
});
//Binding tool change whenever the hash is changed
window.onhashchange = tools.getTool;
//Resizing Body when menu changes size and calling it on ready
window.onresize = tools.ui.resizeTool;
// Login function
function loginFunc() {
$('.loginPanel input').attr('readonly', 1);
amivcore.login($('#loginUsername').val(), $('#loginPassword').val(), function(ret) {
if (ret !== true)
tools.log('Wrong Credentials', 'w');
$('.loginPanel input').removeAttr('readonly');
});
}
// When document loaded
$(document).ready(function() {
// Resizing main wrapper-main
tools.ui.resizeTool();
// Binding the buttons
$('.toggleSidebarBtn').click(tools.ui.toggleSideMenu);
$('.loginAction').click(loginFunc);
$('.logoutAction').click(amivcore.logout);
$('.loginPanel').keypress(function(e) {
if (e.which == 13) {
e.preventDefault();
loginFunc();
}
});
});
amivcore.on('ready', function() {
tools.getTool();
});
amivcore.on('login', function() {
tools.ui.login();
});
amivcore.on('logout', function() {
tools.ui.logout();
});
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root /var/www/;
index index.html;
try_files $uri /index.html =404;
}
source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -6,7 +6,10 @@
"scripts": {
"start": "webpack-dev-server --hot --inline",
"build": "webpack -p --config webpack.config.prod.js",
"lint": "eslint src/**"
"build-dev": "webpack -p --config webpack.config.dev.js",
"build-staging": "webpack -p --config webpack.config.staging.js",
"build-local": "webpack -p --config webpack.config.local.js",
"lint": "eslint src/**/*.js src/*.js"
},
"repository": {
"type": "git",
......@@ -14,24 +17,39 @@
},
"author": "Hermann Blum et al",
"dependencies": {
"@material/drawer": "^0.30.0",
"@material/select": "^0.35.1",
"ajv": "^5.5.0",
"amiv-web-ui-components": "git+https://git@gitlab.ethz.ch/amiv/web-ui-components.git#360e65da63f4511db1f6ac56ce103be9254d1d9f",
"axios": "^0.17.1",
"babel": "^6.23.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"compression-webpack-plugin": "^1.0.1",
"file-loader": "^1.1.5",
"mithril": "^1.1.5",
"client-oauth2": "^4.2.0",
"mithril": "^1.1.6",
"mithril-infinite": "^1.2.4",
"polythene-core-css": "^1.2.0",
"polythene-css": "^1.2.0",
"polythene-mithril": "1.2.0",
"querystring": "^0.2.0",
"uglifyjs-webpack-plugin": "^1.0.1",
"webpack": "^3.8.1"
"showdown": "^1.9.0"
},
"devDependencies": {
"eslint": "^4.10.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-import": "^2.8.0",
"webpack-dev-server": "^2.9.3"
"@babel/cli": "^7.2.3",
"@babel/core": "^7.2.2",
"@babel/plugin-proposal-object-rest-spread": "^7.2.0",
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
"@babel/preset-env": "^7.2.3",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.4",
"compression-webpack-plugin": "^2.0.0",
"css-loader": "^2.1.0",
"eslint": "^5.16.0",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-import-resolver-webpack": "^0.10.1",
"eslint-loader": "^3.0.0",
"eslint-plugin-import": "^2.14.0",
"file-loader": "^3.0.1",
"style-loader": "^0.23.1",
"webpack": "^4.28.3",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.14"
}
}
res/bg/beer.jpg

344 KiB

res/bg/cab-1440.jpg

366 KiB