github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/ui/app/components/job-editor.js (about)

     1  import Component from '@ember/component';
     2  import { assert } from '@ember/debug';
     3  import { inject as service } from '@ember/service';
     4  import { computed, action } from '@ember/object';
     5  import { task } from 'ember-concurrency';
     6  import messageFromAdapterError from 'nomad-ui/utils/message-from-adapter-error';
     7  import localStorageProperty from 'nomad-ui/utils/properties/local-storage';
     8  import { attributeBindings } from '@ember-decorators/component';
     9  import classic from 'ember-classic-decorator';
    10  
    11  @classic
    12  @attributeBindings('data-test-job-editor')
    13  export default class JobEditor extends Component {
    14    @service store;
    15    @service config;
    16  
    17    'data-test-job-editor' = true;
    18  
    19    job = null;
    20    onSubmit() {}
    21  
    22    @computed('_context')
    23    get context() {
    24      return this._context;
    25    }
    26  
    27    set context(value) {
    28      const allowedValues = ['new', 'edit'];
    29  
    30      assert(
    31        `context must be one of: ${allowedValues.join(', ')}`,
    32        allowedValues.includes(value)
    33      );
    34  
    35      this.set('_context', value);
    36    }
    37  
    38    @action updateCode(value) {
    39      if (!this.job.isDestroying && !this.job.isDestroyed) {
    40        this.job.set('_newDefinition', value);
    41      }
    42    }
    43  
    44    _context = null;
    45    parseError = null;
    46    planError = null;
    47    runError = null;
    48  
    49    planOutput = null;
    50  
    51    @localStorageProperty('nomadMessageJobPlan', true) showPlanMessage;
    52  
    53    @computed('planOutput')
    54    get stage() {
    55      return this.planOutput ? 'plan' : 'editor';
    56    }
    57  
    58    @(task(function* () {
    59      this.reset();
    60  
    61      try {
    62        yield this.job.parse();
    63      } catch (err) {
    64        const error =
    65          messageFromAdapterError(err, 'parse jobs') || 'Could not parse input';
    66        this.set('parseError', error);
    67        this.scrollToError();
    68        return;
    69      }
    70  
    71      try {
    72        const plan = yield this.job.plan();
    73        this.set('planOutput', plan);
    74      } catch (err) {
    75        const error =
    76          messageFromAdapterError(err, 'plan jobs') || 'Could not plan job';
    77        this.set('planError', error);
    78        this.scrollToError();
    79      }
    80    }).drop())
    81    plan;
    82  
    83    @task(function* () {
    84      try {
    85        if (this.context === 'new') {
    86          yield this.job.run();
    87        } else {
    88          yield this.job.update();
    89        }
    90  
    91        const id = this.get('job.plainId');
    92        const namespace = this.get('job.namespace.name') || 'default';
    93  
    94        this.reset();
    95  
    96        // Treat the job as ephemeral and only provide ID parts.
    97        this.onSubmit(id, namespace);
    98      } catch (err) {
    99        const error = messageFromAdapterError(err) || 'Could not submit job';
   100        this.set('runError', error);
   101        this.set('planOutput', null);
   102        this.scrollToError();
   103      }
   104    })
   105    submit;
   106  
   107    reset() {
   108      this.set('planOutput', null);
   109      this.set('planError', null);
   110      this.set('parseError', null);
   111      this.set('runError', null);
   112    }
   113  
   114    scrollToError() {
   115      if (!this.get('config.isTest')) {
   116        window.scrollTo(0, 0);
   117      }
   118    }
   119  
   120    @action uploadJobSpec(event) {
   121      const reader = new FileReader();
   122      reader.onload = () => {
   123        this.updateCode(reader.result);
   124      };
   125  
   126      const [file] = event.target.files;
   127      reader.readAsText(file);
   128    }
   129  }