Skip to content
This repository was archived by the owner on Jul 23, 2024. It is now read-only.
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
5 changes: 5 additions & 0 deletions .devcontainer/Dockerfile.frontend
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM docker.io/library/node:20.6.0-bookworm

RUN apt-get update \
&& apt-get install --yes --no-install-recommends \
pre-commit
10 changes: 8 additions & 2 deletions .devcontainer/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@ services:
dockerfile: Dockerfile.backend
volumes:
- ..:/workspace:z
command: sleep infinity
command: cargo run --manifest-path /workspace/backend/Cargo.toml --release -p pin_packing serve --database-url postgres://postgres:password@postgres/pin_packing
environment:
OPA_URL: http://opa:8181
DATABASE_URL: postgres://postgres:password@postgres
RABBITMQ_URL: amqp://rabbitmq:password@rabbitmq
ports:
- "8080:80"

frontend:
image: docker.io/library/node:20.6.0-bookworm
build:
context: .
dockerfile: Dockerfile.frontend
volumes:
- ..:/workspace:z
command: sleep infinity
environment:
SCHEMA_PATH: http://backend

opa:
image: docker.io/openpolicyagent/opa:0.53.1
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@

# Developer Tooling
.vscode

# Generated Schema
pin_packing.graphql
3 changes: 2 additions & 1 deletion backend/.devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"rust-lang.rust-analyzer",
"tamasfe.even-better-toml",
"tsandall.opa",
"ms-kubernetes-tools.vscode-kubernetes-tools"
"ms-kubernetes-tools.vscode-kubernetes-tools",
"cweijan.vscode-database-client2"
],
"settings": {
"rust-analyzer.cargo.features": "all",
Expand Down
5 changes: 4 additions & 1 deletion backend/pin_packing/src/resolvers/pin_library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use crate::tables::{
pin_library::{self, PinStatus},
pin_mount,
};
use async_graphql::{ComplexObject, Context, Object};
use async_graphql::{
connection::{query, Connection, Edge, EmptyFields},
ComplexObject, Context, Object,
};
use opa_client::subject_authorization;
use sea_orm::{ActiveValue, DatabaseConnection, EntityTrait, IntoActiveModel, ModelTrait};
use the_paginator::graphql::{CursorInput, ModelConnection};
Expand Down
3 changes: 2 additions & 1 deletion frontend/.devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"extensions": [
"ms-vscode.vscode-typescript-next",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
"esbenp.prettier-vscode",
"cweijan.vscode-database-client2"
]
}
},
Expand Down
3 changes: 3 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# codegen generated code
src/__generated__/
18 changes: 18 additions & 0 deletions frontend/codegen.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
schema: process.env.SCHEMA_PATH,
documents: ['src/**/*.{ts,tsx}'],
generates: {
'./src/__generated__/': {
preset: 'client',
plugins: [],
presetConfig: {
gqlTagName: 'gql',
}
}
},
ignoreNoDocuments: true,
};

export default config
1 change: 0 additions & 1 deletion frontend/config/paths.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@


const path = require('path');
const fs = require('fs');
const getPublicUrlOrPath = require('react-dev-utils/getPublicUrlOrPath');
Expand Down
17 changes: 15 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@
"build": "node scripts/build.js",
"test": "node scripts/test.js",
"format": "prettier --write **/*.js",
"eslint-lint": "node scripts/lint.js"
"eslint-lint": "node scripts/lint.js",
"compile": "graphql-codegen",
"watch": "graphql-codegen -w"
},
"eslintConfig": {
"extends": [
Expand All @@ -77,8 +79,19 @@
]
},
"dependencies": {
"@apollo/client": "3.5.4",
"@chakra-ui/icons": "^2.1.1",
"@chakra-ui/react": "^2.8.1",
"@diamondlightsource/ui-components": "^1.0.2",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"framer-motion": "^10.16.4",
"graphql": "^16.3.0",
"http-proxy-middleware": "^2.0.6",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
"react-toggle-dark-mode": "^1.1.1"
},
"jest": {
"roots": [
Expand Down
10 changes: 10 additions & 0 deletions frontend/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>XChem Lab</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
146 changes: 146 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/* eslint-disable no-template-curly-in-string */
import { useQuery } from "@apollo/client";
import { gql } from './__generated__/gql';
import React from "react";
import { theme } from "./styles/theme"
import { ChakraProvider, Alert, AlertIcon, AlertTitle, AlertDescription, Button, HStack, useColorMode, useColorModeValue } from "@chakra-ui/react";
import { Table } from "./components/Table";
import {Helmet} from 'react-helmet';
import { DarkModeButton } from "./components/DarkModeButton";

const GET_INFO = gql(`
query pinInfo ($after: String) {
libraryPins(first: 2, after: $after) {
pageInfo {
hasPreviousPage,
hasNextPage,
startCursor,
endCursor
},
edges {
cursor
node {
barcode,
loopSize,
status
}
}
}
}
`);

// Displays libraryPins query in table component. The table can load more data if required
function DisplayPinInfo(): React.JSX.Element {
const { loading, error, data, fetchMore } = useQuery(
GET_INFO,
{
notifyOnNetworkStatusChange: true,
});

//const [isDarkMode, setDarkMode] = React.useState(false);

/* const toggleDarkMode = (checked: boolean) => {
setDarkMode(checked);
};*/

const { colorMode, toggleColorMode } = useColorMode()

var loadingRows = loading ? 2 : 0
const bgColour = useColorModeValue('white', 'black')

if (error) return (
<Alert status='error'>
<AlertIcon />
<AlertTitle>{error.message}</AlertTitle>
<AlertDescription>{error.extraInfo}</AlertDescription>
</Alert>
)

const loadMore = () => {
fetchMore({

variables: {
after: data.libraryPins.pageInfo.endCursor,
},

updateQuery: (previousQueryResult, { fetchMoreResult }) => {
const newEdges = fetchMoreResult.libraryPins.edges;
const pageInfo = fetchMoreResult.libraryPins.pageInfo;

// if newEdges actually have items,
return newEdges.length
? // return a reconstruction of the query result with updated values
{
...previousQueryResult,

libraryPins: {
...previousQueryResult.libraryPins,

edges: [...previousQueryResult.libraryPins.edges, ...newEdges],

pageInfo,
},
}
: // else, return the previous result
previousQueryResult;
},
});
};

return (
<>
<div>
<DarkModeButton
style={{ marginBottom: '1rem', marginLeft: '.25rem', marginTop: '.25rem', position: 'relative', left: '1875px'}}
onClick={toggleColorMode}
variant={'unstyled'}
/>
<Helmet>
<style>{`body { background-color: ${bgColour} }`}</style>
</Helmet>
<Table
headers={[
{
key: 'barcode',
label: 'Barcode',
skeletonWidth: 12
},
{
key: 'loopSize',
label: 'Loop Size',
skeletonWidth: 3
},
{
key: 'status',
label: 'Status',
skeletonWidth: 7
}
]}
data={data ? data.libraryPins.edges.map((edge) => edge.node): []}
loadingRows={loadingRows}
rowVariant={"diamondStriped"}
/>
<HStack justify='center' width='100%'>
<Button marginTop={'10px'}
colorScheme='teal'
variant='outline'
onClick={loadMore}
isLoading={loadingRows !== 0}
loadingText='Loading'
isDisabled={data ? !data.libraryPins.pageInfo.hasNextPage : false}
>
Load More
</Button>
</HStack>
</div>
</>
);
}

export default function App(): React.JSX.Element {
return (
<ChakraProvider theme={theme}>
<DisplayPinInfo />
</ChakraProvider>
);
}
24 changes: 24 additions & 0 deletions frontend/src/components/DarkModeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { IconButton, IconButtonProps, useColorMode, useColorModeValue } from '@chakra-ui/react'
import { SunIcon, MoonIcon } from '@chakra-ui/icons'
import React from 'react'

export interface DarkModeButtonProps extends Omit<IconButtonProps, "aria-label"> { }

const DarkModeButton = ({ ...props }: DarkModeButtonProps) => {
const { toggleColorMode } = useColorMode()

const label = useColorModeValue('Light Mode', 'Dark Mode')
const iconColor = useColorModeValue('#2b2b2b', 'white')
const icon = useColorModeValue(<SunIcon color={iconColor} />, <MoonIcon color={iconColor} />)

return (
<IconButton
aria-label={label}
icon={icon}
onClick={toggleColorMode}
{...props}
/>
)
}

export { DarkModeButton }
Loading