-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
347 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
import React, { useCallback, useEffect, useMemo, useState } from 'react'; | ||
import branchesSlice from '@/redux/modules/branches'; | ||
import { useUIProperty } from '@/shared/hooks'; | ||
import Button from '@material-ui/core/Button'; | ||
import Grid from '@material-ui/core/Grid'; | ||
import Input from '@material-ui/core/Input'; | ||
import Slider from '@material-ui/core/Slider'; | ||
import Typography from '@material-ui/core/Typography'; | ||
import HistoryIcon from 'mdi-react/HistoryIcon'; | ||
import PlayArrowIcon from 'mdi-react/PlayArrowIcon'; | ||
import StopIcon from 'mdi-react/StopIcon'; | ||
import { useSelector } from 'react-redux'; | ||
import styled from 'styled-components'; | ||
|
||
const Container = styled.div` | ||
display: flex; | ||
flex-direction: column; | ||
box-sizing: border-box; | ||
width: 100%; | ||
padding: 30px 20px 0px; | ||
`; | ||
|
||
const InputStyled = styled(Input)` | ||
width: 70px; | ||
`; | ||
|
||
const GridStyled = styled(Grid)` | ||
margin-top: 10px; | ||
`; | ||
|
||
const SliderContainer = styled(Grid)` | ||
&:not(#fake-id-for-hack) { | ||
padding-left: 22px; | ||
padding-top: 30px; | ||
} | ||
`; | ||
|
||
const valueLabelFormat = (value) => -value; | ||
|
||
const Body = () => { | ||
const [, setBodyOpen] = useUIProperty('bodyOpen'); | ||
const [isAnalysing, setIsAnalysing] = useUIProperty('isAnalysing'); | ||
|
||
const { selected: branch } = useSelector(branchesSlice.selectors.getState); | ||
const { commits = 0 } = branch || {}; | ||
const [storedValue, setStoredValue] = useUIProperty('commitsCount', Math.min(100, commits)); | ||
const [value, setValue] = useState(-Math.min(commits, storedValue || 100)); | ||
const min = -commits; | ||
const max = 0; | ||
|
||
const marks = useMemo( | ||
() => [{ | ||
value: min, | ||
label: `${-min}`, | ||
}, min && { | ||
value: Math.floor(min * 0.5), | ||
label: `${Math.floor(-min * 0.5)}`, | ||
}].filter(Boolean), | ||
[min], | ||
); | ||
|
||
const onChange = useCallback( | ||
(_, newValue) => { | ||
setValue(newValue); | ||
}, | ||
[], | ||
); | ||
|
||
const onChangeInput = useCallback( | ||
(event) => { | ||
const newValue = event.target.value; | ||
setValue((prev) => { | ||
if (!newValue && newValue !== 0) { | ||
return prev; | ||
} | ||
return Math.min(max, Math.max(min, -(+newValue))); | ||
}); | ||
}, | ||
[max, min], | ||
); | ||
|
||
const onClick = useCallback( | ||
() => { | ||
if (!value) { | ||
return; | ||
} | ||
|
||
setIsAnalysing((prev) => !prev); | ||
setBodyOpen(false); | ||
}, | ||
[setBodyOpen, setIsAnalysing, value], | ||
); | ||
|
||
useEffect( | ||
() => { | ||
setStoredValue(-value); | ||
}, | ||
[setStoredValue, value], | ||
); | ||
|
||
return ( | ||
<Container> | ||
<Grid container spacing={1} alignItems="center"> | ||
<Grid item> | ||
<HistoryIcon size={26} /> | ||
</Grid> | ||
<Grid item> | ||
<Typography gutterBottom> | ||
Analyze | ||
</Typography> | ||
</Grid> | ||
<Grid item> | ||
<InputStyled | ||
value={-value} | ||
margin="dense" | ||
onChange={onChangeInput} | ||
inputProps={{ | ||
step: 1, | ||
type: 'number', | ||
}} | ||
disabled={isAnalysing} | ||
/> | ||
</Grid> | ||
<Grid item> | ||
<Typography gutterBottom> | ||
last of commits: | ||
</Typography> | ||
</Grid> | ||
</Grid> | ||
<GridStyled container spacing={2} alignItems="center"> | ||
<SliderContainer item xs> | ||
<Slider | ||
min={min} | ||
max={max} | ||
value={value} | ||
marks={marks} | ||
onChange={onChange} | ||
valueLabelFormat={valueLabelFormat} | ||
valueLabelDisplay="on" | ||
track="inverted" | ||
disabled={isAnalysing} | ||
/> | ||
</SliderContainer> | ||
<Grid item> | ||
<Button | ||
variant="outlined" | ||
color={isAnalysing ? 'secondary' : ''} | ||
onClick={onClick} | ||
> | ||
{isAnalysing ? <StopIcon /> : <PlayArrowIcon />} | ||
</Button> | ||
</Grid> | ||
</GridStyled> | ||
</Container> | ||
); | ||
}; | ||
|
||
export default Body; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React from 'react'; | ||
import PollIcon from 'mdi-react/PollIcon'; | ||
import styled from 'styled-components'; | ||
import HeaderContainer from '../shared/HeaderContainer'; | ||
|
||
const Container = styled(HeaderContainer)` | ||
flex: unset; | ||
`; | ||
|
||
const Header = (props) => { | ||
return ( | ||
<Container {...props} title="Analyze commits"> | ||
<PollIcon size={32} /> | ||
</Container> | ||
); | ||
}; | ||
|
||
export default Header; |
92 changes: 82 additions & 10 deletions
92
src/components/Header/components/shared/HeaderContainer.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,109 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import styled from 'styled-components'; | ||
|
||
const HeaderContainer = styled.button` | ||
const Container = styled.button` | ||
position: relative; | ||
display: flex; | ||
box-sizing: border-box; | ||
padding: 5px; | ||
padding: 0; | ||
margin: 0; | ||
font-size: 0.8em; | ||
align-items: center; | ||
flex: 1 1 0; | ||
background: transparent; | ||
border: 0; | ||
border-radius: 0; | ||
color: inherit; | ||
cursor: pointer; | ||
overflow: hidden; | ||
cursor: pointer; | ||
transition: background 0.3s, opacity 0.5s; | ||
outline: 0; | ||
&:focus-visible { | ||
outline: -webkit-focus-ring-color auto 1px; | ||
} | ||
&:hover { | ||
&:disabled { | ||
cursor: default; | ||
} | ||
`; | ||
|
||
const Children = styled.div` | ||
position: relative; | ||
display: flex; | ||
height: 100%; | ||
box-sizing: border-box; | ||
padding: 5px; | ||
align-items: center; | ||
transition: background 0.3s, opacity 0.5s; | ||
flex: 1 1 0; | ||
overflow: hidden; | ||
${Container}:hover:not(:disabled) & { | ||
background: rgba(255, 255, 255, 0.1); | ||
} | ||
&:active { | ||
${Container}:active:not(:disabled) & { | ||
background: rgba(255, 255, 255, 0.2); | ||
} | ||
&:disabled { | ||
${Container}:disabled & { | ||
opacity: 0.4; | ||
} | ||
`; | ||
|
||
const Divider = styled.div` | ||
position: relative; | ||
padding: 5px; | ||
flex-shrink: 0; | ||
max-width: 10px; | ||
min-width: 10px; | ||
height: 100%; | ||
overflow: hidden; | ||
//background: #fff; | ||
:after { | ||
position: absolute; | ||
top: 50%; | ||
left: 50%; | ||
content: ''; | ||
width: 80px; | ||
border: 1px solid rgba(0, 0, 0, 0.3); | ||
height: 80px; | ||
box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.1); | ||
transform: scale(0.3, 1)translate(calc(-200% - 16px), -50%)rotate(45deg); | ||
background: transparent; | ||
transition: background 0.3s; | ||
} | ||
${Container}:hover:not(:disabled) &:after { | ||
background: rgba(255, 255, 255, 0.1); | ||
} | ||
${Container}:active:not(:disabled) &:after { | ||
background: rgba(255, 255, 255, 0.2); | ||
} | ||
`; | ||
|
||
const HeaderContainer = ({ divider, children, ...rest }) => { | ||
return ( | ||
<Container type="button" {...rest}> | ||
<Children>{children}</Children> | ||
{divider && <Divider />} | ||
</Container> | ||
); | ||
}; | ||
|
||
HeaderContainer.propTypes = { | ||
children: PropTypes.oneOfType([ | ||
PropTypes.arrayOf(PropTypes.node), | ||
PropTypes.node, | ||
]), | ||
divider: PropTypes.bool, | ||
}; | ||
|
||
HeaderContainer.defaultProps = { | ||
children: [], | ||
divider: false, | ||
}; | ||
|
||
export default HeaderContainer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.