Skip to content

Commit

Permalink
Merge branch 'master' into refactor/admin-tasks-page
Browse files Browse the repository at this point in the history
  • Loading branch information
I-vasilich-I committed Oct 9, 2023
2 parents 0187a5d + e5de929 commit 5d6ad26
Show file tree
Hide file tree
Showing 28 changed files with 967 additions and 123 deletions.
167 changes: 167 additions & 0 deletions client/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3005,6 +3005,81 @@ export const GratitudeDtoBadgeIdEnum = {

export type GratitudeDtoBadgeIdEnum = typeof GratitudeDtoBadgeIdEnum[keyof typeof GratitudeDtoBadgeIdEnum];

/**
*
* @export
* @interface HeroRadarDto
*/
export interface HeroRadarDto {
/**
*
* @type {string}
* @memberof HeroRadarDto
*/
'githubId': string;
/**
*
* @type {string}
* @memberof HeroRadarDto
*/
'name': string;
/**
*
* @type {number}
* @memberof HeroRadarDto
*/
'rank': number;
/**
*
* @type {number}
* @memberof HeroRadarDto
*/
'total': number;
/**
*
* @type {Array<HeroesRadarBadgeDto>}
* @memberof HeroRadarDto
*/
'badges': Array<HeroesRadarBadgeDto>;
}
/**
*
* @export
* @interface HeroesRadarBadgeDto
*/
export interface HeroesRadarBadgeDto {
/**
*
* @type {string}
* @memberof HeroesRadarBadgeDto
*/
'id': string;
/**
*
* @type {number}
* @memberof HeroesRadarBadgeDto
*/
'count': number;
}
/**
*
* @export
* @interface HeroesRadarDto
*/
export interface HeroesRadarDto {
/**
*
* @type {Array<HeroRadarDto>}
* @memberof HeroesRadarDto
*/
'content': Array<HeroRadarDto>;
/**
*
* @type {PaginationMetaDto}
* @memberof HeroesRadarDto
*/
'pagination': PaginationMetaDto;
}
/**
*
* @export
Expand Down Expand Up @@ -11883,6 +11958,59 @@ export const GratitudesApiAxiosParamCreator = function (configuration?: Configur



setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};

return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @param {number} current
* @param {number} pageSize
* @param {number} [courseId]
* @param {boolean} [notActivist]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getHeroesRadar: async (current: number, pageSize: number, courseId?: number, notActivist?: boolean, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'current' is not null or undefined
assertParamExists('getHeroesRadar', 'current', current)
// verify required parameter 'pageSize' is not null or undefined
assertParamExists('getHeroesRadar', 'pageSize', pageSize)
const localVarPath = `/gratitudes/heroes/radar`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}

const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;

if (courseId !== undefined) {
localVarQueryParameter['courseId'] = courseId;
}

if (notActivist !== undefined) {
localVarQueryParameter['notActivist'] = notActivist;
}

if (current !== undefined) {
localVarQueryParameter['current'] = current;
}

if (pageSize !== undefined) {
localVarQueryParameter['pageSize'] = pageSize;
}



setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
Expand Down Expand Up @@ -11922,6 +12050,19 @@ export const GratitudesApiFp = function(configuration?: Configuration) {
const localVarAxiosArgs = await localVarAxiosParamCreator.getBadges(courseId, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @param {number} current
* @param {number} pageSize
* @param {number} [courseId]
* @param {boolean} [notActivist]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getHeroesRadar(current: number, pageSize: number, courseId?: number, notActivist?: boolean, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<HeroesRadarDto>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getHeroesRadar(current, pageSize, courseId, notActivist, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
}
};

Expand Down Expand Up @@ -11950,6 +12091,18 @@ export const GratitudesApiFactory = function (configuration?: Configuration, bas
getBadges(courseId: number, options?: any): AxiosPromise<Array<BadgeDto>> {
return localVarFp.getBadges(courseId, options).then((request) => request(axios, basePath));
},
/**
*
* @param {number} current
* @param {number} pageSize
* @param {number} [courseId]
* @param {boolean} [notActivist]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getHeroesRadar(current: number, pageSize: number, courseId?: number, notActivist?: boolean, options?: any): AxiosPromise<HeroesRadarDto> {
return localVarFp.getHeroesRadar(current, pageSize, courseId, notActivist, options).then((request) => request(axios, basePath));
},
};
};

Expand Down Expand Up @@ -11981,6 +12134,20 @@ export class GratitudesApi extends BaseAPI {
public getBadges(courseId: number, options?: AxiosRequestConfig) {
return GratitudesApiFp(this.configuration).getBadges(courseId, options).then((request) => request(this.axios, this.basePath));
}

/**
*
* @param {number} current
* @param {number} pageSize
* @param {number} [courseId]
* @param {boolean} [notActivist]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof GratitudesApi
*/
public getHeroesRadar(current: number, pageSize: number, courseId?: number, notActivist?: boolean, options?: AxiosRequestConfig) {
return GratitudesApiFp(this.configuration).getHeroesRadar(current, pageSize, courseId, notActivist, options).then((request) => request(this.axios, this.basePath));
}
}


Expand Down
13 changes: 5 additions & 8 deletions client/src/components/Forms/Heroes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { IGratitudeGetRequest, IGratitudeGetResponse, HeroesFormData } from 'com
import heroesBadges from 'configs/heroes-badges';
import { GratitudeService } from 'services/gratitude';
import { onlyDefined } from 'utils/onlyDefined';
import { useActiveCourseContext } from 'modules/Course/contexts';
import { Course } from 'services/models';
import { getFullName } from 'domain/user';

const { Text, Link, Paragraph } = Typography;
const { useBreakpoint } = Grid;
Expand All @@ -21,11 +22,7 @@ export const fields = {
courseId: 'courseId',
} as const;

const getFullName = (user: { firstName: string | null; lastName: string | null; githubId: string }) =>
user.firstName && user.lastName ? `${user.firstName} ${user.lastName}` : `${user.githubId}`;

export const HeroesForm = ({ setLoading }: { setLoading: (arg: boolean) => void }) => {
const { courses } = useActiveCourseContext();
export const HeroesForm = ({ setLoading, courses }: { setLoading: (arg: boolean) => void; courses: Course[] }) => {
const [heroesData, setHeroesData] = useState<IGratitudeGetResponse[]>([]);
const [heroesCount, setHeroesCount] = useState(initialPage);
const [currentPage, setCurrentPage] = useState(initialPage);
Expand Down Expand Up @@ -122,7 +119,7 @@ export const HeroesForm = ({ setLoading }: { setLoading: (arg: boolean) => void
<Card style={{ position: 'relative', background: 'none' }}>
<div
className="badge-bg"
style={{ backgroundImage: `url(/static/svg/badges/${(heroesBadges as any)[feedback.badgeId].url})` }}
style={{ backgroundImage: `url(/static/svg/badges/${heroesBadges[feedback.badgeId].url})` }}
/>
<div className="badge-note" style={{ marginBottom: 48 }}>
<Paragraph style={{ margin: 0 }}>
Expand All @@ -137,7 +134,7 @@ export const HeroesForm = ({ setLoading }: { setLoading: (arg: boolean) => void
<div className="flex-center" style={{ marginBottom: 48 }}>
<div className="badge">
<Avatar
src={`/static/svg/badges/${(heroesBadges as any)[feedback.badgeId].url}`}
src={`/static/svg/badges/${heroesBadges[feedback.badgeId].url}`}
alt={`${feedback.badgeId} badge`}
size={128}
/>
Expand Down
45 changes: 15 additions & 30 deletions client/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import Link from 'next/link';
import { useRouter } from 'next/router';
import { Fragment, useContext, useMemo } from 'react';
import { Button, Dropdown, Menu, Space, Tooltip } from 'antd';
import { Button, Dropdown, Menu, Space } from 'antd';
import {
EyeOutlined,
LogoutOutlined,
QuestionCircleFilled,
SolutionOutlined,
NotificationOutlined,
} from '@ant-design/icons';
import { Course } from 'services/models';
import { GithubAvatar } from 'components/GithubAvatar';
import { SolidarityUkraine } from './SolidarityUkraine';
import { SessionContext } from 'modules/Course/contexts';
Expand All @@ -19,7 +18,6 @@ import { useActiveCourseContext } from 'modules/Course/contexts/ActiveCourseCont
type Props = {
showCourseName?: boolean;
title?: string;
course?: Course;
};

const MENU_ITEMS = [
Expand All @@ -38,28 +36,34 @@ const MENU_ITEMS = [
icon: <SolutionOutlined />,
title: 'My CV',
},
{
link: 'https://docs.app.rs.school',
icon: <QuestionCircleFilled />,
title: 'Help',
target: '_blank',
},
{
link: '/api/v2/auth/github/logout',
icon: <LogoutOutlined />,
title: 'Logout',
},
];

export function Header({ title, showCourseName, course }: Props) {
export function Header({ title, showCourseName }: Props) {
const { asPath: currentRoute } = useRouter();
const menuActiveItemStyle = { backgroundColor: '#e0f2ff' };

const session = useContext(SessionContext);
const activeCourse = useActiveCourseContext().course ?? course;
const courseLinks = useMemo(() => getNavigationItems(session, activeCourse ?? null), [course]);
const { course } = useActiveCourseContext();
const courseLinks = useMemo(() => getNavigationItems(session, course ?? null), [course]);

const menu = (
<Menu>
{MENU_ITEMS.map(({ link, icon, title }, id, arr) => (
{MENU_ITEMS.map(({ link, icon, title, target }, id, arr) => (
<Fragment key={id}>
{id === arr.length - 1 ? <Menu.Divider /> : null}
<Menu.Item key={id} style={currentRoute === link ? menuActiveItemStyle : undefined}>
<Button type="link" href={link} style={{ textAlign: 'left', width: '100%' }}>
<Button type="link" target={target} href={link} style={{ textAlign: 'left', width: '100%' }}>
{icon} {title}
</Button>
</Menu.Item>
Expand Down Expand Up @@ -96,44 +100,25 @@ export function Header({ title, showCourseName, course }: Props) {
<SolidarityUkraine />
</Space>
<div className="title">
<b>{title}</b> {showCourseName ? activeCourse?.name : null}
<b>{title}</b> {showCourseName ? course?.name : null}
</div>
<div className="profile">
<a target="_blank" href="https://docs.app.rs.school">
<Tooltip title="RS School App docs">
<Button type="primary" ghost size="large" style={{ marginRight: 8 }}>
<QuestionCircleFilled />
<span className="button-text">Help</span>
</Button>
</Tooltip>
</a>
{session.githubId && (
<Dropdown overlay={menu} trigger={['click']}>
<Button type="dashed" size="large">
<GithubAvatar githubId={session?.githubId} size={24} />
<span style={{ marginLeft: '12px' }} className="button-text">
My Profile
</span>
<Button type="link">
<GithubAvatar githubId={session?.githubId} size={32} />
</Button>
</Dropdown>
)}
</div>
<style jsx>{`
.title {
font-size: 120%;
align-self: center;
}
@media all and (max-width: 768px) {
.title {
width: 100%;
order: 3;
text-align: center;
margin-top: 16px;
}
.button-text {
display: none;
}
}
`}</style>
</nav>
Expand Down
17 changes: 17 additions & 0 deletions client/src/components/Heroes/HeroesCountBadge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Badge, Tooltip, Avatar } from 'antd';
import { HeroesRadarBadgeDto } from 'api';
import heroesBadges from 'configs/heroes-badges';

function HeroesCountBadge({ badge: { id, count } }: { badge: HeroesRadarBadgeDto }) {
return (
<div style={{ margin: 5, display: 'inline-block' }}>
<Badge count={count}>
<Tooltip title={heroesBadges[id].name}>
<Avatar src={`/static/svg/badges/${heroesBadges[id].url}`} alt={`${id} badge`} size={48} />
</Tooltip>
</Badge>
</div>
);
}

export default HeroesCountBadge;
Loading

0 comments on commit 5d6ad26

Please sign in to comment.