Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/multiple sessions one window #225

Merged
merged 32 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d5c1438
feat: added a calls-page for desktop to redirect to, direct-link used…
malmen237 Nov 29, 2024
94f6f58
feat: added global call-state to handle everything to do with individ…
malmen237 Nov 29, 2024
d12eb50
feat: modyfied error-state to separate between call-errors and genera…
malmen237 Nov 29, 2024
3543a2d
fix: updated the exit-calls to match current multiple-calls structure
malmen237 Nov 29, 2024
6d570f4
fix: updated the copy-link for new productions to fit current structure
malmen237 Nov 29, 2024
4088d18
fix: updated to also fit when adding additional call and modified to …
malmen237 Nov 29, 2024
d7b6798
fix: updated to new state-structure fot direct-linking to work
malmen237 Nov 29, 2024
2a0f575
fix: updated to new state-structure for multiple calls
malmen237 Nov 29, 2024
39a7417
fix: updated to new state-structure for multiple calls and removed re…
malmen237 Nov 29, 2024
f5c0ba6
feat: changed to peerconnection-ref to allow flexibility, updated to …
malmen237 Nov 29, 2024
ed9180a
fix: project updates and installations
malmen237 Nov 29, 2024
0a63b69
feat: added return to main if no calls, no exit-call if single-call o…
malmen237 Nov 29, 2024
70a3e30
Update src/components/production-line/production-line.tsx
malmen237 Dec 2, 2024
f5a8b5c
fix: added saved-prod-id when manually adding id, removed unused call…
malmen237 Nov 29, 2024
cd0ced0
feat: added local-storage-hook, minor lint-fix
malmen237 Dec 2, 2024
98e5382
fix: updated uuid to crypto-randomuuid
malmen237 Dec 5, 2024
5bc5117
fix: removed unused peerconnection from callstate
malmen237 Dec 5, 2024
d6d7010
feat: added storage-ts instead of local-storage and reinstalled yarn
malmen237 Dec 5, 2024
ee7472c
fix: removed unnecessary check for call-id in state-reducer
malmen237 Dec 5, 2024
888f49e
fix: removed duplicate id from callstate
malmen237 Dec 5, 2024
0860a2a
feat: added confirmation-modal to all leave-call-buttons
malmen237 Dec 5, 2024
b928154
test: updated code to allow multiple calls on mobile
malmen237 Dec 9, 2024
82879c8
fix: added reset to confirmation-modal on header
malmen237 Dec 10, 2024
4676b01
fix: added a close-join-line-view when line has been added
malmen237 Dec 10, 2024
964b878
fix: updated verify-modal to ask yes or no
malmen237 Dec 10, 2024
6af4a9c
fix: moved the navigation-hook-call from the landing-page to the join…
malmen237 Dec 10, 2024
a2ba531
fix: removed old solution left during testing
malmen237 Dec 10, 2024
e3972ab
fix: added comments and solution from pr with device-change
malmen237 Dec 10, 2024
63a4d29
fix: removed boolean that blocked single-line-remove-btn from mobile
malmen237 Dec 10, 2024
ef15f8e
fix: made modal more visable
malmen237 Dec 10, 2024
dc659dc
feat: moved symphony-connection-items into own component and added va…
malmen237 Dec 13, 2024
c4d153c
fix: removed peerconnection-changes from use-rtcconnection
malmen237 Dec 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions aws/cloudfront-functions/README.md

This file was deleted.

39 changes: 0 additions & 39 deletions aws/cloudfront-functions/url-rewrite-spa.yaml

