Add ReactIcons (#149)

This commit is contained in:
Riccardo Graziosi
2022-08-22 10:38:03 +02:00
committed by GitHub
parent 4c73b398e8
commit 6198d814d8
32 changed files with 267 additions and 226 deletions

View File

@@ -1,6 +1,9 @@
import * as React from 'react'; import * as React from 'react';
import I18n from 'i18n-js'; import I18n from 'i18n-js';
import Button from '../common/Button'; import Button from '../common/Button';
import Switch from '../common/Switch';
import ActionLink from '../common/ActionLink';
import { CancelIcon } from '../common/Icons';
interface Props { interface Props {
id: number; id: number;
@@ -61,34 +64,23 @@ class CommentEditForm extends React.Component<Props, State> {
<div> <div>
<div> <div>
{ {
isPowerUser ? isPowerUser &&
<> <Switch
<input htmlId={`isPostUpdateFlagComment${id}`}
id={`isPostUpdateFlagComment${id}`} onClick={e => this.handleCommentIsPostUpdateChange(!isPostUpdate)}
type="checkbox" checked={isPostUpdate || false}
onChange={e => this.handleCommentIsPostUpdateChange(e.target.checked)} label={I18n.t('post.new_comment.is_post_update')}
checked={isPostUpdate || false} />
/>
&nbsp;
<label htmlFor={`isPostUpdateFlagComment${id}`}>
{I18n.t('post.new_comment.is_post_update')}
</label>
</>
:
null
} }
</div> </div>
<div> <div className="editCommentFormActions">
<a className="commentLink" onClick={toggleEditMode}> <ActionLink onClick={toggleEditMode} icon={<CancelIcon />}>
{ I18n.t('common.buttons.cancel') } {I18n.t('common.buttons.cancel')}
</a> </ActionLink>
&nbsp; &nbsp;
<Button <Button onClick={() => handleUpdateComment(body, isPostUpdate)}>
onClick={() => handleUpdateComment(body, isPostUpdate)} {I18n.t('common.buttons.update')}
>
{ I18n.t('common.buttons.update') }
</Button> </Button>
</div> </div>
</div> </div>

View File

@@ -5,6 +5,8 @@ import Separator from '../common/Separator';
import { MutedText } from '../common/CustomTexts'; import { MutedText } from '../common/CustomTexts';
import friendlyDate from '../../helpers/datetime'; import friendlyDate from '../../helpers/datetime';
import { ReplyFormState } from '../../reducers/replyFormReducer'; import { ReplyFormState } from '../../reducers/replyFormReducer';
import ActionLink from '../common/ActionLink';
import { CancelIcon, DeleteIcon, EditIcon, ReplyIcon } from '../common/Icons';
interface Props { interface Props {
id: number; id: number;
@@ -34,43 +36,43 @@ const CommentFooter = ({
toggleEditMode, toggleEditMode,
}: Props) => ( }: Props) => (
<div className="commentFooter"> <div className="commentFooter">
<a className="commentReplyButton commentLink" onClick={handleToggleCommentReply}> <ActionLink
onClick={handleToggleCommentReply}
icon={replyForm.isOpen ? <CancelIcon /> : <ReplyIcon />}
>
{ {
replyForm.isOpen ? replyForm.isOpen ?
I18n.t('common.buttons.cancel') I18n.t('common.buttons.cancel')
: :
I18n.t('post.comments.reply_button') I18n.t('post.comments.reply_button')
} }
</a> </ActionLink>
{ {
isPowerUser || currentUserEmail === commentAuthorEmail ? isPowerUser || currentUserEmail === commentAuthorEmail ?
<> <>
<Separator /> <ActionLink onClick={toggleEditMode} icon={<EditIcon />}>
<a onClick={toggleEditMode} className="commentLink">
{I18n.t('common.buttons.edit')} {I18n.t('common.buttons.edit')}
</a> </ActionLink>
<Separator /> <ActionLink
<a
onClick={() => confirm(I18n.t('common.confirmation')) && handleDeleteComment(id)} onClick={() => confirm(I18n.t('common.confirmation')) && handleDeleteComment(id)}
className="commentLink"> icon={<DeleteIcon />}
{I18n.t('common.buttons.delete')} >
</a> {I18n.t('common.buttons.delete')}
</ActionLink>
</> </>
: :
null null
} }
<Separator />
<MutedText>{friendlyDate(createdAt)}</MutedText> <MutedText>{friendlyDate(createdAt)}</MutedText>
{ {
createdAt !== updatedAt ? createdAt !== updatedAt &&
<> <>
<Separator /> <Separator />
<MutedText>{ I18n.t('common.edited').toLowerCase() }</MutedText> <MutedText>{ I18n.t('common.edited').toLowerCase() }</MutedText>
</> </>
:
null
} }
</div> </div>
); );

View File

@@ -2,6 +2,7 @@ import * as React from 'react';
import I18n from 'i18n-js'; import I18n from 'i18n-js';
import { MutedText } from '../common/CustomTexts'; import { MutedText } from '../common/CustomTexts';
import Switch from '../common/Switch';
interface Props { interface Props {
postUpdateFlagValue: boolean; postUpdateFlagValue: boolean;
@@ -13,21 +14,15 @@ const NewCommentUpdateSection = ({
handlePostUpdateFlag, handlePostUpdateFlag,
}: Props) => ( }: Props) => (
<div className="commentIsUpdateForm"> <div className="commentIsUpdateForm">
<div> <Switch
<input htmlId="isPostUpdateFlag"
id="isPostUpdateFlag" onClick={handlePostUpdateFlag}
type="checkbox" checked={postUpdateFlagValue || false}
onChange={handlePostUpdateFlag} label={I18n.t('post.new_comment.is_post_update')}
checked={postUpdateFlagValue || false} />
/>
&nbsp;
<label htmlFor="isPostUpdateFlag">{I18n.t('post.new_comment.is_post_update')}</label>
</div>
{ {
postUpdateFlagValue ? postUpdateFlagValue &&
<MutedText>{I18n.t('post.new_comment.user_notification')}</MutedText> <MutedText>{I18n.t('post.new_comment.user_notification')}</MutedText>
:
null
} }
</div> </div>
); );

View File

@@ -8,6 +8,8 @@ import IPostStatus from '../../interfaces/IPostStatus';
import IBoard from '../../interfaces/IBoard'; import IBoard from '../../interfaces/IBoard';
import Button from '../common/Button'; import Button from '../common/Button';
import Spinner from '../common/Spinner'; import Spinner from '../common/Spinner';
import ActionLink from '../common/ActionLink';
import { CancelIcon } from '../common/Icons';
interface Props { interface Props {
title: string; title: string;
@@ -93,9 +95,9 @@ const PostEditForm = ({
/> />
<div className="postEditFormButtons"> <div className="postEditFormButtons">
<a onClick={toggleEditMode}> <ActionLink onClick={toggleEditMode} icon={<CancelIcon />}>
{ I18n.t('common.buttons.cancel') } {I18n.t('common.buttons.cancel')}
</a> </ActionLink>
&nbsp; &nbsp;
<Button onClick={() => handleUpdatePost(title, description, boardId, postStatusId)}> <Button onClick={() => handleUpdatePost(title, description, boardId, postStatusId)}>
{ isUpdating ? <Spinner /> : I18n.t('common.buttons.update') } { isUpdating ? <Spinner /> : I18n.t('common.buttons.update') }

View File

@@ -5,6 +5,8 @@ import I18n from 'i18n-js';
import { MutedText } from '../common/CustomTexts'; import { MutedText } from '../common/CustomTexts';
import friendlyDate from '../../helpers/datetime'; import friendlyDate from '../../helpers/datetime';
import Separator from '../common/Separator'; import Separator from '../common/Separator';
import ActionLink from '../common/ActionLink';
import { DeleteIcon, EditIcon } from '../common/Icons';
interface Props { interface Props {
createdAt: string; createdAt: string;
@@ -27,26 +29,29 @@ const PostFooter = ({
}: Props) => ( }: Props) => (
<div className="postFooter"> <div className="postFooter">
<div className="postAuthor"> <div className="postAuthor">
<span>{ I18n.t('post.published_by').toLowerCase() } &nbsp;</span> <span>{I18n.t('post.published_by').toLowerCase()} &nbsp;</span>
<Gravatar email={authorEmail} size={24} className="postAuthorAvatar" /> &nbsp; <Gravatar email={authorEmail} size={24} className="postAuthorAvatar" /> &nbsp;
{authorFullName} {authorFullName}
<Separator />
{friendlyDate(createdAt)}
</div> </div>
{ {
isPowerUser || authorEmail === currentUserEmail ? isPowerUser || authorEmail === currentUserEmail ?
<> <div className="postFooterActions">
<a onClick={toggleEditMode}> <ActionLink onClick={toggleEditMode} icon={<EditIcon />}>
{ I18n.t('common.buttons.edit') } {I18n.t('common.buttons.edit')}
</a> </ActionLink>
<Separator />
<a onClick={() => confirm(I18n.t('common.confirmation')) && handleDeletePost()}> <ActionLink
{ I18n.t('common.buttons.delete') } onClick={() => confirm(I18n.t('common.confirmation')) && handleDeletePost()}
</a> icon={<DeleteIcon />}
<Separator /> >
</> {I18n.t('common.buttons.delete')}
</ActionLink>
</div>
: :
null null
} }
<MutedText>{friendlyDate(createdAt)}</MutedText>
</div> </div>
); );

View File

@@ -9,6 +9,8 @@ import { IOAuth } from '../../../interfaces/IOAuth';
import { AuthenticationPages } from './AuthenticationSiteSettingsP'; import { AuthenticationPages } from './AuthenticationSiteSettingsP';
import { useState } from 'react'; import { useState } from 'react';
import Separator from '../../common/Separator'; import Separator from '../../common/Separator';
import ActionLink from '../../common/ActionLink';
import { BackIcon } from '../../common/Icons';
interface Props { interface Props {
selectedOAuth: IOAuth; selectedOAuth: IOAuth;
@@ -88,16 +90,18 @@ const OAuthForm = ({
return ( return (
<> <>
<a <ActionLink
onClick={() => { onClick={() => {
let confirmation = true; let confirmation = true;
if (isDirty) if (isDirty)
confirmation = confirm(I18n.t('common.unsaved_changes') + ' ' + I18n.t('common.confirmation')); confirmation = confirm(I18n.t('common.unsaved_changes') + ' ' + I18n.t('common.confirmation'));
if (confirmation) setPage('index'); if (confirmation) setPage('index');
}} }}
className="backButton link"> icon={<BackIcon />}
{ I18n.t('common.buttons.back') } customClass="backButton"
</a> >
{I18n.t('common.buttons.back')}
</ActionLink>
<h2>{ I18n.t(`site_settings.authentication.form.title_${page}`) }</h2> <h2>{ I18n.t(`site_settings.authentication.form.title_${page}`) }</h2>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<div className="formRow"> <div className="formRow">

View File

@@ -6,6 +6,8 @@ import Switch from '../../common/Switch';
import Separator from '../../common/Separator'; import Separator from '../../common/Separator';
import { AuthenticationPages } from './AuthenticationSiteSettingsP'; import { AuthenticationPages } from './AuthenticationSiteSettingsP';
import CopyToClipboardButton from '../../common/CopyToClipboardButton'; import CopyToClipboardButton from '../../common/CopyToClipboardButton';
import ActionLink from '../../common/ActionLink';
import { DeleteIcon, EditIcon, TestIcon } from '../../common/Icons';
interface Props { interface Props {
oAuth: IOAuth; oAuth: IOAuth;
@@ -44,23 +46,32 @@ const OAuthProviderItem = ({
label={I18n.t('site_settings.authentication.copy_url')} label={I18n.t('site_settings.authentication.copy_url')}
textToCopy={oAuth.callbackUrl} textToCopy={oAuth.callbackUrl}
/> />
<Separator />
<a onClick={() => <ActionLink
window.open(`/o_auths/${oAuth.id}/start?reason=test`, '', 'width=640, height=640') onClick={() =>
}> window.open(`/o_auths/${oAuth.id}/start?reason=test`, '', 'width=640, height=640')
Test }
</a> icon={<TestIcon />}
<Separator /> >
<a onClick={() => { {I18n.t('common.buttons.test')}
setSelectedOAuth(oAuth.id); </ActionLink>
setPage('edit');
}}> <ActionLink
{ I18n.t('common.buttons.edit') } onClick={() => {
</a> setSelectedOAuth(oAuth.id);
<Separator /> setPage('edit');
<a onClick={() => confirm(I18n.t('common.confirmation')) && handleDeleteOAuth(oAuth.id)}> }}
{ I18n.t('common.buttons.delete') } icon={<EditIcon />}
</a> >
{I18n.t('common.buttons.edit')}
</ActionLink>
<ActionLink
onClick={() => confirm(I18n.t('common.confirmation')) && handleDeleteOAuth(oAuth.id)}
icon={<DeleteIcon />}
>
{I18n.t('common.buttons.delete')}
</ActionLink>
</div> </div>
</li> </li>
); );

View File

@@ -8,6 +8,8 @@ import DragZone from '../../common/DragZone';
import PostBoardLabel from '../../common/PostBoardLabel'; import PostBoardLabel from '../../common/PostBoardLabel';
import Separator from '../../common/Separator'; import Separator from '../../common/Separator';
import BoardForm from './BoardForm'; import BoardForm from './BoardForm';
import ActionLink from '../../common/ActionLink';
import { CancelIcon, DeleteIcon, EditIcon } from '../../common/Icons';
interface Props { interface Props {
id: number; id: number;
@@ -83,13 +85,16 @@ class BoardsEditable extends React.Component<Props, State> {
</div> </div>
<div className="boardEditableActions"> <div className="boardEditableActions">
<a onClick={this.toggleEditMode}>{I18n.t('common.buttons.edit')}</a> <ActionLink onClick={this.toggleEditMode} icon={<EditIcon />}>
{I18n.t('common.buttons.edit')}
</ActionLink>
<Separator /> <ActionLink
onClick={() => confirm(I18n.t('common.confirmation')) && handleDelete(id)}
<a onClick={() => confirm(I18n.t('common.confirmation')) && handleDelete(id)}> icon={<DeleteIcon />}
>
{I18n.t('common.buttons.delete')} {I18n.t('common.buttons.delete')}
</a> </ActionLink>
</div> </div>
</> </>
: :
@@ -102,11 +107,12 @@ class BoardsEditable extends React.Component<Props, State> {
handleUpdate={this.handleUpdate} handleUpdate={this.handleUpdate}
/> />
<a <ActionLink
className="boardFormCancelButton" onClick={this.toggleEditMode}
onClick={this.toggleEditMode}> icon={<CancelIcon />}
>
{I18n.t('common.buttons.cancel')} {I18n.t('common.buttons.cancel')}
</a> </ActionLink>
</> </>
} }
</li> </li>

View File

@@ -68,6 +68,7 @@ const BoardForm = ({
{...register('name', { required: true })} {...register('name', { required: true })}
placeholder={I18n.t('site_settings.boards.form.name')} placeholder={I18n.t('site_settings.boards.form.name')}
autoFocus={mode === 'update'} autoFocus={mode === 'update'}
autoComplete={'off'}
className="formControl" className="formControl"
/> />

View File

@@ -6,6 +6,8 @@ import PostStatusLabel from "../../common/PostStatusLabel";
import DragZone from '../../common/DragZone'; import DragZone from '../../common/DragZone';
import Separator from '../../common/Separator'; import Separator from '../../common/Separator';
import PostStatusForm from './PostStatusForm'; import PostStatusForm from './PostStatusForm';
import ActionLink from '../../common/ActionLink';
import { CancelIcon, DeleteIcon, EditIcon } from '../../common/Icons';
interface Props { interface Props {
id: number; id: number;
@@ -74,13 +76,16 @@ class PostStatusEditable extends React.Component<Props, State> {
<PostStatusLabel name={name} color={color} /> <PostStatusLabel name={name} color={color} />
<div className="postStatusEditableActions"> <div className="postStatusEditableActions">
<a onClick={this.toggleEditMode}>{I18n.t('common.buttons.edit')}</a> <ActionLink onClick={this.toggleEditMode} icon={<EditIcon />}>
{I18n.t('common.buttons.edit')}
</ActionLink>
<Separator /> <ActionLink
onClick={() => confirm(I18n.t('common.confirmation')) && handleDelete(id)}
<a onClick={() => confirm(I18n.t('common.confirmation')) && handleDelete(id)}> icon={<DeleteIcon />}
>
{I18n.t('common.buttons.delete')} {I18n.t('common.buttons.delete')}
</a> </ActionLink>
</div> </div>
</> </>
: :
@@ -93,11 +98,12 @@ class PostStatusEditable extends React.Component<Props, State> {
handleUpdate={this.handleUpdate} handleUpdate={this.handleUpdate}
/> />
<a <ActionLink
className="postStatusFormCancelButton" onClick={this.toggleEditMode}
onClick={this.toggleEditMode}> icon={<CancelIcon />}
>
{I18n.t('common.buttons.cancel')} {I18n.t('common.buttons.cancel')}
</a> </ActionLink>
</> </>
} }
</li> </li>

View File

@@ -72,6 +72,7 @@ const PostStatusForm = ({
{...register('name', { required: true })} {...register('name', { required: true })}
placeholder={I18n.t('site_settings.post_statuses.form.name')} placeholder={I18n.t('site_settings.post_statuses.form.name')}
autoFocus={mode === 'update'} autoFocus={mode === 'update'}
autoComplete={'off'}
className="formControl" className="formControl"
/> />

View File

@@ -6,6 +6,8 @@ import IUser, { UserRoles, USER_ROLE_ADMIN, USER_ROLE_USER, USER_STATUS_ACTIVE,
import Separator from "../../common/Separator"; import Separator from "../../common/Separator";
import UserForm from "./UserForm"; import UserForm from "./UserForm";
import { MutedText } from "../../common/CustomTexts"; import { MutedText } from "../../common/CustomTexts";
import { BlockIcon, CancelIcon, EditIcon, UnblockIcon } from "../../common/Icons";
import ActionLink from "../../common/ActionLink";
interface Props { interface Props {
user: IUser; user: IUser;
@@ -119,18 +121,18 @@ class UserEditable extends React.Component<Props, State> {
</div> </div>
<div className="userEditableActions"> <div className="userEditableActions">
<a <ActionLink
onClick={() => editEnabled && this.toggleEditMode()} onClick={() => editEnabled && this.toggleEditMode()}
className={editEnabled ? '' : 'actionDisabled'} icon={<EditIcon />}
disabled={!editEnabled}
> >
{ I18n.t('common.buttons.edit') } { I18n.t('common.buttons.edit') }
</a> </ActionLink>
<Separator /> <ActionLink
<a
onClick={() => blockEnabled && this._handleUpdateUserStatus()} onClick={() => blockEnabled && this._handleUpdateUserStatus()}
className={blockEnabled ? '' : 'actionDisabled'} icon={user.status !== USER_STATUS_BLOCKED ? <BlockIcon /> : <UnblockIcon />}
disabled={!blockEnabled}
> >
{ {
user.status !== USER_STATUS_BLOCKED ? user.status !== USER_STATUS_BLOCKED ?
@@ -138,15 +140,15 @@ class UserEditable extends React.Component<Props, State> {
: :
I18n.t('site_settings.users.unblock') I18n.t('site_settings.users.unblock')
} }
</a> </ActionLink>
</div> </div>
</> </>
: :
<> <>
<UserForm user={user} updateUserRole={this._handleUpdateUserRole} /> <UserForm user={user} updateUserRole={this._handleUpdateUserRole} />
<a onClick={this.toggleEditMode} className="userEditCancelButton"> <ActionLink onClick={this.toggleEditMode} icon={<CancelIcon />}>
{ I18n.t('common.buttons.cancel') } {I18n.t('common.buttons.cancel')}
</a> </ActionLink>
</> </>
} }
</li> </li>

View File

@@ -0,0 +1,26 @@
import * as React from 'react';
interface Props {
onClick: React.MouseEventHandler<HTMLAnchorElement>;
icon?: React.ReactElement;
disabled?: boolean;
customClass?: string;
children: React.ReactNode;
}
const ActionLink = ({
onClick,
icon,
disabled = false,
customClass,
children,
}: Props) => (
<a
onClick={onClick}
className={`actionLink${disabled ? ' actionLinkDisabled' : ''}${customClass ? ' ' + customClass : ''}`}
>
{icon}{children}
</a>
);
export default ActionLink;

View File

@@ -1,6 +1,8 @@
import * as React from 'react'; import * as React from 'react';
import I18n from 'i18n-js'; import I18n from 'i18n-js';
import { useState } from 'react'; import { useState } from 'react';
import ActionLink from './ActionLink';
import { CopyIcon, DoneIcon } from './Icons';
interface Props { interface Props {
label: string; label: string;
@@ -20,7 +22,7 @@ const CopyToClipboardButton = ({
return ( return (
ready ? ready ?
<a <ActionLink
onClick={() => { onClick={() => {
if (navigator.clipboard) { if (navigator.clipboard) {
navigator.clipboard.writeText(textToCopy).then(() => { navigator.clipboard.writeText(textToCopy).then(() => {
@@ -32,11 +34,14 @@ const CopyToClipboardButton = ({
alertError(); alertError();
} }
}} }}
icon={<CopyIcon />}
> >
{label} {label}
</a> </ActionLink>
: :
<span>{copiedLabel}</span> <span style={{display: 'flex', marginRight: 12}}>
{copiedLabel}
</span>
); );
}; };

View File

@@ -1,11 +1,22 @@
import * as React from 'react'; import * as React from 'react';
import { MdDragIndicator } from 'react-icons/md';
const DragZone = ({dndProvided, isDragDisabled, color = 'black'}) => ( interface Props {
dndProvided: any;
isDragDisabled: boolean;
color?: 'black' | 'white';
}
const DragZone = ({
dndProvided,
isDragDisabled,
color = 'black',
}: Props) => (
<span <span
className={`drag-zone${isDragDisabled ? ' drag-zone-disabled' : ''}`} className={`drag-zone${isDragDisabled ? ' drag-zone-disabled' : ''}`}
{...dndProvided.dragHandleProps} {...dndProvided.dragHandleProps}
> >
<span className={`drag-icon${color === 'white' ? ' drag-icon-white' : ''}`}></span> <MdDragIndicator color={color} size={18} />
</span> </span>
); );

View File

@@ -0,0 +1,28 @@
import * as React from 'react';
import { BsReply } from 'react-icons/bs';
import { FiEdit, FiDelete } from 'react-icons/fi';
import { ImCancelCircle } from 'react-icons/im';
import { TbLock, TbLockOpen } from 'react-icons/tb';
import { MdContentCopy, MdDone, MdOutlineArrowBack } from 'react-icons/md';
import { GrTest } from 'react-icons/gr';
export const EditIcon = () => <FiEdit />;
export const DeleteIcon = () => <FiDelete />;
export const CancelIcon = () => <ImCancelCircle />;
export const BlockIcon = () => <TbLock />;
export const UnblockIcon = () => <TbLockOpen />;
export const CopyIcon = () => <MdContentCopy />;
export const TestIcon = () => <GrTest />;
export const DoneIcon = () => <MdDone />;
export const BackIcon = () => <MdOutlineArrowBack />;
export const ReplyIcon = () => <BsReply />;

View File

@@ -187,4 +187,25 @@
.link { .link {
cursor: pointer; cursor: pointer;
&:hover { text-decoration: underline; } &:hover { text-decoration: underline; }
}
.actionLink {
display: flex;
cursor: pointer;
align-self: center;
margin-right: 12px;
&:hover { text-decoration: underline !important; }
svg {
margin-right: 4px;
align-self: center;
}
&.actionLinkDisabled {
color: $astuto-grey !important;
text-decoration: none !important;
cursor: not-allowed;
}
} }

View File

@@ -1,15 +1,6 @@
.commentsContainer { .commentsContainer {
@extend .my-3; @extend .my-3;
a.commentLink {
color: $primary-color;
&:hover {
text-decoration: underline;
cursor: pointer;
}
}
.commentForm { .commentForm {
@extend @extend
.form-control, .form-control,
@@ -41,7 +32,7 @@
.justify-content-between, .justify-content-between,
.mt-3; .mt-3;
margin-left: 48px; margin-left: 58px;
} }
.currentUserAvatar { .currentUserAvatar {
@@ -71,6 +62,8 @@
.d-flex, .d-flex,
.justify-content-between; .justify-content-between;
} }
.editCommentFormActions { @extend .d-flex; }
} }
.commentsTitle { .commentsTitle {
@@ -113,7 +106,9 @@
} }
.commentFooter { .commentFooter {
font-size: 14px; @extend .d-flex;
font-size: 13px;
} }
} }
} }

View File

@@ -141,12 +141,7 @@
.postAuthorAvatar { @extend .gravatar; } .postAuthorAvatar { @extend .gravatar; }
} }
a { .postFooterActions { @extend .d-flex; }
&:hover {
cursor: pointer;
text-decoration: underline;
}
}
} }
.postEditForm { .postEditForm {
@@ -155,14 +150,7 @@
} }
.postEditFormButtons { .postEditFormButtons {
text-align: right; @extend .d-flex, .justify-content-end;
a {
&:hover {
cursor: pointer;
text-decoration: underline;
}
}
} }
} }
} }

View File

@@ -25,6 +25,7 @@
.columnTitle { .columnTitle {
color: white; color: white;
text-transform: uppercase;
} }
} }

View File

@@ -34,11 +34,9 @@
} }
.oAuthActions { .oAuthActions {
align-self: center; @extend .d-flex;
a { align-self: center;
@extend .link;
}
} }
} }
} }
@@ -46,12 +44,8 @@
.authenticationFormPage { .authenticationFormPage {
a.backButton { a.backButton {
@extend .mb-2; @extend .mb-2, .align-self-start;
font-size: 18px; font-size: 18px;
} }
a.link {
@extend .link;
}
} }

View File

@@ -13,12 +13,6 @@
column-gap: 32px; column-gap: 32px;
a {
cursor: pointer;
&:hover { text-decoration: underline; }
}
.boardInfo { .boardInfo {
@extend @extend
.d-flex, .d-flex,
@@ -30,8 +24,8 @@
.boardDescription { @extend .text-center; } .boardDescription { @extend .text-center; }
} }
.boardEditableActions, .boardFormCancelButton { .boardEditableActions {
@extend .align-self-center; @extend .d-flex, .align-self-center;
} }
} }
} }

View File

@@ -11,15 +11,7 @@
.justify-content-between, .justify-content-between,
.p-3; .p-3;
a { .postStatusEditableActions { @extend .d-flex; }
cursor: pointer;
&:hover { text-decoration: underline; }
}
.postStatusFormCancelButton {
align-self: center;
}
} }
} }

View File

@@ -45,6 +45,7 @@
color: white; color: white;
padding: 8px 4px; padding: 8px 4px;
text-transform: uppercase;
.titleText { @extend .align-self-center; } .titleText { @extend .align-self-center; }
} }

View File

@@ -30,7 +30,7 @@ ul.usersList {
} }
.userEditableActions { .userEditableActions {
@extend .align-self-center; @extend .d-flex, .align-self-center;
} }
.userForm { .userForm {
@@ -41,24 +41,8 @@ ul.usersList {
} }
} }
.updateUserButton { @extend .align-self-center; }
.userEditCancelButton { @extend .align-self-center; }
a {
cursor: pointer;
&:hover { text-decoration: underline; }
}
a.actionDisabled {
@extend .mutedText;
text-decoration: none;
cursor: not-allowed;
}
.updateUserButton { .updateUserButton {
@extend .align-self-center;
margin-left: 16px; margin-left: 16px;
} }

View File

@@ -1,28 +0,0 @@
/* Code taken from: https://gist.github.com/JakeSidSmith/83c324dbe7e4d91ee8c52525b1d504d9 */
/* Thanks JakeSidSmith */
span.drag-icon {
display: inline-block;
width: 16px;
height: 8px;
}
span.drag-icon,
span.drag-icon::before {
background-image: radial-gradient(black 40%, transparent 40%);
background-size: 4px 4px;
background-position: 0 100%;
background-repeat: repeat-x;
}
span.drag-icon.drag-icon-white,
span.drag-icon.drag-icon-white::before {
background-image: radial-gradient(white 40%, transparent 40%);
}
span.drag-icon::before {
content: '';
display: block;
width: 100%;
height: 33%;
}

View File

@@ -22,7 +22,4 @@
@import 'components/SiteSettings/PostStatuses'; @import 'components/SiteSettings/PostStatuses';
@import 'components/SiteSettings/Roadmap'; @import 'components/SiteSettings/Roadmap';
@import 'components/SiteSettings/Users'; @import 'components/SiteSettings/Users';
@import 'components/SiteSettings/Authentication'; @import 'components/SiteSettings/Authentication';
/* Icons */
@import 'icons/drag_icon';

View File

@@ -40,10 +40,9 @@
<div class="actions"> <div class="actions">
<%= f.submit t('common.forms.auth.sign_up'), class: "btn btn-dark btn-block" %> <%= f.submit t('common.forms.auth.sign_up'), class: "btn btn-dark btn-block" %>
</div> </div>
<hr />
<% if not @o_auths.empty? %> <% if not @o_auths.empty? %>
<hr />
<% @o_auths.each do |o_auth| %> <% @o_auths.each do |o_auth| %>
<p> <p>
<%= link_to t('common.forms.auth.sign_up_with', { o_auth: o_auth.name }), <%= link_to t('common.forms.auth.sign_up_with', { o_auth: o_auth.name }),

View File

@@ -29,10 +29,9 @@
<div class="actions"> <div class="actions">
<%= f.submit t('common.forms.auth.log_in'), class: "btn btn-dark btn-block" %> <%= f.submit t('common.forms.auth.log_in'), class: "btn btn-dark btn-block" %>
</div> </div>
<hr />
<% if not @o_auths.empty? %> <% if not @o_auths.empty? %>
<hr />
<% @o_auths.each do |o_auth| %> <% @o_auths.each do |o_auth| %>
<p> <p>
<%= link_to t('common.forms.auth.log_in_with', { o_auth: o_auth.name }), <%= link_to t('common.forms.auth.log_in_with', { o_auth: o_auth.name }),

View File

@@ -53,6 +53,7 @@ en:
update: 'Save' update: 'Save'
confirm: 'Confirm' confirm: 'Confirm'
back: 'Back' back: 'Back'
test: 'Test'
datetime: datetime:
now: 'just now' now: 'just now'
minutes: minutes:

View File

@@ -22,6 +22,7 @@
"react-dom": "^16.9.0", "react-dom": "^16.9.0",
"react-gravatar": "^2.6.3", "react-gravatar": "^2.6.3",
"react-hook-form": "7.33.1", "react-hook-form": "7.33.1",
"react-icons": "4.4.0",
"react-infinite-scroller": "^1.2.4", "react-infinite-scroller": "^1.2.4",
"react-markdown": "^5.0.3", "react-markdown": "^5.0.3",
"react-redux": "^7.1.1", "react-redux": "^7.1.1",

View File

@@ -6388,6 +6388,11 @@ react-hook-form@7.33.1:
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.33.1.tgz#8c4410e3420788d3b804d62cc4c142915c2e46d0" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.33.1.tgz#8c4410e3420788d3b804d62cc4c142915c2e46d0"
integrity sha512-ydTfTxEJdvgjCZBj5DDXRc58oTEfnFupEwwTAQ9FSKzykEJkX+3CiAkGtAMiZG7IPWHuzgT6AOBfogiKhUvKgg== integrity sha512-ydTfTxEJdvgjCZBj5DDXRc58oTEfnFupEwwTAQ9FSKzykEJkX+3CiAkGtAMiZG7IPWHuzgT6AOBfogiKhUvKgg==
react-icons@4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.4.0.tgz#a13a8a20c254854e1ec9aecef28a95cdf24ef703"
integrity sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==
react-infinite-scroller@^1.2.4: react-infinite-scroller@^1.2.4:
version "1.2.4" version "1.2.4"
resolved "https://registry.yarnpkg.com/react-infinite-scroller/-/react-infinite-scroller-1.2.4.tgz#f67eaec4940a4ce6417bebdd6e3433bfc38826e9" resolved "https://registry.yarnpkg.com/react-infinite-scroller/-/react-infinite-scroller-1.2.4.tgz#f67eaec4940a4ce6417bebdd6e3433bfc38826e9"