study board editor WIP
parent
4e9a0c6236
commit
165581d195
|
@ -29,44 +29,44 @@ lichess.studyTourChapter = function(study) {
|
|||
text: "A study can have several chapters.<br>" +
|
||||
"Each chapter has a distinct move tree,<br>" +
|
||||
"and can be created in various ways.",
|
||||
attachTo: '.study_overboard label[for=chapter-name] left'
|
||||
attachTo: '.study__modal label[for=chapter-name] left'
|
||||
}, {
|
||||
title: "From initial position",
|
||||
text: "Just a board setup for a new game.<br>" +
|
||||
"Suited to explore openings.",
|
||||
attachTo: '.study_overboard .study_tabs .init top',
|
||||
attachTo: '.study__modal .tabs-horiz .init top',
|
||||
when: onTab('init')
|
||||
}, {
|
||||
title: "Custom position",
|
||||
text: "Setup the board your way.<br>" +
|
||||
"Suited to explore endgames.",
|
||||
attachTo: '.study_overboard .study_tabs .edit bottom',
|
||||
attachTo: '.study__modal .tabs-horiz .edit bottom',
|
||||
when: onTab('edit')
|
||||
}, {
|
||||
title: "Load an existing lichess game",
|
||||
text: "Paste a lichess game URL<br>" +
|
||||
"(like lichess.org/7fHIU0XI)<br>" +
|
||||
"to load the game moves in the chapter.",
|
||||
attachTo: '.study_overboard .study_tabs .game top',
|
||||
attachTo: '.study__modal .tabs-horiz .game top',
|
||||
when: onTab('game')
|
||||
}, {
|
||||
title: "From a FEN string",
|
||||
text: "Paste a position in FEN format<br>" +
|
||||
"<i>4k3/4rb2/8/7p/8/5Q2/1PP5/1K6 w</i><br>" +
|
||||
"to start the chapter from a position.",
|
||||
attachTo: '.study_overboard .study_tabs .fen top',
|
||||
attachTo: '.study__modal .tabs-horiz .fen top',
|
||||
when: onTab('fen')
|
||||
}, {
|
||||
title: "From a PGN game",
|
||||
text: "Paste a game in PGN format.<br>" +
|
||||
"to load moves, comments and variations in the chapter.",
|
||||
attachTo: '.study_overboard .study_tabs .pgn top',
|
||||
attachTo: '.study__modal .tabs-horiz .pgn top',
|
||||
when: onTab('pgn')
|
||||
}, {
|
||||
title: "Studies support variants",
|
||||
text: "Yes, you can study crazyhouse,<br>" +
|
||||
"and all lichess variants!",
|
||||
attachTo: '.study_overboard label[for=chapter-variant] left',
|
||||
attachTo: '.study__modal label[for=chapter-variant] left',
|
||||
when: onTab('init')
|
||||
}, {
|
||||
title: "Thanks for your time",
|
||||
|
@ -76,7 +76,7 @@ lichess.studyTourChapter = function(study) {
|
|||
text: 'Done',
|
||||
action: tour.next
|
||||
}],
|
||||
attachTo: '.study_overboard .help bottom'
|
||||
attachTo: '.study__modal .help bottom'
|
||||
}].forEach(function(s) {
|
||||
tour.addStep(s.title, s);
|
||||
});
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
@import 'explorer';
|
||||
@import 'training';
|
||||
@import 'practice';
|
||||
@import 'retro';
|
||||
@import 'fork';
|
||||
@import 'side';
|
||||
// @import 'side-clock';
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/* analyse a game replay */
|
||||
@import 'analyse.base';
|
||||
@import 'retro';
|
||||
@import 'acpl';
|
||||
|
||||
$col1-panel-height: 30vh;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@import 'analyse.base';
|
||||
@import '../../../common/css/form/form3';
|
||||
@import '../../../common/css/component/tabs-horiz';
|
||||
|
||||
@import '../study/show';
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
.board-editor-wrap {
|
||||
min-height: 280px;
|
||||
margin-bottom: 2em;
|
||||
.spinner {
|
||||
padding-top: 90px;
|
||||
}
|
||||
}
|
||||
|
||||
.board-editor {
|
||||
display: grid;
|
||||
grid-template-columns: 300px 2vmin 200px;
|
||||
grid-template-rows: min-content auto min-content;
|
||||
grid-template-areas:
|
||||
'. . e-tools'
|
||||
'e-spare-top . e-tools'
|
||||
'e-board . e-tools'
|
||||
'e-spare-bottom . e-tools'
|
||||
'. . e-tools';
|
||||
.main-board {
|
||||
grid-area: e-board;
|
||||
}
|
||||
&__tools {
|
||||
grid-area: e-tools;
|
||||
}
|
||||
&-top {
|
||||
grid-area: spare-top;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
&-bottom {
|
||||
grid-area: spare-bottom;
|
||||
margin-top: .5em;
|
||||
}
|
||||
}
|
|
@ -11,11 +11,15 @@
|
|||
h2 {
|
||||
margin-bottom: .5em;
|
||||
i {
|
||||
margin-left: 10px;
|
||||
opacity: 0.5;
|
||||
font-size: .6em;
|
||||
&, &::before {
|
||||
vertical-align: top;
|
||||
}
|
||||
margin-left: 1rem;
|
||||
opacity: .5;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
opacity: .7;
|
||||
color: $c-primary;
|
||||
}
|
||||
}
|
||||
|
@ -33,4 +37,8 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.chapter-new .tabs-horiz {
|
||||
margin: -1em 0 1.6em 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,3 +6,4 @@
|
|||
@import 'members';
|
||||
@import 'player';
|
||||
@import 'modal';
|
||||
@import 'editor';
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
justify-content: center;
|
||||
align-items: flex-end;
|
||||
border-bottom: 2px solid $c-border;
|
||||
a {
|
||||
@include breakpoint($mq-not-xx-small) {
|
||||
font-size: .9em;
|
||||
}
|
||||
span {
|
||||
@extend %roboto;
|
||||
flex: 1 1 auto;
|
||||
text-align: center;
|
||||
|
|
|
@ -11,10 +11,10 @@ import { title as descTitle } from './chapterDescription';
|
|||
import AnalyseCtrl from '../ctrl';
|
||||
|
||||
export const modeChoices = [
|
||||
['normal', "Normal analysis"],
|
||||
['practice', "Practice with computer"],
|
||||
['conceal', "Hide next moves"],
|
||||
['gamebook', "Interactive lesson"]
|
||||
['normal', 'Normal analysis'],
|
||||
['practice', 'Practice with computer'],
|
||||
['conceal', 'Hide next moves'],
|
||||
['gamebook', 'Interactive lesson']
|
||||
];
|
||||
|
||||
export function fieldValue(e: Event, id: string) {
|
||||
|
@ -28,9 +28,9 @@ export function ctrl(send: SocketSend, chapters: Prop<StudyChapterMeta[]>, setTa
|
|||
|
||||
const vm = {
|
||||
variants: [],
|
||||
open: false,
|
||||
open: true,
|
||||
initial: prop(false),
|
||||
tab: storedProp('study.form.tab', 'init'),
|
||||
tab: storedProp('study.form.tab', 'editor'),
|
||||
editor: null,
|
||||
editorFen: prop(null)
|
||||
};
|
||||
|
@ -86,7 +86,7 @@ export function view(ctrl): VNode {
|
|||
|
||||
const activeTab = ctrl.vm.tab();
|
||||
const makeTab = function(key: string, name: string, title: string) {
|
||||
return h('a.' + key, {
|
||||
return h('span.' + key, {
|
||||
class: { active: activeTab === key },
|
||||
attrs: { title },
|
||||
hook: bind('click', () => ctrl.vm.tab(key), ctrl.root.redraw)
|
||||
|
@ -109,7 +109,7 @@ export function view(ctrl): VNode {
|
|||
hook: bind('click', ctrl.startTour)
|
||||
})
|
||||
]),
|
||||
h('form.chapter_form.material.form', {
|
||||
h('form.form3', {
|
||||
hook: bindSubmit(e => {
|
||||
const o: any = {
|
||||
fen: fieldValue(e, 'fen') || (ctrl.vm.tab() === 'edit' ? ctrl.vm.editorFen() : null)
|
||||
|
@ -121,7 +121,10 @@ export function view(ctrl): VNode {
|
|||
}, ctrl.redraw)
|
||||
}, [
|
||||
h('div.form-group', [
|
||||
h('input#chapter-name', {
|
||||
h('label.form-label', {
|
||||
attrs: {for: 'chapter-name' }
|
||||
}, 'Name'),
|
||||
h('input#chapter-name.form-control', {
|
||||
attrs: {
|
||||
minlength: 2,
|
||||
maxlength: 80
|
||||
|
@ -133,20 +136,16 @@ export function view(ctrl): VNode {
|
|||
el.focus();
|
||||
}
|
||||
})
|
||||
}),
|
||||
h('label.control-label', {
|
||||
attrs: {for: 'chapter-name' }
|
||||
}, 'Name'),
|
||||
h('i.bar')
|
||||
})
|
||||
]),
|
||||
h('div.study_tabs', [
|
||||
makeTab('init', 'Init', 'Start from initial position'),
|
||||
makeTab('edit', 'Edit', 'Start from custom position'),
|
||||
h('div.tabs-horiz', [
|
||||
makeTab('init', 'Empty', 'Start from initial position'),
|
||||
makeTab('edit', 'Editor', 'Start from custom position'),
|
||||
makeTab('game', 'URL', 'Load a game URL'),
|
||||
makeTab('fen', 'FEN', 'Load a FEN position'),
|
||||
makeTab('pgn', 'PGN', 'Load a PGN game')
|
||||
]),
|
||||
activeTab === 'edit' ? h('div.editor_wrap.is2d', {
|
||||
activeTab === 'edit' ? h('div.board-editor-wrap.is2d', {
|
||||
hook: {
|
||||
insert: vnode => {
|
||||
$.when(
|
||||
|
@ -171,29 +170,26 @@ export function view(ctrl): VNode {
|
|||
}
|
||||
}, [spinner()]) : null,
|
||||
activeTab === 'game' ? h('div.form-group', [
|
||||
h('input#chapter-game', {
|
||||
attrs: { placeholder: 'URL of the game' }
|
||||
}),
|
||||
h('label.control-label', {
|
||||
h('label.form-label', {
|
||||
attrs: { 'for': 'chapter-game' }
|
||||
}, 'Load a game from lichess.org or chessgames.com'),
|
||||
h('i.bar')
|
||||
h('input#chapter-game.form-control', {
|
||||
attrs: { placeholder: 'URL of the game' }
|
||||
})
|
||||
]) : null,
|
||||
activeTab === 'fen' ? h('div.form-group.no-label', [
|
||||
h('input#chapter-fen', {
|
||||
activeTab === 'fen' ? h('div.form-group', [
|
||||
h('input#chapter-fen.form-control', {
|
||||
attrs: {
|
||||
value: ctrl.root.node.fen,
|
||||
placeholder: 'Initial FEN position'
|
||||
}
|
||||
}),
|
||||
h('i.bar')
|
||||
})
|
||||
]) : null,
|
||||
activeTab === 'pgn' ? h('div.form-group.no-label', [
|
||||
h('textarea#chapter-pgn', {
|
||||
activeTab === 'pgn' ? h('div.form-groupabel', [
|
||||
h('textarea#chapter-pgn.form-control', {
|
||||
attrs: { placeholder: 'Paste your PGN text here, up to ' + ctrl.multiPgnMax + ' games' }
|
||||
}),
|
||||
h('i.bar'),
|
||||
window.FileReader ? h('input#chapter-pgn-file', {
|
||||
window.FileReader ? h('input#chapter-pgn-file.form-control', {
|
||||
attrs: {
|
||||
type: 'file',
|
||||
accept: '.pgn'
|
||||
|
@ -209,40 +205,37 @@ export function view(ctrl): VNode {
|
|||
})
|
||||
}) : null
|
||||
]) : null,
|
||||
h('div', [
|
||||
h('div.form-group.half.little-margin-bottom', [
|
||||
h('select#chapter-variant', {
|
||||
h('div.form-split', [
|
||||
h('div.form-group.form-half', [
|
||||
h('label.form-label', {
|
||||
attrs: { 'for': 'chapter-variant' }
|
||||
}, 'Variant'),
|
||||
h('select#chapter-variant.form-control', {
|
||||
attrs: { disabled: gameOrPgn }
|
||||
}, gameOrPgn ? [
|
||||
h('option', 'Automatic')
|
||||
] :
|
||||
ctrl.vm.variants.map(v => option(v.key, currentChapterSetup.variant.key, v.name))),
|
||||
h('label.control-label', {
|
||||
attrs: { 'for': 'chapter-variant' }
|
||||
}, 'Variant'),
|
||||
h('i.bar')
|
||||
ctrl.vm.variants.map(v => option(v.key, currentChapterSetup.variant.key, v.name)))
|
||||
]),
|
||||
h('div.form-group.half.little-margin-bottom', [
|
||||
h('select#chapter-orientation', {
|
||||
h('div.form-group.form-half', [
|
||||
h('label.form-label', {
|
||||
attrs: { 'for': 'chapter-orientation' }
|
||||
}, 'Orientation'),
|
||||
h('select#chapter-orientation.form-control', {
|
||||
hook: bind('change', e => {
|
||||
ctrl.vm.editor && ctrl.vm.editor.setOrientation((e.target as HTMLInputElement).value);
|
||||
})
|
||||
}, ['White', 'Black'].map(function(color) {
|
||||
const c = color.toLowerCase();
|
||||
return option(c, currentChapterSetup.orientation, color);
|
||||
})),
|
||||
h('label.control-label', {
|
||||
attrs: { 'for': 'chapter-orientation' }
|
||||
}, 'Orientation'),
|
||||
h('i.bar')
|
||||
}))
|
||||
])
|
||||
]),
|
||||
h('div.form-group.little-margin-bottom', [
|
||||
h('select#chapter-mode', modeChoices.map(c => option(c[0], '', c[1]))),
|
||||
h('label.control-label', {
|
||||
h('div.form-group', [
|
||||
h('label.form-label', {
|
||||
attrs: { 'for': 'chapter-mode' }
|
||||
}, 'Analysis mode'),
|
||||
h('i.bar')
|
||||
h('select#chapter-mode.form-control', modeChoices.map(c => option(c[0], '', c[1])))
|
||||
]),
|
||||
dialog.button('Create chapter')
|
||||
])
|
||||
|
|
|
@ -145,13 +145,13 @@ export function side(ctrl: StudyCtrl): VNode {
|
|||
const activeTab = ctrl.vm.tab();
|
||||
|
||||
const makeTab = function(key: Tab, name: string) {
|
||||
return h('a.' + key, {
|
||||
return h('span.' + key, {
|
||||
class: { active: activeTab === key },
|
||||
hook: bind('mousedown', () => ctrl.vm.tab(key), ctrl.redraw)
|
||||
}, name);
|
||||
};
|
||||
|
||||
const tabs = h('div.study__tabs', [
|
||||
const tabs = h('div.tabs-horiz', [
|
||||
makeTab('chapters', plural(ctrl.relay ? 'Game' : 'Chapter', ctrl.chapters.size())),
|
||||
makeTab('members', plural('Member', ctrl.members.size())),
|
||||
ctrl.members.isOwner() ? h('a.more', {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
}
|
||||
&-wrap {
|
||||
@extend %box-radius, %popup-shadow, %flex-column;
|
||||
background: $c-bg-popup;
|
||||
background: $c-bg-box;
|
||||
position: relative;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
.lobby__app__tabs {
|
||||
.tabs-horiz {
|
||||
@extend %flex-center-nowrap;
|
||||
justify-content: center;
|
||||
align-items: flex-end;
|
|
@ -3,5 +3,6 @@
|
|||
@import '../../../common/css/component/now-playing';
|
||||
@import '../../../common/css/component/color-icon';
|
||||
@import '../../../common/css/component/glowing';
|
||||
@import '../../../common/css/component/tabs-horiz';
|
||||
@import '../../../common/css/base/scrollbar';
|
||||
@import '../lobby';
|
||||
|
|
|
@ -27,7 +27,7 @@ export default function(ctrl: LobbyController) {
|
|||
break;
|
||||
}
|
||||
return h('div.lobby__app.lobby__app-' + ctrl.tab, [
|
||||
h('div.lobby__app__tabs', renderTabs(ctrl)),
|
||||
h('div.tabs-horiz', renderTabs(ctrl)),
|
||||
h('div.lobby__app__content.l' + (ctrl.redirecting ? 'redir' : ctrl.tab), data, body)
|
||||
]);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue