This commit is contained in:
dm
2021-04-07 02:46:09 +02:00
29 changed files with 8094 additions and 223 deletions

19
.vscode/launch.json vendored
View File

@@ -4,11 +4,26 @@
{ {
"type": "node", "type": "node",
"request": "launch", "request": "launch",
"name": "Nodemon", "name": "Launch debug",
"runtimeExecutable": "${workspaceFolder}/node_modules/nodemon/bin/nodemon.js", "runtimeExecutable": "${workspaceFolder}/node_modules/nodemon/bin/nodemon.js",
"skipFiles": ["<node_internals>/**"], "skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/spacedeck.js", "program": "${workspaceFolder}/spacedeck.js",
"cwd": "${workspaceFolder}" "cwd": "${workspaceFolder}",
"env": {
"NODE_APP_INSTANCE" :"dev"
}
},
{
"type": "node",
"request": "launch",
"name": "Launch ldap",
"runtimeExecutable": "${workspaceFolder}/node_modules/nodemon/bin/nodemon.js",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/spacedeck.js",
"cwd": "${workspaceFolder}",
"env": {
"NODE_APP_INSTANCE" :"ldap"
}
} }
] ]
} }

8
CHANGELOG.md Normal file
View File

@@ -0,0 +1,8 @@
# Changelog
## [X.X.X] - 2021-03-23
### Changes
- Replaced phantomjs with puppeteer #169
- Create Hungarian language pack #174

View File

@@ -21,6 +21,20 @@ RUN cd audiowaveform/build/ && cmake -D ENABLE_TESTS=0 -D BUILD_STATIC=1 ..
RUN cd audiowaveform/build/ && make RUN cd audiowaveform/build/ && make
RUN cd audiowaveform/build/ && make install RUN cd audiowaveform/build/ && make install
# install chromium
RUN apk add --no-cache \
chromium \
nss \
freetype \
freetype-dev \
harfbuzz \
ca-certificates \
ttf-freefont
# Tell Puppeteer to skip installing Chrome. We'll be using the installed package.
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true \
PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser
# install other requirements # install other requirements
RUN apk add graphicsmagick ffmpeg ffmpeg-dev ghostscript RUN apk add graphicsmagick ffmpeg ffmpeg-dev ghostscript

View File

@@ -12,7 +12,7 @@ We appreciate filed issues, pull requests and general discussion.
# Features # Features
- Create virtual whiteboards called *Spaces* with virtually unlimited size - Create virtual whiteboards called _Spaces_ with virtually unlimited size
- Drag & drop images, videos and audio from your computer or the web - Drag & drop images, videos and audio from your computer or the web
- 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
@@ -37,7 +37,7 @@ Spacedeck requires:
To run Spacedeck, you only need Node.JS 10.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) after cloning the repository:
npm install npm install
@@ -45,7 +45,6 @@ To install all node dependencies, run (do this once):
See [config/default.json](config/default.json). Set `storage_local_path` for a local sqlite database or `storage_region`, `storage_bucket`, `storage_cdn` and `storage_endpoint` for AWS S3. `mail_provider` may be one of `console` or `smtp`. Also, omit a trailing `/` for the `endpoint`. See [config/default.json](config/default.json). Set `storage_local_path` for a local sqlite database or `storage_region`, `storage_bucket`, `storage_cdn` and `storage_endpoint` for AWS S3. `mail_provider` may be one of `console` or `smtp`. Also, omit a trailing `/` for the `endpoint`.
## Disable DB logs ## Disable DB logs
```json ```json
@@ -61,7 +60,8 @@ Add a custom array of swatches to your config/default.json.
**You should include the swatch transparent (rgba(0,0,0,0)) so users can remove the color applied.** **You should include the swatch transparent (rgba(0,0,0,0)) so users can remove the color applied.**
## Configure default colors ## Configure default colors
You can define text, stroke and fill color in your config/default.json.
You can define text, stroke and fill color in your config/default.json.
**You also should include the default colors in your custom swatches palette.** **You also should include the default colors in your custom swatches palette.**
@@ -107,8 +107,8 @@ For advanced media conversion:
# Data Storage # Data Storage
By default, media files are uploaded to the ```storage``` folder. By default, media files are uploaded to the `storage` folder.
The database is stored in ```database.sqlite``` by default. The database is stored in `database.sqlite` by default.
# Other databases (Not officially supported) # Other databases (Not officially supported)
@@ -129,16 +129,12 @@ Adapt the other values as needed
"storage_password": "password", "storage_password": "password",
``` ```
# Run with Docker # Run with Docker
- configure `config/default.json` - configure `config/default.json`
- configure `volumes` section inside `docker-compose.yml` - adapt your `docker-compose.yml` if needed.
- point to `database.sqlite` on the host system - start the container with `docker-compose up`
- `touch database.sqlite` if it not exists (use `-d` for background process and `--build` for rebuilding the image)
- point to `storage/` on the host system
- `mkdir storage/` if it not exists
- start the container with `sudo docker-compose up -f docker-compose.yml -d --build`
# Hacking # Hacking
@@ -155,7 +151,7 @@ Spacedeck Open source code is released under the GNU Affero General Public Licen
Spacedeck Open - Web-based Collaborative Whiteboard For Rich Media Spacedeck Open - Web-based Collaborative Whiteboard For Rich Media
Copyright (C) 2011-2018 Lukas F. Hartmann, Martin Güther Copyright (C) 2011-2018 Lukas F. Hartmann, Martin Güther
Icons and original CSS design copyright by Thomas Helbig Icons and original CSS design copyright by Thomas Helbig
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the published by the Free Software Foundation, either version 3 of the

View File

@@ -25,7 +25,7 @@
"redis_mock": true, "redis_mock": true,
"redis_host": "localhost", "redis_host": "localhost",
"phantom_api_secret": "very_secret_phantom_password", "export_api_secret": "very_secret_export_password",
"mail_provider": "smtp", "mail_provider": "smtp",
"mail_smtp_host": "your.smtp.host", "mail_smtp_host": "your.smtp.host",

View File

@@ -1,5 +1,4 @@
version: "2.0" version: "2.0"
services: services:
spacedeck: spacedeck:
build: . build: .
@@ -7,6 +6,5 @@ services:
ports: ports:
- "9666:9666" - "9666:9666"
volumes: volumes:
- /absolute/path/to/storage:/app/storage - ./storage:/app/storage
- /absolute/path/to/database.sqlite:/app/database.sqlite - ./database.sqlite:/app/database.sqlite

View File

@@ -12,7 +12,7 @@ server {
listen 80; listen 80;
listen [::]:80; listen [::]:80;
servername spacedeck.domain.de server_name spacedeck.domain.de
return 301 https://$server_name$request_uri; return 301 https://$server_name$request_uri;
} }

58
helpers/exporter.js Normal file
View File

