Convert entry deletion for split view

This commit is contained in:
Johannes Zellner
2022-08-25 19:38:02 +02:00
parent 093358810b
commit 862841e4c1
4 changed files with 270 additions and 199 deletions

View File

@@ -1,24 +1,4 @@
<!-- Modal remove entry -->
<div class="modal fade" id="{{ 'entryRemoveModal-' + $id }}" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<p class="text-bold text-danger" ng-show="entryRemove.error">{{ entryRemove.error }}</p>
<!-- TODO remove fileName later once all translations have been updated -->
<h4 ng-hide="entryRemove.error">{{ 'filemanager.removeDialog.reallyDelete' | tr:{ fileName: selected[0].fileName } }}</h4>
<ul>
<li ng-repeat="entry in selected">{{ entry.fileName }}</li>
</ul>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.no' | tr }}</button>
<button type="button" class="btn btn-danger" ng-click="entryRemove.submit()" ng-hide="entryRemove.error" ng-disabled="entryRemove.busy"><i class="fa fa-circle-notch fa-spin" ng-show="entryRemove.busy"></i> {{ 'main.dialog.yes' | tr }}</button>
</div>
</div>
</div>
</div>
<!-- Modal new directory -->
<div class="modal fade" id="{{ 'newDirectoryModal-' + $id }}" tabindex="-1" role="dialog">
<div class="modal-dialog">
@@ -157,11 +137,8 @@
</div>
</div>
<!-- main content -->
<div class="toolbar">
<div class="btn-group" role="group" style="display: block;">
<!-- TODO figure out why a line break in code between the two buttons results in a gap visually without any margin/padding set -->

View File

@@ -1,19 +1,24 @@
'use strict';
/* global angular */
/* global sanitize */
/* global sanitize, isModalVisible */
angular.module('Application').component('filetree', {
bindings: {
backendId: '<',
backendType: '<',
view: '<'
view: '<',
onUploadFile: '&',
onUploadFolder: '&',
onDeleteEntries: '&'
},
templateUrl: 'components/filetree.html?<%= revision %>',
controller: [ '$scope', '$translate', '$timeout', 'Client', FileTreeController ]
});
function FileTreeController($scope, $translate, $timeout, Client) {
var ctrl = this;
$scope.backendId = this.backendId;
$scope.backendType = this.backendType;
$scope.view = this.view;
@@ -30,6 +35,9 @@ function FileTreeController($scope, $translate, $timeout, Client) {
$scope.dropToBody = false;
$scope.applicationLink = '';
// register so parent can call child
$scope.$parent.registerChild($scope);
$scope.owners = [
{ name: 'cloudron', value: 1000 },
{ name: 'www-data', value: 33 },
@@ -305,6 +313,10 @@ function FileTreeController($scope, $translate, $timeout, Client) {
};
$scope.refresh = function () {
$scope.$parent.refresh();
};
$scope.onRefresh = function () {
$scope.selected = [];
Client.filesGet($scope.backendId, $scope.backendType, $scope.cwd, 'data', function (error, result) {
@@ -495,101 +507,9 @@ function FileTreeController($scope, $translate, $timeout, Client) {
$scope.selected = $scope.entries.slice();
};
$scope.uploadStatus = {
error: null,
busy: false,
fileName: '',
count: 0,
countDone: 0,
size: 0,
done: 0,
percentDone: 0,
files: [],
targetFolder: ''
};
function uploadFiles(files, targetFolder, overwrite) {
if (!files || !files.length) return;
targetFolder = targetFolder || $scope.cwd;
overwrite = !!overwrite;
// prevent it from getting closed
$('#uploadModal').modal({
backdrop: 'static',
keyboard: false
});
$scope.uploadStatus.files = files;
$scope.uploadStatus.targetFolder = targetFolder;
$scope.uploadStatus.error = null;
$scope.uploadStatus.busy = true;
$scope.uploadStatus.count = files.length;
$scope.uploadStatus.countDone = 0;
$scope.uploadStatus.size = 0;
$scope.uploadStatus.sizeDone = 0;
$scope.uploadStatus.done = 0;
$scope.uploadStatus.percentDone = 0;
for (var i = 0; i < files.length; ++i) {
$scope.uploadStatus.size += files[i].size;
}
async.eachSeries(files, function (file, callback) {
var filePath = sanitize(targetFolder + '/' + (file.webkitRelativePath || file.name));
$scope.uploadStatus.fileName = file.name;
Client.filesUpload($scope.backendId, $scope.backendType, filePath, file, overwrite, function (loaded) {
$scope.uploadStatus.percentDone = ($scope.uploadStatus.done+loaded) * 100 / $scope.uploadStatus.size;
$scope.uploadStatus.sizeDone = loaded;
}, function (error) {
if (error) return callback(error);
$scope.uploadStatus.done += file.size;
$scope.uploadStatus.percentDone = $scope.uploadStatus.done * 100 / $scope.uploadStatus.size;
$scope.uploadStatus.countDone++;
callback();
});
}, function (error) {
$scope.uploadStatus.busy = false;
if (error && error.statusCode === 409) {
$scope.uploadStatus.error = 'exists';
return;
} else if (error) {
console.error(error);
$scope.uploadStatus.error = 'generic';
return;
}
$('#uploadModal').modal('hide');
$scope.uploadStatus.fileName = '';
$scope.uploadStatus.count = 0;
$scope.uploadStatus.size = 0;
$scope.uploadStatus.sizeDone = 0;
$scope.uploadStatus.done = 0;
$scope.uploadStatus.percentDone = 100;
$scope.uploadStatus.files = [];
$scope.uploadStatus.targetFolder = '';
$scope.refresh();
});
}
$scope.retryUpload = function (overwrite) {
uploadFiles($scope.uploadStatus.files, $scope.uploadStatus.targetFolder, !!overwrite);
};
// file upload
$('#uploadFileInput').on('change', function (e) { uploadFiles(e.target.files || [], $scope.cwd, false); });
$scope.onUploadFile = function () { $('#uploadFileInput').click(); };
// folder upload
$('#uploadFolderInput').on('change', function (e ) { uploadFiles(e.target.files || [], $scope.cwd, false); });
$scope.onUploadFolder = function () { $('#uploadFolderInput').click(); };
// just events to the parent controller
$scope.onUploadFile = function () { ctrl.onUploadFile({ cwd: $scope.cwd }); };
$scope.onUploadFolder = function () { ctrl.onUploadFolder({ cwd: $scope.cwd }); };
$scope.restartBusy = false;
$scope.onRestartApp = function () {
@@ -799,35 +719,6 @@ function FileTreeController($scope, $translate, $timeout, Client) {
}
};
$scope.entryRemove = {
busy: false,
error: null,
show: function () {
$scope.entryRemove.error = null;
$('#entryRemoveModal-' + $scope.$id).modal('show');
},
submit: function () {
$scope.entryRemove.busy = true;
async.eachLimit($scope.selected, 5, function (entry, callback) {
var filePath = sanitize($scope.cwd + '/' + entry.fileName);
Client.filesRemove($scope.backendId, $scope.backendType, filePath, callback);
}, function (error) {
$scope.entryRemove.busy = false;
if (error) return Client.error(error);
$scope.refresh();
$('#entryRemoveModal-' + $scope.$id).modal('hide');
});
}
};
$translate(['filemanager.list.menu.edit', 'filemanager.list.menu.cut', 'filemanager.list.menu.copy', 'filemanager.list.menu.paste', 'filemanager.list.menu.rename', 'filemanager.list.menu.chown', 'filemanager.list.menu.extract', 'filemanager.list.menu.download', 'filemanager.list.menu.delete' ]).then(function (tr) {
$scope.menuOptions = [
{
@@ -865,7 +756,7 @@ function FileTreeController($scope, $translate, $timeout, Client) {
}, {
text: tr['filemanager.list.menu.delete'],
hasTopDivider: true,
click: function ($itemScope, $event, entry) { $scope.entryRemove.show(); }
click: function ($itemScope, $event, entry) { ctrl.onDeleteEntries({ cwd: $scope.cwd, entries: $scope.selected }); }
}
];
});
@@ -891,27 +782,6 @@ function FileTreeController($scope, $translate, $timeout, Client) {
];
});
$('.file-list').on('scroll', function (event) {
if (event.target.scrollTop > 10) event.target.classList.add('top-scroll-indicator');
else event.target.classList.remove('top-scroll-indicator');
});
// setup all the dialog focus handling
['newFileModal', 'newDirectoryModal', 'renameEntryModal'].forEach(function (id) {
$('#' + id).on('shown.bs.modal', function () {
$(this).find('[autofocus]:first').focus();
});
});
// selects filename (without extension)
['renameEntryModal'].forEach(function (id) {
$('#' + id).on('shown.bs.modal', function () {
var elem = $(this).find('[autofocus]:first');
var text = elem.val();
elem[0].setSelectionRange(0, text.indexOf('.'));
});
});
function scrollInView(element) {
if (!element) return;
@@ -970,6 +840,30 @@ function FileTreeController($scope, $translate, $timeout, Client) {
openPath('.');
// DOM handlers, wait for elements to exist
setTimeout(function () {
$('.file-list').on('scroll', function (event) {
if (event.target.scrollTop > 10) event.target.classList.add('top-scroll-indicator');
else event.target.classList.remove('top-scroll-indicator');
});
// setup all the dialog focus handling
['newFileModal', 'newDirectoryModal', 'renameEntryModal'].forEach(function (id) {
$('#' + id + '-' + $scope.$id).on('shown.bs.modal', function () {
$(this).find('[autofocus]:first').focus();
});
});
// selects filename (without extension)
['renameEntryModal'].forEach(function (id) {
$('#' + id + '-' + $scope.$id).on('shown.bs.modal', function () {
var elem = $(this).find('[autofocus]:first');
var text = elem.val();
elem[0].setSelectionRange(0, text.indexOf('.'));
});
});
}, 0);
// handle save shortcuts
window.addEventListener('keydown', function (event) {
if ($scope.$parent.activeView !== $scope.view || $scope.$parent.viewerOpen || isModalVisible()) return;