Skip to content

Commit

Permalink
Merge pull request #1706 from ushachev/fix-language-icons
Browse files Browse the repository at this point in the history
Replace library of programming language icons
  • Loading branch information
ReDBrother authored Jan 31, 2024
2 parents 7220c7f + 664be39 commit 10f1d0a
Show file tree
Hide file tree
Showing 17 changed files with 864 additions and 159 deletions.
3 changes: 2 additions & 1 deletion services/app/apps/codebattle/.babelrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
],
"plugins": [
"lodash",
"babel-plugin-transform-import-meta"
"babel-plugin-transform-import-meta",
"babel-plugin-react-inline-svg-unique-id"
]
}
4 changes: 0 additions & 4 deletions services/app/apps/codebattle/assets/css/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ $gold: #daa520;
$fa-font-path: '/fonts';

@import 'fonts';
@import '~font-mfizz/dist/font-mfizz.css';
@import 'tournaments';
@import 'taskComponent';

Expand Down Expand Up @@ -565,9 +564,6 @@ a {

.x-username-truncated {
max-width: 180px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.bind-social {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,51 @@
import React from 'react';

import cn from 'classnames';
import ClojureOriginalIcon from 'react-devicons/clojure/original';
import CppOriginalIcon from 'react-devicons/cplusplus/original';
import CsharpOriginalIcon from 'react-devicons/csharp/original';
import DartOriginalIcon from 'react-devicons/dart/original';
import GolangOriginalIcon from 'react-devicons/go/original';
import HaskellOriginalIcon from 'react-devicons/haskell/original';
import JavaOriginalIcon from 'react-devicons/java/original';
import NodejsPlainIcon from 'react-devicons/nodejs/plain';
import TypescriptOriginalIcon from 'react-devicons/typescript/original';

const iconsToClass = {
js: 'icon-nodejs',
javascript: 'icon-nodejs',
ts: 'icon-nodejs',
typescript: 'icon-nodejs',
dart: 'icon-ghost',
golang: 'icon-go',
cpp: 'icon-cplusplus',
csharp: 'icon-csharp',
java: 'icon-java',
kotlin: 'icon-java-bold',
ruby: 'icon-ruby',
elixir: 'icon-elixir',
haskell: 'icon-haskell',
clojure: 'icon-clojure',
python: 'icon-python',
php: 'icon-php-alt',
import ElixirOriginalIcon from './icons/ElixirOriginalIcon';
import KotlinOriginalIcon from './icons/KotlinOriginalIcon';
import PhpOriginalIcon from './icons/PhpOriginalIcon';
import PythonOriginalIcon from './icons/PythonOriginalIcon';
import RubyOriginalIcon from './icons/RubyOriginalIcon';

const iconRenderers = {
js: className => <NodejsPlainIcon className={className} color="green" size="1.25em" />,
javascript: className => <NodejsPlainIcon className={className} color="green" size="1.25em" />,
ts: className => <TypescriptOriginalIcon className={className} size="1.125em" />,
typescript: className => <TypescriptOriginalIcon className={className} size="1.125em" />,
dart: className => <DartOriginalIcon className={className} size="1.125em" />,
golang: className => <GolangOriginalIcon className={className} size="1.25em" />,
cpp: className => <CppOriginalIcon className={className} size="1.25em" />,
csharp: className => <CsharpOriginalIcon className={className} size="1.25em" />,
java: className => (
<JavaOriginalIcon
className={className}
style={{ transform: 'translateY(-0.125em)' }}
size="1.25em"
/>
),
kotlin: className => <KotlinOriginalIcon className={className} />,
ruby: className => <RubyOriginalIcon className={className} />,
elixir: className => <ElixirOriginalIcon className={className} size="1.25em" />,
haskell: className => <HaskellOriginalIcon className={className} size="1.125em" />,
clojure: className => <ClojureOriginalIcon className={className} size="1.125em" />,
python: className => <PythonOriginalIcon className={className} size="1.25em" />,
php: className => <PhpOriginalIcon className={className} size="1.875em" />,
default: () => null,
};

const LanguageIcon = ({ lang }) => (
<span className={cn('d-inline-block', iconsToClass[lang])} style={{ marginTop: 2 }} />
);
const LanguageIcon = ({ className = '', lang }) => {
const renderIcon = iconRenderers[lang] || iconRenderers.default;

return renderIcon(className);
};

export default LanguageIcon;
Original file line number Diff line number Diff line change
@@ -1,41 +1,28 @@
import React from 'react';

import { faFlag } from '@fortawesome/free-regular-svg-icons';
import { faTrophy } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import Tooltip from 'react-bootstrap/Tooltip';

const ResultIcon = ({ gameId, player1, player2 }) => {
const tooltipId = `tooltip-${gameId}-${player1.id}`;
const iconRenderers = {
gaveUp: () => <FontAwesomeIcon icon={faFlag} className="mr-2" transform="grow-1.25" />,
won: () => <FontAwesomeIcon icon={faTrophy} className="mr-2 text-warning" transform="grow-1.25" />,
};

if (player1.result === 'gave_up') {
return (
<OverlayTrigger
overlay={<Tooltip id={tooltipId}>Player gave up</Tooltip>}
placement="left"
>
<span className="align-middle mr-1">
<i className="far fa-flag" aria-hidden="true" />
</span>
</OverlayTrigger>
);
}
const ResultIcon = ({ icon = null }) => {
if (icon === null) return null;

if (player1.result === 'won' && player2.result !== 'gave_up') {
return (
<OverlayTrigger
overlay={<Tooltip id={tooltipId}>Player won</Tooltip>}
placement="left"
>
<span className="align-middle mr-1">
<i className="fa fa-trophy text-warning" aria-hidden="true" />
</span>
</OverlayTrigger>
);
}
const renderIcon = iconRenderers[icon.name];

return (
<span className="align-middle mr-1">
<i className="fa x-opacity-0">&nbsp;</i>
</span>
<OverlayTrigger
overlay={<Tooltip id={icon.tooltip.id}>{icon.tooltip.text}</Tooltip>}
placement="left"
>
{renderIcon()}
</OverlayTrigger>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function UserPopoverContent({ user }) {
}

function UserInfo({
className,
user,
hideInfo = false,
truncate = false,
Expand All @@ -62,20 +63,19 @@ function UserInfo({
}

const isOnline = presenceList.some(({ id }) => id === user?.id);
const userClassName = cn({
const userClassName = cn(className, {
'cb-opacity-50': loading,
});

if (hideInfo) {
return (
<div className={userClassName}>
<UserName
user={user}
truncate={truncate}
isOnline={isOnline}
hideOnlineIndicator={hideOnlineIndicator}
/>
</div>
<UserName
className={userClassName}
user={user}
truncate={truncate}
isOnline={isOnline}
hideOnlineIndicator={hideOnlineIndicator}
/>
);
}

Expand All @@ -85,8 +85,9 @@ function UserInfo({
placement={placement}
component={content}
>
<div className={userClassName}>
<div>
<UserName
className={userClassName}
user={user}
truncate={truncate}
isOnline={isOnline}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,58 +1,34 @@
import React from 'react';

import { faCircle, faRobot } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import cn from 'classnames';

import LanguageIcon from './LanguageIcon';

const renderUserName = ({ name, rank }) => {
const displayRank = rank ? `(${rank})` : '';

return `${name}${displayRank}`;
};
const renderOnlineIndicator = (user, isOnline) => {
if (user.id <= 0) {
return null;
}

const onlineIndicatorClassName = cn('mr-2', {
const UserName = ({
className = '', user, truncate, isOnline, hideOnlineIndicator,
}) => {
const commonClassName = 'd-flex align-items-center';
const onlineIndicatorClassName = cn('mr-1', {
'cb-user-online': isOnline,
'cb-user-offline': !isOnline,
});
const userLinkClassName = cn('text-truncate', {
'text-danger': user.isAdmin,
'x-username-truncated': truncate,
});

const userName = user.rank ? `${user.name}(${user.rank})` : user.name;

return (
<span>
<FontAwesomeIcon
icon={['fa', 'circle']}
className={onlineIndicatorClassName}
/>
</span>
<div className={cn(commonClassName, className)}>
{(!hideOnlineIndicator && !user.isBot) && <FontAwesomeIcon icon={faCircle} className={onlineIndicatorClassName} />}
<LanguageIcon className="mr-1" lang={user.lang} />
{user.isBot && <FontAwesomeIcon className="mr-1" icon={faRobot} transform="up-1" />}
<a href={`/users/${user.id}`} className={userLinkClassName}>{userName}</a>
</div>
);
};

const UserName = ({
user, truncate, isOnline, hideOnlineIndicator,
}) => (
<div className="d-flex align-items-center">
{!hideOnlineIndicator && renderOnlineIndicator(user, isOnline)}
<LanguageIcon lang={user.lang || 'js'} />
{user.id < 0 && <FontAwesomeIcon className="mx-1" icon="robot" transform="up-1" />}
<a
href={`/users/${user.id}`}
key={user.id}
className={cn('d-flex align-items-center', {
'text-danger': user.isAdmin,
})}
>
<p
className={cn('text-truncate m-0', {
'x-username-truncated': truncate,
})}
>
<u className="text-decoration-none">{renderUserName(user)}</u>
</p>
</a>
</div>
);

export default UserName;
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ const UserStats = ({ data, user: userInfo }) => {
<div className="d-flex flex-column ml-2">
<div className="d-flex align-items-center">
<span>{name}</span>
<div className="ml-1">
<LanguageIcon lang={lang} />
</div>
<LanguageIcon className="ml-1" lang={lang} />
</div>
<div className="d-flex justify-content-between align-items-baseline">
<div className="d-flex align-items-baseline">
Expand Down
Loading

0 comments on commit 10f1d0a

Please sign in to comment.