Compare commits

..

48 Commits

Author SHA1 Message Date
e21d30ed6b some files might have been missing (?) 2020-05-08 23:41:15 +02:00
ef4064af3d disabled beta/invite code on registration (can be re-enabled by config and uncommenting the login html file) 2020-04-15 15:41:52 +02:00
7c5fd6485e keep the current tool as long as the cursor is in the web view 2020-04-15 15:36:37 +02:00
mntmn
a92b915bc3 fix password recovery 2020-04-09 22:21:55 +02:00
mntmn
f5a6adc43b remove unused modals 2020-04-09 21:46:23 +02:00
mntmn
40202ff416 fix logging in text on login button 2020-04-09 19:11:26 +02:00
mntmn
b07050095d remove production/development distinction for javascripts 2020-04-09 19:11:06 +02:00
mntmn
9cb04422d8 remove pdf import options 2020-04-09 19:10:34 +02:00
mntmn
d544caf4a7 anonymous editor: don't ask for username if already logged in 2020-04-09 18:05:07 +02:00
mntmn
2dbfae59f9 remove dead functions from folder 2020-04-09 17:56:47 +02:00
mntmn
e25a56e85c filter attributes on space PUT 2020-04-09 17:56:37 +02:00
mntmn
6f1744bc5d show share button only to admins 2020-04-09 17:50:48 +02:00
mntmn
fab2a61f83 fix error message for messing with space memberships 2020-04-09 17:37:49 +02:00
mntmn
9750f08606 bring back copy and paste of artifacts 2020-04-09 17:33:23 +02:00
mntmn
643b75ebe9 remove tiny piece of unused code 2020-04-09 17:27:14 +02:00
mntmn
2f39dd26be fix listing of invited-to-spaces in user's home folder 2020-04-09 17:26:58 +02:00
mntmn
3edde7c53c remove more dead code 2020-04-09 16:22:17 +02:00
mntmn
01a6bec80e fix loading space that user is member of 2020-04-09 16:20:29 +02:00
mntmn
bdb2e9fde5 clean up space memberships table; clean up terminate account view 2020-04-09 15:37:51 +02:00
mntmn
7cf68c94a5 remove unused templates 2020-04-09 15:26:28 +02:00
mntmn
ecdacd6e11 explicitly make new spaces private 2020-04-09 15:23:14 +02:00
mntmn
92cf6c4397 some cleanups to mailer and user deletion 2020-04-09 15:22:06 +02:00
mntmn
d6f93051ef signup: reorder fields to play better with conventions and pw managers 2020-04-09 15:21:47 +02:00
mntmn
4073e36441 remove noisy console.log 2020-04-09 15:02:10 +02:00
mntmn
16ffecdb16 fix error handling and displaying on membership PUT and DELETE; don't allow to change your own role; require at least one admin 2020-04-09 14:55:18 +02:00
mntmn
c05afaba8a remove folder and space 'duplication' leftovers 2020-04-09 14:15:48 +02:00
mntmn
9d3105763b readme update 2020-04-08 22:11:56 +02:00
mntmn
f5e5a7f8fe readme update 2020-04-08 22:11:10 +02:00
mntmn
9ed5a9931f update ws module 2020-04-08 22:00:20 +02:00
mntmn
ddd1ed2cb1 landing: add screenshot 2020-04-08 21:56:41 +02:00
mntmn
2ac0d49f2f quick mobile responsiveness fix 2020-04-08 21:29:16 +02:00
mntmn
80f9b0d93f Spacedeck 6.0 CI WIP; more style, UX cleanups; fix account dialog; add more color swatches; new landing page 2020-04-08 20:45:30 +02:00
mntmn
58250a72ad WIP MNT design/UX cleanup 2020-04-07 20:37:41 +02:00
mntmn
d19d02220e fix phantomjs ssl error and space screenshots 2019-05-19 23:16:30 +02:00
mntmn
69037685c1 add missing email_invited field on memberships 2019-05-19 22:42:23 +02:00
mntmn
3fdb1bf8bb add gulp-concat, gulp-sass deps 2019-05-19 22:38:31 +02:00
mntmn
b72a3af124 remove google login button 2019-05-19 22:38:03 +02:00
mntmn
f7394d3195 remove bin folder 2019-05-19 22:37:46 +02:00
mntmn
3b735d28f6 fix migration 01 2019-05-19 22:37:35 +02:00
mntmn
8ba37a11d6 purge IE 2019-05-15 22:36:53 +02:00
mntmn
58aa3fc41f fix gulpfile to signal completion, clean up a bit 2019-05-15 21:35:29 +02:00
mntmn
db849bcb20 fix most vulns via npm audit fix 2019-05-15 21:29:34 +02:00
mntmn
0efeb8d1df remove electron, docker 2019-05-15 21:25:53 +02:00
mntmn
2fc14e1efe
Update README.md 2018-07-25 11:05:35 +02:00
mntmn
79a3d39015
Remove windows prerelease from README
Releases should be tested and built via CI/CD.
2018-07-17 12:21:32 +02:00
Lukas F. Hartmann
628ceb6c3a Merge branch 'master' of https://github.com/spacedeck/spacedeck-open 2018-07-17 12:18:14 +02:00
Lukas F. Hartmann
9889aaa34c Merge branch 'kaleidos-issues/23/deleting-space-user-is-not-possible' 2018-07-17 12:17:56 +02:00
Hirunatan
ea4f40b628 Implement SMTP email service (#28) 2018-07-17 12:05:27 +02:00
69 changed files with 1444 additions and 2710 deletions

2
.gitignore vendored
View File

@ -1,6 +1,8 @@
node_modules node_modules
javascripts/maps javascripts/maps
javascripts/spacedeck.js javascripts/spacedeck.js
public/stylesheets/*.css
database.sqlite
*.swp *.swp
*~ *~

View File

@ -1,13 +1,13 @@
var gulp = require('gulp'); const gulp = require('gulp')
var sass = require('gulp-sass'); const sass = require('gulp-sass')
var concat = require('gulp-concat'); const concat = require('gulp-concat')
gulp.task('styles', function() { gulp.task('styles', function(done) {
gulp.src('styles/**/*.scss') gulp.src('styles/**/*.scss')
.pipe(sass({ .pipe(sass({
errLogToConsole: true errLogToConsole: true
})) }))
.pipe(gulp.dest('./public/stylesheets/')) .pipe(gulp.dest('./public/stylesheets/'))
.pipe(concat('style.css')); .pipe(concat('style.css'))
}); done()
})

View File

@ -1,15 +1,15 @@
# Spacedeck Open # Spacedeck Open
![Spacedeck 6.0 Screenshot](/public/images/sd6-screenshot.png)
This is the free and open source version of Spacedeck, a web based, real time, collaborative whiteboard application with rich media support. Spacedeck was developed in 6 major releases during Autumn 2011 until the end of 2016 and was originally a commercial SaaS. The developers were Lukas F. Hartmann (mntmn) and Martin GĂĽther (magegu). This is the free and open source version of Spacedeck, a web based, real time, collaborative whiteboard application with rich media support. Spacedeck was developed in 6 major releases during Autumn 2011 until the end of 2016 and was originally a commercial SaaS. The developers were Lukas F. Hartmann (mntmn) and Martin GĂĽther (magegu).
The spacedeck.com online service was shut down on May 1st 2018. We decided to open-source Spacedeck to allow educational and other organizations who currently rely on Spacedeck to migrate to a self-hosted or local version. The spacedeck.com online service was shut down on May 1st 2018. We decided to open-source Spacedeck to allow educational and other organizations who currently rely on Spacedeck to migrate to a self-hosted or local version.
[MNT Research GmbH](https://mntre.com) has restarted development of Spacedeck Open in 2020.
We appreciate filed issues, pull requests and general discussion. We appreciate filed issues, pull requests and general discussion.
**Windows users:** Try the one-click release at https://github.com/spacedeck/spacedeck-open/releases/tag/v0.9
Desktop releases for Linux and Mac will be published here soon. In the meantime, you have to install Node.JS to run Spacedeck.
# Features # Features
- Create virtual whiteboards called *Spaces* with virtually unlimited size - Create virtual whiteboards called *Spaces* with virtually unlimited size
@ -17,27 +17,23 @@ Desktop releases for Linux and Mac will be published here soon. In the meantime,
- Write and format text with full control over fonts, colors and style - Write and format text with full control over fonts, colors and style
- Draw, annotate and highlight with included graphical shapes - Draw, annotate and highlight with included graphical shapes
- Turn your Space into a zooming presentation - Turn your Space into a zooming presentation
- Collaborate and chat in realtime with teammates, students or friends - Collaborate in realtime with teammates, students or friends
- Share Spaces on the web or via email - Share Spaces on the web or via email
- Export your work as printable PDF or ZIP - Export your work as printable PDF or ZIP (currently being fixed, stay tuned)
# Data Import from Spacedeck.com # Use Cases
Spacedeck Open has a data import feature that you can use to migrate your ZIP export from Spacedeck.com. - Education: Virtual classwork with multimedia
- Creative: Mood boards, Brainstorming, Design Thinking
1. Just copy your downloaded ZIP file into the spacedeck root folder. Don't extract it. - Visual note taking and planning
2. Start your local Spacedeck.
3. Navigate to *Account / Profile* (person icon in the top right corner).
4. Click the *Import* button next to the ZIP file name. It is on the bottom of the page.
5. Wait until console output has finished and you're done.
# Requirements, Installation # Requirements, Installation
Spacedeck requires: Spacedeck requires:
- Node.js 9.x: Web Server / API. Download: https://nodejs.org - Node.js 10.x: Web Server / API. Download: https://nodejs.org
To run Spacedeck, you only need Node.JS 9.x. To run Spacedeck, you only need Node.JS 10.x.
To install all node dependencies, run (do this once): To install all node dependencies, run (do this once):
@ -53,10 +49,6 @@ See [config/default.json](config/default.json)
Then open http://localhost:9666 in a web browser. Then open http://localhost:9666 in a web browser.
# Run (desktop app with integrated web server)
electron .
# Optional Dependencies # Optional Dependencies
For advanced media conversion: For advanced media conversion:

0
bin/www Executable file → Normal file
View File

View File

@ -1,8 +1,11 @@
{ {
//"endpoint": "http://localhost:9000", "team_name": "My Open Spacedeck",
"endpoint": "http://localhost:9666", "contact_email": "support@example.org",
"storage_region": "eu-central-1",
"endpoint": "http://localhost:9666",
"invite_code": "", //disabled invite code by default
"storage_region": "eu-central-1",
//"storage_bucket": "sdeck-development", //"storage_bucket": "sdeck-development",
//"storage_cdn": "http://localhost:9123/sdeck-development", //"storage_cdn": "http://localhost:9123/sdeck-development",
//"storage_endpoint": "http://storage:9000", //"storage_endpoint": "http://storage:9000",
@ -18,5 +21,14 @@
"google_access" : "", "google_access" : "",
"google_secret" : "", "google_secret" : "",
"admin_pass": "very_secret_admin_password", "admin_pass": "very_secret_admin_password",
"phantom_api_secret": "very_secret_phantom_password" "phantom_api_secret": "very_secret_phantom_password",
// Choose "console" or "smtp"
"mail_provider": "smtp",
"mail_smtp_host": "your.smtp.host",
"mail_smtp_port": 465,
"mail_smtp_secure": true,
"mail_smtp_require_tls": true,
"mail_smtp_user": "your.smtp.user",
"mail_smtp_pass": "your.secret.smtp.password"
} }

View File

@ -1,18 +1,18 @@
'use strict'; 'use strict';
var swig = require('swig'); const config = require('config');
const nodemailer = require('nodemailer');
const swig = require('swig');
//var AWS = require('aws-sdk'); //var AWS = require('aws-sdk');
module.exports = { module.exports = {
sendMail: (to_email, subject, body, options) => { sendMail: (to_email, subject, body, options) => {
if (!options) { if (!options) {
options = {}; options = {};
} }
// FIXME const teamname = options.teamname || config.get('team_name');
const teamname = options.teamname || "My Open Spacedeck" const from = teamname + ' <' + config.get('contact_email') + '>';
const from = teamname + ' <support@example.org>';
let reply_to = [from]; let reply_to = [from];
if (options.reply_to) { if (options.reply_to) {
@ -29,33 +29,38 @@ module.exports = {
options: options options: options
}); });
//if (process.env.NODE_ENV === 'development') { if (config.get('mail_provider') === 'console') {
console.log("Email: to " + to_email + " in production.\nreply_to: " + reply_to + "\nsubject: " + subject + "\nbody: \n" + htmlText + "\n\n plaintext:\n" + plaintext);
/*} else {
AWS.config.update({region: 'eu-west-1'});
var ses = new AWS.SES();
ses.sendEmail( { console.log("Email: to " + to_email + " in production.\nreply_to: " + reply_to + "\nsubject: " + subject + "\nbody: \n" + htmlText + "\n\n plaintext:\n" + plaintext);
Source: from,
Destination: { ToAddresses: [to_email] }, } else if (config.get('mail_provider') === 'smtp') {
ReplyToAddresses: reply_to,
Message: { const transporter = nodemailer.createTransport({
Subject: { host: config.get('mail_smtp_host'),
Data: subject port: config.get('mail_smtp_port'),
}, secure: config.get('mail_smtp_secure'),
Body: { requireTLS: config.get('mail_smtp_require_tls'),
Text: { auth: {
Data: plaintext, user: config.get('mail_smtp_user'),
}, pass: config.get('mail_smtp_pass'),
Html: {
Data: htmlText
} }
}
}
}, function(err, data) {
if (err) console.error("Error sending email:", err);
else console.log("Email sent.");
}); });
}*/
transporter.sendMail({
from: from,
replyTo: reply_to,
to: to_email,
subject: subject,
text: plaintext,
html: htmlText,
}, function(err, info) {
if (err) {
console.error("Error sending email:", err);
} else {
console.log("Email sent.");
}
});
}
} }
}; };

View File

