Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "harperdb-studio",
"version": "4.8.12",
"version": "4.8.13",
"description": "A UI for HarperDB",
"deploymentUrl": "studio.harperdb.io",
"private": true,
Expand Down
65 changes: 65 additions & 0 deletions src/components/auth/AuthLayout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Outlet } from 'react-router';
import { Col, Container, Row } from 'reactstrap';

function AuthLayout({ children }) {
return (
<Container fluid="xs" className="h-100">
<Row xs="1" sm="2" className="h-100">
<Col className="p-5 auth-studio-info d-none d-sm-flex justify-content-center align-items-center">
<div className="auth-studio-info-container">
<h1 className="auth-title">HarperDB Studio</h1>
<span className="mb-4 auth-subtitle d-inline-block">Manage all your HarperDB instances.</span>
<ul className="auth-info-list-items">
<li>
<h3 className="item-title">Manage All Instances</h3>
<span className="item-subtitle">Set access, cluster, monitor, and more.</span>
</li>
<li>
<h3 className="item-title">Embedded API Server</h3>
<span className="item-subtitle">HarperDB components give you unlimited application flexibility.</span>
</li>
<li>
<h3 className="item-title">Fully Managed Cloud & 5G Instances</h3>
<span className="item-subtitle">Go from zero to code in minutes.</span>
</li>
<li>
<h3 className="item-title">Deploy Anywhere</h3>
<div className="mt-3">
<a
href="https://hub.docker.com/r/harperdb/harperdb"
target="_blank"
rel="noreferrer"
className="deploy-subitem"
>
Docker
</a>
<a
href="https://www.npmjs.com/package/harperdb"
target="_blank"
rel="noreferrer"
className="deploy-subitem"
>
npm
</a>
<a
href="https://docs.harperdb.io/docs/deployments/install-harperdb"
target="_blank"
rel="noreferrer"
className="deploy-subitem"
>
all options
</a>
</div>
</li>
</ul>
</div>
</Col>
<Col className="p-5 d-flex justify-content-center align-items-center auth-form-container">
<Outlet />
</Col>
</Row>
</Container>
);
}

export default AuthLayout;
6 changes: 4 additions & 2 deletions src/components/instance/browse/BrowseDatatable.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ let controller;
let controller2;
let controller3;

