Explorar o código

refactor(ux): update dependencies + adapt to SASS 2.0 color functions

NGPixel hai 7 meses
pai
achega
c9c071fe58

+ 0 - 4
ux/.eslintignore

@@ -1,4 +0,0 @@
-/dist
-/.quasar
-/node_modules
-.eslintrc.js

+ 0 - 87
ux/.eslintrc.cjs

@@ -1,87 +0,0 @@
-module.exports = {
-  // https://eslint.org/docs/user-guide/configuring#configuration-cascading-and-hierarchy
-  // This option interrupts the configuration hierarchy at this file
-  // Remove this if you have an higher level ESLint config file (it usually happens into a monorepos)
-  root: true,
-
-  parserOptions: {
-    ecmaVersion: '2021' // Allows for the parsing of modern ECMAScript features
-  },
-
-  env: {
-    node: true,
-    browser: true,
-    'vue/setup-compiler-macros': true
-  },
-
-  // Rules order is important, please avoid shuffling them
-  extends: [
-    // Base ESLint recommended rules
-    // 'eslint:recommended',
-
-    // Uncomment any of the lines below to choose desired strictness,
-    // but leave only one uncommented!
-    // See https://eslint.vuejs.org/rules/#available-rules
-    // 'plugin:vue/vue3-essential', // Priority A: Essential (Error Prevention)
-    'plugin:vue/vue3-strongly-recommended', // Priority B: Strongly Recommended (Improving Readability)
-    // 'plugin:vue/vue3-recommended', // Priority C: Recommended (Minimizing Arbitrary Choices and Cognitive Overhead)
-
-    'plugin:vue-pug/vue3-strongly-recommended',
-
-    'standard'
-  ],
-
-  plugins: [
-    // https://eslint.vuejs.org/user-guide/#why-doesn-t-it-work-on-vue-files
-    // required to lint *.vue files
-    'vue'
-  ],
-
-  globals: {
-    ga: 'readonly', // Google Analytics
-    __statics: 'readonly',
-    __QUASAR_SSR__: 'readonly',
-    __QUASAR_SSR_SERVER__: 'readonly',
-    __QUASAR_SSR_CLIENT__: 'readonly',
-    __QUASAR_SSR_PWA__: 'readonly',
-    process: 'readonly',
-    APOLLO_CLIENT: 'readonly',
-    EVENT_BUS: 'readonly'
-  },
-
-  // add your custom rules here
-  rules: {
-    // allow async-await
-    'generator-star-spacing': 'off',
-    // allow paren-less arrow functions
-    'arrow-parens': 'off',
-    'one-var': 'off',
-    'no-void': 'off',
-    'multiline-ternary': 'off',
-
-    'import/first': 'off',
-    'import/named': 'error',
-    'import/namespace': 'error',
-    'import/default': 'error',
-    'import/export': 'error',
-    'import/extensions': 'off',
-    'import/no-unresolved': 'off',
-    'import/no-extraneous-dependencies': 'off',
-
-    'prefer-promise-reject-errors': 'off',
-
-    'no-unused-vars': 'off',
-    'vue/multi-word-component-names': 'off',
-
-    // allow debugger during development only
-    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
-
-    // disable bogus rules
-    'vue/valid-template-root': 'off',
-    'vue/no-parsing-error': 'off',
-    'vue-pug/no-parsing-error': 'off',
-    'vue/valid-v-for': 'off',
-    'vue/html-quotes': ['warn', 'single'],
-    'vue/max-attributes-per-line': 'off'
-  }
-}

+ 74 - 0
ux/eslint.config.mjs

@@ -0,0 +1,74 @@
+import js from '@eslint/js'
+import neostandard from 'neostandard'
+import pluginVue from 'eslint-plugin-vue'
+import vueParser from 'vue-eslint-parser'
+import { FlatCompat } from '@eslint/eslintrc'
+
+const compat = new FlatCompat()
+
+export default [
+  js.configs.recommended,
+  ...pluginVue.configs['flat/essential'],
+  ...neostandard(),
+  ...compat.extends(
+    'plugin:vue-pug/vue3-recommended'
+  ),
+  {
+    ignores: [
+      '/dist',
+      '/.quasar',
+      '/node_modules'
+    ],
+    languageOptions: {
+      ecmaVersion: 'latest',
+      sourceType: 'module',
+      parser: vueParser,
+      globals: {
+        __statics: 'readonly',
+        __QUASAR_SSR__: 'readonly',
+        __QUASAR_SSR_SERVER__: 'readonly',
+        __QUASAR_SSR_CLIENT__: 'readonly',
+        __QUASAR_SSR_PWA__: 'readonly',
+        process: 'readonly',
+        Capacitor: 'readonly',
+        chrome: 'readonly',
+        APOLLO_CLIENT: 'readonly',
+        EVENT_BUS: 'readonly'
+      }
+    },
+    rules: {
+      // allow async-await
+      'generator-star-spacing': 'off',
+      // allow paren-less arrow functions
+      'arrow-parens': 'off',
+      'one-var': 'off',
+      'no-void': 'off',
+      'multiline-ternary': 'off',
+
+      'import/first': 'off',
+      'import/named': 'error',
+      'import/namespace': 'error',
+      'import/default': 'error',
+      'import/export': 'error',
+      'import/extensions': 'off',
+      'import/no-unresolved': 'off',
+      'import/no-extraneous-dependencies': 'off',
+
+      'prefer-promise-reject-errors': 'off',
+
+      'no-unused-vars': 'off',
+      'vue/multi-word-component-names': 'off',
+
+      // allow debugger during development only
+      'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
+
+      // disable bogus rules
+      'vue/valid-template-root': 'off',
+      'vue/no-parsing-error': 'off',
+      'vue-pug/no-parsing-error': 'off',
+      'vue/valid-v-for': 'off',
+      'vue/html-quotes': ['warn', 'single'],
+      'vue/max-attributes-per-line': 'off'
+    }
+  }
+]

+ 64 - 64
ux/package.json

@@ -11,36 +11,36 @@
     "build": "NODE_OPTIONS=--max-old-space-size=8192 vite build --emptyOutDir"
   },
   "dependencies": {
-    "@apollo/client": "3.10.8",
-    "@lezer/common": "1.2.1",
+    "@apollo/client": "3.11.8",
+    "@lezer/common": "1.2.3",
     "@mdi/font": "7.4.47",
     "@quasar/extras": "1.16.12",
-    "@simplewebauthn/browser": "10.0.0",
-    "@tiptap/core": "2.4.0",
-    "@tiptap/extension-code-block": "2.4.0",
-    "@tiptap/extension-code-block-lowlight": "2.4.0",
-    "@tiptap/extension-color": "2.4.0",
-    "@tiptap/extension-dropcursor": "2.4.0",
-    "@tiptap/extension-font-family": "2.4.0",
-    "@tiptap/extension-gapcursor": "2.4.0",
-    "@tiptap/extension-hard-break": "2.4.0",
-    "@tiptap/extension-highlight": "2.4.0",
-    "@tiptap/extension-history": "2.4.0",
-    "@tiptap/extension-image": "2.4.0",
-    "@tiptap/extension-mention": "2.4.0",
-    "@tiptap/extension-placeholder": "2.4.0",
-    "@tiptap/extension-table": "2.4.0",
-    "@tiptap/extension-table-cell": "2.4.0",
-    "@tiptap/extension-table-header": "2.4.0",
-    "@tiptap/extension-table-row": "2.4.0",
-    "@tiptap/extension-task-item": "2.4.0",
-    "@tiptap/extension-task-list": "2.4.0",
-    "@tiptap/extension-text-align": "2.4.0",
-    "@tiptap/extension-text-style": "2.4.0",
-    "@tiptap/extension-typography": "2.4.0",
-    "@tiptap/pm": "2.4.0",
-    "@tiptap/starter-kit": "2.4.0",
-    "@tiptap/vue-3": "2.4.0",
+    "@simplewebauthn/browser": "11.0.0",
+    "@tiptap/core": "2.8.0",
+    "@tiptap/extension-code-block": "2.8.0",
+    "@tiptap/extension-code-block-lowlight": "2.8.0",
+    "@tiptap/extension-color": "2.8.0",
+    "@tiptap/extension-dropcursor": "2.8.0",
+    "@tiptap/extension-font-family": "2.8.0",
+    "@tiptap/extension-gapcursor": "2.8.0",
+    "@tiptap/extension-hard-break": "2.8.0",
+    "@tiptap/extension-highlight": "2.8.0",
+    "@tiptap/extension-history": "2.8.0",
+    "@tiptap/extension-image": "2.8.0",
+    "@tiptap/extension-mention": "2.8.0",
+    "@tiptap/extension-placeholder": "2.8.0",
+    "@tiptap/extension-table": "2.8.0",
+    "@tiptap/extension-table-cell": "2.8.0",
+    "@tiptap/extension-table-header": "2.8.0",
+    "@tiptap/extension-table-row": "2.8.0",
+    "@tiptap/extension-task-item": "2.8.0",
+    "@tiptap/extension-task-list": "2.8.0",
+    "@tiptap/extension-text-align": "2.8.0",
+    "@tiptap/extension-text-style": "2.8.0",
+    "@tiptap/extension-typography": "2.8.0",
+    "@tiptap/pm": "2.8.0",
+    "@tiptap/starter-kit": "2.8.0",
+    "@tiptap/vue-3": "2.8.0",
     "@vue/repl": "3.4.0",
     "@xterm/xterm": "5.5.0",
     "apollo-upload-client": "18.0.1",
@@ -49,10 +49,10 @@
     "codemirror": "5.65.11",
     "codemirror-asciidoc": "1.0.4",
     "dependency-graph": "1.0.0",
-    "filesize": "10.1.4",
-    "filesize-parser": "1.5.0",
+    "filesize": "10.1.6",
+    "filesize-parser": "1.5.1",
     "fuse.js": "7.0.0",
-    "graphql": "16.8.1",
+    "graphql": "16.9.0",
     "graphql-tag": "2.12.6",
     "highlight.js": "11.10.0",
     "js-cookie": "3.0.5",
@@ -60,10 +60,10 @@
     "katex": "0.16.11",
     "lodash-es": "4.17.21",
     "lowlight": "3.1.0",
-    "luxon": "3.4.4",
+    "luxon": "3.5.0",
     "markdown-it": "14.1.0",
     "markdown-it-abbr": "2.0.0",
-    "markdown-it-attrs": "4.1.6",
+    "markdown-it-attrs": "4.2.0",
     "markdown-it-decorate": "1.2.2",
     "markdown-it-emoji": "3.0.0",
     "markdown-it-expand-tabs": "1.0.13",
@@ -76,54 +76,54 @@
     "markdown-it-sup": "2.0.0",
     "markdown-it-task-lists": "2.1.1",
     "mitt": "3.0.1",
-    "monaco-editor": "0.50.0",
+    "monaco-editor": "0.52.0",
     "pako": "2.1.0",
-    "pinia": "2.1.7",
-    "prosemirror-commands": "1.5.2",
+    "pinia": "2.2.4",
+    "prosemirror-commands": "1.6.1",
     "prosemirror-history": "1.4.1",
     "prosemirror-keymap": "1.2.2",
-    "prosemirror-model": "1.21.3",
-    "prosemirror-schema-list": "1.4.0",
+    "prosemirror-model": "1.23.0",
+    "prosemirror-schema-list": "1.4.1",
     "prosemirror-state": "1.4.3",
-    "prosemirror-transform": "1.9.0",
-    "prosemirror-view": "1.33.8",
+    "prosemirror-transform": "1.10.2",
+    "prosemirror-view": "1.34.3",
     "pug": "3.0.3",
-    "quasar": "2.16.6",
+    "quasar": "2.17.1",
     "slugify": "1.6.6",
-    "socket.io-client": "4.7.5",
-    "sortablejs": "1.15.2",
+    "socket.io-client": "4.8.0",
+    "sortablejs": "1.15.3",
     "sortablejs-vue3": "1.2.11",
-    "tabulator-tables": "6.2.1",
+    "tabulator-tables": "6.3.0",
     "tippy.js": "6.3.7",
     "twemoji": "14.0.2",
-    "typescript": "5.5.3",
+    "typescript": "5.6.3",
     "uuid": "10.0.0",
-    "v-network-graph": "0.9.16",
-    "vue": "3.4.31",
-    "vue-i18n": "9.13.1",
-    "vue-router": "4.4.0",
+    "v-network-graph": "0.9.17",
+    "vue": "3.5.12",
+    "vue-i18n": "10.0.4",
+    "vue-router": "4.4.5",
     "vue3-otp-input": "0.5.21",
     "vuedraggable": "4.1.0",
     "zxcvbn": "4.4.2"
   },
   "devDependencies": {
-    "@eslint/js": "8.57.0",
-    "@intlify/unplugin-vue-i18n": "4.0.0",
-    "@quasar/app-vite": "2.0.0-beta.15",
-    "@quasar/vite-plugin": "1.7.0",
-    "@types/lodash": "4.17.6",
-    "@vue/devtools": "7.0.27",
-    "@vue/language-plugin-pug": "2.0.26",
-    "autoprefixer": "10.4.19",
+    "@eslint/js": "9.13.0",
+    "@intlify/unplugin-vue-i18n": "5.2.0",
+    "@quasar/app-vite": "2.0.0-beta.24",
+    "@quasar/vite-plugin": "1.8.0",
+    "@types/lodash": "4.17.12",
+    "@vue/devtools": "7.5.2",
+    "@vue/language-plugin-pug": "2.1.6",
+    "autoprefixer": "10.4.20",
     "browserlist": "latest",
-    "eslint": "8.57.0",
-    "eslint-config-standard": "17.1.0",
-    "eslint-plugin-import": "2.29.1",
-    "eslint-plugin-n": "16.6.2",
-    "eslint-plugin-promise": "6.4.0",
-    "eslint-plugin-vue": "9.27.0",
+    "eslint": "9.13.0",
+    "eslint-plugin-import": "2.31.0",
+    "eslint-plugin-n": "17.11.1",
+    "eslint-plugin-promise": "7.1.0",
+    "eslint-plugin-vue": "9.29.0",
     "eslint-plugin-vue-pug": "0.6.2",
-    "sass": "1.77.8"
+    "neostandard": "0.11.6",
+    "sass": "1.80.3"
   },
   "engines": {
     "node": ">= 18.0",

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 353 - 241
ux/pnpm-lock.yaml


+ 4 - 2
ux/src/components/EditorMarkdown.vue

@@ -760,6 +760,8 @@ function notImplemented () {
 </script>
 
 <style lang="scss">
+@use 'sass:color';
+
 $editor-height: calc(100vh - 64px - 96px);
 $editor-preview-height: calc(100vh - 64px - 96px - 32px);
 $editor-height-mobile: calc(100vh - 112px - 16px);
@@ -892,13 +894,13 @@ $editor-height-mobile: calc(100vh - 112px - 16px);
   }
   &-toolbar {
     background-color: $primary;
-    border-left: 60px solid darken($primary, 5%);
+    border-left: 60px solid color.adjust($primary, $lightness: -5%);
     color: #FFF;
     height: 32px;
   }
   &-sidebar {
     background-color: $dark-4;
-    border-top: 32px solid darken($primary, 10%);
+    border-top: 32px solid color.adjust($primary, $lightness: -10%);
     color: #FFF;
     width: 56px;
     display: flex;

+ 4 - 2
ux/src/components/NavEditOverlay.vue

@@ -682,6 +682,8 @@ onBeforeUnmount(() => {
 </script>
 
 <style lang="scss" scoped>
+@use 'sass:color';
+
 .nav-edit {
   height: 100%;
 
@@ -752,7 +754,7 @@ onBeforeUnmount(() => {
 .nav-edit-item-header, .nav-edit-item-separator {
   & + .nav-edit-item-link.is-nested {
     background-color: $negative !important;
-    border-left-color: darken($negative, 10%) !important;
+    border-left-color: color.adjust($negative, $lightness: -10%) !important;
 
     & + div:not(.is-nested) {
       &::before {
@@ -769,7 +771,7 @@ onBeforeUnmount(() => {
 
   .is-nested:first-child {
     background-color: $negative !important;
-    border-left-color: darken($negative, 10%) !important;
+    border-left-color: color.adjust($negative, $lightness: -10%) !important;
 
     & + div:not(.is-nested) {
       &::before {

+ 3 - 1
ux/src/components/PageDataDialog.vue

@@ -143,6 +143,8 @@ function editTemplates () {
 </script>
 
 <style lang="scss">
+@use 'sass:color';
+
 .page-data-dialog {
   &-selector {
     @at-root .body--light & {
@@ -153,7 +155,7 @@ function editTemplates () {
     @at-root .body--dark & {
       background-color: $dark-4;
       box-shadow: inset 0px 1px 0 0 rgba(0,0,0, 0.75), inset 0px -1px 0 0 rgba(0,0,0,.75), 0 -1px 0 0 rgba(255,255,255,.1);
-      border-bottom: 1px solid lighten($dark-3, 10%);
+      border-bottom: 1px solid color.adjust($dark-3, $lightness: 10%);
     }
   }
 }

+ 5 - 3
ux/src/components/PageDataTemplateDialog.vue

@@ -343,6 +343,8 @@ onMounted(() => {
 </script>
 
 <style lang="scss">
+@use 'sass:color';
+
 .page-datatmpl {
   &-selector {
     @at-root .body--light & {
@@ -353,7 +355,7 @@ onMounted(() => {
     @at-root .body--dark & {
       background-color: $dark-4;
       box-shadow: inset 0px 1px 0 0 rgba(0,0,0, 0.75), inset 0px -1px 0 0 rgba(0,0,0,.75), 0 -1px 0 0 rgba(255,255,255,.1);
-      border-bottom: 1px solid lighten($dark-3, 10%);
+      border-bottom: 1px solid color.adjust($dark-3, $lightness: 10%);
     }
   }
   &-sd {
@@ -366,7 +368,7 @@ onMounted(() => {
       border-right: 1px solid $grey-4;
     }
     @at-root .body--dark & {
-      background-color: lighten($dark-3, 2%);
+      background-color: color.adjust($dark-3, $lightness: 2%);
       border-right: 1px solid $dark-5;
     }
 
@@ -425,7 +427,7 @@ onMounted(() => {
       }
     }
     @at-root .body--dark & {
-      background-color: lighten($dark-3, 2%);
+      background-color: color.adjust($dark-3, $lightness: 2%);
       box-shadow: inset 0 -1px 0 0 $dark-6;
       border-bottom-color: rgba(255,255,255,.1);
 

+ 4 - 2
ux/src/components/SideDialog.vue

@@ -73,6 +73,8 @@ const state = reactive({
 </script>
 
 <style lang="scss">
+@use 'sass:color';
+
 .floating-sidepanel {
   .q-dialog__inner {
     right: 24px;
@@ -96,9 +98,9 @@ const state = reactive({
     }
     @at-root .body--dark & {
       background-color: $dark-4;
-      border-top: 1px solid lighten($dark-3, 8%);
+      border-top: 1px solid color.adjust($dark-3, $lightness: 8%);
       box-shadow: inset 0 1px 0 0 $dark-6, inset 0 -1px 0 0 $dark-6;
-      border-bottom: 1px solid lighten($dark-3, 8%);
+      border-bottom: 1px solid color.adjust($dark-3, $lightness: 8%);
     }
   }
 

+ 4 - 3
ux/src/components/TreeBrowserDialog.vue

@@ -425,8 +425,9 @@ onMounted(() => {
 </script>
 
 <style lang="scss">
-.page-save-dialog {
+@use 'sass:color';
 
+.page-save-dialog {
   &-browser {
     height: 300px;
     max-height: 90vh;
@@ -479,12 +480,12 @@ onMounted(() => {
     border-bottom: 1px solid #FFF;
 
     @at-root .body--light & {
-      background-color: lighten($blue-grey-1, 4%);
+      background-color: color.adjust($blue-grey-1, $lightness: 4%);
       border-bottom-color: $blue-grey-1;
       color: $blue-grey-9;
     }
     @at-root .body--dark & {
-      background-color: darken($dark-4, 1%);
+      background-color: color.adjust($dark-4, $lightness: -1%);
       border-bottom-color: $dark-1;
       color: $blue-grey-3;
     }

+ 0 - 0
ux/src/css/animation.scss → ux/src/css/_animation.scss


+ 269 - 0
ux/src/css/_base.scss

@@ -0,0 +1,269 @@
+@use 'sass:color';
+@use '../../node_modules/quasar/src/css/variables.sass' as quasar;
+@use 'theme';
+
+// app global css in SCSS form
+// ------------------------------------------------------------------
+// SCROLLBAR
+// ------------------------------------------------------------------
+
+html {
+  --scrollbarBG: #CCC;
+  --thumbBG: #999;
+}
+body::-webkit-scrollbar {
+  width: 7px;
+}
+body {
+  scrollbar-width: thin;
+  scrollbar-color: var(--thumbBG) var(--scrollbarBG);
+}
+body::-webkit-scrollbar-track {
+  background: var(--scrollbarBG);
+}
+body::-webkit-scrollbar-thumb {
+  background-color: var(--thumbBG);
+  border-radius: 6px;
+  border: 1px solid var(--scrollbarBG);
+}
+
+// ------------------------------------------------------------------
+// FONTS
+// ------------------------------------------------------------------
+
+@font-face {
+  font-family: 'Roboto Mono';
+  src: url(/_assets/fonts/roboto-mono/roboto-mono.woff2);
+}
+
+.font-robotomono {
+  font-family: 'Roboto Mono', Consolas, "Liberation Mono", Courier, monospace;
+}
+
+.text-wordbreak-all {
+  word-break: break-all;
+}
+
+// ------------------------------------------------------------------
+// THEME COLORS
+// ------------------------------------------------------------------
+
+:root {
+  --q-header: #000;
+  --q-sidebar: #1976D2;
+}
+
+.header, .bg-header {
+  background: #000;
+  background: var(--q-header);
+}
+.sidebar, .bg-sidebar {
+  background: #1976D2;
+  background: var(--q-sidebar);
+}
+
+.bg-dark-6 { background-color: #070a0d; }
+.bg-dark-5 { background-color: #0d1117; }
+.bg-dark-4 { background-color: #161b22; }
+.bg-dark-3 { background-color: #1e232a; }
+.bg-dark-2 { background-color: #292f39; }
+.bg-dark-1 { background-color: #343b48; }
+
+// ------------------------------------------------------------------
+// FORMS
+// ------------------------------------------------------------------
+
+.v-textarea.is-monospaced textarea {
+  font-family: 'Roboto Mono', 'Courier New', Courier, monospace;
+  font-size: 13px;
+  font-weight: 600;
+  line-height: 1.4;
+}
+
+.q-field.denser .q-field__control {
+  height: 36px;
+
+  .q-field__prepend {
+    height: 36px;
+  }
+}
+
+.q-field.fill-outline .q-field__control {
+  background-color: #FFF;
+
+  @at-root .body--light & {
+    background-color: #FFF;
+  }
+  @at-root .body--dark & {
+    background-color: theme.$dark;
+  }
+}
+
+.q-field--dark .q-field__control:before {
+  background-color: theme.$dark-5;
+  border-color: rgba(255,255,255,.25);
+}
+
+// ------------------------------------------------------------------
+// ICONS SIZE FIX
+// ------------------------------------------------------------------
+
+.q-btn .q-icon {
+  &.fa-solid,
+  &.fa-regular {
+    font-size: 1.3em;
+  }
+}
+
+.q-select__dropdown-icon {
+  font-size: 16px;
+}
+
+// ------------------------------------------------------------------
+// BUTTONS
+// ------------------------------------------------------------------
+
+.q-btn.acrylic-btn {
+  .q-focus-helper {
+    background-color: currentColor;
+    opacity: .1;
+  }
+
+  &:hover .q-focus-helper {
+    opacity: .3 !important;
+  }
+}
+
+// ------------------------------------------------------------------
+// ICONS
+// ------------------------------------------------------------------
+
+.blueprint-icon {
+  &-alt {
+    filter: hue-rotate(100);
+  }
+}
+
+// ------------------------------------------------------------------
+// DIALOGS
+// ------------------------------------------------------------------
+
+.card-header {
+  display: flex;
+  align-items: center;
+  font-weight: 500;
+  font-size: .9rem;
+  background-color: theme.$dark-3;
+  background-image: radial-gradient(at bottom right, theme.$dark-3, theme.$dark-5);
+  color: #FFF;
+
+  @at-root .body--light & {
+    border-bottom: 1px solid theme.$dark-3;
+    box-shadow: 0 1px 0 0 theme.$dark-6;
+  }
+  @at-root .body--dark & {
+    border-bottom: 1px solid #000;
+    box-shadow: 0 1px 0 0 color.adjust(theme.$dark-3, $lightness: 2%);
+  }
+}
+
+.card-negative {
+  display: flex;
+  align-items: center;
+  font-size: .9rem;
+
+  @at-root .body--light & {
+    background-color: quasar.$red-1;
+    background-image: radial-gradient(at bottom center, color.adjust(quasar.$red-1, $lightness: 2%), color.adjust(quasar.$red-2, $lightness: 2%));
+    border-bottom: 1px solid quasar.$red-3;
+    text-shadow: 0 0 4px #FFF;
+    color: quasar.$red-9;
+  }
+  @at-root .body--dark & {
+    background-color: quasar.$red-9;
+    background-image: radial-gradient(at bottom center, quasar.$red-7, quasar.$red-9);
+    border-bottom: 1px solid quasar.$red-7;
+    text-shadow: 0 0 4px color.adjust(quasar.$red-9, $lightness: -10%);
+    color: #FFF;
+  }
+}
+
+.card-actions {
+  @at-root .body--light & {
+    background-color: #FAFAFA;
+    background-image: linear-gradient(to bottom, #FCFCFC, #F0F0F0);
+    color: theme.$dark-3;
+    border-top: 1px solid #EEE;
+    box-shadow: inset 0 1px 0 0 #FFF;
+  }
+  @at-root .body--dark & {
+    background-color: theme.$dark-3;
+    background-image: radial-gradient(at top left, theme.$dark-3, theme.$dark-5);
+    border-top: 1px solid #000;
+    box-shadow: 0 -1px 0 0 color.adjust(theme.$dark-3, $lightness: 2%);
+  }
+}
+
+// ------------------------------------------------------------------
+// CARDS
+// ------------------------------------------------------------------
+
+.q-card {
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12);
+
+  &.q-card--dark {
+    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12);
+  }
+
+  .q-separator--dark {
+    background-color: rgba(0,0,0,.7);
+  }
+}
+
+// ------------------------------------------------------------------
+// DROPDOWN MENUS
+// ------------------------------------------------------------------
+
+.translucent-menu {
+  backdrop-filter: blur(10px) saturate(180%);
+
+  @at-root .body--light & {
+    background-color: rgba(255,255,255,.8);
+  }
+  @at-root .body--dark & {
+    background-color: rgba(theme.$dark,.7);
+  }
+
+  > .q-card {
+    background-color: transparent !important;
+  }
+}
+
+.q-menu--dark {
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12);
+}
+
+// ------------------------------------------------------------------
+// LOADING ANIMATIONS
+// ------------------------------------------------------------------
+
+.syncing-enter-active {
+  animation: syncing-anim .1s;
+}
+.syncing-leave-active {
+  animation: syncing-anim 1s reverse;
+}
+@keyframes syncing-anim {
+  0% {
+    opacity: 0;
+  }
+  100% {
+    opacity: 1;
+  }
+}
+
+.loading-darker {
+  .q-loading__backdrop {
+    opacity: .75;
+  }
+}

+ 71 - 67
ux/src/css/page-contents.scss → ux/src/css/_page-contents.scss

@@ -1,3 +1,7 @@
+@use 'sass:color';
+@use '../../node_modules/quasar/src/css/variables.sass' as quasar;
+@use 'theme';
+
 .page-contents {
   color: #424242;
   font-size: 16px;
@@ -18,10 +22,10 @@
     color: var(--q-primary);
 
     &.is-internal-link.is-invalid-page {
-      color: $red-8;
+      color: quasar.$red-8;
 
       @at-root .body--dark & {
-        color: $red-2;
+        color: quasar.$red-2;
       }
     }
 
@@ -34,13 +38,13 @@
         padding-left: 3px;
         display: inline-block;
         content: "\f35d";
-        color: $grey-5;
+        color: quasar.$grey-5;
         text-decoration: none;
       }
     }
 
     @at-root .body--dark & {
-      color: $blue-4;
+      color: quasar.$blue-4;
     }
   }
 
@@ -138,14 +142,14 @@
 
   blockquote {
     padding: 1em 1em .3em 1em;
-    background-color: $blue-grey-1;
-    border-left: 55px solid $blue-grey-5;
+    background-color: quasar.$blue-grey-1;
+    border-left: 55px solid quasar.$blue-grey-5;
     border-radius: .5rem;
     margin: 1rem 0;
     position: relative;
 
     @at-root .body--dark & {
-      background-color: $blue-grey-9;
+      background-color: quasar.$blue-grey-9;
     }
 
     &::before {
@@ -169,84 +173,84 @@
     }
 
     &.is-info {
-      background-color: $blue-1;
-      border-color: $blue-3;
-      color: $blue-9;
+      background-color: quasar.$blue-1;
+      border-color: quasar.$blue-3;
+      color: quasar.$blue-9;
 
       &::before {
         content: "\F02FC";
       }
 
       code {
-        background-color: $blue-1;
-        color: $blue-8;
+        background-color: quasar.$blue-1;
+        color: quasar.$blue-8;
       }
 
       @at-root .body--dark & {
-        background-color: $blue-9;
-        color: $blue-5;
-        border-color: $blue-5;
+        background-color: quasar.$blue-9;
+        color: quasar.$blue-5;
+        border-color: quasar.$blue-5;
       }
     }
     &.is-warning {
-      background-color: $orange-1;
-      border-color: $orange-3;
-      color: darken($orange-9, 10%);
+      background-color: quasar.$orange-1;
+      border-color: quasar.$orange-3;
+      color: color.adjust(quasar.$orange-9, $lightness: -10%);
 
       &::before {
         content: "\F0026";
       }
 
       code {
-        background-color: $orange-1;
-        color: $orange-8;
+        background-color: quasar.$orange-1;
+        color: quasar.$orange-8;
       }
 
       @at-root .body--dark & {
-        background-color: darken($orange-9, 5%);
-        color: $orange-1;
-        border-color: $orange-5;
-        box-shadow: 0 0 2px 0 $grey-9;
+        background-color: color.adjust(quasar.$orange-9, $lightness: -5%);
+        color: quasar.$orange-1;
+        border-color: quasar.$orange-5;
+        box-shadow: 0 0 2px 0 quasar.$grey-9;
       }
     }
     &.is-danger {
-      background-color: $red-1;
-      border-color: $red-3;
-      color: $red-9;
+      background-color: quasar.$red-1;
+      border-color: quasar.$red-3;
+      color: quasar.$red-9;
 
       &::before {
         content: "\F0159";
       }
 
       code {
-        background-color: $red-1;
-        color: $red-8;
+        background-color: quasar.$red-1;
+        color: quasar.$red-8;
       }
 
       @at-root .body--dark & {
-        background-color: $red-9;
-        color: $red-1;
-        border-color: $red-5;
+        background-color: quasar.$red-9;
+        color: quasar.$red-1;
+        border-color: quasar.$red-5;
       }
     }
     &.is-success {
-      background-color: $green-1;
-      border-color: $green-3;
-      color: $green-9;
+      background-color: quasar.$green-1;
+      border-color: quasar.$green-3;
+      color: quasar.$green-9;
 
       &::before {
         content: "\F0E1E";
       }
 
       code {
-        background-color: $green-1;
-        color: $green-8;
+        background-color: quasar.$green-1;
+        color: quasar.$green-8;
       }
 
       @at-root .body--dark & {
-        background-color: $green-9;
-        color: $green-5;
-        border-color: $green-5;
+        background-color: quasar.$green-9;
+        color: quasar.$green-5;
+        border-color: quasar.$green-5;
       }
     }
 
@@ -300,11 +304,11 @@
       }
 
       li {
-        background-color: $grey-1;
-        background-image: linear-gradient(to bottom, #FFF, $grey-1);
-        border-right: 1px solid $grey-3;
-        border-bottom: 1px solid $grey-3;
-        border-left: 5px solid $grey-4;
+        background-color: quasar.$grey-1;
+        background-image: linear-gradient(to bottom, #FFF, quasar.$grey-1);
+        border-right: 1px solid quasar.$grey-3;
+        border-bottom: 1px solid quasar.$grey-3;
+        border-left: 5px solid quasar.$grey-4;
         box-shadow: 0 3px 8px 0 rgba(116, 129, 141, 0.1);
         padding: 1rem;
         border-radius: 5px;
@@ -316,13 +320,13 @@
         }
 
         &:hover {
-          background-image: linear-gradient(to bottom, #FFF, lighten($blue-1, 4%));
-          border-left-color: $blue-5;
+          background-image: linear-gradient(to bottom, #FFF, color.adjust(quasar.$blue-1, $lightness: 4%));
+          border-left-color: quasar.$blue-5;
           cursor: pointer;
 
           @at-root .is-rtl & {
-            border-left-color: $grey-3;
-            border-right-width: $blue-5;
+            border-left-color: quasar.$grey-3;
+            border-right-width: quasar.$blue-5;
           }
         }
 
@@ -340,10 +344,10 @@
           > em {
             font-weight: 400;
             font-style: normal;
-            color: $grey-7;
+            color: quasar.$grey-7;
             display: inline-block;
             padding-left: .5rem;
-            border-left: 1px solid $grey-4;
+            border-left: 1px solid quasar.$grey-4;
             margin-left: .5rem;
 
             &.is-block {
@@ -361,11 +365,11 @@
         }
 
         @at-root .body--dark & {
-          background-color: $grey-1;
-          background-image: linear-gradient(to bottom, lighten($grey-9, 5%), $grey-9);
-          border-right: 1px solid $grey-9;
-          border-bottom: 1px solid $grey-9;
-          border-left: 5px solid $grey-7;
+          background-color: quasar.$grey-1;
+          background-image: linear-gradient(to bottom, color.adjust(quasar.$grey-9, $lightness: 5%), quasar.$grey-9);
+          border-right: 1px solid quasar.$grey-9;
+          border-bottom: 1px solid quasar.$grey-9;
+          border-left: 5px solid quasar.$grey-7;
           box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.1);
 
           @at-root .body--dark.is-rtl & {
@@ -374,12 +378,12 @@
           }
 
           &:hover {
-            background-image: linear-gradient(to bottom, lighten($grey-9, 2%), darken($grey-9, 3%));
+            background-image: linear-gradient(to bottom, color.adjust(quasar.$grey-9, $lightness: 2%), color.adjust(quasar.$grey-9, $lightness: -3%));
             border-left-color: mc('indigo', '300');
             cursor: pointer;
 
             @at-root .body--dark.is-rtl & {
-              border-left-color: $grey-9;
+              border-left-color: quasar.$grey-9;
               border-right-width: mc('indigo', '300');
             }
           }
@@ -390,7 +394,7 @@
     &.grid-list {
       margin: 1rem 0 0 0;
       background-color: #FFF;
-      border: 1px solid $grey-3;
+      border: 1px solid quasar.$grey-3;
       padding: 1px;
       display: inline-block;
       list-style-type: none;
@@ -401,7 +405,7 @@
       }
 
       li {
-        background-color: $grey-1;
+        background-color: quasar.$grey-1;
         padding: .6rem 1rem;
         display: block;
 
@@ -419,10 +423,10 @@
         }
 
         @at-root .body--dark & {
-          background-color: $grey-9;
+          background-color: quasar.$grey-9;
 
           &:nth-child(odd) {
-            background-color: darken($grey-9, 5%);
+            background-color: color.adjust(quasar.$grey-9, $lightness: -5%);
           }
         }
       }
@@ -461,7 +465,7 @@
       top: 2px;
       position: relative;
       margin-right: .4em;
-      background-color: $dark-5;
+      background-color: theme.$dark-5;
       border-width: 0;
 
       &::after {
@@ -472,7 +476,7 @@
         font-size: 1.25em;
         font-weight: normal;
         content: '\F0131';
-        color: $grey-10;
+        color: quasar.$grey-10;
         display: block;
         border: none;
         background-color: #FFF;
@@ -481,7 +485,7 @@
 
         @at-root .body--dark & {
           color: #FFF;
-          background-color: $dark-6;
+          background-color: theme.$dark-6;
         }
       }
 
@@ -513,7 +517,7 @@
   //   }
 
   //   @at-root .theme--dark & {
-  //     background-color: darken(mc('grey', '900'), 5%);
+  //     background-color: color.adjust(mc('grey', '900'), $lightness: -5%);
   //     color: mc('indigo', '100');
   //   }
   // }
@@ -586,7 +590,7 @@
   .align-abstopright {
     width: 100px;
     max-height: 100px;
-    border: 2px dashed $red;
+    border: 2px dashed quasar.$red;
     border-radius: 5px;
     padding: 5px;
   }

+ 0 - 0
ux/src/css/quasar.variables.scss → ux/src/css/_theme.scss


+ 3 - 271
ux/src/css/app.scss

@@ -1,273 +1,5 @@
-// app global css in SCSS form
-// ------------------------------------------------------------------
-// SCROLLBAR
-// ------------------------------------------------------------------
+@use 'base';
+@use 'animation';
+@use 'page-contents';
 
-html {
-  --scrollbarBG: #CCC;
-  --thumbBG: #999;
-}
-body::-webkit-scrollbar {
-  width: 7px;
-}
-body {
-  scrollbar-width: thin;
-  scrollbar-color: var(--thumbBG) var(--scrollbarBG);
-}
-body::-webkit-scrollbar-track {
-  background: var(--scrollbarBG);
-}
-body::-webkit-scrollbar-thumb {
-  background-color: var(--thumbBG);
-  border-radius: 6px;
-  border: 1px solid var(--scrollbarBG);
-}
-
-// ------------------------------------------------------------------
-// FONTS
-// ------------------------------------------------------------------
-
-@font-face {
-  font-family: 'Roboto Mono';
-  src: url(/_assets/fonts/roboto-mono/roboto-mono.woff2);
-}
-
-.font-robotomono {
-  font-family: 'Roboto Mono', Consolas, "Liberation Mono", Courier, monospace;
-}
-
-.text-wordbreak-all {
-  word-break: break-all;
-}
-
-// ------------------------------------------------------------------
-// THEME COLORS
-// ------------------------------------------------------------------
-
-:root {
-  --q-header: #000;
-  --q-sidebar: #1976D2;
-}
-
-.header, .bg-header {
-  background: #000;
-  background: var(--q-header);
-}
-.sidebar, .bg-sidebar {
-  background: #1976D2;
-  background: var(--q-sidebar);
-}
-
-.bg-dark-6 { background-color: #070a0d; }
-.bg-dark-5 { background-color: #0d1117; }
-.bg-dark-4 { background-color: #161b22; }
-.bg-dark-3 { background-color: #1e232a; }
-.bg-dark-2 { background-color: #292f39; }
-.bg-dark-1 { background-color: #343b48; }
-
-// ------------------------------------------------------------------
-// FORMS
-// ------------------------------------------------------------------
-
-.v-textarea.is-monospaced textarea {
-  font-family: 'Roboto Mono', 'Courier New', Courier, monospace;
-  font-size: 13px;
-  font-weight: 600;
-  line-height: 1.4;
-}
-
-.q-field.denser .q-field__control {
-  height: 36px;
-
-  .q-field__prepend {
-    height: 36px;
-  }
-}
-
-.q-field.fill-outline .q-field__control {
-  background-color: #FFF;
-
-  @at-root .body--light & {
-    background-color: #FFF;
-  }
-  @at-root .body--dark & {
-    background-color: $dark;
-  }
-}
-
-.q-field--dark .q-field__control:before {
-  background-color: $dark-5;
-  border-color: rgba(255,255,255,.25);
-}
-
-// ------------------------------------------------------------------
-// ICONS SIZE FIX
-// ------------------------------------------------------------------
-
-.q-btn .q-icon {
-  &.fa-solid,
-  &.fa-regular {
-    font-size: 1.3em;
-  }
-}
-
-.q-select__dropdown-icon {
-  font-size: 16px;
-}
-
-// ------------------------------------------------------------------
-// BUTTONS
-// ------------------------------------------------------------------
-
-.q-btn.acrylic-btn {
-  .q-focus-helper {
-    background-color: currentColor;
-    opacity: .1;
-  }
-
-  &:hover .q-focus-helper {
-    opacity: .3 !important;
-  }
-}
-
-// ------------------------------------------------------------------
-// ICONS
-// ------------------------------------------------------------------
-
-.blueprint-icon {
-  &-alt {
-    filter: hue-rotate(100);
-  }
-}
-
-// ------------------------------------------------------------------
-// DIALOGS
-// ------------------------------------------------------------------
-
-.card-header {
-  display: flex;
-  align-items: center;
-  font-weight: 500;
-  font-size: .9rem;
-  background-color: $dark-3;
-  background-image: radial-gradient(at bottom right, $dark-3, $dark-5);
-  color: #FFF;
-
-  @at-root .body--light & {
-    border-bottom: 1px solid $dark-3;
-    box-shadow: 0 1px 0 0 $dark-6;
-  }
-  @at-root .body--dark & {
-    border-bottom: 1px solid #000;
-    box-shadow: 0 1px 0 0 lighten($dark-3, 2%);
-  }
-}
-
-.card-negative {
-  display: flex;
-  align-items: center;
-  font-size: .9rem;
-
-  @at-root .body--light & {
-    background-color: $red-1;
-    background-image: radial-gradient(at bottom center, lighten($red-1, 2%), lighten($red-2, 2%));
-    border-bottom: 1px solid $red-3;
-    text-shadow: 0 0 4px #FFF;
-    color: $red-9;
-  }
-  @at-root .body--dark & {
-    background-color: $red-9;
-    background-image: radial-gradient(at bottom center, $red-7, $red-9);
-    border-bottom: 1px solid $red-7;
-    text-shadow: 0 0 4px darken($red-9, 10%);
-    color: #FFF;
-  }
-}
-
-.card-actions {
-  @at-root .body--light & {
-    background-color: #FAFAFA;
-    background-image: linear-gradient(to bottom, #FCFCFC, #F0F0F0);
-    color: $dark-3;
-    border-top: 1px solid #EEE;
-    box-shadow: inset 0 1px 0 0 #FFF;
-  }
-  @at-root .body--dark & {
-    background-color: $dark-3;
-    background-image: radial-gradient(at top left, $dark-3, $dark-5);
-    border-top: 1px solid #000;
-    box-shadow: 0 -1px 0 0 lighten($dark-3, 2%);
-  }
-}
-
-// ------------------------------------------------------------------
-// CARDS
-// ------------------------------------------------------------------
-
-.q-card {
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12);
-
-  &.q-card--dark {
-    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12);
-  }
-
-  .q-separator--dark {
-    background-color: rgba(0,0,0,.7);
-  }
-}
-
-// ------------------------------------------------------------------
-// DROPDOWN MENUS
-// ------------------------------------------------------------------
-
-.translucent-menu {
-  backdrop-filter: blur(10px) saturate(180%);
-
-  @at-root .body--light & {
-    background-color: rgba(255,255,255,.8);
-  }
-  @at-root .body--dark & {
-    background-color: rgba($dark,.7);
-  }
-
-  > .q-card {
-    background-color: transparent !important;
-  }
-}
-
-.q-menu--dark {
-  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.14), 0 2px 1px -1px rgba(0, 0, 0, 0.12);
-}
-
-// ------------------------------------------------------------------
-// LOADING ANIMATIONS
-// ------------------------------------------------------------------
-
-.syncing-enter-active {
-  animation: syncing-anim .1s;
-}
-.syncing-leave-active {
-  animation: syncing-anim 1s reverse;
-}
-@keyframes syncing-anim {
-  0% {
-    opacity: 0;
-  }
-  100% {
-    opacity: 1;
-  }
-}
-
-.loading-darker {
-  .q-loading__backdrop {
-    opacity: .75;
-  }
-}
-
-// ------------------------------------------------------------------
-// IMPORTS
-// ------------------------------------------------------------------
-
-@import './animation.scss';
 @import 'v-network-graph/lib/style.css';
-@import './page-contents.scss';

+ 3 - 1
ux/src/layouts/AdminLayout.vue

@@ -366,6 +366,8 @@ onMounted(async () => {
 </script>
 
 <style lang="scss">
+@use 'sass:color';
+
 .admin-nav {
   height: 100%;
 }
@@ -381,7 +383,7 @@ onMounted(async () => {
   }
 
   .q-item__label--header {
-    box-shadow: 0 -1px 0 0 rgba(255,255,255,.15), 0 -2px 0 0 darken($dark-6, 1%);
+    box-shadow: 0 -1px 0 0 rgba(255,255,255,.15), 0 -2px 0 0 color.adjust($dark-6, $lightness: -1%);
     padding-top: 16px;
   }
 }

+ 1 - 1
ux/src/pages/AdminDashboard.vue

@@ -116,7 +116,7 @@ q-page.admin-dashboard
             color='primary'
             icon='las la-chart-area'
             :label='t(`admin.analytics.title`)'
-            :disable='!userStore.can(`manage:sites`) || flagsStore.experimental'
+            :disable='!flagsStore.experimental'
             :to='`/_admin/` + adminStore.currentSiteId + `/analytics`'
             )
     //- .col-12.col-lg-9

+ 1 - 1
ux/vite.config.js

@@ -54,7 +54,7 @@ export default defineConfig(({ mode }) => {
       }),
       quasar({
         autoImportComponentCase: 'kebab',
-        sassVariables: 'src/css/quasar.variables.scss'
+        sassVariables: '@/css/_theme.scss'
       })
     ],
     resolve: {

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio