improve gamebook editor UI
This commit is contained in:
parent
ca990d4b6c
commit
4510475440
|
@ -1,5 +1,7 @@
|
|||
.gb_edit .lichess_game .lichess_ground {
|
||||
margin-bottom: -517px;
|
||||
margin-bottom: -409px;
|
||||
}
|
||||
.gb_edit .lichess_game .lichess_ground {
|
||||
}
|
||||
.gb_edit .gamebook_wrap {
|
||||
height: 500px;
|
||||
|
@ -11,7 +13,6 @@
|
|||
}
|
||||
.gb_edit .gamebook .deviation,
|
||||
.gb_edit .gamebook .hint {
|
||||
padding-top: 8px;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
}
|
||||
|
@ -23,29 +24,43 @@
|
|||
resize: vertical;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 8em;
|
||||
height: 10em;
|
||||
border-width: 1px 0;
|
||||
padding: 5px;
|
||||
}
|
||||
.gb_edit .gamebook .hint textarea {
|
||||
height: 5em;
|
||||
height: 7em;
|
||||
}
|
||||
.gb_edit .gamebook .legend {
|
||||
padding: 8px 10px;
|
||||
display: flex;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
.gb_edit .gamebook .legend::before {
|
||||
display: block;
|
||||
float: left;
|
||||
font-size: 2.5em;
|
||||
margin: 2px 8px 0 0;
|
||||
opacity: 0.5;
|
||||
.gb_edit .gamebook .legend i {
|
||||
flex: 0 0 50px;
|
||||
font-size: 26px;
|
||||
opacity: 0.7;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.gb_edit .gamebook .todo {
|
||||
border-left: 5px solid #dc322f!important;
|
||||
.gb_edit .gamebook .legend.clickable:hover {
|
||||
cursor: pointer;
|
||||
background: #3893E8;
|
||||
color: #fff;
|
||||
}
|
||||
.gb_edit .gamebook .done {
|
||||
border-left: 5px solid #759900!important;
|
||||
.gb_edit .gamebook .legend.clickable:hover i {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.gb_edit .gamebook .legend p {
|
||||
flex: 1 1 100%;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
.gb_edit .gamebook .todo i {
|
||||
background: #dc322f;
|
||||
color: #fff;
|
||||
}
|
||||
.gb_edit .gamebook .done i {
|
||||
background: #759900;
|
||||
}
|
||||
|
||||
body.dark .gb_edit .gamebook {
|
||||
|
|
|
@ -793,6 +793,8 @@ export default class AnalyseCtrl {
|
|||
return this.study && this.study.gamebookPlay();
|
||||
}
|
||||
|
||||
isGamebook = (): boolean => !!(this.study && this.study.data.chapter.gamebook);
|
||||
|
||||
withCg<A>(f: (cg: ChessgroundApi) => A): A | undefined {
|
||||
if (this.chessground && this.cgVersion.js === this.cgVersion.dom)
|
||||
return f(this.chessground);
|
||||
|
|
|
@ -2,7 +2,7 @@ import { h } from 'snabbdom'
|
|||
import { Hooks } from 'snabbdom/hooks'
|
||||
import { VNode } from 'snabbdom/vnode'
|
||||
import AnalyseCtrl from '../../ctrl';
|
||||
import { bind } from '../../util';
|
||||
import { bind, iconTag } from '../../util';
|
||||
import { MaybeVNodes } from '../../interfaces';
|
||||
import { throttle } from 'common';
|
||||
|
||||
|
@ -19,60 +19,63 @@ export function render(ctrl: AnalyseCtrl): VNode {
|
|||
|
||||
let content: MaybeVNodes;
|
||||
|
||||
function commentButton(text: string = 'comment') {
|
||||
return h('a.button.thin', {
|
||||
hook: bind('click', () => {
|
||||
study.commentForm.open(study.vm.chapterId, ctrl.path, ctrl.node);
|
||||
}, ctrl.redraw),
|
||||
}, text);
|
||||
}
|
||||
const commentHook: Hooks = bind('click', () => {
|
||||
study.commentForm.open(study.vm.chapterId, ctrl.path, ctrl.node);
|
||||
}, ctrl.redraw);
|
||||
|
||||
if (!ctrl.path) {
|
||||
if (isMyMove) content = [
|
||||
h('div.legend.todo', { class: { done: isCommented } }, [
|
||||
'Help the player find the initial move, with a ',
|
||||
commentButton(),
|
||||
'.'
|
||||
h('div.legend.todo.clickable', {
|
||||
hook: commentHook,
|
||||
class: { done: isCommented }
|
||||
}, [
|
||||
iconTag('c'),
|
||||
h('p', 'Help the player find the initial move, with a comment.')
|
||||
]),
|
||||
renderHint(ctrl)
|
||||
];
|
||||
else content = [
|
||||
h('div.legend.todo', { class: { done: isCommented } }, [
|
||||
'Introduce the gamebook with a ',
|
||||
commentButton(),
|
||||
', and put the opponent\'s first move on the board.'
|
||||
])
|
||||
h('div.legend.todo', { class: { done: isCommented } },
|
||||
'Introduce the gamebook with a comment, and put the opponent\'s first move on the board.'
|
||||
)
|
||||
];
|
||||
}
|
||||
else if (ctrl.onMainline) {
|
||||
if (isMyMove) content = [
|
||||
h('div.legend.todo', { class: { done: isCommented } }, [
|
||||
'Comment the opponent move, and help the player find the next move, with a ',
|
||||
commentButton(),
|
||||
'.'
|
||||
h('div.legend.todo.clickable', {
|
||||
hook: commentHook,
|
||||
class: { done: isCommented }
|
||||
}, [
|
||||
iconTag('c'),
|
||||
h('p', 'Explain the opponent move, and help the player find the next move, with a comment.')
|
||||
]),
|
||||
renderHint(ctrl)
|
||||
];
|
||||
else content = [
|
||||
h('div.legend', [
|
||||
'Reflect on the player\'s correct move, with a ',
|
||||
commentButton(),
|
||||
'; or leave empty to jump immediately to the next move.'
|
||||
h('div.legend.clickable', {
|
||||
hook: commentHook,
|
||||
}, [
|
||||
iconTag('c'),
|
||||
h('p', 'Reflect on the player\'s correct move, with a comment; or leave empty to jump immediately to the next move.')
|
||||
]),
|
||||
hasVariation ? null : h('div.legend', [
|
||||
iconTag('G'),
|
||||
h('p', 'Add variation moves to explain why specific other moves are wrong.')
|
||||
]),
|
||||
hasVariation ? null : h('div.legend', {
|
||||
attrs: { 'data-icon': '' }
|
||||
}, 'Add variation moves to explain why specific other moves are wrong.'),
|
||||
renderDeviation(ctrl)
|
||||
];
|
||||
}
|
||||
else content = [
|
||||
h('div.legend.todo', { class: { done: isCommented } }, [
|
||||
'Explain why this move is wrong in a ',
|
||||
commentButton(),
|
||||
'.'
|
||||
h('div.legend.todo.clickable', {
|
||||
hook: commentHook,
|
||||
class: { done: isCommented }
|
||||
}, [
|
||||
iconTag('c'),
|
||||
h('p', 'Explain why this move is wrong in a comment')
|
||||
]),
|
||||
h('div.legend',
|
||||
'Or promote it as the mainline if it is the right move.')
|
||||
h('div.legend', [
|
||||
h('p', 'Or promote it as the mainline if it is the right move.')
|
||||
])
|
||||
];
|
||||
|
||||
return h('div.gamebook_wrap', {
|
||||
|
@ -84,11 +87,12 @@ export function render(ctrl: AnalyseCtrl): VNode {
|
|||
|
||||
function renderDeviation(ctrl: AnalyseCtrl): VNode {
|
||||
const field = 'deviation';
|
||||
return h('div.deviation.todo', { class: { done: nodeGamebookValue(ctrl.node, field).length > 2 } }, [
|
||||
h('label', {
|
||||
attrs: { for: 'gamebook-deviation' }
|
||||
}, 'When any other wrong move is played:'),
|
||||
h('textarea#gamebook-deviation', {
|
||||
return h('div.deviation', [
|
||||
h('div.legend.todo', { class: { done: nodeGamebookValue(ctrl.node, field).length > 2 } }, [
|
||||
iconTag('c'),
|
||||
h('p', 'When any other wrong move is played:')
|
||||
]),
|
||||
h('textarea', {
|
||||
attrs: { placeholder: 'Explain why all other moves are wrong' },
|
||||
hook: textareaHook(ctrl, field)
|
||||
})
|
||||
|
@ -98,10 +102,11 @@ function renderDeviation(ctrl: AnalyseCtrl): VNode {
|
|||
function renderHint(ctrl: AnalyseCtrl): VNode {
|
||||
const field = 'hint';
|
||||
return h('div.hint', [
|
||||
h('label', {
|
||||
attrs: { for: 'gamebook-hint' }
|
||||
}, 'Optional, on-demand hint for the player:'),
|
||||
h('textarea#gamebook-hint', {
|
||||
h('div.legend', [
|
||||
iconTag(''),
|
||||
h('p', 'Optional, on-demand hint for the player:')
|
||||
]),
|
||||
h('textarea', {
|
||||
attrs: { placeholder: 'Give the player a tip so they can find the right move' },
|
||||
hook: textareaHook(ctrl, field)
|
||||
})
|
||||
|
|
3
ui/analyse/src/study/gamebook/interfaces.ts
Normal file
3
ui/analyse/src/study/gamebook/interfaces.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
export type GamebookOverride = undefined | 'edit' | 'play' | 'analyse';
|
|
@ -2,8 +2,9 @@ import { Prop } from 'common';
|
|||
import { NotifCtrl } from './notif';
|
||||
import { AnalyseData } from '../interfaces';
|
||||
import { StudyPracticeCtrl } from './practice/interfaces';
|
||||
import GamebookPlayCtrl from './gamebook/gamebookPlayCtrl';
|
||||
import { ChapterDescriptionCtrl } from './chapterDescription';
|
||||
import GamebookPlayCtrl from './gamebook/gamebookPlayCtrl';
|
||||
import { GamebookOverride } from './gamebook/interfaces';
|
||||
|
||||
export interface StudyCtrl {
|
||||
data: StudyData;
|
||||
|
@ -61,8 +62,6 @@ export interface StudyVm {
|
|||
gamebookOverride: GamebookOverride;
|
||||
}
|
||||
|
||||
export type GamebookOverride = undefined | 'edit' | 'play' | 'analyse';
|
||||
|
||||
export interface StudyData {
|
||||
id: string;
|
||||
name: string;
|
||||
|
|
|
@ -13,7 +13,7 @@ import { ctrl as tagsCtrl } from './studyTags';
|
|||
import * as tours from './studyTour';
|
||||
import * as xhr from './studyXhr';
|
||||
import { path as treePath } from 'tree';
|
||||
import { StudyCtrl, StudyVm, Tab, TagTypes, StudyData, StudyChapterMeta, ReloadData, GamebookOverride } from './interfaces';
|
||||
import { StudyCtrl, StudyVm, Tab, TagTypes, StudyData, StudyChapterMeta, ReloadData } from './interfaces';
|
||||
import GamebookPlayCtrl from './gamebook/gamebookPlayCtrl';
|
||||
import { ChapterDescriptionCtrl } from './chapterDescription';
|
||||
|
||||
|
@ -40,9 +40,11 @@ export default function(data: StudyData, ctrl: AnalyseCtrl, tagTypes: TagTypes,
|
|||
sticky: sticked,
|
||||
write: true
|
||||
},
|
||||
behind: 0, // how many events missed because sync=off
|
||||
updatedAt: Date.now() - data.secondsSinceUpdate * 1000, // how stale is the study
|
||||
gamebookOverride: undefined
|
||||
// how many events missed because sync=off
|
||||
behind: 0,
|
||||
// how stale is the study
|
||||
updatedAt: Date.now() - data.secondsSinceUpdate * 1000,
|
||||
gamebookOverride: undefined
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -334,7 +336,7 @@ export default function(data: StudyData, ctrl: AnalyseCtrl, tagTypes: TagTypes,
|
|||
for (let i in chapters)
|
||||
if (chapters[i].id === currentId) return chapters[parseInt(i) + 1];
|
||||
},
|
||||
setGamebookOverride(o: GamebookOverride) {
|
||||
setGamebookOverride(o) {
|
||||
vm.gamebookOverride = o;
|
||||
instanciateGamebookPlay();
|
||||
vm.mode.write = o !== 'play';
|
||||
|
|
|
@ -197,7 +197,7 @@ function buttons(ctrl: AnalyseCtrl) {
|
|||
active: ctrl.explorer.enabled()
|
||||
}
|
||||
}, [iconTag(']')]),
|
||||
ctrl.ceval.possible && ctrl.ceval.allowed() ? h('button.hint--bottom', {
|
||||
ctrl.ceval.possible && ctrl.ceval.allowed() && !ctrl.isGamebook() ? h('button.hint--bottom', {
|
||||
attrs: {
|
||||
'data-hint': 'Practice with computer',
|
||||
'data-act': 'practice'
|
||||
|
|
Loading…
Reference in a new issue