garage-box/src/ObjectList.tsx
2022-02-28 17:59:06 +01:00

163 lines
3.9 KiB
TypeScript

import React from 'react';
import { Link, useParams } from 'react-router-dom';
import { S3Client, ListObjectsV2Command } from '@aws-sdk/client-s3';
import Alert from 'react-bootstrap/Alert';
import Breadcrumb from 'react-bootstrap/Breadcrumb';
import Card from 'react-bootstrap/Card';
import ListGroup from 'react-bootstrap/ListGroup';
import { LinkContainer } from 'react-router-bootstrap'
type Props = {
client: S3Client;
bucket: string;
prefix: string;
};
type State = {
loaded: boolean;
folders: string[];
files: string[];
};
var cache: { [path: string]: State; } = {};
class ObjectList extends React.Component<Props, State> {
state = {
loaded: false,
folders: [],
files: [],
};
constructor(props: Props) {
super(props);
}
async componentDidMount() {
console.log(this.props);
if (cache[this.path()]) {
this.setState(cache[this.path()]);
}
let command = new ListObjectsV2Command({
Bucket: this.props.bucket,
Prefix: this.props.prefix,
Delimiter: '/',
});
try {
const pxlen = this.props.prefix.length;
const data = await this.props.client.send(command);
console.log("ok", data);
const folders = (data.CommonPrefixes || []).map((cp) => cp.Prefix!.substring(pxlen));
const files = (data.Contents || []).map((obj) => obj.Key!.substring(pxlen));
folders.sort();
files.sort();
this.setState({
loaded: true,
folders: folders,
files: files,
});
cache[this.path()] = this.state;
} catch(error) {
console.log("err", error);
}
}
path() {
return this.props.bucket + "/" + this.props.prefix;
}
renderBreadcrumbs() {
let spl = this.props.prefix.split("/");
let items = [];
for (var i = 0; i < spl.length - 1; i++) {
if (i < spl.length - 2) {
items.push(
<LinkContainer to={ "/" + this.props.bucket + "/" + spl.slice(0, i+1).join("/") + "/" }>
<Breadcrumb.Item>{ spl[i] }</Breadcrumb.Item>
</LinkContainer>
);
} else {
items.push(
<Breadcrumb.Item active>{ spl[i] }</Breadcrumb.Item>
);
}
}
return (
<Breadcrumb>
<LinkContainer to="/">
<Breadcrumb.Item>my buckets</Breadcrumb.Item>
</LinkContainer>
{ this.props.prefix == "" ?
<Breadcrumb.Item active>{ this.props.bucket }</Breadcrumb.Item>
:
<LinkContainer to={ "/" + this.props.bucket + "/" }>
<Breadcrumb.Item>{ this.props.bucket }</Breadcrumb.Item>
</LinkContainer>
}
{ items }
</Breadcrumb>
);
}
render() {
if (!this.state.loaded) {
return (
<>
{ this.renderBreadcrumbs() }
<Alert variant="secondary">Loading...</Alert>
</>
);
}
return (
<>
{ this.renderBreadcrumbs() }
<ListGroup>
{ this.state.folders.map((f) =>
<LinkContainer to={ "/" + this.props.bucket + "/" + this.props.prefix + f }>
<ListGroup.Item key={f + "/"} action>
{ f }
</ListGroup.Item>
</LinkContainer>
)}
{ this.state.files.map((f) =>
<ListGroup.Item key={f}>
{ f }
</ListGroup.Item>
)}
</ListGroup>
</>
);
}
}
interface IClient {
client: S3Client;
}
export const ObjectList1 = ({ client }: IClient) => {
const params = useParams();
const bucket = params["bucket"]!;
return <>
<ObjectList client={client} bucket={bucket} prefix="" key={bucket} />
</>;
};
export const ObjectList2 = ({ client }: IClient) => {
const params = useParams();
const bucket = params["bucket"]!;
const prefix = params["*"] || "";
const key = bucket + "/" + prefix;
return <>
<ObjectList client={client} bucket={bucket} prefix={prefix} key={key} />
</>;
};