Skip to content

Commit

Permalink
initial work on react ui prototype in conda-store-ui
Browse files Browse the repository at this point in the history
  • Loading branch information
telamonian committed Apr 14, 2022
1 parent a98b394 commit a339f7e
Show file tree
Hide file tree
Showing 10 changed files with 3,952 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ docs/_build
# nix
.direnv
**/.DS_Store

# vscode
.history/
.vscode/
*.code-workspace
1 change: 1 addition & 0 deletions conda-store-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# conda-store-ui
46 changes: 46 additions & 0 deletions conda-store-ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"name": "conda-store-ui",
"version": "0.0.1",
"description": "UI elements for building a frontend for conda-store",
"scripts": {
"build": "tsc --build",
"build:watch": "tsc --build --watch",
"clean": "rimraf dist lib types *.tsbuildinfo",
"clean:slate": "yarn run clean && rimraf node_modules",
"start": "webpack server",
"start:chromium": "webpack serve --open 'chromium'",
"start:prod": "NODE_ENV=production webpack serve",
"watch": "npm-run-all -p *:watch",
"webpack": "webpack --color",
"webpack:prod": "NODE_ENV=production webpack --color",
"webpack:watch": "webpack --color --watch"
},
"keywords": [],
"license": "BSD-3-Clause",
"dependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0",
"@mui/material":"^5.6.1",
"@emotion/react": "^11.9.0",
"@emotion/styled": "^11.8.1",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0"
},
"devDependencies": {
"css-loader": "^6.7.1",
"css-minimizer-webpack-plugin": "^3.4.1",
"less":"^4.1.2",
"less-loader": "^10.2.0",
"mini-css-extract-plugin": "^2.6.0",
"postcss":"^8.4.12",
"postcss-loader": "^6.2.1",
"source-map-loader": "^3.0.1",
"html-webpack-plugin": "^5.5.0",
"rimraf": "^3.0.2",
"ts-loader": "^8.0.17",
"typescript": "^4.6.3",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.8.1"
}
}
165 changes: 165 additions & 0 deletions conda-store-ui/src/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Copyright (c) 2020, Max Klein
*
* This file is part of the tree-finder library, distributed under the terms of
* the BSD 3 Clause license. The full license can be found in the LICENSE file.
*/
import * as React from "react"
import {createRoot} from "react-dom/client";
import Autocomplete from "@mui/material/Autocomplete";
import IconButton from "@mui/material/IconButton";
import Stack from "@mui/material/Stack";
import SvgIcon from "@mui/material/SvgIcon";
import TextField from "@mui/material/TextField";

interface Spec {
name: string | null
current: number | null
request: number | null
}

const nameOptions = ["numpy", "pandas"];
const versionInfo = {
dask: {
current: 14.37,
default: 15,
options: [1.00, 2.00, 14.37, 15],
},
numpy: {
current: 1.99,
default: 1.99,
options: [1.00, 1.10, 1.99],
},
pandas: {
default: 1.99,
options: [1.00, 1.10, 1.99],
},
spark: {
default: 1.99,
options: [1.00, 1.10, 1.99],
},

};

const getNameOptions = () => nameOptions;
const getVersionDefault = (name: string) => versionInfo[name as keyof typeof versionInfo].default;
const getVersionCurrent = (name: string) => versionInfo[name as keyof typeof versionInfo].current ?? null;
const getVersionOptions = (name: string) => versionInfo[name as keyof typeof versionInfo].options;

export function PackagePickerList() {
const [specs, setSpecs] = React.useState<Spec[]>([{name: null, current: null, request: null}]);

const onSpecChange = (newSpec: Spec, ix?: number) => {
specs.splice(ix ?? specs.length, 1, newSpec);
setSpecs([...specs]);
}

return (
<Stack>
{specs.map((x, i) =>
<PackagePickerItem
ix={i}
key={i}
onSpecChange={onSpecChange}
spec={x}
/>
)}
<IconButton
onClick={() => onSpecChange({name: null, current: null, request: null})}
sx={{width: 24}}
>
<PlusIcon/>
</IconButton>
</Stack>
);
}

export function PackagePickerItem(params: {
spec: Spec,
ix: number,
onSpecChange: (newSpec: Spec, key: number) => void,
}) {
return (
<Stack direction="row">
<Autocomplete
onChange={(event: any, name: string | null) => {
params.onSpecChange({name, current: name === null ? null : getVersionDefault(name)}, params.ix)
}}
options={getNameOptions()}
renderInput={(params) => <TextField {...params} label="Pkg Name" />}
sx = {{minWidth: 300}}
value={params.spec.name}
/>
<Autocomplete
disabled={!params.spec.name}
onChange={(event: any, version: number | null) => {
params.onSpecChange({name: params.spec.name, current: version}, params.ix)
}}
options={params.spec.name === null ? [] : getVersionOptions(params.spec.name)}
renderInput={(params) => <TextField {...params} label="Pkg Version" />}
sx = {{minWidth: 150}}
value={params.spec.name === null ? null : params.spec.current}
/>
</Stack>
);
}

