[FE] Improve /certificate UI
This commit is contained in:
parent
3d348cf12e
commit
a527f4e33e
540
docx/main.ts
540
docx/main.ts
@ -1,540 +0,0 @@
|
|||||||
import * as fs from "fs";
|
|
||||||
import {
|
|
||||||
Document, Packer, Paragraph, PageOrientation, ImageRun,
|
|
||||||
HorizontalPositionRelativeFrom, VerticalPositionRelativeFrom,
|
|
||||||
convertMillimetersToTwip,
|
|
||||||
FrameAnchorType,
|
|
||||||
HorizontalPositionAlign,
|
|
||||||
VerticalPositionAlign,
|
|
||||||
TextRun,
|
|
||||||
AlignmentType,
|
|
||||||
ShadingType,
|
|
||||||
} from "docx";
|
|
||||||
import { join } from "path";
|
|
||||||
import * as QR from "qrcode";
|
|
||||||
|
|
||||||
|
|
||||||
function cm(centimeters: number) {
|
|
||||||
return convertMillimetersToTwip((100 * centimeters) / 150);
|
|
||||||
}
|
|
||||||
|
|
||||||
function cmToEmu(cm: number) {
|
|
||||||
return Math.round(cm * 360000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function cmText(cm: number) {
|
|
||||||
return Math.round(cm * 567);
|
|
||||||
}
|
|
||||||
|
|
||||||
type ImgConfig = {
|
|
||||||
name: string,
|
|
||||||
height: number,
|
|
||||||
width: number,
|
|
||||||
horizontalOffset: number,
|
|
||||||
verticalOffset: number,
|
|
||||||
}
|
|
||||||
|
|
||||||
function getImage(data: ImgConfig): ImageRun {
|
|
||||||
return new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", data.name)),
|
|
||||||
transformation: {
|
|
||||||
height: cm(data.height),
|
|
||||||
width: cm(data.width),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 0,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(data.horizontalOffset),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(data.verticalOffset),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const imgFondoDoc = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "fondo_certificado.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(20.97),
|
|
||||||
width: cm(29.8),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 0,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: 0,
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: 0,
|
|
||||||
},
|
|
||||||
behindDocument: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const imgMatpel = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "matpel-logo.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(2.81),
|
|
||||||
width: cm(2.81),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(0.7),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(0.7),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgCIP = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "colegio_ingenieros_logo.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(2.15),
|
|
||||||
width: cm(2.15),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(0.91),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(3.64),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgCEE = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "cee_logo.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(2.22),
|
|
||||||
width: cm(3.11),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(0.29),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(18),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgMTC = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "mtc_logo.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(1.3),
|
|
||||||
width: cm(4.08),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(5.13),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(19.33),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgEEG = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "eeg_f_logo.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(4.39),
|
|
||||||
width: cm(6.4),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(23.25),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(0),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgOSHA = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "osha_logo.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(1.55),
|
|
||||||
width: cm(4.46),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(24.34),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(4.95),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgAguila = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "aguila_logo.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(2.62),
|
|
||||||
width: cm(2.68),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(25.45),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(6.57),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgMichigan = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "michigan_logo.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(2.47),
|
|
||||||
width: cm(2.6),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(25.59),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(9.54),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgCEEM = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "ceem_logo.jpg")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(1),
|
|
||||||
width: cm(3.99),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(24.97),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(12.5),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const imgEATE = new ImageRun({
|
|
||||||
data: fs.readFileSync(join(__dirname, "img", "eate_logo.jpg")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(2.21),
|
|
||||||
width: cm(3.28),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(25.54),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(14.09),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const certificateName = new Paragraph({
|
|
||||||
frame: {
|
|
||||||
position: {
|
|
||||||
x: cmText(3.13),
|
|
||||||
y: cmText(1.9),
|
|
||||||
},
|
|
||||||
width: cmText(14.28),
|
|
||||||
height: cmText(3.19),
|
|
||||||
anchor: {
|
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
|
||||||
vertical: FrameAnchorType.MARGIN,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
new TextRun({
|
|
||||||
text: "CAPACITACIÓN EN MANEJO; MANIPULACIÓN Y TRANSPORTE DE MATERIALES Y RESIDUOS PELIGROSOS - MATPEL I - Advertencia".toUpperCase(),
|
|
||||||
bold: true,
|
|
||||||
font: "Arial",
|
|
||||||
size: 32,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
alignment: AlignmentType.CENTER,
|
|
||||||
});
|
|
||||||
|
|
||||||
const certificatePersonName = new Paragraph({
|
|
||||||
frame: {
|
|
||||||
position: {
|
|
||||||
x: cmText(0),
|
|
||||||
y: cmText(6.5),
|
|
||||||
},
|
|
||||||
width: cmText(23),
|
|
||||||
height: cmText(1.5),
|
|
||||||
anchor: {
|
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
|
||||||
vertical: FrameAnchorType.MARGIN,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
new TextRun({
|
|
||||||
text: "fernando enrique araoz morales".toUpperCase(),
|
|
||||||
bold: true,
|
|
||||||
font: "Arial",
|
|
||||||
allCaps: true,
|
|
||||||
size: 48,
|
|
||||||
underline: {},
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
alignment: AlignmentType.CENTER,
|
|
||||||
});
|
|
||||||
|
|
||||||
// "Se expide el presente certificado a:"
|
|
||||||
const certificateExpedite = new Paragraph({
|
|
||||||
frame: {
|
|
||||||
position: {
|
|
||||||
x: cmText(2.85),
|
|
||||||
y: cmText(5.15),
|
|
||||||
},
|
|
||||||
width: cmText(14.28),
|
|
||||||
height: cmText(1),
|
|
||||||
anchor: {
|
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
|
||||||
vertical: FrameAnchorType.MARGIN,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
new TextRun({
|
|
||||||
text: "Se expide el presente certificado a:",
|
|
||||||
font: "Arial",
|
|
||||||
size: 22,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
alignment: AlignmentType.CENTER,
|
|
||||||
});
|
|
||||||
|
|
||||||
// N° XXXX-202X-EEG
|
|
||||||
const certificateCode = new Paragraph({
|
|
||||||
frame: {
|
|
||||||
position: {
|
|
||||||
x: cmText(17.1),
|
|
||||||
y: cmText(5.35),
|
|
||||||
},
|
|
||||||
width: cmText(3.68),
|
|
||||||
height: cmText(0.7),
|
|
||||||
anchor: {
|
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
|
||||||
vertical: FrameAnchorType.MARGIN,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
new TextRun({
|
|
||||||
text: "N° 0524-2023-EEG",
|
|
||||||
font: "Arial",
|
|
||||||
size: 20,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
alignment: AlignmentType.CENTER,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Identificado con dni ...
|
|
||||||
const certificateBody = new Paragraph({
|
|
||||||
frame: {
|
|
||||||
position: {
|
|
||||||
x: cmText(1.51),
|
|
||||||
y: cmText(8.35),
|
|
||||||
},
|
|
||||||
width: cmText(20.08),
|
|
||||||
height: cmText(3.7),
|
|
||||||
anchor: {
|
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
|
||||||
vertical: FrameAnchorType.MARGIN,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
new TextRun({
|
|
||||||
text: "Identificado con DNI N° ",
|
|
||||||
font: "Arial",
|
|
||||||
size: 24,
|
|
||||||
}),
|
|
||||||
new TextRun({
|
|
||||||
text: "74059695",
|
|
||||||
font: "Arial",
|
|
||||||
size: 24,
|
|
||||||
bold: true,
|
|
||||||
}),
|
|
||||||
new TextRun({
|
|
||||||
text: ", al haber aprobado el curso de capacitación sobre ",
|
|
||||||
font: "Arial",
|
|
||||||
size: 24,
|
|
||||||
}),
|
|
||||||
new TextRun({
|
|
||||||
text: "MANEJO DE MATERIALES Y RESIDUOS PELIGROSOS - MATPEL I - Advertencia",
|
|
||||||
font: "Arial",
|
|
||||||
size: 24,
|
|
||||||
bold: true,
|
|
||||||
}),
|
|
||||||
new TextRun({
|
|
||||||
text: ", según lo estipulado en la Ley N°28256 (ley que regula el Transporte de Materiales y Residuos Peligrosos) y Decreto Supremo N° 021-2008-MTC (Reglamento Nacional de Transporte Terrestre de Materiales y Residuos Peligrosos) con una duración de 12 horas lectivas.\n",
|
|
||||||
font: "Arial",
|
|
||||||
size: 24,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
alignment: AlignmentType.JUSTIFIED,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Se expide certificado...
|
|
||||||
const certificateFinishLabel = new Paragraph({
|
|
||||||
frame: {
|
|
||||||
position: {
|
|
||||||
x: cmText(1.52),
|
|
||||||
y: cmText(11.25),
|
|
||||||
},
|
|
||||||
width: cmText(20.1),
|
|
||||||
height: cmText(0.8),
|
|
||||||
anchor: {
|
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
|
||||||
vertical: FrameAnchorType.MARGIN,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
new TextRun({
|
|
||||||
text: "Se expide certificado para los fines que se estime conveniente.",
|
|
||||||
font: "Arial",
|
|
||||||
size: 24,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
alignment: AlignmentType.CENTER,
|
|
||||||
style: "highlighting: none;",
|
|
||||||
});
|
|
||||||
|
|
||||||
// Fecha de Emision: ...
|
|
||||||
const certificateDate = new Paragraph({
|
|
||||||
frame: {
|
|
||||||
position: {
|
|
||||||
x: cmText(16),
|
|
||||||
y: cmText(16.5),
|
|
||||||
},
|
|
||||||
width: cmText(9),
|
|
||||||
height: cmText(1.4),
|
|
||||||
anchor: {
|
|
||||||
horizontal: FrameAnchorType.MARGIN,
|
|
||||||
vertical: FrameAnchorType.TEXT,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
new TextRun({
|
|
||||||
text: "Fecha de Emisión:\t\t{fecha_emision}",
|
|
||||||
font: "Arial",
|
|
||||||
size: 20,
|
|
||||||
break: 1,
|
|
||||||
}),
|
|
||||||
new TextRun({
|
|
||||||
text: "Fecha de Expiración:\t\t{fecha_expiracion}",
|
|
||||||
font: "Arial",
|
|
||||||
size: 20,
|
|
||||||
break: 1,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
alignment: AlignmentType.LEFT,
|
|
||||||
style: "highlighting: none;",
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function create() {
|
|
||||||
const qr = await QR.toDataURL(/* join(__dirname, "img", "qr.png"), */ `https://www.eegsac.com/alumnoscertificados.php?DNI=${"74059695"}`, {margin: 1});
|
|
||||||
|
|
||||||
const imgQR = new ImageRun({
|
|
||||||
data: qr, // fs.readFileSync(join(__dirname, "img", "qr.png")),
|
|
||||||
transformation: {
|
|
||||||
height: cm(2.47),
|
|
||||||
width: cm(2.47),
|
|
||||||
},
|
|
||||||
floating: {
|
|
||||||
zIndex: 1,
|
|
||||||
horizontalPosition: {
|
|
||||||
relative: HorizontalPositionRelativeFrom.LEFT_MARGIN,
|
|
||||||
offset: cmToEmu(26.3),
|
|
||||||
},
|
|
||||||
verticalPosition: {
|
|
||||||
relative: VerticalPositionRelativeFrom.TOP_MARGIN,
|
|
||||||
offset: cmToEmu(16.48),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const doc = new Document({
|
|
||||||
sections: [
|
|
||||||
{
|
|
||||||
properties: {
|
|
||||||
page: {
|
|
||||||
size: {
|
|
||||||
orientation: PageOrientation.LANDSCAPE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
children: [
|
|
||||||
certificateName,
|
|
||||||
certificatePersonName,
|
|
||||||
certificateExpedite,
|
|
||||||
certificateCode,
|
|
||||||
certificateBody,
|
|
||||||
certificateFinishLabel,
|
|
||||||
certificateDate,
|
|
||||||
new Paragraph({
|
|
||||||
children: [
|
|
||||||
imgFondoDoc,
|
|
||||||
imgMatpel,
|
|
||||||
imgCIP,
|
|
||||||
imgCEE,
|
|
||||||
imgMTC,
|
|
||||||
imgEEG,
|
|
||||||
imgOSHA,
|
|
||||||
imgAguila,
|
|
||||||
imgMichigan,
|
|
||||||
imgCEEM,
|
|
||||||
imgEATE,
|
|
||||||
imgQR,
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Used to export the file into a .docx file
|
|
||||||
Packer.toBuffer(doc).then((buffer) => {
|
|
||||||
fs.writeFileSync("My Document.docx", buffer);
|
|
||||||
// fs.rmSync(join(__dirname, "temp", "qr.png"));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
create();
|
|
@ -12,6 +12,7 @@ const { glob } = require("glob");
|
|||||||
entryPoints: files,
|
entryPoints: files,
|
||||||
bundle: false,
|
bundle: false,
|
||||||
minify: true,
|
minify: true,
|
||||||
|
sourcemap: false,
|
||||||
logLevel: "info",
|
logLevel: "info",
|
||||||
plugins: [solidPlugin({
|
plugins: [solidPlugin({
|
||||||
solid: {
|
solid: {
|
||||||
@ -32,6 +33,7 @@ build({
|
|||||||
],
|
],
|
||||||
bundle: true,
|
bundle: true,
|
||||||
minify: true,
|
minify: true,
|
||||||
|
sourcemap: false,
|
||||||
logLevel: "info",
|
logLevel: "info",
|
||||||
plugins: [
|
plugins: [
|
||||||
solidPlugin({
|
solidPlugin({
|
||||||
|
@ -31,7 +31,7 @@ type ImgConfig = {
|
|||||||
export function getImage(data: ImgConfig): ImageRun {
|
export function getImage(data: ImgConfig): ImageRun {
|
||||||
return new ImageRun({
|
return new ImageRun({
|
||||||
// Magic path, based on dist folder
|
// Magic path, based on dist folder
|
||||||
data: fs.readFileSync(join(__dirname, "..", "..", "..", "img", data.name)),
|
data: fs.readFileSync(join(__dirname, "..", "..", "img", data.name)),
|
||||||
transformation: {
|
transformation: {
|
||||||
height: cm(data.height),
|
height: cm(data.height),
|
||||||
width: cm(data.width),
|
width: cm(data.width),
|
||||||
@ -62,7 +62,6 @@ export async function getQR(data : {
|
|||||||
const qr = await QR.toDataURL(`https://www.eegsac.com/alumnoscertificados.php?DNI=${data.dni}`, {margin: 1});
|
const qr = await QR.toDataURL(`https://www.eegsac.com/alumnoscertificados.php?DNI=${data.dni}`, {margin: 1});
|
||||||
|
|
||||||
return new ImageRun({
|
return new ImageRun({
|
||||||
// Magic path, based on dist folder
|
|
||||||
data: qr,
|
data: qr,
|
||||||
transformation: {
|
transformation: {
|
||||||
height: cm(data.height),
|
height: cm(data.height),
|
||||||
|
@ -10,6 +10,7 @@ import { getMatpel } from "./generator/matpel";
|
|||||||
import { getMecanicaBasica } from "./generator/mecanicaBasica";
|
import { getMecanicaBasica } from "./generator/mecanicaBasica";
|
||||||
import { getManejoDefensivo } from "./generator/manejoDefensivo";
|
import { getManejoDefensivo } from "./generator/manejoDefensivo";
|
||||||
|
|
||||||
|
const generatable = [1, 2, 10, 11, 12];
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CertificateService {
|
export class CertificateService {
|
||||||
@ -39,6 +40,7 @@ export class CertificateService {
|
|||||||
curso_nombre: raw.curso_nombre,
|
curso_nombre: raw.curso_nombre,
|
||||||
personaId: raw.persona?.id,
|
personaId: raw.persona?.id,
|
||||||
cursoGIEId: raw.cursoGIE?.id,
|
cursoGIEId: raw.cursoGIE?.id,
|
||||||
|
generatable: generatable.indexOf(raw.curso) !== -1,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +59,6 @@ export class CertificateService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
if (registerR.length === 0) {
|
if (registerR.length === 0) {
|
||||||
throw new BadRequestException("ID invalido");
|
throw new BadRequestException("ID invalido");
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ async function bootstrap() {
|
|||||||
const app = await NestFactory.create(AppModule);
|
const app = await NestFactory.create(AppModule);
|
||||||
|
|
||||||
// Serve static files
|
// Serve static files
|
||||||
app.use("/static", express.static(path.join(__dirname, "..", "..", "static")));
|
app.use("/static", express.static(path.join(__dirname, "..", "static")));
|
||||||
|
|
||||||
await app.listen(3000);
|
await app.listen(3000);
|
||||||
}
|
}
|
||||||
|
@ -13,4 +13,7 @@ export interface RegisterReturn {
|
|||||||
// New fields
|
// New fields
|
||||||
personaId?: number,
|
personaId?: number,
|
||||||
cursoGIEId?: number,
|
cursoGIEId?: number,
|
||||||
|
|
||||||
|
// Can be automatically generated
|
||||||
|
generatable: boolean,
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,17 @@ export function Certs() {
|
|||||||
Registrar certificado
|
Registrar certificado
|
||||||
</h1>
|
</h1>
|
||||||
<Search setPerson={setPerson}/>
|
<Search setPerson={setPerson}/>
|
||||||
<Registers person={person()} lastUpdate={lastUpdate()} />
|
<div
|
||||||
<NewRegister
|
class="grid"
|
||||||
person={person()}
|
style={{"grid-template-columns": "50% 50%"}}
|
||||||
onSuccess={() => setLastUpdate((x) => x + 1)}
|
>
|
||||||
/>
|
<Registers person={person()} lastUpdate={lastUpdate()} />
|
||||||
|
<NewRegister
|
||||||
|
person={person()}
|
||||||
|
onSuccess={() => setLastUpdate((x) => x + 1)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -18,10 +18,6 @@ export function NewRegister(props: {person: Person | null, onSuccess: () => void
|
|||||||
|
|
||||||
const [selectedSubject, setSelectedSubject] = createSignal<number | null>(null);
|
const [selectedSubject, setSelectedSubject] = createSignal<number | null>(null);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const datePicker = (
|
const datePicker = (
|
||||||
<input
|
<input
|
||||||
id="create-date"
|
id="create-date"
|
||||||
@ -94,16 +90,9 @@ export function NewRegister(props: {person: Person | null, onSuccess: () => void
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<h2 class="my-4 font-bold text-xl">3. Crear nuevos registros</h2>
|
<h2 class="mb-4 font-bold text-xl">3. Crear nuevos registros</h2>
|
||||||
|
|
||||||
<Show when={props.person?.id !== -1}>
|
<Show when={props.person?.id !== -1}>
|
||||||
<p
|
|
||||||
class="my-2 p-1 rounded w-fit mx-4 bg-c-error text-c-on-error"
|
|
||||||
style={{opacity: error() === "" ? "0" : "1", "user-select": "none"}}
|
|
||||||
>
|
|
||||||
{error()}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<form
|
<form
|
||||||
class="px-4 grid"
|
class="px-4 grid"
|
||||||
style={{"grid-template-columns": "30rem 12rem 10rem auto", "grid-column-gap": "1rem"}}
|
style={{"grid-template-columns": "30rem 12rem 10rem auto", "grid-column-gap": "1rem"}}
|
||||||
@ -123,9 +112,7 @@ export function NewRegister(props: {person: Person | null, onSuccess: () => void
|
|||||||
<br/>
|
<br/>
|
||||||
{datePicker}
|
{datePicker}
|
||||||
<br/>
|
<br/>
|
||||||
</div>
|
<br />
|
||||||
<div>
|
|
||||||
<br/>
|
|
||||||
<input
|
<input
|
||||||
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-md cursor-pointer
|
class="bg-c-primary text-c-on-primary px-4 py-2 rounded-md cursor-pointer
|
||||||
disabled:opacity-50 disabled:cursor-not-allowed"
|
disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
@ -135,6 +122,13 @@ export function NewRegister(props: {person: Person | null, onSuccess: () => void
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<p
|
||||||
|
class="my-2 p-1 rounded w-fit mx-4 bg-c-error text-c-on-error"
|
||||||
|
style={{opacity: error() === "" ? "0" : "1", "user-select": "none"}}
|
||||||
|
>
|
||||||
|
{error()}
|
||||||
|
</p>
|
||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -64,7 +64,7 @@ export function SearchableSelect(props: {
|
|||||||
<br/>
|
<br/>
|
||||||
<div
|
<div
|
||||||
class="border-c-outline border-2 rounded overflow-y-scroll"
|
class="border-c-outline border-2 rounded overflow-y-scroll"
|
||||||
style={{"max-height": "12rem", "min-height": "12rem"}}
|
style={{"max-height": "18rem", "min-height": "12rem"}}
|
||||||
>
|
>
|
||||||
<For each={props.subjects}>
|
<For each={props.subjects}>
|
||||||
{(s) => (
|
{(s) => (
|
||||||
|
@ -36,7 +36,7 @@ export function Registers(props: { person: Person | null, lastUpdate: number })
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<h2 class="my-4 font-bold text-xl">2. Revisar registros actuales</h2>
|
<h2 class="mb-4 font-bold text-xl">2. Revisar registros actuales</h2>
|
||||||
|
|
||||||
<div class="px-4">
|
<div class="px-4">
|
||||||
<Show when={props.person !== null}>
|
<Show when={props.person !== null}>
|
||||||
@ -60,7 +60,6 @@ export function Registers(props: { person: Person | null, lastUpdate: number })
|
|||||||
<table class="table-auto border border-c-outline my-4">
|
<table class="table-auto border border-c-outline my-4">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="p-2">APELLIDOS Y NOMBRES</th>
|
|
||||||
<th class="p-2">CURSO</th>
|
<th class="p-2">CURSO</th>
|
||||||
<th class="p-2">FECHA</th>
|
<th class="p-2">FECHA</th>
|
||||||
<th class="p-2">CÓDIGO</th>
|
<th class="p-2">CÓDIGO</th>
|
||||||
@ -152,20 +151,21 @@ function Register(props: {cert: RegisterReturn, onUpdate: () => void}) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<tr class="odd:bg-c-surface-variant">
|
<tr class="odd:bg-c-surface-variant">
|
||||||
<td class="py-2 px-4">{props.cert.nombre}</td>
|
|
||||||
<td class="py-2 px-4">{props.cert.curso_nombre}</td>
|
<td class="py-2 px-4">{props.cert.curso_nombre}</td>
|
||||||
<td class="py-2 px-4 font-mono">{props.cert.fecha_inscripcion.toString()}</td>
|
<td class="py-2 px-4 font-mono">{props.cert.fecha_inscripcion.toString()}</td>
|
||||||
<td class="py-2 px-4">{props.cert.codigo}</td>
|
<td class="py-2 px-4">{props.cert.codigo}</td>
|
||||||
<td class="py-2 pl-8 pr-4">
|
<td class="py-2 px-4">
|
||||||
<button
|
<Show when={props.cert.generatable}>
|
||||||
class="rounded-full py-1 px-2 shadow"
|
<button
|
||||||
style={{"background-color": "#0055d5", "color": "#ffffff"}}
|
class="rounded-full py-1 px-2 shadow"
|
||||||
onclick={getCertificate}
|
style={{"background-color": "#0055d5", "color": "#ffffff"}}
|
||||||
>
|
onclick={getCertificate}
|
||||||
|
>
|
||||||
DOCX
|
DOCX
|
||||||
</button>
|
</button>
|
||||||
|
</Show>
|
||||||
</td>
|
</td>
|
||||||
<td class="py-2 pl-8 pr-4">
|
<td class="py-2 px-4">
|
||||||
<button
|
<button
|
||||||
class="rounded-full py-1 px-2 shadow
|
class="rounded-full py-1 px-2 shadow
|
||||||
bg-c-primary
|
bg-c-primary
|
||||||
@ -176,7 +176,7 @@ function Register(props: {cert: RegisterReturn, onUpdate: () => void}) {
|
|||||||
Editar
|
Editar
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
<td class="py-2 pl-4 pr-8">
|
<td class="py-2 px-4">
|
||||||
<button
|
<button
|
||||||
class={`rounded-full py-1 px-2 shadow
|
class={`rounded-full py-1 px-2 shadow
|
||||||
${deleteConfirmation() ? "bg-c-error-container text-c-on-error-container" : "bg-c-error text-c-on-error"}
|
${deleteConfirmation() ? "bg-c-error-container text-c-on-error-container" : "bg-c-error text-c-on-error"}
|
||||||
|
@ -67,7 +67,7 @@ export function Search(props: {setPerson: (p: Person | null) => void}) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="p-4 grid" style={{"grid-template-columns": "40rem auto"}}>
|
<div class="p-4 grid" style={{"grid-template-columns": "20rem auto"}}>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="my-2 font-bold text-xl">1. Buscar persona</h2>
|
<h2 class="my-2 font-bold text-xl">1. Buscar persona</h2>
|
||||||
<form onSubmit={searchDNI} class="px-4">
|
<form onSubmit={searchDNI} class="px-4">
|
||||||
@ -77,7 +77,7 @@ export function Search(props: {setPerson: (p: Person | null) => void}) {
|
|||||||
id="search-dni"
|
id="search-dni"
|
||||||
class="bg-c-background text-c-on-background border-c-outline border-2 rounded px-2 py-1
|
class="bg-c-background text-c-on-background border-c-outline border-2 rounded px-2 py-1
|
||||||
invalid:border-c-error invalid:text-c-error
|
invalid:border-c-error invalid:text-c-error
|
||||||
focus:border-c-primary outline-none
|
focus:border-c-primary outline-none font-mono
|
||||||
disabled:opacity-50 disabled:cursor-not-allowed"
|
disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
type="text"
|
type="text"
|
||||||
minLength={8}
|
minLength={8}
|
||||||
@ -123,7 +123,7 @@ export function Search(props: {setPerson: (p: Person | null) => void}) {
|
|||||||
</Show>
|
</Show>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<img src={qrBase64() ?? ""} height="225" width="225" />
|
<img src={qrBase64() ?? ""} height="150" width="150" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
{
|
{
|
||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"declaration": false,
|
||||||
|
"sourceMap": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,5 @@
|
|||||||
"include": [
|
"include": [
|
||||||
"src/**/*.ts",
|
"src/**/*.ts",
|
||||||
"src/**/*.tsx",
|
"src/**/*.tsx",
|
||||||
"docx/**/*.ts",
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user