diff --git a/client/components/main/accessibility.css b/client/components/main/accessibility.css index 1929848b9..3dd9cb220 100644 --- a/client/components/main/accessibility.css +++ b/client/components/main/accessibility.css @@ -72,3 +72,28 @@ border-radius: 5px; margin-right: 5px; } + +/* Accessibility page styles */ +.accessibility-page { + padding: 20px; + max-width: 800px; + margin: 0 auto; +} + +.accessibility-page h2 { + font-size: 24px; + margin-bottom: 20px; + color: #4d4d4d; +} + +.accessibility-page-content { + background-color: #fff; + padding: 20px; + border-radius: 3px; + box-shadow: 0 1px 2px rgba(0,0,0,0.15); +} + +.accessibility-page-content p { + margin-bottom: 16px; + line-height: 1.6; +} diff --git a/client/components/main/accessibility.jade b/client/components/main/accessibility.jade index 7c798d771..004832fa6 100644 --- a/client/components/main/accessibility.jade +++ b/client/components/main/accessibility.jade @@ -1,8 +1,18 @@ template(name="accessibilityHeaderBar") if currentUser h1 - | {{_ 'accessibility-title'}} + if isAccessibilityEnabled + = accessibilityTitle + else + | {{_ 'accessibility'}} template(name="accessibility") if currentUser - | {{_ 'accessibility-content'}} + .accessibility-page + if isAccessibilityEnabled + .accessibility-page-content + +viewer + | {{accessibilityContent}} + else + .accessibility-page-content + | {{_ 'accessibility-info-not-added-yet'}} diff --git a/client/components/main/accessibility.js b/client/components/main/accessibility.js index 38d8f6591..b6204dc4b 100644 --- a/client/components/main/accessibility.js +++ b/client/components/main/accessibility.js @@ -1,11 +1,38 @@ import { ReactiveCache } from '/imports/reactiveCache'; import { TAPi18n } from '/imports/i18n'; +// Shared helpers for both accessibility templates +const accessibilityHelpers = { + accessibilityTitle() { + const setting = AccessibilitySettings.findOne({}); + return setting && setting.title ? setting.title : TAPi18n.__('accessibility-title'); + }, + accessibilityContent() { + const setting = AccessibilitySettings.findOne({}); + return setting && setting.body ? setting.body : TAPi18n.__('accessibility-content'); + }, + isAccessibilityEnabled() { + const setting = AccessibilitySettings.findOne({}); + return setting && setting.enabled; + } +}; + +// Main accessibility page component BlazeComponent.extendComponent({ onCreated() { this.error = new ReactiveVar(''); this.loading = new ReactiveVar(false); Meteor.subscribe('setting'); + Meteor.subscribe('accessibilitySettings'); }, + ...accessibilityHelpers }).register('accessibility'); + +// Header bar component +BlazeComponent.extendComponent({ + onCreated() { + Meteor.subscribe('accessibilitySettings'); + }, + ...accessibilityHelpers +}).register('accessibilityHeaderBar'); diff --git a/client/components/settings/settingBody.jade b/client/components/settings/settingBody.jade index fed5bf5a3..166449dd1 100644 --- a/client/components/settings/settingBody.jade +++ b/client/components/settings/settingBody.jade @@ -189,24 +189,22 @@ template(name='announcementSettings') template(name='accessibilitySettings') ul#accessibility-setting.setting-detail + li + a(href="/accessibility" style="text-decoration: underline; color: blue;") {{_ 'accessibility'}} li a.flex.js-toggle-accessibility .materialCheckBox(class="{{#if currentAccessibility.enabled}}is-checked{{/if}}") - span {{_ 'admin-accessibility-active'}} - li - .title {{_ 'accessibility-title'}} - .form-group - input.wekan-form-control#accessibility-title(type="text", placeholder="" value="{{currentSetting.accessibilityTitle}}") + span {{_ 'accessibility-page-enabled'}} li .accessibility-content(class="{{#if currentAccessibility.enabled}}{{else}}hide{{/if}}") ul li - .title {{_ 'admin-accessibility-title'}} - textarea#admin-accessibility.wekan-form-control= currentAccessibility.accessibilityTitle + .title {{_ 'accessibility-title'}} + textarea#admin-accessibility-title.wekan-form-control= currentAccessibility.title li - .title {{_ 'admin-accessibility-content'}} - textarea#admin-accessibility.wekan-form-control= currentAccessibility.accessibilityContent + .title {{_ 'accessibility-content'}} + textarea#admin-accessibility-content.wekan-form-control= currentAccessibility.body li button.js-accessibility-save.primary {{_ 'save'}} diff --git a/client/components/settings/settingBody.js b/client/components/settings/settingBody.js index be8322af3..9021957c6 100644 --- a/client/components/settings/settingBody.js +++ b/client/components/settings/settingBody.js @@ -12,6 +12,7 @@ BlazeComponent.extendComponent({ this.accountSetting = new ReactiveVar(false); this.tableVisibilityModeSetting = new ReactiveVar(false); this.announcementSetting = new ReactiveVar(false); + this.accessibilitySetting = new ReactiveVar(false); this.layoutSetting = new ReactiveVar(false); this.webhookSetting = new ReactiveVar(false); @@ -20,6 +21,7 @@ BlazeComponent.extendComponent({ Meteor.subscribe('accountSettings'); Meteor.subscribe('tableVisibilityModeSettings'); Meteor.subscribe('announcements'); + Meteor.subscribe('accessibilitySettings'); Meteor.subscribe('globalwebhooks'); }, @@ -106,6 +108,7 @@ BlazeComponent.extendComponent({ this.emailSetting.set('email-setting' === targetID); this.accountSetting.set('account-setting' === targetID); this.announcementSetting.set('announcement-setting' === targetID); + this.accessibilitySetting.set('accessibility-setting' === targetID); this.layoutSetting.set('layout-setting' === targetID); this.webhookSetting.set('webhook-setting' === targetID); this.tableVisibilityModeSetting.set('tableVisibilityMode-setting' === targetID); @@ -242,7 +245,6 @@ BlazeComponent.extendComponent({ const displayAuthenticationMethod = $('input[name=displayAuthenticationMethod]:checked').val() === 'true'; const defaultAuthenticationMethod = $('#defaultAuthenticationMethod').val(); -/* const accessibilityPageEnabled = $('input[name=accessibilityPageEnabled]:checked').val() === 'true'; const accessibilityTitle = $('#accessibility-title') .val() @@ -250,7 +252,6 @@ BlazeComponent.extendComponent({ const accessibilityContent = $('#accessibility-content') .val() .trim(); -*/ const spinnerName = $('#spinnerName').val(); try { @@ -274,13 +275,11 @@ BlazeComponent.extendComponent({ oidcBtnText, mailDomainName, legalNotice, - }, - }); -/* accessibilityPageEnabled, accessibilityTitle, accessibilityContent, -*/ + }, + }); } catch (e) { return; } finally { @@ -317,7 +316,6 @@ BlazeComponent.extendComponent({ 'click a.js-toggle-hide-logo': this.toggleHideLogo, 'click a.js-toggle-hide-card-counter-list': this.toggleHideCardCounterList, 'click a.js-toggle-hide-board-member-list': this.toggleHideBoardMemberList, - 'click a.js-toggle-accessibility-page-enabled': this.toggleAccessibilityPageEnabled, 'click button.js-save-layout': this.saveLayout, 'click a.js-toggle-display-authentication-method': this .toggleDisplayAuthenticationMethod, @@ -469,6 +467,59 @@ BlazeComponent.extendComponent({ }, }).register('announcementSettings'); +BlazeComponent.extendComponent({ + onCreated() { + this.loading = new ReactiveVar(false); + }, + + setLoading(w) { + this.loading.set(w); + }, + + currentAccessibility() { + return AccessibilitySettings.findOne(); + }, + + saveAccessibility() { + const title = $('#admin-accessibility-title') + .val() + .trim(); + const content = $('#admin-accessibility-content') + .val() + .trim(); + AccessibilitySettings.update(AccessibilitySettings.findOne()._id, { + $set: { + title: title, + body: content + }, + }); + }, + + toggleAccessibility() { + this.setLoading(true); + const accessibilitySetting = this.currentAccessibility(); + const isActive = accessibilitySetting.enabled; + AccessibilitySettings.update(accessibilitySetting._id, { + $set: { enabled: !isActive }, + }); + this.setLoading(false); + if (isActive) { + $('.accessibility-content').slideUp(); + } else { + $('.accessibility-content').slideDown(); + } + }, + + events() { + return [ + { + 'click a.js-toggle-accessibility': this.toggleAccessibility, + 'click button.js-accessibility-save': this.saveAccessibility, + }, + ]; + }, +}).register('accessibilitySettings'); + Template.selectAuthenticationMethod.onCreated(function() { this.authenticationMethods = new ReactiveVar([]); diff --git a/client/components/sidebar/sidebar.css b/client/components/sidebar/sidebar.css index 7dffd8256..831719f36 100644 --- a/client/components/sidebar/sidebar.css +++ b/client/components/sidebar/sidebar.css @@ -106,7 +106,7 @@ top: 7px; font-size: 1em; line-height: 1.6em; - color: #999; + color: #000; } .sidebar .sidebar-shortcuts .sidebar-btn { margin-left: 3px; @@ -146,6 +146,23 @@ font-size: 24px; transition: transform 0.5s; } +.sidebar-accessibility { + color: #4d4d4d; + padding: 5px 10px; + display: flex; + align-items: center; + text-decoration: none; + border-radius: 3px; + cursor: pointer; + margin-left: auto; + margin-right: 30px; +} +.sidebar-accessibility:hover { + background-color: #d9d9d9; +} +.sidebar-accessibility span { + margin-left: 5px; +} .board-sidebar.is-open .sidebar-tongue { left: -28px; } diff --git a/client/components/sidebar/sidebar.jade b/client/components/sidebar/sidebar.jade index 53e856b06..f71808765 100644 --- a/client/components/sidebar/sidebar.jade +++ b/client/components/sidebar/sidebar.jade @@ -12,6 +12,10 @@ template(name="sidebar") a.sidebar-btn.js-keyboard-shortcuts-toggle( title="{{#if isKeyboardShortcuts}}{{_ 'keyboard-shortcuts-enabled'}}{{else}}{{_ 'keyboard-shortcuts-disabled'}}{{/if}}") i.fa(class="fa-solid fa-{{#if isKeyboardShortcuts}}check-square-o{{else}}ban{{/if}}") + if isAccessibilityEnabled + a.sidebar-accessibility + i.fa.fa-universal-access + span {{_ 'accessibility'}} a.sidebar-xmark.js-close-sidebar ✕ .sidebar-content.js-board-sidebar-content //a.hide-btn.js-hide-sidebar @@ -26,7 +30,6 @@ template(name="sidebar") template(name='homeSidebar') hr +membersWidget - | {{_ 'accessibility'}} hr +labelsWidget hr diff --git a/client/components/sidebar/sidebar.js b/client/components/sidebar/sidebar.js index 28b7408fc..e0a37ebbb 100644 --- a/client/components/sidebar/sidebar.js +++ b/client/components/sidebar/sidebar.js @@ -26,6 +26,9 @@ BlazeComponent.extendComponent({ this._hideCardCounterList = new ReactiveVar(false); this._hideBoardMemberList = new ReactiveVar(false); Sidebar = this; + + // Subscribe to accessibility settings + Meteor.subscribe('accessibilitySettings'); }, onDestroyed() { @@ -115,6 +118,11 @@ BlazeComponent.extendComponent({ return user && user.isVerticalScrollbars(); }, + isAccessibilityEnabled() { + const setting = AccessibilitySettings.findOne({}); + return setting && setting.enabled; + }, + events() { return [ { @@ -145,6 +153,10 @@ BlazeComponent.extendComponent({ 'click .js-show-week-of-year-toggle'() { ReactiveCache.getCurrentUser().toggleShowWeekOfYear(); }, + 'click .sidebar-accessibility'() { + FlowRouter.go('accessibility'); + Sidebar.toggle(); + }, 'click .js-close-sidebar'() { Sidebar.toggle() }, diff --git a/imports/i18n/data/en.i18n.json b/imports/i18n/data/en.i18n.json index a940fe7c8..f857a5359 100644 --- a/imports/i18n/data/en.i18n.json +++ b/imports/i18n/data/en.i18n.json @@ -1270,6 +1270,7 @@ "supportPopup-title": "Support", "accessibility": "Accessibility", "accessibility-page-enabled": "Accessibility page enabled", - "accessibility-title": "Accessibility topic", + "accessibility-info-not-added-yet": "Accessibility info has not been added yet", + "accessibility-title": "Accessibility title", "accessibility-content": "Accessibility content" } diff --git a/server/publications/accessibilitySettings.js b/server/publications/accessibilitySettings.js new file mode 100644 index 000000000..8f634ce51 --- /dev/null +++ b/server/publications/accessibilitySettings.js @@ -0,0 +1,3 @@ +Meteor.publish('accessibilitySettings', function() { + return AccessibilitySettings.find({}); +});