diff --git a/package-lock.json b/package-lock.json index d02cdbc82..5d7622b14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -78,6 +78,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", "dev": true, + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.2", @@ -3440,6 +3441,7 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -3945,6 +3947,7 @@ "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -3989,6 +3992,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -4565,6 +4569,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001587", "electron-to-chromium": "^1.4.668", @@ -7068,6 +7073,7 @@ "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-7.0.1.tgz", "integrity": "sha512-33AmZ+xjZhg2JMCe+vDf6a9mzWukE7l+wAtesjE7KyteqqKjzxv7aVQeWnul1Ve26mWvEQqyPwl0OctNBfSR9w==", "dev": true, + "peer": true, "dependencies": { "file-type": "^12.0.0", "globby": "^10.0.0", @@ -8032,6 +8038,7 @@ "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -8785,6 +8792,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", @@ -9353,6 +9361,7 @@ "version": "6.0.16", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -9971,6 +9980,7 @@ "resolved": "https://registry.npmjs.org/sass/-/sass-1.75.0.tgz", "integrity": "sha512-ShMYi3WkrDWxExyxSZPst4/okE9ts46xZmJDSawJQrnte7M1V9fScVB+uNXOVKRBt0PggHOwoZcn8mYX4trnBw==", "dev": true, + "peer": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -11123,6 +11133,7 @@ "version": "5.94.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", + "peer": true, "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", @@ -11169,6 +11180,7 @@ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", "dev": true, + "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.2.0", @@ -11260,6 +11272,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -11372,6 +11385,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", diff --git a/resources/assets/js/app.js b/resources/assets/js/app.js index 0965adf78..5be6a1051 100644 --- a/resources/assets/js/app.js +++ b/resources/assets/js/app.js @@ -6,3 +6,4 @@ require("./ckeditor.js"); require("./bootstrap.js"); require("./helpers.js"); +require("./theme.js"); diff --git a/resources/assets/js/theme.js b/resources/assets/js/theme.js new file mode 100644 index 000000000..18bc84944 --- /dev/null +++ b/resources/assets/js/theme.js @@ -0,0 +1,80 @@ +/*! + * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2025 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + */ + +(() => { + 'use strict' + + const getStoredTheme = () => localStorage.getItem('theme') + const setStoredTheme = theme => localStorage.setItem('theme', theme) + + const getPreferredTheme = () => { + const storedTheme = getStoredTheme() + if (storedTheme) { + return storedTheme + } + + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' + } + + const setTheme = theme => { + if (theme === 'auto') { + document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')) + } else { + document.documentElement.setAttribute('data-bs-theme', theme) + } + } + + setTheme(getPreferredTheme()) + + const showActiveTheme = (theme, focus = false) => { + const themeSwitcher = document.querySelector('#bd-theme') + + if (!themeSwitcher) { + return + } + + const themeSwitcherText = document.querySelector('#bd-theme-text') + const activeThemeIcon = document.querySelector('.theme-icon-active use') + const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`) + const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href') + + document.querySelectorAll('[data-bs-theme-value]').forEach(element => { + element.classList.remove('active') + element.setAttribute('aria-pressed', 'false') + }) + + btnToActive.classList.add('active') + btnToActive.setAttribute('aria-pressed', 'true') + activeThemeIcon.setAttribute('href', svgOfActiveBtn) + const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})` + themeSwitcher.setAttribute('aria-label', themeSwitcherLabel) + + if (focus) { + themeSwitcher.focus() + } + } + + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + const storedTheme = getStoredTheme() + if (storedTheme !== 'light' && storedTheme !== 'dark') { + setTheme(getPreferredTheme()) + } + }) + + window.addEventListener('DOMContentLoaded', () => { + showActiveTheme(getPreferredTheme()) + + document.querySelectorAll('[data-bs-theme-value]') + .forEach(toggle => { + toggle.addEventListener('click', () => { + const theme = toggle.getAttribute('data-bs-theme-value') + setStoredTheme(theme) + setTheme(theme) + showActiveTheme(theme, true) + }) + }) + }) +})() diff --git a/resources/assets/sass/_variables.scss b/resources/assets/sass/_variables.scss index 0e2bd9f95..2795da902 100644 --- a/resources/assets/sass/_variables.scss +++ b/resources/assets/sass/_variables.scss @@ -1,4 +1,5 @@ // Body + $body-bg: #f5f8fa; // Typography diff --git a/resources/assets/sass/app.scss b/resources/assets/sass/app.scss index ddf990cc1..53aae4afb 100644 --- a/resources/assets/sass/app.scss +++ b/resources/assets/sass/app.scss @@ -22,8 +22,8 @@ $font-family-base: "Hind Siliguri", sans-serif; html, body { - background-color: #fff; - color: black; + //background-color: #fff; + //color: black; --bs-body-font-family: "Hind Siliguri", sans-serif; --bs-body-font-size: 1rem; --bs-body-font-weight: 100; @@ -151,15 +151,16 @@ body { } .view-header { - background-color: #f0f0f0; + background-color: var(--bs-secondary-bg); } .tab-link { - color: black; +// color: black; } .item-black { - color: black; +// color: black; + color: var(--bs-body-color); } .bronze { @@ -168,6 +169,7 @@ body { div.bronze-bg { background-color: #c9ae5d; + color: rgb(33,37,41); } .pyrite { @@ -176,6 +178,7 @@ div.bronze-bg { div.pyrite-bg { background-color: #ffdf00; + color: rgb(33,37,41); } div.hours-danger, @@ -219,3 +222,14 @@ td.hours-success { a { text-decoration: none; } + +[data-bs-theme=dark] .logo-light { + display: none; +} +[data-bs-theme=light] .logo-dark { + display: none; +} + +.tab-link { + color: var(--bs-secondary-color); +} diff --git a/resources/assets/sass/mix/dashboard.scss b/resources/assets/sass/mix/dashboard.scss index 821c9d02b..77a4baa1a 100644 --- a/resources/assets/sass/mix/dashboard.scss +++ b/resources/assets/sass/mix/dashboard.scss @@ -63,7 +63,7 @@ input:checked + .slider:before { div.clocks div.card-body { text-align: center; - background-color: lightgrey; + background-color: var(--bs-tertiary-bg); } div.clocks iframe { diff --git a/resources/assets/sass/mix/footer_white.scss b/resources/assets/sass/mix/footer_white.scss index 1f47a3aaf..497911bdb 100644 --- a/resources/assets/sass/mix/footer_white.scss +++ b/resources/assets/sass/mix/footer_white.scss @@ -46,7 +46,7 @@ table.availability td.available { text-align: center; padding-top: 25px; padding-bottom: 25px; - background-color: #eee; + background-color: var(--bs-secondary-bg); } #myFooter .fa { diff --git a/resources/assets/sass/mix/roster.scss b/resources/assets/sass/mix/roster.scss index 1ae16b47f..32b08cab3 100644 --- a/resources/assets/sass/mix/roster.scss +++ b/resources/assets/sass/mix/roster.scss @@ -4,3 +4,8 @@ thead.sticky th { top: 0; box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.4); } + + +[data-bs-theme=dark] thead.sticky th { + background: var(--bs-secondary-bg); +} diff --git a/resources/assets/sass/mix/sidebar.scss b/resources/assets/sass/mix/sidebar.scss index 30be1f585..65cdf1ee7 100644 --- a/resources/assets/sass/mix/sidebar.scss +++ b/resources/assets/sass/mix/sidebar.scss @@ -6,12 +6,12 @@ } #pill-sidebar button { - color: #606060; + color: var(--bs-secondary-color); font-weight: bold; font-size: 12px; } #pill-sidebar a.nav-link { - color: black; + color: var(--bs-body-color); font-size: 14px; } diff --git a/resources/views/dashboard/admin/incident_reports/index.blade.php b/resources/views/dashboard/admin/incident_reports/index.blade.php index 5b0db652e..cdc87e42c 100644 --- a/resources/views/dashboard/admin/incident_reports/index.blade.php +++ b/resources/views/dashboard/admin/incident_reports/index.blade.php @@ -10,10 +10,10 @@
\ No newline at end of file
+
+
+
+
diff --git a/resources/views/inc/scenery_index.blade.php b/resources/views/inc/scenery_index.blade.php
index 9b1eac1c0..babce2aa8 100644
--- a/resources/views/inc/scenery_index.blade.php
+++ b/resources/views/inc/scenery_index.blade.php
@@ -27,7 +27,7 @@
@php ($active = ' active')
@endif
The Air Traffic Manager is responsible to the Deputy Director - Air Traffic Services for the overall administration of the ARTCC. The ATM is responsible for appointing ARTCC staff members and delegation of authorities.
The Deputy Air Traffic Manager reports to the Air Traffic Manager and acts as Air Traffic Manager in their absence. The Deputy Air Traffic Manager is jointly responsible for administration and accuracy of the roster including visiting controllers.
The Training Administrator works with the Air Traffic Manager and Deputy Air Traffic Manager to build training programs, establish training procedures and recommend instructors and mentors. The Training Administrator works with Instructors and Mentors to develop knowledge and mentors to help develop teaching ability.
Responsible to the Air Traffic Manager for the operation and maintenance of all IT services including, but not limited to, the Website, TeamSpeak and Email services and any other tasking as directed.
The Events Coordinator is responsible to the Deputy Air Traffic Manager for the coordination, planning, dissemination and creation of events to neighboring facilities, virtual airlines, VATUSA and VATSIM.
@@ -124,7 +124,7 @@ {{ $s->full_name }} @endforeach @endif - +The Facility Engineer is responsible to the Senior Staff for creation of sector files, radar client files, training scenarios, Letters of Agreement, Memorandums of Understanding, Standard Operating Procedures and other requests as directed and submission to the Air Traffic Manager for approval prior to dissemination.