Skip to content

Commit

Permalink
Transition to Redux Toolkit, Tinymce React Editor, and Framer Motion (#…
Browse files Browse the repository at this point in the history
…21)

* Transition to Redux Slices

- Go from Animejs to motion-frame
- Cleanup speaker card components
- Update dependencies

* Move to TinyMce React Editor

- Fix Speaker Cards

* Cleanup Mobile Ticket Button

- Now animates it's expansion
- Uses Framer to move it's location
- Cleanup some styling around the button and header
  • Loading branch information
w9jds authored Aug 10, 2024
1 parent 0f54dd1 commit 9d799dc
Show file tree
Hide file tree
Showing 57 changed files with 6,710 additions and 5,304 deletions.
9 changes: 9 additions & 0 deletions config/webpack/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 4,7 @@ const { DevfestDetails } = require('../../src/config/delorean.details.js');

const HtmlWebpackPlugin = require('html-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');

const ENV_DEST = process.env.ENV_DEST ? process.env.ENV_DEST : 'dev';

Expand Down Expand Up @@ -79,6 80,14 @@ module.exports = {
},
}),
new webpack.EnvironmentPlugin(['NODE_ENV']),
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, '../../node_modules/tinymce'),
to: path.resolve(__dirname, '../../dist/static/tinymce/'),
},
],
}),
new HtmlWebpackPlugin({
eventName: `${DevfestDetails.location} ${DevfestDetails.name} ${DevfestDetails.year}`,
description: DevfestDetails.description,
Expand Down
10,006 changes: 5,825 additions & 4,181 deletions package-lock.json

Large diffs are not rendered by default.

91 changes: 46 additions & 45 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,70 11,71 @@
"author": "Jeremy Shore",
"license": "MIT",
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@googlemaps/js-api-loader": "^1.16.2",
"@mui/icons-material": "^5.14.13",
"@mui/material": "^5.14.13",
"@mui/x-date-pickers": "^6.16.2",
"animejs": "^3.2.1",
"classnames": "^2.3.2",
"@emotion/react": "^11.13.0",
"@emotion/styled": "^11.13.0",
"@googlemaps/js-api-loader": "^1.16.8",
"@mui/icons-material": "^5.16.7",
"@mui/material": "^5.16.7",
"@mui/x-date-pickers": "^6.20.2",
"@reduxjs/toolkit": "^2.2.7",
"@tinymce/tinymce-react": "^5.1.1",
"classnames": "^2.5.1",
"date-fns": "^2.30.0",
"date-fns-timezone": "^0.1.4",
"dompurify": "^3.0.6",
"firebase": "^10.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-dropzone": "^8.2.0",
"react-redux": "^8.1.3",
"react-router-dom": "^6.17.0",
"redux": "^4.2.1",
"redux-actions": "^3.0.0",
"redux-saga": "^1.2.3",
"reselect": "^4.1.8",
"dompurify": "^3.1.6",
"firebase": "^10.12.5",
"framer-motion": "^11.3.24",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-dropzone": "^14.2.3",
"react-redux": "^9.1.2",
"react-router-dom": "^6.24.1",
"redux-saga": "^1.3.0",
"reselect": "^5.1.1",
"timezone-support": "^3.1.0",
"tinymce": "^6.7.0"
"tinymce": "^7.3.0"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/core": "^7.25.2",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-react-constant-elements": "^7.22.5",
"@babel/plugin-transform-react-inline-elements": "^7.22.5",
"@babel/plugin-transform-runtime": "^7.23.2",
"@babel/preset-env": "^7.23.2",
"@babel/preset-react": "^7.22.15",
"@babel/preset-typescript": "^7.23.2",
"@babel/plugin-transform-react-constant-elements": "^7.25.1",
"@babel/plugin-transform-react-inline-elements": "^7.24.7",
"@babel/plugin-transform-runtime": "^7.24.7",
"@babel/preset-env": "^7.25.3",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@svgr/webpack": "^8.1.0",
"@types/google.maps": "^3.54.3",
"@types/node": "^20.8.6",
"@types/react-redux": "^7.1.27",
"@types/redux-actions": "^2.6.3",
"@types/google.maps": "^3.55.12",
"@types/node": "^22.2.0",
"@types/react-redux": "^7.1.33",
"@types/redux-actions": "^2.6.5",
"babel-plugin-add-react-displayname": "^0.0.5",
"buffer": "^6.0.3",
"css-loader": "^6.8.1",
"copy-webpack-plugin": "^12.0.2",
"css-loader": "^7.1.2",
"file-loader": "^6.2.0",
"html-loader": "^4.2.0",
"html-webpack-plugin": "^5.5.3",
"html-loader": "^5.1.0",
"html-webpack-plugin": "^5.6.0",
"markdown-loader": "^8.0.0",
"mini-css-extract-plugin": "^2.7.6",
"mini-css-extract-plugin": "^2.9.0",
"path": "^0.12.7",
"react-svg-loader": "^3.0.3",
"sass": "^1.69.3",
"sass-loader": "^13.3.2",
"source-map-loader": "^4.0.1",
"sass": "^1.77.8",
"sass-loader": "^16.0.0",
"source-map-loader": "^5.0.0",
"stream-browserify": "^3.0.0",
"style-loader": "^3.3.3",
"ts-loader": "^9.5.0",
"style-loader": "^4.0.0",
"ts-loader": "^9.5.1",
"tsconfig-paths-webpack-plugin": "^4.1.0",
"tslib": "^2.6.2",
"tslib": "^2.6.3",
"tslint": "^6.1.3",
"tslint-react": "^5.0.0",
"typescript": "^5.2.2",
"typescript": "^5.5.4",
"url-loader": "^4.1.1",
"webpack": "^5.89.0",
"webpack": "^5.93.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"webpack-merge": "^5.10.0"
"webpack-dev-server": "^5.0.4",
"webpack-merge": "^6.0.1"
}
}
53 changes: 16 additions & 37 deletions src/components/MainLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,19 1,16 @@
import React, { FC, Fragment, useState, useEffect } from 'react';
import { connect } from 'react-redux';
import { Dispatch, bindActionCreators } from 'redux';
import { useDispatch, useSelector } from 'react-redux';
import { Route, Routes } from 'react-router-dom';

import { Profile } from 'models/user';
import { ApplicationState } from 'models/states';
import { FirebaseConfig } from 'config/delorean.config';

import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged, User } from 'firebase/auth';
import { doc, getDoc, getFirestore } from 'firebase/firestore';

import { getUser, getUserProfile } from 'store/current/selectors';
import { setFirebaseApplication, getSiteData, setUser, setUserProfile } from 'store/current/actions';
import { getIsEditMode } from 'store/admin/selectors';
import { getUserProfile } from 'store/current/selectors';
import { isEditMode } from 'store/admin/selectors';

import Home from 'pages/Home';
import Conduct from 'pages/Conduct';
Expand All @@ -30,8 27,7 @@ import SpeakerEditor from './editors/Speaker';
import SessionEditor from './editors/Session';

import 'stylesheets/main.scss';

type MainLayoutProps = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;
import { getSiteData, setFirebaseApplication, setUser, setUserProfile } from 'store/current/reducer';

export enum DeloreanRoutes {
HOME = '/',
Expand All @@ -41,37 37,33 @@ export enum DeloreanRoutes {
CODE_OF_CONDUCT = '/code-of-conduct'
}

const MainLayout: FC<MainLayoutProps> = ({
user,
profile,
isEditMode,
const MainLayout: FC = () => {
const dispatch = useDispatch();

const profile = useSelector(getUserProfile);
const isEditing = useSelector(isEditMode);

setUser,
setUserProfile,
setFirebaseApplication,
getSiteData
}) => {
const [firstLoad, setFirstLoad] = useState(true);

useEffect(() => {
const firebaseApp = initializeApp(FirebaseConfig);
const auth = getAuth(firebaseApp);
const db = getFirestore(firebaseApp);

setFirebaseApplication(firebaseApp);
dispatch(setFirebaseApplication(firebaseApp));

const verifyLogin = async (user: User) => {
if (firstLoad && user) {
setUser(user);
dispatch(setUser(user));

let profile = await getDoc(doc(db, `/users/${user.uid}`));
setUserProfile(profile.data() as Profile);
const profile = await getDoc(doc(db, `/users/${user.uid}`));
dispatch(setUserProfile(profile.data() as Profile))
setFirstLoad(false);
}
}

onAuthStateChanged(auth, verifyLogin);
getSiteData();
dispatch(getSiteData());
}, [])

const buildAdminPanels = () => {
Expand Down Expand Up @@ -103,24 95,11 @@ const MainLayout: FC<MainLayoutProps> = ({
<Route path="/*" element={<Home />} />
</Routes>

{isEditMode ? <EditOverlay /> : null}
{isEditing ? <EditOverlay /> : null}

<Footer />
</Fragment>
)
}

const mapStateToProps = (state: ApplicationState) => ({
user: getUser(state),
profile: getUserProfile(state),
isEditMode: getIsEditMode(state)
});

const mapDispatchToProps = (dispatch: Dispatch) => bindActionCreators({
setUser,
setUserProfile,
setFirebaseApplication,
getSiteData
}, dispatch);

export default connect(mapStateToProps, mapDispatchToProps)(MainLayout);
export default MainLayout;
File renamed without changes.
54 changes: 54 additions & 0 deletions src/components/dialogs/Details.tsx
Original file line number Diff line number Diff line change
@@ -0,0 1,54 @@
import React, { FC } from 'react';
import { useDispatch } from 'react-redux';
import createDOMPurity from 'dompurify';

import { Speaker } from 'models/speaker';
import { Clear } from '@mui/icons-material';

import Socials from '../../controls/SpeakerCard/Socials';
import Subtitle from '../../controls/SpeakerCard/Subtitle';
import { Typography, DialogContent, Divider, Button } from '@mui/material';
import { closeDialog } from 'store/dialogs/reducer';

import './Details.scss';

type Props = {
speaker: Speaker;
};

const DOMPurify = createDOMPurity(window);

const Details: FC<Props> = ({ speaker }) => {
const dispatch = useDispatch();

const close = () => {
dispatch(closeDialog());
}

return (
<DialogContent className="speaker-details">
<Button className="action close" onClick={close}>
<Clear />
</Button>

<div className="header">
<img title="Speaker Portrait" className="portrait-image portrait-avatar" src={speaker.portraitUrl} />
</div>
<div className="content">
<Typography variant="h6">{speaker.name}</Typography>
<Subtitle title={speaker.title} company={speaker.company} />
</div>

<Socials speaker={speaker} />

{speaker?.bio && (
<>
<Divider />
<div className="bio" dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(speaker.bio) }} />
</>
)}
</DialogContent>
);
}

export default Details;
8 changes: 4 additions & 4 deletions src/components/dialogs/SiteConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 8,8 @@ import { Loader } from '@googlemaps/js-api-loader';

import Configuration from 'models/config';
import { ApplicationState } from 'models/states';
import { toggleConfig } from 'store/config/reducer';
import { MapsConfig } from 'config/delorean.config';
import { closeConfigDialog } from 'store/config/actions';
import { isConfigDialogOpen } from 'store/config/selectors';
import { getDatabase, getCurrentConfig } from 'store/current/selectors';

Expand Down Expand Up @@ -42,7 42,7 @@ const SiteConfig: FC<SiteConfigProps> = ({
open,
config,

closeConfigDialog
toggleConfig
}) => {
const ref = useRef();
const [autocomplete, setAutoComplete] = useState<google.maps.places.Autocomplete>();
Expand Down Expand Up @@ -96,7 96,7 @@ const SiteConfig: FC<SiteConfigProps> = ({

const handleClose = () => {
setAutoComplete(null);
closeConfigDialog();
toggleConfig();
};

const save = async () => {
Expand Down Expand Up @@ -253,7 253,7 @@ const mapStateToProps = (state: ApplicationState) => ({
});

const mapDispatchToProps = (dispatch: Dispatch) => bindActionCreators({
closeConfigDialog
toggleConfig
}, dispatch);

export default connect(mapStateToProps, mapDispatchToProps)(SiteConfig);
Loading

0 comments on commit 9d799dc

Please sign in to comment.