Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Commit

Permalink
added pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
Kai Mansfield authored and kaimsfd committed Oct 12, 2023
1 parent f74a970 commit 3d2d043
Show file tree
Hide file tree
Showing 18 changed files with 1,064 additions and 16 deletions.
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 \
sqlite3 pre-commit
8 changes: 6 additions & 2 deletions .devcontainer/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,18 @@ 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
Expand Down
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
1 change: 1 addition & 0 deletions backend/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/pin_packing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
anyhow = { workspace = true }
async-graphql = { workspace = true }
axum = { workspace = true }
clap = { workspace = true }
Expand Down
49 changes: 45 additions & 4 deletions backend/pin_packing/src/resolvers/pin_library.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ 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 sea_orm::{
ActiveValue, CursorTrait, DatabaseConnection, EntityTrait, IntoActiveModel, ModelTrait,
};

#[ComplexObject]
impl pin_library::Model {
Expand All @@ -23,10 +28,46 @@ impl PinLibraryQuery {
async fn library_pins(
&self,
ctx: &Context<'_>,
) -> async_graphql::Result<Vec<pin_library::Model>> {
after: Option<String>,
before: Option<String>,
first: Option<i32>,
last: Option<i32>,
) -> async_graphql::Result<Connection<String, pin_library::Model, EmptyFields, EmptyFields>>
{
subject_authorization!("xchemlab.pin_packing.read_pin_library", ctx).await?;
let database = ctx.data::<DatabaseConnection>()?;
Ok(pin_library::Entity::find().all(database).await?)
let pin_query = pin_library::Entity::find();
query(
after,
before,
first,
last,
|after, before, first, last| async move {
let mut pin_cursor = pin_query.cursor_by(pin_library::Column::Barcode);
if let Some(after) = after {
pin_cursor.after(after);
}
if let Some(before) = before {
pin_cursor.before(before);
}
if let Some(first) = first {
pin_cursor.first(first as u64);
}
if let Some(last) = last {
pin_cursor.last(last as u64);
}

let pins = pin_cursor.all(database).await?;

let mut connection = Connection::new(true, true);
connection.edges.extend(
pins.into_iter()
.map(|pin| Edge::new(pin.barcode.clone(), pin)),
);
Ok::<_, async_graphql::Error>(connection)
},
)
.await
}
}

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
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
8 changes: 8 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@
]
},
"dependencies": {
"@apollo/client": "^3.8.5",
"@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.8.1",
"http-proxy-middleware": "^2.0.6",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
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>Your React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
54 changes: 54 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useQuery, gql, DocumentNode } from "@apollo/client";
import React from "react";
import { Pagination, Table, theme } from "@diamondlightsource/ui-components"
import { ChakraProvider } from "@chakra-ui/react";

const GET_INFO: DocumentNode = gql`
query pinInfo {
libraryPins {
barcode,
loopSize,
status
}
}
`;

function DisplayPinInfo(): React.JSX.Element {
const { loading, error, data } = useQuery(GET_INFO);

if (loading) return <p>Loading...</p>;
if (error) return <p>Error : {error.message} {error.extraInfo}</p>;

return (
<><Table
headers={[
{
key: 'barcode',
label: 'Barcode'
},
{
key: 'loopSize',
label: 'Loop Size'
},
{
key: 'status',
label: 'Status'
}
]}
data={data.libraryPins} />
<Pagination
total={6} onPageChange={(page) => {
console.log(`On page: ${page}`)
}}
/>
</>
);
}

export default function App(): React.JSX.Element {
return (
<ChakraProvider theme={theme}>
<DisplayPinInfo />
</ChakraProvider>
);
}
40 changes: 40 additions & 0 deletions frontend/src/components/BarcodeTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { Component } from 'react';
import '../styles/Table.css';

class BarcodeTable extends Component {
render() {
// Sample data for the table
const data = [
{ barcode: '0123456789-0123456789', loopSize: '90', status: 'Ready' },
{ barcode: '0123456789-0123456789', loopSize: '75', status: 'Occupied' },
{ barcode: '0123456789-0123456789', loopSize: '90', status: 'Dirty' },
{ barcode: '0123456789-0123456789', loopSize: '75', status: 'Broken' }
];

return (
<div>
<h2 className='wrapper'>Pin Library</h2>
<table>
<thead>
<tr>
<th className={'wrapper th-td-spacing'}>Barcode</th>
<th className={'wrapper th-td-spacing'}>Loop Size</th>
<th className={'wrapper th-td-spacing'}>Status</th>
</tr>
</thead>
<tbody>
{data.map((item, index) => (
<tr key={index}>
<td className={'wrapper item-vspacing'}>{item.barcode}</td>
<td className={'wrapper item-vspacing'}>{item.loopSize}</td>
<td className={'status-wrapper item-vspacing'}>{item.status}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
}

export default BarcodeTable;
Empty file removed frontend/src/index.ts
Empty file.
33 changes: 33 additions & 0 deletions frontend/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import * as ReactDOM from "react-dom/client";
import { ApolloClient, InMemoryCache, ApolloProvider, createHttpLink, ApolloLink, NormalizedCacheObject } from "@apollo/client";
import App from "./App";
import { setContext } from '@apollo/client/link/context';


const httpLink: ApolloLink = createHttpLink({
uri: '/api',
});

const authLink: ApolloLink = setContext((_, { headers }) => {
const token: string = "ValidToken";
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
}
}
});

const client: ApolloClient<NormalizedCacheObject> = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});

const root: ReactDOM.Root = ReactDOM.createRoot(document.getElementById("root"));

root.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);
12 changes: 12 additions & 0 deletions frontend/src/setupProxy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { createProxyMiddleware } = require ('http-proxy-middleware');

module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://backend',
changeOrigin: true,
pathRewrite: {'^/api' : ''}
})
);
};
20 changes: 20 additions & 0 deletions frontend/src/styles/Table.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.wrapper {
padding-left: 10px;
}

.status-wrapper {
padding-left: 30px;
}

.item-vspacing {
padding-top: 0px;
}

.th-td-spacing {
padding-left: 10px
}

.barcode-spacing {
padding-bottom: 10px;
padding-left: 0px;
}
Loading

0 comments on commit 3d2d043

Please sign in to comment.