Files
cloudron-box/webadmin/src/views/settings.html

458 lines
26 KiB
HTML
Raw Normal View History

<!-- Modal change avatar -->
<div class="modal fade" id="avatarChangeModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Change your Cloudron Avatar</h4>
</div>
<div class="modal-body settings-avatar-selector">
<img id="previewAvatar" width="128" height="128" ng-src="{{avatarChange.avatar.data || avatarChange.avatar.url || client.avatar}}"/>
<input type="file" id="avatarFileInput" style="display: none" accept="image/png"/>
<br/>
<br/>
<div class="grid">
<div class="item" ng-repeat="avatar in avatarChange.availableAvatars" style="background-image: url('{{avatar.data || avatar.url}}');" ng-click="avatarChange.setPreviewAvatar(avatar)"></div>
<div class="item add" ng-click="avatarChange.showCustomAvatarSelector()"></div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
2017-01-29 02:01:01 -08:00
<button type="button" class="btn btn-success" ng-click="avatarChange.doChangeAvatar()" ng-disabled="avatarChange.busy"><i class="fa fa-circle-o-notch fa-spin" ng-show="avatarChange.busy"></i> Change</button>
</div>
</div>
</div>
</div>
<!-- Modal change cloudron name -->
<div class="modal fade" id="cloudronNameChangeModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Change Cloudron Name</h4>
</div>
<div class="modal-body">
<form name="cloudronNameChangeForm" role="form" novalidate ng-submit="cloudronNameChange.submit()" autocomplete="off">
<div class="form-group" ng-class="{ 'has-error': (cloudronNameChangeForm.name.$dirty && cloudronNameChangeForm.name.$invalid) }">
<label class="control-label">Name</label>
<div class="control-label" ng-show="(!cloudronNameChangeForm.name.$dirty && cloudronNameChange.error.name) || (cloudronNameChangeForm.name.$dirty && cloudronNameChangeForm.name.$invalid)">
<small ng-show="cloudronNameChangeForm.name.$error.required">A name is required</small>
<small ng-show="cloudronNameChangeForm.name.$error.maxlength">The name is too long</small>
<small ng-show="!cloudronNameChangeForm.name.$dirty && cloudronNameChange.error.name">{{ cloudronNameChange.error.name }}</small>
</div>
<input type="text" class="form-control" ng-model="cloudronNameChange.name" name="name" id="inputCloudronName" ng-maxlength="30" required autofocus>
</div>
<input class="ng-hide" type="submit" ng-disabled="cloudronNameChangeForm.$invalid"/>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
2017-01-29 02:01:01 -08:00
<button type="button" class="btn btn-success" ng-click="cloudronNameChange.submit()" ng-disabled="cloudronNameChangeForm.$invalid || cloudronNameChange.busy"><i class="fa fa-circle-o-notch fa-spin" ng-show="cloudronNameChange.busy"></i> Change</button>
</div>
</div>
</div>
</div>
<!-- Modal backup failed -->
<div class="modal fade" id="createBackupFailedModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Unable to create backup</h4>
</div>
<div class="modal-body">
{{ createBackup.errorMessage }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-success" data-dismiss="modal">OK</button>
</div>
</div>
</div>
</div>
2016-06-28 13:45:50 -05:00
<!-- Modal plan change -->
2016-06-28 14:02:45 -05:00
<div class="modal fade" id="planChangeModal" tabindex="-1" role="dialog">
2016-06-28 13:45:50 -05:00
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">Cloudron Change Plan</h4>
</div>
<div class="modal-body">
2016-06-30 10:27:29 -05:00
This will change your plan from <b>{{ currentPlan.name }}</b> to <b>{{ planChange.requestedPlan.name }}</b>.
2016-06-28 13:45:50 -05:00
<br/>
<br/>
Your apps and data will be migrated to the new Cloudron and will take around 15 minutes.
2016-06-28 14:02:45 -05:00
<br/>
2016-06-28 14:36:19 -05:00
<br/>
<br/>
<form name="planChangeForm" role="form" novalidate ng-submit="planChange.doChangePlan(planChangeForm)" autocomplete="off">
2016-06-28 14:02:45 -05:00
<fieldset>
<input type="password" style="display: none;">
2016-06-28 14:02:45 -05:00
<div class="form-group" ng-class="{ 'has-error': (!planChangeForm.password.$dirty && planChange.error.password) || (planChangeForm.password.$dirty && planChangeForm.password.$invalid) }">
<label class="control-label" for="inputDeveloperModeChangePassword">Give your password to verify that you are performing that action</label>
<div class="control-label" ng-show="(!planChangeForm.password.$dirty && planChange.error.password) || (planChangeForm.password.$dirty && planChangeForm.password.$invalid)">
<small ng-show=" planChangeForm.password.$dirty && planChangeForm.password.$invalid">A password is required</small>
<small ng-show="!planChangeForm.password.$dirty && planChange.error.password">Wrong password</small>
</div>
2016-06-28 14:36:19 -05:00
<input type="password" class="form-control" ng-model="planChange.password" id="inputPlanChangePassword" name="password" required autofocus>
2016-06-28 14:02:45 -05:00
</div>
<input class="ng-hide" type="submit" ng-disabled="planChangeForm.$invalid"/>
</fieldset>
</form>
2016-06-28 13:45:50 -05:00
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
2017-01-29 02:01:01 -08:00
<button type="button" class="btn btn-success" ng-click="planChange.doChangePlan()" ng-disabled="planChange.busy"><i class="fa fa-circle-o-notch fa-spin" ng-show="planChange.busy"></i> Confirm</button>
2016-06-28 13:45:50 -05:00
</div>
</div>
</div>
</div>
<!-- modal backup config -->
<div class="modal fade" id="configureBackupModal" tabindex="-1" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Configure Backup Storage</h4>
</div>
<div class="modal-body">
<p>Cloudron makes a complete backup of your system every day.</p>
<form name="configureBackupForm" role="form" novalidate ng-submit="configureBackup.submit()" autocomplete="off">
<fieldset>
<p class="has-error text-center" ng-show="configureBackup.error">{{ configureBackup.error.generic }}</p>
<div class="form-group">
<label class="control-label" for="storageProviderProvider">Storage provider <sup><a ng-href="{{ config.webServerOrigin }}/references/selfhosting/#backups" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
<select class="form-control" id="storageProviderProvider" ng-model="configureBackup.provider" ng-options="a.value as a.name for a in storageProvider" ng-change=configureBackup.clearForm()></select>
</div>
<!-- Noop -->
<div class="form-group" ng-show="configureBackup.provider === 'noop'">
<p class="has-error">
This option breaks the backup and restore functionality of Cloudron and should only be used for testing. Please make sure the server is completely backed up using alternate means.
</p>
</div>
<!-- Filesystem -->
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.backupFolder }" ng-show="configureBackup.provider === 'filesystem'">
<label class="control-label" for="inputConfigureBackupFolder">Local backup directory</label>
2017-09-19 11:58:20 -07:00
<input type="text" class="form-control" ng-model="configureBackup.backupFolder" id="inputConfigureBackupFolder" name="backupFolder" ng-disabled="configureBackup.busy" placeholder="Directory for backups" ng-required="configureBackup.provider === 'filesystem'">
2017-04-23 22:28:12 -07:00
<p class="has-error" ng-show="configureBackup.provider === 'filesystem'">
Please ensure that the backup directory is an external disk
</p>
</div>
2017-07-25 15:05:55 -07:00
<!-- S3/Minio/SOS -->
2017-09-21 12:13:43 -07:00
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.endpoint }" ng-show="configureBackup.provider === 'minio' || configureBackup.provider === 's3-v4-compat'">
2017-04-22 13:47:44 -07:00
<label class="control-label" for="inputConfigureBackupEndpoint">Endpoint</label>
2017-09-21 12:13:43 -07:00
<input type="text" class="form-control" ng-model="configureBackup.endpoint" id="inputConfigureBackupEndpoint" name="endpoint" ng-disabled="configureBackup.busy" placeholder="URL of Minio/S3 Compatible" ng-required="configureBackup.provider === 'minio' || configureBackup.provider === 's3-v4-compat'">
2017-04-22 13:47:44 -07:00
</div>
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.bucket }" ng-show="s3like(configureBackup.provider)">
2016-10-11 10:54:33 +02:00
<label class="control-label" for="inputConfigureBackupBucket">Bucket name</label>
<input type="text" class="form-control" ng-model="configureBackup.bucket" id="inputConfigureBackupBucket" name="bucket" ng-disabled="configureBackup.busy" ng-required="s3like(configureBackup.provider)">
</div>
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.prefix }" ng-show="s3like(configureBackup.provider)">
2016-10-11 10:54:33 +02:00
<label class="control-label" for="inputConfigureBackupPrefix">Prefix</label>
<input type="text" class="form-control" ng-model="configureBackup.prefix" id="inputConfigureBackupPrefix" name="prefix" ng-disabled="configureBackup.busy" placeholder="Prefix for backup file names">
</div>
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.region }" ng-show="configureBackup.provider === 's3'">
<label class="control-label" for="inputConfigureBackupRegion">Region</label>
<select class="form-control" name="region" id="inputConfigureBackupRegion" ng-model="configureBackup.region" ng-options="a.value as a.name for a in s3Regions" ng-disabled="configureBackup.busy" ng-required="configureBackup.provider === 's3'"></select>
2016-10-11 14:20:31 +02:00
</div>
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.accessKeyId }" ng-show="s3like(configureBackup.provider)">
<label class="control-label" for="inputConfigureBackupAccessKeyId">Access key id</label>
<input type="text" class="form-control" ng-model="configureBackup.accessKeyId" id="inputConfigureBackupAccessKeyId" name="accessKeyId" ng-disabled="configureBackup.busy" ng-required="s3like(configureBackup.provider)">
</div>
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.secretAccessKey }" ng-show="s3like(configureBackup.provider)">
<label class="control-label" for="inputConfigureBackupSecretAccessKey">Secret access key</label>
<input type="text" class="form-control" ng-model="configureBackup.secretAccessKey" id="inputConfigureBackupSecretAccessKey" name="secretAccessKey" ng-disabled="configureBackup.busy" ng-required="s3like(configureBackup.provider)">
</div>
2017-09-26 10:46:02 -07:00
<div class="form-group" ng-show="configureBackup.provider !== 'noop'">
<label class="control-label" for="storageFormat">Storage Format</label>
<select class="form-control" id="storageFormat" ng-change="configureBackup.key = ''" ng-model="configureBackup.format" ng-options="a.value as a.name for a in formats"></select>
2017-09-26 10:46:02 -07:00
</div>
<div class="form-group" ng-show="configureBackup.provider !== 'noop'">
<label class="control-label" for="storageRetention">Retention Time</label>
<select class="form-control" id="storageRetention" ng-model="configureBackup.retentionSecs" ng-options="a.value as a.name for a in retentionTimes"></select>
</div>
2017-09-26 10:46:02 -07:00
<div class="form-group" ng-class="{ 'has-error': configureBackup.error.key }" ng-show="configureBackup.provider !== 'noop' && configureBackup.format === 'tgz'">
<label class="control-label" for="inputConfigureBackupKey">Encryption key (optional)</label>
2017-02-09 13:20:42 -08:00
<input type="text" class="form-control" ng-model="configureBackup.key" id="inputConfigureBackupKey" name="prefix" ng-disabled="configureBackup.busy" placeholder="Passphrase used to encrypt the backups">
2016-12-19 12:41:35 -08:00
</div>
<input class="ng-hide" type="submit" ng-disabled="configureBackupForm.$invalid"/>
</fieldset>
</form>
</div>
<div class="modal-footer ">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-outline btn-success pull-right" ng-click="configureBackup.submit()" ng-disabled="configureBackupForm.$invalid || configureBackup.busy">
2017-01-29 02:01:01 -08:00
<i class="fa fa-circle-o-notch fa-spin" ng-show="configureBackup.busy"></i><span>Save</span>
</button>
</div>
</div>
</div>
</div>
<div class="content">
<div class="text-left">
<h1>Settings</h1>
</div>
<div class="text-left">
<h3>About</h3>
</div>
<div class="card" style="margin-bottom: 15px;">
<div class="row">
<div class="col-xs-4" style="min-width: 150px;">
<div class="settings-avatar" ng-click="avatarChange.showChangeAvatar()" style="background-image: url('{{ client.avatar }}');">
<div class="overlay"></div>
</div>
</div>
<div class="col-xs-8">
<table width="100%">
<tr>
<td class="text-muted" style="vertical-align: top;">Name</td>
<td class="text-right" style="vertical-align: top; white-space: nowrap;">{{ config.cloudronName }} <a href="" ng-click="cloudronNameChange.show()"><i class="fa fa-pencil text-small"></i></a></td>
</tr>
<tr ng-show="config.provider === 'caas'">
<td class="text-muted" style="vertical-align: top;">Model</td>
<td class="text-right" style="vertical-align: top; white-space: nowrap;">{{ config.size }} - {{ config.region }}</td>
</tr>
<tr>
<td class="text-muted" style="vertical-align: top;">Version</td>
<td class="text-right" style="vertical-align: top; white-space: nowrap;">{{ config.version }}</td>
</tr>
<tr>
<td class="text-muted" style="vertical-align: top;">Provider</td>
<td class="text-right" style="vertical-align: top; white-space: nowrap;">{{ config.provider }}</td>
</tr>
</table>
</div>
</div>
</div>
<div class="text-left" ng-show="config.provider === 'caas'">
<h3>Plans</h3>
</div>
<div class="card" style="margin-bottom: 15px;" ng-show="config.provider === 'caas'">
<div class="row">
<div class="col-xs-12 text-right">
<a href="{{ config.webServerOrigin }}/console.html#/userprofile?view=credit_card" target="_blank">Change payment method</a>
or
<a href="{{ config.webServerOrigin }}/console.html" target="_blank">Cancel this Cloudron</a>
</div>
</div>
<div class="row">
<div class="col-xs-10 plans" style="margin-left: 20px">
<div ng-repeat="plan in availablePlans">
<label>
<input type="radio" ng-model="planChange.requestedPlan" ng-value="plan">
{{ plan.name }} ({{ plan.slug | uppercase }}) - {{ plan.price/100 }}{{ currency }}/month
<span ng-show="currentPlan.name === plan.name" style="font-weight: bold"> (current plan)
</span>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<button class="btn btn-primary pull-right" ng-disabled="planChange.requestedPlan.name === currentPlan.name" ng-click="planChange.showChangePlan()">Change Plan</button>
</div>
</div>
</div>
<div class="text-left" ng-show="backupConfig.provider !== 'caas'">
<h3>Cloudron.io Account</h3>
</div>
<div class="card" style="margin-bottom: 15px;" ng-show="backupConfig.provider !== 'caas'">
<div class="row" ng-show="currentSubscription.plan.id === 'free' || currentSubscription.plan.id === 'undecided'">
<div class="col-xs-12">
With a paid plan, you get continuous updates for the Cloudron and apps. This ensures you are running the latest versions of apps and keeps your server secure. All paid plans come with support via <a href="mailto:support@cloudron.io">email</a> and <a target="_blank" href="https://chat.cloudron.io">live chat</a>.
</div>
</div>
<br/>
<div class="row">
<div class="col-xs-6">
<span class="text-muted">Account Email</span>
</div>
<div class="col-xs-6 text-right">
<a ng-href="{{ config.webServerOrigin + '/console.html#/userprofile?email=' + appstoreConfig.profile.email }}" target="_blank">{{ appstoreConfig.profile.email }}</a>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<span class="text-muted">Cloudron ID</span>
</div>
<div class="col-xs-6 text-right">
<span>{{ appstoreConfig.cloudronId }}</span>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<span class="text-muted">Subscription</span>
</div>
<div class="col-xs-6 text-right">
<span>{{ currentSubscription.plan.name }}</span>
</div>
</div>
<br/>
<div class="row">
<div class="col-xs-12">
<a class="btn btn-primary pull-right" ng-href="{{ config.webServerOrigin + '/console.html#/userprofile?view=subscriptions&email=' + appstoreConfig.profile.email }}" target="_blank" ng-show="currentSubscription.plan && currentSubscription.plan.id !== 'free' && currentSubscription.plan.id !== 'undecided'">Configure</a>
<a class="btn btn-success pull-right" ng-href="{{ config.webServerOrigin + '/console.html#/userprofile?view=subscriptions&email=' + appstoreConfig.profile.email + '&cloudronId=' + appstoreConfig.cloudronId }}" target="_blank" ng-show="currentSubscription.plan.id === 'free' || currentSubscription.plan.id === 'undecided'">Setup Subscription</a>
</div>
</div>
</div>
<div class="text-left">
<h3>Backups</h3>
</div>
<div class="card" style="margin-bottom: 15px;">
<div class="row" ng-show="backupConfig.provider !== 'caas'">
<div class="col-xs-6">
<span class="text-muted">Provider</span>
</div>
<div class="col-xs-6 text-right">
<span>{{ backupConfig.provider === 'caas' ? 'cloudron.io' : backupConfig.provider }}</span>
</div>
</div>
<div class="row" ng-show="backupConfig.provider !== 'caas'">
<div class="col-xs-6">
<span class="text-muted">Location</span>
</div>
<div class="col-xs-6 text-right">
2017-09-19 11:58:20 -07:00
<span ng-show="backupConfig.provider === 'filesystem'">{{ backupConfig.backupFolder }}</span>
2017-09-21 12:25:39 -07:00
<span ng-show="backupConfig.provider === 'minio' || backupConfig.provider === 'exoscale-sos' || backupConfig.provider === 's3-v4-compat' || backupConfig.provider === 'digitalocean-spaces'">{{ backupConfig.bucket + '/' + backupConfig.prefix }}</span>
<span ng-show="backupConfig.provider === 's3'">{{ backupConfig.region + ' ' + backupConfig.bucket + '/' + backupConfig.prefix }}</span>
</div>
</div>
<br/>
2017-09-26 07:39:16 -07:00
<div class="row">
<div class="col-xs-4">
<span class="text-muted">Backup ID</span>
</div>
<div class="col-xs-8 text-right">
<span ng-click-select ng-show="lastBackup">{{ lastBackup.id }}</span>
<span ng-hide="lastBackup">No backups have been made yet</span>
</div>
</div>
<div class="row">
<div class="col-xs-6">
<span class="text-muted">Last backup</span>
</div>
<div class="col-xs-6 text-right">
<span ng-show="lastBackup">{{ lastBackup.creationTime | prettyDate }}</span>
2017-09-26 07:39:16 -07:00
<span ng-hide="lastBackup">-</span>
</div>
</div>
<div class="row" ng-show="backupConfig.provider !== 'caas'">
<br/>
<div class="col-md-12">
<div ng-show="createBackup.busy" class="progress progress-striped active animateMe">
<div class="progress-bar progress-bar-success" role="progressbar" style="width: {{ createBackup.percent }}%"></div>
</div>
</div>
</div>
<div class="row" ng-show="backupConfig.provider !== 'caas'">
<div class="col-md-11" ng-show="createBackup.busy">
<p class="text-muted status" style="text-overflow: ellipsis; white-space: nowrap; overflow: hidden">
{{ createBackup.detail || 'Syncing ...' }}
</p>
</div>
</div>
<div class="row" ng-show="backupConfig.provider !== 'caas'">
<div class="col-md-6">
<p ng-show="createBackup.busy">{{ createBackup.message }}</p>
<p ng-hide="createBackup.busy">
<div class="has-error" ng-show="createBackup.percent === 100 && createBackup.result">{{ createBackup.result }}</div>
</p>
</div>
<div class="col-md-6 text-right">
<button class="btn btn-outline btn-primary pull-right" ng-click="configureBackup.show()" ng-disabled="createBackup.busy">Configure</button>
<button class="btn btn-outline btn-primary" ng-click="createBackup.doCreateBackup()" ng-disabled="createBackup.busy" style="margin-right: 10px">Backup now</button>
</div>
</div>
</div>
<div class="text-left">
<h3>Updates</h3>
</div>
<div class="card" style="margin-bottom: 15px;">
<div class="row">
<div class="col-md-12">
<p>Configure the update schedule for the platform and the apps</p>
<p class="text-danger" ng-show="autoUpdate.error"><br/>{{ autoUpdate.error }}</p>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="radio">
<label>
<input type="radio" name="scheduleRadio" ng-change="autoUpdate.success = false" ng-model="autoUpdate.pattern" value="00 00 1,3,5,23 * * *">
Every night
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="scheduleRadio" ng-change="autoUpdate.success = false" ng-model="autoUpdate.pattern" value="00 00 3,5 * * 3">
Wednesday night
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="scheduleRadio" ng-change="autoUpdate.success = false" ng-model="autoUpdate.pattern" value="00 00 1,3,5,23 * * 6">
Saturday night
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="scheduleRadio" ng-change="autoUpdate.success = false" ng-model="autoUpdate.pattern" value="never">
Update manually (Not recommended)
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<i class="fa fa-circle-o-notch fa-spin" ng-show="autoUpdate.busy"></i>
<span class="text-success text-bold" ng-show="autoUpdate.success && autoUpdate.pattern === autoUpdate.currentPattern">Saved</span>
</div>
<div class="col-md-6 text-right">
<button class="btn btn-outline btn-primary pull-right" ng-click="autoUpdate.submit()" ng-disabled="autoUpdate.busy || autoUpdate.pattern === autoUpdate.currentPattern"> Save</button>
<button class="btn btn-outline btn-primary" ng-click="autoUpdate.checkNow()" ng-disabled="autoUpdate.busy" style="margin-right: 10px">Check now</button>
</div>
</div>
</div>
</div>