mirror of
https://github.com/portainer/portainer.git
synced 2025-08-08 07:15:23 +02:00
* feat(UX): schedule creation UX overhaul (#2485)
* feat(api): add a new Recurring property on Schedule * feat(schedules): date to cron convert + recurring flag * feat(schedules): update angularjs-datetime-picker from v1 to v2 * chore(app): use minified dependency for angularjs-datetime-picker * chore(vendor): rollback version of angularjs-datetime-picker * * feat(ux): replace datepicker for schedule creation/details * feat(container-stats): add refresh rate of 1 and 3 seconds (#2493) * fix(templates): set var to default value if no value selected (#2323) * fix(templates): set preset to true iff var type is preset * fix(templates): add env var value when changing type * feat(security): shutdown instance after 5minutes if no admin account created (#2500) * feat(security): skip admin check if --no-auth * fix(security): change error message * fix(vendor): use datepicker minified version * feat(schedule-creation): replace angular-datetime-picker * feat(schedule): parse cron to datetime * fix(schedule): fix zero based months
This commit is contained in:
parent
9e1800e2ec
commit
1a94158f77
13 changed files with 196 additions and 26 deletions
|
@ -7,6 +7,38 @@ angular.module('portainer.app').component('scheduleForm', {
|
|||
formValidationError: ''
|
||||
};
|
||||
|
||||
ctrl.scheduleValues = [{
|
||||
displayed: 'Every hour',
|
||||
cron: '0 0 * * *'
|
||||
},
|
||||
{
|
||||
displayed: 'Every 2 hours',
|
||||
cron: '0 0 0/2 * *'
|
||||
}, {
|
||||
displayed: 'Every day',
|
||||
cron: '0 0 0 * *'
|
||||
}
|
||||
];
|
||||
|
||||
ctrl.formValues = {
|
||||
datetime: ctrl.model.CronExpression ? cronToDatetime(ctrl.model.CronExpression) : moment(),
|
||||
scheduleValue: ctrl.scheduleValues[0],
|
||||
cronMethod: 'basic'
|
||||
};
|
||||
|
||||
function cronToDatetime(cron) {
|
||||
strings = cron.split(' ');
|
||||
if (strings.length !== 5) {
|
||||
return moment();
|
||||
}
|
||||
return moment(cron, 's m H D M');
|
||||
}
|
||||
|
||||
function datetimeToCron(datetime) {
|
||||
var date = moment(datetime);
|
||||
return '0 '.concat(date.minutes(), ' ', date.hours(), ' ', date.date(), ' ', (date.month() + 1));
|
||||
}
|
||||
|
||||
this.action = function() {
|
||||
ctrl.state.formValidationError = '';
|
||||
|
||||
|
@ -15,6 +47,15 @@ angular.module('portainer.app').component('scheduleForm', {
|
|||
return;
|
||||
}
|
||||
|
||||
if (ctrl.formValues.cronMethod === 'basic') {
|
||||
if (ctrl.model.Recurring === false) {
|
||||
ctrl.model.CronExpression = datetimeToCron(ctrl.formValues.datetime);
|
||||
} else {
|
||||
ctrl.model.CronExpression = ctrl.formValues.scheduleValue.cron;
|
||||
}
|
||||
} else {
|
||||
ctrl.model.Recurring = true;
|
||||
}
|
||||
ctrl.formAction();
|
||||
};
|
||||
|
||||
|
|
|
@ -18,24 +18,107 @@
|
|||
</div>
|
||||
<!-- !name-input -->
|
||||
<!-- cron-input -->
|
||||
<div class="form-group">
|
||||
<label for="schedule_cron" class="col-sm-1 control-label text-left">Cron rule</label>
|
||||
<div class="col-sm-11">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.model.CronExpression" id="schedule_cron" name="schedule_cron" placeholder="0 2 * * *" required>
|
||||
</div>
|
||||
<!-- schedule-method-select -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Schedule configuration
|
||||
</div>
|
||||
<div class="form-group" ng-show="scheduleForm.schedule_cron.$invalid">
|
||||
<div class="col-sm-12 small text-warning">
|
||||
<div ng-messages="scheduleForm.schedule_cron.$error">
|
||||
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
||||
<div class="form-group"></div>
|
||||
<div class="form-group" style="margin-bottom: 0">
|
||||
<div class="boxselector_wrapper">
|
||||
<div>
|
||||
<input type="radio" id="config_basic" ng-model="$ctrl.formValues.cronMethod" value="basic">
|
||||
<label for="config_basic">
|
||||
<div class="boxselector_header">
|
||||
<i class="fa fa-calendar-alt" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Basic configuration
|
||||
</div>
|
||||
<p>Select date from calendar</p>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<input type="radio" id="config_advanced" ng-model="$ctrl.formValues.cronMethod" value="advanced">
|
||||
<label for="config_advanced">
|
||||
<div class="boxselector_header">
|
||||
<i class="fa fa-edit" aria-hidden="true" style="margin-right: 2px;"></i>
|
||||
Advanced configuration
|
||||
</div>
|
||||
<p>Write your own cron rule</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
You can refer to the <a href="https://godoc.org/github.com/robfig/cron#hdr-CRON_Expression_Format" target="_blank">following documentation</a> to get more information about the supported cron expression format.
|
||||
</span>
|
||||
<!-- !schedule-method-select -->
|
||||
<!-- basic-schedule -->
|
||||
<div ng-if="$ctrl.formValues.cronMethod === 'basic'">
|
||||
<div class="form-group">
|
||||
<label for="recurring" class="col-sm-2 control-label text-left">Recurring schedule</label>
|
||||
<div class="col-sm-10">
|
||||
<label class="switch" style="margin-left: 20px;">
|
||||
<input type="checkbox" name="recurring" ng-model="$ctrl.model.Recurring"><i></i>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- not-recurring -->
|
||||
<div ng-if="!$ctrl.model.Recurring">
|
||||
<div class="form-group">
|
||||
<label for="schedule_cron" class="col-sm-2 control-label text-left">Schedule date</label>
|
||||
<div class="col-sm-10">
|
||||
<input class="form-control" moment-picker ng-model="$ctrl.formValues.datetime" format="YYYY-MM-DD HH:mm">
|
||||
</div>
|
||||
<div ng-show="scheduleForm.datepicker.$invalid">
|
||||
<div class="col-sm-12 small text-warning">
|
||||
<div ng-messages="scheduleForm.datepicker.$error">
|
||||
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !not-recurring -->
|
||||
<!-- recurring -->
|
||||
<div ng-if="$ctrl.model.Recurring">
|
||||
<div class="form-group">
|
||||
<label for="schedule_value" class="col-sm-2 control-label text-left">Schedule time</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="schedule_value" name="schedule_value" class="form-control"
|
||||
ng-model="$ctrl.formValues.scheduleValue" ng-options="value.displayed for value in $ctrl.scheduleValues" required
|
||||
></select>
|
||||
</div>
|
||||
<div ng-show="scheduleForm.schedule_value.$invalid">
|
||||
<div class="col-sm-12 small text-warning">
|
||||
<div ng-messages="scheduleForm.schedule_value.$error">
|
||||
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !recurring -->
|
||||
</div>
|
||||
<!-- !basic-schedule -->
|
||||
<!-- advanced-schedule -->
|
||||
<div ng-if="$ctrl.formValues.cronMethod === 'advanced'">
|
||||
<div class="form-group">
|
||||
<label for="schedule_cron" class="col-sm-2 control-label text-left">Cron rule</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" ng-model="$ctrl.model.CronExpression" id="schedule_cron" name="schedule_cron"
|
||||
placeholder="0 2 * * *" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-show="scheduleForm.schedule_cron.$invalid">
|
||||
<div class="col-sm-12 small text-warning">
|
||||
<div ng-messages="scheduleForm.schedule_cron.$error">
|
||||
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<span class="col-sm-12 text-muted small">
|
||||
You can refer to the <a href="https://godoc.org/github.com/robfig/cron#hdr-CRON_Expression_Format" target="_blank">following documentation</a> to get more information about the supported cron expression format.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- !advanced-schedule -->
|
||||
<!-- !cron-input -->
|
||||
<div class="col-sm-12 form-section-title">
|
||||
Job configuration
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
function ScheduleDefaultModel() {
|
||||
this.Name = '';
|
||||
this.Recurring = false;
|
||||
this.CronExpression = '';
|
||||
this.JobType = 1;
|
||||
this.Job = new ScriptExecutionDefaultJobModel();
|
||||
|
@ -16,6 +17,7 @@ function ScriptExecutionDefaultJobModel() {
|
|||
function ScheduleModel(data) {
|
||||
this.Id = data.Id;
|
||||
this.Name = data.Name;
|
||||
this.Recurring = data.Recurring;
|
||||
this.JobType = data.JobType;
|
||||
this.CronExpression = data.CronExpression;
|
||||
this.Created = data.Created;
|
||||
|
@ -42,6 +44,7 @@ function ScriptExecutionTaskModel(data) {
|
|||
|
||||
function ScheduleCreateRequest(model) {
|
||||
this.Name = model.Name;
|
||||
this.Recurring = model.Recurring;
|
||||
this.CronExpression = model.CronExpression;
|
||||
this.Image = model.Job.Image;
|
||||
this.Endpoints = model.Job.Endpoints;
|
||||
|
@ -54,6 +57,7 @@ function ScheduleCreateRequest(model) {
|
|||
function ScheduleUpdateRequest(model) {
|
||||
this.id = model.Id;
|
||||
this.Name = model.Name;
|
||||
this.Recurring = model.Recurring;
|
||||
this.CronExpression = model.CronExpression;
|
||||
this.Image = model.Job.Image;
|
||||
this.Endpoints = model.Job.Endpoints;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue