1
0
Fork 0
mirror of https://github.com/muerwre/vault-frontend.git synced 2025-04-25 04:46:40 +07:00

random titles

This commit is contained in:
Fedor Katurov 2019-11-13 15:09:05 +07:00
parent 7583a57b04
commit 9233ccbada
10 changed files with 63 additions and 11 deletions

View file

@ -3,6 +3,7 @@ import { INotification, NOTIFICATION_TYPES } from '~/redux/types';
import styles from './styles.scss';
import { NotificationMessage } from '../NotificationMessage';
import { Icon } from '~/components/input/Icon';
import { getRandomPhrase } from '~/constants/phrases';
interface IProps {
notifications: INotification[];
@ -14,13 +15,15 @@ const NOTIFICATION_RENDERERS = {
};
const NotificationBubble: FC<IProps> = ({ notifications, onClick }) => {
const placeholder = getRandomPhrase('NOTHING_HERE');
return (
<div className={styles.wrap}>
<div className={styles.list}>
{notifications.length === 0 && (
<div className={styles.placeholder}>
<Icon icon="bell_ring" />
<div>НЕТ УВЕДОМЛЕНИЙ</div>
<div>{placeholder}</div>
</div>
)}
{notifications.length > 0 &&

View file

@ -87,6 +87,10 @@ $notification_color: darken($content_bg, 2%);
flex-direction: column;
text-transform: uppercase;
font: $font_16_semibold;
box-sizing: border-box;
padding: 80px;
text-align: center;
line-height: 1.6em;
svg {
width: 120px;

View file

@ -5,6 +5,7 @@ import styles from './styles.scss';
import { connect } from 'react-redux';
import { selectAuthProfile } from '~/redux/auth/selectors';
import { ProfileLoader } from '~/containers/profile/ProfileLoader';
import { Group } from '~/components/containers/Group';
const mapStateToProps = state => ({
profile: selectAuthProfile(state),
@ -18,7 +19,7 @@ const ProfileDescriptionUnconnected: FC<IProps> = ({ profile: { user, is_loading
return (
<div className={styles.wrap}>
{user.description && (
<div
<Group
className={styles.content}
dangerouslySetInnerHTML={{ __html: formatText(user.description) }}
/>

View file

@ -3,6 +3,7 @@
min-height: 200px;
display: flex;
box-sizing: border-box;
flex-direction: column;
}
.placeholder {

14
src/constants/phrases.ts Normal file
View file

@ -0,0 +1,14 @@
import { useMemo } from 'react';
export const PHRASES = {
BORIS_TITLE: ['Снова вместе', 'Я видел это во сне', 'Что тут у нас?'],
NOTHING_HERE: [
'Тут пусто и одиноко',
'Совсем ничего',
'Хм... Где все?',
'Тут будут наши с тобой сообщения',
],
};
export const getRandomPhrase = (key: keyof typeof PHRASES) =>
useMemo(() => PHRASES[key][Math.floor(Math.random() * PHRASES[key].length)], []);

View file

@ -10,6 +10,7 @@ import { CommentForm } from '~/components/node/CommentForm';
import { Group } from '~/components/containers/Group';
import boris from '~/sprites/boris_robot.svg';
import { NodeNoComments } from '~/components/node/NodeNoComments';
import { getRandomPhrase } from '~/constants/phrases';
const mapStateToProps = state => ({
node: selectNode(state),
@ -36,6 +37,8 @@ const BorisLayoutUnconnected: FC<IProps> = ({
user: { is_user },
nodeLoadNode,
}) => {
const title = getRandomPhrase('BORIS_TITLE');
useEffect(() => {
if (is_loading) return;
nodeLoadNode(id, 'DESC');
@ -47,8 +50,7 @@ const BorisLayoutUnconnected: FC<IProps> = ({
<div className={styles.image}>
<div className={styles.caption}>
<div>СНОВА</div>
<div>ВМЕСТЕ</div>
<div className={styles.caption_text}>{title}</div>
</div>
<img src={boris} />
</div>

View file

@ -129,3 +129,8 @@
font-size: 48px;
}
}
.caption_text {
max-width: 400px;
text-transform: uppercase;
}

View file

@ -60,3 +60,9 @@ export const apiAuthGetUpdates = ({
.get(API.USER.GET_UPDATES, configWithToken(access, { params: { exclude_dialogs, last } }))
.then(resultMiddleware)
.catch(errorMiddleware);
export const apiUpdateUser = ({ access, user }): Promise<IResultWithStatus<{ user: IUser }>> =>
api
.patch(API.USER.ME, { user }, configWithToken(access))
.then(resultMiddleware)
.catch(errorMiddleware);

View file

@ -12,6 +12,7 @@ import {
authSendMessage,
authSetUpdates,
authLoggedIn,
authSetLastSeenMessages,
} from '~/redux/auth/actions';
import {
apiUserLogin,
@ -20,6 +21,7 @@ import {
apiAuthGetUserMessages,
apiAuthSendMessage,
apiAuthGetUpdates,
apiUpdateUser,
} from '~/redux/auth/api';
import { modalSetShown, modalShowDialog } from '~/redux/modal/actions';
import { selectToken, selectAuthProfile, selectAuthUser, selectAuthUpdates } from './selectors';
@ -248,15 +250,25 @@ function* startPollingSaga() {
}
}
function* setLastSeenMessages({ last_seen_messages }: ReturnType<typeof authSetLastSeenMessages>) {
if (!Date.parse(last_seen_messages)) return;
const { data, error } = yield call(reqWrapper, apiUpdateUser, { user: { last_seen_messages } });
console.log({ data, error });
}
function* authSaga() {
yield takeLatest(REHYDRATE, checkUserSaga);
yield takeLatest([REHYDRATE, AUTH_USER_ACTIONS.LOGGED_IN], startPollingSaga);
yield takeLatest(AUTH_USER_ACTIONS.LOGOUT, logoutSaga);
yield takeLatest(AUTH_USER_ACTIONS.SEND_LOGIN_REQUEST, sendLoginRequestSaga);
yield takeLatest(AUTH_USER_ACTIONS.GOT_AUTH_POST_MESSAGE, gotPostMessageSaga);
yield takeLatest(AUTH_USER_ACTIONS.OPEN_PROFILE, openProfile);
yield takeLatest(AUTH_USER_ACTIONS.GET_MESSAGES, getMessages);
yield takeLatest(AUTH_USER_ACTIONS.SEND_MESSAGE, sendMessage);
yield takeLatest([REHYDRATE, AUTH_USER_ACTIONS.LOGGED_IN], startPollingSaga);
yield takeLatest(AUTH_USER_ACTIONS.SET_LAST_SEEN_MESSAGES, setLastSeenMessages);
}
export default authSaga;

View file

@ -1,18 +1,21 @@
import isValid from 'date-fns/isValid';
import { IMAGE_MIME_TYPES } from '~/utils/uploader';
const isValidEmail = (email: string): boolean => !!email
&& String(email)
&& !!String(email).match(
const isValidEmail = (email: string): boolean =>
!!email &&
String(email) &&
!!String(email).match(
/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/
);
const isLikeEmail = (email: string): boolean => !!email && String(email) && !!String(email).match(/^([^\@]+)@([^\@]+)\.([^\@]+)$$/);
const isLikeEmail = (email: string): boolean =>
!!email && String(email) && !!String(email).match(/^([^\@]+)@([^\@]+)\.([^\@]+)$$/);
const isNonEmpty = (value: string): boolean => !!value && value.trim().length > 0;
const isLikePhone = isNonEmpty;
const isAtLeast = (length: number, value: string): boolean => !!value && value.trim().length >= length;
const isAtLeast = (length: number, value: string): boolean =>
!!value && value.trim().length >= length;
const isMimeOfImage = (mime): boolean => !!mime && IMAGE_MIME_TYPES.indexOf(mime) >= 0;
@ -28,5 +31,6 @@ export const VALIDATORS = {
IS_IMAGE_MIME: isMimeOfImage,
IS_DATE: isDate,
IS_STRINGY_DATE: isStringDate,
EVOLVE: (validator: (val: any) => boolean, error: string) => (val: any) => (!val || !validator(val) ? error : null)
EVOLVE: (validator: (val: any) => boolean, error: string) => (val: any) =>
!val || !validator(val) ? error : null,
};