diff --git a/custom.css b/custom.css index 805f9ff..3c76a05 100644 --- a/custom.css +++ b/custom.css @@ -1,5 +1,57 @@ /* Custom styling for IT Learning Notes */ +/* Table of Contents styling */ +.toc { + background-color: #f8f9fa; + border: 1px solid #eaecef; + border-radius: 4px; + padding: 1em; + margin-bottom: 2em; +} + +.toc ul, .toc ol { + list-style-type: none; + padding-left: 1em; +} + +.toc li { + margin: 0.5em 0; +} + +/* Back to top link styling */ +a[href^="#"] { + text-decoration: none; + color: #4183c4; + font-weight: 600; +} + +a[href^="#"]:hover { + text-decoration: underline; +} + +/* Navigation links at bottom of sections */ +a[href="#user-management-solutions-"], +a[href="#storage-management-solutions-"], +a[href="#service-management-solutions-"], +a[href="#network-solutions-"], +a[href="#security-solutions-"], +a[href="#container-management-solutions-"], +a[href="#system-recovery-solutions-"], +a[href="#shell-scripting-solutions-"] { + display: inline-block; + background-color: #f1f8ff; + padding: 0.3em 0.6em; + margin: 1.5em 0; + border-radius: 4px; + border-left: 4px solid #4183c4; + font-size: 0.9em; +} + +/* Section anchor targets */ +div[id^="scenario-"] { + scroll-margin-top: 70px; +} + /* Ensure all sections are properly visible */ .section { display: block !important; diff --git a/custom.js b/custom.js index 0519ecb..54409e4 100644 --- a/custom.js +++ b/custom.js @@ -1 +1,164 @@ - \ No newline at end of file +// Custom JavaScript for IT Learning Notes + +// Wait for the DOM to be fully loaded +document.addEventListener('DOMContentLoaded', function() { + // Improve anchor link scrolling behavior + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', function(e) { + e.preventDefault(); + const targetId = this.getAttribute('href'); + + // Only process internal page links + if (targetId.startsWith('#')) { + const targetElement = document.querySelector(targetId); + + if (targetElement) { + // Smooth scroll to the target + window.scrollTo({ + top: targetElement.offsetTop - 60, // Account for header/navigation + behavior: 'smooth' + }); + + // Update URL without reloading the page + history.pushState(null, null, targetId); + } + } + }); + }); + + // Add "Back to Top" links if they don't exist in the content + const sections = document.querySelectorAll('h2'); + sections.forEach(section => { + // Check if there's already a back-to-top link after this section + const nextElement = section.nextElementSibling; + const hasBackToTop = false; + + // Find the end of this section (next h2 or end of document) + let currentElement = section.nextElementSibling; + while (currentElement && currentElement.tagName !== 'H2') { + if (currentElement.tagName === 'A' && + currentElement.getAttribute('href') && + currentElement.getAttribute('href').includes('top')) { + hasBackToTop = true; + break; + } + currentElement = currentElement.nextElementSibling; + } + + // Add back-to-top link if needed + if (!hasBackToTop && currentElement && currentElement.tagName === 'H2') { + const backToTop = document.createElement('a'); + backToTop.href = '#'; + backToTop.textContent = 'Back to Top'; + backToTop.className = 'back-to-top'; + backToTop.style.display = 'block'; + backToTop.style.marginBottom = '2em'; + + // Insert before the next heading + section.parentNode.insertBefore(backToTop, currentElement); + } + }); + + // Fix for any dynamically loaded content + setTimeout(function() { + // Force redraw of content area + const content = document.querySelector('.content'); + if (content) { + content.style.display = 'none'; + content.offsetHeight; // Force reflow + content.style.display = 'block'; + } + + // Scroll to anchor if present in URL + if (window.location.hash) { + const element = document.getElementById(window.location.hash.substring(1)); + if (element) { + element.scrollIntoView({behavior: 'smooth'}); + } + } + }, 100); +}); + +// Create a table of contents if it doesn't exist +function generateTableOfContents() { + // Only run if we don't have a TOC div already + if (!document.querySelector('.toc')) { + const headings = document.querySelectorAll('h2'); + if (headings.length > 2) { // Only if we have a reasonable number of headings + const toc = document.createElement('div'); + toc.className = 'toc'; + + const tocTitle = document.createElement('h2'); + tocTitle.textContent = 'Table of Contents'; + toc.appendChild(tocTitle); + + const tocList = document.createElement('ul'); + + headings.forEach(heading => { + if (!heading.textContent.toLowerCase().includes('table of contents')) { + const listItem = document.createElement('li'); + const link = document.createElement('a'); + + // Create an id for the heading if it doesn't have one + if (!heading.id) { + heading.id = heading.textContent.toLowerCase() + .replace(/[^\w]+/g, '-'); + } + + link.href = '#' + heading.id; + link.textContent = heading.textContent; + + listItem.appendChild(link); + tocList.appendChild(listItem); + } + }); + + toc.appendChild(tocList); + + // Insert after the first heading (title) + const title = document.querySelector('h1'); + if (title && title.nextElementSibling) { + title.parentNode.insertBefore(toc, title.nextElementSibling.nextElementSibling); + } + } + } +} + +// Run when the page loads +window.addEventListener('load', function() { + // Generate TOC if needed + generateTableOfContents(); + + // Enable all sections that might have been hidden + document.querySelectorAll('.content-hidden') + .forEach(el => el.classList.remove('content-hidden')); +}); + +// Monitor for any dynamically added elements and ensure they're visible +const observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.addedNodes && mutation.addedNodes.length > 0) { + for (let i = 0; i < mutation.addedNodes.length; i++) { + const node = mutation.addedNodes[i]; + if (node.nodeType === 1) { // Element node + if (node.classList && ( + node.classList.contains('section') || + node.classList.contains('content') || + node.classList.contains('content-hidden') + )) { + node.style.display = 'block'; + node.style.visibility = 'visible'; + node.style.opacity = '1'; + node.classList.remove('content-hidden'); + } + } + } + } + }); +}); + +// Start observing the document body for changes +observer.observe(document.body, { + childList: true, + subtree: true +}); \ No newline at end of file diff --git a/src/SUMMARY.md b/src/SUMMARY.md index cbdda9a..b800a9c 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -15,37 +15,11 @@ # My Solutions Portfolio - [Portfolio Overview](solutions/README.md) - -## User Management [👤] -- [User Management Solutions](solutions/user-management.md) -- [Creating Users with Specific Requirements (v1-S1)](solutions/user-management.md#scenario-creating-users-with-specific-requirements) -- [Departmental User Structure (v1-S1 Expanded)](solutions/user-management.md#scenario-creating-users-with-specific-requirements-1) - -## Storage Management [💾] -- [Storage Management Solutions](solutions/storage-management.md) -- [LVM Configuration and Extension (v1-S2)](solutions/storage-management.md#scenario-v1-s2-lvm-configuration-and-management) -- [Create and Extend Logical Volume (v1-S2)](solutions/storage-management.md#scenario-v1-s2-create-a-new-2gb-partition-on-devsdb-and-extend-the-logical-volume-by-500mb-using-lvm) - -## Service Management [⚙️] -- [Service Management Solutions](solutions/service-management.md) -- [Time Synchronization and Security (v1-S3)](solutions/service-management.md#scenario-v1-s3-time-synchronization-and-security-configuration) - -## Networking [🌐] -- [Network Solutions](solutions/networking.md) -- [Network Interface Configuration (v1-S7)](solutions/networking.md#scenario-v1-s7-network-interface-configuration) - -## Security [🔒] -- [Security Solutions](solutions/security.md) -- [SELinux and Firewall Configuration (v1-S3)](solutions/security.md#scenario-v1-s3-selinux-and-firewall-configuration) - -## Container Management [📦] -- [Container Management Solutions](solutions/container-management.md) -- [Container Deployment (v1-S4)](solutions/container-management.md#scenario-v1-s4-container-management) - -## System Recovery & Maintenance [🔧] -- [System Recovery Solutions](solutions/system-recovery.md) -- [System Recovery and Maintenance (v1-S5)](solutions/system-recovery.md#scenario-v1-s5-system-recovery-and-maintenance) - -## Shell Scripting [📜] -- [Shell Scripting Solutions](solutions/shell-scripting.md) -- [File Management Script (v1-S6)](solutions/shell-scripting.md#scenario-v1-s6-shell-scripting) +- [User Management Solutions [👤]](solutions/user-management.md) +- [Storage Management Solutions [💾]](solutions/storage-management.md) +- [Service Management Solutions [⚙️]](solutions/service-management.md) +- [Network Solutions [🌐]](solutions/networking.md) +- [Security Solutions [🔒]](solutions/security.md) +- [Container Management Solutions [📦]](solutions/container-management.md) +- [System Recovery Solutions [🔧]](solutions/system-recovery.md) +- [Shell Scripting Solutions [📜]](solutions/shell-scripting.md) diff --git a/src/solutions/storage-management.md b/src/solutions/storage-management.md index 7a3484c..eebf213 100644 --- a/src/solutions/storage-management.md +++ b/src/solutions/storage-management.md @@ -2,6 +2,20 @@ This section documents my solutions to storage management scenarios, including partitioning, LVM, filesystem management, and storage troubleshooting. +
+ +## Table of Contents +- [Scenario Tags](#scenario-tags) +- [Scenario: LVM Configuration and Management](#scenario-v1-s2-lvm-configuration-and-management) +- [Scenario: Create a new 2GB partition](#scenario-v1-s2-create-a-new-2gb-partition-on-devsdb-and-extend-the-logical-volume-by-500mb-using-lvm) +- [Scenario: Storage Configuration](#scenario-v2-s2-storage-configuration) +- [Scenario: Dynamic Storage Management](#scenario-v3-s2-dynamic-storage-management) +- [Scenario: Advanced File System Management](#scenario-v3-s8-advanced-file-system-management) + +
+ +
+ ## Scenario Tags | Tag | Description | @@ -11,6 +25,10 @@ This section documents my solutions to storage management scenarios, including p | [v3-S2] | Dynamic Storage Management - Practice Scenarios v3 | | [v3-S8] | Advanced File System Management - Practice Scenarios v3 | +[Back to Top](#storage-management-solutions-) + +
+ ## Scenario: [v1-S2] LVM Configuration and Management ### Original Problem @@ -64,8 +82,9 @@ df -h - Filesystem Management - Storage Troubleshooting ---- ---- +[Back to Top](#storage-management-solutions-) + +
## Scenario: [v1-S2] Create a new 2GB partition on /dev/sdb and extend the logical volume by 500MB using LVM @@ -188,6 +207,10 @@ lsblk -f - Filesystem Management - Storage Troubleshooting +[Back to Top](#storage-management-solutions-) + +
+ ## Scenario: [v2-S2] Storage Configuration ### Original Problem @@ -208,6 +231,10 @@ From Practice Scenarios v2, Scenario 2: ### Solution Steps [Your solution will be added here] +[Back to Top](#storage-management-solutions-) + +
+ ## Scenario: [v3-S2] Dynamic Storage Management ### Original Problem @@ -228,6 +255,10 @@ From Practice Scenarios v3, Scenario 2: ### Solution Steps [Your solution will be added here] +[Back to Top](#storage-management-solutions-) + +
+ ## Scenario: [v3-S8] Advanced File System Management ### Original Problem @@ -248,4 +279,6 @@ From Practice Scenarios v3, Scenario 8: - Required Outcome: [To be filled] ### Solution Steps -[Your solution will be added here] \ No newline at end of file +[Your solution will be added here] + +[Back to Top](#storage-management-solutions-) \ No newline at end of file diff --git a/src/solutions/user-management.md b/src/solutions/user-management.md index 7264709..aeb55af 100644 --- a/src/solutions/user-management.md +++ b/src/solutions/user-management.md @@ -2,6 +2,19 @@ This section contains my solutions to various user management scenarios from the practice exercises. +
+ +## Table of Contents +- [Scenario Tags](#scenario-tags) +- [Scenario: Creating Users with Specific Requirements](#scenario-creating-users-with-specific-requirements) +- [Scenario: Creating Users with Specific Requirements (Expanded)](#scenario-creating-users-with-specific-requirements-1) +- [Scenario: System Access and File Management](#scenario-v2-s1-system-access-and-file-management) +- [Scenario: Advanced User Management](#scenario-v3-s1-advanced-user-management) + +
+ +
+ ## Scenario Tags | Tag | Description | @@ -10,6 +23,10 @@ This section contains my solutions to various user management scenarios from the | [v2-S1] | System Access and File Management - Practice Scenarios v2 | | [v3-S1] | Advanced User Management - Practice Scenarios v3 | +[Back to Top](#user-management-solutions-) + +
+ ## Scenario: Creating Users with Specific Requirements ### Original Problem @@ -51,10 +68,11 @@ From Practice Scenarios v1: Create a user named 'john' with a custom shell and h - Security Best Practices - System Verification -*** -*** +[Back to Top](#user-management-solutions-) -## Scenario: Creating Users with Specific Requirements-1 +
+ +## Scenario: Creating Users with Specific Requirements (Expanded) ### Original Problem - Create a new user called 'analyst1' with home directory '/home/analyst1' @@ -133,6 +151,10 @@ sudo chage -l analyst1 > [NOTE] > This scenario is a good example of how to create a user with a specific home directory, add them to a group, create a directory owned by the group with SGID set, and set password expiry. +[Back to Top](#user-management-solutions-) + +
+ ## Scenario: [v2-S1] System Access and File Management ### Original Problem @@ -152,6 +174,10 @@ From Practice Scenarios v2, Scenario 1: ### Solution Steps [Your solution will be added here] +[Back to Top](#user-management-solutions-) + +
+ ## Scenario: [v3-S1] Advanced User Management ### Original Problem @@ -175,3 +201,5 @@ From Practice Scenarios v3, Scenario 1: ### Solution Steps [Your solution will be added here] +[Back to Top](#user-management-solutions-) +