• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RoundingWell / care-ops-frontend / 692f9f2e-3aac-4156-9197-4812d5314b95

20 Aug 2025 07:09AM UTC coverage: 92.095% (-7.9%) from 100.0%
692f9f2e-3aac-4156-9197-4812d5314b95

Pull #1488

circleci

paulfalgout
Test patient overline on worklist
Pull Request #1488: Add subgrid to lists

1639 of 1844 branches covered (88.88%)

Branch coverage included in aggregate %.

5771 of 6202 relevant lines covered (93.05%)

195.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.3
/src/js/views/programs/sidebar/program/programs-sidebar_views.js
1
import hbs from 'handlebars-inline-precompile';
2
import { View } from 'marionette';
3
import dayjs from 'dayjs';
4

5
import 'scss/modules/buttons.scss';
6
import 'scss/modules/textarea-flex.scss';
7
import 'scss/modules/sidebar.scss';
8

9
import intl from 'js/i18n';
10
import keyCodes from 'js/utils/formatting/key-codes';
11
import removeNewline from 'js/utils/formatting/remove-newline';
12
import trim from 'js/utils/formatting/trim';
13

14
import InputWatcherBehavior from 'js/behaviors/input-watcher';
15

16
import ProgramDetailsTemplate from './program-details.hbs';
17
import ProgramNameTemplate from './program-name.hbs';
18
import ProgramSidebarTemplate from './program-sidebar.hbs';
19

20
import './programs-sidebar.scss';
21

22
const { ENTER_KEY } = keyCodes;
130✔
23

24
const i18n = intl.programs.sidebar.program.programsSidebarViews;
130✔
25

26
export const headingText = i18n.headingText;
130✔
27

28
const DisabledSaveView = View.extend({
130✔
29
  className: 'u-margin--t-8 sidebar__save',
30
  template: hbs`<button class="button--green" disabled>{{ @intl.programs.sidebar.program.programsSidebarViews.disabledSaveView.saveBtn }}</button>`,
31
});
32

33
const SaveView = View.extend({
130✔
34
  className: 'u-margin--t-8 sidebar__save',
35
  template: hbs`
36
    <button class="button--green js-save">{{ @intl.programs.sidebar.program.programsSidebarViews.saveView.saveBtn }}</button>
37
    <button class="button--text u-margin--r-4 js-cancel">{{ @intl.programs.sidebar.program.programsSidebarViews.saveView.cancelBtn }}</button>
38
  `,
39
  triggers: {
40
    'click .js-cancel': 'cancel',
41
    'click .js-save': 'save',
42
  },
43
});
44

45
const NameView = View.extend({
130✔
46
  template: ProgramNameTemplate,
47
  behaviors: [InputWatcherBehavior],
48
  ui: {
49
    input: '.js-input',
50
    spacer: '.js-spacer',
51
  },
52
  onWatchKeydown(evt) {
53
    if (evt.which === ENTER_KEY) {
16!
54
      evt.preventDefault();
×
55
      return;
×
56
    }
57
  },
58
  onWatchChange(text) {
59
    const newText = removeNewline(text);
16✔
60
    this.ui.input.val(newText);
16✔
61
    this.ui.spacer.text(newText || ' ');
16✔
62

63
    this.model.set('name', newText);
16✔
64
  },
65
  templateContext() {
66
    return {
2✔
67
      error: this.getOption('error'),
68
      isNew: this.model.isNew(),
69
    };
70
  },
71
  onDomRefresh() {
72
    if (this.model.isNew()) {
2!
73
      this.ui.input.focus();
×
74
    }
75
  },
76
});
77

78
const DetailsView = View.extend({
130✔
79
  className: 'pos--relative',
80
  template: ProgramDetailsTemplate,
81
  behaviors: [InputWatcherBehavior],
82
  ui: {
83
    input: '.js-input',
84
    spacer: '.js-spacer',
85
  },
86
  onWatchChange(text) {
87
    this.ui.input.val(text);
×
88
    this.ui.spacer.text(text || ' ');
×
89

90
    this.model.set('details', trim(text));
×
91
  },
92
});
93

94
const ToggleView = View.extend({
130✔
95
  template: hbs`
96
    <button class="programs-sidebar__toggle button-secondary {{#if status}}is-on{{/if}} js-toggle" {{#if isDisabled}}disabled{{/if}}>
97
      {{#if status}}{{fas "toggle-on"}}{{else}}{{far "toggle-off"}}{{/if}}
98
      {{formatMessage (intlGet "programs.shared.components.toggleComponent.toggle") status=status}}
99
    </button>
100
  `,
101
  templateContext() {
102
    return {
4✔
103
      status: this.getOption('status'),
104
      isDisabled: this.getOption('isDisabled'),
105
    };
106
  },
107
  triggers: {
108
    'click .js-toggle': 'click',
109
  },
110
});
111

