From 7c2ab4e5bd8e191a74f2ed3779a911e6ef160537 Mon Sep 17 00:00:00 2001 From: Johannes Zellner Date: Wed, 8 Jul 2020 17:30:37 +0200 Subject: [PATCH] Initial filemanager view --- gulpfile.js | 12 +++- src/filemanager.html | 113 ++++++++++++++++++++++++++++++++++++ src/js/client.js | 10 ++++ src/js/filemanager.js | 129 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 263 insertions(+), 1 deletion(-) create mode 100644 src/filemanager.html create mode 100644 src/js/filemanager.js diff --git a/gulpfile.js b/gulpfile.js index 6a8ae9f07..62b568047 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -105,6 +105,15 @@ gulp.task('js-logs', function () { .pipe(gulp.dest('dist/js')); }); +gulp.task('js-filemanager', function () { + return gulp.src(['src/js/filemanager.js', 'src/js/client.js']) + .pipe(ejs({ apiOrigin: apiOrigin, appstore: appstore }, {}, { ext: '.js' })) + .pipe(sourcemaps.init()) + .pipe(concat('filemanager.js', { newLine: ';' })) + .pipe(sourcemaps.write()) + .pipe(gulp.dest('dist/js')); +}); + gulp.task('js-terminal', function () { return gulp.src(['src/js/terminal.js', 'src/js/client.js']) .pipe(ejs({ apiOrigin: apiOrigin, appstore: appstore }, {}, { ext: '.js' })) @@ -159,7 +168,7 @@ gulp.task('js-restore', function () { .pipe(gulp.dest('dist/js')); }); -gulp.task('js', gulp.series([ 'js-index', 'js-logs', 'js-terminal', 'js-login', 'js-setupaccount', 'js-setup', 'js-setupdns', 'js-restore' ])); +gulp.task('js', gulp.series([ 'js-index', 'js-logs', 'js-filemanager', 'js-terminal', 'js-login', 'js-setupaccount', 'js-setup', 'js-setupdns', 'js-restore' ])); // -------------- // HTML @@ -225,6 +234,7 @@ gulp.task('watch', function (done) { gulp.watch(['src/js/setupdns.js', 'src/js/client.js'], gulp.series(['js-setupdns'])); gulp.watch(['src/js/restore.js', 'src/js/client.js'], gulp.series(['js-restore'])); gulp.watch(['src/js/logs.js', 'src/js/client.js'], gulp.series(['js-logs'])); + gulp.watch(['src/js/filemanager.js', 'src/js/client.js'], gulp.series(['js-filemanager'])); gulp.watch(['src/js/terminal.js', 'src/js/client.js'], gulp.series(['js-terminal'])); gulp.watch(['src/js/login.js'], gulp.series(['js-login'])); gulp.watch(['src/js/setupaccount.js'], gulp.series(['js-setupaccount'])); diff --git a/src/filemanager.html b/src/filemanager.html new file mode 100644 index 000000000..4f4b62462 --- /dev/null +++ b/src/filemanager.html @@ -0,0 +1,113 @@ + + + + + + + FileManager + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cloudron is offline. Reconnecting... + +
+
+
+
+
+

FileManager for {{ app.fqdn }}

+ +
+
+ +
+ + Path: {{ cwd }} + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameSizeOwnerActions
Up
+ + + {{ entry.filePath }}{{ entry.size | prettyDiskSize }}{{ entry.uid | prettyOwner }} + +
+
+
+
+
+ + + diff --git a/src/js/client.js b/src/js/client.js index fc24328a8..3af492d1d 100644 --- a/src/js/client.js +++ b/src/js/client.js @@ -2384,6 +2384,16 @@ angular.module('Application').service('Client', ['$http', '$interval', '$timeout }); }; + // FileManager API + Client.prototype.filesGet = function (appId, path, callback) { + get('/api/v1/apps/' + appId + '/files/' + path, null, function (error, data, status) { + if (error) return callback(error); + if (status !== 200) return callback(new ClientError(status, data)); + + callback(null, data); + }); + }; + client = new Client(); return client; }]); diff --git a/src/js/filemanager.js b/src/js/filemanager.js new file mode 100644 index 000000000..06b10d0ea --- /dev/null +++ b/src/js/filemanager.js @@ -0,0 +1,129 @@ +'use strict'; + +/* global angular */ + +// create main application module +var app = angular.module('Application', ['angular-md5', 'ui-notification']); + +angular.module('Application').filter('prettyOwner', function () { + return function (uid) { + if (uid === 1) return 'root'; + if (uid === 33) return 'cloudron'; + if (uid === 1000) return 'cloudron'; + if (uid === 1001) return 'git'; + + return 'unkown'; + } +}); + +app.controller('FileManagerController', ['$scope', 'Client', function ($scope, Client) { + var search = decodeURIComponent(window.location.search).slice(1).split('&').map(function (item) { return item.split('='); }).reduce(function (o, k) { o[k[0]] = k[1]; return o; }, {}); + + $scope.initialized = false; + $scope.client = Client; + $scope.cwd = '/'; + $scope.appId = search.appId; + $scope.app = null; + $scope.entries = []; + + function sanitize(filePath) { + filePath = filePath.split('/').filter(function (a) { return !!a; }).reduce(function (a, v) { + if (v === '.'); // do nothing + else if (v === '..') a.pop(); + else a.push(v); + return a; + }, []).join('/'); + + return '/' + filePath; + } + + $scope.refresh = function () { + Client.filesGet($scope.appId, $scope.cwd, function (error, result) { + if (error) return Client.error(error); + + console.log(result); + + $scope.entries = result.entries; + }); + }; + + $scope.uploadFile = function () { + console.log('uploadFile'); + }; + + $scope.uploadFolder = function () { + console.log('uploadFolder'); + }; + + $scope.remove = function (entry) { + console.log('remove', entry); + }; + + $scope.open = function (entry) { + if (entry.isDirectory) { + setDirectory($scope.cwd + '/' + entry.filePath); + } else if (entry.isFile) { + console.log('open', entry) + } else {} + }; + + $scope.goDirectoryUp = function () { + setDirectory($scope.cwd + '/..') + }; + + function setDirectory(path) { + path = sanitize(path); + + if ($scope.cwd === path) return; + + $scope.cwd = path; + $scope.refresh(); + } + + function init() { + + Client.getStatus(function (error, status) { + if (error) return Client.initError(error, init); + + if (!status.activated) { + console.log('Not activated yet, redirecting', status); + window.location.href = '/'; + return; + } + + // check version and force reload if needed + if (!localStorage.version) { + localStorage.version = status.version; + } else if (localStorage.version !== status.version) { + localStorage.version = status.version; + window.location.reload(true); + } + + console.log('Running filemanager version ', localStorage.version); + + // get user profile as the first thing. this populates the "scope" and affects subsequent API calls + Client.refreshUserInfo(function (error) { + if (error) return Client.initError(error, init); + + Client.refreshConfig(function (error) { + if (error) return Client.initError(error, init); + + Client.getApp($scope.appId, function (error, result) { + if (error) return Client.initError(error, init); + + $scope.app = result; + + // now mark the Client to be ready + Client.setReady(); + + $scope.refresh(); + + $scope.initialized = true; + }); + }); + }); + }); + } + + init(); +}]);