export function PlusIcon() {
return (
<SvgIcon xmlns="http://www.w3.org/2000/svg" width="16" viewBox="0 0 24 24">
<g fill="#616161">
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</g>
</SvgIcon>
)
}

export function PackagePicker() {
const [nameValue, setNameValue] = React.useState<string | null>(null);

const [versionDisabled, setVersionDisabled] = React.useState<boolean>(true);
const [versionOptions, setVersionOptions] = React.useState<number[]>([]);
const [versionValue, setVersionValue] = React.useState<number | null>(null);

const onNameChange = (event: any, newValue: string | null) => {
setNameValue(newValue);

if (newValue !== null) {
setVersionDisabled(false);
setVersionOptions(versionInfo[newValue as keyof typeof versionInfo].options);
setVersionValue(versionInfo[newValue as keyof typeof versionInfo].default);
} else {
setVersionDisabled(true);
setVersionOptions([]);
setVersionValue(null);
}
}

return (
<Stack direction="row">
<Autocomplete
onChange={onNameChange}
options={nameOptions}
renderInput={(params) => <TextField {...params} label="Pkg Name" />}
sx = {{minWidth: 300}}
value={nameValue}
/>
<Autocomplete
disabled={versionDisabled}
onChange={(event: any, newValue: number | null) => {
setVersionValue(newValue);
}}
options={versionOptions}
renderInput={(params) => <TextField {...params} label="Pkg Version" />}
sx = {{minWidth: 150}}
value={versionValue}
/>
</Stack>
);
}

const rootElem = document.createElement("div");
document.body.appendChild(rootElem);
const root = createRoot(rootElem);

root.render(<PackagePickerList/>);
34 changes: 34 additions & 0 deletions conda-store-ui/style/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2020, Max Klein
*
* This file is part of the tree-finder library, distributed under the terms of
* the BSD 3 Clause license. The full license can be found in the LICENSE file.
*/

@import url('~tree-finder/dist/tree-finder.css');
@import url('~tree-finder/dist/theme/material.css');

body {
margin-right: 0;
margin-bottom: 0;
}

tree-finder-panel {
height: calc(100vh - 8px);
}

tree-finder-grid {
padding: 0;
margin-left: 12px;
overflow-x: auto;
}

/* tree-finder .rt-virtual-panel,
tree-finder .rt-scroll-table-clip {
display: inline-block;
} */

/* tree-finder .tf-panel-grid {
padding-left: 0;
width: fit-content;
} */
11 changes: 11 additions & 0 deletions conda-store-ui/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"extends": "./tsconfigbase",
"compilerOptions": {
"baseUrl": ".",
"declarationDir": "./types",
"outDir": "lib",
"rootDir": "src"
},
"include": ["src/**/*"]
}
17 changes: 17 additions & 0 deletions conda-store-ui/tsconfigbase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"compilerOptions": {
"composite": true,
"declaration": true,
"declarationMap": true,
"incremental": true,
"jsx": "react",
"module": "esnext",
"moduleResolution": "node",
"noEmitOnError": true,
"noImplicitAny": true,
"sourceMap": true,
"strictNullChecks": true,
"target": "es2019"
}
}
69 changes: 69 additions & 0 deletions conda-store-ui/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2020, Max Klein
*
* This file is part of the tree-finder library, distributed under the terms of
* the BSD 3 Clause license. The full license can be found in the LICENSE file.
*/
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

// const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
// To improve build times for large projects enable fork-ts-checker-webpack-plugin
// const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");

const { dependencySrcMapRules, stylingRules, svgUrlRules, getContext, getOptimization, getResolve, tsRules } = require("./webpack.rules");

const isProd = process.env.NODE_ENV === "production";

const simpleExampleConfig = {
devtool: "source-map",
entry: "src/index.tsx",
watch: false,
...getContext(__dirname),

output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js"
},

module: {
rules: [
...dependencySrcMapRules,
...stylingRules,
...svgUrlRules,
...tsRules,
],
},

resolve: {
...getResolve(__dirname),
},

// devServer: {
// // contentBase: [path.join(__dirname, "examples"), path.join(__dirname, ".")],
// // inline: false,
// // publicPath: "/dist/",

// // dev-server writes to disk instead of keeping the bundle in memory
// writeToDisk: true,
// },

plugins: [
new HtmlWebpackPlugin({
title: "simple tree-finder example"
}),
new MiniCssExtractPlugin(),
],

mode: isProd ? "production": "development",

optimization: {
minimize: isProd,
...isProd && getOptimization(),
},
}

module.exports = [
simpleExampleConfig,
];
Loading

0 comments on commit a339f7e

Please sign in to comment.