File

src/app/tasks/task-schedule-create/task-schedule-create.component.ts

Description

Component handling a creation of a task schedule.

Implements

OnInit

Example

Metadata

encapsulation ViewEncapsulation.None
selector app-task-schedule-create
styleUrls styles.scss
templateUrl ./task-schedule-create.component.html

Index

Properties
Methods

Constructor

constructor(routingStateService: RoutingStateService, tasksService: TasksService, router: Router, groupRouteService: GroupRouteService, blockerService: BlockerService, notificationService: NotificationService, route: ActivatedRoute)

Constructor

Parameters :
Name Type Optional Description
routingStateService RoutingStateService
tasksService TasksService
router Router
groupRouteService GroupRouteService
blockerService BlockerService
notificationService NotificationService
route ActivatedRoute

Methods

buildForm
buildForm(schedule: )

Build the form

Parameters :
Name Type Optional Description
schedule
Returns : void
cancel
cancel()

Cancel

Returns : void
detailsTask
detailsTask(taskName: string)

Navigate to the task page

Parameters :
Name Type Optional Description
taskName string
Returns : void
ngOnInit
ngOnInit()

On Init

Returns : void
submit
submit(schedule: )

Create a schedule

Parameters :
Name Type Optional Description
schedule
Returns : void

Properties

form
form: FormGroup
Type : FormGroup

Form Group

kvValidators
kvValidators:

Validators args / props component

Private ngUnsubscribe$
ngUnsubscribe$: Subject<any>
Type : Subject<any>

Unsubscribe

schedule$
schedule$: Observable<any>
Type : Observable<any>

Schedule Object

submitted
submitted:
Default value : false

Form Submitted

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { RoutingStateService } from '../../shared/services/routing-state.service';
import { Observable, EMPTY, Subject, of, throwError } from 'rxjs';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { catchError, finalize, map, mergeMap, takeUntil } from 'rxjs/operators';
import { TasksService } from '../tasks.service';
import { FormArray, FormControl, FormGroup, Validators } from '@angular/forms';
import { TaskScheduleCreateValidator } from './task-schedule-create.validator';
import { GroupRouteService } from '../../shared/services/group-route.service';
import { NotificationService } from '../../shared/services/notification.service';
import { TaskLaunchValidator } from '../task-launch/task-launch.validator';
import { TaskSchedule } from '../model/task-schedule';
import { Page } from '../../shared/model/page';
import { AppError } from '../../shared/model/error.model';
import { KvRichTextValidator } from '../../shared/components/kv-rich-text/kv-rich-text.validator';
import { BlockerService } from '../../shared/components/blocker/blocker.service';

/**
 * Component handling a creation of a task schedule.
 *
 * @author Damien Vitrac
 */
@Component({
  selector: 'app-task-schedule-create',
  templateUrl: './task-schedule-create.component.html',
  styleUrls: ['styles.scss'],
  encapsulation: ViewEncapsulation.None
})
export class TaskScheduleCreateComponent implements OnInit {

  /**
   * Unsubscribe
   */
  private ngUnsubscribe$: Subject<any> = new Subject();

  /**
   * Schedule Object
   */
  schedule$: Observable<any>;

  /**
   * Form Group
   */
  form: FormGroup;

  /**
   * Form Submitted
   */
  submitted = false;

  /**
   * Validators args / props component
   */
  kvValidators = {
    args: {
      key: [Validators.required],
      value: []
    },
    props: {
      key: [Validators.required, TaskLaunchValidator.key],
      value: []
    }
  };

  /**
   * Constructor
   *
   * @param {RoutingStateService} routingStateService
   * @param {TasksService} tasksService
   * @param {Router} router
   * @param {GroupRouteService} groupRouteService
   * @param {BlockerService} blockerService
   * @param {NotificationService} notificationService
   * @param {ActivatedRoute} route
   */
  constructor(private routingStateService: RoutingStateService,
              private tasksService: TasksService,
              private router: Router,
              private groupRouteService: GroupRouteService,
              private blockerService: BlockerService,
              private notificationService: NotificationService,
              private route: ActivatedRoute) {
  }

