summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/pipeline_schedules/components/interval_pattern_input.js
blob: 4d623763ca7f8f247220ce694660f57be13139ea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import Vue from 'vue';

const inputNameAttribute = 'schedule[cron]';

export default {
  props: {
    initialCronInterval: {
      type: String,
      required: false,
      default: '',
    },
  },
  data() {
    return {
      inputNameAttribute,
      cronInterval: this.initialCronInterval,
      cronIntervalPresets: {
        everyDay: '0 4 * * *',
        everyWeek: '0 4 * * 0',
        everyMonth: '0 4 1 * *',
      },
      cronSyntaxUrl: 'https://en.wikipedia.org/wiki/Cron',
      customInputEnabled: false,
    };
  },
  computed: {
    intervalIsPreset() {
      return _.contains(this.cronIntervalPresets, this.cronInterval);
    },
    // The text input is editable when there's a custom interval, or when it's
    // a preset interval and the user clicks the 'custom' radio button
    isEditable() {
      return !!(this.customInputEnabled || !this.intervalIsPreset);
    },
  },
  methods: {
    toggleCustomInput(shouldEnable) {
      this.customInputEnabled = shouldEnable;

      if (shouldEnable) {
        // We need to change the value so other radios don't remain selected
        // because the model (cronInterval) hasn't changed. The server trims it.
        this.cronInterval = `${this.cronInterval} `;
      }
    },
  },
  created() {
    if (this.intervalIsPreset) {
      this.enableCustomInput = false;
    }
  },
  watch: {
    cronInterval() {
      // updates field validation state when model changes, as
      // glFieldError only updates on input.
      Vue.nextTick(() => {
        gl.pipelineScheduleFieldErrors.updateFormValidityState();
      });
    },
  },
  template: `
    <div class="interval-pattern-form-group">
      <div class="cron-preset-radio-input">
        <input
          id="custom"
          class="label-light"
          type="radio"
          :name="inputNameAttribute"
          :value="cronInterval"
          :checked="isEditable"
          @click="toggleCustomInput(true)"
        />

        <label for="custom">
          Custom
        </label>

        <span class="cron-syntax-link-wrap">
          (<a :href="cronSyntaxUrl" target="_blank">Cron syntax</a>)
        </span>
      </div>

      <div class="cron-preset-radio-input">
        <input
          id="every-day"
          class="label-light"
          type="radio"
          v-model="cronInterval"
          :name="inputNameAttribute"
          :value="cronIntervalPresets.everyDay"
          @click="toggleCustomInput(false)"
        />

        <label class="label-light" for="every-day">
          Every day (at 4:00am)
        </label>
      </div>

      <div class="cron-preset-radio-input">
        <input
          id="every-week"
          class="label-light"
          type="radio"
          v-model="cronInterval"
          :name="inputNameAttribute"
          :value="cronIntervalPresets.everyWeek"
          @click="toggleCustomInput(false)"
        />

        <label class="label-light" for="every-week">
          Every week (Sundays at 4:00am)
        </label>
      </div>

      <div class="cron-preset-radio-input">
        <input
          id="every-month"
          class="label-light"
          type="radio"
          v-model="cronInterval"
          :name="inputNameAttribute"
          :value="cronIntervalPresets.everyMonth"
          @click="toggleCustomInput(false)"
        />

        <label class="label-light" for="every-month">
          Every month (on the 1st at 4:00am)
        </label>
      </div>

      <div class="cron-interval-input-wrapper">
        <input
          id="schedule_cron"
          class="form-control inline cron-interval-input"
          type="text"
          placeholder="Define a custom pattern with cron syntax"
          required="true"
          v-model="cronInterval"
          :name="inputNameAttribute"
          :disabled="!isEditable"
        />
      </div>
    </div>
  `,
};