Huge updates
7
Makefile
@@ -4,7 +4,7 @@ VENV := .venv
|
|||||||
PY := $(VENV)/bin/python
|
PY := $(VENV)/bin/python
|
||||||
PIP := $(VENV)/bin/pip
|
PIP := $(VENV)/bin/pip
|
||||||
|
|
||||||
all: clean-output clean-venv build search
|
all: fix-permissions clean-output clean-venv build search
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@echo "Building project..."
|
@echo "Building project..."
|
||||||
@@ -31,6 +31,11 @@ norm:
|
|||||||
@echo "sorting out the backups..."
|
@echo "sorting out the backups..."
|
||||||
find . -path ./backups -prune -o -type f -name '*~' -exec mv {} backups/ \;
|
find . -path ./backups -prune -o -type f -name '*~' -exec mv {} backups/ \;
|
||||||
|
|
||||||
|
fix-permissions:
|
||||||
|
echo "shakkal123" | sudo -S chown -R zaine:zaine .
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Show help message
|
# Show help message
|
||||||
help:
|
help:
|
||||||
@echo "Available targets:"
|
@echo "Available targets:"
|
||||||
|
|||||||
BIN
assets/fonts/NotoSans-Regular.ttf
Normal file
BIN
assets/fonts/Roboto-Regular.ttf
Normal file
BIN
assets/fonts/times.ttf
Normal file
BIN
assets/images/240226-pr.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
assets/images/26-02-26-di-errors-2.png
Normal file
|
After Width: | Height: | Size: 265 KiB |
BIN
assets/images/26-02-26-di-errors.png
Normal file
|
After Width: | Height: | Size: 324 KiB |
BIN
assets/images/27-02-26-xserver.png
Normal file
|
After Width: | Height: | Size: 118 KiB |
BIN
assets/images/career/05-03-26-api-protocols.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
assets/images/lima-third-meeting.jpg
Normal file
|
After Width: | Height: | Size: 2.5 MiB |
BIN
assets/images/reviews/competency-powerbi-report.png
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
assets/images/reviews/journeys-api-side-by-side-upgrade.png
Normal file
|
After Width: | Height: | Size: 179 KiB |
BIN
assets/images/reviews/timesheets/timesheet-01-03-26.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
assets/images/reviews/timesheets/timesheet-15-02-26.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
assets/images/reviews/timesheets/timesheet-22-02-26.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
@@ -3,6 +3,35 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
console.error('[gallery-init] BiggerPicture not found. Check script path.');
|
console.error('[gallery-init] BiggerPicture not found. Check script path.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const VIDEO_EXTENSIONS = ['mp4', 'webm', 'mov', 'm4v', 'ogv'];
|
||||||
|
|
||||||
|
const isVideo = (href) => {
|
||||||
|
if (!href) return false;
|
||||||
|
href = href.toLowerCase();
|
||||||
|
return VIDEO_EXTENSIONS.some(ext => href.endsWith('.' + ext));
|
||||||
|
};
|
||||||
|
|
||||||
|
// 1b) Convert MP4 links into inline <video> players
|
||||||
|
// Convert video links into inline <video> players BUT keep the <a>
|
||||||
|
const videoLinks = document.querySelectorAll('a[href]');
|
||||||
|
videoLinks.forEach(a => {
|
||||||
|
const href = a.getAttribute("href");
|
||||||
|
if (!isVideo(href)) return;
|
||||||
|
|
||||||
|
const video = document.createElement("video");
|
||||||
|
video.controls = true;
|
||||||
|
video.preload = "metadata";
|
||||||
|
video.style.maxWidth = "100%";
|
||||||
|
video.style.borderRadius = "6px";
|
||||||
|
|
||||||
|
const source = document.createElement("source");
|
||||||
|
source.src = href;
|
||||||
|
source.type = "video/" + href.split('.').pop(); // guesses correct mime
|
||||||
|
video.appendChild(source);
|
||||||
|
|
||||||
|
// Replace the link with the inline video
|
||||||
|
a.parentNode.replaceChild(video, a);
|
||||||
|
});
|
||||||
|
|
||||||
// 1) Wrap Org-exported images so they’re clickable
|
// 1) Wrap Org-exported images so they’re clickable
|
||||||
const imgs = document.querySelectorAll('.figure img, img.org-svg');
|
const imgs = document.querySelectorAll('.figure img, img.org-svg');
|
||||||
@@ -39,7 +68,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
// 3) Build galleries per content container
|
// 3) Build galleries per content container
|
||||||
const containers = document.querySelectorAll('main, article, .content, body');
|
const containers = document.querySelectorAll('main, article, .content, body');
|
||||||
containers.forEach((container) => {
|
containers.forEach((container) => {
|
||||||
const links = Array.from(container.querySelectorAll('.figure a, a:has(img.org-svg)'));
|
//const links = Array.from(container.querySelectorAll('.figure a, a:has(img.org-svg)'));
|
||||||
|
const links = Array.from(container.querySelectorAll(
|
||||||
|
'.figure a, a:has(img.org-svg), a[href$=".mp4"], a[href$=".webm"], a[href$=".mov"], a[href$=".m4v"], a[href$=".ogv"]'
|
||||||
|
));
|
||||||
if (!links.length) return;
|
if (!links.length) return;
|
||||||
|
|
||||||
// Start the lightbox on click
|
// Start the lightbox on click
|
||||||
@@ -69,7 +101,37 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Called once after open and on every slide change
|
// Called once after open and on every slide change
|
||||||
onOpen(containerEl) { setupRotation(containerEl); enhanceSVG(containerEl); },
|
//onOpen(containerEl) { setupRotation(containerEl); enhanceSVG(containerEl); }
|
||||||
|
onOpen(containerEl) {
|
||||||
|
const linkEl = bp.currItem;
|
||||||
|
const href = linkEl?.href || "";
|
||||||
|
|
||||||
|
if (href.endsWith(".mp4")) {
|
||||||
|
// Turn off image rotation (not applicable for video)
|
||||||
|
teardownRotation();
|
||||||
|
|
||||||
|
const htmlLayer = containerEl.querySelector(".bp-html");
|
||||||
|
const imgLayer = containerEl.querySelector(".bp-img");
|
||||||
|
|
||||||
|
if (!htmlLayer) return;
|
||||||
|
|
||||||
|
// Hide the default image layer
|
||||||
|
if (imgLayer) imgLayer.style.display = "none";
|
||||||
|
|
||||||
|
// Insert video player
|
||||||
|
htmlLayer.innerHTML = `
|
||||||
|
<video controls autoplay style="max-width:95vw; max-height:95vh">
|
||||||
|
<source src="${href}" type="video/mp4">
|
||||||
|
</video>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return; // Do not run image/SVG enhancements
|
||||||
|
}
|
||||||
|
|
||||||
|
// Image behaviour
|
||||||
|
setupRotation(containerEl);
|
||||||
|
enhanceSVG(containerEl);
|
||||||
|
} ,
|
||||||
onUpdate(containerEl){ setupRotation(containerEl); enhanceSVG(containerEl); }
|
onUpdate(containerEl){ setupRotation(containerEl); enhanceSVG(containerEl); }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
398
assets/scripts/sitemap-interactive.js
Normal file
@@ -0,0 +1,398 @@
|
|||||||
|
/**
|
||||||
|
* sitemap-interactive.js
|
||||||
|
* Drop into /assets/scripts/ — no .org changes required.
|
||||||
|
*
|
||||||
|
* Handles two page structures generated by org-publish:
|
||||||
|
* 1. FLAT LIST — a top-level <ul class="org-ul"> (e.g. Sitemap)
|
||||||
|
* 2. OUTLINE — <div class="outline-2/3"> with <h2>/<h3> headings and
|
||||||
|
* nested <ul class="org-ul"> (e.g. "2025 List", "Blogs List")
|
||||||
|
*
|
||||||
|
* Activated on any page whose <h1 class="title"> matches SITEMAP_PATTERNS.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const SITEMAP_PATTERNS = ["sitemap", "list"];
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
const titleEl = document.querySelector("h1.title");
|
||||||
|
if (!titleEl) return;
|
||||||
|
const title = titleEl.textContent.trim().toLowerCase();
|
||||||
|
if (!SITEMAP_PATTERNS.some((p) => title.includes(p))) return;
|
||||||
|
|
||||||
|
const contentDiv = document.getElementById("content");
|
||||||
|
if (!contentDiv) return;
|
||||||
|
|
||||||
|
const hasOutline = !!contentDiv.querySelector(".outline-2, .outline-3");
|
||||||
|
const topUl = !hasOutline && contentDiv.querySelector("ul.org-ul");
|
||||||
|
if (!hasOutline && !topUl) return;
|
||||||
|
|
||||||
|
// ── Parsers ───────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function parseLi(li) {
|
||||||
|
const link = li.querySelector(":scope > a");
|
||||||
|
const childUl = li.querySelector(":scope > ul");
|
||||||
|
const textNode = Array.from(li.childNodes).find(
|
||||||
|
(n) => n.nodeType === Node.TEXT_NODE && n.textContent.trim()
|
||||||
|
);
|
||||||
|
const tags = Array.from(li.querySelectorAll(".post-tag")).map((t) =>
|
||||||
|
t.textContent.trim()
|
||||||
|
);
|
||||||
|
const dateEl = li.querySelector(".post-date");
|
||||||
|
const date = dateEl ? dateEl.textContent.trim() : null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
label: link
|
||||||
|
? link.textContent.trim()
|
||||||
|
: textNode
|
||||||
|
? textNode.textContent.trim()
|
||||||
|
: li.childNodes[0]?.textContent?.trim() || "",
|
||||||
|
href: link ? link.getAttribute("href") : null,
|
||||||
|
tags,
|
||||||
|
date,
|
||||||
|
children: childUl ? parseUl(childUl) : [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseUl(ul) {
|
||||||
|
return Array.from(ul.children)
|
||||||
|
.filter((li) => li.tagName === "LI")
|
||||||
|
.map(parseLi);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseFlatList() {
|
||||||
|
return { tree: parseUl(topUl), replaceTarget: topUl, wrapOutline: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseOutline() {
|
||||||
|
const tree = [];
|
||||||
|
const outline2s = contentDiv.querySelectorAll(":scope .outline-2");
|
||||||
|
|
||||||
|
if (outline2s.length === 0) {
|
||||||
|
// Only outline-3 directly (flat month grouping without year wrapper)
|
||||||
|
contentDiv.querySelectorAll(":scope .outline-3").forEach((section) => {
|
||||||
|
const heading = section.querySelector("h3");
|
||||||
|
const ul = section.querySelector("ul.org-ul");
|
||||||
|
tree.push({
|
||||||
|
label: heading ? heading.textContent.trim() : "Section",
|
||||||
|
href: null, tags: [], date: null,
|
||||||
|
children: ul ? parseUl(ul) : [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
outline2s.forEach((o2) => {
|
||||||
|
const h2 = o2.querySelector(":scope > div > h2, :scope > h2");
|
||||||
|
const groupNode = {
|
||||||
|
label: h2 ? h2.textContent.trim() : "Group",
|
||||||
|
href: null, tags: [], date: null,
|
||||||
|
children: [],
|
||||||
|
};
|
||||||
|
const outline3s = o2.querySelectorAll(".outline-3");
|
||||||
|
if (outline3s.length > 0) {
|
||||||
|
outline3s.forEach((o3) => {
|
||||||
|
const h3 = o3.querySelector(":scope > div > h3, :scope > h3");
|
||||||
|
const ul = o3.querySelector("ul.org-ul");
|
||||||
|
groupNode.children.push({
|
||||||
|
label: h3 ? h3.textContent.trim() : "Month",
|
||||||
|
href: null, tags: [], date: null,
|
||||||
|
children: ul ? parseUl(ul) : [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const ul = o2.querySelector("ul.org-ul");
|
||||||
|
if (ul) groupNode.children = parseUl(ul);
|
||||||
|
}
|
||||||
|
tree.push(groupNode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return { tree, replaceTarget: null, wrapOutline: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsed = hasOutline ? parseOutline() : parseFlatList();
|
||||||
|
const { tree } = parsed;
|
||||||
|
if (!tree.length) return;
|
||||||
|
|
||||||
|
// ── Styles ────────────────────────────────────────────────────────────
|
||||||
|
if (!document.getElementById("sm-styles")) {
|
||||||
|
const style = document.createElement("style");
|
||||||
|
style.id = "sm-styles";
|
||||||
|
style.textContent = `
|
||||||
|
.sitemap-interactive { font-family: inherit; margin: 1.5rem 0; }
|
||||||
|
.sm-toolbar {
|
||||||
|
display: flex; align-items: center; gap: .6rem;
|
||||||
|
margin-bottom: 1rem; flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.sm-search {
|
||||||
|
flex: 1; min-width: 160px; padding: .35rem .7rem;
|
||||||
|
border: 1px solid var(--border, #444); border-radius: 4px;
|
||||||
|
background: var(--bg, transparent); color: inherit; font-size: .9rem;
|
||||||
|
}
|
||||||
|
.sm-search:focus { outline: 2px solid var(--accent, #7aa2f7); outline-offset: 1px; }
|
||||||
|
.sm-expand-all, .sm-collapse-all {
|
||||||
|
padding: .3rem .65rem; border: 1px solid var(--border, #444);
|
||||||
|
border-radius: 4px; background: transparent; color: inherit;
|
||||||
|
font-size: .8rem; cursor: pointer; opacity: .75; transition: opacity .15s;
|
||||||
|
}
|
||||||
|
.sm-expand-all:hover, .sm-collapse-all:hover { opacity: 1; }
|
||||||
|
|
||||||
|
.sm-tree ul { list-style: none; margin: 0; padding: 0 0 0 1.4rem; }
|
||||||
|
.sm-tree > ul { padding-left: 0; }
|
||||||
|
.sm-tree li { margin: 0; }
|
||||||
|
.sm-node {
|
||||||
|
display: flex; align-items: center; gap: .4rem;
|
||||||
|
padding: .2rem .3rem; border-radius: 4px;
|
||||||
|
line-height: 1.5; transition: background .1s; flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.sm-node:hover { background: var(--hover-bg, rgba(122,162,247,.08)); }
|
||||||
|
.sm-node.sm-hidden { display: none; }
|
||||||
|
|
||||||
|
.sm-toggle {
|
||||||
|
width: 1.2rem; height: 1.2rem; display: inline-flex;
|
||||||
|
align-items: center; justify-content: center;
|
||||||
|
cursor: pointer; border: none; background: none; color: inherit;
|
||||||
|
font-size: .7rem; opacity: .6;
|
||||||
|
transition: transform .18s, opacity .15s;
|
||||||
|
flex-shrink: 0; padding: 0; border-radius: 3px;
|
||||||
|
}
|
||||||
|
.sm-toggle:hover { opacity: 1; background: var(--hover-bg, rgba(122,162,247,.15)); }
|
||||||
|
.sm-toggle.open { transform: rotate(90deg); }
|
||||||
|
.sm-toggle-placeholder { width: 1.2rem; flex-shrink: 0; }
|
||||||
|
|
||||||
|
.sm-icon { font-size: .8rem; opacity: .5; flex-shrink: 0; }
|
||||||
|
|
||||||
|
.sm-label a { color: var(--link, inherit); text-decoration: none; font-size: .9rem; }
|
||||||
|
.sm-label a:hover { text-decoration: underline; }
|
||||||
|
.sm-label span { font-size: .9rem; font-weight: 600; opacity: .85; }
|
||||||
|
|
||||||
|
.sm-badge {
|
||||||
|
font-size: .65rem; padding: .05rem .35rem; border-radius: 8px;
|
||||||
|
background: var(--badge-bg, rgba(122,162,247,.15));
|
||||||
|
color: var(--badge-fg, #7aa2f7); opacity: .8;
|
||||||
|
}
|
||||||
|
.sm-date { font-size: .75rem; opacity: .45; margin-left: .2rem; }
|
||||||
|
.sm-tags { display: inline-flex; gap: .25rem; margin-left: .2rem; }
|
||||||
|
.sm-tag {
|
||||||
|
font-size: .65rem; padding: .05rem .3rem; border-radius: 8px;
|
||||||
|
background: var(--tag-bg, rgba(160,200,120,.15));
|
||||||
|
color: var(--tag-fg, #9ece6a); opacity: .85;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sm-children { overflow: hidden; }
|
||||||
|
.sm-children.collapsed { display: none; }
|
||||||
|
.sm-label mark {
|
||||||
|
background: var(--mark-bg, rgba(255,200,50,.3));
|
||||||
|
color: inherit; border-radius: 2px; padding: 0 1px;
|
||||||
|
}
|
||||||
|
.sm-count { font-size: .78rem; opacity: .45; margin-top: .8rem; }
|
||||||
|
`;
|
||||||
|
document.head.appendChild(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Widget scaffold ───────────────────────────────────────────────────
|
||||||
|
const wrapper = document.createElement("div");
|
||||||
|
wrapper.className = "sitemap-interactive";
|
||||||
|
wrapper.innerHTML = `
|
||||||
|
<div class="sm-toolbar">
|
||||||
|
<input class="sm-search" type="search" placeholder="Filter pages…" aria-label="Filter" />
|
||||||
|
<button class="sm-expand-all">⊞ Expand all</button>
|
||||||
|
<button class="sm-collapse-all">⊟ Collapse all</button>
|
||||||
|
</div>
|
||||||
|
<div class="sm-tree" role="tree"></div>
|
||||||
|
<p class="sm-count"></p>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const treeEl = wrapper.querySelector(".sm-tree");
|
||||||
|
const searchEl = wrapper.querySelector(".sm-search");
|
||||||
|
const countEl = wrapper.querySelector(".sm-count");
|
||||||
|
|
||||||
|
// ── Tree builder ──────────────────────────────────────────────────────
|
||||||
|
function countLeaves(nodes) {
|
||||||
|
let n = 0;
|
||||||
|
for (const node of nodes) {
|
||||||
|
if (!node.children || !node.children.length) n++;
|
||||||
|
else n += countLeaves(node.children);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildTree(nodes) {
|
||||||
|
const ul = document.createElement("ul");
|
||||||
|
for (const node of nodes) {
|
||||||
|
const li = document.createElement("li");
|
||||||
|
const row = document.createElement("div");
|
||||||
|
row.className = "sm-node";
|
||||||
|
const hasChildren = node.children && node.children.length > 0;
|
||||||
|
|
||||||
|
let childrenEl;
|
||||||
|
if (hasChildren) {
|
||||||
|
const toggle = document.createElement("button");
|
||||||
|
toggle.className = "sm-toggle open";
|
||||||
|
toggle.innerHTML = "▶";
|
||||||
|
toggle.setAttribute("aria-expanded", "true");
|
||||||
|
childrenEl = document.createElement("div");
|
||||||
|
childrenEl.className = "sm-children";
|
||||||
|
childrenEl.appendChild(buildTree(node.children));
|
||||||
|
toggle.addEventListener("click", () => {
|
||||||
|
childrenEl.classList.toggle("collapsed");
|
||||||
|
toggle.classList.toggle("open");
|
||||||
|
toggle.setAttribute("aria-expanded",
|
||||||
|
String(!childrenEl.classList.contains("collapsed")));
|
||||||
|
});
|
||||||
|
row.appendChild(toggle);
|
||||||
|
} else {
|
||||||
|
const ph = document.createElement("span");
|
||||||
|
ph.className = "sm-toggle-placeholder";
|
||||||
|
row.appendChild(ph);
|
||||||
|
}
|
||||||
|
|
||||||
|
const icon = document.createElement("span");
|
||||||
|
icon.className = "sm-icon";
|
||||||
|
icon.textContent = hasChildren ? "📂" : "📄";
|
||||||
|
row.appendChild(icon);
|
||||||
|
|
||||||
|
const labelEl = document.createElement("span");
|
||||||
|
labelEl.className = "sm-label";
|
||||||
|
if (node.href) {
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = node.href;
|
||||||
|
a.textContent = node.label;
|
||||||
|
labelEl.appendChild(a);
|
||||||
|
} else {
|
||||||
|
const s = document.createElement("span");
|
||||||
|
s.textContent = node.label;
|
||||||
|
labelEl.appendChild(s);
|
||||||
|
}
|
||||||
|
row.appendChild(labelEl);
|
||||||
|
|
||||||
|
if (hasChildren) {
|
||||||
|
const badge = document.createElement("span");
|
||||||
|
badge.className = "sm-badge";
|
||||||
|
badge.textContent = countLeaves(node.children);
|
||||||
|
row.appendChild(badge);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.date) {
|
||||||
|
const dateSpan = document.createElement("span");
|
||||||
|
dateSpan.className = "sm-date";
|
||||||
|
dateSpan.textContent = node.date;
|
||||||
|
row.appendChild(dateSpan);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.tags && node.tags.length) {
|
||||||
|
const tagsEl = document.createElement("span");
|
||||||
|
tagsEl.className = "sm-tags";
|
||||||
|
node.tags.forEach((t) => {
|
||||||
|
const tag = document.createElement("span");
|
||||||
|
tag.className = "sm-tag";
|
||||||
|
tag.textContent = t;
|
||||||
|
tagsEl.appendChild(tag);
|
||||||
|
});
|
||||||
|
row.appendChild(tagsEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
li.appendChild(row);
|
||||||
|
if (hasChildren) li.appendChild(childrenEl);
|
||||||
|
ul.appendChild(li);
|
||||||
|
}
|
||||||
|
return ul;
|
||||||
|
}
|
||||||
|
|
||||||
|
treeEl.appendChild(buildTree(tree));
|
||||||
|
|
||||||
|
// ── Search / filter ───────────────────────────────────────────────────
|
||||||
|
function escapeRe(s) {
|
||||||
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterTree(q) {
|
||||||
|
const query = q.trim().toLowerCase();
|
||||||
|
const re = query ? new RegExp(escapeRe(query), "gi") : null;
|
||||||
|
let visible = 0;
|
||||||
|
|
||||||
|
function walk(ul) {
|
||||||
|
let anyVisible = false;
|
||||||
|
for (const li of ul.children) {
|
||||||
|
const row = li.querySelector(":scope > .sm-node");
|
||||||
|
const childrenDiv = li.querySelector(":scope > .sm-children");
|
||||||
|
const labelEl = row.querySelector(".sm-label");
|
||||||
|
const target = labelEl.querySelector("a") || labelEl.querySelector("span");
|
||||||
|
const text = target.dataset.orig || target.textContent;
|
||||||
|
target.dataset.orig = text;
|
||||||
|
|
||||||
|
let selfMatch = false;
|
||||||
|
if (!query) {
|
||||||
|
target.innerHTML = "";
|
||||||
|
target.textContent = text;
|
||||||
|
selfMatch = true;
|
||||||
|
} else if (text.toLowerCase().includes(query)) {
|
||||||
|
target.innerHTML = text.replace(re, (m) => `<mark>${m}</mark>`);
|
||||||
|
selfMatch = true;
|
||||||
|
} else {
|
||||||
|
target.innerHTML = "";
|
||||||
|
target.textContent = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
let childVisible = false;
|
||||||
|
if (childrenDiv) {
|
||||||
|
childVisible = walk(childrenDiv.querySelector("ul"));
|
||||||
|
if (query) {
|
||||||
|
childrenDiv.classList.toggle("collapsed", !childVisible && !selfMatch);
|
||||||
|
const toggle = row.querySelector(".sm-toggle");
|
||||||
|
if (toggle) toggle.classList.toggle("open", childVisible || selfMatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const show = !query || selfMatch || childVisible;
|
||||||
|
row.classList.toggle("sm-hidden", !show);
|
||||||
|
if (show) {
|
||||||
|
anyVisible = true;
|
||||||
|
if (!childrenDiv) visible++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return anyVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
walk(treeEl.querySelector("ul"));
|
||||||
|
countEl.textContent = query
|
||||||
|
? `${visible} page${visible !== 1 ? "s" : ""} matching "${query}"`
|
||||||
|
: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
searchEl.addEventListener("input", (e) => filterTree(e.target.value));
|
||||||
|
|
||||||
|
wrapper.querySelector(".sm-expand-all").addEventListener("click", () => {
|
||||||
|
treeEl.querySelectorAll(".sm-children").forEach((el) => el.classList.remove("collapsed"));
|
||||||
|
treeEl.querySelectorAll(".sm-toggle").forEach((el) => {
|
||||||
|
el.classList.add("open");
|
||||||
|
el.setAttribute("aria-expanded", "true");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
wrapper.querySelector(".sm-collapse-all").addEventListener("click", () => {
|
||||||
|
treeEl.querySelectorAll(".sm-children").forEach((el) => el.classList.add("collapsed"));
|
||||||
|
treeEl.querySelectorAll(".sm-toggle").forEach((el) => {
|
||||||
|
el.classList.remove("open");
|
||||||
|
el.setAttribute("aria-expanded", "false");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── Inject into page ──────────────────────────────────────────────────
|
||||||
|
if (parsed.wrapOutline) {
|
||||||
|
// Hide original outline divs (direct children of content only)
|
||||||
|
contentDiv.querySelectorAll(":scope > .outline-2, :scope > .outline-3")
|
||||||
|
.forEach((el) => (el.style.display = "none"));
|
||||||
|
// Insert after title + optional intro <p>
|
||||||
|
const insertAfter = contentDiv.querySelector(":scope > p") || titleEl;
|
||||||
|
insertAfter.insertAdjacentElement("afterend", wrapper);
|
||||||
|
} else {
|
||||||
|
parsed.replaceTarget.replaceWith(wrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === "loading") {
|
||||||
|
document.addEventListener("DOMContentLoaded", init);
|
||||||
|
} else {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -62,7 +62,18 @@
|
|||||||
--kb-card-text: #e5e7eb;
|
--kb-card-text: #e5e7eb;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Times';
|
||||||
|
src: url('../fonts/times.ttf') format('ttf');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Noto';
|
||||||
|
src: url('../fonts/NotoSans-Regular.ttf') format('ttf');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
html, body{
|
html, body{
|
||||||
background-color: var(--bg);
|
background-color: var(--bg);
|
||||||
@@ -70,6 +81,7 @@ html, body{
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
transition: background-color .3s, color .3s;
|
transition: background-color .3s, color .3s;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
font-family: 'Noto', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3{ color: var(--heading); }
|
h1, h2, h3{ color: var(--heading); }
|
||||||
|
|||||||
@@ -5,11 +5,6 @@ See the categories: @@html:<a href="../../home/categories.html">Categories</a>@@
|
|||||||
|
|
||||||
* 2025
|
* 2025
|
||||||
|
|
||||||
** February 2026
|
|
||||||
- [[file:2025-list.sync-conflict-20260222-170216-VT6366A.org][2025 List]] @@html:<span class="post-date">22-02-2026 17:02</span>@@
|
|
||||||
- [[file:2025-list.sync-conflict-20260222-170034-NE5VEIB.org][2025 List]] @@html:<span class="post-date">22-02-2026 17:00</span>@@
|
|
||||||
- [[file:2025-list.sync-conflict-20260222-165714-NE5VEIB.org][2025 List]] @@html:<span class="post-date">22-02-2026 16:56</span>@@
|
|
||||||
|
|
||||||
** December 2025
|
** December 2025
|
||||||
- [[file:12-december/28-12-week-review.org][[28-12-2025] - Weekly Review]] @@html:<span class="post-date">28-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:12-december/28-12-week-review.org][[28-12-2025] - Weekly Review]] @@html:<span class="post-date">28-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:12-december/21-12-week-review.org][[21-12-2025] - Weekly Review]] @@html:<span class="post-date">21-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:12-december/21-12-week-review.org][[21-12-2025] - Weekly Review]] @@html:<span class="post-date">21-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
#+TITLE: 2025 List
|
|
||||||
#+OPTIONS: toc:nil num:nil
|
|
||||||
|
|
||||||
See the categories: @@html:<a href="../../home/categories.html">Categories</a>@@
|
|
||||||
|
|
||||||
* 2025
|
|
||||||
|
|
||||||
** December 2025
|
|
||||||
- [[file:12-december/28-12-week-review.org][[28-12-2025] - Weekly Review]] @@html:<span class="post-date">28-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:12-december/21-12-week-review.org][[21-12-2025] - Weekly Review]] @@html:<span class="post-date">21-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:12-december/14-12-week-review.org][[14-12-2025] - Weekly Review]] @@html:<span class="post-date">09-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:12-december/07-12-week-review.org][[07-12-2025] - Weekly Review]] @@html:<span class="post-date">07-12-2025 20:34</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
|
|
||||||
** November 2025
|
|
||||||
- [[file:11-november/30-11-week-review.org][[30-11-2025] - Weekly Review]] @@html:<span class="post-date">30-11-2025 17:09</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/23-11-week-review.org][[23-11-2025] - Weekly Review]] @@html:<span class="post-date">17-11-2025 18:05</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/16-11-week-review.org][[16-11-2025] - Weekly Review]] @@html:<span class="post-date">10-11-2025 17:44</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/09-11-week-review.org][[09-11-2025] - Weekly Review]] @@html:<span class="post-date">09-11-2025 20:08</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/02-11-week-review.org][[02-11-2025] - Weekly Review]] @@html:<span class="post-date">02-11-2025 00:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
|
|
||||||
** August 2025
|
|
||||||
- [[file:08-august/third-time.org][Third Time]] @@html:<span class="post-date">28-08-2025 17:08</span>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/benefits-of-reading.org][Benefits of Reading]] @@html:<span class="post-date">14-08-2025 23:36</span>@@ @@html:<a href="/tags/reading.html"> <span class="post-tag">reading</span> </a>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/hilberts.hotel.org][Hilbert's Hotel]] @@html:<span class="post-date">11-08-2025 18:39</span>@@ @@html:<a href="/tags/maths.html"> <span class="post-tag">maths</span> </a>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/spending-the-whole-day-on-this-website.org][09-08-2025: Website Changes]] @@html:<span class="post-date">09-08-2025 00:00</span>@@ @@html:<a href="/tags/emacs.html"> <span class="post-tag">emacs</span> </a>@@ @@html:<a href="/tags/website.html"> <span class="post-tag">website</span> </a>@@
|
|
||||||
- [[file:08-august/what-do-i-want-to-do-with-emacs.org][What Do I Want To Do With Emacs]] @@html:<span class="post-date">08-08-2025 00:00</span>@@ @@html:<a href="/tags/emacs.html"> <span class="post-tag">emacs</span> </a>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:08-august/wacom-with-arch.org][Wacom With Arch]] @@html:<span class="post-date">08-08-2025 00:00</span>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/zettelkasten.org][Zettelkasten Method]] @@html:<span class="post-date">07-08-2025 00:00</span>@@ @@html:<a href="/tags/education.html"> <span class="post-tag">education</span> </a>@@
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#+TITLE: 2025 List
|
|
||||||
#+OPTIONS: toc:nil num:nil
|
|
||||||
|
|
||||||
See the categories: @@html:<a href="../../home/categories.html">Categories</a>@@
|
|
||||||
|
|
||||||
* 2025
|
|
||||||
|
|
||||||
** February 2026
|
|
||||||
- [[file:2025-list.sync-conflict-20260222-165714-NE5VEIB.org][2025 List]] @@html:<span class="post-date">22-02-2026 16:56</span>@@
|
|
||||||
|
|
||||||
** December 2025
|
|
||||||
- [[file:12-december/28-12-week-review.org][[28-12-2025] - Weekly Review]] @@html:<span class="post-date">28-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:12-december/21-12-week-review.org][[21-12-2025] - Weekly Review]] @@html:<span class="post-date">21-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:12-december/14-12-week-review.org][[14-12-2025] - Weekly Review]] @@html:<span class="post-date">09-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:12-december/07-12-week-review.org][[07-12-2025] - Weekly Review]] @@html:<span class="post-date">07-12-2025 20:34</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
|
|
||||||
** November 2025
|
|
||||||
- [[file:11-november/30-11-week-review.org][[30-11-2025] - Weekly Review]] @@html:<span class="post-date">30-11-2025 17:09</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/23-11-week-review.org][[23-11-2025] - Weekly Review]] @@html:<span class="post-date">17-11-2025 18:05</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/16-11-week-review.org][[16-11-2025] - Weekly Review]] @@html:<span class="post-date">10-11-2025 17:44</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/09-11-week-review.org][[09-11-2025] - Weekly Review]] @@html:<span class="post-date">09-11-2025 20:08</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/02-11-week-review.org][[02-11-2025] - Weekly Review]] @@html:<span class="post-date">02-11-2025 00:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
|
|
||||||
** August 2025
|
|
||||||
- [[file:08-august/third-time.org][Third Time]] @@html:<span class="post-date">28-08-2025 17:08</span>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/benefits-of-reading.org][Benefits of Reading]] @@html:<span class="post-date">14-08-2025 23:36</span>@@ @@html:<a href="/tags/reading.html"> <span class="post-tag">reading</span> </a>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/hilberts.hotel.org][Hilbert's Hotel]] @@html:<span class="post-date">11-08-2025 18:39</span>@@ @@html:<a href="/tags/maths.html"> <span class="post-tag">maths</span> </a>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/spending-the-whole-day-on-this-website.org][09-08-2025: Website Changes]] @@html:<span class="post-date">09-08-2025 00:00</span>@@ @@html:<a href="/tags/emacs.html"> <span class="post-tag">emacs</span> </a>@@ @@html:<a href="/tags/website.html"> <span class="post-tag">website</span> </a>@@
|
|
||||||
- [[file:08-august/what-do-i-want-to-do-with-emacs.org][What Do I Want To Do With Emacs]] @@html:<span class="post-date">08-08-2025 00:00</span>@@ @@html:<a href="/tags/emacs.html"> <span class="post-tag">emacs</span> </a>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:08-august/wacom-with-arch.org][Wacom With Arch]] @@html:<span class="post-date">08-08-2025 00:00</span>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/zettelkasten.org][Zettelkasten Method]] @@html:<span class="post-date">07-08-2025 00:00</span>@@ @@html:<a href="/tags/education.html"> <span class="post-tag">education</span> </a>@@
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#+TITLE: 2025 List
|
|
||||||
#+OPTIONS: toc:nil num:nil
|
|
||||||
|
|
||||||
See the categories: @@html:<a href="../../home/categories.html">Categories</a>@@
|
|
||||||
|
|
||||||
* 2025
|
|
||||||
|
|
||||||
** February 2026
|
|
||||||
- [[file:2025-list.sync-conflict-20260222-170034-NE5VEIB.org][2025 List]] @@html:<span class="post-date">22-02-2026 17:00</span>@@
|
|
||||||
- [[file:2025-list.sync-conflict-20260222-165714-NE5VEIB.org][2025 List]] @@html:<span class="post-date">22-02-2026 16:56</span>@@
|
|
||||||
|
|
||||||
** December 2025
|
|
||||||
- [[file:12-december/28-12-week-review.org][[28-12-2025] - Weekly Review]] @@html:<span class="post-date">28-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:12-december/21-12-week-review.org][[21-12-2025] - Weekly Review]] @@html:<span class="post-date">21-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:12-december/14-12-week-review.org][[14-12-2025] - Weekly Review]] @@html:<span class="post-date">09-12-2025 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:12-december/07-12-week-review.org][[07-12-2025] - Weekly Review]] @@html:<span class="post-date">07-12-2025 20:34</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
|
|
||||||
** November 2025
|
|
||||||
- [[file:11-november/30-11-week-review.org][[30-11-2025] - Weekly Review]] @@html:<span class="post-date">30-11-2025 17:09</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/23-11-week-review.org][[23-11-2025] - Weekly Review]] @@html:<span class="post-date">17-11-2025 18:05</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/16-11-week-review.org][[16-11-2025] - Weekly Review]] @@html:<span class="post-date">10-11-2025 17:44</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/09-11-week-review.org][[09-11-2025] - Weekly Review]] @@html:<span class="post-date">09-11-2025 20:08</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:11-november/02-11-week-review.org][[02-11-2025] - Weekly Review]] @@html:<span class="post-date">02-11-2025 00:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
|
|
||||||
** August 2025
|
|
||||||
- [[file:08-august/third-time.org][Third Time]] @@html:<span class="post-date">28-08-2025 17:08</span>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/benefits-of-reading.org][Benefits of Reading]] @@html:<span class="post-date">14-08-2025 23:36</span>@@ @@html:<a href="/tags/reading.html"> <span class="post-tag">reading</span> </a>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/hilberts.hotel.org][Hilbert's Hotel]] @@html:<span class="post-date">11-08-2025 18:39</span>@@ @@html:<a href="/tags/maths.html"> <span class="post-tag">maths</span> </a>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/spending-the-whole-day-on-this-website.org][09-08-2025: Website Changes]] @@html:<span class="post-date">09-08-2025 00:00</span>@@ @@html:<a href="/tags/emacs.html"> <span class="post-tag">emacs</span> </a>@@ @@html:<a href="/tags/website.html"> <span class="post-tag">website</span> </a>@@
|
|
||||||
- [[file:08-august/wacom-with-arch.org][Wacom With Arch]] @@html:<span class="post-date">08-08-2025 00:00</span>@@ @@html:<a href="/tags/insights.html"> <span class="post-tag">insights</span> </a>@@
|
|
||||||
- [[file:08-august/what-do-i-want-to-do-with-emacs.org][What Do I Want To Do With Emacs]] @@html:<span class="post-date">08-08-2025 00:00</span>@@ @@html:<a href="/tags/emacs.html"> <span class="post-tag">emacs</span> </a>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
|
||||||
- [[file:08-august/zettelkasten.org][Zettelkasten Method]] @@html:<span class="post-date">07-08-2025 00:00</span>@@ @@html:<a href="/tags/education.html"> <span class="post-tag">education</span> </a>@@
|
|
||||||
@@ -2,8 +2,13 @@
|
|||||||
#+OPTIONS: num:nil
|
#+OPTIONS: num:nil
|
||||||
#+DATE: <2026-02-15 Sun 12:00>
|
#+DATE: <2026-02-15 Sun 12:00>
|
||||||
#+filetags: :review:
|
#+filetags: :review:
|
||||||
#+WIP: t
|
|
||||||
#+COMMENTS: t
|
#+COMMENTS: t
|
||||||
#+SLUG: 15-02-26-week-review
|
#+SLUG: 15-02-26-week-review
|
||||||
|
|
||||||
Content
|
This week was quite difficult to get through, but Alhamdulillah we managed. The reason it was difficult was because I was working on some really interesting things but the implementation for the whole user story had to be reworked, some of the TOPS seniors were concerned with the Post Deployment Tests alongside the new way in which TMC gets deployed. Anyways, one of the senior engineer said he was gonna look at finding out a new way to do PDT, as right now there are 2 of us who are blocked due to this. Not really our fault but scope always change.
|
||||||
|
|
||||||
|
Also had my first ever refinement session, which I held on <2026-02-13 Fri>.
|
||||||
|
|
||||||
|
On a brighter note, Ramadan begins next week!
|
||||||
|
|
||||||
|
[[../../../assets/images/reviews/timesheets/timesheet-15-02-26.png]]
|
||||||
|
|||||||
35
blogs/2026/02-february/22-02-week-review.org
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#+TITLE: [22-02-2026] - Weekly Review
|
||||||
|
#+OPTIONS: num:nil
|
||||||
|
#+DATE: <2026-02-22 Sun 12:00>
|
||||||
|
#+filetags: :review:
|
||||||
|
#+COMMENTS: t
|
||||||
|
#+SLUG: 22-02-26-week-review
|
||||||
|
|
||||||
|
* Review
|
||||||
|
I started to work on upgrading Journeys web API from net 4.8 to net 9. The upgrade was extremely confusing, as each TMC instance is unique in it's own right, so figuring out the Dependency Inversions, Authentication, Authorisation and all that stuff was a manual process.
|
||||||
|
|
||||||
|
In the end, the PR was made, and the base net 9 project is underway. Apparently, this API is the one that consumes the most resources, so upgrading this (alongside the other 5) could yield a saving of 110k whole british pounds.
|
||||||
|
|
||||||
|
On another note, Ramadan has officially started on the night of <2026-02-17 Tue>. It's imperative I take more screen breaks as my eyesight is getting worse, and I randomly get dizziness due to prolonged screen activity.
|
||||||
|
|
||||||
|
Some other things I worked on:
|
||||||
|
|
||||||
|
- Reintroducing nextcloud, this time with more capability for file editing.
|
||||||
|
- Added an office suite extension for nextcloud, so now I can edit excel files online.
|
||||||
|
- Working on the ~zone~ dashboard.
|
||||||
|
- Got back into some powerbi (after I found some .pbix files which I'm /pretty sure/ is not meant to be seen by the company.
|
||||||
|
|
||||||
|
* Other things
|
||||||
|
|
||||||
|
** Competencies
|
||||||
|
Not sure to what extent this is of any use but I can see the progress of everyone's competencies. Interesting find.
|
||||||
|
|
||||||
|
[[../../../assets/images/reviews/competency-powerbi-report.png]]
|
||||||
|
|
||||||
|
** Journeys stuff
|
||||||
|
|
||||||
|
[[../../../assets/images/reviews/journeys-api-side-by-side-upgrade.png]]
|
||||||
|
|
||||||
|
* Timesheet
|
||||||
|
|
||||||
|
[[../../../assets/images/reviews/timesheets/timesheet-22-02-26.png]]
|
||||||
14
blogs/2026/02-february/24-02-26.org
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#+TITLE: Integration tests failing (sob)
|
||||||
|
#+OPTIONS: num:nil
|
||||||
|
#+DATE: <2026-02-24 Tue 16:55>
|
||||||
|
#+filetags: :life:
|
||||||
|
#+COMMENTS: t
|
||||||
|
#+SLUG: 24-02-26
|
||||||
|
|
||||||
|
Oh man today was hectic. Got an email at three am in the morning that the integration tests have failed for journeys web api (it failed at 4pm the day before but didn't even inform me). Anyways went back to sleep after sehri and decided it was a morning problem.
|
||||||
|
|
||||||
|
Spent from 8:15 all the way till 14:45 diagnosing the issue. You'll never guess what it was.
|
||||||
|
|
||||||
|
[[../../../assets/images/240226-pr.png]]
|
||||||
|
|
||||||
|
THREE PACKAGE CHANGES. Anyways I need to clock out, this was a hilarious reason for the integration tests to fail.
|
||||||
15
blogs/2026/02-february/26-02-26.org
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#+TITLE: Starting the Journeys Upgrade
|
||||||
|
#+OPTIONS: num:nil
|
||||||
|
#+DATE: <2026-02-26 Thu 17:32>
|
||||||
|
#+filetags: :life:
|
||||||
|
#+COMMENTS: t
|
||||||
|
#+SLUG: 26-02-26
|
||||||
|
|
||||||
|
I picked up a huge task. Its estimated duration is 40 hours and was said that it's likely an underestimate.
|
||||||
|
Migrating the endpoints themselves isn't a difficult task. It's the dependency inversions. I spent the whole day and only ended up getting 2 out of so many done, mainly because I was stuck on some DI's.
|
||||||
|
|
||||||
|
Times like this I can't figure out what I'm doing wrong, but as of right now this is what I am getting:
|
||||||
|
|
||||||
|
[[../../../assets/images/26-02-26-di-errors.png]]
|
||||||
|
|
||||||
|
[[../../../assets/images/26-02-26-di-errors-2.png]]
|
||||||
10
blogs/2026/02-february/27-02-26.org
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#+TITLE: Journeys rambles again...
|
||||||
|
#+OPTIONS: num:nil
|
||||||
|
#+DATE: <2026-02-27 Fri 17:12>
|
||||||
|
#+filetags: :life:
|
||||||
|
#+COMMENTS: t
|
||||||
|
#+SLUG: 27-02-26
|
||||||
|
|
||||||
|
Got off on a call with a senior (we spent 3 hours debugging). Turns out that xservermap and whatever dependencies it has requires a total of 3 repository changes in order for the net 9 version of the project to be able to wire up the dependencies correctly. Ehhh not a pleasant sight. I guess for the moment this endpoint is blocked until those changes are checked in and out there.
|
||||||
|
|
||||||
|
[[../../../assets/images/27-02-26-xserver.png]]
|
||||||
16
blogs/2026/02-february/third-meeting.org
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#+TITLE: Third Meeting with lima :)
|
||||||
|
#+OPTIONS: num:nil
|
||||||
|
#+DATE: <2026-02-01 Sun 12:00>
|
||||||
|
#+filetags: :life:
|
||||||
|
#+COMMENTS: t
|
||||||
|
#+SLUG: third-meeting-with-lima
|
||||||
|
|
||||||
|
Today was the third meeting with lima.
|
||||||
|
|
||||||
|
The day started off quite warm, I was up early and had class from 11am all the way until 2:15pm. I left class and immediately went home, got changed and we all left around 2:30pm. The drive there had me feeling a little nervous, we stopped at the service station to pray, then I drove the rest of the way (which helped ease the nerves). Oh and there was a huge accident that we saw. Driving when it's raining requires extra caution.
|
||||||
|
|
||||||
|
Once we got there it took a while to bring in all the gifts, but I think it worked perfectly, because I got to see lima without many people around and give her her Eid gifts (that smile was contagious, almost melted right there and then).
|
||||||
|
|
||||||
|
Majority of the time there we spoke about final details for the Nikah, but the highlight was speaking to lima (!!!). She said I was soft, which made me really happy, because I know she wants safety, comfort and softness, so I want to try my best and provide those things for her at the very least.
|
||||||
|
|
||||||
|
/Writing this up made me want the days to go by faster./
|
||||||
14
blogs/2026/03-march/01-03-week-review.org
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#+TITLE: [01-03-2026] - Weekly Review
|
||||||
|
#+OPTIONS: num:nil
|
||||||
|
#+DATE: <2026-03-01 Sun 12:00>
|
||||||
|
#+filetags: :review:
|
||||||
|
#+COMMENTS: t
|
||||||
|
#+SLUG: 01-03-26-week-review
|
||||||
|
|
||||||
|
* Review
|
||||||
|
|
||||||
|
Majority of this week was spent working on the Journeys upgrade. Albeit the fact that it's the second week of Ramadan, I worked a total of 42.5 hours, which is way too much. I definitely do need to establish a work-life balance...
|
||||||
|
|
||||||
|
* Timesheet
|
||||||
|
|
||||||
|
[[../../../assets/images/reviews/timesheets/timesheet-01-03-26.png]]
|
||||||
@@ -5,10 +5,18 @@ See the categories: @@html:<a href="../../home/categories.html">Categories</a>@@
|
|||||||
|
|
||||||
* 2026
|
* 2026
|
||||||
|
|
||||||
|
** March 2026
|
||||||
|
- [[file:03-march/01-03-week-review.org][[01-03-2026] - Weekly Review]] @@html:<span class="post-date">01-03-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
|
|
||||||
** February 2026
|
** February 2026
|
||||||
|
- [[file:02-february/27-02-26.org][Journeys rambles again...]] @@html:<span class="post-date">27-02-2026 17:12</span>@@ @@html:<a href="/tags/life.html"> <span class="post-tag">life</span> </a>@@
|
||||||
|
- [[file:02-february/26-02-26.org][Starting the Journeys Upgrade]] @@html:<span class="post-date">26-02-2026 17:32</span>@@ @@html:<a href="/tags/life.html"> <span class="post-tag">life</span> </a>@@
|
||||||
|
- [[file:02-february/24-02-26.org][Integration tests failing (sob)]] @@html:<span class="post-date">24-02-2026 16:55</span>@@ @@html:<a href="/tags/life.html"> <span class="post-tag">life</span> </a>@@
|
||||||
|
- [[file:02-february/22-02-week-review.org][[22-02-2026] - Weekly Review]] @@html:<span class="post-date">22-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]] @@html:<span class="post-date">15-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]] @@html:<span class="post-date">15-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]] @@html:<span class="post-date">08-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]] @@html:<span class="post-date">08-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]] @@html:<span class="post-date">01-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]] @@html:<span class="post-date">01-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
|
- [[file:02-february/third-meeting.org][Third Meeting with lima :)]] @@html:<span class="post-date">01-02-2026 12:00</span>@@ @@html:<a href="/tags/life.html"> <span class="post-tag">life</span> </a>@@
|
||||||
|
|
||||||
** January 2026
|
** January 2026
|
||||||
- [[file:01-january/25-01-week-review.org][[25-01-2026] - Weekly Review]] @@html:<span class="post-date">25-01-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:01-january/25-01-week-review.org][[25-01-2026] - Weekly Review]] @@html:<span class="post-date">25-01-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
|
|||||||
@@ -4,14 +4,17 @@
|
|||||||
See the categories: @@html:<a href="../home/categories.html">Categories</a>@@
|
See the categories: @@html:<a href="../home/categories.html">Categories</a>@@
|
||||||
|
|
||||||
* Blogs:
|
* Blogs:
|
||||||
- [[file:2026/2026-list.org][2026 List]] @@html:<span class="post-date">22-02-2026 22:37</span>@@
|
- [[file:2026/2026-list.org][2026 List]] @@html:<span class="post-date">08-03-2026 12:51</span>@@
|
||||||
- [[file:2025/2025-list.org][2025 List]] @@html:<span class="post-date">22-02-2026 22:37</span>@@
|
- [[file:2025/2025-list.org][2025 List]] @@html:<span class="post-date">08-03-2026 12:51</span>@@
|
||||||
- [[file:2025/2025-list.sync-conflict-20260222-170216-VT6366A.org][2025 List]] @@html:<span class="post-date">22-02-2026 17:02</span>@@
|
- [[file:2026/03-march/01-03-week-review.org][[01-03-2026] - Weekly Review]] @@html:<span class="post-date">01-03-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:2025/2025-list.sync-conflict-20260222-170034-NE5VEIB.org][2025 List]] @@html:<span class="post-date">22-02-2026 17:00</span>@@
|
- [[file:2026/02-february/27-02-26.org][Journeys rambles again...]] @@html:<span class="post-date">27-02-2026 17:12</span>@@ @@html:<a href="/tags/life.html"> <span class="post-tag">life</span> </a>@@
|
||||||
- [[file:2025/2025-list.sync-conflict-20260222-165714-NE5VEIB.org][2025 List]] @@html:<span class="post-date">22-02-2026 16:56</span>@@
|
- [[file:2026/02-february/26-02-26.org][Starting the Journeys Upgrade]] @@html:<span class="post-date">26-02-2026 17:32</span>@@ @@html:<a href="/tags/life.html"> <span class="post-tag">life</span> </a>@@
|
||||||
|
- [[file:2026/02-february/24-02-26.org][Integration tests failing (sob)]] @@html:<span class="post-date">24-02-2026 16:55</span>@@ @@html:<a href="/tags/life.html"> <span class="post-tag">life</span> </a>@@
|
||||||
|
- [[file:2026/02-february/22-02-week-review.org][[22-02-2026] - Weekly Review]] @@html:<span class="post-date">22-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:2026/02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]] @@html:<span class="post-date">15-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:2026/02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]] @@html:<span class="post-date">15-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:2026/02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]] @@html:<span class="post-date">08-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:2026/02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]] @@html:<span class="post-date">08-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:2026/02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]] @@html:<span class="post-date">01-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:2026/02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]] @@html:<span class="post-date">01-02-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
|
- [[file:2026/02-february/third-meeting.org][Third Meeting with lima :)]] @@html:<span class="post-date">01-02-2026 12:00</span>@@ @@html:<a href="/tags/life.html"> <span class="post-tag">life</span> </a>@@
|
||||||
- [[file:2026/01-january/25-01-week-review.org][[25-01-2026] - Weekly Review]] @@html:<span class="post-date">25-01-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:2026/01-january/25-01-week-review.org][[25-01-2026] - Weekly Review]] @@html:<span class="post-date">25-01-2026 12:00</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:2026/01-january/18-01-week-review.org][[18-01-2026] - Weekly Review]] @@html:<span class="post-date">18-01-2026 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:2026/01-january/18-01-week-review.org][[18-01-2026] - Weekly Review]] @@html:<span class="post-date">18-01-2026 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
- [[file:2026/01-january/11-01-week-review.org][[11-01-2026] - Weekly Review]] @@html:<span class="post-date">11-01-2026 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
- [[file:2026/01-january/11-01-week-review.org][[11-01-2026] - Weekly Review]] @@html:<span class="post-date">11-01-2026 12:12</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@
|
||||||
|
|||||||
156
build-site.el
@@ -70,6 +70,7 @@
|
|||||||
<script src=\"/assets/scripts/search.js\" defer></script>
|
<script src=\"/assets/scripts/search.js\" defer></script>
|
||||||
<script src=\"/assets/scripts/svg-pan-zoom.min.js\" defer></script>
|
<script src=\"/assets/scripts/svg-pan-zoom.min.js\" defer></script>
|
||||||
<script src=\"/assets/scripts/gallery-init.js\" defer></script>
|
<script src=\"/assets/scripts/gallery-init.js\" defer></script>
|
||||||
|
<script src=\"/assets/scripts/sitemap-interactive.js\" defer></script>
|
||||||
"
|
"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -91,7 +92,6 @@
|
|||||||
|
|
||||||
(defvar z-preamble
|
(defvar z-preamble
|
||||||
"
|
"
|
||||||
<a href=\"https://notes.zainezq.com\"> <img src=\"/assets/images/1_to_2.svg\" alt=\"Web Site Logo\" class=\"web-logo\" /> </a>
|
|
||||||
<div class=\"banner-header\">
|
<div class=\"banner-header\">
|
||||||
<a href=\"/\"> <img src=\"/assets/images/gr.png\" alt=\"Site Logo\" class=\"banner-logo\" /> </a>
|
<a href=\"/\"> <img src=\"/assets/images/gr.png\" alt=\"Site Logo\" class=\"banner-logo\" /> </a>
|
||||||
<nav>
|
<nav>
|
||||||
@@ -99,8 +99,7 @@
|
|||||||
<a href=\"/blogs/2026/2026-list.html \">2026 | </a>
|
<a href=\"/blogs/2026/2026-list.html \">2026 | </a>
|
||||||
<a href=\"/blogs/blogs-list.html\">Blogs | </a>
|
<a href=\"/blogs/blogs-list.html\">Blogs | </a>
|
||||||
<a href=\"/posts/career/career-list.html\">Career | </a>
|
<a href=\"/posts/career/career-list.html\">Career | </a>
|
||||||
<a href=\"/home/services.html\">Services</a>
|
<a href=\"https://zone.zainezq.com\">Dashboard</a>
|
||||||
|
|
||||||
|
|
||||||
<input type=\"search\\\" id=\"search-input\" placeholder=\"Search…\" aria-label=\"Search notes\" />
|
<input type=\"search\\\" id=\"search-input\" placeholder=\"Search…\" aria-label=\"Search notes\" />
|
||||||
<button id=\"search-btn\" aria-label=\"Search\">🔍</button>
|
<button id=\"search-btn\" aria-label=\"Search\">🔍</button>
|
||||||
@@ -215,56 +214,60 @@ A file has comments if:
|
|||||||
(add-to-list 'org-export-filter-body-functions
|
(add-to-list 'org-export-filter-body-functions
|
||||||
#'z/org-html-insert-comments-into-body)
|
#'z/org-html-insert-comments-into-body)
|
||||||
|
|
||||||
|
(defun z/lima--ensure-sitemap-file (project)
|
||||||
|
"Ensure the sitemap source file exists under the project's base directory."
|
||||||
|
(let* ((base-dir (file-name-as-directory
|
||||||
|
(org-publish-property :base-directory project)))
|
||||||
|
(fname (or (org-publish-property :sitemap-filename project)
|
||||||
|
"lima-list.org"))
|
||||||
|
(title (or (org-publish-property :sitemap-title project)
|
||||||
|
"Lima"))
|
||||||
|
(sitemap-path (expand-file-name fname base-dir)))
|
||||||
|
;; If file missing or you want to always regenerate, write header.
|
||||||
|
(unless (file-exists-p sitemap-path)
|
||||||
|
(with-temp-file sitemap-path
|
||||||
|
(insert "#+TITLE: " title "\n"
|
||||||
|
"#+OPTIONS: toc:nil num:nil\n\n")))))
|
||||||
|
|
||||||
(defun z/lima-sitemap-format-entry (entry style project)
|
(defun z/lima-sitemap-format-entry (entry style project)
|
||||||
"Format sitemap ENTRY for lima, ensuring .html links."
|
"Format sitemap entry for Lima; skip dirs, keep nested paths, and prefix /lima/."
|
||||||
(let* ((file (if (listp entry) (car entry) entry))
|
(let* ((file (if (listp entry) (car entry) entry))
|
||||||
(title (org-publish-find-title file project))
|
(base-dir (file-name-as-directory
|
||||||
(base (file-name-base file)))
|
(org-publish-property :base-directory project)))
|
||||||
|
;; Ensure we work with an absolute file path under base-dir
|
||||||
|
(abs (if (file-name-absolute-p file)
|
||||||
|
file
|
||||||
|
(expand-file-name file base-dir))))
|
||||||
|
;; Skip directories
|
||||||
|
(unless (file-directory-p abs)
|
||||||
|
(let* ((rel (file-relative-name abs base-dir)) ;; guaranteed no “…/..” backtracking now
|
||||||
|
(rel-noext (file-name-sans-extension rel))
|
||||||
|
(title (org-publish-find-title abs project)))
|
||||||
(format "[[file:%s.html][%s]]"
|
(format "[[file:%s.html][%s]]"
|
||||||
base
|
rel-noext
|
||||||
(or title base))))
|
(or title (file-name-nondirectory rel-noext)))))))
|
||||||
|
|
||||||
|
(defun z/copy-neighbor-attachments (source-dir pub-dir)
|
||||||
;; (defun z/publish-lima-file (plist filename pub-dir)
|
"Copy sibling directories named .attachments.* from SOURCE-DIR to PUB-DIR."
|
||||||
;; "Publish Org or Markdown file from lima directory."
|
(let ((dirs (directory-files source-dir t "^\\.attachments\\..+")))
|
||||||
;; (let* ((ext (file-name-extension filename))
|
(dolist (d dirs)
|
||||||
;; (base (file-name-base filename))
|
(when (file-directory-p d)
|
||||||
;; (output-file (expand-file-name
|
(let* ((target (expand-file-name (file-name-nondirectory d) pub-dir)))
|
||||||
;; (concat base ".html")
|
(make-directory target t)
|
||||||
;; pub-dir)))
|
;; copy-directory: (DIRECTORY NEWNAME &optional KEEP-TIME PARENTS COPY-CONTENTS)
|
||||||
|
(copy-directory d target t t t))))))
|
||||||
;; ;; Ensure output directory exists
|
|
||||||
;; (make-directory pub-dir t)
|
|
||||||
|
|
||||||
;; (cond
|
|
||||||
;; ;; ORG FILES
|
|
||||||
;; ((string= ext "org")
|
|
||||||
;; (org-publish-org-to 'z-html filename ".html" plist pub-dir))
|
|
||||||
|
|
||||||
;; ;; MARKDOWN FILES
|
|
||||||
;; ((string= ext "md")
|
|
||||||
;; (message "Converting %s → %s" filename output-file)
|
|
||||||
;; (let ((exit-code
|
|
||||||
;; (call-process
|
|
||||||
;; "pandoc"
|
|
||||||
;; nil
|
|
||||||
;; "*pandoc-output*"
|
|
||||||
;; t
|
|
||||||
;; filename
|
|
||||||
;; "-o"
|
|
||||||
;; output-file
|
|
||||||
;; "--standalone")))
|
|
||||||
;; (unless (eq exit-code 0)
|
|
||||||
;; (error "Pandoc failed with exit code %s" exit-code)))))))
|
|
||||||
|
|
||||||
(defun z/publish-lima-file (plist filename pub-dir)
|
(defun z/publish-lima-file (plist filename pub-dir)
|
||||||
"Publish Org or Markdown file from lima directory."
|
"Publish Org or Markdown file from lima directory."
|
||||||
(let* ((ext (file-name-extension filename))
|
(let* ((ext (downcase (or (file-name-extension filename) "")))
|
||||||
(base (file-name-base filename)))
|
(base (file-name-base filename))
|
||||||
|
(src-dir (file-name-directory filename)))
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
;; ORG FILES
|
;; ORG FILES (publish as-is)
|
||||||
((string= ext "org")
|
((string= ext "org")
|
||||||
|
;; Ensure sibling .attachments.* are published
|
||||||
|
(z/copy-neighbor-attachments src-dir pub-dir)
|
||||||
(org-publish-org-to 'z-html filename ".html" plist pub-dir))
|
(org-publish-org-to 'z-html filename ".html" plist pub-dir))
|
||||||
|
|
||||||
;; MARKDOWN FILES
|
;; MARKDOWN FILES
|
||||||
@@ -272,45 +275,52 @@ A file has comments if:
|
|||||||
(let* ((temp-org
|
(let* ((temp-org
|
||||||
(expand-file-name
|
(expand-file-name
|
||||||
(concat base ".org")
|
(concat base ".org")
|
||||||
(make-temp-file "lima-build-" t)))) ;; temp directory
|
(make-temp-file "lima-build-" t))))
|
||||||
|
|
||||||
;; Convert Markdown → Org
|
;; Convert Markdown → Org with pandoc
|
||||||
(call-process
|
(call-process "pandoc" nil nil nil
|
||||||
"pandoc"
|
filename "-f" "markdown" "-t" "org" "-o" temp-org)
|
||||||
nil nil nil
|
|
||||||
filename
|
|
||||||
"-f" "markdown"
|
|
||||||
"-t" "org"
|
|
||||||
"-o" temp-org)
|
|
||||||
|
|
||||||
;; Ensure title exists
|
;; Ensure #+TITLE exists
|
||||||
|
|
||||||
|
;; Ensure front matter at top of temp-org
|
||||||
(with-temp-buffer
|
(with-temp-buffer
|
||||||
(insert-file-contents temp-org)
|
(insert-file-contents temp-org)
|
||||||
|
|
||||||
|
;; Build values
|
||||||
|
(let* ((title base)
|
||||||
|
(slug base)
|
||||||
|
(date (format-time-string "<%Y-%m-%d %a %H:%M>")))
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(unless (re-search-forward "^#\\+TITLE:" nil t)
|
|
||||||
(goto-char (point-min))
|
;; Insert front matter
|
||||||
(insert "#+TITLE: " base "\n\n"))
|
;; (Always ensure they are at the absolute top)
|
||||||
|
(insert "#+TITLE: " title "\n"
|
||||||
|
"#+OPTIONS: num:nil\n"
|
||||||
|
"#+DATE: " date "\n"
|
||||||
|
"#+COMMENTS: t\n"
|
||||||
|
"#+SLUG: " slug "\n\n"))
|
||||||
|
|
||||||
|
;; Write back to file
|
||||||
(write-region (point-min) (point-max) temp-org))
|
(write-region (point-min) (point-max) temp-org))
|
||||||
|
|
||||||
;; Publish using ORIGINAL base name
|
;; Ensure sibling .attachments.* are published
|
||||||
(let ((output-file
|
(z/copy-neighbor-attachments src-dir pub-dir)
|
||||||
(expand-file-name
|
|
||||||
(concat base ".html")
|
|
||||||
pub-dir)))
|
|
||||||
(org-publish-org-to
|
|
||||||
'z-html
|
|
||||||
temp-org
|
|
||||||
".html"
|
|
||||||
plist
|
|
||||||
pub-dir)
|
|
||||||
|
|
||||||
;; Rename to correct base if needed
|
;; Publish using ORIGINAL base name
|
||||||
(let ((generated
|
(let ((output-file (expand-file-name (concat base ".html") pub-dir)))
|
||||||
(expand-file-name
|
(org-publish-org-to 'z-html temp-org ".html" plist pub-dir)
|
||||||
|
;; temp-org base may differ; normalize to requested base
|
||||||
|
(let ((generated (expand-file-name
|
||||||
(concat (file-name-base temp-org) ".html")
|
(concat (file-name-base temp-org) ".html")
|
||||||
pub-dir)))
|
pub-dir)))
|
||||||
(when (file-exists-p generated)
|
(when (and (file-exists-p generated)
|
||||||
(rename-file generated output-file t)))))))))
|
(not (string-equal generated output-file)))
|
||||||
|
(rename-file generated output-file t))))))
|
||||||
|
|
||||||
|
(t
|
||||||
|
;; Default: treat as attachment
|
||||||
|
(org-publish-attachment plist filename pub-dir)))))
|
||||||
|
|
||||||
|
|
||||||
(setq org-html-htmlize-output-type 'css)
|
(setq org-html-htmlize-output-type 'css)
|
||||||
@@ -496,8 +506,8 @@ A file has comments if:
|
|||||||
:html-validation-link nil
|
:html-validation-link nil
|
||||||
:html-preamble ,z-preamble
|
:html-preamble ,z-preamble
|
||||||
:html-postamble ,z-postamble
|
:html-postamble ,z-postamble
|
||||||
:auto-sitemap t
|
|
||||||
:sitemap-filename "lima-list.org"
|
:sitemap-filename "lima-list.org"
|
||||||
|
:auto-sitemap t
|
||||||
:sitemap-title "Lima"
|
:sitemap-title "Lima"
|
||||||
:sitemap-style list
|
:sitemap-style list
|
||||||
:sitemap-sort-files anti-chronologically
|
:sitemap-sort-files anti-chronologically
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
|
|
||||||
|
|
||||||
* TODO
|
* TODO
|
||||||
|
- Give lima accounts to all the services
|
||||||
|
- Figure out a solution for the shared calendar
|
||||||
|
- change the font
|
||||||
* DOING
|
* DOING
|
||||||
- Database permissions (roles, accounts and schemas)
|
- Database permissions (roles, accounts and schemas)
|
||||||
- how pipelines work
|
- how pipelines work
|
||||||
|
|||||||
@@ -6,9 +6,10 @@
|
|||||||
- [[file:../tags/emacs.org][@@html:<span class="post-tag">emacs</span>@@]] (2)
|
- [[file:../tags/emacs.org][@@html:<span class="post-tag">emacs</span>@@]] (2)
|
||||||
- [[file:../tags/insights.org][@@html:<span class="post-tag">insights</span>@@]] (4)
|
- [[file:../tags/insights.org][@@html:<span class="post-tag">insights</span>@@]] (4)
|
||||||
- [[file:../tags/introduction.org][@@html:<span class="post-tag">introduction</span>@@]] (3)
|
- [[file:../tags/introduction.org][@@html:<span class="post-tag">introduction</span>@@]] (3)
|
||||||
- [[file:../tags/learning.org][@@html:<span class="post-tag">learning</span>@@]] (13)
|
- [[file:../tags/learning.org][@@html:<span class="post-tag">learning</span>@@]] (14)
|
||||||
|
- [[file:../tags/life.org][@@html:<span class="post-tag">life</span>@@]] (4)
|
||||||
- [[file:../tags/maths.org][@@html:<span class="post-tag">maths</span>@@]] (1)
|
- [[file:../tags/maths.org][@@html:<span class="post-tag">maths</span>@@]] (1)
|
||||||
- [[file:../tags/notes.org][@@html:<span class="post-tag">notes</span>@@]] (14)
|
- [[file:../tags/notes.org][@@html:<span class="post-tag">notes</span>@@]] (15)
|
||||||
- [[file:../tags/reading.org][@@html:<span class="post-tag">reading</span>@@]] (1)
|
- [[file:../tags/reading.org][@@html:<span class="post-tag">reading</span>@@]] (1)
|
||||||
- [[file:../tags/review.org][@@html:<span class="post-tag">review</span>@@]] (18)
|
- [[file:../tags/review.org][@@html:<span class="post-tag">review</span>@@]] (20)
|
||||||
- [[file:../tags/website.org][@@html:<span class="post-tag">website</span>@@]] (2)
|
- [[file:../tags/website.org][@@html:<span class="post-tag">website</span>@@]] (2)
|
||||||
@@ -10,7 +10,7 @@ Feel free to explore:
|
|||||||
|
|
||||||
** Lima
|
** Lima
|
||||||
|
|
||||||
- [[file:lima/lima-list.org][lima's page]]
|
- [[file:lima/index.org][lima's page]]
|
||||||
|
|
||||||
** Main Pages:
|
** Main Pages:
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 402 KiB |
BIN
lima/dummy.jpg
|
Before Width: | Height: | Size: 73 KiB |
12
lima/index.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
## Welcome to the new lima page!
|
||||||
|
|
||||||
|
I made quite a few changes. It all started when I realised that not everyone knows how to use `.org` files and editing with them (they are quite niche). So I decided to make a very unique solution by having markdown files, which through a process of very complicated transformations result into the very page you’re looking at now :)
|
||||||
|
|
||||||
|
- You can edit files using this link in [nextcloud](https://nextcloud.zainezq.com/apps/files/files/18016?dir=/lima-website).
|
||||||
|
- You can pretty much use all the text editing features, minus a few unique ones like callouts.
|
||||||
|
- Inserting attachments is a cool feature, you can simply just use the *insert attachments* button, and insert the image that you want to insert.
|
||||||
|
- To insert links to other pages, you can use the insert link button and insert the URL where the page exists. For example, If I wanted to add a link to the main page it would be: <https://zainezq.com/>
|
||||||
|
- One other thing is the [server dashboard](https://zone.zainezq.com/), the purpose of this is so that whenever any changes are made here, you can just click the **Update Website** button which rebuilds the website (cool isn’t it. Had to meddle with makefiles and threads).
|
||||||
|
- I probably didn’t explain it as well, but you can create folders and files under the `lima-website` directory. The files must have a `.md` extension at the end (markdown).
|
||||||
|
|
||||||
|
- One other thing, a more personal one: what do you think of all this? am i doing too much? am i doing too little? am i overengineering things? am i forcing you to do something you dont wanna do? these little trinkets work for me, but i’m not sure if it would work for someone else, so at any point if you have reservations, let me know okay?
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
#+TITLE: Lima
|
#+TITLE: Lima
|
||||||
|
|
||||||
- [[file:linking.html][linking]]
|
- [[file:index.html][index]]
|
||||||
- [[file:test.html][test]]
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Meeting notes
|
|
||||||
|
|
||||||
* 📅 15 January 2021, via Nextcloud Talk
|
|
||||||
* 👥 Julius, Vanessa, Jan, …
|
|
||||||
|
|
||||||
## Tasks ✅
|
|
||||||
|
|
||||||
* [ ] Finish marketing campaign
|
|
||||||
* [ ] To do 2
|
|
||||||
* [ ] …
|
|
||||||
|
|
||||||
## Agenda 📑
|
|
||||||
|
|
||||||
* What we want to change
|
|
||||||
* …
|
|
||||||
|
|
||||||
## Recap from last meeting 🔁
|
|
||||||
|
|
||||||
* …
|
|
||||||
|
|
||||||
## Discussion 💬
|
|
||||||
|
|
||||||
* Vanessa suggested …
|
|
||||||
* Julius brought up …
|
|
||||||
* …
|
|
||||||
|
|
||||||
::: error
|
|
||||||
|
|
||||||
NOOOO
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||

|
|
||||||
14
lima/test.md
@@ -1,14 +0,0 @@
|
|||||||
hello
|
|
||||||
|
|
||||||
this is further testing
|
|
||||||
|
|
||||||
| Hello | | |
|
|
||||||
|-------|--|--|
|
|
||||||
| ;£7;£ | | |
|
|
||||||
| | | |
|
|
||||||
|
|
||||||
remfsdfsd
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
(format
|
(format
|
||||||
"<div class=\"filetags\">%s</div>\n"
|
"<div class=\"filetags\">%s</div>\n"
|
||||||
(mapconcat (lambda (tag)
|
(mapconcat (lambda (tag)
|
||||||
(format "<a href=\"/categories.html\"> <span class=\"post-tag\">%s</span> </a>" tag))
|
(format "<a href=\"/home/categories.html\"> <span class=\"post-tag\">%s</span> </a>" tag))
|
||||||
tags " ")))))
|
tags " ")))))
|
||||||
|
|
||||||
(defun z/insert-filetags-after-title (output backend info)
|
(defun z/insert-filetags-after-title (output backend info)
|
||||||
|
|||||||
1460
org-web-build.log
@@ -5,10 +5,13 @@ See the categories: @@html:<a href="../../home/categories.html">Categories</a>@@
|
|||||||
|
|
||||||
See the following page for more details: @@html:<a href="./career-intro.html">Career Intro</a>@@
|
See the following page for more details: @@html:<a href="./career-intro.html">Career Intro</a>@@
|
||||||
|
|
||||||
|
** February 2026
|
||||||
|
- [[file:restful-api.org][Restful API]] @@html:<span class="post-date">15-02-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
|
|
||||||
** January 2026
|
** January 2026
|
||||||
- [[file:database-permissions.org][Database permissions, roles and accounts]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:database-permissions.org][Database Permissions, Roles, and Accounts]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
- [[file:monitoring-and-logging.org][Monitoring and Logging]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:monitoring-and-logging.org][Monitoring and Logging]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
- [[file:pipelines.org][Pipelines and how they work]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:pipelines.org][Pipelines and how they work (as well as CI/CD)]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
|
|
||||||
** December 2025
|
** December 2025
|
||||||
- [[file:probation-objectives.org][Probation Objectives:]] @@html:<span class="post-date">08-12-2025 17:55</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:probation-objectives.org][Probation Objectives:]] @@html:<span class="post-date">08-12-2025 17:55</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
|
|||||||
@@ -1,9 +1,245 @@
|
|||||||
#+TITLE: Database permissions, roles and accounts
|
#+TITLE: Database Permissions, Roles, and Accounts
|
||||||
#+OPTIONS: num:nil
|
#+OPTIONS: num:nil
|
||||||
#+DATE: <2026-01-18 Sun 23:00>
|
#+DATE: <2026-01-18 Sun 23:00>
|
||||||
#+filetags: :learning:notes:
|
#+filetags: :learning:notes:
|
||||||
#+WIP: t
|
#+WIP:
|
||||||
#+COMMENTS: t
|
#+COMMENTS: t
|
||||||
#+SLUG: database-permissions
|
#+SLUG: database-permissions
|
||||||
|
|
||||||
* TODO
|
* Introduction
|
||||||
|
Database security is a crucial part of database administration. It ensures that only authorised users can access, modify, or manage data. Three core concepts used to control access are:
|
||||||
|
|
||||||
|
1. Accounts (logins/users)
|
||||||
|
2. Roles
|
||||||
|
3. Permissions
|
||||||
|
|
||||||
|
These concepts work together to create structured and secure access control inside a database system.
|
||||||
|
|
||||||
|
* 1. Database Accounts
|
||||||
|
|
||||||
|
A *database account* represents an identity that can connect to the database system. In Microsoft SQL Server this is typically split into two layers:
|
||||||
|
|
||||||
|
- *Login* → Authentication at the server level
|
||||||
|
- *User* → Authorisation inside a specific database
|
||||||
|
|
||||||
|
** Login (Server Level)
|
||||||
|
|
||||||
|
A login allows someone or something to authenticate with the SQL Server instance.
|
||||||
|
|
||||||
|
Example: Creating a login
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
CREATE LOGIN student_user
|
||||||
|
WITH PASSWORD = 'StrongPassword123!';
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
You can also create a login linked to Windows authentication.
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
CREATE LOGIN [DOMAIN\Zaine] FROM WINDOWS;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Database User
|
||||||
|
|
||||||
|
A login must be mapped to a user inside a database before it can access that database.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
USE SchoolDB;
|
||||||
|
|
||||||
|
CREATE USER student_user
|
||||||
|
FOR LOGIN student_user;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Now the login can access the *SchoolDB* database as the user *student_user*.
|
||||||
|
|
||||||
|
* 2. Permissions
|
||||||
|
|
||||||
|
Permissions define *what actions a user can perform*. These actions include reading data, inserting rows, modifying tables, or executing procedures.
|
||||||
|
|
||||||
|
Common SQL Server permissions include:
|
||||||
|
|
||||||
|
- SELECT → Read data
|
||||||
|
- INSERT → Add new data
|
||||||
|
- UPDATE → Modify data
|
||||||
|
- DELETE → Remove data
|
||||||
|
- EXECUTE → Run stored procedures
|
||||||
|
- ALTER → Modify database objects
|
||||||
|
- CONTROL → Full control over an object
|
||||||
|
|
||||||
|
** Granting Permissions
|
||||||
|
|
||||||
|
Permissions are given using the *GRANT* statement.
|
||||||
|
|
||||||
|
Example: Allow a user to read data from a table.
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
GRANT SELECT
|
||||||
|
ON Students
|
||||||
|
TO student_user;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Grant Multiple Permissions
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
GRANT SELECT, INSERT
|
||||||
|
ON Students
|
||||||
|
TO student_user;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
This allows the user to read and add new rows.
|
||||||
|
|
||||||
|
** Revoking Permissions
|
||||||
|
|
||||||
|
If a permission should be removed:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
REVOKE INSERT
|
||||||
|
ON Students
|
||||||
|
FROM student_user;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Denying Permissions
|
||||||
|
|
||||||
|
A *DENY* explicitly blocks an action, even if another role grants it.
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
DENY DELETE
|
||||||
|
ON Students
|
||||||
|
TO student_user;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
* 3. Roles
|
||||||
|
|
||||||
|
Roles are collections of permissions that can be assigned to multiple users. They simplify permission management by allowing administrators to assign permissions once and reuse them.
|
||||||
|
|
||||||
|
Instead of granting permissions to many individual users, you grant them to a role.
|
||||||
|
|
||||||
|
Example scenario:
|
||||||
|
|
||||||
|
- Many students should be able to view course data.
|
||||||
|
- Instead of assigning permissions to each student individually, create a role.
|
||||||
|
|
||||||
|
** Creating a Role
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
CREATE ROLE student_role;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Assign Permissions to the Role
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
GRANT SELECT
|
||||||
|
ON Courses
|
||||||
|
TO student_role;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Add Users to the Role
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
ALTER ROLE student_role
|
||||||
|
ADD MEMBER student_user;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Now *student_user* inherits all permissions from *student_role*.
|
||||||
|
|
||||||
|
* 4. Built-in Database Roles
|
||||||
|
|
||||||
|
SQL Server includes several predefined roles that already have common permission sets.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
| Role Name | Purpose |
|
||||||
|
|---------------+-----------------------------------|
|
||||||
|
| db_owner | Full control over the database |
|
||||||
|
| db_datareader | Read all tables |
|
||||||
|
| db_datawriter | Insert/update/delete all tables |
|
||||||
|
| db_ddladmin | Create or modify database objects |
|
||||||
|
|
||||||
|
Example: Add a user to the read-only role.
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
ALTER ROLE db_datareader
|
||||||
|
ADD MEMBER student_user;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
This allows the user to read all tables without giving modification rights.
|
||||||
|
|
||||||
|
* 5. Example: Simple University Database Security
|
||||||
|
|
||||||
|
Assume a database called *UniversityDB* with two tables:
|
||||||
|
|
||||||
|
- Students
|
||||||
|
- Courses
|
||||||
|
|
||||||
|
Goal:
|
||||||
|
|
||||||
|
- Students → Read course information
|
||||||
|
- Teachers → Modify course data
|
||||||
|
- Admin → Full control
|
||||||
|
|
||||||
|
** Step 1: Create Roles
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
CREATE ROLE student_role;
|
||||||
|
CREATE ROLE teacher_role;
|
||||||
|
CREATE ROLE admin_role;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Step 2: Assign Permissions
|
||||||
|
|
||||||
|
Student role (read-only):
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
GRANT SELECT
|
||||||
|
ON Courses
|
||||||
|
TO student_role;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Teacher role:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
GRANT SELECT, INSERT, UPDATE
|
||||||
|
ON Courses
|
||||||
|
TO teacher_role;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Admin role:
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
GRANT CONTROL
|
||||||
|
ON DATABASE::UniversityDB
|
||||||
|
TO admin_role;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
** Step 3: Add Users
|
||||||
|
|
||||||
|
#+BEGIN_SRC sql
|
||||||
|
ALTER ROLE student_role ADD MEMBER student_user;
|
||||||
|
ALTER ROLE teacher_role ADD MEMBER teacher_user;
|
||||||
|
ALTER ROLE admin_role ADD MEMBER admin_user;
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Now permissions are organised through roles instead of assigning them individually.
|
||||||
|
|
||||||
|
* 6. Why Roles Are Important
|
||||||
|
|
||||||
|
Roles provide several benefits:
|
||||||
|
|
||||||
|
- *Simpler management* → Change permissions in one place
|
||||||
|
- *Scalability* → Works well with many users
|
||||||
|
- *Security consistency* → Reduces risk of incorrect permissions
|
||||||
|
- *Easier auditing* → Clear structure of access control
|
||||||
|
|
||||||
|
Without roles, administrators would need to manually manage permissions for every individual user.
|
||||||
|
|
||||||
|
* Summary
|
||||||
|
|
||||||
|
Database access control relies on three key components:
|
||||||
|
|
||||||
|
- *Accounts* identify who is accessing the system (logins and users).
|
||||||
|
- *Permissions* define what actions can be performed.
|
||||||
|
- *Roles* group permissions together for easier management.
|
||||||
|
|
||||||
|
In Microsoft SQL Server, administrators typically create logins, map them to database users, assign them to roles, and grant permissions to those roles. This layered approach ensures a secure and manageable database system.
|
||||||
|
|||||||
@@ -2,14 +2,118 @@
|
|||||||
#+OPTIONS: num:nil
|
#+OPTIONS: num:nil
|
||||||
#+DATE: <2026-01-18 Sun 23:00>
|
#+DATE: <2026-01-18 Sun 23:00>
|
||||||
#+filetags: :learning:notes:
|
#+filetags: :learning:notes:
|
||||||
#+WIP: t
|
#+WIP:
|
||||||
#+COMMENTS: t
|
#+COMMENTS: t
|
||||||
#+SLUG: monitoring-and-logging
|
#+SLUG: monitoring-and-logging
|
||||||
|
|
||||||
* TODO
|
* Monitoring and Logging Tools Overview
|
||||||
|
|
||||||
Talk about Kibana, Grafana, Prometheus, and others.
|
Modern systems, especially cloud and distributed applications, require tools to observe performance, detect issues, and analyse logs. Tools like Kibana, Grafana, and Prometheus are widely used for these purposes.
|
||||||
- [ ] Research popular monitoring and logging tools
|
|
||||||
- [ ] Write about their features and use cases
|
* Kibana
|
||||||
- [ ] Include examples of how to set them up
|
** Purpose
|
||||||
- [ ] Discuss best practices for monitoring and logging
|
Log visualisation and analysis.
|
||||||
|
|
||||||
|
** How it works
|
||||||
|
Kibana is part of the Elastic Stack (formerly ELK Stack) and is used to visualise data stored in Elasticsearch.
|
||||||
|
|
||||||
|
** Key Features
|
||||||
|
- Search and analyse large log datasets
|
||||||
|
- Interactive dashboards
|
||||||
|
- Log filtering and querying
|
||||||
|
- Security and anomaly detection features
|
||||||
|
|
||||||
|
** Common Use Cases
|
||||||
|
- Viewing application logs
|
||||||
|
- Debugging errors in production systems
|
||||||
|
- Security monitoring
|
||||||
|
|
||||||
|
** Example Setup
|
||||||
|
1. Install Elasticsearch
|
||||||
|
2. Send logs using Logstash or Filebeat
|
||||||
|
3. Use Kibana to visualise logs
|
||||||
|
|
||||||
|
* Prometheus
|
||||||
|
** Purpose
|
||||||
|
Metrics collection and monitoring.
|
||||||
|
|
||||||
|
Prometheus is designed to collect numeric metrics over time from systems and applications.
|
||||||
|
|
||||||
|
** Key Features
|
||||||
|
- Time-series database
|
||||||
|
- Powerful query language (PromQL)
|
||||||
|
- Built-in alerting
|
||||||
|
- Pull-based metrics collection
|
||||||
|
|
||||||
|
** Common Use Cases
|
||||||
|
- Monitoring servers and containers
|
||||||
|
- Tracking CPU, memory, and request latency
|
||||||
|
- Infrastructure monitoring in Kubernetes
|
||||||
|
|
||||||
|
** Example Setup
|
||||||
|
1. Install Prometheus
|
||||||
|
2. Configure targets to scrape metrics
|
||||||
|
3. Expose metrics via a /metrics endpoint
|
||||||
|
4. Query metrics using PromQL
|
||||||
|
|
||||||
|
* Grafana
|
||||||
|
** Purpose
|
||||||
|
Visualisation and dashboards.
|
||||||
|
|
||||||
|
Grafana is commonly used with Prometheus but can connect to many different data sources.
|
||||||
|
|
||||||
|
** Key Features
|
||||||
|
- Highly customisable dashboards
|
||||||
|
- Supports many data sources (Prometheus, Elasticsearch, databases)
|
||||||
|
- Alerting and notifications
|
||||||
|
- Real-time visual monitoring
|
||||||
|
|
||||||
|
** Common Use Cases
|
||||||
|
- Infrastructure monitoring dashboards
|
||||||
|
- Business metrics visualisation
|
||||||
|
- Combining logs, metrics, and traces
|
||||||
|
|
||||||
|
** Example Setup
|
||||||
|
1. Install Grafana
|
||||||
|
2. Connect a data source (Prometheus, Elasticsearch, etc.)
|
||||||
|
3. Build dashboards using panels and queries
|
||||||
|
|
||||||
|
* Other Popular Tools
|
||||||
|
|
||||||
|
** Logstash
|
||||||
|
- Log processing pipeline
|
||||||
|
- Collects, transforms, and sends logs to Elasticsearch
|
||||||
|
|
||||||
|
** Filebeat
|
||||||
|
- Lightweight log shipper
|
||||||
|
- Sends logs from servers to Elasticsearch
|
||||||
|
|
||||||
|
** Loki
|
||||||
|
- Log aggregation system designed by Grafana Labs
|
||||||
|
- Integrates well with Grafana dashboards
|
||||||
|
|
||||||
|
* Best Practices for Monitoring and Logging
|
||||||
|
|
||||||
|
** Monitor Key Metrics
|
||||||
|
- CPU usage
|
||||||
|
- Memory usage
|
||||||
|
- Request latency
|
||||||
|
- Error rates
|
||||||
|
|
||||||
|
** Centralise Logs
|
||||||
|
Send logs from all services to a single platform.
|
||||||
|
|
||||||
|
** Use Alerts
|
||||||
|
Configure alerts to notify you of abnormal behavior.
|
||||||
|
|
||||||
|
** Combine Logs and Metrics
|
||||||
|
- Metrics tell you that something is wrong
|
||||||
|
- Logs help you understand why it is wrong
|
||||||
|
|
||||||
|
** Create Meaningful Dashboards
|
||||||
|
Focus on actionable information instead of displaying excessive data.
|
||||||
|
|
||||||
|
* Simple Summary
|
||||||
|
- Prometheus collects metrics
|
||||||
|
- Grafana visualises metrics
|
||||||
|
- Kibana analyses logs
|
||||||
|
|||||||
@@ -1,9 +1,666 @@
|
|||||||
#+TITLE: Pipelines and how they work
|
#+TITLE: Pipelines and how they work (as well as CI/CD)
|
||||||
#+OPTIONS: num:nil
|
#+OPTIONS: num:nil
|
||||||
#+DATE: <2026-01-18 Sun 23:00>
|
#+DATE: <2026-01-18 Sun 23:00>
|
||||||
#+filetags: :learning:notes:
|
#+filetags: :learning:notes:
|
||||||
#+WIP: t
|
#+WIP:
|
||||||
#+COMMENTS: t
|
#+COMMENTS: t
|
||||||
#+SLUG: pipelines
|
#+SLUG: pipelines-learning
|
||||||
|
|
||||||
|
|
||||||
|
* Summary
|
||||||
|
CI/CD stands for Continuous Integration and Continuous Delivery/Deployment. It’s a development practice that automates building, testing, and delivering software so code changes can be released quickly and reliably.
|
||||||
|
|
||||||
|
** Continuous Integration (CI)
|
||||||
|
|
||||||
|
CI means developers frequently merge their code into a shared repository. Every time code is pushed:
|
||||||
|
|
||||||
|
1. The code is built automatically.
|
||||||
|
2. Automated tests run.
|
||||||
|
3. If something breaks, the team is alerted.
|
||||||
|
|
||||||
|
Goal: catch bugs early and ensure new code works with the rest of the project.
|
||||||
|
|
||||||
|
** Continuous Delivery / Continuous Deployment (CD)
|
||||||
|
CD takes the tested code from CI and prepares it for release.
|
||||||
|
|
||||||
|
- Continuous Delivery: Code is automatically prepared for production, but a human approves the final deployment.
|
||||||
|
|
||||||
|
- Continuous Deployment: Code is automatically deployed to production with no manual approval.
|
||||||
|
|
||||||
|
Goal: make releases faster and safer.
|
||||||
|
|
||||||
|
** Pipelines
|
||||||
|
A pipeline is the automated workflow that runs these steps in sequence. Think of it as a script that defines what happens after a code change.
|
||||||
|
|
||||||
|
Typical pipeline stages:
|
||||||
|
|
||||||
|
1. Source – code pushed to repository
|
||||||
|
2. Build – compile the application
|
||||||
|
3. Test – run automated tests
|
||||||
|
4. Package – create deployable artifact (e.g., Docker image)
|
||||||
|
5. Deploy – release to staging or production
|
||||||
|
|
||||||
|
Example simplified pipeline:
|
||||||
|
|
||||||
|
~Code Push → Build → Test → Package → Deploy~
|
||||||
|
|
||||||
|
Why CI/CD is useful
|
||||||
|
|
||||||
|
- Faster development cycles
|
||||||
|
|
||||||
|
- Fewer integration bugs
|
||||||
|
|
||||||
|
- Automated testing and deployment
|
||||||
|
|
||||||
|
- More reliable releases
|
||||||
|
|
||||||
|
Common CI/CD tools
|
||||||
|
|
||||||
|
- GitHub Actions
|
||||||
|
|
||||||
|
- Jenkins
|
||||||
|
|
||||||
|
- GitLab CI/CD
|
||||||
|
|
||||||
|
- CircleCI
|
||||||
|
|
||||||
|
In short:
|
||||||
|
CI/CD uses pipelines to automatically build, test, and deploy software whenever code changes are made.
|
||||||
|
|
||||||
|
|
||||||
|
* Learning by example
|
||||||
|
|
||||||
|
During the first wave in 2026, we planned to get the netcore version of site visits out to customers. There were a bunch of tasks relating to this, so I asked AI to conceptually explain them.
|
||||||
|
|
||||||
|
* Prompt:
|
||||||
|
|
||||||
|
I want to understand builds and pipelines in more depth. we have a set of tasks to get a new upgraded project to customers. this is task 1:
|
||||||
|
|
||||||
|
Add the .net core version to the TMC release pipeline.
|
||||||
|
Follow this guide so that the build artifacts are included in the TMC release
|
||||||
|
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Documents?path=/TMC/Deployment/AddingANewProjectToTMC.md&_a=preview
|
||||||
|
|
||||||
|
(This will add the artifact to the release, you will then need to test this locally, see the other task)
|
||||||
|
|
||||||
|
After that, we need to make the below changes as we did for the DriverWebAPI:
|
||||||
|
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/TMC_Release/pullrequest/23129?path=/ReleasePackagesConfig.csv&_a=files
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment/pullrequest/23154?_a=files
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/TMCBranchTool/pullrequest/23766?_a=files
|
||||||
|
|
||||||
|
this is task 2:
|
||||||
|
Add application file and make deployable locally
|
||||||
|
See this PR from when we previously did on Drivers: https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/23188?path=/manifests/customers/dev/LocalDeploy/DEV/_apps.yml
|
||||||
|
|
||||||
|
Note: That some of the properties in the files are different to what you have for a local deploy, if in doubt refer to main to ensure that we have no consistencies.
|
||||||
|
|
||||||
|
Also, we don't need to alter the connection string as this has already been done.
|
||||||
|
|
||||||
|
====
|
||||||
|
|
||||||
|
This requires the previous tasks to be completed (main build and artifact added to release)
|
||||||
|
|
||||||
|
Follow this commit as an example
|
||||||
|
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/commit/aeb2dbf1bbcef1b672aee05fdc7988959afd1a36?refName=refs/heads/main
|
||||||
|
|
||||||
|
Create a new application file for the dotnet core version of the service, swap it out in the manifests for the local deploy along with any relevant configuration
|
||||||
|
|
||||||
|
There may be some differences due to this being a web api rather than a background service, and the fact that we use the appsettings.json rather than the app.config - in which case look to Arrivals and departures and vehiclev2 if that is still around
|
||||||
|
|
||||||
|
Set up local TMC and deploy - make sure it works as expected
|
||||||
|
|
||||||
|
This is now possible on the new domain joined machines with a VM - did it myself and it works well
|
||||||
|
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Documents?path=/TMC/Deployment/Local%20Deployment%20and%20running%20ATFs%20on%20non-domain%20joined%20machines.md&_a=preview
|
||||||
|
|
||||||
|
this is 3:
|
||||||
|
Make deployable in QA (Toblerone)
|
||||||
|
Check out this commit for the AVL where the new service was added to the templates and the deploy file, use what was learned from the local deploy to ensure this works in the same way
|
||||||
|
|
||||||
|
Check if you can just apply this to the toblerone box, the deploy_all.yml file governs what is actually deployed, this might not be possible but worth a check
|
||||||
|
|
||||||
|
Test that Toblerone deploys okay
|
||||||
|
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/commit/59db355dbb80c784d7b7ca9f3bb30fc00ef1d13e?refName=refs/heads/main&path=/manifests
|
||||||
|
|
||||||
|
See this PR for how we did it last time for the Driver Web API: https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/23320
|
||||||
|
|
||||||
|
This needs to be changed for the current release, potentially the previous release if it errors when that happens as well as the ad hoc. See the last three files in the above PR.
|
||||||
|
|
||||||
|
task 4:
|
||||||
|
Add artifact to the ad-hoc pipelines for QA / Cert
|
||||||
|
Need to complete the previous Toblerone QA task first!
|
||||||
|
|
||||||
|
We need to add a similar artifact for SiteVisits to the ad hoc QA / Cert release pipeline like so:
|
||||||
|
|
||||||
|
Image
|
||||||
|
|
||||||
|
And then give it a run and make sure it works.
|
||||||
|
|
||||||
|
See the release pipeline here: TMC.SiteVisitsWebApi - Pipelines
|
||||||
|
|
||||||
|
task 5:
|
||||||
|
Ensure that you test each endpoint with different data, ensuring the experience is exactly the same for each endpoint (auth, request / response)
|
||||||
|
|
||||||
|
As we are planning to hotswap the instances over, they must work exactly the same
|
||||||
|
|
||||||
|
Make sure its on the same URL
|
||||||
|
|
||||||
|
task 6:
|
||||||
|
Make deployable in the rest of QA
|
||||||
|
We have this running in Toblerone QA, once we are happy with the API in Toblerone we need to roll it out to the rest of QA.
|
||||||
|
|
||||||
|
Aaron also suggested considering doing the internal CERT environments at this stage, then we have a more live like environment tested early on too.
|
||||||
|
|
||||||
|
See this PR for how we did this for the Driver Web API: https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/24329?path=/manifests/TemplateFiles/26.1/QA/deploy_tmc.yml
|
||||||
|
|
||||||
|
task 7:
|
||||||
|
Ensure that the new Serilog logs are captured into elastic
|
||||||
|
This file needs updating with the paths for the serilogs in the sitevisitswebapi
|
||||||
|
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/ELK-Beats?path=/inventories/uat_web_servers/templates/filebeat~planBstructuredLogs.yml
|
||||||
|
|
||||||
|
However it does not look like servicename and customername parsing is working for the existing logs
|
||||||
|
|
||||||
|
Effectively, add a line like this but for our SiteVisits API:
|
||||||
|
|
||||||
|
Image
|
||||||
|
|
||||||
|
task 8:
|
||||||
|
Make deployable in UAT
|
||||||
|
Update UAT to use the new dotnet core version of the API, use what was learned from the local deploy to ensure this works in the same way
|
||||||
|
|
||||||
|
Use this commit for reference
|
||||||
|
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/commit/2fce44462b699b88e4c2597c8492a1a0dad1614d?refName=refs/heads/main
|
||||||
|
|
||||||
|
See this PR for what we did last time for UAT (incorporates other environments): https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/25631?path=/manifests/TemplateFiles/26.2/UAT/deploy_all_zero_predeploy.yml
|
||||||
|
|
||||||
|
task 9:
|
||||||
|
Make deployable in live
|
||||||
|
Update live to use the new dotnet core version of the API, use what was learned from the local deploy to ensure this works in the same way
|
||||||
|
|
||||||
|
Use this commit for reference
|
||||||
|
|
||||||
|
https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/commit/ce61205a1f53649e7b1313fb78eb72225d99503d?refName=refs/heads/main&path=/manifests/customers/prod/CEVA_BAXTER/LIVE/_customer.yml
|
||||||
|
|
||||||
|
See this PR for what we did last time for live (incorporates other environments): https://azdo.microlise.com/MicroliseCollection/Microlise/_git/Deployment.Manifests.MFD/pullrequest/25631?path=/manifests/TemplateFiles/26.2/UAT/deploy_all_zero_predeploy.yml
|
||||||
|
|
||||||
|
|
||||||
|
* Response
|
||||||
|
|
||||||
|
You’re essentially looking at a **full CI/CD path** for introducing a **new version of a service (.NET Core API)** into a large enterprise deployment system. The tasks look complicated because they touch **multiple layers of the delivery pipeline**, not just code.
|
||||||
|
|
||||||
|
I'll explain this in a **mental model first**, then walk through **what each task is really doing in the pipeline**.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
** 1. The Big Picture: What a Build & Release Pipeline Is
|
||||||
|
|
||||||
|
In enterprise systems like Azure DevOps, deployment is usually split into two major stages.
|
||||||
|
|
||||||
|
1. Build Pipeline (CI)
|
||||||
|
|
||||||
|
Purpose: **Turn source code into deployable artifacts**
|
||||||
|
|
||||||
|
Steps typically include:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
Code → Restore packages → Compile → Run tests → Package → Publish artifact
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Output = **artifact**
|
||||||
|
|
||||||
|
Example artifact:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
SiteVisitsWebApi.zip
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
This artifact contains:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
dlls
|
||||||
|
configs
|
||||||
|
dependencies
|
||||||
|
startup files
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Think of an **artifact** as a **versioned package of your application**.
|
||||||
|
|
||||||
|
|
||||||
|
2. Release Pipeline (CD)
|
||||||
|
|
||||||
|
Purpose: **Take the artifact and deploy it to environments**
|
||||||
|
|
||||||
|
Example environments:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
Local
|
||||||
|
QA
|
||||||
|
CERT
|
||||||
|
UAT
|
||||||
|
LIVE
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Each environment might have:
|
||||||
|
- different configs
|
||||||
|
- different servers
|
||||||
|
- different manifests
|
||||||
|
|
||||||
|
|
||||||
|
*Your System Specifically*
|
||||||
|
|
||||||
|
You are working with something like:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
|
||||||
|
|
||||||
|
Git Repo
|
||||||
|
↓
|
||||||
|
Build Pipeline
|
||||||
|
↓
|
||||||
|
Artifacts
|
||||||
|
↓
|
||||||
|
TMC Release Pipeline
|
||||||
|
↓
|
||||||
|
Deployment Manifests
|
||||||
|
↓
|
||||||
|
Servers
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
** 2. Why This Task Exists
|
||||||
|
|
||||||
|
You are **introducing a new .NET Core version of an API**.
|
||||||
|
|
||||||
|
Previously there was likely:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
SiteVisitsWebApi (.NET Framework)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Now:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
SiteVisitsWebApi (.NET Core)
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
So you must:
|
||||||
|
|
||||||
|
1. Build it
|
||||||
|
2. Package it
|
||||||
|
3. Add it to release pipeline
|
||||||
|
4. Update deployment configs
|
||||||
|
5. Deploy to environments gradually
|
||||||
|
|
||||||
|
|
||||||
|
** 3. What Each Task Actually Means
|
||||||
|
|
||||||
|
I'll translate the tasks into **plain engineering intent**.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*** Task 1: Add .NET Core Version to Build + Release
|
||||||
|
|
||||||
|
What is happening?
|
||||||
|
|
||||||
|
You add the **new project to the build pipeline** so it produces an artifact.
|
||||||
|
|
||||||
|
Before:
|
||||||
|
|
||||||
|
~Build → DriverWebAPI artifact~
|
||||||
|
|
||||||
|
After:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
|
||||||
|
Build → DriverWebAPI artifact
|
||||||
|
→ SiteVisitsWebApi artifact
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
Why the PRs exist
|
||||||
|
|
||||||
|
These repositories control deployment:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
TMC_Release
|
||||||
|
Deployment
|
||||||
|
TMCBranchTool
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
They likely manage:
|
||||||
|
|
||||||
|
| Repo | Purpose |
|
||||||
|
| ------------- | ------------------------- |
|
||||||
|
| TMC_Release | release packaging |
|
||||||
|
| Deployment | deployment scripts |
|
||||||
|
| TMCBranchTool | release branch automation |
|
||||||
|
|
||||||
|
|
||||||
|
What ReleasePackagesConfig.csv probably does
|
||||||
|
|
||||||
|
Something like:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
|
||||||
|
ServiceName,ArtifactName,DeploymentType
|
||||||
|
DriverWebApi,DriverWebApi.zip,WebApi
|
||||||
|
SiteVisitsWebApi,SiteVisitsWebApi.zip,WebApi
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
So the pipeline knows:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
Include this artifact in the release bundle
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
Result of Task 1
|
||||||
|
|
||||||
|
Your pipeline will now produce:
|
||||||
|
|
||||||
|
Artifacts:
|
||||||
|
|
||||||
|
~DriverWebApi~
|
||||||
|
|
||||||
|
~SiteVisitsWebApi~
|
||||||
|
|
||||||
|
|
||||||
|
And release pipeline can access them.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*** Task 2: Make Deployable Locally
|
||||||
|
|
||||||
|
Now you test deployment **without affecting real environments**.
|
||||||
|
|
||||||
|
This uses **deployment manifests**.
|
||||||
|
|
||||||
|
|
||||||
|
What a manifest is
|
||||||
|
|
||||||
|
A manifest is basically a **deployment recipe**.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
#+begin_src yaml
|
||||||
|
|
||||||
|
apps:
|
||||||
|
- name: sitevisitswebapi
|
||||||
|
artifact: SiteVisitsWebApi
|
||||||
|
port: 5000
|
||||||
|
config: appsettings.json
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
It tells the deployment system:
|
||||||
|
|
||||||
|
deploy this artifact
|
||||||
|
with these configs
|
||||||
|
to this environment
|
||||||
|
|
||||||
|
|
||||||
|
What you do here
|
||||||
|
|
||||||
|
Create a new **application definition**.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
~_apps.yml~
|
||||||
|
|
||||||
|
Add:
|
||||||
|
|
||||||
|
~sitevisitswebapi~
|
||||||
|
|
||||||
|
Then configure:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
artifact source
|
||||||
|
ports
|
||||||
|
configs
|
||||||
|
environment variables
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
Why they mention differences
|
||||||
|
|
||||||
|
Your service is:
|
||||||
|
|
||||||
|
~Web API~
|
||||||
|
|
||||||
|
instead of
|
||||||
|
|
||||||
|
~Background Windows Service~
|
||||||
|
|
||||||
|
So deployment might differ:
|
||||||
|
|
||||||
|
| Background service | Web API |
|
||||||
|
| ------------------ | ----------------------- |
|
||||||
|
| runs as service | hosted in IIS / kestrel |
|
||||||
|
| app.config | appsettings.json |
|
||||||
|
|
||||||
|
Result of Task 2
|
||||||
|
|
||||||
|
You can now run:
|
||||||
|
|
||||||
|
local TMC deployment
|
||||||
|
|
||||||
|
and your API launches locally.
|
||||||
|
|
||||||
|
*** Task 3: Deploy to QA (Toblerone)
|
||||||
|
|
||||||
|
Now you move from:
|
||||||
|
|
||||||
|
Local → QA
|
||||||
|
|
||||||
|
"Toblerone" appears to be a **specific QA environment/server**.
|
||||||
|
|
||||||
|
|
||||||
|
You update manifests like:
|
||||||
|
|
||||||
|
deploy_all.yml
|
||||||
|
|
||||||
|
Which probably contains:
|
||||||
|
|
||||||
|
#+begin_src yaml
|
||||||
|
|
||||||
|
|
||||||
|
apps:
|
||||||
|
- driverwebapi
|
||||||
|
- sitevisitswebapi
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
So the deployment engine knows:
|
||||||
|
|
||||||
|
deploy this service in QA
|
||||||
|
|
||||||
|
|
||||||
|
Then test deployment.
|
||||||
|
|
||||||
|
|
||||||
|
*** Task 4: Add to Ad-hoc QA / Cert Pipelines
|
||||||
|
|
||||||
|
These are **manual release pipelines**.
|
||||||
|
|
||||||
|
Example use:
|
||||||
|
|
||||||
|
~Dev: deploy specific service to QA quickly~
|
||||||
|
|
||||||
|
|
||||||
|
Instead of full release.
|
||||||
|
|
||||||
|
You add the artifact there so people can manually deploy it.
|
||||||
|
|
||||||
|
|
||||||
|
*** Task 5: Endpoint Testing
|
||||||
|
|
||||||
|
Critical step.
|
||||||
|
|
||||||
|
You must confirm the new API behaves **exactly like the old one**.
|
||||||
|
|
||||||
|
Because they plan a **hotswap**.
|
||||||
|
|
||||||
|
Meaning:
|
||||||
|
|
||||||
|
Old API → replace with new API
|
||||||
|
same URL
|
||||||
|
same behaviour
|
||||||
|
|
||||||
|
If anything changes, clients break
|
||||||
|
|
||||||
|
So test:
|
||||||
|
|
||||||
|
Auth
|
||||||
|
Request formats
|
||||||
|
Response formats
|
||||||
|
Error codes
|
||||||
|
|
||||||
|
|
||||||
|
*** Task 6: Deploy to Remaining QA
|
||||||
|
|
||||||
|
Once Toblerone works:
|
||||||
|
|
||||||
|
Toblerone QA → All QA environments
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
QA1
|
||||||
|
QA2
|
||||||
|
QA3
|
||||||
|
|
||||||
|
Maybe also:
|
||||||
|
|
||||||
|
Internal CERT
|
||||||
|
|
||||||
|
|
||||||
|
*** Task 7: Logging (Serilog → Elastic)
|
||||||
|
|
||||||
|
The new API logs differently.
|
||||||
|
|
||||||
|
Probably something like:
|
||||||
|
|
||||||
|
~logs/sitevisitswebapi/*.log~
|
||||||
|
|
||||||
|
|
||||||
|
Filebeat must be told to collect them.
|
||||||
|
|
||||||
|
Example config:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
- type: log
|
||||||
|
paths:
|
||||||
|
- /logs/sitevisitswebapi/*.log
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Then logs go:
|
||||||
|
|
||||||
|
~Server → Filebeat → Elasticsearch → Kibana~
|
||||||
|
|
||||||
|
|
||||||
|
*** Task 8: Deploy to UAT
|
||||||
|
|
||||||
|
UAT = staging environment.
|
||||||
|
|
||||||
|
Production-like testing
|
||||||
|
|
||||||
|
Here you update the deployment manifests to use the **new API**.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*** Task 9: Deploy to Live
|
||||||
|
|
||||||
|
Final production rollout.
|
||||||
|
|
||||||
|
Same process:
|
||||||
|
|
||||||
|
manifest updates
|
||||||
|
deploy pipeline
|
||||||
|
verification
|
||||||
|
|
||||||
|
|
||||||
|
** 4. The Entire Flow (Visual)
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
|
||||||
|
|
||||||
|
Code (SiteVisitsWebApi)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Build Pipeline
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Artifact Produced
|
||||||
|
(SiteVisitsWebApi.zip)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
TMC Release Pipeline
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Deployment Manifests
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
Local Deploy
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
QA (Toblerone)
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
All QA
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
UAT
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
LIVE
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
** 5. Why Enterprise Pipelines Feel Complicated
|
||||||
|
|
||||||
|
Because deployment is separated into **many independent systems**:
|
||||||
|
|
||||||
|
| Layer | Responsibility |
|
||||||
|
| ------------------ | ----------------------- |
|
||||||
|
| Build pipeline | compile code |
|
||||||
|
| Artifact storage | store packages |
|
||||||
|
| Release pipeline | orchestrate deployments |
|
||||||
|
| Manifests | describe environments |
|
||||||
|
| Deployment scripts | actually install |
|
||||||
|
| Logging | monitor |
|
||||||
|
|
||||||
|
Each lives in **different repos**.
|
||||||
|
|
||||||
|
|
||||||
|
** 6. The Most Important Concept to Understand
|
||||||
|
|
||||||
|
Everything revolves around **artifacts**.
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
Source Code
|
||||||
|
↓
|
||||||
|
Build
|
||||||
|
↓
|
||||||
|
Artifact
|
||||||
|
↓
|
||||||
|
Deploy artifact everywhere
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
You **never deploy source code directly**.
|
||||||
|
|
||||||
|
|
||||||
|
** 7. What You're Really Doing in This Ticket
|
||||||
|
|
||||||
|
You are teaching the deployment system:
|
||||||
|
|
||||||
|
"Hey, there is a new service now"
|
||||||
|
|
||||||
|
Then gradually making every environment aware of it.
|
||||||
|
|
||||||
* TODO
|
|
||||||
|
|||||||
323
posts/career/restful-api.org
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
#+TITLE: Restful API
|
||||||
|
#+OPTIONS: num:nil
|
||||||
|
#+DATE: <2026-02-15 Sun 23:00>
|
||||||
|
#+filetags: :learning:notes:
|
||||||
|
#+WIP: t
|
||||||
|
#+COMMENTS: t
|
||||||
|
#+SLUG: restful-api
|
||||||
|
|
||||||
|
[[../../assets/images/career/05-03-26-api-protocols.png]]
|
||||||
|
Note: REST and Webhooks are styles, not protocols
|
||||||
|
|
||||||
|
* What is a RESTful API?
|
||||||
|
|
||||||
|
A *RESTful API* is a web service that follows the principles of *REST (Representational State Transfer)*. REST is an architectural style used for designing networked applications.
|
||||||
|
|
||||||
|
In a RESTful system:
|
||||||
|
|
||||||
|
- Everything is treated as a *resource*
|
||||||
|
- Resources are identified using *URLs*
|
||||||
|
- Standard *HTTP methods* are used to interact with resources
|
||||||
|
- Communication is usually done using *JSON*
|
||||||
|
|
||||||
|
Example resource:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
/users
|
||||||
|
/users/1
|
||||||
|
/users/1/orders
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
These represent data stored on the server.
|
||||||
|
|
||||||
|
* Core HTTP Methods
|
||||||
|
|
||||||
|
REST APIs rely heavily on HTTP verbs.
|
||||||
|
|
||||||
|
| Method | Purpose | Example Endpoint |
|
||||||
|
|--------+-----------------------------+------------------|
|
||||||
|
| GET | Retrieve data | GET /users |
|
||||||
|
| POST | Create a new resource | POST /users |
|
||||||
|
| PUT | Update an existing resource | PUT /users/1 |
|
||||||
|
| DELETE | Remove a resource | DELETE /users/1 |
|
||||||
|
|
||||||
|
* Example Resource: User
|
||||||
|
|
||||||
|
Assume we have a simple *User* resource:
|
||||||
|
|
||||||
|
#+begin_src json
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Alice",
|
||||||
|
"email": "alice@email.com"
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
The API allows clients to create, read, update, and delete users.
|
||||||
|
|
||||||
|
* Creating a REST API in C# (ASP.NET Core)
|
||||||
|
|
||||||
|
In C#, REST APIs are commonly built using *ASP.NET Core Web API*.
|
||||||
|
|
||||||
|
Example project creation:
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
dotnet new webapi -n UserApi
|
||||||
|
cd UserApi
|
||||||
|
dotnet run
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
This creates a ready-to-run REST API project.
|
||||||
|
|
||||||
|
* Defining a Model
|
||||||
|
|
||||||
|
First, define the resource model.
|
||||||
|
|
||||||
|
File: Models/User.cs
|
||||||
|
|
||||||
|
#+begin_src csharp
|
||||||
|
namespace UserApi.Models
|
||||||
|
{
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string Email { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
This represents the data stored and returned by the API.
|
||||||
|
|
||||||
|
* Creating a Controller
|
||||||
|
|
||||||
|
Controllers handle HTTP requests.
|
||||||
|
|
||||||
|
File: Controllers/UserController.cs
|
||||||
|
|
||||||
|
#+begin_src csharp
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using UserApi.Models;
|
||||||
|
|
||||||
|
namespace UserApi.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class UserController : ControllerBase
|
||||||
|
{
|
||||||
|
private static List<User> users = new List<User>()
|
||||||
|
{
|
||||||
|
new User { Id = 1, Name = "Alice", Email = "alice@email.com" },
|
||||||
|
new User { Id = 2, Name = "Bob", Email = "bob@email.com" }
|
||||||
|
};
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public ActionResult<List<User>> GetUsers()
|
||||||
|
{
|
||||||
|
return Ok(users);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Endpoint created:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
GET /api/user
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
#+begin_src json
|
||||||
|
[
|
||||||
|
{ "id": 1, "name": "Alice", "email": "alice@email.com" },
|
||||||
|
{ "id": 2, "name": "Bob", "email": "bob@email.com" }
|
||||||
|
]
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Getting a Single Resource
|
||||||
|
|
||||||
|
Add an endpoint to retrieve a specific user.
|
||||||
|
|
||||||
|
#+begin_src csharp
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public ActionResult<User> GetUser(int id)
|
||||||
|
{
|
||||||
|
var user = users.FirstOrDefault(u => u.Id == id);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(user);
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Endpoint:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
GET /api/user/1
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Creating a Resource (POST)
|
||||||
|
|
||||||
|
Clients send JSON data to create a new user.
|
||||||
|
|
||||||
|
#+begin_src csharp
|
||||||
|
[HttpPost]
|
||||||
|
public ActionResult<User> CreateUser(User newUser)
|
||||||
|
{
|
||||||
|
newUser.Id = users.Max(u => u.Id) + 1;
|
||||||
|
users.Add(newUser);
|
||||||
|
|
||||||
|
return CreatedAtAction(nameof(GetUser), new { id = newUser.Id }, newUser);
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Example request:
|
||||||
|
|
||||||
|
#+begin_src json
|
||||||
|
POST /api/user
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Charlie",
|
||||||
|
"email": "charlie@email.com"
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Updating a Resource (PUT)
|
||||||
|
|
||||||
|
#+begin_src csharp
|
||||||
|
[HttpPut("{id}")]
|
||||||
|
public IActionResult UpdateUser(int id, User updatedUser)
|
||||||
|
{
|
||||||
|
var user = users.FirstOrDefault(u => u.Id == id);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Name = updatedUser.Name;
|
||||||
|
user.Email = updatedUser.Email;
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Endpoint:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
PUT /api/user/1
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Deleting a Resource
|
||||||
|
|
||||||
|
#+begin_src csharp
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
public IActionResult DeleteUser(int id)
|
||||||
|
{
|
||||||
|
var user = users.FirstOrDefault(u => u.Id == id);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
users.Remove(user);
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Endpoint:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
DELETE /api/user/1
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* REST Principles
|
||||||
|
|
||||||
|
A good REST API should follow these key ideas:
|
||||||
|
|
||||||
|
** 1. Statelessness
|
||||||
|
|
||||||
|
Each request contains all information needed.
|
||||||
|
|
||||||
|
The server does *not store client session state*.
|
||||||
|
|
||||||
|
** 2. Resource-Based URLs
|
||||||
|
|
||||||
|
Endpoints should represent *nouns*, not verbs.
|
||||||
|
|
||||||
|
Good:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
GET /users
|
||||||
|
POST /users
|
||||||
|
GET /users/1
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Bad:
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
GET /getUsers
|
||||||
|
POST /createUser
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** 3. Standard HTTP Status Codes
|
||||||
|
|
||||||
|
| Code | Meaning |
|
||||||
|
|------+--------------|
|
||||||
|
| 200 | OK |
|
||||||
|
| 201 | Created |
|
||||||
|
| 204 | No Content |
|
||||||
|
| 400 | Bad Request |
|
||||||
|
| 404 | Not Found |
|
||||||
|
| 500 | Server Error |
|
||||||
|
|
||||||
|
* Example Full API Structure
|
||||||
|
|
||||||
|
#+begin_src
|
||||||
|
UserApi/
|
||||||
|
├── Controllers/
|
||||||
|
│ └── UserController.cs
|
||||||
|
├── Models/
|
||||||
|
│ └── User.cs
|
||||||
|
├── Program.cs
|
||||||
|
└── appsettings.json
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Testing the API
|
||||||
|
|
||||||
|
You can test APIs using tools like:
|
||||||
|
|
||||||
|
- curl
|
||||||
|
- Postman
|
||||||
|
- Swagger UI (included with ASP.NET)
|
||||||
|
|
||||||
|
Example curl request:
|
||||||
|
|
||||||
|
#+begin_src bash
|
||||||
|
curl http://localhost:5000/api/user
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
* Summary
|
||||||
|
|
||||||
|
A RESTful API:
|
||||||
|
|
||||||
|
- Exposes *resources via URLs*
|
||||||
|
- Uses *HTTP methods (GET, POST, PUT, DELETE)*
|
||||||
|
- Communicates typically using *JSON*
|
||||||
|
- Is *stateless*
|
||||||
|
- Returns *standard HTTP status codes*
|
||||||
|
|
||||||
|
In C#, *ASP.NET Core Web API* makes building REST APIs straightforward using:
|
||||||
|
|
||||||
|
- Models
|
||||||
|
- Controllers
|
||||||
|
- Routing
|
||||||
|
- Built-in JSON serialization
|
||||||
@@ -4,10 +4,11 @@
|
|||||||
See the categories: @@html:<a href="../home/categories.html">Categories</a>@@
|
See the categories: @@html:<a href="../home/categories.html">Categories</a>@@
|
||||||
|
|
||||||
* Posts:
|
* Posts:
|
||||||
- [[file:career/career-list.org][Career List]] @@html:<span class="post-date">22-02-2026 22:37</span>@@
|
- [[file:career/career-list.org][Career List]] @@html:<span class="post-date">08-03-2026 12:51</span>@@
|
||||||
- [[file:career/database-permissions.org][Database permissions, roles and accounts]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:career/restful-api.org][Restful API]] @@html:<span class="post-date">15-02-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
|
- [[file:career/database-permissions.org][Database Permissions, Roles, and Accounts]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
- [[file:career/monitoring-and-logging.org][Monitoring and Logging]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:career/monitoring-and-logging.org][Monitoring and Logging]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
- [[file:career/pipelines.org][Pipelines and how they work]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:career/pipelines.org][Pipelines and how they work (as well as CI/CD)]] @@html:<span class="post-date">18-01-2026 23:00</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
- [[file:career/probation-objectives.org][Probation Objectives:]] @@html:<span class="post-date">08-12-2025 17:55</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:career/probation-objectives.org][Probation Objectives:]] @@html:<span class="post-date">08-12-2025 17:55</span>@@ @@html:<a href="/tags/review.html"> <span class="post-tag">review</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
- [[file:career/airflow.org][Datamarts, Airflow and DAG's]] @@html:<span class="post-date">15-11-2025 18:37</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:career/airflow.org][Datamarts, Airflow and DAG's]] @@html:<span class="post-date">15-11-2025 18:37</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
- [[file:career/normalisation.org][Benefits of Normalisation]] @@html:<span class="post-date">10-11-2025 18:04</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
- [[file:career/normalisation.org][Benefits of Normalisation]] @@html:<span class="post-date">10-11-2025 18:04</span>@@ @@html:<a href="/tags/learning.html"> <span class="post-tag">learning</span> </a>@@ @@html:<a href="/tags/notes.html"> <span class="post-tag">notes</span> </a>@@
|
||||||
|
|||||||
@@ -2,20 +2,24 @@
|
|||||||
#+OPTIONS: toc:nil num:nil
|
#+OPTIONS: toc:nil num:nil
|
||||||
|
|
||||||
* Recently Updated (top 26 files - per lima's request)
|
* Recently Updated (top 26 files - per lima's request)
|
||||||
- [[file:index.org][Home Page]] @@html:<span class="post-date">2026-02-22 22:24</span>@@
|
- [[file:blogs/2026/02-february/27-02-26.org][Journeys rambles again...]] @@html:<span class="post-date">2026-03-07 16:33</span>@@
|
||||||
- [[file:blogs/2025/2025-list.sync-conflict-20260222-170216-VT6366A.org][2025 List]] @@html:<span class="post-date">2026-02-22 17:02</span>@@
|
- [[file:blogs/2026/03-march/01-03-week-review.org][[01-03-2026] - Weekly Review]] @@html:<span class="post-date">2026-03-07 12:45</span>@@
|
||||||
- [[file:blogs/2025/2025-list.sync-conflict-20260222-170034-NE5VEIB.org][2025 List]] @@html:<span class="post-date">2026-02-22 17:00</span>@@
|
- [[file:posts/career/restful-api.org][Restful API]] @@html:<span class="post-date">2026-03-05 13:20</span>@@
|
||||||
- [[file:blogs/2025/2025-list.sync-conflict-20260222-165714-NE5VEIB.org][2025 List]] @@html:<span class="post-date">2026-02-22 16:56</span>@@
|
- [[file:posts/career/database-permissions.org][Database Permissions, Roles, and Accounts]] @@html:<span class="post-date">2026-03-05 13:06</span>@@
|
||||||
|
- [[file:posts/career/monitoring-and-logging.org][Monitoring and Logging]] @@html:<span class="post-date">2026-03-05 12:58</span>@@
|
||||||
|
- [[file:posts/career/pipelines.org][Pipelines and how they work (as well as CI/CD)]] @@html:<span class="post-date">2026-03-05 11:52</span>@@
|
||||||
|
- [[file:blogs/2026/02-february/third-meeting.org][Third Meeting with lima :)]] @@html:<span class="post-date">2026-03-03 12:02</span>@@
|
||||||
|
- [[file:blogs/2026/02-february/22-02-week-review.org][[22-02-2026] - Weekly Review]] @@html:<span class="post-date">2026-02-27 17:07</span>@@
|
||||||
|
- [[file:blogs/2026/02-february/26-02-26.org][Starting the Journeys Upgrade]] @@html:<span class="post-date">2026-02-26 17:37</span>@@
|
||||||
|
- [[file:blogs/2026/02-february/24-02-26.org][Integration tests failing (sob)]] @@html:<span class="post-date">2026-02-24 17:00</span>@@
|
||||||
|
- [[file:home/backlog.org][Backlog]] @@html:<span class="post-date">2026-02-23 16:40</span>@@
|
||||||
|
- [[file:index.org][Home Page]] @@html:<span class="post-date">2026-02-23 12:37</span>@@
|
||||||
|
- [[file:blogs/2026/02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]] @@html:<span class="post-date">2026-02-23 10:02</span>@@
|
||||||
- [[file:home/services.org][Service]] @@html:<span class="post-date">2026-02-11 13:26</span>@@
|
- [[file:home/services.org][Service]] @@html:<span class="post-date">2026-02-11 13:26</span>@@
|
||||||
- [[file:blogs/2026/02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]] @@html:<span class="post-date">2026-02-11 12:21</span>@@
|
|
||||||
- [[file:blogs/2026/02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]] @@html:<span class="post-date">2026-02-11 12:20</span>@@
|
- [[file:blogs/2026/02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]] @@html:<span class="post-date">2026-02-11 12:20</span>@@
|
||||||
- [[file:blogs/2026/02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]] @@html:<span class="post-date">2026-02-11 12:20</span>@@
|
- [[file:blogs/2026/02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]] @@html:<span class="post-date">2026-02-11 12:20</span>@@
|
||||||
- [[file:blogs/2026/01-january/25-01-week-review.org][[25-01-2026] - Weekly Review]] @@html:<span class="post-date">2026-02-11 11:43</span>@@
|
- [[file:blogs/2026/01-january/25-01-week-review.org][[25-01-2026] - Weekly Review]] @@html:<span class="post-date">2026-02-11 11:43</span>@@
|
||||||
- [[file:blogs/2026/01-january/18-01-week-review.org][[18-01-2026] - Weekly Review]] @@html:<span class="post-date">2026-01-18 23:05</span>@@
|
- [[file:blogs/2026/01-january/18-01-week-review.org][[18-01-2026] - Weekly Review]] @@html:<span class="post-date">2026-01-18 23:05</span>@@
|
||||||
- [[file:home/backlog.org][Backlog]] @@html:<span class="post-date">2026-01-18 23:03</span>@@
|
|
||||||
- [[file:posts/career/monitoring-and-logging.org][Monitoring and Logging]] @@html:<span class="post-date">2026-01-18 23:03</span>@@
|
|
||||||
- [[file:posts/career/database-permissions.org][Database permissions, roles and accounts]] @@html:<span class="post-date">2026-01-18 23:01</span>@@
|
|
||||||
- [[file:posts/career/pipelines.org][Pipelines and how they work]] @@html:<span class="post-date">2026-01-18 23:00</span>@@
|
|
||||||
- [[file:blogs/2026/01-january/11-01-week-review.org][[11-01-2026] - Weekly Review]] @@html:<span class="post-date">2026-01-17 21:23</span>@@
|
- [[file:blogs/2026/01-january/11-01-week-review.org][[11-01-2026] - Weekly Review]] @@html:<span class="post-date">2026-01-17 21:23</span>@@
|
||||||
- [[file:posts/career/airflow.org][Datamarts, Airflow and DAG's]] @@html:<span class="post-date">2026-01-17 21:17</span>@@
|
- [[file:posts/career/airflow.org][Datamarts, Airflow and DAG's]] @@html:<span class="post-date">2026-01-17 21:17</span>@@
|
||||||
- [[file:blogs/2025/12-december/21-12-week-review.org][[21-12-2025] - Weekly Review]] @@html:<span class="post-date">2026-01-17 21:09</span>@@
|
- [[file:blogs/2025/12-december/21-12-week-review.org][[21-12-2025] - Weekly Review]] @@html:<span class="post-date">2026-01-17 21:09</span>@@
|
||||||
@@ -24,7 +28,3 @@
|
|||||||
- [[file:posts/career/probation-objectives.org][Probation Objectives:]] @@html:<span class="post-date">2026-01-17 21:06</span>@@
|
- [[file:posts/career/probation-objectives.org][Probation Objectives:]] @@html:<span class="post-date">2026-01-17 21:06</span>@@
|
||||||
- [[file:home/status.org][Competency Status Board]] @@html:<span class="post-date">2026-01-10 20:47</span>@@
|
- [[file:home/status.org][Competency Status Board]] @@html:<span class="post-date">2026-01-10 20:47</span>@@
|
||||||
- [[file:posts/career/invest-principles.org][Invest Principles]] @@html:<span class="post-date">2026-01-04 17:15</span>@@
|
- [[file:posts/career/invest-principles.org][Invest Principles]] @@html:<span class="post-date">2026-01-04 17:15</span>@@
|
||||||
- [[file:posts/career/lean.org][Lean]] @@html:<span class="post-date">2025-12-30 21:04</span>@@
|
|
||||||
- [[file:home/notes.org][Notes]] @@html:<span class="post-date">2025-12-18 22:30</span>@@
|
|
||||||
- [[file:home/setup.org][Setup]] @@html:<span class="post-date">2025-12-18 22:00</span>@@
|
|
||||||
- [[file:posts/career/wireframe-designs.org][Wireframe Designs]] @@html:<span class="post-date">2025-12-16 21:44</span>@@
|
|
||||||
|
|||||||
20
sitemap.org
@@ -28,18 +28,16 @@
|
|||||||
- [[file:posts/career/normalisation.org][Benefits of Normalisation]]
|
- [[file:posts/career/normalisation.org][Benefits of Normalisation]]
|
||||||
- [[file:posts/career/airflow.org][Datamarts, Airflow and DAG's]]
|
- [[file:posts/career/airflow.org][Datamarts, Airflow and DAG's]]
|
||||||
- [[file:posts/career/probation-objectives.org][Probation Objectives:]]
|
- [[file:posts/career/probation-objectives.org][Probation Objectives:]]
|
||||||
- [[file:posts/career/database-permissions.org][Database permissions, roles and accounts]]
|
- [[file:posts/career/database-permissions.org][Database Permissions, Roles, and Accounts]]
|
||||||
- [[file:posts/career/monitoring-and-logging.org][Monitoring and Logging]]
|
- [[file:posts/career/monitoring-and-logging.org][Monitoring and Logging]]
|
||||||
- [[file:posts/career/pipelines.org][Pipelines and how they work]]
|
- [[file:posts/career/pipelines.org][Pipelines and how they work (as well as CI/CD)]]
|
||||||
|
- [[file:posts/career/restful-api.org][Restful API]]
|
||||||
- [[file:posts/career/career-list.org][Career List]]
|
- [[file:posts/career/career-list.org][Career List]]
|
||||||
- blogs
|
- blogs
|
||||||
- [[file:blogs/blogs-intro.org][Blogs Introduction]]
|
- [[file:blogs/blogs-intro.org][Blogs Introduction]]
|
||||||
- [[file:blogs/publish-pages.org][How to publish pages using Org Publish]]
|
- [[file:blogs/publish-pages.org][How to publish pages using Org Publish]]
|
||||||
- [[file:blogs/blogs-list.org][Blogs List]]
|
- [[file:blogs/blogs-list.org][Blogs List]]
|
||||||
- 2025
|
- 2025
|
||||||
- [[file:blogs/2025/2025-list.sync-conflict-20260222-165714-NE5VEIB.org][2025 List]]
|
|
||||||
- [[file:blogs/2025/2025-list.sync-conflict-20260222-170034-NE5VEIB.org][2025 List]]
|
|
||||||
- [[file:blogs/2025/2025-list.sync-conflict-20260222-170216-VT6366A.org][2025 List]]
|
|
||||||
- [[file:blogs/2025/2025-list.org][2025 List]]
|
- [[file:blogs/2025/2025-list.org][2025 List]]
|
||||||
- 11-november
|
- 11-november
|
||||||
- [[file:blogs/2025/11-november/02-11-week-review.org][[02-11-2025] - Weekly Review]]
|
- [[file:blogs/2025/11-november/02-11-week-review.org][[02-11-2025] - Weekly Review]]
|
||||||
@@ -67,10 +65,17 @@
|
|||||||
- [[file:blogs/2026/01-january/11-01-week-review.org][[11-01-2026] - Weekly Review]]
|
- [[file:blogs/2026/01-january/11-01-week-review.org][[11-01-2026] - Weekly Review]]
|
||||||
- [[file:blogs/2026/01-january/18-01-week-review.org][[18-01-2026] - Weekly Review]]
|
- [[file:blogs/2026/01-january/18-01-week-review.org][[18-01-2026] - Weekly Review]]
|
||||||
- [[file:blogs/2026/01-january/25-01-week-review.org][[25-01-2026] - Weekly Review]]
|
- [[file:blogs/2026/01-january/25-01-week-review.org][[25-01-2026] - Weekly Review]]
|
||||||
|
- 03-march
|
||||||
|
- [[file:blogs/2026/03-march/01-03-week-review.org][[01-03-2026] - Weekly Review]]
|
||||||
- 02-february
|
- 02-february
|
||||||
- [[file:blogs/2026/02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]]
|
- [[file:blogs/2026/02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]]
|
||||||
|
- [[file:blogs/2026/02-february/third-meeting.org][Third Meeting with lima :)]]
|
||||||
- [[file:blogs/2026/02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]]
|
- [[file:blogs/2026/02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]]
|
||||||
- [[file:blogs/2026/02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]]
|
- [[file:blogs/2026/02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]]
|
||||||
|
- [[file:blogs/2026/02-february/22-02-week-review.org][[22-02-2026] - Weekly Review]]
|
||||||
|
- [[file:blogs/2026/02-february/24-02-26.org][Integration tests failing (sob)]]
|
||||||
|
- [[file:blogs/2026/02-february/26-02-26.org][Starting the Journeys Upgrade]]
|
||||||
|
- [[file:blogs/2026/02-february/27-02-26.org][Journeys rambles again...]]
|
||||||
- books
|
- books
|
||||||
- [[file:books/books-list.org][Books List]]
|
- [[file:books/books-list.org][Books List]]
|
||||||
- clean-code
|
- clean-code
|
||||||
@@ -78,13 +83,14 @@
|
|||||||
- lima
|
- lima
|
||||||
- [[file:lima/lima-list.org][Lima]]
|
- [[file:lima/lima-list.org][Lima]]
|
||||||
- tags
|
- tags
|
||||||
- [[file:tags/learning.org][Tag: learning]]
|
|
||||||
- [[file:tags/introduction.org][Tag: introduction]]
|
- [[file:tags/introduction.org][Tag: introduction]]
|
||||||
|
- [[file:tags/learning.org][Tag: learning]]
|
||||||
- [[file:tags/notes.org][Tag: notes]]
|
- [[file:tags/notes.org][Tag: notes]]
|
||||||
- [[file:tags/review.org][Tag: review]]
|
- [[file:tags/review.org][Tag: review]]
|
||||||
|
- [[file:tags/website.org][Tag: website]]
|
||||||
- [[file:tags/education.org][Tag: education]]
|
- [[file:tags/education.org][Tag: education]]
|
||||||
- [[file:tags/insights.org][Tag: insights]]
|
- [[file:tags/insights.org][Tag: insights]]
|
||||||
- [[file:tags/website.org][Tag: website]]
|
- [[file:tags/life.org][Tag: life]]
|
||||||
- [[file:tags/emacs.org][Tag: emacs]]
|
- [[file:tags/emacs.org][Tag: emacs]]
|
||||||
- [[file:tags/maths.org][Tag: maths]]
|
- [[file:tags/maths.org][Tag: maths]]
|
||||||
- [[file:tags/reading.org][Tag: reading]]
|
- [[file:tags/reading.org][Tag: reading]]
|
||||||
@@ -2,9 +2,10 @@
|
|||||||
#+OPTIONS: toc:nil num:nil title:nil
|
#+OPTIONS: toc:nil num:nil title:nil
|
||||||
|
|
||||||
* Posts tagged learning
|
* Posts tagged learning
|
||||||
- [[file:../posts/career/database-permissions.org][Database permissions, roles and accounts]]
|
- [[file:../posts/career/restful-api.org][Restful API]]
|
||||||
|
- [[file:../posts/career/database-permissions.org][Database Permissions, Roles, and Accounts]]
|
||||||
- [[file:../posts/career/monitoring-and-logging.org][Monitoring and Logging]]
|
- [[file:../posts/career/monitoring-and-logging.org][Monitoring and Logging]]
|
||||||
- [[file:../posts/career/pipelines.org][Pipelines and how they work]]
|
- [[file:../posts/career/pipelines.org][Pipelines and how they work (as well as CI/CD)]]
|
||||||
- [[file:../posts/career/airflow.org][Datamarts, Airflow and DAG's]]
|
- [[file:../posts/career/airflow.org][Datamarts, Airflow and DAG's]]
|
||||||
- [[file:../posts/career/normalisation.org][Benefits of Normalisation]]
|
- [[file:../posts/career/normalisation.org][Benefits of Normalisation]]
|
||||||
- [[file:../posts/career/management-of-self.org][Management of self training]]
|
- [[file:../posts/career/management-of-self.org][Management of self training]]
|
||||||
|
|||||||
8
tags/life.org
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#+TITLE: Tag: life
|
||||||
|
#+OPTIONS: toc:nil num:nil title:nil
|
||||||
|
|
||||||
|
* Posts tagged life
|
||||||
|
- [[file:../blogs/2026/02-february/27-02-26.org][Journeys rambles again...]]
|
||||||
|
- [[file:../blogs/2026/02-february/26-02-26.org][Starting the Journeys Upgrade]]
|
||||||
|
- [[file:../blogs/2026/02-february/24-02-26.org][Integration tests failing (sob)]]
|
||||||
|
- [[file:../blogs/2026/02-february/third-meeting.org][Third Meeting with lima :)]]
|
||||||
@@ -2,9 +2,10 @@
|
|||||||
#+OPTIONS: toc:nil num:nil title:nil
|
#+OPTIONS: toc:nil num:nil title:nil
|
||||||
|
|
||||||
* Posts tagged notes
|
* Posts tagged notes
|
||||||
- [[file:../posts/career/database-permissions.org][Database permissions, roles and accounts]]
|
- [[file:../posts/career/restful-api.org][Restful API]]
|
||||||
|
- [[file:../posts/career/database-permissions.org][Database Permissions, Roles, and Accounts]]
|
||||||
- [[file:../posts/career/monitoring-and-logging.org][Monitoring and Logging]]
|
- [[file:../posts/career/monitoring-and-logging.org][Monitoring and Logging]]
|
||||||
- [[file:../posts/career/pipelines.org][Pipelines and how they work]]
|
- [[file:../posts/career/pipelines.org][Pipelines and how they work (as well as CI/CD)]]
|
||||||
- [[file:../posts/career/probation-objectives.org][Probation Objectives:]]
|
- [[file:../posts/career/probation-objectives.org][Probation Objectives:]]
|
||||||
- [[file:../posts/career/airflow.org][Datamarts, Airflow and DAG's]]
|
- [[file:../posts/career/airflow.org][Datamarts, Airflow and DAG's]]
|
||||||
- [[file:../posts/career/normalisation.org][Benefits of Normalisation]]
|
- [[file:../posts/career/normalisation.org][Benefits of Normalisation]]
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#+OPTIONS: toc:nil num:nil title:nil
|
#+OPTIONS: toc:nil num:nil title:nil
|
||||||
|
|
||||||
* Posts tagged review
|
* Posts tagged review
|
||||||
|
- [[file:../blogs/2026/03-march/01-03-week-review.org][[01-03-2026] - Weekly Review]]
|
||||||
|
- [[file:../blogs/2026/02-february/22-02-week-review.org][[22-02-2026] - Weekly Review]]
|
||||||
- [[file:../blogs/2026/02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]]
|
- [[file:../blogs/2026/02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]]
|
||||||
- [[file:../blogs/2026/02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]]
|
- [[file:../blogs/2026/02-february/08-02-week-review.org][[08-02-2026] - Weekly Review]]
|
||||||
- [[file:../blogs/2026/02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]]
|
- [[file:../blogs/2026/02-february/01-02-week-review.org][[01-02-2026] - Weekly Review]]
|
||||||
|
|||||||
5
wip.org
@@ -2,7 +2,4 @@
|
|||||||
#+OPTIONS: toc:nil num:nil
|
#+OPTIONS: toc:nil num:nil
|
||||||
|
|
||||||
* Work in progress
|
* Work in progress
|
||||||
- [[file:blogs/2026/02-february/15-02-week-review.org][[15-02-2026] - Weekly Review]] @@html:<span class="post-date">15-02-2026 12:00</span>@@
|
- [[file:posts/career/restful-api.org][Restful API]] @@html:<span class="post-date">15-02-2026 23:00</span>@@
|
||||||
- [[file:posts/career/database-permissions.org][Database permissions, roles and accounts]] @@html:<span class="post-date">18-01-2026 23:00</span>@@
|
|
||||||
- [[file:posts/career/monitoring-and-logging.org][Monitoring and Logging]] @@html:<span class="post-date">18-01-2026 23:00</span>@@
|
|
||||||
- [[file:posts/career/pipelines.org][Pipelines and how they work]] @@html:<span class="post-date">18-01-2026 23:00</span>@@
|
|
||||||