Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1e707d5
feat: add custom views page
mtrezza Jul 10, 2025
5f61237
chore: address lint issues
mtrezza Jul 10, 2025
eab8cf3
fix: populate classes in Views dialog
mtrezza Jul 10, 2025
d485379
fix: handle view query errors
mtrezza Jul 10, 2025
8825239
fix: align view table headers
mtrezza Jul 10, 2025
49cd9fc
feat: link pointers in views
mtrezza Jul 10, 2025
6ed37ba
fix: preserve filter URL for pointer links
mtrezza Jul 10, 2025
bb8eabd
fix: improve views table usability
mtrezza Jul 10, 2025
e97fbd9
fix: sync views column widths
mtrezza Jul 10, 2025
1de7b4c
fix: align resizable view columns
mtrezza Jul 10, 2025
5781c2b
fix: align view headers with columns
mtrezza Jul 10, 2025
c0ca3e2
fix: stabilize column resize
mtrezza Jul 10, 2025
0404b3e
fix: sync view headers with scroll
mtrezza Jul 10, 2025
1708ad9
fix: allow route for views page
mtrezza Jul 10, 2025
d490260
fix: parse route query string
mtrezza Jul 11, 2025
7c6230a
Revert "fix: sync view headers with scroll"
mtrezza Jul 11, 2025
510dea2
Revert "fix: allow route for views page"
mtrezza Jul 11, 2025
d18cb6a
Revert "fix: parse route query string"
mtrezza Jul 11, 2025
80ef8c1
feat: Allow editing views (#2889)
mtrezza Jul 11, 2025
eef72bd
fix: Prevent stale pointer navigation (#2890)
mtrezza Jul 12, 2025
146ec5d
fix: Handle invalid pointers in Views results (#2891)
mtrezza Jul 12, 2025
5b96bea
Update TableView.scss
mtrezza Jul 12, 2025
f9514dd
Cell height fix
mtrezza Jul 12, 2025
dc36630
fix: Center pill in Views table cells (#2895)
mtrezza Jul 12, 2025
d74b4f8
docs: Add Views feature (#2896)
mtrezza Jul 12, 2025
d657be1
fix: Display ISO string for date objects in views (#2897)
mtrezza Jul 13, 2025
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
3 changes: 3 additions & 0 deletions src/dashboard/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import SlowQueries from './Analytics/SlowQueries/SlowQueries.react';
import styles from 'dashboard/Apps/AppsIndex.scss';
import UsersSettings from './Settings/UsersSettings.react';
import Webhooks from './Data/Webhooks/Webhooks.react';
import Views from './Data/Views/Views.react';
import { AsyncStatus } from 'lib/Constants';
import baseStyles from 'stylesheets/base.scss';
import { get } from 'lib/AJAX';
Expand Down Expand Up @@ -270,6 +271,8 @@ export default class Dashboard extends React.Component {

<Route path="cloud_code" element={<CloudCode />} />
<Route path="cloud_code/*" element={<CloudCode />} />
<Route path="views/:name" element={<Views />} />
<Route path="views" element={<Views />} />
<Route path="webhooks" element={<Webhooks />} />

<Route path="jobs">{JobsRoute}</Route>
Expand Down
5 changes: 5 additions & 0 deletions src/dashboard/DashboardView.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ export default class DashboardView extends React.Component {
});
}

coreSubsections.push({
name: 'Views',
link: '/views',
});

//webhooks requires removal of heroku link code, then it should work.
if (
features.hooks &&
Expand Down
111 changes: 111 additions & 0 deletions src/dashboard/Data/Views/CreateViewDialog.react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import Dropdown from 'components/Dropdown/Dropdown.react';
import Field from 'components/Field/Field.react';
import Label from 'components/Label/Label.react';
import Modal from 'components/Modal/Modal.react';
import Option from 'components/Dropdown/Option.react';
import React from 'react';
import TextInput from 'components/TextInput/TextInput.react';
import Checkbox from 'components/Checkbox/Checkbox.react';

function isValidJSON(value) {
try {
JSON.parse(value);
return true;
} catch {
return false;
}
}

export default class CreateViewDialog extends React.Component {
constructor() {
super();
this.state = {
name: '',
className: '',
query: '[]',
showCounter: false,
};
}

valid() {
return (
this.state.name.length > 0 &&
this.state.className.length > 0 &&
isValidJSON(this.state.query)
);
}

render() {
const { classes, onConfirm, onCancel } = this.props;
return (
<Modal
type={Modal.Types.INFO}
icon="plus"
iconSize={40}
title="Create a new view?"
subtitle="Define a custom query to display data."
confirmText="Create"
cancelText="Cancel"
disabled={!this.valid()}
onCancel={onCancel}
onConfirm={() =>
onConfirm({
name: this.state.name,
className: this.state.className,
query: JSON.parse(this.state.query),
showCounter: this.state.showCounter,
})
}
>
<Field
label={<Label text="Name" />}
input={
<TextInput
value={this.state.name}
onChange={name => this.setState({ name })}
/>
}
/>
<Field
label={<Label text="Class" />}
input={
<Dropdown
value={this.state.className}
onChange={className => this.setState({ className })}
>
{classes.map(c => (
<Option key={c} value={c}>
{c}
</Option>
))}
</Dropdown>
}
/>
<Field
label={
<Label
text="Query"
description="An aggregation pipeline that returns an array of items."
/>
}
input={
<TextInput
multiline={true}
value={this.state.query}
onChange={query => this.setState({ query })}
/>
}
/>
<Field
label={<Label text="Show object counter" />}
input={
<Checkbox
checked={this.state.showCounter}
onChange={showCounter => this.setState({ showCounter })}
/>
}
/>
</Modal>
);
}
}
Loading
Loading