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,17 +1,17 @@
# Windows Electron Build # Windows Electron Build
sqlite3 needs to be manually built for the iojs version that electron ships. The following code assumes electron v1.8.4. sqlite3 needs to be manually built for the iojs version that electron ships. The following code assumes electron v1.8.4.
```` ````
npm -g install windows-build-tools npm -g install windows-build-tools
cd node_modules\sqlite3 cd node_modules\sqlite3
node-gyp configure --module_name=node_sqlite3 --module_path=../lib/binding/electron-v1.8-win32-x64 node-gyp configure --module_name=node_sqlite3 --module_path=../lib/binding/electron-v1.8-win32-x64
node-gyp rebuild --target=1.8.4 --target_platform=win32 --dist-url=https://atom.io/download/atom-shell --module_name=node_sqlite3 --module_path=../lib/binding/electron-v1.8-win32-x64 --msvs_version=2015 node-gyp rebuild --target=1.8.4 --target_platform=win32 --dist-url=https://atom.io/download/atom-shell --module_name=node_sqlite3 --module_path=../lib/binding/electron-v1.8-win32-x64 --msvs_version=2015
cd ..\.. cd ..\..
```` ````

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,9 +1127,12 @@ 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) {
this._last_bounds_width = this.active_space.width; this._last_bounds_width = this.active_space.width;
@ -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) {
@ -1788,9 +1793,7 @@ var SpacedeckSections = {
if (this.active_space_role=="viewer") { if (this.active_space_role=="viewer") {
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,18 +2500,9 @@ 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") { this.create_artifact_via_upload(null, file, true);
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);
}
} }
} }
}, },
@ -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") { this.create_artifact_via_upload(evt, file, (files.length>1));
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));
}
} }
} 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,8 +202,10 @@ function setup_whiteboard_directives() {
}, },
handle_mouse_down_space: function(evt) { handle_mouse_down_space: function(evt) {
if (evt.target != evt.currentTarget && !_.include(["wrapper"],evt.target.className)) return; if (evt.which != 2) {
if (evt.target != evt.currentTarget && !_.include(["wrapper"],evt.target.className)) return;
}
var $scope = this.vm.$root; var $scope = this.vm.$root;
$scope.opened_dialog="none"; $scope.opened_dialog="none";
@ -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,11 +104,18 @@ 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) {
var attrs = req.body; // is the user trying to change their own role?
mem.role = attrs.role; if (mem.user_id == req.user._id) {
mem.save(function() { res.status(400).json({
res.status(201).json(mem); "error": "Cannot change your own role."
}); });
} else {
var attrs = req.body;
mem.role = attrs.role;
mem.save(function() {
res.status(201).json(mem);
});
}
} }
}); });
} else { } else {
@ -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.findOne({ where: { db.Membership.count({ where: {
_id: req.params.membership_id space_id: req.space._id,
}}).then(function(mem) { role: "admin"
mem.destroy().then(function() { }}).then(function(adminCount) {
res.sendStatus(204); db.Membership.findOne({ where: {
}); _id: req.params.membership_id
}}).then(function(mem) {
// deleting an admin? need at least 1
if (mem.role != "admin" || adminCount > 1) {
mem.destroy().then(function() {
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,74 +48,12 @@ 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"))
return false; return false;
@ -143,7 +81,8 @@ 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: {
_id: req.query.parent_space_id _id: req.query.parent_space_id
@ -176,14 +115,17 @@ 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 => {
if (!memberships) memberships = []; if (!memberships) memberships = [];
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.
if(err)res.status(400).json(err); // all objects (indirectly) belonging to the user have
else res.sendStatus(204); // to be walked and deleted first.
});
} else { user.destroy().then(err => {
res.bad_request("password_incorrect"); if(err)res.status(400).json(err);
}
} else {
user.remove((err) => {
if (err) res.status(400).json(err);
else res.sendStatus(204); else res.sendStatus(204);
}); });
} else {
res.bad_request("Please enter the correct current password.");
} }
} else {
res.status(403).json({error: "Access denied."});
} }
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(201);
res.sendStatus(400);
} else {
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');
}); });
@ -132,15 +124,15 @@ router.get('/s/:token', (req, res) => {
db.Space.findOne({where: {"edit_hash": token}}).then(function (space) { db.Space.findOne({where: {"edit_hash": token}}).then(function (space) {
if (space) { if (space) {
if (req.accepts('text/html')){ if (req.accepts('text/html')){
res.redirect("/spaces/"+space._id + "?spaceAuth=" + token); res.redirect("/spaces/"+space._id + "?spaceAuth=" + token);
} else { } else {
res.status(200).json(space); res.status(200).json(space);
} }
} else { } else {
if (req.accepts('text/html')) { if (req.accepts('text/html')) {
res.status(404).render('not_found', { title: 'Page Not Found.' }); res.status(404).render('not_found', { title: 'Page Not Found.' });
} else { } else {
res.status(404).json({}); res.status(404).json({});
} }
} }
}); });

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;
} }
} }
@ -1159,4 +1099,4 @@
margin: 4px; margin: 4px;
z-index: 100; z-index: 100;
border-radius: 50px; border-radius: 50px;
} }

