Skip to content

Commit

Permalink
collapse filters in group
Browse files Browse the repository at this point in the history
  • Loading branch information
olmobrutall committed Jul 29, 2019
1 parent 1a3bcc9 commit 99a38a2
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 50 deletions.
2 changes: 2 additions & 0 deletions Signum.Entities/EnumMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ public enum SearchMessage
PleaseSelectAnEntity,
[Description("Please select one or several Entities")]
PleaseSelectOneOrSeveralEntities,
[Description("{0} filters collapsed")]
_0FiltersCollapsed,
}

public enum SelectorMessage
Expand Down
1 change: 1 addition & 0 deletions Signum.React/Scripts/FindOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export interface PinnedFilter {
export interface FilterGroupOptionParsed {
groupOperation: FilterGroupOperation;
frozen: boolean;
expanded: boolean;
token?: QueryToken;
filters: FilterOptionParsed[];
pinned?: PinnedFilter;
Expand Down
4 changes: 2 additions & 2 deletions Signum.React/Scripts/Finder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,8 @@ export class TokenCompleter {
value: fo.value,
pinned: fo.pinned && { ...fo.pinned },
filters: fo.filters.map(f => this.toFilterOptionParsed(f)),
frozen: false,
expanded: false,
} as FilterGroupOptionParsed);
else
return ({
Expand All @@ -927,8 +929,6 @@ export class TokenCompleter {
}
}



export function parseFilterValues(filterOptions: FilterOptionParsed[]): Promise<void> {

const needToStr: Lite<any>[] = [];
Expand Down
116 changes: 68 additions & 48 deletions Signum.React/Scripts/SearchControl/FilterBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default class FilterBuilder extends React.Component<FilterBuilderProps>{
token: lastToken && hasAnyOrAll(lastToken) ? getTokenParents(lastToken).filter(a => a.queryTokenType == "AnyOrAll").lastOrNull() : undefined,
filters: [],
frozen: false,
expanded: true,
} as FilterGroupOptionParsed :
{
token: this.props.lastToken,
Expand Down Expand Up @@ -192,6 +193,7 @@ export class FilterGroupComponent extends React.Component<FilterGroupComponentsP
token: lastToken && hasAnyOrAll(lastToken) ? getTokenParents(lastToken).filter(a => a.queryTokenType == "AnyOrAll").lastOrNull() : this.props.prefixToken,
filters: [],
frozen: false,
expanded: true,
} as FilterGroupOptionParsed :
{
token: lastToken,
Expand All @@ -206,6 +208,14 @@ export class FilterGroupComponent extends React.Component<FilterGroupComponentsP
this.forceUpdate(() => this.props.onHeightChanged());
};

handleExpandCollapse = (e: React.MouseEvent<any>) => {
e.preventDefault();
const fg = this.props.filterGroup;
fg.expanded = !fg.expanded;

this.forceUpdate(() => this.props.onHeightChanged());
}

render() {
const fg = this.props.filterGroup;

Expand All @@ -224,15 +234,18 @@ export class FilterGroupComponent extends React.Component<FilterGroupComponentsP
<td colSpan={3} style={{ backgroundColor: fg.groupOperation == "Or" ? "#eee" : "#fff", border: "1px solid #ddd" }}>
<div className="justify-content-between d-flex" >
<div className="form-inline">
<a href="#" onClick={this.handleExpandCollapse} className={classes(fg.expanded ? "sf-hide-group-button" : "sf-show-group-button", "mx-2")} >
<FontAwesomeIcon icon={fg.expanded ? ["far", "minus-square"] : ["far", "plus-square"]} className="mr-2" />
</a>
<label>Group:</label>
<select className="form-control form-control-sm sf-group-selector ml-2" value={fg.groupOperation as any} disabled={readOnly} onChange={this.handleChangeOperation}>
<select className="form-control form-control-xs sf-group-selector mx-2" value={fg.groupOperation as any} disabled={readOnly} onChange={this.handleChangeOperation}>
{FilterGroupOperation.values().map((ft, i) => <option key={i} value={ft as any}>{FilterGroupOperation.niceToString(ft)}</option>)}
</select>
</div>

<div className="form-inline">
<label>Prefix:</label>
<div className={classes("rw-widget-xs ml-3", fg.token == null ? "hidden" : undefined)}>
<div className={classes("rw-widget-xs mx-2", fg.token == null ? "hidden" : undefined)}>
<QueryTokenBuilder
prefixQueryToken={this.props.prefixToken}
queryToken={fg.token}
Expand All @@ -242,12 +255,11 @@ export class FilterGroupComponent extends React.Component<FilterGroupComponentsP
readOnly={readOnly} />
</div>
</div>
{fg.pinned && <div>
{(this.props.renderValue ? this.props.renderValue(this) : this.renderValue())}



</div>}
{fg.pinned &&
<div>
{(this.props.renderValue ? this.props.renderValue(this) : this.renderValue())}
</div>
}
<div>
{this.props.showPinnedFilters &&
<button className={classes("btn", "btn-link", "btn-sm", "sf-user-filter", fg.pinned && "active")} onClick={e => { fg.pinned = fg.pinned ? undefined : {}; this.changeFilter(); }} disabled={this.props.readOnly}>
Expand All @@ -260,51 +272,59 @@ export class FilterGroupComponent extends React.Component<FilterGroupComponentsP
<table className="table-sm" style={{ width: "100%" }}>
<thead>
{fg.pinned && <PinnedFilterEditor pinned={fg.pinned} onChange={() => this.changeFilter()} readonly={readOnly} />}
<tr>
{fg.expanded && <tr>
<th style={{ minWidth: "24px" }}></th>
<th>{SearchMessage.Field.niceToString()}</th>
<th>{SearchMessage.Operation.niceToString()}</th>
<th style={{ paddingRight: "20px" }}>{SearchMessage.Value.niceToString()}</th>
</tr>
}
</thead>
<tbody>
{fg.filters.map((f, i) => isFilterGroupOptionParsed(f) ?

<FilterGroupComponent key={i} filterGroup={f} readOnly={Boolean(this.props.readOnly)} onDeleteFilter={this.handlerDeleteFilter}
prefixToken={fg.token}
subTokensOptions={this.props.subTokensOptions} queryDescription={this.props.queryDescription}
onTokenChanged={this.props.onTokenChanged} onFilterChanged={this.props.onFilterChanged}
lastToken={this.props.lastToken} onHeightChanged={this.props.onHeightChanged} renderValue={this.props.renderValue}
showPinnedFilters={this.props.showPinnedFilters}
disableValue={this.props.disableValue || Boolean(fg.pinned)}
/> :

<FilterConditionComponent key={i} filter={f} readOnly={Boolean(this.props.readOnly)} onDeleteFilter={this.handlerDeleteFilter}
prefixToken={fg.token}
subTokensOptions={this.props.subTokensOptions} queryDescription={this.props.queryDescription}
onTokenChanged={this.props.onTokenChanged} onFilterChanged={this.props.onFilterChanged} renderValue={this.props.renderValue}
showPinnedFilters={this.props.showPinnedFilters}
disableValue={this.props.disableValue || Boolean(fg.pinned)}
/>
)}
{!this.props.readOnly &&
<tr className="sf-filter-create">
<td colSpan={4}>
<a href="#" title={TitleManager.useTitle ? SearchMessage.AddFilter.niceToString() : undefined}
className="sf-line-button sf-create"
onClick={e => this.handlerNewFilter(e, false)}>
<FontAwesomeIcon icon="plus" className="sf-create" />&nbsp;{SearchMessage.AddFilter.niceToString()}
</a>

<a href="#" title={TitleManager.useTitle ? SearchMessage.AddGroup.niceToString() : undefined}
className="sf-line-button sf-create ml-3"
onClick={e => this.handlerNewFilter(e, true)}>
<FontAwesomeIcon icon="plus" className="sf-create" />&nbsp;{SearchMessage.AddGroup.niceToString()}
</a>
</td>
{fg.expanded ?
<tbody>
{fg.filters.map((f, i) => isFilterGroupOptionParsed(f) ?

<FilterGroupComponent key={i} filterGroup={f} readOnly={Boolean(this.props.readOnly)} onDeleteFilter={this.handlerDeleteFilter}
prefixToken={fg.token}
subTokensOptions={this.props.subTokensOptions} queryDescription={this.props.queryDescription}
onTokenChanged={this.props.onTokenChanged} onFilterChanged={this.props.onFilterChanged}
lastToken={this.props.lastToken} onHeightChanged={this.props.onHeightChanged} renderValue={this.props.renderValue}
showPinnedFilters={this.props.showPinnedFilters}
disableValue={this.props.disableValue || Boolean(fg.pinned)}
/> :

<FilterConditionComponent key={i} filter={f} readOnly={Boolean(this.props.readOnly)} onDeleteFilter={this.handlerDeleteFilter}
prefixToken={fg.token}
subTokensOptions={this.props.subTokensOptions} queryDescription={this.props.queryDescription}
onTokenChanged={this.props.onTokenChanged} onFilterChanged={this.props.onFilterChanged} renderValue={this.props.renderValue}
showPinnedFilters={this.props.showPinnedFilters}
disableValue={this.props.disableValue || Boolean(fg.pinned)}
/>
)}
{!this.props.readOnly &&
<tr className="sf-filter-create">
<td colSpan={4}>
<a href="#" title={TitleManager.useTitle ? SearchMessage.AddFilter.niceToString() : undefined}
className="sf-line-button sf-create"
onClick={e => this.handlerNewFilter(e, false)}>
<FontAwesomeIcon icon="plus" className="sf-create" />&nbsp;{SearchMessage.AddFilter.niceToString()}
</a>

<a href="#" title={TitleManager.useTitle ? SearchMessage.AddGroup.niceToString() : undefined}
className="sf-line-button sf-create ml-3"
onClick={e => this.handlerNewFilter(e, true)}>
<FontAwesomeIcon icon="plus" className="sf-create" />&nbsp;{SearchMessage.AddGroup.niceToString()}
</a>
</td>
</tr>
}
</tbody> :
<tbody>
<tr>
<td colSpan={4} style={{ color: "#aaa", textAlign: "center", fontSize: "smaller" }}> {SearchMessage._0FiltersCollapsed.niceToString(fg.filters.length)}</td>
</tr>
}
</tbody>
</tbody>
}
</table>
</div>
</td>
Expand Down Expand Up @@ -525,11 +545,11 @@ export class PinnedFilterEditor extends React.Component<PinnedFilterEditorProps>

var val = binding.getValue();
if (this.props.readonly)
return <span className="numeric form-control form-control-xs" style={{ width: "30px" }}>{val}</span>;
return <span className="numeric form-control form-control-xs" style={{ width: "60px" }}>{val}</span>;

return (
<NumericTextBox value={val == undefined ? null : val} onChange={n => { binding.setValue(n == null ? undefined : n); this.props.onChange(); }}
validateKey={ValueLine.isNumber} formControlClass="form-control form-control-xs" htmlAttributes={{ placeholder: title, style: { width: "30px" } }} />
validateKey={ValueLine.isNumber} formControlClass="form-control form-control-xs" htmlAttributes={{ placeholder: title, style: { width: "60px" } }} />
);
}

Expand Down
10 changes: 10 additions & 0 deletions Signum.React/Scripts/SearchControl/Search.css
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,13 @@ ul.sf-context-menu li a:not([disabled]) {
.sf-query-token-part .rw-list-empty, .rw-list-option, .rw-list-optgroup {
padding: 0 .5em;
}

.sf-hide-group-button{
font-weight: bold;
color: dimgray;
}

.sf-show-group-button {
font-weight: bold;
color: black;
}
1 change: 1 addition & 0 deletions Signum.React/Scripts/Signum.Entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,7 @@ export module SearchMessage {
export const PleaseSelectOneOrMore0_G = new MessageKey("SearchMessage", "PleaseSelectOneOrMore0_G");
export const PleaseSelectAnEntity = new MessageKey("SearchMessage", "PleaseSelectAnEntity");
export const PleaseSelectOneOrSeveralEntities = new MessageKey("SearchMessage", "PleaseSelectOneOrSeveralEntities");
export const _0FiltersCollapsed = new MessageKey("SearchMessage", "_0FiltersCollapsed");
}

export module SelectorMessage {
Expand Down

0 comments on commit 99a38a2

Please sign in to comment.