This file was deleted.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@emotion/styled": "^11.11.5",
"@eyevinn/media-event-filter": "^3.4.0",
"@hookform/error-message": "^2.0.1",
"@martinstark/storage-ts": "^1.1.0",
"@types/react-router-dom": "^5.3.3",
"bowser": "^2.11.0",
"react": "^18.3.1",
Expand Down
6 changes: 3 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { BrowserRouter, Routes, Route } from "react-router-dom";
import styled from "@emotion/styled";
import { useState } from "react";
import { ProductionLine } from "./components/production-line/production-line.tsx";
import { ErrorPage } from "./components/router-error.tsx";
import { useDevicePermissions } from "./use-device-permission.ts";
import { LandingPage } from "./components/landing-page/landing-page.tsx";
Expand All @@ -19,6 +18,7 @@ import { ManageProductions } from "./components/manage-productions/manage-produc
import { isValidBrowser } from "./bowser.ts";
import { DisplayContainerHeader } from "./components/landing-page/display-container-header.tsx";
import { NavigateToRootButton } from "./components/navigate-to-root-button/navigate-to-root-button.tsx";
import { CallsPage } from "./components/calls-page/calls-page.tsx";

const DisplayBoxPositioningContainer = styled(FlexContainer)`
justify-content: center;
Expand Down Expand Up @@ -126,8 +126,8 @@ const App = () => {
errorElement={<ErrorPage />}
/>
<Route
path="/production/:productionId/line/:lineId"
element={<ProductionLine />}
path="/production-calls/production/:productionId/line/:lineId"
element={<CallsPage />}
errorElement={<ErrorPage />}
/>
<Route path="*" element={<NotFound />} />
Expand Down
5 changes: 5 additions & 0 deletions src/assets/icons/campaign_off.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/icons/campaign_on.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions src/components/accessing-local-storage/access-local-storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useCallback } from "react";
import { createStorage, StorageType } from "@martinstark/storage-ts";

type Schema = {
username: string;
};

// Create a store of the desired type. If it is not available,
// in-memory storage will be used as a fallback.
const store = createStorage<Schema>({
type: StorageType.LOCAL,
prefix: "id",
silent: true,
});

export function useStorage<Key extends keyof Schema>(key: Key) {
const readFromStorage = useCallback((): Schema[Key] | null => {
return store.read(key);
}, [key]);

const writeToStorage = useCallback(
(value: Schema[Key]): void => {
store.write(key, value);
},
[key]
);

return { readFromStorage, writeToStorage };
}
151 changes: 151 additions & 0 deletions src/components/calls-page/calls-page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import styled from "@emotion/styled";
import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useGlobalState } from "../../global-state/context-provider";
import { JoinProduction } from "../landing-page/join-production";
import { ProductionLine } from "../production-line/production-line";
import { SecondaryButton } from "../landing-page/form-elements";
import { NavigateToRootButton } from "../navigate-to-root-button/navigate-to-root-button";
import { DisplayContainerHeader } from "../landing-page/display-container-header";
import { Modal } from "../modal/modal";
import { VerifyDecision } from "../verify-decision/verify-decision";
import { ModalConfirmationText } from "../modal/modal-confirmation-text";

const Container = styled.div`
display: flex;
flex-direction: column;
flex-wrap: wrap;
padding: 2rem;
`;

const CallsContainer = styled.div`
display: flex;
flex-direction: row;
flex-wrap: wrap;
padding: 2rem;
`;

const CallContainer = styled.div`
display: flex;
flex-direction: column;
padding: 2rem;
max-width: 40rem;
min-width: 30rem;
`;

const AddCallContainer = styled.div`
display: flex;
flex-direction: column;
padding: 4rem;
max-width: 40rem;
min-width: 30rem;
`;

const ButtonWrapper = styled.div`
margin: 0 1rem 1rem 0;
:last-of-type {
margin: 0 0 4rem;
}
`;

export const CallsPage = () => {
const [productionId, setProductionId] = useState<string | null>(null);
const [addCallActive, setAddCallActive] = useState(false);
const [confirmExitModalOpen, setConfirmExitModalOpen] = useState(false);
const [{ calls, selectedProductionId }, dispatch] = useGlobalState();
const { productionId: paramProductionId, lineId: paramLineId } = useParams();
const navigate = useNavigate();

const isEmpty = Object.values(calls).length === 0;
const isSingleCall = Object.values(calls).length === 1;

useEffect(() => {
if (selectedProductionId) {
setProductionId(selectedProductionId);
}
}, [selectedProductionId]);

useEffect(() => {
if (isEmpty && !paramProductionId && !paramLineId) {
navigate("/");
}
}, [isEmpty, paramProductionId, paramLineId, navigate]);

const runExitAllCalls = async () => {
setProductionId(null);
navigate("/");
Object.entries(calls).forEach(([callId]) => {
if (callId) {
dispatch({
type: "REMOVE_CALL",
payload: { id: callId },
});
}
});
};

return (
<Container>
<ButtonWrapper>
<NavigateToRootButton
resetOnExitRequest={() => setConfirmExitModalOpen(true)}
/>
{confirmExitModalOpen && (
<Modal onClose={() => setConfirmExitModalOpen(false)}>
<DisplayContainerHeader>Confirm</DisplayContainerHeader>
<ModalConfirmationText>
Are you sure you want to leave all calls?
</ModalConfirmationText>
<VerifyDecision
confirm={runExitAllCalls}
abort={() => setConfirmExitModalOpen(false)}
/>
</Modal>
)}
</ButtonWrapper>
<CallsContainer>
{Object.entries(calls).map(
([callId, callState]) =>
callId &&
callState.joinProductionOptions && (
<CallContainer key={callId}>
<ProductionLine
id={callId}
callState={callState}
isSingleCall={isSingleCall}
/>
</CallContainer>
)
)}
{!isEmpty && (
<AddCallContainer>
<ButtonWrapper>
<SecondaryButton
type="button"
onClick={() => setAddCallActive(!addCallActive)}
>
Add Call
</SecondaryButton>
</ButtonWrapper>
{addCallActive && productionId && (
<JoinProduction
addAdditionalCallId={productionId}
closeAddCallView={() => setAddCallActive(false)}
/>
)}
</AddCallContainer>
)}
{isEmpty && paramProductionId && paramLineId && (
<CallContainer>
<JoinProduction
preSelected={{
preSelectedProductionId: paramProductionId,
preSelectedLineId: paramLineId,
}}
/>
</CallContainer>
)}
</CallsContainer>
</Container>
);
};
75 changes: 58 additions & 17 deletions src/components/error.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import styled from "@emotion/styled";
import { FC } from "react";
import { FC, useEffect, useState } from "react";
import { errorColour } from "../css-helpers/defaults";
import { useGlobalState } from "../global-state/context-provider";

Expand Down Expand Up @@ -29,25 +29,66 @@ const CloseErrorButton = styled.button`
`;

export const ErrorBanner: FC = () => {
const [callError, setCallError] = useState<string[] | null>(null);
const [{ error }, dispatch] = useGlobalState();

useEffect(() => {
const displayedMessages = new Set<string>();
if (error.callErrors) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Object.entries(error.callErrors).forEach(([_, singleError]) => {
// _ is needed to destructure the object
if (singleError && !displayedMessages.has(singleError.message)) {
console.error(`Error:`, singleError.message); // Display only unique errors
displayedMessages.add(singleError.message);
}
});
const uniqueErrors = Array.from(displayedMessages);
setCallError(uniqueErrors);
}
}, [error.callErrors]);

const resetError = () => {
if (error.callErrors) {
Object.entries(error.callErrors).forEach(([callId]) => {
setCallError(null);
dispatch({
type: "ERROR",
payload: { callId, error: null },
});
});
}
};

return (
error && (
<ErrorDisplay>
{`${error.name}: ${error.message}`}{" "}
<CloseErrorButton
type="button"
onClick={() =>
dispatch({
type: "ERROR",
payload: null,
})
}
>
close
</CloseErrorButton>
</ErrorDisplay>
)
<>
{error.globalError && (
<ErrorDisplay>
{`${error.globalError.name}: ${error.globalError.message}`}{" "}
<CloseErrorButton
type="button"
onClick={() =>
dispatch({
type: "ERROR",
payload: { error: null },
})
}
>
close
</CloseErrorButton>
</ErrorDisplay>
)}
{callError &&
error.callErrors &&
callError.map((uniqueErrors) => (
<ErrorDisplay key={uniqueErrors}>
{uniqueErrors}{" "}
<CloseErrorButton type="button" onClick={() => resetError()}>
close
</CloseErrorButton>
</ErrorDisplay>
))}
</>
);
};

Expand Down
Loading
Loading