1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-07-31 15:24:31 +03:00

Started interface user shortcut form interface

Built controller actions and initual UI.
Still needs JS logic for shortcut input handling.
This commit is contained in:
Dan Brown
2022-11-08 21:17:45 +00:00
parent 1fc994177f
commit 66c8809799
13 changed files with 232 additions and 40 deletions

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0 3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm8 7H9c-.55 0-1-.45-1-1s.45-1 1-1h6c.55 0 1 .45 1 1s-.45 1-1 1zm1-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z"/></svg>

After

Width:  |  Height:  |  Size: 367 B

View File

@ -1,35 +1,3 @@
/**
* The default mapping of unique id to shortcut key.
* @type {Object<string, string>}
*/
const defaultMap = {
// Header actions
"home": "1",
"shelves_view": "2",
"books_view": "3",
"settings_view": "4",
"favorites_view": "5",
"profile_view": "6",
"global_search": "/",
"logout": "0",
// Generic actions
"edit": "e",
"new": "n",
"copy": "c",
"delete": "d",
"favorite": "f",
"export": "x",
"sort": "s",
"permissions": "p",
"move": "m",
"revisions": "r",
// Navigation
"next": "ArrowRight",
"prev": "ArrowLeft",
};
function reverseMap(map) {
const reversed = {};
for (const [key, value] of Object.entries(map)) {
@ -45,14 +13,12 @@ class Shortcuts {
setup() {
this.container = this.$el;
this.mapById = defaultMap;
this.mapById = JSON.parse(this.$opts.keyMap);
this.mapByShortcut = reverseMap(this.mapById);
this.hintsShowing = false;
this.hideHints = this.hideHints.bind(this);
// TODO - Allow custom key maps
// TODO - Allow turning off shortcuts
this.setupListeners();
}

View File

@ -473,4 +473,10 @@ div[editor-type="markdown"] .title-input.page-title input[type="text"] {
.custom-file-input:focus + label {
border-color: var(--color-primary);
outline: 1px solid var(--color-primary);
}
input.shortcut-input {
width: auto;
max-width: 120px;
height: auto;
}

View File

@ -2,7 +2,7 @@
<div class="grid mx-l">
<div>
<a href="{{ url('/') }}" data-shortcut="home" class="logo">
<a href="{{ url('/') }}" data-shortcut="home_view" class="logo">
@if(setting('app-logo', '') !== 'none')
<img class="logo-image" src="{{ setting('app-logo', '') === '' ? url('/logo.png') : url(setting('app-logo', '')) }}" alt="Logo">
@endif
@ -62,7 +62,7 @@
</span>
<ul refs="dropdown@menu" class="dropdown-menu" role="menu">
<li>
<a href="{{ url('/favourites') }}" data-shortcut="favorites_view" class="icon-item">
<a href="{{ url('/favourites') }}" data-shortcut="favourites_view" class="icon-item">
@icon('star')
<div>{{ trans('entities.my_favourites') }}</div>
</a>
@ -90,6 +90,12 @@
</form>
</li>
<li><hr></li>
<li>
<a href="{{ url('/preferences/shortcuts') }}" class="icon-item">
@icon('shortcuts')
<div>{{ 'Shortcuts' }}</div>
</a>
</li>
<li>
@include('common.dark-mode-toggle', ['classes' => 'icon-item'])
</li>

View File

@ -5,7 +5,7 @@
{{ csrf_field() }}
<input type="hidden" name="type" value="{{ get_class($entity) }}">
<input type="hidden" name="id" value="{{ $entity->id }}">
<button type="submit" data-shortcut="favorite" class="icon-list-item text-primary">
<button type="submit" data-shortcut="favourite" class="icon-list-item text-primary">
<span>@icon($isFavourite ? 'star' : 'star-outline')</span>
<span>{{ $isFavourite ? trans('common.unfavourite') : trans('common.favourite') }}</span>
</button>

View File

@ -1,7 +1,7 @@
<div id="sibling-navigation" class="grid half collapse-xs items-center mb-m px-m no-row-gap fade-in-when-active print-hidden">
<div>
@if($previous)
<a href="{{ $previous->getUrl() }}" data-shortcut="prev" class="outline-hover no-link-style block rounded">
<a href="{{ $previous->getUrl() }}" data-shortcut="previous" class="outline-hover no-link-style block rounded">
<div class="px-m pt-xs text-muted">{{ trans('common.previous') }}</div>
<div class="inline-block">
<div class="icon-list-item no-hover">

View File

@ -31,7 +31,12 @@
<!-- Translations for JS -->
@stack('translations')
</head>
<body component="shortcuts" class="@stack('body-class')">
<body
@if(setting()->getForCurrentUser('ui-shortcuts-enabled', false))
component="shortcuts"
option:shortcuts:key-map="{{ \BookStack\Settings\UserShortcutMap::fromUserPreferences()->toJson() }}"
@endif
class="@stack('body-class')">
@include('layouts.parts.base-body-start')
@include('common.skip-to-content')

View File

@ -0,0 +1,11 @@
<div class="flex-container-row justify-space-between items-center gap-m item-list-row">
<label for="shortcut-{{ $label }}" class="bold flex px-m py-xs">{{ $label }}</label>
<div class="px-m py-xs">
<input type="text"
class="small flex-none shortcut-input px-s py-xs"
id="shortcut-{{ $id }}"
name="shortcut[{{ $id }}]"
readonly
value="{{ $shortcuts->getShortcut($id) }}">
</div>
</div>

View File

@ -0,0 +1,78 @@
@extends('layouts.simple')
@section('body')
<div class="container small my-xl">
<section class="card content-wrap">
<form action="{{ url('/preferences/shortcuts') }}" method="post">
{{ method_field('put') }}
{{ csrf_field() }}
<h1 class="list-heading">Interface Keyboard Shortcuts</h1>
<div class="flex-container-row items-center gap-m wrap mb-m">
<p class="flex mb-none min-width-m text-small text-muted">
Here you can enable or disable keyboard system interface shortcuts, used for navigation
and actions. You can customize each of the shortcuts below.
</p>
<div class="flex min-width-m text-m-right">
@include('form.toggle-switch', [
'name' => 'enabled',
'value' => $enabled,
'label' => 'Keyboard shortcuts enabled',
])
</div>
</div>
<hr>
<h2 class="list-heading mb-m">Navigation</h2>
<div class="flex-container-row wrap gap-m mb-xl">
<div class="flex min-width-l item-list">
@include('users.preferences.parts.shortcut-control', ['label' => 'Homepage', 'id' => 'home_view'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('entities.shelves'), 'id' => 'shelves_view'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('entities.books'), 'id' => 'books_view'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('settings.settings'), 'id' => 'settings_view'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('entities.my_favourites'), 'id' => 'favourites_view'])
</div>
<div class="flex min-width-l item-list">
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.view_profile'), 'id' => 'profile_view'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('auth.logout'), 'id' => 'logout'])
@include('users.preferences.parts.shortcut-control', ['label' => 'Global Search', 'id' => 'global_search'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.next'), 'id' => 'next'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.previous'), 'id' => 'previous'])
</div>
</div>
<h2 class="list-heading mb-m">Common Actions</h2>
<div class="flex-container-row wrap gap-m mb-xl">
<div class="flex min-width-l item-list">
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.new'), 'id' => 'new'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.edit'), 'id' => 'edit'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.copy'), 'id' => 'copy'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.delete'), 'id' => 'delete'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.favourite'), 'id' => 'favourite'])
</div>
<div class="flex min-width-l item-list">
@include('users.preferences.parts.shortcut-control', ['label' => trans('entities.export'), 'id' => 'export'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.sort'), 'id' => 'sort'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('entities.permissions'), 'id' => 'permissions'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('common.move'), 'id' => 'move'])
@include('users.preferences.parts.shortcut-control', ['label' => trans('entities.revisions'), 'id' => 'revisions'])
</div>
</div>
<p class="text-small text-muted">
Note: When shortcuts are enabled a helper overlay is available via pressing "?" which will
highlight the available shortcuts for actions currently visible on the screen.
</p>
<div class="form-group text-right">
<button class="button">{{ 'Save Shortcuts' }}</button>
</div>
</form>
</section>
</div>
@stop