Initial filemanager view

This commit is contained in:
Johannes Zellner
2020-07-08 17:30:37 +02:00
parent b86dff8601
commit 7c2ab4e5bd
4 changed files with 263 additions and 1 deletions

113
src/filemanager.html Normal file
View File

@@ -0,0 +1,113 @@
<!DOCTYPE html>
<html ng-app="Application" ng-controller="FileManagerController">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
<title> FileManager </title>
<link id="favicon" href="/api/v1/cloudron/avatar" rel="icon" type="image/png">
<link rel="apple-touch-icon" href="/api/v1/cloudron/avatar">
<link rel="icon" href="/api/v1/cloudron/avatar">
<!-- CSS -->
<link type="text/css" rel="stylesheet" href="/3rdparty/angular-ui-notification.css"/>
<link type="text/css" rel="stylesheet" href="/theme.css">
<!-- Custom Fonts -->
<link type="text/css" rel="stylesheet" href="/3rdparty/fontawesome/css/all.min.css">
<!-- jQuery-->
<script type="text/javascript" src="/3rdparty/js/jquery.min.js"></script>
<!-- async -->
<script type="text/javascript" src="/3rdparty/js/async-3.2.0.min.js"></script>
<!-- Bootstrap Core JavaScript -->
<script type="text/javascript" src="/3rdparty/js/bootstrap.min.js"></script>
<!-- Angularjs scripts -->
<script type="text/javascript" src="/3rdparty/js/angular.min.js"></script>
<script type="text/javascript" src="/3rdparty/js/angular-loader.min.js"></script>
<script type="text/javascript" src="/3rdparty/js/angular-animate.min.js"></script>
<script type="text/javascript" src="/3rdparty/js/angular-base64.min.js"></script>
<script type="text/javascript" src="/3rdparty/js/angular-md5.min.js"></script>
<script type="text/javascript" src="/3rdparty/js/angular-sanitize.min.js"></script>
<script type="text/javascript" src="/3rdparty/js/angular-ui-notification.js"></script>
<!-- Angular directives for bootstrap https://angular-ui.github.io/bootstrap/ -->
<script type="text/javascript" src="/3rdparty/js/ui-bootstrap-tpls-1.3.3.min.js"></script>
<!-- colors -->
<script type="text/javascript" src="/3rdparty/js/colors.js"></script>
<!-- moment -->
<script type="text/javascript" src="/3rdparty/js/moment.min.js"></script>
<!-- Main Application -->
<script type="text/javascript" src="/js/filemanager.js"></script>
</head>
<body class="filemanager">
<a class="offline-banner animateMe" ng-show="client.offline" ng-cloak href="https://cloudron.io/documentation/troubleshooting/" target="_blank"><i class="fa fa-circle-notch fa-spin"></i> Cloudron is offline. Reconnecting...</a>
<div class="main-container animateMe ng-hide " ng-show="initialized">
<br/>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="card">
<h3>FileManager for {{ app.fqdn }}</h3>
<br/>
<br/>
<div>
<button class="btn btn-primary" ng-click="refresh()"><i class="fas fa-sync-alt"></i></button>
<span>Path: <b>{{ cwd }}</b></span>
<button class="btn btn-primary pull-right" ng-click="uploadFile()">Upload File</button>
<button class="btn btn-primary pull-right" ng-click="uploadFolder()">Upload Folder</button>
</div>
<br/>
<table class="table table-hover" style="margin: 0;">
<thead>
<tr>
<th style="width: 5%;">Type</th>
<th style="width:65%">Name</th>
<th style="width:10%">Size</th>
<th style="width:10%">Owner</th>
<th style="width: 10%" class="text-right">Actions</th>
</tr>
</thead>
<tbody>
<tr ng-disabled="cwd === '/'">
<td><i class="fas fa-level-up-alt"></i></td>
<td class="hand elide-table-cell" ng-click="goDirectoryUp()">Up</td>
<td class="text-right no-wrap" style="vertical-align: bottom"></td>
<td class="text-right no-wrap" style="vertical-align: bottom"></td>
<td class="text-right no-wrap" style="vertical-align: bottom"></td>
</tr>
<tr ng-repeat="entry in entries">
<td>
<i class="fas fa-folder" ng-show="entry.isDirectory"></i>
<i class="far fa-file" ng-show="entry.isFile"></i>
</td>
<td class="hand elide-table-cell" ng-click="open(entry)">{{ entry.filePath }}</td>
<td class="hand elide-table-cell" ng-click="open(entry)">{{ entry.size | prettyDiskSize }}</td>
<td class="hand elide-table-cell" ng-click="open(entry)">{{ entry.uid | prettyOwner }}</td>
<td class="text-right no-wrap" style="vertical-align: bottom">
<button class="btn btn-xs btn-danger" ng-click="remove(entry)"><i class="far fa-trash-alt"></i></button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -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;
}]);

129
src/js/filemanager.js Normal file
View File

@@ -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();
}]);