• 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

77.42
/src/js/views/programs/program/workflows/workflows_views.js
1
import Radio from 'backbone.radio';
2

3
import hbs from 'handlebars-inline-precompile';
4
import { View, CollectionView, Behavior } from 'marionette';
5

6
import { alphaSort } from 'js/utils/sorting';
7

8
import 'scss/modules/buttons.scss';
9
import 'scss/modules/table-list.scss';
10

11
import { PROGRAM_BEHAVIORS } from 'js/static';
12
import intl from 'js/i18n';
13

14
import Droplist from 'js/components/droplist';
15

16
import PreloadRegion from 'js/regions/preload_region';
17

18
import { OwnerComponent as FlowOwnerComponent } from 'js/views/programs/shared/flows_views';
19
import { DueDayComponent, OwnerComponent, BehaviorComponent } from 'js/views/programs/shared/actions_views';
20

21
import ActionItemTemplate from './action-item.hbs';
22
import FlowItemTemplate from './flow-item.hbs';
23
import LayoutTemplate from './layout.hbs';
24

25
import 'scss/domain/program-action-state.scss';
26
import './workflows.scss';
27

28
const EmptyView = View.extend({
130✔
29
  className: 'table-list__empty-list',
30
  template: hbs`<h2>{{ @intl.programs.program.workflows.workflowsViews.emptyView }}</h2>`,
31
});
32

33
const RowBehavior = Behavior.extend({
130✔
34
  modelEvents: {
35
    'editing': 'onEditing',
36
    'change': 'onChange',
37
  },
38
  onChange() {
39
    this.view.render();
2✔
40
  },
41
  onEditing(isEditing) {
42
    this.$el.toggleClass('is-selected', isEditing);
7✔
43
  },
44
  onInitialize() {
45
    if (this.view.model.isNew()) this.$el.addClass('is-selected');
39✔
46
  },
47
});
48

49
const ActionItemView = View.extend({
130✔
50
  className: 'table-list__item',
51
  behaviors: [RowBehavior],
52
  regions: {
53
    behavior: '[data-behavior-region]',
54
    owner: '[data-owner-region]',
55
    due: '[data-due-region]',
56
  },
57
  template: ActionItemTemplate,
58
  templateContext() {
59
    return {
25✔
60
      hasForm: this.model.getForm(),
61
      icon: this.model.hasOutreach() ? 'share-from-square' : 'file-lines',
25!
62
    };
63
  },
64
  triggers: {
65
    'click': 'click',
66
  },
67
  onClick() {
68
    if (this.model.isNew()) {
1!
69
      Radio.trigger('event-router', 'program:action:new', this.model.getProgram().id);
×
70
      return;
×
71
    }
72

73
    Radio.trigger('event-router', 'program:action', this.model.getProgram().id, this.model.id);
1✔
74
  },
75
  onRender() {
76
    this.showBehavior();
25✔
77
    this.showOwner();
25✔
78
    this.showDue();
25✔
79
  },
80
  showBehavior() {
81
    const isDisabled = this.model.isNew();
25✔
82
    const isFromFlow = !!this.model.getProgramFlow();
25✔
83
    const behaviorComponent = new BehaviorComponent({
25✔
84
      isConditionalAvailable: isFromFlow,
85
      behavior: this.model.get('behavior'),
86
      isCompact: true,
87
      state: { isDisabled },
88
    });
89

90
    this.listenTo(behaviorComponent, 'change:status', ({ behavior }) => {
25✔
91
      this.model.save({ behavior });
×
92
    });
93

94
    this.showChildView('behavior', behaviorComponent);
25✔
95
  },
96
  showOwner() {
97
    const isDisabled = this.model.isNew();
25✔
98
    const isFromFlow = !!this.model.getProgramFlow();
25✔
99
    const ownerComponent = new OwnerComponent({ owner: this.model.getOwner(), isFromFlow, isCompact: true, state: { isDisabled } });
25✔
100

101
    this.listenTo(ownerComponent, 'change:owner', owner => {
25✔
102
      this.model.saveOwner(owner);
×
103
    });
104

105
    this.showChildView('owner', ownerComponent);
25✔
106
  },
107
  showDue() {
108
    const isDisabled = this.model.isNew();
25✔
109
    const dueDayComponent = new DueDayComponent({ day: this.model.get('days_until_due'), isCompact: true, state: { isDisabled } });
25✔
110

111
    this.listenTo(dueDayComponent, 'change:day', day => {
25✔
112
      this.model.save({ days_until_due: day });
×
113
    });
114

115
    this.showChildView('due', dueDayComponent);
25✔
116
  },
117
});
118