  /**
   * On Init
   */
  ngOnInit() {
    this.schedule$ = this.route.params
      .pipe(
        mergeMap(
          (params: Params) => {
            let result: Observable<any>;
            if (this.groupRouteService.isSimilar(params.id)) {
              if (this.groupRouteService.group(params.id)) {
                result = of(this.groupRouteService.group(params.id));
              } else {
                return throwError(`Group selection not found.`);
              }
            } else {
              result = this.tasksService.getDefinition(params.id);
            }
            return result.pipe(map((data) => {
              if (this.groupRouteService.isSimilar(params.id)) {
                return {
                  params: params,
                  taskDefinitions: data
                };
              } else {
                return {
                  params: params,
                  taskDefinitions: [data.name]
                };
              }
            }));
          }
        ),
        mergeMap(
          (schedule) => this.tasksService.getSchedules({ q: '', page: 0, size: 10000, sort: null, order: null })
            .pipe(map((schedules: Page<TaskSchedule>) => {
              return {
                params: schedule.params,
                taskDefinitions: schedule.taskDefinitions,
                schedules: schedules.items.map((item) => item.name.toLowerCase())
              };
            })),
        ),
        map((schedule) => {
          this.buildForm(schedule);
          return schedule;
        }),
        catchError((error) => {
          this.notificationService.error(error.toString());
          this.cancel();
          return EMPTY;
        })
      );
  }

  /**
   * Build the form
   */
  buildForm(schedule) {
    const names = new FormArray(schedule.taskDefinitions.map(() => {
      return new FormControl('', [
        Validators.required, ((control: FormControl) => {
          return TaskScheduleCreateValidator.existName(control, schedule.schedules);
        })
      ]);
    }), [TaskScheduleCreateValidator.uniqueName]);
    this.form = new FormGroup({
      'cron': new FormControl('', [Validators.required, TaskScheduleCreateValidator.cron]),
      'names': names,
      'args': new FormControl('', KvRichTextValidator.validateKvRichText(this.kvValidators.args)),
      'props': new FormControl('', KvRichTextValidator.validateKvRichText(this.kvValidators.props))
    });
  }

  /**
   * Create a schedule
   */
  submit(schedule) {
    this.submitted = true;
    if (!this.form.valid) {
      this.notificationService.error('Some field(s) are missing or invalid.');
    } else {
      const getClean = (val: string): Array<string> => val.split('\n')
        .filter((a) => a !== '');

      const taskArguments = getClean(this.form.get('args').value);
      const taskProperties = getClean(this.form.get('props').value);
      const cronExpression = this.form.get('cron').value;
      const scheduleParams = schedule.taskDefinitions
        .map((taskName: string, index: number) => ({
            args: taskArguments.join(','),
            props: taskProperties.join(','),
            cronExpression: cronExpression,
            task: taskName,
            schedulerName: (this.form.get('names') as FormArray).controls
              .map((control: FormControl) => control.value)[index]
          })
        );

      this.blockerService.lock();
      this.tasksService.createSchedules(scheduleParams)
        .pipe(takeUntil(this.ngUnsubscribe$), finalize(() => this.blockerService.unlock()))
        .subscribe(
          data => {
            if (scheduleParams.length === 1) {
              this.notificationService.success(`Successfully schedule creation "${scheduleParams[0].schedulerName}"`);
            } else {
              this.notificationService.success(`Successfully ${scheduleParams.length} schedules creation`);
            }
            this.cancel();
          },
          error => {
            this.notificationService.error(AppError.is(error) ? error.getMessage() : error);
          }
        );
    }
  }

  /**
   * Navigate to the task page
   * @param {string} taskName
   */
  detailsTask(taskName: string) {
    this.router.navigate([`/tasks/definitions/${taskName}`]);
  }

