GS Onboarding (backend and frontend)#10
Conversation
Yarik-Popov
left a comment
There was a problem hiding this comment.
Overall good start on the backend. Ill review the frontend later. Some changes are needed
backend/api/endpoints/command.py
Outdated
| num_commands = len(items) | ||
|
|
||
| command = Command ( | ||
| id=1+num_commands, |
There was a problem hiding this comment.
You dont need this as its error prone. Let the orm handle the auto increment
backend/api/endpoints/command.py
Outdated
| try: | ||
| query = select(Command).where(Command.id == id) | ||
| command = db.exec(query).one() | ||
| db.delete(command) | ||
| db.commit() | ||
|
|
||
| query2 = select(Command).where(Command.id != id) | ||
| items = db.exec(query2).all() | ||
| return {"data": items} | ||
| except: | ||
| raise HTTPException(status_code=404, detail="Item does not exist") No newline at end of file |
There was a problem hiding this comment.
The orm will not raise an exception if an item doesnt exist. It will return None and you should check against it
| from fastapi import Request, Response | ||
| from starlette.middleware.base import BaseHTTPMiddleware | ||
|
|
||
| from ...utils.logging import logger |
backend/data/data_models.py
Outdated
| # TODO: (Member) Implement this method | ||
| return self | ||
|
|
||
| if (self.params == None and self.format == None): |
There was a problem hiding this comment.
Dont compare using == against None use is None instead. Also you dont need the extra () for if and elif, while statements
backend/data/data_models.py
Outdated
| if (self.params == None and self.format == None): | ||
| return self | ||
| elif (self.params == None or self.format == None): | ||
| raise(ValueError) |
There was a problem hiding this comment.
The proper syntax is raise ValueError() as your case throws the class and not the instance.
backend/data/data_models.py
Outdated
| elif (len(self.params.split(",")) == len(self.format.split(","))): | ||
| return self | ||
| else: | ||
| raise(ValueError) |
| # TODO: Figure out a better way to check the times | ||
| assert result.get("created_on") | ||
| assert result.get("updated_on") | ||
| created_on_dt = datetime.fromisoformat(result.get("created_on")) | ||
| updated_on_dt = datetime.fromisoformat(result.get("updated_on")) | ||
| assert isinstance(created_on_dt, datetime) | ||
| assert isinstance(updated_on_dt, datetime) |
There was a problem hiding this comment.
Thanks. Not a part of the onboarding but definitely something that can be improved. Ill link this in the task to improve the gs onboarding.
Yarik-Popov
left a comment
There was a problem hiding this comment.
Good step in the right direction. Looks like I forgot to submit my requested changes for the frontend earlier. Sorry about that but all the requested changes are here for both the frontend and backend.
frontend/src/input/command_input.tsx
Outdated
| let paramsObject : { [key: string]: string } = {} | ||
| for(const param of parameters) { | ||
| paramsObject[param] = "" | ||
| } |
There was a problem hiding this comment.
Theres a bug if you input data into a text field then switch the type. The text field still has the data displayed but then you click submit it says missing parameter. It might be due to this and the fact that the input does have a value property
frontend/src/input/command_input.tsx
Outdated
|
|
||
| {/* TODO: (Member) Add input handling here if the selected command has a param input*/} | ||
| {commandType && | ||
| commandType.params?.split(",").map((param) => (<input id={param} placeholder={`Enter ${param}`} onChange={changeParam}/>))} |
There was a problem hiding this comment.
This should have a value property that is an individual param. It should fix the bug i described above
frontend/src/input/command_input.tsx
Outdated
| setParams(paramsObject); | ||
| } | ||
|
|
||
| const changeParam = (e: any) => { |
There was a problem hiding this comment.
Use a specific type here insteas of any or if you dont know the type use unknown
frontend/src/input/command_input.tsx
Outdated
| //console.log(`Command: `, commandType) | ||
| //console.log(`Parameters: `, params) | ||
|
|
||
| const changeCommandType = (e: any) => { |
There was a problem hiding this comment.
Use a specific type here instead of any. Or if you dont know the type, use unknown as it is safer
frontend/src/input/command_input.tsx
Outdated
| /* | ||
| <input value={params} onChange={(e) => setParams(e.target.value)}/> | ||
| {// Use parameters of command type to output input boxes} | ||
| { .params.map(param => (<input id={} value={}>{cmd.name}</option>))} | ||
| */ | ||
| //console.log(`Command: `, commandType) | ||
| //console.log(`Parameters: `, params) |
There was a problem hiding this comment.
Do not leave code commented out. If its not needed remove it. This also applies to line 52
backend/data/data_models.py
Outdated
| elif len(self.params.split(",")) == len(self.format.split(",")): | ||
| return self | ||
| else: | ||
| raise ValueError() |
There was a problem hiding this comment.
Add a descriptive error message
frontend/src/input/command_input.tsx
Outdated
|
|
||
| setCommandType(data.data[0]) | ||
|
|
||
| const parameters = commandType?.params?.split(",") || [] |
There was a problem hiding this comment.
commandType will be null on the first render but not sure if it matters here
frontend/src/input/command_input.tsx
Outdated
| // TODO: (Member) Setup state and useEffect calls here | ||
| const [mainCommands, setMainCommands] = useState<MainCommandResponse[]>([]) | ||
| const [commandType, setCommandType] = useState<MainCommandResponse | null>(null) | ||
| const [params, setParams] = useState<{[key: string] : string}>({}) |
There was a problem hiding this comment.
Probably use a custom type instead of {[key: string]: string} maybe look into StringMap
frontend/src/input/command_input.tsx
Outdated
| const paramsList = [] | ||
| for (const param of allParams) { | ||
| if (!params[param]) { | ||
| alert("Parameter missing") |
There was a problem hiding this comment.
From a UX perspective probably best to indicate which parameter is missing
Yarik-Popov
left a comment
There was a problem hiding this comment.
Backend lgtm. Some changes are needed on the frontend.
frontend/src/input/command_input.tsx
Outdated
| if(!data.data) { | ||
| alert("Error occured. Please try again later.") | ||
| } |
There was a problem hiding this comment.
This code will never run because an empty array in Typescript is truthy. So !data.data will always be false. Also add a return at the end of the if block. You should be comparing against the length
frontend/src/input/command_input.tsx
Outdated
| const allParams = commandType?.params?.split(",") || []; | ||
| const paramsList = [] | ||
|
|
||
| let sendAlert = false |
There was a problem hiding this comment.
The sendAlert variable is redundant you can just use the length of the missingParams array to check if there is something missing
frontend/src/input/command_input.tsx
Outdated
| const CommandInput = () => { | ||
| // TODO: (Member) Setup state and useEffect calls here | ||
| const [mainCommands, setMainCommands] = useState<MainCommandResponse[]>([]) | ||
| const [commandType, setCommandType] = useState<MainCommandResponse>({id: 0, name: "", params: null, format: null, data_size: 0, total_size: 0}) |
There was a problem hiding this comment.
I think having null as the default value and checking against it in the code would probably be better than having a default object.
frontend/src/input/command_input.tsx
Outdated
| } | ||
|
|
||
| const changeCommandType = (e: React.ChangeEvent<HTMLSelectElement>) => { | ||
| const type : MainCommandResponse = mainCommands.find(cmd => cmd.id == +e.target.value) || {id: 0, name: "", params: null, format: null, data_size: 0, total_size: 0} |
There was a problem hiding this comment.
Just let type be undefined and show an alert that an error occurred and return from the function. Also, probably not a good idea to use type as a variable name as it is a soft keyword in Typescript
Yarik-Popov
left a comment
There was a problem hiding this comment.
Do not use loose equals. Should be last set of changes
frontend/src/input/command_input.tsx
Outdated
| useEffect(() => { | ||
| const setMainCommandsFn = async () => { | ||
| const data = await getMainCommands() | ||
| if(data.data.length == 0) { |
There was a problem hiding this comment.
Do not use double equals == in comparisons. Use ===
There was a problem hiding this comment.
Because == is loosely equal. Example:
0 == [] // true
0 == '0' //true
But:
[] == '0' // false
There was a problem hiding this comment.
Here's even more cursed things about javascript:
0 < null // false
0 > null // false
0 == null // false
But
0 <= null // true
0 >= null // true
But if you were to replace all of the null above with undefined, they would all be false
There was a problem hiding this comment.
You can disregard the last 2 comments in the thread, they are just me showing you some trivia about js and why we use Typescript
frontend/src/input/command_input.tsx
Outdated
| } | ||
| paramsList.push(params.get(param)) | ||
| } | ||
| if(missingParams.length != 0) { |
There was a problem hiding this comment.
Do not use != in comparisons. Use !== instead
|
Lgtm. Dm me your email and ill add u to the notion |
No description provided.