119
const FlowItemView = View.extend({
130✔
120
  className: 'table-list__item',
121
  behaviors: [RowBehavior],
122
  regions: {
123
    owner: '[data-owner-region]',
124
  },
125
  template: FlowItemTemplate,
126
  templateContext() {
127
    return {
16✔
128
      published: !!this.model.get('published_at'),
129
      isAutomated: this.model.get('behavior') === PROGRAM_BEHAVIORS.AUTOMATED,
130
    };
131
  },
132
  triggers: {
133
    'click': 'click',
134
  },
135
  onClick() {
136
    if (this.model.isNew()) {
×
137
      Radio.trigger('event-router', 'programFlow:new', this.model.getProgram().id);
×
138
      return;
×
139
    }
140

141
    Radio.trigger('event-router', 'programFlow', this.model.id);
×
142
  },
143
  onRender() {
144
    this.showOwner();
16✔
145
  },
146
  showOwner() {
147
    const isDisabled = this.model.isNew();
16✔
148
    const ownerComponent = new FlowOwnerComponent({ owner: this.model.getOwner(), isCompact: true, state: { isDisabled } });
16✔
149

150
    this.listenTo(ownerComponent, 'change:owner', owner => {
16✔
151
      this.model.saveOwner(owner);
×
152
    });
153

154
    this.showChildView('owner', ownerComponent);
16✔
155
  },
156
});
157

158
const ListView = CollectionView.extend({
130✔
159
  className: 'table-list__list list-page__list',
160
  childView(item) {
161
    if (item.type === 'program-flows') {
39✔
162
      return FlowItemView;
15✔
163
    }
164

165
    return ActionItemView;
24✔
166
  },
167
  emptyView: EmptyView,
168
  viewComparator(viewA, viewB) {
169
    return alphaSort('desc', viewA.model.get('updated_at'), viewB.model.get('updated_at'));
71✔
170
  },
171
});
172

173
const LayoutView = View.extend({
130✔
174
  className: 'flex-region workflows__content',
175
  regions: {
176
    content: {
177
      el: '[data-content-region]',
178
      regionClass: PreloadRegion,
179
      replaceElement: true,
180
    },
181
    add: '[data-add-region]',
182
  },
183
  template: LayoutTemplate,
184
});
185

186
const AddActionDroplist = Droplist.extend({
130✔
187
  popWidth: 248,
188
  picklistOptions() {
189
    return {
3✔
190
      headingText: intl.programs.program.workflows.workflowsViews.addActionHeading,
191
      itemClassName: 'u-text--italic',
192
    };
193
  },
194
  viewOptions: {
195
    className: 'button-primary',
196
    template: hbs`{{far "circle-plus"}}<span>{{ @intl.programs.program.workflows.workflowsViews.addAction }}</span>{{far "angle-down" classes="workflows__arrow"}}`,
197
  },
198
  picklistEvents: {
199
    'picklist:item:select': 'onSelect',
200
  },
201
  onSelect({ model }) {
202
    model.get('onSelect')();
3✔
203
  },
204
});
205

206
export {
207
  ListView,
208
  LayoutView,
209
  AddActionDroplist,
210
};
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