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 }}
+
+
+
+
+
+
+
+
+
+ | Type |
+ Name |
+ Size |
+ Owner |
+ Actions |
+
+
+
+
+ |
+ 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();
+}]);