Skip to content
This repository was archived by the owner on May 13, 2024. It is now read-only.

Commit a236e0d

Browse files
authored
Merge pull request #777 from derrabauke/feat-reject-report
feat: reject report
2 parents 89c5b29 + 7e9df37 commit a236e0d

File tree

13 files changed

+205
-56
lines changed

13 files changed

+205
-56
lines changed

app/analysis/edit/template.hbs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,26 @@
157157
</SyCheckbox>
158158
</f.input>
159159

160+
<f.input @name="rejected" as |fi|>
161+
<SyCheckbox
162+
data-test-rejected
163+
@checked={{fi.value}}
164+
@onChange={{fi.update}}
165+
@disabled={{or
166+
(not this.canVerify)
167+
this.hasSelectedOwnReports
168+
}}
169+
>
170+
Reject report
171+
{{#if (eq model.rejected null)}}
172+
<NotIdenticalWarning />
173+
{{/if}}
174+
{{#if (not (eq f.model.rejected model.rejected))}}
175+
<ChangedWarning />
176+
{{/if}}
177+
</SyCheckbox>
178+
</f.input>
179+
160180
<f.input @name="billed" as |fi|>
161181
<SyCheckbox
162182
data-test-billed

app/analysis/index/controller.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ export const AnalysisQueryParams = new QueryParams({
8888
replace: true,
8989
refresh: true,
9090
},
91+
rejected: {
92+
defaultValue: undefined,
93+
replace: true,
94+
refresh: true,
95+
},
9196
notBillable: {
9297
defaultValue: undefined,
9398
replace: true,

app/analysis/index/template.hbs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,23 @@
125125
/>
126126
</fs.group>
127127
<fs.group @label="State">
128+
<fs.label>
129+
Rejected
130+
<fs.filter
131+
data-test-filter-rejected
132+
@type="button"
133+
@selected={{this.rejected}}
134+
@valuePath="value"
135+
@labelPath="label"
136+
@options={{array
137+
(hash label="All" value="")
138+
(hash label="Rejected" value="1")
139+
(hash label="Not rejected" value="0")
140+
}}
141+
@onChange={{fn (mut this.rejected)}}
142+
/>
143+
</fs.label>
144+
128145
<fs.label>
129146
Review
130147
<fs.filter
@@ -260,6 +277,9 @@
260277
<col />
261278
<col />
262279
<col />
280+
<col />
281+
<col />
282+
<col />
263283
</colgroup>
264284
<thead>
265285
<tr>
@@ -303,6 +323,7 @@
303323
@current={{this.ordering}}
304324
@by="verified_by__username"
305325
>Verified by</SortHeader>
326+
<th>Rejected</th>
306327
<th>Review</th>
307328
<th>Not billable</th>
308329
<th>Billed</th>
@@ -323,6 +344,8 @@
323344
<col />
324345
<col />
325346
<col />
347+
<col />
348+
<col />
326349
</colgroup>
327350
<tbody>
328351
{{#each reports as |report|}}
@@ -351,6 +374,7 @@
351374
report.verifiedBy
352375
report.verifiedBy.username
353376
}}</td>
377+
<td><SyCheckmark @checked={{report.rejected}} /></td>
354378
<td><SyCheckmark @checked={{report.review}} /></td>
355379
<td><SyCheckmark @checked={{report.notBillable}} /></td>
356380
<td><SyCheckmark @checked={{report.billed}} /></td>
@@ -381,13 +405,6 @@
381405
<col />
382406
<col />
383407
<col />
384-
<col />
385-
<col />
386-
<col />
387-
<col />
388-
<col />
389-
<col />
390-
<col />
391408
</colgroup>
392409
<tfoot>
393410
<tr>
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
import { tagName } from "@ember-decorators/component";
21
import Component from "@ember/component";
32
import { inject as service } from "@ember/service";
4-
import classic from "ember-classic-decorator";
53

6-
@classic
7-
@tagName("")
84
export default class ReportReviewWarning extends Component {
95
@service
106
session;
117

128
@service
139
unverifiedReports;
10+
11+
@service
12+
rejectedReports;
1413
}
Lines changed: 53 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,53 @@
1-
{{#if this.unverifiedReports.hasReports}}
2-
<li class="nav-top-list-item" title="You have reports to verify">
3-
<LinkTo
4-
@route="analysis.index"
5-
@query={{hash
6-
fromDate=null
7-
toDate=this.unverifiedReports.reportsToDate
8-
reviewer=this.session.data.user.id
9-
editable=1
10-
verified=0
11-
customer=null
12-
project=null
13-
task=null
14-
user=null
15-
billingType=null
16-
costCenter=null
17-
review=""
18-
notBillable=""
19-
}}
20-
>
21-
<FaIcon @icon="exclamation-triangle" @prefix="fas" />
22-
{{this.unverifiedReports.amountReports}}
23-
</LinkTo>
24-
</li>
25-
{{/if}}
1+
<div class="flex">
2+
{{#if this.unverifiedReports.hasReports}}
3+
<li class="nav-top-list-item" title="You have reports to verify">
4+
<LinkTo
5+
@route="analysis.index"
6+
@query={{hash
7+
fromDate=null
8+
toDate=this.unverifiedReports.reportsToDate
9+
reviewer=this.session.data.user.id
10+
editable=1
11+
verified=0
12+
customer=null
13+
project=null
14+
task=null
15+
user=null
16+
billingType=null
17+
costCenter=null
18+
review=""
19+
notBillable=""
20+
}}
21+
>
22+
<FaIcon @icon="exclamation-triangle" @prefix="fas" />
23+
{{this.unverifiedReports.amountReports}}
24+
</LinkTo>
25+
</li>
26+
{{/if}}
27+
{{#if this.rejectedReports.hasReports}}
28+
<li class="nav-top-list-item" title="You have rejected reports">
29+
<LinkTo
30+
@route="analysis.index"
31+
@query={{hash
32+
fromDate=null
33+
toDate=this.unverifiedReports.reportsToDate
34+
reviewer=this.session.data.user.id
35+
editable=1
36+
rejected=1
37+
verified=0
38+
customer=null
39+
project=null
40+
task=null
41+
user=null
42+
billingType=null
43+
costCenter=null
44+
review=""
45+
notBillable=""
46+
}}
47+
>
48+
<FaIcon @icon="times-circle" />
49+
{{this.rejectedReports.amountReports}}
50+
</LinkTo>
51+
</li>
52+
{{/if}}
53+
</div>

app/components/user-selection/component.js

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,7 @@ export default class UserSelection extends Component {
1717

1818
constructor(...args) {
1919
super(...args);
20-
this.fetchUsers();
21-
}
22-
23-
async fetchUsers() {
24-
try {
25-
await this.tracking.users.perform();
26-
} catch (e) {
27-
if (e.taskInstance && e.taskInstance.isCanceling) {
28-
return;
29-
}
30-
throw e;
31-
}
20+
this.tracking.users.perform();
3221
}
3322

3423
@restartableTask

app/models/report-intersection.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Model, { attr, belongsTo } from "@ember-data/model";
33
export default Model.extend({
44
comment: attr("string"),
55
notBillable: attr("boolean", { allowNull: true, defaultValue: null }),
6+
rejected: attr("boolean", { allowNull: true, defaultValue: null }),
67
review: attr("boolean", { allowNull: true, defaultValue: null }),
78
billed: attr("boolean", { allowNull: true, defaultValue: null }),
89
verified: attr("boolean", { allowNull: true, defaultValue: null }),

app/models/report.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ export default class Report extends Model {
5656
*/
5757
@attr("boolean", { defaultValue: false }) review;
5858

59+
/**
60+
* Whether the report got rejected by the reviewer
61+
*
62+
* @property {Boolean} reject
63+
* @public
64+
*/
65+
@attr("boolean", { defaultValue: false }) rejected;
66+
5967
/**
6068
* Whether the report is not billable
6169
*

app/services/rejected-reports.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import Service, { inject as service } from "@ember/service";
2+
import { macroCondition, isTesting } from "@embroider/macros";
3+
import { tracked } from "@glimmer/tracking";
4+
import moment from "moment";
5+
6+
const INTERVAL_DELAY = 10 * 60000; // 10 Minutes
7+
8+
export default class RejectedReportsService extends Service {
9+
@service
10+
store;
11+
12+
@service
13+
session;
14+
15+
@service
16+
notify;
17+
18+
@tracked amountReports = 0;
19+
@tracked intervalId;
20+
21+
get hasReports() {
22+
return this.amountReports > 0;
23+
}
24+
25+
get reportsToDate() {
26+
return moment().subtract(1, "month").endOf("month");
27+
}
28+
29+
constructor(...args) {
30+
super(...args);
31+
32+
this.pollReports();
33+
34+
/* instanbul ignore next */
35+
if (macroCondition(isTesting())) {
36+
this.intervalId = null;
37+
} else {
38+
this.intervalId = setInterval(
39+
this.pollReports.bind(this),
40+
INTERVAL_DELAY
41+
);
42+
}
43+
}
44+
45+
async pollReports() {
46+
try {
47+
const reports = await this.store.query("report", {
48+
to_date: this.reportsToDate.format("YYYY-MM-DD"),
49+
reviewer: this.session.data.user.id,
50+
editable: 1,
51+
rejected: 1,
52+
page: { number: 1, size: 1 },
53+
});
54+
55+
this.amountReports = reports.meta.pagination.count;
56+
} catch (e) {
57+
this.notify.error("Error while polling reports");
58+
}
59+
}
60+
61+
willDestroy() {
62+
clearInterval(this.intervalId);
63+
}
64+
}

app/services/tracking.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ export default class TrackingService extends Service {
258258
* @property {EmberConcurrency.Task} users
259259
* @public
260260
*/
261-
@task
261+
@dropTask
262262
*users() {
263263
return yield this.store.query("user", {});
264264
}
@@ -288,7 +288,7 @@ export default class TrackingService extends Service {
288288
* @param {Number} customer The customer id to filter by
289289
* @public
290290
*/
291-
@task
291+
@dropTask
292292
*projects(customer) {
293293
if (!customer) {
294294
// We can't test this because the UI prevents it
@@ -305,7 +305,7 @@ export default class TrackingService extends Service {
305305
* @param {Number} project The project id to filter by
306306
* @public
307307
*/
308-
@task
308+
@dropTask
309309
*tasks(project) {
310310
if (!project) {
311311
// We can't test this because the UI prevents it

app/styles/analysis.scss

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
&:nth-child(4),
2626
&:nth-child(5),
2727
&:nth-child(6) {
28-
width: 11%;
28+
width: 10%;
2929
}
3030

3131
&:nth-child(8) {
@@ -34,12 +34,13 @@
3434

3535
&:nth-child(9),
3636
&:nth-child(10),
37-
&:nth-child(11){
38-
width: 6%;
37+
&:nth-child(11),
38+
&:nth-child(12) {
39+
width: 5%;
3940
}
4041

4142
&:nth-child(7) {
42-
width: 20%;
43+
width: 21%;
4344
}
4445
}
4546

@@ -50,7 +51,7 @@
5051

5152
.analysis-scrollable-container::after,
5253
.analysis-scrollable-container::before {
53-
content: '';
54+
content: "";
5455
position: absolute;
5556
z-index: 1;
5657
left: 0;

app/styles/app.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ strong {
5555
font-weight: bold;
5656
}
5757

58+
.flex {
59+
display: flex;
60+
}
61+
5862
.pointer {
5963
cursor: pointer;
6064
}
@@ -322,6 +326,7 @@ strong {
322326
color: darken($color-border, 25%);
323327
height: 100%;
324328
display: flex;
329+
flex-direction: column;
325330
align-items: center;
326331
justify-content: center;
327332
text-align: center;

0 commit comments

Comments
 (0)