112
const TimestampsView = View.extend({
130✔
113
  className: 'sidebar__footer flex',
114
  template: hbs`
115
    <div class="sidebar__footer-left"><h4 class="sidebar__label">{{ @intl.programs.sidebar.program.programsSidebarViews.timestampsView.createdAt }}</h4><div>{{formatDateTime created_at "AT_TIME"}}</div></div>
116
    <div><h4 class="sidebar__label">{{ @intl.programs.sidebar.program.programsSidebarViews.timestampsView.updatedAt }}</h4><div>{{formatDateTime updated_at "AT_TIME"}}</div></div>
117
  `,
118
});
119

120
const SidebarView = View.extend({
130✔
121
  childViewTriggers: {
122
    'save': 'save',
123
    'cancel': 'cancel',
124
    'toggle': 'toggle',
125
  },
126
  className: 'flex-grow',
127
  template: ProgramSidebarTemplate,
128
  regions: {
129
    name: '[data-name-region]',
130
    details: '[data-details-region]',
131
    published: '[data-published-region]',
132
    archived: '[data-archived-region]',
133
    save: '[data-save-region]',
134
  },
135
  templateContext() {
136
    return {
2✔
137
      isNew: this.model.isNew(),
138
    };
139
  },
140
  initialize({ program }) {
141
    this.program = program;
2✔
142
    this.model = this.program.clone();
2✔
143

144
    if (!this.model.isNew()) {
2!
145
      this.listenTo(this.program, {
2✔
146
        'change:published_at': this.showPublished,
147
        'change:archived_at': this.showArchived,
148
      });
149
    }
150
  },
151
  onRender() {
152
    this.showForm();
2✔
153
    this.showPublished();
2✔
154
    this.showArchived();
2✔
155
  },
156
  showForm() {
157
    this.stopListening(this.model);
2✔
158
    this.model = this.program.clone();
2✔
159
    this.listenTo(this.model, 'change:name change:details', this.showSave);
2✔
160

161
    if (this.model.isNew()) this.showDisabledSave();
2!
162
    else this.getRegion('save').empty();
2✔
163

164
    this.showName();
2✔
165
    this.showDetails();
2✔
166
  },
167
  showName(error) {
168
    this.showChildView('name', new NameView({ model: this.model, program: this.program, error }));
2✔
169
  },
170
  showDetails() {
171
    this.showChildView('details', new DetailsView({ model: this.model, program: this.program }));
2✔
172
  },
173
  showSave() {
174
    if (!this.model.isValid()) return this.showDisabledSave();
16✔
175

176
    this.showChildView('save', new SaveView({ model: this.model }));
14✔
177
  },
178
  showPublished() {
179
    if (this.program.isNew()) return;
2!
180

181
    const isPublished = !!this.program.get('published_at');
2✔
182

183
    const toggleView = new ToggleView({
2✔
184
      status: isPublished,
185
    });
186

187
    this.listenTo(toggleView, 'click', () => {
2✔
188
      const newPublishedAt = isPublished ? null : dayjs.utc().format();
×
189
      this.program.save({ published_at: newPublishedAt });
×
190
    });
191

192
    this.showChildView('published', toggleView);
2✔
193
  },
194
  showArchived() {
195
    if (this.program.isNew()) return;
2!
196

197
    const isArchived = !!this.program.get('archived_at');
2✔
198

199
    const toggleView = new ToggleView({
2✔
200
      status: isArchived,
201
    });
202

203
    this.listenTo(toggleView, 'click', () => {
2✔
204
      const newArchivedAt = isArchived ? null : dayjs.utc().format();
×
205
      this.program.save({ archived_at: newArchivedAt });
×
206
    });
207

208
    this.showChildView('archived', toggleView);
2✔
209
  },
210
  showDisabledSave() {
211
    this.showChildView('save', new DisabledSaveView());
2✔
212
  },
213
  onSave() {
214
    if (this.model.isNew()) this.showDisabledSave();
2!
215
    else this.getRegion('save').empty();
2✔
216
  },
217
  showErrors({ name }) {
218
    this.showName(name);
×
219
    this.showDisabledSave();
×
220
  },
221
  onCancel() {
222
    if (this.model.isNew()) {
×
223
      this.triggerMethod('close', this);
×
224
      return;
×
225
    }
226

227
    this.showForm();
×
228
  },
229
});
230

231
export {
232
  SidebarView,
233
  TimestampsView,
234
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc