From 7dc22774532872fc99aa7768cf299ab623e9d155 Mon Sep 17 00:00:00 2001 From: tusooa Date: Mon, 9 Jan 2023 13:02:16 -0500 Subject: Use stylelint --- src/components/tab_switcher/tab_switcher.scss | 50 ++++++++++++++++----------- 1 file changed, 30 insertions(+), 20 deletions(-) (limited to 'src/components/tab_switcher') diff --git a/src/components/tab_switcher/tab_switcher.scss b/src/components/tab_switcher/tab_switcher.scss index d930368c..705925c8 100644 --- a/src/components/tab_switcher/tab_switcher.scss +++ b/src/components/tab_switcher/tab_switcher.scss @@ -1,5 +1,6 @@ -@import '../../_variables.scss'; +@import "../../variables"; +/* stylelint-disable no-descending-specificity */ .tab-switcher { display: flex; @@ -19,8 +20,9 @@ flex-direction: row; flex: 0 0 auto; - &::after, &::before { - content: ''; + &::after, + &::before { + content: ""; flex: 1 1 auto; border-bottom: 1px solid; border-bottom-color: $fallback--border; @@ -39,6 +41,7 @@ border-bottom-color: var(--border, $fallback--border); } } + .tab { width: 100%; min-width: 1px; @@ -48,6 +51,7 @@ margin-bottom: 6px - 99px; } } + .contents.scrollable-tabs { flex-basis: 0; } @@ -70,10 +74,11 @@ overflow-x: hidden; flex-direction: column; - &::after, &::before { + &::after, + &::before { flex-shrink: 0; - flex-basis: .5em; - content: ''; + flex-basis: 0.5em; + content: ""; border-right: 1px solid; border-right-color: $fallback--border; border-right-color: var(--border, $fallback--border); @@ -107,7 +112,7 @@ &::before { flex: 0 0 6px; - content: ''; + content: ""; border-right: 1px solid; border-right-color: $fallback--border; border-right-color: var(--border, $fallback--border); @@ -131,12 +136,13 @@ margin-left: 1em; @media all and (max-width: 800px) { - padding-left: .25em; - padding-right: calc(.25em + 200px); - margin-right: calc(.25em - 200px); - margin-left: .25em; + padding-left: 0.25em; + padding-right: calc(0.25em + 200px); + margin-right: calc(0.25em - 200px); + margin-left: 0.25em; + .text { - display: none + display: none; } } } @@ -145,15 +151,17 @@ .contents { flex: 1 0 auto; - min-height: 0px; + min-height: 0; .hidden { display: none; } + .full-height:not(.hidden) { height: 100%; display: flex; flex-direction: column; + > *:not(.mobile-label) { flex: 1; } @@ -196,7 +204,8 @@ position: relative; box-sizing: border-box; - &::after, &::before { + &::after, + &::before { display: block; flex: 1 1 auto; } @@ -209,7 +218,7 @@ &:not(.active) { &::after { - content: ''; + content: ""; position: absolute; z-index: 7; } @@ -217,11 +226,11 @@ } .mobile-label { - padding-left: .3em; - padding-bottom: .25em; - margin-top: .5em; - margin-left: .2em; - margin-bottom: .25em; + padding-left: 0.3em; + padding-bottom: 0.25em; + margin-top: 0.5em; + margin-left: 0.2em; + margin-bottom: 0.25em; border-bottom: 1px solid var(--border, $fallback--border); @media all and (min-width: 800px) { @@ -229,3 +238,4 @@ } } } +/* stylelint-enable no-descending-specificity */ -- cgit v1.2.3-70-g09d2 From 1a852b96eff060c8eaab9477c85eb4a3bd91c748 Mon Sep 17 00:00:00 2001 From: tusooa Date: Thu, 2 Mar 2023 21:15:43 -0500 Subject: Give tab switcher a role --- src/components/tab_switcher/tab_switcher.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/components/tab_switcher') diff --git a/src/components/tab_switcher/tab_switcher.jsx b/src/components/tab_switcher/tab_switcher.jsx index c8d390bc..a7ef8560 100644 --- a/src/components/tab_switcher/tab_switcher.jsx +++ b/src/components/tab_switcher/tab_switcher.jsx @@ -117,6 +117,7 @@ export default { onClick={this.clickTab(index)} class={classesTab.join(' ')} type="button" + role="tab" > {props.label ? '' : props.label} @@ -131,6 +132,7 @@ export default { onClick={this.clickTab(index)} class={classesTab.join(' ')} type="button" + role="tab" > {!props.icon ? '' : ()} @@ -167,11 +169,15 @@ export default { return (
-
+
{tabs}
-- cgit v1.2.3-70-g09d2 From 4d23d31fecf480abfccc4db3ac79c6640078dc3b Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 14 Mar 2023 21:50:43 +0200 Subject: initial admin settings prototype (WIP) --- src/components/admin_modal/admin_modal.js | 68 ++++++++++++ src/components/admin_modal/admin_modal.scss | 80 ++++++++++++++ src/components/admin_modal/admin_modal.vue | 121 +++++++++++++++++++++ src/components/admin_modal/admin_modal_content.js | 88 +++++++++++++++ .../admin_modal/admin_modal_content.scss | 56 ++++++++++ src/components/admin_modal/tabs/general_tab.js | 33 ++++++ src/components/desktop_nav/desktop_nav.js | 5 +- src/components/desktop_nav/desktop_nav.vue | 9 +- src/components/notification/notification.vue | 2 +- .../settings_modal/admin_tabs/instance_tab.js | 29 +++++ .../settings_modal/admin_tabs/instance_tab.vue | 35 ++++++ src/components/settings_modal/helpers/setting.js | 14 ++- .../settings_modal/helpers/string_setting.js | 9 ++ .../settings_modal/helpers/string_setting.vue | 25 +++++ src/components/settings_modal/settings_modal.js | 23 +++- src/components/settings_modal/settings_modal.vue | 3 +- .../settings_modal/settings_modal_admin_content.js | 76 +++++++++++++ .../settings_modal_admin_content.scss | 56 ++++++++++ .../settings_modal_admin_content.vue | 21 ++++ .../settings_modal/settings_modal_content.js | 88 --------------- .../settings_modal/settings_modal_content.scss | 56 ---------- .../settings_modal/settings_modal_content.vue | 83 -------------- .../settings_modal/settings_modal_user_content.js | 88 +++++++++++++++ .../settings_modal_user_content.scss | 56 ++++++++++ .../settings_modal/settings_modal_user_content.vue | 83 ++++++++++++++ src/components/tab_switcher/tab_switcher.jsx | 8 +- src/modules/adminSettings.js | 5 +- src/modules/interface.js | 21 +++- 28 files changed, 985 insertions(+), 256 deletions(-) create mode 100644 src/components/admin_modal/admin_modal.js create mode 100644 src/components/admin_modal/admin_modal.scss create mode 100644 src/components/admin_modal/admin_modal.vue create mode 100644 src/components/admin_modal/admin_modal_content.js create mode 100644 src/components/admin_modal/admin_modal_content.scss create mode 100644 src/components/admin_modal/tabs/general_tab.js create mode 100644 src/components/settings_modal/admin_tabs/instance_tab.js create mode 100644 src/components/settings_modal/admin_tabs/instance_tab.vue create mode 100644 src/components/settings_modal/helpers/string_setting.js create mode 100644 src/components/settings_modal/helpers/string_setting.vue create mode 100644 src/components/settings_modal/settings_modal_admin_content.js create mode 100644 src/components/settings_modal/settings_modal_admin_content.scss create mode 100644 src/components/settings_modal/settings_modal_admin_content.vue delete mode 100644 src/components/settings_modal/settings_modal_content.js delete mode 100644 src/components/settings_modal/settings_modal_content.scss delete mode 100644 src/components/settings_modal/settings_modal_content.vue create mode 100644 src/components/settings_modal/settings_modal_user_content.js create mode 100644 src/components/settings_modal/settings_modal_user_content.scss create mode 100644 src/components/settings_modal/settings_modal_user_content.vue (limited to 'src/components/tab_switcher') diff --git a/src/components/admin_modal/admin_modal.js b/src/components/admin_modal/admin_modal.js new file mode 100644 index 00000000..525f09aa --- /dev/null +++ b/src/components/admin_modal/admin_modal.js @@ -0,0 +1,68 @@ +import Modal from 'src/components/modal/modal.vue' +import PanelLoading from 'src/components/panel_loading/panel_loading.vue' +import AsyncComponentError from 'src/components/async_component_error/async_component_error.vue' +import getResettableAsyncComponent from 'src/services/resettable_async_component.js' +import Popover from '../popover/popover.vue' +import Checkbox from 'src/components/checkbox/checkbox.vue' +import { library } from '@fortawesome/fontawesome-svg-core' +import { + newImporter, + newExporter +} from 'src/services/export_import/export_import.js' +import { + faTimes, + faFileUpload, + faFileDownload, + faChevronDown +} from '@fortawesome/free-solid-svg-icons' +import { + faWindowMinimize +} from '@fortawesome/free-regular-svg-icons' + +library.add( + faTimes, + faWindowMinimize, + faFileUpload, + faFileDownload, + faChevronDown +) + +const AdminModal = { + data () { + return {} + }, + components: { + Modal, + Popover, + Checkbox, + AdminModalContent: getResettableAsyncComponent( + () => import('./admin_modal_content.vue'), + { + loadingComponent: PanelLoading, + errorComponent: AsyncComponentError, + delay: 0 + } + ) + }, + methods: { + closeModal () { + this.$store.dispatch('closeAdminModal') + }, + peekModal () { + this.$store.dispatch('togglePeekAdminModal') + } + }, + computed: { + modalActivated () { + return this.$store.state.interface.adminModalState !== 'hidden' + }, + modalOpenedOnce () { + return this.$store.state.interface.adminModalLoaded + }, + modalPeeked () { + return this.$store.state.interface.adminModalState === 'minimized' + } + } +} + +export default AdminModal diff --git a/src/components/admin_modal/admin_modal.scss b/src/components/admin_modal/admin_modal.scss new file mode 100644 index 00000000..0d916f32 --- /dev/null +++ b/src/components/admin_modal/admin_modal.scss @@ -0,0 +1,80 @@ +@import "src/variables"; + +.admin-modal { + overflow: hidden; + + .setting-list, + .option-list { + list-style-type: none; + padding-left: 2em; + + li { + margin-bottom: 0.5em; + } + + .suboptions { + margin-top: 0.3em; + } + } + + .admin-modal-panel { + overflow: hidden; + transition: transform; + transition-timing-function: ease-in-out; + transition-duration: 300ms; + width: 1000px; + max-width: 90vw; + height: 90vh; + + @media all and (max-width: 800px) { + max-width: 100vw; + height: 100%; + } + + >.panel-body { + height: 100%; + overflow-y: hidden; + + .btn { + min-height: 2em; + min-width: 10em; + padding: 0 2em; + } + } + } + + .admin-footer { + display: flex; + + >* { + margin-right: 0.5em; + } + + .extra-content { + display: flex; + flex-grow: 1; + } + } + + &.peek { + .admin-modal-panel { + /* Explanation: + * Modal is positioned vertically centered. + * 100vh - 100% = Distance between modal's top+bottom boundaries and screen + * (100vh - 100%) / 2 = Distance between bottom (or top) boundary and screen + * + 100% - we move modal completely off-screen, it's top boundary touches + * bottom of the screen + * - 50px - leaving tiny amount of space so that titlebar + tiny amount of modal is visible + */ + transform: translateY(calc(((100vh - 100%) / 2 + 100%) - 50px)); + + @media all and (max-width: 800px) { + /* For mobile, the modal takes 100% of the available screen. + This ensures the minimized modal is always 50px above the browser bottom + bar regardless of whether or not it is visible. + */ + transform: translateY(calc(100% - 50px)); + } + } + } +} diff --git a/src/components/admin_modal/admin_modal.vue b/src/components/admin_modal/admin_modal.vue new file mode 100644 index 00000000..d7e5a80f --- /dev/null +++ b/src/components/admin_modal/admin_modal.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/src/components/admin_modal/admin_modal_content.js b/src/components/admin_modal/admin_modal_content.js new file mode 100644 index 00000000..897cc163 --- /dev/null +++ b/src/components/admin_modal/admin_modal_content.js @@ -0,0 +1,88 @@ +import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx' + +import DataImportExportTab from './tabs/data_import_export_tab.vue' +import MutesAndBlocksTab from './tabs/mutes_and_blocks_tab.vue' +import NotificationsTab from './tabs/notifications_tab.vue' +import FilteringTab from './tabs/filtering_tab.vue' +import SecurityTab from './tabs/security_tab/security_tab.vue' +import ProfileTab from './tabs/profile_tab.vue' +import GeneralTab from './tabs/general_tab.vue' +import VersionTab from './tabs/version_tab.vue' +import ThemeTab from './tabs/theme_tab/theme_tab.vue' + +import { library } from '@fortawesome/fontawesome-svg-core' +import { + faWrench, + faUser, + faFilter, + faPaintBrush, + faBell, + faDownload, + faEyeSlash, + faInfo +} from '@fortawesome/free-solid-svg-icons' + +library.add( + faWrench, + faUser, + faFilter, + faPaintBrush, + faBell, + faDownload, + faEyeSlash, + faInfo +) + +const AdminModalContent = { + components: { + TabSwitcher, + + DataImportExportTab, + MutesAndBlocksTab, + NotificationsTab, + FilteringTab, + SecurityTab, + ProfileTab, + GeneralTab, + VersionTab, + ThemeTab + }, + computed: { + isLoggedIn () { + return !!this.$store.state.users.currentUser + }, + open () { + return this.$store.state.interface.AdminModalState !== 'hidden' + }, + bodyLock () { + return this.$store.state.interface.AdminModalState === 'visible' + } + }, + methods: { + onOpen () { + const targetTab = this.$store.state.interface.AdminModalTargetTab + // We're being told to open in specific tab + if (targetTab) { + const tabIndex = this.$refs.tabSwitcher.$slots.default().findIndex(elm => { + return elm.props && elm.props['data-tab-name'] === targetTab + }) + if (tabIndex >= 0) { + this.$refs.tabSwitcher.setTab(tabIndex) + } + } + // Clear the state of target tab, so that next time Admin is opened + // it doesn't force it. + this.$store.dispatch('clearAdminModalTargetTab') + } + }, + mounted () { + this.onOpen() + }, + watch: { + open: function (value) { + if (value) this.onOpen() + } + } +} + +export default AdminModalContent diff --git a/src/components/admin_modal/admin_modal_content.scss b/src/components/admin_modal/admin_modal_content.scss new file mode 100644 index 00000000..2db7b2f8 --- /dev/null +++ b/src/components/admin_modal/admin_modal_content.scss @@ -0,0 +1,56 @@ +@import "src/variables"; + +.admin_tab-switcher { + height: 100%; + + .setting-item { + border-bottom: 2px solid var(--fg, $fallback--fg); + margin: 1em 1em 1.4em; + padding-bottom: 1.4em; + + > div, + > label { + display: block; + margin-bottom: 0.5em; + + &:last-child { + margin-bottom: 0; + } + } + + .select-multiple { + display: flex; + + .option-list { + margin: 0; + padding-left: 0.5em; + } + } + + &:last-child { + border-bottom: none; + padding-bottom: 0; + margin-bottom: 1em; + } + + select { + min-width: 10em; + } + + textarea { + width: 100%; + max-width: 100%; + height: 100px; + } + + .unavailable, + .unavailable svg { + color: var(--cRed, $fallback--cRed); + color: $fallback--cRed; + } + + .number-input { + max-width: 6em; + } + } +} diff --git a/src/components/admin_modal/tabs/general_tab.js b/src/components/admin_modal/tabs/general_tab.js new file mode 100644 index 00000000..8c166f19 --- /dev/null +++ b/src/components/admin_modal/tabs/general_tab.js @@ -0,0 +1,33 @@ +import BooleanSetting from '../settings_modal/helpers/boolean_setting.vue' +import ChoiceSetting from '../settings_modal/helpers/choice_setting.vue' +import IntegerSetting from '../settings_modal/helpers/integer_setting.vue' + +import { library } from '@fortawesome/fontawesome-svg-core' +import { + faGlobe +} from '@fortawesome/free-solid-svg-icons' + +library.add( + faGlobe +) + +const GeneralTab = { + components: { + BooleanSetting, + ChoiceSetting, + IntegerSetting, + }, + computed: { + mergedConfig () { + console.log(this.$store.state) + return this.$store.state + } + }, + methods: { + changeDefaultScope (value) { + this.$store.dispatch('setProfileOption', { name: 'defaultScope', value }) + } + } +} + +export default GeneralTab diff --git a/src/components/desktop_nav/desktop_nav.js b/src/components/desktop_nav/desktop_nav.js index 745b1a81..f6a2e294 100644 --- a/src/components/desktop_nav/desktop_nav.js +++ b/src/components/desktop_nav/desktop_nav.js @@ -107,7 +107,10 @@ export default { this.searchBarHidden = hidden }, openSettingsModal () { - this.$store.dispatch('openSettingsModal') + this.$store.dispatch('openSettingsModal', 'user') + }, + openAdminModal () { + this.$store.dispatch('openSettingsModal', 'admin') } } } diff --git a/src/components/desktop_nav/desktop_nav.vue b/src/components/desktop_nav/desktop_nav.vue index dc8bbfd3..49382f8e 100644 --- a/src/components/desktop_nav/desktop_nav.vue +++ b/src/components/desktop_nav/desktop_nav.vue @@ -48,20 +48,19 @@ icon="cog" /> - - +
- + +