240 lines
16 KiB
HTML
240 lines
16 KiB
HTML
<!-- modal volume add -->
|
|
<div class="modal fade" id="volumeAddModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">{{ 'volumes.addVolumeDialog.title' | tr }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form name="volumeAddForm" role="form" novalidate ng-submit="volumeAdd.submit()" autocomplete="off">
|
|
<fieldset>
|
|
<p class="has-error text-center" ng-show="volumeAdd.error">{{ volumeAdd.error }}</p>
|
|
|
|
<div class="form-group">
|
|
<label class="control-label">{{ 'volumes.name' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeAdd.name" name="name" ng-disabled="volumeAdd.busy" ng-required="true" autofocus>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="control-label" for="mountType">{{ 'volumes.mountType' | tr }}</label>
|
|
<select class="form-control" id="mountType" ng-model="volumeAdd.mountType" ng-options="a.value as a.name for a in mountTypes"></select>
|
|
<p class="small">
|
|
<span class="text-warning" ng-show="volumeAdd.mountType === 'mountpoint'" ng-bind-html="'volumes.addVolumeDialog.mountpointWarning' | tr"></span>
|
|
<span class="text-info" ng-hide="volumeAdd.mountType === 'mountpoint' || volumeAdd.mountType === 'filesystem'" ng-bind-html="'volumes.addVolumeDialog.mountTypeInfo' | tr"></span>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'filesystem'">
|
|
<label class="control-label">{{ 'volumes.localDirectory' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeAdd.hostPath" name="hostPath" ng-disabled="volumeAdd.busy" placeholder="/srv/shared" ng-required="volumeAdd.mountType === 'filesystem'" autofocus>
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'mountpoint'">
|
|
<label class="control-label">{{ 'volumes.hostPath' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeAdd.hostPath" name="hostPath" ng-disabled="volumeAdd.busy" placeholder="/mnt/data" ng-required="volumeAdd.mountType === 'mountpoint'" autofocus>
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'ext4'">
|
|
<label class="control-label">{{ 'volumes.addVolumeDialog.diskPath' | tr }}</label>
|
|
<select class="form-control" ng-model="volumeAdd.ext4Disk" ng-options="item as item.label for item in ext4BlockDevices track by item.path" ng-required="volumeAdd.mountType === 'ext4'"></select>
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'xfs'">
|
|
<label class="control-label">{{ 'volumes.addVolumeDialog.diskPath' | tr }}</label>
|
|
<select class="form-control" ng-model="volumeAdd.xfsDisk" ng-options="item as item.label for item in xfsBlockDevices track by item.path" ng-required="volumeAdd.mountType === 'xfs'"></select>
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'cifs' || volumeAdd.mountType === 'nfs' || volumeAdd.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeAddHost">{{ 'volumes.addVolumeDialog.server' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeAdd.host" id="volumeAddHost" name="host" ng-disabled="volumeAdd.busy" placeholder="Server IP or hostname" ng-required="volumeAdd.mountType === 'cifs' || volumeAdd.mountType === 'nfs' || volumeAdd.mountType === 'sshfs'">
|
|
</div>
|
|
|
|
<div class="checkbox" ng-show="volumeAdd.mountType === 'cifs'">
|
|
<label>
|
|
<input type="checkbox" ng-model="volumeAdd.seal">{{ 'backups.configureBackupStorage.cifsSealSupport' | tr }}</input>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeAddPort">{{ 'volumes.addVolumeDialog.port' | tr }}</label>
|
|
<input type="number" class="form-control" ng-model="volumeAdd.port" id="volumeAddPort" name="port" ng-disabled="volumeAdd.busy" ng-required="volumeAdd.mountType === 'sshfs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'cifs' || volumeAdd.mountType === 'nfs' || volumeAdd.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeAddRemoteDir">{{ 'volumes.addVolumeDialog.remoteDirectory' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeAdd.remoteDir" id="volumeAddRemoteDir" name="remoteDir" ng-disabled="volumeAdd.busy" placeholder="/share" ng-required="volumeAdd.mountType === 'cifs' || volumeAdd.mountType === 'nfs' || volumeAdd.mountType === 'sshfs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'cifs'">
|
|
<label class="control-label" for="volumeAddUsername">{{ 'volumes.addVolumeDialog.username' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeAdd.username" id="volumeAddUsername" name="cifsUsername" ng-disabled="volumeAdd.busy" ng-required="volumeAdd.mountType === 'cifs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'cifs'">
|
|
<label class="control-label" for="volumeAddPassword">{{ 'volumes.addVolumeDialog.password' | tr }}</label>
|
|
<input type="password" class="form-control" ng-model="volumeAdd.password" id="volumeAddPassword" name="cifsPassword" ng-disabled="volumeAdd.busy" password-reveal ng-required="volumeAdd.mountType === 'cifs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeAddUser">{{ 'volumes.addVolumeDialog.user' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeAdd.user" id="volumeAddUser" name="user" ng-disabled="volumeAdd.busy" ng-required="volumeAdd.mountType === 'sshfs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeAdd.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeAddPrivateKey">{{ 'volumes.addVolumeDialog.privateKey' | tr }}</label>
|
|
<textarea class="form-control" ng-model="volumeAdd.privateKey" id="volumeAddPrivateKey" name="privateKey" ng-disabled="volumeAdd.busy" ng-required="volumeAdd.mountType === 'sshfs'"></textarea>
|
|
</div>
|
|
|
|
<input class="ng-hide" type="submit" ng-disabled="volumeAddForm.$invalid || volumeAdd.busy"/>
|
|
</fieldset>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer ">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
|
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="volumeAdd.submit()" ng-disabled="volumeAddForm.$invalid || volumeAdd.busy"><i class="fa fa-circle-notch fa-spin" ng-show="volumeAdd.busy"></i> {{ 'main.dialog.save' | tr }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- modal volume edit -->
|
|
<div class="modal fade" id="volumeEditModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">{{ 'volumes.editVolumeDialog.title' | tr:{ name: volumeEdit.name } }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form name="volumeEditForm" role="form" novalidate ng-submit="volumeEdit.submit()" autocomplete="off">
|
|
<fieldset>
|
|
<p class="has-error text-center" ng-show="volumeEdit.error">{{ volumeEdit.error }}</p>
|
|
|
|
<div><b>{{ 'volumes.mountType' | tr }}:</b> {{ volumeEdit.mountType }}</div>
|
|
<br/>
|
|
|
|
<div class="form-group" ng-show="volumeEdit.mountType === 'cifs' || volumeEdit.mountType === 'nfs' || volumeEdit.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeAddHost">{{ 'volumes.addVolumeDialog.server' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeEdit.host" id="volumeEditHost" name="host" ng-disabled="volumeEdit.busy" placeholder="Server IP or hostname" ng-required="volumeEdit.mountType === 'cifs' || volumeEdit.mountType === 'nfs' || volumeEdit.mountType === 'sshfs'">
|
|
</div>
|
|
|
|
<div class="checkbox" ng-show="volumeEdit.mountType === 'cifs'">
|
|
<label>
|
|
<input type="checkbox" ng-model="volumeEdit.seal">{{ 'backups.configureBackupStorage.cifsSealSupport' | tr }}</input>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeEdit.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeEditPort">{{ 'volumes.addVolumeDialog.port' | tr }}</label>
|
|
<input type="number" class="form-control" ng-model="volumeEdit.port" id="volumeEditPort" name="port" ng-disabled="volumeEdit.busy" ng-required="volumeEdit.mountType === 'sshfs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeEdit.mountType === 'cifs' || volumeEdit.mountType === 'nfs' || volumeEdit.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeEditRemoteDir">{{ 'volumes.addVolumeDialog.remoteDirectory' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeEdit.remoteDir" id="volumeAddRemoteDir" name="remoteDir" ng-disabled="volumeEdit.busy" placeholder="/share" ng-required="volumeEdit.mountType === 'cifs' || volumeAdd.mountType === 'nfs' || volumeAdd.mountType === 'sshfs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeEdit.mountType === 'cifs'">
|
|
<label class="control-label" for="volumeEditUsername">{{ 'volumes.addVolumeDialog.username' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeEdit.username" id="volumeEditUsername" name="cifsUsername" ng-disabled="volumeEdit.busy" ng-required="volumeEdit.mountType === 'cifs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeEdit.mountType === 'cifs'">
|
|
<label class="control-label" for="volumeEditPassword">{{ 'volumes.addVolumeDialog.password' | tr }}</label>
|
|
<input type="password" class="form-control" ng-model="volumeEdit.password" id="volumeEditPassword" name="cifsPassword" ng-disabled="volumeEdit.busy" password-reveal ng-required="volumeEdit.mountType === 'cifs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeEdit.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeEditUser">{{ 'volumes.addVolumeDialog.user' | tr }}</label>
|
|
<input type="text" class="form-control" ng-model="volumeEdit.user" id="volumeEditAddUser" name="user" ng-disabled="volumeEdit.busy" ng-required="volumeEdit.mountType === 'sshfs'">
|
|
</div>
|
|
|
|
<div class="form-group" ng-show="volumeEdit.mountType === 'sshfs'">
|
|
<label class="control-label" for="volumeEditPrivateKey">{{ 'volumes.addVolumeDialog.privateKey' | tr }}</label>
|
|
<textarea class="form-control" ng-model="volumeEdit.privateKey" id="volumeEditPrivateKey" name="privateKey" ng-disabled="volumeEdit.busy" ng-required="volumeEdit.mountType === 'sshfs'"></textarea>
|
|
</div>
|
|
|
|
<input class="ng-hide" type="submit" ng-disabled="volumeEditForm.$invalid || volumeEdit.busy"/>
|
|
</fieldset>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer ">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
|
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="volumeEdit.submit()" ng-disabled="volumeEditForm.$invalid || volumeEdit.busy"><i class="fa fa-circle-notch fa-spin" ng-show="volumeEdit.busy"></i> {{ 'main.dialog.save' | tr }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Modal volume remove -->
|
|
<div class="modal fade" id="volumeRemoveModal" tabindex="-1" role="dialog">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h4 class="modal-title">{{ 'volumes.removeVolumeDialog.title' | tr:{ volume:volumeRemove.volume.name } }}</h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<p ng-bind-html="'volumes.removeVolumeDialog.description' | tr:{ volume:volumeRemove.volume.name }"></p>
|
|
<p class="has-error" ng-show="volumeRemove.error">{{ volumeRemove.error }}</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'main.dialog.cancel' | tr }}</button>
|
|
<button type="button" class="btn btn-danger" ng-click="volumeRemove.submit()" ng-disabled="volumeRemove.busy"><i class="fa fa-circle-notch fa-spin" ng-show="volumeRemove.busy"></i> {{ 'volumes.removeVolumeDialog.removeAction' | tr }}</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="content">
|
|
<h1 class="section-header">
|
|
{{ 'volumes.title' | tr }}
|
|
<button class="btn btn-primary btn-outline" ng-click="volumeAdd.show()"><i class="fa fa-plus"></i> {{ 'volumes.addVolumeAction' | tr }}</button>
|
|
</h1>
|
|
|
|
<div class="card card-large">
|
|
<p ng-bind-html="'volumes.description' | tr"></p>
|
|
|
|
<div class="row ng-hide" ng-show="!ready">
|
|
<div class="col-lg-12 text-center">
|
|
<h2><i class="fa fa-circle-notch fa-spin"></i></h2>
|
|
</div>
|
|
</div>
|
|
<div class="row animateMeOpacity ng-hide" ng-show="ready">
|
|
<div class="col-lg-12">
|
|
<table class="table table-hover" style="margin-top: 10px; table-layout: fixed;">
|
|
<thead>
|
|
<tr>
|
|
<th style="width: 30px"></th>
|
|
<th class="text-left">{{ 'volumes.name' | tr }}</th>
|
|
<th class="text-left">{{ 'volumes.type' | tr }}</th>
|
|
<th class="text-left hide-mobile" style="width: 40%;">{{ 'volumes.hostPath' | tr }}</th>
|
|
<th class="text-right">{{ 'main.actions' | tr }}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr ng-repeat="volume in volumes">
|
|
<td>
|
|
<i class="fa fa-circle" ng-style="{ color: volume.status.state === 'active' ? '#27CE65' : '#d9534f' }" ng-show="volume.status" uib-tooltip="{{ volume.status.message }}"></i>
|
|
<i class="fa fa-circle-notch fa-spin" ng-hide="volume.status"></i>
|
|
</td>
|
|
<td>
|
|
{{ volume.name }}
|
|
</td>
|
|
<td>
|
|
{{ volume.mountType }}
|
|
</td>
|
|
<td class="hide-mobile" style="text-wrap: nowrap; overflow: hidden; text-overflow: ellipsis;" ng-hide="(volume.mountType === 'mountpoint' || volume.mountType === 'filesystem')">{{ volume.mountOptions.host || volume.mountOptions.diskPath || volume.hostPath }}{{ volume.mountOptions.remoteDir }}</td>
|
|
<td class="hide-mobile" style="text-wrap: nowrap; overflow: hidden; text-overflow: ellipsis;" ng-show="(volume.mountType === 'mountpoint' || volume.mountType === 'filesystem')">{{ volume.hostPath }}</td>
|
|
<td class="text-right" style="text-wrap: nowrap;">
|
|
<button class="btn btn-xs btn-default" ng-click="remount(volume)" ng-show="isMountProvider(volume.mountType)" ng-disabled="volume.remounting" uib-tooltip="{{ 'volumes.remountActionTooltip' | tr }}"><i class="fa fa-sync-alt" ng-class="{ 'fa-spin': volume.remounting }"></i></button>
|
|
<button class="btn btn-xs btn-default" ng-click="volumeEdit.show(volume)" ng-show="isNetworkProvider(volume.mountType)" ng-disabled="volume.remounting" uib-tooltip="{{ 'volumes.editActionTooltip' | tr }}"><i class="fa fa-pencil-alt"></i></button>
|
|
<a class="btn btn-xs btn-default" ng-href="{{ '/filemanager.html#/home/volume/' + volume.id }}" target="_blank" uib-tooltip="{{ 'volumes.openFileManagerActionTooltip' | tr }}"><i class="fas fa-folder"></i></a>
|
|
<button class="btn btn-xs btn-danger" ng-click="volumeRemove.show(volume)" uib-tooltip="{{ 'volumes.removeVolumeActionTooltip' | tr }}"><i class="far fa-trash-alt"></i></button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|