Added new files regarding airflow and fixed the png's not zooming in nested panes

This commit is contained in:
2025-12-29 18:47:48 +00:00
parent f217e8828f
commit 80101cd34b
16 changed files with 259 additions and 120 deletions

View File

@@ -6,7 +6,11 @@
* Cheat sheet
[[./assets/git-cheat-sheet-1.png]]
[[./assets/git-cheat-sheet-2.png]]
[[./assets/Screenshot_20251227_153037.png]]
* Open Source Projects:
- [[https://github.com/codecrafters-io/build-your-own-x?tab=readme-ov-file][Build your own `x`]]

View File

@@ -14,3 +14,5 @@
* [[id:dd55d635-59de-4ed9-8ff0-423782c2e0ae][clean-code]]
* [[id:4426cc9a-1568-4fc8-9242-269654c43a3b][naqshe-hayat]]
- [[id:dc9ece84-0b14-4afd-b25a-786cf1618996][Head First Design Patterns]]

View File

@@ -1,7 +1,7 @@
:PROPERTIES:
:ID: 939e301b-6463-46a8-b57e-0af606e7e7ef
:END:
#+title: postgres
#+title: Postgres
#+filetags: :database:index:
#+begin_src bash
@@ -24,41 +24,41 @@ To get your phone logged in, there's two ways:
Im thinking of having this as our shared calendar and file system. The only users are us 2 and its completely off the internet (self-hosted).
network issues resolved by:
** network issues resolved by:
docker network connect postgres_network postgres
#+begin_src bash
docker network connect postgres_network postgres
zaine@zaine-HP-ProDesk-400-G1-SFF [21:00:27] [~/docker-services/nextcloud]
-> % psql -h zserver.zapto.org -p 5432 -U zaine -d zxq_db
Password for user zaine:
psql (14.18 (Ubuntu 14.18-0ubuntu0.22.04.1), server 17.5 (Debian 17.5-1.pgdg120+1))
WARNING: psql major version 14, server major version 17.
Some psql features might not work.
Type "help" for help.
zaine@zaine-HP-ProDesk-400-G1-SFF [21:00:27] [~/docker-services/nextcloud]
-> % psql -h zserver.zapto.org -p 5432 -U zaine -d zxq_db
Password for user zaine:
psql (14.18 (Ubuntu 14.18-0ubuntu0.22.04.1), server 17.5 (Debian 17.5-1.pgdg120+1))
WARNING: psql major version 14, server major version 17.
Some psql features might not work.
Type "help" for help.
zxq_db=# \c nextcloud
psql (14.18 (Ubuntu 14.18-0ubuntu0.22.04.1), server 17.5 (Debian 17.5-1.pgdg120+1))
WARNING: psql major version 14, server major version 17.
Some psql features might not work.
You are now connected to database "nextcloud" as user "zaine".
nextcloud=# GRANT ALL PRIVILEGES ON DATABASE nextcloud TO nextcloud;
GRANT
nextcloud=# GRANT USAGE ON SCHEMA public TO nextcloud;
GRANT CREATE ON SCHEMA public TO nextcloud;
GRANT
GRANT
nextcloud=# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO nextcloud;
GRANT
nextcloud=# GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO nextcloud;
GRANT
nextcloud=#
zaine
M22ZN-fmefj-RdF36-3BMfT-LfWo8
zaine
zxh123!
zxq_db=# \c nextcloud
psql (14.18 (Ubuntu 14.18-0ubuntu0.22.04.1), server 17.5 (Debian 17.5-1.pgdg120+1))
WARNING: psql major version 14, server major version 17.
Some psql features might not work.
You are now connected to database "nextcloud" as user "zaine".
nextcloud=# GRANT ALL PRIVILEGES ON DATABASE nextcloud TO nextcloud;
GRANT
nextcloud=# GRANT USAGE ON SCHEMA public TO nextcloud;
GRANT CREATE ON SCHEMA public TO nextcloud;
GRANT
GRANT
nextcloud=# GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO nextcloud;
GRANT
nextcloud=# GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO nextcloud;
GRANT
nextcloud=#
zaine
M22ZN-fmefj-RdF36-3BMfT-LfWo8
zaine
zxh123!
#+end_src

View File

@@ -1,7 +1,9 @@
:PROPERTIES:
:ID: e448cd99-afee-4702-947f-644bb34dc1aa
:END:
#+title: database_moc
#+title: Database MOC
#+filetags: :database:moc:
[[id:939e301b-6463-46a8-b57e-0af606e7e7ef][postgres]]
- [[id:939e301b-6463-46a8-b57e-0af606e7e7ef][Postgres]]
- [[id:c6cf8f7a-778f-4e83-b607-753ef8dbb3f1][Airflow]]

View File

@@ -0,0 +1,25 @@
:PROPERTIES:
:ID: c6cf8f7a-778f-4e83-b607-753ef8dbb3f1
:END:
#+title: Airflow
#+filetags: :database:docs:
* xcom
XComs stands for cross-communications, and as the name suggests, it allows [[id:1ea42d73-3cd1-4cac-a6ee-028de21d08d5][Airflow Tasks]] to talk to each other (because by default, tasks are entirely isolated and can run on seperate machines).
See [[https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/xcoms.html][this]]
* parquets
*Key Takeaways*
- What is Parquet: An open-source columnar storage file format for efficient analytics.
- Core Benefits: Superior compression, faster query performance (via column pruning and predicate pushdown), and schema evolution support.
- Common Alternatives: Compared to row-based (CSV, Avro), columnar (ORC), and table formats (Iceberg, Delta Lake).
- DuckDB & MotherDuck: Parquet integrates seamlessly with DuckDB for high-performance SQL queries directly on Parquet files.
*What is Parquet?*
Parquet is a columnar storage file format. When data engineers ask 'what is a Parquet file?', the simple answer is that it's a file that stores data in columns, not rows. This Parquet data format is designed for efficient data processing, particularly in the context of big data applications. Developed as part of the Apache Hadoop ecosystem, Parquet has gained widespread adoption due to its ability to optimize storage and query performance.
[[https://motherduck.com/learn-more/why-choose-parquet-table-file-format/][See this]]

View File

@@ -0,0 +1,5 @@
:PROPERTIES:
:ID: c6cf8f7a-778f-4e83-b607-753ef8dbb3f1
:END:
#+title: airflow

View File

@@ -0,0 +1,14 @@
:PROPERTIES:
:ID: 1ea42d73-3cd1-4cac-a6ee-028de21d08d5
:END:
#+title: Airflow Tasks
#+filetags: :airflow:database:definitions:
A task in the context of airflow is the basic unit of execution. They are arranged into [[id:3b16e19a-62f0-4705-a451-a8790181941f][Dags]] and then have upstream and downstream dependencies set between them in order to express the order in which they should be run.
There are three kinds of tasks:
1. Operators: they are predefined task templates that you can string together quickly.
2. Sensors: special subclass of operators, which are entirely about waiting for an external event to happen.
3. A Taskflow-decorated @task, which is a custom python function packaged as a task.
[[https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/tasks.html][See this]]

View File

@@ -0,0 +1,6 @@
:PROPERTIES:
:ID: 1ea42d73-3cd1-4cac-a6ee-028de21d08d5
:END:
#+title: Airflow Tasks
#+filetags: :airflow:database:docs:

View File

@@ -0,0 +1,7 @@
:PROPERTIES:
:ID: 3b16e19a-62f0-4705-a451-a8790181941f
:END:
#+title: Airflow Dags
#+filetags: :airflow:database:definitions:
A DAG (short for directed acyclic graphs) is a model that encapsulates everything needed to execute a workflow. [[https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/dags.html][See this]]

View File

@@ -0,0 +1,6 @@
:PROPERTIES:
:ID: 3b16e19a-62f0-4705-a451-a8790181941f
:END:
#+title: Airflow Dags
A DAG (short for directed acyclic graphs) is a model that encapsulates everything needed to execute a workflow. [[https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/dags.html][See this]]

View File

@@ -12,6 +12,9 @@ A complete alphabetical index of all published pages.
- [[id:ed4c372b-0314-4b6e-9119-742f69b5e434][afp_lec_5]]
- [[id:4bc71106-1d2b-4c71-836d-54b738fe5ff5][afp_week2]]
- [[id:1f395b8c-cf55-43eb-9430-dd9449f6b575][afp_week5]]
- [[id:c6cf8f7a-778f-4e83-b607-753ef8dbb3f1][Airflow]]
- [[id:3b16e19a-62f0-4705-a451-a8790181941f][Airflow Dags]]
- [[id:1ea42d73-3cd1-4cac-a6ee-028de21d08d5][Airflow Tasks]]
- [[id:e7f2302b-16eb-476d-a7b9-be12f077819d][AOC Notes]]
* B
- [[id:580cc3a5-af8e-4cbe-b5ad-5b06680e6c37][Backlog]]
@@ -24,7 +27,7 @@ A complete alphabetical index of all published pages.
- [[id:f9838952-9753-471b-a2cc-d72e01a53ef6][career_capital]]
- [[id:dd55d635-59de-4ed9-8ff0-423782c2e0ae][clean-code]]
* D
- [[id:e448cd99-afee-4702-947f-644bb34dc1aa][database_moc]]
- [[id:e448cd99-afee-4702-947f-644bb34dc1aa][Database MOC]]
- [[id:d4f96bfb-b83d-449b-9f74-f602a1a3c2d3][deliberate_practice]]
- [[id:631b2086-4b8f-4fe3-829d-be1dc014e293][Design patterns]]
* E
@@ -76,7 +79,7 @@ A complete alphabetical index of all published pages.
- [[id:2c2d8df4-ad36-40ab-9f30-8a047b372956][old_nextcloud_server_code]]
- [[id:a9829b5d-690d-4a21-ba94-ac8beac4d439][old_nginx_code]]
* P
- [[id:939e301b-6463-46a8-b57e-0af606e7e7ef][postgres]]
- [[id:939e301b-6463-46a8-b57e-0af606e7e7ef][Postgres]]
- [[id:2BFB84B2-2129-4AE3-8E69-290CA5BF9747][pre_work_prep_microlise]]
- [[id:125c81dc-c14f-4b4d-93c6-0a2b157735ac][python-dictionary]]
- [[id:9d534e89-7f0b-494c-bff6-7b3be05b85d1][python-lambda]]
@@ -102,6 +105,7 @@ A complete alphabetical index of all published pages.
* U
- [[id:4a8edaed-9ebd-402b-9c5f-7a0cb4399102][uml_fyp]]
- [[id:797d6e3e-98eb-4bc7-88b6-e096ef7306ad][uni_moc]]
- [[id:dc9ece84-0b14-4afd-b25a-786cf1618996][Untitled]]
- [[id:d939e477-d1e9-43ea-960e-8727246d12a3][useful-c-imports]]
* W
- [[id:7612a9a6-ae70-4525-93a0-81bac857df39][wacom-notes]]

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 347 KiB

View File

@@ -4,79 +4,66 @@ document.addEventListener('DOMContentLoaded', () => {
return;
}
// 1) Wrap Org-exported images so theyre clickable
const imgs = document.querySelectorAll('.figure img, img.org-svg');
imgs.forEach((img) => {
if (img.closest('a')) return; // already wrapped
const a = document.createElement('a');
const href = img.currentSrc || img.src;
a.href = href;
a.dataset.img = href; // lets BP pre-size/raster slides
a.dataset.alt = img.alt || '';
const setDims = () => {
a.dataset.width = img.naturalWidth || img.width || 1920;
a.dataset.height = img.naturalHeight || img.height || 1080;
};
if (img.complete) setDims(); else img.addEventListener('load', setDims);
img.style.cursor = 'zoom-in';
img.parentElement.insertBefore(a, img);
a.appendChild(img);
});
function setupGalleries(root = document) {
const imgs = root.querySelectorAll('.figure img, img.org-svg');
imgs.forEach((img) => {
if (img.closest('a')) return;
const a = document.createElement('a');
const href = img.currentSrc || img.src;
a.href = href;
a.dataset.img = href;
a.dataset.alt = img.alt || '';
const setDims = () => {
a.dataset.width = img.naturalWidth || img.width || 1920;
a.dataset.height = img.naturalHeight || img.height || 1080;
};
if (img.complete) setDims(); else img.addEventListener('load', setDims);
img.style.cursor = 'zoom-in';
img.parentElement.insertBefore(a, img);
a.appendChild(img);
});
const containers = root.querySelectorAll('main, article, .content, body');
containers.forEach((container) => {
const links = Array.from(container.querySelectorAll('.figure a, a:has(img.org-svg)'));
if (!links.length) return;
links.forEach((link) => {
if (link.dataset.bpBound) return;
link.dataset.bpBound = 'true';
link.addEventListener('click', (e) => {
e.preventDefault();
document.querySelectorAll(".theme-toggle").forEach(el => el.classList.add("hidden"));
bp.open({
items: links,
el: link,
caption: (el) => el.querySelector('img')?.alt || el.title || '',
maxZoom: 40,
onClose(containerEl) {
destroyPanZoom();
teardownRotation();
if (containerEl) containerEl.classList.add('bp-fadeout');
document.querySelectorAll(".theme-toggle").forEach(el => el.classList.remove("hidden"));
},
onOpen(containerEl) { setupRotation(containerEl); enhanceSVG(containerEl); },
onUpdate(containerEl){ setupRotation(containerEl); enhanceSVG(containerEl); }
});
});
});
});
}
// 2) One global BP instance
const bp = BiggerPicture({ target: document.body });
// SVG pan/zoom handle
let activePanZoom = null;
const destroyPanZoom = () => { try { activePanZoom?.destroy(); } catch(_){} activePanZoom = null; };
// Simple rotate state (for non-SVG images)
let activeContainer = null;
let currentRotation = 0;
let rotateControls = null;
// 3) Build galleries per content container
const containers = document.querySelectorAll('main, article, .content, body');
containers.forEach((container) => {
const links = Array.from(container.querySelectorAll('.figure a, a:has(img.org-svg)'));
if (!links.length) return;
// Start the lightbox on click
links.forEach((link, index) => {
link.addEventListener('click', (e) => {
e.preventDefault();
document.querySelectorAll(".theme-toggle").forEach(el => {
el.classList.add("hidden");
});
bp.open({
// IMPORTANT: pass the anchor ELEMENTS, not custom objects
items: links,
el: link,
caption: (el) => el.querySelector('img')?.alt || el.title || '',
maxZoom: 40, // for raster images (PNG/JPG); SVG handled separately
// Fade-out polish + cleanup
onClose(containerEl) {
destroyPanZoom();
teardownRotation();
if (containerEl) containerEl.classList.add('bp-fadeout');
const themeToggle = document.querySelector(".theme-toggle");
if (themeToggle) {
themeToggle.classList.remove("hidden");
}
},
// Called once after open and on every slide change
onOpen(containerEl) { setupRotation(containerEl); enhanceSVG(containerEl); },
onUpdate(containerEl){ setupRotation(containerEl); enhanceSVG(containerEl); }
});
});
});
});
// 4) Simple rotate buttons for raster images
function ensureRotateControls() {
if (rotateControls) return rotateControls;
@@ -110,11 +97,11 @@ document.addEventListener('DOMContentLoaded', () => {
return btn;
};
const left = mkBtn('⟲', 'Rotate image 90° left');
const left = mkBtn('⟲', 'Rotate image 90° left');
const right = mkBtn('⟳', 'Rotate image 90° right');
left.addEventListener('click', (e) => {
e.stopPropagation(); // dont close the lightbox
e.stopPropagation();
if (!activeContainer) return;
currentRotation = (currentRotation - 90 + 360) % 360;
applyRotation();
@@ -139,11 +126,10 @@ document.addEventListener('DOMContentLoaded', () => {
const imgRoot = activeContainer.querySelector('.bp-img');
if (!imgRoot) return null;
let imgEl = imgRoot.querySelector('img');
const imgEl = imgRoot.querySelector('img');
if (!imgEl) return null;
const src = (imgEl.currentSrc || imgEl.src || '').toLowerCase();
// We only rotate raster images; SVGs are handled via svg-pan-zoom
if (src.endsWith('.svg')) return null;
let wrapper = imgRoot.querySelector('.bp-rotate-wrapper');
@@ -156,7 +142,6 @@ document.addEventListener('DOMContentLoaded', () => {
imgRoot.appendChild(wrapper);
wrapper.appendChild(imgEl);
} else if (!wrapper.contains(imgEl)) {
// Slide changed and BiggerPicture replaced the <img>
wrapper.innerHTML = '';
wrapper.appendChild(imgEl);
}
@@ -181,13 +166,12 @@ document.addEventListener('DOMContentLoaded', () => {
function teardownRotation() {
activeContainer = null;
currentRotation = 0;
if (rotateControls) {
rotateControls.style.display = 'none';
}
if (rotateControls) rotateControls.style.display = 'none';
}
// 4) If current slide is an SVG, swap to inline + enable svg-pan-zoom
let activePanZoom = null;
const destroyPanZoom = () => { try { activePanZoom?.destroy(); } catch(_){} activePanZoom = null; };
async function enhanceSVG(containerEl) {
try {
destroyPanZoom();
@@ -199,14 +183,12 @@ document.addEventListener('DOMContentLoaded', () => {
const isSVG = src.toLowerCase().endsWith('.svg');
const htmlLayer = containerEl.querySelector('.bp-html');
if (!isSVG || !htmlLayer) {
// ensure any previous holder is removed and bitmap is visible
const old = htmlLayer?.querySelector('.bp-svg-holder');
if (old) old.remove();
imgEl.style.visibility = '';
return;
}
// Create/clear holder
let holder = htmlLayer.querySelector('.bp-svg-holder');
if (!holder) {
holder = document.createElement('div');
@@ -217,10 +199,8 @@ document.addEventListener('DOMContentLoaded', () => {
}
holder.innerHTML = '';
// Hide the bitmap so only the inline SVG shows
imgEl.style.visibility = 'hidden';
// Inline the SVG
const res = await fetch(src, { cache: 'force-cache' });
const text = await res.text();
holder.innerHTML = text;
@@ -228,9 +208,9 @@ document.addEventListener('DOMContentLoaded', () => {
const svg = holder.querySelector('svg');
if (!svg) { imgEl.style.visibility = ''; return; }
svg.style.maxWidth = '95vw';
svg.style.maxWidth = '95vw';
svg.style.maxHeight = '95vh';
svg.style.display = 'block';
svg.style.display = 'block';
if (typeof window.svgPanZoom === 'function') {
activePanZoom = svgPanZoom(svg, {
@@ -239,11 +219,10 @@ document.addEventListener('DOMContentLoaded', () => {
fit: true,
center: true,
minZoom: 0.05,
maxZoom: 400, // effectively "unlimited"
maxZoom: 400,
zoomScaleSensitivity: 0.25,
dblClickZoomEnabled: true
});
// Keep wheel inside lightbox
holder.addEventListener('wheel', (e) => e.stopPropagation(), { passive: true });
} else {
console.warn('[gallery-init] svg-pan-zoom not loaded');
@@ -252,4 +231,27 @@ document.addEventListener('DOMContentLoaded', () => {
console.error('[gallery-init] SVG enhance failed:', err);
}
}
setupGalleries(document);
const dynamicObserver = new MutationObserver((mutations) => {
for (const m of mutations) {
for (const node of m.addedNodes) {
if (!(node instanceof HTMLElement)) continue;
if (node.querySelectorAll) setupGalleries(node);
}
}
});
dynamicObserver.observe(document.body, { childList: true, subtree: true });
let lastUrl = location.href;
const urlObserver = new MutationObserver(() => {
const currentUrl = location.href;
if (currentUrl !== lastUrl) {
lastUrl = currentUrl;
console.log('[gallery-init] URL changed → reinitializing galleries');
setupGalleries(document);
}
});
urlObserver.observe(document, { subtree: true, childList: true });
});

View File

@@ -0,0 +1,57 @@
* Head First Design Patterns
:PROPERTIES:
:NOTER_DOCUMENT: ../../../pdfs/bootcamp/Head First Design Patterns.pdf
:ID: dc9ece84-0b14-4afd-b25a-786cf1618996
:END:
** Chapter 1
:PROPERTIES:
:NOTER_PAGE: 36
:END:
*** Structural:
The Strategy Pattern defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
- Encapsulate what varies
- Favor composition over inheritance
- Program to interfaces, not implementations
** Chapter 2
:PROPERTIES:
:NOTER_PAGE: 82
:END:
*** Observer:
The Observer Pattern defines a one-to-many dependency between objects so that when
one object changes state, all of its dependents are notified and updated automatically.
Subjects, or as we also know them, Observables, update Observers using a common
interface
Observers are loosely coupled in that the Observable knows nothing about them,
other than that they implement the Observer interface.
You can push or pull data from the Observable when using the pattern (pull is
considered more “correct”).
Dont depend on a specific order of notification for your Observers.
Java has several implementations of the Observer Pattern, including the general
purpose java.util.Observable
- Strive for loosely coupled designs between objects that interact
** Notes for page 137
:PROPERTIES:
:NOTER_PAGE: 137
:END:
- Classes should be open for extension, but closed for modification.
** Notes for page 142
:PROPERTIES:
:NOTER_PAGE: 142
:END:
Notes for the decaroter pattern.
** Notes for page 143
:PROPERTIES:
:NOTER_PAGE: 143
:END:
Decorator pattern: The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

View File

@@ -0,0 +1,5 @@
* Head First Design Patterns
:PROPERTIES:
:NOTER_DOCUMENT: ../../../pdfs/bootcamp/Head First Design Patterns.pdf
:ID: dc9ece84-0b14-4afd-b25a-786cf1618996
:END: