mirror of
https://github.com/bakhirev/assayo.git
synced 2024-11-16 08:11:40 +00:00
update
This commit is contained in:
parent
6362f71a80
commit
57008ac20e
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { getClassNameForTimeZone } from '../helpers';
|
import { getPositionForTimeZone, getColorForTimeZone } from '../helpers';
|
||||||
|
|
||||||
import style from '../styles/index.module.scss';
|
import style from '../styles/index.module.scss';
|
||||||
|
|
||||||
|
@ -13,11 +13,12 @@ function Point({
|
||||||
timezone,
|
timezone,
|
||||||
authors,
|
authors,
|
||||||
}: PointProps): React.ReactElement | null {
|
}: PointProps): React.ReactElement | null {
|
||||||
const className = getClassNameForTimeZone(timezone);
|
const position = getPositionForTimeZone(timezone);
|
||||||
|
const color = getColorForTimeZone(authors);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
title={authors.join(', ')}
|
title={authors.join(', ')}
|
||||||
className={`${style.time_zone_map_point} ${className}`}
|
className={`${style.time_zone_map_point} ${position} ${color}`}
|
||||||
>
|
>
|
||||||
{authors.length}
|
{authors.length}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import dataGripStore from 'ts/store/DataGrip';
|
||||||
|
|
||||||
import style from '../styles/index.module.scss';
|
import style from '../styles/index.module.scss';
|
||||||
|
|
||||||
const REF_TIMEZONE_CLASS = {
|
const REF_TIMEZONE_CLASS = {
|
||||||
|
@ -46,10 +48,23 @@ export function getGroupsByTimeZone(authors: any[]) {
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getClassNameForTimeZone(timezone?: string) {
|
export function getPositionForTimeZone(timezone?: string) {
|
||||||
const suffix = (timezone || '')
|
const suffix = (timezone || '')
|
||||||
.replace('+', 'p')
|
.replace('+', 'p')
|
||||||
.replace('-', 'm')
|
.replace('-', 'm')
|
||||||
.replace(':', '');
|
.replace(':', '');
|
||||||
return REF_TIMEZONE_CLASS[suffix] || style.time_zone_map_point_hide;
|
return REF_TIMEZONE_CLASS[suffix] || style.time_zone_map_point_hide;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getColorForTimeZone(authors: string[]) {
|
||||||
|
let isDismissed = false;
|
||||||
|
for (let i = 0, l = authors.length; i < l; i++) {
|
||||||
|
const item = dataGripStore.dataGrip.author.statisticByName[authors[i]];
|
||||||
|
if (item?.isStaff) continue;
|
||||||
|
if (!item?.isDismissed) return style.time_zone_map_point_active;
|
||||||
|
if (item?.isDismissed) isDismissed = true;
|
||||||
|
}
|
||||||
|
return isDismissed
|
||||||
|
? style.time_zone_map_point_dismissed
|
||||||
|
: '';
|
||||||
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
|
|
||||||
color: var(--color-white);
|
color: var(--color-white);
|
||||||
border-radius: var(--border-radius-l);
|
border-radius: var(--border-radius-l);
|
||||||
background-color: var(--color-second);
|
background-color: var(--color-black);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,4 +82,6 @@
|
||||||
&_m1100 { top: 67%; left: 0; }
|
&_m1100 { top: 67%; left: 0; }
|
||||||
&_m1200 { top: 62%; left: 97%; }
|
&_m1200 { top: 62%; left: 97%; }
|
||||||
&_hide { display: none }
|
&_hide { display: none }
|
||||||
|
&_active { background-color: var(--color-first) }
|
||||||
|
&_dismissed { background-color: var(--color-second) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import ICommit from 'ts/interfaces/Commit';
|
||||||
import IHashMap, { HashMap } from 'ts/interfaces/HashMap';
|
import IHashMap, { HashMap } from 'ts/interfaces/HashMap';
|
||||||
|
|
||||||
import { ONE_DAY } from 'ts/helpers/formatter';
|
import { ONE_DAY } from 'ts/helpers/formatter';
|
||||||
import { createHashMap, createIncrement, increment } from 'ts/helpers/Math';
|
import { createIncrement, increment } from 'ts/helpers/Math';
|
||||||
|
|
||||||
import userSettings from 'ts/store/UserSettings';
|
import userSettings from 'ts/store/UserSettings';
|
||||||
|
|
||||||
|
@ -24,21 +24,21 @@ export default class DataGripByAuthor {
|
||||||
this.statisticByName = {};
|
this.statisticByName = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommit(commit: ICommit) {
|
addCommit(commit: ICommit, totalCommits: number) {
|
||||||
const statistic = this.commits.get(commit.author);
|
const statistic = this.commits.get(commit.author);
|
||||||
if (statistic) {
|
if (statistic) {
|
||||||
this.#updateCommitByAuthor(statistic, commit);
|
this.#updateCommitByAuthor(statistic, commit, totalCommits);
|
||||||
} else {
|
} else {
|
||||||
this.#addCommitByAuthor(commit);
|
this.#addCommitByAuthor(commit);
|
||||||
}
|
}
|
||||||
this.#setMoneyByMonth(commit);
|
this.#setMoneyByMonth(commit);
|
||||||
}
|
}
|
||||||
|
|
||||||
#updateCommitByAuthor(statistic: any, commit: ICommit) {
|
#updateCommitByAuthor(statistic: any, commit: ICommit, totalCommits: number) {
|
||||||
statistic.commits += 1;
|
statistic.commits += 1;
|
||||||
statistic.lastCommit = commit;
|
statistic.lastCommit = commit;
|
||||||
statistic.device = statistic.device || commit.device;
|
statistic.device = statistic.device || commit.device;
|
||||||
statistic.days[commit.timestamp] = true;
|
statistic.days.set(commit.timestamp, true);
|
||||||
statistic.tasks[commit.task] = commit.added + commit.changes + commit.removed
|
statistic.tasks[commit.task] = commit.added + commit.changes + commit.removed
|
||||||
+ (statistic.tasks[commit.task] ? statistic.tasks[commit.task] : 0);
|
+ (statistic.tasks[commit.task] ? statistic.tasks[commit.task] : 0);
|
||||||
increment(statistic.types, commit.type);
|
increment(statistic.types, commit.type);
|
||||||
|
@ -55,7 +55,9 @@ export default class DataGripByAuthor {
|
||||||
debugger;
|
debugger;
|
||||||
}
|
}
|
||||||
statistic.commitsByHour[commit.hours] += 1;
|
statistic.commitsByHour[commit.hours] += 1;
|
||||||
|
if (totalCommits < 50000) {
|
||||||
statistic.wordStatistics = DataGripByAuthor.#updateWordStatistics(commit, statistic.wordStatistics);
|
statistic.wordStatistics = DataGripByAuthor.#updateWordStatistics(commit, statistic.wordStatistics);
|
||||||
|
}
|
||||||
|
|
||||||
if (commit.company && statistic.lastCompany !== commit.company) {
|
if (commit.company && statistic.lastCompany !== commit.company) {
|
||||||
statistic.lastCompany = commit.company;
|
statistic.lastCompany = commit.company;
|
||||||
|
@ -80,7 +82,7 @@ export default class DataGripByAuthor {
|
||||||
commits: 1,
|
commits: 1,
|
||||||
firstCommit: commit,
|
firstCommit: commit,
|
||||||
lastCommit: commit,
|
lastCommit: commit,
|
||||||
days: createHashMap(commit.timestamp),
|
days: new Map([[commit.timestamp, true]]),
|
||||||
tasks: { [commit.task]: commit.added + commit.changes + commit.removed },
|
tasks: { [commit.task]: commit.added + commit.changes + commit.removed },
|
||||||
types: createIncrement(commit.type),
|
types: createIncrement(commit.type),
|
||||||
scopes: createIncrement(commit.scope),
|
scopes: createIncrement(commit.scope),
|
||||||
|
@ -171,7 +173,7 @@ export default class DataGripByAuthor {
|
||||||
const from = dot.firstCommit.milliseconds;
|
const from = dot.firstCommit.milliseconds;
|
||||||
const to = dot.lastCommit.milliseconds;
|
const to = dot.lastCommit.milliseconds;
|
||||||
|
|
||||||
const workDays = Object.keys(dot.days).length;
|
const workDays = dot.days.size;
|
||||||
const allDaysInProject = Math.ceil((to - from) / ONE_DAY);
|
const allDaysInProject = Math.ceil((to - from) / ONE_DAY);
|
||||||
const lazyDays = Math.floor((allDaysInProject * WORK_AND_HOLIDAYS) - workDays) + 1;
|
const lazyDays = Math.floor((allDaysInProject * WORK_AND_HOLIDAYS) - workDays) + 1;
|
||||||
|
|
||||||
|
@ -242,8 +244,16 @@ export default class DataGripByAuthor {
|
||||||
...this.employment.staff,
|
...this.employment.staff,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
this.updateSort();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSort() {
|
||||||
|
const position = new Map();
|
||||||
|
this.list.forEach((name: string, index: number) => {
|
||||||
|
position.set(name, index);
|
||||||
|
});
|
||||||
this.statistic.sort((a: any, b: any) => (
|
this.statistic.sort((a: any, b: any) => (
|
||||||
this.list.indexOf(a.author) - this.list.indexOf(b.author)
|
position.get(a.author) - position.get(b.author)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import ICommit from 'ts/interfaces/Commit';
|
import ICommit from 'ts/interfaces/Commit';
|
||||||
import IHashMap from 'ts/interfaces/HashMap';
|
import IHashMap, { HashMap } from 'ts/interfaces/HashMap';
|
||||||
import userSettings from 'ts/store/UserSettings';
|
import userSettings from 'ts/store/UserSettings';
|
||||||
import { createHashMap, createIncrement, increment } from 'ts/helpers/Math';
|
import { createIncrement, increment } from 'ts/helpers/Math';
|
||||||
|
|
||||||
interface IStatByAuthor {
|
interface IStatByAuthor {
|
||||||
commits: number; // number of commits by author in this scope
|
commits: number; // number of commits by author in this scope
|
||||||
days: IHashMap<boolean>; // commit timestamp
|
days: HashMap<boolean>; // commit timestamp
|
||||||
types: IHashMap<number>; // commit type by author in this scope (fix, feat)
|
types: IHashMap<number>; // commit type by author in this scope (fix, feat)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IStatByScope {
|
interface IStatByScope {
|
||||||
scope: string; // scope name
|
scope: string; // scope name
|
||||||
commits: number; // number of commits in this scope
|
commits: number; // number of commits in this scope
|
||||||
days: IHashMap<boolean>; // commit timestamp
|
days: HashMap<boolean>; // commit timestamp
|
||||||
tasks: IHashMap<boolean>; // task name in this scope (JIRA-123)
|
tasks: HashMap<boolean>; // task name in this scope (JIRA-123)
|
||||||
types: IHashMap<number>; // commit type in this scope (fix, feat)
|
types: IHashMap<number>; // commit type in this scope (fix, feat)
|
||||||
authors: IHashMap<IStatByAuthor>; // stat by author for this scope
|
authors: IHashMap<IStatByAuthor>; // stat by author for this scope
|
||||||
}
|
}
|
||||||
|
@ -42,14 +42,14 @@ export default class DataGripByScope {
|
||||||
#updateCommitByScope(commit: ICommit) {
|
#updateCommitByScope(commit: ICommit) {
|
||||||
const statistic = this.commits[commit.scope] as IStatByScope;
|
const statistic = this.commits[commit.scope] as IStatByScope;
|
||||||
statistic.commits += 1;
|
statistic.commits += 1;
|
||||||
statistic.days[commit.timestamp] = true;
|
statistic.days.set(commit.timestamp, true);
|
||||||
statistic.tasks[commit.task] = true;
|
statistic.tasks.set(commit.task, true);
|
||||||
increment(statistic.types, commit.type);
|
increment(statistic.types, commit.type);
|
||||||
|
|
||||||
const author = statistic.authors[commit.author];
|
const author = statistic.authors[commit.author];
|
||||||
if (author) {
|
if (author) {
|
||||||
author.commits += 1;
|
author.commits += 1;
|
||||||
author.days[commit.timestamp] = true;
|
author.days.set(commit.timestamp, true);
|
||||||
increment(author.types, commit.type);
|
increment(author.types, commit.type);
|
||||||
} else {
|
} else {
|
||||||
statistic.authors[commit.author] = this.#getDefaultAuthorForScope(commit);
|
statistic.authors[commit.author] = this.#getDefaultAuthorForScope(commit);
|
||||||
|
@ -60,8 +60,8 @@ export default class DataGripByScope {
|
||||||
this.commits[commit.scope] = {
|
this.commits[commit.scope] = {
|
||||||
scope: commit.scope,
|
scope: commit.scope,
|
||||||
commits: 1,
|
commits: 1,
|
||||||
days: createHashMap(commit.timestamp),
|
days: new Map([[commit.timestamp, true]]),
|
||||||
tasks: createHashMap(commit.task),
|
tasks: new Map([[commit.task, true]]),
|
||||||
types: createIncrement(commit.type),
|
types: createIncrement(commit.type),
|
||||||
authors: createIncrement(commit.author, this.#getDefaultAuthorForScope(commit)),
|
authors: createIncrement(commit.author, this.#getDefaultAuthorForScope(commit)),
|
||||||
};
|
};
|
||||||
|
@ -70,7 +70,7 @@ export default class DataGripByScope {
|
||||||
#getDefaultAuthorForScope(commit: ICommit): IStatByAuthor {
|
#getDefaultAuthorForScope(commit: ICommit): IStatByAuthor {
|
||||||
return {
|
return {
|
||||||
commits: 1,
|
commits: 1,
|
||||||
days: { [commit.timestamp]: true },
|
days: new Map([[commit.timestamp, true]]),
|
||||||
types: { [commit.type]: 1 },
|
types: { [commit.type]: 1 },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -84,18 +84,20 @@ export default class DataGripByScope {
|
||||||
let cost = 0;
|
let cost = 0;
|
||||||
for (let name in dot.authors) {
|
for (let name in dot.authors) {
|
||||||
const user = dot.authors[name];
|
const user = dot.authors[name];
|
||||||
const days: number = Object.keys(user.days).length;
|
const days: number = user.days.size;
|
||||||
// TODO: need middle salary in month;
|
// TODO: need middle salary in month;
|
||||||
salaryCache[name] = salaryCache[name] || userSettings.getCurrentSalaryInDay(name);
|
salaryCache[name] = salaryCache[name] || userSettings.getCurrentSalaryInDay(name);
|
||||||
cost += days * salaryCache[name];
|
cost += days * salaryCache[name];
|
||||||
dot.authors[name] = { ...user, days };
|
dot.authors[name] = { ...user, days };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dot.tasks.delete('');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...dot,
|
...dot,
|
||||||
days: Object.keys(dot.days).length,
|
days: dot.days.size,
|
||||||
cost,
|
cost,
|
||||||
tasks: Object.keys(dot.tasks).filter(t => t),
|
tasks: dot.tasks.size,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -27,8 +27,8 @@ export default class DataGripByType {
|
||||||
#updateCommitByType(commit: ICommit) {
|
#updateCommitByType(commit: ICommit) {
|
||||||
const statistic = this.commits[commit.type];
|
const statistic = this.commits[commit.type];
|
||||||
statistic.commits += 1;
|
statistic.commits += 1;
|
||||||
statistic.days[commit.timestamp] = true;
|
statistic.days.set(commit.timestamp, true);
|
||||||
statistic.tasks[commit.task] = true;
|
statistic.tasks.set(commit.task, true);
|
||||||
|
|
||||||
increment(statistic.commitsByAuthors, commit.author);
|
increment(statistic.commitsByAuthors, commit.author);
|
||||||
if (!statistic.daysByAuthors[commit.author]) statistic.daysByAuthors[commit.author] = {};
|
if (!statistic.daysByAuthors[commit.author]) statistic.daysByAuthors[commit.author] = {};
|
||||||
|
@ -39,8 +39,8 @@ export default class DataGripByType {
|
||||||
this.commits[commit.type] = {
|
this.commits[commit.type] = {
|
||||||
type: commit.type,
|
type: commit.type,
|
||||||
commits: 1,
|
commits: 1,
|
||||||
days: createIncrement(commit.timestamp, true),
|
days: new Map([[commit.timestamp, true]]),
|
||||||
tasks: createIncrement(commit.task, true),
|
tasks: new Map([[commit.task, true]]),
|
||||||
commitsByAuthors: createIncrement(commit.author, true),
|
commitsByAuthors: createIncrement(commit.author, true),
|
||||||
daysByAuthors: {
|
daysByAuthors: {
|
||||||
[commit.author]: createIncrement(commit.timestamp, true),
|
[commit.author]: createIncrement(commit.timestamp, true),
|
||||||
|
@ -56,8 +56,8 @@ export default class DataGripByType {
|
||||||
.filter((dot: any) => dot.commits > 5 || isCorrectType[dot?.type || ''])
|
.filter((dot: any) => dot.commits > 5 || isCorrectType[dot?.type || ''])
|
||||||
.map((dot: any) => ({
|
.map((dot: any) => ({
|
||||||
...dot,
|
...dot,
|
||||||
tasks: Object.keys(dot.tasks).length,
|
tasks: dot.tasks.size,
|
||||||
days: Object.keys(dot.days).length,
|
days: dot.days.size,
|
||||||
daysByAuthorsTotal: Object.values(dot.daysByAuthors)
|
daysByAuthorsTotal: Object.values(dot.daysByAuthors)
|
||||||
.reduce((t: number, v: any) => (t + Object.keys(v).length), 0),
|
.reduce((t: number, v: any) => (t + Object.keys(v).length), 0),
|
||||||
}))
|
}))
|
||||||
|
|
|
@ -66,13 +66,13 @@ class DataGrip {
|
||||||
this.scoring.clear();
|
this.scoring.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
addCommit(commit: ICommit | ISystemCommit) {
|
addCommit(commit: ICommit | ISystemCommit, totalCommits: number) {
|
||||||
if (commit.author === 'GitHub') return;
|
if (commit.author === 'GitHub') return;
|
||||||
this.pr.addCommit(commit); // @ts-ignore
|
this.pr.addCommit(commit); // @ts-ignore
|
||||||
this.release.addCommit(commit); // @ts-ignore
|
this.release.addCommit(commit); // @ts-ignore
|
||||||
if (!commit.commitType) {
|
if (!commit.commitType) {
|
||||||
this.firstLastCommit.update(commit.milliseconds, commit);
|
this.firstLastCommit.update(commit.milliseconds, commit);
|
||||||
this.author.addCommit(commit);
|
this.author.addCommit(commit, totalCommits);
|
||||||
this.scope.addCommit(commit);
|
this.scope.addCommit(commit);
|
||||||
this.type.addCommit(commit);
|
this.type.addCommit(commit);
|
||||||
this.timestamp.addCommit(commit);
|
this.timestamp.addCommit(commit);
|
||||||
|
|
|
@ -28,7 +28,9 @@ export default class RecommendationsTeamByType {
|
||||||
|
|
||||||
getBusFactor(dataGrip: any) {
|
getBusFactor(dataGrip: any) {
|
||||||
if (dataGrip.author.list.length < 2) return null;
|
if (dataGrip.author.list.length < 2) return null;
|
||||||
|
if (dataGrip.type.statistic.length > 200) return null; // for performance
|
||||||
|
|
||||||
|
// TODO: bad performance
|
||||||
const oneMaintainer = dataGrip.type.statistic.filter((statistic: any) => {
|
const oneMaintainer = dataGrip.type.statistic.filter((statistic: any) => {
|
||||||
const limit = statistic.commits * 0.8;
|
const limit = statistic.commits * 0.8;
|
||||||
return dataGrip.author.list.some((name: string) => statistic.commitsByAuthors[name] >= limit);
|
return dataGrip.author.list.some((name: string) => statistic.commitsByAuthors[name] >= limit);
|
||||||
|
|
|
@ -29,9 +29,17 @@ const TIMESTAMP = [
|
||||||
ONE_DAY * 3,
|
ONE_DAY * 3,
|
||||||
];
|
];
|
||||||
|
|
||||||
export function getDayName(index:number, weekday: 'long' | 'short') {
|
// for performance
|
||||||
|
const dayNameCache = new Map();
|
||||||
|
export function getDayName(index:number, weekday: 'long' | 'short') { // @ts-ignore
|
||||||
|
const code = window?.localization?.language || 'ru';
|
||||||
|
const response = dayNameCache.get(`${code}${index}${weekday}`);
|
||||||
|
if (response) return response;
|
||||||
|
|
||||||
const date = new Date(TIMESTAMP[index]);
|
const date = new Date(TIMESTAMP[index]);
|
||||||
return date.toLocaleString(getLangPrefix(), { weekday: weekday || 'long' });
|
const dayName = date.toLocaleString(getLangPrefix(), { weekday: weekday || 'long' });
|
||||||
|
dayNameCache.set(`${code}${index}${weekday}`, dayName);
|
||||||
|
return dayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDateByTimestamp(timestamp: string) {
|
export function getDateByTimestamp(timestamp: string) {
|
||||||
|
|
77
src/ts/pages/Team/components/Country/components/Map.tsx
Normal file
77
src/ts/pages/Team/components/Country/components/Map.tsx
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
import React, { useMemo, useState } from 'react';
|
||||||
|
import { observer } from 'mobx-react-lite';
|
||||||
|
|
||||||
|
import dataGripStore from 'ts/store/DataGrip';
|
||||||
|
|
||||||
|
import SelectWithButtons from 'ts/components/UiKit/components/SelectWithButtons';
|
||||||
|
import UiKitCheckbox from 'ts/components/UiKit/components/Checkbox';
|
||||||
|
import TimeZoneMap from 'ts/components/TimeZoneMap';
|
||||||
|
import PageWrapper from 'ts/components/Page/Box';
|
||||||
|
import Title from 'ts/components/Title';
|
||||||
|
import { t } from 'ts/helpers/Localization';
|
||||||
|
|
||||||
|
import style from '../../../styles/country.module.scss';
|
||||||
|
|
||||||
|
function getOptions(companies: any[]) {
|
||||||
|
const options = companies.map((item: any) => ({ id: item.company, title: item.company }));
|
||||||
|
return [
|
||||||
|
{ id: '', title: t('page.common.filter.allUsers') },
|
||||||
|
{ id: Math.random(), title: 'Unknown' },
|
||||||
|
...options,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
const CustomMap = observer(() => {
|
||||||
|
const companies = dataGripStore.dataGrip.company.statistic;
|
||||||
|
const companyOptions = useMemo(() => getOptions(companies), companies);
|
||||||
|
|
||||||
|
const [company, setCompany] = useState<string>('');
|
||||||
|
const [isStaff, setIsStaff] = useState<boolean>(true);
|
||||||
|
const [isActive, setIsActive] = useState<boolean>(true);
|
||||||
|
const [isDismissed, setIsDismissed] = useState<boolean>(true);
|
||||||
|
|
||||||
|
const authors = dataGripStore.dataGrip.author.statistic
|
||||||
|
.filter((author: any) => {
|
||||||
|
if (company && author.lastCompany !== company) return false;
|
||||||
|
if (!isStaff && author.isStaff) return false;
|
||||||
|
if (!isActive && !author.isDismissed && !author.isStaff) return false;
|
||||||
|
if (!isDismissed && author.isDismissed && !author.isStaff) return false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageWrapper>
|
||||||
|
<Title title="page.team.country.byTimezone"/>
|
||||||
|
<TimeZoneMap authors={authors}/>
|
||||||
|
<div className={style.team_country_filter}>
|
||||||
|
<UiKitCheckbox
|
||||||
|
title="page.team.country.filters.active"
|
||||||
|
className={style.team_country_filter_checkbox}
|
||||||
|
value={isActive}
|
||||||
|
onChange={() => setIsActive(!isActive)}
|
||||||
|
/>
|
||||||
|
<UiKitCheckbox
|
||||||
|
title="page.team.country.filters.dismissed"
|
||||||
|
className={style.team_country_filter_checkbox}
|
||||||
|
value={isDismissed}
|
||||||
|
onChange={() => setIsDismissed(!isDismissed)}
|
||||||
|
/>
|
||||||
|
<UiKitCheckbox
|
||||||
|
title="page.team.country.filters.staff"
|
||||||
|
className={style.team_country_filter_checkbox}
|
||||||
|
value={isStaff}
|
||||||
|
onChange={() => setIsStaff(!isStaff)}
|
||||||
|
/>
|
||||||
|
<SelectWithButtons
|
||||||
|
title="page.team.tree.filters.author"
|
||||||
|
className={style.team_country_filter_select}
|
||||||
|
value={company}
|
||||||
|
options={companyOptions}
|
||||||
|
onChange={(id: string) => setCompany(id)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</PageWrapper>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default CustomMap;
|
|
@ -13,10 +13,9 @@ import NothingFound from 'ts/components/NothingFound';
|
||||||
import Title from 'ts/components/Title';
|
import Title from 'ts/components/Title';
|
||||||
import Countries from './components/Countries';
|
import Countries from './components/Countries';
|
||||||
import CountryCharts from './components/Charts';
|
import CountryCharts from './components/Charts';
|
||||||
import TimeZoneMap from 'ts/components/TimeZoneMap';
|
|
||||||
import PageWrapper from 'ts/components/Page/Box';
|
|
||||||
import fullScreen from 'ts/store/FullScreen';
|
import fullScreen from 'ts/store/FullScreen';
|
||||||
|
|
||||||
|
import CustomMap from './components/Map';
|
||||||
import Travel from './components/Travel';
|
import Travel from './components/Travel';
|
||||||
|
|
||||||
const Country = observer(({
|
const Country = observer(({
|
||||||
|
@ -36,15 +35,8 @@ const Country = observer(({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!fullScreen.isOpen && (
|
{!fullScreen.isOpen && <CustomMap />}
|
||||||
<>
|
{!fullScreen.isOpen && <CountryCharts />}
|
||||||
<PageWrapper>
|
|
||||||
<Title title="page.team.country.byTimezone"/>
|
|
||||||
<TimeZoneMap authors={authors}/>
|
|
||||||
</PageWrapper>
|
|
||||||
<CountryCharts/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{canShowByCountries ? (
|
{canShowByCountries ? (
|
||||||
<>
|
<>
|
||||||
|
|
16
src/ts/pages/Team/styles/country.module.scss
Normal file
16
src/ts/pages/Team/styles/country.module.scss
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
@import 'src/styles/variables';
|
||||||
|
|
||||||
|
.team_country_filter {
|
||||||
|
margin-top: var(--space-m);
|
||||||
|
|
||||||
|
&_checkbox,
|
||||||
|
&_select {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: var(--space-xxl);
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
&_select {
|
||||||
|
min-width: 350px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -65,8 +65,10 @@ class DataGripStore {
|
||||||
|
|
||||||
processingCommitGrouping(commits: (ICommit | ISystemCommit)[]) {
|
processingCommitGrouping(commits: (ICommit | ISystemCommit)[]) {
|
||||||
commits.sort((a, b) => a.milliseconds - b.milliseconds);
|
commits.sort((a, b) => a.milliseconds - b.milliseconds);
|
||||||
|
|
||||||
|
const totalCommits = commits.length;
|
||||||
commits.forEach((commit: ICommit | ISystemCommit) => {
|
commits.forEach((commit: ICommit | ISystemCommit) => {
|
||||||
dataGrip.addCommit(commit);
|
dataGrip.addCommit(commit, totalCommits);
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => this.processingFileGrouping(commits), PROCESSING_DELAY);
|
setTimeout(() => this.processingFileGrouping(commits), PROCESSING_DELAY);
|
||||||
|
@ -128,7 +130,7 @@ class DataGripStore {
|
||||||
? depersonalized.getCommit(commit)
|
? depersonalized.getCommit(commit)
|
||||||
: commit;
|
: commit;
|
||||||
|
|
||||||
dataGrip.addCommit(localCommit);
|
dataGrip.addCommit(localCommit, 0);
|
||||||
fileGrip.addCommit(localCommit);
|
fileGrip.addCommit(localCommit);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,9 @@ export default `
|
||||||
§ page.team.company.active.yes: active
|
§ page.team.company.active.yes: active
|
||||||
§ page.team.company.active.no: contract has expired
|
§ page.team.company.active.no: contract has expired
|
||||||
§ page.team.country.byTimezone: By the time of the last commit
|
§ page.team.country.byTimezone: By the time of the last commit
|
||||||
|
§ page.team.country.filters.active: Works
|
||||||
|
§ page.team.country.filters.dismissed: Dismissed
|
||||||
|
§ page.team.country.filters.staff: Staff
|
||||||
§ page.team.country.pieByDomain.title: By email, timezone and language
|
§ page.team.country.pieByDomain.title: By email, timezone and language
|
||||||
§ page.team.country.pieByTimezone.title: By timezone
|
§ page.team.country.pieByTimezone.title: By timezone
|
||||||
§ page.team.country.chart.item: employments
|
§ page.team.country.chart.item: employments
|
||||||
|
|
|
@ -130,6 +130,9 @@ export default `
|
||||||
§ page.team.company.active.yes: active
|
§ page.team.company.active.yes: active
|
||||||
§ page.team.company.active.no: contract has expired
|
§ page.team.company.active.no: contract has expired
|
||||||
§ page.team.country.byTimezone: By the time of the last commit
|
§ page.team.country.byTimezone: By the time of the last commit
|
||||||
|
§ page.team.country.filters.active: Works
|
||||||
|
§ page.team.country.filters.dismissed: Dismissed
|
||||||
|
§ page.team.country.filters.staff: Staff
|
||||||
§ page.team.country.pieByDomain.title: By email, timezone and language
|
§ page.team.country.pieByDomain.title: By email, timezone and language
|
||||||
§ page.team.country.pieByTimezone.title: By timezone
|
§ page.team.country.pieByTimezone.title: By timezone
|
||||||
§ page.team.country.chart.item: employments
|
§ page.team.country.chart.item: employments
|
||||||
|
|
|
@ -130,6 +130,9 @@ export default `
|
||||||
§ page.team.company.active.yes: active
|
§ page.team.company.active.yes: active
|
||||||
§ page.team.company.active.no: contract has expired
|
§ page.team.company.active.no: contract has expired
|
||||||
§ page.team.country.byTimezone: By the time of the last commit
|
§ page.team.country.byTimezone: By the time of the last commit
|
||||||
|
§ page.team.country.filters.active: Works
|
||||||
|
§ page.team.country.filters.dismissed: Dismissed
|
||||||
|
§ page.team.country.filters.staff: Staff
|
||||||
§ page.team.country.pieByDomain.title: By email, timezone and language
|
§ page.team.country.pieByDomain.title: By email, timezone and language
|
||||||
§ page.team.country.pieByTimezone.title: By timezone
|
§ page.team.country.pieByTimezone.title: By timezone
|
||||||
§ page.team.country.chart.item: employments
|
§ page.team.country.chart.item: employments
|
||||||
|
|
|
@ -130,6 +130,9 @@ export default `
|
||||||
§ page.team.company.active.yes: active
|
§ page.team.company.active.yes: active
|
||||||
§ page.team.company.active.no: contract has expired
|
§ page.team.company.active.no: contract has expired
|
||||||
§ page.team.country.byTimezone: By the time of the last commit
|
§ page.team.country.byTimezone: By the time of the last commit
|
||||||
|
§ page.team.country.filters.active: Works
|
||||||
|
§ page.team.country.filters.dismissed: Dismissed
|
||||||
|
§ page.team.country.filters.staff: Staff
|
||||||
§ page.team.country.pieByDomain.title: By email, timezone and language
|
§ page.team.country.pieByDomain.title: By email, timezone and language
|
||||||
§ page.team.country.pieByTimezone.title: By timezone
|
§ page.team.country.pieByTimezone.title: By timezone
|
||||||
§ page.team.country.chart.item: employments
|
§ page.team.country.chart.item: employments
|
||||||
|
|
|
@ -130,6 +130,9 @@ export default `
|
||||||
§ page.team.company.active.yes: active
|
§ page.team.company.active.yes: active
|
||||||
§ page.team.company.active.no: contract has expired
|
§ page.team.company.active.no: contract has expired
|
||||||
§ page.team.country.byTimezone: By the time of the last commit
|
§ page.team.country.byTimezone: By the time of the last commit
|
||||||
|
§ page.team.country.filters.active: Works
|
||||||
|
§ page.team.country.filters.dismissed: Dismissed
|
||||||
|
§ page.team.country.filters.staff: Staff
|
||||||
§ page.team.country.pieByDomain.title: By email, timezone and language
|
§ page.team.country.pieByDomain.title: By email, timezone and language
|
||||||
§ page.team.country.pieByTimezone.title: By timezone
|
§ page.team.country.pieByTimezone.title: By timezone
|
||||||
§ page.team.country.chart.item: employments
|
§ page.team.country.chart.item: employments
|
||||||
|
|
|
@ -130,6 +130,9 @@ export default `
|
||||||
§ page.team.company.active.yes: active
|
§ page.team.company.active.yes: active
|
||||||
§ page.team.company.active.no: contract has expired
|
§ page.team.company.active.no: contract has expired
|
||||||
§ page.team.country.byTimezone: By the time of the last commit
|
§ page.team.country.byTimezone: By the time of the last commit
|
||||||
|
§ page.team.country.filters.active: Works
|
||||||
|
§ page.team.country.filters.dismissed: Dismissed
|
||||||
|
§ page.team.country.filters.staff: Staff
|
||||||
§ page.team.country.pieByDomain.title: By email, timezone and language
|
§ page.team.country.pieByDomain.title: By email, timezone and language
|
||||||
§ page.team.country.pieByTimezone.title: By timezone
|
§ page.team.country.pieByTimezone.title: By timezone
|
||||||
§ page.team.country.chart.item: employments
|
§ page.team.country.chart.item: employments
|
||||||
|
|
|
@ -130,6 +130,9 @@ export default `
|
||||||
§ page.team.company.active.yes: активна
|
§ page.team.company.active.yes: активна
|
||||||
§ page.team.company.active.no: контракт истёк
|
§ page.team.company.active.no: контракт истёк
|
||||||
§ page.team.country.byTimezone: По времени последнего коммита
|
§ page.team.country.byTimezone: По времени последнего коммита
|
||||||
|
§ page.team.country.filters.active: Работают
|
||||||
|
§ page.team.country.filters.dismissed: Уволенные
|
||||||
|
§ page.team.country.filters.staff: Помощники
|
||||||
§ page.team.country.pieByDomain.title: По почте, времени и языку
|
§ page.team.country.pieByDomain.title: По почте, времени и языку
|
||||||
§ page.team.country.pieByTimezone.title: По времени
|
§ page.team.country.pieByTimezone.title: По времени
|
||||||
§ page.team.country.chart.item: сотрудников
|
§ page.team.country.chart.item: сотрудников
|
||||||
|
|
|
@ -125,6 +125,9 @@ export default `
|
||||||
§ page.team.company.active.yes: active
|
§ page.team.company.active.yes: active
|
||||||
§ page.team.company.active.no: contract has expired
|
§ page.team.company.active.no: contract has expired
|
||||||
§ page.team.country.byTimezone: By the time of the last commit
|
§ page.team.country.byTimezone: By the time of the last commit
|
||||||
|
§ page.team.country.filters.active: Works
|
||||||
|
§ page.team.country.filters.dismissed: Dismissed
|
||||||
|
§ page.team.country.filters.staff: Staff
|
||||||
§ page.team.country.pieByDomain.title: By email, timezone and language
|
§ page.team.country.pieByDomain.title: By email, timezone and language
|
||||||
§ page.team.country.pieByTimezone.title: By timezone
|
§ page.team.country.pieByTimezone.title: By timezone
|
||||||
§ page.team.country.chart.item: employments
|
§ page.team.country.chart.item: employments
|
||||||
|
|
Loading…
Reference in a new issue