From 5902ca0201db9ee66f86064ac498f19305e3869b Mon Sep 17 00:00:00 2001 From: TaylorS15 Date: Sun, 19 Feb 2023 15:26:27 -0500 Subject: [PATCH] added modal to select source documentation --- frontend/src/Navigation.tsx | 31 ++++- frontend/src/api/docs.ts | 18 +++ frontend/src/models/misc.ts | 11 ++ frontend/src/preferences/SelectDocsModal.tsx | 122 +++++++++++++++++++ frontend/src/preferences/preferenceSlice.ts | 12 +- 5 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 frontend/src/api/docs.ts create mode 100644 frontend/src/preferences/SelectDocsModal.tsx diff --git a/frontend/src/Navigation.tsx b/frontend/src/Navigation.tsx index 2b4fd23..51990ea 100644 --- a/frontend/src/Navigation.tsx +++ b/frontend/src/Navigation.tsx @@ -6,8 +6,12 @@ import Info from './assets/info.svg'; import Link from './assets/link.svg'; import { ActiveState } from './models/misc'; import APIKeyModal from './preferences/APIKeyModal'; +import SelectDocsModal from './preferences/SelectDocsModal'; import { useSelector } from 'react-redux'; -import { selectApiKeyStatus } from './preferences/preferenceSlice'; +import { + selectApiKeyStatus, + selectSelectedDocsStatus, +} from './preferences/preferenceSlice'; import { useState } from 'react'; //TODO - Need to replace Chat button to open secondary nav with scrollable past chats option and new chat at top @@ -24,6 +28,11 @@ export default function Navigation({ const [apiKeyModalState, setApiKeyModalState] = useState( isApiKeySet ? 'INACTIVE' : 'ACTIVE', ); + + const isSelectedDocsSet = useSelector(selectSelectedDocsStatus); + const [selectedDocsModalState, setSelectedDocsModalState] = + useState(isSelectedDocsSet ? 'INACTIVE' : 'ACTIVE'); + return ( <>
-
+
{ @@ -59,6 +68,18 @@ export default function Navigation({ key

Reset Key

+ +
{ + setSelectedDocsModalState('ACTIVE'); + }} + > + key +

+ Select Source Documentation +

+
@@ -87,11 +108,17 @@ export default function Navigation({ > menu toggle + + ); } diff --git a/frontend/src/api/docs.ts b/frontend/src/api/docs.ts new file mode 100644 index 0000000..1a219ad --- /dev/null +++ b/frontend/src/api/docs.ts @@ -0,0 +1,18 @@ +import { Doc } from '../models/misc'; + +export async function getDocs(): Promise> { + //Fetch default source docs + const response = await fetch( + 'https://d3dg1063dc54p9.cloudfront.net/combined.json', + ); + const data = await response.json(); + + //Create array of Doc objects + const docs: Array = []; + + data.forEach((doc: Doc) => { + docs.push(doc); + }); + + return docs; +} diff --git a/frontend/src/models/misc.ts b/frontend/src/models/misc.ts index dbf21ae..5f9ed13 100644 --- a/frontend/src/models/misc.ts +++ b/frontend/src/models/misc.ts @@ -3,3 +3,14 @@ export type ActiveState = 'ACTIVE' | 'INACTIVE'; export type User = { avatar: string; }; + +export type Doc = { + name: string; + language: string; + version: string; + description: string; + fullName: string; + dat: string; + docLink: string; + model: string; +}; diff --git a/frontend/src/preferences/SelectDocsModal.tsx b/frontend/src/preferences/SelectDocsModal.tsx new file mode 100644 index 0000000..47d63ab --- /dev/null +++ b/frontend/src/preferences/SelectDocsModal.tsx @@ -0,0 +1,122 @@ +import { useEffect, useState } from 'react'; +import { useDispatch } from 'react-redux'; +import { ActiveState, Doc } from '../models/misc'; +import { setSelectedDocs, selectSelectedDocs } from './preferenceSlice'; +import { getDocs } from '../api/docs'; + +export default function APIKeyModal({ + modalState, + setModalState, + isCancellable = true, +}: { + modalState: ActiveState; + setModalState: (val: ActiveState) => void; + isCancellable?: boolean; +}) { + const dispatch = useDispatch(); + const [isError, setIsError] = useState(false); + const [docs, setDocs] = useState([]); + const [localSelectedDocs, setLocalSelectedDocs] = useState(null); + const [isDocsListOpen, setIsDocsListOpen] = useState(false); + + function handleSubmit() { + if (!localSelectedDocs) { + setIsError(true); + } else { + dispatch(setSelectedDocs(localSelectedDocs)); + setModalState('INACTIVE'); + setLocalSelectedDocs(null); + setIsError(false); + } + } + + function handleCancel() { + setSelectedDocs(null); + setIsError(false); + setModalState('INACTIVE'); + } + + useEffect(() => { + async function requestDocs() { + const data = await getDocs(); + setDocs(data); + } + + requestDocs(); + }, []); + + return ( +
+
+

Select Source Documentation

+

+ Please select the library of documentation that you would like to use + with our app. +

+
+
setIsDocsListOpen(!isDocsListOpen)} + > + {!localSelectedDocs ? ( +

Select

+ ) : ( +

+ {localSelectedDocs.name} {localSelectedDocs.version} +

+ )} +
+ {isDocsListOpen && ( +
+ {docs.map((doc, index) => { + if (doc.model) { + return ( +
{ + setLocalSelectedDocs(doc); + setIsDocsListOpen(false); + }} + className="h-10 w-full cursor-pointer border-x-2 border-b-2 hover:bg-gray-100" + > +

+ {doc.name} {doc.version} +

+
+ ); + } + })} +
+ )} +
+
+ {isCancellable && ( + + )} + {' '} + {isError && ( +

+ Please select source documentation. +

+ )} +
+
+
+ ); +} diff --git a/frontend/src/preferences/preferenceSlice.ts b/frontend/src/preferences/preferenceSlice.ts index 6121f9d..0323a5b 100644 --- a/frontend/src/preferences/preferenceSlice.ts +++ b/frontend/src/preferences/preferenceSlice.ts @@ -1,12 +1,15 @@ import { createSlice } from '@reduxjs/toolkit'; +import { Doc } from '../models/misc'; import store from '../store'; interface Preference { apiKey: string; + selectedDocs: Doc | null; } const initialState: Preference = { apiKey: '', + selectedDocs: null, }; export const prefSlice = createSlice({ @@ -16,10 +19,13 @@ export const prefSlice = createSlice({ setApiKey: (state, action) => { state.apiKey = action.payload; }, + setSelectedDocs: (state, action) => { + state.selectedDocs = action.payload; + }, }, }); -export const { setApiKey } = prefSlice.actions; +export const { setApiKey, setSelectedDocs } = prefSlice.actions; export default prefSlice.reducer; type RootState = ReturnType; @@ -27,3 +33,7 @@ type RootState = ReturnType; export const selectApiKey = (state: RootState) => state.preference.apiKey; export const selectApiKeyStatus = (state: RootState) => !!state.preference.apiKey; +export const selectSelectedDocs = (state: RootState) => + state.preference.selectedDocs; +export const selectSelectedDocsStatus = (state: RootState) => + !!state.preference.selectedDocs;