View File

@ -96,41 +96,37 @@
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;
border-bottom-left-radius: $radius*3; border-bottom-left-radius: $radius*3;
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;
border-top-left-radius: $radius*3; border-top-left-radius: $radius*3;
@ -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;
} }
} }
} }
@ -121,6 +118,10 @@ $predelay: 0;
display: inline-block; display: inline-block;
position: relative; position: relative;
vertical-align: middle; vertical-align: middle;
a {
text-decoration: none;
}
&.dropdown-block { &.dropdown-block {
display: block; display: block;
@ -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,33 +247,37 @@ $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;
}
}
&.top.right { &.top.right {
> .dialog, > .dialog,
> .dropdown-menu { > .dropdown-menu {
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;
@ -139,4 +138,4 @@
display: inline-block !important; display: inline-block !important;
width: auto !important; width: auto !important;
padding-right: 15px !important; padding-right: 15px !important;
} }

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,16 +333,15 @@
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,15 +428,8 @@
border-style: solid; border-style: solid;
border-width: 10px; border-width: 10px;
border-color: transparent; border-color: transparent;
-webkit-background-clip: padding-box; background-clip: padding-box;
-moz-background-clip: padding-box; transition: all .05s ease-in-out;
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;
} }
div { div {

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: 20px;
padding-right: 10px; 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; section {
padding-top: 40px; margin-left: 300px;
padding-bottom: 40px;
} > * {
max-width: 600px;
.landing-plans-wrapper { }
background-image: url("../images/sd5-hero2-compressed.jpg");
background-size: cover;
background-position: center;
padding-top: 80px;
padding-bottom: 100px;
}
.landing-box {
width: 800px;
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 {
margin-right: 20px;
}
} }
@media screen and (max-width: 1000px) {
#landing {
section {
margin-left: 20px;
margin-right: 20px;
}
}
.footer {
margin-left: 20px;
margin-right: 20px;
}
@media screen and (min-width: 801px) { .header-right {
.plans-table-mobile { right: auto;
display: none; padding-left: 10px;
} padding-right: 20px;
} padding-top: 80px;
}
@media screen and (max-width: 800px) {
#folder-wrapper {
ul.lead.lead-xl, p.lead.lead-xl, ol.lead.lead-xl { padding-top: 128px;
font-size: 20px !important; }
}
.header-right {
> span:first-child {
display: none;
}
}
.plans-table {
display: none;
}
.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,9 +59,9 @@
} }
.close { .close {
position: fixed; margin-left: 44px;
margin: 44px 44px; margin-bottom: 44px;
.icon {display: block; } .icon {display: block; }
} }
figure { figure {
@ -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;
// }
}

14
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.
// //
@ -420,4 +408,4 @@ table {
td, td,
th { th {
padding: 0; padding: 0;
} }

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;
@ -154,4 +142,4 @@
} }
} }
} }
} }

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,10 +33,7 @@
@include translate3d(0, 0, 0); @include translate3d(0, 0, 0);
// @include backface-visibility(hidden); // @include backface-visibility(hidden);
-webkit-perspective: 1000; perspective: 1000;
-moz-perspective: 1000;
-ms-perspective: 1000;
perspective: 1000;
.panel-toggles { .panel-toggles {
@include transition( all 0.15s ease-in-out); @include transition( all 0.15s ease-in-out);
@ -99,10 +96,7 @@
display: table-cell; display: table-cell;
vertical-align: middle; vertical-align: middle;
// @include backface-visibility(hidden); // @include backface-visibility(hidden);
-webkit-perspective: 1000; perspective: 1000;
-moz-perspective: 1000;
-ms-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;
@ -48,4 +44,4 @@ $gutter-c: 40px;
$gutter-d: 60px; $gutter-d: 60px;
$gutter-e: 80px; $gutter-e: 80px;
$folder-gutter: 20px; $folder-gutter: 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>
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.
<p class="lead"> </p>
<a href="/login" class="btn btn-primary btn-block btn-xl">[[__("login")]]</a> <p>
</p> Spacedeck is not meant for creating polished designs, but it is a good fit for:
</p>
<p class="lead"> <ul>
[[__("landing_claim")]] <li>Moodboards</li>
</p> <li>Collages</li>
<li>Teaching (Virtual Blackboards)</li>
<p class="lead"> <li>Shared Whiteboards</li>
[[__("landing_example")]] <li>Design Thinking</li>
</p> </ul>
<img src="/images/sd6-screenshot.png" alt="Screenshot of Spacedeck 6.0">
<ul> <p>
<li class="lead"> 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>.
[[__("landing_features_1") | safe ]] </p>
</li> </section>
<li class="lead">
[[__("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>
</div>
</div>
</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,38 +132,36 @@
</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">
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="label">[[__("terminate_reason")]]</label> <label class="label">[[__("terminate_reason")]]</label>
<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 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 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 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> </div-->
<button class="btn btn-primary btn-block"> <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" >
@ -140,14 +12,8 @@
</button> </button>
</span> </span>
<div class="btn-group dark" v-if="active_space_role!='viewer'">
<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"> <div class="btn-group light 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>
@ -158,17 +24,13 @@
<span class="icon icon-triangle-4-right"></span> <span class="icon icon-triangle-4-right"></span>
</button> </button>
</div> </div>
<!--button class="btn btn-md btn-dark btn-round btn-icon" v-on:click="download_space()" title="[[__("download_space")]]">
<span class="icon icon-download"></span>
</button-->
<div class="btn-group dark" id="meta-toggle" style="margin-right:10px"> <!--div class="btn-group light" 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,19 +126,11 @@
<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>

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,69 +1,48 @@
<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">
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('ellipse',$event)"> <div class="btn-group">
<span class="icon icon-shape-circle"></span> <button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('ellipse',$event)">
<span class="icon-label">[[__("tool_circle")]]</span> <span class="icon icon-shape-circle"></span>
</button> <span class="icon-label">[[__("tool_circle")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('hexagon',$event)">
<span class="icon icon-shape-hexagon"></span>
<span class="icon-label">[[__("tool_hexagon")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('square',$event)">
<span class="icon icon-shape-square"></span>
<span class="icon-label">[[__("tool_square")]]</span>
</button>
<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-label">[[__("tool_bubble")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('cloud',$event)">
<span class="icon icon-shape-cloud"></span>
<span class="icon-label">[[__("tool_cloud")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('burst',$event)">
<span class="icon icon-shape-burst"></span>
<span class="icon-label">[[__("tool_burst")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('star',$event)">
<span class="icon icon-shape-star"></span>
<span class="icon-label">[[__("tool_star")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('heart',$event)">
<span class="icon icon-shape-heart"></span>
<span class="icon-label">[[__("tool_heart")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('hexagon',$event)"> </div>
<span class="icon icon-shape-hexagon"></span>
<span class="icon-label">[[__("tool_hexagon")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('square',$event)">
<span class="icon icon-shape-square"></span>
<span class="icon-label">[[__("tool_square")]]</span>
</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)">
<span class="icon icon-shape-bubble"></span>
<span class="icon-label">[[__("tool_bubble")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('cloud',$event)">
<span class="icon icon-shape-cloud"></span>
<span class="icon-label">[[__("tool_cloud")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('burst',$event)">
<span class="icon icon-shape-burst"></span>
<span class="icon-label">[[__("tool_burst")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('star',$event)">
<span class="icon icon-shape-star"></span>
<span class="icon-label">[[__("tool_star")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="add_shape('heart',$event)">
<span class="icon icon-shape-heart"></span>
<span class="icon-label">[[__("tool_heart")]]</span>
</button>
<button class="btn btn-icon-labeled btn-transparent" v-on:click="start_drawing_arrow()">
<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 light vertical">
<a class="btn btn-icon btn-transparent"
title="[[__("home")]]" href="/spaces"
v-if="(!active_space.parent_space_id && !guest_nickname)">
<span class="icon icon-folder"></span>
</a>
<a class="btn btn-icon btn-dark"
title="Parent Folder"
href="/folders/{{active_space.parent_space_id}}"
v-if="(active_space.parent_space_id && !guest_nickname)">
<span class="icon icon-sd6 icon-svg"></span>
</a>
<div class="btn-group dark"> <button class="btn btn-divider"></button>
<!--div id="search-dialog" class="dropdown bottom light center static" v-bind:class="{open:opened_dialog=='search'}"> <div class="dropdown top left light" v-bind:class="{open:opened_dialog=='shapes'}">
<div class="btn-collapse in">
<button class="btn btn-transparent btn-icon-labeled" v-bind:class="{open:opened_dialog=='search'}" v-on:click="open_dialog('search')" >
<span class="icon icon-search"></span>
<span class="icon-label">[[__("tool_search")]]</span>
</button>
</div>
<div class="dialog dialog-search">
xinclude "./search.html"
</div>
</div-->
<div class="dropdown bottom light center" 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,13 +81,13 @@
</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'}">
<span class="icon icon-text-typeface"></span> <span class="icon icon-text-typeface"></span>
<span class="icon-label">Font</span> <span class="icon-label">Font</span>
</button> </button>
</div> </div>
<div class="dialog"> <div class="dialog">
@ -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,13 +9,10 @@
<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]]';
@ -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">