v0.3.0 finalizations
parent
0dee8b8c9b
commit
8d3417e6a5
|
@ -0,0 +1 @@
|
|||
Subproject commit 3cfe0ed9c01c16d10db7dd96701757ea8ee0a1d2
|
|
@ -1,4 +1,5 @@
|
|||
var passport = require('passport'),
|
||||
crypto = require('crypto'),
|
||||
secret = require('./secrets.js'),
|
||||
User = require('./models/user.js'),
|
||||
GoogleStrategy = require('passport-google-oauth2').Strategy,
|
||||
|
@ -30,12 +31,19 @@ passport.use(new GoogleStrategy({
|
|||
else {
|
||||
user.googleID = profile.id;
|
||||
user.lastLogin = Date.now();
|
||||
user.save(function(err) {
|
||||
if (err) {
|
||||
console.log('Error saving new (invited) user '+err);
|
||||
var failMessage = 'Something went wrong finding your session. Would you like to <a href="/bug">report this error</a>?';
|
||||
} else { successMessage = 'Your account has been created. Next maybe you should download the <a href="/android">android app</a>. ' }
|
||||
done(null, user, { success:successMessage, failure:failMessage });
|
||||
crypto.randomBytes(32, function(err,buf) {
|
||||
if (err) {console.log('Unable to get random bytes:',err);}
|
||||
if (!buf) {console.log('Unable to get random buffer');}
|
||||
else {
|
||||
user.sk32 = buf.toString('hex');
|
||||
user.save(function(err) {
|
||||
if (err) {
|
||||
console.log('Error saving new (invited) user '+err);
|
||||
var failMessage = 'Something went wrong finding your session. Would you like to <a href="/bug">report this error</a>?';
|
||||
} else { successMessage = 'Your account has been created. Next maybe you should download the <a href="/android">android app</a>. ' }
|
||||
done(null, user, { success:successMessage, failure:failMessage });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,31 +1,33 @@
|
|||
secret = require('./secrets.js');
|
||||
|
||||
module.exports = {
|
||||
|
||||
throwErr: function(req,err){
|
||||
console.log('Middleware error:'+err+'\nfor request:\n'+req);
|
||||
if (secret.env==='production') {
|
||||
req.flash('error', 'An error occured. <br>Would you like to <a href="/bug">report it</a>?');
|
||||
req.flash('error-message',err);
|
||||
} else {
|
||||
req.flash('error',err);
|
||||
req.flash('error-message',err);
|
||||
}
|
||||
},
|
||||
|
||||
ensureAuth: function(req,res,next){
|
||||
if (req.isAuthenticated()) { return next(); }
|
||||
else {
|
||||
req.session.returnTo = req.path;
|
||||
console.log('mw.ensureAuth: Going to redirect to '+req.path+' after login.'); // TODO: Correct next path
|
||||
req.flash('error', 'You must be signed in to do that. <a href="/login">Click here to log in</a>. ');
|
||||
res.redirect('/');
|
||||
}
|
||||
},
|
||||
|
||||
ensureAdmin: function(req,res,next){
|
||||
if (req.user.isAdmin) { return next(); }
|
||||
else { res.sendStatus(401); }
|
||||
var throwErr = function(req,err){
|
||||
console.log('Middleware error:'+err+'\nfor request:\n'+req);
|
||||
if (secret.env==='production') {
|
||||
req.flash('error', 'An error occured. <br>Would you like to <a href="/bug">report it</a>?');
|
||||
req.flash('error-message',err);
|
||||
} else {
|
||||
req.flash('error',err);
|
||||
req.flash('error-message',err);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var ensureAuth = function(req,res,next){
|
||||
if (req.isAuthenticated()) { return next(); }
|
||||
else {
|
||||
// req.session.returnTo = req.path;
|
||||
// console.log('mw.ensureAuth: Going to redirect to '+req.path+' after login.'); // TODO: Correct next path
|
||||
req.flash('error', 'You must be signed in to do that. <a href="/login">Click here to log in</a>. ');
|
||||
res.redirect(req.path);
|
||||
}
|
||||
};
|
||||
|
||||
var ensureAdmin = function(req,res,next){
|
||||
if (req.isAuthenticated()&&req.user.isAdmin) { return next(); }
|
||||
else { res.sendStatus(401); }
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
throwErr,
|
||||
ensureAuth,
|
||||
ensureAdmin
|
||||
};
|
|
@ -26,5 +26,6 @@ module.exports = mongoose.model('User', {
|
|||
dir: Number,
|
||||
alt: Number,
|
||||
spd: Number
|
||||
}
|
||||
},
|
||||
sk32: {type:String, required:true, unique:true}
|
||||
});
|
||||
|
|
|
@ -1,11 +1,23 @@
|
|||
var router = require('express').Router(),
|
||||
fs= require('fs'),
|
||||
mw = require('../middleware.js'),
|
||||
mail = require('../mail.js'),
|
||||
User = require('../models/user.js'),
|
||||
Request = require('../models/request.js');
|
||||
|
||||
router.route('/')
|
||||
.all(mw.ensureAdmin, function(req,res,next){
|
||||
fs.readFile(__dirname+'/../../adminMongo/config/app.json', 'utf-8', function(err,data) {
|
||||
if (err) {console.log('Couldn\'t find adminMongo\'s config/app.json due to an error:',err);}
|
||||
if (!data) {console.log('Couldn\'t find adminMongo\'s config/app.json');}
|
||||
else {
|
||||
res.redirect( req.protocol +'://'+ req.get('host') +':'+ JSON.parse(data).app['port'] +'/Local/tracman' );
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.route('/requests')
|
||||
.all([mw.ensureAuth, mw.ensureAdmin], function(req,res,next){
|
||||
.all(mw.ensureAdmin, function(req,res,next){
|
||||
next();
|
||||
}).get(function(req,res){
|
||||
User.findById(req.session.passport.user, function(err, user){
|
||||
|
@ -45,7 +57,7 @@ router.route('/requests')
|
|||
});
|
||||
|
||||
router.route('/users')
|
||||
.all([mw.ensureAuth, mw.ensureAdmin], function(req,res,next) {
|
||||
.all(mw.ensureAdmin, function(req,res,next) {
|
||||
next();
|
||||
}).get(function(req,res){
|
||||
User.findById(req.session.passport.user, function(err, user){
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
var router = require('express').Router(),
|
||||
mail = require('../mail.js'),
|
||||
mw = require('../middleware.js');
|
||||
|
||||
router.route('/suggestion')
|
||||
.get(function(req,res){
|
||||
res.redirect('https://productpains.com/product/tracman');
|
||||
// res.render('suggestion.html', {user:req.user});
|
||||
}).post(function(req,res){
|
||||
mail.sendSuggestion({
|
||||
name: (req.body.name)?req.body.name:req.user.name,
|
||||
email: (req.body.email)?req.body.email:req.user.email,
|
||||
suggestion: req.body.suggestion
|
||||
}, function (err, raw) {
|
||||
if (err){ mw.throwErr(req,err); }
|
||||
else { req.flash('success','Thanks for the suggestion! '); }
|
||||
res.redirect('/map');
|
||||
});
|
||||
});
|
||||
|
||||
router.route('/bug')
|
||||
.all(mw.ensureAuth, function(req,res,next){
|
||||
next();
|
||||
}).get(function(req,res){
|
||||
res.render('bug.html', {
|
||||
user: req.user,
|
||||
errorMessage: req.flash('error-message')
|
||||
});
|
||||
}).post(function(req,res){
|
||||
mail.sendBugReport({
|
||||
source: (req.query.source)?req.body.name:'web',
|
||||
name: (req.body.name)?req.body.name:req.user.name,
|
||||
email: (req.body.email)?req.body.email:req.user.email,
|
||||
errorMessage: req.body.errorMessage,
|
||||
recreation: req.body.recreation,
|
||||
bug: req.body.bug
|
||||
}, function (err, raw) {
|
||||
if (err){ mw.throwErr(req,err); }
|
||||
else { req.flash('success','Thanks for the report! '); }
|
||||
res.redirect('/map');
|
||||
});
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -13,7 +13,7 @@ router.route('/')
|
|||
// Get user
|
||||
User.findById(req.session.passport.user, function(err, user){
|
||||
if (err){ mw.throwErr(req,err); }
|
||||
if (!user){ next(); }
|
||||
if (!user){ console.log(req.session.passport); next(); }
|
||||
// If user found:
|
||||
else {
|
||||
// Open index
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
var router = require('express').Router(),
|
||||
mw = require('../middleware.js'),
|
||||
secret = require('../secrets.js'),
|
||||
slug = require('slug'),
|
||||
User = require('../models/user.js');
|
||||
|
||||
// Show map
|
||||
|
@ -42,7 +43,7 @@ router.get('/:slug?', function(req,res,next){
|
|||
if (mapuser==''&&user=='') {
|
||||
res.redirect('/');
|
||||
} else {
|
||||
if (mapuser==''&&user!='') { mapuser = user; }
|
||||
if (user!=''&&mapuser=='') { mapuser = user; }
|
||||
res.render('map.html', {
|
||||
api: secret.mapAPI,
|
||||
mapuser: mapuser,
|
||||
|
@ -56,6 +57,26 @@ router.get('/:slug?', function(req,res,next){
|
|||
|
||||
});
|
||||
|
||||
router.post('/:slug?', mw.ensureAuth, function(req,res,next){
|
||||
// Set new user settings
|
||||
User.findByIdAndUpdate(req.session.passport.user, {$set:{name: req.body.name,
|
||||
slug: slug(req.body.slug),
|
||||
settings: {
|
||||
units: req.body.units,
|
||||
defaultMap: req.body.map,
|
||||
defaultZoom: req.body.zoom,
|
||||
showSpeed: (req.body.showSpeed)?true:false,
|
||||
showAlt: (req.body.showAlt)?true:false,
|
||||
showStreetview: (req.body.showStreet)?true:false
|
||||
}
|
||||
}}, function(err, user){
|
||||
if (err) { console.log('Error updating user settings:',err); mw.throwErr(req,err); }
|
||||
else { req.flash('success', 'Settings updated. '); }
|
||||
res.redirect('/map#');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Redirect /id/ to /slug/
|
||||
router.get('/id/:id', function(req,res,next){
|
||||
User.findById(req.params.id, function(err, user){
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"main": "server.js",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.15.0",
|
||||
"browserify": "^13.0.1",
|
||||
"connect-flash": "^0.1.1",
|
||||
"cookie-parser": "^1.4.1",
|
||||
"email-templates": "^2.1.0",
|
||||
|
@ -15,6 +16,7 @@
|
|||
"moment": "^2.12.0",
|
||||
"mongodb": "^2.1.4",
|
||||
"mongoose": "^4.3.5",
|
||||
"node-jose": "^0.8.0",
|
||||
"nunjucks": "^2.3.0",
|
||||
"passport": "^0.3.2",
|
||||
"passport-google-id-token": "^0.4.0",
|
||||
|
|
68
server.js
68
server.js
|
@ -11,6 +11,7 @@
|
|||
User = require('./config/models/user.js'),
|
||||
app = express(),
|
||||
http = require('http').Server(app),
|
||||
// mongo_express = require('mongo-express/lib/middleware'),
|
||||
io = require('socket.io')(http);
|
||||
}
|
||||
|
||||
|
@ -102,6 +103,7 @@
|
|||
}
|
||||
|
||||
/* RUNTIME */ {
|
||||
|
||||
// Check for tracking users
|
||||
function checkForUsers(room) {
|
||||
if (room) {
|
||||
|
@ -118,46 +120,68 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Websockets
|
||||
io.on('connection', function(socket) {
|
||||
// Websockets
|
||||
io.on('connection', function(sock) {
|
||||
|
||||
socket.on('room', function(room) {
|
||||
socket.join(room);
|
||||
// Set room to map user ID
|
||||
sock.on('room', function(room) {
|
||||
sock.join(room);
|
||||
if (room.slice(0,4)!='app-'){
|
||||
// External user
|
||||
User.findById({_id:room}, function(err, user) {
|
||||
if (err) { console.log('Sockets error finding tracked user of room '+room+'\n'+err); }
|
||||
if (user) {
|
||||
io.to('app-'+room).emit('activate','true'); }
|
||||
});
|
||||
} else {
|
||||
} else { // Sets location
|
||||
checkForUsers(room.slice(4));
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('app', function(loc){
|
||||
// Recieving beacon
|
||||
sock.on('app', function(loc){
|
||||
loc.time = Date.now();
|
||||
io.to(loc.usr).emit('trac', loc);
|
||||
User.findByIdAndUpdate(loc.usr, {last:{
|
||||
lat: parseFloat(loc.lat),
|
||||
lon: parseFloat(loc.lon),
|
||||
dir: parseFloat(loc.dir||0),
|
||||
spd: parseFloat(loc.spd||0),
|
||||
time: Date.now()
|
||||
}}, function(err, user) {
|
||||
if (err) { console.log('Could not update last location of user '+loc.user+'\n'+err); }
|
||||
if (!user) { console.log("No user found: "+loc.user); }
|
||||
// TODO: Fix this error always being thrown with loc.user = undefined
|
||||
});
|
||||
|
||||
// Check for sk32 token
|
||||
if (loc.tok) {
|
||||
// Get loc.usr
|
||||
User.findById(loc.usr, function(err, user) {
|
||||
if (err) { console.log('Error finding user:',err); }
|
||||
if (!user) { console.log('User not found'); }
|
||||
else {
|
||||
// Confirm sk32 token
|
||||
if (loc.tok!=user.sk32) { console.log('loc.tok!=user.sk32 || ',loc.tok,'!=',user.sk32); }
|
||||
else {
|
||||
// Broadcast location to spectators
|
||||
io.to(loc.usr).emit('trac', loc);
|
||||
// Echo broadcast to transmittors
|
||||
io.to('app-'+loc.usr).emit('trac', loc);
|
||||
// Save in db as last seen
|
||||
user.last = {
|
||||
lat: parseFloat(loc.lat),
|
||||
lon: parseFloat(loc.lon),
|
||||
dir: parseFloat(loc.dir||0),
|
||||
spd: parseFloat(loc.spd||0),
|
||||
time: loc.time
|
||||
};
|
||||
user.save(function(err) {
|
||||
if (err) { console.log('Error saving user last location:'+loc.user+'\n'+err); }
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.onclose = function(reason){
|
||||
|
||||
// Shutdown (check for users)
|
||||
sock.onclose = function(reason){
|
||||
var closedroom = Object.keys(
|
||||
socket.adapter.sids[socket.id]).slice(1)[0];
|
||||
sock.adapter.sids[sock.id]).slice(1)[0];
|
||||
setTimeout(function() {
|
||||
checkForUsers(closedroom);
|
||||
}, 3000);
|
||||
Object.getPrototypeOf(this).onclose.call(this,reason);
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
var speakeasy = require('speakeasy');
|
||||
var User = require('./config/models/user.js');
|
||||
|
||||
User.update(
|
||||
{isPro:false},
|
||||
{sk32: speakeasy.generateSecret({length: 20}).base32},
|
||||
{ multi: true },
|
||||
function(err, num){
|
||||
if (err) {console.log(err);}
|
||||
else {console.log(num,'updated');}
|
||||
}
|
||||
);
|
|
@ -0,0 +1,3 @@
|
|||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
|
||||
},{}]},{},[1]);
|
|
@ -1,6 +1,21 @@
|
|||
$(document).ready(function(){
|
||||
$(".hamburger").click(function(){
|
||||
$(".hamburger").toggleClass("is-active");
|
||||
|
||||
// Open drawer with hamburger
|
||||
$('.hamburger').click(function(){
|
||||
$('.hamburger').toggleClass('is-active');
|
||||
$('nav').toggleClass('visible');
|
||||
});
|
||||
|
||||
// Close drawer after tapping on nav
|
||||
$('nav').click(function(){
|
||||
$('.hamburger').removeClass('is-active');
|
||||
$('nav').removeClass('visible');
|
||||
});
|
||||
|
||||
// Close drawer by tapping outside it
|
||||
$('.wrap, section').click(function(){
|
||||
$('.hamburger').removeClass('is-active');
|
||||
$('nav').removeClass('visible');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
{% extends 'templates/base.html' %}
|
||||
{% block title %}{{ super() }} | Bug Report{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<section class='dark'>
|
||||
<div class='container'>
|
||||
<h1>Submit a Bug Report</h1>
|
||||
|
||||
<p>You can use this form to submit a bug report. You can also <a href="https://github.com/Tracman-org/Server/issues/new">post the issue on github</a>. Or maybe you'd like to <a href="/suggestion">suggest a feature</a> instead? </p>
|
||||
|
||||
<script src="/static/js/validator.min.js"></script>
|
||||
<form id='suggestions-form' class='col-lg-10 col-lg-offset-1 form-horizontal' role="form" method="POST" data-toggle="validator">
|
||||
|
||||
<div class='form-group' id='error-message' title="If you recieved an error message, put it here. An error message may be added automatically. ">
|
||||
<label class='control-label col-sm-2 col-lg-3' for="errorMessage">Error message (if any) </label>
|
||||
<div class='input-group col-xs-12 col-sm-10 col-lg-9'>
|
||||
<textarea class='form-control' name="errorMessage" rows="3" maxlength="2400" {% if errorMessage.length %}disabled{% endif %}>{{ errorMessage }}</textarea>
|
||||
</div>
|
||||
<div class='help-block with-errors col-xs-12 col-sm-10 col-sm-offset-2 col-lg-9 col-lg-offset-3'></div>
|
||||
</div>
|
||||
|
||||
<div class='form-group' id='recreation' title="Help me recreate the issue. ">
|
||||
<label class='control-label col-sm-2 col-lg-3' for="recreation">What were you doing when this happened? </label>
|
||||
<div class='input-group col-xs-12 col-sm-10 col-lg-9'>
|
||||
<textarea class='form-control' name="recreation" rows="4" maxlength="2400"></textarea>
|
||||
</div>
|
||||
<div class='help-block with-errors col-xs-12 col-sm-10 col-sm-offset-2 col-lg-9 col-lg-offset-3'></div>
|
||||
</div>
|
||||
|
||||
<div class='form-group' id='bug' title="Describe the problem here. ">
|
||||
<label class='control-label col-sm-2 col-lg-3' for="bug">What happened? </label>
|
||||
<div class='input-group col-xs-12 col-sm-10 col-lg-9'>
|
||||
<textarea class='form-control' name="bug" rows="4" maxlength="2400"></textarea>
|
||||
</div>
|
||||
<div class='help-block with-errors col-xs-12 col-sm-10 col-sm-offset-2 col-lg-9 col-lg-offset-3'></div>
|
||||
</div>
|
||||
|
||||
<div class='form-group' id='name' title="Put your name here if you want. ">
|
||||
<label class='control-label col-sm-2 col-lg-3' for="name">Name</label>
|
||||
<div class='input-group col-xs-12 col-sm-10 col-lg-9'>
|
||||
<input class='form-control' name="name" type="text" value="{{ user.name }}"
|
||||
maxlength="160"><br>
|
||||
</div>
|
||||
<div class='help-block with-errors col-xs-12 col-sm-10 col-sm-offset-2 col-lg-9 col-lg-offset-3'></div>
|
||||
</div>
|
||||
|
||||
<div class='form-group' id='email' title="Put an email address if you want a reply. ">
|
||||
<label class='control-label col-sm-2 col-lg-3' for="email">Email</label>
|
||||
<div class='input-group col-xs-12 col-sm-10 col-lg-9'>
|
||||
<input class='form-control' name="email" type="email" value="{{ user.email }}"
|
||||
maxlength="160" data-error="That's not an email address"><br>
|
||||
</div>
|
||||
<div class='help-block with-errors col-xs-12 col-sm-10 col-sm-offset-2 col-lg-9 col-lg-offset-3'></div>
|
||||
</div>
|
||||
|
||||
<div class='form-group flexbox' id='buttons'>
|
||||
<button type="submit" class='btn yellow'>SUBMIT</button>
|
||||
<a class='btn' href="/dashboard">nevermind</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -12,12 +12,13 @@
|
|||
<div class='container'>
|
||||
<h1>Tracman</h1>
|
||||
<h3>Display your realtime GPS location on a map</h3>
|
||||
<a class='btn' href="#" data-scrollto="overview">More info<i class='fa fa-angle-down'></i></a>
|
||||
<!--<a class='btn' href="#" data-scrollto="overview">More info<i class='fa fa-angle-down'></i></a>-->
|
||||
{% if user %}
|
||||
<a class='btn' href="/map">Map<i class='fa fa-angle-right'></i></a>
|
||||
{% else %}
|
||||
<a class='btn' href="#" data-scrollto="get">Request invite<i class='fa fa-angle-down'></i></a>
|
||||
<a class='btn' href="/map/keith">View example<i class='fa fa-angle-right'></i></a>
|
||||
<a class='btn' href="#" data-scrollto="get">Request invite<i class='fa fa-angle-down'></i></a>
|
||||
<a class='btn' href="/login">Login<i class='fa fa-angle-right'></i></a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</section>
|
||||
|
|
166
views/map.html
166
views/map.html
|
@ -5,6 +5,7 @@
|
|||
{{super()}}
|
||||
<link href="/static/css/map.css" rel="stylesheet">
|
||||
<style>
|
||||
#notset {display:none}
|
||||
.popup {
|
||||
padding: 5vw;
|
||||
border-radius: 5vw;
|
||||
|
@ -15,9 +16,11 @@
|
|||
-moz-box-shadow: 3px 4px 6px #000;
|
||||
-webkit-box-shadow: 3px 4px 6px #000;
|
||||
box-shadow: 3px 4px 6px #000;
|
||||
top: 10vh; bottom: 10vh;
|
||||
left:10vw; right: 10vw;
|
||||
top: calc(60px + 5vw);
|
||||
bottom: calc(30px + 5vw);
|
||||
left:5vw; right: 5vw;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}.popup .close {
|
||||
position: relative;
|
||||
top: -15px;
|
||||
|
@ -100,7 +103,7 @@
|
|||
</div>
|
||||
<h2>Share</h2>
|
||||
<p>This link will display the map of your location:
|
||||
<br><a href="/map/{{user.slug}}">https://tracman.org/map/{{user.slug}}</a>
|
||||
<a href="/map/{{user.slug}}">https://tracman.org/map/{{user.slug}}</a>
|
||||
<br>Here are some buttons for your convienence:
|
||||
<a href="https://twitter.com/home?status=A%20map%20of%20my%20realtime%20location:%20https://tracman.org/map/{{user.slug}}" target="_blank"><i class="share fa fa-twitter"></i></a>
|
||||
<a href="https://www.facebook.com/sharer/sharer.php?u=https://tracman.org/map/{{user.slug}}" target="_blank"><i class="share fa fa-facebook"></i></a>
|
||||
|
@ -225,8 +228,8 @@
|
|||
</div>
|
||||
</form>
|
||||
|
||||
<!--{% if not user.isPro %}<p style="clear:both">Want to try <a href="/pro">Tracman Pro</a>? It's free during beta testing. </p>{% endif %}-->
|
||||
<!--<p style="clear:both">Would you like to submit a <a href="/suggestion">suggestion</a> or <a href="/bug">bug report</a>? </p>-->
|
||||
{% if not user.isPro %}<p style="clear:both">Want to try <a href="/pro">Tracman Pro</a>? It's free during beta testing. </p>{% endif %}
|
||||
<p style="clear:both">Would you like to submit a <a href="https://productpains.com/create/tracman">suggestion</a> or <a href="https://github.com/Tracman-org/Server/issues/new">bug report</a>? </p>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
@ -254,6 +257,7 @@
|
|||
display: flex;
|
||||
justify-content: space-around;
|
||||
}#controls .btn {
|
||||
padding: 15px 0;
|
||||
background: #222;
|
||||
width: 30vw;
|
||||
}#controls .btn:hover {
|
||||
|
@ -276,11 +280,12 @@
|
|||
</div>
|
||||
|
||||
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
|
||||
<script src="/static/js/bundle.js"></script>
|
||||
<script src="https://maps.googleapis.com/maps/api/js?key={{api}}&callback=gmapsCb" async defer></script>
|
||||
<script>
|
||||
// Variables
|
||||
{ var wpid, map, pano, sv, marker, elevator,
|
||||
socket = io.connect(),
|
||||
sock = io.connect(),
|
||||
mapuserid = {{mapuser._id |dump|safe}},
|
||||
userid{% if user._id %} = {{user._id |dump|safe}}{% endif %},
|
||||
settings = JSON.parse('{{mapuser.settings |dump|safe}}'),
|
||||
|
@ -292,12 +297,16 @@
|
|||
}
|
||||
|
||||
// Connect to socket.io
|
||||
socket.on('connect', function(){
|
||||
socket.emit('room',
|
||||
sock.on('connect', function(){
|
||||
sock.emit('room',
|
||||
(userid)? 'app-'+userid :mapuserid
|
||||
);
|
||||
});
|
||||
|
||||
// }).on('data', function (data) {
|
||||
// console.log(data);
|
||||
}).on('error', function (err){
|
||||
console.error('Unable to connect Socket.IO', err);
|
||||
});
|
||||
|
||||
// Check for location.hash capability (IE9+)
|
||||
if (!'onhashchange' in window) {
|
||||
alert("location.hash won't work in IE<9. If you don't know how to fix this, google 'how to update browser'. ");
|
||||
|
@ -421,26 +430,21 @@
|
|||
|
||||
// Open popups
|
||||
function setPopups() {
|
||||
console.log('Setting popups');
|
||||
if (location.hash === "#share") {
|
||||
console.log('Setting popups to share');
|
||||
$('.settings.popup').hide();
|
||||
$('.share.popup').show();
|
||||
} else if (location.hash === "#settings") {
|
||||
console.log('Setting popups to settings');
|
||||
$('.share.popup').hide();
|
||||
$('.settings.popup').show();
|
||||
} else {
|
||||
console.log('Setting popups to default');
|
||||
} else {
|
||||
$('.settings.popup').hide();
|
||||
$('.share.popup').hide;
|
||||
$('.share.popup').hide();
|
||||
}
|
||||
} setPopups(); // Execute immediately
|
||||
window.onhashchange = setPopups; // Execute on change
|
||||
|
||||
// Get location
|
||||
socket.on('trac', function(loc) {
|
||||
console.log('recieved location');
|
||||
sock.on('trac', function(loc) {
|
||||
loc = parseLoc(loc);
|
||||
if (disp!='1' || !settings.showStreetview) {
|
||||
$('.tim').text('location updated '+loc.time);
|
||||
|
@ -457,69 +461,86 @@
|
|||
updateStreetView(loc,10);
|
||||
});
|
||||
|
||||
// Set location
|
||||
function setLocation() {
|
||||
if (!userid==mapuserid) {alert('You are not logged in! ');}
|
||||
else {
|
||||
if (!navigator.geolocation) {alert('Geolocation not enabled. ');}
|
||||
{% if user %}
|
||||
var token = '{{user.sk32}}';
|
||||
|
||||
// Set location
|
||||
function setLocation() {
|
||||
if (!userid==mapuserid) {alert('You are not logged in! '); next();}
|
||||
else {
|
||||
navigator.geolocation.getCurrentPosition(function(pos){
|
||||
console.log('Emitting location');
|
||||
socket.emit('app',{
|
||||
usr: userid,
|
||||
lat: pos.coords.latitude,
|
||||
lon: pos.coords.longitude,
|
||||
spd: (pos.coords.speed||0)
|
||||
});
|
||||
}, function(err) {
|
||||
if (err) { alert('ERROR: '+err); }
|
||||
else { location.reload(); }
|
||||
}, { enableHighAccuracy:true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Track location
|
||||
function trackLocation() {
|
||||
if (!userid==mapuserid) { alert('You are not logged in! '); }
|
||||
else {
|
||||
// Stop tracking
|
||||
if (wpid) {
|
||||
$('#controls > .track').html('<i class="fa fa-crosshairs"></i> Track').tooltip('hide');
|
||||
navigator.geolocation.clearWatch(wpid);
|
||||
wpid = undefined;
|
||||
// Start tracking
|
||||
} else {
|
||||
$('#controls > .track').html('<i class="fa fa-crosshairs fa-spin"></i> Stop').tooltip('show');
|
||||
if (!navigator.geolocation) { alert('Unable to track location. '); }
|
||||
if (!navigator.geolocation) {alert('Geolocation not enabled. ');}
|
||||
else {
|
||||
wpid = navigator.geolocation.watchPosition(function(pos) {
|
||||
socket.emit('app', {
|
||||
usr: '{{user.id}}',
|
||||
navigator.geolocation.getCurrentPosition(function(pos){
|
||||
newloc = {
|
||||
tok: token,
|
||||
usr: userid,
|
||||
lat: pos.coords.latitude,
|
||||
lon: pos.coords.longitude,
|
||||
spd: (pos.coords.speed||0)
|
||||
});
|
||||
// console.log('Sent location:',pos.coords.latitude.toFixed(2)+','+pos.coords.longitude.toFixed(2));
|
||||
}, function(err){
|
||||
alert('Failed to track: \n'+err);
|
||||
}
|
||||
sock.emit('app',newloc);
|
||||
toggleMaps(newloc);
|
||||
}, function(err) {
|
||||
console.log('done getting position');
|
||||
if (err) { console.log('ERROR: '+err); }
|
||||
}, { enableHighAccuracy:true });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear location
|
||||
function clearLocation() {
|
||||
if (!userid==mapuserid) { alert('You are not logged in! '); }
|
||||
else {
|
||||
socket.emit('app', {
|
||||
usr: userid,
|
||||
lat:0, lon:0, spd:0
|
||||
});
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
// Track location
|
||||
function trackLocation() {
|
||||
if (!userid==mapuserid) { alert('You are not logged in! '); }
|
||||
else {
|
||||
// Stop tracking
|
||||
if (wpid) {
|
||||
$('#controls > .track').html('<i class="fa fa-crosshairs"></i> Track').tooltip('hide');
|
||||
navigator.geolocation.clearWatch(wpid);
|
||||
wpid = undefined;
|
||||
// Start tracking
|
||||
} else {
|
||||
$('#controls > .track').html('<i class="fa fa-crosshairs fa-spin"></i> Stop').tooltip('show');
|
||||
if (!navigator.geolocation) { alert('Unable to track location. '); }
|
||||
else {
|
||||
wpid = navigator.geolocation.watchPosition(function(pos) {
|
||||
newloc = {
|
||||
tok: token,
|
||||
usr: '{{user.id}}',
|
||||
lat: pos.coords.latitude,
|
||||
lon: pos.coords.longitude,
|
||||
spd: (pos.coords.speed||0)
|
||||
};
|
||||
sock.emit('app',newloc);
|
||||
toggleMaps(newloc);
|
||||
}, function(err){
|
||||
alert('Failed to track: \n'+err);
|
||||
}, { enableHighAccuracy:true });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clear location
|
||||
function clearLocation() {
|
||||
if (!userid==mapuserid) { alert('You are not logged in! '); }
|
||||
else {
|
||||
// Stop tracking
|
||||
if (wpid) {
|
||||
$('#controls > .track').html('<i class="fa fa-crosshairs"></i> Track').tooltip('hide');
|
||||
navigator.geolocation.clearWatch(wpid);
|
||||
wpid = undefined;
|
||||
}
|
||||
newloc = {
|
||||
tok: token,
|
||||
usr: userid,
|
||||
lat:0, lon:0, spd:0
|
||||
}
|
||||
sock.emit('app',newloc);
|
||||
toggleMaps(newloc);
|
||||
}
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
|
||||
// Check altitude
|
||||
function getAltitude(loc,elev,cb){
|
||||
|
@ -586,4 +607,5 @@
|
|||
}
|
||||
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
{% extends 'templates/base.html' %}
|
||||
{% block title %}{{super()}} | Suggestion{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
<section class='dark'>
|
||||
<div class='container'>
|
||||
<h1>Suggest a Feature</h1>
|
||||
|
||||
<p>You can use this form to suggest new features. Or maybe you need to <a href="/bug">submit a bug report</a> instead? </p>
|
||||
|
||||
<script src="/static/js/validator.min.js"></script>
|
||||
<form id='suggestions-form' class='col-lg-10 col-lg-offset-1 form-horizontal' role="form" method="POST" data-toggle="validator">
|
||||
|
||||
<div class='form-group' id='suggestion'>
|
||||
<label class='control-label col-sm-2 col-lg-3' for="suggestion">What feature could improve Tracman? </label>
|
||||
<div class='input-group col-xs-12 col-sm-10 col-lg-9'>
|
||||
<textarea class='form-control' name="suggestion" rows="5" required maxlength="2400" data-error="You have to make a suggestion! "></textarea>
|
||||
</div>
|
||||
<div class='help-block with-errors col-xs-12 col-sm-10 col-sm-offset-2 col-lg-9 col-lg-offset-3'></div>
|
||||
</div>
|
||||
|
||||
<div class='form-group' id='name' title="Put your name here if you want. ">
|
||||
<label class='control-label col-sm-2 col-lg-3' for="name">Name</label>
|
||||
<div class='input-group col-xs-12 col-sm-10 col-lg-9'>
|
||||
<input class='form-control' name="name" type="text" value="{{ user.name }}"
|
||||
maxlength="160"><br>
|
||||
</div>
|
||||
<div class='help-block with-errors col-xs-12 col-sm-10 col-sm-offset-2 col-lg-9 col-lg-offset-3'></div>
|
||||
</div>
|
||||
|
||||
<div class='form-group' id='email' title="Put an email address if you want a reply. ">
|
||||
<label class='control-label col-sm-2 col-lg-3' for="email">Email</label>
|
||||
<div class='input-group col-xs-12 col-sm-10 col-lg-9'>
|
||||
<input class='form-control' name="email" type="email" value="{{ user.email }}"
|
||||
maxlength="160" data-error="That's not an email address"><br>
|
||||
</div>
|
||||
<div class='help-block with-errors col-xs-12 col-sm-10 col-sm-offset-2 col-lg-9 col-lg-offset-3'></div>
|
||||
</div>
|
||||
|
||||
<div class='form-group flexbox' id='buttons'>
|
||||
<button type="submit" class='btn yellow'>SUBMIT</button>
|
||||
<a class='btn' href="/dashboard">nevermind</a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue