Skip to content

Commit 9b3d38a

Browse files
authored
Merge pull request hexlet-codebattle#1070 from valerr/master
add special event icons in replayer
2 parents cc14ff3 + 9fff2b0 commit 9b3d38a

5 files changed

Lines changed: 67 additions & 25 deletions

File tree

services/app/assets/css/style.scss

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,12 +209,17 @@ a {
209209
}
210210

211211
.cb-slider-action {
212-
width: 20px;
212+
width: 5px;
213213
height: 20px;
214214
left: 0;
215-
top: 12px;
216-
opacity: 0;
217-
transform: translateY(-100%);
215+
top: 50%;
216+
transform: translate(0, -50%);
217+
z-index: 15;
218+
}
219+
220+
.cb-slider-action:hover {
221+
display: block;
222+
height: 28px;
218223
}
219224

220225
.cb-slider-handle {

services/app/assets/js/widgets/components/CodebattleSliderBar.jsx

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import { Tooltip, OverlayTrigger } from 'react-bootstrap';
23
import { replayerMachineStates } from '../machines/game';
34

45
const handleClassnames = 'cb-slider-handle position-absolute rounded-circle';
@@ -14,14 +15,32 @@ const SliderBar = ({ value, className }) => (
1415
/>
1516
);
1617

17-
const SliderAction = ({ value, className }) => (
18-
<div
19-
className={className}
20-
style={{
21-
left: `${value * 100}%`,
22-
}}
23-
/>
24-
);
18+
const SliderAction = ({
19+
value, className, setGameState, event,
20+
}) => (
21+
<div>
22+
<OverlayTrigger
23+
placement="top"
24+
overlay={(
25+
<Tooltip id="tooltip-top">
26+
{`Check started by ${event.userName}`}
27+
</Tooltip>
28+
)}
29+
>
30+
<div
31+
role="button"
32+
aria-hidden="true"
33+
onClick={() => {
34+
setGameState(value);
35+
}}
36+
className={className}
37+
style={{
38+
left: `${value * 100}%`,
39+
}}
40+
/>
41+
</OverlayTrigger>
42+
</div>
43+
);
2544

2645
const SliderHandle = ({ value, className }) => (
2746
<div
@@ -34,12 +53,10 @@ const SliderHandle = ({ value, className }) => (
3453
</div>
3554
);
3655

37-
const CodebattleSliderBar = ({ gameCurrent, handlerPosition, lastIntent }) => (
56+
const CodebattleSliderBar = ({
57+
gameCurrent, handlerPosition, lastIntent, mainEvents, recordsCount, setGameState,
58+
}) => (
3859
<>
39-
<SliderAction
40-
value={0.5}
41-
className="cb-slider-action position-absolute bg-info"
42-
/>
4360
<div className="cb-slider-timeline position-absolute rounded w-100 x-bg-gray">
4461
{
4562
gameCurrent.matches({ replayer: replayerMachineStates.holded })
@@ -54,11 +71,20 @@ const CodebattleSliderBar = ({ gameCurrent, handlerPosition, lastIntent }) => (
5471
className={`${sliderBarClassnames} bg-danger`}
5572
value={handlerPosition}
5673
/>
57-
<SliderHandle
58-
className={handleClassnames}
59-
value={handlerPosition}
60-
/>
6174
</div>
75+
{mainEvents.map(event => (
76+
<SliderAction
77+
value={event.recordId / recordsCount}
78+
className="cb-slider-action position-absolute bg-warning rounded"
79+
key={event.recordId}
80+
event={event}
81+
setGameState={setGameState}
82+
/>
83+
))}
84+
<SliderHandle
85+
className={handleClassnames}
86+
value={handlerPosition}
87+
/>
6288
</>
6389
);
6490

services/app/assets/js/widgets/containers/CodebattlePlayer.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ class CodebattlePlayer extends Component {
188188

189189
render() {
190190
const { current: gameCurrent } = this.context;
191+
const { recordsCount, mainEvents } = this.props;
191192

192193
const {
193194
isEnabled, direction, handlerPosition, lastIntent,
@@ -222,9 +223,12 @@ class CodebattlePlayer extends Component {
222223
onIntentEnd={this.onSliderHandleChangeIntentEnd}
223224
>
224225
<CodebattleSliderBar
226+
mainEvents={mainEvents}
225227
gameCurrent={gameCurrent}
226228
handlerPosition={handlerPosition}
227229
lastIntent={lastIntent}
230+
recordsCount={recordsCount}
231+
setGameState={this.setGameState}
228232
/>
229233
</Slider>
230234
</ControlPanel>
@@ -241,10 +245,12 @@ CodebattlePlayer.contextType = GameContext;
241245

242246
const mapStateToProps = state => {
243247
const recordsCount = playbookRecordsSelector(state).length;
248+
const { mainEvents } = state.playbook;
244249

245250
return {
246251
recordsCount,
247252
stepCoefficient: 1.0 / recordsCount,
253+
mainEvents,
248254
};
249255
};
250256

services/app/assets/js/widgets/lib/player.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,13 @@ const reduceOriginalRecords = (acc, record, index) => {
132132
const { checkResult } = record;
133133

134134
const newPlayers = updatePlayers(players, { id: record.id, checkResult });
135+
const userName = _.find(players, { id: record.id }).name;
135136
const data = {
136137
type,
137138
userId: record.id,
138139
checkResult,
140+
userName,
141+
recordId: record.recordId,
139142
};
140143
const newRecord = createFinalRecord(index, data, {
141144
players: newPlayers,

services/app/assets/js/widgets/slices/playbook.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { createSlice } from '@reduxjs/toolkit';
2-
import { addRecord } from '../lib/player';
2+
import { addRecord, parse } from '../lib/player';
33
import { actions as editorActions } from './editor';
44
import { actions as executionOutputActions } from './executionOutput';
55

66
const initialState = {
7+
mainEvents: [],
78
players: [],
89
task: {},
910
initRecords: [],
@@ -14,9 +15,10 @@ const playbook = createSlice({
1415
name: 'playbook',
1516
initialState,
1617
reducers: {
17-
loadPlaybook: (state, { payload }) => (
18-
{ ...state, ...payload }
19-
),
18+
loadPlaybook: (state, { payload }) => {
19+
const mainEvents = payload.records.filter(record => parse(record).type === 'check_complete').map(parse);
20+
return { ...state, ...payload, mainEvents };
21+
},
2022
},
2123
extraReducers: {
2224
[editorActions.updateEditorText]: (state, { payload }) => {

0 commit comments

Comments
 (0)