Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ const App: React.FC = () => {
}): [], undefined, selectedFile==null),
{type: 'divider'},
newSimulationButton,
getItem('Simulations', 'simulations', <InsertRowAboveOutlined />),
getItem('Examples', 'examples', <InsertRowAboveOutlined />),
{type: 'divider'},
runStopButton,
Expand Down
4 changes: 4 additions & 0 deletions src/containers/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Console from './Console'
import Examples from './Examples'
import RunInCloud from './RunInCloud'
import {useStoreActions, useStoreState} from '../hooks'
import Simulations from './Simulations';
const { Content } = Layout;

const Main = () => {
Expand Down Expand Up @@ -33,6 +34,9 @@ const Main = () => {
<Tabs.TabPane tab="Edit" key="editfile">
<Edit />
</Tabs.TabPane>
<Tabs.TabPane tab="Simulations" key="simulations">
<Simulations />
</Tabs.TabPane>
<Tabs.TabPane tab="Examples" key="examples">
<Examples />
</Tabs.TabPane>
Expand Down
86 changes: 86 additions & 0 deletions src/containers/Simulations.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import {useCallback, useState, useEffect} from 'react'
import { useMeasure } from 'react-use';
import { Select, Button, Divider } from 'antd';
import {Simulation} from '../store/simulation'
import {SimulationFile} from '../store/app'
import {useStoreActions, useStoreState} from '../hooks'
import { CaretRightOutlined, EditOutlined } from '@ant-design/icons';
import { Card, Layout, Skeleton, Row, Col, notification } from 'antd';
import {track} from '../utils/metrics'
import { AtomifyFile } from '../store/files';

const {Option} = Select

const { Header } = Layout;
const { Meta } = Card;

const Simulations = () => {
const files = useStoreState(state => state.files.files)
const syncFilesJupyterLite = useStoreActions(actions => actions.files.syncFilesJupyterLite)
const [myRef, { width }] = useMeasure<HTMLDivElement>();

useEffect(() => {
setInterval(() => {
syncFilesJupyterLite()
}, 1000)
}, [])

useEffect(() => {
(async () => {
const folders = Object.values(files).filter(file => file.type === "directory")
folders.forEach(folder => {
const filesInFolder = Object.values(files).filter(file => file.type !== "directory" && file.path.startsWith(folder.name))
let image: AtomifyFile
filesInFolder.forEach(file => {
if (file.mimetype === "image/png") {
image = file
}
})
})


})()
}, [files])

const renderCard = (simulation: AtomifyFile) => {
return (
<Card
key={simulation.name}
style={{ width: 300, marginLeft: 'auto', marginRight: 'auto' }}
actions={[
<CaretRightOutlined key="setting"/>,
<EditOutlined key="edit"/>,
]}
>
<Meta
title={simulation.name}
description={"Test"}
/>
</Card>
)}

const chunkIt = (array: Simulation[], chunkSize: number) => {
const chunks: Simulation[][] = []

for (let i = 0; i < array.length; i += chunkSize) {
const chunk = array.slice(i, i + chunkSize);
chunks.push(chunk)
}
return chunks
}



return (
<>
<Header className="site-layout-background" style={{ fontSize: 25 }}>
Simulations
</Header>
<div style={{padding: 10, margin: 10}} ref={myRef}>
<h1>Your simulations</h1>

{folders.map(renderCard)}
</div>
</>)
}
export default Simulations
29 changes: 29 additions & 0 deletions src/hooks/files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {useState, useEffect} from 'react'
import localforage from 'localforage'

localforage.config({
driver : localforage.INDEXEDDB,
name : 'JupyterLite Storage',
storeName : 'files', // Should be alphanumeric, with underscores.
description : 'some description'
});

export const useListSimulations = async () => {
const [loading, setLoading] = useState(true)
const [error, setError] = useState(false)

useEffect(() => {
(async () => {
const keys = await localforage.keys()
const simulations = []

for (let key of keys) {
const file = await localforage.getItem(key) as any
if (file.type === 'directory') {

}
}
})()

})
}
2 changes: 1 addition & 1 deletion src/store/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface AppModel {
}

export const appModel: AppModel = {
selectedMenu: 'examples',
selectedMenu: 'simulations',
setSelectedMenu: action((state, selectedMenu: string) => {
state.selectedMenu = selectedMenu
}),
Expand Down
90 changes: 90 additions & 0 deletions src/store/files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { action, Action, thunk, Thunk } from 'easy-peasy';
import localforage from 'localforage'

localforage.config({
driver : localforage.INDEXEDDB,
name : 'JupyterLite Storage',
storeName : 'files', // Should be alphanumeric, with underscores.
description : 'some description'
});

export interface AtomifyFile {
created: Date
format: string
last_modified: Date
mimetype: string
name: string
path: string
type: string
writeable: boolean
text: () => Promise<string>
writeText: (content: string) => Promise<void>
}

export interface FilesModel {
files: {[key: string]: AtomifyFile}
setFiles: Action<FilesModel, {[key: string]: AtomifyFile}>
syncFilesJupyterLite: Thunk<FilesModel, undefined>
}

export const filesModel: FilesModel = {
files: {},
setFiles: action((state, render: {[key: string]: AtomifyFile}) => {
state.files = render
}),
syncFilesJupyterLite: thunk(async (actions, dummy: undefined, {getStoreState}) => {
// @ts-ignore
const state = getStoreState().files as FilesModel

const newFiles = {...state.files}
let anyChanges = false

// First find all files from JupyterLite and sync them in
const keys = await localforage.keys()
for (let key of keys) {
const file = await localforage.getItem(key) as any
if (!state.files[key]) {
const dateModified = new Date(file.date_modified)
// Create AtomifyFile object
const newFile: AtomifyFile = {
created: new Date(file.created),
format: file.format,
last_modified: new Date(file.last_modified),
mimetype: file.mimetype,
name: file.name,
path: file.path,
type: file.type,
writeable: file.writeable,
text: async () => {
const file = await localforage.getItem(key) as any
return file.content
},
writeText: async (content: string) => {
const file = await localforage.getItem(key) as any

await localforage.setItem(key, {
...file,
content
})
}
}

newFiles[key] = newFile
anyChanges = true
}
}

// Then remove any files that no longer are there
Object.keys(state.files).forEach(key => {
if (keys.indexOf(key) === -1) {
// This file no longer exists in JupyterLite
delete newFiles[key]
anyChanges = true
}
})

if (anyChanges) {
actions.setFiles(newFiles)
}
})
};
5 changes: 4 additions & 1 deletion src/store/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { SettingsModel, settingsModel } from './settings'
import { SimulationStatusModel, simulationStatusModel } from './simulationstatus'
import { ProcessingModel, processingModel } from './processing'
import { RenderModel, renderModel } from './render'
import { FilesModel, filesModel } from './files'
import { AppModel, appModel } from './app'
import { persist } from 'easy-peasy';

Expand All @@ -13,6 +14,7 @@ export interface StoreModel {
processing: ProcessingModel,
app: AppModel,
render: RenderModel
files: FilesModel
}

export const storeModel: StoreModel = {
Expand All @@ -21,5 +23,6 @@ export const storeModel: StoreModel = {
simulationStatus: simulationStatusModel,
processing: processingModel,
app: appModel,
render: renderModel
render: renderModel,
files: filesModel
};