Passed
Push — master ( 1a6db4...d22713 )
by Muhammad Dyas
01:40
created

NewPollFormCard.buildMultipleVoteSection   B

Complexity

Conditions 3

Size

Total Lines 59
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 48
dl 0
loc 59
rs 8.7018
c 0
b 0
f 0
cc 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
import BaseCard from './BaseCard';
2
import {ClosableType, LocaleTimezone, PollForm} from '../helpers/interfaces';
3
import {MAX_NUM_OF_OPTIONS} from '../config/default';
4
import {chat_v1 as chatV1} from '@googleapis/chat';
5
import {offsetToTimezone} from '../helpers/time';
6
import {createButton} from '../helpers/cards';
7
8
export default class NewPollFormCard extends BaseCard {
9
  private config: PollForm;
10
  private timezone: LocaleTimezone;
11
12
  constructor(config: PollForm, timezone: LocaleTimezone) {
13
    super();
14
    this.config = config;
15
    this.timezone = timezone;
16
  }
17
18
  create() {
19
    this.buildSections();
20
    this.buildFooter();
21
    return this.card;
22
  }
23
24
  buildSections() {
25
    this.buildTopicInputSection();
26
    this.buildOptionSwitchSection();
27
    this.buildCloseConfigSection();
28
    if (this.config.autoClose) {
29
      this.buildAutoCloseSection();
30
    }
31
    this.buildMultipleVoteSection();
32
  }
33
34
  buildTopicInputSection() {
35
    const widgets = [];
36
    widgets.push(this.buildHelpText());
37
    widgets.push(this.topicInput(this.config.topic));
38
    for (let i = 0; i < MAX_NUM_OF_OPTIONS; ++i) {
39
      const choice = this.config.choices?.[i];
40
      widgets.push(this.optionInput(i, choice));
41
    }
42
    this.card.sections!.push({
43
      'collapsible': true,
44
      'uncollapsibleWidgetsCount': 6,
45
      widgets,
46
    });
47
  }
48
49
  buildOptionSwitchSection() {
50
    this.card.sections!.push({
51
      'widgets': [
52
        {
53
          'decoratedText': {
54
            'bottomLabel': 'If this checked the voters name will be not shown',
55
            'text': 'Anonymous voter',
56
            'switchControl': {
57
              'controlType': 'SWITCH',
58
              'name': 'is_anonymous',
59
              'value': '1',
60
              'selected': this.config.anon ?? false,
61
            },
62
          },
63
          'horizontalAlignment': 'CENTER',
64
        },
65
        {
66
          'decoratedText': {
67
            'bottomLabel': 'After the poll is created, other member can add more option',
68
            'text': 'Allow to add more option(s)',
69
            'switchControl': {
70
              'controlType': 'SWITCH',
71
              'name': 'allow_add_option',
72
              'value': '1',
73
              'selected': this.config.optionable ?? true,
74
            },
75
          },
76
          'horizontalAlignment': 'CENTER',
77
        },
78
      ],
79
    });
80
  }
81
82
  buildCloseConfigSection() {
83
    const widgets: chatV1.Schema$GoogleAppsCardV1Widget[] = [
84
      {
85
        'selectionInput': {
86
          'type': 'DROPDOWN',
87
          'label': 'Allow to manually close poll',
88
          'name': 'type',
89
          'items': [
90
            {
91
              'text': 'Yes, but only creator',
92
              'value': '1',
93
              'selected': this.config.type === ClosableType.CLOSEABLE_BY_CREATOR,
94
            },
95
            {
96
              'text': 'Yes, anyone can close',
97
              'value': '2',
98
              'selected': this.config.type === ClosableType.CLOSEABLE_BY_ANYONE,
99
            },
100
            {
101
              'text': 'No, I want unclosable poll',
102
              'value': '0',
103
              'selected': this.config.type === ClosableType.UNCLOSEABLE,
104
            },
105
          ],
106
        },
107
        'horizontalAlignment': 'START',
108
      },
109
      {
110
        'decoratedText': {
111
          'topLabel': '',
112
          'text': 'Automatic close poll at certain time',
113
          'bottomLabel': 'The schedule time will show up',
114
          'switchControl': {
115
            'controlType': 'SWITCH',
116
            'name': 'is_autoclose',
117
            'value': '1',
118
            'selected': this.config.autoClose ?? false,
119
            'onChangeAction': {
120
              'function': 'new_poll_on_change',
121
              'parameters': [],
122
            },
123
          },
124
        },
125
      }];
126
    this.card.sections!.push({
127
      widgets,
128
    });
129
  }
130
131
  buildAutoCloseSection() {
132
    const widgets: chatV1.Schema$GoogleAppsCardV1Widget[] = [];
133
    const timezone = offsetToTimezone(this.timezone.offset);
134
    const nowMs = Date.now() + this.timezone.offset + 18000000;
135
    widgets.push(
136
      {
137
        'dateTimePicker': {
138
          'label': 'Close schedule time ' + timezone,
139
          'name': 'close_schedule_time',
140
          'type': 'DATE_AND_TIME',
141
          'valueMsEpoch': nowMs.toString(),
142
        },
143
      });
144
145
    widgets.push(
146
      {
147
        'decoratedText': {
148
          'text': 'Auto mention <b>@all</b> on 5 minutes before poll closed',
149
          'bottomLabel': 'This is to prevent other users to vote before the poll is closed',
150
          'switchControl': {
151
            'controlType': 'SWITCH',
152
            'name': 'auto_mention',
153
            'value': '1',
154
            'selected': this.config.autoMention ?? false,
155
          },
156
        },
157
      });
158
    this.card.sections!.push({
159
      widgets,
160
    });
161
  }
162
163
  buildMultipleVoteSection() {
164
    const widgets: chatV1.Schema$GoogleAppsCardV1Widget[] = [];
165
166
    const items = [
167
      {
168
        'text': 'No Limit',
169
        'value': '0',
170
        'selected': false,
171
      },
172
      {
173
        'text': '1',
174
        'value': '1',
175
        'selected': false,
176
      },
177
      {
178
        'text': '2',
179
        'value': '2',
180
        'selected': false,
181
      },
182
      {
183
        'text': '3',
184
        'value': '3',
185
        'selected': false,
186
      },
187
      {
188
        'text': '4',
189
        'value': '4',
190
        'selected': false,
191
      },
192
      {
193
        'text': '5',
194
        'value': '5',
195
        'selected': false,
196
      },
197
      {
198
        'text': '6',
199
        'value': '6',
200
        'selected': false,
201
      },
202
    ];
203
      // set selected item
204
    if (this.config.voteLimit !== undefined && items?.[this.config.voteLimit]) {
205
      items[this.config.voteLimit].selected = true;
206
    } else {
207
      items[1].selected = true;
208
    }
209
    widgets.push(
210
      {
211
        'selectionInput': {
212
          'type': 'DROPDOWN',
213
          'label': 'Vote Limit (Max options that can be voted)',
214
          'name': 'vote_limit',
215
          items,
216
        },
217
      });
218
219
    this.card.sections!.push({
220
      widgets,
221
    });
222
  }
223
224
  buildHelpText() {
225
    return {
226
      textParagraph: {
227
        text: 'Enter the poll topic and up to 10 choices in the poll. Blank options will be omitted.<br>' +
228
          'For scheduled auto close, the minimum time is 5 minutes after poll created.',
229
      },
230
    };
231
  }
232
233
  topicInput(topic: string) {
234
    return {
235
      textInput: {
236
        label: 'Topic',
237
        type: 'MULTIPLE_LINE',
238
        name: 'topic',
239
        value: topic,
240
      },
241
    };
242
  }
243
244
  optionInput(
245
    index: number, value: string): chatV1.Schema$GoogleAppsCardV1Widget {
246
    return {
247
      textInput: {
248
        label: `Option ${index + 1}`,
249
        type: 'SINGLE_LINE',
250
        name: `option${index}`,
251
        value: value || '',
252
      },
253
    };
254
  }
255
256
  buildFooter() {
257
    this.card.fixedFooter = {
258
      'primaryButton': createButton('Submit', 'start_poll'),
259
    };
260
  }
261
}
262