function BrowseDatatable({ tableState, setTableState, activeTable, tableDescriptionAttributes }) {
function BrowseDatatable({ tableState, setTableState, activeTable }) {
const navigate = useNavigate();
const { compute_stack_id, schema, table, customer_id } = useParams();
const auth = useStoreState(instanceState, (s) => s.auth);
Expand Down Expand Up @@ -74,6 +74,7 @@ function BrowseDatatable({ tableState, setTableState, activeTable, tableDescript
hashAttribute,
dynamicAttributesFromDataTable,
dataTableColumns,
schemaAttributes,
error,
} = await getTableData({
schema,
Expand Down Expand Up @@ -114,6 +115,7 @@ function BrowseDatatable({ tableState, setTableState, activeTable, tableDescript
hashAttribute,
dataTableColumns,
dynamicAttributesFromDataTable,
schemaAttributes,
error,
});
}
Expand Down Expand Up @@ -175,7 +177,7 @@ function BrowseDatatable({ tableState, setTableState, activeTable, tableDescript
columns={tableState.dataTableColumns || []}
data={tableState.tableData || []}
error={tableState.error}
tableDescriptionAttributes={tableDescriptionAttributes}
tableDescriptionAttributes={tableState.schemaAttributes}
dynamicAttributesFromDataTable={tableState.dynamicAttributesFromDataTable}
currentPage={tableState.page}
pageSize={tableState.pageSize}
Expand Down
14 changes: 10 additions & 4 deletions src/components/instance/browse/EntityManagerRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ function EntityManagerRow({ item, itemType, baseUrl, isActive, toggleDropItem, i
toggleConfirmDropItem(false);
};

const syncInstanceStructure = () => {
buildInstanceStructure({ auth, url });
};
const handleSetActive = () =>
isActive || isDropping || isConfirmingDropItem ? false : navigate(`${baseUrl}/${item}`);

Expand All @@ -66,7 +69,10 @@ function EntityManagerRow({ item, itemType, baseUrl, isActive, toggleDropItem, i
key={item}
title={`View${isActive ? 'ing' : ''} ${itemType} ${item}`}
className={`item-row ${isActive ? 'active' : ''}`}
onClick={handleSetActive}
onClick={() => {
handleSetActive();
syncInstanceStructure();
}}
tabIndex="0"
>
<Col className={`item-label ${isConfirmingDropItem ? 'text-danger text-nowrap' : ''}`}>
Expand All @@ -86,7 +92,7 @@ function EntityManagerRow({ item, itemType, baseUrl, isActive, toggleDropItem, i
title={`confirm drop ${itemType} ${item}`}
onClick={confirmItemForDrop}
>
<i className="fa fa-check text-white" />
<i className="text-white fa fa-check" />
</Button>
<Button
id="cancelDropItem"
Expand All @@ -95,7 +101,7 @@ function EntityManagerRow({ item, itemType, baseUrl, isActive, toggleDropItem, i
title={`Cancel drop ${itemType} ${item}`}
onClick={cancelConfirmDrop}
>
<i className="fa fa-times text-white" />
<i className="text-white fa fa-times" />
</Button>
</>
) : isDropping ? (
Expand All @@ -106,7 +112,7 @@ function EntityManagerRow({ item, itemType, baseUrl, isActive, toggleDropItem, i
title={`Drop ${itemType} ${item}`}
onClick={selectItemForDrop}
>
<i className="fa fa-minus text-white" />
<i className="text-white fa fa-minus" />
</Button>
) : isActive ? (
<Button tabIndex="-1" color="purple" className="round">
Expand Down
41 changes: 6 additions & 35 deletions src/components/instance/browse/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ import { useStoreState } from 'pullstate';
import { ErrorBoundary } from 'react-error-boundary';

import instanceState from '../../../functions/state/instanceState';
import describeTable from '../../../functions/api/instance/describeTable';

import ErrorFallback from '../../shared/ErrorFallback';
import addError from '../../../functions/api/lms/addError';
import useInstanceAuth from '../../../functions/state/instanceAuths';
import EmptyPrompt from '../../shared/EmptyPrompt';
import buildInstanceStructure from '../../../functions/instance/browse/buildInstanceStructure';
import { clearTableDescriptionCache } from '../../../functions/instance/state/describeTableCache';

const DataTable = lazy(() => import(/* webpackChunkName: "browse-datatable" */ './BrowseDatatable'));
const BrowseDatatable = lazy(() => import(/* webpackChunkName: "browse-datatable" */ './BrowseDatatable'));
const EntityManager = lazy(() => import(/* webpackChunkName: "browse-entitymanager" */ './EntityManager'));
const JSONEditor = lazy(() => import(/* webpackChunkName: "browse-jsonviewer" */ './JSONEditor'));
const CSVUpload = lazy(() => import(/* webpackChunkName: "browse-csvupload" */ './CsvUpload'));
Expand All @@ -40,7 +38,7 @@ function NoPrimaryKeyMessage({ table }) {
<Card className="my-3 missing-primary-key">
<CardBody>
<CardTitle>No Primary Key</CardTitle>
<i className="fa fa-warning mt-3" />
<i className="mt-3 fa fa-warning" />
<span className="mt-3">
The table {`'${table}'`} does not have a primary key. The HarperDB Studio does not currently support tables
without a primary key defined. Please see the{' '}
Expand All @@ -59,16 +57,13 @@ function BrowseIndex() {
const location = useLocation();
const { schema, table, action, customer_id, compute_stack_id } = useParams();
const [instanceAuths] = useInstanceAuth({});
const auth = instanceAuths?.[compute_stack_id];
const url = useStoreState(instanceState, (s) => s.url);
const registration = useStoreState(instanceState, (s) => s.registration);
const version = registration?.version;
const [major, minor] = version?.split('.') || [];
const versionAsFloat = `${major}.${minor}`;
const structure = useStoreState(instanceState, (s) => s.structure);
const [entities, setEntities] = useState({ schemas: [], tables: [], activeTable: false });
const [tableState, setTableState] = useState(defaultTableState);
const [tableDescription, setTableDescription] = useState(null);
const baseUrl = `/o/${customer_id}/i/${compute_stack_id}/browse`;
const showForm = instanceAuths[compute_stack_id]?.super || instanceAuths[compute_stack_id]?.structure === true;
const showTableForm =
Expand All @@ -81,29 +76,11 @@ function BrowseIndex() {
: "This user has not been granted access to any tables. A super-user must update this user's role.";
const [hasHashAttr, setHasHashAttr] = useState(true);

const syncInstanceStructure = () => {
buildInstanceStructure({ auth, url });
};

useEffect(() => {
const fetchDescribeTable = async () => {
if (table) {
try {
const result = await describeTable({ auth, url, schema, table });
setTableDescription(result);
} catch (e) {
addError(e);
}
}
};
fetchDescribeTable();
}, [auth, url, schema, table]);

useEffect(() => {
if (tableDescription) {
setHasHashAttr(Boolean(tableDescription.hash_attribute));
if (tableState) {
setHasHashAttr(Boolean(tableState.hashAttribute));
}
}, [tableDescription]);
}, [tableState]);

const validate = () => {
if (structure) {
Expand Down Expand Up @@ -146,7 +123,6 @@ function BrowseIndex() {

// eslint-disable-next-line
useEffect(validate, [structure, schema, table, compute_stack_id]);
useEffect(syncInstanceStructure, [auth, url, schema, table]);
useEffect(() => {
const clearTableDescriptionCacheInterval = setInterval(() => {
clearTableDescriptionCache();
Expand Down Expand Up @@ -198,12 +174,7 @@ function BrowseIndex() {
) : schema && table && action && entities.activeTable ? (
<JSONEditor newEntityAttributes={tableState.newEntityAttributes} hashAttribute={tableState.hashAttribute} />
) : schema && table && entities.activeTable ? (
<DataTable
activeTable={entities.activeTable}
tableDescriptionAttributes={tableDescription?.attributes}
tableState={tableState}
setTableState={setTableState}
/>
<BrowseDatatable activeTable={entities.activeTable} tableState={tableState} setTableState={setTableState} />
) : schema && table && !hasHashAttr ? (
<NoPrimaryKeyMessage />
) : (
Expand Down
1 change: 0 additions & 1 deletion src/components/instance/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ function InstanceIndex() {
if (thisInstance && instanceAuth) {
instanceState.update(() => thisInstance);
const { error } = await buildInstanceStructure({ auth: instanceAuth, url: thisInstance.url });
await registrationInfo({ auth: instanceAuth, url: thisInstance.url });
setLoadingInstance(false);
if (error) {
if (config.is_local_studio) {
Expand Down
Loading