summaryrefslogtreecommitdiffstats
path: root/client/src/admin
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/admin')
-rw-r--r--client/src/admin/api/logout.js7
-rw-r--r--client/src/admin/context/index.js3
-rw-r--r--client/src/admin/data/translations.js41
-rw-r--r--client/src/admin/hocs/WithHover.jsx18
-rw-r--r--client/src/admin/hocs/WithTranslation.jsx11
-rw-r--r--client/src/admin/hocs/index.js4
-rw-r--r--client/src/admin/jsx/App.jsx32
-rw-r--r--client/src/admin/jsx/Info.jsx10
-rw-r--r--client/src/admin/jsx/LangSwitch.jsx42
-rw-r--r--client/src/admin/jsx/MainScreen.jsx10
-rw-r--r--client/src/admin/jsx/TopBar.jsx35
-rw-r--r--client/src/admin/jsx/User.jsx39
-rw-r--r--client/src/admin/scss/_colors.scss5
-rw-r--r--client/src/admin/scss/_forms.scss52
-rw-r--r--client/src/admin/scss/_globals.scss12
-rw-r--r--client/src/admin/scss/_info.scss8
-rw-r--r--client/src/admin/scss/_main.scss16
-rwxr-xr-xclient/src/admin/scss/_reset.scss52
-rw-r--r--client/src/admin/scss/_topBar.scss114
-rw-r--r--client/src/admin/scss/index.scss14
20 files changed, 498 insertions, 27 deletions
diff --git a/client/src/admin/api/logout.js b/client/src/admin/api/logout.js
new file mode 100644
index 0000000..b0a9841
--- /dev/null
+++ b/client/src/admin/api/logout.js
@@ -0,0 +1,7 @@
+export default () => (
+ fetch('/api/user/logout', {
+ method: 'POST',
+ })
+ .then(() => window.location.href = "/")
+ .catch(() => {})
+);
diff --git a/client/src/admin/context/index.js b/client/src/admin/context/index.js
new file mode 100644
index 0000000..6353dc0
--- /dev/null
+++ b/client/src/admin/context/index.js
@@ -0,0 +1,3 @@
+import React from 'react';
+
+export default React.createContext();
diff --git a/client/src/admin/data/translations.js b/client/src/admin/data/translations.js
new file mode 100644
index 0000000..b4c34a2
--- /dev/null
+++ b/client/src/admin/data/translations.js
@@ -0,0 +1,41 @@
+export const defaultLanguage = 'en';
+export const fallbackLanguage = 'en';
+export const translations = {
+ "en": {
+ "main-title": "Website Manager",
+ "login-to-admin": "Login to Admin Panel",
+ "login-info": "Put your user name and password, then click login button",
+ "login": "Login",
+ "user": "User name",
+ "password": "Password",
+ "no-saved-websites": "You don't have any saved projects, create a new one",
+ "create-new-project": "Create new project",
+ "create-new-project-hover": "Click to create new project",
+ "edit-current-project": "Edit current project",
+ "edit-current-project-hover": "Click to edit current active projecct",
+ "show-saved-projects": "Show saved projects",
+ "show-saved-projects-hover": "Click to show list of all saved projects",
+ "click-to-change-language": "Click to change language in the website manager",
+ "click-to-change-user": "Click to logout or change user password",
+ "logout": "Logout",
+ "click-to-logout": "Click to logout/change current user",
+ "user-settings": "User settings",
+ "click-to-change-user-settings": "Click to change user name, password or to completely remove current user",
+ },
+ "de": {
+ "main-title": "Website Manager",
+ },
+ "es": {
+ "main-title": "Website Manager",
+ },
+ "pl": {
+ "main-title": "Website Manager",
+ "login-to-admin": "Zaloguj do Panelu Administracyjnego",
+ "no-saved-websites": "Nie masz jeszcze żadnych zapisanych projektów, utwórz nowy",
+ "create-new-project": "Utwórz nowy projekt",
+ "edit-current-project": "Edytuj bieżący projekt",
+ "show-saved-projects": "Pokaż zapisane projekty",
+ },
+};
+
+export const languages = Object.keys(translations);
diff --git a/client/src/admin/hocs/WithHover.jsx b/client/src/admin/hocs/WithHover.jsx
new file mode 100644
index 0000000..2a5cdcb
--- /dev/null
+++ b/client/src/admin/hocs/WithHover.jsx
@@ -0,0 +1,18 @@
+import React, {useContext} from 'react';
+import Context from '../context';
+
+
+const WithHover = ({ children, message, classes }) => {
+ const { setHover } = useContext(Context);
+ return (
+ <div
+ onMouseEnter={()=>setHover(message)}
+ onMouseLeave={()=>setHover(null)}
+ className={classes}
+ >
+ {children}
+ </div>
+ )
+};
+
+export default WithHover;
diff --git a/client/src/admin/hocs/WithTranslation.jsx b/client/src/admin/hocs/WithTranslation.jsx
new file mode 100644
index 0000000..b31b7c9
--- /dev/null
+++ b/client/src/admin/hocs/WithTranslation.jsx
@@ -0,0 +1,11 @@
+import React, {useContext} from 'react';
+import Context from '../context';
+import { translations, fallbackLanguage } from '../data/translations';
+
+const WithTranslation = (key) => {
+ const { lang } = useContext(Context);
+
+ return translations[lang][key] || translations[fallbackLanguage][key];
+};
+
+export default WithTranslation;
diff --git a/client/src/admin/hocs/index.js b/client/src/admin/hocs/index.js
new file mode 100644
index 0000000..df8c0c7
--- /dev/null
+++ b/client/src/admin/hocs/index.js
@@ -0,0 +1,4 @@
+import WithHover from './WithHover.jsx';
+import WithTranslation from './WithTranslation.jsx';
+
+export { WithHover, WithTranslation as t };
diff --git a/client/src/admin/jsx/App.jsx b/client/src/admin/jsx/App.jsx
index c5be77c..146af70 100644
--- a/client/src/admin/jsx/App.jsx
+++ b/client/src/admin/jsx/App.jsx
@@ -3,33 +3,35 @@ import ReactDOM from 'react-dom';
import "../scss/index.scss";
-import texts from '../../common/data/texts.js';
-import TopBar from '../../common/jsx/TopBar.jsx';
-import Info from '../../common/jsx/Info.jsx';
+import TopBar from './TopBar.jsx';
+import Info from './Info.jsx';
import MainScreen from './MainScreen.jsx';
+import Context from '../context';
+import { defaultLanguage } from '../data/translations';
const App = () => {
- const [adminLang, setAdminLang] = useState('en');
+ const [lang, setLang] = useState(defaultLanguage);
const [projects, setProjects] = useState([]);
const [info, setInfo] = useState('');
const [hover, setHover] = useState('');
const [view, setView] = useState('main');
const [user, setUser] = useState(null);
- const t = (key) => texts[adminLang][key] || texts['en'][key];
- // useEffect(() => {
- // setInfo('no-saved-websites')
- // setHover('');
- // }, [user]);
+ useEffect(() => {
+ setInfo('no-saved-websites');
+ setUser('admin@op.pl');
+ }, []);
return (
- <div className="main">
- <TopBar lang={adminLang} setLang={setAdminLang} setHover={setHover} user={user} setUser={setUser} t={t} />
- <div className="main__content">
- { view === 'main' && <MainScreen projects={projects} t={t} setHover={setHover} /> }
+ <Context.Provider value={{ lang, setHover, setInfo }}>
+ <div className="main">
+ <TopBar lang={lang} setLang={setLang} user={user} setUser={setUser} />
+ <div className="main__content">
+ { view === 'main' && <MainScreen projects={projects} /> }
+ </div>
+ <Info info={info} hover={hover} />
</div>
- <Info info={info} hover={hover} t={t} />
- </div>
+ </Context.Provider>
)
};
diff --git a/client/src/admin/jsx/Info.jsx b/client/src/admin/jsx/Info.jsx
new file mode 100644
index 0000000..75294e1
--- /dev/null
+++ b/client/src/admin/jsx/Info.jsx
@@ -0,0 +1,10 @@
+import React from 'react';
+import { t } from '../hocs';
+
+const Info = ({ info, hover }) => (
+ <p className="info">
+ { hover ? t(hover) : t(info) }
+ </p>
+);
+
+export default Info;
diff --git a/client/src/admin/jsx/LangSwitch.jsx b/client/src/admin/jsx/LangSwitch.jsx
new file mode 100644
index 0000000..2494bef
--- /dev/null
+++ b/client/src/admin/jsx/LangSwitch.jsx
@@ -0,0 +1,42 @@
+import React from 'react';
+import { WithHover } from '../hocs';
+import { languages } from '../data/translations.js'
+
+const LangSwitch = ({ lang, setLang, opened, setOpened}) => {
+ const handleSetLang = (key) => {
+ setLang(key);
+ setOpened(false);
+ };
+
+ return (
+ <div className="lang-switch">
+ <WithHover message="click-to-change-language">
+ <span
+ className={`lang-switch__main-item${opened === 'lang' ? ' lang-switch__main-item--active' : ''}`}
+ onClick={() => setOpened(opened !== 'lang' ? 'lang' : false)}
+ >
+ {lang}
+ </span>
+ {
+ opened === 'lang' && (
+ <div className="lang-switch__list">
+ {
+ languages.map(key => key !== lang && (
+ <span
+ className="lang-switch__item"
+ key={key}
+ onClick={() => handleSetLang(key)}
+ >
+ {key}
+ </span>
+ ))
+ }
+ </div>
+ )
+ }
+ </WithHover>
+ </div>
+ );
+};
+
+export default LangSwitch;
diff --git a/client/src/admin/jsx/MainScreen.jsx b/client/src/admin/jsx/MainScreen.jsx
index ff28256..3d65384 100644
--- a/client/src/admin/jsx/MainScreen.jsx
+++ b/client/src/admin/jsx/MainScreen.jsx
@@ -1,21 +1,21 @@
import React, { Fragment } from 'react';
-import WithHover from '../../common/jsx/WithHover.jsx';
+import { WithHover, t } from '../hocs';
-const MainScreen = ({ projects, t, setHover }) => (
+const MainScreen = ({ projects }) => (
<div className="main-screen">
<h1 className="main-screen__header">{ t('main-title') }</h1>
<div className="main-screen__list">
{ !projects.length && (
- <WithHover setHover={setHover} message="edit-current-project-hover">
+ <WithHover message="edit-current-project-hover">
<p className="main-screen__item">{ t('edit-current-project') }</p>
</WithHover>
)}
{ !projects.length && (
- <WithHover setHover={setHover} message="show-saved-projects-hover">
+ <WithHover message="show-saved-projects-hover">
<p className="main-screen__item">{ t('show-saved-projects') }</p>
</WithHover>
)}
- <WithHover setHover={setHover} message="create-new-project-hover">
+ <WithHover message="create-new-project-hover">
<p className="main-screen__item">{ t('create-new-project') }</p>
</WithHover>
</div>
diff --git a/client/src/admin/jsx/TopBar.jsx b/client/src/admin/jsx/TopBar.jsx
new file mode 100644
index 0000000..e9be676
--- /dev/null
+++ b/client/src/admin/jsx/TopBar.jsx
@@ -0,0 +1,35 @@
+import React, {useState} from 'react';
+import LangSwitch from './LangSwitch.jsx';
+import User from './User.jsx';
+
+const TopBar = ({ user, setUser, lang, setLang }) => {
+ const [opened, setOpened] = useState(false);
+
+ return (
+ <div className="top-bar">
+ { opened !== false && (
+ <div
+ className="top-bar__fog"
+ onClick={() => setOpened(false)}
+ />
+ )}
+ <LangSwitch
+ lang={lang}
+ setLang={setLang}
+ opened={opened}
+ setOpened={setOpened}
+ />
+ { user && (
+ <User
+ user={user}
+ setUser={setUser}
+ opened={opened}
+ setOpened={setOpened}
+ />
+ )
+ }
+ </div>
+ );
+};
+
+export default TopBar;
diff --git a/client/src/admin/jsx/User.jsx b/client/src/admin/jsx/User.jsx
new file mode 100644
index 0000000..22b96b4
--- /dev/null
+++ b/client/src/admin/jsx/User.jsx
@@ -0,0 +1,39 @@
+import React from 'react';
+import { WithHover, t } from '../hocs';
+import logout from '../api/logout';
+
+const User = ({ user, setUser, opened, setOpened }) => {
+ const handleLogout = () => {
+ setOpened(false);
+ logout();
+ };
+ const handleChangePass = () => { setOpened(false) };
+ const handleRemoveUser = () => { setOpened(false) };
+
+ return (
+ <div className="user">
+ <WithHover message="click-to-change-user">
+ <span
+ className={`user__main-item${opened === 'user' ? ' user__main-item--active' : ''}`}
+ onClick={() => setOpened(opened !== 'user' ? 'user' : false)}
+ >
+ {user}
+ </span>
+ {
+ opened === 'user' && (
+ <div className="user__list" >
+ <WithHover message="click-to-logout">
+ <span className="user__item" onClick={handleLogout}>{t('logout')}</span>
+ </WithHover>
+ <WithHover message="click-to-change-user-settings">
+ <span className="user__item" onClick={handleChangePass}>{t('user-settings')}</span>
+ </WithHover>
+ </div>
+ )
+ }
+ </WithHover>
+ </div>
+ );
+};
+
+export default User;
diff --git a/client/src/admin/scss/_colors.scss b/client/src/admin/scss/_colors.scss
new file mode 100644
index 0000000..45ae737
--- /dev/null
+++ b/client/src/admin/scss/_colors.scss
@@ -0,0 +1,5 @@
+$background: #181818;
+$background-menu: #222;
+$text: #fff;
+$text-selected: orange;
+$text-inactive: #aaa;
diff --git a/client/src/admin/scss/_forms.scss b/client/src/admin/scss/_forms.scss
new file mode 100644
index 0000000..0585cd6
--- /dev/null
+++ b/client/src/admin/scss/_forms.scss
@@ -0,0 +1,52 @@
+// Text Input
+
+.text-input {
+ text-align: left;
+ margin-bottom: 1.5em;
+ transition: all .3s;
+ cursor: text;
+
+ &:focus-within {
+ transform: scale(1.05,1.05);
+ }
+}
+
+.text-input-label {
+ font-size: 1.25em;
+ width: 100%;
+ color: #aaa;
+ display:block;
+ transform:translateY(-1.75em);
+ transform-origin: 0 0;
+ transition: all .3s;
+ z-index: -1;
+ cursor: text;
+}
+
+.text-input-field {
+ font-size: 1.5rem;
+ box-shadow: none;
+ background: $background;
+ color: $text;
+ border-radius: 0;
+ border-color: #ccc;
+ border-style: none none solid none;
+ width: 100%;
+ transition: all .5s;
+ padding: 5px;
+
+ &::placeholder {
+ color: transparent;
+ }
+
+ &:focus {
+ box-shadow: none;
+ outline: none;
+ border-color: $text-selected;
+ }
+
+ &:focus + .text-input-label,
+ &:not(:placeholder-shown) + .text-input-label {
+ transform: translateY(-3em) scale(0.8);
+ }
+}
diff --git a/client/src/admin/scss/_globals.scss b/client/src/admin/scss/_globals.scss
new file mode 100644
index 0000000..f03ad86
--- /dev/null
+++ b/client/src/admin/scss/_globals.scss
@@ -0,0 +1,12 @@
+html {
+ background: $background;
+}
+
+* {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: -moz-none;
+ -o-user-select: none;
+ user-select: none;
+}
+
diff --git a/client/src/admin/scss/_info.scss b/client/src/admin/scss/_info.scss
new file mode 100644
index 0000000..ac32949
--- /dev/null
+++ b/client/src/admin/scss/_info.scss
@@ -0,0 +1,8 @@
+.info {
+ display: block;
+ color: #ddd;
+ flex-grow: 0;
+ text-align: center;
+ padding-bottom: 3vh;
+ padding-top: 3vh;
+}
diff --git a/client/src/admin/scss/_main.scss b/client/src/admin/scss/_main.scss
new file mode 100644
index 0000000..e182f3c
--- /dev/null
+++ b/client/src/admin/scss/_main.scss
@@ -0,0 +1,16 @@
+.main {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+
+ &__content {
+ flex-grow: 1;
+ display: flex;
+ flex-direction: column;
+ }
+}
diff --git a/client/src/admin/scss/_reset.scss b/client/src/admin/scss/_reset.scss
new file mode 100755
index 0000000..2928cc4
--- /dev/null
+++ b/client/src/admin/scss/_reset.scss
@@ -0,0 +1,52 @@
+* {
+ box-sizing: border-box;
+}
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+body {
+ line-height: 1;
+}
+ol, ul {
+ list-style: none;
+}
+blockquote, q {
+ quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: '';
+ content: none;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+html{
+ min-width: 320px;
+ background: white;
+}
+
diff --git a/client/src/admin/scss/_topBar.scss b/client/src/admin/scss/_topBar.scss
new file mode 100644
index 0000000..af9fcd6
--- /dev/null
+++ b/client/src/admin/scss/_topBar.scss
@@ -0,0 +1,114 @@
+@keyframes showTopMenu {
+ 0% {transform: translateY(100%) scale(0.8) ; opacity: 0;}
+ 80% {transform: translateY(100%) scale(1.1); opacity: 100%;}
+ 100% {transform: translateY(100%) scale(1); opacity: 100%;}
+}
+
+.top-bar {
+ flex-grow: 0;
+ display: flex;
+ justify-content: end;
+ padding: 1em;
+
+
+ &__fog {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ }
+}
+
+.user {
+ position: relative;
+
+ &__list {
+ position: absolute;
+ display: block;
+ bottom: 0;
+ right: 0;
+ transform: translateY(100%);
+ background: $background-menu;
+ animation: showTopMenu .3s;
+ }
+
+ &__main-item {
+ color: $text;
+ display: block;
+ padding: .5em;
+ white-space: nowrap;
+ transition: color .3s;
+ cursor: pointer;
+
+ &--active {
+ background: $background-menu;
+ color: $text-selected;
+ }
+
+ &:hover {
+ color: $text-selected;
+ }
+ }
+
+ &__item {
+ display: block;
+ color: $text;
+ padding: .5em;
+ font-weight: normal;
+ transition: color .3s;
+ cursor: pointer;
+ white-space: nowrap;
+ text-align: right;
+
+ &:hover {
+ color: $text-selected;
+ }
+ }
+}
+
+.lang-switch {
+ display: inline-block;
+ position: relative;
+
+ &__list {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ transform: translateY(100%);
+ background: $background-menu;
+ animation: showTopMenu .3s;
+ }
+
+ &__main-item {
+ transition: .3s color;
+ padding: .5em;
+ display: block;
+ color: $text;
+ font-weight: normal;
+ cursor: pointer;
+
+ &:hover {
+ color: $text-selected;
+ }
+
+ &--active {
+ background: $background-menu;
+ color: $text-selected;
+ }
+ }
+
+ &__item {
+ padding: .5em;
+ display: block;
+ color: $text;
+ font-weight: normal;
+ cursor: pointer;
+ transition: color .3s;
+
+ &:hover {
+ color: $text-selected;
+ }
+ }
+}
diff --git a/client/src/admin/scss/index.scss b/client/src/admin/scss/index.scss
index 67553bb..ab61dd9 100644
--- a/client/src/admin/scss/index.scss
+++ b/client/src/admin/scss/index.scss
@@ -1,8 +1,8 @@
-@import '../../common/scss/reset';
-@import '../../common/scss/colors';
-@import '../../common/scss/globals';
-@import '../../common/scss/forms';
-@import '../../common/scss/main';
-@import '../../common/scss/info';
-@import '../../common/scss/topBar';
+@import 'reset';
+@import 'colors';
+@import 'globals';
+@import 'forms';
+@import 'main';
+@import 'info';
+@import 'topBar';
@import 'mainScreen';