@@ -0,0 +1,58 @@
'use strict';
const db = require('../models/db');
const config = require('config');
const puppeteer = require('puppeteer');
const os = require('os');
module.exports = {
// type = "pdf" or "png"
takeScreenshot: function(space,type,on_success,on_error) {
var spaceId = space._id;
var space_url = config.get("endpoint")+"/api/spaces/"+spaceId+"/html";
var export_path = os.tmpdir()+"/"+spaceId+"."+type;
var timeout = 5000;
if (type=="pdf") timeout = 30000;
space_url += "?api_token="+config.get("export_api_secret");
console.log("[space-screenshot] url: "+space_url);
console.log("[space-screenshot] export_path: "+export_path);
(async () => {
let browser;
let page;
try {
browser = await puppeteer.launch(
{
headless: true,
args: ['--disable-dev-shm-usage', '--no-sandbox']
}
);
page = await browser.newPage();
page.setDefaultTimeout(timeout);
await page.setJavaScriptEnabled(false);
await page.goto(space_url, {waitUntil: 'networkidle2'});
await page.emulateMediaType('screen');
if (type=="pdf") {
let margin = 2;
await page.pdf({path: export_path, printBackground: true, width: space.width+margin+'px', height: space.height+margin+'px' });
}else{
await page.screenshot({path: export_path, printBackground: true});
}
await browser.close();
on_success(export_path);
} catch (error) {
console.error(error);
console.error("[space-screenshot] puppeteer abnormal exit for url "+space_url);
on_error();
}
})();
}
};

View File

@@ -1,70 +0,0 @@
'use strict';
const db = require('../models/db');
const config = require('config');
const phantom = require('node-phantom-simple');
const os = require('os');
module.exports = {
// type = "pdf" or "png"
takeScreenshot: function(space,type,on_success,on_error) {
var spaceId = space._id;
var space_url = config.get("endpoint")+"/api/spaces/"+spaceId+"/html";
var export_path = os.tmpdir()+"/"+spaceId+"."+type;
var timeout = 5000;
if (type=="pdf") timeout = 30000;
space_url += "?api_token="+config.get("phantom_api_secret");
console.log("[space-screenshot] url: "+space_url);
console.log("[space-screenshot] export_path: "+export_path);
var on_success_called = false;
var on_exit = function(exit_code) {
if (exit_code>0) {
console.error("phantom abnormal exit for url "+space_url);
if (!on_success_called && on_error) {
on_error();
}
}
};
phantom.create({ path: require('phantomjs-prebuilt').path }, function (err, browser) {
if (err) {
console.error(err);
} else {
return browser.createPage(function (err, page) {
console.log("page created, opening ",space_url);
if (type=="pdf") {
var psz = {
width: space.width+"px",
height: space.height+"px"
};
page.set('paperSize', psz);
}
page.set('settings.resourceTimeout',timeout);
page.set('settings.javascriptEnabled',false);
return page.open(space_url, function (err,status) {
page.render(export_path, function() {
on_success_called = true;
if (on_success) {
on_success(export_path);
}
page.close();
browser.exit();
});
});
});
}
}, {
onExit: on_exit
});
}
};

View File

@@ -320,5 +320,6 @@
"follow_present": "Folgen", "follow_present": "Folgen",
"mute_present": "Entfolgen", "mute_present": "Entfolgen",
"follow_present_help": "Wenn jemand den Space präsentiert, folgen die anderen Mitglieder automatisch der Präsentation. Mit diesem Knopf lässt sich das an- oder ausschalten.", "follow_present_help": "Wenn jemand den Space präsentiert, folgen die anderen Mitglieder automatisch der Präsentation. Mit diesem Knopf lässt sich das an- oder ausschalten.",
"media": "Media" "media": "Media",
} "tool_edit_text": "Text bearbeiten"
}

328
locales/hu.js Normal file
View File

