html structure
41
.gitignore
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules
|
||||
jspm_packages
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
@@ -1,2 +1,5 @@
|
||||
# openworktime
|
||||
time traking web app for work projects [frontend: angular + materializecss. backend: nodejs+express+mongodb]
|
||||
|
||||
|
||||

|
||||
|
||||
9
config.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
|
||||
/*'secret': process.env.SECRET,
|
||||
'database': process.env.MONGO_DSN,*/
|
||||
'secret': 'secretfortoken',
|
||||
'database': 'mongodb://localhost/comunalcar',
|
||||
"port" : process.env.PORT || 3000
|
||||
|
||||
};
|
||||
102
controllers/travelController.js
Normal file
@@ -0,0 +1,102 @@
|
||||
//File: controllers/travelController.js
|
||||
var mongoose = require('mongoose');
|
||||
var travelModel = mongoose.model('travelModel');
|
||||
|
||||
var userModel = mongoose.model('userModel');
|
||||
|
||||
//GET
|
||||
exports.findAllTravels = function(req, res) {
|
||||
|
||||
travelModel.find(function(err, travels) {
|
||||
if(err) res.send(500, err.message);
|
||||
|
||||
res.status(200).jsonp(travels);
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
//GET
|
||||
exports.findById = function(req, res) {
|
||||
travelModel.findById(req.params.id, function(err, travel) {
|
||||
if(err) return res.send(500, err.message);
|
||||
|
||||
console.log('GET /travel/' + req.params.id);
|
||||
res.status(200).jsonp(travel);
|
||||
});
|
||||
};
|
||||
|
||||
exports.findAllTravelsFromUsername = function(req, res) {
|
||||
travelModel.find({
|
||||
owner: req.params.username
|
||||
}, function(err, travels) {
|
||||
|
||||
if (err) throw err;
|
||||
|
||||
if (!travels) {
|
||||
res.json({ success: false, message: 'no travels for user' });
|
||||
} else if (travels) {
|
||||
console.log(travels);
|
||||
// return the information including token as JSON
|
||||
res.jsonp(travels);
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
exports.addTravel = function(req, res) {
|
||||
console.log('POST new travel, title: ' + req.body.title);
|
||||
var travel = new travelModel({
|
||||
title: req.body.title,
|
||||
description: req.body.description,
|
||||
owner: req.body.owner,
|
||||
from: req.body.from,
|
||||
to: req.body.to,
|
||||
date: req.body.date,
|
||||
periodic: req.body.periodic,
|
||||
generateddate: req.body.generateddate,
|
||||
seats: req.body.seats,
|
||||
package: req.body.package,
|
||||
icon: req.body.icon,
|
||||
phone: req.body.phone,
|
||||
telegram: req.body.telegram,
|
||||
collectivized: req.body.collectivized,
|
||||
modality: req.body.modality
|
||||
});
|
||||
|
||||
travel.save(function(err, travel) {
|
||||
if(err) return res.send(500, err.message);
|
||||
res.status(200).jsonp(travel);
|
||||
});
|
||||
};
|
||||
|
||||
//PUT
|
||||
exports.updateTravel = function(req, res) {
|
||||
ActivityModel.findById(req.params.id, function(err, tvshow) {
|
||||
tvshow.title = req.body.petId;
|
||||
tvshow.year = req.body.year;
|
||||
tvshow.country = req.body.country;
|
||||
tvshow.poster = req.body.poster;
|
||||
tvshow.seasons = req.body.seasons;
|
||||
tvshow.genre = req.body.genre;
|
||||
tvshow.summary = req.body.summary;
|
||||
|
||||
tvshow.save(function(err) {
|
||||
if(err) return res.send(500, err.message);
|
||||
res.status(200).jsonp(tvshow);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//DELETE
|
||||
exports.deleteTravel = function(req, res) {
|
||||
ActivityModel.findById(req.params.id, function(err, activity) {
|
||||
activity.remove(function(err) {
|
||||
if(err) return res.send(500, err.message);
|
||||
res.status(200).jsonp(req.params.id);
|
||||
console.log('DELETE /activities/' + req.params.id);
|
||||
})
|
||||
});
|
||||
};
|
||||
154
controllers/userController.js
Normal file
@@ -0,0 +1,154 @@
|
||||
//File: controllers/userController.js
|
||||
var mongoose = require('mongoose');
|
||||
var userModel = mongoose.model('userModel');
|
||||
|
||||
/* */
|
||||
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
|
||||
var express = require("express");
|
||||
var app = express();
|
||||
var config = require('../config'); // get our config file
|
||||
app.set('superSecret', config.secret); // secret variable
|
||||
/* */
|
||||
|
||||
//GET - Return all Users in the DB
|
||||
exports.findAllUsers = function(req, res) {
|
||||
userModel.find(function(err, users) {
|
||||
if(err) res.send(500, err.message);
|
||||
|
||||
//password deletion
|
||||
for(var i=0; i<users.length; i++)
|
||||
{
|
||||
users[i].password="";
|
||||
console.log(users[i].password);
|
||||
}
|
||||
|
||||
console.log('GET /users');
|
||||
res.status(200).jsonp(users);
|
||||
});
|
||||
};
|
||||
|
||||
//GET - Return a User with specified ID
|
||||
exports.findById = function(req, res) {
|
||||
userModel.findById(req.params.id, function(err, user) {
|
||||
if(err) return res.send(500, err.message);
|
||||
|
||||
console.log('GET /users/' + req.params.id);
|
||||
//password deletion
|
||||
|
||||
user.password="";
|
||||
res.status(200).jsonp(user);
|
||||
});
|
||||
};
|
||||
|
||||
exports.findUserByUsername = function(req, res) {
|
||||
userModel.find({
|
||||
username: req.params.username
|
||||
}, function(err, user) {
|
||||
|
||||
if (err) throw err;
|
||||
|
||||
if (!user) {
|
||||
res.json({ success: false, message: 'no user found' });
|
||||
} else if (user) {
|
||||
// return the information including token as JSON
|
||||
//res.jsonp(user);
|
||||
user.password="";
|
||||
console.log(user);
|
||||
res.status(200).jsonp(user[0]);
|
||||
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
//POST - Insert a new User in the DB
|
||||
exports.addUser = function(req, res) {
|
||||
console.log('POST new user, name: ' + req.body.username);
|
||||
//console.log(req.body);
|
||||
|
||||
var user = new userModel({
|
||||
username: req.body.username,
|
||||
password: req.body.password,
|
||||
description: req.body.description,
|
||||
avatar: req.body.avatar,
|
||||
mail: req.body.mail,
|
||||
phone: req.body.phone,
|
||||
telegram: req.body.telegram
|
||||
});
|
||||
|
||||
user.save(function(err, user) {
|
||||
if(err) return res.send(500, err.message);
|
||||
res.status(200).jsonp(user);
|
||||
});
|
||||
};
|
||||
|
||||
//PUT - Update a user already exists
|
||||
exports.updateUser = function(req, res) {
|
||||
userModel.findById(req.params.id, function(err, user) {
|
||||
user.username = req.body.username;
|
||||
user.password = req.body.password;
|
||||
user.description = req.body.description;
|
||||
user.avatar = req.body.avatar;
|
||||
user.mail = req.body.mail;
|
||||
user.phone = req.body.phone;
|
||||
user.telegram = req.body.telegram;
|
||||
|
||||
user.save(function(err) {
|
||||
if(err) return res.send(500, err.message);
|
||||
user.password="";
|
||||
res.status(200).jsonp(user);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//DELETE - Delete a user with specified ID
|
||||
exports.deleteUser = function(req, res) {
|
||||
userModel.findById(req.params.id, function(err, user) {
|
||||
user.remove(function(err) {
|
||||
if(err) return res.send(500, err.message);
|
||||
res.status(200).jsonp(req.params.id);
|
||||
console.log('DELETE /users/' + req.params.id);
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
//POST - auth user
|
||||
exports.login = function(req, res) {
|
||||
// find the user
|
||||
userModel.findOne({
|
||||
username: req.body.username
|
||||
}, function(err, user) {
|
||||
|
||||
if (err) throw err;
|
||||
|
||||
if (!user) {
|
||||
res.json({ success: false, message: 'Authentication failed. User not found.' });
|
||||
} else if (user) {
|
||||
|
||||
// check if password matches
|
||||
if (user.password != req.body.password) {
|
||||
res.json({ success: false, message: 'Authentication failed. Wrong password.' });
|
||||
} else {
|
||||
|
||||
// if user is found and password is right
|
||||
// create a token
|
||||
var token = jwt.sign(user, app.get('superSecret'), {
|
||||
//expiresInMinutes: 1440 // expires in 24 hours
|
||||
expiresIn: '60m'
|
||||
});
|
||||
console.log(user);
|
||||
// return the information including token as JSON
|
||||
res.json({
|
||||
success: true,
|
||||
message: 'Enjoy your token!',
|
||||
token: token,
|
||||
avatar: user.avatar
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
25
models/travelModel.js
Normal file
@@ -0,0 +1,25 @@
|
||||
var mongoose = require('mongoose'),
|
||||
Schema = mongoose.Schema;
|
||||
|
||||
|
||||
var travelSchema = new Schema({
|
||||
title: { type: String },
|
||||
description: { type: String },
|
||||
owner: { type: String },
|
||||
from: { type: String },
|
||||
to: { type: String },
|
||||
date: { type: Date },
|
||||
periodic: { type: Boolean },
|
||||
generateddate: { type: Date },
|
||||
seats: { type: Number },
|
||||
package: { type: Boolean },
|
||||
icon: { type: String },
|
||||
phone: { type: Number },
|
||||
telegram: { type: String },
|
||||
collectivized: { type: Boolean },
|
||||
modality: { type: String } //if is an offering travel or asking for travel
|
||||
})
|
||||
module.exports = mongoose.model('travelModel', travelSchema);
|
||||
|
||||
|
||||
//modality can be: offering, asking, package
|
||||
14
models/userModel.js
Normal file
@@ -0,0 +1,14 @@
|
||||
var mongoose = require('mongoose'),
|
||||
Schema = mongoose.Schema;
|
||||
|
||||
|
||||
var userSchema = new Schema({
|
||||
username: { type: String },
|
||||
password: { type: String },
|
||||
description: { type: String },
|
||||
avatar: { type: String },
|
||||
mail: { type: String },
|
||||
phone: { type: String },
|
||||
telegram: { type: String }
|
||||
})
|
||||
module.exports = mongoose.model('userModel', userSchema);
|
||||
17
package.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "openworktime",
|
||||
"version": "0.0.1",
|
||||
"description": "openworktime, time traking app",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"body-parser": "latest",
|
||||
"express": "^4.7.1",
|
||||
"jsonwebtoken": "latest",
|
||||
"method-override": "^2.1.2",
|
||||
"mongoose": "latest",
|
||||
"morgan": "latest"
|
||||
}
|
||||
}
|
||||
BIN
screenshot2.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
126
server.js
Executable file
@@ -0,0 +1,126 @@
|
||||
var express = require("express"),
|
||||
app = express(),
|
||||
bodyParser = require("body-parser"),
|
||||
methodOverride = require("method-override"),
|
||||
mongoose = require('mongoose');
|
||||
|
||||
|
||||
var morgan = require('morgan');
|
||||
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
|
||||
var config = require('./config'); // get our config file
|
||||
|
||||
mongoose.Promise = global.Promise;
|
||||
// Connection to DB
|
||||
mongoose.connect(config.database, function(err, res) {
|
||||
if(err) throw err;
|
||||
console.log('Connected to Database');
|
||||
});
|
||||
app.set('superSecret', config.secret); // secret variable
|
||||
|
||||
// Middlewares
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
app.use(bodyParser.json());
|
||||
app.use(methodOverride());
|
||||
|
||||
// use morgan to log requests to the console
|
||||
app.use(morgan('dev'));
|
||||
|
||||
// Import Models and controllers
|
||||
var userMdl = require('./models/userModel')(app, mongoose);
|
||||
var userCtrl = require('./controllers/userController');
|
||||
|
||||
var travelMdl = require('./models/travelModel')(app, mongoose);
|
||||
var travelCtrl = require('./controllers/travelController');
|
||||
|
||||
/*// Example Route
|
||||
var router = express.Router();
|
||||
router.get('/', function(req, res) {
|
||||
res.send("Hello world!");
|
||||
});
|
||||
app.use(router);*/
|
||||
app.use(express.static(__dirname + '/web'));
|
||||
|
||||
|
||||
//CORS
|
||||
app.use(function(req, res, next) {
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
|
||||
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Access-Token");
|
||||
next();
|
||||
});
|
||||
|
||||
// API routes ------------------------------------------------------
|
||||
var apiRoutes = express.Router();
|
||||
|
||||
apiRoutes.route('/users')
|
||||
.get(userCtrl.findAllUsers)
|
||||
.post(userCtrl.addUser);
|
||||
apiRoutes.route('/users/:id')
|
||||
.get(userCtrl.findById);
|
||||
apiRoutes.route('/users/byusername/:username')
|
||||
.get(userCtrl.findUserByUsername);
|
||||
apiRoutes.route('/travels/user/:username')
|
||||
.get(travelCtrl.findAllTravelsFromUsername);
|
||||
|
||||
apiRoutes.route('/auth')
|
||||
.post(userCtrl.login);
|
||||
|
||||
apiRoutes.route('/travels')
|
||||
.get(travelCtrl.findAllTravels);
|
||||
|
||||
apiRoutes.route('/travels/:id')
|
||||
.get(travelCtrl.findById)
|
||||
|
||||
// OJU AQUÏ TREC la verificació de token temporalment, per fer les proves des de l'app
|
||||
// route middleware to verify a token
|
||||
apiRoutes.use(function(req, res, next) {
|
||||
|
||||
// check header or url parameters or post parameters for token
|
||||
var token = req.body.token || req.query.token || req.headers['x-access-token'];
|
||||
|
||||
// decode token
|
||||
if (token) {
|
||||
|
||||
// verifies secret and checks exp
|
||||
jwt.verify(token, app.get('superSecret'), function(err, decoded) {
|
||||
if (err) {
|
||||
return res.json({ success: false, message: 'Failed to authenticate token.' });
|
||||
} else {
|
||||
// if everything is good, save to request for use in other routes
|
||||
req.decoded = decoded;
|
||||
//console.log("decoded " + decoded);
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
// if there is no token
|
||||
// return an error
|
||||
return res.status(201).send({
|
||||
success: false,
|
||||
message: 'No token provided.'
|
||||
});
|
||||
|
||||
}
|
||||
}); //fi verificació de token
|
||||
|
||||
|
||||
apiRoutes.route('/users/:id')
|
||||
.put(userCtrl.updateUser)
|
||||
.delete(userCtrl.deleteUser);
|
||||
|
||||
apiRoutes.route('/travels')
|
||||
.post(travelCtrl.addTravel);
|
||||
|
||||
apiRoutes.route('/travels/:id')
|
||||
.put(travelCtrl.updateTravel)
|
||||
.delete(travelCtrl.deleteTravel);
|
||||
|
||||
app.use('/api', apiRoutes);
|
||||
// end of API routes -------------------------------------
|
||||
|
||||
// Start server
|
||||
app.listen(config.port, function() {
|
||||
console.log("Node server running on http://localhost:3000");
|
||||
});
|
||||
29
webapp/controllers.js
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
angular.module('workApp', [])
|
||||
.controller('workController', function(
|
||||
$scope, $http
|
||||
) {
|
||||
$scope.username="";
|
||||
|
||||
if(localStorage.getItem('w_username')){
|
||||
$scope.username=localStorage.getItem('w_username');
|
||||
}
|
||||
|
||||
$scope.onNew = function(){
|
||||
|
||||
};
|
||||
|
||||
$scope.openCode = function(){
|
||||
toastr.info("Visiting code");
|
||||
var urlCode="https://github.com/idoctnef/openworktime";
|
||||
if(typeof process !== 'undefined'){
|
||||
console.log(process.versions['electron']);
|
||||
const {shell} = require('electron');
|
||||
|
||||
shell.openExternal(urlCode);
|
||||
}else{
|
||||
window.open(urlCode);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
8461
webapp/css/materialize.css
vendored
Normal file
16
webapp/css/materialize.min.css
vendored
Normal file
BIN
webapp/fonts/2fcrYFNaTjcS6g4U3t-Y5ZjZjT5FdEJ140U2DJYC3mY.woff2
Normal file
23
webapp/fonts/icons.css
Normal file
@@ -0,0 +1,23 @@
|
||||
/* fallback */
|
||||
@font-face {
|
||||
font-family: 'Material Icons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Material Icons'), local('MaterialIcons-Regular'), url(2fcrYFNaTjcS6g4U3t-Y5ZjZjT5FdEJ140U2DJYC3mY.woff2) format('woff2');
|
||||
}
|
||||
|
||||
.material-icons {
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px;
|
||||
line-height: 1;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
word-wrap: normal;
|
||||
direction: ltr;
|
||||
-moz-font-feature-settings: 'liga';
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
BIN
webapp/fonts/roboto/Roboto-Bold.eot
Normal file
BIN
webapp/fonts/roboto/Roboto-Bold.ttf
Normal file
BIN
webapp/fonts/roboto/Roboto-Bold.woff
Normal file
BIN
webapp/fonts/roboto/Roboto-Bold.woff2
Normal file
BIN
webapp/fonts/roboto/Roboto-Light.eot
Normal file
BIN
webapp/fonts/roboto/Roboto-Light.ttf
Normal file
BIN
webapp/fonts/roboto/Roboto-Light.woff
Normal file
BIN
webapp/fonts/roboto/Roboto-Light.woff2
Normal file
BIN
webapp/fonts/roboto/Roboto-Medium.eot
Normal file
BIN
webapp/fonts/roboto/Roboto-Medium.ttf
Normal file
BIN
webapp/fonts/roboto/Roboto-Medium.woff
Normal file
BIN
webapp/fonts/roboto/Roboto-Medium.woff2
Normal file
BIN
webapp/fonts/roboto/Roboto-Regular.eot
Normal file
BIN
webapp/fonts/roboto/Roboto-Regular.ttf
Normal file
BIN
webapp/fonts/roboto/Roboto-Regular.woff
Normal file
BIN
webapp/fonts/roboto/Roboto-Regular.woff2
Normal file
BIN
webapp/fonts/roboto/Roboto-Thin.eot
Normal file
BIN
webapp/fonts/roboto/Roboto-Thin.ttf
Normal file
BIN
webapp/fonts/roboto/Roboto-Thin.woff
Normal file
BIN
webapp/fonts/roboto/Roboto-Thin.woff2
Normal file
BIN
webapp/img/avatars/anteater.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
webapp/img/avatars/bat.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
webapp/img/avatars/beetle.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
webapp/img/avatars/bulldog.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
webapp/img/avatars/butterfly.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/avatars/camel.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
webapp/img/avatars/cat.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
webapp/img/avatars/chameleon.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
webapp/img/avatars/clown-fish.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
webapp/img/avatars/cobra.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
webapp/img/avatars/cow.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
webapp/img/avatars/crab.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
webapp/img/avatars/crocodile.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
webapp/img/avatars/duck.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
webapp/img/avatars/elephant.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/avatars/frog.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
webapp/img/avatars/giraffe.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
webapp/img/avatars/hen.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
webapp/img/avatars/hippopotamus.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/avatars/kangaroo.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/avatars/lion.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
webapp/img/avatars/llama.png
Normal file
|
After Width: | Height: | Size: 8.4 KiB |
BIN
webapp/img/avatars/macaw.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
webapp/img/avatars/monkey.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
webapp/img/avatars/moose.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/avatars/mouse.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
webapp/img/avatars/octopus.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
webapp/img/avatars/ostrich.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
webapp/img/avatars/owl.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
webapp/img/avatars/panda.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
webapp/img/avatars/pelican.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/avatars/penguin.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
webapp/img/avatars/pig.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
webapp/img/avatars/rabbit.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
webapp/img/avatars/racoon.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
webapp/img/avatars/ray.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
webapp/img/avatars/rhinoceros.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
webapp/img/avatars/sea-cow.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
webapp/img/avatars/shark.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
webapp/img/avatars/sheep.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
webapp/img/avatars/siberian-husky.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
webapp/img/avatars/sloth.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
webapp/img/avatars/snake.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/avatars/spider.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
webapp/img/avatars/squirrel.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
webapp/img/avatars/swan.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
webapp/img/avatars/tiger.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
webapp/img/avatars/toucan.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/avatars/turtle.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
webapp/img/avatars/whale.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
webapp/img/webicons/ai.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/webicons/allocation-1.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/webicons/allocation-2.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
webapp/img/webicons/allocation.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
webapp/img/webicons/attach.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
webapp/img/webicons/avatar-1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
webapp/img/webicons/avatar.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
webapp/img/webicons/background-1.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
webapp/img/webicons/background.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
webapp/img/webicons/browser-1.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
webapp/img/webicons/browser-2.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
webapp/img/webicons/browser-3.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
webapp/img/webicons/browser-4.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
webapp/img/webicons/browser-5.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
webapp/img/webicons/browser-6.png
Normal file
|
After Width: | Height: | Size: 18 KiB |