Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add relational filter conditions in data browser #2576

Merged
merged 21 commits into from
Jul 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5776e69
feat:Add relational filter conditions (#2496)
vardhan0604 Jun 26, 2024
8e0b31e
Merge branch 'alpha' of https://github.com/vardhan0604/parse-dashboar…
vardhan0604 Jun 26, 2024
4077cbb
undo changes in Parse-Dashboard/parse-dashboard-config.json
vardhan0604 Jun 26, 2024
9876a2f
fixes lint issue
vardhan0604 Jun 26, 2024
6efa332
undo changes in parse-dashboard-config.json
vardhan0604 Jun 27, 2024
e164e9b
Merge branch 'alpha' into alpha
mtrezza Jun 27, 2024
2efe0e7
corrected the variable name using right naming conventions
vardhan0604 Jun 28, 2024
6c62582
fixing continous loading of the table
vardhan0604 Jun 28, 2024
8d24ccd
delete file
mtrezza Jun 28, 2024
fd9b237
remove empty lines
mtrezza Jun 28, 2024
8563152
removing duplicacy
vardhan0604 Jun 29, 2024
3c0ae28
Merge branch 'alpha' of https://github.com/vardhan0604/parse-dashboar…
vardhan0604 Jun 29, 2024
7cea685
added the default class as the current class in the filter
vardhan0604 Jul 1, 2024
a5c0db3
updated filter dialog UI
vardhan0604 Jul 1, 2024
7c6645b
updated the readme.md
vardhan0604 Jul 1, 2024
0449e04
Update README.md
mtrezza Jul 1, 2024
d5c4346
fixed new class not showing locally
vardhan0604 Jul 2, 2024
3e5f899
Merge branch 'alpha' of https://github.com/vardhan0604/parse-dashboar…
vardhan0604 Jul 2, 2024
b6b3e72
updated the filter dialog UI
vardhan0604 Jul 2, 2024
6411715
fix new class not loading without reload
vardhan0604 Jul 3, 2024
695cbaf
lint fix
mtrezza Jul 6, 2024
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
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ Parse Dashboard is a standalone dashboard for managing your [Parse Server](https
- [Configuring Localized Push Notifications](#configuring-localized-push-notifications)
- [Run with Docker](#run-with-docker)
- [Features](#features)
- [Data Browser](#data-browser)
- [Filters](#filters)
- [Browse as User](#browse-as-user)
- [Change Pointer Key](#change-pointer-key)
- [Limitations](#limitations)
Expand Down Expand Up @@ -815,6 +817,26 @@ If you are not familiar with Docker, ``--port 8080`` will be passed in as argume
# Features
*(The following is not a complete list of features but a work in progress to build a comprehensive feature list.)*

## Data Browser

### Filters

▶️ *Core > Browser > Filter*

The filter dialog allows to add relational filter conditions based on other classes that have a pointer to the current class.

For example, users in the `_User` class may have:

- purchases in a `Purchase` class with a `_User` pointer field
- transactions in a `Payment` class with a `_User` pointer field

A relational filter allows you filter all users who:

- purchased a specific item (in `Purchase` class)
- payed with a specific payment method (in `Payment` class)

To apply such a filter, simply go to the `_User` class and add the two required filter conditions with the `Purchase` and `Payment` classes.

## Browse as User

▶️ *Core > Browser > Browse*
Expand Down
100 changes: 60 additions & 40 deletions src/components/BrowserFilter/BrowserFilter.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,16 @@ export default class BrowserFilter extends React.Component {
toggle() {
let filters = this.props.filters;
if (this.props.filters.size === 0) {
const available = Filters.availableFilters(
this.props.schema,
null,
this.state.blacklistedFilters
const available = Filters.findRelatedClasses(
this.props.className,
this.props.allClassesSchema,
this.state.blacklistedFilters,
this.state.filters
);
const field = Object.keys(available)[0];
filters = new List([new Map({ field: field, constraint: available[field][0] })]);
const { filterClass, filterField, filterConstraint } = Filters.getFilterDetails(available);
filters = new List([
new Map({ class: filterClass, field: filterField, constraint: filterConstraint }),
]);
}
this.setState(prevState => ({
open: !prevState.open,
Expand All @@ -65,14 +68,17 @@ export default class BrowserFilter extends React.Component {
}

addRow() {
const available = Filters.availableFilters(
this.props.schema,
this.state.filters,
this.state.blacklistedFilters
const available = Filters.findRelatedClasses(
this.props.className,
this.props.allClassesSchema,
this.state.blacklistedFilters,
this.state.filters
);
const field = Object.keys(available)[0];
const { filterClass, filterField, filterConstraint } = Filters.getFilterDetails(available);
this.setState(({ filters }) => ({
filters: filters.push(new Map({ field: field, constraint: available[field][0] })),
filters: filters.push(
new Map({ class: filterClass, field: filterField, constraint: filterConstraint })
),
editMode: true,
}));
}
Expand Down Expand Up @@ -125,7 +131,12 @@ export default class BrowserFilter extends React.Component {
if (this.props.filters.size) {
popoverStyle.push(styles.active);
}
const available = Filters.availableFilters(this.props.schema, this.state.filters);
const available = Filters.findRelatedClasses(
this.props.className,
this.props.allClassesSchema,
this.state.blacklistedFilters,
this.state.filters
);
popover = (
<Popover
fixed={true}
Expand Down Expand Up @@ -154,6 +165,11 @@ export default class BrowserFilter extends React.Component {
filters={this.state.filters}
onChange={filters => this.setState({ filters: filters })}
onSearch={this.apply.bind(this)}
allClasses={this.props.allClassesSchema}
allClassesSchema={Filters.findRelatedClasses(
this.props.className,
this.props.allClassesSchema
)}
renderRow={props => (
<FilterRow
{...props}
Expand Down Expand Up @@ -194,33 +210,37 @@ export default class BrowserFilter extends React.Component {
)}
{!this.state.confirmName && (
<div className={styles.footer}>
<Button
color="white"
value="Save"
width="120px"
onClick={() => this.setState({ confirmName: true })}
/>
<Button
color="white"
value="Clear"
disabled={this.state.filters.size === 0}
width="120px"
onClick={() => this.clear()}
/>
<Button
color="white"
value="Add"
disabled={Object.keys(available).length === 0}
width="120px"
onClick={() => this.addRow()}
/>
<Button
color="white"
primary={true}
value="Apply"
width="120px"
onClick={() => this.apply()}
/>
<div className={styles.btnFlex}>
<Button
color="white"
value="Save"
width="120px"
onClick={() => this.setState({ confirmName: true })}
/>
<Button
color="white"
value="Clear"
disabled={this.state.filters.size === 0}
width="120px"
onClick={() => this.clear()}
/>
</div>
<div className={styles.btnFlex}>
<Button
color="white"
value="Add"
disabled={Object.keys(available).length === 0}
width="120px"
onClick={() => this.addRow()}
/>
<Button
color="white"
primary={true}
value="Apply"
width="120px"
onClick={() => this.apply()}
/>
</div>
</div>
)}
</div>
Expand Down
21 changes: 18 additions & 3 deletions src/components/BrowserFilter/BrowserFilter.scss
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,24 @@

.body {
position: absolute;
display: flex;
flex-direction: column;
max-height: 500px;
overflow: hidden;
top: 30px;
right: 0;
border-radius: 5px 0 5px 5px;
background: #797691;
width: 535px;
width: 685px;
font-size: 14px;
}

.footer {
background: rgba(0,0,0,0.2);
padding: 11px 0;
padding: 11px 16px;
text-align: center;

display: flex;
justify-content: space-between;
> button {
margin-right: 10px;

Expand Down Expand Up @@ -148,3 +153,13 @@
display: inline-block;
vertical-align: top;
}

.flex{
display: flex;
align-items: center;
}

.btnFlex{
display: flex;
gap: 12px;
}
48 changes: 45 additions & 3 deletions src/components/BrowserFilter/FilterRow.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,15 @@ function compareValue(
}

const FilterRow = ({
classes,
fields,
constraints,
compareInfo,
currentClass,
currentField,
currentConstraint,
compareTo,
onChangeClass,
onChangeField,
onChangeConstraint,
onChangeCompareTo,
Expand All @@ -119,13 +122,52 @@ const FilterRow = ({
}
}, []);

const buildSuggestions = input => {
const buildFieldSuggestions = input => {
const regex = new RegExp(input.split('').join('.*?'), 'i');
return fields.filter(f => regex.test(f));
};
const buildClassSuggestions = input => {
const regex = new RegExp(input.split('').join('.*?'), 'i');
return classes.filter(f => regex.test(f));
};

return (
<div className={styles.row}>
<div className={`${styles.row} ${styles.flex}`}>
<Autocomplete
inputStyle={{
transition: '0s background-color ease-in-out',
}}
suggestionsStyle={{
width: '140px',
maxHeight: '360px',
overflowY: 'auto',
fontSize: '14px',
background: '#343445',
borderBottomLeftRadius: '5px',
borderBottomRightRadius: '5px',
color: 'white',
cursor: 'pointer',
}}
suggestionsItemStyle={{
background: '#343445',
color: 'white',
height: '30px',
lineHeight: '30px',
borderBottom: '0px',
}}
containerStyle={{
display: 'inline-block',
width: '140px',
verticalAlign: 'top',
height: '30px',
}}
strict={true}
value={currentClass}
suggestions={classes}
onChange={onChangeClass}
buildSuggestions={buildClassSuggestions}
buildLabel={() => ''}
/>
<Autocomplete
inputStyle={{
transition: '0s background-color ease-in-out',
Expand Down Expand Up @@ -158,7 +200,7 @@ const FilterRow = ({
value={currentField}
suggestions={fields}
onChange={onChangeField}
buildSuggestions={buildSuggestions}
buildSuggestions={buildFieldSuggestions}
buildLabel={() => ''}
/>
<ChromeDropdown
Expand Down
Loading
Loading