Merge branch 'master' into emailNotifications

This commit is contained in:
David Baldwynn 2017-10-30 11:22:07 -07:00
commit 3652b41fc8
91 changed files with 2921 additions and 1467 deletions

View file

@ -3,13 +3,12 @@ TellForm 2.1.0
[![Build Status](https://travis-ci.org/tellform/tellform.svg?branch=master)](https://travis-ci.org/tellform/tellform)
![Project Status](https://img.shields.io/badge/status-2.1.0-green.svg)
[![Code Climate](https://codeclimate.com/github/whitef0x0/tellform/badges/gpa.svg)](https://codeclimate.com/github/whitef0x0/tellform)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3491e86eb7194308b8fc80711d736ede)](https://www.codacy.com/app/david-baldwin/tellform?utm_source=github.com&utm_medium=referral&utm_content=whitef0x0/tellform&utm_campaign=Badge_Grade)
[![Gitter](https://badges.gitter.im/whitef0x0/tellform.svg)](https://gitter.im/whitef0x0/tellform?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/3491e86eb7194308b8fc80711d736ede)](https://www.codacy.com/app/david-baldwin/tellform?utm_source=github.com&utm_medium=referral&utm_content=tellform/tellform&utm_campaign=Badge_Grade)
[![Gitter](https://badges.gitter.im/tellform/tellform.svg)](https://gitter.im/tellform/tellform?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
> An *opensource alternative to TypeForm* that can create [stunning mobile-ready forms](https://tellform.com/examples) , surveys and questionnaires.
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/whitef0x0/tellform/tree/master)
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/tellform/tellform/tree/master)
## Table of Contents
@ -94,7 +93,7 @@ MAILER_FROM=user@domain.com
# Use this for one of Nodemailer's pre-configured service providers
MAILER_SERVICE_PROVIDER=SendGrid
# Use these for a custom service provider
# Use these for a custom service provider
# Note: MAILER_SMTP_HOST will override MAILER_SERVICE_PROVIDER
MAILER_SMTP_HOST=smtp.domain.com
MAILER_SMTP_PORT=465
@ -202,7 +201,7 @@ TellForm's configuration is done with environment variables. To set an option fo
## Where to get help
[Gitter Chat](https://gitter.im/whitef0x0/tellform)
[Gitter Chat](https://gitter.im/tellform/tellform)
[Official Twitter](https://twitter.com/tellform_real)
@ -247,9 +246,9 @@ Love our work and community? [Become a backer](https://opencollective.com/tellfo
## Contributors
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
| [<img src="https://avatars2.githubusercontent.com/u/1160417?v=3" width="100px;"/><br /><sub>David Baldwynn</sub>](http://baldwynn.me)<br />[💻](https://github.com/tellform/TellForm/commits?author=whitef0x0 "Code") [🔧](#tool-whitef0x0 "Tools") [🚇](#infra-whitef0x0 "Infrastructure (Hosting, Build-Tools, etc)") [📖](https://github.com/tellform/TellForm/commits?author=whitef0x0 "Documentation") [💡](#example-whitef0x0 "Examples") [🎨](#design-whitef0x0 "Design") [🔍](#fundingFinding-whitef0x0 "Funding Finding") [👀](#review-whitef0x0 "Reviewed Pull Requests") [⚠️](https://github.com/tellform/TellForm/commits?author=whitef0x0 "Tests") | [<img src="https://avatars2.githubusercontent.com/u/313117?v=3" width="100px;"/><br /><sub>Samuel Laulhau</sub>](https://samuellaulhau.fr)<br />[💻](https://github.com/tellform/TellForm/commits?author=lalop "Code") [🌍](#translation-lalop "Translation") | [<img src="https://avatars0.githubusercontent.com/u/313507?v=3" width="100px;"/><br /><sub>Arun Pattnaik</sub>](http://arun.co)<br />[🎨](#design-arunpattnaik "Design") | [<img src="https://avatars0.githubusercontent.com/u/5405744?v=3" width="100px;"/><br /><sub>Thiên Toán</sub>](https://toanalien.com)<br />[🐛](https://github.com/tellform/TellForm/issues?q=author%3Atoanalien "Bug reports") [💻](https://github.com/tellform/TellForm/commits?author=toanalien "Code") [📖](https://github.com/tellform/TellForm/commits?author=toanalien "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/8615608?v=3" width="100px;"/><br /><sub>Adrian Portabales</sub>](https://github.com/AdrianP-)<br />[🐛](https://github.com/tellform/TellForm/issues?q=author%3AAdrianP- "Bug reports") [💻](https://github.com/tellform/TellForm/commits?author=AdrianP- "Code") | [<img src="https://avatars3.githubusercontent.com/u/8433587?v=3" width="100px;"/><br /><sub>Peter Thaleikis</sub>](https://github.com/spekulatius)<br />[📖](https://github.com/tellform/TellForm/commits?author=spekulatius "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/1247388?v=3" width="100px;"/><br /><sub>Mickaël Andrieu</sub>](http://www.mickael-andrieu.com)<br />[📖](https://github.com/tellform/TellForm/commits?author=mickaelandrieu "Documentation") |
| [<img src="https://avatars2.githubusercontent.com/u/1160417?v=3" width="100px;"/><br /><sub>David Baldwynn</sub>](http://baldwynn.me)<br />[💻](https://github.com/tellform/tellform/commits?author=whitef0x0 "Code") [🔧](#tool-whitef0x0 "Tools") [🚇](#infra-whitef0x0 "Infrastructure (Hosting, Build-Tools, etc)") [📖](https://github.com/tellform/tellform/commits?author=whitef0x0 "Documentation") [💡](#example-whitef0x0 "Examples") [🎨](#design-whitef0x0 "Design") [🔍](#fundingFinding-whitef0x0 "Funding Finding") [👀](#review-whitef0x0 "Reviewed Pull Requests") [⚠️](https://github.com/tellform/tellform/commits?author=whitef0x0 "Tests") | [<img src="https://avatars2.githubusercontent.com/u/313117?v=3" width="100px;"/><br /><sub>Samuel Laulhau</sub>](https://samuellaulhau.fr)<br />[💻](https://github.com/tellform/tellform/commits?author=lalop "Code") [🌍](#translation-lalop "Translation") | [<img src="https://avatars0.githubusercontent.com/u/313507?v=3" width="100px;"/><br /><sub>Arun Pattnaik</sub>](http://arun.co)<br />[🎨](#design-arunpattnaik "Design") | [<img src="https://avatars0.githubusercontent.com/u/5405744?v=3" width="100px;"/><br /><sub>Thiên Toán</sub>](https://toanalien.com)<br />[🐛](https://github.com/tellform/tellform/issues?q=author%3Atoanalien "Bug reports") [💻](https://github.com/tellform/tellform/commits?author=toanalien "Code") [📖](https://github.com/tellform/tellform/commits?author=toanalien "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/8615608?v=3" width="100px;"/><br /><sub>Adrian Portabales</sub>](https://github.com/AdrianP-)<br />[🐛](https://github.com/tellform/tellform/issues?q=author%3AAdrianP- "Bug reports") [💻](https://github.com/tellform/tellform/commits?author=AdrianP- "Code") | [<img src="https://avatars3.githubusercontent.com/u/8433587?v=3" width="100px;"/><br /><sub>Peter Thaleikis</sub>](https://github.com/spekulatius)<br />[📖](https://github.com/tellform/tellform/commits?author=spekulatius "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/1247388?v=3" width="100px;"/><br /><sub>Mickaël Andrieu</sub>](http://www.mickael-andrieu.com)<br />[📖](https://github.com/tellform/tellform/commits?author=mickaelandrieu "Documentation") |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars1.githubusercontent.com/u/1522464?v=3" width="100px;"/><br /><sub>Ahmad Luqman</sub>](https://github.com/ahmad-luqman)<br />[📖](https://github.com/tellform/TellForm/commits?author=ahmad-luqman "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/3691490?v=3" width="100px;"/><br /><sub>Peter Dave Hello</sub>](https://www.peterdavehello.org/)<br />[📖](https://github.com/tellform/TellForm/commits?author=PeterDaveHello "Documentation") |
| [<img src="https://avatars1.githubusercontent.com/u/1522464?v=3" width="100px;"/><br /><sub>Ahmad Luqman</sub>](https://github.com/ahmad-luqman)<br />[📖](https://github.com/tellform/tellform/commits?author=ahmad-luqman "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/3691490?v=3" width="100px;"/><br /><sub>Peter Dave Hello</sub>](https://www.peterdavehello.org/)<br />[📖](https://github.com/tellform/tellform/commits?author=PeterDaveHello "Documentation") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
## Mentions on the Web

View file

@ -102,7 +102,7 @@ exports.createSubmission = function(req, res) {
exports.listSubmissions = function(req, res) {
var _form = req.form;
FormSubmission.find({ form: _form._id }).sort('-created').lean().exec(function(err, _submissions) {
FormSubmission.find({ form: _form._id }).sort('created').lean().exec(function(err, _submissions) {
if (err) {
console.error(err);
res.status(500).send({
@ -148,15 +148,7 @@ exports.read = function(req, res) {
if(!req.user || (req.form.admin.id !== req.user.id) ){
readForRender(req, res);
} else {
FormSubmission.find({ form: req.form._id }).exec(function(err, _submissions) {
if (err) {
res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
}
var newForm = req.form.toJSON();
newForm.submissions = _submissions;
if (req.userId) {
if(req.form.admin._id+'' === req.userId+''){
@ -167,7 +159,6 @@ exports.read = function(req, res) {
});
}
return res.json(newForm);
});
}
};
@ -279,7 +270,7 @@ exports.list = function(req, res) {
Form.find(searchObj)
.sort('-created')
.select('title language submissions admin isLive')
.select('title language admin submissions isLive')
.populate('admin.username', 'admin._id')
.lean()
.exec(function(err, forms) {
@ -311,7 +302,6 @@ exports.formByID = function(req, res, next, id) {
}
Form.findById(id)
.populate('admin')
.populate('submissions')
.exec(function(err, form) {
if (err) {
return next(err);

View file

@ -9,16 +9,10 @@ var errorHandler = require('../errors.server.controller'),
config = require('../../../config/config'),
User = mongoose.model('User'),
tokgen = require('../../libs/tokenGenerator'),
fs = require('fs');
require.extensions['.html'] = function (module, filename) {
module.exports = fs.readFileSync(filename, 'utf8');
};
var welcomeEmail = require("../../views/welcome.email.view.html");
var verificationEmail = require("../../views/verification.email.view.html");
fs = require('fs'),
i18n = require('i18n'),
async = require('async'),
pug = require('pug');
var nev = require('email-verification')(mongoose);
@ -26,6 +20,15 @@ var nev = require('email-verification')(mongoose);
var config_nev = function () {
nev.configure({
verifyMailOptions: {
from: config.mailer.from
},
confirmMailOptions: {
from: config.mailer.from
},
persistentUserModel: User,
tempUserCollection: config.tempUserCollection,
emailAndUsernameUnique: true,
@ -33,19 +36,7 @@ var config_nev = function () {
verificationURL: config.baseUrl+'/#!/verify/${URL}',
transportOptions: config.mailer.options,
verifyMailOptions: {
from: config.mailer.from,
subject: '✔ Activate your new TellForm account!',
html: verificationEmail,
text: 'Please verify your account by clicking the following link, or by copying and pasting it into your browser: ${URL}'
},
confirmMailOptions: {
from: config.mailer.from,
subject: '✔ Welcome to {{app.title}}!',
html: welcomeEmail,
text: 'Your account has been successfully verified.'
},
verifySendMailCallback: function(err, info) {
if (err) {
throw err;
@ -63,13 +54,22 @@ var config_nev = function () {
throw err;
}
});
};
config_nev();
exports.validateVerificationToken = function(req, res){
nev.confirmTempUser(req.params.token, function(err, user) {
const fn = pug.compileFile(__dirname + "/../../views/welcome.email.view.pug");
var renderedHtml = fn(res.locals);
var emailTemplate = {
subject: i18n.__('WELCOME_EMAIL_SUBJECT', config.app.title),
html: renderedHtml,
text: i18n.__('WELCOME_EMAIL_TEXT')
};
nev.confirmTempUser(req.params.token, emailTemplate, function(err, user) {
if(err) {
return res.status(500).send( {message: err } );
} else if (user){
@ -83,7 +83,16 @@ exports.validateVerificationToken = function(req, res){
};
exports.resendVerificationEmail = function(req, res, next){
nev.resendVerificationEmail(req.body.email, function(err, userFound) {
const fn = pug.compileFile(__dirname + "/../../views/verification.email.view.pug");
var renderedHtml = fn(res.locals);
var emailTemplate = {
subject: i18n.__('VERIFICATION_EMAIL_SUBJECT'),
html: renderedHtml,
text: i18n.__('VERIFICATION_EMAIL_TEXT')
};
nev.resendVerificationEmail(req.body.email, emailTemplate, function(err, userFound) {
if(err) {
return res.status(500).send( {message: errorHandler.getErrorMessage(err) } );
}
@ -107,23 +116,35 @@ exports.signup = function(req, res) {
// Init Variables
var user = new User(req.body);
// Set language to visitor's language
user.language = req.cookies['userLang'];
// Add missing user fields
user.provider = 'local';
// Then save the temporary user
nev.createTempUser(user, function (err, existingPersistentUser, newTempUser) {
if (err) {
console.log(err);
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
}
// new user created
if (newTempUser) {
var URL = newTempUser[nev.options.URLFieldName];
nev.sendVerificationEmail(user.email, URL, function (sendEmailErr, info) {
if (sendEmailErr) {
const fn = pug.compileFile(__dirname + "/../../views/verification.email.view.pug");
var renderedHtml = fn(res.locals);
var URL = newTempUser[nev.options.URLFieldName];
var emailTemplate = {
subject: i18n.__('VERIFICATION_EMAIL_SUBJECT'),
html: renderedHtml,
text: i18n.__('VERIFICATION_EMAIL_TEXT')
};
nev.sendVerificationEmail(user.email, URL, emailTemplate, function (sendEmailErr, info) {
if (sendEmailErr) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
@ -131,7 +152,7 @@ exports.signup = function(req, res) {
return res.status(200).send('An email has been sent to you. Please check it to verify your account.');
});
} else {
return res.status(400).send({message: 'Error: User already exists!'});
return res.status(400).send({message: 'User with username/email already exists!'});
}
});
};
@ -140,6 +161,7 @@ exports.signup = function(req, res) {
* Signin after passport authentication
*/
exports.signin = function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err || !user) {
res.status(400).send(info);
@ -155,6 +177,8 @@ exports.signin = function(req, res, next) {
message: errorHandler.getErrorMessage(loginErr)
});
}
res.cookie('langCookie', user.language, { maxAge: 90000, httpOnly: true });
return res.json(user);
});
}
@ -165,138 +189,11 @@ exports.signin = function(req, res, next) {
* Signout
*/
exports.signout = function(req, res) {
if(req.cookies.hasOwnProperty('userLang')){
res.destroyCookie('userLang');
}
req.logout();
return res.status(200).send('You have successfully logged out.');
};
/**
* OAuth callback
*/
exports.oauthCallback = function(strategy) {
return function(req, res, next) {
passport.authenticate(strategy, function(err, user, redirectURL) {
if (err || !user) {
return res.redirect('/#!/signin');
}
req.login(user, function(err) {
if (err) {
return res.redirect('/#!/signin');
}
return res.redirect(redirectURL || '/');
});
})(req, res, next);
};
};
/**
* Helper function to save or update a OAuth user profile
*/
exports.saveOAuthUserProfile = function(req, providerUserProfile, done) {
if (!req.user) {
// Define a search query fields
var searchMainProviderIdentifierField = 'providerData.' + providerUserProfile.providerIdentifierField;
var searchAdditionalProviderIdentifierField = 'additionalProvidersData.' + providerUserProfile.provider + '.' + providerUserProfile.providerIdentifierField;
// Define main provider search query
var mainProviderSearchQuery = {};
mainProviderSearchQuery.provider = providerUserProfile.provider;
mainProviderSearchQuery[searchMainProviderIdentifierField] = providerUserProfile.providerData[providerUserProfile.providerIdentifierField];
// Define additional provider search query
var additionalProviderSearchQuery = {};
additionalProviderSearchQuery[searchAdditionalProviderIdentifierField] = providerUserProfile.providerData[providerUserProfile.providerIdentifierField];
// Define a search query to find existing user with current provider profile
var searchQuery = {
$or: [mainProviderSearchQuery, additionalProviderSearchQuery]
};
User.findOne(searchQuery, function(err, user) {
if (err) {
return done(err);
} else {
if (!user) {
var possibleUsername = providerUserProfile.username || ((providerUserProfile.email) ? providerUserProfile.email.split('@')[0] : '');
User.findUniqueUsername(possibleUsername, null, function(availableUsername) {
var newUser = new User({
firstName: providerUserProfile.firstName,
lastName: providerUserProfile.lastName,
username: availableUsername,
displayName: providerUserProfile.displayName,
email: providerUserProfile.email,
provider: providerUserProfile.provider,
providerData: providerUserProfile.providerData
});
// And save the user
newUser.save(function(userSaveErr) {
return done(userSaveErr, user);
});
});
}
return done(err, user);
}
});
} else {
// User is already logged in, join the provider data to the existing user
var user = req.user;
// Check if user exists, is not signed in using this provider, and doesn't have that provider data already configured
if (user.provider !== providerUserProfile.provider && (!user.additionalProvidersData || !user.additionalProvidersData[providerUserProfile.provider])) {
// Add the provider data to the additional provider data field
if (!user.additionalProvidersData) {
user.additionalProvidersData = {};
}
user.additionalProvidersData[providerUserProfile.provider] = providerUserProfile.providerData;
// Then tell mongoose that we've updated the additionalProvidersData field
user.markModified('additionalProvidersData');
// And save the user
user.save(function(err) {
return done(err, user, '/#!/settings/accounts');
});
} else {
return done(new Error('User is already connected using this provider'), user);
}
}
};
/**
* Remove OAuth provider
*/
exports.removeOAuthProvider = function(req, res, next) {
var user = req.user;
var provider = req.param('provider');
if (user && provider) {
// Delete the additional provider
if (user.additionalProvidersData[provider]) {
delete user.additionalProvidersData[provider];
// Then tell mongoose that we've updated the additionalProvidersData field
user.markModified('additionalProvidersData');
}
user.save(function(err) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
} else {
req.login(user, function(err) {
if (err) {
res.status(400).send(err);
} else {
res.json(user);
}
});
}
});
}
};
/* Generate API Key for User */

View file

@ -11,7 +11,8 @@ var _ = require('lodash'),
config = require('../../../config/config'),
nodemailer = require('nodemailer'),
async = require('async'),
crypto = require('crypto');
crypto = require('crypto'),
pug = require('pug');
var smtpTransport = nodemailer.createTransport(config.mailer.options);
@ -32,7 +33,7 @@ exports.forgot = function(req, res) {
if (req.body.username) {
User.findOne({
$or: [
{'username': req.body.username},
{'username': req.body.username.toLowerCase()},
{'email': req.body.username}
]
}, '-salt -password', function(err, user) {
@ -42,12 +43,27 @@ exports.forgot = function(req, res) {
});
}
if (!user) {
return res.status(400).send({
message: 'No account with that username or email has been found'
});
} else if (user.provider !== 'local') {
return res.status(400).send({
message: 'It seems like you signed up using your ' + user.provider + ' account'
var tempUserModel = mongoose.model(config.tempUserCollection);
tempUserModel.findOne({
$or: [
{'username': req.body.username.toLowerCase()},
{'email': req.body.username}
]
}).lean().exec(function(err, user) {
if(err){
return res.status(500).send({
message: err.message
});
}
if(!user){
return res.status(400).send({
message: 'No account with that username or email has been found'
});
}
return res.status(400).send({
message: 'The account associated with this email has not been activated yet'
});
});
} else {
user.resetPasswordToken = token;
@ -65,13 +81,12 @@ exports.forgot = function(req, res) {
}
},
function(token, user, done) {
res.render('templates/reset-password-email', {
name: user.displayName || 'TellForm User',
appName: config.app.title,
url: 'http://' + req.headers.host + '/auth/reset/' + token
}, function(err, emailHTML) {
done(err, emailHTML, user);
});
const fn = pug.compileFile(__dirname + "/../../views/templates/reset-password-email.server.view.pug");
res.locals['url'] = 'http://' + req.headers.host + '/auth/reset/' + token;
console.log(res.locals);
var renderedHtml = fn(res.locals);
done(null, renderedHtml, user);
},
// If valid email, send reset email using service
function(emailHTML, user, done) {
@ -138,10 +153,21 @@ exports.validateResetToken = function(req, res) {
* Reset password POST from email token
*/
exports.reset = function(req, res, next) {
if(req.body.newPassword.length < 4){
return res.status(400).send({
message: 'Password must be at least 4 characters long'
});
}
if(req.body.newPassword !== req.body.verifyPassword){
return res.status(400).send({
message: 'Passwords do not match'
});
}
// Init Variables
var passwordDetails = req.body;
async.waterfall([
function(done) {
User.findOne({
resetPasswordToken: req.params.token,
@ -150,32 +176,25 @@ exports.reset = function(req, res, next) {
}
}, function(err, user) {
if (!err && user) {
if (passwordDetails.newPassword === passwordDetails.verifyPassword) {
user.password = passwordDetails.newPassword;
user.resetPasswordToken = null;
user.resetPasswordExpires = null;
user.password = passwordDetails.newPassword;
user.resetPasswordToken = null;
user.resetPasswordExpires = null;
user.save(function(err) {
if (err) {
done(err, null);
}
done(null, user);
});
} else {
done('Passwords do not match', null);
}
user.save(function(err, savedUser) {
if (err) {
done(err, null);
}
done(null, savedUser);
});
} else {
done('Password reset token is invalid or has expired.', null);
}
});
},
function(user, done) {
res.render('templates/reset-password-confirm-email', {
name: user.displayName,
appName: config.app.title
}, function(err, emailHTML) {
done(err, emailHTML, user);
});
const fn = pug.compileFile(__dirname + "/../../views/templates/reset-password-confirm-email.server.view.pug");
var renderedHtml = fn(res.locals);
done(null, renderedHtml, user);
},
// If valid email, send reset email using service
function(emailHTML, user, done) {

View file

@ -37,18 +37,11 @@ var validateLocalStrategyProperty = function(property) {
return ((this.provider !== 'local' && !this.updated) || propHasLength);
};
/**
* A Validation function for local strategy password
*/
var validateLocalStrategyPassword = function(password) {
return (this.provider !== 'local' || (password && password.length > 6));
};
/**
* A Validation function for username
*/
var validateUsername = function(username) {
return (username.match(/^[a-zA-Z0-9]+$/) !== null);
return (username.match(/^[a-zA-Z0-9.-_]+$/) !== null);
};
@ -69,23 +62,17 @@ var UserSchema = new Schema({
email: {
type: String,
trim: true,
lowercase: true,
unique: 'Account already exists with this email',
required: 'Please enter your email',
validate: {
validator: validateLocalStrategyProperty,
message: 'Please fill in your email'
},
match: [/.+\@.+\..+/, 'Please fill a valid email address']
match: [/.+\@.+\..+/, 'Please fill a valid email address'],
required: [true, 'Email is required']
},
username: {
type: String,
unique: true,
required: true,
lowercase: true,
validate: {
validator: validateUsername,
message: 'Please use a valid username'
}
match: [/^[a-zA-Z0-9\-]+$/, 'Username can only contain alphanumeric characters and \'-\''],
required: [true, 'Username is required']
},
passwordHash: {
type: String,
@ -96,7 +83,6 @@ var UserSchema = new Schema({
},
provider: {
type: String,
required: 'Provider is required',
default: 'local'
},
providerData: {},
@ -112,7 +98,6 @@ var UserSchema = new Schema({
type: String,
enum: ['en', 'fr', 'es', 'it', 'de'],
default: 'en',
required: 'User must have a language'
},
lastModified: {
type: Date

View file

@ -25,10 +25,13 @@ module.exports = function(app) {
} else {
app.route('/forms/:formIdFast([a-zA-Z0-9]+)/render')
.get(forms.readForRender);
app.route('/view/')
.get(core.form);
}
app.route('/forms/:formIdFast([a-zA-Z0-9]+)')
.post(forms.createSubmission)
.post(forms.createSubmission)
app.route('/forms')
.get(auth.isAuthenticatedOrApiKey, forms.list)

View file

@ -14,7 +14,6 @@ module.exports = function(app) {
// Setting up the users profile api
app.route('/users/me').get(auth.isAuthenticatedOrApiKey, users.getUser);
app.route('/users').put(auth.isAuthenticatedOrApiKey, users.update);
app.route('/users/accounts').delete(users.requiresLogin, users.removeOAuthProvider);
// Setting up the users account verification api
app.route('/auth/verify/:token').get(users.validateVerificationToken);

View file

@ -1,8 +0,0 @@
{% extends 'layout.server.view.html' %}
{% block content %}
<h1>Page Not Found</h1>
<pre>
{{url}} is not a valid path.
</pre>
{% endblock %}

View file

@ -0,0 +1,8 @@
extends layout.server.view.pug
block content
section.public-form.auth.sigin-view.valign-wrapper
div.row.valign
h3.col-md-12.text-center=__('404_HEADER')
div.col-md-4.col-md-offset-4
div.col-md-12.text-center(style="padding-bottom: 50px;")=__('404_BODY', url)

View file

@ -1,8 +0,0 @@
{% extends 'layout.server.view.html' %}
{% block content %}
<h1>Server Error</h1>
<pre>
{{error}}
</pre>
{% endblock %}

View file

@ -0,0 +1,12 @@
extends layout.server.view.pug
block content
section.public-form.auth.sigin-view.valign-wrapper
div.row.valign
h3.col-md-12.text-center=__('500_HEADER')
div.col-md-4.col-md-offset-4
if process.env.NODE_ENV == 'development'
div.col-md-12.text-center(style="padding-bottom: 50px;")
| #{error}
else
div.col-md-12.text-center(style="padding-bottom: 50px;")=__('500_BODY')

View file

@ -1,139 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{{title}} Form</title>
<!-- General META -->
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- Semantic META -->
<meta name="keywords" content="{{keywords}}">
<meta name="description" content="{{description}}">
<!-- Facebook META -->
<meta property="og:site_name" content="{{title}}">
<meta property="og:title" content="{{title}}">
<meta property="og:description" content="{{description}}">
<meta property="og:url" content="{{url}}">
<meta property="og:image" content="/img/brand/logo.png">
<meta property="og:type" content="website">
<!-- Twitter META -->
<meta name="twitter:title" content="{{title}}">
<meta name="twitter:description" content="{{description}}">
<meta name="twitter:url" content="{{url}}">
<meta name="twitter:image" content="/img/brand/logo.png">
<style>
.loader {
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 9999;
background: url('/static/dist/page-loader.gif') 50% 35% no-repeat rgb(249,249,249);
background-size: 50px 50px;
}
</style>
<!-- Fav Icon -->
<link href="/static/modules/core/img/brand/favicon.ico" rel="shortcut icon" type="image/x-icon">
<!-- HTML5 Shim -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body ng-cloak>
<div class="loader"></div>
<section class="content">
<section ui-view></section>
</section>
<!--Embedding The User Object signupDisabled, socketPort and socketUrl Boolean -->
<script type="text/javascript">
var user = {{ user | json | safe }};
var signupDisabled = {{signupDisabled | safe}};
var socketPort = false;
{% if socketPort %}
socketPort = {{socketPort | safe }};
{% endif %}
var socketUrl = "{{socketUrl | safe}}";
var subdomainsDisabled = {{subdomainsDisabled | safe}};
</script>
<script src="/static/lib/jquery/dist/jquery.min.js" type="text/javascript"></script>
<link rel="stylesheet" href="/static/lib/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="/static/lib/bootstrap/dist/css/bootstrap.min.css">
<!--Bower CSS dependencies-->
{% for bowerCssFile in bowerCssFiles %}
<link rel="stylesheet" href="{{bowerCssFile}}">
{% endfor %}
<link rel="stylesheet" href="/static/lib/angular-input-stars/angular-input-stars.css">
<link rel="stylesheet" href="/static/lib/jquery-ui/themes/flick/jquery-ui.min.css"/>
<!-- end Bower CSS dependencies-->
<!--Application CSS Files-->
{% for cssFile in cssFiles %}
<link rel="stylesheet" href="{{cssFile}}">
{% endfor %}
<!-- end Application CSS Files-->
<!--Socket.io Client Dependency-->
<script src="/static/lib/socket.io-client/dist/socket.io.min.js"></script>
<script src="/static/lib/jquery-ui/jquery-ui.js" type="text/javascript"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="/static/dist/vendor.min.js"></script>
<script src="/static/lib/angular-ui-date/src/date.js" type="text/javascript"></script>
<!--Application JavaScript Files-->
{% for jsFile in formJSFiles %}
<script type="text/javascript" src="{{jsFile}}"></script>
{% endfor %}
<!-- end Application Javascript dependencies-->
{% if process.env.NODE_ENV === 'development' %}
<!--Livereload script rendered -->
<script async type="text/javascript" src="http://{{request.hostname}}:35729/livereload.js"></script>
{% endif %}
<script>
Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
</script>
{% if google_analytics_id %}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', '{{google_analytics_id}}', 'auto');
ga('send', 'pageview');
</script>
{% endif %}
<script type="text/javascript">
window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
heap.load("2213510609");
</script>
</body>
</html>

View file

@ -0,0 +1,106 @@
doctype html
html(lang='en', xmlns='http://www.w3.org/1999/xhtml')
head
title=title
// General META
meta(charset='utf-8')
meta(http-equiv='Content-type', content='text/html;charset=UTF-8')
meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
meta(name='viewport', content='width=device-width,initial-scale=1,maximum-scale=1')
meta(name='apple-mobile-web-app-capable', content='yes')
meta(name='apple-mobile-web-app-status-bar-style', content='black')
// Semantic META
meta(name='keywords', content='keywords')
meta(name='description', content='description')
// Facebook META
meta(property='og:site_name', content=title)
meta(property='og:title', content=title)
meta(property='og:description', content='description')
meta(property='og:url', content='url')
meta(property='og:image', content='/img/brand/logo.png')
meta(property='og:type', content='website')
// Twitter META
meta(name='twitter:title', content=title)
meta(name='twitter:description', content='description')
meta(name='twitter:url', content='url')
meta(name='twitter:image', content='/img/brand/logo.png')
style.
.loader {
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 9999;
background: url('/static/dist/page-loader.gif') 50% 35% no-repeat rgb(249,249,249);
background-size: 50px 50px;
}
// Fav Icon
link(href='/static/modules/core/img/brand/favicon.ico', rel='shortcut icon', type='image/x-icon')
body(ng-cloak='')
.loader
section.content
section(ui-view='')
//Embedding The User Object signupDisabled, socketPort and socketUrl Boolean
script(type='text/javascript').
var signupDisabled = !{signupDisabled};
var socketPort = false;
var socketUrl = false;
var subdomainsDisabled = !{subdomainsDisabled};
//Embedding socketPort
if socketPort
script(type='text/javascript').
socketPort = !{socketPort}
//Embedding socketUrl
if socketUrl
script(type='text/javascript').
socketUrl = !{socketUrl}
script(src='/static/lib/jquery/dist/jquery.min.js', type='text/javascript')
link(rel='stylesheet', href='/static/lib/font-awesome/css/font-awesome.min.css')
link(rel='stylesheet', href='/static/lib/bootstrap/dist/css/bootstrap.min.css')
//Bower CSS dependencies
each bowerCssFile in bowerCssFiles
link(rel='stylesheet', href=bowerCssFile)
link(rel='stylesheet', href='/static/lib/angular-input-stars/angular-input-stars.css')
link(rel='stylesheet', href='/static/lib/jquery-ui/themes/flick/jquery-ui.min.css')
// end Bower CSS dependencies
//Application CSS Files
each cssFile in cssFiles
link(rel='stylesheet', href=cssFile)
// end Application CSS Files
//Socket.io Client Dependency
script(src='/static/lib/socket.io-client/dist/socket.io.min.js')
script(src='/static/lib/jquery-ui/jquery-ui.js', type='text/javascript')
script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js', integrity='sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa', crossorigin='anonymous')
//Minified Bower Dependencies
script(src='/static/dist/vendor.min.js')
script(src='/static/lib/angular-ui-date/src/date.js', type='text/javascript')
//Application JavaScript Files
each jsFile in formJSFiles
script(type='text/javascript', src=jsFile)
// end Application Javascript dependencies
if process.env.NODE_ENV === 'development'
//Livereload script rendered
script(async='', type='text/javascript', src='http://#{request.hostname}:35729/livereload.js')
script Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
if google_analytics_id
script window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;ga('create','{{google_analytics_id}}','auto');ga('send','pageview')
script(src='https://www.google-analytics.com/analytics.js', async='')
script(type="text/javascript").
window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
heap.load("2213510609");

View file

@ -1,4 +0,0 @@
{% extends 'layout.server.view.html' %}
{% block content %}
<section class="content" ui-view></section>
{% endblock %}

View file

@ -0,0 +1,55 @@
extends layout.server.view.pug
block content
section.content(ui-view='', ng-cloak='')
script(src='/static/lib/file-saver.js/FileSaver.js', type='text/javascript')
//Embedding The User Object
script(type='text/javascript').
var user = null;
//Embedding The signupDisabled Boolean
script(type='text/javascript').
var signupDisabled = !{signupDisabled};
var socketPort = false;
var socketUrl = false;
var subdomainsDisabled = !{subdomainsDisabled};
var locale = "en";
//Embedding locale
if locale
script(type='text/javascript').
locale = "!{locale}";
//Embedding socketPort
if socketPort
script(type='text/javascript').
socketPort = !{socketPort}
//Embedding socketUrl
if socketUrl
script(type='text/javascript').
socketUrl = "!{socketUrl}"
//Socket.io Client Dependency
script(src='https://cdn.socket.io/socket.io-1.4.5.js')
//Bower JS dependencies
each bowerJSFile in bowerJSFiles
script(type='text/javascript', src=bowerJSFile)
// end Bower JS dependencies
script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.8/angular-strap.min.js')
//Application JavaScript Files
each jsFile in jsFiles
script(type='text/javascript', src=jsFile)
// end Application Javascript dependencies
if process.env.NODE_ENV === 'development'
script(type='text/javascript', src='http://#{request.hostname}:35729/livereload.js')
script(src='https://cdn.ravenjs.com/2.3.0/angular/raven.min.js')
script Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();

View file

@ -1,135 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{{title}}</title>
<!-- General META -->
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- Semantic META -->
<meta name="keywords" content="{{keywords}}">
<meta name="description" content="{{description}}">
<!-- Facebook META -->
<meta property="og:site_name" content="{{title}}">
<meta property="og:title" content="{{title}}">
<meta property="og:description" content="{{description}}">
<meta property="og:url" content="{{url}}">
<meta property="og:image" content="/img/brand/logo.png">
<meta property="og:type" content="website">
<!-- Twitter META -->
<meta name="twitter:title" content="{{title}}">
<meta name="twitter:description" content="{{description}}">
<meta name="twitter:url" content="{{url}}">
<meta name="twitter:image" content="/img/brand/logo.png">
<!-- Fav Icon -->
<link href="/static/modules/core/img/brand/favicon.ico" rel="shortcut icon" type="image/x-icon">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,900'>
<!--Bower CSS dependencies-->
{% for bowerCssFile in bowerCssFiles %}
<link rel="stylesheet" href="{{bowerCssFile}}">
{% endfor %}
<link rel="stylesheet" href="/static/lib/angular-input-stars/angular-input-stars.css">
<link rel="stylesheet" href="/static/lib/jquery-ui/themes/flick/jquery-ui.css"/>
<link rel="stylesheet" href="/static/modules/core/css/github-fork-ribbon.css"/>
<!-- end Bower CSS dependencies-->
<!--Application CSS Files-->
{% for cssFile in cssFiles %}
<link rel="stylesheet" href="{{cssFile}}">
{% endfor %}
<!-- end Application CSS Files-->
<!-- HTML5 Shim -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body ng-cloak>
{% block content %}{% endblock %}
<script src="/static/lib/file-saver.js/FileSaver.js" type="text/javascript"></script>
<!--Embedding The User Object-->
<script type="text/javascript">
var user = {{ user | json | safe }};
</script>
<!--Embedding The signupDisabled Boolean-->
<script type="text/javascript">
var signupDisabled = {{signupDisabled | safe}};
var socketPort = false;
{% if socketPort %}
socketPort = {{socketPort | safe}};
{% endif %}
var socketUrl = "{{socketUrl | safe}}" || false;
var subdomainsDisabled = {{subdomainsDisabled | safe}};
</script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!--Socket.io Client Dependency-->
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<!--Bower JS dependencies-->
{% for bowerJSFile in bowerJSFiles %}
<script type="text/javascript" src="{{bowerJSFile}}"></script>
{% endfor %}
<!-- end Bower JS dependencies-->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.8/angular-strap.min.js"></script>
<!--Application JavaScript Files-->
{% for jsFile in jsFiles %}
<script type="text/javascript" src="{{jsFile}}"></script>
{% endfor %}
<!-- end Application Javascript dependencies-->
{% if process.env.NODE_ENV === 'development' %}
<!--Livereload script rendered -->
<script type="text/javascript" src="http://{{request.hostname}}:35729/livereload.js"></script>
{% endif %}
<script src="https://cdn.ravenjs.com/2.3.0/angular/raven.min.js"></script>
<script>
Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
</script>
<!-- [if lt IE 9]>
<section class="browsehappy jumbotron hide">
<h1>Hello there!</h1>
<p>You are using an old browser which we unfortunately do not support.</p>
<p>Please <a href="http://browsehappy.com/">click here</a> to update your browser before using the website.</p>
<p><a href="http://browsehappy.com" class="btn btn-primary btn-lg" role="button">Yes, upgrade my browser!</a></p>
</section>
<![endif] -->
<script>
window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;
ga('create','{{google_analytics_id}}','auto');ga('send','pageview')
</script>
<script src="https://www.google-analytics.com/analytics.js" async defer></script>
<script type="text/javascript">
window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
heap.load("2213510609");
</script>
</body>
</html>

View file

@ -0,0 +1,61 @@
doctype html
html(lang='en', xmlns='http://www.w3.org/1999/xhtml')
head
title=title
// General META
meta(charset='utf-8')
meta(http-equiv='Content-type', content='text/html;charset=UTF-8')
meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
meta(name='viewport', content='width=device-width,initial-scale=1,maximum-scale=1')
meta(name='apple-mobile-web-app-capable', content='yes')
meta(name='apple-mobile-web-app-status-bar-style', content='black')
// Semantic META
meta(name='keywords', content=keywords)
meta(name='description', content=description)
// Facebook META
meta(property='og:site_name', content=title)
meta(property='og:title', content=title)
meta(property='og:description', content=description)
meta(property='og:url', content=url)
meta(property='og:image', content='/img/brand/logo.png')
meta(property='og:type', content='website')
// Twitter META
meta(name='twitter:title', content=title)
meta(name='twitter:description', content=description)
meta(name='twitter:url', content=url)
meta(name='twitter:image', content='/img/brand/logo.png')
// Fav Icon
link(href='/static/modules/core/img/brand/favicon.ico', rel='shortcut icon', type='image/x-icon')
link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css')
link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', integrity='sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u', crossorigin='anonymous')
link(rel='stylesheet', href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,900')
//Bower CSS dependencies
each bowerCssFile in bowerCssFiles
link(rel='stylesheet', href=bowerCssFile)
link(rel='stylesheet', href='/static/lib/angular-input-stars/angular-input-stars.css')
link(rel='stylesheet', href='/static/lib/jquery-ui/themes/flick/jquery-ui.css')
link(rel='stylesheet', href='/static/modules/core/css/github-fork-ribbon.css')
// end Bower CSS dependencies
//Application CSS Files
each cssFile in cssFiles
link(rel='stylesheet', href=cssFile)
// end Application CSS Files
body
block content
script window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;ga('create','{{google_analytics_id}}','auto');ga('send','pageview')
script(src='https://www.google-analytics.com/analytics.js', async='', defer='')
script(type="text/javascript").
window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
heap.load("2213510609");

View file

@ -1,94 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{{title}}</title>
<!-- General META -->
<meta charset="utf-8">
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- Semantic META -->
<meta name="keywords" content="{{keywords}}">
<meta name="description" content="{{description}}">
<!-- Facebook META -->
<meta property="og:site_name" content="{{title}}">
<meta property="og:title" content="{{title}}">
<meta property="og:description" content="{{description}}">
<meta property="og:url" content="{{url}}">
<meta property="og:image" content="/img/brand/logo.png">
<meta property="og:type" content="website">
<!-- Twitter META -->
<meta name="twitter:title" content="{{title}}">
<meta name="twitter:description" content="{{description}}">
<meta name="twitter:url" content="{{url}}">
<meta name="twitter:image" content="/img/brand/logo.png">
<!-- Fav Icon -->
<link href="/static/modules/core/img/brand/favicon.ico" rel="shortcut icon" type="image/x-icon">
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,900'>
<!--Bower CSS dependencies-->
<!-- end Bower CSS dependencies-->
<!--Application CSS Files-->
{% for cssFile in cssFiles %}
<link rel="stylesheet" href="{{cssFile}}">
{% endfor %}
<!-- end Application CSS Files-->
<!-- HTML5 Shim -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<redoc spec-url='/static/swagger.json'></redoc>
<script src="https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js"> </script>
<!--Bower JS dependencies-->
{% for bowerJSFile in bowerJSFiles %}
<script type="text/javascript" src="{{bowerJSFile}}"></script>
{% endfor %}
<!-- end Bower JS dependencies-->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.8/angular-strap.min.js"></script>
{% if process.env.NODE_ENV === 'development' %}
<script src="https://cdn.ravenjs.com/2.3.0/angular/raven.min.js"></script>
<script>
Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
</script>
<!-- [if lt IE 9]>
<section class="browsehappy jumbotron hide">
<h1>Hello there!</h1>
<p>You are using an old browser which we unfortunately do not support.</p>
<p>Please <a href="http://browsehappy.com/">click here</a> to update your browser before using the website.</p>
<p><a href="http://browsehappy.com" class="btn btn-primary btn-lg" role="button">Yes, upgrade my browser!</a></p>
</section>
<![endif] -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', '{{google_analytics_id}}', 'auto');
ga('send', 'pageview');
</script>
</body>
</html>

View file

@ -0,0 +1,62 @@
doctype html
html(lang='en', xmlns='http://www.w3.org/1999/xhtml')
head
title #{title}
// General META
meta(charset='utf-8')
meta(http-equiv='Content-type', content='text/html;charset=UTF-8')
meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
meta(name='viewport', content='width=device-width,initial-scale=1,maximum-scale=1')
meta(name='apple-mobile-web-app-capable', content='yes')
meta(name='apple-mobile-web-app-status-bar-style', content='black')
// Semantic META
meta(name='keywords', content='#{keywords}')
meta(name='description', content='#{description}')
// Facebook META
meta(property='og:site_name', content='#{title}')
meta(property='og:title', content='#{title}')
meta(property='og:description', content='#{description}')
meta(property='og:url', content='{{url}}')
meta(property='og:image', content='/img/brand/logo.png')
meta(property='og:type', content='website')
// Twitter META
meta(name='twitter:title', content='#{title}')
meta(name='twitter:description', content='#{description}')
meta(name='twitter:url', content='{{url}}')
meta(name='twitter:image', content='/img/brand/logo.png')
// Fav Icon
link(href='/static/modules/core/img/brand/favicon.ico', rel='shortcut icon', type='image/x-icon')
link(rel='stylesheet', href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,900')
//Application CSS Files
each cssFile in cssFiles
link(rel='stylesheet', href='#{cssFile}')
// end Application CSS Files
body
redoc(spec-url='/static/swagger.json')
script(src='https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js')
//Bower JS dependencies
each bowerJSFile in bowerJSFiles
script(type='text/javascript', src='#{bowerJSFile}')
// end Bower JS dependencies
script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.8/angular-strap.min.js')
if process.env.NODE_ENV === 'development'
script(src='https://cdn.ravenjs.com/2.3.0/angular/raven.min.js')
script Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
script window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;ga('create','{{google_analytics_id}}','auto');ga('send','pageview')
script(src='https://www.google-analytics.com/analytics.js', async='', defer='')
script(type="text/javascript").
window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
heap.load("2213510609");

View file

@ -30,7 +30,7 @@
<p>Hello there!</p>
<p>This is a courtesy message to confirm that your password was just changed.</p>
<p>Thanks so much for using our services! If you have any questions, or suggestions, please feel free to email us here at&nbsp;<a href="mailto:team@tellform.com">team@tellform.com</a>.</p>
<p> - The {{appName}} team</p>
<p> - The #{appName} team</p>
</td>
<td width="36"></td>
</tr>

View file

@ -0,0 +1,41 @@
doctype html
html
head
body(style='padding: 0; width: 100% !important; -webkit-text-size-adjust: 100%; margin: 0; -ms-text-size-adjust: 100%', marginheight='0', marginwidth='0')
center
table(cellpadding='8', cellspacing='0', style='*width: 540px; padding: 0; width: 100% !important; background: #ffffff; margin: 0; background-color: #ffffff', border='0')
tbody
tr
td(valign='top')
table(cellpadding='0', cellspacing='0', style='border-radius: 6px; -webkit-border-radius: 6px; border: 1px #c0c0c0 solid; -moz-border-radius: 6px', border='0', align='center')
tbody
tr
td(colspan='3', height='6')
tr
td
table(cellpadding='0', cellspacing='0', style='line-height: 25px', border='0', align='center')
tbody
tr
td(colspan='3', height='30')
tr
td(width='36')
td(width='454', align='left', style="color: #444444; border-collapse: collapse; font-size: 11pt; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; max-width: 454px", valign='top')
p=__('EMAIL_GREETING')
p=__('RESET_PASSWORD_CONFIRMATION_EMAIL_BODY_1')
p=__("VERIFICATION_EMAIL_PARAGRAPH_2")
a(href='mailto:team@tellform.com') team@tellform.com
p=__('EMAIL_SIGNATURE')
td(width='36')
tr
td(colspan='3', height='36')
table(cellpadding='0', cellspacing='0', align='center', border='0')
tbody
tr
td(height='10')
tr
td(style='padding: 0; border-collapse: collapse')
table(cellpadding='0', cellspacing='0', align='center', border='0')
tbody
tr(style="color: #c0c0c0; font-size: 11px; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; -webkit-text-size-adjust: none")
td(width='400', align='left')
td(width='128', align='right') © TellForm 2017

View file

@ -0,0 +1,44 @@
doctype html
html
head
body(style='padding: 0; width: 100% !important; -webkit-text-size-adjust: 100%; margin: 0; -ms-text-size-adjust: 100%', marginheight='0', marginwidth='0')
center
table(cellpadding='8', cellspacing='0', style='*width: 540px; padding: 0; width: 100% !important; background: #ffffff; margin: 0; background-color: #ffffff', border='0')
tbody
tr
td(valign='top')
table(cellpadding='0', cellspacing='0', style='border-radius: 6px; -webkit-border-radius: 6px; border: 1px #c0c0c0 solid; -moz-border-radius: 6px', border='0', align='center')
tbody
tr
td(colspan='3', height='6')
tr
td
table(cellpadding='0', cellspacing='0', style='line-height: 25px', border='0', align='center')
tbody
tr
td(colspan='3', height='30')
tr
td(width='36')
td(width='454', align='left', style="color: #444444; border-collapse: collapse; font-size: 11pt; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; max-width: 454px", valign='top')
p=__('EMAIL_GREETING')
p=__('RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_1')
p
a(href=url)=__('RESET_PASSWORD_REQUEST_EMAIL_LINK_TEXT')
p=__('RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_2')
p=__('VERIFICATION_EMAIL_PARAGRAPH_2')
a(href='mailto:team@tellform.com') team@tellform.com
p=__('EMAIL_SIGNATURE')
td(width='36')
tr
td(colspan='3', height='36')
table(cellpadding='0', cellspacing='0', align='center', border='0')
tbody
tr
td(height='10')
tr
td(style='padding: 0; border-collapse: collapse')
table(cellpadding='0', cellspacing='0', align='center', border='0')
tbody
tr(style="color: #c0c0c0; font-size: 11px; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; -webkit-text-size-adjust: none")
td(width='400', align='left')
td(width='128', align='right') © TellForm 2017

View file

@ -1,65 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<head>
@import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&subset=latin,latin-ext);
<style>
a {
color: #007ee6;
text-decoration: none;
}
</style>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
</head>
<body style="padding: 0; width: 100% !important; -webkit-text-size-adjust: 100%; margin: 0; -ms-text-size-adjust: 100%;" marginheight="0" marginwidth="0">
<center>
<table cellpadding="8" cellspacing="0" style="*width: 540px; padding: 0; width: 100% !important; background: #ffffff; margin: 0; background-color: #ffffff;" border="0">
<tr>
<td valign="top">
<table cellpadding="0" cellspacing="0" style="border-radius: 6px; -webkit-border-radius: 6px; border: 1px #c0c0c0 solid; -moz-border-radius: 6px;" border="0" align="center">
<tr>
<td colspan="3" height="6"></td>
</tr>
<tr>
<td>
<table cellpadding="0" cellspacing="0" style="line-height: 25px;" border="0" align="center">
<tr>
<td colspan="3" height="30"></td>
</tr>
<tr>
<td width="36"></td>
<td width="454" align="left" style="color: #444444; border-collapse: collapse; font-size: 11pt; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; max-width: 454px;" valign="top">
<p>Hello there!</p>
<p>Welcome to TellForm! Here is a special link to activate your new account:</p>
<p><a href="https://${URL}">Activate my account</a></p>
<p>Thanks so much for using our services! If you have any questions, or suggestions, please feel free to email us here at&nbsp;<a href="mailto:team@tellform.com">team@tellform.com</a>.</p>
<p> - The TellForm team</p>
</td>
<td width="36"></td>
</tr>
<tr>
<td colspan="3" height="36"></td>
</tr>
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" align="center" border="0">
<tr>
<td height="10"></td>
</tr>
<tr>
<td style="padding: 0; border-collapse: collapse;">
<table cellpadding="0" cellspacing="0" align="center" border="0">
<tr style="color: #c0c0c0; font-size: 11px; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; -webkit-text-size-adjust: none;">
<td width="400" align="left"></td>
<td width="128" align="right">© TellForm 2017</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</center>
</body>
</head>

View file

@ -0,0 +1,49 @@
html
head
style.
a {
color: #007ee6;
text-decoration: none;
}
meta(content='text/html; charset=utf-8', http-equiv='Content-Type')
body(style='padding: 0; width: 100% !important; -webkit-text-size-adjust: 100%; margin: 0; -ms-text-size-adjust: 100%', marginheight='0', marginwidth='0')
center
table(cellpadding='8', cellspacing='0', style='*width: 540px; padding: 0; width: 100% !important; background: #ffffff; margin: 0; background-color: #ffffff', border='0')
tbody
tr
td(valign='top')
table(cellpadding='0', cellspacing='0', style='border-radius: 6px; -webkit-border-radius: 6px; border: 1px #c0c0c0 solid; -moz-border-radius: 6px', border='0', align='center')
tbody
tr
td(colspan='3', height='6')
tr
td
table(cellpadding='0', cellspacing='0', style='line-height: 25px', border='0', align='center')
tbody
tr
td(colspan='3', height='30')
tr
td(width='36')
td(width='454', align='left', style="color: #444444; border-collapse: collapse; font-size: 11pt; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; max-width: 454px", valign='top')
p=__('EMAIL_GREETING')
p=__('VERIFICATION_EMAIL_PARAGRAPH_1')
p
a(href='http://${URL}')=__('VERIFICATION_EMAIL_LINK_TEXT')
p=__('VERIFICATION_EMAIL_PARAGRAPH_2')
a(href='mailto:team@tellform.com')
| team@tellform.com
p=__('EMAIL_SIGNATURE')
td(width='36')
tr
td(colspan='3', height='36')
table(cellpadding='0', cellspacing='0', align='center', border='0')
tbody
tr
td(height='10')
tr
td(style='padding: 0; border-collapse: collapse')
table(cellpadding='0', cellspacing='0', align='center', border='0')
tbody
tr(style="color: #c0c0c0; font-size: 11px; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; -webkit-text-size-adjust: none")
td(width='400', align='left')
td(width='128', align='right') © TellForm 2017

View file

@ -1,64 +0,0 @@
<!DOCTYPE html>
<html>
<head>@import url(//fonts.googleapis.com/css?family=Open+Sans:300,400,600,700&subset=latin,latin-ext);
<style>
a {
color: #007ee6;
text-decoration: none;
}
</style>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
</head>
<body style="padding: 0; width: 100% !important; -webkit-text-size-adjust: 100%; margin: 0; -ms-text-size-adjust: 100%;" marginheight="0" marginwidth="0">
<center>
<table cellpadding="8" cellspacing="0" style="*width: 540px; padding: 0; width: 100% !important; background: #ffffff; margin: 0; background-color: #ffffff;" border="0">
<tr>
<td valign="top">
<table cellpadding="0" cellspacing="0" style="border-radius: 6px; -webkit-border-radius: 6px; border: 1px #c0c0c0 solid; -moz-border-radius: 6px;" border="0" align="center">
<tr>
<td colspan="3" height="6"></td>
</tr>
<tr>
<td>
<table cellpadding="0" cellspacing="0" style="line-height: 25px;" border="0" align="center">
<tr>
<td colspan="3" height="30"></td>
</tr>
<tr>
<td width="36"></td>
<td width="454" align="left" style="color: #444444; border-collapse: collapse; font-size: 11pt; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; max-width: 454px;" valign="top">
<p>Hello there!</p>
<p>We would like to welcome you as our newest member!</p>
<p>Thanks so much for using TellForm! If you have any questions, or suggestions, please feel free to email us here at&nbsp;<a href="mailto:team@tellform.com">team@tellform.com</a>.</p>
<p> - The TellForm team</p>
</td>
<td width="36"></td>
</tr>
<tr>
<td colspan="3" height="36"></td>
</tr>
</table>
</td>
</tr>
</table>
<table cellpadding="0" cellspacing="0" align="center" border="0">
<tr>
<td height="10"></td>
</tr>
<tr>
<td style="padding: 0; border-collapse: collapse;">
<table cellpadding="0" cellspacing="0" align="center" border="0">
<tr style="color: #c0c0c0; font-size: 11px; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; -webkit-text-size-adjust: none;">
<td width="400" align="left"></td>
<td width="128" align="right">© TellForm 2017</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</center>
</body>
</html>

View file

@ -0,0 +1,48 @@
html
head
style.
a {
color: #007ee6;
text-decoration: none;
}
meta(content='text/html; charset=utf-8', http-equiv='Content-Type')
body(style='padding: 0; width: 100% !important; -webkit-text-size-adjust: 100%; margin: 0; -ms-text-size-adjust: 100%', marginheight='0', marginwidth='0')
center
table(cellpadding='8', cellspacing='0', style='*width: 540px; padding: 0; width: 100% !important; background: #ffffff; margin: 0; background-color: #ffffff', border='0')
tbody
tr
td(valign='top')
table(cellpadding='0', cellspacing='0', style='border-radius: 6px; -webkit-border-radius: 6px; border: 1px #c0c0c0 solid; -moz-border-radius: 6px', border='0', align='center')
tbody
tr
td(colspan='3', height='6')
tr
td
table(cellpadding='0', cellspacing='0', style='line-height: 25px', border='0', align='center')
tbody
tr
td(colspan='3', height='30')
tr
td(width='36')
td(width='454', align='left', style="color: #444444; border-collapse: collapse; font-size: 11pt; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; max-width: 454px", valign='top')
p=__('EMAIL_GREETING')
p=__('WELCOME_EMAIL_PARAGRAPH_1')
p=__('WELCOME_EMAIL_PARAGRAPH_2')
a(href='mailto:team@tellform.com')
| team@tellform.com
p=__('EMAIL_SIGNATURE')
td(width='36')
tr
td(colspan='3', height='36')
table(cellpadding='0', cellspacing='0', align='center', border='0')
tbody
tr
td(height='10')
tr
td(style='padding: 0; border-collapse: collapse')
table(cellpadding='0', cellspacing='0', align='center', border='0')
tbody
tr(style="color: #c0c0c0; font-size: 11px; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; -webkit-text-size-adjust: none")
td(width='400', align='left')
td(width='128', align='right') © TellForm 2017

View file

@ -2,7 +2,7 @@
"name": "tellform",
"description": "Opensource alternative to TypeForm",
"version": "2.0.0",
"homepage": "https://github.com/whitef0x0/tellform",
"homepage": "https://github.com/tellform/tellform",
"authors": [
"David Baldwynn <polydaic@gmail.com> (http://baldwynn.me)"
],

2
config/env/all.js vendored
View file

@ -28,7 +28,7 @@ module.exports = {
socketPort: process.env.SOCKET_PORT || 20523,
socketPortExternallyVisible: (process.env.SOCKET_PORT_EXTERN_VISIBLE === 'TRUE'),
templateEngine: 'swig',
templateEngine: 'pug',
signupDisabled: (process.env.SIGNUP_DISABLED === 'TRUE'),
enableClusterMode: (process.env.ENABLE_CLUSTER_MODE === 'TRUE'),

View file

@ -20,7 +20,8 @@ var fs = require('fs'),
config = require('./config'),
consolidate = require('consolidate'),
path = require('path'),
client = new raven.Client(config.DSN);
client = new raven.Client(config.DSN),
i18n = require('i18n');
var mongoose = require('mongoose');
@ -35,6 +36,18 @@ var configureSocketIO = function (app, db) {
return server;
};
var supportedLanguages = ['en', 'de', 'fr', 'it', 'es'];
function containsAnySupportedLanguages(preferredLanguages){
for (var i = 0; i < preferredLanguages.length; i++) {
var currIndex = supportedLanguages.indexOf(preferredLanguages[i]);
if (currIndex > -1) {
return supportedLanguages[currIndex];
}
}
return null;
}
module.exports = function(db) {
// Initialize express app
var app = express();
@ -176,11 +189,11 @@ module.exports = function(db) {
}));
// Set swig as the template engine
app.engine('server.view.html', consolidate[config.templateEngine]);
// Set template engine as defined in the config files
app.engine('server.view.pug', consolidate.pug);
// Set views path and view engine
app.set('view engine', 'server.view.html');
app.set('view engine', 'server.view.pug');
app.set('views', './app/views');
// Enable logger (morgan)
@ -200,6 +213,7 @@ module.exports = function(db) {
extended: true,
limit: '100mb'
}));
app.use(bodyParser.json({ limit: '100mb' }));
app.use(methodOverride());
@ -220,7 +234,6 @@ module.exports = function(db) {
app.use(cookieParser());
// Express MongoDB session storage
app.use(session({
saveUninitialized: true,
resave: true,
@ -237,14 +250,41 @@ module.exports = function(db) {
app.use(passport.initialize());
app.use(passport.session());
//Setup i18n
i18n.configure({
locales: supportedLanguages,
directory: __dirname + '/locales',
defaultLocale: 'en',
cookie: 'userLang'
});
app.use(i18n.init);
//Visitor Language Detection
app.use(function(req, res, next) {
var acceptLanguage = req.headers['accept-language'];
var languages = acceptLanguage.match(/[a-z]{2}(?!-)/g) || [];
var supportedLanguage = containsAnySupportedLanguages(languages);
if(!req.user && supportedLanguage !== null){
var currLanguage = res.cookie('userLang');
if(currLanguage && currLanguage !== supportedLanguage || !currLanguage){
res.clearCookie('userLang');
res.cookie('userLang', supportedLanguage, { maxAge: 90000, httpOnly: true });
}
} else if(req.user && (!req.cookies.hasOwnProperty('userLang') || req.cookies['userLang'] !== req.user.language) ){
res.cookie('userLang', req.user.language, { maxAge: 90000, httpOnly: true });
}
next();
});
// Globbing routing files
config.getGlobbedFiles('./app/routes/**/*.js').forEach(function(routePath) {
require(path.resolve(routePath))(app);
});
// Add headers for Sentry
app.use(function (req, res, next) {
// Website you wish to allow to connect

21
config/locales/de.json Normal file
View file

@ -0,0 +1,21 @@
{
"404_HEADER": "404 - Seite nicht gefunden",
"500_HEADER": "500 - Interner Serverfehler",
"404_BODY": "%s ist kein gültiger Pfad.",
"500_BODY": "Ein unerwarteter Fehler scheint aufgetreten zu sein, warum nicht versuchen, Ihre Seite zu aktualisieren oder Sie können uns kontaktieren, wenn das Problem weiterhin besteht.",
"EMAIL_GREETING": "Hallo da!",
"VERIFICATION_EMAIL_PARAGRAPH_1": "Willkommen bei TellForm! Hier ist ein spezieller Link um deinen neuen Account zu aktivieren:",
"VERIFICATION_EMAIL_LINK_TEXT": "Mein Konto aktivieren",
"VERIFICATION_EMAIL_PARAGRAPH_2": "Vielen Dank für die Nutzung unserer Dienste! Wenn Sie Fragen oder Anregungen haben, senden Sie uns bitte eine E-Mail an",
"VERIFICATION_EMAIL_SUBJECT": "Aktiviere dein neues TellForm-Konto!",
"VERIFICATION_EMAIL_TEXT": "Bitte bestätigen Sie Ihren Account, indem Sie auf den folgenden Link klicken oder ihn in Ihren Browser kopieren und einfügen: $ {URL}",
"EMAIL_SIGNATURE": "- Das TellForm-Team",
"WELCOME_EMAIL_PARAGRAPH_1": "Wir möchten Sie als unser neustes Mitglied begrüßen!",
"WELCOME_EMAIL_PARAGRAPH_2": "Wir wünschen Ihnen viel Spaß mit TellForm! Wenn Sie Probleme haben, senden Sie uns bitte eine E-Mail an",
"WELCOME_EMAIL_SUBJECT": "Willkommen bei %s!",
"WELCOME_EMAIL_TEXT": "Ihr Konto wurde erfolgreich verifiziert.",
"RESET_PASSWORD_CONFIRMATION_EMAIL_PARAGRAPH_1": "Dies ist eine Höflichkeitsnachricht, um zu bestätigen, dass Ihr Passwort gerade geändert wurde.",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_1": "Hier ist ein spezieller Link, mit dem Sie Ihr Passwort zurücksetzen können: Bitte beachten Sie, dass es innerhalb einer Stunde zu Ihrem Schutz abläuft:",
"RESET_PASSWORD_REQUEST_EMAIL_LINK_TEXT": "Passwort zurücksetzen",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_2": "Falls Sie dies nicht gewünscht haben, ignorieren Sie bitte diese E-Mail und Ihr Passwort bleibt unverändert."
}

22
config/locales/en.json Normal file
View file

@ -0,0 +1,22 @@
{
"500_HEADER": "500 - Internal Server Error",
"404_HEADER": "404 - Page not found",
"404_BODY": "%s is not a valid path",
"500_BODY": "An unexpected error seems to have occured. Why not try refreshing your page? Or you can contact us if the problem persists.",
"EMAIL_GREETING": "Hello there!",
"VERIFICATION_EMAIL_PARAGRAPH_1": "Welcome to TellForm! Here is a special link to activate your new account:",
"VERIFICATION_EMAIL_LINK_TEXT": "Activate my account",
"VERIFICATION_EMAIL_PARAGRAPH_2": "Thanks so much for using our services! If you have any questions, or suggestions, please feel free to email us here at",
"VERIFICATION_EMAIL_SUBJECT": "Activate your new TellForm account!",
"VERIFICATION_EMAIL_TEXT": "Please verify your account by clicking the following link, or by copying and pasting it into your browser: ${URL}",
"EMAIL_SIGNATURE": "- The TellForm team",
"WELCOME_EMAIL_PARAGRAPH_1": "We would like to welcome you as our newest member!",
"WELCOME_EMAIL_PARAGRAPH_2": "We hope you enjoy using TellForm! If you have any trouble please feel free to email us here at",
"WELCOME_EMAIL_SUBJECT": "Welcome to %s!",
"WELCOME_EMAIL_TEXT": "Your account has been successfully verified.",
"RESET_PASSWORD_CONFIRMATION_EMAIL_PARAGRAPH_1": "This is a courtesy message to confirm that your password was just changed.",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_1": "Here is a special link that will allow you to reset your password. Please note it will expire in one hour for your protection:",
"RESET_PASSWORD_REQUEST_EMAIL_LINK_TEXT": "Reset Your Password",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_2": "If you did not request this, please ignore this email and your password will remain unchanged.",
"RESET_PASSWORD_CONFIRMATION_EMAIL_BODY_1": "RESET_PASSWORD_CONFIRMATION_EMAIL_BODY_1"
}

21
config/locales/es.json Normal file
View file

@ -0,0 +1,21 @@
{
"404_HEADER": "404 - Página no encontrada",
"500_HEADER": "500 - Error interno del servidor",
"404_BODY": "%s no es una ruta válida",
"500_BODY": "Parece que se produjo un error inesperado. ¿Por qué no intenta actualizar su página? O puede contactarnos si el problema persiste",
"EMAIL_GREETING": "¡Hola!",
"VERIFICATION_EMAIL_PARAGRAPH_1": "Bienvenido a TellForm. Aquí hay un enlace especial para activar su nueva cuenta:",
"VERIFICATION_EMAIL_LINK_TEXT": "Activar mi cuenta",
"VERIFICATION_EMAIL_PARAGRAPH_2": "¡Muchas gracias por utilizar nuestros servicios! Si tiene alguna pregunta o sugerencia, no dude en enviarnos un correo electrónico aquí",
"VERIFICATION_EMAIL_SUBJECT": "¡Active su nueva cuenta TellForm!",
"VERIFICATION_EMAIL_TEXT": "Verifique su cuenta haciendo clic en el siguiente enlace, o copiándolo y pegándolo en su navegador: $ {URL}",
"EMAIL_SIGNATURE": "- El equipo de TellForm",
"WELCOME_EMAIL_PARAGRAPH_1": "¡Nos gustaría darle la bienvenida como nuestro miembro más nuevo!",
"WELCOME_EMAIL_PARAGRAPH_2": "Esperamos que disfrute utilizando TellForm. Si tiene algún problema, no dude en enviarnos un correo electrónico aquí",
"WELCOME_EMAIL_SUBJECT": "¡Bienvenido a %s!",
"WELCOME_EMAIL_TEXT": "Su cuenta ha sido verificada con éxito",
"RESET_PASSWORD_CONFIRMATION_EMAIL_PARAGRAPH_1": "Este es un mensaje de cortesía para confirmar que su contraseña acaba de cambiarse",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_1": "Aquí hay un enlace especial que le permitirá restablecer su contraseña. Tenga en cuenta que caducará en una hora para su protección:",
"RESET_PASSWORD_REQUEST_EMAIL_LINK_TEXT": "Restablecer su contraseña",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_2": "Si no lo solicitó, ignore este correo electrónico y su contraseña no cambiará".
}

21
config/locales/fr.json Normal file
View file

@ -0,0 +1,21 @@
{
"404_HEADER": "404 - Page non trouvée",
"500_HEADER": "500 - Erreur interne du serveur",
"404_BODY": "%s n'est pas un chemin valide.",
"500_BODY": "Une erreur inattendue semble s'être produite, pourquoi ne pas essayer d'actualiser votre page? Ou vous pouvez nous contacter si le problème persiste.",
"EMAIL_GREETING": "Bonjour!",
"VERIFICATION_EMAIL_PARAGRAPH_1": "Bienvenue sur TellForm! Voici un lien spécial pour activer votre nouveau compte:",
"VERIFICATION_EMAIL_LINK_TEXT": "Activer mon compte",
"VERIFICATION_EMAIL_PARAGRAPH_2": "Merci beaucoup pour l'utilisation de nos services! Si vous avez des questions ou des suggestions, n'hésitez pas à nous envoyer un courriel ici",
"VERIFICATION_EMAIL_SUBJECT": "¡Active su nueva cuenta TellForm!",
"VERIFICATION_EMAIL_TEXT": "Verifique su cuenta haciendo clic en el siguiente enlace, o copiándolo y pegándolo en su navegador: $ {URL}",
"EMAIL_SIGNATURE": "- L'équipe TellForm",
"WELCOME_EMAIL_PARAGRAPH_1": "Nous aimerions vous accueillir en tant que nouveau membre!",
"WELCOME_EMAIL_PARAGRAPH_2": "Nous espérons que vous apprécierez l'utilisation de TellForm! Si vous avez des problèmes, n'hésitez pas à nous envoyer un e-mail ici",
"WELCOME_EMAIL_SUBJECT": "Bienvenue dans %s!",
"WELCOME_EMAIL_TEXT": "Votre compte a été vérifié avec succès.",
"RESET_PASSWORD_CONFIRMATION_EMAIL_PARAGRAPH_1": "Ceci est un message de courtoisie pour confirmer que votre mot de passe a été modifié.",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_1": "Voici un lien spécial qui vous permettra de réinitialiser votre mot de passe Veuillez noter qu'il expirera dans une heure pour votre protection:",
"RESET_PASSWORD_REQUEST_EMAIL_LINK_TEXT": "Réinitialiser votre mot de passe",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_2": "Si vous ne l'avez pas demandé, veuillez ignorer cet e-mail et votre mot de passe restera inchangé."
}

21
config/locales/it.json Normal file
View file

@ -0,0 +1,21 @@
{
"404_HEADER": "404 - Pagina non trovata",
"500_HEADER": "500 - Errore Server Interno",
"404_BODY": "%s non è un percorso valido",
"500_BODY": "Si è verificato un errore imprevisto: perché non provare a rinfrescare la tua pagina oppure puoi contattarci se il problema persiste",
"EMAIL_GREETING": "Ciao!",
"VERIFICATION_EMAIL_PARAGRAPH_1": "Benvenuti a TellForm! Ecco un collegamento speciale per attivare il tuo nuovo account:",
"VERIFICATION_EMAIL_LINK_TEXT": "Attiva il mio account",
"VERIFICATION_EMAIL_PARAGRAPH_2": "Grazie mille per l'utilizzo dei nostri servizi! Se hai domande o suggerimenti, non esitate a contattarci via",
"VERIFICATION_EMAIL_SUBJECT": "Attiva il tuo nuovo account TellForm",
"VERIFICATION_EMAIL_TEXT": "Verifica il tuo account facendo clic sul seguente collegamento o copiandolo e incollandolo nel tuo browser: $ {URL}",
"EMAIL_SIGNATURE": "- Il team TellForm",
"WELCOME_EMAIL_PARAGRAPH_1": "Vorremmo darVi il benvenuto come il nostro nuovo membro!",
"WELCOME_EMAIL_PARAGRAPH_2": "Speriamo che ti piace usare TellForm! Se hai problemi, non esitate a contattarci via",
"WELCOME_EMAIL_SUBJECT": "Benvenuto a %s!",
"WELCOME_EMAIL_TEXT": "Il tuo account è stato verificato correttamente.",
"RESET_PASSWORD_CONFIRMATION_EMAIL_PARAGRAPH_1": "Si tratta di un messaggio di cortesia per confermare che la password è stata appena modificata".
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_1": "Ecco un collegamento speciale che ti permetterà di reimpostare la tua password. Si prega di notare che scadrà in un'ora per la protezione:",
"RESET_PASSWORD_REQUEST_EMAIL_LINK_TEXT": "Ripristina la tua password",
"RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_2": "Se non l'hai richiesta, ignora questa email e la tua password rimane invariata."
}

View file

@ -14,9 +14,11 @@ module.exports = function () {
passwordField: 'password'
},
function (username, password, done) {
console.log('\n\n\n\n\nusername: '+username);
console.log('password: '+password)
User.findOne({
$or: [
{'username': username},
{'username': username.toLowerCase()},
{'email': username}
]
}, function (err, user) {

View file

@ -23,11 +23,11 @@ module.exports = function(grunt) {
// Unified Watch Object
var watchFiles = {
serverViews: ['app/views/**/*.*'],
serverViews: ['app/views/**/*.pug'],
serverJS: ['gruntfile.js', 'server.js', 'config/**/*.js', 'app/**/*.js', '!app/tests/'],
clientViews: ['public/modules/**/*.html', 'public/form_modules/forms/base/**/*.html', '!public/modules/forms/base/**/*.html',],
clientJS: ['public/js/*.js', 'public/form_modules/**/*.js', 'public/modules/**/*.js'],
clientJS: ['public/form_modules/**/*.js', 'public/modules/**/*.js'],
clientCSS: ['public/modules/**/*.css'],
serverTests: ['app/tests/**/*.js'],
@ -145,10 +145,14 @@ module.exports = function(grunt) {
}
},
ngAnnotate: {
options:{
add: true,
remove: true
},
production: {
files: {
'public/dist/application.js': '<%= applicationJavaScriptFiles %>',
'public/dist/form-application.js': '<%= formApplicationJavaScriptFiles %>'
'public/dist/application.js': ['public/application.js', 'public/config.js', 'public/form_modules/**/*.js'],
'public/dist/form_application.js': ['public/form-application.js', 'public/form-config.js', 'public/form_modules/**/*.js']
}
}
},
@ -291,7 +295,7 @@ module.exports = function(grunt) {
target: {
src: ['./scripts/setup.js']
}
}
},
});
grunt.event.on('coverage', function(lcov, done){
@ -335,7 +339,7 @@ module.exports = function(grunt) {
grunt.registerTask('secure', ['env:secure', 'lint', 'html2js:main', 'html2js:forms', 'concurrent:default']);
// Lint task(s).
grunt.registerTask('lint', ['jshint', 'csslint']);
grunt.registerTask('lint', ['jshint', 'csslint', 'i18nlint:client', 'i18nlint:server']);
grunt.registerTask('lint:tests', ['jshint:allTests']);
// Build task(s).

View file

@ -2,7 +2,7 @@
"name": "TellForm",
"description": "Opensource alternative to TypeForm",
"version": "2.1.0",
"homepage": "https://github.com/whitef0x0/tellform",
"homepage": "https://github.com/tellform/tellform",
"authors": [
"David Baldwynn <polydaic@gmail.com> (http://baldwynn.me)"
],
@ -10,7 +10,7 @@
"private": true,
"repository": {
"type": "git",
"url": "https://github.com/whitef0x0/tellform.git"
"url": "https://github.com/tellform/tellform.git"
},
"engines": {
"node": "6.x.x",
@ -19,8 +19,8 @@
"scripts": {
"addcontrib": "all-contributors add",
"generate": "all-contributors generate",
"start": "npm run version && grunt",
"test": "npm run version && grunt test",
"start": "grunt",
"test": "grunt test",
"postinstall": "bower install --config.interactive=false; grunt build;",
"init": "node scripts/setup.js"
},
@ -33,11 +33,11 @@
"compression": "~1.6.0",
"connect": "^3.4.1",
"connect-mongo": "~0.8.2",
"consolidate": "~0.13.1",
"consolidate": "~0.14.5",
"cookie-parser": "~1.4.0",
"deep-diff": "^0.3.4",
"dotenv": "^2.0.0",
"email-verification": "~0.4.1",
"email-verification": "github:tellform/node-email-verification",
"express": "~4.13.3",
"express-session": "~1.12.1",
"glob": "^7.0.3",
@ -51,6 +51,7 @@
"grunt-html2js": "~0.3.5",
"grunt-ng-annotate": "~1.0.1",
"helmet": "3.5.0",
"i18n": "^0.8.3",
"jit-grunt": "^0.9.1",
"lodash": "^4.17.4",
"main-bower-files": "~2.9.0",
@ -65,6 +66,7 @@
"passport-localapikey-update": "^0.5.0",
"path-exists": "^2.1.0",
"prerender-node": "^2.2.1",
"pug": "^2.0.0-rc.4",
"random-js": "^1.0.8",
"raven": "^0.9.0",
"request": "^2.83.0",
@ -87,14 +89,15 @@
"grunt-contrib-concat": "^1.0.1",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-uglify": "^0.11.1",
"grunt-contrib-watch": "~0.6.1",
"grunt-execute": "^0.2.2",
"grunt-i18nlint": "github:jwarby/grunt-i18nlint",
"grunt-karma": "~0.12.1",
"grunt-mocha-istanbul": "^3.0.1",
"grunt-mocha-test": "~0.12.1",
"grunt-contrib-watch": "~0.6.1",
"grunt-newer": "~1.1.1",
"grunt-usemin": "^3.1.1",
"grunt-karma": "~0.12.1",
"grunt-nodemon": "~0.4.0",
"grunt-usemin": "^3.1.1",
"grunt-wiredep": "^3.0.1",
"istanbul": "^0.4.0",
"jasmine-core": "^2.4.1",

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,9 +1,9 @@
angular.module('TellForm-Form.form_templates', []).run(['$templateCache', function($templateCache) {
"use strict";
$templateCache.put("form_modules/forms/base/views/form-not-found.client.view.html",
"<script>$(\".loader\").fadeOut(\"slow\");</script><section class=\"public-form auth sigin-view valign-wrapper\"><div class=\"row valign\"><h3 class=\"col-md-12 text-center\">404 - Form Does not Exist</h3><div class=\"col-md-4 col-md-offset-4\"><div class=\"col-md-12 text-center\" style=\"padding-bottom: 50px\">The form you are trying to access does not exist. Sorry about that!</div></div></div></section>");
"<script>$(\".loader\").fadeOut(\"slow\");</script><section class=\"public-form auth sigin-view valign-wrapper\"><div class=\"row valign\"><h3 class=\"col-md-12 text-center\">{{ 'FORM_404_HEADER' | translate }}</h3><div class=\"col-md-4 col-md-offset-4\"><div class=\"col-md-12 text-center\" style=\"padding-bottom: 50px\">{{ 'FORM_404_BODY' | translate }}</div></div></div></section>");
$templateCache.put("form_modules/forms/base/views/form-unauthorized.client.view.html",
"<script>$(\".loader\").fadeOut(\"slow\");</script><section class=\"public-form auth sigin-view valign-wrapper\"><div class=\"row valign\"><h3 class=\"col-md-12 text-center\">Not Authorized to Access Form</h3><div class=\"col-md-4 col-md-offset-4\"><div class=\"col-md-12 text-center\" style=\"padding-bottom: 50px\">The form you are trying to access is currently private and not accesible publically.<br>If you are the owner of the form, you can set it to \"Public\" in the \"Configuration\" panel in the form admin.</div></div></div></section>");
"<script>$(\".loader\").fadeOut(\"slow\");</script><section class=\"public-form auth sigin-view valign-wrapper\"><div class=\"row valign\"><h3 class=\"col-md-12 text-center\">{{ 'FORM_UNAUTHORIZED_HEADER' | translate }}</h3><div class=\"col-md-4 col-md-offset-4\"><div class=\"col-md-12 text-center\" style=\"padding-bottom: 50px\">{{ 'FORM_UNAUTHORIZED_BODY1' | translate }}<br>{{ 'FORM_UNAUTHORIZED_BODY2' | translate }}</div></div></div></section>");
$templateCache.put("form_modules/forms/base/views/submit-form.client.view.html",
"<section class=public-form><submit-form-directive myform=myform></submit-form-directive></section><script ng-if=myform.analytics.gaCode>window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;\n" +
" ga('create', '{{myform.analytics.gaCode}}', 'auto'); ga('send', 'pageview');</script><script ng-if=myform.analytics.gaCode src=https://www.google-analytics.com/analytics.js async defer></script>");
@ -12,11 +12,11 @@ angular.module('TellForm-Form.form_templates', []).run(['$templateCache', functi
$templateCache.put("form_modules/forms/base/views/directiveViews/field/date.html",
"<div class=\"field row\" ng-click=\"setActiveField(field._id, index, true)\"><div class=\"col-xs-12 field-title\" ng-style=\"{'color': design.colors.questionColor}\"><h3><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=\"!field.required && !field.fieldValue\">{{ 'OPTIONAL' | translate }}</span></h3><p class=col-xs-12><small>{{field.description}}</small></p></div><div class=\"col-xs-12 field-input\"><div class=\"control-group input-append\"><input class=focusOn ng-focus=\"setActiveField(field._id, null, false)\" ng-style=\"{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}\" ng-class=\"{ 'no-border': !!field.fieldValue }\" ui-date=dateOptions ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required placeholder=MM/DD/YYYY on-tab-key=nextField() on-tab-and-shift-key=prevField() ng-change=nextField()></div></div></div>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/dropdown.html",
"<div class=\"field row dropdown\" ng-if=\"field.fieldOptions.length > 0\"><div class=\"col-xs-12 field-title\" ng-style=\"{'color': design.colors.questionColor}\"><h3><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>{{ 'OPTIONAL' | translate }}</span></h3><p class=col-xs-12><small>{{field.description}}</small></p></div><div class=\"col-xs-12 field-input\"><ui-select ng-model=field.fieldValue ng-focus=\"setActiveField(field._id, null, false)\" theme=selectize search-enabled=true search-by=option_value set-search-to-answer=true ng-required=field.required on-tab-and-shift-key=prevField() on-tab-key=nextField() ng-change=nextField()><ui-select-match placeholder=\"Type or select an option\"></ui-select-match><ui-select-choices repeat=\"option in field.fieldOptions | filter: $select.search\" ng-class=\"{'active': option.option_value === field.fieldValue }\"><span ng-bind-html=\"option.option_value | highlight: $select.search\"></span></ui-select-choices></ui-select></div></div><br>");
"<div class=\"field row dropdown\" ng-if=\"field.fieldOptions.length > 0\"><div class=\"col-xs-12 field-title\" ng-style=\"{'color': design.colors.questionColor}\"><h3><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>{{ 'OPTIONAL' | translate }}</span></h3><p class=col-xs-12><small>{{field.description}}</small></p></div><div class=\"col-xs-12 field-input\"><ui-select ng-model=field.fieldValue ng-focus=\"setActiveField(field._id, null, false)\" theme=selectize search-enabled=true search-by=option_value set-search-to-answer=true ng-required=field.required on-tab-and-shift-key=prevField() on-tab-key=nextField() ng-change=nextField()><ui-select-match placeholder=\"{{ 'OPTION_PLACEHOLDER' | translate }}\"></ui-select-match><ui-select-choices repeat=\"option in field.fieldOptions | filter: $select.search\" ng-class=\"{'active': option.option_value === field.fieldValue }\"><span ng-bind-html=\"option.option_value | highlight: $select.search\"></span></ui-select-choices></ui-select></div></div><br>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/hidden.html",
"<input type=hidden>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/legal.html",
"<div class=\"field row radio legal\" on-enter-or-tab-key=nextField() on-tab-and-shift-key=prevField() key-to-truthy key-char-truthy=y key-char-falsey=n field=field on-valid-key=nextField()><div class=\"col-xs-12 field-title\" ng-style=\"{'color': design.colors.questionColor}\"><h3><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>{{ 'OPTIONAL' | translate }}</span></h3><br><p class=col-xs-12>{{field.description}}</p></div><div class=\"col-xs-12 field-input container\"><div class=row-fluid><label class=\"btn col-md-5 col-xs-12\" ng-class=\"{activeBtn: field.fieldValue == 'true'}\"><input class=focusOn ng-style=\"{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}\" type=radio value=true ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required ng-change=\"nextField()\"><div class=letter style=float:left>Y</div><span>{{ 'LEGAL_ACCEPT' | translate }}</span></label><label class=\"btn col-md-5 col-md-offset-1 col-xs-12\" ng-class=\"{activeBtn: field.fieldValue == 'false'}\"><input class=focusOn ng-style=\"{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}\" type=radio value=false ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required ng-change=\"nextField()\"><div class=letter style=float:left>N</div><span>{{ 'LEGAL_NO_ACCEPT' | translate }}</span></label></div></div></div><br>");
"<div class=\"field row radio legal\" on-enter-or-tab-key=nextField() on-tab-and-shift-key=prevField() key-to-truthy key-char-truthy=y key-char-falsey=n field=field on-valid-key=nextField()><div class=\"col-xs-12 field-title\" ng-style=\"{'color': design.colors.questionColor}\"><h3><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>{{ 'OPTIONAL' | translate }}</span></h3><br><p class=col-xs-12>{{field.description}}</p></div><div class=\"col-xs-12 field-input container\"><div class=row-fluid><label class=\"btn col-md-5 col-xs-12\" ng-class=\"{activeBtn: field.fieldValue == 'true'}\"><input class=focusOn ng-style=\"{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}\" type=radio value=true ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required ng-change=\"nextField()\"><div class=letter style=float:left>{{ 'Y' | translate }}</div><span>{{ 'LEGAL_ACCEPT' | translate }}</span></label><label class=\"btn col-md-5 col-md-offset-1 col-xs-12\" ng-class=\"{activeBtn: field.fieldValue == 'false'}\"><input class=focusOn ng-style=\"{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}\" type=radio value=false ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required ng-change=\"nextField()\"><div class=letter style=float:left>{{ 'N' | translate }}</div><span>{{ 'LEGAL_NO_ACCEPT' | translate }}</span></label></div></div></div><br>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/radio.html",
"<div class=\"field row radio\" on-enter-or-tab-key=nextField() on-tab-and-shift-key=prevField() key-to-option field=field ng-if=\"field.fieldOptions.length > 0\"><div class=\"col-xs-12 field-title\" ng-style=\"{'color': design.colors.questionColor}\"><h3><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>{{ 'OPTIONAL' | translate }}</span></h3><p class=col-xs-12><small>{{field.description}}</small></p></div><div class=\"col-xs-12 field-input\"><div ng-repeat=\"option in field.fieldOptions\" class=row-fluid><label class=\"btn col-md-4 col-xs-12 col-sm-12\" style=\"margin: 0.5em; padding-left:30px\" ng-class=\"{activeBtn: field.fieldValue == field.fieldOptions[$index].option_value}\"><div class=letter style=float:left>{{$index+1}}</div><input ng-style=\"{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}\" ng-focus=\"setActiveField(field._id, null, false)\" type=radio class=focusOn value={{option.option_value}} ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required ng-change=\"$root.nextField()\"> <span ng-bind=option.option_value></span></label></div></div></div><br>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/rating.html",
@ -24,10 +24,10 @@ angular.module('TellForm-Form.form_templates', []).run(['$templateCache', functi
$templateCache.put("form_modules/forms/base/views/directiveViews/field/statement.html",
"<div class=\"statement field row\" on-enter-or-tab-key=nextField() on-tab-and-shift-key=prevField()><div class=\"row field-title field-title\"><div class=col-xs-1><i class=\"fa fa-quote-left fa-1\"></i></div><h2 class=\"text-left col-xs-9\">{{field.title}}</h2><p class=col-xs-12><small>{{field.description}}</small></p></div><div class=\"row field-title field-input\"><p class=col-xs-12 ng-if=field.description.length>{{field.description}}</p><br><div class=\"col-xs-offset-1 col-xs-11\"><button class=\"btn focusOn\" ng-style=\"{'font-size': '1.3em', 'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}\" ng-click=nextField()>{{ 'CONTINUE' | translate }}</button></div></div></div>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/textarea.html",
"<div class=\"field row\" ng-click=\"setActiveField(field._id, index, true)\"><div class=\"col-xs-12 field-title\" ng-style=\"{'color': design.colors.questionColor}\"><h3><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>{{ 'OPTIONAL' | translate }}</span></h3><small>{{ 'NEWLINE' | translate }}</small><p><small>{{field.description}}</small></p></div><div class=\"col-xs-12 field-input\"><small style=font-size:0.6em>Press SHIFT+ENTER to add a newline</small><textarea class=\"textarea focusOn\" type=text ng-focus=\"setActiveField(field._id, null, false)\" ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-class=\"{ 'no-border': !!field.fieldValue }\" value={{field.fieldValue}} ng-required=field.required on-enter-or-tab-key=nextField() on-tab-and-shift-key=prevField() style=\"border: none; border-left: lightgrey dashed 2px\">\n" +
"<div class=\"field row\" ng-click=\"setActiveField(field._id, index, true)\"><div class=\"col-xs-12 field-title\" ng-style=\"{'color': design.colors.questionColor}\"><h3><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>{{ 'OPTIONAL' | translate }}</span></h3><small>{{ 'NEWLINE' | translate }}</small><p><small>{{field.description}}</small></p></div><div class=\"col-xs-12 field-input\"><small style=font-size:0.6em>{{ 'ADD_NEW_LINE_INSTR' | translate }}</small><textarea class=\"textarea focusOn\" type=text ng-focus=\"setActiveField(field._id, null, false)\" ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-class=\"{ 'no-border': !!field.fieldValue }\" value={{field.fieldValue}} ng-required=field.required on-enter-or-tab-key=nextField() on-tab-and-shift-key=prevField() style=\"border: none; border-left: lightgrey dashed 2px\">\n" +
" </textarea></div></div><div><div class=\"btn btn-lg btn-default\" style=\"padding: 4px; margin-top:8px; background: rgba(255,255,255,0.5)\"><button ng-disabled=\"!field.fieldValue || forms.myForm.{{field.fieldType}}{{$index}}.$invalid\" ng-style=\"{'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}\" ng-click=$root.nextField() class=\"btn col-sm-5 col-xs-5\">{{ 'OK' | translate }} <i class=\"fa fa-check\"></i></button><div class=\"col-sm-3 col-xs-6\" style=margin-top:0.2em><small style=\"color:#ddd; font-size:70%\">{{ 'ENTER' | translate }}</small></div></div></div>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/textfield.html",
"<div class=\"textfield field row\" ng-click=\"setActiveField(field._id, index, true)\"><div class=\"col-xs-12 field-title row-fluid\" ng-style=\"{'color': design.colors.questionColor}\"><h3 class=col-xs-12><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>({{ 'OPTIONAL' | translate }})</span></h3><p class=col-xs-12><small>{{field.description}}</small></p></div><div class=\"col-xs-12 field-input\"><input ng-style=\"{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}\" name={{field.fieldType}}{{index}} type={{input_type}} ng-pattern=validateRegex placeholder={{placeholder}} ng-class=\"{ 'no-border': !!field.fieldValue }\" class=\"focusOn text-field-input\" ng-focus=\"setActiveField(field._id, null, false)\" ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" value=field.fieldValue on-enter-or-tab-key=nextField() on-tab-and-shift-key=prevField() ng-required=field.required aria-describedby=\"inputError2Status\"></div><div class=col-xs-12><div ng-show=\"forms.myForm.{{field.fieldType}}{{index}}.$invalid && !!forms.myForm.{{field.fieldType}}{{index}}.$viewValue \" class=\"alert alert-danger\" role=alert><span class=\"glyphicon glyphicon-exclamation-sign\" aria-hidden=true></span> <span class=sr-only>Error:</span> <span ng-if=\"field.fieldType == 'email'\">{{ 'ERROR_EMAIL_INVALID' | translate }}</span> <span ng-if=\"field.fieldType == 'number'\">{{ 'ERROR_NOT_A_NUMBER' | translate }}</span> <span ng-if=\"field.fieldType == 'link'\">{{ 'ERROR_URL_INVALID' | translate }}</span></div></div></div><div><div class=\"btn btn-lg btn-default\" ng-disabled=\"!field.fieldValue || field.$invalid\" style=\"padding: 4px; margin-top:8px; background: rgba(255,255,255,0.5)\"><button ng-disabled=\"!field.fieldValue || field.$invalid\" ng-style=\"{'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}\" ng-click=nextField() class=\"btn col-sm-5 col-xs-5\">{{ 'OK' | translate }} <i class=\"fa fa-check\"></i></button><div class=\"col-xs-6 col-sm-3\" style=margin-top:0.2em><small style=\"color:#ddd; font-size:70%\">{{ 'ENTER' | translate }}</small></div></div></div>");
"<div class=\"textfield field row\" ng-click=\"setActiveField(field._id, index, true)\"><div class=\"col-xs-12 field-title row-fluid\" ng-style=\"{'color': design.colors.questionColor}\"><h3 class=col-xs-12><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>({{ 'OPTIONAL' | translate }})</span></h3><p class=col-xs-12><small>{{field.description}}</small></p></div><div class=\"col-xs-12 field-input\"><input ng-style=\"{'color': design.colors.answerColor, 'border-color': design.colors.answerColor}\" name={{field.fieldType}}{{index}} type={{input_type}} ng-pattern=validateRegex placeholder={{placeholder}} ng-class=\"{ 'no-border': !!field.fieldValue }\" class=\"focusOn text-field-input\" ng-focus=\"setActiveField(field._id, null, false)\" ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" value=field.fieldValue on-enter-or-tab-key=nextField() on-tab-and-shift-key=prevField() ng-required=field.required aria-describedby=\"inputError2Status\"></div><div class=col-xs-12><div ng-show=\"forms.myForm.{{field.fieldType}}{{index}}.$invalid && !!forms.myForm.{{field.fieldType}}{{index}}.$viewValue \" class=\"alert alert-danger\" role=alert><span class=\"glyphicon glyphicon-exclamation-sign\" aria-hidden=true></span> <span class=sr-only>{{ 'ERROR' | translate }}:</span> <span ng-if=\"field.fieldType == 'email'\">{{ 'ERROR_EMAIL_INVALID' | translate }}</span> <span ng-if=\"field.fieldType == 'number'\">{{ 'ERROR_NOT_A_NUMBER' | translate }}</span> <span ng-if=\"field.fieldType == 'link'\">{{ 'ERROR_URL_INVALID' | translate }}</span></div></div></div><div><div class=\"btn btn-lg btn-default\" ng-disabled=\"!field.fieldValue || field.$invalid\" style=\"padding: 4px; margin-top:8px; background: rgba(255,255,255,0.5)\"><button ng-disabled=\"!field.fieldValue || field.$invalid\" ng-style=\"{'background-color':design.colors.buttonColor, 'color':design.colors.buttonTextColor}\" ng-click=nextField() class=\"btn col-sm-5 col-xs-5\">{{ 'OK' | translate }} <i class=\"fa fa-check\"></i></button><div class=\"col-xs-6 col-sm-3\" style=margin-top:0.2em><small style=\"color:#ddd; font-size:70%\">{{ 'ENTER' | translate }}</small></div></div></div>");
$templateCache.put("form_modules/forms/base/views/directiveViews/field/yes_no.html",
"<div class=\"field row radio\" ng-click=\"setActiveField(field._id, index, true)\" key-to-truthy key-char-truthy=y key-char-falsey=n field=field on-tab-key=nextField() on-tab-and-shift-key=prevField() on-valid-key=nextField()><div class=\"col-xs-12 field-title\" ng-style=\"{'color': design.colors.questionColor}\"><h3 class=row><small class=field-number>{{index+1}} <i class=\"fa fa-angle-double-right\" aria-hidden=true></i></small> {{field.title}} <span class=required-error ng-show=!field.required>{{ 'OPTIONAL' | translate }}</span></h3><p class=row>{{field.description}}</p></div><div class=\"col-xs-12 field-input\"><div class=row><label class=\"btn btn-default col-md-2 col-sm-3 col-xs-7\" style=\"background: rgba(0,0,0,0.1); text-align:left\"><input type=radio value=true class=focusOn style=\"opacity: 0; margin-left: 0px\" ng-focus=\"setActiveField(field._id, null, false)\" ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required ng-change=\"nextField()\"><div class=letter>{{ 'Y' | translate }}</div><span>{{ 'YES' | translate }}</span> <i ng-show=\"field.fieldValue === 'true'\" class=\"fa fa-check\" aria-hidden=true></i></label></div><div class=row style=\"margin-top: 10px\"><label class=\"btn btn-default col-md-2 col-sm-3 col-xs-7\" style=\"background: rgba(0,0,0,0.1); text-align:left\"><input type=radio value=false style=\"opacity:0; margin-left:0px\" ng-focus=\"setActiveField(field._id, null, false)\" ng-model=field.fieldValue ng-model-options=\"{ debounce: 250 }\" ng-required=field.required ng-change=\"nextField()\"><div class=letter>{{ 'N' | translate }}</div><span>{{ 'NO' | translate }}</span> <i ng-show=\"field.fieldValue === 'false'\" class=\"fa fa-check\" aria-hidden=true></i></label></div></div></div><br>");
$templateCache.put("form_modules/forms/base/views/directiveViews/form/submit-form.client.view.html",

View file

@ -2,7 +2,7 @@
angular.module('view-form').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('english', {
$translateProvider.translations('en', {
FORM_SUCCESS: 'Form entry successfully submitted!',
REVIEW: 'Review',
BACK_TO_FORM: 'Go back to Form',
@ -28,10 +28,22 @@ angular.module('view-form').config(['$translateProvider', function ($translatePr
CANCEL: 'Cancel',
SUBMIT: 'Submit',
UPLOAD_FILE: 'Upload your File',
Y: 'Y',
N: 'N',
OPTION_PLACEHOLDER: 'Type or select an option',
ADD_NEW_LINE_INSTR: 'Press SHIFT+ENTER to add a newline',
ERROR: 'Error',
FORM_404_HEADER: '404 - Form Does Not Exist',
FORM_404_BODY: 'The form you are trying to access does not exist. Sorry about that!',
FORM_UNAUTHORIZED_HEADER: 'Not Authorized to Access Form',
FORM_UNAUTHORIZED_BODY1: 'The form you are trying to access is currently private and not accesible publically.',
FORM_UNAUTHORIZED_BODY2: 'If you are the owner of the form, you can set it to "Public" in the "Configuration" panel in the form admin.',
});
$translateProvider.preferredLanguage('english')
.fallbackLanguage('english')
$translateProvider.preferredLanguage('en')
.fallbackLanguage('en')
.useSanitizeValueStrategy('escape');
}]);

View file

@ -2,7 +2,7 @@
angular.module('view-form').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('french', {
$translateProvider.translations('fr', {
FORM_SUCCESS: 'Votre formulaire a été enregistré!',
REVIEW: 'Incomplet',
BACK_TO_FORM: 'Retourner au formulaire',
@ -30,6 +30,16 @@ angular.module('view-form').config(['$translateProvider', function ($translatePr
UPLOAD_FILE: 'Envoyer un fichier',
Y: 'O',
N: 'N',
OPTION_PLACEHOLDER: 'Tapez ou sélectionnez une option',
ADD_NEW_LINE_INSTR: 'Appuyez sur MAJ + ENTRÉE pour ajouter une nouvelle ligne',
ERROR: 'Erreur',
FORM_404_HEADER: '404 - Le formulaire n\'existe pas',
FORM_404_BODY: 'Le formulaire auquel vous essayez d\'accéder n\'existe pas. Désolé pour ça!',
FORM_UNAUTHORIZED_HEADER: 'Non autorisé à accéder au formulaire',
   FORM_UNAUTHORIZED_BODY1: 'Le formulaire auquel vous essayez d\'accéder est actuellement privé et inaccessible publiquement.',
   FORM_UNAUTHORIZED_BODY2: 'Si vous êtes le propriétaire du formulaire, vous pouvez le définir sur "Public" dans le panneau "Configuration" du formulaire admin.',
});
}]);

View file

@ -2,12 +2,12 @@
angular.module('view-form').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('german', {
$translateProvider.translations('de', {
FORM_SUCCESS: 'Ihre Angaben wurden gespeichert.',
REVIEW: 'Unvollständig',
BACK_TO_FORM: 'Zurück zum Formular',
EDIT_FORM: '',
CREATE_FORM: '',
EDIT_FORM: 'Bearbeiten Sie diese TellForm',
CREATE_FORM: 'Dieses TellForm erstellen',
ADVANCEMENT: '{{done}} von {{total}} beantwortet',
CONTINUE_FORM: 'Zum Formular',
REQUIRED: 'verpflichtend',
@ -30,6 +30,16 @@ angular.module('view-form').config(['$translateProvider', function ($translatePr
UPLOAD_FILE: 'Datei versenden',
Y: 'J',
N: 'N',
OPTION_PLACEHOLDER: 'Geben oder wählen Sie eine Option aus',
ADD_NEW_LINE_INSTR: 'Drücken Sie UMSCHALT + EINGABETASTE, um eine neue Zeile hinzuzufügen',
ERROR: 'Fehler',
FORM_404_HEADER: '404 - Formular existiert nicht',
FORM_404_BODY: 'Das Formular, auf das Sie zugreifen möchten, existiert nicht. Das tut mir leid!',
FORM_UNAUTHORIZED_HEADER: 'Nicht zum Zugriffsformular berechtigt\' ',
   FORM_UNAUTHORIZED_BODY1: 'Das Formular, auf das Sie zugreifen möchten, ist derzeit privat und nicht öffentlich zugänglich.',
   FORM_UNAUTHORIZED_BODY2: 'Wenn Sie der Eigentümer des Formulars sind, können Sie es im Fenster "Konfiguration" im Formular admin auf "Öffentlich" setzen.',
});
}]);

View file

@ -2,12 +2,12 @@
angular.module('view-form').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('italian', {
$translateProvider.translations('it', {
FORM_SUCCESS: 'Il formulario è stato inviato con successo!',
REVIEW: 'Incompleto',
BACK_TO_FORM: 'Ritorna al formulario',
EDIT_FORM: '',
CREATE_FORM: '',
EDIT_FORM: 'Modifica questo TellForm',
CREATE_FORM: 'Crea questo TellForm',
ADVANCEMENT: '{{done}} su {{total}} completate',
CONTINUE_FORM: 'Vai al formulario',
REQUIRED: 'obbligatorio',
@ -30,6 +30,16 @@ angular.module('view-form').config(['$translateProvider', function ($translatePr
UPLOAD_FILE: 'Invia un file',
Y: 'S',
N: 'N',
OPTION_PLACEHOLDER: 'Digitare o selezionare un\'opzione',
ADD_NEW_LINE_INSTR: 'Premere SHIFT + INVIO per aggiungere una nuova riga',
ERROR: 'Errore',
FORM_404_HEADER: '404 - Il modulo non esiste',
FORM_404_BODY: 'La forma che stai cercando di accedere non esiste. Ci dispiace!',
FORM_UNAUTHORIZED_HEADER: 'Non autorizzato per accedere al modulo',
   FORM_UNAUTHORIZED_BODY1: 'Il modulo che si sta tentando di accedere è attualmente privato e non accessibile in pubblico.',
   FORM_UNAUTHORIZED_BODY2: 'Se sei il proprietario del modulo, puoi impostarlo su "Pubblico" nel pannello "Configurazione" nell\'amministratore di moduli.',
});
}]);

View file

@ -2,34 +2,44 @@
angular.module('view-form').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('spanish', {
FORM_SUCCESS: '¡El formulario ha sido enviado con éxito!',
REVIEW: 'Revisar',
BACK_TO_FORM: 'Regresar al formulario',
EDIT_FORM: '',
CREATE_FORM: '',
ADVANCEMENT: '{{done}} de {{total}} contestadas',
CONTINUE_FORM: 'Continuar al formulario',
REQUIRED: 'Información requerida',
COMPLETING_NEEDED: '{{answers_not_completed}} respuesta(s) necesita(n) ser completada(s)',
OPTIONAL: 'Opcional',
ERROR_EMAIL_INVALID: 'Favor de proporcionar un correo electrónico válido',
ERROR_NOT_A_NUMBER: 'Por favor, introduzca sólo números válidos',
ERROR_URL_INVALID: 'Favor de proporcionar un url válido',
OK: 'OK',
ENTER: 'pulse INTRO',
YES: 'Si',
NO: 'No',
NEWLINE: 'presione SHIFT+INTRO para crear una nueva línea',
CONTINUE: 'Continuar',
LEGAL_ACCEPT: 'Yo acepto',
LEGAL_NO_ACCEPT: 'Yo no acepto',
DELETE: 'Eliminar',
CANCEL: 'Cancelar',
SUBMIT: 'Registrar',
UPLOAD_FILE: 'Cargar el archivo',
Y: 'S',
N: 'N'
});
$translateProvider.translations('es', {
FORM_SUCCESS: '¡El formulario ha sido enviado con éxito!',
REVIEW: 'Revisar',
BACK_TO_FORM: 'Regresar al formulario',
EDIT_FORM: 'Editar este TellForm',
CREATE_FORM: 'Crear este TellForm',
ADVANCEMENT: '{{done}} de {{total}} contestadas',
CONTINUE_FORM: 'Continuar al formulario',
REQUIRED: 'Información requerida',
COMPLETING_NEEDED: '{{answers_not_completed}} respuesta(s) necesita(n) ser completada(s)',
OPTIONAL: 'Opcional',
ERROR_EMAIL_INVALID: 'Favor de proporcionar un correo electrónico válido',
ERROR_NOT_A_NUMBER: 'Por favor, introduzca sólo números válidos',
ERROR_URL_INVALID: 'Favor de proporcionar un url válido',
OK: 'OK',
ENTER: 'pulse INTRO',
YES: 'Si',
NO: 'No',
NEWLINE: 'presione SHIFT+INTRO para crear una nueva línea',
CONTINUE: 'Continuar',
LEGAL_ACCEPT: 'Yo acepto',
LEGAL_NO_ACCEPT: 'Yo no acepto',
DELETE: 'Eliminar',
CANCEL: 'Cancelar',
SUBMIT: 'Registrar',
UPLOAD_FILE: 'Cargar el archivo',
Y: 'S',
N: 'N',
OPTION_PLACEHOLDER: 'Escriba o seleccione una opción',
ADD_NEW_LINE_INSTR: 'Presione MAYÚS + ENTRAR para agregar una nueva línea',
ERROR: 'Error',
FORM_404_HEADER: '404 - La forma no existe',
FORM_404_BODY: 'El formulario al que intenta acceder no existe. ¡Lo siento por eso!',
FORM_UNAUTHORIZED_HEADER: 'Non autorizzato per accedere al modulo',
   FORM_UNAUTHORIZED_BODY1: 'Il modulo che si sta tentando di accedere è attualmente privato e non accessibile in pubblico.',
   FORM_UNAUTHORIZED_BODY2: 'Se sei il proprietario del modulo, puoi impostarlo su "Pubblico" nel pannello "Configurazione" nell\'amministratore di moduli.',
});
}]);

View file

@ -438,11 +438,11 @@ section.public-form .btn {
}
/*CREATE-NEW FORM MODAL*/
.form-item.create-new.new-form {
.form-item.new-form {
background-color: rgb(300,131,131);
z-index: 11;
}
.form-item.create-new.new-form:hover {
.form-item.new-form:hover {
background-color: rgb(300,100,100);
}
.form-item.new-form input[type='text'] {

View file

@ -24,7 +24,7 @@
on-tab-and-shift-key="prevField()"
on-tab-key="nextField()"
ng-change="nextField()">
<ui-select-match placeholder="Type or select an option">
<ui-select-match placeholder="{{ 'OPTION_PLACEHOLDER' | translate }}">
</ui-select-match>
<ui-select-choices repeat="option in field.fieldOptions | filter: $select.search"
ng-class="{'active': option.option_value === field.fieldValue }">

View file

@ -29,7 +29,7 @@
ng-required="field.required"
ng-change="nextField()"/>
<div class="letter" style="float:left">
Y
{{ 'Y' | translate }}
</div>
<span>{{ 'LEGAL_ACCEPT' | translate }}</span>
</label>
@ -43,7 +43,7 @@
ng-required="field.required"
ng-change="nextField()"/>
<div class="letter" style="float:left">
N
{{ 'N' | translate }}
</div>
<span>{{ 'LEGAL_NO_ACCEPT' | translate }}</span>
</label>

View file

@ -14,7 +14,9 @@
</p>
</div>
<div class="col-xs-12 field-input">
<small style="font-size:0.6em;">Press SHIFT+ENTER to add a newline</small>
<small style="font-size:0.6em;">
{{ 'ADD_NEW_LINE_INSTR' | translate }}
</small>
<textarea class="textarea focusOn" type="text"
ng-focus="setActiveField(field._id, null, false)"
ng-model="field.fieldValue"

View file

@ -38,7 +38,7 @@
<div class="col-xs-12">
<div ng-show="forms.myForm.{{field.fieldType}}{{index}}.$invalid && !!forms.myForm.{{field.fieldType}}{{index}}.$viewValue " class="alert alert-danger" role="alert">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<span class="sr-only">Error:</span>
<span class="sr-only">{{ 'ERROR' | translate }}:</span>
<span ng-if="field.fieldType == 'email'"> {{ 'ERROR_EMAIL_INVALID' | translate }} </span>
<span ng-if="field.fieldType == 'number'"> {{ 'ERROR_NOT_A_NUMBER' | translate }} </span>
<span ng-if="field.fieldType == 'link'"> {{ 'ERROR_URL_INVALID' | translate }} </span>

View file

@ -3,10 +3,12 @@ $(".loader").fadeOut("slow");
</script>
<section class="public-form auth sigin-view valign-wrapper">
<div class="row valign">
<h3 class="col-md-12 text-center">404 - Form Does not Exist </h3>
<h3 class="col-md-12 text-center">
{{ 'FORM_404_HEADER' | translate }}
</h3>
<div class="col-md-4 col-md-offset-4">
<div class="col-md-12 text-center" style="padding-bottom: 50px;">
The form you are trying to access does not exist. Sorry about that!
{{ 'FORM_404_BODY' | translate }}
</div>
</div>
</section>

View file

@ -3,10 +3,13 @@ $(".loader").fadeOut("slow");
</script>
<section class="public-form auth sigin-view valign-wrapper">
<div class="row valign">
<h3 class="col-md-12 text-center">Not Authorized to Access Form</h3>
<h3 class="col-md-12 text-center">
{{ 'FORM_UNAUTHORIZED_HEADER' | translate }}
</h3>
<div class="col-md-4 col-md-offset-4">
<div class="col-md-12 text-center" style="padding-bottom: 50px;">
The form you are trying to access is currently private and not accesible publically. <br> If you are the owner of the form, you can set it to "Public" in the "Configuration" panel in the form admin.
{{ 'FORM_UNAUTHORIZED_BODY1' | translate }} <br>
{{ 'FORM_UNAUTHORIZED_BODY2' | translate }}
</div>
</div>
</div>

View file

@ -8,9 +8,9 @@ angular.module('core').config(['$translateProvider', function ($translateProvide
SIGNIN_TAB: 'Sign In',
SIGNOUT_TAB: 'Signout',
EDIT_PROFILE: 'Edit Profile',
MY_FORMS: 'My Forms',
MY_SETTINGS: 'My Settings',
CHANGE_PASSWORD: 'Change Password'
CHANGE_PASSWORD: 'Change Password',
TOGGLE_NAVIGATION: 'Toggle navigation'
});
$translateProvider.preferredLanguage('en')

View file

@ -8,8 +8,8 @@ angular.module('core').config(['$translateProvider', function ($translateProvide
SIGNIN_TAB: 'Connexion',
SIGNOUT_TAB: 'Créer un compte',
EDIT_PROFILE: 'Modifier Mon Profil',
MY_FORMS: 'Mes Formulaires',
MY_SETTINGS: 'Mes Paramètres',
CHANGE_PASSWORD: 'Changer mon Mot de Pass'
CHANGE_PASSWORD: 'Changer mon Mot de Pass',
TOGGLE_NAVIGATION: 'Basculer la navigation',
});
}]);

View file

@ -0,0 +1,15 @@
'use strict';
angular.module('core').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('de', {
MENU: 'MENÜ',
SIGNUP_TAB: 'Anmelden',
SIGNIN_TAB: 'Anmeldung',
SIGNOUT_TAB: 'Abmelden',
EDIT_PROFILE: 'Profil bearbeiten',
MY_SETTINGS: 'Meine Einstellungen',
CHANGE_PASSWORD: 'Passwort ändern',
TOGGLE_NAVIGATION: 'Navigation umschalten'
});
}]);

View file

@ -0,0 +1,15 @@
'use strict';
angular.module('core').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('it', {
MENU: 'MENÜ',
SIGNUP_TAB: 'Vi Phrasal',
SIGNIN_TAB: 'Accedi',
SIGNOUT_TAB: 'Esci',
EDIT_PROFILE: 'Modifica Profilo',
MY_SETTINGS: 'Mie Impostazioni',
CHANGE_PASSWORD: 'Cambia la password',
TOGGLE_NAVIGATION: 'Attiva la navigazione'
});
}]);

View file

@ -8,9 +8,9 @@ angular.module('core').config(['$translateProvider', function ($translateProvide
SIGNIN_TAB: 'Entrar',
SIGNOUT_TAB: 'Salir',
EDIT_PROFILE: 'Editar Perfil',
MY_FORMS: 'Mis formularios',
MY_SETTINGS: 'Mis configuraciones',
CHANGE_PASSWORD: 'Cambiar contraseña'
CHANGE_PASSWORD: 'Cambiar contraseña',
TOGGLE_NAVIGATION: 'Navegación de palanca'
});
}]);

View file

@ -1,7 +1,7 @@
'use strict';
angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', '$window', '$translate', '$locale',
function ($rootScope, $scope, Menus, $state, Auth, User, $window, $translate, $locale) {
angular.module('core').controller('HeaderController', ['$rootScope', '$scope', 'Menus', '$state', 'Auth', 'User', '$window', '$translate',
function ($rootScope, $scope, Menus, $state, Auth, User, $window, $translate) {
$rootScope.signupDisabled = $window.signupDisabled;
@ -12,12 +12,8 @@ angular.module('core').controller('HeaderController', ['$rootScope', '$scope', '
$rootScope.languages = $scope.languages = ['en', 'fr', 'es', 'it', 'de'];
//Set global app language
if($scope.authentication.isAuthenticated()){
$rootScope.language = $scope.user.language;
}else {
$rootScope.language = $locale.id.substring(0,2);
}
$translate.use($rootScope.language);
$rootScope.language = $scope.user.language;
$translate.use($scope.user.language);
$scope.isCollapsed = false;
$rootScope.hideNav = false;

View file

@ -2,7 +2,7 @@
<div class="container" >
<div class="navbar-header">
<button class="navbar-toggle" type="button" data-ng-click="toggleCollapsibleMenu()">
<span class="sr-only">Toggle navigation</span>
<span class="sr-only">{{ 'TOGGLE_NAVIGATION' | translate }}</span>
<span>{{ 'MENU_BTN' | translate }}</span>
</button>
<a href="/#!/" class="navbar-brand">

View file

@ -93,7 +93,7 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
IS_NOT_EQUAL_TO: 'is not equal to',
IS_GREATER_THAN: 'is greater than',
IS_GREATER_OR_EQUAL_THAN: 'is greater or equal than',
IS_SMALLER_THAN: 'is_smaller_than',
IS_SMALLER_THAN: 'is smaller than',
IS_SMALLER_OR_EQUAL_THAN: 'is smaller or equal than',
CONTAINS: 'contains',
DOES_NOT_CONTAINS: 'does not contain',
@ -129,7 +129,6 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
LOCATION: 'Location',
IP_ADDRESS: 'IP Address',
DATE_SUBMITTED: 'Date Submitted',
GENERATED_PDF: 'Generated PDF',
//Design View
BACKGROUND_COLOR: 'Background Color',

View file

@ -2,34 +2,188 @@
angular.module('forms').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('french', {
FORM_SUCCESS: 'Votre formulaire a été enregistré!',
REVIEW: 'Incomplet',
BACK_TO_FORM: 'Retourner au formulaire',
EDIT_FORM: 'Éditer le Tellform',
CREATE_FORM: 'Créer un TellForm',
ADVANCEMENT: '{{done}} complétés sur {{total}}',
CONTINUE_FORM: 'Aller au formulaire',
REQUIRED: 'obligatoire',
COMPLETING_NEEDED: '{{answers_not_completed}} réponse(s) doive(nt) être complétée(s)',
OPTIONAL: 'facultatif',
ERROR_EMAIL_INVALID: 'Merci de rentrer une adresse mail valide',
ERROR_NOT_A_NUMBER: 'Merce de ne rentrer que des nombres',
ERROR_URL_INVALID: 'Merci de rentrer une url valide',
OK: 'OK',
ENTER: 'presser ENTRÉE',
YES: 'Oui',
NO: 'Non',
NEWLINE: 'presser SHIFT+ENTER pour créer une nouvelle ligne',
CONTINUE: 'Continuer',
LEGAL_ACCEPT: 'Jaccepte',
LEGAL_NO_ACCEPT: 'Je naccepte pas',
DELETE: 'Supprimer',
CANCEL: 'Réinitialiser',
SUBMIT: 'Enregistrer',
UPLOAD_FILE: 'Envoyer un fichier',
Y: 'O',
N: 'N',
});
$translateProvider.translations('fr', {
// Configurer la vue de l'onglet Formulaire
ADVANCED_SETTINGS: 'Paramètres avancés',
FORM_NAME: "Nom du formulaire",
FORM_STATUS: 'Statut du formulaire',
PUBLIC: 'Public',
PRIVATE: "Privé",
GA_TRACKING_CODE: "Code de suivi Google Analytics",
DISPLAY_FOOTER: "Afficher le pied de formulaire?",
SAVE_CHANGES: 'Enregistrer les modifications',
CANCEL: 'Annuler',
DISPLAY_START_PAGE: "Afficher la page de démarrage?",
DISPLAY_END_PAGE: "Afficher la page de fin personnalisée?",
// Afficher les formulaires
CREATE_A_NEW_FORM: "Créer un nouveau formulaire",
CREATE_FORM: "Créer un formulaire",
CREATED_ON: 'Créé le',
MY_FORMS: 'Mes formes',
NAME: "Nom",
LANGUE: 'Langue',
FORM_PAUSED: 'Formulaire en pause',
// Modifier le modal de champ
EDIT_FIELD: "Modifier ce champ",
SAVE_FIELD: 'Enregistrer',
ON: 'ON',
OFF: "OFF",
REQUIRED_FIELD: "Obligatoire",
LOGIC_JUMP: 'Saut logique',
SHOW_BUTTONS: 'Boutons supplémentaires',
SAVE_START_PAGE: "Enregistrer",
// Affichage du formulaire d'administration
ARE_YOU_SURE: 'Es-tu ABSOLUMENT sûr?',
READ_WARNING: "De mauvaises choses inattendues se produiront si vous ne lisez pas ceci!",
DELETE_WARNING1: 'Cette action NE PEUT PAS être annulée. Cela supprimera définitivement le "',
DELETE_WARNING2: '" forme et supprime toutes les soumissions de formulaire associées. ',
DELETE_CONFIRM: "Veuillez taper le nom du formulaire pour confirmer.",
I_UNDERSTAND: 'Je comprends les conséquences, efface ce formulaire.',
DELETE_FORM_SM: 'Supprimer',
DELETE_FORM_MD: "Supprimer le formulaire",
DELETE: "Supprimer",
FORM: 'Formulaire',
VIEW: "Afficher",
LIVE: "Live",
PREVIEW: 'Aperçu',
COPY: "Copier",
COPY_AND_PASTE: "Copiez et collez ceci pour ajouter votre TellForm à votre site Web",
CHANGE_WIDTH_AND_HEIGHT: "Changez les valeurs de largeur et de hauteur pour mieux vous convenir",
POWERED_BY: "Alimenté par",
TELLFORM_URL: "Votre TellForm est en permanence sur cette URL",
// Modifier la vue de formulaire
DISABLED: "Désactivé",
OUI: 'OUI',
NO: 'NON',
ADD_LOGIC_JUMP: 'Ajouter un saut de logique',
ADD_FIELD_LG: "Cliquez pour ajouter un nouveau champ",
ADD_FIELD_MD: "Ajouter un nouveau champ",
ADD_FIELD_SM: "Ajouter un champ",
EDIT_START_PAGE: "Modifier la page de démarrage",
EDIT_END_PAGE: "Modifier la page de fin",
WELCOME_SCREEN: 'Page de démarrage',
END_SCREEN: 'Fin de page',
INTRO_TITLE: "Titre",
INTRO_PARAGRAPH: 'Paragraphe',
INTRO_BTN: 'Bouton de démarrage',
TITLE: "Titre",
PARAGRAPHE: 'Paragraphe',
BTN_TEXT: "Bouton Retour",
BOUTONS: 'Boutons',
BUTTON_TEXT: "Texte",
BUTTON_LINK: "Lien",
ADD_BUTTON: 'Ajouter un bouton',
PREVIEW_FIELD: 'Question d\'aperçu',
QUESTION_TITLE: "Titre",
QUESTION_DESCRIPTION: 'Description',
OPTIONS: 'Options',
ADD_OPTION: 'Ajouter une option',
NUM_OF_STEPS: "Nombre d'étapes",
CLICK_FIELDS_FOOTER: 'Cliquez sur les champs pour les ajouter ici',
SHAPE: 'Forme',
IF_THIS_FIELD: "Si ce champ",
IS_EQUAL_TO: 'est égal à',
IS_NOT_EQUAL_TO: 'n\'est pas égal à',
IS_GREATER_THAN: 'est supérieur à',
IS_GREATER_OR_EQUAL_THAN: 'est supérieur ou égal à',
IS_SMALLER_THAN: 'est plus petit que',
IS_SMALLER_OR_EQUAL_THAN: 'est plus petit ou égal à',
CONTAINS: 'contient',
DOES_NOT_CONTAINS: 'ne contient pas',
ENDS_WITH: "se termine par",
DOES_NOT_END_WITH: "ne finit pas avec",
STARTS_WITH: 'commence par',
DOES_NOT_START_WITH: "ne commence pas par",
THEN_JUMP_TO: 'alors saute à',
// Modifier la vue des soumissions
TOTAL_VIEWS: 'total des visites uniques',
RESPONSES: "réponses",
COMPLETION_RATE: "taux d'achèvement",
AVERAGE_TIME_TO_COMPLETE: 'moy. le temps d\'achèvement',
DESKTOP_AND_LAPTOP: 'Desktops',
TABLETS: 'Tablettes',
PHONES: 'Téléphones',
OTHER: 'Autre',
UNIQUE_VISITS: 'Visites uniques',
FIELD_TITLE: 'Titre du champ',
FIELD_VIEWS: 'Vues de champ',
FIELD_DROPOFF: "Achèvement du champ",
FIELD_RESPONSES: 'Réponses sur le terrain',
DELETE_SELECTED: 'Supprimer la sélection',
EXPORT_TO_EXCEL: 'Exporter vers Excel',
EXPORT_TO_CSV: 'Export vers CSV',
EXPORT_TO_JSON: "Exporter vers JSON",
PERCENTAGE_COMPLETE: 'Pourcentage terminé',
TIME_ELAPSED: 'Temps écoulé',
DEVICE: "Dispositif",
LOCATION: "Emplacement",
IP_ADDRESS: 'Adresse IP',
DATE_SUBMITTED: 'Date de soumission',
// Vue de conception
BACKGROUND_COLOR: "Couleur d'arrière-plan",
DESIGN_HEADER: "Changez l'apparence de votre formulaire",
QUESTION_TEXT_COLOR: "Couleur du texte de la question",
ANSWER_TEXT_COLOR: "Couleur du texte de la réponse",
BTN_BACKGROUND_COLOR: "Couleur d'arrière-plan du bouton",
BTN_TEXT_COLOR: "Couleur du texte du bouton",
// Vue de partage
EMBED_YOUR_FORM: "Intégrez votre formulaire",
SHARE_YOUR_FORM: "Partager votre formulaire",
// Onglets d'administration
CREATE_TAB: "Créer",
DESIGN_TAB: 'Design',
CONFIGURE_TAB: 'Configurer',
ANALYZE_TAB: "Analyser",
SHARE_TAB: "Partager",
// Types de champs
SHORT_TEXT: "Texte court",
EMAIL: "E-mail",
MULTIPLE_CHOICE: 'Choix multiple',
DROPDOWN: 'Menu Déroulant',
DATE: 'Date',
PARAGRAPH_T: "Paragraphe",
OUI_NON: 'Oui / Non',
LEGAL: 'Légal',
RATING: "Évaluation",
NUMBERS: "Chiffres",
SIGNATURE: 'Signature',
FILE_UPLOAD: 'Téléchargement de fichier',
OPTION_SCALE: 'Option Scale',
PAYMENT: 'Paiement',
STATEMENT: 'Déclaration',
LINK: "Lien",
// Aperçu du formulaire
FORM_SUCCESS: 'Entrée de formulaire soumise avec succès!',
REVIEW: 'Réviser',
BACK_TO_FORM: "Revenir au formulaire",
EDIT_FORM: "Modifier ce TellForm",
ADVANCEMENT: '{{done}} sur {{total}} a répondu',
CONTINUE_FORM: "Continuer à se former",
REQUIRED: 'requis',
COMPLETING_NEEDED: '{{answers_not_completed}} réponse (s) doivent être complétées',
OPTIONAL: 'optionnel',
ERROR_EMAIL_INVALID: "Veuillez entrer une adresse email valide",
ERROR_NOT_A_NUMBER: "Veuillez entrer uniquement des numéros valides",
ERROR_URL_INVALID: "S'il vous plaît une adresse valide",
OK: 'OK',
ENTER: 'appuyez sur ENTRER',
NEWLINE: 'appuyez sur MAJ + ENTRÉE pour créer une nouvelle ligne',
CONTINUE: "Continuer",
LEGAL_ACCEPT: 'J\'accepte',
LEGAL_NO_ACCEPT: "Je n'accepte pas",
SUBMIT: "Soumettre",
UPLOAD_FILE: "Télécharger votre fichier"
});
}]);

View file

@ -2,34 +2,189 @@
angular.module('forms').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('german', {
FORM_SUCCESS: 'Ihre Angaben wurden gespeichert.',
REVIEW: 'Unvollständig',
BACK_TO_FORM: 'Zurück zum Formular',
EDIT_FORM: '',
CREATE_FORM: '',
ADVANCEMENT: '{{done}} von {{total}} beantwortet',
CONTINUE_FORM: 'Zum Formular',
REQUIRED: 'verpflichtend',
COMPLETING_NEEDED: 'Es fehlen/fehtl noch {{answers_not_completed}} Antwort(en)',
OPTIONAL: 'fakultativ',
ERROR_EMAIL_INVALID: 'Bitte gültige Mailadresse eingeben',
ERROR_NOT_A_NUMBER: 'Bitte nur Zahlen eingeben',
ERROR_URL_INVALID: 'Bitte eine gültige URL eingeben',
OK: 'Okay',
ENTER: 'Eingabetaste drücken',
YES: 'Ja',
NO: 'Nein',
NEWLINE: 'Für eine neue Zeile SHIFT+ENTER drücken',
CONTINUE: 'Weiter',
LEGAL_ACCEPT: 'I accept',
LEGAL_NO_ACCEPT: 'I dont accept',
DELETE: 'Entfernen',
CANCEL: 'Canceln',
SUBMIT: 'Speichern',
UPLOAD_FILE: 'Datei versenden',
Y: 'J',
N: 'N',
});
$translateProvider.translations('de', {
// Konfigurieren der Formularregisterkarte
ADVANCED_SETTINGS: 'Erweiterte Einstellungen',
FORM_NAME: 'Formularname',
FORM_STATUS: 'Formularstatus',
PUBLIC: 'Öffentlich',
PRIVATE: 'Privat',
GA_TRACKING_CODE: 'Google Analytics Tracking-Code',
DISPLAY_FOOTER: 'Formularfußzeile anzeigen?',
SAVE_CHANGES: 'Änderungen speichern',
CANCEL: 'Abbrechen',
DISPLAY_START_PAGE: 'Startseite anzeigen?',
DISPLAY_END_PAGE: 'Benutzerdefinierte Endseite anzeigen?',
// Listenformularansicht
CREATE_A_NEW_FORM: 'Erstelle ein neues Formular',
CREATE_FORM: 'Formular erstellen',
CREATED_ON: 'Erstellt am',
MY_FORMS: 'Meine Formulare',
NAME: 'Name',
SPRACHE: 'Sprache',
FORM_PAUSED: 'Formular pausiert',
// Feld Modal bearbeiten
EDIT_FIELD: 'Dieses Feld bearbeiten',
SAVE_FIELD: 'Speichern',
ON: 'ON',
AUS: 'AUS',
REQUIRED_FIELD: 'Erforderlich',
LOGIC_JUMP: 'Logischer Sprung',
SHOW_BUTTONS: 'Zusätzliche Schaltflächen',
SAVE_START_PAGE: 'Speichern',
// Admin-Formularansicht
ARE_YOU_SURE: "Bist du ABSOLUT sicher?",
READ_WARNING: 'Unerwartete schlimme Dinge werden passieren, wenn Sie das nicht lesen!',
DELETE_WARNING1: 'Diese Aktion kann NICHT rückgängig gemacht werden. Dies wird dauerhaft die "',
DELETE_WARNING2: '"Formular und entferne alle verknüpften Formulareinreichungen.',
DELETE_CONFIRM: 'Bitte geben Sie den Namen des zu bestätigenden Formulars ein.',
I_UNDERSTAND: "Ich verstehe die Konsequenzen, lösche dieses Formular.",
DELETE_FORM_SM: 'Löschen',
DELETE_FORM_MD: 'Formular löschen',
DELETE: 'Löschen',
FORM: 'Formular',
VIEW: 'Ansicht',
LIVE: 'Leben',
PREVIEW: 'Vorschau',
COPY: 'Kopieren',
COPY_AND_PASTE: 'Kopieren und einfügen, um Ihre TellForm auf Ihrer Website hinzuzufügen',
CHANGE_WIDTH_AND_HEIGHT: 'Ändern Sie die Werte für Breite und Höhe, um Ihnen am besten zu entsprechen',
POWERED_BY: 'Unterstützt von',
TELLFORM_URL: "Ihr TellForm ist dauerhaft unter dieser URL",
// Formularansicht bearbeiten
DISABLED: 'Deaktiviert',
JA: 'JA',
NO: 'NEIN',
ADD_LOGIC_JUMP: 'Logic Jump hinzufügen',
ADD_FIELD_LG: 'Klicken Sie auf Neues Feld hinzufügen',
ADD_FIELD_MD: 'Neues Feld hinzufügen',
ADD_FIELD_SM: 'Feld hinzufügen',
EDIT_START_PAGE: 'Startseite bearbeiten',
EDIT_END_PAGE: 'Endseite bearbeiten',
WELCOME_SCREEN: 'Startseite',
END_SCREEN: 'Ende Seite',
INTRO_TITLE: 'Titel',
INTRO_PARAGRAPH: "Absatz",
INTRO_BTN: 'Start Knopf',
TITLE: "Titel",
PARAGRAPH: "Absatz",
BTN_TEXT: 'Zurück Button',
TASTEN: 'Knöpfe',
BUTTON_TEXT: 'Text',
BUTTON_LINK: 'Link',
ADD_BUTTON: 'Schaltfläche hinzufügen',
PREVIEW_FIELD: 'Vorschaufrage',
QUESTION_TITLE: 'Titel',
QUESTION_DESCRIPTION: 'Beschreibung',
OPTIONS: 'Optionen',
ADD_OPTION: 'Option hinzufügen',
NUM_OF_STEPS: 'Anzahl der Schritte',
CLICK_FIELDS_FOOTER: 'Klicken Sie auf Felder, um sie hier hinzuzufügen',
FORM: 'Formular',
IF_THIS_FIELD: 'Wenn dieses Feld',
IS_EQUAL_TO: 'ist gleich',
IS_NOT_EQUAL_TO: 'ist nicht gleich',
IS_GREATER_THAN: 'ist größer als',
IS_GREATER_OR_EQUAL_THAN: 'ist größer oder gleich',
IS_SMALLER_THAN: 'ist kleiner als',
IS_SMALLER_OR_EQUAL_THAN: 'ist kleiner oder gleich',
CONTAINS: 'enthält',
DOES_NOT_CONTAINS: 'enthält nicht',
ENDS_WITH: 'endet mit',
DOES_NOT_END_WITH: 'endet nicht mit',
STARTS_WITH: 'beginnt mit',
DOES_NOT_START_WITH: 'beginnt nicht mit',
THEN_JUMP_TO: 'Springe dann zu',
// Bearbeiten der Einreichungsansicht
TOTAL_VIEWS: 'Gesamtzahl eindeutiger Besuche',
RESPONSES: 'Antworten',
COMPLETION_RATE: 'Abschlussrate',
AVERAGE_TIME_TO_COMPLETE: 'avg. Fertigstellungszeit',
DESKTOP_AND_LAPTOP: 'Desktops',
TABLETS: "Tabletten",
PHONES: 'Telefone',
OTHER: 'Andere',
UNIQUE_VISITS: 'Eindeutige Besuche',
FIELD_TITLE: 'Feldtitel',
FIELD_VIEWS: 'Feld Ansichten',
FIELD_DROPOFF: 'Feldabschluss',
FIELD_RESPONSES: 'Feldantworten',
DELETE_SELECTED: 'Ausgewählte löschen',
EXPORT_TO_EXCEL: 'Export nach Excel',
EXPORT_TO_CSV: 'In CSV exportieren',
EXPORT_TO_JSON: 'Export nach JSON',
PERCENTAGE_COMPLETE: 'Prozent abgeschlossen',
TIME_ELAPSED: 'Zeit verstrichen',
DEVICE: 'Gerät',
LOCATION: 'Ort',
IP_ADDRESS: 'IP-Adresse',
DATE_SUBMITTED: 'Eingereichtes Datum',
// Entwurfsansicht
BACKGROUND_COLOR: 'Hintergrundfarbe',
DESIGN_HEADER: 'Ändern Sie, wie Ihr Formular aussieht',
QUESTION_TEXT_COLOR: 'Fragetextfarbe',
ANSWER_TEXT_COLOR: 'Textfarbe beantworten',
BTN_BACKGROUND_COLOR: 'Schaltfläche Hintergrundfarbe',
BTN_TEXT_COLOR: 'Schaltfläche Textfarbe',
// Freigabeansicht
EMBED_YOUR_FORM: 'Einbetten Ihres Formulars',
SHARE_YOUR_FORM: 'Teilen Sie Ihr Formular',
// Admin-Registerkarten
CREATE_TAB: 'Erstellen',
DESIGN_TAB: 'Entwurf',
CONFIGURE_TAB: 'Konfigurieren',
ANALYZE_TAB: 'Analysieren',
SHARE_TAB: 'Freigeben',
// Feldtypen
SHORT_TEXT: 'Kurztext',
EMAIL: 'Email',
MULTIPLE_CHOICE: 'Mehrfachauswahl',
DROPDOWN: 'Dropdown-Liste',
DATE: 'Datum',
PARAGRAPH_T: "Absatz",
YES_NO: 'Ja / Nein',
LEGAL: "Rechtliche",
RATING: 'Bewertung',
NUMBERS: 'Zahlen',
SIGNATURE: "Unterschrift",
FILE_UPLOAD: 'Datei-Upload',
OPTION_SCALE: 'Optionsskala',
ZAHLUNG: "Zahlung",
STATEMENT: 'Anweisung',
LINK: 'Link',
// Formularvorschau
FORM_SUCCESS: 'Formulareintrag erfolgreich gesendet!',
REVIEW: 'Überprüfung',
BACK_TO_FORM: 'Gehe zurück zu Formular',
EDIT_FORM: 'Bearbeiten Sie diese TellForm',
ADVANCEMENT: '{{done}} von {{total}} wurde beantwortet',
CONTINUE_FORM: 'Weiter zum Formular',
REQUIRED: 'erforderlich',
COMPLETING_NEEDED: '{{answers_not_completed}} Antwort (en) müssen ausgefüllt werden',
OPTIONAL: 'optional',
ERROR_EMAIL_INVALID: 'Geben Sie eine gültige E-Mail-Adresse ein',
ERROR_NOT_A_NUMBER: 'Bitte nur gültige Nummern eingeben',
ERROR_URL_INVALID: 'Bitte eine gültige URL',
OK: 'OK',
ENTER: 'ENTER drücken',
NEWLINE: 'Drücken Sie UMSCHALT + EINGABETASTE, um eine neue Zeile zu erstellen',
CONTINUE: 'Weiter',
LEGAL_ACCEPT: "Ich akzeptiere",
LEGAL_NO_ACCEPT: "Ich akzeptiere nicht",
SUBMIT: 'Senden',
UPLOAD_FILE: 'Hochladen Ihrer Datei'
});
}]);

View file

@ -2,34 +2,189 @@
angular.module('forms').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('italian', {
FORM_SUCCESS: 'Il formulario è stato inviato con successo!',
REVIEW: 'Incompleto',
BACK_TO_FORM: 'Ritorna al formulario',
EDIT_FORM: '',
CREATE_FORM: '',
ADVANCEMENT: '{{done}} su {{total}} completate',
CONTINUE_FORM: 'Vai al formulario',
REQUIRED: 'obbligatorio',
COMPLETING_NEEDED: '{{answers_not_completed}} risposta/e deve/ono essere completata/e',
OPTIONAL: 'opzionale',
ERROR_EMAIL_INVALID: 'Si prega di inserire un indirizzo email valido',
ERROR_NOT_A_NUMBER: 'Si prega di inserire solo numeri',
ERROR_URL_INVALID: 'Grazie per inserire un URL valido',
OK: 'OK',
ENTER: 'premere INVIO',
YES: 'Sì',
NO: 'No',
NEWLINE: 'premere SHIFT+INVIO per creare una nuova linea',
CONTINUE: 'Continua',
LEGAL_ACCEPT: 'I accept',
LEGAL_NO_ACCEPT: 'I dont accept',
DELETE: 'Cancella',
CANCEL: 'Reset',
SUBMIT: 'Registra',
UPLOAD_FILE: 'Invia un file',
Y: 'S',
N: 'N',
});
$translateProvider.translations('it', {
// Configura la visualizzazione scheda modulo
ADVANCED_SETTINGS: 'Impostazioni avanzate',
FORM_NAME: 'Nome modulo',
FORM_STATUS: 'Stato modulo',
PUBLIC: 'pubblico',
PRIVATE: 'Privato',
GA_TRACKING_CODE: 'Codice di monitoraggio di Google Analytics',
DISPLAY_FOOTER: 'Visualizza piè di pagina?',
SAVE_CHANGES: 'Salva modifiche',
CANCEL: 'Annulla',
DISPLAY_START_PAGE: 'Visualizza pagina iniziale?',
DISPLAY_END_PAGE: 'Mostra pagina finale personalizzata?',
// Visualizzazione dei moduli di elenco
CREATE_A_NEW_FORM: 'Crea un nuovo modulo',
CREATE_FORM: 'Crea modulo',
CREATED_ON: 'Creato su',
MY_FORMS: 'Le mie forme',
NAME: 'Nome',
LINGUA: 'Lingua',
FORM_PAUSED: 'Forme in pausa',
// Modifica campo modale
EDIT_FIELD: 'Modifica questo campo',
SAVE_FIELD: 'Salva',
ON: 'ON',
OFF: 'OFF',
REQUIRED_FIELD: 'Obbligatorio',
LOGIC_JUMP: 'Jump Logic',
SHOW_BUTTONS: 'Pulsanti aggiuntivi',
SAVE_START_PAGE: 'Salva',
// Visualizzazione modulo di amministrazione
ARE_YOU_SURE: 'Sei ASSOLUTAMENTE sicuro?',
READ_WARNING: 'Le cose cattive impreviste avverranno se non lo leggi!',
DELETE_WARNING1: 'Questa azione NON può essere annullata. Ciò eliminerà in modo permanente il "',
DELETE_WARNING2: '" forma e rimuovi tutti i moduli di modulo associati. ',
DELETE_CONFIRM: 'Inserisci il nome del modulo per confermare',
I_UNDERSTAND: "Capisco le conseguenze, elimina questa forma",
DELETE_FORM_SM: 'Elimina',
DELETE_FORM_MD: 'Elimina modulo',
DELETE: 'Elimina',
FORM: 'Forma',
VIEW: 'Visualizza',
LIVE: 'Live',
PREVIEW: 'Anteprima',
COPY: 'Copia',
COPY_AND_PASTE: 'Copia e incolla questo per aggiungere il tuo TellForm al tuo sito web',
CHANGE_WIDTH_AND_HEIGHT: 'Modifica i valori di larghezza e di altezza per adattarti al meglio',
POWERED_BY: 'Offerto da',
TELLFORM_URL: 'Il tuo TellForm è permanente in questo URL',
// Modifica vista modulo
DISABLED: 'disabilitato',
YES: 'SI',
NO: 'NO',
ADD_LOGIC_JUMP: 'Aggiungi logico salto',
ADD_FIELD_LG: 'Clicca per aggiungere nuovo campo',
ADD_FIELD_MD: 'Aggiungi nuovo campo',
ADD_FIELD_SM: 'Aggiungi campo',
EDIT_START_PAGE: 'Modifica pagina iniziale',
EDIT_END_PAGE: 'Modifica pagina finale',
WELCOME_SCREEN: 'Pagina iniziale',
END_SCREEN: 'Fine pagina',
INTRO_TITLE: 'Titolo',
INTRO_PARAGRAPH: 'Paragrafo',
INTRO_BTN: 'Pulsante Start',
TITLE: 'Titolo',
PARAGRAFO: 'Paragrafo',
BTN_TEXT: 'Tornare indietro',
TASTI: 'Pulsanti',
BUTTON_TEXT: 'Testo',
BUTTON_LINK: 'Link',
ADD_BUTTON: 'Aggiungi pulsante',
PREVIEW_FIELD: 'Anteprima domanda',
QUESTION_TITLE: 'Titolo',
QUESTION_DESCRIPTION: 'Descrizione',
OPTIONS: 'Opzioni',
ADD_OPTION: 'Aggiungi opzione',
NUM_OF_STEPS: 'Numero di passi',
CLICK_FIELDS_FOOTER: 'Clicca sui campi per aggiungerli qui',
FORMA: 'Forma',
IF_THIS_FIELD: 'Se questo campo',
IS_EQUAL_TO: 'è uguale a',
IS_NOT_EQUAL_TO: 'non è uguale a',
IS_GREATER_THAN: 'è maggiore di',
IS_GREATER_OR_EQUAL_THAN: 'è maggiore o uguale a',
IS_SMALLER_THAN: 'è inferiore a',
IS_SMALLER_OR_EQUAL_THAN: 'è più piccolo o uguale a quello',
CONTAINS: 'contiene',
DOES_NOT_CONTAINS: 'non contiene',
ENDS_WITH: 'finisce con',
DOES_NOT_END_WITH: 'non finisce con',
STARTS_WITH: 'inizia con',
DOES_NOT_START_WITH: 'non inizia con',
THEN_JUMP_TO: 'poi salta a',
// Modifica visualizzazione presentazioni
TOTAL_VIEWS: 'visite totali totali',
RESPONSES: 'risposte',
COMPLETION_RATE: 'tasso di completamento',
AVERAGE_TIME_TO_COMPLETE: 'avg. tempo di completamento',
DESKTOP_AND_LAPTOP: 'Desktop',
TABLETS: 'compresse',
PHONES: 'Telefoni',
OTHER: 'Altro',
UNIQUE_VISITS: 'Visite Uniche',
FIELD_TITLE: 'Titolo del campo',
FIELD_VIEWS: 'Viste sul campo',
FIELD_DROPOFF: 'Completamento del campo',
FIELD_RESPONSES: 'Risposte sul campo',
DELETE_SELECTED: 'Elimina selezionata',
EXPORT_TO_EXCEL: 'Esporta in Excel',
EXPORT_TO_CSV: 'Esporta in CSV',
EXPORT_TO_JSON: 'Esporta in JSON',
PERCENTAGE_COMPLETE: 'Percentuale completa',
TIME_ELAPSED: 'Tempo trascorso',
DEVICE: 'Dispositivo',
LOCATION: 'Posizione',
IP_ADDRESS: 'Indirizzo IP',
DATE_SUBMITTED: 'Data trasmessa',
// Vista di progettazione
BACKGROUND_COLOR: 'Colore di sfondo',
DESIGN_HEADER: 'Modifica il tuo aspetto forma',
QUESTION_TEXT_COLOR: 'Colore del testo di domanda',
ANSWER_TEXT_COLOR: 'Rispondere al colore del testo',
BTN_BACKGROUND_COLOR: 'Colore di sfondo del pulsante',
BTN_TEXT_COLOR: 'Colore del testo pulsante',
// Vista condivisione
EMBED_YOUR_FORM: 'Inserisci il tuo modulo',
SHARE_YOUR_FORM: 'Condividi il tuo modulo',
// Schede amministratore
CREATE_TAB: 'Crea',
DESIGN_TAB: 'Design',
CONFIGURE_TAB: 'Configura',
ANALYZE_TAB: 'Analizza',
SHARE_TAB: 'Condividi',
// Tipi di campo
SHORT_TEXT: 'Testo corto',
EMAIL: 'E-mail',
MULTIPLE_CHOICE: 'Scelta multipla',
DROPDOWN: 'Dropdown',
DATE: 'Data',
PARAGRAPH_T: 'Paragrafo',
YES_NO: 'Sì / no',
LEGAL: 'Legale',
RATING: 'Valutazione',
NUMBERS: 'Numeri',
SIGNATURE: 'Firma',
FILE_UPLOAD: 'Caricamento file',
OPTION_SCALE: 'Scala opzione',
PAGAMENTO: 'Pagamento',
STATEMENT: 'Dichiarazione',
LINK: 'Link',
// Anteprima del modulo
FORM_SUCCESS: 'Inserimento modulo con successo presentato!',
REVIEW: 'Recensione',
BACK_TO_FORM: 'Torna alla scheda',
EDIT_FORM: 'Modifica questo TellForm',
ADVANCEMENT: '{{done}} su {{total}} ha risposto',
CONTINUE_FORM: "Continua a formare",
REQUIRED: 'richiesta',
COMPLETING_NEEDED: '{{answers_not_completed}} answer (s) need completing',
OPTIONAL: 'facoltativo',
ERROR_EMAIL_INVALID: 'Inserisci un indirizzo e-mail valido',
ERROR_NOT_A_NUMBER: 'Inserisci solo numeri validi',
ERROR_URL_INVALID: 'Per favore un url valido',
OK: 'OK',
ENTER: 'premere INVIO',
NEWLINE: 'premere SHIFT + INVIO per creare una nuova riga',
CONTINUE: 'Continua',
LEGAL_ACCEPT: 'accetto',
LEGAL_NO_ACCEPT: 'Non accetto',
SUBMIT: 'Invia',
UPLOAD_FILE: 'Carica il tuo file'
});
}]);

View file

@ -29,8 +29,8 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
//Edit Field Modal
EDIT_FIELD: 'Editar este campo',
SAVE_FIELD: 'Grabar',
ON: 'ON',
OFF: 'OFF',
ON: 'EN',
OFF: 'APAGADO',
REQUIRED_FIELD: 'Requerido',
LOGIC_JUMP: 'Salto lógico',
SHOW_BUTTONS: 'Botones adicionales',
@ -127,7 +127,6 @@ angular.module('forms').config(['$translateProvider', function ($translateProvid
LOCATION: 'Lugar',
IP_ADDRESS: 'Dirección IP',
DATE_SUBMITTED: 'Fecha de envío',
GENERATED_PDF: 'PDF generado',
//Design View
BACKGROUND_COLOR: 'Color de fondo',

View file

@ -1,8 +1,8 @@
'use strict';
// Forms controller
angular.module('forms').controller('AdminFormController', ['$rootScope', '$window', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', '$uibModal', 'myForm', '$filter',
function($rootScope, $window, $scope, $stateParams, $state, Forms, CurrentForm, $http, $uibModal, myForm, $filter) {
angular.module('forms').controller('AdminFormController', ['$rootScope', '$window', '$scope', '$stateParams', '$state', 'Forms', 'CurrentForm', '$http', '$uibModal', 'myForm', '$filter', '$translate',
function($rootScope, $window, $scope, $stateParams, $state, Forms, CurrentForm, $http, $uibModal, myForm, $filter, $translate) {
//Set active tab to Create
$scope.activePill = 0;

View file

@ -16,10 +16,10 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
rows: []
};
var initController = function(){
var getSubmissions = function(){
$http({
method: 'GET',
url: '/forms'+$scope.myform._id+'/submissions'
url: '/forms/'+$scope.myform._id+'/submissions'
}).then(function successCallback(response) {
var defaultFormFields = _.cloneDeep($scope.myform.form_fields);
@ -31,9 +31,6 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
if(submissions[i].form_fields[x].fieldType === 'dropdown'){
submissions[i].form_fields[x].fieldValue = submissions[i].form_fields[x].fieldValue.option_value;
}
//var oldValue = submissions[i].form_fields[x].fieldValue || '';
//submissions[i].form_fields[x] = _.merge(defaultFormFields, submissions[i].form_fields);
//submissions[i].form_fields[x].fieldValue = oldValue;
}
submissions[i].selected = false;
}
@ -42,8 +39,21 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
});
};
initController();
var getVisitors = function(){
$http({
method: 'GET',
url: '/forms/'+$scope.myform._id+'/visitors'
}).then(function successCallback(response) {
var defaultFormFields = _.cloneDeep($scope.myform.form_fields);
var visitors = response.data || [];
$scope.visitors = visitors;
});
};
getSubmissions();
getVisitors();
/*
** Analytics Functions
@ -62,50 +72,8 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
return (totalTime/numSubmissions).toFixed(0);
})();
$scope.DeviceStatistics = (function(){
var newStatItem = function(){
return {
visits: 0,
responses: 0,
completion: 0,
average_time: 0,
total_time: 0
};
};
var stats = {
desktop: newStatItem(),
tablet: newStatItem(),
phone: newStatItem(),
other: newStatItem()
};
if($scope.myform.analytics && $scope.myform.analytics.visitors) {
var visitors = $scope.myform.analytics.visitors;
for (var i = 0; i < visitors.length; i++) {
var visitor = visitors[i];
var deviceType = visitor.deviceType;
stats[deviceType].visits++;
if (visitor.isSubmitted) {
stats[deviceType].total_time = stats[deviceType].total_time + visitor.timeElapsed;
stats[deviceType].responses++;
}
if(stats[deviceType].visits) {
stats[deviceType].completion = 100*(stats[deviceType].responses / stats[deviceType].visits).toFixed(2);
}
if(stats[deviceType].responses){
stats[deviceType].average_time = (stats[deviceType].total_time / stats[deviceType].responses).toFixed(0);
}
}
}
return stats;
})();
var updateFields = $interval(initController, 1000000);
var updateFields = $interval(getSubmissions, 100000);
var updateFields = $interval(getVisitors, 1000000);
$scope.$on('$destroy', function() {
if (updateFields) {
@ -173,3 +141,4 @@ angular.module('forms').directive('editSubmissionsFormDirective', ['$rootScope',
};
}
]);

View file

@ -1,72 +1,75 @@
'use strict';
//TODO: DAVID: URGENT: Make this a $resource that fetches valid field types from server
angular.module('forms').service('FormFields', [ '$filter',
function($filter) {
angular.module('forms').service('FormFields', [ '$rootScope', '$translate', '$window',
function($rootScope, $translate, $window) {
$translate.use($window.user.language);
console.log($translate.instant('SHORT_TEXT'));
this.types = [
{
name : 'textfield',
value : $filter('translate')('SHORT_TEXT'),
value : $translate.instant('SHORT_TEXT'),
},
{
name : 'email',
value : $filter('translate')('EMAIL'),
value : $translate.instant('EMAIL'),
},
{
name : 'radio',
value : $filter('translate')('MULTIPLE_CHOICE'),
value : $translate.instant('MULTIPLE_CHOICE'),
},
{
name : 'dropdown',
value : $filter('translate')('DROPDOWN'),
value : $translate.instant('DROPDOWN'),
},
{
name : 'date',
value : $filter('translate')('DATE'),
value : $translate.instant('DATE'),
},
{
name : 'textarea',
value : $filter('translate')('PARAGRAPH'),
value : $translate.instant('PARAGRAPH'),
},
{
name : 'yes_no',
value : $filter('translate')('YES_NO'),
value : $translate.instant('YES_NO'),
},
{
name : 'legal',
value : $filter('translate')('LEGAL'),
value : $translate.instant('LEGAL'),
},
// {
// name : 'sig',
// value : $filter('translate')('SIGNATURE'),
// value : $translate.instant('SIGNATURE'),
// },
// {
// name : 'file',
// value : $filter('translate')('FILE_UPLOAD'),
// value : $translate.instant('FILE_UPLOAD'),
// },
{
name : 'rating',
value : $filter('translate')('RATING'),
value : $translate.instant('RATING'),
},
{
name : 'link',
value : $filter('translate')('LINK'),
value : $translate.instant('LINK'),
},
{
name : 'number',
value : $filter('translate')('NUMBERS'),
value : $translate.instant('NUMBERS'),
},
// {
// name : 'scale',
// value : $filter('translate')('OPINION SCALE'),
// value : $translate.instant('OPINION SCALE'),
// },
// {
// name : 'stripe',
// value : $filter('translate')('PAYMENT'),
// value : $translate.instant('PAYMENT'),
// },
{
name : 'statement',
value : $filter('translate')('STATEMENT')
value : $translate.instant('STATEMENT')
}
];
}

View file

@ -487,8 +487,6 @@
</div>
</div>
</script>
<!-- Add Fields Element -->
@ -509,7 +507,8 @@
</field-icon-directive>
</span>
<span class="hidden-xs" style="padding-left:0.3em;">{{type.value}}</span>
<span class="hidden-xs" style="padding-left:0.3em;"> {{type.value}}
</span>
</div>
</div>
</div>

View file

@ -28,7 +28,7 @@
<section class="container">
<br>
<div class="row">
<div ng-click="openCreateModal()" class="col-xs-6 col-xs-offset-3 col-sm-4 col-sm-offset-1 col-md-3 col-md-offset-1 form-item create-new">
<div ng-click="openCreateModal()" class="col-xs-6 col-xs-offset-3 col-sm-4 col-sm-offset-1 col-md-3 col-md-offset-1 form-item new-button create-new">
<div class="title-row col-xs-12">
<h4 class="fa fa-plus fa-6"></h4>
</div>

View file

@ -310,12 +310,12 @@ section.public-form field-directive .btn[disabled]{
}
/*CREATE-NEW FORM MODAL*/
.form-item.create-new.new-form {
.form-item.new-form {
background-color: #832383;
background-color: rgb(300,131,131);
z-index: 11;
}
.form-item.create-new.new-form:hover {
.form-item.new-form:hover {
background-color: #3079b5;
}
.form-item.new-form input[type='text'] {
@ -398,19 +398,23 @@ h3.forms-list-title {
font-size: 1.3em;
}
.form-item.create-new .title-row{
.form-item.create-new .title-row {
padding: 0;
}
.form-item.create-new .title-row h4 {
font-size: 7em;
}
.form-item .details-row{
margin-top: 3.2em;
.form-item.create-new.new-button .details-row {
padding-top: 20%;
}
.form-item .details-row small {
.form-item .details-row small {
font-size: 0.6em;
}
.form-item.create-new .details-row small {
.form-item.create-new .details-row small {
font-size: 0.95em;
}
.form-item.create-new input {
max-width: 100%
}

View file

@ -55,16 +55,17 @@ angular.module('users').config(['$translateProvider', function ($translateProvid
SUBMIT_BTN: 'Submit',
ASK_FOR_NEW_PASSWORD: 'Ask for new password reset',
PASSWORD_RESET_INVALID: 'Password reset is invalid',
PASSWORD_RESET_SUCCESS: 'Passport successfully reset',
PASSWORD_CHANGE_SUCCESS: 'Passport successfully changed',
PASSWORD_RESET_INVALID: 'Password reset link is invalid',
PASSWORD_RESET_SUCCESS: 'Password successfully reset',
PASSWORD_CHANGE_SUCCESS: 'Password successfully changed',
RESET_PASSWORD: 'Reset your password',
CHANGE_PASSWORD: 'Change your password',
CONTINUE_TO_LOGIN: 'Continue to login page',
VERIFY_SUCCESS: 'Account successfully activated',
VERIFY_ERROR: 'Verification link is invalid or has expired'
VERIFY_ERROR: 'Verification link is invalid or has expired',
ERROR: 'Error'
});
$translateProvider.preferredLanguage('en')

View file

@ -38,14 +38,15 @@ angular.module('users').config(['$translateProvider', function ($translateProvid
SUBMIT_BTN: 'Enregistrer',
ASK_FOR_NEW_PASSWORD: 'Demander un nouveau mot de pass ',
PASSWORD_RESET_INVALID: 'Le nouveau mot de passe est invalid',
PASSWORD_RESET_INVALID: 'Ce lien de réinitialisation de mot de passe a déjà expiré',
PASSWORD_RESET_SUCCESS: 'Mot de passe réinitialisé avec succès',
PASSWORD_CHANGE_SUCCESS: 'Mot de passe enregistré avec succès',
CONTINUE_TO_LOGIN: 'Allez à la page de connexion',
VERIFY_SUCCESS: 'Votre compte est activé !',
VERIFY_ERROR: 'Le lien de vérification est invalide ou à expiré'
VERIFY_ERROR: 'Le lien de vérification est invalide ou à expiré',
ERROR: 'Erreur'
});
}]);

View file

@ -0,0 +1,70 @@
'use strict';
angular.module('users').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('de', {
ACCESS_DENIED_TEXT: 'Sie müssen eingeloggt sein, um auf diese Seite zugreifen zu können',
USERNAME_OR_EMAIL_LABEL: 'Benutzername oder E-Mail',
USERNAME_LABEL: 'Benutzername',
PASSWORD_LABEL: 'Passwort',
CURRENT_PASSWORD_LABEL: 'Aktuelles Passwort',
NEW_PASSWORD_LABEL: 'Neues Passwort',
VERIFY_PASSWORD_LABEL: 'Passwort bestätigen',
UPDATE_PASSWORD_LABEL: 'Passwort aktualisieren',
FIRST_NAME_LABEL: 'Vorname',
LAST_NAME_LABEL: 'Nachname',
LANGUAGE_LABEL: 'Sprache',
EMAIL_LABEL: 'Email',
SIGNUP_ACCOUNT_LINK: 'Haben Sie kein Konto? Hier registrieren',
SIGN_IN_ACCOUNT_LINK: 'Haben Sie bereits ein Konto? Hier anmelden',
SIGNUP_HEADER_TEXT: 'Registrieren',
SIGNIN_HEADER_TEXT: 'Anmelden',
SIGNUP_ERROR_TEXT: 'Konnte die Registrierung aufgrund von Fehlern nicht abschließen',
ENTER_ACCOUNT_EMAIL: 'Geben Sie Ihre Konto-E-Mail ein.',
RESEND_VERIFICATION_EMAIL: 'Bestätigungs-E-Mail erneut senden',
SAVE_CHANGES: 'Änderungen speichern',
CANCEL_BTN: 'Abbrechen',
EDIT_PROFILE: 'Bearbeiten Sie Ihr Profil',
UPDATE_PROFILE_BTN: 'Profil aktualisieren',
PROFILE_SAVE_SUCCESS: 'Profil wurde erfolgreich gespeichert',
PROFILE_SAVE_ERROR: 'Könnte Ihr Profil nicht speichern.',
CONNECTED_SOCIAL_ACCOUNTS: 'Verbundene Sozialkonten',
CONNECT_OTHER_SOCIAL_ACCOUNTS: 'Andere soziale Konten verbinden',
FORGOT_PASSWORD_LINK: 'Passwort vergessen?',
REVERIFY_ACCOUNT_LINK: 'Bestätige deine Bestätigungs-E-Mail erneut',
SIGNIN_BTN: "Anmelden",
SIGNUP_BTN: 'Registrieren',
SAVE_PASSWORD_BTN: 'Passwort speichern',
SUCCESS_HEADER: 'Anmeldung erfolgreich',
SUCCESS_TEXT: 'Sie haben ein Konto erfolgreich bei TellForm registriert.',
VERIFICATION_EMAIL_SENT: 'Bestätigungs-E-Mail wurde gesendet',
VERIFICATION_EMAIL_SENT_TO: 'Es wurde eine Bestätigungs-E-Mail gesendet.',
NOT_ACTIVATED_YET: 'Dein Account ist noch nicht aktiviert',
BEFORE_YOU_CONTINUE: 'Bevor Sie fortfahren, überprüfen Sie bitte Ihre E-Mail-Adresse auf Überprüfung. Wenn Sie nicht innerhalb von 24 Stunden erhalten Sie uns eine Zeile bei ',
CHECK_YOUR_EMAIL: 'Überprüfe deine E-Mail und klicke auf den Aktivierungslink, um deinen Account zu aktivieren. Wenn Sie irgendwelche Fragen haben, lassen Sie uns eine Zeile bei ',
WEITER: 'Weiter',
PASSWORD_RESTORE_HEADER: 'Wiederherstellen Ihres Passworts',
ENTER_YOUR_EMAIL: 'Geben Sie Ihre E-Mail-Adresse ein.',
SUBMIT_BTN: 'Senden',
ASK_FOR_NEW_PASSWORD: 'Neues Passwort zurücksetzen',
PASSWORD_RESET_INVALID: 'Dieser Link zum Zurücksetzen des Passworts ist bereits abgelaufen',
PASSWORD_RESET_SUCCESS: 'Passport erfolgreich zurückgesetzt',
PASSWORD_CHANGE_SUCCESS: 'Pass wurde erfolgreich geändert',
RESET_PASSWORD: 'Passwort zurücksetzen',
CHANGE_PASSWORD: 'Ändern Sie Ihr Passwort',
CONTINUE_TO_LOGIN: 'Weiter zur Anmeldeseite',
VERIFY_SUCCESS: 'Konto erfolgreich aktiviert',
VERIFY_ERROR: 'Überprüfungslink ist ungültig oder abgelaufen',
ERROR: 'Fehler'
});
}]);

View file

@ -0,0 +1,70 @@
'use strict';
angular.module('users').config(['$translateProvider', function ($translateProvider) {
$translateProvider.translations('it', {
ACCESS_DENIED_TEXT: 'Devi aver effettuato l\'accesso per accedere a questa pagina',
USERNAME_OR_EMAIL_LABEL: 'Nome utente o posta elettronica',
USERNAME_LABEL: 'Nome utente',
PASSWORD_LABEL: 'Password',
CURRENT_PASSWORD_LABEL: 'Current Password',
NEW_PASSWORD_LABEL: 'Nuova password',
VERIFY_PASSWORD_LABEL: 'Verifica password',
UPDATE_PASSWORD_LABEL: 'Aggiorna password',
FIRST_NAME_LABEL: 'Nome',
LAST_NAME_LABEL: 'Cognome',
LANGUAGE_LABEL: 'Lingua',
EMAIL_LABEL: 'Email',
SIGNUP_ACCOUNT_LINK: 'Non hai un account? Iscriviti qui ',
SIGN_IN_ACCOUNT_LINK: 'Hai già un account? Accedi qui ',
SIGNUP_HEADER_TEXT: 'Iscriviti',
SIGNIN_HEADER_TEXT: 'Accedi',
SIGNUP_ERROR_TEXT: 'Impossibile completare la registrazione a causa di errori',
ENTER_ACCOUNT_EMAIL: "Inserisci l'email del tuo account.",
RESEND_VERIFICATION_EMAIL: 'Ripeti l\'email di verifica',
SAVE_CHANGES: 'Salva modifiche',
CANCEL_BTN: 'Annulla',
EDIT_PROFILE: 'Modifica il tuo profilo',
UPDATE_PROFILE_BTN: 'Aggiorna profilo',
PROFILE_SAVE_SUCCESS: 'Profilo salvato con successo',
PROFILE_SAVE_ERROR: 'Impossibile salvare il tuo profilo.',
CONNECTED_SOCIAL_ACCOUNTS: 'Conti sociali connessi',
CONNECT_OTHER_SOCIAL_ACCOUNTS: 'Connetti altri account sociali',
FORGOT_PASSWORD_LINK: 'Hai dimenticato la password?',
REVERIFY_ACCOUNT_LINK: 'Ripeti la tua email di verifica',
SIGNIN_BTN: 'Accedi',
SIGNUP_BTN: 'Iscriviti',
SAVE_PASSWORD_BTN: 'Salva password',
SUCCESS_HEADER: 'Registra il successo',
SUCCESS_TEXT: 'Hai registrato un account con TellForm.',
VERIFICATION_EMAIL_SENT: 'L\'email di verifica è stata inviata',
VERIFICATION_EMAIL_SENT_TO: 'E\' stata inviata un\'email di verifica a ',
NOT_ACTIVATED_YET: 'Ma il tuo account non è ancora attivato',
BEFORE_YOU_CONTINUE: 'Prima di continuare, assicurati di controllare la tua email per la nostra verifica. Se non lo ricevi entro 24 ore ci cali una linea a ',
CHECK_YOUR_EMAIL: 'Controlla la tua email e fai clic sul link di attivazione per attivare il tuo account. Se hai domande, fai una linea a ',
CONTINUA: 'Continua',
PASSWORD_RESTORE_HEADER: 'Ripristina password',
ENTER_YOUR_EMAIL: 'Inserisci l\'email del tuo account',
SUBMIT_BTN: 'Invia',
ASK_FOR_NEW_PASSWORD: 'Richiedi nuova password reimpostata',
PASSWORD_RESET_INVALID: 'Questo collegamento per la reimpostazione della password è già scaduto',
PASSWORD_RESET_SUCCESS: 'Passaporto resettato con successo',
PASSWORD_CHANGE_SUCCESS: 'Passaporto modificato con successo',
RESET_PASSWORD: 'Ripristina la tua password',
CHANGE_PASSWORD: 'Modifica password',
CONTINUE_TO_LOGIN: 'Continua alla pagina di login',
VERIFY_SUCCESS: 'Account attivato correttamente',
VERIFY_ERROR: 'Il collegamento di verifica non è valido o è scaduto',
ERROR: 'Errore'
});
}]);

View file

@ -55,7 +55,7 @@ angular.module('users').config(['$translateProvider', function ($translateProvid
SUBMIT_BTN: 'Enviar',
ASK_FOR_NEW_PASSWORD: 'Pedir reseteo de contraseña',
PASSWORD_RESET_INVALID: 'El reseteo de la contraseña es inválido',
PASSWORD_RESET_INVALID: 'Este enlace de restablecimiento de contraseña ya ha caducado',
PASSWORD_RESET_SUCCESS: 'Contraseña exitosamente reseteada',
PASSWORD_CHANGE_SUCCESS: 'Contraseña exitosamente cambiada',
RESET_PASSWORD: 'Resetear contraseña',
@ -64,6 +64,7 @@ angular.module('users').config(['$translateProvider', function ($translateProvid
CONTINUE_TO_LOGIN: 'Ir a la página de ingreso',
VERIFY_SUCCESS: 'Cuenta activada exitosamente',
VERIFY_ERROR: 'El link de verificación es inválido o inexistente'
VERIFY_ERROR: 'El link de verificación es inválido o inexistente',
ERROR: 'Error'
});
}]);

View file

@ -1,32 +1,35 @@
'use strict';
angular.module('users').controller('AuthenticationController', ['$scope', '$location', '$state', '$rootScope', 'User', 'Auth',
function($scope, $location, $state, $rootScope, User, Auth) {
angular.module('users').controller('AuthenticationController', ['$scope', '$location', '$state', '$rootScope', 'User', 'Auth', '$translate', '$window',
function($scope, $location, $state, $rootScope, User, Auth, $translate, $window) {
$scope = $rootScope;
$scope.credentials = {};
$scope.error = '';
$scope.forms = {};
$scope.signin = function() {
User.login($scope.credentials).then(
function(response) {
Auth.login(response);
$scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User);
if(!$scope.forms.signinForm.$invalid){
User.login($scope.credentials).then(
function(response) {
Auth.login(response);
$scope.user = $rootScope.user = Auth.ensureHasCurrentUser(User);
if($state.previous.name !== 'home' && $state.previous.name !== 'verify' && $state.previous.name !== '') {
$state.go($state.previous.name);
} else {
$state.go('listForms');
if($state.previous.name !== 'home' && $state.previous.name !== 'verify' && $state.previous.name !== '') {
$state.go($state.previous.name);
} else {
$state.go('listForms');
}
},
function(error) {
$rootScope.user = Auth.ensureHasCurrentUser(User);
$scope.user = $rootScope.user;
$scope.error = error;
console.error('loginError: '+error);
}
},
function(error) {
$rootScope.user = Auth.ensureHasCurrentUser(User);
$scope.user = $rootScope.user;
$scope.error = error;
console.error('loginError: '+error);
}
);
);
}
};
$scope.signup = function() {
@ -35,20 +38,22 @@ angular.module('users').controller('AuthenticationController', ['$scope', '$loca
return;
}
User.signup($scope.credentials).then(
function(response) {
$state.go('signup-success');
},
function(error) {
console.error(error);
if(error) {
$scope.error = error;
console.error(error);
} else {
console.error('No response received');
}
}
);
if(!$scope.forms.signupForm.$invalid){
User.signup($scope.credentials).then(
function(response) {
$state.go('signup-success');
},
function(error) {
console.error(error);
if(error) {
$scope.error = error;
console.error(error);
} else {
console.error('No response received');
}
}
);
}
};
}

View file

@ -1,19 +1,23 @@
'use strict';
angular.module('users').controller('PasswordController', ['$scope', '$stateParams', '$state', 'User',
function($scope, $stateParams, $state, User) {
angular.module('users').controller('PasswordController', ['$scope', '$stateParams', '$state', 'User', '$translate', '$window',
function($scope, $stateParams, $state, User, $translate, $window) {
$translate.use($window.locale);
$scope.error = '';
$scope.forms = {};
// Submit forgotten password account id
$scope.askForPasswordReset = function() {
User.askForPasswordReset($scope.credentials).then(
function(response){
$scope.success = response.message;
$scope.error = null;
$scope.credentials = null;
},
function(error){
$scope.error = error;
$scope.success = null;
$scope.credentials = null;
}
);
@ -21,21 +25,25 @@ angular.module('users').controller('PasswordController', ['$scope', '$stateParam
// Change user password
$scope.resetUserPassword = function() {
$scope.success = $scope.error = null;
User.resetPassword($scope.passwordDetails, $stateParams.token).then(
function(response){
// If successful show success message and clear form
$scope.success = response.message;
$scope.passwordDetails = null;
if(!$scope.forms.resetPasswordForm.$invalid){
$scope.success = $scope.error = null;
User.resetPassword($scope.passwordDetails, $stateParams.token).then(
function(response){
// If successful show success message and clear form
$scope.success = response.message;
$scope.error = null;
$scope.passwordDetails = null;
// And redirect to the index page
$state.go('reset-success');
},
function(error){
$scope.error = error.message || error;
$scope.passwordDetails = null;
}
);
// And redirect to the index page
$state.go('reset-success');
},
function(error){
$scope.error = error.message || error;
$scope.success = null;
$scope.passwordDetails = null;
}
);
}
};
}
]);

View file

@ -33,8 +33,10 @@ angular.module('users').controller('SettingsController', ['$scope', '$rootScope'
}).success(function(response) {
// If successful show success message and clear form
$scope.success = true;
$scope.error = null;
$scope.user = response;
}).error(function(response) {
$scope.success = null;
$scope.error = response.message;
});
};
@ -47,8 +49,10 @@ angular.module('users').controller('SettingsController', ['$scope', '$rootScope'
user.$update(function(response) {
$scope.success = true;
$scope.error = null;
$scope.user = response;
}, function(response) {
$scope.success = null;
$scope.error = response.data.message;
});
} else {
@ -63,8 +67,10 @@ angular.module('users').controller('SettingsController', ['$scope', '$rootScope'
$http.post('/users/password', $scope.passwordDetails).success(function(response) {
// If successful show success message and clear form
$scope.success = true;
$scope.error = null;
$scope.passwordDetails = null;
}).error(function(response) {
$scope.success = null;
$scope.error = response.message;
});
};

View file

@ -1,7 +1,8 @@
'use strict';
angular.module('users').controller('VerifyController', ['$scope', '$state', '$rootScope', 'User', 'Auth', '$stateParams',
function($scope, $state, $rootScope, User, Auth, $stateParams) {
angular.module('users').controller('VerifyController', ['$scope', '$state', '$rootScope', 'User', 'Auth', '$stateParams', '$translate', '$window',
function($scope, $state, $rootScope, User, Auth, $stateParams, $translate, $window) {
$translate.use($window.locale);
$scope.isResetSent = false;
$scope.credentials = {};
@ -12,11 +13,13 @@ angular.module('users').controller('VerifyController', ['$scope', '$state', '$ro
User.resendVerifyEmail($scope.credentials.email).then(
function(response){
$scope.success = response.message;
$scope.error = null;
$scope.credentials = null;
$scope.isResetSent = true;
},
function(error){
$scope.error = error;
$scope.success = null;
$scope.credentials.email = null;
$scope.isResetSent = false;
}
@ -30,11 +33,13 @@ angular.module('users').controller('VerifyController', ['$scope', '$state', '$ro
User.validateVerifyToken($stateParams.token).then(
function(response){
$scope.success = response.message;
$scope.error = null;
$scope.isResetSent = true;
$scope.credentials.email = null;
},
function(error){
$scope.isResetSent = false;
$scope.success = null;
$scope.error = error;
$scope.credentials.email = null;
}

View file

@ -1,4 +1,15 @@
<section class="text-center auth">
<h3 class="col-md-12">{{ 'ACCESS_DENIED_TEXT' | translate }}</h3>
<a href="/#!/sigin" class="col-md-12">{{ 'SIGNIN_BTN' | translate }}</a>
<section class="row auth" data-ng-controller="PasswordController">
<div class="row valign">
<div class="col-md-4 col-md-offset-4">
<div class="col-md-12 text-center" style="padding-bottom: 50px;">
<img src="/static/modules/core/img/logo_white.svg" height="100px">
</div>
<h3 class="col-md-12 text-center">{{ 'ACCESS_DENIED_TEXT' | translate }}</h3>
<div class="col-md-12 text-center">
<a class="btn btn-signup btn-rounded btn-block" href="/#!/signin" >
{{ 'ASK_FOR_NEW_PASSWORD' | translate }}
</a>
</div>
</div>
</div>
</section>

View file

@ -1,25 +1,4 @@
<section class="auth sigin-view valign-wrapper" data-ng-controller="AuthenticationController">
<!--<h3 class="col-md-12 text-center">{{ 'SIGNIN_HEADER_TEXT' | translate }}</h3>-->
<!--
<div class="col-md-12 text-center">
<a href="/auth/facebook" class="undecorated-link">
<img src="/modules/users/img/buttons/facebook.png">
</a>
<a href="/auth/twitter" class="undecorated-link">
<img src="/modules/users/img/buttons/twitter.png">
</a>
<a href="/auth/google" class="undecorated-link">
<img src="/modules/users/img/buttons/google.png">
</a>
<a href="/auth/linkedin" class="undecorated-link">
<img src="/modules/users/img/buttons/linkedin.png">
</a>
<a href="/auth/github" class="undecorated-link">
<img src="/modules/users/img/buttons/github.png">
</a>
</div>
-->
<!-- <h3 class="col-md-12 text-center">Or with your account</h3> -->
<div class="row valign">
<div class="col-md-4 col-md-offset-4">
@ -27,18 +6,18 @@
<img src="/static/modules/core/img/logo_white.svg" height="100px">
</div>
<div class="col-md-12">
<form class="signin form-horizontal" autocomplete="off">
<form name="forms.signinForm" class="signin form-horizontal" autocomplete="off">
<fieldset>
<div data-ng-show="error" class="text-center text-danger">
Error: <strong data-ng-bind="error"></strong>
{{ 'ERROR' | translate }}: <strong data-ng-bind="error"></strong>
</div>
<div class="form-group">
<!--<label for="username">{{ 'USERNAME_LABEL' | translate }}</label>-->
<input type="text" id="username" name="username" class="form-control" data-ng-model="credentials.username" placeholder="{{ 'USERNAME_OR_EMAIL_LABEL' | translate }}" ng-minlength="4">
<input type="text" id="username" name="username" class="form-control" data-ng-model="credentials.username" placeholder="{{ 'USERNAME_OR_EMAIL_LABEL' | translate }}" required pattern=".{4,}" title="Username/Email must be at least 4 characters">
</div>
<div class="form-group">
<!--<label for="password">{{ 'PASSWORD_LABEL' | translate }}</label>-->
<input type="password" id="password" name="password" class="form-control" data-ng-model="credentials.password" placeholder="{{ 'PASSWORD_LABEL' | translate }}" ng-minlength="4">
<input type="password" id="password" name="password" class="form-control" data-ng-model="credentials.password" placeholder="{{ 'PASSWORD_LABEL' | translate }}" pattern=".{4,}" required title="Passwords must be at least 4 characters">
</div>
<div class="form-group">
<button class="btn btn-signup btn-rounded btn-block" ng-click="signin()">{{ 'SIGNIN_BTN' | translate }}</button>

View file

@ -1,22 +1,4 @@
<section class="auth signup-view success" data-ng-controller="AuthenticationController">
<!-- <h3 class="col-md-12 text-center">Sign up using your social accounts</h3>
<div class="col-md-12 text-center">
<a href="/auth/facebook" class="undecorated-link">
<img src="/modules/users/img/buttons/facebook.png">
</a>
<a href="/auth/twitter" class="undecorated-link">
<img src="/modules/users/img/buttons/twitter.png">
</a>
<a href="/auth/google" class="undecorated-link">
<img src="/modules/users/img/buttons/google.png">
</a>
<a href="/auth/linkedin" class="undecorated-link">
<img src="/modules/users/img/buttons/linkedin.png">
</a>
<a href="/auth/github" class="undecorated-link">
<img src="/modules/users/img/buttons/github.png">
</a>
</div> -->
<h3 class="col-xs-offset-2 col-xs-8 col-md-offset-3 col-md-6 text-center">{{ 'SUCCESS_HEADER' | translate }}</h3>
<div class="col-xs-offset-2 col-xs-8 col-md-offset-3 col-md-6">
<h2>

View file

@ -1,30 +1,10 @@
<section class="auth signup-view valign-wrapper" data-ng-controller="AuthenticationController">
<!-- <h3 class="col-md-12 text-center">Sign up using your social accounts</h3>
<div class="col-md-12 text-center">
<a href="/auth/facebook" class="undecorated-link">
<img src="/modules/users/img/buttons/facebook.png">
</a>
<a href="/auth/twitter" class="undecorated-link">
<img src="/modules/users/img/buttons/twitter.png">
</a>
<a href="/auth/google" class="undecorated-link">
<img src="/modules/users/img/buttons/google.png">
</a>
<a href="/auth/linkedin" class="undecorated-link">
<img src="/modules/users/img/buttons/linkedin.png">
</a>
<a href="/auth/github" class="undecorated-link">
<img src="/modules/users/img/buttons/github.png">
</a>
</div> -->
<!--<h3 class="col-md-12 text-center">{{ 'SIGNUP_HEADER_TEXT' | translate }}</h3>-->
<div class="row valign">
<div class="col-md-12 text-center vcenter" style="padding-bottom: 50px;">
<img src="/static/modules/core/img/logo_white.svg" height="100px">
</div>
<div class="col-xs-offset-3 col-xs-6 col-sm-offset-4 col-sm-4">
<form name="userForm" data-ng-submit="signup()" class="signin form-horizontal" autocomplete="off">
<form name="forms.signupForm" data-ng-submit="signup()" class="signin form-horizontal" autocomplete="off">
<fieldset>
<div data-ng-show="error" id="signup_errors" class="text-center">
{{'SIGNUP_ERROR_TEXT' | translate}}: <br>
@ -32,15 +12,15 @@
</div>
<div class="form-group">
<!--<label for="username">{{ 'USERNAME_LABEL' | translate }}</label>-->
<input type="text" id="username" name="username" class="form-control" ng-pattern="languageRegExp" ng-minlength="4" ng-model="credentials.username" placeholder="{{ 'USERNAME_LABEL' | translate }}" ng-minlength="4">
<input type="text" id="username" name="username" class="form-control" ng-pattern="languageRegExp" ng-minlength="4" ng-model="credentials.username" placeholder="{{ 'USERNAME_LABEL' | translate }}" required pattern=".{4,}" title="Username/Email must be at least 4 characters">
</div>
<div class="form-group">
<!--<label for="email">{{ 'EMAIL_LABEL' | translate }}</label>-->
<input type="email" id="email" name="email" class="form-control" ng-model="credentials.email" placeholder="{{ 'EMAIL_LABEL' | translate }}">
<input type="email" id="email" name="email" class="form-control" ng-model="credentials.email" placeholder="{{ 'EMAIL_LABEL' | translate }}" required pattern=".{4,}" title="Email must be at least 4 characters">
</div>
<div class="form-group">
<!--<label for="password">{{ 'PASSWORD_LABEL' | translate }}</label>-->
<input type="password" id="password" name="password" class="form-control" ng-model="credentials.password" placeholder="{{ 'PASSWORD_LABEL' | translate }}" ng-minlength="4">
<input type="password" id="password" name="password" class="form-control" ng-model="credentials.password" placeholder="{{ 'PASSWORD_LABEL' | translate }}" pattern=".{4,}" required title="Passwords must be at least 4 characters">
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-signup btn-rounded btn-block">{{ 'SIGNUP_BTN' | translate }}</button>

View file

@ -7,18 +7,23 @@
<div class="col-md-12">
<form data-ng-submit="askForPasswordReset()" autocomplete="off">
<fieldset>
<div class="form-group">
<input type="text" id="username" name="username" class="form-control" data-ng-model="credentials.username" placeholder="{{ 'USERNAME_OR_EMAIL_LABEL' | translate }}">
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-signup btn-rounded btn-block">{{ 'PASSWORD_RESTORE_HEADER' | translate }}</button>
</div>
<div data-ng-show="error" class="text-center">
<strong>Error: {{error}}</strong>
<strong>{{ 'ERROR' | translate }}: {{error}}</strong>
</div>
<div data-ng-show="success" class="text-center">
<strong>{{success}}</strong>
</div>
<div class="form-group">
<input type="text" id="username" name="username" class="form-control" data-ng-model="credentials.username" placeholder="{{ 'USERNAME_OR_EMAIL_LABEL' | translate }}">
</div>
<div class="text-center form-group" ng-if="!success">
<button type="submit" class="btn btn-signup btn-rounded btn-block">{{ 'PASSWORD_RESTORE_HEADER' | translate }}</button>
</div>
<div class="col-md-12 text-center" ng-if="success">
<a class="btn btn-signup btn-rounded btn-block" href="/#!/signin" >
{{ 'CONTINUE_TO_LOGIN' | translate }}
</a>
</div>
</fieldset>
</form>
</div>

View file

@ -1,4 +1,17 @@
<section class="row text-center">
<h3 class="col-md-12">{{ 'PASSWORD_RESET_INVALID' | translate }}</h3>
<a href="/#!/password/forgot" class="col-md-12">{{ 'ASK_FOR_NEW_PASSWORD' | translate }}</a>
<section class="row auth" data-ng-controller="PasswordController">
<div class="row valign">
<div class="col-md-4 col-md-offset-4">
<div class="col-md-12 text-center" style="padding-bottom: 50px;">
<img src="/static/modules/core/img/logo_white.svg" height="100px">
</div>
<h3 class="col-md-12 text-center">
{{ 'PASSWORD_RESET_INVALID' | translate }}
</h3>
<div class="col-md-12 text-center">
<a class="btn btn-signup btn-rounded btn-block" href="/#!/password/forgot" >
{{ 'ASK_FOR_NEW_PASSWORD' | translate }}
</a>
</div>
</div>
</div>
</section>

View file

@ -1,4 +1,16 @@
<section class="row text-center">
<h3 class="col-md-12">{{ 'PASSWORD_RESET_SUCCESS' | translate }}</h3>
<a href="/#!/" class="col-md-12">{{ 'CONTINUE_TO_LOGIN' | translate }}</a>
<section class="row auth" data-ng-controller="PasswordController">
<div class="row valign">
<div class="col-md-4 col-md-offset-4">
<div class="col-md-12 text-center" style="padding-bottom: 50px;">
<img src="/static/modules/core/img/logo_white.svg" height="100px">
</div>
<h3 class="col-md-12 text-center">{{ 'PASSWORD_RESET_SUCCESS' | translate }}</h3>
<div class="col-md-12 text-center">
<a class="btn btn-signup btn-rounded btn-block" href="/#!/signin" >
{{ 'CONTINUE_TO_LOGIN' | translate }}
</a>
</div>
</div>
</div>
</section>

View file

@ -1,25 +1,25 @@
<section class="row auth" data-ng-controller="PasswordController">
<h3 class="col-md-12 text-center">{{ 'RESET_PASSWORD' | translate }}</h3>
<div class="col-xs-offset-2 col-xs-8 col-md-offset-3 col-md-6">
<form data-ng-submit="resetUserPassword()" class="signin form-horizontal" autocomplete="off">
<form name="forms.resetPasswordForm" data-ng-submit="resetUserPassword()" class="signin form-horizontal" autocomplete="off">
<fieldset>
<div ng-if="error" class="text-center text-danger">
<strong>{{error}}</strong>
</div>
<div ng-if="success" class="text-center text-success">
<strong>{{success}}</strong>
</div>
<div class="form-group">
<label for="newPassword">{{ 'NEW_PASSWORD_LABEL' | translate }}</label>
<input type="password" id="newPassword" name="newPassword" class="form-control" data-ng-model="passwordDetails.newPassword" placeholder="{{ 'NEW_PASSWORD_LABEL' | translate }}">
<input type="password" id="newPassword" name="newPassword" class="form-control" data-ng-model="passwordDetails.newPassword" placeholder="{{ 'NEW_PASSWORD_LABEL' | translate }}" required pattern=".{4,}" title="Username/Email must be at least 4 characters">
</div>
<div class="form-group">
<label for="verifyPassword">{{ 'VERIFY_PASSWORD_LABEL' | translate }}</label>
<input type="password" id="verifyPassword" name="verifyPassword" class="form-control" data-ng-model="passwordDetails.verifyPassword" placeholder="{{ 'VERIFY_PASSWORD_LABEL' | translate }}">
<input type="password" id="verifyPassword" name="verifyPassword" class="form-control" data-ng-model="passwordDetails.verifyPassword" placeholder="{{ 'VERIFY_PASSWORD_LABEL' | translate }}" required pattern=".{4,}" title="Username/Email must be at least 4 characters">
</div>
<div class="text-center form-group">
<button type="submit" class="btn btn-large btn-primary">{{ 'UPDATE_PASSWORD_LABEL' | translate }}</button>
</div>
<div data-ng-show="error" class="text-center text-danger">
<strong>{{error}}</strong>
</div>
<div data-ng-show="success" class="text-center text-success">
<strong>{{success}}</strong>
</div>
</fieldset>
</form>
</div>

View file

@ -10,7 +10,7 @@
},
"externalDocs": {
"description": "Find out how to host your own TellForm instance.",
"url": "https://github.com/whitef0x0/tellform"
"url": "https://github.com/tellform/tellform"
},
"host": "api.tellform.com",
"basePath": "/",