Переглянути джерело

Merged with feature 633

feature/646
Djordje Mitrovic 3 роки тому
джерело
коміт
a4489664b2

+ 2
- 0
.gitignore Переглянути файл

@@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

/.idea

+ 6
- 0
src/AppRoutes.js Переглянути файл

@@ -4,6 +4,7 @@ import { Redirect, Route, Switch } from "react-router-dom";

import {
LOGIN_PAGE,
ADMIN_LOGIN_PAGE,
HOME_PAGE,
NOT_FOUND_PAGE,
ERROR_PAGE,
@@ -21,9 +22,11 @@ import {
MY_OFFERS_PAGE,
// PRICES_PAGE,
ABOUT_PAGE,
ADMIN_HOME_PAGE,
// POLICY_PRIVACY_PAGE,
} from "./constants/pages";
import LoginPage from "./pages/LoginPage/LoginPage";
import AdminLoginPage from "./pages/AdminLoginPage/AdminLoginPage";
import HomePage from "./pages/HomePage/HomePageMUI";
import NotFoundPage from "./pages/ErrorPages/NotFoundPage";
import ErrorPage from "./pages/ErrorPages/ErrorPage";
@@ -42,6 +45,7 @@ import MyOffers from "./pages/MyOffers/MyOffers";
// import PricesPage from "./pages/Prices/PricesPage";
import AboutPage from "./pages/About/AboutPage";
import AuthRoute from "./components/Router/AuthRoute";
import AdminHomePage from "./pages/AdminHomePage/AdminHomePage";
// import PrivacyPolicyPage from "./pages/PrivacyPolicy/PrivacyPolicyPage";

const AppRoutes = () => {
@@ -49,6 +53,8 @@ const AppRoutes = () => {
<Switch>
<Route exact path={BASE_PAGE} component={HomePage} />
<AuthRoute exact path={LOGIN_PAGE} component={LoginPage} />
<AuthRoute exact path={ADMIN_LOGIN_PAGE} component={AdminLoginPage} />
<Route path={ADMIN_HOME_PAGE} component={AdminHomePage} />
<Route path={NOT_FOUND_PAGE} component={NotFoundPage} />
<Route path={ERROR_PAGE} component={ErrorPage} />
<AuthRoute path={REGISTER_SUCCESSFUL_PAGE} component={RegisterSuccessful} />

+ 7
- 0
src/assets/images/svg/logo-vertical-admin.svg
Різницю між файлами не показано, бо вона завелика
Переглянути файл


+ 3
- 2
src/components/Login/Description/LoginDescription.js Переглянути файл

@@ -3,17 +3,18 @@ import PropTypes from "prop-types";
import { LoginDescription as Description } from "./LoginDescription.styled";
import { useTranslation } from "react-i18next";

const LoginDescription = () => {
const LoginDescription = (props) => {
const { t } = useTranslation();
return (
<Description component="h1" variant="h6">
{t("login.welcomeText")}
{props.isAdmin?t("admin.login.welcomeText"):t("login.welcomeText")}
</Description>
);
};

LoginDescription.propTypes = {
children: PropTypes.node,
isAdmin: PropTypes.bool
};

export default LoginDescription;

+ 18
- 7
src/components/Login/Login.js Переглянути файл

@@ -8,8 +8,9 @@ import {
fetchLogin,
} from "../../store/actions/login/loginActions";
import { selectLoginError } from "../../store/selectors/loginSelectors";
import { HOME_PAGE } from "../../constants/pages";
import { HOME_PAGE, ADMIN_HOME_PAGE } from "../../constants/pages";
import { ReactComponent as Logo } from "../../assets/images/svg/logo-vertical.svg";
import { ReactComponent as LogoAdmin } from "../../assets/images/svg/logo-vertical-admin.svg";
import { LoginPageContainer, LoginFormContainer } from "./Login.styled";
import loginValidation from "../../validations/loginValidation";
import loginInitialValues from "../../initialValues/loginInitialValues";
@@ -22,7 +23,7 @@ import ForgotPasswordLink from "./ForgotPasswordLink/ForgotPasswordLink";
import LoginButton from "./LoginButton/LoginButton";
import RegisterLink from "./RegisterLink/RegisterLink";

const Login = () => {
const Login = (props) => {
const dispatch = useDispatch();
const error = useSelector(selectLoginError);
const history = useHistory();
@@ -36,6 +37,12 @@ const Login = () => {

// Api response callback function on success
const handleApiResponseSuccess = () => {
props.isAdmin ? history.push({
pathname: ADMIN_HOME_PAGE,
state: {
from: history.location.pathname,
},
}) :
history.push({
pathname: HOME_PAGE,
state: {
@@ -75,6 +82,7 @@ const Login = () => {
password,
handleApiResponseSuccess,
handleApiResponseError,
isAdmin: props.isAdmin
})
);
}
@@ -103,16 +111,18 @@ const Login = () => {

return (
<LoginPageContainer>
<Logo />
<LoginTitle />
<LoginDescription />
{
props.isAdmin ? <LogoAdmin/> : <Logo/>
}
<LoginTitle isAdmin={props.isAdmin} />
<LoginDescription isAdmin={props.isAdmin}/>
<LoginFormContainer component="form" onSubmit={handleSubmitForm}>
<EmailField formik={formik} />
<PasswordField formik={formik} ref={passwordRef} />
<ErrorMessage formik={formik} />
<ForgotPasswordLink />
{!props.isAdmin ? <ForgotPasswordLink/>:<></>}
<LoginButton formik={formik} />
<RegisterLink />
{!props.isAdmin ? <RegisterLink/>:<></>}
</LoginFormContainer>
</LoginPageContainer>
);
@@ -126,5 +136,6 @@ Login.propTypes = {
pathname: PropTypes.string,
}),
}),
isAdmin: PropTypes.bool
};
export default Login;

+ 5
- 2
src/components/Login/Title/LoginTitle.js Переглянути файл

@@ -3,17 +3,20 @@ import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
import { LoginTitle as Title } from "./LoginTitle.styled";

const LoginTitle = () => {
const LoginTitle = (props) => {
const { t } = useTranslation();
return (
<Title component="h1" variant="h5">
{t("login.logInTitle")}
{
props.isAdmin ? t("admin.login.logInTitle") : t("login.logInTitle")
}
</Title>
);
};

LoginTitle.propTypes = {
children: PropTypes.node,
isAdmin: PropTypes.bool
};

export default LoginTitle;

+ 2
- 0
src/constants/pages.js Переглянути файл

@@ -1,6 +1,7 @@
export const BASE_PAGE = '/';
export const LOGIN_PAGE = '/login';
export const FORGOT_PASSWORD_PAGE = '/forgot-password';
export const ADMIN_LOGIN_PAGE = '/admin/login';
export const HOME_PAGE = '/home';
export const ERROR_PAGE = '/error-page';
export const NOT_FOUND_PAGE = '/not-found';
@@ -17,3 +18,4 @@ export const MY_OFFERS_PAGE = "/myoffers"
export const ABOUT_PAGE = "/about";
export const PRICES_PAGE = "/prices";
export const POLICY_PRIVACY_PAGE = "/policy";
export const ADMIN_HOME_PAGE = "/admin/home";

+ 18
- 0
src/i18n/resources/rs.js Переглянути файл

@@ -407,4 +407,22 @@ export default {
imagesReview: "Pregled fotografija",
offer: "Proizvod:",
},
admin: {
login:{
welcome: "React template",
welcomeText: "Trampa sa kolegama na dohvat ruke",
emailFormat: "Nevalidan format email adrese!",
emailRequired: "Email adresa je obavezna!",
noUsers: "Ne postoji korisnik sa zadatom email adresom.",
passwordStrength: "Your password is {{strength}}.",
passwordLength: "Lozinka mora imati najmanje 8 karaktera!",
email: "Unesite email adresu kako biste se prijavili",
logInTitle: "Uloguj se",
logIn: "Uloguj se",
usernameRequired: "Username je obavezan!",
passwordRequired: "Lozinka je obavezna!",
wrongCredentials: "Pogrešan mail ili lozinka!",
headerTitle: "Ulogujte se",
}
}
};

+ 14
- 0
src/pages/AdminHomePage/AdminHomePage.js Переглянути файл

@@ -0,0 +1,14 @@
import React from 'react'
import PropTypes from 'prop-types'

const AdminHomePage = () => {
return (
<div>Admin home page brateee</div>
)
}

AdminHomePage.propTypes = {
children: PropTypes.node,
}

export default AdminHomePage

+ 15
- 0
src/pages/AdminLoginPage/AdminLoginPage.js Переглянути файл

@@ -0,0 +1,15 @@
import React from 'react'
import PropTypes from 'prop-types'
import Login from '../../components/Login/Login'

const LoginPage = () => {
return (
<Login isAdmin/>
)
}

LoginPage.propTypes = {
children: PropTypes.node,
}

export default LoginPage

+ 1
- 1
src/pages/LoginPage/LoginPage.js Переглянути файл

@@ -4,7 +4,7 @@ import Login from '../../components/Login/Login'

const LoginPage = () => {
return (
<Login />
<Login isAdmin={false}/>
)
}


+ 8
- 0
src/store/saga/loginSaga.js Переглянути файл

@@ -39,12 +39,17 @@ import { clearChat } from "../actions/chat/chatActions";

function* fetchLogin({ payload }) {
try {
const isAdmin = payload.isAdmin;
// delete payload.isAdmin
const { data } = yield call(attemptLogin, payload);
if (data.token) {
const token = data.token;
const refresh = data.refresh;
const tokenDecoded = jwt.decode(token);
const refreshDecoded = jwt.decode(refresh);
if(isAdmin && !tokenDecoded.roles.includes("Admin")){
throw Error("Not an admin login on /login");
}
const accessToken = {
token: token,
exp: tokenDecoded.exp,
@@ -65,6 +70,9 @@ function* fetchLogin({ payload }) {
}
}
} catch (e) {
if(e.message){
yield put(fetchUserError(e.message));
}
if (e.response && e.response.data) {
if (payload.handleApiResponseError) {
yield call(payload.handleApiResponseError, e.response.status);

+ 1
- 0
src/util/helpers/routeHelpers.js Переглянути файл

@@ -1,4 +1,5 @@
import {
ADMIN_LOGIN_PAGE,
FORGOT_PASSWORD_MAIL_SENT,
FORGOT_PASSWORD_PAGE,
LOGIN_PAGE,

Завантаження…
Відмінити
Зберегти