mirror of
https://github.com/mediacms-io/mediacms.git
synced 2026-03-10 23:17:21 -04:00
Frontent dev env (#247)
* Added frontend development files/environment * More items-categories related removals * Improvements in pages templates (inc. static pages) * Improvements in video player * Added empty home page message + cta * Updates in media, playlist and management pages * Improvements in material icons font loading * Replaced media & playlists links in frontend dev-env * frontend package version update * chnaged frontend dev url port * static files update * Changed default position of theme switcher * enabled frontend docker container
This commit is contained in:
5
frontend/src/static/js/utils/contexts/ApiUrlContext.js
Normal file
5
frontend/src/static/js/utils/contexts/ApiUrlContext.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
export const ApiUrlContext = createContext(mediacmsConfig(window.MediaCMS).api);
|
||||
export const ApiUrlConsumer = ApiUrlContext.Consumer;
|
||||
129
frontend/src/static/js/utils/contexts/HeaderContext.js
Normal file
129
frontend/src/static/js/utils/contexts/HeaderContext.js
Normal file
@@ -0,0 +1,129 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
const config = mediacmsConfig(window.MediaCMS);
|
||||
|
||||
const links = config.url;
|
||||
const theme = config.theme;
|
||||
const user = config.member;
|
||||
|
||||
const hasThemeSwitcher = theme.switch.enabled && 'header' === theme.switch.position;
|
||||
|
||||
function popupTopNavItems() {
|
||||
const items = [];
|
||||
|
||||
if (!user.is.anonymous) {
|
||||
if (user.can.addMedia) {
|
||||
items.push({
|
||||
link: links.user.addMedia,
|
||||
icon: 'video_call',
|
||||
text: 'Upload media',
|
||||
itemAttr: {
|
||||
className: 'visible-only-in-small',
|
||||
},
|
||||
});
|
||||
|
||||
if (user.pages.media) {
|
||||
items.push({
|
||||
link: user.pages.media,
|
||||
icon: 'video_library',
|
||||
text: 'My media',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
items.push({
|
||||
link: links.signout,
|
||||
icon: 'exit_to_app',
|
||||
text: 'Sign out',
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function popupMiddleNavItems() {
|
||||
const items = [];
|
||||
|
||||
if (hasThemeSwitcher) {
|
||||
items.push({
|
||||
itemType: 'open-subpage',
|
||||
icon: 'brightness_4',
|
||||
iconPos: 'left',
|
||||
text: 'Switch theme',
|
||||
buttonAttr: {
|
||||
className: 'change-page',
|
||||
'data-page-id': 'switch-theme',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (user.is.anonymous) {
|
||||
if (user.can.login) {
|
||||
items.push({
|
||||
itemType: 'link',
|
||||
icon: 'login',
|
||||
iconPos: 'left',
|
||||
text: 'Sign in',
|
||||
link: links.signin,
|
||||
linkAttr: {
|
||||
className: hasThemeSwitcher ? 'visible-only-in-small' : 'visible-only-in-extra-small',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (user.can.register) {
|
||||
items.push({
|
||||
itemType: 'link',
|
||||
icon: 'person_add',
|
||||
iconPos: 'left',
|
||||
text: 'Register',
|
||||
link: links.register,
|
||||
linkAttr: {
|
||||
className: hasThemeSwitcher ? 'visible-only-in-small' : 'visible-only-in-extra-small',
|
||||
},
|
||||
});
|
||||
}
|
||||
} else {
|
||||
items.push({
|
||||
link: links.user.editProfile,
|
||||
icon: 'brush',
|
||||
text: 'Edit profile',
|
||||
});
|
||||
|
||||
if (user.can.changePassword) {
|
||||
items.push({
|
||||
link: links.changePassword,
|
||||
icon: 'lock',
|
||||
text: 'Change password',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
function popupBottomNavItems() {
|
||||
const items = [];
|
||||
|
||||
if (user.is.admin) {
|
||||
items.push({
|
||||
link: links.admin,
|
||||
icon: 'admin_panel_settings',
|
||||
text: 'MediaCMS administration',
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
export const HeaderContext = createContext({
|
||||
hasThemeSwitcher,
|
||||
popupNavItems: {
|
||||
top: popupTopNavItems(),
|
||||
middle: popupMiddleNavItems(),
|
||||
bottom: popupBottomNavItems(),
|
||||
},
|
||||
});
|
||||
|
||||
export const HeaderConsumer = HeaderContext.Consumer;
|
||||
101
frontend/src/static/js/utils/contexts/LayoutContext.js
Normal file
101
frontend/src/static/js/utils/contexts/LayoutContext.js
Normal file
@@ -0,0 +1,101 @@
|
||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||
import { BrowserCache } from '../classes/';
|
||||
import { PageStore } from '../stores/';
|
||||
import { addClassname, removeClassname } from '../helpers/';
|
||||
import SiteContext from './SiteContext';
|
||||
|
||||
let slidingSidebarTimeout;
|
||||
|
||||
function onSidebarVisibilityChange(visibleSidebar) {
|
||||
clearTimeout(slidingSidebarTimeout);
|
||||
|
||||
addClassname(document.body, 'sliding-sidebar');
|
||||
|
||||
slidingSidebarTimeout = setTimeout(function () {
|
||||
if ('media' === PageStore.get('current-page')) {
|
||||
if (visibleSidebar) {
|
||||
addClassname(document.body, 'overflow-hidden');
|
||||
} else {
|
||||
removeClassname(document.body, 'overflow-hidden');
|
||||
}
|
||||
} else {
|
||||
if (!visibleSidebar || 767 < window.innerWidth) {
|
||||
removeClassname(document.body, 'overflow-hidden');
|
||||
} else {
|
||||
addClassname(document.body, 'overflow-hidden');
|
||||
}
|
||||
}
|
||||
|
||||
if (visibleSidebar) {
|
||||
addClassname(document.body, 'visible-sidebar');
|
||||
} else {
|
||||
removeClassname(document.body, 'visible-sidebar');
|
||||
}
|
||||
|
||||
slidingSidebarTimeout = setTimeout(function () {
|
||||
slidingSidebarTimeout = null;
|
||||
removeClassname(document.body, 'sliding-sidebar');
|
||||
}, 220);
|
||||
}, 20);
|
||||
}
|
||||
|
||||
export const LayoutContext = createContext();
|
||||
|
||||
export const LayoutProvider = ({ children }) => {
|
||||
const site = useContext(SiteContext);
|
||||
const cache = new BrowserCache('MediaCMS[' + site.id + '][layout]', 86400);
|
||||
|
||||
const enabledSidebar = !!(document.getElementById('app-sidebar') || document.querySelector('.page-sidebar'));
|
||||
|
||||
const [visibleSidebar, setVisibleSidebar] = useState(cache.get('visible-sidebar'));
|
||||
const [visibleMobileSearch, setVisibleMobileSearch] = useState(false);
|
||||
|
||||
const toggleMobileSearch = () => {
|
||||
setVisibleMobileSearch(!visibleMobileSearch);
|
||||
};
|
||||
|
||||
const toggleSidebar = () => {
|
||||
const newval = !visibleSidebar;
|
||||
onSidebarVisibilityChange(newval);
|
||||
setVisibleSidebar(newval);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (visibleSidebar) {
|
||||
addClassname(document.body, 'visible-sidebar');
|
||||
} else {
|
||||
removeClassname(document.body, 'visible-sidebar');
|
||||
}
|
||||
if ('media' !== PageStore.get('current-page') && 1023 < window.innerWidth) {
|
||||
cache.set('visible-sidebar', visibleSidebar);
|
||||
}
|
||||
}, [visibleSidebar]);
|
||||
|
||||
useEffect(() => {
|
||||
PageStore.once('page_init', () => {
|
||||
if ('media' === PageStore.get('current-page')) {
|
||||
setVisibleSidebar(false);
|
||||
removeClassname(document.body, 'visible-sidebar');
|
||||
}
|
||||
});
|
||||
|
||||
setVisibleSidebar(
|
||||
'media' !== PageStore.get('current-page') &&
|
||||
1023 < window.innerWidth &&
|
||||
(null === visibleSidebar || visibleSidebar)
|
||||
);
|
||||
}, []);
|
||||
|
||||
const value = {
|
||||
enabledSidebar,
|
||||
visibleSidebar,
|
||||
setVisibleSidebar,
|
||||
visibleMobileSearch,
|
||||
toggleMobileSearch,
|
||||
toggleSidebar,
|
||||
};
|
||||
|
||||
return <LayoutContext.Provider value={value}>{children}</LayoutContext.Provider>;
|
||||
};
|
||||
|
||||
export const LayoutConsumer = LayoutContext.Consumer;
|
||||
5
frontend/src/static/js/utils/contexts/LinksContext.js
Normal file
5
frontend/src/static/js/utils/contexts/LinksContext.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
export const LinksContext = createContext(mediacmsConfig(window.MediaCMS).url);
|
||||
export const LinksConsumer = LinksContext.Consumer;
|
||||
5
frontend/src/static/js/utils/contexts/MemberContext.js
Normal file
5
frontend/src/static/js/utils/contexts/MemberContext.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
export const MemberContext = createContext(mediacmsConfig(window.MediaCMS).member);
|
||||
export const MemberConsumer = MemberContext.Consumer;
|
||||
@@ -0,0 +1,4 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
export const PlaylistsContext = createContext(mediacmsConfig(window.MediaCMS).playlists);
|
||||
@@ -0,0 +1,5 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
export const ShareOptionsContext = createContext(mediacmsConfig(window.MediaCMS).media.share.options);
|
||||
|
||||
5
frontend/src/static/js/utils/contexts/SidebarContext.js
Normal file
5
frontend/src/static/js/utils/contexts/SidebarContext.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
export const SidebarContext = createContext(mediacmsConfig(window.MediaCMS).sidebar);
|
||||
export const SidebarConsumer = SidebarContext.Consumer;
|
||||
7
frontend/src/static/js/utils/contexts/SiteContext.js
Normal file
7
frontend/src/static/js/utils/contexts/SiteContext.js
Normal file
@@ -0,0 +1,7 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
export const SiteContext = createContext(mediacmsConfig(window.MediaCMS).site);
|
||||
export const SiteConsumer = SiteContext.Consumer;
|
||||
|
||||
export default SiteContext;
|
||||
12
frontend/src/static/js/utils/contexts/TextsContext.js
Normal file
12
frontend/src/static/js/utils/contexts/TextsContext.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
const notifications = mediacmsConfig(window.MediaCMS).notifications.messages;
|
||||
|
||||
const texts = {
|
||||
notifications,
|
||||
};
|
||||
|
||||
export const TextsContext = createContext(texts);
|
||||
|
||||
export const TextsConsumer = TextsContext.Consumer;
|
||||
80
frontend/src/static/js/utils/contexts/ThemeContext.js
Normal file
80
frontend/src/static/js/utils/contexts/ThemeContext.js
Normal file
@@ -0,0 +1,80 @@
|
||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||
import { BrowserCache } from '../classes/';
|
||||
import { addClassname, removeClassname, supportsSvgAsImg } from '../helpers/';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
import SiteContext from './SiteContext';
|
||||
|
||||
const config = mediacmsConfig(window.MediaCMS);
|
||||
|
||||
function initLogo(logo) {
|
||||
let light = null;
|
||||
let dark = null;
|
||||
|
||||
if (void 0 !== logo.darkMode) {
|
||||
if (supportsSvgAsImg() && void 0 !== logo.darkMode.svg && '' !== logo.darkMode.svg) {
|
||||
dark = logo.darkMode.svg;
|
||||
} else if (void 0 !== logo.darkMode.img && '' !== logo.darkMode.img) {
|
||||
dark = logo.darkMode.img;
|
||||
}
|
||||
}
|
||||
|
||||
if (void 0 !== logo.lightMode) {
|
||||
if (supportsSvgAsImg() && void 0 !== logo.lightMode.svg && '' !== logo.lightMode.svg) {
|
||||
light = logo.lightMode.svg;
|
||||
} else if (void 0 !== logo.lightMode.img && '' !== logo.lightMode.img) {
|
||||
light = logo.lightMode.img;
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== light || null !== dark) {
|
||||
if (null === light) {
|
||||
light = dark;
|
||||
} else if (null === dark) {
|
||||
dark = light;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
light,
|
||||
dark,
|
||||
};
|
||||
}
|
||||
|
||||
function initMode(cachedValue, defaultValue) {
|
||||
return 'light' === cachedValue || 'dark' === cachedValue ? cachedValue : defaultValue;
|
||||
}
|
||||
|
||||
export const ThemeContext = createContext();
|
||||
|
||||
export const ThemeProvider = ({ children }) => {
|
||||
const site = useContext(SiteContext);
|
||||
const cache = new BrowserCache('MediaCMS[' + site.id + '][theme]', 86400);
|
||||
const [themeMode, setThemeMode] = useState(initMode(cache.get('mode'), config.theme.mode));
|
||||
const logos = initLogo(config.theme.logo);
|
||||
const [logo, setLogo] = useState(logos[themeMode]);
|
||||
|
||||
const changeMode = () => {
|
||||
setThemeMode('light' === themeMode ? 'dark' : 'light');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if ('dark' === themeMode) {
|
||||
addClassname(document.body, 'dark_theme');
|
||||
} else {
|
||||
removeClassname(document.body, 'dark_theme');
|
||||
}
|
||||
cache.set('mode', themeMode);
|
||||
setLogo(logos[themeMode]);
|
||||
}, [themeMode]);
|
||||
|
||||
const value = {
|
||||
logo,
|
||||
currentThemeMode: themeMode,
|
||||
changeThemeMode: changeMode,
|
||||
themeModeSwitcher: config.theme.switch,
|
||||
};
|
||||
|
||||
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
|
||||
};
|
||||
|
||||
export const ThemeConsumer = ThemeContext.Consumer;
|
||||
22
frontend/src/static/js/utils/contexts/UserContext.js
Normal file
22
frontend/src/static/js/utils/contexts/UserContext.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { config as mediacmsConfig } from '../settings/config.js';
|
||||
|
||||
export const UserContext = createContext();
|
||||
|
||||
const member = mediacmsConfig(window.MediaCMS).member;
|
||||
|
||||
export const UserProvider = ({ children }) => {
|
||||
const value = {
|
||||
isAnonymous: member.is.anonymous,
|
||||
username: member.username,
|
||||
thumbnail: member.thumbnail,
|
||||
userCan: member.can,
|
||||
pages: member.pages,
|
||||
};
|
||||
|
||||
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
|
||||
};
|
||||
|
||||
export const UserConsumer = UserContext.Consumer;
|
||||
|
||||
export default UserContext;
|
||||
12
frontend/src/static/js/utils/contexts/index.ts
Normal file
12
frontend/src/static/js/utils/contexts/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export * from './ApiUrlContext';
|
||||
export * from './HeaderContext';
|
||||
export * from './LayoutContext';
|
||||
export * from './LinksContext';
|
||||
export * from './MemberContext';
|
||||
export * from './PlaylistsContext';
|
||||
export * from './ShareOptionsContext';
|
||||
export * from './SidebarContext';
|
||||
export * from './SiteContext';
|
||||
export * from './TextsContext';
|
||||
export * from './ThemeContext';
|
||||
export * from './UserContext';
|
||||
Reference in New Issue
Block a user