Files
MSE-PI-E2EEDA-Plein-de-eeee…/report/meetings/260611-final/ui.typ
2026-06-14 16:24:40 +02:00

197 lines
6.9 KiB
Typst

#import "/metadata.typ": *
#import "/tail/bibliography.typ": *
#import "/tail/glossary.typ": *
#import "/main/architecture/description.typ": *
#import "/resources/slides.typ": *
// Chemin racine des images — adapter selon ta structure de projet
#let img-root = "../../resources/img/ui_images/images/"
// ── Palette ───────────────────────────────────────────────────────────────────
#let c-dark = rgb("#0F172A")
#let c-teal = rgb("#0EA5E9")
#let c-text = rgb("#1E293B")
#let c-muted = rgb("#64748B")
#let c-white = rgb("#FFFFFF")
#let c-border = rgb("#E2E8F0")
// ── Helpers ───────────────────────────────────────────────────────────────────
#let icon-circle(img-path, size: 38pt, bg: rgb("#0EA5E9")) = {
box(
width: size, height: size,
fill: bg, radius: (size / 2),
inset: 0pt, clip: true,
)[
#align(center + horizon)[
#image(img-path, width: (size * 0.62), height: (size * 0.62), fit: "contain")
]
]
}
#let badge(label, fill: rgb("#EF4444")) = {
box(fill: fill, radius: 3pt, inset: (x: 5pt, y: 2pt))[
#text(size: 6.5pt, weight: "bold", fill: rgb("#FFFFFF"))[#label]
]
}
#let devsec-col(phase-title, items) = {
block(width: 100%)[
#block(
width: 100%, height: 28pt,
fill: c-dark,
radius: (top-left: 5pt, top-right: 5pt, bottom-left: 0pt, bottom-right: 0pt),
inset: 0pt,
)[
#pad(x: 7pt)[
#align(horizon + center)[
#text(size: 8.5pt, weight: "bold", fill: rgb("#FFFFFF"))[#phase-title]
]
]
]
#block(
width: 100%,
fill: rgb("#F1F5F9"),
radius: (top-left: 0pt, top-right: 0pt, bottom-left: 5pt, bottom-right: 5pt),
inset: 8pt,
)[
#for item in items {
grid(columns: (30pt, 1fr), gutter: 6pt,
icon-circle(item.at("icon"), size: 28pt, bg: item.at("bg", default: c-teal)),
align(left + horizon)[
#text(size: 8pt, weight: "bold", fill: c-text)[#item.at("name")]
#linebreak()
#item.at("extra", default: [])
],
)
v(5pt)
}
]
]
}
== Cycle DevSecOps
#slide[
#grid(columns: (1fr, 1fr, 1fr, 1fr), gutter: 8pt,
devsec-col("① Code & PR Gate", (
(icon: img-root + "image10.png", bg: rgb("#3178C6"), name: "TypeScript",
extra: [#text(size: 6.5pt, fill: c-muted)[tsc / ESLint]]),
(icon: img-root + "image11.png", bg: rgb("#DD0031"), name: "Angular CI",
extra: [#text(size: 6.5pt, fill: c-muted)[Build check]]),
(icon: img-root + "image19.png", bg: rgb("#1F2328"), name: "GitHub Actions",
extra: [#text(size: 6.5pt, fill: c-muted)[Coverage]]),
)),pause,
devsec-col("② SAST · SCA", (
(icon: img-root + "image7.png", bg: rgb("#000000"), name: "SpotBugs",
extra: [#badge("BLOCKING")]),
(icon: img-root + "image13.png", bg: rgb("#1F2328"), name: "CodeQL",
extra: [#badge("BLOCKING")]),
(icon: img-root + "image14.png", bg: rgb("#F97316"), name: "Dep. Check",
extra: [#badge("NON-BLOCK", fill: rgb("#F97316"))]),
)),pause,
devsec-col("③ DAST · Tests", (
(icon: img-root + "image15.png", bg: rgb("#00549E"), name: "OWASP ZAP",
extra: [#badge("BLOCKING")]),
(icon: img-root + "image16.png", bg: rgb("#DD0031"), name: "Karma Tests",
extra: [#badge("BLOCKING")]),
(icon: img-root + "image17.png", bg: rgb("#64748B"), name: "Runtime check",
extra: [#text(size: 6.5pt, fill: c-muted)[HTTP headers]]),
)),pause,
devsec-col("④ Build · Deploy", (
(icon: img-root + "image18.png", bg: rgb("#0DB7ED"), name: "Docker",
extra: [#text(size: 6.5pt, fill: c-muted)[SHA-tagged]]),
(icon: img-root + "image19.png", bg: rgb("#1F2328"), name: "GHCR Push",
extra: [#text(size: 6.5pt, fill: c-muted)[main only]]),
(icon: img-root + "image17.png", bg: rgb("#10B981"), name: "SSH Deploy",
extra: [#text(size: 6.5pt, fill: c-muted)[cert-auth]]),
)),pause,
)
#v(7pt)
#rect(width: 100%, height: 26pt, fill: c-dark, radius: 4pt, inset: 0pt)[
#pad(x: 20pt)[
#align(horizon)[
#grid(columns: (1fr, 1fr, 1fr),
align(center + horizon)[#text(size: 8pt, fill: rgb("#FFFFFF"))[🔐 #h(2pt) Shift-left security]],
align(center + horizon)[#text(size: 8pt, fill: rgb("#FFFFFF"))[🔑 #h(2pt) Zero secret in code]],
align(center + horizon)[#text(size: 8pt, fill: rgb("#FFFFFF"))[🔄 #h(2pt) Automated Deployment]],
)
]
]
]
#v(6pt)
]
// ── SLIDE 3 — Dashboard ───────────────────────────────────────────────────────
== Dashboard
#slide[
#align(center + horizon)[
#figure(
image(img-root + "image20.png", width: 100%, fit: "contain"),
caption: [Dashboard]
)
]
]
// ── SLIDE 4 — Details Page ────────────────────────────────────────────────────
== Details Page
#slide[
#align(center + horizon)[
#figure(
image(img-root + "image21.png", width: 100%, fit: "contain"),
caption: [Details page]
)
]
]
// ── SLIDE 5 — Notification ────────────────────────────────────────────────────
== Notification
#slide[
#grid(columns: (1fr, 1fr), gutter: 16pt,
// Screenshot Telegram
align(center + horizon)[
#figure(
image(img-root + "image22.png", height: 300pt, fit: "contain"),
caption: [Telegram notification]
)
],
// Carte descriptive
rect(width: 100%, radius: 6pt, stroke: 0.5pt + c-border, fill: rgb("#FFFFFF"), inset: 12pt)[
#text(size: 10pt, weight: "bold", fill: c-text)[CO₂ Alerts System]
#v(5pt)
#line(length: 100%, stroke: 0.5pt + c-border)
#v(6pt)
#let alert-row(col, level, desc) = {
grid(columns: (10pt, 52pt, 1fr), gutter: 5pt,
box(width: 8pt, height: 8pt, fill: col, radius: 4pt),
text(size: 8.5pt, weight: "bold")[#level],
text(size: 8pt, fill: c-muted)[#desc],
)
v(4pt)
}
#alert-row(rgb("#f44336"), "Critical", "> 2000 ppm")
#alert-row(rgb("#F97316"), "Very Poor", "1500-2000 ppm")
#alert-row(rgb("#ff9800"), "Poor", "1200-1500 ppm")
#alert-row(rgb("#ffc107"), "Moderate", "1000-1200 ppm")
#alert-row(rgb("#8bc34a"), "Good", "800-1000 ppm")
#alert-row(rgb("#4caf50"), "Excellent", "< 800 ppm")
#v(6pt)
#line(length: 100%, stroke: 0.5pt + c-border)
#v(6pt)
#v(6pt)
],
)
]