Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

View button for editor #466

Merged
merged 15 commits into from
Apr 23, 2024
16 changes: 9 additions & 7 deletions backend/src/config/mailer.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ const configFromName = (transportUrl) => {
const parts = transportUrl.replace('smtp://', '').split(':');
const [emailName, otherInfo] = parts;
const domain = otherInfo.split('.');
const [,domName, dom] = domain;
const [, domName, dom] = domain;

return `${emailName}@${domName}.${dom}`
}
return `${emailName}@${domName}.${dom}`;
};

export class MailerConfig implements MailerOptionsFactory {
/* eslint-disable-next-line class-methods-use-this */
Expand All @@ -17,7 +17,9 @@ export class MailerConfig implements MailerOptionsFactory {
const options: MailerOptions = {
transport: transportUrl,
defaults: {
from: `"Run IT" <${transportUrl ? configFromName(transportUrl) : "test"}>`,
from: `"Run IT" <${
transportUrl ? configFromName(transportUrl) : 'test'
}>`,
},
template: {
dir: `${process.cwd()}/src/users/templates`,
Expand All @@ -32,9 +34,9 @@ export class MailerConfig implements MailerOptionsFactory {
case 'production':
return options;
default:
options.transport =
process.env.TRANSPORT_MAILER_URL ??
{ jsonTransport: true }
options.transport = process.env.TRANSPORT_MAILER_URL ?? {
jsonTransport: true,
};
options.preview = true;
return options;
}
Expand Down
40 changes: 22 additions & 18 deletions backend/src/users/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* eslint-disable no-param-reassign */
/* eslint-disable class-methods-use-this */

import { mkdirSync, openSync, appendFileSync } from 'fs';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { ILike, Repository } from 'typeorm';
Expand All @@ -13,7 +14,6 @@ import { Snippets } from '../entities/snippet.entity';
import { User } from './interfaces/users.interface';
import { RecoverUserDto } from './dto/recover-user.dto';
import { cipher, decipher } from './secure/cipher';
import { mkdirSync, openSync, appendFileSync } from 'fs';

@Injectable()
export class UsersService {
Expand Down Expand Up @@ -76,23 +76,27 @@ export class UsersService {
const url = `${frontendUrl}/recovery/${recoverHash}`;

try {
this.mailerService.sendMail({
to: email,
// FIXME: use i18n
subject: 'Ссылка для изменения пароля на runit.hexlet.ru',
template: 'recover',
context: {
url,
},
})
.then((data) => {
if (process.env.NODE_ENV !== "production" && !process.env.TRANSPORT_MAILER_URL) {
const logsDirName = process.env.LOGS_PATH ?? 'logs';
mkdirSync(logsDirName, { recursive: true });
openSync(`${logsDirName}/mail.log`, 'a');
appendFileSync(`${logsDirName}/mail.log`, `${data.message}\n`);
}
});
this.mailerService
.sendMail({
to: email,
// FIXME: use i18n
subject: 'Ссылка для изменения пароля на runit.hexlet.ru',
template: 'recover',
context: {
url,
},
})
.then((data) => {
if (
process.env.NODE_ENV !== 'production' &&
!process.env.TRANSPORT_MAILER_URL
) {
const logsDirName = process.env.LOGS_PATH ?? 'logs';
mkdirSync(logsDirName, { recursive: true });
openSync(`${logsDirName}/mail.log`, 'a');
appendFileSync(`${logsDirName}/mail.log`, `${data.message}\n`);
}
});
} catch (e) {
throw new Error(e);
}
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/components/ActionsToolbar/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useSelector } from 'react-redux';
import {
DistributeHorizontal,
DistributeVertical,
} from 'react-bootstrap-icons';

function DisplayIconView() {
const { direction } = useSelector((state) => state.editor);
switch (direction) {
case 'horizontal':
return <DistributeHorizontal />;
case 'vertical':
return <DistributeVertical />;
default:
return <DistributeHorizontal />;
}
}

export default DisplayIconView;
22 changes: 20 additions & 2 deletions frontend/src/pages/snippet/ActionsToolbar.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { useTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';

import Button from 'react-bootstrap/Button';
import Col from 'react-bootstrap/Col';
import { BoxArrowUp, Files, PlayFill } from 'react-bootstrap-icons';
import { actions } from '../../slices';
import { useAuth, useRunButton } from '../../hooks';
import DisplayIconView from '../../components/ActionsToolbar/index.jsx';

function ActionsToolbar({ snippet }) {
const { t } = useTranslation();
Expand All @@ -14,7 +15,7 @@ function ActionsToolbar({ snippet }) {
const { snippetData, code } = snippet;
const { name: snippetName, ownerUsername } = snippetData;
const { isLoggedIn } = useAuth();

const { direction } = useSelector((state) => state.editor);
const handleShare = () => {
dispatch(
actions.openModal({
Expand Down Expand Up @@ -49,8 +50,25 @@ function ActionsToolbar({ snippet }) {
}
};

const handleView = () => {
if (direction === 'horizontal') {
dispatch(actions.updateDirection('vertical'));
return;
}
if (direction === 'vertical') {
dispatch(actions.updateDirection('horizontal'));
}
};

return (
<Col className="toolbar">
<Button
className="btn-icon-only-full-height d-none d-md-inline-block"
onClick={handleView}
variant="nofill-body"
>
<DisplayIconView />
</Button>
<Button
className="btn-icon-only-full-height"
onClick={handleDuplicate}
Expand Down
14 changes: 10 additions & 4 deletions frontend/src/pages/snippet/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function ResizeHandler({ direction = 'horizontal' }) {

function SnippetPage() {
const { isLoggedIn } = useAuth();
const { isAllSaved, isReady, code, hasSnippetData, snippetData } =
const { isAllSaved, isReady, code, hasSnippetData, snippetData, direction } =
useSelector((state) => state.editor);
const snippetApi = useSnippets();
const params = useParams();
Expand Down Expand Up @@ -67,9 +67,15 @@ function SnippetPage() {

const debouncedValue = useDebounce(code, AUTOSAVE_TIMEOUT);

const direction = useMediaQuery('(min-width: 768px)')
? 'horizontal'
: 'vertical';
const isNotMobile = useMediaQuery('(min-width: 768px)');

useEffect(() => {
if (isNotMobile) {
dispatch(actions.updateDirection('horizontal'));
} else {
dispatch(actions.updateDirection('vertical'));
}
}, [dispatch, isNotMobile]);

useEffect(() => {
const editorData = editorDataRef.current;
Expand Down
18 changes: 18 additions & 0 deletions frontend/src/slices/editorSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const initialState = {
code: DEFAULT_CODE,
savedCode: DEFAULT_CODE,
isAllSaved: true,
direction: 'horizontal',
isNotMobile: false,
};

const editorSlice = createSlice({
Expand Down Expand Up @@ -49,6 +51,22 @@ const editorSlice = createSlice({
const code = payload ?? DEFAULT_CODE;
return { ...initialState, code };
},
updateDirection(state, { payload }) {
const direction = payload;
switch (direction) {
case 'vertical':
state.direction = 'vertical';
break;
case 'horizontal':
state.direction = 'horizontal';
break;
default:
state.direction = 'horizontal';
}
},
updateIsNotMobile(state, { payload }) {
state.isNotMobile = payload;
},
},
});

Expand Down
Loading