Skip to content

Commit 3aaa904

Browse files
ammsalmenatlibfi-jonollil
andauthoredJun 18, 2024··
Add Mailer functionality & Dependency Update (#91)
* Add mailer and mailer cli * Dependency update (#90) * Bump braces from 3.0.2 to 3.0.3 (#89) * Bump the development-dependencies group across 1 directory with 8 updates (#88) | Package | From | To | | --- | --- | --- | | [@babel/cli](https://github.com/babel/babel/tree/HEAD/packages/babel-cli) | `7.24.5` | `7.24.7` | | [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) | `7.24.5` | `7.24.7` | | [@babel/node](https://github.com/babel/babel/tree/HEAD/packages/babel-node) | `7.23.9` | `7.24.7` | | [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) | `7.24.5` | `7.24.7` | | [@natlibfi/fixugen](https://github.com/natlibfi/fixugen-js) | `2.0.5` | `2.0.6` | | [nock](https://github.com/nock/nock) | `14.0.0-beta.6` | `14.0.0-beta.7` | | [nodemon](https://github.com/remy/nodemon) | `3.1.0` | `3.1.3` | * Bump debug from 4.3.4 to 4.3.5 in the production-dependencies group (#86) * 2.3.0-alpha.12 --------- Co-authored-by: natlibfi-jonollil <53558796+natlibfi-jonollil@users.noreply.github.com>
1 parent 8200445 commit 3aaa904

10 files changed

+1712
-569
lines changed
 

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ dist
55
.nyc_output
66
configCrowd.js
77
.DS_Store
8+
.env

‎README.md

+11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
# Shared modules for Melinda's backend applications [![NPM Version](https://img.shields.io/npm/v/@natlibfi/melinda-backend-commons.svg)](https://npmjs.org/package/@natlibfi/melinda-backend-commons)
22

3+
## Mailer cli
4+
### Envs:
5+
* Required
6+
* MELINDA_MAILER_SMTP_CONFIG: contains stringified smtp config
7+
* e.g. '{"host":"smtp.url.com","port":587,"secure": false,"auth":{"user":"","pass":""}}'
8+
* Optional
9+
* MELINDA_MAILER_EMAIL_FROM: Email from
10+
* MELINDA_MAILER_EMAIL_TO: Email to
11+
* MELINDA_MAILER_SUBJECT: Email subject
12+
* MELINDA_MAILER_TEMPLATE: Email template name
13+
314
## License and copyright
415

516
Copyright (c) 2018-2024 **University Of Helsinki (The National Library Of Finland)**

‎package-lock.json

+1,013-567
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"url": "git@github.com:natlibfi/melinda-backend-commons-js.git"
1515
},
1616
"license": "MIT",
17-
"version": "2.3.0-alpha.10",
17+
"version": "2.3.0-alpha.12",
1818
"main": "./dist/index.js",
1919
"bin": {
2020
"gen-jwt-token": "./dist/gen-jwt-token.js",
@@ -44,9 +44,12 @@
4444
"debug": "^4.3.4",
4545
"express-winston": "^4.2.0",
4646
"moment": "^2.30.1",
47+
"nodemailer": "^6.9.13",
48+
"nodemailer-express-handlebars": "^6.1.2",
4749
"pretty-print-ms": "^1.0.5",
4850
"uuid": "^9.0.1",
49-
"winston": "^3.13.0"
51+
"winston": "^3.13.0",
52+
"yargs": "^17.7.2"
5053
},
5154
"devDependencies": {
5255
"@babel/cli": "^7.24.5",

‎src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './utils';
2+
export {sendEmail} from './mailer';

‎src/mailer.js

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import nodemailer from 'nodemailer';
2+
import hbs from 'nodemailer-express-handlebars';
3+
import {createLogger} from './utils.js';
4+
import path from 'path';
5+
6+
export async function sendEmail({messageOptions = false, smtpConfig = false}) {
7+
if (!messageOptions || !smtpConfig) {
8+
throw new Error('Mailer is missing parametters');
9+
}
10+
const logger = createLogger();
11+
const {from, to, subject, templateName, context} = messageOptions;
12+
13+
// Establish email connection
14+
const transporter = nodemailer.createTransport(smtpConfig);
15+
16+
const viewPath = path.resolve(__dirname, './mailerTemplates/views');
17+
const partialsPath = path.resolve(__dirname, './mailerTemplates/partials');
18+
logger.debug(viewPath);
19+
logger.debug(partialsPath);
20+
21+
transporter.use('compile', hbs({
22+
viewEngine: {
23+
//extension name
24+
extName: '.handlebars',
25+
// layout path declare
26+
layoutsDir: viewPath,
27+
defaultLayout: false,
28+
//partials directory path
29+
partialsDir: partialsPath
30+
},
31+
//View path declare
32+
partialsDir: partialsPath,
33+
viewPath,
34+
extName: '.handlebars'
35+
}));
36+
37+
// Verify server is ready to accept messages
38+
await transporter.verify();
39+
40+
const nodemailerMessage = {
41+
from,
42+
to,
43+
subject,
44+
template: templateName,
45+
context
46+
};
47+
48+
// Send message, main try/catch should catch errors occurring here
49+
await transporter.sendMail(nodemailerMessage);
50+
}
51+

‎src/mailerCli.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {sendEmail} from './mailer';
2+
import fs from 'fs';
3+
import yargs from 'yargs';
4+
import {createLogger, handleInterrupt} from './utils.js';
5+
run();
6+
7+
async function run() {
8+
const logger = createLogger();
9+
10+
process
11+
.on('SIGINT', handleInterrupt)
12+
.on('unhandledRejection', handleInterrupt)
13+
.on('uncaughtException', handleInterrupt);
14+
15+
const args = yargs(process.argv.slice(2))
16+
.scriptName('melinda-mailer-cli')
17+
.wrap(yargs.terminalWidth())
18+
.epilog('Copyright (C) 2024 University Of Helsinki (The National Library Of Finland)')
19+
.usage('$0 <JSON file> [options] and env variable info in README')
20+
.showHelpOnFail(true)
21+
.example(['$ node $0/dist/cli.js file.json -e example@mail.com -s "Example subject" -t exampleTemplate'])
22+
.env('MELINDA_MAILER')
23+
.positional('file', {type: 'string', describe: 'File for template context'})
24+
.options({
25+
f: {type: 'string', default: false, alias: 'emailFrom', describe: 'Email from'},
26+
e: {type: 'string', default: false, alias: 'emailTo', describe: 'Email to'},
27+
s: {type: 'string', default: false, alias: 'subject', describe: 'Email subject'},
28+
t: {type: 'string', default: false, alias: 'template', describe: 'Email template'}
29+
})
30+
.check((args) => {
31+
const [file] = args._;
32+
if (file === undefined) {
33+
throw new Error('No file argument given');
34+
}
35+
36+
if (!fs.existsSync(file)) {
37+
throw new Error(`File ${file} does not exist`);
38+
}
39+
40+
return true;
41+
})
42+
.parseSync();
43+
44+
// console.log(JSON.stringify(args));
45+
logger.info(`Reading context file ${args._[0]}`);
46+
const context = JSON.parse(fs.readFileSync(args._[0], {encoding: 'UTF-8'}));
47+
logger.info('Reading smtp config from env');
48+
const smtpConfig = JSON.parse(args.smtpConfig);
49+
const messageOptions = {
50+
from: args.f,
51+
to: args.e,
52+
subject: args.s,
53+
templateName: args.t,
54+
context
55+
};
56+
logger.debug(JSON.stringify(messageOptions));
57+
logger.debug(JSON.stringify(smtpConfig));
58+
await sendEmail({smtpConfig, messageOptions});
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
<footer>
2+
<!-- [Footer partial (footer.hbs)] -->
3+
<div id="footer" class="footer">
4+
<!-- Footer fills user's viewport with empty filler-->
5+
<div class="flex-fill"></div>
6+
<!-- Footer content contains Melinda banner and NatLib banner -->
7+
<div class="footer-content" style="display: flex;flex-direction: column;font-size: 18px;letter-spacing: 0.05rem;">
8+
<!-- Melinda banner with four service info sections-->
9+
<div class="melinda-banner">
10+
<!-- Service logo and contact information -->
11+
<div id="melindaLogoAndContact" class="melinda-logo-and-contact-info">
12+
13+
<div class="melinda-logo">
14+
<a href="/">
15+
<imgsrc="https:
16+
//static.kansalliskirjasto.fi/melinda/images/logo-melinda-text-vertical-white-cropped.png">
17+
</a>
18+
</div>
19+
20+
<div class="melinda-contact-info">
21+
<div class="footer-heading-small">Sähköposti:</div>
22+
<a href="mailto:melinda-posti@helsinki.fi">
23+
<div class="footer-email">
24+
melinda-posti@helsinki.fi
25+
</div>
26+
</a>
27+
<div class="footer-heading-small">Postiosoite:</div>
28+
<div class="footer-text">Kansalliskirjasto</div>
29+
<div class="footer-text">Melinda</div>
30+
<div class="footer-text">PL 15</div>
31+
<div class="footer-text">00014 Helsingin yliopisto</div>
32+
</div>
33+
34+
</div>
35+
36+
<!-- Service description -->
37+
<div id="melindaAbout" class="melinda-about">
38+
39+
<div class="footer-heading">
40+
Melinda
41+
</div>
42+
43+
<div class="footer-text">
44+
45+
<div class="footer-paragraph">
46+
Melinda kokoaa kirjastoaineistoja kuvailevat metatiedot yhteen paikkaan.
47+
Melinda on järjestelmäriippumaton: kirjastot kuvailevat aineistonsa
48+
yhteiseen tietokantaan Melindan tarjoamassa työympäristössä. Metatiedoista
49+
kootaan kaikkien suomalaisten kirjastojen yhteinen metatietovaranto. Voit hakea tietoja
50+
Melindan yhteisestä tietokannasta Melinda-OPACista.
51+
</div>
52+
53+
<div class="footer-link-list">
54+
55+
<a href="https://www.kansalliskirjasto.fi/fi/palvelut/melinda" target="_blank" rel=”noopener noreferrer”>
56+
<div class="footer-link">
57+
<div class="footer-link-text">
58+
Lisätietoa Melindasta
59+
</div>
60+
</div>
61+
</a>
62+
63+
<a href="https://www.kansalliskirjasto.fi/sv/tjanster/melinda" target="_blank" rel=”noopener noreferrer”>
64+
<div class="footer-link">
65+
<div class="footer-link-text">
66+
Om Melinda på svenska
67+
</div>
68+
</div>
69+
</a>
70+
71+
<a href="https://www.kansalliskirjasto.fi/en/services/melinda" target="_blank" rel=”noopener noreferrer”>
72+
<div class="footer-link">
73+
<div class="footer-link-text">
74+
About Melinda in English
75+
</div>
76+
</div>
77+
</a>
78+
79+
</div>
80+
81+
</div>
82+
83+
</div>
84+
85+
<!-- Group of links related to service -->
86+
<div id="melindaLinks" class="melinda-links">
87+
88+
<div class="footer-heading">
89+
Palvelut
90+
</div>
91+
92+
<div class="footer-link-list">
93+
94+
<a href="https://melinda.kansalliskirjasto.fi">
95+
<div class="footer-link">
96+
<div class="footer-link-text">
97+
Melinda-OPAC
98+
</div>
99+
</div>
100+
</a>
101+
102+
<a href="/">
103+
<div class="footer-link">
104+
<div class="footer-link-text">
105+
Kuvailijan aputyökalut
106+
</div>
107+
</div>
108+
</a>
109+
110+
<a href="https://cyrillux.melinda.kansalliskirjasto.fi">
111+
<div class="footer-link">
112+
<div class="footer-link-text">
113+
Cyrillux
114+
</div>
115+
</div>
116+
</a>
117+
118+
<a href="https://merge.melinda.kansalliskirjasto.fi">
119+
<div class="footer-link">
120+
<div class="footer-link-text">
121+
Merge
122+
</div>
123+
</div>
124+
</a>
125+
126+
<a href="https://poistot.melinda.kansalliskirjasto.fi">
127+
<div class="footer-link">
128+
<div class="footer-link-text">
129+
Poistot
130+
</div>
131+
</div>
132+
</a>
133+
134+
</div>
135+
136+
</div>
137+
138+
<!-- Social media links -->
139+
<div id="melindaSocialMedia" class="melinda-social-media">
140+
141+
<div class="footer-heading">
142+
Linkit
143+
</div>
144+
145+
<div class="footer-link-list">
146+
147+
<a href="https://www.kiwi.fi/x/CID9Ag" target="_blank" rel=”noopener noreferrer”>
148+
<div class="footer-link">
149+
<div class="footer-link-text">
150+
Melindan asiakaswiki
151+
</div>
152+
</div>
153+
</a>
154+
155+
<a href="https://www.kiwi.fi/x/OYMrC" target="_blank" rel=”noopener noreferrer”>
156+
<div class="footer-link">
157+
<div class="footer-link-text">
158+
Melinda-sanasto
159+
</div>
160+
</div>
161+
</a>
162+
163+
<a href="https://www.kiwi.fi/x/TIL9Ag" target="_blank" rel=”noopener noreferrer”>
164+
<div class="footer-link">
165+
<div class="footer-link-text">
166+
Usein kysyttyä
167+
</div>
168+
</div>
169+
</a>
170+
171+
<a href="https://www.kiwi.fi/pages/viewrecentblogposts.action?key=melinda" target="_blank" rel=”noopener
172+
noreferrer”>
173+
<div class="footer-link">
174+
<div class="footer-link-text">
175+
Melindan blogi
176+
</div>
177+
</div>
178+
</a>
179+
180+
<a href="https://www.kiwi.fi/x/xID9Ag" target="_blank" rel=”noopener noreferrer”>
181+
<div class="footer-link">
182+
<div class="footer-link-text">
183+
Kansallinen metatietovaranto -hanke
184+
</div>
185+
</div>
186+
</a>
187+
188+
<a href="https://www.kiwi.fi/x/_TKOBQ" target="_blank" rel=”noopener noreferrer”>
189+
<div class="footer-link">
190+
<div class="footer-link-text">
191+
Tietosuojailmoitukset
192+
</div>
193+
</div>
194+
</a>
195+
196+
<a href="https://www.kiwi.fi/x/r4LzDw" target="_blank" rel=”noopener noreferrer”>
197+
<div class="footer-link">
198+
<div class="footer-link-text">
199+
Saavutettavuusselostukset
200+
</div>
201+
</div>
202+
</a>
203+
</div>
204+
</div>
205+
</div>
206+
207+
<!-- NatLib banner to identify the site as a National Library service -->
208+
<div class="natlib-banner">
209+
210+
<!-- NatLib logo -->
211+
<div id="natLibLogo" class="natlib-logo">
212+
<a href="https://www.kansalliskirjasto.fi" target="_blank" rel=”noopener noreferrer”>
213+
<img src="https://static.kansalliskirjasto.fi/melinda/images/logo-natlib-centered-white-cropped.png">
214+
</a>
215+
</div>
216+
217+
<!-- NatLib text -->
218+
<div id="natLibText" class="natlib-text">
219+
Palvelun tarjoaa Kansalliskirjasto
220+
</div>
221+
222+
<!-- Link to service provider -->
223+
<div id="natLibLink" class="natlib-link">
224+
<a href="https://www.kansalliskirjasto.fi" target="_blank" rel=”noopener noreferrer”>
225+
<div class="footer-link">
226+
<div class="footer-link-text">
227+
kansalliskirjasto.fi
228+
</div>
229+
</div>
230+
</a>
231+
</div>
232+
233+
</div>
234+
</div>
235+
</div>
236+
</footer>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<header>
2+
<div id="navbar" class="navbar">
3+
4+
<!-- Navbar contains two menu bars, primary and secondary -->
5+
<div class="navbar-menu-bars">
6+
7+
<!-- Primary menu bar contains Melinda logo and primary navigation links -->
8+
<div class="primary-menu-bar"
9+
style="display: flex; flex-direction: row; background-color: var(--color-primary-white); padding: 12px; height: 66px;">
10+
11+
<div class="logo-area">
12+
<a href="/">
13+
<img style="max-height: 50px;"
14+
src="https://static.kansalliskirjasto.fi/melinda/images/logo-melinda-text-horizontal-color-cropped.png">
15+
</a>
16+
</div>
17+
</div>
18+
</div>
19+
</div>
20+
<hl></hl>
21+
</header>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
1+
<!DOCTYPE html>
2+
<html lang="fi">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Poistot raportti</title>
8+
<style type="text/css">
9+
/* CLIENT-SPECIFIC STYLES */
10+
:root {
11+
12+
/* MELINDA COLORS ORIGINAL*/
13+
--color-melinda-green: #0DB14B;
14+
--color-melinda-darkblue: #00224F;
15+
--color-melinda-lightblue: #00B3F0;
16+
17+
/* MELINDA CUSTOM COLORS (MUTED FOR APPLICAITON) */
18+
--color-melinda-green-custom: #248f4d;
19+
--color-melinda-lightblue-custom: #28a4cf;
20+
21+
/* PRIMARY COLORS */
22+
/* - blue: primary text colour, main brand colour */
23+
/* - white: secondary text and link colour, primary background colour */
24+
--color-primary-blue: #002855;
25+
--color-primary-white: #FFFFFF;
26+
--color-primary-black: #000000;
27+
28+
29+
/* FUNCTIONAL COLORS */
30+
/* - blue: primary link and button colour, in forms used as a focus colour */
31+
/* - red: warning, error, rejected. Use in forms and alerts */
32+
/* - green: OK, pass, accepted. use in forms and alerts */
33+
/* - yellow: alert, attention, use in only bacground color */
34+
--color-functional-blue: #0D2FC4;
35+
--color-functional-red: #A0270A;
36+
--color-functional-green: #3A785E;
37+
--color-functional-yellow: #FAE196;
38+
}
39+
40+
#root {
41+
margin-bottom: 10px;
42+
}
43+
44+
.footer {
45+
display: flex;
46+
flex-grow: 1;
47+
flex-direction: column;
48+
font-family: var(--font-family-content);
49+
}
50+
51+
.footer-filler {
52+
flex-grow: 1;
53+
}
54+
55+
.footer-content {
56+
display: flex;
57+
flex-direction: column;
58+
font-size: 18px;
59+
letter-spacing: 0.05rem;
60+
line-height: var(--font-line-height-content-medium);
61+
}
62+
63+
/* ************************************************************ */
64+
65+
66+
.footer-heading {
67+
padding-bottom: 15px;
68+
}
69+
70+
.footer-heading-small {
71+
color: var(--color-primary-white);
72+
padding-top: 16px;
73+
}
74+
75+
.footer-text {
76+
color: var(--color-primary-white);
77+
}
78+
79+
.footer-paragraph {
80+
padding-top: 5px;
81+
padding-bottom: 15px;
82+
padding-right: 50px;
83+
max-width: 750px;
84+
}
85+
86+
.footer-link-list {
87+
display: flex;
88+
flex-direction: column;
89+
gap: 15px;
90+
}
91+
92+
.footer a .footer-email {
93+
color: var(--color-primary-white);
94+
}
95+
96+
.footer-link {
97+
display: flex;
98+
}
99+
100+
.footer a {
101+
text-decoration: none;
102+
}
103+
104+
.footer a .footer-link {
105+
display: flex;
106+
color: var(--color-primary-white);
107+
cursor: pointer;
108+
}
109+
110+
.footer-link-text {
111+
color: var(--color-primary-white);
112+
}
113+
114+
.footer-link-text a {
115+
display: flex;
116+
color: var(--color-primary-white);
117+
}
118+
119+
.footer-link:hover .footer-link-text,
120+
.footer-email:hover a {
121+
text-decoration: underline;
122+
text-underline-position: auto;
123+
}
124+
125+
.icon-open-in-new {
126+
padding-left: 5px;
127+
display: flex;
128+
flex-direction: column;
129+
align-items: end;
130+
justify-content: end;
131+
padding-bottom: 5px;
132+
}
133+
134+
.footer-link .icon-arrow {
135+
transform: translateX(0px);
136+
transition: transform 0.5s;
137+
}
138+
139+
.footer-link:hover .icon-arrow {
140+
transform: translateX(10px);
141+
transition: transform 0.75s;
142+
}
143+
144+
145+
/* ************************************************************ */
146+
/* Melinda banner specific styles in footer*/
147+
148+
.melinda-banner {
149+
display: flex;
150+
flex-direction: row;
151+
flex-grow: 1;
152+
color: var(--color-primary-white);
153+
background-color: var(--color-melinda-green-custom);
154+
padding: 48px;
155+
gap: 25px;
156+
}
157+
158+
.melinda-logo-and-contact-info {
159+
display: flex;
160+
flex-direction: column;
161+
flex-basis: 0;
162+
flex-grow: 1;
163+
}
164+
165+
.melinda-about,
166+
.melinda-links,
167+
.melinda-social-media {
168+
display: flex;
169+
flex-direction: column;
170+
}
171+
172+
.melinda-links,
173+
.melinda-social-media {
174+
flex-basis: 0;
175+
flex-grow: 1;
176+
}
177+
178+
.melinda-about {
179+
flex-grow: 3;
180+
flex-basis: 0;
181+
}
182+
183+
.melinda-contact-info {
184+
display: flex;
185+
flex-direction: column;
186+
}
187+
188+
.melinda-logo img {
189+
max-height: 150px;
190+
}
191+
192+
.melinda-banner a:hover .footer-link-text,
193+
.melinda-banner a:hover .footer-link-icon,
194+
.melinda-banner a:hover .footer-email {
195+
color: var(--color-primary-blue);
196+
text-decoration-color: var(--color-primary-blue);
197+
}
198+
199+
.melinda-banner a:active .footer-link,
200+
.melinda-banner .footer-email:active,
201+
.melinda-logo a:active {
202+
outline-color: var(--color-primary-white);
203+
outline-style: solid;
204+
outline-width: 0.2rem;
205+
}
206+
207+
.melinda-banner a:active .footer-link {
208+
outline-offset: 0.4rem
209+
}
210+
211+
.melinda-banner .footer-email:active {
212+
outline-offset: 0.1rem
213+
}
214+
215+
.melinda-logo a:active {
216+
outline-offset: 0.6rem
217+
}
218+
219+
220+
/* ************************************************************ */
221+
/* NatLib banner specific styles in footer*/
222+
223+
.natlib-banner {
224+
display: flex;
225+
flex-direction: row;
226+
flex-grow: 1;
227+
color: var(--color-primary-white);
228+
background-color: var(--color-primary-blue);
229+
gap: 40px;
230+
padding-top: 20px;
231+
padding-bottom: 20px;
232+
padding-left: 48px;
233+
padding-right: 48px;
234+
}
235+
236+
.natlib-logo,
237+
.natlib-text,
238+
.natlib-link {
239+
display: flex;
240+
}
241+
242+
.natlib-link {
243+
font-family: var(--font-family-content);
244+
justify-content: flex-end;
245+
align-items: center;
246+
}
247+
248+
.natlib-text,
249+
.natlib-link {
250+
flex-basis: 0;
251+
flex-grow: 1;
252+
}
253+
254+
.natlib-logo img {
255+
max-height: 78px;
256+
}
257+
258+
.natlib-text {
259+
align-items: center;
260+
justify-content: flex-start;
261+
}
262+
263+
.natlib-banner .footer-link:hover .footer-link-text,
264+
.natlib-banner .footer-link:hover .footer-link-icon {
265+
color: var(--color-red-80);
266+
text-decoration-color: var(--color-red-80);
267+
}
268+
269+
.natlib-logo a:active,
270+
.natlib-link a:active {
271+
outline-color: var(--color-primary-white);
272+
outline-style: solid;
273+
outline-width: 0.2rem;
274+
}
275+
276+
.natlib-logo a:active {
277+
outline-offset: 0.6rem
278+
}
279+
280+
.natlib-link a:active {
281+
outline-offset: 0.4rem
282+
}
283+
</style>
284+
</head>
285+
286+
<body>
287+
<div id="bodywrapper" class="viewport-full flex-column">
288+
{{>header}}
289+
<div id="root">
290+
<table border="0" cellspacing="0" cellpadding="0" role="presentation" width="100%">
291+
<caption>Poistoissa käsitellyt tietueet</caption>
292+
<thead>
293+
<tr>
294+
<th>Nimeke</th>
295+
<th>Melinda-ID</th>
296+
<th>Tila</th>
297+
</tr>
298+
</thead>
299+
<tbody>
300+
{{#each recordInfo}}
301+
<tr>
302+
<td>{{this.metadata.title}}</td>
303+
<td>{{this.metadata.id}}</td>
304+
<td>{{this.status}}</td>
305+
</tr>
306+
{{/each}}
307+
</tbody>
308+
</table>
309+
</div>
310+
{{>footer}}
311+
</div>
312+
</body>
313+
314+
</html>

0 commit comments

Comments
 (0)
Please sign in to comment.