Skip to content

Commit

Permalink
Merge pull request #27 from catalystneuro/feature/previous-project-logs
Browse files Browse the repository at this point in the history
feat: add previous project logs button
  • Loading branch information
nathan-vm authored Jun 24, 2024
2 parents a3a194b + 2cf3617 commit 226d36a
Show file tree
Hide file tree
Showing 12 changed files with 244 additions and 31 deletions.
21 changes: 19 additions & 2 deletions src/backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,14 +344,31 @@ def post(self):
# NOTE: Should lock access to the file
pass


@api.route('/log')
class CurrentLog(Resource):
@api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
def get(self):
return open(CURRENT_LOG_FILE, "r").read()


@api.route('/log/<path:log_name>')
class ProjectLog(Resource):
@api.doc(responses={200: "Success", 400: "Bad Request",404: "Not found", 500: "Internal server error"})
def get(self, log_name):

project_path = request.args.get('project')
project_path = Path(project_path)

if(log_name):
log_path = Path(project_path) / "logs" / f"{log_name}.log"
if log_path.is_file():
log = open(log_path, "r").read()
return log
else:
return f"{log_name} log not found.", 404

return "missing log_name", 400

@api.route('/load')
class Load(Resource):
@api.doc(responses={200: "Success", 400: "Bad Request", 500: "Internal server error"})
Expand Down Expand Up @@ -669,7 +686,7 @@ def post(self):
data, project_path = resolve_request_data(request)
vame.visualization(
**data,
# save_logs=True
save_logs=True
)
return dict(result=get_visualization_images(project_path))
except Exception as exception:
Expand Down
3 changes: 2 additions & 1 deletion src/frontend/Pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ class Pipeline {

this.data = {
videos: result.videos,
csvs: result.csvs
csvs: result.csvs,
logs: result.logs
}

this.workflow = result.workflow
Expand Down
51 changes: 51 additions & 0 deletions src/frontend/components/TerminalModal/LogComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { TerminalDiv } from './styles';
import { get } from '../../utils/requests';

interface TerminalProps {
logName?: string;
projectPath: string;
}

const LogComponent: React.FC<TerminalProps> = ({ logName,projectPath }) => {
const logRef = useRef<HTMLUListElement>(null);
const [logs, setLogs] = useState('');

const fetchLogs = useCallback(async () => {
try {
let uri = "log"
if (logName && projectPath) uri = `log/${logName}?project=${projectPath}`
const url = encodeURI(uri)

const logResponse = await get(url, { 'Content-Type': 'text/plain' })
setLogs(logResponse as string);
} catch {
setLogs(logName ? `No log files found for: ${logName}` : `No log files found.`);
}
},[logName,projectPath])

useEffect(() => {
fetchLogs()
}, []);

useEffect(() => {
logRef.current?.lastElementChild?.scrollIntoView()
}, [logs]);


if (!logs) return (<TerminalDiv id={logName ? `terminal-${logName}` : "terminal"}><li><span>Loading {logName} logs file...</span></li></TerminalDiv>)

return (
<TerminalDiv ref={logRef} id={logName ? `terminal-${logName}` : "terminal"}>
{logs.split('\n').map((line, index) => (
<li key={index}>
<span>
{line}
</span>
</li>
))}
</TerminalDiv>
);
};

export default LogComponent;
37 changes: 37 additions & 0 deletions src/frontend/components/TerminalModal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { FC, MouseEventHandler, useCallback, useRef } from "react";
import LogComponent from "./LogComponent";
import { BaseModalBackground, TerminalContainer } from "./styles";

interface ModalProps {
projectPath: string;
logName: string | string[];
isOpen: boolean;
onClose: () => void;
}

const TerminalModal: FC<ModalProps> = ({ isOpen, onClose, logName,projectPath }) => {

const node = useRef(null)

const handleBackgroundClick = useCallback<MouseEventHandler<HTMLDivElement>>((e)=>{

if (node.current === e.target) {
onClose()
}
},[node])

return (
<>
{isOpen &&
<BaseModalBackground onClick={handleBackgroundClick} ref={node}>
{typeof logName === "string" ? <LogComponent logName={logName} projectPath={projectPath} /> : (
<TerminalContainer >
{logName?.map(l=><LogComponent key={l} logName={l} projectPath={projectPath} />)}
</TerminalContainer>
)}
</BaseModalBackground>}
</>
)
}

export default TerminalModal
50 changes: 50 additions & 0 deletions src/frontend/components/TerminalModal/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import styled from 'styled-components';

export const BaseModalBackground = styled.div`
display: flex;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 30;
background-color: rgba(0, 0, 0, 0.5);
align-items: center;
justify-content: center;
`

export const TerminalContainer = styled.div`
border-radius: 20px;
overflow: hidden;
display: flex;
flex-direction: row;
justify-content: space-between;
width: 80%;
height: 80%;
max-width: 80%;
max-height: 80%;
`;

export const TerminalDiv = styled.ul`
width: 100%;
margin: 0;
scroll-behavior: smooth;
list-style: none;
padding: 10px;
overflow: hidden;
background-color: #181c24;
overflow-y: auto !important;
color: white;
font-family: monospace;
font-size: 12px;
li {
padding: 5px;
}
`;
7 changes: 7 additions & 0 deletions src/frontend/tabs/CommunityAnalysis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import { PaddedTab} from "../components/elements"

import communitySchema from '../../schema/community.schema.json'
import { TabProps } from "./types"
import TerminalModal from "../components/TerminalModal"
import { useState } from "react"

const CommunityAnalysis = ({
pipeline,
onFormSubmit,
block
}: TabProps) => {
const [terminal, setTerminal] = useState(false)

const schema = structuredClone(communitySchema)

Expand All @@ -20,6 +23,10 @@ const CommunityAnalysis = ({

return (
<PaddedTab>
<button onClick={()=>setTerminal(true)}>Open logs</button>

<TerminalModal projectPath={pipeline.path} logName={["community"]} isOpen={terminal} onClose={()=>setTerminal(false)}/>

<DynamicForm
initialValues={{}}
schema={schema}
Expand Down
10 changes: 9 additions & 1 deletion src/frontend/tabs/CommunityVideos.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useState } from "react"
import DynamicForm from "../components/DynamicForm"
import { PaddedTab} from "../components/elements"
import TerminalModal from "../components/TerminalModal"
import { VideoGrid } from "../components/VideoGrid"
import { TabProps } from "./types"

Expand All @@ -8,6 +10,7 @@ const CommunityVideos = ({
onFormSubmit,
block
}: TabProps) => {
const [terminal, setTerminal] = useState(false)

const hasCommunityVideos = pipeline.workflow.community_videos_created

Expand Down Expand Up @@ -37,7 +40,12 @@ const CommunityVideos = ({
}, {})


return VideoGrid({ videos: organizedVideos, pipeline })
return <>
<button onClick={()=>setTerminal(true)}>Open logs</button>

<TerminalModal projectPath={pipeline.path} logName={["community_videos"]} isOpen={terminal} onClose={()=>setTerminal(false)}/>
<VideoGrid videos={organizedVideos} pipeline={pipeline} />
</>
}

export default CommunityVideos
8 changes: 7 additions & 1 deletion src/frontend/tabs/Model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import Pipeline from "../Pipeline"
import { PaddedTab } from "../components/elements"
import styled from "styled-components"
import { TabProps } from "./types"
import TerminalModal from "../components/TerminalModal"
import { useState } from "react"

const FlexDiv = styled.div`
display: flex;
Expand All @@ -19,7 +21,7 @@ const Model = ({
onFormSubmit,
block
}: TabProps) => {

const [terminal, setTerminal] = useState(false)
const isModeled = pipeline.workflow.modeled

if (isModeled) {
Expand All @@ -30,6 +32,10 @@ const Model = ({

return (
<PaddedTab>
<button onClick={()=>setTerminal(true)}>Open logs</button>

<TerminalModal projectPath={pipeline.path} logName={["train_model", "evaluate_model"]} isOpen={terminal} onClose={()=>setTerminal(false)}/>

<FlexDiv>
{evaluationImages.map((imgPath => {
return <Image src={
Expand Down
11 changes: 9 additions & 2 deletions src/frontend/tabs/MotifVideos.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { useState } from "react"
import Pipeline from "../Pipeline"
import DynamicForm, { DynamicFormProps } from "../components/DynamicForm"
import { VideoGrid } from "../components/VideoGrid"
import { PaddedTab } from "../components/elements"
import { TabProps } from "./types"
import TerminalModal from "../components/TerminalModal"

const MotifVideos = ({
pipeline,
onFormSubmit,
block
}: TabProps) => {

const [terminal, setTerminal] = useState(false)

const hasMotifVideos = pipeline.workflow.motif_videos_created

Expand Down Expand Up @@ -37,7 +39,12 @@ const MotifVideos = ({
}, {})


return VideoGrid({ videos: organizedVideos, pipeline })
return <>
<button onClick={()=>setTerminal(true)}>Open logs</button>

<TerminalModal projectPath={pipeline.path} logName={["motif_videos"]} isOpen={terminal} onClose={()=>setTerminal(false)}/>
<VideoGrid videos={organizedVideos} pipeline={pipeline} />
</>
}

export default MotifVideos
14 changes: 12 additions & 2 deletions src/frontend/tabs/Organize.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { useState } from "react"

import DynamicForm from "../components/DynamicForm"
import organizeSchema from '../../schema/organize.schema.json'
import TerminalModal from "../components/TerminalModal"
import { PaddedTab } from "../components/elements"

import { TabProps } from "./types"

import organizeSchema from '../../schema/organize.schema.json'

const Organize = ({
pipeline,
onFormSubmit,
block
}: TabProps) => {

const pose_ref_index_extra_description = pipeline.workflow.pose_ref_index_description ?? ""

const schema = structuredClone(organizeSchema)
Expand All @@ -26,8 +30,14 @@ const Organize = ({
Object.values(schema.properties).forEach(v => v.readOnly = true)
}

const [terminal, setTerminal]=useState(false)

return (
<PaddedTab>
<button onClick={()=>setTerminal(true)}>Open logs</button>

<TerminalModal projectPath={pipeline.path} logName={["egocentric_alignment", "create_trainset"]} isOpen={terminal} onClose={()=>setTerminal(false)}/>

<DynamicForm
initialValues={{}}
schema={schema}
Expand Down
23 changes: 16 additions & 7 deletions src/frontend/tabs/Segmentation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,32 @@ import DynamicForm, { DynamicFormProps } from "../components/DynamicForm"
import Pipeline from "../Pipeline"
import { PaddedTab } from "../components/elements"
import { TabProps } from "./types"
import TerminalModal from "../components/TerminalModal"

const Segmentation = ({
pipeline,
onFormSubmit,
block
}: TabProps) => {

const [terminal, setTerminal] = useState(false)
const isSegmented = pipeline.workflow.segmented


return (
<PaddedTab>
{isSegmented ? <p>Pose segmentation has been completed successfully!</p> : <DynamicForm
initialValues={{}}
blockSubmission={block}
submitText="Run Pose Segmentation"
onFormSubmit={onFormSubmit}
/>}
{isSegmented ?
<>
<button onClick={() => setTerminal(true)}>Open logs</button>

<TerminalModal projectPath={pipeline.path} logName={["pose_segmentation"]} isOpen={terminal} onClose={() => setTerminal(false)} />
<p>Pose segmentation has been completed successfully!</p>
</>
: <DynamicForm
initialValues={{}}
blockSubmission={block}
submitText="Run Pose Segmentation"
onFormSubmit={onFormSubmit}
/>}
</PaddedTab>
)
}
Expand Down
Loading

0 comments on commit 226d36a

Please sign in to comment.