diff --git a/.gitignore b/.gitignore index 44dd6e32f..9011c1da1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,5 @@ node_modules/ -coverage/ -.nyc_output/ -webadmin/dist/ installer/src/certs/server.key -dashboard/public/theme.css -dashboard/public/theme.css.map # vim swap files *.swp diff --git a/dashboard/.gitignore b/dashboard/.gitignore index 319b798ab..72ed5c090 100644 --- a/dashboard/.gitignore +++ b/dashboard/.gitignore @@ -1,11 +1,16 @@ dist/ node_modules/ +# will get generated on build +public/theme.css +public/theme.css.map + # vim swap files *.swp # these are not done yet -src/translation/ja.json -src/translation/pl.json -src/translation/si.json -src/translation/gl.json +public/translation/ja.json +public/translation/pl.json +public/translation/si.json +public/translation/gl.json +public/translation/hr.json diff --git a/dashboard/.jshintrc b/dashboard/.jshintrc deleted file mode 100644 index 21979ddc5..000000000 --- a/dashboard/.jshintrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "node": true, - "browser": true, - "unused": true, - "esversion": 6, - "globalstrict": false, - "predef": [ - "$", - "angular", - "async", - "describe", - "it", - "before", - "after", - "require", - "monaco", - "Mimer", - "ISTATES" - ] -} diff --git a/dashboard/LICENSE b/dashboard/LICENSE deleted file mode 100644 index 8c3b00b35..000000000 --- a/dashboard/LICENSE +++ /dev/null @@ -1,35 +0,0 @@ -The Cloudron Subscription license -Copyright (c) 2022 Cloudron UG - -With regard to the Cloudron Software: - -This software and associated documentation files (the "Software") may only be -used in production, if you (and any entity that you represent) have agreed to, -and are in compliance with, the Cloudron Subscription Terms of Service, available -at https://cloudron.io/legal/terms.html (the “Subscription Terms”), or other -agreement governing the use of the Software, as agreed by you and Cloudron, -and otherwise have a valid Cloudron Subscription. Subject to the foregoing sentence, -you are free to modify this Software and publish patches to the Software. You agree -that Subscription and/or its licensors (as applicable) retain all right, title and -interest in and to all such modifications and/or patches, and all such modifications -and/or patches may only be used, copied, modified, displayed, distributed, or otherwise -exploited with a valid Cloudron subscription. Notwithstanding the foregoing, you may copy -and modify the Software for development and testing purposes, without requiring a -subscription. You agree that Cloudron and/or its licensors (as applicable) retain -all right, title and interest in and to all such modifications. You are not -granted any other rights beyond what is expressly stated herein. Subject to the -foregoing, it is forbidden to copy, merge, publish, distribute, sublicense, -and/or sell the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -For all third party components incorporated into the Cloudron Software, those -components are licensed under the original license provided by the owner of the -applicable component. - diff --git a/dashboard/README.md b/dashboard/README.md deleted file mode 100644 index 1ea4f1bbe..000000000 --- a/dashboard/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Cloudron Dashboard - -This is the front end code of Cloudron. The backend code is [here](https://git.cloudron.io/cloudron/box). - -## Developing - -* `npm install` -* `gulp develop --api-origin=https://my.example.com` - -## License - -Please note that the Cloudron code is under a source-available license. This is not the same as an -open source license but ensures the code is available for inspection (and hacking!). - -## Contributions - -Just to give a heads-up, we are a bit restrictive in merging changes. We are a small team and -would like to keep our maintenance burden low. It might be best to first discuss features in the [forum](https://forum.cloudron.io), -which also helps to determine how many other people will use it to justify maintenance for a feature. - diff --git a/dashboard/src/activation.html b/dashboard/activation.html similarity index 81% rename from dashboard/src/activation.html rename to dashboard/activation.html index e1c4a9614..e6744f4dc 100644 --- a/dashboard/src/activation.html +++ b/dashboard/activation.html @@ -9,43 +9,42 @@ + + + - - - - + - - - - + - - - - - - + + + + + + - + - - - - + + + + - + + + diff --git a/dashboard/src/appstatus.html b/dashboard/appstatus.html similarity index 100% rename from dashboard/src/appstatus.html rename to dashboard/appstatus.html diff --git a/dashboard/src/authcallback.html b/dashboard/authcallback.html similarity index 100% rename from dashboard/src/authcallback.html rename to dashboard/authcallback.html diff --git a/dashboard/develop.sh b/dashboard/develop.sh index 7790c176c..997f54a62 100755 --- a/dashboard/develop.sh +++ b/dashboard/develop.sh @@ -3,7 +3,7 @@ set -eu echo "=> Set API origin" -export VITE_API_ORIGIN="my.nebulon.space" +export VITE_API_ORIGIN="https://my.nebulon.space" echo "=> Run vite locally" npm run dev diff --git a/dashboard/eslint.config.js b/dashboard/eslint.config.js new file mode 100644 index 000000000..bbea42f1a --- /dev/null +++ b/dashboard/eslint.config.js @@ -0,0 +1,22 @@ +import globals from 'globals'; +import js from '@eslint/js'; +import pluginVue from 'eslint-plugin-vue'; + +export default [ + js.configs.recommended, + ...pluginVue.configs['flat/essential'], + { + files: ["**/*.js"], + languageOptions: { + globals: { + ...globals.browser, + }, + ecmaVersion: 13, + sourceType: 'module' + }, + rules: { + semi: "error", + "prefer-const": "error" + } + } +]; diff --git a/dashboard/gulpfile.js b/dashboard/gulpfile.js deleted file mode 100644 index f1d6b3a9f..000000000 --- a/dashboard/gulpfile.js +++ /dev/null @@ -1,217 +0,0 @@ -/* jslint node:true */ - -'use strict'; - -const argv = require('yargs').argv, - concat = require('gulp-concat'), - ejs = require('gulp-ejs'), - execSync = require('child_process').execSync, - fs = require('fs'), - gulp = require('gulp'), - sass = require('gulp-sass')(require('sass')), - serve = require('gulp-serve'), - sourcemaps = require('gulp-sourcemaps'); - -if (argv.help || argv.h) { - console.log('Supported arguments for "gulp develop":'); - console.log(' --api-origin '); - console.log(' --revision '); - console.log(' --appstore-console-origin '); - - process.exit(1); -} - -const revision = argv.revision || ''; - -let apiOrigin = ''; -if (argv.apiOrigin) { - if (argv.apiOrigin.indexOf('https://') === 0) apiOrigin = argv.apiOrigin; - else apiOrigin = 'https://' + argv.apiOrigin; -} - -var appstore = { - consoleOrigin: argv.appstoreConsoleOrigin || '' -}; - -console.log(); -console.log('Cloudron API: %s', apiOrigin || 'default'); -console.log('Building for revision: %s', revision); -console.log(); -console.log('Overriding appstore origin:'); -console.log(' Console: %s', appstore.consoleOrigin || 'no'); -console.log(); - -gulp.task('fontawesome', function () { - return gulp.src('node_modules/@fortawesome/fontawesome-free/**/*') - .pipe(gulp.dest('dist/3rdparty/fontawesome/')); -}); - -gulp.task('noto-sans', function () { - return gulp.src('node_modules/@fontsource/noto-sans/**/*') - .pipe(gulp.dest('dist/3rdparty/noto-sans/')); -}); - -gulp.task('bootstrap', function () { - return gulp.src('node_modules/bootstrap-sass/assets/javascripts/bootstrap.min.js') - .pipe(gulp.dest('dist/3rdparty/js')); -}); - -gulp.task('moment', function () { - return gulp.src('node_modules/moment/min/*') - .pipe(gulp.dest('dist/3rdparty/js')); -}); - -gulp.task('3rdparty-copy', function () { - return gulp.src([ - 'src/3rdparty/**/*.js', - 'src/3rdparty/**/*.map', - 'src/3rdparty/**/*.css', - 'src/3rdparty/**/*.otf', - 'src/3rdparty/**/*.eot', - 'src/3rdparty/**/*.svg', - 'src/3rdparty/**/*.gif', - 'src/3rdparty/**/*.ttf', - 'node_modules/chart.js/dist/chart.umd.js' - ]).pipe(gulp.dest('dist/3rdparty/')); -}); - -gulp.task('3rdparty', gulp.series(['3rdparty-copy', 'moment', 'bootstrap', 'fontawesome', 'noto-sans'])); - -// -------------- -// JavaScript -// -------------- - -gulp.task('js-index', function () { - return gulp.src([ - 'src/js/index.js', - 'src/js/client.js', - 'src/js/utils.js', - 'src/views/*.js' - ]) - .pipe(ejs({ apiOrigin: apiOrigin, revision: revision, appstore: appstore }, {}, { ext: '.js' })) - .pipe(sourcemaps.init()) - .pipe(concat('index.js', { newLine: ';' })) - .pipe(sourcemaps.write()) - .pipe(gulp.dest('dist/js')); -}); - -gulp.task('js-passwordreset', function () { - return gulp.src(['src/js/passwordreset.js', 'src/js/utils.js']) - .pipe(ejs({ apiOrigin: apiOrigin, revision: revision, appstore: appstore }, {}, { ext: '.js' })) - .pipe(sourcemaps.init()) - .pipe(concat('passwordreset.js', { newLine: ';' })) - .pipe(sourcemaps.write()) - .pipe(gulp.dest('dist/js')); -}); - -gulp.task('js-setupaccount', function () { - return gulp.src(['src/js/setupaccount.js', 'src/js/utils.js']) - .pipe(ejs({ apiOrigin: apiOrigin, revision: revision, appstore: appstore }, {}, { ext: '.js' })) - .pipe(sourcemaps.init()) - .pipe(concat('setupaccount.js', { newLine: ';' })) - .pipe(sourcemaps.write()) - .pipe(gulp.dest('dist/js')); -}); - -gulp.task('js-activation', function () { - return gulp.src(['src/js/activation.js', 'src/js/client.js', 'src/js/utils.js']) - .pipe(ejs({ apiOrigin: apiOrigin, revision: revision, appstore: appstore }, {}, { ext: '.js' })) - .pipe(sourcemaps.init()) - .pipe(concat('activation.js', { newLine: ';' })) - .pipe(sourcemaps.write()) - .pipe(gulp.dest('dist/js')); -}); - -gulp.task('js-setup', function () { - return gulp.src(['src/js/setup.js', 'src/js/client.js', 'src/js/utils.js']) - .pipe(ejs({ apiOrigin: apiOrigin, revision: revision, appstore: appstore }, {}, { ext: '.js' })) - .pipe(sourcemaps.init()) - .pipe(concat('setup.js', { newLine: ';' })) - .pipe(sourcemaps.write()) - .pipe(gulp.dest('dist/js')); -}); - -gulp.task('js-restore', function () { - return gulp.src(['src/js/restore.js', 'src/js/client.js', 'src/js/utils.js']) - .pipe(ejs({ apiOrigin: apiOrigin, revision: revision, appstore: appstore }, {}, { ext: '.js' })) - .pipe(sourcemaps.init()) - .pipe(concat('restore.js', { newLine: ';' })) - .pipe(sourcemaps.write()) - .pipe(gulp.dest('dist/js')); -}); - -gulp.task('js', gulp.series([ 'js-index', 'js-passwordreset', 'js-setupaccount', 'js-activation', 'js-setup', 'js-restore' ])); - -// -------------- -// HTML -// -------------- - -gulp.task('html-views', function () { - return gulp.src('src/views/**/*.html').pipe(gulp.dest('dist/views')); -}); - -gulp.task('html-raw', function () { - return gulp.src('src/*.html').pipe(ejs({ apiOrigin: apiOrigin, revision: revision }, {}, { ext: '.html' })).pipe(gulp.dest('dist')); -}); - -gulp.task('html', gulp.series(['html-views', 'html-raw'])); - -// -------------- -// CSS -// -------------- - -gulp.task('css', function () { - return gulp.src('src/*.scss') - .pipe(sass({ includePaths: [ - 'node_modules/bootstrap-sass/assets/stylesheets/', - 'node_modules/@fontsource/' - ]}).on('error', sass.logError)) - .pipe(gulp.dest('dist')); -}); - -gulp.task('images', function () { - return gulp.src('src/img/**') - .pipe(gulp.dest('dist/img')); -}); - -gulp.task('translation', function () { - return gulp.src('src/translation/**') - .pipe(gulp.dest('dist/translation')); -}); - -gulp.task('timezones', function (done) { - execSync('./scripts/createTimezones.js ./dist/js/timezones.js'); - done(); -}); - -// -------------- -// Utilities -// -------------- - -gulp.task('clean', function (done) { - fs.rm('dist', { recursive: true, force: true }, done); -}); - -gulp.task('default', gulp.series(['clean', 'html', 'js', 'timezones', '3rdparty', 'translation', 'images', 'css'])); - -gulp.task('watch', function (done) { - gulp.watch(['src/*.scss'], gulp.series(['css'])); - gulp.watch(['src/img/*'], gulp.series(['images'])); - gulp.watch(['src/translation/*'], gulp.series(['translation'])); - gulp.watch(['src/**/*.html'], gulp.series(['html'])); - gulp.watch(['src/views/*.html'], gulp.series(['html-views'])); - gulp.watch(['scripts/createTimezones.js', 'src/js/utils.js'], gulp.series(['timezones'])); - gulp.watch(['src/js/activation.js', 'src/js/client.js', 'src/js/utils.js'], gulp.series(['js-activation'])); - gulp.watch(['src/js/setup.js', 'src/js/client.js', 'src/js/utils.js'], gulp.series(['js-setup'])); - gulp.watch(['src/js/restore.js', 'src/js/client.js', 'src/js/utils.js'], gulp.series(['js-restore'])); - gulp.watch(['src/js/passwordreset.js', 'src/js/utils.js'], gulp.series(['js-passwordreset'])); - gulp.watch(['src/js/setupaccount.js', 'src/js/utils.js'], gulp.series(['js-setupaccount'])); - gulp.watch(['src/js/index.js', 'src/js/client.js', 'src/views/*.js', 'src/js/utils.js'], gulp.series(['js-index'])); - gulp.watch(['src/3rdparty/**/*'], gulp.series(['3rdparty'])); - done(); -}); - -gulp.task('serve', serve({ root: 'dist', port: 4000, hostname: '0.0.0.0' })); - -gulp.task('develop', gulp.series(['default', 'watch', 'serve'])); - diff --git a/dashboard/index.html b/dashboard/index.html index 7078d2642..7f18ee11a 100644 --- a/dashboard/index.html +++ b/dashboard/index.html @@ -1,211 +1,210 @@ - - + + - - Cloudron Dashboard - + + Cloudron Dashboard + - - - + + + - - + + - - + + - - - - + + + + - - + + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - - - - - + + + + + - + - - + + - - + + - - + + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + + {{ 'main.offline' | tr }} + + +