This commit is contained in:
Бахирев 2024-05-03 00:54:10 +03:00
parent 6f27ca2970
commit 8196e23ed8
19 changed files with 231 additions and 202 deletions

View file

@ -27,7 +27,7 @@
"build-rename-css": "mv build/static/css/main.*.css build/static/index.css && rm -rf build/static/css", "build-rename-css": "mv build/static/css/main.*.css build/static/index.css && rm -rf build/static/css",
"build-rename-html": "rm build/index.html && mv build/local.html build/index.html", "build-rename-html": "rm build/index.html && mv build/local.html build/index.html",
"dev": "set PORT=3006 && react-app-rewired start", "dev": "set PORT=3006 && react-app-rewired start",
"build": "react-scripts build && npm run build-rename", "build": "react-scripts build",
"build-local": "set REACT_APP_TYPE=local && react-scripts build && npm run build-rename && npm run build-rename-html", "build-local": "set REACT_APP_TYPE=local && react-scripts build && npm run build-rename && npm run build-rename-html",
"test": "react-scripts test", "test": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject",

View file

@ -22,7 +22,7 @@ function Columns({ week, day, max }: IColumnsProps): React.ReactElement | null {
return ( return (
<div <div
key={hour} key={hour}
className={style.hour} className={style.hours_chart_hour}
style={{ style={{
color, color,
backgroundColor: `rgba(${backgroundColor}, ${opacity})`, backgroundColor: `rgba(${backgroundColor}, ${opacity})`,

View file

@ -8,19 +8,19 @@ function Header(): React.ReactElement | null {
if (!hour) return ( if (!hour) return (
<div <div
key={hour} key={hour}
className={style.day_name} className={style.hours_chart_day_name}
></div> ></div>
); );
return ( return (
<div <div
key={hour} key={hour}
className={style.day_time} className={style.hours_chart_day_time}
> >
<span className={style.day_time_hh}> <span className={style.hours_chart_day_time_hh}>
{get2Number(hour - 1)} {get2Number(hour - 1)}
</span> </span>
<span className={style.day_time_mm}> <span className={style.hours_chart_day_time_mm}>
:00 :00
</span> </span>
</div> </div>

View file

@ -6,24 +6,24 @@ import style from '../styles/legend.module.scss';
function Legend(): React.ReactElement | null { function Legend(): React.ReactElement | null {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<div className={style.legend}> <div className={style.hours_chart_legend}>
<div className={style.legend_item}> <div className={style.hours_chart_legend_item}>
<div className={style.legend_work}></div> <div className={style.hours_chart_legend_work}></div>
<div className={style.legend_title}> <div className={style.hours_chart_legend_title}>
{t('uiKit.hoursChart.work')} {t('uiKit.hoursChart.work')}
</div> </div>
</div> </div>
<div className={style.legend_item}> <div className={style.hours_chart_legend_item}>
<div className={style.legend_weekend}></div> <div className={style.hours_chart_legend_weekend}></div>
<div className={style.legend_title}> <div className={style.hours_chart_legend_title}>
{t('uiKit.hoursChart.weekend')} {t('uiKit.hoursChart.weekend')}
</div> </div>
</div> </div>
<div className={style.legend_item}> <div className={style.hours_chart_legend_item}>
<div className={style.legend_count}> <div className={style.hours_chart_legend_count}>
42 42
</div> </div>
<div className={style.legend_title}> <div className={style.hours_chart_legend_title}>
{t('uiKit.hoursChart.days')} {t('uiKit.hoursChart.days')}
</div> </div>
</div> </div>

View file

@ -1,90 +1,94 @@
@import 'src/styles/variables'; @import 'src/styles/variables';
.user { .hours_chart {
display: block; &_user {
box-sizing: border-box; display: block;
vertical-align: top; box-sizing: border-box;
margin: 24px 0 0 0; vertical-align: top;
margin: 24px 0 0 0;
--commits-by-hours-size: calc((100vw - 400px) / 25); --commits-by-hours-size: calc((100vw - 400px) / 25);
} }
.title { &_title {
display: inline-block; display: inline-block;
width: 200px; width: 200px;
text-align: left; text-align: left;
white-space: nowrap; white-space: nowrap;
} }
.data { &_data {
display: inline-block; display: inline-block;
width: 100%; width: 100%;
vertical-align: top; vertical-align: top;
} }
.day { &_day {
display: block; display: block;
width: 100%; width: 100%;
vertical-align: top; vertical-align: top;
white-space: nowrap; white-space: nowrap;
} }
.day_time, &_day_time,
.day_name, &_day_name,
.hour { &_hour {
font-size: var(--font-xs); font-size: var(--font-xs);
display: inline-block; display: inline-block;
width: var(--commits-by-hours-size); width: var(--commits-by-hours-size);
height: var(--commits-by-hours-size); height: var(--commits-by-hours-size);
text-align: center; text-align: center;
line-height: var(--commits-by-hours-size); line-height: var(--commits-by-hours-size);
vertical-align: top; vertical-align: top;
box-sizing: border-box; box-sizing: border-box;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
-webkit-print-color-adjust: exact; -webkit-print-color-adjust: exact;
} }
.day_time, &_day_time,
.day_name { &_day_name {
box-sizing: border-box; box-sizing: border-box;
border-bottom: 1px solid grey; border-bottom: 1px solid grey;
} }
.day_name { &_day_name {
font-size: var(--font-xs); font-size: var(--font-xs);
border-right: 1px solid grey; border-right: 1px solid grey;
} }
.hour { &_hour {
color: white; color: white;
border-radius: 6px; border-radius: 6px;
border: 1px solid #FFFFFF; border: 1px solid #FFFFFF;
background-color: var(--color-first); background-color: var(--color-first);
}
} }
@media (max-width: 1300px) { @media (max-width: 1300px) {
.day_time_mm { .hours_chart_day_time_mm {
display: none; display: none;
} }
} }
@media (max-width: 1000px) { @media (max-width: 1000px) {
.user { .hours_chart_user {
--commits-by-hours-size: calc((100vw - 156px) / 25); --commits-by-hours-size: calc((100vw - 156px) / 25);
} }
} }
@media (max-width: 900px) { @media (max-width: 900px) {
.day_time, .hours_chart {
.day_name, &_day_time,
.hour { &_day_name,
font-size: var(--font-xxs); &_hour {
} font-size: var(--font-xxs);
}
.hour { &_hour {
border-radius: 0; border-radius: 0;
border: none; border: none;
}
} }
} }

View file

@ -21,9 +21,9 @@ function HoursChart({
return ( return (
<div <div
key={day} key={day}
className={style.day} className={style.hours_chart_day}
> >
<div className={style.day_name}> <div className={style.hours_chart_day_name}>
{getDayName(day, 'short')} {getDayName(day, 'short')}
</div> </div>
<Columns <Columns
@ -36,9 +36,9 @@ function HoursChart({
}); });
return ( return (
<div className={style.user}> <div className={style.hours_chart_user}>
<div className={style.data}> <div className={style.hours_chart_data}>
<div className={style.day}> <div className={style.hours_chart_day}>
<Header /> <Header />
</div> </div>
{items} {items}

View file

@ -1,6 +1,6 @@
@import 'src/styles/variables'; @import 'src/styles/variables';
.legend { .hours_chart_legend {
display: block; display: block;
box-sizing: border-box; box-sizing: border-box;
vertical-align: top; vertical-align: top;

View file

@ -3,7 +3,7 @@
.recommendations_container { .recommendations_container {
position: relative; position: relative;
display: block; display: block;
margin: 0; margin: 0 auto 12px 0;
padding: 0; padding: 0;
text-align: left; text-align: left;

View file

@ -42,10 +42,10 @@ function Header({
{formattedTitle} {formattedTitle}
</span> </span>
{column.title && column.sortDirection === -1 && ( {column.title && column.sortDirection === -1 && (
<div className={headerStyle.sort_down} /> <div className={headerStyle.table_sort_down} />
)} )}
{column.title && column.sortDirection === 1 && ( {column.title && column.sortDirection === 1 && (
<div className={headerStyle.sort_up} /> <div className={headerStyle.table_sort_up} />
)} )}
</div> </div>
); );

View file

@ -1,28 +1,23 @@
@import 'src/styles/variables'; @import 'src/styles/variables';
.title { .table {
font-size: var(--font-l); &_sort_up,
font-weight: 100; &_sort_down {
margin: 24px 0; display: inline-block;
color: var(--color-black); height: 0;
} width: 0;
margin: 0 0 -5px 8px;
.sort_up,
.sort_down { cursor: pointer;
display: inline-block; transform: rotateZ(-45deg);
height: 0;
width: 0; border: 6px solid var(--color-grey);
margin: 0 0 -5px 8px; border-left-color: white;
border-bottom-color: white;
cursor: pointer; }
transform: rotateZ(-45deg);
&_sort_down {
border: 6px solid var(--color-grey); margin: 0 0 3px 8px;
border-left-color: white; transform: rotateZ(135deg);
border-bottom-color: white; }
}
.sort_down {
margin: 0 0 3px 8px;
transform: rotateZ(135deg);
} }

View file

@ -163,8 +163,7 @@ export default class DataGripByAuthor {
const moneyLosses = lazyDays > 0 const moneyLosses = lazyDays > 0
? Math.ceil(lazyDays * middleSalaryInDay) ? Math.ceil(lazyDays * middleSalaryInDay)
: 0; : 0;
const salaryInMonth = settingsStore.getMiddleSalaryInMonth(dot.author); const moneyAll = Math.ceil((allDaysInProject / 30) * middleSalaryInMonth);
const moneyAll = Math.ceil((allDaysInProject / 30) * salaryInMonth);
const tasksEntries = Object.entries(dot.tasks).filter(t => t[0]); const tasksEntries = Object.entries(dot.tasks).filter(t => t[0]);
const tasks = tasksEntries.map(t => t[0]); const tasks = tasksEntries.map(t => t[0]);

View file

@ -16,7 +16,7 @@ function getParametersFromURL(): IHashMap<string> {
}; };
} }
function loadJsDump(url: string, callback: Function) { function loadJsLocal(url: string, callback: Function) {
const script = document.createElement('script'); const script = document.createElement('script');
script.src = url; script.src = url;
script.async = true; // @ts-ignore script.async = true; // @ts-ignore
@ -27,6 +27,30 @@ function loadJsDump(url: string, callback: Function) {
document.body.appendChild(script); document.body.appendChild(script);
} }
function loadJsLGlobal(url: string, callback: Function) {
fetch(url)
.then((response) => response.text())
.then((text) => {
if (!text) return callback();
if (text[0] === 'r') {
eval(text);
return callback();
} else {
// @ts-ignore
window.report = text.split('\n');
}
callback();
});
}
function loadJsDump(url: string, callback: Function) {
if (url?.[0] === '.') {
loadJsLocal(url, callback);
} else {
loadJsLGlobal(url, callback);
}
}
function loadCssFile(url: string) { function loadCssFile(url: string) {
const node = document.createElement('link'); const node = document.createElement('link');
node.setAttribute('rel', 'stylesheet'); node.setAttribute('rel', 'stylesheet');

View file

@ -15,93 +15,104 @@ import Welcome from '../../Welcome/index';
import Settings from '../../Settings/index'; import Settings from '../../Settings/index';
import DebugPage from '../../Debug/index'; import DebugPage from '../../Debug/index';
interface IViewWithChartsProps {
showSplashScreen: boolean;
}
function ViewWithCharts({ showSplashScreen }: IViewWithChartsProps) {
return (
<>
<Confirm />
<Routes>
<Route
path="/settings"
element={(
<PageWrapper>
<Settings />
</PageWrapper>
)}
/>
<Route
path="/debug"
element={(
<PageWrapper>
<DebugPage />
</PageWrapper>
)}
/>
<Route
path="/print"
element={(
<PageWrapper>
<PrintAll />
</PageWrapper>
)}
/>
<Route
path="/:type/:page"
element={(
<PageWrapper>
<Team />
</PageWrapper>
)}
/>
<Route
path="/:type/:page/:userId"
element={(
<PageWrapper>
<Person />
</PageWrapper>
)}
/>
<Route
path="*"
element={(
<PageWrapper>
<Team />
</PageWrapper>
)}
/>
</Routes>
{showSplashScreen && <SplashScreen />}
</>
);
}
function ViewWithText() {
return (
<Routes>
<Route
path="*"
element={(
<Welcome />
)}
/>
</Routes>
);
}
const Success = observer((): React.ReactElement => { const Success = observer((): React.ReactElement => {
const [showSplashScreen, setShowSplashScreen] = useState<boolean>(true); const [showSplashScreen, setShowSplashScreen] = useState<boolean>(true);
const showChart = dataGripStore.showApplication;
useEffect(() => { useEffect(() => {
// @ts-ignore // @ts-ignore
dataGripStore.setCommits(window?.report || []); dataGripStore.setCommits(window?.report || []);
}, []); }, []);
const dropArea = ( return (
<DropZone
onChange={(type: string, data: any[]) => {
setShowSplashScreen(false);
if (type === 'dump') dataGripStore.setCommits(data);
setTimeout(() => {
setShowSplashScreen(true);
});
}}
/>
);
return dataGripStore.showApplication ? (
<>
<Confirm />
{dropArea}
<Routes>
<Route
path="/settings"
element={(
<PageWrapper>
<Settings />
</PageWrapper>
)}
/>
<Route
path="/debug"
element={(
<PageWrapper>
<DebugPage />
</PageWrapper>
)}
/>
<Route
path="/print"
element={(
<PageWrapper>
<PrintAll />
</PageWrapper>
)}
/>
<Route
path="/:type/:page"
element={(
<PageWrapper>
<Team />
</PageWrapper>
)}
/>
<Route
path="/:type/:page/:userId"
element={(
<PageWrapper>
<Person />
</PageWrapper>
)}
/>
<Route
path="*"
element={(
<PageWrapper>
<Team />
</PageWrapper>
)}
/>
</Routes>
{showSplashScreen && <SplashScreen />}
</>
) : (
<> <>
{dropArea} {showChart && <ViewWithCharts showSplashScreen={showSplashScreen} />}
<Routes> {!showChart && <ViewWithText />}
<Route <DropZone
path="*" onChange={(type: string, data: any[]) => {
element={( setShowSplashScreen(false);
<Welcome /> if (type === 'dump') dataGripStore.setCommits(data);
)} setTimeout(() => {
/> setShowSplashScreen(true);
</Routes> });
}}
/>
</> </>
); );
}); });

View file

@ -14,7 +14,6 @@ const Month = observer(({ user }: IPersonCommonProps): React.ReactElement => {
return ( return (
<> <>
<br/>
<PageWrapper template="table"> <PageWrapper template="table">
<YearChart <YearChart
showEvents={false} showEvents={false}

View file

@ -33,9 +33,6 @@ const Tasks = observer(({
})} })}
watch={`${mode}${dataGripStore.dataGrip.hash}${user.author}`} watch={`${mode}${dataGripStore.dataGrip.hash}${user.author}`}
> >
<br/>
<br/>
<br/>
<TasksView <TasksView
mode={mode} mode={mode}
rowsForExcel={rows} rowsForExcel={rows}

View file

@ -46,7 +46,6 @@ const Tempo = observer(({ user, filters }: IPersonCommonProps): React.ReactEleme
return ( return (
<> <>
<br/>
<PageWrapper template="table"> <PageWrapper template="table">
<DataLoader <DataLoader
to="response" to="response"

View file

@ -132,7 +132,6 @@ const Week = observer(({
return ( return (
<> <>
<br/>
<Recommendations <Recommendations
mode={mode} mode={mode}
recommendations={recommendations} recommendations={recommendations}

View file

@ -47,7 +47,7 @@ export default function getEmptySettings(): IUserSetting {
const value = { const value = {
RUB: 200000, RUB: 200000,
USD: 12000, USD: 3000,
}[currency] || 3000; }[currency] || 3000;
return { return {

View file

@ -1,6 +1,8 @@
@import 'src/styles/variables'; @import 'src/styles/variables';
.table_filters { .table_filters {
margin: 0 0 24px;
&_item { &_item {
display: inline-block; display: inline-block;
width: 350px; width: 350px;