@@ -0,0 +1,328 @@
{
"ok": "Rendben",
"cancel": "Mégse",
"close": "Bezárás",
"open": "Megnyitás",
"folder": "Mappa",
"save": "Mentés",
"saved": "Mentve",
"created": "létrehozva",
"duplicate": "Másolás",
"delete": "Törlés",
"remove": "Eltávolítás",
"set": "készlet",
"reset": "alaphelyzet",
"thanks": "Köszönöm",
"share": "Megosztás",
"signup": "Feliratkozás",
"login": "Bejelentkezés",
"logout": "Kijelentkezés",
"email": "E-mail-cím",
"password": "Jelszó",
"width": "Szélesség",
"height": "Magasság",
"nick": "Név",
"role": "Szerepkör",
"members": "Tagok",
"actions": "Műveletek",
"or": "vagy",
"you": "Ön",
"via": "ezen keresztül:",
"by": "szerző:",
"zero": "Nulla",
"page": "Oldal:",
"new": "Új",
"copy": "Másolás",
"home": "Kezdőoldal",
"owner": "Tulajdonos",
"space": "Hely",
"second": "másodperc",
"not_found": "Nem található.",
"untitled_space": "Névtelen hely",
"untitled_folder": "Névtelen mappa",
"untitled": "névtelen",
"sure": "Biztos vagy benne?",
"specify": "Kérjük, részletezze",
"confirm": "Erősítse meg a műveletet",
"error_unknown_email": "Ez az e-mail/jelszó kombináció ismeretlen.",
"error_password_confirmation": "A megadott jelszavak nem egyeznek.",
"error_domain_blocked": "Tartománya letiltva.",
"error_user_email_already_used": "Ez az e-mail cím már használatban van.",
"support": "Spacedeck támogatás",
"offline": "Kapcsolat nélküli üzemmód. Kattintson további információkért.",
"error": "Sajnálom, de valami rosszul ment. Kérjük, lépjen kapcsolatba a support@spacedeck.com-al",
"welcome": "Üdvözöljük",
"claim": "A digitális rajztáblája.",
"trynow": "Próbálja most.",
"about": "Rólunk",
"terms": "Feltételek",
"contact": "Kapcsolat",
"privacy": "Adatvédelem",
"business_adress": "Üzleti cím",
"post_adress": "Posta cím",
"phone": "Telefon",
"ceo": "Ügyvezető igazgató",
"name": "Név",
"confirm_subject": "Spacedeck e-mail megerősítés",
"confirm_body": "Köszönjük, hogy feliratkozott a Spacedeck-re.\nKérjük, hogy kattintson az alábbi linkre az e-mail cím megerősítéséhez.\n",
"confirm_action": "Erősítse meg most",
"team_invite_membership_subject": "Csapat meghívó %-s számára",
"team_invite_membership_body": "Meghívták a(z) %s oldalra a Spacedeck-en. Kattintson a következő hivatkozásra a meghívás elfogadásához.",
"team_invite_user_body": "Meghívták a(z)%s oldalra a Spacedeck-en.\nAz ideiglenes jelszó \"%s\".\n Kérjük, kattintson a következő hivatkozásra a meghívás elfogadásához.",
"team_invite_admin_body": "%s meghívást kapott a csapatodba: %s. Az ideiglenes jelszó \"%s\".",
"team_invite_membership_acction": "Elfogad",
"team_new_member_subject": "A(z) %s új csapattagja feliratkozott",
"team_new_member_body": "%s most csatlakozott a(z) %s csoporthoz a Spacedeck-en.",
"space_invite_membership_subject": "%s meghívott %s helyre",
"space_invite_membership_body": "%s meghívta, hogy csatlakozzon a(z) %s helyre a Spacedecken. Kattintson a következő linkre a meghívás elfogadásához.",
"space_invite_membership_action": "Elfogad",
"folder_invite_membership_subject": "Hely",
"folder_invite_membership_body": "Meghívták a Spacedeck csoportjába. Kérjük, hogy kattintson a következő linkre a meghívás elfogadásához.",
"folder_invite_membership_acction": "Elfogad",
"login_google": "Bejelentkezés a Google-al",
"save_changes": "Változtatások mentése",
"upgrade": "Frissítés",
"upgrade_now": "Frissítés most",
"create_space": "Hely létrehozása",
"create_folder": "Mappa létrehozása",
"email_unconfirmed": "E-mail nincs megerősítve",
"confirmation_sent": "E-mail elküldve",
"folder_filter": "Szűrő",
"sort_by": "Rendezés",
"last_modified": "Utoljára módosítva",
"last_opened": "Utoljára nyitva",
"title": "Cím",
"edit_team": "Csapat szerkesztése",
"edit_account": "Fiók szerkesztése",
"log_out": "Kijelentkezés",
"no_spaces_yet": "Isten hozta! Itt létrehozhat helyeket és mappákat a bal felső sarokban található gombokkal.",
"new_folder_title": "Új cím a mappához",
"folder_settings": "Mappa beállításai",
"upload_cover_image": "Borító kép feltöltése",
"spacedeck_pro_ad_folders": "A Spacedeck Pro segítségével korlátlan mennyiségű helyet foglalhat el a mappákban és kezelheti az egyes mappák hozzáférési vezérléseit. Szeretne többet megtudni a Pro funkcióiról?",
"spacedeck_pro_ad_versions": "A Spacedeck Pro segítségével korlátlan verziókat menthet az egyes helyekről, hogy nyomon kövesse az előrehaladást vagy biztonságban tartsa a pillanatképeket. Szeretne többet megtudni a Pro funkcióiról?",
"spacedeck_pro_ad_pdf": "A Spacedeck Pro segítségével a helyeket éles PDF-fájlokként exportálhatja archiváláshoz, postázáshoz vagy nyomtatáshoz. Szeretne többet megtudni a Pro funkcióiról?",
"spacedeck_pro_ad_zip": "A Spacedeck Pro segítségével exportálhatja a hely tartalmát ZIP-csomagként. Szeretne többet megtudni a Pro funkcióiról?",
"spacedeck_pro_ad_colors": "A Spacedeck Pro segítségével professzionális színválasztóval keverheti össze saját színeit.",
"profile_caption": "Profil",
"upload_avatar": "Avatar feltöltése",
"uploading_avatar": "Avatar feltöltése…",
"avatar_dimensions": "Ajánlott méretek: 200 × 200 képpont.",
"profile_name": "Név",
"profile_email": "E-mail cím",
"send_again": "Küldje újra",
"confirmation_sent_long": "E-mail megerősítő hivatkozáds elküldve.Kérjük, ellenőrizze a beérkező leveleket.",
"confirmation_sent_another": "Egy másik megerősítő link elküldve.",
"confirmation_sent_dialog_text": "E-mailt küldtünk Önnek, amelyben elmagyaráztuk, hogyan erősítse meg e-mail címét.",
"payment_caption": "Fizetés",
"language_caption": "Nyelv",
"notifications_caption": "Értesítések",
"notifications_option_chat": "E-mailben értesítsen az új megjegyzésekről",
"notifications_option_spaces": "Küldjön napi összefoglalót arról, hogy mi történt a helyeim és mappáim között",
"password_caption": "Jelszó",
"current_password": "Jelenlegi jelszó",
"new_password": "Új jelszó",
"verify_password": "Jelszó megerősítése",
"change_password": "Jelszó módosítása",
"reset_password": "Jelszó visszaállítása",
"terminate_caption": "Fiók törlése",
"terminate_warning": "Ha törli a fiókját, akkor az összes hely, mappa és üzenet, beleértve az Ön összes tartalmát és a helyeiben létrehozott más embereket megsemmisül.",
"terminate_warning2": "Ezt nem lehet visszavonni.",
"terminate_reason": "Üzenet",
"terminate_reason_caption": "Segítsen nekünk a fejlesztésben, ha megosztja a lemondás okait.",
"terminate_terminate": "Leállít",
"space_blank1": "Üdvözöljük egy friss, új helyen!",
"space_blank2": "Húzza ide a fájlokat, hivatkozások beillesztése",
"space_blank3": "vagy használja az alábbi eszközöket",
"space_blank4": "hogy ezt a helyet tartalommal töltse meg.",
"draft": "Piszkozat",
"publish": "Közzététel",
"published": "Közzétett",
"save_version": "Verzió mentése",
"version_saved": "Verzió mentve",
"post": "Üzenet küldése",
"chat_invite_cta1": "Az együttműködés szórakoztató!",
"chat_invite_cta2": "Miért ne",
"chat_invite_cta3": "hívjon meg néhány embert",
"chat_invite_cta4": "Önnel dolgozni?",
"chat_message_placeholder": "Írja meg az üzenetét…",
"view": "Nézet",
"edit": "Szerkesztés",
"present": "Jelen van",
"chat": "Csevegés",
"meta": "Meta",
"tool_search": "Keresés",
"tool_upload": "Feltöltés",
"tool_text": "Szöveg",
"tool_shape": "Forma",
"tool_zones": "Zónák",
"tool_canvas": "Vászon",
"search_media": "Keresés a médiában…",
"type_here": "Írja ide",
"text_formats": "Formátumok",
"format_p": "Bekezdés",
"format_bullets": "Listajeles lista",
"format_numbers": "Számozott lista",
"format_h1": "1. címsor",
"format_h2": "2. címsor",
"format_h3": "3. címsor",
"font_size": "Betűméret",
"line_height": "Sormagasság",
"tool_align": "Igazítás",
"tool_styles": "Stílusok",
"tool_bullets": "Felsorolás",
"tool_numbers": "Számok",
"tool_font": "Betűtípus",
"color_fill": "Kitöltés",
"color_stroke": "Vonás",
"color_text": "Szöveg",
"tool_type": "Típus",
"tool_box": "Doboz",
"tool_link": "Hivatkozás",
"tool_layout": "Elrendezés",
"tool_options": "Lehetőségek",
"tool_stroke": "Vonás ",
"tool_delete": "Törlés",
"tool_lock": "Lezár",
"tool_copy": "Másol",
"stack": "Halom",
"tool_circle": "Kör",
"tool_hexagon": "Hatszög",
"tool_square": "Négyzet",
"tool_diamond": "Gyémánt",
"tool_bubble": "Buborék",
"tool_cloud": "Felhő",
"tool_burst": "Sorozatfelvétel",
"tool_star": "Csillag",
"tool_heart": "Szív",
"tool_scribble": "Irkál",
"tool_line": "Vonal",
"tool_arrow": "Nyíl",
"search_media_placeholder": "Keresés az internetes médiában…",
"add_zone": "Új zóna",
"palette": "Paletta",
"picker": "Választó",
"background_image_caption": "Kép",
"background_color_caption": "Szín",
"upload_background_caption": "Kattintson egy háttérkép feltöltéséhez",
"upload_background": "Háttér feltöltése",
"access_caption": "Hozzáférés",
"versions_caption": "Verziók",
"info_caption": "Információ",
"mode_private": "Magán: Csak a tagok tekinthetik meg és szerkeszthetik",
"mode_public": "Nyilvános: A hivatkozás birtokában bárki megtekintheti",
"invite_collaborators": "Hívjon meg együttműködőket",
"revoke_access": "Hozzáférés visszavonása",
"invite": "Meghívók küldése",
"invitee_email_address": "Az új tag e-mail címe",
"optional_message": "Választható üzenet",
"role_viewer": "Néző",
"role_editor": "Szerkesztő",
"role_admin": "Adminisztrátor",
"new_space_title": "Új cím a helynek",
"team": "Csoport",
"search": "Keresés",
"search_no_results": "keresés_nincsenek_eredmények",
"search_clear": "keresés_törlés",
"rename": "Átnevezés",
"mobile": "mobil",
"image": "kép",
"tool_filter": "szűrő",
"canel": "mégse",
"invite_membership_action": "meghívni_tagságot",
"viewer": "néző",
"editor": "szerkesztő",
"admin": "adminisztrátor ",
"logging_in": "bejelentkezés",
"password_confirmation": "Jelszó megerősítése",
"confirm_again": "E-mailt küldtünk Önnek, amelyben elmagyaráztuk, hogyan erősítse meg e-mail címét.",
"confirmed": "Fiókját sikeresen megerősítettük. Köszönjük.",
"signing_up": "Feliratkozás",
"password_check_inbox": "Kérjük, ellenőrizze a beérkező leveleket",
"new_space": "Új hely",
"tool_more": "Több",
"what_is_your_name": "Üdvözöljük a %s oldalon! Kérjük, hogy válasszon egy felhasználónevet.",
"lang": "hu",
"landing_title": "Rajztáblája az interneten.",
"landing_claim": "A Spacedeck segítségével könnyedén kombinálhat mindenféle típusú médiát a virtuális rajztáblákon: szöveges jegyzeteket, fotókat, internetes linkeket, sőt videókat és hangfelvételeket.",
"landing_example": "Az emberek a Spacedeck segítségével szervezik ötleteiket, csoportokban, hogy egy pillantással teljes projekteket láthassanak vagy iskolákban és egyetemeken gazdagabb, összekapcsolt tanulási tapasztalatokkal.",
"spaces": "Saját helyek",
"access_editor_link": "Azonnali hivatkozás szerkesztése",
"access_editor_link_desc": "Adja meg ezt a hivatkozást mindenkinek, akinek képesnek kell lennie a hely azonnali szerkesztésére, nincs szükség fiókra:",
"access_editor_link_desc_slug": "Ez a hivatkozás tartalmazza a hely nevét is.",
"access_anonymous_edit_blocking": "Névtelen szerkesztők csak a saját tételeiket változtathatják meg",
"access_current_members": "Current Members",
"access_new_members": "Új tagok meghívása",
"access_no_members": "A Hely tagjai itt jelennek meg.",
"comments": "hozzászólások",
"landing_customers": "Ezrek bíznak benne.",
"landing_features_title": "Gyerekjáték használni.",
"landing_features_text": "Az új Spacedeck 5 korszerű, gyönyörű felhasználói felülettel rendelkezik, amely minden eddiginél könnyebbé és szórakoztatóbbá teszi munkáját - miközben még erőteljesebb funkciókat kínál:",
"landing_features_1": "<b>Fogd és vidd</b> képeket, videókat és hangokat a számítógépről vagy az internetről",
"landing_features_2": "<b>Szöveg írása és formázása</b> de a betűtípusok, a színek és a stílus teljes ellenőrzésével",
"landing_features_3": "<b>Rajzoljon, kommentáljon és jelöljön ki</b> a mellékelt grafikus alakzatokkal",
"landing_features_4": "</b>Kapcsolja tábláját <b>nagyító prezentációvá</b>",
"landing_features_5": "<b>Együttműködés és csevegés</b> valós időben csoport társaival, diákjaival vagy barátaival. ",
"landing_features_6": "<b>Helyek megosztása</b> az interneten vagy e-mailben",
"landing_features_7": "<b>Exportálja munkáját</b> nyomtatható PDF vagy ZIP formátumban",
"landing_pricing": "Hihetetlenül megfizethető.",
"landing_pricing_lite": "Ingyenes/személyes használat",
"landing_pricing_lite_text": "Az alap, átfogó verzió a képek gyűjtésére és a jegyzetek vezetésére.",
"landing_pricing_pro_features_list": "<ul><li>Korlátlan helyek</li><li>Mappa struktúrák</li><li>PDF és ZIP exportálás</li><li>Nincs vízjel</li><li>Egyéni hátterek</li><li>Tevékenység előzmények</li><li>20 GB tárhely</li><ul>",
"landing_pricing_pro": "€4,90/Felhasználó/hónap. <br><small>or 49,90/Felhasználó /év</small>",
"landing_pricing_pro_text": "Turbófeltöltve minden elvárt erővel.",
"landing_pricing_pro_features": "Turbófeltöltve minden elvárt erővel.",
"welcome_subject": "Üdvözöljük a Spacedeck-en",
"welcome_body": "Üdvözlet!\nKöszönjük, hogy feliratkozott a Spacedeck webhelyre.<br>Reméljük, hogy élvezni fogja a Helyek szolgáltatásban való munkát.<br>Ne feledje, hogy fiókjában korlátlan számú munkatárs található. Nyugodtan ossza meg helyeit barátaival és kollégáival a világ minden tájáról.",
"invite_emails": "E-mail címek (vesszővel elválasztva)",
"history_recently_updated": "Mostanában frissítve",
"history_recently_empty": "Még nem történt semmi.",
"parent_folder": "szülő_mappa",
"created_by": "Készítette",
"last_updated": "Utolsó frissítés",
"feedback_sent": "Köszönjük a visszajelzését!",
"role_member": "Tag",
"team_invite_membership_action": "Meghívás elfogadása",
"space_message_subject": "Új üzenet a következő helyen % s",
"space_message_body": "%s ezt írta %s-ban: \n",
"pro_ad_history_headline": "A Spacedeck Pro verzióra való frissítéskor itt láthatja az összes (megosztott) hely legújabb frissítésének előzményeit.",
"password_reset_subject": "Spacedeck jelszavának visszaállítása",
"password_reset_body": "Ön kérte a Spacedeck jelszavának visszaállítását.\n Kérjük, hogy kattintson a következő hivatkozásra az új jelszó beállításához.",
"password_reset_action": "Visszaállítás most",
"was_offline": "A Spacedeck-hez való kapcsolat megszakadt. Ha nem mentett munkája van, kérjük, tartsa nyitva ezt a böngészőfület a kapcsolat helyreállításáig, majd érintse meg újra a nem mentett objektumokat.",
"subscription_failed_user_subject": "Probléma a Spacedeck fizetésével",
"subscription_failed_user_body": "Sajnos nem tudtuk feldolgozni a fizetési módját. A fiók beállításokban könnyedén létrehozhat egy új fizetési módot, beleértve a PayPalt is.",
"subscription_failed_team_subject": "Probléma a Spacedeck fizetésével",
"subscription_failed_team_body": "Sajnos nem tudtuk feldolgozni a fizetési módját a Team-fiókjához. Kérjük, javítsa ki fizetési módját a lehető leghamarabb.",
"team_name": "Csoport név",
"subdomain": "altartomány",
"team_adresses": "E-mail címek",
"add": "Hozzáadás",
"invited": "meghívott",
"duplicate_destination": "Melyik mappába kívánja másolni ezt a helyet?",
"duplicate_confirm": "A(z)% s másolat% s-ra?",
"duplicate_success": "% s másolva lett% s-ra.",
"goto_space": "Lépjen a(z)% s helyre",
"goto_folder": "Lépjen a(z)% s mappába",
"stay_here": "Maradjon itt",
"sharing": "Megosztás",
"list": "Lista exportálása",
"link": "Hivatkozás",
"download_space": "Hely letöltése ",
"download_as_pdf": "Hely letöltése PDF formátumban",
"type": "Típus",
"download": "Letöltés",
"Previous Zone": "Előző zóna",
"Next Zone": "Következő zóna",
"promote": "Népszerűsít",
"demote": "Lefokoz",
"more": "Több",
"lock": "Lezár",
"unlock": "Felold",
"follow_present": "Követ",
"mute_present": "Követés megszüntetése",
"follow_present_help": "Ha valaki más mutatja be ezt a helyet, a többi tag automatikusan követi az előadást. Ezzel a gombbal kapcsolhatja be vagy ki a követést.",
"export": "Exportál",
"media": "Média",
"tool_edit_text": "Szöveg szerkesztése"
}