@ -57,11 +57,6 @@ module.exports = (req, res, next) => {
"_id": spaceId "_id": spaceId
}}).then(function(space) { }}).then(function(space) {
//.populate("creator", userMapping)
//if (err) {
// res.status(400).json(err);
//} else {
if (space) { if (space) {
if (space.access_mode == "public") { if (space.access_mode == "public") {
if (space.password) { if (space.password) {

View File

@ -91,7 +91,8 @@ module.exports = {
user_id: Sequelize.STRING, user_id: Sequelize.STRING,
role: Sequelize.STRING, role: Sequelize.STRING,
code: Sequelize.STRING, code: Sequelize.STRING,
state: {type: Sequelize.STRING, defaultValue: "pending"}, state: {type: Sequelize.STRING, defaultValue: "pending"}, // valid: "pending", "active"
email_invited: Sequelize.STRING,
created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}, created_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW},
updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW} updated_at: {type: Sequelize.DATE, defaultValue: Sequelize.NOW}
}), }),
@ -278,21 +279,20 @@ module.exports = {
getUserRoleInSpace: (originalSpace, user, cb) => { getUserRoleInSpace: (originalSpace, user, cb) => {
originalSpace.path = []; originalSpace.path = [];
console.log("getUserRoleInSpace",originalSpace._id,user._id,user.home_folder_id);
if (originalSpace._id == user.home_folder_id || (originalSpace.creator_id && originalSpace.creator_id == user._id)) { if (originalSpace._id == user.home_folder_id || (originalSpace.creator_id && originalSpace.creator_id == user._id)) {
cb("admin"); cb("admin");
} else { } else {
var findMembershipsForSpace = function(space, allMemberships, prevRole) { var findMembershipsForSpace = function(space, allMemberships, prevRole) {
Membership.findAll({ where: { Membership.findAll({ where: {
"space": space._id "space_id": space._id
}}).then(function(parentMemberships) { }}).then(function(parentMemberships) {
var currentMemberships = parentMemberships.concat(allMemberships); var currentMemberships = parentMemberships.concat(allMemberships);
if (space.parent_space_id) { if (space.parent_space_id) {
Space.findOne({ where: { Space.findOne({ where: {
"_id": space.parent_space_id "_id": space.parent_space_id
}}, function(err, parentSpace) { }}).then(function(parentSpace) {
findMembershipsForSpace(parentSpace, currentMemberships, prevRole); findMembershipsForSpace(parentSpace, currentMemberships, prevRole);
}); });
} else { } else {

View File

@ -2,7 +2,7 @@
module.exports = { module.exports = {
up: function(migration, DataTypes) { up: function(migration, DataTypes) {
return [ return Promise.all([
migration.changeColumn('memberships', 'space_id', migration.changeColumn('memberships', 'space_id',
{ {
type: DataTypes.STRING, type: DataTypes.STRING,
@ -36,11 +36,11 @@ module.exports = {
onUpdate: 'CASCADE' onUpdate: 'CASCADE'
} }
) )
] ])
}, },
down: function(migration, DataTypes) { down: function(migration, DataTypes) {
return [ return Promise.all([
migration.changeColumn('memberships', 'space_id', migration.changeColumn('memberships', 'space_id',
{ {
type: DataTypes.STRING, type: DataTypes.STRING,
@ -52,7 +52,6 @@ module.exports = {
onUpdate: 'NO ACTION' onUpdate: 'NO ACTION'
} }
), ),
,
migration.changeColumn('artifacts', 'space_id', migration.changeColumn('artifacts', 'space_id',
{ {
type: DataTypes.STRING, type: DataTypes.STRING,
@ -75,6 +74,6 @@ module.exports = {
onUpdate: 'NO ACTION' onUpdate: 'NO ACTION'
} }
) )
] ])
} }
}; }

View File

@ -3,48 +3,52 @@
"version": "1.0.0", "version": "1.0.0",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "electron ." "start": "node spacedeck.js"
}, },
"engines": { "engines": {
"node": ">=7.8.0" "node": ">=10.0.0"
}, },
"dependencies": { "dependencies": {
"archiver": "1.3.0", "archiver": "1.3.0",
"async": "2.3.0", "async": "2.3.0",
"basic-auth": "1.1.0", "basic-auth": "1.1.0",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"body-parser": "~1.17.1", "body-parser": "^1.19.0",
"cheerio": "0.22.0", "cheerio": "0.22.0",
"config": "1.25.1", "config": "1.25.1",
"cookie-parser": "~1.4.3", "cookie-parser": "~1.4.3",
"electron": "^1.8.4",
"execSync": "latest", "execSync": "latest",
"express": "~4.13.0", "express": "^4.16.4",
"file-type": "^7.6.0", "file-type": "^7.6.0",
"glob": "7.1.1", "glob": "7.1.1",
"gm": "1.23.0", "gm": "^1.23.1",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-sass": "^4.0.2",
"helmet": "^3.5.0", "helmet": "^3.5.0",
"i18n-2": "0.6.3", "i18n-2": "0.6.3",
"log-timestamp": "latest", "log-timestamp": "latest",
"mock-aws-s3": "^2.6.0", "mock-aws-s3": "^2.6.0",
"moment": "^2.19.3", "moment": "^2.19.3",
"morgan": "1.8.1", "morgan": "^1.9.1",
"node-phantom-simple": "2.2.4", "node-phantom-simple": "2.2.4",
"phantomjs-prebuilt": "2.1.14", "node-server-screenshot": "^0.2.1",
"nodemailer": "^4.6.7",
"phantomjs-prebuilt": "^2.1.16",
"read-chunk": "^2.1.0", "read-chunk": "^2.1.0",
"request": "2.81.0", "request": "^2.88.0",
"sanitize-html": "^1.11.1", "sanitize-html": "^1.11.1",
"sequelize": "^4.37.6", "sequelize": "^4.37.6",
"serve-favicon": "~2.4.2", "serve-favicon": "~2.4.2",
"serve-static": "^1.13.1", "serve-static": "^1.13.1",
"slug": "0.9.1", "slug": "^1.1.0",
"sqlite3": "^4.0.0", "sqlite3": "^4.0.0",
"swig": "1.4.2", "swig": "1.4.2",
"umzug": "^2.1.0", "umzug": "^2.1.0",
"underscore": "1.8.3", "underscore": "1.8.3",
"uuid": "^3.2.1", "uuid": "^3.2.1",
"validator": "7.0.0", "validator": "7.0.0",
"ws": "2.2.3" "ws": "3.3.1"
}, },
"main": "app.js", "main": "app.js",
"description": "", "description": "",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="17.370329mm"
height="17.370247mm"
viewBox="0 0 17.370329 17.370247"
version="1.1"
id="svg3417"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="sd6-icon-white.svg"
inkscape:export-filename="/home/mntmn/code/spacedeck-open/public/images/favicon.png"
inkscape:export-xdpi="93.585312"
inkscape:export-ydpi="93.585312">
<defs
id="defs3411" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6"
inkscape:cx="68.901329"
inkscape:cy="26.613846"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="2560"
inkscape:window-height="1376"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata3414">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-61.618407,-79.672019)">
<path
inkscape:connector-curvature="0"
id="path1681-6-5-3-7-4-9-2-0-2-9-7"
d="m 69.103371,79.69206 c -0.792105,0.07526 -1.553632,0.368078 -2.179688,0.99414 -0.967242,0.967233 -1.023215,2.24006 -0.822265,3.46875 -1.228429,-0.200703 -2.499819,-0.144769 -3.466797,0.822266 -1.252082,1.252133 -1.178244,3.043412 -0.677734,4.544922 0.500509,1.50151 1.477937,2.995513 2.832031,4.349611 1.354102,1.3541 2.848091,2.33152 4.349609,2.83203 1.501518,0.50051 3.292795,0.57437 4.544922,-0.67773 0.9673,-0.96727 1.023249,-2.24001 0.822266,-3.468755 1.228416,0.200714 2.499803,0.146691 3.466796,-0.820313 1.252124,-1.252112 1.17824,-3.045353 0.677735,-4.546874 -0.500505,-1.501522 -1.477926,-2.995502 -2.832031,-4.34961 -1.354109,-1.354105 -2.848087,-2.329573 -4.34961,-2.830078 -0.750761,-0.250253 -1.57313,-0.393617 -2.365234,-0.318359 z m 0.251953,3.427734 c -0.06232,0.06232 0.187775,-0.12686 1.025391,0.152344 0.837615,0.279204 1.980359,0.976455 3.005859,2.001953 1.025498,1.0255 1.720796,2.16629 2,3.003906 0.279204,0.837616 0.09198,1.087707 0.154297,1.025391 0.06232,-0.06232 -0.187775,0.124907 -1.025391,-0.154297 -0.817005,-0.272334 -1.926016,-0.966798 -2.93164,-1.951172 -0.02107,-0.02133 -0.03343,-0.04515 -0.05469,-0.06641 -0.02194,-0.02194 -0.04635,-0.0349 -0.06836,-0.05664 -0.984356,-1.005615 -1.678841,-2.112692 -1.951172,-2.929687 -0.279204,-0.837616 -0.09198,-1.087708 -0.154297,-1.025391 z m -4.289063,4.289063 c -0.06231,0.06232 0.187774,-0.124903 1.025391,0.154296 0.81575,0.271911 1.923337,0.965368 2.927735,1.947266 0.02276,0.02306 0.03561,0.04929 0.05859,0.07227 0.023,0.023 0.04918,0.03581 0.07227,0.05859 0.981898,1.004395 1.67535,2.111982 1.947265,2.927735 0.279205,0.837619 0.09198,1.087705 0.154297,1.025385 0.06232,-0.0623 -0.187772,0.12492 -1.02539,-0.154291 -0.837619,-0.27921 -1.980364,-0.974504 -3.00586,-2 -1.025488,-1.025491 -1.720791,-2.168245 -2,-3.00586 -0.279208,-0.837615 -0.09198,-1.087708 -0.154297,-1.02539 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.4395833;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:37.79527664;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="17.370329mm"
height="17.370247mm"
viewBox="0 0 17.370329 17.370247"
version="1.1"
id="svg3417"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="sd6-icon.svg">
<defs
id="defs3411" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6"
inkscape:cx="68.901329"
inkscape:cy="26.613846"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="2560"
inkscape:window-height="1376"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata3414">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-61.618407,-79.672019)">
<path
inkscape:connector-curvature="0"
id="path1681-6-5-3-7-4-9-2-0-2-9-7"
d="m 69.103371,79.69206 c -0.792105,0.07526 -1.553632,0.368078 -2.179688,0.99414 -0.967242,0.967233 -1.023215,2.24006 -0.822265,3.46875 -1.228429,-0.200703 -2.499819,-0.144769 -3.466797,0.822266 -1.252082,1.252133 -1.178244,3.043412 -0.677734,4.544922 0.500509,1.50151 1.477937,2.995513 2.832031,4.349611 1.354102,1.3541 2.848091,2.33152 4.349609,2.83203 1.501518,0.50051 3.292795,0.57437 4.544922,-0.67773 0.9673,-0.96727 1.023249,-2.24001 0.822266,-3.468755 1.228416,0.200714 2.499803,0.146691 3.466796,-0.820313 1.252124,-1.252112 1.17824,-3.045353 0.677735,-4.546874 -0.500505,-1.501522 -1.477926,-2.995502 -2.832031,-4.34961 -1.354109,-1.354105 -2.848087,-2.329573 -4.34961,-2.830078 -0.750761,-0.250253 -1.57313,-0.393617 -2.365234,-0.318359 z m 0.251953,3.427734 c -0.06232,0.06232 0.187775,-0.12686 1.025391,0.152344 0.837615,0.279204 1.980359,0.976455 3.005859,2.001953 1.025498,1.0255 1.720796,2.16629 2,3.003906 0.279204,0.837616 0.09198,1.087707 0.154297,1.025391 0.06232,-0.06232 -0.187775,0.124907 -1.025391,-0.154297 -0.817005,-0.272334 -1.926016,-0.966798 -2.93164,-1.951172 -0.02107,-0.02133 -0.03343,-0.04515 -0.05469,-0.06641 -0.02194,-0.02194 -0.04635,-0.0349 -0.06836,-0.05664 -0.984356,-1.005615 -1.678841,-2.112692 -1.951172,-2.929687 -0.279204,-0.837616 -0.09198,-1.087708 -0.154297,-1.025391 z m -4.289063,4.289063 c -0.06231,0.06232 0.187774,-0.124903 1.025391,0.154296 0.81575,0.271911 1.923337,0.965368 2.927735,1.947266 0.02276,0.02306 0.03561,0.04929 0.05859,0.07227 0.023,0.023 0.04918,0.03581 0.07227,0.05859 0.981898,1.004395 1.67535,2.111982 1.947265,2.927735 0.279205,0.837619 0.09198,1.087705 0.154297,1.025385 0.06232,-0.0623 -0.187772,0.12492 -1.02539,-0.154291 -0.837619,-0.27921 -1.980364,-0.974504 -3.00586,-2 -1.025488,-1.025491 -1.720791,-2.168245 -2,-3.00586 -0.279208,-0.837615 -0.09198,-1.087708 -0.154297,-1.02539 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.4395833;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:37.79527664;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="81.731232mm"
height="17.370247mm"
viewBox="0 0 81.731232 17.370247"
version="1.1"
id="svg2651"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
sodipodi:docname="sd6-logo-black.svg">
<defs
id="defs2645" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8"
inkscape:cx="80.852573"
inkscape:cy="-16.110417"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="2560"
inkscape:window-height="1376"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1" />
<metadata
id="metadata2648">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-29.059958,-86.19285)">
<g
id="g3248">
<path
inkscape:connector-curvature="0"
id="path1681-6-5-3-7-4-9-2-0-2-9-7"
d="m 36.544922,86.212891 c -0.792105,0.07526 -1.553632,0.368078 -2.179688,0.99414 -0.967242,0.967233 -1.023215,2.24006 -0.822265,3.46875 -1.228429,-0.200703 -2.499819,-0.144769 -3.466797,0.822266 -1.252082,1.252133 -1.178244,3.043412 -0.677734,4.544922 0.500509,1.50151 1.477937,2.995513 2.832031,4.349611 1.354102,1.3541 2.848091,2.33152 4.349609,2.83203 1.501518,0.50051 3.292795,0.57437 4.544922,-0.67773 0.9673,-0.96727 1.023249,-2.24001 0.822266,-3.468755 1.228416,0.200714 2.499803,0.146691 3.466796,-0.820313 1.252124,-1.252112 1.17824,-3.045353 0.677735,-4.546874 -0.500505,-1.501522 -1.477926,-2.995502 -2.832031,-4.34961 -1.354109,-1.354105 -2.848087,-2.329573 -4.34961,-2.830078 -0.750761,-0.250253 -1.57313,-0.393617 -2.365234,-0.318359 z m 0.251953,3.427734 c -0.06232,0.06232 0.187775,-0.12686 1.025391,0.152344 0.837615,0.279204 1.980359,0.976455 3.005859,2.001953 1.025498,1.0255 1.720796,2.16629 2,3.003906 0.279204,0.837616 0.09198,1.087707 0.154297,1.025391 0.06232,-0.06232 -0.187775,0.124907 -1.025391,-0.154297 -0.817005,-0.272334 -1.926016,-0.966798 -2.93164,-1.951172 -0.02107,-0.02133 -0.03343,-0.04515 -0.05469,-0.06641 -0.02194,-0.02194 -0.04635,-0.0349 -0.06836,-0.05664 -0.984356,-1.005615 -1.678841,-2.112692 -1.951172,-2.929687 -0.279204,-0.837616 -0.09198,-1.087708 -0.154297,-1.025391 z m -4.289063,4.289063 c -0.06231,0.06232 0.187774,-0.124903 1.025391,0.154296 0.81575,0.271911 1.923337,0.965368 2.927735,1.947266 0.02276,0.02306 0.03561,0.04929 0.05859,0.07227 0.023,0.023 0.04918,0.03581 0.07227,0.05859 0.981898,1.004395 1.67535,2.111982 1.947265,2.927735 0.279205,0.837619 0.09198,1.087705 0.154297,1.025385 0.06232,-0.0623 -0.187772,0.12492 -1.02539,-0.154291 -0.837619,-0.27921 -1.980364,-0.974504 -3.00586,-2 -1.025488,-1.025491 -1.720791,-2.168245 -2,-3.00586 -0.279208,-0.837615 -0.09198,-1.087708 -0.154297,-1.02539 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.4395833;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:37.79527664;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<g
id="g2614"
transform="matrix(0.26458333,0,0,0.26458333,-523.78744,61.714265)">
<g
id="flowRoot1610-0-6-8-1-1"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;line-height:1.25;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.37800002;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:37.79527664;stroke-opacity:1"
transform="matrix(2.6369365,0,0,2.6369365,2045.0224,86.079903)"
aria-label="Spacedeck">
<path
id="path3214"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
d="m 52.795627,11.002199 h 2.693247 C 55.466146,8.82601 53.73315,7.3543837 51.028539,7.3543837 c -2.659155,0 -4.573974,1.4488985 -4.556928,3.6137233 -0.0057,1.767088 1.232985,2.76143 3.244397,3.221669 l 1.215938,0.284097 c 1.27844,0.295462 1.852317,0.642061 1.863681,1.295486 -0.01136,0.710244 -0.676152,1.204575 -1.806861,1.204575 -1.244349,0 -2.06255,-0.57956 -2.125052,-1.698905 h -2.693246 c 0.03409,2.721656 1.926182,4.022824 4.852389,4.022824 2.897797,0 4.613748,-1.312532 4.625112,-3.522812 -0.01136,-1.857999 -1.267076,-2.99439 -3.562586,-3.500084 l -1.000024,-0.227278 c -1.056844,-0.227279 -1.727315,-0.57956 -1.704587,-1.272758 0.0057,-0.636379 0.55115,-1.0966177 1.642085,-1.0966177 1.096618,0 1.698905,0.4943297 1.77277,1.3238957 z"
inkscape:connector-curvature="0" />
<path
id="path3216"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
d="m 57.068458,22.422928 h 2.778476 v -4.687613 h 0.05682 c 0.352281,0.806838 1.136391,1.53981 2.454605,1.53981 1.931864,0 3.48872,-1.5114 3.48872,-4.483062 0,-3.07962 -1.647767,-4.483063 -3.471674,-4.483063 -1.380715,0 -2.136415,0.806838 -2.471651,1.607994 h -0.08523 v -1.494355 h -2.750066 z m 2.721656,-7.636547 c 0,-1.426171 0.590923,-2.306874 1.607993,-2.306874 1.028434,0 1.59663,0.903431 1.59663,2.306874 0,1.409125 -0.568196,2.323919 -1.59663,2.323919 -1.01707,0 -1.607993,-0.909112 -1.607993,-2.323919 z"
inkscape:connector-curvature="0" />
<path
id="path3218"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
d="m 69.778991,19.297853 c 1.215939,0 2.056868,-0.471602 2.534152,-1.363669 h 0.06818 v 1.215938 h 2.613699 v -5.931961 c 0,-1.846635 -1.642085,-2.909161 -3.86373,-2.909161 -2.346647,0 -3.676224,1.181847 -3.897821,2.772794 l 2.562562,0.09091 c 0.119321,-0.556832 0.579559,-0.897749 1.312532,-0.897749 0.681834,0 1.113663,0.329553 1.113663,0.914794 v 0.02841 c 0,0.534104 -0.57956,0.647743 -2.068232,0.778428 -1.767088,0.147731 -3.244396,0.801156 -3.244396,2.73302 0,1.727315 1.198892,2.568244 2.869387,2.568244 z m 0.857975,-1.818226 c -0.642061,0 -1.096617,-0.306825 -1.096617,-0.886384 0,-0.562514 0.443193,-0.903431 1.232984,-1.022752 0.517058,-0.07387 1.153437,-0.187505 1.465945,-0.352282 v 0.829566 c 0,0.852293 -0.715927,1.431852 -1.602312,1.431852 z"
inkscape:connector-curvature="0" />
<path
id="path3220"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
d="m 80.767893,19.314899 c 2.454605,0 3.977369,-1.426171 4.051234,-3.585314 h -2.596653 c -0.102275,0.926159 -0.659107,1.431853 -1.420489,1.431853 -0.977296,0 -1.613675,-0.823883 -1.613675,-2.375057 0,-1.53981 0.642061,-2.363693 1.613675,-2.363693 0.795474,0 1.312532,0.539785 1.420489,1.431852 h 2.596653 c -0.0625,-2.147779 -1.630721,-3.54554 -4.056916,-3.54554 -2.744384,0 -4.403515,1.82959 -4.403515,4.505791 0,2.664836 1.647767,4.500108 4.409197,4.500108 z"
inkscape:connector-curvature="0" />
<path
id="path3222"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
d="m 90.336304,19.314899 c 2.289828,0 3.795546,-1.107981 4.113736,-2.823932 l -2.551198,-0.07387 c -0.215914,0.579559 -0.78411,0.892067 -1.5114,0.892067 -1.068208,0 -1.727315,-0.710245 -1.727315,-1.778452 v -0.07386 h 5.818322 v -0.693199 c 0,-2.875069 -1.750042,-4.454653 -4.227374,-4.454653 -2.636427,0 -4.32965,1.806862 -4.32965,4.511473 0,2.795521 1.670495,4.494426 4.414879,4.494426 z m -1.676177,-5.471723 c 0.03977,-0.869339 0.727291,-1.528446 1.647767,-1.528446 0.914795,0 1.573902,0.636379 1.585266,1.528446 z"
inkscape:connector-curvature="0" />
<path
id="path3224"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
d="m 99.10072,19.275125 c 1.31821,0 2.10232,-0.732972 2.4546,-1.53981 h 0.0852 v 1.414807 h 2.75007 V 7.5134784 h -2.77848 v 4.4035156 h -0.0568 C 101.22577,11.115838 100.46439,10.309 99.089356,10.309 c -1.823907,0 -3.477356,1.403443 -3.477356,4.483063 0,2.971662 1.562537,4.483062 3.48872,4.483062 z m 0.96593,-2.164825 c -1.028432,0 -1.602309,-0.914794 -1.602309,-2.323919 0,-1.403443 0.568196,-2.306874 1.602309,-2.306874 1.01707,0 1.608,0.880703 1.608,2.306874 0,1.414807 -0.59661,2.323919 -1.608,2.323919 z"
inkscape:connector-curvature="0" />
<path
id="path3226"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
d="m 110.24303,19.314899 c 2.28983,0 3.79555,-1.107981 4.11374,-2.823932 l -2.5512,-0.07387 c -0.21591,0.579559 -0.78411,0.892067 -1.5114,0.892067 -1.06821,0 -1.72731,-0.710245 -1.72731,-1.778452 v -0.07386 h 5.81832 v -0.693199 c 0,-2.875069 -1.75004,-4.454653 -4.22737,-4.454653 -2.63643,0 -4.32965,1.806862 -4.32965,4.511473 0,2.795521 1.67049,4.494426 4.41487,4.494426 z m -1.67617,-5.471723 c 0.0398,-0.869339 0.72729,-1.528446 1.64777,-1.528446 0.91479,0 1.5739,0.636379 1.58526,1.528446 z"
inkscape:connector-curvature="0" />
<path
id="path3228"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
d="m 119.89384,19.314899 c 2.4546,0 3.97736,-1.426171 4.05123,-3.585314 h -2.59665 c -0.10228,0.926159 -0.65911,1.431853 -1.42049,1.431853 -0.9773,0 -1.61368,-0.823883 -1.61368,-2.375057 0,-1.53981 0.64206,-2.363693 1.61368,-2.363693 0.79547,0 1.31253,0.539785 1.42049,1.431852 h 2.59665 c -0.0625,-2.147779 -1.63072,-3.54554 -4.05692,-3.54554 -2.74438,0 -4.40351,1.82959 -4.40351,4.505791 0,2.664836 1.64777,4.500108 4.4092,4.500108 z"
inkscape:connector-curvature="0" />
<path
id="path3230"
style="font-style:normal;font-variant:normal;font-weight:800;font-stretch:normal;font-size:16.00038528px;font-family:Inter;-inkscape-font-specification:'Inter, Ultra-Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none"
d="m 125.3826,19.150122 h 2.77848 v -2.619381 l 0.56251,-0.681835 2.0796,3.301216 h 3.2103 l -3.22167,-4.926255 3.09667,-3.801228 h -3.1478 l -2.45461,3.125076 h -0.125 V 7.5134784 h -2.77848 z"
inkscape:connector-curvature="0" />
</g>
<path
d="m 2146.72,133.51812 a 23.030019,11.514995 45 0 1 -24.427,-8.1423 23.030019,11.514995 45 0 1 -8.1423,-24.427 23.030019,11.514995 45 0 1 24.427,8.1423 23.030019,11.514995 45 0 1 8.1423,24.427 z m -16.2137,16.2138 a 23.030019,11.514995 45 0 1 -24.427,-8.1424 23.030019,11.514995 45 0 1 -8.1424,-24.4269 23.030019,11.514995 45 0 1 24.4271,8.1422 23.030019,11.514995 45 0 1 8.1423,24.4271 z"
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:37.79527664;stroke-opacity:1"
id="path1681-6-5-3-7-4-9-2-0-2-7-6"
inkscape:connector-curvature="0" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

View File

@ -133,18 +133,6 @@ function load_spaces(id, is_home, on_success, on_error) {
}, on_error); }, on_error);
} }
function load_importables(user, on_success, on_error) {
load_resource("get", "/users/"+user._id+"/importables", null, on_success, on_error);
}
function import_zip(user, filename, on_success, on_error) {
load_resource("get", "/users/"+user._id+"/import?zip="+filename, null, on_success, on_error);
}
function load_writable_folders(on_success, on_error) {
load_resource("get", "/spaces?writablefolders=true", null, on_success, on_error);
}
function load_history(s, on_success, on_error) { function load_history(s, on_success, on_error) {
load_resource("get", "/spaces/"+ s._id +"/digest", null, on_success, on_error); load_resource("get", "/spaces/"+ s._id +"/digest", null, on_success, on_error);
} }
@ -190,12 +178,10 @@ function delete_space(s, on_success, on_error) {
load_resource("delete", "/spaces/"+s._id, null, on_success, on_error); load_resource("delete", "/spaces/"+s._id, null, on_success, on_error);
} }
function delete_artifact(a, on_success, on_error) { function delete_artifact(a, on_success, on_error) {
load_resource("delete", "/spaces/"+a.space_id+"/artifacts/"+a._id); load_resource("delete", "/spaces/"+a.space_id+"/artifacts/"+a._id);
} }
function duplicate_space(s, to_space_id, on_success, on_error) { function duplicate_space(s, to_space_id, on_success, on_error) {
var path = "/spaces/"+s._id+"/duplicate"; var path = "/spaces/"+s._id+"/duplicate";
if(to_space_id) { if(to_space_id) {
@ -274,8 +260,8 @@ function delete_user(u, password, on_success, on_error) {
load_resource("delete", "/users/"+u._id +"?password="+password,null,on_success,on_error); load_resource("delete", "/users/"+u._id +"?password="+password,null,on_success,on_error);
} }
function create_user(name, email, password, password_confirmation, on_success, on_error) { function create_user(name, email, password, password_confirmation, invite_code, on_success, on_error) {
load_resource("post", "/users", {email:email, nickname:name, password:password, password_confirmation: password_confirmation}, on_success, on_error); load_resource("post", "/users", {email:email, nickname:name, password:password, password_confirmation: password_confirmation, invite_code: invite_code}, on_success, on_error);
} }
function create_session(email, password, on_success, on_error) { function create_session(email, password, on_success, on_error) {

View File

@ -9,19 +9,12 @@ SpacedeckAccount = {
account_tab: 'invoices', account_tab: 'invoices',
password_change_error: null, password_change_error: null,
feedback_text: "", feedback_text: "",
importables: [], // spacedeck.com zip import files
}, },
methods: { methods: {
show_account: function() { show_account: function() {
this.activate_dropdown('account'); this.activate_dropdown('account');
}, },
start_zip_import: function(f) {
if (confirm("Your archive will be imported in the background. This can take a few minutes. You can continue using Spacedeck in the meantime.")) {
import_zip(this.user, f);
}
},
account_save_user_digest: function(val) { account_save_user_digest: function(val) {
this.user.prefs_email_digest = val; this.user.prefs_email_digest = val;
this.save_user(function() { this.save_user(function() {

View File

@ -63,8 +63,8 @@ var SpacedeckSections = {
active_style: { active_style: {
border_radius: 0, border_radius: 0,
stroke: 0, stroke: 0,
font_family: "Avenir W01", font_family: "Inter",
font_size: 18, font_size: 36,
line_height: 1.5, line_height: 1.5,
letter_spacing: 0, letter_spacing: 0,
@ -110,18 +110,30 @@ var SpacedeckSections = {
color_picker_opacity: 255, color_picker_opacity: 255,
swatches: [ swatches: [
{id:0, hex:"#4a2f7e"}, {id:1, hex:"#ff00ff"},
{id:1, hex:"#9b59b6"}, {id:2, hex:"#ffff00"},
{id:2, hex:"#3498db"}, {id:3, hex:"#00ffff"},
{id:3, hex:"#2ecc71"}, {id:5, hex:"#ff0000"},
{id:4, hex:"#f1c40f"}, {id:6, hex:"#00ff00"},
{id:5, hex:"#e67e22"}, {id:7, hex:"#0000ff"},
{id:6, hex:"#d55c4b"}, {id:8, hex:"#000000"},
{id:7, hex:"#6f4021"}, {id:9, hex:"#222222"},
{id:8, hex:"#ffffff"}, {id:10, hex:"#444444"},
{id:9, hex:"#95a5a6"}, {id:11, hex:"#888888"},
{id:10, hex:"#252525"}, {id:12, hex:"#bbbbbb"},
{id:11, hex:"rgba(0,0,0,0)"}, {id:13, hex:"#dddddd"},
{id:14, hex:"#ffffff"},
{id:20, hex:"#4a2f7e"},
{id:21, hex:"#9b59b6"},
{id:22, hex:"#3498db"},
{id:23, hex:"#2ecc71"},
{id:24, hex:"#f1c40f"},
{id:25, hex:"#e67e22"},
{id:26, hex:"#d55c4b"},
{id:27, hex:"#6f4021"},
{id:29, hex:"#95a5a6"},
{id:30, hex:"rgba(0,0,0,0)"},
], ],
swatches_text: [ swatches_text: [
@ -136,18 +148,8 @@ var SpacedeckSections = {
], ],
fonts: [ fonts: [
"Arial", "Inter",
"Courier", "Courier"
"Georgia",
"Verdana",
"Comic Sans MS",
"Montserrat",
"Lato",
"Roboto",
"Crimson Text",
"EB Garamond",
"Vollkorn",
"Avenir W01"
], ],
detected_text_formats: {}, detected_text_formats: {},
@ -180,7 +182,7 @@ var SpacedeckSections = {
toolbar_props_in: false, toolbar_props_in: false,
toolbar_artifacts_x: "-1000px", toolbar_artifacts_x: "-1000px",
toolbar_artifacts_y: "-1000px", toolbar_artifacts_y: "-1000px",
toolbar_artifacts_in: false toolbar_artifacts_in: true
}, },
methods: { methods: {
@ -1057,7 +1059,7 @@ var SpacedeckSections = {
this.toolbar_props_x = pp.x+"px"; this.toolbar_props_x = pp.x+"px";
this.toolbar_props_y = pp.y+"px"; this.toolbar_props_y = pp.y+"px";
this.hide_toolbar_artifacts(); //this.hide_toolbar_artifacts();
} }
this.selection_metrics.x1 = sr.x1; this.selection_metrics.x1 = sr.x1;
@ -1125,8 +1127,11 @@ var SpacedeckSections = {
var er = this.enclosing_rect(this.active_space_artifacts); var er = this.enclosing_rect(this.active_space_artifacts);
if (!er) return; if (!er) return;
this.active_space.width =Math.max(er.x2+100, window.innerWidth); // resize space
this.active_space.height=Math.max(er.y2+100, window.innerHeight); this.active_space.width =Math.max((parseInt(er.x2/window.innerWidth)+2)*window.innerWidth, window.innerWidth);
this.active_space.height=Math.max((parseInt(er.y2/window.innerHeight)+2)*window.innerHeight, window.innerHeight);
console.log("bounds: ",this.active_space.width,this.active_space.height);
if (this._last_bounds_width != this.active_space.width || if (this._last_bounds_width != this.active_space.width ||
this._last_bounds_height != this.active_space.height) { this._last_bounds_height != this.active_space.height) {
@ -1544,7 +1549,7 @@ var SpacedeckSections = {
add_artifact: function (space, item_type, url, evt) { add_artifact: function (space, item_type, url, evt) {
this.active_tool = "pointer"; this.active_tool = "pointer";
this.mouse_state = "idle"; this.mouse_state = "idle";
this.hide_toolbar_artifacts(); //this.hide_toolbar_artifacts();
if (!url && (item_type == 'image' || item_type == 'video' || item_type == 'embed')) { if (!url && (item_type == 'image' || item_type == 'video' || item_type == 'embed')) {
url = prompt("URL?"); url = prompt("URL?");
@ -1724,7 +1729,7 @@ var SpacedeckSections = {
var a = { var a = {
space_id: this.active_space._id, space_id: this.active_space._id,
mime: "x-spacedeck/shape", mime: "x-spacedeck/shape",
description: "Text", description: "",
x: point.x, x: point.x,
y: point.y, y: point.y,
z: point.z, z: point.z,
@ -1736,7 +1741,7 @@ var SpacedeckSections = {
fill_color: "#000000", fill_color: "#000000",
shape: shape_type, shape: shape_type,
valign: "middle", valign: "middle",
align: "center" align: "center",
}; };
if (this.guest_nickname) { if (this.guest_nickname) {
@ -1789,8 +1794,6 @@ var SpacedeckSections = {
return false; return false;
} }
this.hide_toolbar_artifacts();
// 1. create placeholder artifact // 1. create placeholder artifact
var w=300,h=150; var w=300,h=150;
var fill="transparent"; var fill="transparent";
@ -2293,11 +2296,6 @@ var SpacedeckSections = {
if (!pastedText) return; if (!pastedText) return;
if (!pastedText.match(/<[a-zA-Z]+>/g)) {
// crappy heuristic if this is actually HTML
pastedText = pastedText.replace(/\n/g,"<br>");
}
this.insert_embedded_artifact(pastedText); this.insert_embedded_artifact(pastedText);
}, },
@ -2344,32 +2342,6 @@ var SpacedeckSections = {
this.create_artifact_via_embed_url(text); this.create_artifact_via_embed_url(text);
return; return;
} }
var new_item = {
mime: "text/html",
description: text.replace("\n", "<br />"),
title: "",
space_id: space._id
};
var w = 400;
var h = 300;
var point = this.find_place_for_item(w,h);
new_item.x = point.x;
new_item.y = point.y;
new_item.w = w;
new_item.h = h;
new_item.z = point.z;
if (this.guest_nickname) {
new_item.editor_name = this.guest_nickname;
}
save_artifact(new_item, function(saved_item) {
this.update_board_artifact_viewmodel(saved_item);
this.active_space_artifacts.push(saved_item);
}.bind(this));
}, },
create_artifact_via_embed_url: function(url) { create_artifact_via_embed_url: function(url) {
@ -2528,20 +2500,11 @@ var SpacedeckSections = {
this.opened_dialog = "none"; this.opened_dialog = "none";
if (files && files.length) { if (files && files.length) {
console.log("file: ",files[0]);
for (var i=0; i<files.length; i++) { for (var i=0; i<files.length; i++) {
var file = files[i]; var file = files[i];
if (file.type === "application/pdf") {
var point = {x: 100, y: 100}; //fixme, center upload?
this.dropped_point = point;
this.pending_pdf_file = file;
this.activate_modal('pdfoptions');
} else {
this.create_artifact_via_upload(null, file, true); this.create_artifact_via_upload(null, file, true);
} }
} }
}
}, },
handle_image_file_upload: function(evt) { handle_image_file_upload: function(evt) {
@ -2578,12 +2541,11 @@ var SpacedeckSections = {
}, },
hide_toolbar_props: function() { hide_toolbar_props: function() {
this.toolbar_props_in = false; // FIXME test
//this.toolbar_props_in = false;
}, },
show_toolbar_artifacts: function(x,y) { show_toolbar_artifacts: function(x,y) {
this.toolbar_artifacts_x = (x-175)+"px";
this.toolbar_artifacts_y = y+"px";
this.toolbar_artifacts_in = true; this.toolbar_artifacts_in = true;
}, },
@ -2593,29 +2555,19 @@ var SpacedeckSections = {
start_adding_artifact: function(evt) { start_adding_artifact: function(evt) {
evt = fixup_touches(evt); evt = fixup_touches(evt);
// toggle
if (this.toolbar_artifacts_in) {
this.hide_toolbar_artifacts();
return;
}
this.show_toolbar_artifacts(evt.pageX,evt.pageY);
}, },
start_drawing_scribble: function(evt) { start_drawing_scribble: function(evt) {
this.hide_toolbar_artifacts();
this.active_tool = "scribble"; this.active_tool = "scribble";
this.opened_dialog = "none"; this.opened_dialog = "none";
}, },
start_drawing_arrow: function(evt) { start_drawing_arrow: function(evt) {
this.hide_toolbar_artifacts();
this.active_tool = "arrow"; this.active_tool = "arrow";
this.opened_dialog = "none"; this.opened_dialog = "none";
}, },
start_drawing_line: function(evt) { start_drawing_line: function(evt) {
this.hide_toolbar_artifacts();
this.active_tool = "line"; this.active_tool = "line";
this.opened_dialog = "none"; this.opened_dialog = "none";
}, },
@ -2894,32 +2846,6 @@ var SpacedeckSections = {
}.bind(this),500); }.bind(this),500);
}, },
approve_pdf_upload: function(evt,approve_pdf_upload, mode){
this.close_modal();
if(mode == "classic"){
this.create_artifact_via_upload(evt, this.pending_pdf_file, false);
}
if(mode == "grid") {
this.global_spinner = true;
save_pdf_file(this.active_space, this.dropped_point, this.pending_pdf_file, approve_pdf_upload, function(createdArtifacts){
this.global_spinner = false;
_.each(createdArtifacts, function(new_artifact){
this.update_board_artifact_viewmodel(new_artifact);
this.active_space_artifacts.push(new_artifact)
}.bind(this));
}.bind(this), function(xhr) {
this.global_spinner = false;
alert("Error PDF ("+xhr.status+")");
}.bind(this));
}
},
handle_data_drop: function(evt) { handle_data_drop: function(evt) {
if (this.active_space_role=="viewer") { if (this.active_space_role=="viewer") {
return false; return false;
@ -2932,17 +2858,8 @@ var SpacedeckSections = {
if (files && files.length) { if (files && files.length) {
for (var i=0; i<files.length; i++) { for (var i=0; i<files.length; i++) {
var file = files[i]; var file = files[i];
if (file.type === "application/pdf") {
var point = this.cursor_point_to_space(evt);
this.dropped_point = point;
this.pending_pdf_file = file;
this.activate_modal('pdfoptions');
} else {
this.create_artifact_via_upload(evt, file, (files.length>1)); this.create_artifact_via_upload(evt, file, (files.length>1));
} }
}
} else { } else {
var json = evt.dataTransfer.getData('application/json'); var json = evt.dataTransfer.getData('application/json');

View File

@ -18,8 +18,6 @@ var SpacedeckSpaces = {
active_space_path: [], active_space_path: [],
access_settings_space: null, access_settings_space: null,
access_settings_memberships: [], access_settings_memberships: [],
duplicate_folders: [],
duplicate_folder_id: "",
pending_pdf_files: [], pending_pdf_files: [],
meta_visible: false, meta_visible: false,
@ -110,27 +108,6 @@ var SpacedeckSpaces = {
space_auth = get_query_param("spaceAuth"); space_auth = get_query_param("spaceAuth");
var userReady = function() { var userReady = function() {
if (get_query_param("embedded")) {
this.embedded = true;
this.guest_signup_enabled = true;
if (get_query_param("publish_cta")) {
this.publish_cta = get_query_param("publish_cta");
}
if (get_query_param("nosocial")) {
this.social_bar = false;
}
}
if (get_query_param("confirm") && this.logged_in) {
var token = get_query_param("confirm");
confirm_user(this.user, token, function() {
this.redirect_to("/spaces/"+space_id+"?show_access=1");
}.bind(this), function() {
alert("An error occured confirming your email with the given token.");
});
return;
}
this.close_dropdown(); this.close_dropdown();
this.active_space_loaded = false; this.active_space_loaded = false;
@ -158,9 +135,7 @@ var SpacedeckSpaces = {
load_space(space_id, function(space, role) { load_space(space_id, function(space, role) {
document.title = space.name; document.title = space.name;
this.active_space_role = role || "viewer"; //via req header from backend this.active_space_role = role || "viewer"; // via req header from backend
this.space_embed_html = "<iframe width=\"1024\" height=\"768\" seamless src=\""+ENV.webEndpoint+"/spaces/"+space._id+"?embedded=1\"></iframe>";
if (!is_home) { if (!is_home) {
load_members(space, function(members) { load_members(space, function(members) {
@ -273,9 +248,9 @@ var SpacedeckSpaces = {
this.discover_zones(); this.discover_zones();
//window.setTimeout(function() { window.setTimeout(function() {
// this.zoom_to_fit(); this.zoom_to_fit();
//}.bind(this),10); }.bind(this),10);
if (on_success) { if (on_success) {
on_success(); on_success();
@ -301,15 +276,6 @@ var SpacedeckSpaces = {
// FIXME // FIXME
this.active_join_link = ""; this.active_join_link = "";
this.join_link_role = "viewer"; this.join_link_role = "viewer";
// FIXME
if (this.active_space_role == "admin") {
this.space_info_section="access";
} else if (this.active_space_role == "editor") {
//this.space_info_section="versions";
} else {
this.space_info_section="info";
}
} }
}.bind(this), function(xhr) { }.bind(this), function(xhr) {
@ -338,7 +304,7 @@ var SpacedeckSpaces = {
userReady(); userReady();
} }
if (space_auth) { if (!this.user && space_auth) {
if (this.guest_nickname) { if (this.guest_nickname) {
userReady(); userReady();
} else { } else {
@ -673,47 +639,6 @@ var SpacedeckSpaces = {
location.href = "/api/spaces/" + space._id + "/list"; location.href = "/api/spaces/" + space._id + "/list";
}, },
duplicate_space_into_folder: function() {
load_writable_folders( function(folders){
this.duplicate_folders = _.sortBy(folders, function (folder) { return folder.name; });
}.bind(this), function(xhr) {
console.error(xhr);
});
},
duplicate_folder_confirm: function() {
var folderId = this.duplicate_folder_id;
var idx = _.findIndex(this.duplicate_folders, function(s) { return s._id == folderId;});
if (idx<0) idx = 0;
var folder = this.duplicate_folders[idx];
console.log("df f",folder);
if (!folder) return;
duplicate_space(this.active_space, folder._id, function(new_space) {
this.duplicate_folders = [];
this.duplicate_folder = null;
smoke.quiz(__("duplicate_success", this.active_space.name, folder.name), function(e, test){
if (e == __("goto_space", new_space.name)){
this.redirect_to("/spaces/" + new_space._id);
}else if (e == __("goto_folder", folder.name)){
this.redirect_to("/folders/" + folder._id);
}
}.bind(this), {
button_1: __("goto_space", new_space.name),
button_2: __("goto_folder", folder.name),
button_cancel:__("stay_here")
});
}.bind(this), function(xhr){
console.error(xhr);
smoke.prompt("error: " + xhr.statusText);
}.bind(this));
},
toggle_follow_mode: function() { toggle_follow_mode: function() {
this.deselect(); this.deselect();
this.follow_mode = !this.follow_mode; this.follow_mode = !this.follow_mode;
@ -819,9 +744,12 @@ var SpacedeckSpaces = {
this.invite_message = ""; this.invite_message = "";
} }
}.bind(this), function(xhr){ }.bind(this), function(xhr){
try {
text = JSON.stringify(xhr.responseText); var res = JSON.parse(xhr.response);
smoke.alert("Error: "+text); alert("Error: "+res.error);
} catch (e) {
console.error(e, xhr);
}
}.bind(this)); }.bind(this));
}.bind(this)); }.bind(this));
}, },
@ -829,9 +757,13 @@ var SpacedeckSpaces = {
update_member: function(space, m, role) { update_member: function(space, m, role) {
m.role = role; m.role = role;
save_membership(space, m, function() { save_membership(space, m, function() {
console.log("saved")
}.bind(this), function(xhr) { }.bind(this), function(xhr) {
console.error(xhr); try {
var res = JSON.parse(xhr.response);
alert("Error: "+res.error);
} catch (e) {
console.error(e, xhr);
}
}.bind(this)); }.bind(this));
}, },
@ -840,7 +772,12 @@ var SpacedeckSpaces = {
delete_membership(space, m, function() { delete_membership(space, m, function() {
this.access_settings_memberships.splice(this.access_settings_memberships.indexOf(m), 1); this.access_settings_memberships.splice(this.access_settings_memberships.indexOf(m), 1);
}.bind(this), function(xhr) { }.bind(this), function(xhr) {
console.error(xhr); try {
var res = JSON.parse(xhr.response);
alert("Error: "+res.error);
} catch (e) {
console.error(e, xhr);
}
}.bind(this)); }.bind(this));
}, },
@ -876,10 +813,6 @@ var SpacedeckSpaces = {
}.bind(this)); }.bind(this));
}, },
emojified_comment: function(comment) {
return twemoji.parse(comment);
},
set_folder_sorting: function(key,reverse) { set_folder_sorting: function(key,reverse) {
this.folder_sorting = key; this.folder_sorting = key;
this.folder_reverse = reverse?-1:1; this.folder_reverse = reverse?-1:1;

View File

@ -11,6 +11,7 @@ SpacedeckUsers = {
login_email: "", login_email: "",
login_password: "", login_password: "",
signup_password: "", signup_password: "",
signup_invite_code: "",
signup_password_confirmation: "", signup_password_confirmation: "",
account_remove_error: null, account_remove_error: null,
loading_user: false, loading_user: false,
@ -30,12 +31,6 @@ SpacedeckUsers = {
if (on_success) { if (on_success) {
on_success(user); on_success(user);
} }
// see spacedeck_account.js
load_importables(this.user, function(files) {
this.importables = files;
}.bind(this));
}.bind(this), function() { }.bind(this), function() {
// error // error
this.loading_user = false; this.loading_user = false;
@ -122,7 +117,7 @@ SpacedeckUsers = {
signup_guest: function(on_success) { signup_guest: function(on_success) {
}, },
signup_submit: function($event, name, email, password, password_confirmation, on_success) { signup_submit: function($event, name, email, password, password_confirmation, invite_code, on_success) {
this.creating_user = true; this.creating_user = true;
this.signup_error = null; this.signup_error = null;
@ -136,7 +131,7 @@ SpacedeckUsers = {
$event.stopPropagation(); $event.stopPropagation();
} }
create_user(name, email, password, password_confirmation, function(session) { create_user(name, email, password, password_confirmation, invite_code, function(session) {
this.creating_user = false; this.creating_user = false;
this.login_submit(email, password, null, on_success); this.login_submit(email, password, null, on_success);
}.bind(this), function(req) { }.bind(this), function(req) {
@ -152,8 +147,8 @@ SpacedeckUsers = {
}.bind(this)); }.bind(this));
}, },
signup_submit_modal: function($event, name, email, password, password_confirmation) { signup_submit_modal: function($event, name, email, password, password_confirmation, invite_code) {
this.signup_submit($event, name, email, password, password_confirmation, function() { this.signup_submit($event, name, email, password, password_confirmation, invite_code, function() {
alert("Success."); alert("Success.");
location.reload(); location.reload();
}); });
@ -201,27 +196,29 @@ SpacedeckUsers = {
this.password_reset_confirm_error = null; this.password_reset_confirm_error = null;
this.password_reset_send = false; this.password_reset_send = false;
if(password != password_confirmation) { if (password != password_confirmation) {
this.password_reset_confirm_error = "Passwords do not match."; this.password_reset_confirm_error = "Passwords do not match.";
return; return;
} }
if(password.length < 5) { if (password.length < 5) {
this.password_reset_confirm_error = "Password too short (must have at least 5 characters)."; this.password_reset_confirm_error = "Password too short (must have at least 5 characters).";
return; return;
} }
confirm_password_reset(password, this.reset_token, function(parsed,req) { confirm_password_reset(password, this.reset_token, function(parsed,req) {
if(req.status==201){ if (req.status==201) {
alert("New password set successfully.");
this.active_view = "login"; this.active_view = "login";
} else {
alert("An unknown error occured.");
} }
}.bind(this), function(req) { }.bind(this), function(req) {
if (req.status==404) { if (req.status==404) {
var msg = "user not found"; alert("Error: Unknown user.");
} else { } else {
var msg = "error: " + req.statusText; alert("Error: "+req.statusText);
} }
this.password_reset_confirm_error = msg;
}.bind(this)); }.bind(this));
}, },

View File

@ -80,10 +80,16 @@ function setup_whiteboard_directives() {
evt.stopPropagation(); evt.stopPropagation();
} }
var a = $scope.find_artifact_by_id(evt.currentTarget.id.replace("artifact-",""));
if ($scope.active_tool == "zoom") return; if ($scope.active_tool == "zoom") return;
if (evt.which == 2) {
// middle mouse button
this.handle_mouse_down_space(evt);
return;
}
var a = $scope.find_artifact_by_id(evt.currentTarget.id.replace("artifact-",""));
if ($scope.active_tool == "eyedrop") { if ($scope.active_tool == "eyedrop") {
var arts = $scope.selected_artifacts(); var arts = $scope.selected_artifacts();
if (!$scope.is_selected(a) && arts.length > 0) { if (!$scope.is_selected(a) && arts.length > 0) {
@ -196,7 +202,9 @@ function setup_whiteboard_directives() {
}, },
handle_mouse_down_space: function(evt) { handle_mouse_down_space: function(evt) {
if (evt.which != 2) {
if (evt.target != evt.currentTarget && !_.include(["wrapper"],evt.target.className)) return; if (evt.target != evt.currentTarget && !_.include(["wrapper"],evt.target.className)) return;
}
var $scope = this.vm.$root; var $scope = this.vm.$root;
@ -214,7 +222,7 @@ function setup_whiteboard_directives() {
this.deselect(); this.deselect();
this.mouse_state = "transform"; this.mouse_state = "transform";
$scope.mouse_state = this.mouse_state; $scope.mouse_state = this.mouse_state;
this.start_adding_note(evt); this.start_drawing_note(evt);
return; return;
} else if ($scope.active_tool=="arrow") { } else if ($scope.active_tool=="arrow") {
@ -492,6 +500,7 @@ function setup_whiteboard_directives() {
if (!xdists[0] || xdists[0][0]>TOL) { if (!xdists[0] || xdists[0][0]>TOL) {
results.snapx = [0,x]; // distance, coordinate results.snapx = [0,x]; // distance, coordinate
} else { } else {
// FIXME snap rulers are broken
//$scope.snap_ruler_x = xdists[0][1]; //$scope.snap_ruler_x = xdists[0][1];
} }
if (!ydists[0] || ydists[0][0]>TOL) { if (!ydists[0] || ydists[0][0]>TOL) {
@ -516,6 +525,41 @@ function setup_whiteboard_directives() {
return point; return point;
}, },
start_drawing_note: function(evt) {
evt.preventDefault();
evt.stopPropagation();
var $scope = this.vm.$root;
var point = this.cursor_point_to_space(evt);
this.offset_point_in_wrapper(point);
var z = $scope.highest_z()+1;
var a = {
space_id: $scope.active_space._id,
mime: "text/html",
description: "<p>Text</p>",
x: point.x,
y: point.y,
z: z,
w: 64,
h: 64,
align: "center",
valign: "middle",
stroke_color: "#000000",
fill_color: "rgb(241, 196, 15)",
stroke: 0
};
$scope.save_artifact(a, function(saved_a) {
$scope.update_board_artifact_viewmodel(saved_a);
$scope.active_space_artifacts.push(saved_a);
$scope.select(evt,a);
$scope.transform_ox = 0;
$scope.transform_oy = 0;
$scope.begin_transaction();
}.bind(this));
},
start_drawing_scribble: function(evt) { start_drawing_scribble: function(evt) {
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
@ -691,7 +735,7 @@ function setup_whiteboard_directives() {
this.mouse_state = "idle"; this.mouse_state = "idle";
$scope.mouse_state = this.mouse_state; $scope.mouse_state = this.mouse_state;
this.lasso = null; this.lasso = null;
$scope.active_tool = "pointer"; //$scope.active_tool = "pointer"; disabled to keep the same tool (eg. "Scribble") after drawing a single line.
$scope.end_transaction(); $scope.end_transaction();
$scope.show_toolbar_props(); $scope.show_toolbar_props();
@ -851,7 +895,7 @@ function setup_whiteboard_directives() {
var scale_x = lead_x ? (moved_x)/lead_x : 1; var scale_x = lead_x ? (moved_x)/lead_x : 1;
var scale_y = lead_y ? (moved_y)/lead_y : 1; var scale_y = lead_y ? (moved_y)/lead_y : 1;
if (!$scope.transform_lock) scale_y = scale_x; if ($scope.transform_lock) scale_y = scale_x;
$scope.update_selected_artifacts(function(a) { $scope.update_selected_artifacts(function(a) {
var old_a = $scope.find_artifact_before_transaction(a); var old_a = $scope.find_artifact_before_transaction(a);

File diff suppressed because it is too large Load Diff

View File

@ -138,7 +138,6 @@ router.get('/', function(req, res, next) {
"$exists": 1 "$exists": 1
} }
}).populate("space").exec(function(err, memberships) { }).populate("space").exec(function(err, memberships) {
async.map(memberships, function(membership, memcb) { async.map(memberships, function(membership, memcb) {
Space.getRecursiveSubspacesForSpace(membership.space, function(err, spaces) { Space.getRecursiveSubspacesForSpace(membership.space, function(err, spaces) {
cb(null, spaces.map(function(s) { cb(null, spaces.map(function(s) {

View File

@ -51,8 +51,7 @@ router.get('/png', function(req, res, next) {
if (!req.space.thumbnail_updated_at || req.space.thumbnail_updated_at < req.space.updated_at || !req.space.thumbnail_url) { if (!req.space.thumbnail_updated_at || req.space.thumbnail_updated_at < req.space.updated_at || !req.space.thumbnail_url) {
db.Space.update({ thumbnail_updated_at: triggered }, {where : {"_id": req.space._id }}); db.Space.update({ thumbnail_updated_at: triggered }, {where : {"_id": req.space._id }});
phantom.takeScreenshot(req.space, "png", phantom.takeScreenshot(req.space, "png", function(local_path) {
function(local_path) {
var localResizedFilePath = local_path + ".thumb.jpg"; var localResizedFilePath = local_path + ".thumb.jpg";
gm(local_path).resize(640, 480).quality(70.0).autoOrient().write(localResizedFilePath, function(err) { gm(local_path).resize(640, 480).quality(70.0).autoOrient().write(localResizedFilePath, function(err) {
@ -79,14 +78,14 @@ router.get('/png', function(req, res, next) {
var oldPath = url.parse(oldUrl).pathname; var oldPath = url.parse(oldUrl).pathname;
uploader.removeFile(oldPath, function(err, res) {}); uploader.removeFile(oldPath, function(err, res) {});
} }
fs.unlink(local_path); fs.unlinkSync(local_path);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
}); });
try { try {
fs.unlink(localResizedFilePath); fs.unlinkSync(localResizedFilePath);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
@ -95,7 +94,7 @@ router.get('/png', function(req, res, next) {
}, },
function() { function() {
// on_error // on_error
console.error("phantom could not create screenshot for space " + req.space_id); console.error("[space screenshot] could not create screenshot for space " + req.space_id);
res.status(404).send("Not found"); res.status(404).send("Not found");
}); });
} else { } else {

View File

@ -45,10 +45,12 @@ router.post('/', function(req, res, next) {
"email": membership.email_invited "email": membership.email_invited
}}).then(function(user) { }}).then(function(user) {
// existing user? then immediately activate membership
if (user) { if (user) {
membership.user_id = user._id; membership.user_id = user._id;
membership.state = "active"; membership.state = "active";
} else { } else {
// if not, invite via email and invite code
membership.code = crypto.randomBytes(64).toString('hex').substring(0, 12); membership.code = crypto.randomBytes(64).toString('hex').substring(0, 12);
} }
@ -84,13 +86,13 @@ router.post('/', function(req, res, next) {
} else { } else {
res.status(400).json({ res.status(400).json({
"error": "user already in space" "error": "This email is already included in the Space memberships."
}); });
} }
} else { } else {
res.status(403).json({ res.status(403).json({
"error": "not_permitted" "error": "Only administrators can do that."
}); });
} }
}); });
@ -102,12 +104,19 @@ router.put('/:membership_id', function(req, res, next) {
_id: req.params.membership_id _id: req.params.membership_id
}}).then(function(mem) { }}).then(function(mem) {
if (mem) { if (mem) {
// is the user trying to change their own role?
if (mem.user_id == req.user._id) {
res.status(400).json({
"error": "Cannot change your own role."
});
} else {
var attrs = req.body; var attrs = req.body;
mem.role = attrs.role; mem.role = attrs.role;
mem.save(function() { mem.save(function() {
res.status(201).json(mem); res.status(201).json(mem);
}); });
} }
}
}); });
} else { } else {
res.sendStatus(403); res.sendStatus(403);
@ -118,13 +127,25 @@ router.put('/:membership_id', function(req, res, next) {
}); });
router.delete('/:membership_id', function(req, res, next) { router.delete('/:membership_id', function(req, res, next) {
if (req.user) { if (req.user && req.spaceRole == 'admin') {
db.Membership.count({ where: {
space_id: req.space._id,
role: "admin"
}}).then(function(adminCount) {
db.Membership.findOne({ where: { db.Membership.findOne({ where: {
_id: req.params.membership_id _id: req.params.membership_id
}}).then(function(mem) { }}).then(function(mem) {
// deleting an admin? need at least 1
if (mem.role != "admin" || adminCount > 1) {
mem.destroy().then(function() { mem.destroy().then(function() {
res.sendStatus(204); res.sendStatus(204);
}); });
} else {
res.status(400).json({
"error": "Space needs at least one administrator."
});
}
})
}); });
} else { } else {
res.sendStatus(403); res.sendStatus(403);

View File

@ -48,73 +48,11 @@ router.get('/', function(req, res, next) {
error: "auth required" error: "auth required"
}); });
} else { } else {
if (req.query.writablefolders) { if (req.query.search) {
db.Membership.find({where: {
user_id: req.user._id
}}, (memberships) => {
var validMemberships = memberships.filter((m) => {
if (!m.space_id || (m.space_id == "undefined"))
return false;
return true;
});
var editorMemberships = validMemberships.filter((m) => {
return (m.role == "editor") || (m.role == "admin")
});
var spaceIds = editorMemberships.map(function(m) {
return m.space_id;
});
// TODO port
var q = {
"space_type": "folder",
"$or": [{
"creator": req.user._id
}, {
"_id": {
"$in": spaceIds
},
"creator": {
"$ne": req.user._id
}
}]
};
db.Space
.findAll({where: q})
.then(function(spaces) {
var updatedSpaces = spaces.map(function(s) {
var spaceObj = s; //.toObject();
return spaceObj;
});
async.map(spaces, (space, cb) => {
Space.getRecursiveSubspacesForSpace(space, (err, spaces) => {
var allSpaces = spaces;
cb(err, allSpaces);
})
}, (err, spaces) => {
var allSpaces = _.flatten(spaces);
var onlyFolders = _.filter(allSpaces, (s) => {
return s.space_type == "folder";
})
var uniqueFolders = _.unique(onlyFolders, (s) => {
return s._id;
})
res.status(200).json(uniqueFolders);
});
});
});
} else if (req.query.search) {
db.Membership.findAll({where:{ db.Membership.findAll({where:{
user_id: req.user._id user_id: req.user._id
}}).then(memberships => { }}).then(memberships => {
// search for spaces
var validMemberships = memberships.filter(function(m) { var validMemberships = memberships.filter(function(m) {
if (!m.space_id || (m.space_id == "undefined")) if (!m.space_id || (m.space_id == "undefined"))
@ -143,6 +81,7 @@ router.get('/', function(req, res, next) {
}); });
} else if (req.query.parent_space_id && req.query.parent_space_id != req.user.home_folder_id) { } else if (req.query.parent_space_id && req.query.parent_space_id != req.user.home_folder_id) {
// list spaces in a folder
db.Space db.Space
.findOne({where: { .findOne({where: {
@ -176,6 +115,8 @@ router.get('/', function(req, res, next) {
}); });
} else { } else {
// list home folder and spaces/folders that the user is a member of
db.Membership.findAll({ where: { db.Membership.findAll({ where: {
user_id: req.user._id user_id: req.user._id
}}).then(memberships => { }}).then(memberships => {
@ -184,6 +125,7 @@ router.get('/', function(req, res, next) {
var validMemberships = memberships.filter(function(m) { var validMemberships = memberships.filter(function(m) {
if (!m.space_id || (m.space_id == "undefined")) if (!m.space_id || (m.space_id == "undefined"))
return false; return false;
return true;
}); });
var spaceIds = validMemberships.map(function(m) { var spaceIds = validMemberships.map(function(m) {
@ -228,14 +170,18 @@ router.post('/', function(req, res, next) {
attrs.creator_id = req.user._id; attrs.creator_id = req.user._id;
attrs.edit_hash = crypto.randomBytes(64).toString('hex').substring(0, 7); attrs.edit_hash = crypto.randomBytes(64).toString('hex').substring(0, 7);
attrs.edit_slug = slug(attrs.name); attrs.edit_slug = slug(attrs.name);
attrs.access_mode = "private";
db.Space.create(attrs).then(createdSpace => { db.Space.create(attrs).then(createdSpace => {
//if (err) res.sendStatus(400); res.status(201).json(createdSpace);
// create initial admin membership
var membership = { var membership = {
_id: uuidv4(), _id: uuidv4(),
user_id: req.user._id, user_id: req.user._id,
space_id: attrs._id, space_id: attrs._id,
role: "admin" role: "admin",
state: "active"
}; };
db.Membership.create(membership).then(() => { db.Membership.create(membership).then(() => {
@ -314,8 +260,17 @@ router.put('/:id', function(req, res) {
newAttr.edit_slug = slug(newAttr['name']); newAttr.edit_slug = slug(newAttr['name']);
delete newAttr['_id']; delete newAttr['_id'];
delete newAttr['editor_name'];
delete newAttr['creator']; delete newAttr['creator'];
delete newAttr['creator_id'];
delete newAttr['space_type'];
if (req['spaceRole'] != "admin") {
delete newAttr['access_mode']
delete newAttr['password']
delete newAttr['edit_hash']
delete newAttr['edit_slug']
delete newAttr['editors_locking']
}
db.Space.update(newAttr, {where: { db.Space.update(newAttr, {where: {
"_id": space._id "_id": space._id
@ -362,43 +317,6 @@ router.post('/:id/background', function(req, res, next) {
}); });
}); });
var handleDuplicateSpaceRequest = function(req, res, parentSpace) {
Space.duplicateSpace(req.space, req.user, 0, (err, newSpace) => {
if (err) {
console.error(err);
res.status(400).json(err);
} else {
res.status(201).json(newSpace);
}
}, parentSpace);
}
router.post('/:id/duplicate', (req, res, next) => {
if (req.query.parent_space_id) {
Space.findOne({
_id: req.query.parent_space_id
}).populate('creator', userMapping).exec((err, parentSpace) => {
if (!parentSpace) {
res.status(404).json({
"error": "parent space not found for duplicate"
});
} else {
db.getUserRoleInSpace(parentSpace, req.user, (role) => {
if (role == "admin" ||  role == "editor") {
handleDuplicateSpaceRequest(req, res, parentSpace);
} else {
res.status(403).json({
"error": "not authed for parent_space_id"
});
}
});
}
});
} else {
handleDuplicateSpaceRequest(req, res);
}
});
router.delete('/:id', function(req, res, next) { router.delete('/:id', function(req, res, next) {
if (req.user) { if (req.user) {
const space = req.space; const space = req.space;
@ -418,136 +336,4 @@ router.delete('/:id', function(req, res, next) {
} }
}); });
router.post('/:id/artifacts-pdf', function(req, res, next) {
if (req.spaceRole == "editor" || req.spaceRole == "admin") {
var withZones = (req.query.zones) ? req.query.zones == "true" : false;
var fileName = (req.query.filename || "upload.bin").replace(/[^a-zA-Z0-9\.]/g, '');
var localFilePath = os.tmpdir() + "/" + fileName;
var writeStream = fs.createWriteStream(localFilePath);
var stream = req.pipe(writeStream);
req.on('end', function() {
var rawName = fileName.slice(0, fileName.length - 4);
var outputFolder = os.tmpdir() + "/" + rawName;
fs.mkdir(outputFolder, function(err) {
var images = outputFolder + "/" + rawName + "-page-%03d.jpeg";
// FIXME not portable
exec.execFile("gs", ["-sDEVICE=jpeg", "-dDownScaleFactor=4", "-dDOINTERPOLATE", "-dNOPAUSE", "-dJPEGQ=80", "-dBATCH", "-sOutputFile=" + images, "-r250", "-f", localFilePath], {}, function(error, stdout, stderr) {
if (error === null) {
glob(outputFolder + "/*.jpeg", function(er, files) {
var count = files.length;
var delta = 10;
var limitPerRow = Math.ceil(Math.sqrt(count));
var startX = parseInt(req.query.x, delta);
var startY = parseInt(req.query.y, delta);
async.mapLimit(files, 20, function(localfilePath, cb) {
var fileName = path.basename(localfilePath);
var baseName = path.basename(localfilePath, ".jpeg");
var number = parseInt(baseName.slice(baseName.length - 3, baseName.length), 10);
gm(localFilePath).size((err, size) => {
var w = 350;
var h = w;
var x = startX + (((number - 1) % limitPerRow) * w);
var y = startY + ((parseInt(((number - 1) / limitPerRow), 10) + 1) * w);
var userId;
if (req.user) userId = req.user._id;
var a = db.Artifact.create({
_id: uuidv4(),
mime: "image/jpg",
space_id: req.space._id,
user_id: userId,
editor_name: req.guest_name,
w: w,
h: h,
x: x,
y: y,
z: (number + (count + 100))
}).then(a => {
payloadConverter.convert(a, fileName, localfilePath, (error, artifact) => {
if (error) res.status(400).json(error);
else {
if (withZones) {
var zone = {
_id: uuidv4(),
mime: "x-spacedeck/zone",
description: "Zone " + (number),
space_id: req.space._id,
user_id: userId,
editor_name: req.guest_name,
w: artifact.w + 20,
h: artifact.h + 40,
x: x - 10,
y: y - 30,
z: number,
order: number,
valign: "middle",
align: "center"
};
db.Artifact.create(zone).then((z) => {
redis.sendMessage("create", "Artifact", z.toJSON(), req.channelId);
cb(null, [artifact, zone]);
});
} else {
cb(null, [artifact]);
}
}
});
});
});
}, function(err, artifacts) {
// FIXME not portable
exec.execFile("rm", ["-r", outputFolder], function(err) {
res.status(201).json(_.flatten(artifacts));
async.eachLimit(artifacts, 10, (artifact_or_artifacts, cb) => {
if (artifact_or_artifacts instanceof Array) {
_.each(artifact_or_artifacts, (a) => {
redis.sendMessage("create", "Artifact", JSON.stringify(a), req.channelId);
});
} else  {
redis.sendMessage("create", "Artifact", JSON.stringify(artifact_or_artifacts), req.channelId);
}
cb(null);
});
});
});
});
} else {
console.error("error:", error);
// FIXME not portable
exec.execFile("rm", ["-r", outputFolder], function(err) {
fs.unlink(localFilePath);
res.status(400).json({});
});
}
});
});
});
} else {
res.status(401).json({
"error": "no access"
});
}
});
module.exports = router; module.exports = router;

View File

@ -51,12 +51,18 @@ router.post('/', function(req, res) {
var nickname = req.body["nickname"]; var nickname = req.body["nickname"];
var password = req.body["password"]; var password = req.body["password"];
var password_confirmation = req.body["password_confirmation"]; var password_confirmation = req.body["password_confirmation"];
var invite_code = req.body["invite_code"];
if (password_confirmation != password) { if (password_confirmation != password) {
res.status(400).json({"error":"password_confirmation"}); res.status(400).json({"error":"password_confirmation"});
return; return;
} }
if (config.invite_code && invite_code != config.invite_code) {
res.status(400).json({"error":"Invalid Invite Code."});
return;
}
if (!validator.isEmail(email)) { if (!validator.isEmail(email)) {
res.status(400).json({"error":"email_invalid"}); res.status(400).json({"error":"email_invalid"});
return; return;
@ -83,28 +89,31 @@ router.post('/', function(req, res) {
res.sendStatus(400); res.sendStatus(400);
}) })
.then(u => { .then(u => {
var homeSpace = { var homeFolder = {
_id: uuidv4(), _id: uuidv4(),
name: req.i18n.__("home"), name: req.i18n.__("home"),
space_type: "folder", space_type: "folder",
creator_id: u._id creator_id: u._id
}; };
db.Space.create(homeSpace) db.Space.create(homeFolder)
.error(err => { .error(err => {
res.sendStatus(400); res.sendStatus(400);
}) })
.then(homeSpace => { .then(homeFolder => {
u.home_folder_id = homeSpace._id; u.home_folder_id = homeFolder._id;
u.save() u.save()
.then(() => { .then(() => {
res.status(201).json({}); // home folder created,
// auto accept pending invites
mailer.sendMail(u.email, req.i18n.__("confirm_subject"), req.i18n.__("confirm_body"), { db.Membership.update({
action: { "state": "active"
link: config.endpoint + "/confirm/" + u.confirmation_token, }, {
name: req.i18n.__("confirm_action") where: {
"email_invited": u.email,
"state": "pending"
} }
}); });
res.status(201).json({});
}) })
.error(err => { .error(err => {
res.status(400).json(err); res.status(400).json(err);
@ -119,7 +128,6 @@ router.post('/', function(req, res) {
db.User.findAll({where: {email: email}}) db.User.findAll({where: {email: email}})
.then(users => { .then(users => {
if (users.length == 0) { if (users.length == 0) {
//var domain = email.slice(email.lastIndexOf('@')+1);
createUser(); createUser();
} else { } else {
res.status(400).json({"error":"user_email_already_used"}); res.status(400).json({"error":"user_email_already_used"});
@ -168,36 +176,35 @@ router.post('/:id/password', function(req, res, next) {
}); });
}); });
} else { } else {
res.status(403).json({"error": "old password wrong"}); res.status(403).json({"error": "Please enter the correct current password."});
} }
} else { } else {
res.status(403).json({"error": "wrong user"}); res.status(403).json({"error": "Access denied."});
} }
} else { } else {
res.status(400).json({"error": "password_to_short"}); res.status(400).json({"error": "Please choose a new password with at least 6 characters."});
} }
}); });
router.delete('/:id', (req, res, next) => { router.delete('/:id', (req, res, next) => {
const user = req.user; const user = req.user;
if(user._id == req.params.id) { if (user._id == req.params.id) {
if (user.account_type == 'email') {
if (bcrypt.compareSync(req.query.password, user.password_hash)) { if (bcrypt.compareSync(req.query.password, user.password_hash)) {
user.remove((err) => {
// TODO: this doesn't currently work.
// all objects (indirectly) belonging to the user have
// to be walked and deleted first.
user.destroy().then(err => {
if(err)res.status(400).json(err); if(err)res.status(400).json(err);
else res.sendStatus(204); else res.sendStatus(204);
}); });
} else { } else {
res.bad_request("password_incorrect"); res.bad_request("Please enter the correct current password.");
} }
} else { } else {
user.remove((err) => { res.status(403).json({error: "Access denied."});
if (err) res.status(400).json(err);
else res.sendStatus(204);
});
} }
}
else res.status(403).json({error: ""});
}); });
router.put('/:user_id/confirm', (req, res) => { router.put('/:user_id/confirm', (req, res) => {
@ -253,13 +260,6 @@ router.post('/:user_id/avatar', (req, res, next) => {
}); });
}); });
router.post('/feedback', function(req, res, next) {
var text = req.body.text;
// FIXME
mailer.sendMail("support@example.org", "Support Request by " + req.user.email, text, {reply_to: req.user.email});
res.sendStatus(201);
});
router.post('/password_reset_requests', (req, res, next) => { router.post('/password_reset_requests', (req, res, next) => {
const email = req.query.email; const email = req.query.email;
db.User.findOne({where: {"email": email}}).then((user) => { db.User.findOne({where: {"email": email}}).then((user) => {
@ -283,21 +283,16 @@ router.post('/password_reset_requests', (req, res, next) => {
router.post('/password_reset_requests/:confirm_token/confirm', function(req, res, next) { router.post('/password_reset_requests/:confirm_token/confirm', function(req, res, next) {
var password = req.body.password; var password = req.body.password;
User db.User
.findOne({where: {"password_reset_token": req.params.confirm_token}}) .findOne({where: {"password_reset_token": req.params.confirm_token}})
.then((user) => { .then((user) => {
if (user) { if (user) {
bcrypt.genSalt(10, (err, salt) => { bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(password, salt, function(err, hash) { bcrypt.hash(password, salt, function(err, hash) {
user.password_hash = hash; user.password_hash = hash;
user.password_token = null; user.password_token = null;
user.save(function(err, updatedUser){ user.save().then(function(updatedUser) {
if (err) {
res.sendStatus(400);
} else {
res.sendStatus(201); res.sendStatus(201);
}
}); });
}); });
}); });
@ -315,19 +310,4 @@ router.post('/:user_id/confirm', function(req, res, next) {
res.sendStatus(201); res.sendStatus(201);
}); });
router.get('/:user_id/importables', function(req, res, next) {
glob('*.zip', function(err, files) {
res.status(200).json(files);
});
});
router.get('/:user_id/import', function(req, res, next) {
if (req.query.zip) {
res.send("importing");
importer.importZIP(req.user, req.query.zip);
} else {
res.sendStatus(400);
}
});
module.exports = router; module.exports = router;

View File

@ -54,10 +54,6 @@ router.get('/password-confirm/:token', (req, res) => {
res.render('spacedeck', { title: 'Signup' }); res.render('spacedeck', { title: 'Signup' });
}); });
router.get('/team', (req, res) => {
res.render('spacedeck');
});
router.get('/de/*', (req, res) => { router.get('/de/*', (req, res) => {
res.redirect("/t/de"); res.redirect("/t/de");
}); });
@ -82,10 +78,6 @@ router.get('/en', (req, res) => {
res.redirect("/t/end"); res.redirect("/t/end");
}); });
router.get('/it', (req, res) => {
res.redirect("/t/en");
});
router.get('/account', (req, res) => { router.get('/account', (req, res) => {
res.render('spacedeck'); res.render('spacedeck');
}); });

View File

@ -26,6 +26,9 @@ const serveStatic = require('serve-static');
const isProduction = app.get('env') === 'production'; const isProduction = app.get('env') === 'production';
// workaround for libssl_conf.so error triggered by phantomjs
process.env['OPENSSL_CONF'] = '/dev/null';
console.log("Booting Spacedeck Open… (environment: " + app.get('env') + ")"); console.log("Booting Spacedeck Open… (environment: " + app.get('env') + ")");
app.use(logger(isProduction ? 'combined' : 'dev')); app.use(logger(isProduction ? 'combined' : 'dev'));
@ -72,7 +75,7 @@ app.use(helmet.frameguard())
app.use(helmet.xssFilter()) app.use(helmet.xssFilter())
app.use(helmet.hsts({ app.use(helmet.hsts({
maxAge: 7776000000, maxAge: 7776000000,
includeSubdomains: true includeSubDomains: true
})) }))
app.disable('x-powered-by'); app.disable('x-powered-by');
app.use(helmet.noSniff()) app.use(helmet.noSniff())

View File

@ -26,12 +26,12 @@
} }
} }
/*&.artifact-text.text-blank [contentEditable=true]:not(.text-editing) p:first-child::after { &.artifact-text.text-blank [contentEditable=true]:not(.text-editing) p:first-child::after {
content: "Double click to edit"; content: "Double click to edit";
opacity: 0.25; opacity: 0.25;
} }
&.artifact-text.text-blank [contentEditable=true].text-editing p:first-child::after { /*&.artifact-text.text-blank [contentEditable=true].text-editing p:first-child::after {
content: "Type here"; content: "Type here";
opacity: 0.25; opacity: 0.25;
}*/ }*/
@ -469,11 +469,10 @@
color: black; color: black;
//@include user-select(none); //@include user-select(none);
white-space: normal; white-space: normal;
font-size: 18px; font-size: 36px;
&.artifact-zone { &.artifact-zone {
border: 1px solid rgba(46,204,113,1); background-color: rgba(0,0,0,0.05);
background-color: rgba(46,204,113,0.025);
border-radius: 10px; border-radius: 10px;
&:after {display: none; } &:after {display: none; }
.shape {display: none; } .shape {display: none; }
@ -553,6 +552,10 @@ body:not(.present-mode) {
cursor: grab !important; cursor: grab !important;
} }
.tool-note {
cursor: crosshair !important;
}
.artifact.state-idle { .artifact.state-idle {
.progress, .progress-text { .progress, .progress-text {
display: none; display: none;

View File

@ -7,12 +7,6 @@
.btn-group.colors { .btn-group.colors {
.btn { .btn {
// padding: 4px;
// background-clip: content-box;
// padding-right: 2px;
// &:last-child {
// padding-right: 4px;
// }
box-shadow: inset 0 0 30px 0px rgba(40,40,40,0.1); box-shadow: inset 0 0 30px 0px rgba(40,40,40,0.1);
} }
} }
@ -64,7 +58,7 @@
backface-visibility: hidden; backface-visibility: hidden;
cursor: pointer; cursor: pointer;
background-color: $light; background-color: $light;
color: $medium;; color: $black;
@include user-select(none); @include user-select(none);
&:last-child {border: none;} &:last-child {border: none;}
@ -82,12 +76,9 @@
&.btn-link { &.btn-link {
background-color: transparent; background-color: transparent;
color: $medium;; color: $medium;
} }
&.facebook {background-color: $facebook !important; color: white !important;}
&.twitter {background-color: $twitter !important; color: white !important; }
&.btn-round { &.btn-round {
border-radius: 100px !important; border-radius: 100px !important;
} }
@ -96,21 +87,10 @@
border-radius: 6px !important; border-radius: 6px !important;
} }
// &.close {
// position: absolute;
// top: 15px;
// right: 15px;
// z-index: 4000;
// font-size: 40px;
// }
&.btn-nude { &.btn-nude {
min-width: 0 !important; min-width: 0 !important;
// font-size: inherit !important;
padding: 0 !important; padding: 0 !important;
// height: auto !important;
background-color: transparent; background-color: transparent;
color: $medium;
} }
&.btn-nude + .btn-nude { &.btn-nude + .btn-nude {
@ -123,7 +103,7 @@
&.btn-stroke { &.btn-stroke {
box-shadow: inset 0 0 0 1px $dark; box-shadow: inset 0 0 0 1px $dark;
color: $dark !important; color: $black;
background-color: transparent; background-color: transparent;
&:active { &:active {
box-shadow: inset 0 0 0 1px white; box-shadow: inset 0 0 0 1px white;
@ -132,9 +112,8 @@
} }
&.btn-stroke-darken { &.btn-stroke-darken {
//box-shadow: inset 0 0 0 1px rgba(0,0,0,0.1); border: 1px solid $black;
border: 1px solid rgba(0,0,0,0.1); color: $black;
color: $medium;
background-color: transparent; background-color: transparent;
&:active { &:active {
//box-shadow: inset 0 0 0 1px $dark; //box-shadow: inset 0 0 0 1px $dark;
@ -263,9 +242,18 @@
&.btn-transparent { &.btn-transparent {
background-color: transparent; background-color: transparent;
color: $medium; color: $dark;
&.active {color: $darker !important; } &.active {
&.open {color: white !important; } //color: $black !important;
color: $white;
background-color: $black;
}
&.open {
//color: $black !important;
color: $white;
background-color: $black;
border-radius: 0;
}
} }
&.btn-transparent-medium { &.btn-transparent-medium {
@ -313,7 +301,7 @@
&.btn-dark { &.btn-dark {
background-color: $dark ; background-color: $dark ;
color: $medium; color: $white;
} }
&.btn-medium { &.btn-medium {
@ -481,7 +469,6 @@
&.btn-icon { &.btn-icon {
padding: 0px !important; padding: 0px !important;
font-weight: bold;
max-width: 60px; max-width: 60px;
&.btn-xl { max-width: 80px; } &.btn-xl { max-width: 80px; }
@ -508,30 +495,6 @@
} }
} }
&.btn-social {
position: relative;
&:hover .icon,
.number {
@include scale(0,0);
opacity: 0;
}
&:hover .number {
@include transition( all 0.1s 0.1s ease-in-out);
@include scale(1,1);
opacity: 1;
}
.number,
.icon {
@include transition( all 0.1s 0s ease-in-out);
position: absolute;
top: 0;
left: 0;
}
}
&.btn-md.btn-icon-labeled { &.btn-md.btn-icon-labeled {
.icon:before { .icon:before {
line-height: 29px; line-height: 29px;
@ -567,7 +530,6 @@
.icon:before {line-height: 42px; } .icon:before {line-height: 42px; }
.icon-label { .icon-label {
font-size: 11px; font-size: 11px;
text-transform: capitalize;
text-align: center; text-align: center;
margin: 8px 0; margin: 8px 0;
display: block; display: block;
@ -580,7 +542,7 @@
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
padding: 0 0px; padding: 0 0px;
font-weight: bold; font-weight: 300;
} }
&.hover { &.hover {
@ -714,7 +676,6 @@
} }
> * { > * {
border-radius: 0 !important;
background-clip: padding-box; background-clip: padding-box;
width: 100%; width: 100%;
float: left; float: left;
@ -775,7 +736,7 @@
} }
} }
.btn-group { .btn-group {
@include scale(0,0); //@include scale(0,0);
//@include transition( all 0.1s 0s ease-in-out); //@include transition( all 0.1s 0s ease-in-out);
position: absolute; position: absolute;
@ -787,7 +748,7 @@
margin-left: -12px; margin-left: -12px;
.btn { .btn {
@include scale(0,0); //@include scale(0,0);
//@include transition( all 0.1s 0.05s ease-in-out); //@include transition( all 0.1s 0.05s ease-in-out);
@ -979,31 +940,7 @@
} }
} }
.btn-group.bottom-left > .btn { // !btn-group
border-radius: 0px;
&:first-child{
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
&.last,
&:last-child{
border-top-right-radius: 3px;
border-bottom-right-radius: 0px;
}
}
.btn-xyz {
position: relative;
display: inline-block;
line-height: 0px;
padding: 0px;
font-size: 0px;
vertical-align: middle;
white-space: nowrap;
@include clearfix;
min-height: 44px;
}
.btn-group { .btn-group {
position: relative; position: relative;
@ -1014,13 +951,16 @@
vertical-align: middle; vertical-align: middle;
white-space: nowrap; white-space: nowrap;
//border: 1px solid $dark;
border-radius: 5px;
&.dark { &.dark {
border-radius: $radius; border-radius: $radius;
background-color: $dark; background-color: $dark;
color: $lighter; color: $white;
.btn { .btn {
color: $lighter; color: $white;
} }
} }

View File

@ -96,15 +96,14 @@
border-bottom-right-radius: $radius*3; border-bottom-right-radius: $radius*3;
} }
.dialog-account {
width: 600px;
margin: auto;
margin-top: 100px;
}
.dialog { .dialog {
font-size: 13px;
ol, ul, p {
font-size: inherit;
}
> .btn-block:last-child { > .btn-block:last-child {
border-top-left-radius: 0px; border-top-left-radius: 0px;
border-top-right-radius: 0px; border-top-right-radius: 0px;
@ -112,24 +111,21 @@
border-bottom-right-radius: $radius*3; border-bottom-right-radius: $radius*3;
} }
min-width: 200px;
@include backface-visibility(hidden);
white-space: normal;
z-index: 1000;
position: absolute; position: absolute;
// white-space: normal; font-size: 15px;
border: 1px solid black;
box-shadow: 0 0 30px 1px rgba(0, 0, 0, 0.15);
border-radius: 5px;
white-space: normal;
opacity: 0; opacity: 0;
@include user-select(none); @include transition(all 0.125s ease-in-out);
@include transition( all 0.125s ease-in-out);
pointer-events: none; pointer-events: none;
background-color: $light; background-color: $light;
color: $medium; color: $dark;
&.dark {background-color: $dark; } &.dark {
background-color: $dark;
border-radius: $radius*3; }
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.05), 0 2px 7px rgba(0, 0, 0, 0.1);
.dialog-tabs-wrapper { .dialog-tabs-wrapper {
overflow: hidden; overflow: hidden;
@ -150,15 +146,13 @@
&:hover span {color: $dark; } &:hover span {color: $dark; }
&.open span { &.open span {
background-color: $light; background-color: white;
color: $dark; color: $dark;
opacity: 1; opacity: 1;
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.05), 0 2px 7px rgba(0, 0, 0, 0.1) !important;
border-bottom-right-radius: 0px !important; border-bottom-right-radius: 0px !important;
border-bottom-left-radius: 0px !important; border-bottom-left-radius: 0px !important;
border-top-left-radius: $radius*3; border-top-left-radius: $radius*3;
border-top-right-radius: $radius*3; border-top-right-radius: $radius*3;
} }
&:first-child span { &:first-child span {
@ -200,7 +194,6 @@
text-align: center; text-align: center;
} }
.dialog-section { .dialog-section {
&:first-child {border: none !important; } &:first-child {border: none !important; }
border-top: 2px solid rgba(0,0,0,0.1); border-top: 2px solid rgba(0,0,0,0.1);
@ -228,4 +221,13 @@
h4 .icon { h4 .icon {
height: 38px; height: 38px;
} }
// account dialog
&.dialog-freestanding {
margin: auto;
position: relative;
top: 150px;
border: none;
width: 800px;
}
} }

View File

@ -43,9 +43,6 @@ $predelay: 0;
&.hover:hover, &.hover:hover,
&.open { &.open {
// &:before {opacity: 0.125; }
// pointer-events: auto;
background-color: $dark;
background-color: $light; background-color: $light;
> * { > * {
@ -111,8 +108,8 @@ $predelay: 0;
} }
&:last-child > .btn{ &:last-child > .btn{
border-top-right-radius: $radius ; border-top-right-radius: $radius;
border-bottom-right-radius: $radius ; border-bottom-right-radius: $radius;
} }
} }
} }
@ -122,6 +119,10 @@ $predelay: 0;
position: relative; position: relative;
vertical-align: middle; vertical-align: middle;
a {
text-decoration: none;
}
&.dropdown-block { &.dropdown-block {
display: block; display: block;
.dropdown-toggle { .dropdown-toggle {
@ -143,8 +144,7 @@ $predelay: 0;
&.light > .dropdown-menu, &.light > .dropdown-menu,
&.light > .dialog { &.light > .dialog {
background: $light; background: white;
color: $medium;
} }
> .dropdown-menu { > .dropdown-menu {
@ -189,8 +189,6 @@ $predelay: 0;
} }
} }
&.hover:hover > .dialog, &.hover:hover > .dialog,
&.hover:hover > .dropdown-menu, &.hover:hover > .dropdown-menu,
@ -206,9 +204,7 @@ $predelay: 0;
&.open { &.open {
> .dialog, > .dialog,
> .dropdown-menu { > .dropdown-menu {
-webkit-transform: translate3d(-50%, -50%, 100px) scale(1); //transform: translate3d(-50%, -50%, 100px) scale(1);
-ms-transform: translate3d(-50%, -50%, 100px) scale(1);
transform: translate3d(-50%, -50%, 100px) scale(1);
} }
} }
@ -217,10 +213,8 @@ $predelay: 0;
left: 50%; left: 50%;
top: 50%; top: 50%;
margin-top: 0px; margin-top: 0px;
@include transform-origin(center center); //@include transform-origin(center center);
-webkit-transform: translate3d(-50%, -50%, 100px) scale(0.93,0.8); //transform: translate3d(-50%, -50%, 100px) scale(0.93,0.8);
-ms-transform: translate3d(-50%, -50%, 100px) scale(0.93,0.8);
transform: translate3d(-50%, -50%, 100px) scale(0.93,0.8);
} }
} }
@ -230,10 +224,8 @@ $predelay: 0;
top: auto; top: auto;
bottom: 100%; bottom: 100%;
margin-bottom: 16px; margin-bottom: 16px;
@include transform-origin(bottom left); //@include transform-origin(bottom left);
-webkit-transform: translate3d(-33%, 0%, 100px) scale(0.93,0.8); //transform: translate3d(-33%, 0%, 100px) scale(0.93,0.8);
-ms-transform: translate3d(-33%, 0%, 100px) scale(0.93,0.8);
transform: translate3d(-33%, 0%, 100px) scale(0.93,0.8);
} }
} }
@ -243,10 +235,8 @@ $predelay: 0;
top: auto; top: auto;
bottom: 100%; bottom: 100%;
margin-bottom: 16px; margin-bottom: 16px;
@include transform-origin(bottom center); //@include transform-origin(bottom center);
-webkit-transform: translate3d(-50%, 0%, 100px) scale(0.93,0.8); //transform: translate3d(-50%, 0%, 100px) scale(0.93,0.8);
-ms-transform: translate3d(-50%, 0%, 100px) scale(0.93,0.8);
transform: translate3d(-50%, 0%, 100px) scale(0.93,0.8);
} }
} }
@ -257,10 +247,16 @@ $predelay: 0;
top: 100%; top: 100%;
bottom: auto; bottom: auto;
margin-top: -16px; margin-top: -16px;
@include transform-origin(top center); //@include transform-origin(top center);
-webkit-transform: translate3d(-50%, 0%, 100px) scale(0.93,0.8); //transform: translate3d(-50%, 0%, 100px) scale(0.93,0.8);
-ms-transform: translate3d(-50%, 0%, 100px) scale(0.93,0.8); }
transform: translate3d(-50%, 0%, 100px) scale(0.93,0.8); }
&.top.left {
> .dialog,
> .dropdown-menu {
left: 70px;
margin-top: -60px;
} }
} }
@ -270,20 +266,18 @@ $predelay: 0;
top: 100%; top: 100%;
bottom: auto; bottom: auto;
left: auto; left: auto;
right: 0;
margin-top: 16px; right: 70px;
@include transform-origin(top right); margin-top: -60px;
-webkit-transform: translate3d(0%, 0%, 100px) scale(0.93,0.8);
-ms-transform: translate3d(0%, 0%, 100px) scale(0.93,0.8); //@include transform-origin(top right);
transform: translate3d(0%, 0%, 100px) scale(0.93,0.8); //transform: translate3d(0%, 0%, 100px) scale(0.93,0.8);
} }
&.hover:hover, &.hover:hover,
&.open { &.open {
> .dialog, > .dialog,
> .dropdown-menu { > .dropdown-menu {
-webkit-transform: translate3d(0%, 0%, 100px) scale(1); //transform: translate3d(0%, 0%, 100px) scale(1);
-ms-transform: translate3d(0%, 0%, 100px) scale(1);
transform: translate3d(0%, 0%, 100px) scale(1);
} }
} }
@ -312,9 +306,7 @@ $predelay: 0;
> .dialog, > .dialog,
> .dropdown-menu { > .dropdown-menu {
-webkit-transform: translate3d(-50%, 0%, 100px) scale(1); //transform: translate3d(-50%, 0%, 100px) scale(1);
-ms-transform: translate3d(-50%, 0%, 100px) scale(1);
transform: translate3d(-50%, 0%, 100px) scale(1);
} }
} }
} }
@ -324,9 +316,7 @@ $predelay: 0;
&.open { &.open {
> .dialog, > .dialog,
> .dropdown-menu { > .dropdown-menu {
-webkit-transform: translate3d(-33%, 0%, 100px) scale(1) !important; //transform: translate3d(-33%, 0%, 100px) scale(1) !important;
-ms-transform: translate3d(-33%, 0%, 100px) scale(1) !important;
transform: translate3d(-33%, 0%, 100px) scale(1) !important;
} }
} }
} }
@ -334,7 +324,7 @@ $predelay: 0;
.dropdown { .dropdown {
&.options-3 { /*&.options-3 {
&.option-1:after { margin-left: -68px;} &.option-1:after { margin-left: -68px;}
&.option-2:after { margin-left: -8px;} &.option-2:after { margin-left: -8px;}
&.option-3:after { margin-left: 52px;} &.option-3:after { margin-left: 52px;}
@ -348,8 +338,9 @@ $predelay: 0;
-webkit-transform: scale(1); -webkit-transform: scale(1);
-ms-transform: scale(1); -ms-transform: scale(1);
transform: scale(1); transform: scale(1);
} }*/
/*
&:after { &:after {
@include transition( all 0.1s ease-in-out 0s); @include transition( all 0.1s ease-in-out 0s);
content: ""; content: "";
@ -362,26 +353,24 @@ $predelay: 0;
margin-left: -8px; margin-left: -8px;
pointer-events: none !important; pointer-events: none !important;
left: 50%; left: 50%;
-webkit-transform: scale(0,0); //transform: scale(0,0);
-ms-transform: scale(0,0);
transform: scale(0,0);
} }
&.bottom:after, &.bottomleft:after { &.bottom:after, &.bottomleft:after {
@include transform-origin(bottom center); //@include transform-origin(bottom center);
bottom: 100%; bottom: 100%;
border-bottom: 8px solid transparent; border-bottom: 8px solid transparent;
border-right: 8px solid transparent; border-right: 8px solid transparent;
border-top: 8px solid #303030; border-top: 8px solid #303030;
border-left: 8px solid transparent; border-left: 8px solid transparent;
} }
*/
&.top:after { /*&.top:after {
@include transform-origin(top center); @include transform-origin(top center);
top: 100%; top: 100%;
border-bottom: 8px solid #303030; border-bottom: 8px solid #303030;
border-right: 8px solid transparent; border-right: 8px solid transparent;
border-top: 8px solid transparent; border-top: 8px solid transparent;
border-left: 8px solid transparent; border-left: 8px solid transparent;
} }*/
} }

View File

@ -254,7 +254,6 @@
// word-wrap: break-word; // word-wrap: break-word;
.item { .item {
box-shadow: 0 0 1pxrgba(0,0,0,0.1);
display: inline-block; display: inline-block;
text-align: left; text-align: left;
padding-right: $folder-gutter*2; padding-right: $folder-gutter*2;
@ -397,7 +396,10 @@
&:active { opacity: 0.95 !important; } &:active { opacity: 0.95 !important; }
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.025), 0 2px 7px rgba(0, 0, 0, 0.025); box-shadow: 0 0 30px 1px rgba(0, 0, 0, 0.15);
border: 1px solid black;
// ???
@include opacity(1); @include opacity(1);
color: $medium; color: $medium;
// color: white; // color: white;
@ -476,7 +478,6 @@
left: 0px; left: 0px;
z-index: 100; z-index: 100;
width: auto; width: auto;
background-color: rgba(255,255,255,1);
.dropdown { .dropdown {
position: absolute; position: absolute;
@ -501,30 +502,6 @@
color: $dark; color: $dark;
text-align: left; text-align: left;
} }
.item-social {
padding: 8px;
border-right: 2px solid rgba(0,0,0,0.025);
@include clearfix;
color: $medium;
.item-likes,
.item-comments,
.item-shares {
position: relative;
&:hover {
.icon {opacity: 0; }
.number {opacity: 1; }
}
.number {
position: absolute;
opacity: 0;
top: 0;
left: 0;
}
.icon {opacity: 0.5; }
}
}
} }
.item-appendix { .item-appendix {

View File

@ -28,7 +28,6 @@
line-height: 1.5; line-height: 1.5;
width: 100%; width: 100%;
text-align: left; text-align: left;
color: $medium;
font-weight: normal; font-weight: normal;
cursor: pointer; cursor: pointer;
border-radius: $radius; border-radius: $radius;

View File

@ -2,24 +2,14 @@
@import "mixins"; @import "mixins";
.input-select { .input-select {
// background-color: rgba(255,255,255,0.04); background-color: rgba(255,255,255,0.04);
// background-image: url('images/select_arrow.gif'); background-image: url('images/select_arrow.gif');
border-radius: $radius; border-radius: $radius;
display: inline-block; display: inline-block;
width: 100%; width: 100%;
} }
@-moz-document url-prefix() {
select.input{
background-repeat: no-repeat;
background-position: right center;
cursor: pointer;
}
}
select { select {
-webkit-appearance:none;
// -moz-appearance:window;
appearance:none; appearance:none;
padding-left: 0px; padding-left: 0px;
width: 100%; width: 100%;

View File

@ -23,7 +23,6 @@ input:invalid {
top: 0; top: 0;
right: 0; right: 0;
line-height: 1; line-height: 1;
font-size: 10px;
margin: 12px; margin: 12px;
color: red; color: red;
margin-right: 25px; margin-right: 25px;
@ -113,43 +112,26 @@ select {
&.input-white { &.input-white {
background-color: white; background-color: white;
color: $medium;
box-shadow: inset 0 0 1px 1px rgba(0, 0, 0, 0.05), inset 0 0px 4px rgba(0, 0, 0, 0.1); box-shadow: inset 0 0 1px 1px rgba(0, 0, 0, 0.05), inset 0 0px 4px rgba(0, 0, 0, 0.1);
} }
&.input-light { &.input-light {
background-color: $light; background-color: $light;
color: $medium;
} }
&.input-dark { &.input-dark {
background-color: $darker; background-color: $darker;
color: $medium;
} }
&.input-lighten { &.input-lighten {
background-color: rgba(255,255,255,0.05); background-color: rgba(255,255,255,0.05);
color: $medium !important;
} }
&.input-darken { &.input-darken {
background-color: rgba(0,0,0,0.05); background-color: rgba(0,0,0,0.05);
color: $medium;
} }
&.input-transparent { &.input-transparent {
background-color: transparent; background-color: transparent;
color: $medium;
}
// &:focus {color: white; }
&:invalid {
// background-color: rgba(198,101,84,0.05);
// color: rgba(198,101,84,0.75)
&:after {
}
} }
@include input-focus(); @include input-focus();

View File

@ -69,26 +69,27 @@
} }
.handles { .handles {
// background-color: rgba(40,140,215,0.45); //border: 1px solid rgba(255,255,255,0.5);
border: 1px solid rgba(255,255,255,0.5);
position: absolute; position: absolute;
left: 0; left: 0;
top: 0; top: 0;
bottom: 0; bottom: -1;
right: 0; right: 0;
z-index: 800; z-index: 800;
pointer-events: none; pointer-events: none;
background: rgba(255,255,255,0.1);
&:after{ &:after{
border: 1px dotted rgba(40,140,215,1); border: 4px dotted #000000;
content: ""; content: "";
display: block; display: block;
position: absolute; position: absolute;
height: auto; height: auto;
width: auto; width: auto;
top: -1px; top: 0px;
left: -1px; left: 0px;
right: -1px; right: 0px;
bottom: -1px; bottom: -1px;
} }
} }
@ -97,7 +98,7 @@
border: 8px solid rgba(255,255,255,0.5); border: 8px solid rgba(255,255,255,0.5);
&:after{ &:after{
border: 8px dotted rgba(40,140,215,1); border: 8px dotted #000000;
top: -4px; top: -4px;
left: -4px; left: -4px;
right: -4px; right: -4px;
@ -332,15 +333,14 @@
pointer-events:auto; pointer-events:auto;
z-index: 2000; z-index: 2000;
position: absolute; position: absolute;
width: 30px !important;
height: 30px !important;
border-radius: 100%; border-radius: 100%;
margin: -15px;
border: 1px solid rgba(0,0,0,0.25); border: 1px solid black;
margin: -5px;
padding: 4px;
&:hover { &:hover {
background-color: rgba(255,255,255,0.5); background-color: black;
cursor: move; cursor: move;
} }
} }
@ -428,14 +428,7 @@
border-style: solid; border-style: solid;
border-width: 10px; border-width: 10px;
border-color: transparent; border-color: transparent;
-webkit-background-clip: padding-box;
-moz-background-clip: padding-box;
background-clip: padding-box; background-clip: padding-box;
-webkit-transition: all .05s ease-in-out;
-moz-transition: all .05s ease-in-out;
-ms-transition: all .05s ease-in-out;
-o-transition: all .05s ease-in-out;
transition: all .05s ease-in-out; transition: all .05s ease-in-out;
} }

View File

@ -5,7 +5,6 @@
.header-left, .header-left,
.header-right { .header-right {
position: absolute; position: absolute;
//@include transition( all 0.25s ease-in-out);
@include backface-visibility(hidden); @include backface-visibility(hidden);
z-index: 3000; z-index: 3000;
top: 10px; top: 10px;
@ -27,21 +26,21 @@
.home { .home {
margin-top: -20px; margin-top: -20px;
margin-left: -20px; margin-left: -20px;
// .icon {color: $dark; }
} }
.header-left { .header-left {
@include transform-origin(center left);
left: 0; left: 0;
padding-left: 10px; padding-left: 10px;
padding-left: 20px;
padding-top: 20px;
} }
.header-right { .header-right {
@include transform-origin(center right);
right: 0; right: 0;
padding-right: 10px; padding-right: 20px;
padding-top: 20px;
} }
.header-center { .header-center {
@include transform-origin(center center);
width: 100%; width: 100%;
left: 0; left: 0;
right: 0; right: 0;
@ -56,7 +55,7 @@
} }
} }
.header-left > * { margin-right: 10px; } .header-left > * { margin-right: 10px; }
.header-right > * { margin-left: 5px; } .header-right > * { margin-left: 10px; }
.header-right { font-size: 0;} .header-right { font-size: 0;}
.title { .title {
@ -90,21 +89,3 @@
opacity: 0.5; opacity: 0.5;
} }
} }
.present-mode #space-header {
background-color: transparent !important;
}
#space-siblings {
background-color: rgba(245, 245, 245, 0.95);
padding: 35px;
max-height: 450px;
overflow-y: scroll;
margin-top: 54px;
border-bottom: 1px solid #eee;
.btn {
margin-bottom: 50px;
}
}

View File

@ -85,3 +85,12 @@
transform: rotateZ(45deg) translateX(-8px); transform: rotateZ(45deg) translateX(-8px);
} }
.icon-svg {
background-size: 26px;
background-position: center;
background-repeat: no-repeat;
}
.icon-sd6 {
background-image: url(/images/sd6-icon-white.svg);
}

View File

@ -1,257 +1,52 @@
@import "vars"; @import "vars";
#landing-header { #landing-header {
background-color: rgba(255,255,255,0.3); background-color: white;
height: 64px; height: 64px;
position: absolute; position: relative;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
} }
.landing-keyvisual-wrapper { #landing {
background-image: url("../images/sd5-keyvisual-compressed.jpg"); margin-top: 100px;
background-size: cover;
background-position: center;
padding-top: 40px;
padding-bottom: 40px;
}
.landing-plans-wrapper { section {
background-image: url("../images/sd5-hero2-compressed.jpg"); margin-left: 300px;
background-size: cover;
background-position: center;
padding-top: 80px;
padding-bottom: 100px;
}
.landing-box { > * {
width: 800px; max-width: 600px;
margin: auto;
max-width: 90%;
background-color: white;
padding: 40px;
margin-bottom: 80px;
margin-top: 80px;
position: relative;
box-shadow: 0px 0px 50px rgba(0,0,0,0.2);
h1 {
margin-bottom: 20px;
} }
&.black {
background-color: #222;
color: white;
padding: 20px;
text-align: center;
}
&.overlap {
position: absolute;
z-index: 2;
margin-top: -65px;
left: 50%;
top: 0px;
margin-left: -250px;
width: 500px;
}
&.screenshot {
width: 90%;
max-width: 90%;
padding: 20px;
box-shadow: none;
background-color: transparent;
img {
width: 100%;
position: absolute;
top: 0px;
left: 0px;
opacity: 0.3;
}
}
&.landing-box-left {
margin-left: 30px;
}
}
.lead-xxl {
}
.lead {
margin-bottom: 20px;
}
.lead-xl {
}
.plans-box {
background: linear-gradient(to bottom, #FEFFFF 25%,#D0D8E2 100%);
padding: 40px;
border-radius: 9px;
}
.landing-box.plans-box {
margin-top: 200px;
width: 900px;
}
.plans-table {
tr {
vertical-align: top;
}
th {
font-size: 42px;
padding-top: 40px;
text-align: center;
}
th.best-plan {
padding-top: 20px;
font-size: 48px;
padding-bottom: 0px;
}
td {
padding: 20px;
width: 30%;
p, li {
font-size: 18px;
}
li {
margin-bottom: 10px;
}
}
td.best-plan {
width: 40%;
p {
font-size: 22px;
}
}
td li {
list-style-type: none;
text-align: center;
}
ul {
margin: 0 !important;
padding: 0 !important;
}
.upgrade-buttons {
text-align:center;
margin-top:20px;
}
}
.logo-row {
position: relative;
padding: 80px;
background-color: white;
text-align: center;
width: 100%;
&.blue {
background-color: $blue;
color: white;
}
}
.logo-row div {
display: inline-block;
width: 200px;
}
.landing-row {
background-color: white;
padding-bottom: 80px;
padding-top: 40px;
}
#keyvisual {
border-radius: 20px;
box-shadow: 0px 0px 20px #eee;
width: 640px;
height: 420px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
background-image: url('/images/landing/spacedeck-screenshot1.jpg');
background-color: white;
margin: auto;
margin-top: 40px;
margin-bottom: 40px;
border: 1px solid #eee;
}
#legal {
.landing-box {
width: 800px;
} }
} }
.footer { .footer {
padding: 40px; margin-left: 300px;
padding-bottom: 80px; margin-top: 100px;
text-align: center; margin-bottom: 100px;
color: $medium; }
a { @media screen and (max-width: 1000px) {
#landing {
section {
margin-left: 20px;
margin-right: 20px; margin-right: 20px;
} }
}
@media screen and (min-width: 801px) {
.plans-table-mobile {
display: none;
} }
} .footer {
margin-left: 20px;
@media screen and (max-width: 800px) { margin-right: 20px;
ul.lead.lead-xl, p.lead.lead-xl, ol.lead.lead-xl {
font-size: 20px !important;
} }
.header-right { .header-right {
> span:first-child { right: auto;
display: none; padding-left: 10px;
} padding-right: 20px;
padding-top: 80px;
} }
.plans-table { #folder-wrapper {
display: none; padding-top: 128px;
}
.plans-table-mobile {
display: block;
tbody {
display: block;
width: 100%;
}
tr {
display: block;
width: 100%;
}
td, th {
display: block;
width: 100%;
}
ul, li {
width: 100%;
}
} }
} }

View File

@ -2,7 +2,6 @@
@import "mixins"; @import "mixins";
.wrapper { .wrapper {
//@include transition( all 0.25s ease-in-out);
position: relative; position: relative;
margin: auto; margin: auto;
max-width: 1160px; max-width: 1160px;

View File

@ -59,8 +59,8 @@
} }
.close { .close {
position: fixed; margin-left: 44px;
margin: 44px 44px; margin-bottom: 44px;
.icon {display: block; } .icon {display: block; }
} }
@ -135,7 +135,6 @@
outline: none; outline: none;
display: inline-block; display: inline-block;
text-align: left; text-align: left;
@include user-select(none);
border-radius: $radius*3; border-radius: $radius*3;
background-color: $light !important; background-color: $light !important;
@ -146,7 +145,6 @@
.modal-header { .modal-header {
padding: 30px 40px; padding: 30px 40px;
position: relative; position: relative;
color: $medium;
} }
.close-search { .close-search {
@ -279,25 +277,5 @@
// Footer (for actions) // Footer (for actions)
.modal-footer { .modal-footer {
// border-bottom-left-radius: $radius; margin-top: 20px;
// border-bottom-right-radius: $radius;
// background-color: $dark !important;
// padding: 40px;
// padding-top: 0px;
// text-align: right; // right align buttons
@include clearfix(); // clear it in case folks use .pull-* classes on buttons
// Properly space out buttons
// .btn + .btn {
// margin-left: 5px;
// margin-bottom: 0; // account for input[type="submit"] which gets the bottom margin like all other inputs
// }
// // but override that for button groups
// .btn-group .btn + .btn {
// margin-left: -1px;
// }
// // and override it for block buttons as well
// .btn-block + .btn-block {
// margin-left: 0;
// }
} }

12
styles/normalize.scss vendored
View File

@ -1,17 +1,5 @@
/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ /*! normalize.css v3.0.0 | MIT License | git.io/normalize */
//
// 1. Set default font family to sans-serif.
// 2. Prevent iOS text size adjust after orientation change, without disabling
// user zoom.
//
html {
font-family: sans-serif; // 1
-ms-text-size-adjust: 100%; // 2
-webkit-text-size-adjust: 100%; // 2
}
// //
// Remove default margin. // Remove default margin.
// //

View File

@ -27,6 +27,5 @@
right: 0; right: 0;
z-index: 800; z-index: 800;
pointer-events: none; pointer-events: none;
opacity: 0.25;
display: block; display: block;
} }

View File

@ -6,22 +6,18 @@
li { li {
&.checked { &.checked {
&:before {background-color: $medium !important; }
> a, > a,
> span { > span {
color: $medium;
} }
} }
&:hover { &:hover {
&:before {background-color: $medium; }
> a, > a,
> span { > span {
background-color: rgba(0,0,0,0.025) !important; background-color: rgba(0,0,0,0.025) !important;
} }
} }
&:before {background-color: $medium; }
> a, > a,
> span { > span {
color: $medium; color: $medium;
@ -30,7 +26,7 @@
} }
.select-list { .select-list {
&:empty:before{ &:empty:before {
position: absolute; position: absolute;
top: 50%; top: 50%;
left: 50%; left: 50%;
@ -45,17 +41,14 @@
opacity: 0.5; opacity: 0.5;
} }
-webkit-mask-image: -webkit-gradient(linear, left top, left 15px, from(rgba(0,0,0,0)), to(rgba(0,0,0,0.5)));
background-clip: padding-box; background-clip: padding-box;
font-size: 15px; //font-size: 15px;
line-height: 14px; //line-height: 14px;
list-style: none; list-style: none;
margin: 0px; margin: 0px;
padding: 15px 0; padding: 15px 0;
text-align: left; text-align: left;
// background-color: $dark; // background-color: $dark;
color: $medium;
border-radius: $radius; border-radius: $radius;
.divider + li span {border: none !important; } .divider + li span {border: none !important; }
@ -90,15 +83,11 @@
} }
&:hover { &:hover {
// background-color: rgba(0,0,0,0.025); background-color: black;
&:before {
background-color: $medium;
display: block;
}
> a, > a,
> span { > span {
color: $medium; color: white;
color: $dark;
} }
} }
@ -126,9 +115,8 @@
display: block; display: block;
cursor: pointer; cursor: pointer;
white-space: nowrap; white-space: nowrap;
color: $medium;
margin: 0 25px; margin: 0 25px;
padding: 16px 3px; padding: 10px 0px;
// line-height: 50px; // line-height: 50px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;

View File

@ -118,7 +118,7 @@
padding: 0 !important; padding: 0 !important;
.wrapper { .wrapper {
border: 1px dotted rgba(128,128,128,0.5); border: 4px solid black;
transition-duration: 0.25s; transition-duration: 0.25s;
transition-property: width, height, background-color; transition-property: width, height, background-color;
@ -132,32 +132,27 @@
max-height: 100%; max-height: 100%;
position: relative; position: relative;
overflow: scroll; overflow: scroll;
/** {
-moz-user-select: none !important; // firefox has selection problems
}*/
} }
.snap-ruler-h { .snap-ruler-h {
pointer-events: none; pointer-events: none;
position: fixed; position: fixed;
z-index: 0; z-index: 2000;
right: 0px; right: 0px;
height: 1px; height: 1px;
background-color: rgba(0,0,0,0.5); background-color: black;
left: 0px; left: 0px;
} }
.snap-ruler-v { .snap-ruler-v {
pointer-events: none; pointer-events: none;
position: fixed; position: fixed;
z-index: 0; z-index: 2000;
top: 0px; top: 0px;
bottom: 0px; bottom: 0px;
width: 1px; width: 1px;
background-color: rgba(0,0,0,0.5); background-color: black;
} }
.cursor { .cursor {
@ -227,30 +222,12 @@
} }
#space { #space {
/*-webkit-user-select: all; // user-select: all;
-ms-user-select: all;
-moz-user-select: all;
user-select: all;*/
position: relative; position: relative;
height: 100% !important; height: 100% !important;
//padding-top: 64px !important;
background-color: #eee; background-color: #eee;
} }
#made-with {
position: fixed;
width: 100%;
bottom: 0;
padding: 12px;
opacity: 0.25;
a {color: $dark; }
p {
text-align: center;
font-size: 11px;
}
}
#baseline { #baseline {
position: absolute; position: absolute;
width: 100%; width: 100%;
@ -298,8 +275,8 @@
.space-bounds { .space-bounds {
position: absolute; position: absolute;
left: 0px; left: 0;
top: 0px; top: 0;
pointer-events: none; pointer-events: none;
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;

View File

@ -65,10 +65,15 @@
html, html,
body { body {
height:100%; height:100%;
-webkit-tap-highlight-color: transparent;
background-color: white; background-color: white;
background-color: $light; color: $black;
color: $darker; }
body {
max-width: 100%;
padding: 0px;
text-rendering: optimizeLegibility;
cursor: default;
} }
*[contenteditable="true"] { *[contenteditable="true"] {
@ -81,70 +86,12 @@ body {
@include box-sizing(border-box); @include box-sizing(border-box);
} }
body {
max-width: 100%;
padding: 0px;
text-rendering: optimizeLegibility;
//@include user-select(none);
cursor: default;
}
.img img { .img img {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
} }
.plan { /*.layer {
color: $medium;
border-radius: $radius;
display: inline-block;
padding: 30px;
background-color: transparent;
border: 2px solid rgba(0,0,0,0.05);
width: 100%;
&.active {
background-color: white;
border: none;
}
h4 {
color: black;
margin-bottom: 0px;
}
p {
font-size: 13px;
line-height: 1.4;
margin-top: 5px;
margin-bottom: 5px;
}
ul {
list-style: none;
font-size: 10px;
margin: 0px;
padding: 0px;
border-top: 2px solid rgba(0,0,0,0.05);
padding-top: 20px;
margin-top: 20px;
margin-bottom: 20px;
li {padding-top: 2px; }
}
}
#startup {
background-position: center;
background-image:url(/images/diamond.svg);
background-repeat: no-repeat;
}
#home {
background-color: white;
}
.layer {
@include transition( all 0.2s ease-in-out); @include transition( all 0.2s ease-in-out);
@include backface-visibility(hidden); @include backface-visibility(hidden);
position: absolute; position: absolute;
@ -172,7 +119,7 @@ body {
pointer-events: auto; pointer-events: auto;
opacity: 1; opacity: 1;
} }
} }*/
[draggable] { [draggable] {
-moz-user-select: none; -moz-user-select: none;

View File

@ -8,10 +8,9 @@
} }
.table { .table {
width: 100%; width: 100%;
color: $medium;;
font-family: $main-font; font-family: $main-font;
// border-radius: $radius; border-radius: $radius;
// border: 2px solid rgba(0,0,0,0.0125) !important; border: 2px solid rgba(0,0,0,0.0125);
} }
.table thead > tr > th:first-child, .table thead > tr > th:first-child,

View File

@ -19,50 +19,23 @@
} }
margin: auto; margin: auto;
//text-align: center;
position: fixed; position: fixed;
bottom: 0px; top: 20px;
//width: 100%;
z-index: 3000; z-index: 3000;
padding: $gutter-b; padding: 0;
font-size: 0; font-size: 0;
line-height: 0; line-height: 0;
transition-duration: 0.15s; box-shadow: 0 0 30px 1px rgba(0, 0, 0, 0.15);
transition-timing-function: ease-in-out; border: 1px solid black;
transition-delay: initial; border-radius: 5px;
transition-property: opacity, transform;
@include backface-visibility(hidden); // FIXME questionable?
@include translate3d(0, 10px, 0);
pointer-events: none !important; pointer-events: none !important;
opacity: 0;
&.out {
@include translate3d(0, 10px, 0);
* {pointer-events: none !important; }
button, input, .dialog {
display: none;
}
}
&.in {
@include translate3d(0, 0, 0);
&.out {
@include translate3d(0, 10px, 0);
* {pointer-events: none !important; }
}
}
> * { > * {
margin: 0 2px;
margin-top: 4px;
pointer-events: auto !important; pointer-events: auto !important;
&.out {
margin: 0;
opacity: 0;
}
} }
&.toolbar-vertical { &.toolbar-vertical {
@ -187,7 +160,6 @@
} }
.toolbar-properties { .toolbar-properties {
bottom: 64px;
z-index: 0; z-index: 0;
&.in { &.in {
@ -196,12 +168,12 @@
.icon-sm { .icon-sm {
z-index: 110; z-index: 110;
background-color: #222; //background-color: #222;
border-radius: 50px; border-radius: 50px;
} }
.jewel { .jewel {
border: 2px solid rgba(255,255,255,0.5); border: 2px solid #888;
background-color: transparent; background-color: transparent;
color: #989898; color: #989898;
width: 36px; width: 36px;
@ -228,5 +200,22 @@
.toolbar-elements > .btn-group, .toolbar-elements > .btn-group,
.toolbar-properties > .btn-group { .toolbar-properties > .btn-group {
box-shadow: 0 0 30px rgba(0,0,0,0.5); //box-shadow: 0 0 30px rgba(0,0,0,0.5);
background-color: $white;
}
.toolbar-elements {
left: 20px;
}
.toolbar-properties {
right: 30px;
}
.zoom-bar {
position: absolute;
bottom: 30px;
right: 30px;
box-shadow: 0 0 30px 1px rgba(0, 0, 0, 0.15);
border: 1px solid black;
} }

View File

@ -33,9 +33,6 @@
@include translate3d(0, 0, 0); @include translate3d(0, 0, 0);
// @include backface-visibility(hidden); // @include backface-visibility(hidden);
-webkit-perspective: 1000;
-moz-perspective: 1000;
-ms-perspective: 1000;
perspective: 1000; perspective: 1000;
.panel-toggles { .panel-toggles {
@ -99,9 +96,6 @@
display: table-cell; display: table-cell;
vertical-align: middle; vertical-align: middle;
// @include backface-visibility(hidden); // @include backface-visibility(hidden);
-webkit-perspective: 1000;
-moz-perspective: 1000;
-ms-perspective: 1000;
perspective: 1000; perspective: 1000;
z-index: 1000; z-index: 1000;

View File

@ -1,6 +1,8 @@
@import "vars"; @import "vars";
@import "mixins"; @import "mixins";
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;900&display=swap');
body { body {
background-color: $light; background-color: $light;
color: $medium; color: $medium;
@ -25,7 +27,7 @@ hr {
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 { h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6 {
color: inherit; color: inherit;
font-family: inherit; font-family: inherit;
font-weight: 500; font-weight: 900;
line-height: 1.3; line-height: 1.3;
margin-top: 0px; margin-top: 0px;
margin-bottom: 1em; margin-bottom: 1em;
@ -46,8 +48,7 @@ strong {font-weight: 500; }
small {font-size: 75%; } small {font-size: 75%; }
a { a {
text-decoration: none; color: black;
color: $medium;
} }
dl { dl {

View File

@ -9,13 +9,6 @@ $green: #2ecc71;
$red: #ff5955; $red: #ff5955;
$yellow: #f1c40f; $yellow: #f1c40f;
$light: #f5f5f5;
$lightish: #eee;
$facebook: #3e5b97;
$twitter: #2aa7de;
$color-1 : #4a2f7e; // purple $color-1 : #4a2f7e; // purple
$color-2 : #9b59b6; // lilac $color-2 : #9b59b6; // lilac
$color-3 : #3498db; // blue $color-3 : #3498db; // blue
@ -32,15 +25,18 @@ $black: #111; // black
$darker: #292929; $darker: #292929;
$dark: #222; // dark $dark: #222; // dark
$medium: #888; // medium $medium: #888; // medium
$light: #f5f5f5;
$lightish: #eee; // fixme
$lighter: #989898; $lighter: #989898;
$white: #ffffff;
$sidebar-width: 280px; $sidebar-width: 280px;
$main-font: Avenir W01; $main-font: Inter;
$sec-font: Avenir W01; $sec-font: Inter;
$font-size: 18px; $font-size: 20px;
$line-height: 24px; $line-height: 1.5em;
$gutter-a: 10px; $gutter-a: 10px;
$gutter-b: 20px; $gutter-b: 20px;

View File

@ -1,62 +1,34 @@
{% extends 'layouts/outer.html' %} {% extends 'layouts/outer.html' %}
{% block title %}[[ __("welcome") ]]{% endblock %} {% block title %}Spacedeck{% endblock %}
{% block content %} {% block content %}
<div id="landing"> <div id="landing">
<div class="landing-keyvisual-wrapper"> <section>
<div class="landing-box"> <h1>Work Together, Visually.</h1>
<h2>[[__("landing_title")]]</h2> <p>
Whenever you need to lay out pictures, text notes, video and audio clips on a blank canvas,
<p class="lead"> Spacedeck can help you.
<a href="/signup" class="btn btn-primary btn-block btn-xl">[[__("signup")]]</a>
</p> </p>
<p>
<p class="lead"> Spacedeck is a browser based application. It is the right tool for you if you want to quickly put together a collage of your idea or concept, either for yourself or to share it with teammembers, clients or students. Changes are updated in realtime.
<a href="/login" class="btn btn-primary btn-block btn-xl">[[__("login")]]</a>
</p> </p>
<p>
<p class="lead"> Spacedeck is not meant for creating polished designs, but it is a good fit for:
[[__("landing_claim")]]
</p> </p>
<p class="lead">
[[__("landing_example")]]
</p>
<ul> <ul>
<li class="lead"> <li>Moodboards</li>
[[__("landing_features_1") | safe ]] <li>Collages</li>
</li> <li>Teaching (Virtual Blackboards)</li>
<li>Shared Whiteboards</li>
<li class="lead"> <li>Design Thinking</li>
[[__("landing_features_2") | safe ]]
</li>
<li class="lead">
[[__("landing_features_3") | safe ]]
</li>
<li class="lead">
[[__("landing_features_4") | safe ]]
</li>
<li class="lead">
[[__("landing_features_5") | safe ]]
</li>
<li class="lead">
[[__("landing_features_6") | safe ]]
</li>
<li class="lead">
[[__("landing_features_7") | safe ]]
</li>
</ul> </ul>
</div> <img src="/images/sd6-screenshot.png" alt="Screenshot of Spacedeck 6.0">
</div> <p>
The hosted version of Spacedeck 6.0 is currently in beta and invite only. You can also self-host and <a href="https://github.com/spacedeck/spacedeck-open">participate in the open source development</a>.
</p>
</section>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -9,39 +9,25 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link href="[[ '/images/favicon.png' | cdn ]]" rel="icon" type="image/x-icon" /> <link href="[[ '/images/favicon.png' | cdn ]]" rel="icon" type="image/x-icon" />
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,700,600,800,300|Montserrat:400,700|EB+Garamond|Vollkorn|Lato|Roboto|Source+Code+Pro|Ubuntu|Raleway|Playfair+Display|Crimson+Text' rel='stylesheet' type='text/css'>
<link type="text/css" rel="stylesheet" href="https://fast.fonts.net/cssapi/ee1a3484-4d98-4f9f-9f55-020a7b37f3c5.css"/>
<link rel="stylesheet" href="[[ '/stylesheets/style.css' | cdn ]]"> <link rel="stylesheet" href="[[ '/stylesheets/style.css' | cdn ]]">
<script> var csrf_token = '[[ csrf_token ]]'; </script> <script> var csrf_token = '[[ csrf_token ]]'; </script>
<script src="[[ '/javascripts/jquery-2.1.4.min.js' | cdn ]]"></script> <!--script src="[[ '/javascripts/jquery-2.1.4.min.js' | cdn ]]"></script-->
</head> </head>
<body> <body>
<!--[if lt IE 10]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<header id="landing-header" class="header"> <header id="landing-header" class="header">
<div class="header-left"> <div class="header-left">
<a class="btn btn-transparent btn-nude" href="[[config.endpoint]]/"><img src="[[ '/images/sd5-logo.svg' | cdn ]]" width="190"></a> <a class="btn btn-transparent btn-nude" href="[[config.endpoint]]/"><img src="[[ '/images/sd6-logo-black.svg' | cdn ]]" width="190"></a>
</div> </div>
<div class="header-right pull-right"> <div class="header-right pull-right">
{% if !user %} {% if !user %}
<span class="btn-group dark round">
{% if (locale != "de") %}<a href="/t/de" rel="alternate" hreflang="de" class="btn btn-transparent btn-md">Deutsch</a>{% endif %}
{% if (locale != "en") %}<a href="/t/en" rel="alternate" hreflang="en" class="btn btn-transparent btn-md">English</a>{% endif %}
{% if (locale != "fr") %}<a href="/t/fr" rel="alternate" hreflang="fr" class="btn btn-transparent btn-md">Français</a>{% endif %}
</span>
<a class="btn btn-md btn-dark btn-round" href="/login">[[__("login")]]</a> <a class="btn btn-md btn-dark btn-round" href="/login">[[__("login")]]</a>
<a class="btn btn-md btn-blue btn-round" href="/signup">[[__("signup")]]</a> <a class="btn btn-md btn-dark btn-round" href="/signup">[[__("signup")]]</a>
{% else %} {% else %}
<a class="btn btn-md btn-blue btn-round" href="/spaces">[[__("spaces")]]</a> <a class="btn btn-md btn-dark btn-round" href="/spaces">[[__("spaces")]]</a>
<a class="btn btn-md btn-dark btn-round" href="/logout">[[__("logout")]]</a> <a class="btn btn-md btn-dark btn-round" href="/logout">[[__("logout")]]</a>
{% endif %} {% endif %}
</div> </div>
@ -52,8 +38,11 @@
<div class="footer"> <div class="footer">
<p> <p>
<div class="col-xs-6"> <div class="col-xs-6">
<a href="/contact">[[ __("contact") ]]</a> &copy; 2020 <a href="https://mntre.com">MNT Research GmbH</a>, Fehlerstr. 8, 12161 Berlin, Germany<br>
<span style="color:#888">&copy; 2011–2018 The Spacedeck Open Developers <a href="https://github.com/spacedeck/spacedeck-open">https://github.com/spacedeck/spacedeck-open</a></span> &copy; 2011–2019 Spacedeck GmbH (in liquidation)<br>
Source Code: <a href="https://github.com/mntmn/spacedeck-open">https://github.com/mntmn/spacedeck-open</a>
<br>
Font: <a href="https://rsms.me/inter/">Inter by rsms</a>
</div> </div>
</p> </p>
</div> </div>

View File

@ -1,16 +1,30 @@
<div id="team" class="dialog in" style="padding:100px;z-index:20000;position:absolute;width:100%;min-height:100%;background-color:#eee" v-if="active_view == 'account' && user" v-cloak> <header id="dialog-header" class="header" v-if="(active_view == 'account' && user)" v-cloak>
<div v-cloak class="header-left pull-left">
<a class="btn btn-dark btn-md btn-round btn-icon" href="/spaces">
<span class="icon icon-svg icon-sd6"></span>
</a>
<h5>Edit Account</h5>
</div>
<a href="/spaces" class="btn btn-round btn-icon btn-dark btn-md pull-right" style="position:absolute;top:30px;right:30px"><span class="icon icon-cross-0"></span></a> <div class="header-right pull-right">
<a class="btn btn-dark btn-md btn-round btn-icon" href="/spaces">
<span class="icon icon-cross-0"></span>
</a>
</div>
</header>
<div class="dialog-freestanding dialog in" v-if="active_view == 'account' && user" v-cloak>
<div class="dialog-tabs" style="margin:auto"> <div class="dialog-tabs" style="margin:auto">
<div class="dialog-tab" v-bind:class="{open:account=='profile'}" v-on:click="account='profile'"><span>[[__("profile_caption")]]</span></div> <div class="dialog-tab" v-bind:class="{open:account=='profile'}" v-on:click="account='profile'"><span>[[__("profile_caption")]]</span></div>
<div class="dialog-tab" v-bind:class="{open:account=='language'}" v-on:click="account='language'"><span>[[__("language_caption")]]</span></div> <div class="dialog-tab" v-bind:class="{open:account=='language'}" v-on:click="account='language'"><span>[[__("language_caption")]]</span></div>
<div class="dialog-tab" v-bind:class="{open:account=='notifications'}" v-on:click="account='notifications'"><span>[[__("notifications_caption")]]</span></div> <div class="dialog-tab" v-bind:class="{open:account=='notifications'}" v-on:click="account='notifications'"><span>[[__("notifications_caption")]]</span></div>
<div class="dialog-tab" v-if="user.account_type=='email'" v-bind:class="{open:account=='password'}" v-on:click="account='password'"><span>[[__("password_caption")]]</span></div> <div class="dialog-tab" v-bind:class="{open:account=='password'}" v-on:click="account='password'"><span>[[__("password_caption")]]</span></div>
<div class="dialog-tab" v-bind:class="{open:account=='terminate'}" v-on:click="account='terminate'"><span>[[__("terminate_caption")]]</span></div> <div class="dialog-tab" v-bind:class="{open:account=='terminate'}" v-on:click="account='terminate'"><span>[[__("terminate_caption")]]</span></div>
</div> </div>
<div class="dialog-section text-left" style="background-color:#f5f5f5;padding-top:40px;padding-bottom:40px"> <div class="dialog-section text-left">
<div class="collapse" v-bind:class="{in:account=='profile'}"> <div class="collapse" v-bind:class="{in:account=='profile'}">
<div class="labels-inline relative" style="margin-bottom:40px"> <div class="labels-inline relative" style="margin-bottom:40px">
<div class="form-group"> <div class="form-group">
@ -64,29 +78,7 @@
v-on:change="user.email_changed=true" v-on:change="user.email_changed=true"
placeholder="mail@example.com"> placeholder="mail@example.com">
<button class="btn btn-md btn-darken" v-if="user.account_type=='email'" v-on:click=" save_user()" style="margin-top:20px">[[__("ok")]]</button> <button class="btn btn-md btn-dark" v-on:click=" save_user()" style="margin-top:20px">Save</button>
</div>
<div class="form-group" v-if="!user.confirmed_at">
<p v-if="!user.confirmed_at && !account_confirmed_sent">[[__("confirmation_sent_long")]]</p>
<span
class="btn btn-xs btn-stroke-darken btn-round"
v-on:click=" confirm_again()"
v-if="!user.confirmed_at && !account_confirmed_sent"
>[[__("send_again")]]</span>
<p v-if="account_confirmed_sent">
<span class="icon icon-check"></span> <span>[[__("confirmation_sent_another")]]</span>
</p>
</div>
<div class="form-group">
<label class="label">Spacedeck.com Data Import</label>
<p v-if="!importables">No .ZIP files found in Spacedeck application folder.</p>
<ul>
<li v-for="f in importables">{{f}} <button v-on:click="start_zip_import(f)">Start Import</button></li>
</ul>
</div> </div>
</div> </div>
</div> </div>
@ -121,7 +113,7 @@
</div> </div>
<div class="collapse" v-bind:class="{in:account=='password'}"> <div class="collapse" v-bind:class="{in:account=='password'}">
<h4 class="modal-title">Change Password</h4> <h4>Change Password</h4>
<div class="modal-section labels-inline"> <div class="modal-section labels-inline">
<div class="form-group"> <div class="form-group">
<label class="label">[[__("current_password")]]</label> <label class="label">[[__("current_password")]]</label>
@ -140,23 +132,17 @@
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<div class="btn-cluster">
<button <button
class="btn btn-transparent btn-block" class="btn btn-dark btn-md"
v-on:click="save_user_password(password_change_current, password_change_new, password_change_new_confirmation);" > v-on:click="save_user_password(password_change_current, password_change_new, password_change_new_confirmation);" >
[[__("change_password")]] [[__("change_password")]]
</button> </button>
</div> </div>
</div> </div>
</div>
<div class="collapse" v-bind:class="{in:account=='terminate'}"> <div class="collapse" v-bind:class="{in:account=='terminate'}">
<div class=""> <h4>Terminate Account</h4>
<p>[[__("terminate_warning")]]</p> <div class="modal-section labels-inline">
<p>[[__("terminate_warning2")]]</p>
</div>
<div class="labels-inline" v-if="user.account_type == 'email'">
<div class="form-group"> <div class="form-group">
<label class="label">[[__("current_password")]]</label> <label class="label">[[__("current_password")]]</label>
<input v-model="account_remove_password" class="input input-white no-b" type="password"> <input v-model="account_remove_password" class="input input-white no-b" type="password">
@ -167,11 +153,15 @@
<textarea class="input input-white no-b" v-model="account_remove_feedback"></textarea> <textarea class="input input-white no-b" v-model="account_remove_feedback"></textarea>
<p class="message">[[__("terminate_reason_caption")]]</p> <p class="message">[[__("terminate_reason_caption")]]</p>
</div> </div>
</div>
<div class="modal-section labels-inline">
<div class="center alert alert-danger" v-if="account_remove_error">{{account_remove_error}}</div> <div class="center alert alert-danger" v-if="account_remove_error">{{account_remove_error}}</div>
</div> </div>
<button class="btn btn-transparent btn-block" v-on:click="remove_account(account_remove_password, account_remove_feedback)">[[__("terminate_terminate")]]</button> <div class="modal-footer">
<button class="btn btn-stroke-darken btn-md" v-on:click="remove_account(account_remove_password, account_remove_feedback)">Terminate Account</button>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,15 +1,23 @@
<header id="folder-header" class="header" v-if="(active_view == 'folders' && active_folder)" v-cloak> <header id="folder-header" class="header" v-if="(active_view == 'folders' && active_folder)" v-cloak>
<div v-cloak class="header-left pull-left"> <div v-cloak class="header-left pull-left">
<a class="btn btn-stroke-darken btn-md btn-round btn-icon" href="/spaces"> <a class="btn btn-dark btn-md btn-round btn-icon" href="/spaces">
<span class="icon icon-home"></span> <span class="icon icon-svg icon-sd6"></span>
</a> </a>
<button v-if="logged_in && (active_space_role == 'editor' || active_space_role == 'admin')" class="btn btn-primary btn-md btn-round" v-on:click="create_space('space')">[[ __('create_space') ]]</button> <button v-if="logged_in && (active_space_role == 'editor' || active_space_role == 'admin')" class="btn btn-dark btn-md btn-round" v-on:click="create_space('space')">[[ __('create_space') ]]</button>
<button v-if="logged_in && (active_space_role == 'editor' || active_space_role == 'admin')" class="btn btn-stroke-darken btn-md btn-round" v-on:click="create_space('folder')"> <button v-if="logged_in && (active_space_role == 'editor' || active_space_role == 'admin')" class="btn btn-stroke-darken btn-md btn-round" v-on:click="create_space('folder')">
<span v-bind:class="{'disabled-pro':!is_pro(user)}">[[ __('create_folder') ]]</span> <span>[[ __('create_folder') ]]</span>
</button> </button>
</div>
<div class="header-right pull-right"> <label class="relative compact-hidden">
<span class="icon icon-sm icon-zoom no-events absolute-top-left" style="margin: 5px;"></span>
<input id="folder-search"
type="search" name="search"
style="padding-left: 40px !important; margin-right: 10px;"
placeholder="[[ __('search') ]]"
class="input input-md input-white input-round no-b w-2"
v-model="folder_spaces_search" v-on:change="search_spaces">
</label>
<div class="dropdown top light m-r-20 compact-hidden" v-bind:class="{open : active_dropdown=='folder_sorting'}"> <div class="dropdown top light m-r-20 compact-hidden" v-bind:class="{open : active_dropdown=='folder_sorting'}">
<button class="btn btn-sm btn-nude" v-on:click="activate_dropdown('folder_sorting')"> <button class="btn btn-sm btn-nude" v-on:click="activate_dropdown('folder_sorting')">
<span>[[ __('sort_by') ]]</span>: <span>[[ __('sort_by') ]]</span>:
@ -33,29 +41,15 @@
v-on:click="set_folder_sorting('space_type',false)"> v-on:click="set_folder_sorting('space_type',false)">
<span>[[ __('type') ]]</span> <span>[[ __('type') ]]</span>
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
</div>
<label class="relative compact-hidden"> <div class="header-right pull-right">
<span class="icon icon-sm icon-zoom no-events absolute-top-left" style="margin: 5px;"></span>
<input id="folder-search"
type="search" name="search"
style="padding-left: 40px !important; margin-right: 10px;"
placeholder="[[ __('search') ]]"
class="input input-md input-white input-round no-b w-2"
v-model="folder_spaces_search" v-on:change="search_spaces">
</label>
<button class="btn btn-stroke-darken btn-md btn-round" v-if="!user.confirmed_at" v-on:click="confirm_again()">
<span v-if="!account_confirmed_sent">[[ __('email_unconfirmed') ]]</span>
<span v-if="account_confirmed_sent">[[ __('confirmation_sent') ]]</span>
</button>
<div class="dropdown top right light" v-bind:class="{open: active_dropdown=='account'}"> <div class="dropdown top right light" v-bind:class="{open: active_dropdown=='account'}">
<button <button
class="profile-avatar btn btn-md btn-icon btn-darken btn-round" class="profile-avatar btn btn-md btn-icon btn-dark btn-round"
v-bind:style="background_image_style([user.avatar_thumb_uri])" v-bind:style="background_image_style([user.avatar_thumb_uri])"
v-bind:class="{'has-avatar-image':!!user.avatar_thumb_uri}" v-on:click="show_account();"> v-bind:class="{'has-avatar-image':!!user.avatar_thumb_uri}" v-on:click="show_account();">
<span class="icon icon-user" v-if="logged_in && !user.avatar_thumb_uri"></span></button> <span class="icon icon-user" v-if="logged_in && !user.avatar_thumb_uri"></span></button>
@ -76,13 +70,6 @@
</a> </a>
</li> </li>
<li v-on:click="activate_modal('support')">
<span>
<span class="icon icon-sm icon-info"></span>
<span>[[ __('support') ]]</span>
</span>
</li>
<li v-on:click="logout()"> <li v-on:click="logout()">
<span> <span>
<span class="icon icon-sm icon-logout"></span> <span class="icon icon-sm icon-logout"></span>
@ -94,12 +81,12 @@
</div> </div>
<div class="btn-group dark round" id="meta-toggle" style="margin-right:10px"> <!--div class="btn-group dark round" id="meta-toggle" style="margin-right:10px">
<button class="btn btn-md btn-transparent btn-icon btn-icon" v-on:click="toggle_meta()"> <button class="btn btn-md btn-transparent btn-icon btn-icon" v-on:click="toggle_meta()">
<span class="jewel" style="color: white; background-color: red" v-if="meta_unseen>0">{{meta_unseen}}</span> <span class="jewel" style="color: white; background-color: red" v-if="meta_unseen>0">{{meta_unseen}}</span>
<span class="icon icon-menu"></span> <span class="icon icon-menu"></span>
</button> </button>
</div> </div-->
</div> </div>
</header> </header>
@ -111,10 +98,8 @@
<div id="folder-breadcrumb"> <div id="folder-breadcrumb">
<a v-for="item in active_space_path" type="button" class="btn btn-sm btn-transparent" href="/{{item.space_type}}s/{{item._id}}" v-sd-droppable="handle_folder_drop;item"> <span v-for="item in active_space_path" class="btn btn-sm btn-transparent" v-sd-droppable="handle_folder_drop;item">
<span>{{item.name}}</span> <a href="/{{item.space_type}}s/{{item._id}}">{{item.name}}</a>&nbsp; â–¶</span>
<span class="seperator">/</span>
</a>
<a v-if="(active_space_role != 'admin')" type="button" class="btn btn-sm btn-transparent"> <a v-if="(active_space_role != 'admin')" type="button" class="btn btn-sm btn-transparent">
<span>{{active_folder.name}}</span> <span>{{active_folder.name}}</span>
@ -128,12 +113,10 @@
<ul class="select-list"> <ul class="select-list">
<li><span class="tile-rename" v-on:click="rename_folder(active_folder)">[[__("rename")]]</span></li> <li><span class="tile-rename" v-on:click="rename_folder(active_folder)">[[__("rename")]]</span></li>
<li v-if="active_space_role == 'admin'"><span class="tile-share" v-on:click="activate_access()">[[__("share")]]</span></li> <li v-if="active_space_role == 'admin'"><span class="tile-share" v-on:click="activate_access()">[[__("share")]]</span></li>
<li><a v-on:click=" open_url('[[config.endpoint]]/api/spaces/'+active_folder._id+'/list')" target="_blank">[[__("list")]]</a></li>
</ul> </ul>
</div> </div>
</div> </div>
<div v-if="active_folder._id == user.home_folder_id"> <div v-if="active_folder._id == user.home_folder_id">
<span>[[ __('home') ]]</span> <span>[[ __('home') ]]</span>
</div> </div>
@ -146,7 +129,6 @@
</div> </div>
</div> </div>
<div id="folder-empty" v-if="folder_spaces_filter"> <div id="folder-empty" v-if="folder_spaces_filter">
<div v-if="active_profile_spaces | empty?"> <div v-if="active_profile_spaces | empty?">
<p><b>"{{folder_spaces_filter}}"</b> <br/>[[ __('search_no_results') ]]</p> <p><b>"{{folder_spaces_filter}}"</b> <br/>[[ __('search_no_results') ]]</p>
@ -174,7 +156,6 @@
<div class="dropdown-menu" role="menu"> <div class="dropdown-menu" role="menu">
<ul class="select-list"> <ul class="select-list">
<li v-on:click="duplicate_space(item)"><span><span class="icon icon-sm icon-duplicate"></span>[[ __('duplicate') ]]</span></li>
<li v-on:click="rename_space(item)"><span><span class="icon icon-sm icon-tag"></span>[[ __('rename') ]]</span></li> <li v-on:click="rename_space(item)"><span><span class="icon icon-sm icon-tag"></span>[[ __('rename') ]]</span></li>
<li v-on:click="delete_space(item)"><span><span class="icon icon-sm icon-trash"></span>[[ __('delete') ]]</span></li> <li v-on:click="delete_space(item)"><span><span class="icon icon-sm icon-trash"></span>[[ __('delete') ]]</span></li>
</ul> </ul>

View File

@ -1,17 +1,11 @@
<header id="landing-header" class="header" v-cloak v-if="(active_view == 'login' || active_view == 'signup' || active_view == 'password-reset' || active_view == 'password-confirm')"> <header id="landing-header" class="header" v-cloak v-if="(active_view == 'login' || active_view == 'signup' || active_view == 'password-reset' || active_view == 'password-confirm')">
<div class="header-left"> <div class="header-left">
<a class="btn btn-transparent btn-nude" href="/"><img src="/images/sd5-logo.svg" width="190"></a> <a class="btn btn-transparent btn-nude" href="/"><img src="/images/sd6-logo-black.svg" width="190"></a>
</div> </div>
<div class="header-right pull-right"> <div class="header-right pull-right">
<span class="btn-group dark round"> <a v-if="active_view != 'login'" class="btn btn-md btn-dark btn-round" href="/login">[[__("login")]]</a>
{% if (locale != "de") %}<a href="/t/de?r={{active_view}}" class="btn btn-transparent btn-md">Deutsch</a>{% endif %} <a v-if="active_view != 'signup'" class="btn btn-md btn-dark btn-round" href="/signup">[[__("signup")]]</a>
{% if (locale != "en") %}<a href="/t/en?r={{active_view}}" class="btn btn-transparent btn-md">English</a>{% endif %}
{% if (locale != "fr") %}<a href="/t/fr?r={{active_view}}" class="btn btn-transparent btn-md">Français</a>{% endif %}
</span>
<a class="btn btn-md btn-dark btn-round" href="/login">[[__("login")]]</a>
<a class="btn btn-md btn-blue btn-round" href="/signup">[[__("signup")]]</a>
</div> </div>
</header> </header>
@ -23,10 +17,7 @@
<div id="login" v-bind:class="{active : active_view == 'login'}"> <div id="login" v-bind:class="{active : active_view == 'login'}">
<div class="content"> <div class="content">
<form v-on:submit="login_submit(user_forms_email, login_password, $event)"> <form v-on:submit="login_submit(user_forms_email, login_password, $event)">
<h3>Login</h3>
<span class="btn btn-xs btn-darken pull-right" v-on:click="login_google();">[[__("login_google")]]</span>
<h4>[[__("login")]]</h4>
<div class="tight"> <div class="tight">
<div class="form-group"> <div class="form-group">
@ -37,16 +28,15 @@
</div> </div>
</div> </div>
<button type="submit" class="btn btn-primary btn-block"> <button type="submit" class="btn btn-dark btn-block">
<span v-show="!loading_user">[[__("login")]]</span> <span v-show="!loading_user">Login</span>
<span v-show="loading_user">[[__("logging_in")]]</span> <span v-show="loading_user">Logging in…</span>
</button> </button>
<div class="center alert alert-danger" v-if="login_error">{{login_error}}</div> <div class="center alert alert-danger" v-if="login_error">{{login_error}}</div>
<div class="pull-right"> <div style="margin-top:2em">
<a class="btn btn-xs btn-darken" href="/signup">[[__("signup")]]</a>&nbsp; <a href="/password-reset">Forgot Password</a>
<a class="btn btn-xs btn-darken" href="/password-reset">[[__("reset_password")]]</a>
</div> </div>
</form> </form>
</div> </div>
@ -54,23 +44,12 @@
<div id="signup" v-bind:class="{active : active_view == 'signup'}"> <div id="signup" v-bind:class="{active : active_view == 'signup'}">
<div class="content"> <div class="content">
<form v-on:submit="signup_submit($event, user_forms_name, user_forms_email, signup_password, signup_password_confirmation)"> <form v-on:submit="signup_submit($event, user_forms_name, user_forms_email, signup_password, signup_password_confirmation, signup_invite_code)">
<span class="btn btn-xs btn-darken pull-right" v-on:click="login_google();">[[__("login_google")]]</span>
<h4>[[__("signup")]]</h4> <h4>[[__("signup")]]</h4>
<div class="tight"> <div class="tight">
<div class="form-group"> <div class="form-group">
<input class="input" type="text" id="user-name" v-model="user_forms_name" placeholder="[[__("name")]]" v-focus autofocus> <input class="input" type="email" required id="user-email" v-model="user_forms_email" placeholder="[[__("email")]]" autofocus v-focus>
</div>
</div>
<div class="tight">
<div class="form-group">
<input class="input" type="email" required id="user-email" v-model="user_forms_email" placeholder="[[__("email")]]">
</div> </div>
<div class="form-group"> <div class="form-group">
@ -78,21 +57,33 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<input class="input" id="user-password-confirmation" required type="password" v-model="signup_password_confirmation" placeholder="[[__("password_confirmation")]]"> <input class="input" id="user-password-confirmation" required type="password" v-model="signup_password_confirmation" placeholder="Repeat Password">
</div> </div>
</div> </div>
<div style="margin-top: -7px; margin-bottom: 7px;"><small>By signing up you agree to our <a href="/terms" target="_blank">TOS</a> and <a href="/privacy" target="_blank">Privacy Policy.</a></small><br/> <div class="tight">
<div class="form-group">
<input class="input" type="text" id="user-name" v-model="user_forms_name" placeholder="Pick a username">
</div>
<!--
Disabled textbox so people don't have to input beta code when registering.
Remember to also set invite_code to an empty string ("") in /config/default.conf!
<div class="form-group">
<input class="input" id="invite-code" required type="text" v-model="signup_invite_code" placeholder="Beta Invite Code">
</div>-->
</div> </div>
<button class="btn btn-primary btn-block"> <!--div style="margin-top: -7px; margin-bottom: 7px;"><small>By signing up you agree to our <a href="/terms" target="_blank">TOS</a> and <a href="/privacy" target="_blank">Privacy Policy.</a></small><br/>
</div-->
<button class="btn btn-dark btn-block">
<span v-if="!creating_user">[[__("signup")]]</span> <span v-if="!creating_user">[[__("signup")]]</span>
<span v-if="creating_user">[[__("signing_up")]]</span> <span v-if="creating_user">[[__("signing_up")]]</span>
</button> </button>
<div class="center alert alert-danger" style="width:100%;" v-if="signup_error">{{signup_error}}</div> <div class="center alert alert-danger" style="width:100%;" v-if="signup_error">{{signup_error}}</div>
<a class="btn btn-link btn-block" href="/login" style="margin-top: 20px">[[__("login")]]</a>
</form> </form>
</div> </div>
</div> </div>
@ -107,12 +98,12 @@
</div> </div>
</div> </div>
<div class="text-center alert alert-danger" v-if="password_reset_error">{{password_reset_error}}</div> <div class="text-center alert alert-danger" v-if="password_reset_error">{{password_reset_error}}</div>
<button class="btn btn-primary btn-block" v-on:click="password_reset_submit($event, reset_email)">[[__("reset_password")]]</button> <button class="btn btn-dark btn-block" v-on:click="password_reset_submit($event, reset_email)">[[__("reset_password")]]</button>
</form> </form>
</div> </div>
<div class="content" v-if="password_reset_send==true"> <div class="content" v-if="password_reset_send==true">
<h4>[[__("password_confirmation")]]</h4> <h4>Reset Password</h4>
[[__("password_check_inbox")]] Please check your email inbox.
</div> </div>
</div> </div>
@ -123,16 +114,16 @@
<div class="tight"> <div class="tight">
<div class="form-group"> <div class="form-group">
<input class="input" id="user-password" type="password" v-model="signup_password" placeholder="[[__("password")]]"> <input class="input" id="user-password" type="password" v-model="signup_password" placeholder="New Password">
</div> </div>
<div class="form-group"> <div class="form-group">
<input class="input" id="user-password" type="password" v-model="signup_password_confirmation" placeholder="[[__("password_confirmation")]]"> <input class="input" id="user-password" type="password" v-model="signup_password_confirmation" placeholder="Repeat Password">
</div> </div>
</div> </div>
<div class="text-center alert alert-danger" v-if="password_reset_confirm_error">{{password_reset_confirm_error}}</div> <div class="text-center alert alert-danger" v-if="password_reset_confirm_error">{{password_reset_confirm_error}}</div>
<button class="btn btn-primary btn-block" v-on:click="password_reset_confirm($event, signup_password, signup_password_confirmation)">[[__("save")]]</button> <button class="btn btn-dark btn-block" v-on:click="password_reset_confirm($event, signup_password, signup_password_confirmation)">[[__("save")]]</button>
</form> </form>
</div> </div>
</div> </div>

View File

@ -3,7 +3,7 @@
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content" style="width:760px"> <div class="modal-content" style="width:760px">
<div class="modal-header" style="padding-bottom:0"> <div class="modal-header" style="padding-bottom:0">
<h3 class="text-left"><span class="icon icon-share icon-sm"></span> [[__("share")]]: {{access_settings_space.name}}</h3> <h3 class="text-left">[[__("share")]]: {{access_settings_space.name}}</h3>
<button type="button" class="btn btn-icon btn-light btn-round close" v-on:click=" close_modal()"> <button type="button" class="btn btn-icon btn-light btn-round close" v-on:click=" close_modal()">
<span class="icon icon-cross-1"></span> <span class="icon icon-cross-1"></span>
</button> </button>
@ -68,7 +68,7 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<button class="btn btn-primary btn-md btn-round" v-on:click="invite_member(access_settings_space, invite_email, invite_message, invite_member_role)"> [[__("invite")]] </button> <button class="btn btn-primary btn-md" v-on:click="invite_member(access_settings_space, invite_email, invite_message, invite_member_role)"> [[__("invite")]] </button>
</div> </div>
</div> </div>
@ -85,14 +85,19 @@
</tr> </tr>
<tr v-for="member in access_settings_memberships" v-bind:class="member.state"> <tr v-for="member in access_settings_memberships" v-bind:class="member.state">
<td> <td>
<span class="editor-avatar btn btn-xs btn-round btn-icon" v-if="member.user">{{member.user.initials}}</span> <span class="editor-avatar btn btn-md btn-dark btn-icon btn-round"
<span class="editor-avatar btn btn-xs btn-round btn-icon icon-hourglass" v-if="!member.user"></span> v-if="member.user"
v-bind:style="background_image_style([member.user.avatar_thumb_uri])"
v-bind:class="{'has-avatar-image':!!member.user.avatar_thumb_uri}">
<span class="icon icon-user" v-if="!member.user.avatar_thumb_uri"></span>
</span>
<span class="editor-avatar btn btn-md btn-round btn-icon icon-hourglass" v-if="!member.user"></span>
</td> </td>
<td> <td>
<span class="editor-email" v-if="member.state == 'active'">{{member.user.email}}</span> <span class="editor-name" v-if="member.user && member.state == 'active'">{{member.user.nickname}}</span>
<span class="editor-email" v-if="member.state == 'pending'">{{member.email_invited}}</span> <span class="editor-email" v-if="!member.user || member.state == 'pending'">(pending)</span>
<span class="editor-name" v-if="member.state == 'active'">{{member.user.nickname}}</span> <span class="editor-email" v-if="member.user && member.state == 'active'">({{member.user.email}})</span>
<span class="editor-email" v-if="member.state == 'pending'">(pending)</span> <span class="editor-email" v-if="!member.user || member.state == 'pending'">({{member.email_invited}})</span>
</td> </td>
<td> <td>
<div class="form-group"> <div class="form-group">
@ -113,7 +118,7 @@
</p> </p>
<div class="form-group" style="padding-top: 40px"> <div class="form-group" style="padding-top: 40px">
<button class="btn btn-primary btn-md btn-round" v-on:click="close_modal();"> [[__("ok")]] </button> <button class="btn btn-primary btn-md" v-on:click="close_modal();"> [[__("ok")]] </button>
</div> </div>
</div> </div>

View File

@ -1,131 +1,3 @@
<!-- FIXME modal -->
<div class="modal" v-if="(duplicate_folders.length > 0)" v-cloak>
<div class="modal-wrapper">
<div class="modal-dialog">
<button type="button" class="btn btn-icon btn-light btn-round close" v-on:click="duplicate_folders = []">
<span class="icon icon-cross-1"></span>
</button>
<div class="modal-content">
<div class="modal-body labels-inline">
<div class="modal-section">
<div class="form-group">
<label>
[[__("duplicate_destination")]]
</label>
</div>
<div class="form-group">
<select v-on:change="duplicate_folder_id=$event.target.value">
<option v-for="f in duplicate_folders" value="{{f._id}}">{{f.name}}</option>
</select>
</div>
<div class="form-group">
<button class="btn btn-md btn-round btn-primary" v-on:click="duplicate_folder_confirm(); ">
<span class="icon-label">[[__("ok")]]</span>
</button>
<button class="btn btn-md btn-round btn-darken pull-right" v-on:click="duplicate_folders = [];">
<span class="icon-label">[[__("cancel")]]</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-cloak class="header-left" v-show="active_space_loaded">
<div class="btn-group dark">
<div class="pull-left">
<a
class="btn btn-stroke-darken btn-md btn-round btn-icon"
title="[[__("home")]]" href="/spaces"
v-if="(logged_in && !embedded && !active_space.parent_space_id && !guest_nickname)">
<span class="icon icon-home"></span>
</a>
<a
class="btn btn-stroke-darken btn-md btn-round btn-icon"
title="[[__("parent_folder")]]"
href="/folders/{{active_space.parent_space_id}}"
v-if="(active_space.parent_space_id && !guest_nickname)">
<span class="icon icon-arrow-left-light"></span>
</a>
<input class="input input-md input-transparent w-auto"
id="space-title"
v-model="active_space.name" name="title" v-on:keydown="save_space_keydown($event)"
v-if="space_editing_title && logged_in" style="padding-right:0" v-focus>
<span class="input input-md input-transparent w-auto"
v-if="!space_editing_title && logged_in"
v-on:click="edit_space_title()">{{active_space.name}}</span>
<span v-if="!logged_in" class="btn btn-dark btn-round btn-md">{{active_space.name}}</span>
<button class="btn btn-md btn-transparent btn-icon" v-if="space_editing_title" v-on:click="save_space_keydown()">
<span class="icon icon-check"></span>
</button>
<div class="dropdown top left light" v-bind:class="{open: active_dropdown=='space'}">
<button class="btn btn-md btn-icon btn-dark" v-on:click="activate_dropdown('space')">
<span class="icon icon-triangle-down"></span></button>
<div class="dropdown-menu" role="menu">
<ul class="select-list">
<li v-on:click="activate_access()" v-if="logged_in">
<span>
<span class="icon icon-sm icon-share"></span>
<span>[[ __('share') ]]</span>
</span>
</li>
<li v-on:click="edit_space_title()" v-if="logged_in">
<span>
<span class="icon icon-sm icon-tag"></span>
<span>[[ __('rename') ]]</span>
</span>
</li>
<li v-on:click="duplicate_space_into_folder()" v-if="logged_in">
<span>
<span class="icon icon-sm icon-duplicate"></span>
<span>[[ __('duplicate') ]]</span>
</span>
</li>
<li v-on:click="download_space()">
<span>
<span class="icon icon-sm icon-download"></span>
<span>[[ __('download_space') ]]</span>
</span>
</li>
<li v-on:click="activate_modal('support')" v-if="logged_in">
<span>
<span class="icon icon-sm icon-info"></span>
<span>[[ __('support') ]]</span>
</span>
</li>
</ul>
</div>
</div>
</div>
</div>
<span class="btn btn-red btn-md" id="offline-indicator" v-bind:class="{offline: was_offline}" v-on:click="show_offline_help()">[[__("offline")]]</span>
</div>
<div v-cloak class="header-right" v-if="active_space_loaded"> <div v-cloak class="header-right" v-if="active_space_loaded">
<span v-for="active_user in active_space_users" > <span v-for="active_user in active_space_users" >
@ -141,13 +13,7 @@
</button> </button>
</span> </span>
<div class="btn-group dark" v-if="active_space_role!='viewer'"> <div class="btn-group light round" v-if="zones.length">
<button class="btn btn-md btn-transparent btn-icon" title="Start Presentation (others follow what you see)" v-on:click="toggle_present_mode()" v-bind:class="{open:present_mode}">
<span class="icon icon-presentation"></span>
</button>
</div>
<div class="btn-group dark round" v-if="zones.length">
<button class="btn btn-md btn-transparent btn-icon" v-on:click="go_to_previous_zone()" title="[[__("Previous Zone")]]"> <button class="btn btn-md btn-transparent btn-icon" v-on:click="go_to_previous_zone()" title="[[__("Previous Zone")]]">
<span class="icon icon-triangle-4-left"></span> <span class="icon icon-triangle-4-left"></span>
</button> </button>
@ -159,16 +25,12 @@
</button> </button>
</div> </div>
<!--button class="btn btn-md btn-dark btn-round btn-icon" v-on:click="download_space()" title="[[__("download_space")]]"> <!--div class="btn-group light" id="meta-toggle" style="margin-right:10px">
<span class="icon icon-download"></span>
</button-->
<div class="btn-group dark" id="meta-toggle" style="margin-right:10px">
<button class="btn btn-md btn-transparent btn-icon" v-on:click="toggle_meta()" title="[[__("chat")]]"> <button class="btn btn-md btn-transparent btn-icon" v-on:click="toggle_meta()" title="[[__("chat")]]">
<span class="jewel" style="color: white; background-color: red" v-if="meta_unseen>0">{{meta_unseen}}</span> <span class="jewel" style="color: white; background-color: red" v-if="meta_unseen>0">{{meta_unseen}}</span>
<span class="icon icon-messages"></span> <span class="icon icon-messages"></span>
</button> </button>
</div> </div-->
</div> </div>
{% include "./tool/toolbar-elements.html" %} {% include "./tool/toolbar-elements.html" %}
@ -181,9 +43,8 @@
<div class="space-empty" v-cloak v-if="active_view == 'space' && !present_mode && active_space_artifacts.length == 0"> <div class="space-empty" v-cloak v-if="active_view == 'space' && !present_mode && active_space_artifacts.length == 0">
<div class="table-fake"> <div class="table-fake">
<div class="cell"> <div class="cell">
<p>Click anywhere to add content.<br> <p>Use the toolbar to add content.<br>
You can also drop images, sounds and video<br> You can also drop images or sound and video files.</p>
or use copy and paste.</p>
</div> </div>
</div> </div>
</div> </div>
@ -206,7 +67,7 @@
<div id="space-clipboard" style="position:fixed;top:0;left:0;z-index:0;opacity:0;background-color:white"><textarea v-model="selected_artifacts_json" cols="2" rows="2" id="clipboard-ta" class="mousetrap"></textarea></div> <div id="space-clipboard" style="position:fixed;top:0;left:0;z-index:0;opacity:0;background-color:white"><textarea v-model="selected_artifacts_json" cols="2" rows="2" id="clipboard-ta" class="mousetrap"></textarea></div>
<div class="space-bounds" v-bind:style="{width: active_space.width*bounds_zoom + 'px', height: active_space.height*bounds_zoom + 'px', 'background-color': active_space.background_color}"></div> <div class="space-bounds" v-bind:style="{width: (active_space.width*bounds_zoom+1000) + 'px', height: (active_space.height*bounds_zoom+1000) + 'px', 'background-color': active_space.background_color}"></div>
<div class="wrapper" <div class="wrapper"
v-bind:style="{ v-bind:style="{
@ -244,7 +105,6 @@
<a class="link btn btn-round btn-primary btn-sm" v-if="a.view.link" v-bind:href="a.view.link" target="_blank">{{a.view.link_caption}}</a> <a class="link btn btn-round btn-primary btn-sm" v-if="a.view.link" v-bind:href="a.view.link" target="_blank">{{a.view.link_caption}}</a>
</span> </span>
<div class="btn btn-xs btn-icon btn-round btn-primary edit" v-show="editing_artifact_id!=a._id && is_selected(a)" v-on:touchstart="delayed_edit_artifact($event)"><span class="icon icon-pencil" v-on:click="toggle_selected_artifact_editing(true)" v-on:"touchstart:delayed_edit_artifact($event)"></span></div>
<input v-show="is_selected(a)" type="text" id="ios-focuser-{{a._id}}" class="ios-focuser"> <input v-show="is_selected(a)" type="text" id="ios-focuser-{{a._id}}" class="ios-focuser">
</div> </div>
@ -266,7 +126,6 @@
<a class="link btn btn-round btn-primary btn-sm" v-if="a.view.link" v-bind:href="a.view.link" target="_blank">{{a.view.link_caption}}</a> <a class="link btn btn-round btn-primary btn-sm" v-if="a.view.link" v-bind:href="a.view.link" target="_blank">{{a.view.link_caption}}</a>
</span> </span>
<div class="btn btn-xs btn-icon btn-round btn-primary edit" v-show="editing_artifact_id!=a._id && is_selected(a)" v-on:touchstart="delayed_edit_artifact($event)"><span class="icon icon-pencil" v-on:click="toggle_selected_artifact_editing(true)" v-on:"touchstart:delayed_edit_artifact($event)"></span></div>
<input v-show="is_selected(a)" type="text" id="ios-focuser-{{a._id}}" class="ios-focuser"> <input v-show="is_selected(a)" type="text" id="ios-focuser-{{a._id}}" class="ios-focuser">
</div> </div>
@ -286,11 +145,6 @@
<source v-for="rep in a.payload_alternatives" v-bind:src="rep.payload_uri" v-bind:type="rep.mime" /> <source v-for="rep in a.payload_alternatives" v-bind:src="rep.payload_uri" v-bind:type="rep.mime" />
</video> </video>
<a class="btn btn-md btn-icon btn-round btn-primary edit"
v-show="a.mime == 'application/pdf'"
v-bind:href="a.payload_uri" target="_blank"
><span class="icon icon-link"></span></a>
<span v-if="a.view.link.length>0" class="link-wrapper"> <span v-if="a.view.link.length>0" class="link-wrapper">
<a class="link btn btn-round btn-primary btn-sm" v-if="a.view.link" v-bind:href="a.view.link" target="_blank">{{a.view.link_caption}}</a> <a class="link btn btn-round btn-primary btn-sm" v-if="a.view.link" v-bind:href="a.view.link" target="_blank">{{a.view.link_caption}}</a>
</span> </span>
@ -463,7 +317,7 @@
</div> </div>
<div v-if="active_space_loaded" v-cloak> <div v-if="active_space_loaded" v-cloak>
<div id="minimap" <!--div id="minimap"
v-bind:style="{width: ''+(active_space.width/minimap_scale)+'px', height: ''+(active_space.height/minimap_scale)+'px', bottom: '66px', right: '20px'}" v-bind:style="{width: ''+(active_space.width/minimap_scale)+'px', height: ''+(active_space.height/minimap_scale)+'px', bottom: '66px', right: '20px'}"
v-if="active_space" v-if="active_space"
v-on:mousedown="handle_minimap_mousedown($event)" v-on:mousedown="handle_minimap_mousedown($event)"
@ -475,17 +329,16 @@
v-on:mouseup="handle_minimap_mouseup($event)"> v-on:mouseup="handle_minimap_mouseup($event)">
<div v-for="a in active_space_artifacts" v-bind:style="{left: ''+(a.x/minimap_scale)+ 'px', top: ''+(a.y/minimap_scale) + 'px', width: ''+(a.w/minimap_scale)+ 'px', height: ''+(a.h/minimap_scale) + 'px'}"></div> <div v-for="a in active_space_artifacts" v-bind:style="{left: ''+(a.x/minimap_scale)+ 'px', top: ''+(a.y/minimap_scale) + 'px', width: ''+(a.w/minimap_scale)+ 'px', height: ''+(a.h/minimap_scale) + 'px'}"></div>
<div class="window" v-bind:style="{left: ''+(scroll_left/minimap_scale) + 'px', top: ''+(scroll_top/minimap_scale)+ 'px', width: ''+(window_width/minimap_scale)+ 'px', height: ''+(window_height/minimap_scale) + 'px'}"></div> <div class="window" v-bind:style="{left: ''+(scroll_left/minimap_scale) + 'px', top: ''+(scroll_top/minimap_scale)+ 'px', width: ''+(window_width/minimap_scale)+ 'px', height: ''+(window_height/minimap_scale) + 'px'}"></div>
</div-->
</div> <div class="btn-group light zoom-bar">
<button class="btn btn-icon btn-md btn-white" v-on:click="zoom_in()">
<div class="btn-group dark" style="position:absolute;bottom:20px;right:20px;">
<button class="btn btn-icon btn-md btn-transparent" v-on:click="zoom_in()">
<span class="icon icon-plus"></span> <span class="icon icon-plus"></span>
</button> </button>
<button class="btn btn-md btn-transparent no-p" v-on:click="zoom_to_original()"> <button class="btn btn-md btn-white no-p" v-on:click="zoom_to_original()">
{{viewport_zoom_percent}}% {{viewport_zoom_percent}}%
</button> </button>
<button class="btn btn-icon btn-md btn-transparent" v-on:click="zoom_out()"> <button class="btn btn-icon btn-md btn-white" v-on:click="zoom_out()">
<span class="icon icon-minus"></span> <span class="icon icon-minus"></span>
</button> </button>
</div> </div>

View File

@ -126,20 +126,12 @@
<label class="label label-sm text-center">[[__("font_size")]]</label> <label class="label label-sm text-center">[[__("font_size")]]</label>
<input class="input no-b no-p text-center text-large" spellcheck="false" type="text" pattern="[0-9]" maxlength="64" v-model="active_style.font_size"> <input class="input no-b no-p text-center text-large" spellcheck="false" type="text" pattern="[0-9]" maxlength="64" v-model="active_style.font_size">
<!--button tabindex="-1" class="input-drag btn btn-transparent btn-icon" style="cursor: ns-resize;" v-sd-fader="true" sd-fader-var-y="active_style.font_size" sd-fader-min-y="8" sd-fader-max-y="400" sd-fader-sens="0.2"> <button tabindex="-1" class="input-drag btn btn-transparent btn-icon" style="cursor: ns-resize;" v-sd-fader="true" sd-fader-var-y="active_style.font_size" sd-fader-min-y="30" sd-fader-max-y="200" sd-fader-sens="5">
<span class="icon icon-triangles-vertical"></span> <span class="icon icon-triangles-vertical"></span>
</button--> </button>
<span class="input-unit">px</span> <span class="input-unit">px</span>
</div> </div>
<div class="form-group no-m">
<span class="font-size-swatches" v-show="opened_dialog=='color-text'">
<button class="btn btn-sm" v-on:click="apply_font_size(64)" style="font-size:32px">Big</button>
<button class="btn btn-sm" v-on:click="apply_font_size(32)" style="font-size:24px">Medium</button>
<button class="btn btn-sm" v-on:click="apply_font_size(18)" style="font-size:14px">Small</button>
</span>
</div>
<!--div class="form-group no-m"> <!--div class="form-group no-m">
<label class="label label-sm text-center">[[__("line_height")]]</label> <label class="label label-sm text-center">[[__("line_height")]]</label>
<input disabled class="input no-b no-p text-center text-large" spellcheck="false" type="text" pattern="[0-9\.]" maxlength="64" v-model="active_style.line_height"> <input disabled class="input no-b no-p text-center text-large" spellcheck="false" type="text" pattern="[0-9\.]" maxlength="64" v-model="active_style.line_height">

View File

@ -1,5 +1,5 @@
<div id="layout" class="relative"> <div id="layout" class="relative">
<div class="dialog-section no-p-b"> <div class="dialog-section">
<div class="btn-group"> <div class="btn-group">
<button class="btn btn-transparent btn-icon" v-on:click="layout_stack_top()"> <button class="btn btn-transparent btn-icon" v-on:click="layout_stack_top()">
<span class="icon icon-stack-3d-top"></span> <span class="icon icon-stack-3d-top"></span>

View File

@ -1,7 +1,8 @@
<h4 class="dialog-title">[[__("tool_shape")]]</h4> <h4 class="dialog-title">[[__("tool_shape")]]</h4>
<div id="shapes"> <div id="shapes">
<div class="dialog-section no-p-h" style="white-space: normal;"> <div class="dialog-section">
<div class="btn-group">
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('ellipse',$event)"> <button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('ellipse',$event)">
<span class="icon icon-shape-circle"></span> <span class="icon icon-shape-circle"></span>
<span class="icon-label">[[__("tool_circle")]]</span> <span class="icon-label">[[__("tool_circle")]]</span>
@ -17,11 +18,6 @@
<span class="icon-label">[[__("tool_square")]]</span> <span class="icon-label">[[__("tool_square")]]</span>
</button> </button>
<!--button class="btn btn-icon-labeled btn-transparent rot45" v-on:click="add_shape('diamond',$event)">
<span class="icon icon-shape-square"></span>
<span class="icon-label">[[__("tool_diamond")]]</span>
</button-->
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('speechbubble',$event)"> <button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('speechbubble',$event)">
<span class="icon icon-shape-bubble"></span> <span class="icon icon-shape-bubble"></span>
<span class="icon-label">[[__("tool_bubble")]]</span> <span class="icon-label">[[__("tool_bubble")]]</span>
@ -47,23 +43,6 @@
<span class="icon-label">[[__("tool_heart")]]</span> <span class="icon-label">[[__("tool_heart")]]</span>
</button> </button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="start_drawing_arrow()"> </div>
<span class="icon icon-tool-arrow"></span>
<span class="icon-label">[[__("tool_arrow")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="start_drawing_line()">
<span class="icon icon-tool-line"></span>
<span class="icon-label">[[__("tool_line")]]</span>
</button>
</div> </div>
</div> </div>
<!--
<div class="dialog-section no-p">
<div class="btn-cluster">
<button class="btn btn-transparent text-center"> Upload </button>
<button class="btn btn-transparent text-center" v-on:click="start_drawing_scribble()"> Draw </button>
</div>
</div>
-->

View File

@ -24,6 +24,6 @@
<!--button class="btn btn-transparent btn-icon-labeled" v-on:click="apply_formatting($event,'insertUnorderedList')"> <!--button class="btn btn-transparent btn-icon-labeled" v-on:click="apply_formatting($event,'insertUnorderedList')">
<span class="icon icon-text-list-bullet"></span> <span class="icon icon-text-list-bullet"></span>
<span class="icon-label">Bullets</span> <span class="icon-label">Bullets</span>
</button--> </button--!>
</div> </div>
</div> </div>

View File

@ -1,21 +1,24 @@
<div class="toolbar toolbar-elements" v-bind:class="{in:toolbar_artifacts_in,out:!toolbar_artifacts_in}" v-show="!is_active_space_role('viewer') && active_space_loaded" v-bind:style="{left:toolbar_artifacts_x,top:toolbar_artifacts_y}"> <div class="toolbar toolbar-elements" v-bind:class="{in:toolbar_artifacts_in,out:!toolbar_artifacts_in}" v-show="!is_active_space_role('viewer') && active_space_loaded">
<div class="btn-group dark"> <div class="btn-group light vertical">
<!--div id="search-dialog" class="dropdown bottom light center static" v-bind:class="{open:opened_dialog=='search'}"> <a class="btn btn-icon btn-transparent"
<div class="btn-collapse in"> title="[[__("home")]]" href="/spaces"
<button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='search'}" v-on:click="open_dialog('search')" > v-if="(!active_space.parent_space_id && !guest_nickname)">
<span class="icon icon-search"></span> <span class="icon icon-folder"></span>
<span class="icon-label">[[__("tool_search")]]</span> </a>
</button>
</div>
<div class="dialog dialog-search"> <a class="btn btn-icon btn-dark"
xinclude "./search.html" title="Parent Folder"
</div> href="/folders/{{active_space.parent_space_id}}"
</div--> v-if="(active_space.parent_space_id && !guest_nickname)">
<div class="dropdown bottom light center" v-bind:class="{open:opened_dialog=='shapes'}"> <span class="icon icon-sd6 icon-svg"></span>
</a>
<button class="btn btn-divider"></button>
<div class="dropdown top left light" v-bind:class="{open:opened_dialog=='shapes'}">
<div class="btn-collapse in"> <div class="btn-collapse in">
<button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='shapes'}" v-on:click="open_dialog('shapes')"> <button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='shapes'}" v-on:click="open_dialog('shapes')">
<span class="icon icon-shapes"></span> <span class="icon icon-shapes"></span>
@ -28,30 +31,35 @@
</div> </div>
</div> </div>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="start_drawing_scribble()"> <button class="btn btn-icon-labeled btn-transparent" v-on:click="start_drawing_scribble()" v-bind:class="{active:active_tool=='scribble'}">
<span class="icon icon-tool-scribble"></span> <span class="icon icon-tool-scribble"></span>
<span class="icon-label">[[__("tool_scribble")]]</span> <span class="icon-label">[[__("tool_scribble")]]</span>
</button> </button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="start_drawing_arrow()" v-bind:class="{active:active_tool=='arrow'}">
<span class="icon icon-tool-arrow"></span>
<span class="icon-label">[[__("tool_arrow")]]</span>
</button>
<div class="dropdown bottom light center"> <div class="dropdown bottom light center">
<div class="btn-collapse in"> <div class="btn-collapse in">
<button class="btn btn-transparent btn-icon-labeled" v-on:click="handle_insert_image_url()" v-on:touchstart="handle_insert_image_url()"> <button class="btn btn-transparent btn-icon-labeled" v-on:click="handle_insert_image_url()" v-on:touchstart="handle_insert_image_url()">
<span class="icon icon-upload"></span> <span class="icon icon-upload"></span>
<span class="icon-label" >[[__("tool_upload")]]</span> <span class="icon-label" >Media</span>
</button> </button>
</div> </div>
</div> </div>
<div class="dropdown bottom light center"> <div class="dropdown bottom light center">
<div class="btn-collapse in"> <div class="btn-collapse in">
<button class="btn btn-transparent btn-icon-labeled" v-on:click=" add_artifact(active_space, 'text', null, $event)"> <button class="btn btn-transparent btn-icon-labeled" v-on:click="active_tool='note'" v-bind:class="{active:active_tool=='note'}">
<span class="icon icon-tool-text"></span> <span class="icon icon-tool-text"></span>
<span class="icon-label">[[__("tool_text")]]</span> <span class="icon-label">[[__("tool_text")]]</span>
</button> </button>
</div> </div>
</div> </div>
<div class="dropdown bottom light center"> <div class="dropdown top left light">
<div class="btn-collapse"> <div class="btn-collapse">
<button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='image'}" v-on:click="open_dialog('image')"> <button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='image'}" v-on:click="open_dialog('image')">
<span class="icon icon-picture"></span> <span class="icon icon-picture"></span>
@ -64,7 +72,7 @@
</div> </div>
</div> </div>
<div class="dropdown bottom light center" v-bind:class="{open:opened_dialog=='zones'}"> <div class="dropdown top left light" v-bind:class="{open:opened_dialog=='zones'}">
<div class="btn-collapse in"> <div class="btn-collapse in">
<button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='zones'}" v-on:click="open_dialog('zones')"> <button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='zones'}" v-on:click="open_dialog('zones')">
<span class="icon icon-zone"></span> <span class="icon icon-zone"></span>
@ -79,7 +87,7 @@
<button class="btn btn-divider" v-show="logged_in"></button> <button class="btn btn-divider" v-show="logged_in"></button>
<div class="dropdown bottom light center" v-show="logged_in" v-bind:class="{open:opened_dialog=='background'}"> <div class="dropdown top left center" v-show="logged_in" v-bind:class="{open:opened_dialog=='background'}">
<div class="btn-collapse in"> <div class="btn-collapse in">
<button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='background'}" v-on:click="open_dialog('background')"> <button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='background'}" v-on:click="open_dialog('background')">
<span class="letter">bg</span> <span class="letter">bg</span>
@ -92,6 +100,25 @@
</div> </div>
</div> </div>
<button class="btn btn-transparent btn-icon-labeled"
v-if="active_space_role=='admin'"
v-on:click="activate_access()">
<span class="icon icon-share"></span>
<span class="icon-label">[[ __('share') ]]</span>
</button>
<!--
<li v-on:click="edit_space_title()" v-if="logged_in">
<span>
<span class="icon icon-sm icon-tag"></span>
<span>[[ __('rename') ]]</span>
</span>
</li>
-->
<button class="btn btn-transparent btn-icon-labeled" title="Start Presentation (others follow what you see)" v-on:click="toggle_present_mode()" v-bind:class="{open:present_mode}">
<span class="icon icon-presentation"></span>
<span class="icon-label">[[ __('present') ]]</span>
</button>
</div> </div>
</div> </div>

View File

@ -1,42 +1,38 @@
<div class="toolbar toolbar-properties" v-cloak v-show="active_space_loaded && !is_active_space_role('viewer')" v-bind:class="{in:toolbar_props_in,out:!toolbar_props_in}" v-bind:style="{left:toolbar_props_x,top:toolbar_props_y}" v-if="active_space_loaded"> <div class="toolbar toolbar-properties" v-cloak v-show="active_space_loaded && !is_active_space_role('viewer')" v-bind:class="{in:toolbar_props_in,out:!toolbar_props_in}" v-if="active_space_loaded">
<div class="btn-group dark"> <div class="btn-group light vertical">
<div class="dropdown topleft light" <div class="dropdown top right light"
v-bind:class="{open : opened_dialog.match('color') , v-bind:class="{open : opened_dialog.match('color') ,
'option-1':opened_dialog=='color-fill' , 'option-1':opened_dialog=='color-fill' ,
'option-2':opened_dialog=='color-stroke' , 'option-2':opened_dialog=='color-stroke' ,
'option-3':opened_dialog=='color-text', 'option-3':opened_dialog=='color-text',
'options-3':selection_metrics.contains_text}"> 'options-3':selection_metrics.contains_text}">
<label <button
class="dropdown-toggle btn btn-icon btn-transparent no-r-r" class="dropdown-toggle btn btn-icon btn-transparent"
v-on:click="open_dialog('color-fill')" v-on:click="open_dialog('color-fill')"
v-bind:class="{open:opened_dialog=='color-fill'}"> v-bind:class="{open:opened_dialog=='color-fill'}">
<span class="icon icon-tool-fill icon-sm"></span> <span class="icon icon-tool-fill icon-sm"></span>
<span class="jewel" v-bind:style="{'background-color':active_style.fill_color}"></span> <span class="jewel" v-bind:style="{'background-color':active_style.fill_color}"></span>
</label> </button><br>
<label <button
class="dropdown-toggle btn btn-icon btn-transparent no-r" class="dropdown-toggle btn btn-icon btn-transparent"
v-bind:class="{open:opened_dialog=='color-stroke'}" v-bind:class="{open:opened_dialog=='color-stroke'}"
v-on:click="open_dialog('color-stroke')"> v-on:click="open_dialog('color-stroke')">
<span class="icon icon-tool-stroke icon-sm"></span> <span class="icon icon-tool-stroke icon-sm"></span>
<span class="jewel jewel-stroke" v-bind:style="{'border-color':active_style.stroke_color}"></span> <span class="jewel jewel-stroke" v-bind:style="{'border-color':active_style.stroke_color}"></span>
</label> </button><br>
<label <button
class="dropdown-toggle btn btn-icon btn-transparent no-r-l" class="dropdown-toggle btn btn-icon btn-transparent"
v-on:click="open_dialog('color-text')" v-on:click="open_dialog('color-text')"
v-bind:class="{open:opened_dialog=='color-text'}"> v-bind:class="{open:opened_dialog=='color-text'}">
<span class="icon icon-tool-text icon-sm"></span> <span class="icon icon-tool-text icon-sm"></span>
<span class="jewel" v-bind:style="{'border-color':active_style.text_color}">{{active_style.font_size}}</span> <span class="jewel" v-bind:style="{'border-color':active_style.text_color}">{{active_style.font_size}}</span>
</label> </button>
<div class="dialog"> <div class="dialog">
{% include "./color.html" %} {% include "./color.html" %}
</div> </div>
</div> </div>
</div>
<div class="btn-group dark">
<!-- <button class="btn btn-transparent btn-icon-labeled"> <!-- <button class="btn btn-transparent btn-icon-labeled">
<span class="icon icon-tool-eyedrop"></span> <span class="icon icon-tool-eyedrop"></span>
<span class="icon-label">Eyedrop</span> <span class="icon-label">Eyedrop</span>
@ -45,11 +41,11 @@
<button class="btn btn-divider"></button> <button class="btn btn-divider"></button>
--> -->
<div class="dropdown top light center" v-bind:class="{open:opened_dialog=='text-styles'}"> <div class="dropdown top light right" v-bind:class="{open:opened_dialog=='text-styles'}">
<div class="btn-collapse in"> <div class="btn-collapse in">
<button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('text-styles')" v-bind:class="{open : opened_dialog=='text-styles'}"> <button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('text-styles')" v-bind:class="{open : opened_dialog=='text-styles'}">
<span class="icon icon-text-styles"></span> <span class="icon icon-text-styles"></span>
<span class="icon-label">styles</span> <span class="icon-label">Styles</span>
</button> </button>
</div> </div>
@ -58,21 +54,7 @@
</div> </div>
</div> </div>
<div class="dropdown top light center" v-bind:class="{open:opened_dialog=='filter'}"> <div class="dropdown top light right" v-bind:class="{open:opened_dialog=='type-align'}">
<div class="btn-collapse" v-bind:class="{in:selection_metrics.contains_images}">
<!-- <div class="btn-collapse" v-bind:class="in:selection_metrics.count>0"> -->
<button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('filter')" v-bind:class="{open : opened_dialog=='filter'}">
<span class="icon icon-contrast"></span>
<span class="icon-label">[[__("tool_filter")]]</span>
</button>
</div>
<div class="dialog">
{% include "./filter.html" %}
</div>
</div>
<div class="dropdown top light center" v-bind:class="{open:opened_dialog=='type-align'}">
<div class="btn-collapse" v-bind:class="{in:selection_metrics.contains_text}"> <div class="btn-collapse" v-bind:class="{in:selection_metrics.contains_text}">
<button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('type-align')" v-bind:class="{open : opened_dialog=='type-align'}"> <button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('type-align')" v-bind:class="{open : opened_dialog=='type-align'}">
<span class="icon icon-text-align-left-alt"></span> <span class="icon icon-text-align-left-alt"></span>
@ -85,9 +67,9 @@
</div> </div>
</div> </div>
<div class="dropdown top light center" v-bind:class="{open:opened_dialog=='layout'}"> <div class="dropdown top light right" v-bind:class="{open:opened_dialog=='layout'}">
<div class="btn-collapse" v-bind:class="{in:selection_metrics.count>0}"> <div class="btn-collapse in">
<button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('layout')" v-bind:class="{open : opened_dialog=='layout'}"> <button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('layout')" v-bind:class="{open : opened_dialog=='layout'}">
<span class="icon icon-cluster"></span> <span class="icon icon-cluster"></span>
<span class="icon-label">[[__("tool_layout")]]</span> <span class="icon-label">[[__("tool_layout")]]</span>
@ -99,7 +81,7 @@
</div> </div>
</div> </div>
<div class="dropdown top light center" v-bind:class="{open:opened_dialog=='text-settings'}"> <div class="dropdown top light right" v-bind:class="{open:opened_dialog=='text-settings'}">
<div class="btn-collapse in"> <div class="btn-collapse in">
<button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('text-settings')" v-bind:class="{open : opened_dialog=='text-settings'}"> <button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('text-settings')" v-bind:class="{open : opened_dialog=='text-settings'}">
@ -115,7 +97,7 @@
<button class="btn btn-divider"></button> <button class="btn btn-divider"></button>
<div class="dropdown top light center" v-bind:class="{open:opened_dialog=='object-options'}"> <div class="dropdown top light right" v-bind:class="{open:opened_dialog=='object-options'}">
<button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('object-options')" v-bind:class="{open : opened_dialog=='object-options'}"> <button class="btn btn-transparent btn-icon-labeled" v-on:click="open_dialog('object-options')" v-bind:class="{open : opened_dialog=='object-options'}">
<span class="icon icon-cogwheel"></span> <span class="icon icon-cogwheel"></span>
<span class="icon-label">[[__("more")]]</span> <span class="icon-label">[[__("more")]]</span>

View File

@ -2,11 +2,11 @@
<div id="zones" style="max-height:500px;overflow-y:scroll"> <div id="zones" style="max-height:500px;overflow-y:scroll">
<div class="dialog-section"> <div class="dialog-section">
<p v-if="zones.length<2"> <!--p v-if="zones.length<2">
Turn your Space into a zooming presentation by placing some Zones and switch through them when presenting. Turn your Space into a zooming presentation by placing some Zones and switch through them when presenting.
</p> </p-->
<button v-on:click="add_zone()" class="btn btn-sm btn-primary">[[__("add_zone")]]</button> <button v-on:click="add_zone()" class="btn btn-sm btn-dark">[[__("add_zone")]]</button>
</div> </div>
<div class="dialog-section no-p" v-for="z in zones | orderBy 'order'" style="white-space: nowrap;text-align:left;cursor:pointer" v-on:click="zoom_to_zone(z)"> <div class="dialog-section no-p" v-for="z in zones | orderBy 'order'" style="white-space: nowrap;text-align:left;cursor:pointer" v-on:click="zoom_to_zone(z)">

View File

@ -9,14 +9,11 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<link href="[[ '/images/favicon.png' | cdn ]]" rel="icon" type="image/x-icon" /> <link href="[[ '/images/favicon.png' | cdn ]]" rel="icon" type="image/x-icon" />
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,700,600,800,300|Montserrat:400,700|EB+Garamond|Vollkorn|Lato|Roboto|Source+Code+Pro|Ubuntu|Raleway|Playfair+Display|Crimson+Text' rel='stylesheet' type='text/css'> <link href='https://fonts.googleapis.com/css?family=Inter' rel='stylesheet' type='text/css'>
<link type="text/css" rel="stylesheet" href="https://fast.fonts.net/cssapi/ee1a3484-4d98-4f9f-9f55-020a7b37f3c5.css"/>
<link rel="stylesheet" href="[[ '/stylesheets/style.css' | cdn ]]"> <link rel="stylesheet" href="[[ '/stylesheets/style.css' | cdn ]]">
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script> <script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twemoji/1.3.2/twemoji.min.js"></script>
<script> <script>
window.socket_auth = '[[socket_auth]]'; window.socket_auth = '[[socket_auth]]';
window.browser_lang = '[[locale]]'; window.browser_lang = '[[locale]]';
@ -31,53 +28,45 @@
}; };
</script> </script>
{% if process.env.NODE_ENV == "production" %} <script src="/javascripts/jquery-2.1.4.min.js"></script>
<script src="[[ '/javascripts/spacedeck.js' | cdn ]]"></script> <script src="/javascripts/i18next-1.11.2.js"></script>
{% else %} <script src="/javascripts/clipboard.js"></script>
<script minify src="/javascripts/jquery-2.1.4.min.js"></script>
<script minify src="/javascripts/i18next-1.11.2.js"></script>
<script minify src="/javascripts/clipboard.js"></script>
<script minify src="/javascripts/lodash.compat.js"></script> <script src="/javascripts/lodash.compat.js"></script>
<script minify src="/javascripts/fastclick.js"></script> <script src="/javascripts/fastclick.js"></script>
<script minify src="/javascripts/vue.js"></script> <script src="/javascripts/vue.js"></script>
<script minify src="/javascripts/moment.js"></script> <script src="/javascripts/moment.js"></script>
<script minify src="/javascripts/medium.patched.js"></script> <script src="/javascripts/medium.patched.js"></script>
<script minify src="/javascripts/route-recognizer.js"></script> <script src="/javascripts/route-recognizer.js"></script>
<script minify src="/javascripts/backend.js"></script> <script src="/javascripts/backend.js"></script>
<script minify src="/javascripts/link_parser.js"></script> <script src="/javascripts/link_parser.js"></script>
<script minify src="/javascripts/vector-render.js"></script> <script src="/javascripts/vector-render.js"></script>
<script minify src="/javascripts/mousetrap.js"></script> <script src="/javascripts/mousetrap.js"></script>
<script minify src="/javascripts/smoke.js"></script> <script src="/javascripts/smoke.js"></script>
<script minify src="/javascripts/helper.js"></script> <script src="/javascripts/helper.js"></script>
<script minify src="/javascripts/packer.growing.js"></script> <script src="/javascripts/packer.growing.js"></script>
<script minify src="/javascripts/spacedeck_routes.js"></script> <script src="/javascripts/spacedeck_routes.js"></script>
<script minify src="/javascripts/spacedeck_formatting.js"></script> <script src="/javascripts/spacedeck_formatting.js"></script>
<script minify src="/javascripts/spacedeck_sections.js"></script> <script src="/javascripts/spacedeck_sections.js"></script>
<script minify src="/javascripts/spacedeck_spaces.js"></script> <script src="/javascripts/spacedeck_spaces.js"></script>
<script minify src="/javascripts/spacedeck_teams.js"></script> <script src="/javascripts/spacedeck_teams.js"></script>
<script minify src="/javascripts/spacedeck_board_artifacts.js"></script> <script src="/javascripts/spacedeck_board_artifacts.js"></script>
<script minify src="/javascripts/spacedeck_users.js"></script> <script src="/javascripts/spacedeck_users.js"></script>
<script minify src="/javascripts/spacedeck_account.js"></script> <script src="/javascripts/spacedeck_account.js"></script>
<script minify src="/javascripts/spacedeck_modals.js"></script> <script src="/javascripts/spacedeck_modals.js"></script>
<script minify src="/javascripts/spacedeck_avatars.js"></script> <script src="/javascripts/spacedeck_avatars.js"></script>
<script minify src="/javascripts/spacedeck_websockets.js"></script> <script src="/javascripts/spacedeck_websockets.js"></script>
<script minify src="/javascripts/spacedeck_whiteboard.js"></script> <script src="/javascripts/spacedeck_whiteboard.js"></script>
<script minify src="/javascripts/spacedeck_directives.js"></script> <script src="/javascripts/spacedeck_directives.js"></script>
<script minify src="/javascripts/spacedeck_vue.js"></script> <script src="/javascripts/spacedeck_vue.js"></script>
{% endif %}
<script>if (window.module) module = window.module;</script> <script>if (window.module) module = window.module;</script>
</head> </head>
<body id="main" v-bind:class="{'present-mode':present_mode,'modal-open':active_modal}" v-on:click="handle_body_click($event)"> <body id="main" v-bind:class="{'present-mode':present_mode,'modal-open':active_modal}" v-on:click="handle_body_click($event)">
<!--[if lt IE 10]>
<p class="browsehappy">You are using an <strong>outdated</strong> version of Internet Explorer. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
{% include "./partials/login.html" %} {% include "./partials/login.html" %}
{% include "./partials/space.html" %} {% include "./partials/space.html" %}
{% include "./partials/folders.html" %} {% include "./partials/folders.html" %}
@ -88,10 +77,6 @@
{% include "./partials/modal/access.html" %} {% include "./partials/modal/access.html" %}
{% include "./partials/modal/folder-settings.html" %} {% include "./partials/modal/folder-settings.html" %}
{% include "./partials/modal/support.html" %}
{% include "./partials/modal/login.html" %}
{% include "./partials/modal/pdfoptions.html" %}
</body> </body>
<script type="text/javascript"> <script type="text/javascript">