  /**
   * Cancel
   */
  cancel() {
    this.routingStateService.back('/tasks/definitions');
  }

}
<app-page *ngIf="schedule$ | async as schedule; else loading">

  <app-page-head>
    <app-page-head-back [defaultUrl]="'/tasks/definitions'"></app-page-head-back>
    <app-page-head-title>Create <strong>schedule(s)</strong></app-page-head-title>
  </app-page-head>

  <div dataflowLayoutType type="large">
    <div class="dataflow-alert dataflow-alert-info">
      Create a schedule for a task, simply provide a <strong>name</strong> and a <strong>CRON expression</strong>.
      <br>Optionally, you can add <strong>properties</strong> and <strong>arguments</strong>.
    </div>

    <form class="schedule-form task-create" [formGroup]="form" name="form" (submit)="submit(schedule)">
      <div>
        <h2>Setup the schedule</h2>
        <div *ngIf="schedule.taskDefinitions.length == 1">
          <div class="row" style="margin-bottom: 12px">
            <div class="col-xs-4">
              <label>Task Name:</label>
            </div>
            <div class="col-xs-20">
              <a style="cursor: pointer" (click)="detailsTask(schedule.taskDefinitions[0])">
                {{ schedule.taskDefinitions[0] }}</a>
            </div>
          </div>
          <div class="row form-group" [class.has-error]="submitted && form.get('names').controls[0].invalid">
            <div class="col-xs-4">
              <label class="control-label" for="name">Schedule name:</label>
            </div>
            <div class="col-xs-10">
              <div formArrayName="names">
                <input id="name" name="name" [formControl]="form.get('names').controls[0]"
                       class="form-control input-sm"/>
                <div class="errors-name" *ngIf="submitted && form.get('names.0').invalid">
                  <div *ngIf="form.get('names.0').errors?.required" class="help-block">The name is required.</div>
                  <div *ngIf="form.get('names.0').errors?.exist" class="help-block">The name already exists.</div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div *ngIf="schedule.taskDefinitions.length > 1">
          <div class="row form-group">
            <div class="col-xs-4">
              <label class="control-label">Tasks:</label>
            </div>
            <div class="col-xs-10">
              <div class="alert alert-danger" style="max-width: 700px"
                   *ngIf="submitted && form.get('names').errors?.notUnique">
                Duplicate schedule name on the form.
              </div>
              <table class="table table-form table-form-stripped" style="max-width: 700px">
                <thead>
                <tr>
                  <th style="padding-top: 4px" width="50%">Task</th>
                  <th style="padding-top: 4px" width="50%">Schedule name</th>
                </tr>
                </thead>
                <tbody>
                <tr *ngFor="let item of schedule.taskDefinitions; index as i">
                  <td class="td-label"><a style="cursor: pointer" (click)="detailsTask(item)">{{ item }}</a></td>
                  <td>
                    <div [class.has-error]="submitted && form.get('names.' + i).invalid">
                      <input [formControl]="form.get('names').controls[i]" type="text" class="form-control input-sm"/>
                      <div *ngIf="submitted && form.get('names.' + i).invalid">
                        <div *ngIf="form.get('names.' + i).errors?.required" class="help-block">The name is required.
                        </div>
                        <div *ngIf="form.get('names.' + i).errors?.exist" class="help-block">The name already exists.
                        </div>
                      </div>
                    </div>
                  </td>
                </tr>
                </tbody>
              </table>
            </div>
          </div>
        </div>
        <div class="row form-group" [class.has-error]="submitted && form.get('cron').invalid">
          <div class="col-xs-4">
            <label class="control-label" for="cron">Cron Expression:</label>
          </div>
          <div class="col-xs-20">
            <div style="max-width: 260px">
              <input id="cron" name="cron" formControlName="cron" class="form-control input-sm"/>
              <div class="errors-cron" *ngIf="submitted && form.get('cron').invalid">
                <span class="help-block"
                      *ngIf="form.get('cron').errors?.required">The cron expression is required.</span>
                <span class="help-block"
                      *ngIf="submitted && form.get('cron').errors?.formatError">The cron expression is not valid.</span>
              </div>
            </div>
          </div>
        </div>

        <h2>Task Arguments and Properties</h2>

        <div class="row form-group" [class.has-error]="form.get('args').invalid && submitted">
          <div class="col-xs-4">
            <label class="control-label">Arguments:</label>
          </div>
          <div class="col-xs-10">
            <app-kv-rich-text [validators]="kvValidators.args" [formControl]="form.get('args')"
                              placeholder="--myarg=myvalue"></app-kv-rich-text>
            <span class="help-block" *ngIf="form.get('args').invalid && submitted">
            One or more arguments are invalid.<br/>Example: <code>myarg=myvalue</code>.
          </span>
          </div>

        </div>

        <div class="row form-group" [class.has-error]="form.get('props').invalid && submitted">
          <div class="col-xs-4">
            <label class="control-label">Parameters:</label>
          </div>
          <div class="col-xs-10">
            <app-kv-rich-text [validators]="kvValidators.props" [formControl]="form.get('props')"
                              placeholder="app.myparam=myvalue"></app-kv-rich-text>
            <span class="help-block" *ngIf="form.get('props').invalid && submitted">
          One or more parameters are invalid.<br/>Example: <code>app.myarg=myvalue</code>.
          </span>
          </div>
        </div>

        <!--
        <div class="builder">
          <div class="row">
            <div class="col-md-12">
              <div class="col-1-layout" formArrayName="args">
                <h3>Task Arguments</h3>
                <p>You can add optional task arguments before launching the task.</p>
                <table class="table table-actions table-form">
                  <thead>
                  <tr>
                    <th>Key</th>
                    <th>Value</th>
                    <th>&nbsp;</th>
                  </tr>
                  </thead>
                  <tbody>
                  <tr *ngFor="let f of form.get('args').controls;let i = index"
                      [formGroupName]="i">
                    <td>
                      <div [class.has-error]="submitted && form.get('args.' + i).invalid">
                        <input formControlName="key" type="text" class="form-control input-sm"/>
                        <div *ngIf="submitted && form.get('args.' + i + '.key').invalid"
                             class="help-block">Invalid key
                        </div>
                        <div *ngIf="submitted && form.get('args.' + i).invalid" class="help-block">
                          Invalid key
                        </div>
                      </div>
                    </td>
                    <td>
                      <div [class.has-error]="submitted && form.get('args.' + i).invalid">
                        <input formControlName="val" type="text" class="form-control input-sm"/>
                        <div *ngIf="submitted && form.get('args.' + i + '.val').invalid"
                             class="help-block">Invalid value
                        </div>
                      </div>
                    </td>
                    <td class="table-actions" width="10px" nowrap="">
                      <div class="actions-btn" role="group">
                        <button [disabled]="form.get('args').controls.length == (i+1)" type="button"
                                class="btn btn-danger"
                                (click)="form.get('args').removeAt(i)">
                          <span class="fa fa-times" style="margin-top: 2px"></span>
                        </button>
                      </div>
                    </td>
                  </tr>
                  </tbody>
                </table>
              </div>
            </div>
            <div class="col-md-12">
              <div class="col-2-layout" formArrayName="params">
                <h3>Task Properties</h3>
                <p>You can add optional task properties before launching the task.</p>
                <table class="table table-actions table-form">
                  <thead>
                  <tr>
                    <th>Key</th>
                    <th>Value</th>
                    <th>&nbsp;</th>
                  </tr>
                  </thead>
                  <tbody>
                  <tr *ngFor="let f of form.get('params').controls;let i = index"
                      [formGroupName]="i">
                    <td>
                      <div [class.has-error]="submitted && form.get('params.' + i).invalid">
                        <input formControlName="key" type="text" class="form-control input-sm"/>
                        <div *ngIf="submitted && form.get('params.' + i + '.key').invalid" class="help-block">
                          The key should start with `app.` or `deployer.` or `scheduler.`.
                        </div>
                        <div class="help-block"
                             *ngIf="submitted && form.get('params.' + i).invalid && !form.get('params.' + i + '.key').invalid">
                          Invalid key
                        </div>
                      </div>
                    </td>
                    <td>
                      <div [class.has-error]="form.get('params.' + i).invalid">
                        <input formControlName="val" type="text" class="form-control input-sm"/>
                        <div *ngIf="submitted && form.get('params.' + i + '.val').invalid" class="help-block">Invalid
                          value
                        </div>
                      </div>
                    </td>
                    <td class="table-actions" width="10px" nowrap="">
                      <div class="actions-btn" role="group">
                        <button [disabled]="form.get('params').controls.length == (i + 1)" type="button"
                                class="btn btn-danger" (click)="form.get('params').removeAt(i)">
                          <span class="fa fa-times" style="margin-top: 2px"></span>
                        </button>
                      </div>
                    </td>
                  </tr>
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        </div>
        -->



      </div>
      <app-page-actions>
        <button (click)="cancel()" type="button" class="btn btn-default">Cancel</button>
        <button id="btn-submit" type="submit" class="btn btn-primary">Schedule the task</button>
      </app-page-actions>
    </form>
  </div>
</app-page>
<ng-template #loading>
  <app-loader></app-loader>
</ng-template>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""