View File

@@ -244,7 +244,7 @@
"what_is_your_name": "La benvenguda a %s! Mercés de causir un escais-nom.", "what_is_your_name": "La benvenguda a %s! Mercés de causir un escais-nom.",
"lang": "en", "lang": "en",
"landing_title": "Vòstre tablèu blanc sul Web.", "landing_title": "Vòstre tablèu blanc sul Web.",
"landing_claim": "Spacedeck vos permet de facilament combinar quin que siá tipe de mèdias sus un tablèu virtual: tèxte, nòtas, ligams web, amai vidèos e enregistraments àudio. ", "landing_claim": "Spacedeck vos permet de facilament combinar quin tipe que siá de mèdias sus un tablèu virtual: tèxte, nòtas, ligams web, amai vidèos e enregistraments àudio. ",
"landing_example": "Lo monde utiliza Spacedeck per organizar lors idèas, en equipa per veire totes los projèctes en una ulhada, a lescòla e a luniversitat pels mai rics, experiéncia daprendissatge connectat.", "landing_example": "Lo monde utiliza Spacedeck per organizar lors idèas, en equipa per veire totes los projèctes en una ulhada, a lescòla e a luniversitat pels mai rics, experiéncia daprendissatge connectat.",
"spaces": "Mos espacis", "spaces": "Mos espacis",
"access_editor_link": "Ligam de modificacion dirècta", "access_editor_link": "Ligam de modificacion dirècta",

