File clean up. Refactor header.
This commit is contained in:
@@ -5165,6 +5165,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>manageroot</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>profile</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -5304,6 +5325,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>photourl</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
</children>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"short_name": "Bodyshop",
|
||||
"short_name": "Bodyshop.app",
|
||||
"name": "Bodyshop Management System",
|
||||
"description": "The ultimate bodyshop management system",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
@@ -20,6 +21,6 @@
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#002366",
|
||||
"background_color": "#000000"
|
||||
"theme_color": "#fff",
|
||||
"background_color": "#fff"
|
||||
}
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
import { Avatar, Col, Dropdown, Icon, Menu, Row } from "antd";
|
||||
import i18next from "i18next";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import UserImage from "../../assets/User.svg";
|
||||
import { setUserLanguage, signOutStart } from "../../redux/user/user.actions";
|
||||
import { selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import SignOut from "../sign-out/sign-out.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
signOutStart: () => dispatch(signOutStart()),
|
||||
setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(function CurrentUserDropdown({ currentUser, signOutStart, setUserLanguage }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleMenuClick = e => {
|
||||
if (e.item.props.actiontype === "lang-select") {
|
||||
i18next.changeLanguage(e.key, (err, t) => {
|
||||
if (err)
|
||||
return console.log("Error encountered when changing languages.", err);
|
||||
setUserLanguage(e.key);
|
||||
console.log("clicking");
|
||||
});
|
||||
}
|
||||
};
|
||||
const menu = (
|
||||
<Menu mode="vertical" onClick={handleMenuClick}>
|
||||
<Menu.Item>
|
||||
<SignOut signOutStart={signOutStart} />
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<Link to="/manage/profile"> {t("menus.currentuser.profile")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<Icon type="global" />
|
||||
<span>{t("menus.currentuser.languageselector")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item actiontype="lang-select" key="en_us">
|
||||
{t("general.languages.english")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="fr">
|
||||
{t("general.languages.french")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="es">
|
||||
{t("general.languages.spanish")}
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dropdown overlay={menu}>
|
||||
<Row>
|
||||
<Col span={8}>
|
||||
<Avatar size="large" alt="Avatar" src={UserImage} />
|
||||
</Col>
|
||||
<Col span={16} style={{ color: "white" }}>
|
||||
{currentUser.displayName || t("general.labels.unknown")}
|
||||
</Col>
|
||||
</Row>
|
||||
</Dropdown>
|
||||
);
|
||||
});
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
export default function FooterComponent() {
|
||||
return (
|
||||
<Row>
|
||||
<Col span={8} offset={9}>
|
||||
<Col span={8} offset={8}>
|
||||
Copyright Snapt Software 2019. All rights reserved.
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
import React from "react";
|
||||
// import { Icon, Button, Input, AutoComplete } from "antd";
|
||||
|
||||
// const { Option } = AutoComplete;
|
||||
|
||||
// function onSelect(value) {
|
||||
// console.log("onSelect", value);
|
||||
// }
|
||||
|
||||
// function getRandomInt(max, min = 0) {
|
||||
// return Math.floor(Math.random() * (max - min + 1)) + min; // eslint-disable-line no-mixed-operators
|
||||
// }
|
||||
|
||||
// function searchResult(query) {
|
||||
// return new Array(getRandomInt(5))
|
||||
// .join(".")
|
||||
// .split(".")
|
||||
// .map((item, idx) => ({
|
||||
// query,
|
||||
// category: `${query}${idx}`,
|
||||
// count: getRandomInt(200, 100)
|
||||
// }));
|
||||
// }
|
||||
|
||||
// function renderOption(item) {
|
||||
// return (
|
||||
// <Option key={item.category} text={item.category}>
|
||||
// <div className='global-search-item'>
|
||||
// <span className='global-search-item-desc'>
|
||||
// Found {item.query} on
|
||||
// <a
|
||||
// href={`https://s.taobao.com/search?q=${item.query}`}
|
||||
// target='_blank'
|
||||
// rel='noopener noreferrer'>
|
||||
// {item.category}
|
||||
// </a>
|
||||
// </span>
|
||||
// <span className='global-search-item-count'>{item.count} results</span>
|
||||
// </div>
|
||||
// </Option>
|
||||
// );
|
||||
// }
|
||||
|
||||
export default class GlobalSearch extends React.Component {
|
||||
state = {
|
||||
dataSource: []
|
||||
};
|
||||
|
||||
// handleSearch = value => {
|
||||
// this.setState({
|
||||
// dataSource: value ? searchResult(value) : []
|
||||
// });
|
||||
// };
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div />
|
||||
// <div style={{ width: 300 }}>
|
||||
// <AutoComplete
|
||||
// size="large"
|
||||
// style={{ width: "100%" }}
|
||||
// dataSource={dataSource.map(renderOption)}
|
||||
// onSelect={onSelect}
|
||||
// onSearch={this.handleSearch}
|
||||
// placeholder="input here"
|
||||
// optionLabelProp="text"
|
||||
// >
|
||||
// <Input
|
||||
// suffix={
|
||||
// <Button style={{ marginRight: -12 }} size="large" type="primary">
|
||||
// <Icon type="search" />
|
||||
// </Button>
|
||||
// }
|
||||
// />
|
||||
// </AutoComplete>
|
||||
// </div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,35 @@
|
||||
import { Col, Icon, Menu, Row } from "antd";
|
||||
import { Avatar, Col, Icon, Menu, Row } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import CurrentUserDropdown from "../current-user-dropdown/current-user-dropdown.component";
|
||||
import GlobalSearch from "../global-search/global-search.component";
|
||||
import UserImage from "../../assets/User.svg";
|
||||
import { signOutStart } from "../../redux/user/user.actions";
|
||||
import ManageSignInButton from "../manage-sign-in-button/manage-sign-in-button.component";
|
||||
|
||||
export default ({ landingHeader, selectedNavItem }) => {
|
||||
export default ({
|
||||
landingHeader,
|
||||
selectedNavItem,
|
||||
logo,
|
||||
handleMenuClick,
|
||||
currentUser
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
//TODO Add
|
||||
return (
|
||||
<Row type="flex" justify="space-around">
|
||||
<Col span={16}>
|
||||
<Row type="flex" justify="space-around" align="middle">
|
||||
{logo ? (
|
||||
<Col span={4}>
|
||||
<img alt="Shop Logo" src={logo} style={{ height: "40px" }} />
|
||||
</Col>
|
||||
) : null}
|
||||
<Col span={14}>
|
||||
<Menu
|
||||
theme="dark"
|
||||
className="header"
|
||||
selectedKeys={selectedNavItem}
|
||||
mode="horizontal"
|
||||
onClick={handleMenuClick}
|
||||
>
|
||||
<Menu.Item>
|
||||
<GlobalSearch />
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item key="home">
|
||||
<Link to="/manage">
|
||||
<Icon type="home" />
|
||||
@@ -64,16 +72,47 @@ export default ({ landingHeader, selectedNavItem }) => {
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
|
||||
{!landingHeader ? null : (
|
||||
<Menu.Item>
|
||||
<ManageSignInButton />
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<div>
|
||||
<Avatar
|
||||
size="medium"
|
||||
alt="Avatar"
|
||||
src={currentUser.photoURL ? currentUser.photoURL : UserImage}
|
||||
style={{ margin: "10px" }}
|
||||
/>
|
||||
{currentUser.displayName || t("general.labels.unknown")}
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Menu.Item onClick={signOutStart()}>
|
||||
{t("user.actions.signout")}
|
||||
</Menu.Item>
|
||||
)}
|
||||
<Menu.Item>
|
||||
<Link to="/manage/profile">{t("menus.currentuser.profile")}</Link>
|
||||
</Menu.Item>
|
||||
<Menu.SubMenu
|
||||
title={
|
||||
<span>
|
||||
<Icon type="global" />
|
||||
<span>{t("menus.currentuser.languageselector")}</span>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Menu.Item actiontype="lang-select" key="en_us">
|
||||
{t("general.languages.english")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="fr">
|
||||
{t("general.languages.french")}
|
||||
</Menu.Item>
|
||||
<Menu.Item actiontype="lang-select" key="es">
|
||||
{t("general.languages.spanish")}
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
</Col>
|
||||
<Col span={6} offset={2}>
|
||||
{!landingHeader ? <CurrentUserDropdown /> : null}
|
||||
</Col>
|
||||
<Col span={4}>{!landingHeader ? null : <ManageSignInButton />}</Col>
|
||||
</Row>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,52 @@
|
||||
import React from "react";
|
||||
import HeaderComponent from "./header.component";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import i18next from "i18next";
|
||||
import { setUserLanguage, signOutStart } from "../../redux/user/user.actions";
|
||||
import {
|
||||
selectCurrentUser,
|
||||
selectBodyshop
|
||||
} from "../../redux/user/user.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
signOutStart: () => dispatch(signOutStart()),
|
||||
setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(function HeaderContainer({
|
||||
landingHeader,
|
||||
currentUser,
|
||||
bodyshop,
|
||||
signOutStart,
|
||||
setUserLanguage
|
||||
}) {
|
||||
const handleMenuClick = e => {
|
||||
if (e.item.props.actiontype === "lang-select") {
|
||||
i18next.changeLanguage(e.key, (err, t) => {
|
||||
if (err)
|
||||
return console.log("Error encountered when changing languages.", err);
|
||||
setUserLanguage(e.key);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default ({ landingHeader, signedIn }) => {
|
||||
return (
|
||||
<HeaderComponent landingHeader={landingHeader} selectedNavItem={null} />
|
||||
<HeaderComponent
|
||||
handleMenuClick={handleMenuClick}
|
||||
signOutStart={signOutStart}
|
||||
landingHeader={landingHeader}
|
||||
selectedNavItem={null}
|
||||
currentUser={currentUser}
|
||||
logo={bodyshop ? bodyshop.logo_img_path : null}
|
||||
/>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
@@ -37,7 +37,10 @@ export default connect(
|
||||
}
|
||||
if (!err) {
|
||||
console.log("values", values);
|
||||
updateUserDetails({ displayName: values.displayname });
|
||||
updateUserDetails({
|
||||
displayName: values.displayname,
|
||||
photoURL: values.photoURL
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -59,6 +62,12 @@ export default connect(
|
||||
rules: [{ required: true }]
|
||||
})(<Input name="displayname" />)}
|
||||
</Form.Item>
|
||||
<Form.Item label={t("user.fields.photourl")}>
|
||||
{getFieldDecorator("photoURL", {
|
||||
initialValue: currentUser.photoURL
|
||||
})(<Input name="photoURL" />)}
|
||||
</Form.Item>
|
||||
|
||||
<Button
|
||||
type="primary"
|
||||
key="submit"
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export default function SignoutComponent({ signOutStart }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return <div onClick={signOutStart}>{t("user.actions.signout")}</div>;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
export default WithInlineEdit = WrappedComponent => props => {
|
||||
const [editing, setEditing] = useState(false);
|
||||
const [modified, setModified] = useState(false);
|
||||
const [originalValue, setOriginalValue] = useState(null);
|
||||
|
||||
const toggleEdit = () => {
|
||||
setEditing(!editing);
|
||||
|
||||
if (editing) {
|
||||
this.input.focus();
|
||||
}
|
||||
};
|
||||
|
||||
return editing ? (
|
||||
<Form.Item style={{ margin: 0 }}>
|
||||
{form.getFieldDecorator(dataIndex, {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: `${title} is required.`
|
||||
}
|
||||
],
|
||||
initialValue: record[dataIndex]
|
||||
})(
|
||||
<Input
|
||||
ref={node => (this.input = node)}
|
||||
onPressEnter={this.save}
|
||||
onBlur={this.save}
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
) : (
|
||||
<div
|
||||
className="editable-cell-value-wrap"
|
||||
style={{ paddingRight: 24 }}
|
||||
onClick={toggleEdit}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WithInlineEdit;
|
||||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 8.0 KiB |
@@ -1,8 +1,11 @@
|
||||
import React from 'react'
|
||||
import ManageRootPageComponent from './manage-root.page.component'
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
import ManageRootPageComponent from "./manage-root.page.component";
|
||||
import { useTranslation } from "react-i18next";
|
||||
export default function ManageRootPageContainer() {
|
||||
return (
|
||||
<ManageRootPageComponent />
|
||||
)
|
||||
const { t } = useTranslation();
|
||||
useEffect(() => {
|
||||
document.title = t("titles.manageroot");
|
||||
}, [t]);
|
||||
|
||||
return <ManageRootPageComponent />;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import HeaderContainer from "../../components/header/header.container";
|
||||
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
||||
import "./manage.page.styles.scss";
|
||||
|
||||
|
||||
const ManageRootPage = lazy(() =>
|
||||
import("../manage-root/manage-root.page.container")
|
||||
);
|
||||
|
||||
@@ -34,6 +34,7 @@ export function* signInWithEmail({ payload: { email, password } }) {
|
||||
uid: user.uid,
|
||||
email: user.email,
|
||||
displayName: user.displayName,
|
||||
photoURL: user.photoURL,
|
||||
authorized: true
|
||||
})
|
||||
);
|
||||
@@ -62,6 +63,7 @@ export function* isUserAuthenticated() {
|
||||
uid: user.uid,
|
||||
email: user.email,
|
||||
displayName: user.displayName,
|
||||
photoURL: user.photoURL,
|
||||
authorized: true
|
||||
})
|
||||
);
|
||||
|
||||
@@ -327,6 +327,7 @@
|
||||
"jobsavailable": "Available Jobs | $t(titles.app)",
|
||||
"jobsdetail": "Job {{ro_number}} | $t(titles.app)",
|
||||
"jobsdocuments": "Job Documents {{ro_number}} | $t(titles.app)",
|
||||
"manageroot": "Home | $t(titles.app)",
|
||||
"profile": "My Profile | $t(titles.app)",
|
||||
"schedule": "Schedule | $t(titles.app)",
|
||||
"vehicledetail": "Vehicle Details {{vehicle}} | $t(titles.app)"
|
||||
@@ -337,7 +338,8 @@
|
||||
"updateprofile": "Update Profile"
|
||||
},
|
||||
"fields": {
|
||||
"displayname": "Display Name"
|
||||
"displayname": "Display Name",
|
||||
"photourl": "Avatar URL"
|
||||
}
|
||||
},
|
||||
"vehicles": {
|
||||
|
||||
@@ -327,6 +327,7 @@
|
||||
"jobsavailable": "Empleos disponibles | $t(titles.app)",
|
||||
"jobsdetail": "Trabajo {{ro_number}} | $t(titles.app)",
|
||||
"jobsdocuments": "Documentos de trabajo {{ro_number}} | $ t (títulos.app)",
|
||||
"manageroot": "Casa | $t(titles.app)",
|
||||
"profile": "Mi perfil | $t(titles.app)",
|
||||
"schedule": "Horario | $t(titles.app)",
|
||||
"vehicledetail": "Detalles del vehículo {{vehicle}} | $t(titles.app)"
|
||||
@@ -337,7 +338,8 @@
|
||||
"updateprofile": "Actualización del perfil"
|
||||
},
|
||||
"fields": {
|
||||
"displayname": "Nombre para mostrar"
|
||||
"displayname": "Nombre para mostrar",
|
||||
"photourl": "URL de avatar"
|
||||
}
|
||||
},
|
||||
"vehicles": {
|
||||
|
||||
@@ -327,6 +327,7 @@
|
||||
"jobsavailable": "Emplois disponibles | $t(titles.app)",
|
||||
"jobsdetail": "Travail {{ro_number}} | $t(titles.app)",
|
||||
"jobsdocuments": "Documents de travail {{ro_number}} | $ t (titres.app)",
|
||||
"manageroot": "Accueil | $t(titles.app)",
|
||||
"profile": "Mon profil | $t(titles.app)",
|
||||
"schedule": "Horaire | $t(titles.app)",
|
||||
"vehicledetail": "Détails du véhicule {{vehicle} | $t(titles.app)"
|
||||
@@ -337,7 +338,8 @@
|
||||
"updateprofile": "Mettre à jour le profil"
|
||||
},
|
||||
"fields": {
|
||||
"displayname": "Afficher un nom"
|
||||
"displayname": "Afficher un nom",
|
||||
"photourl": "URL de l'avatar"
|
||||
}
|
||||
},
|
||||
"vehicles": {
|
||||
|
||||
Reference in New Issue
Block a user