Skip to content

Commit 32a790f

Browse files
committed
2 parents f73e6f9 + fe73c69 commit 32a790f

File tree

7 files changed

+132
-19
lines changed

7 files changed

+132
-19
lines changed

api/src/routes/authorities.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,44 @@ authoritiesRouter.get(
109109
}
110110
);
111111

112+
authoritiesRouter.post("/bulk-pdf", ReturnValidationErrors, async (req: Request, res: Response) => {
113+
const { ids } = req.body;
114+
const idList = eval(ids);
115+
116+
const PDF_TEMPLATE = fs.readFileSync(__dirname + "/../templates/pdf/FormBTemplate.html");
117+
118+
let allItemData = "";
119+
120+
for (let id of idList) {
121+
let item = await loadSingleAuthority(req, id);
122+
123+
if (item) {
124+
(item as any).API_PORT = API_PORT;
125+
126+
if (item.authority_type == "temporary") item.authority_type = "TEMPORARY";
127+
else if (item.authority_type == "acting") item.authority_type = "ACTING";
128+
else item.authority_type = "SUBSTANTIVE";
129+
130+
let t = new ExpressHandlebars();
131+
132+
const template = t.handlebars.compile(PDF_TEMPLATE.toString(), {});
133+
let data = template(item, {
134+
helpers: {
135+
eq: function (a1: string, a2: string) {
136+
return a1 == a2;
137+
},
138+
},
139+
});
140+
141+
allItemData += data + '<div style="page-break-after: always;"></div>';
142+
}
143+
}
144+
let pdf = await generatePDF(allItemData);
145+
res.setHeader("Content-disposition", `attachment; filename="FormB_BULKPRINT.pdf"`);
146+
res.setHeader("Content-type", "application/pdf");
147+
res.send(pdf);
148+
});
149+
112150
authoritiesRouter.get(
113151
"/:id/pdf/draft",
114152
[param("id").isMongoId().notEmpty()],

api/src/routes/integration-router.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ integrationRouter.use(RequiresData);
99

1010
integrationRouter.get("/authorities-for-user/:email", async (req: Request, res: Response) => {
1111
const { email } = req.params;
12-
console.log("Authorities requested for", email);
13-
1412
let db = req.store.Authorities as GenericService<Authority>;
1513
let regex = RegExp(email, "i");
1614
let auths = await db.getAll({ "employee.email": { $regex: regex } });
@@ -37,7 +35,5 @@ integrationRouter.get("/authorities-for-user/:email", async (req: Request, res:
3735
results.push({ email: auth.employee.email, authority_lines, modified_date });
3836
}
3937

40-
console.log("** Sending", results.length);
41-
4238
res.json({ data: results });
4339
});

k8s/manifests-qa/ingress.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#The commented out sections below are for when the application is set up for SSL
22
#They should be uncommented out when application is SSL enabled
3-
apiVersion: traefik.containo.us/v1alpha1
3+
apiVersion: traefik.io/v1alpha1
44
kind: IngressRoute
55
metadata:
66
name: signing-authority-qa-ingressroute
@@ -24,7 +24,7 @@ spec:
2424
secretName: signing-authority-cert
2525

2626
---
27-
apiVersion: traefik.containo.us/v1alpha1
27+
apiVersion: traefik.io/v1alpha1
2828
kind: IngressRoute
2929
metadata:
3030
name: http-to-https-redirect
@@ -42,7 +42,7 @@ spec:
4242
- name: signing-authority-qa
4343
port: 3000
4444
---
45-
apiVersion: traefik.containo.us/v1alpha1
45+
apiVersion: traefik.io/v1alpha1
4646
kind: Middleware
4747
metadata:
4848
name: redirect-to-https

k8s/manifests-test/ingress.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#The commented out sections below are for when the application is set up for SSL
22
#They should be uncommented out when application is SSL enabled
3-
apiVersion: traefik.containo.us/v1alpha1
3+
apiVersion: traefik.io/v1alpha1
44
kind: IngressRoute
55
metadata:
66
name: signing-authority-test-ingressroute
@@ -24,7 +24,7 @@ spec:
2424
secretName: signing-authority-cert
2525

2626
---
27-
apiVersion: traefik.containo.us/v1alpha1
27+
apiVersion: traefik.io/v1alpha1
2828
kind: IngressRoute
2929
metadata:
3030
name: http-to-https-redirect
@@ -42,7 +42,7 @@ spec:
4242
- name: signing-authority-test
4343
port: 3000
4444
---
45-
apiVersion: traefik.containo.us/v1alpha1
45+
apiVersion: traefik.io/v1alpha1
4646
kind: Middleware
4747
metadata:
4848
name: redirect-to-https

web/src/modules/departments/views/DepartmentFormBList.vue

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
background-color="white"
5454
/>
5555
</v-col>
56-
<v-col cols="12" md="6">
56+
<v-col cols="12" md="6" class="d-flex">
5757
<v-select
5858
label="Activity"
5959
prepend-inner-icon="mdi-filter"
@@ -66,6 +66,7 @@
6666
hide-details
6767
background-color="white"
6868
/>
69+
<v-btn class="my-0 ml-5" style="height: 40px" color="secondary" @click="printClick"> Bulk Print</v-btn>
6970
</v-col>
7071
</v-row>
7172

@@ -89,12 +90,47 @@
8990
</v-card-text>
9091
</v-card>
9192
</BaseCard>
93+
94+
<v-dialog v-model="showPrintDialog" persistent width="600">
95+
<v-app-bar dark color="#0097A9">
96+
<v-toolbar-title>Generate Form A</v-toolbar-title>
97+
<v-spacer />
98+
<v-icon title="Close" @click="closePrintDialog">mdi-close</v-icon>
99+
</v-app-bar>
100+
<v-card tile>
101+
<v-card-text class="pt-3">
102+
<p>
103+
This procedure bulk prints all of the Form B authorizations listed below. You can remove items from the list
104+
by clicking the "X" on the right side.
105+
</p>
106+
107+
<v-list dense>
108+
<div v-for="(item, idx) of printList" :key="idx">
109+
<v-divider></v-divider>
110+
<v-list-item>
111+
<v-list-item-content>
112+
{{ item.employee.title }} - {{ item.employee.name }} ({{ convertType(item.authority_type) }})
113+
</v-list-item-content>
114+
<v-list-item-icon>
115+
<v-btn color="warning" class="my-0" small icon @click="removeMatchingItem(idx)"
116+
><v-icon>mdi-close</v-icon></v-btn
117+
>
118+
</v-list-item-icon>
119+
</v-list-item>
120+
</div>
121+
</v-list>
122+
123+
<v-btn color="primary" class="mb-0" @click="doPrint" :disabled="printList.length == 0">Print All</v-btn>
124+
</v-card-text>
125+
</v-card>
126+
</v-dialog>
92127
</v-container>
93128
</template>
94129

95130
<script>
96131
import { mapActions, mapState } from "vuex";
97132
import { clone, uniq, isEmpty } from "lodash";
133+
import { AUTHORITY_URL } from "@/urls";
98134
import createFormB from "@/modules/forms/formB/components/createFormB.vue";
99135
100136
export default {
@@ -144,6 +180,9 @@ export default {
144180
formBItems: [],
145181
loadingFormB: false,
146182
formBLink: "",
183+
184+
showPrintDialog: false,
185+
printList: [],
147186
}),
148187
mounted: async function() {
149188
this.departmentId = this.$route.params.departmentId;
@@ -269,7 +308,6 @@ export default {
269308
}
270309
271310
if (this.programFilter != "All") {
272-
console.log("FILTER ON ", this.programFilter);
273311
list = list.filter((i) => i.program_branch == this.programFilter);
274312
}
275313
@@ -284,6 +322,42 @@ export default {
284322
if (input == "acting") return "Acting";
285323
return "Substantive";
286324
},
325+
326+
printClick() {
327+
this.printList = clone(this.allItems);
328+
329+
this.showPrintDialog = true;
330+
},
331+
332+
doPrint() {
333+
const idList = this.printList.map((item) => item._id);
334+
335+
// do a post to a _blank window with the ids in the body
336+
const form = document.createElement('form');
337+
form.method = 'POST';
338+
form.action = `${AUTHORITY_URL}/bulk-pdf`;
339+
form.target = '_blank';
340+
341+
const input = document.createElement('input');
342+
input.type = 'hidden';
343+
input.name = 'ids';
344+
input.value = JSON.stringify(idList);
345+
346+
form.appendChild(input);
347+
document.body.appendChild(form);
348+
form.submit();
349+
document.body.removeChild(form);
350+
351+
// return `${AUTHORITY_URL}/${this.formB._id}/pdf`;
352+
},
353+
354+
removeMatchingItem(idx) {
355+
this.printList.splice(idx, 1);
356+
},
357+
358+
closePrintDialog() {
359+
this.showPrintDialog = false;
360+
},
287361
},
288362
};
289363
</script>

web/src/modules/departments/views/DepartmentPendingGroupDetail.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@
161161
<strong>{{ item.activity }}</strong>
162162
</v-card-subtitle>
163163
<v-card-text>
164+
<v-alert v-if="item.status == 'Archived'" color="warning" outlined>This Form A is 'Archived' and is no longer valid.</v-alert>
165+
164166
<v-data-table
165167
:headers="headers"
166168
:items="item.positions"

web/src/modules/departments/views/DepartmentPositionList.vue

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
<v-card-title>Delegations by Position</v-card-title>
4444
<v-card-text>
4545
<v-row>
46-
<v-col>
46+
<v-col cols="4">
4747
<v-select
4848
label="Filter Program"
4949
v-model="programFilter"
@@ -54,7 +54,7 @@
5454
background-color="white"
5555
/>
5656
</v-col>
57-
<v-col>
57+
<v-col class="d-flex">
5858
<v-select
5959
label="Filter Activity"
6060
v-model="activityFilter"
@@ -65,17 +65,16 @@
6565
outlined
6666
background-color="white"
6767
/>
68-
</v-col>
69-
<v-col>
7068
<v-btn
7169
:disabled="!canGenerate"
7270
color="secondary"
73-
class="my-0"
71+
class="my-0 ml-5"
72+
style="height: 40px"
7473
@click="generateFormAClick"
7574
v-if="canAdminister"
7675
>Generate Form A</v-btn
77-
></v-col
78-
>
76+
>
77+
</v-col>
7978
</v-row>
8079

8180
<v-data-table
@@ -456,6 +455,10 @@ export default {
456455
457456
return item.position;
458457
},
458+
459+
closeUpdateDialog() {
460+
this.showUpdateDialog = false;
461+
},
459462
},
460463
};
461464
</script>

0 commit comments

Comments
 (0)