View File

@@ -86,7 +86,7 @@ module.exports = (req, res, next) => {
// space is private // space is private
// special permission for screenshot/pdf export from backend // special permission for screenshot/pdf export from backend
if (req.query['api_token'] && req.query['api_token'] == config.get('phantom_api_secret')) { if (req.query['api_token'] && req.query['api_token'] == config.get('export_api_secret')) {
finalizeReq(space, "viewer"); finalizeReq(space, "viewer");
return; return;
} }

7466
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -30,10 +30,8 @@
"mock-aws-s3": "^2.6.0", "mock-aws-s3": "^2.6.0",
"moment": "^2.19.3", "moment": "^2.19.3",
"morgan": "^1.9.1", "morgan": "^1.9.1",
"node-phantom-simple": "2.2.4",
"node-server-screenshot": "^0.2.1",
"nodemailer": "^4.6.7", "nodemailer": "^4.6.7",
"phantomjs-prebuilt": "^2.1.16", "puppeteer": "8.0.0",
"read-chunk": "^2.1.0", "read-chunk": "^2.1.0",
"request": "^2.88.0", "request": "^2.88.0",
"sanitize-html": "^1.11.1", "sanitize-html": "^1.11.1",

View File

@@ -8,6 +8,8 @@ var SpacedeckSections = {
data: { data: {
MAX_COLUMNS: 20, MAX_COLUMNS: 20,
isShift: false,
redo_stack: [], redo_stack: [],
undo_stack: [], undo_stack: [],
@@ -62,7 +64,7 @@ var SpacedeckSections = {
active_style: { active_style: {
border_radius: 0, border_radius: 0,
stroke: 0, stroke: 2,
font_family: "Inter", font_family: "Inter",
font_size: 36, font_size: 36,
line_height: 1.5, line_height: 1.5,
@@ -206,7 +208,9 @@ var SpacedeckSections = {
Mousetrap.bind('shift+left', function(evt) { this.if_editable(function() {this.nudge_selected_artifacts(-10,0,evt);}) }.bind(this)); Mousetrap.bind('shift+left', function(evt) { this.if_editable(function() {this.nudge_selected_artifacts(-10,0,evt);}) }.bind(this));
Mousetrap.bind('shift+right', function(evt) { this.if_editable(function() {this.nudge_selected_artifacts(10,0,evt);}) }.bind(this)); Mousetrap.bind('shift+right', function(evt) { this.if_editable(function() {this.nudge_selected_artifacts(10,0,evt);}) }.bind(this));
Mousetrap.bind('space', function(evt) { this.activate_pan_tool(evt); }.bind(this)); Mousetrap.bind('space', function(evt) { this.activate_pan_tool(evt); }.bind(this));
Mousetrap.bind(['shift'], function(evt) { this.isShift = true; }.bind(this), 'keydown');
Mousetrap.bind(['shift'], function(evt) { this.isShift = false; }.bind(this), 'keyup');
Mousetrap.bind('shift+up', function(evt) { this.if_editable(function() {this.nudge_selected_artifacts(0,-10,evt);}) }.bind(this));
$(document).bind("beforecopy", this.handle_onbeforecopy.bind(this)); $(document).bind("beforecopy", this.handle_onbeforecopy.bind(this));
$(window).bind("beforeunload", this.handle_onunload.bind(this)); $(window).bind("beforeunload", this.handle_onunload.bind(this));
$(window).bind("resize", this.handle_window_resize.bind(this)); $(window).bind("resize", this.handle_window_resize.bind(this));
@@ -1356,7 +1360,7 @@ var SpacedeckSections = {
}, },
reset_stroke: function() { reset_stroke: function() {
this.active_style.stroke = 0; this.active_style.stroke = 2;
this.active_style.border_radius = 0; this.active_style.border_radius = 0;
this.active_style.stroke_style = "solid"; this.active_style.stroke_style = "solid";
}, },
@@ -1714,7 +1718,7 @@ var SpacedeckSections = {
h: h, h: h,
stroke_color: this.active_style.stroke_color, stroke_color: this.active_style.stroke_color,
text_color: this.active_style.text_color, text_color: this.active_style.text_color,
stroke: 0, stroke: this.active_style.stroke,
fill_color: this.active_style.fill_color, fill_color: this.active_style.fill_color,
shape: shape_type, shape: shape_type,
valign: "middle", valign: "middle",
@@ -2292,17 +2296,19 @@ var SpacedeckSections = {
for (var i=0; i<parsed.length; i++) { for (var i=0; i<parsed.length; i++) {
if (parsed[i].mime) { if (parsed[i].mime) {
var z = this.highest_z()+1; var z = this.highest_z()+1;
if (parsed.length==1) { if(!this.isShift) {
var w = parsed[i].w; if (parsed.length==1) {
var h = parsed[i].h; var w = parsed[i].w;
var point = this.find_place_for_item(w,h); var h = parsed[i].h;
parsed[i].x = point.x; var point = this.find_place_for_item(w,h);
parsed[i].y = point.y; parsed[i].x = point.x;
parsed[i].z = point.z; parsed[i].y = point.y;
} else { parsed[i].z = point.z;
parsed[i].x = parsed[i].x+50; } else {
parsed[i].y = parsed[i].y+50; parsed[i].x = parsed[i].x+100;
parsed[i].y = parsed[i].z+z; parsed[i].y = parsed[i].y+100;
parsed[i].y = parsed[i].z+z;
}
} }
this.clone_artifact(parsed[i], 0,0, function(a) { this.clone_artifact(parsed[i], 0,0, function(a) {
this.multi_select([a]); this.multi_select([a]);

View File

@@ -99,7 +99,7 @@ var SpacedeckSpaces = {
}.bind(this), {value: dft || "Guest "+parseInt(10000*Math.random()), ok: __("ok"), cancel: __("cancel")}); }.bind(this), {value: dft || "Guest "+parseInt(10000*Math.random()), ok: __("ok"), cancel: __("cancel")});
}, },
load_space: function(space_id, on_success, on_error, space_auth) { load_space: function(space_id, on_success, on_error) {
this.folder_spaces_filter=""; this.folder_spaces_filter="";
this.folder_spaces_search=""; this.folder_spaces_search="";
@@ -308,7 +308,8 @@ var SpacedeckSpaces = {
userReady(); userReady();
} }
if (!this.user && space_auth) { if (!this.user.nickname && space_auth) {
this.guest_nickname = get_query_param("nickname") || this.guest_nickname;
if (this.guest_nickname) { if (this.guest_nickname) {
userReady(); userReady();
} else { } else {

View File

@@ -23,6 +23,9 @@ function vec2_angle(v) {
function render_vector_drawing(a, padding) { function render_vector_drawing(a, padding) {
var shape = a.shape || ""; var shape = a.shape || "";
var path = []; var path = [];
if(typeof a.control_points == 'string'){
a.control_points = JSON.parse(a.control_points);
}
var p = a.control_points[0]; var p = a.control_points[0];
if (!p) return ""; if (!p) return "";

File diff suppressed because one or more lines are too long

View File

@@ -5,7 +5,7 @@ const db = require('../../models/db');
var mailer = require('../../helpers/mailer'); var mailer = require('../../helpers/mailer');
var uploader = require('../../helpers/uploader'); var uploader = require('../../helpers/uploader');
var space_render = require('../../helpers/space-render'); var space_render = require('../../helpers/space-render');
var phantom = require('../../helpers/phantom'); var exporter = require('../../helpers/exporter');
var async = require('async'); var async = require('async');
var moment = require('moment'); var moment = require('moment');
@@ -51,7 +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", function(local_path) { exporter.takeScreenshot(req.space, "png", 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) {
@@ -109,7 +109,7 @@ function make_export_filename(space, extension) {
router.get('/pdf', function(req, res, next) { router.get('/pdf', function(req, res, next) {
var s3_filename = make_export_filename(req.space, "pdf"); var s3_filename = make_export_filename(req.space, "pdf");
phantom.takeScreenshot(req.space, "pdf", function(local_path) { exporter.takeScreenshot(req.space, "pdf", function(local_path) {
uploader.uploadFile(s3_filename, "application/pdf", local_path, function(err, url) { uploader.uploadFile(s3_filename, "application/pdf", local_path, function(err, url) {
res.status(201).json({ res.status(201).json({
url: url url: url

View File

@@ -9,7 +9,7 @@ var redis = require('../../helpers/redis');
var mailer = require('../../helpers/mailer'); var mailer = require('../../helpers/mailer');
var uploader = require('../../helpers/uploader'); var uploader = require('../../helpers/uploader');
var space_render = require('../../helpers/space-render'); var space_render = require('../../helpers/space-render');
var phantom = require('../../helpers/phantom'); var exporter = require('../../helpers/exporter');
var async = require('async'); var async = require('async');
var fs = require('fs'); var fs = require('fs');

View File

@@ -10,7 +10,7 @@ var redis = require('../../helpers/redis');
var mailer = require('../../helpers/mailer'); var mailer = require('../../helpers/mailer');
var uploader = require('../../helpers/uploader'); var uploader = require('../../helpers/uploader');
var space_render = require('../../helpers/space-render'); var space_render = require('../../helpers/space-render');
var phantom = require('../../helpers/phantom'); var exporter = require('../../helpers/exporter');
var payloadConverter = require('../../helpers/artifact_converter'); var payloadConverter = require('../../helpers/artifact_converter');
var slug = require('slug'); var slug = require('slug');

View File

@@ -1,10 +1,10 @@
"use strict"; "use strict";
const puppeteer = require('puppeteer');
var config = require('config'); var config = require('config');
require('../../models/db'); require('../../models/db');
var fs = require('fs'); var fs = require('fs');
var phantom = require('node-phantom-simple');
var md5 = require('md5'); var md5 = require('md5');
var express = require('express'); var express = require('express');
@@ -19,40 +19,39 @@ function website_to_png(url,on_success,on_error) {
console.log("[webgrabber] url: "+url); console.log("[webgrabber] url: "+url);
console.log("[webgrabber] export_path: "+export_path); console.log("[webgrabber] export_path: "+export_path);
var on_success_called = false;
var on_exit = function(exit_code) {
if (exit_code>0) {
console.log("[phantom-webgrabber] abnormal exit for url "+url);
if (!on_success_called && on_error) {
on_error();
}
}
};
fs.stat(export_path, function(err, stat) { fs.stat(export_path, function(err, stat) {
if (!err) { if (!err) {
// file exists // file exists
console.log("[webgrabber] serving cached snapshot of url: "+url); console.log("[webgrabber] serving cached snapshot of url: "+url);
on_success(export_path); on_success(export_path);
} else { } else {
phantom.create({ path: require('phantomjs-prebuilt').path }, function (err, browser) { (async () => {
return browser.createPage(function (err, page) { let browser;
page.set('settings.resourceTimeout',timeout); let page;
page.set('settings.javascriptEnabled',false); try {
browser = await puppeteer.launch(
return page.open(url, function(err, status) { {
console.log("[webgrabber] status: "+status); headless: true,
page.render(export_path, function() { args: ['--disable-dev-shm-usage', '--no-sandbox']
on_success_called = true; }
on_success(export_path); );
browser.exit(); page = await browser.newPage();
});
}); page.setDefaultTimeout(timeout);
}); await page.setJavaScriptEnabled(false);
}, { await page.goto(url, {waitUntil: 'networkidle2'});
onExit: on_exit await page.emulateMedia('screen');
}); await page.screenshot({path: export_path, printBackground: true});
await browser.close();
on_success(export_path);
} catch (error) {
console.error(error);
console.log("[webgrabber] puppeteer abnormal exit for url "+url);
on_error();
}
})();
} }
}); });
} }

View File

@@ -78,6 +78,22 @@ router.get('/oc', (req, res) => {
res.redirect("/t/oc"); res.redirect("/t/oc");
}); });
router.get('/es/*', (req, res) => {
res.redirect("/t/es");
});
router.get('/es', (req, res) => {
res.redirect("/t/es");
});
router.get('/hu/*', (req, res) => {
res.redirect("/t/hu");
});
router.get('/hu', (req, res) => {
res.redirect("/t/hu");
});
router.get('/en/*', (req, res) => { router.get('/en/*', (req, res) => {
res.redirect("/t/en"); res.redirect("/t/en");
}); });
@@ -87,7 +103,7 @@ router.get('/en', (req, res) => {
}); });
router.get('/account', (req, res) => { router.get('/account', (req, res) => {
res.render('spacedeck'); res.render('spacedeck', { config:config });
}); });
router.get('/login', (req, res) => { router.get('/login', (req, res) => {

View File

@@ -33,7 +33,7 @@ console.log("Booting Spacedeck Open… (environment: " + app.get('env') + ")");
app.use(logger(isProduction ? 'combined' : 'dev')); app.use(logger(isProduction ? 'combined' : 'dev'));
i18n.expressBind(app, { i18n.expressBind(app, {
locales: ["en", "de", "fr", "oc", "es"], locales: ["de", "en", "es", "fr", "hu", "oc"],
defaultLocale: "en", defaultLocale: "en",
cookieName: "spacedeck_locale", cookieName: "spacedeck_locale",
devMode: (app.get('env') == 'development') devMode: (app.get('env') == 'development')

View File

@@ -3,12 +3,17 @@
@import "unicode"; @import "unicode";
@-webkit-keyframes appear { @-webkit-keyframes appear {
0% { opacity: 0;} 0% {
30% { opacity: 0;} opacity: 0;
100% { opacity: 1; } }
30% {
opacity: 0;
}
100% {
opacity: 1;
}
} }
.avatar { .avatar {
background-color: $blue; background-color: $blue;
font-family: $main-font; font-family: $main-font;
@@ -26,7 +31,9 @@
#user-root { #user-root {
margin-left: 5px !important; margin-left: 5px !important;
padding: 0px !important; padding: 0px !important;
.btn {margin-right: 10px; } .btn {
margin-right: 10px;
}
} }
#sidebar.folder-sidebar { #sidebar.folder-sidebar {
@@ -70,7 +77,9 @@
li { li {
display: inline-block; display: inline-block;
line-height: 44px; line-height: 44px;
&.active span {color: $light; } &.active span {
color: $light;
}
span { span {
color: $medium; color: $medium;
display: inline-block; display: inline-block;
@@ -82,8 +91,6 @@
} }
} }
#folder { #folder {
position: absolute; position: absolute;
height: 100%; height: 100%;
@@ -137,7 +144,7 @@
z-index: initial; z-index: initial;
} }
.folder .icon { .folder .icon {
color: $yellow; color: $yellow;
opacity: 1; opacity: 1;
} }
@@ -150,7 +157,7 @@
width: 100%; width: 100%;
} }
> .icon { > .icon {
margin-left: -15px margin-left: -15px;
} }
} }
@@ -176,30 +183,30 @@
// margin-top: -18px; // margin-top: -18px;
margin-right: -60px; margin-right: -60px;
// margin-bottom: -18px; // margin-bottom: -18px;
@include transition( all 0.125s ease-in-out); @include transition(all 0.125s ease-in-out);
.icon { .icon {
left: 0px; left: 0px;
top: 0px; top: 0px;
line-height: 60px; line-height: 60px;
font-size: 13px; font-size: 13px;
position: absolute; position: absolute;
@include scale(0,0); @include scale(0, 0);
@include transition( all 0.125s ease-in-out); @include transition(all 0.125s ease-in-out);
@include opacity(0.25); @include opacity(0.25);
} }
&:hover { &:hover {
margin-right: -12px; margin-right: -12px;
.icon { .icon {
@include scale(1,1); @include scale(1, 1);
} }
} }
} }
} }
#folder-header { #folder-header {
background-color: rgba(41,41,41,0.95); background-color: rgba(41, 41, 41, 0.95);
background-color: rgba(245,245,245,0.95); background-color: rgba(245, 245, 245, 0.95);
} }
#folder-wrapper { #folder-wrapper {
@@ -212,15 +219,22 @@
margin: auto; margin: auto;
} }
#folder-grid .item { #folder-grid .item {
float: left; float: left;
width: 100%; width: 100%;
@media screen and (min-width: 640px) {width: 50%; } @media screen and (min-width: 640px) {
@media screen and (min-width: 800px) {width: 33.333333%; } width: 50%;
@media screen and (min-width: 1000px) {width: 25%; } }
@media screen and (min-width: 1200px) {width: 20%; } @media screen and (min-width: 800px) {
width: 33.333333%;
}
@media screen and (min-width: 1000px) {
width: 25%;
}
@media screen and (min-width: 1200px) {
width: 20%;
}
} }
.compact-hidden { .compact-hidden {
@@ -256,8 +270,8 @@
.item { .item {
display: inline-block; display: inline-block;
text-align: left; text-align: left;
padding-right: $folder-gutter*2; padding-right: $folder-gutter * 2;
padding-bottom: $folder-gutter*2; padding-bottom: $folder-gutter * 2;
margin-bottom: $folder-gutter; margin-bottom: $folder-gutter;
position: relative; position: relative;
@@ -265,36 +279,38 @@
cursor: pointer; cursor: pointer;
.folder-drop {display:none; } .folder-drop {
display: none;
}
&.appear > a, &.appear > a,
&.creating > a { &.creating > a {
opacity: 0; opacity: 0;
-webkit-animation: appear 0.25s ease-out 0.05s; -webkit-animation: appear 0.25s ease-out 0.05s;
-moz-animation: appear 0.25s ease-out 0.05s; -moz-animation: appear 0.25s ease-out 0.05s;
-ms-animation: appear 0.25s ease-out 0.05s; -ms-animation: appear 0.25s ease-out 0.05s;
-o-animation: appear 0.25s ease-out 0.05s; -o-animation: appear 0.25s ease-out 0.05s;
animation: appear 0.25s ease-out 0.05s; animation: appear 0.25s ease-out 0.05s;
-webkit-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards; -moz-animation-fill-mode: forwards;
-ms-animation-fill-mode: forwards; -ms-animation-fill-mode: forwards;
-o-animation-fill-mode: forwards; -o-animation-fill-mode: forwards;
animation-fill-mode: forwards; animation-fill-mode: forwards;
} }
&.deleting > a { &.deleting > a {
-webkit-animation: disappear 0.25s ease-out 0.05s; -webkit-animation: disappear 0.25s ease-out 0.05s;
-moz-animation: disappear 0.25s ease-out 0.05s; -moz-animation: disappear 0.25s ease-out 0.05s;
-ms-animation: disappear 0.25s ease-out 0.05s; -ms-animation: disappear 0.25s ease-out 0.05s;
-o-animation: disappear 0.25s ease-out 0.05s; -o-animation: disappear 0.25s ease-out 0.05s;
animation: disappear 0.25s ease-out 0.05s; animation: disappear 0.25s ease-out 0.05s;
-webkit-animation-fill-mode: forwards; -webkit-animation-fill-mode: forwards;
-moz-animation-fill-mode: forwards; -moz-animation-fill-mode: forwards;
-ms-animation-fill-mode: forwards; -ms-animation-fill-mode: forwards;
-o-animation-fill-mode: forwards; -o-animation-fill-mode: forwards;
animation-fill-mode: forwards; animation-fill-mode: forwards;
} }
&.tag-important > a { &.tag-important > a {
@@ -308,7 +324,7 @@
&.dropping { &.dropping {
.folder-drop { .folder-drop {
display:block; display: block;
} }
} }
@@ -349,7 +365,13 @@
background-color: $darker; background-color: $darker;
position: absolute; position: absolute;
bottom: 2px; bottom: 2px;
-webkit-mask-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,0)), to(rgba(0,0,0,0.1))); -webkit-mask-image: -webkit-gradient(
linear,
left top,
left bottom,
from(rgba(0, 0, 0, 0)),
to(rgba(0, 0, 0, 0.1))
);
background-color: black; background-color: black;
pointer-events: none; pointer-events: none;
} }
@@ -360,7 +382,7 @@
.fav-toggle { .fav-toggle {
margin-right: -12px; margin-right: -12px;
.icon { .icon {
@include scale(1,1); @include scale(1, 1);
@include opacity(1); @include opacity(1);
} }
} }
@@ -384,7 +406,7 @@
> a { > a {
/* aspect ratio without spacer image */ /* aspect ratio without spacer image */
&:before{ &:before {
content: ""; content: "";
display: block; display: block;
padding-top: 100%; /* initial ratio of 1:1*/ padding-top: 100%; /* initial ratio of 1:1*/
@@ -392,9 +414,11 @@
} }
background-color: white; background-color: white;
border-radius: $radius*2; border-radius: $radius * 2;
&:active { opacity: 0.95 !important; } &:active {
opacity: 0.95 !important;
}
box-shadow: 0 0 30px 1px rgba(0, 0, 0, 0.15); box-shadow: 0 0 30px 1px rgba(0, 0, 0, 0.15);
border: 1px solid black; border: 1px solid black;
@@ -406,7 +430,7 @@
font-weight: 400; font-weight: 400;
display: block; display: block;
text-decoration: none; text-decoration: none;
border-radius: $radius*2; border-radius: $radius * 2;
position: relative; position: relative;
.item-thumbnail { .item-thumbnail {
@@ -420,8 +444,9 @@
overflow: hidden; overflow: hidden;
background-color: transparent; background-color: transparent;
border-top-left-radius: $radius*2; background-size: cover;
border-top-right-radius: $radius*2; border-top-left-radius: $radius * 2;
border-top-right-radius: $radius * 2;
border-bottom-left-radius: 10px; border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px; border-bottom-right-radius: 10px;
@@ -431,7 +456,7 @@
.item-title { .item-title {
display: block; display: block;
border-top: 1px solid rgba(0,0,0,0.05); border-top: 1px solid rgba(0, 0, 0, 0.05);
background-color: white; background-color: white;
font-size: 18px; font-size: 18px;
width: 100%; width: 100%;
@@ -439,15 +464,15 @@
left: 0px; left: 0px;
bottom: 0px; bottom: 0px;
position: absolute; position: absolute;
border-bottom-left-radius: $radius*2; border-bottom-left-radius: $radius * 2;
border-bottom-right-radius: $radius*2; border-bottom-right-radius: $radius * 2;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
color: $dark; color: $dark;
text-align: left; text-align: left;
} }
.thumbnail-loading { .thumbnail-loading {
position: absolute; position: absolute;
z-index: 0; z-index: 0;
@@ -464,11 +489,11 @@
} }
.item-meta { .item-meta {
border-top: 2px solid rgba(0,0,0,0.025); border-top: 2px solid rgba(0, 0, 0, 0.025);
border-radius: 2*$radius; border-radius: 2 * $radius;
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
@include clearfix; @include clearfix;
color: $medium; color: $medium;
position: absolute; position: absolute;
@@ -493,8 +518,8 @@
left: 0px; left: 0px;
bottom: 0px; bottom: 0px;
position: relative; position: relative;
border-bottom-left-radius: $radius*2; border-bottom-left-radius: $radius * 2;
border-bottom-right-radius: $radius*2; border-bottom-right-radius: $radius * 2;
//white-space: nowrap; //white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -509,7 +534,7 @@
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: $folder-gutter*2; right: $folder-gutter * 2;
color: $medium; color: $medium;
font-size: 11px; font-size: 11px;
font-family: $main-font; font-family: $main-font;

View File

@@ -3,7 +3,12 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Spacedeck Open</title> <title>Spacedeck Open</title>
<meta name="description" content=""> <meta name="title" content="Spacedeck Open">
<meta name="description" content="Whenever you need to lay out pictures, text notes, video and audio clips on a blank canvas, Spacedeck can help you."/>
<meta name="keywords" content="spacedeck, collaboration, teams, collages, moodboards, teaching, shared whiteboards, design thinking"/>
<meta name="author" content="MNT Research GmbH"/>
<meta name="copyright" content="MNT Research GmbH"/>
<meta name="robots" content="index,follow"/>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="viewport" content="width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
@@ -24,6 +29,5 @@
<a class="btn btn-md btn-dark 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>
<% } %> <% } %>
</div> </div>
</header> </header>

View File

@@ -110,7 +110,10 @@
</label> </label>
<label class="radio" v-bind:class="{checked: user.prefs_language=='es'}" v-on:click="save_user_language('es')"> <label class="radio" v-bind:class="{checked: user.prefs_language=='es'}" v-on:click="save_user_language('es')">
<input type="radio" id="user-preferences_language" name="language" value="es"><span>Español</span> <input type="radio" id="user-preferences_language" name="language" value="es"><span>Español</span>
</label> </label>
<label class="radio" v-bind:class="{checked: user.prefs_language=='hu'}" v-on:click="save_user_language('hu')">
<input type="radio" id="user-preferences_language" name="language" value="hu"><span>Magyar</span>
</label>
</div> </div>
</div> </div>

View File

@@ -18,7 +18,7 @@
webEndpoint: location.origin, webEndpoint: location.origin,
apiEndpoint: location.origin, apiEndpoint: location.origin,
websocketsEndpoint: location.origin.replace("https:","wss:").replace("http:","ws:"), websocketsEndpoint: location.origin.replace("https:","wss:").replace("http:","ws:"),
options: <%- config.spacedeck ? JSON.stringify(config.spacedeck) : "{}" %> options: <%- config && config.spacedeck ? JSON.stringify(config.spacedeck) : "{}" %>
}; };
</script> </script>
@@ -74,15 +74,17 @@
<script type="text/javascript"> <script type="text/javascript">
window.locales = {}; window.locales = {};
window.locales.en = {};
window.locales.de = {}; window.locales.de = {};
window.locales.fr = {}; window.locales.en = {};
window.locales.oc = {};
window.locales.es = {}; window.locales.es = {};
window.locales.en.translation = <%- include("./../locales/en.js") %>; window.locales.fr = {};
window.locales.hu = {};
window.locales.oc = {};
window.locales.de.translation = <%- include("./../locales/de.js") %>; window.locales.de.translation = <%- include("./../locales/de.js") %>;
window.locales.fr.translation = <%- include("./../locales/fr.js") %>; window.locales.en.translation = <%- include("./../locales/en.js") %>;
window.locales.oc.translation = <%- include("./../locales/oc.js") %>;
window.locales.es.translation = <%- include("./../locales/es.js") %>; window.locales.es.translation = <%- include("./../locales/es.js") %>;
window.locales.fr.translation = <%- include("./../locales/fr.js") %>;
window.locales.hu.translation = <%- include("./../locales/hu.js") %>;
window.locales.oc.translation = <%- include("./../locales/oc.js") %>;
</script> </script>
</html> </html>