Skip to content

Commit

Permalink
v5.6.0-PrivateGrids1
Browse files Browse the repository at this point in the history
  • Loading branch information
rakib committed Mar 5, 2025
1 parent 4bf490b commit ea1451e
Show file tree
Hide file tree
Showing 15 changed files with 243 additions and 126 deletions.
3 changes: 2 additions & 1 deletion components/auth-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export default function AuthState({ classes, nextOverride = ``, hideOnUsersLoadi
hideOnUsersLoading == true && usersLoading ? <></> : (
<span className={`authStateComponent ${user != null ? `hasUserSignedIn` : `noUserSignedIn`} ${classes} textOverflow extended`} style={{minWidth: `fit-content`}}>
{user != null ? (
`Welcome, ${user?.name} - Credits: ${(20_000 - user?.properties)?.toLocaleString()}`
` ${user?.name}`
// `Welcome, ${user?.name} - Credits: ${(20_000 - user?.properties)?.toLocaleString()}`
) : (nextOverride != `` && authState == AuthStates.Next) ? nextOverride : authState}
</span>
)
Expand Down
40 changes: 24 additions & 16 deletions components/boards/boards.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import Board from './board';
import { toast } from 'react-toastify';
import { Types } from '../../shared/types/types';
import { User } from '../../shared/models/User';
import MultiSelector from '../selector/multi-selector';
import { collection, getDocs } from 'firebase/firestore';
import IVFSkeleton from '../loaders/skeleton/ivf_skeleton';
import { AuthGrids, GridTypes, Types } from '../../shared/types/types';
import { useState, useEffect, useContext, useRef } from 'react';
import { generateArray, logToast } from '../../shared/constants';
import { capWords, replaceAll, StateContext } from '../../pages/_app';
import { Droppable, Draggable, DragDropContext } from 'react-beautiful-dnd';
import { Board as BoardModel, createBoard } from '../../shared/models/Board';
import { generateArray, logToast, withinXTime } from '../../shared/constants';
import { addBoardToDatabase, boardsTable, db, updateDocFieldsWTimeStamp } from '../../firebase';

export enum ItemTypes {
Expand All @@ -34,6 +35,14 @@ export const getLoadingLabel = (lbl: string, authState, user) => {
return user != null ? `${lbl} Loading` : `${!nonFormAuthStates.includes(authState) ? authState : `Register`} to View ${lbl}`;
}

export const recentlyAuthenticated = (usr: User, interval = 5, timePass = `minutes`) => {
let isRecentlyAuthenticated = false;
let userRecentAuth = usr?.auth?.lastAuthenticated;
let userRecentlyAuthenticated = withinXTime(userRecentAuth, interval, timePass);
isRecentlyAuthenticated = userRecentlyAuthenticated;
return isRecentlyAuthenticated;
}

export default function Boards(props: any) {
let {
user,
Expand All @@ -42,8 +51,11 @@ export default function Boards(props: any) {
setLoading,
globalUserData,
setSystemStatus,
setActiveOptions,
switchSelectedGrid,
rte, router, setRte,
openAuthenticationForm,
userRecentlyAuthenticated,
boards, setBoards, boardsLoading,
grids, gridsLoading, selectedGrids, selectedGrid,
} = useContext<any>(StateContext);
Expand All @@ -64,18 +76,14 @@ export default function Boards(props: any) {

const updateSelectedGrids = async (updatedSelectedGrids) => {
let thisGrid = updatedSelectedGrids[0];

// const openAuthenticationForm = () => {
// setOnAuthenticateLabel(`View Private Grid`);
// setOnAuthenticateFunction(`Switch Grid`);
// setAuthenticateOpen(true);
// setUpNextGrid(thisGrid);
// }

switchSelectedGrid(user, thisGrid);
// if (thisGrid?.options?.private == true && thisGrid?.gridType == GridTypes.Private) {
// openAuthenticationForm();
// } else switchSelectedGrid(user, thisGrid);
if (AuthGrids?.includes(thisGrid?.gridType)) {
if (userRecentlyAuthenticated) {
switchSelectedGrid(user, thisGrid);
} else {
setActiveOptions([selectedGrid]);
openAuthenticationForm(thisGrid);
}
} else switchSelectedGrid(user, thisGrid);
}

const onDragEnd = (dragEndEvent) => {
Expand Down Expand Up @@ -126,7 +134,7 @@ export default function Boards(props: any) {
}

const createBoardComponent = () => (
<div className={`createBoard lists extended`}>
<div className={`createBoard lists extended transition ${AuthGrids?.includes(selectedGrid?.gridType) && !userRecentlyAuthenticated ? `blurred pointerEventsNone` : ``}`}>
<div className={`list items addListDiv`}>
<div className={`formItems items`}>
<div className={`addListFormItem`}>
Expand Down Expand Up @@ -213,7 +221,7 @@ export default function Boards(props: any) {
{selectedGrid?.options?.newestBoardsOnTop ? ((boardsLoading || user?.uid != selectedGrid?.ownerUID) ? <></> : createBoardComponent()) : <></>}

<DragDropContext onDragEnd={onDragEnd}>
<div id={`allBoards`} className={`boards`}>
<div id={`allBoards`} className={`boards transition ${AuthGrids?.includes(selectedGrid?.gridType) && !userRecentlyAuthenticated ? `blurred pointerEventsNone` : ``}`}>
<div className={`flex ${boards && boards?.length > 0 ? `hasBoards` : `noBoards`} ${boards && boards?.length == 1 ? `oneBoard` : ``}`}>
{(boardsLoading || selectedGrid == null) ? <>
<div className={`flex isColumn`} style={{ paddingTop: 5 }}>
Expand Down
54 changes: 32 additions & 22 deletions components/modals/authenticate/authenticate-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,29 @@ import { StateContext } from '../../../pages/_app';
import { logToast } from '../../../shared/constants';
import Authenticate, { onAuthenticate } from './authenticate';
import { deleteDatabaseData, deleteUserAuth } from '../../../firebase';
import { AuthGrids } from '../../../shared/types/types';

export default function AuthenticationDialog({ }: any) {
const { user, signOutReset, onSignOut, onAuthenticateFunction, authenticateOpen, setAuthenticateOpen } = useContext<any>(StateContext);
const {
user,
onSignOut,
upNextGrid,
signOutReset,
globalUserData,
authenticateOpen,
setAuthenticateOpen,
hardSetSelectedGrid,
onAuthenticateFunction,
} = useContext<any>(StateContext);

const deleteAndCloseDialog = () => {
setAuthenticateOpen(false);
deleteUserFromDatabases();
}
const setAuthGrid = () => {
setAuthenticateOpen(false);
hardSetSelectedGrid(upNextGrid, globalUserData?.grids);
}

const deleteUserFromDatabases = async () => {
toast.info(`Deleting User ${user?.id}`);
Expand All @@ -22,10 +42,18 @@ export default function AuthenticationDialog({ }: any) {
});
}

const onCloseLogic = (e?: any) => {
setAuthenticateOpen(!authenticateOpen);
if (onAuthenticateFunction == `Set Grid`) {
const unAuthGrids = globalUserData?.grids?.filter(gr => !AuthGrids?.includes(gr?.gridType));
hardSetSelectedGrid(unAuthGrids[0], globalUserData?.grids);
}
}

return (
<Dialog
open={authenticateOpen}
onClose={(e) => setAuthenticateOpen(!authenticateOpen)}
onClose={(e) => onCloseLogic(e)}
slotProps={{
paper: {
component: `form`,
Expand All @@ -35,28 +63,10 @@ export default function AuthenticationDialog({ }: any) {
const formData = new FormData(event.currentTarget);
const formJson = Object.fromEntries((formData as any).entries());
const { password } = formJson;
// const switchGrid = () => {
// setAuthenticateOpen(false);
// switchSelectedGrid(user, upNextGrid);
// // let usrGridURL = `/user/${user?.rank}/grids/${upNextGrid?.rank}`;
// // router.replace(usrGridURL, undefined, {
// // shallow: true,
// // });
// }
// const setGrid = () => {
// setAuthenticateOpen(false);
// setSelectedGrd(upNextGrid);
// // let usrGridURL = `/user/${user?.rank}/grids/${upNextGrid?.rank}`;
// // router.replace(usrGridURL, undefined, {
// // shallow: true,
// // });
// }
const deleteAndCloseDialog = () => {
setAuthenticateOpen(false);
deleteUserFromDatabases();
}
if (onAuthenticateFunction == `Default`) {
onAuthenticate(user, password, deleteAndCloseDialog, event);
} else if (onAuthenticateFunction == `Set Grid`) {
onAuthenticate(user, password, setAuthGrid, event);
}
},
},
Expand Down
11 changes: 7 additions & 4 deletions components/modals/authenticate/authenticate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,20 @@ export const onAuthenticate = (usr: User, password: string, onAuthenticatedFunct
let lastAttemptWithin24Hours = withinXTime(lastAttempt, defaultTimePass, defaultInterval);

signInWithEmailAndPassword(auth, email, password).then(async (userCredential) => {
if (userCredential != null) {
const successfulAuthentication = userCredential != null;
if (successfulAuthentication) {
let closeButton: any = document.querySelector(`.alertButton`);
if (closeButton) closeButton.click();
updateDocFieldsWTimeStamp(usr, { 'auth.lastAuthenticated': date });
updateDocFieldsWTimeStamp(usr, { [`auth.attempts`]: 0, [`auth.lastAuthenticated`]: date });
onAuthenticatedFunction(usr);
}
}).catch((error) => {
if (lastAttemptWithin24Hours == true) {
if (nextAttemptNumber <= maxAuthAttempts) {
attemptsToUse = nextAttemptNumber;
updateDocFieldsWTimeStamp(usr, { 'auth.attempts': attemptsToUse, 'auth.lastAttempt': date });
let attemptsRemaining = maxAuthAttempts - attemptsToUse;
toast.warn(`${attemptsRemaining} Attempts Left`);
updateDocFieldsWTimeStamp(usr, { [`auth.attempts`]: attemptsToUse, [`auth.lastAttempt`]: date });
} else {
const errorMessage = error.message;
const nextTryDate = moment(new Date(lastAttempt))?.add(defaultTimePass, defaultInterval)?.format(momentFormats?.default);
Expand All @@ -56,7 +59,7 @@ export const onAuthenticate = (usr: User, password: string, onAuthenticatedFunct
}
}
}
} else updateDocFieldsWTimeStamp(usr, { 'auth.attempts': 1, 'auth.lastAttempt': date });
} else updateDocFieldsWTimeStamp(usr, { [`auth.attempts`]: 1, [`auth.lastAttempt`]: date });

return;
});
Expand Down
11 changes: 8 additions & 3 deletions components/selector/multi-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,20 @@ const MultiSelector = forwardRef((props: any, ref) => {
placeholder = `Start Typing or Click Here`,
} = props;

let { user, selectedGrid, activeOptions, setActiveOptions } = useContext<any>(StateContext);
let { user, selectedGrid, activeOptions, setActiveOptions, openAuthenticationForm, userRecentlyAuthenticated } = useContext<any>(StateContext);

let [hoveringOver, setHoveringOver] = useState(false);

const onChangeValue = (val) => {
if (single) val = isValid(val) && val?.length > 0 ? [val[val.length - 1]] : [];
if (single && val?.length == 0) return;
setActiveOptions(val);
onChange(val);

const updateSelection = () => {
setActiveOptions(val);
onChange(val);
}

updateSelection();
}

useImperativeHandle(ref, () => ({
Expand Down
30 changes: 30 additions & 0 deletions components/time.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import moment from 'moment-timezone';
import { StateContext } from '../pages/_app';
import { useContext, useEffect } from 'react';
import { momentFormats } from '../shared/constants';

export default function Time({ dynamic = true, wSeconds = true }) {
const { currentTime, setCurrentTime } = useContext<any>(StateContext);

useEffect(() => {
const updateTime = () => {
const format = wSeconds ? momentFormats.wSeconds : momentFormats.default;
setCurrentTime(moment().format(format));
}

updateTime();

if (dynamic == true) {
const interval = setInterval(updateTime, 1000);
return () => clearInterval(interval);
}
}, [dynamic, wSeconds])

return <>
<div className={`timeComponent`}>
<div className={`timeElement`}>
{currentTime}
</div>
</div>
</>
}
1 change: 1 addition & 0 deletions main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@use './styles/grids';
@use './styles/utility';
@use './styles/columns';
@use './styles/migration';
@use './styles/contextmenu';
@use './shared/admin/features';
@use './styles/itemsoverwrite';
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "product-ivf",
"version": "5.5.0",
"version": "5.6.0",
"description": "Nextra docs template",
"scripts": {
"dev": "next dev",
Expand Down
Loading

1 comment on commit ea1451e

@vercel
Copy link

@vercel vercel bot commented on ea1451e Mar 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.