Skip to content
Snippets Groups Projects
Commit f4a9db3e authored by Michaela Brückner's avatar Michaela Brückner :unicorn: Committed by David Siegfried
Browse files

Accessibility: Adds an alternative, high-contrast color-scheme, closes #96

Closes #96

Merge request studip/studip!728
parent 263edc8e
No related branches found
No related tags found
No related merge requests found
Showing
with 1683 additions and 56 deletions
<?php
/**
* Settings_AccessibilityController - Administration of all user accessibility related
* settings
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* @author Michaela Brückner <brueckner@data-quest.de>
* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
* @category Stud.IP
* @since 5.2
*/
require_once 'settings.php';
class Settings_AccessibilityController extends Settings_SettingsController
{
public function before_filter(&$action, &$args)
{
parent::before_filter($action, $args);
PageLayout::setTitle(_('Barrierefreiheitseinstellungen'));
Navigation::activateItem('/profile/settings/accessibility');
SkipLinks::addIndex(_('Barrierefreiheitseinstellungen anpassen'), 'layout_content', 100);
}
public function index_action()
{
}
public function store_action()
{
CSRFProtection::verifyUnsafeRequest();
$this->config->store('USER_HIGH_CONTRAST', Request::bool('enable_high_contrast'));
$this->config->store('SKIPLINKS_ENABLE', Request::bool('skiplinks_enable'));
PageLayout::postSuccess(_('Ihre Einstellungen wurden gespeichert.'));
$this->redirect('settings/accessibility');
}
}
<? if (!$print_schedules): ?>
<form class="default" method="post"
action="<?= $controller->link_for('resources/print/clipboard_rooms') ?>">
<?= CSRFProtection::tokenTag() ?>
<? if ($clipboard_selected): ?>
<? if ($clipboard_selected): ?>
<form class="default" method="post"
action="<?= $controller->link_for('resources/print/clipboard_rooms') ?>">
<?= CSRFProtection::tokenTag() ?>
<input type="hidden" name="clipboard_id" value="<?= htmlReady($selected_clipboard_id) ?>">
<input type="hidden" name="schedule_type" value="<?= htmlReady($schedule_type) ?>">
<input type="hidden" name="date" value="<?= htmlReady($selected_date_string) ?>">
......@@ -27,16 +29,16 @@
) ?>
</legend>
<ul>
<? foreach ($available_rooms as $room): ?>
<li>
<label>
<input type="checkbox" value="<?= htmlReady($room->id) ?>"
checked="checked"
name="selected_room_ids[]">
<?= htmlReady($room->getFullName()) ?>
</label>
</li>
<? endforeach ?>
<? foreach ($available_rooms as $room): ?>
<li>
<label>
<input type="checkbox" value="<?= htmlReady($room->id) ?>"
checked="checked"
name="selected_room_ids[]">
<?= htmlReady($room->getFullName()) ?>
</label>
</li>
<? endforeach ?>
</ul>
<? endif ?>
</fieldset>
......@@ -52,8 +54,13 @@
'null'
) ?>
</div>
<? else: ?>
<? if(count($available_clipboards)) : ?>
</form>
<? else: ?>
<? if(count($available_clipboards)) : ?>
<form class="default" method="post"
action="<?= $controller->link_for('resources/print/clipboard_rooms') ?>">
<?= CSRFProtection::tokenTag() ?>
<fieldset>
<label>
<?= _('Individuelle Raumgruppe') ?>:
......@@ -69,21 +76,21 @@
<?= _('Art des Belegungsplanes') ?>:
<select name="schedule_type">
<option value="w"
<?= $selected_schedule == 'w'
? 'selected="selected"'
: '' ?>>
<?= $selected_schedule == 'w'
? 'selected="selected"'
: '' ?>>
<?= _('Wochenplan') ?>
</option>
<option value="w+we"
<?= $selected_schedule == 'w+we'
? 'selected="selected"'
: '' ?>>
<?= $selected_schedule == 'w+we'
? 'selected="selected"'
: '' ?>>
<?= _('Wochenplan inklusive Wochenende') ?>
</option>
<option value="d"
<?= $selected_schedule == 'd'
? 'selected="selected"'
: '' ?>>
<?= $selected_schedule == 'd'
? 'selected="selected"'
: '' ?>>
<?= _('Tagesplan') ?>
</option>
</select>
......@@ -111,19 +118,19 @@
'select_clipboard'
) ?>
</div>
<? else :?>
<?= MessageBox::info(
_('Sie müssen zunächst Raumgruppen erstellen'),
[
sprintf(
_('Klicken %shier%s, um ein Raumgruppen anzulegen.'),
'<a href="' . URLHelper::getLink('dispatch.php/room_management/overview/rooms') . '">',
'</a>')
]
)?>
<? endif ?>
</form>
<? else :?>
<?= MessageBox::info(
_('Sie müssen zunächst Raumgruppen erstellen'),
[
sprintf(
_('Klicken %shier%s, um ein Raumgruppen anzulegen.'),
'<a href="' . URLHelper::getLink('dispatch.php/room_management/overview/rooms') . '">',
'</a>')
]
)?>
<? endif ?>
</form>
<? endif ?>
<? else: ?>
<? if (Request::get("allday")) {
$min_time = '00:00:00';
......@@ -158,14 +165,14 @@
],
'defaultView' =>
in_array(Request::get("defaultView"), ['dayGridMonth','timeGridWeek','timeGridDay'])
? Request::get("defaultView")
: 'timeGridWeek',
? Request::get("defaultView")
: 'timeGridWeek',
'defaultDate' => Request::get("defaultDate", $print_date),
'eventSources' => [
[
'url' => URLHelper::getURL(
'api.php/resources/resource/'
. $room->id . '/booking_plan'
. $room->id . '/booking_plan'
),
'method' => 'GET',
'extraParams' => [
......
<form method="post" action="<?= $controller->store() ?>" class="default">
<?= CSRFProtection::tokenTag() ?>
<fieldset>
<legend id="accessibility"><?= _('Barrierefreiheitseinstellungen') ?></legend>
<label>
<input type="checkbox" name="enable_high_contrast"
value="1"
<? if ($config->USER_HIGH_CONTRAST) echo 'checked'; ?>>
<?= _('Kontrastreiches Farbschema aktivieren') ?>
<?= tooltipIcon(
_('Mit dieser Einstellung wird ein Farbschema mit hohem Kontrast aktiviert.')
) ?>
</label>
<label>
<input type="checkbox" name="skiplinks_enable"
value="1"
<? if ($config->SKIPLINKS_ENABLE) echo 'checked'; ?>>
<?= _('Skiplinks einblenden') ?>
<?= tooltipIcon(_('Mit dieser Einstellung wird nach dem ersten Drücken der Tab-Taste eine '
.'Liste mit Skiplinks eingeblendet, mit deren Hilfe Sie mit der Tastatur '
.'schneller zu den Hauptinhaltsbereichen der Seite navigieren können. '
.'Zusätzlich wird der aktive Bereich einer Seite hervorgehoben.')) ?>
</label>
</fieldset>
<footer>
<?= \Studip\Button::create(_('Speichern')) ?>
</footer>
</form>
......@@ -46,17 +46,6 @@ $start_pages = [
</label>
<? endif ?>
<label>
<input type="checkbox" name="skiplinks_enable"
value="1"
<? if ($config->SKIPLINKS_ENABLE) echo 'checked'; ?>>
<?= _('Skiplinks einblenden') ?>
<?= tooltipIcon(_('Mit dieser Einstellung wird nach dem ersten Drücken der Tab-Taste eine '
.'Liste mit Skiplinks eingeblendet, mit deren Hilfe Sie mit der Tastatur '
.'schneller zu den Hauptinhaltsbereichen der Seite navigieren können. '
.'Zusätzlich wird der aktive Bereich einer Seite hervorgehoben.')) ?>
</label>
<label>
<input type="checkbox"
name="showsem_enable"
......
<?php
class AddHighContrastConfigEntry extends Migration
{
public function description()
{
return 'Adds configuration field USER_HIGH_CONTRAST';
}
public function up()
{
$db = DBManager::get();
$db->exec(
"INSERT IGNORE INTO `config`
(`field`, `value`, `type`, `range`,
`section`,
`mkdate`, `chdate`,
`description`)
VALUES
('USER_HIGH_CONTRAST', '0', 'boolean', 'user',
'accessibility', UNIX_TIMESTAMP(), UNIX_TIMESTAMP(),
'Schaltet ein barrierefreies Stylesheet mit hohem Kontrast ein oder aus.')"
);
}
public function down()
{
$db = DBManager::get();
$db->exec(
"DELETE FROM `config_values`
WHERE `field` = 'USER_HIGH_CONTRAST'"
);
$db->exec(
"DELETE FROM `config`
WHERE `field` = 'USER_HIGH_CONTRAST'"
);
}
}
......@@ -38,6 +38,11 @@ class AvatarNavigation extends Navigation
$navigation = new Navigation(_('Einstellungen'), 'dispatch.php/settings/general');
$navigation->setImage(Icon::create('admin'));
$this->addSubNavigation('settings', $navigation);
// Link to accessibility settings
$navigation = new Navigation(_('Barrierefreiheit'), 'dispatch.php/settings/accessibility');
$navigation->setImage(Icon::create('accessibility'));
$this->addSubNavigation('accessibility', $navigation);
}
// Link to logout
......
......@@ -114,6 +114,11 @@ class ProfileNavigation extends Navigation
$navigation->addSubNavigation('tfa', new Navigation(_('Zwei-Faktor-Authentifizierung'), 'dispatch.php/tfa'));
}
$navigation->addSubNavigation('accessibility', new Navigation(
_('Barrierefreiheitseinstellungen'),
'dispatch.php/settings/accessibility'
));
$this->addSubNavigation('settings', $navigation);
}
......
......@@ -120,7 +120,7 @@ class Seminar_Auth
# Check for user supplied automatic login procedure
if ($uid = $this->auth_preauth()) {
$this->auth["uid"] = $uid;
$sess->regenerate_session_id(['auth', '_language', 'phpCAS']);
$sess->regenerate_session_id(['auth', '_language', 'phpCAS', 'contrast']);
$sess->freeze();
$GLOBALS['user'] = new Seminar_User($this->auth['uid']);
return true;
......@@ -170,7 +170,7 @@ class Seminar_Auth
case "log":
if ($uid = $this->auth_validatelogin()) {
$this->auth["uid"] = $uid;
$keep_session_vars = ['auth', 'forced_language', '_language'];
$keep_session_vars = ['auth', 'forced_language', '_language', 'contrast'];
if ($this->auth['perm'] === 'root') {
$keep_session_vars[] = 'plugins_disabled';
}
......@@ -455,5 +455,9 @@ class Seminar_Auth
// init of output via I18N
$_language_path = init_i18n($_SESSION['_language']);
include 'config.inc.php';
if (isset($_SESSION['contrast'])) {
PageLayout::addStylesheet('accessibility.css');
}
}
}
......@@ -101,12 +101,20 @@ if ($auth->is_authenticated() && is_object($user) && $user->id != "nobody") {
if (UserConfig::get($user->id)->PERSONAL_STARTPAGE > 0 && $i_page == "index.php" && !$perm->have_perm("root")) {
$seminar_open_redirected = TRUE;
}
if ($_SESSION['contrast']) {
UserConfig::get($GLOBALS['user']->id)->store('USER_HIGH_CONTRAST', 1);
unset($_SESSION['contrast']);
}
$user_did_login = true;
}
TwoFactorAuth::get()->secureSession();
}
if (isset($_SESSION['contrast']) || UserConfig::get($GLOBALS['user']->id)->USER_HIGH_CONTRAST) {
PageLayout::addStylesheet('accessibility.css');
}
// init of output via I18N
$_language_path = init_i18n($_SESSION['_language']);
//force reload of config to get translated data
......
<svg viewBox="0 0 54 54" xmlns="http://www.w3.org/2000/svg"><g fill="#28497c"><path d="m27 8c10.5 0 19 8.5 19 19s-8.5 19-19 19-19-8.6-19-19 8.5-19 19-19m0-5c-13.3 0-24 10.7-24 24s10.7 24 24 24 24-10.7 24-24-10.7-24-24-24z"/><circle cx="27" cy="15" r="4"/><path d="m38.2 19.1c-.6-.9-1.7-1.1-2.7-.8l-5.8 2.1c-.8.4-1.8.6-2.7.6h-.2c-.9 0-1.9-.2-2.8-.5l-5.8-2.1c-1-.4-2.1-.1-2.7.8-.8 1.2-.2 2.8 1.1 3.3l7.4 2.7c.3.1.5.4.5.7v3.7c0 .3-.1.6-.2.9l-4.5 7.9c-.5.9-.4 2.1.3 2.8 1.1 1 2.7.7 3.4-.5l3.5-6.1 3.6 6.2c.6 1 1.9 1.4 3 .8 1-.6 1.4-2 .8-3.1l-4.6-7.9c-.2-.3-.2-.6-.2-.9v-3.8c0-.3.2-.6.5-.7l7.2-2.6c1.2-.6 1.8-2.2.9-3.5z"/></g></svg>
\ No newline at end of file
......@@ -23,6 +23,14 @@ page_open(['sess' => 'Seminar_Session', 'auth' => 'Seminar_Default_Auth', 'perm'
$auth->login_if(Request::get('again') && ($auth->auth['uid'] == 'nobody'));
// if desired, switch to high contrast stylesheet and store when user logs in
if (Request::get('unset_contrast')) {
unset($_SESSION['contrast']);
}
if (Request::get('set_contrast') ) {
$_SESSION['contrast'] = true;
}
// evaluate language clicks
// has to be done before seminar_open to get switching back to german (no init of i18n at all))
if (Request::get('set_language')) {
......
......@@ -40,6 +40,7 @@ if ($auth->auth["uid"]!="nobody") {
$logout_user=$user->id;
$_language = $_SESSION['_language'];
$contrast = UserConfig::get($GLOBALS['user']->id)->USER_HIGH_CONTRAST;
// TODO this needs to be generalized or removed
//erweiterung cas
......@@ -66,6 +67,6 @@ if ($auth->auth["uid"]!="nobody") {
page_close();
}
header("Location:" . URLHelper::getURL("index.php?logout=true&set_language=$_language"));
header("Location:" . URLHelper::getURL("index.php?logout=true&set_language=$_language&set_contrast=$contrast"));
?>
This diff is collapsed.
......@@ -59,6 +59,25 @@ div.index_container {
}
}
div#contrast {
display: flex;
align-items: center;
gap: 5px;
border-top: 1px solid @light-gray-color;
font-size: 0.9em;
padding: 10px;
a {
text-decoration: underline;
color: @contrast-blue;
&:hover, &:focus {
font-size: 1em;
color: @red;
}
}
}
div.login_info {
border-top: 1px solid @light-gray-color;
font-size: 0.8em;
......
//if you like, change this (your brand color)
@base-color: #28497c; // #28497c
@contrast-blue: #2849d8;
//PLEASE, no changes from here
//@base-gray: #3c454e; // #3c454e
......
......@@ -62,6 +62,19 @@ if ($bg_mobile) {
<? endforeach; ?>
</div>
<div id="contrast">
<? if (isset($_SESSION['contrast'])) : ?>
<?= Icon::create('accessibility')->asImg(24) ?>
<a href="index.php?unset_contrast=1"><?= _('Normalen Kontrast aktivieren') ?></a>
<?= tooltipIcon(_('Aktiviert standardmäßige, nicht barrierefreie Kontraste.')); ?>
<? else : ?>
<?= Icon::create('accessibility')->asImg(24) ?>
<a href="index.php?set_contrast=1" id="highcontrastlink"><?= _('Hohen Kontrast aktivieren')?></a>
<?= tooltipIcon(_('Aktiviert einen hohen Kontrast gemäß WCAG 2.1. Diese Einstellung wird nach dem Login übernommen.
Sie können sie in Ihren persönlichen Einstellungen ändern.')); ?>
<? endif ?>
</div>
<div class="login_info">
<div>
<?= _('Aktive Veranstaltungen') ?>:
......
......@@ -14,7 +14,8 @@ module.exports = {
"studip-wysiwyg": assetsPath + "/entry-wysiwyg.js",
"studip-installer": assetsPath + "/entry-installer.js",
"print": path.resolve(__dirname, "resources/assets/stylesheets") + "/print.less",
"webservices": path.resolve(__dirname, "resources/assets/stylesheets") + "/webservices.scss"
"webservices": path.resolve(__dirname, "resources/assets/stylesheets") + "/webservices.scss",
"accessibility": path.resolve(__dirname, "resources/assets/stylesheets") + "/highcontrast.scss"
},
output: {
path: path.resolve(__dirname, "public/assets"),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment