From d4fa0589b98942346e420c3afa26e5664344064f Mon Sep 17 00:00:00 2001 From: Clayton1805 Date: Fri, 6 Sep 2024 23:45:03 -0300 Subject: [PATCH] feat: remove pre-selected key from filter fields --- .../Autocomplete/Autocomplete.react.js | 5 + .../BrowserFilter/BrowserFilter.react.js | 39 ++-- .../BrowserFilter/FilterRow.react.js | 2 + src/components/Filter/Filter.react.js | 206 ++++++++++++++---- 4 files changed, 185 insertions(+), 67 deletions(-) diff --git a/src/components/Autocomplete/Autocomplete.react.js b/src/components/Autocomplete/Autocomplete.react.js index 4904fffc9f..91d0eff873 100644 --- a/src/components/Autocomplete/Autocomplete.react.js +++ b/src/components/Autocomplete/Autocomplete.react.js @@ -61,6 +61,11 @@ export default class Autocomplete extends Component { window.addEventListener('resize', this.handleResize); this.fieldRef.current.addEventListener('scroll', this.handleScroll); this.recalculatePosition(); + + if (this.props.initialFocusOnTheField) { + this.inputRef.current.focus(); + } + this._ignoreBlur = false; this._suggestionClicked = false; } diff --git a/src/components/BrowserFilter/BrowserFilter.react.js b/src/components/BrowserFilter/BrowserFilter.react.js index 38aeba2825..b02d5131f8 100644 --- a/src/components/BrowserFilter/BrowserFilter.react.js +++ b/src/components/BrowserFilter/BrowserFilter.react.js @@ -32,6 +32,7 @@ export default class BrowserFilter extends React.Component { confirmName: false, name: '', blacklistedFilters: Filters.BLACKLISTED_FILTERS.concat(props.blacklistedFilters), + filtersArrayDraft: [], }; this.toggle = this.toggle.bind(this); this.wrapRef = React.createRef(); @@ -44,19 +45,7 @@ export default class BrowserFilter extends React.Component { } toggle() { - let filters = this.props.filters; - if (this.props.filters.size === 0) { - const available = Filters.findRelatedClasses( - this.props.className, - this.props.allClassesSchema, - this.state.blacklistedFilters, - this.state.filters - ); - const { filterClass, filterField, filterConstraint } = Filters.getFilterDetails(available); - filters = new List([ - new Map({ class: filterClass, field: filterField, constraint: filterConstraint }), - ]); - } + const filters = this.props.filters; this.setState(prevState => ({ open: !prevState.open, filters: filters, @@ -68,18 +57,14 @@ export default class BrowserFilter extends React.Component { } addRow() { - const available = Filters.findRelatedClasses( - this.props.className, - this.props.allClassesSchema, - this.state.blacklistedFilters, - this.state.filters - ); - const { filterClass, filterField, filterConstraint } = Filters.getFilterDetails(available); - this.setState(({ filters }) => ({ - filters: filters.push( - new Map({ class: filterClass, field: filterField, constraint: filterConstraint }) - ), - editMode: true, + this.setState(({ filtersArrayDraft }) => ({ + filtersArrayDraft: [ + ...filtersArrayDraft, + new Map({ + class: this.props.className, + field: '', + }), + ], })); } @@ -164,6 +149,10 @@ export default class BrowserFilter extends React.Component { schema={this.props.schema} filters={this.state.filters} onChange={filters => this.setState({ filters: filters })} + setFiltersArrayDraft={callback => + this.setState({ filtersArrayDraft: callback(this.state.filtersArrayDraft) }) + } + filtersArrayDraft={this.state.filtersArrayDraft} onSearch={this.apply.bind(this)} allClasses={this.props.allClassesSchema} allClassesSchema={Filters.findRelatedClasses( diff --git a/src/components/BrowserFilter/FilterRow.react.js b/src/components/BrowserFilter/FilterRow.react.js index eb10875eb3..d87ce1a796 100644 --- a/src/components/BrowserFilter/FilterRow.react.js +++ b/src/components/BrowserFilter/FilterRow.react.js @@ -115,6 +115,7 @@ const FilterRow = ({ active, parentContentId, editMode, + initialFocusOnTheField, }) => { const setFocus = useCallback(input => { if (input !== null && editMode) { @@ -202,6 +203,7 @@ const FilterRow = ({ onChange={onChangeField} buildSuggestions={buildFieldSuggestions} buildLabel={() => ''} + initialFocusOnTheField={initialFocusOnTheField} /> + filtersArrayDraftState.filter((_, indexElement) => indexElement !== index) + ); +} + +function changeClassDraft(setFiltersArrayDraft, index, newClassName) { + setFiltersArrayDraft(filtersArrayDraftState => + filtersArrayDraftState.map((element, indexElement) => { + if (indexElement === index) { + return new Map({ + class: newClassName, + field: '', + }); + } else { + return element; + } + }) + ); +} + +function changeFieldDraft( + schema, + currentClassName, + filters, + index, + newField, + fields, + setFiltersArrayDraft +) { + const fieldIsValid = fields.find(field => field === newField); + + if (fieldIsValid) { + const newFilterDraft = new Map({ + class: currentClassName, + field: newField, + constraint: Filters.FieldConstraints[schema[currentClassName][newField].type][0], + compareTo: Filters.DefaultComparisons[schema[currentClassName][newField].type], + }); + + deleteRowDraft(setFiltersArrayDraft, index); + return filters.push(newFilterDraft); + } else { + return filters; + } +} + +function getFields(available, currentClassName, field, currentApp, className) { + let fields = []; + if (available[currentClassName]) { + fields = Object.keys(available[currentClassName]).concat([]); + } + if (field !== '' && fields.indexOf(field) < 0) { + fields.push(field); + } + + // Get the column preference of the current class. + const currentColumnPreference = currentApp.columnPreference + ? currentApp.columnPreference[className] + : null; + + // Check if the preference exists. + if (currentColumnPreference) { + const fieldsToSortToTop = currentColumnPreference + .filter(item => item.filterSortToTop) + .map(item => item.name); + // Sort the fields. + fields.sort((a, b) => { + // Only "a" should sorted to the top. + if (fieldsToSortToTop.includes(a) && !fieldsToSortToTop.includes(b)) { + return -1; + } + // Only "b" should sorted to the top. + if (!fieldsToSortToTop.includes(a) && fieldsToSortToTop.includes(b)) { + return 1; + } + // Both should sorted to the top -> they should be sorted to the same order as in the "fieldsToSortToTop" array. + if (fieldsToSortToTop.includes(a) && fieldsToSortToTop.includes(b)) { + return fieldsToSortToTop.indexOf(a) - fieldsToSortToTop.indexOf(b); + } + return stringCompare(a, b); + }); + } + // If there's no preference: Use the default sort function. + else { + fields.sort(); + } + + return fields; +} + const Filter = ({ schema, filters, @@ -84,17 +176,38 @@ const Filter = ({ onSearch, blacklist, className, + setFiltersArrayDraft, + filtersArrayDraft, }) => { const [compare, setCompare] = useState(false); + const [filtersArrayDraftLengthMemory, setFiltersArrayDraftLengthMemory] = useState(0); const hasCompareTo = filters.some(filter => filter.get('compareTo') !== undefined); - if(compare !== hasCompareTo){ + if (compare !== hasCompareTo) { setCompare(hasCompareTo); } const currentApp = React.useContext(CurrentApp); blacklist = blacklist || []; const available = Filters.findRelatedClasses(className, allClasses, blacklist, filters); const classes = Object.keys(available).concat([]); + + useEffect(() => { + if (filters.size === 0) { + setFiltersArrayDraft(() => [ + new Map({ + class: className, + field: '', + }), + ]); + } else { + setFiltersArrayDraft(() => []); + } + }, []); + + useEffect(() => { + setFiltersArrayDraftLengthMemory(filtersArrayDraft.length); + }, [filtersArrayDraft]); + return (
Class
@@ -123,45 +236,8 @@ const Filter = ({ const field = filter.get('field'); const constraint = filter.get('constraint'); const compareTo = filter.get('compareTo'); - let fields = []; - if (available[currentClassName]) { - fields = Object.keys(available[currentClassName]).concat([]); - } - if (fields.indexOf(field) < 0) { - fields.push(field); - } + const fields = getFields(available, currentClassName, field, currentApp, className); - // Get the column preference of the current class. - const currentColumnPreference = currentApp.columnPreference - ? currentApp.columnPreference[className] - : null; - - // Check if the preference exists. - if (currentColumnPreference) { - const fieldsToSortToTop = currentColumnPreference - .filter(item => item.filterSortToTop) - .map(item => item.name); - // Sort the fields. - fields.sort((a, b) => { - // Only "a" should sorted to the top. - if (fieldsToSortToTop.includes(a) && !fieldsToSortToTop.includes(b)) { - return -1; - } - // Only "b" should sorted to the top. - if (!fieldsToSortToTop.includes(a) && fieldsToSortToTop.includes(b)) { - return 1; - } - // Both should sorted to the top -> they should be sorted to the same order as in the "fieldsToSortToTop" array. - if (fieldsToSortToTop.includes(a) && fieldsToSortToTop.includes(b)) { - return fieldsToSortToTop.indexOf(a) - fieldsToSortToTop.indexOf(b); - } - return stringCompare(a, b); - }); - } - // If there's no preference: Use the default sort function. - else { - fields.sort(); - } const constraints = Filters.FieldConstraints[schema[currentClassName][field].type].filter( c => blacklist.indexOf(c) < 0 ); @@ -206,6 +282,52 @@ const Filter = ({ }, }); })} + + {filtersArrayDraft.map((filter, i) => { + const currentClassName = filter.get('class'); + const field = filter.get('field'); + const fields = getFields(available, currentClassName, field, currentApp, className); + + return renderRow({ + classes, + fields, + constraints: ['exists'], + compareInfo: { + type: undefined, + targetClass: null, + }, + currentClass: currentClassName, + currentField: field, + currentConstraint: 'exists', + key: i + 'draft' + filtersArrayDraft.length, + initialFocusOnTheField: + filtersArrayDraftLengthMemory === 0 || + (filtersArrayDraftLengthMemory < filtersArrayDraft.length && + filtersArrayDraft.length - 1 === i), + onChangeClass: newClassName => { + changeClassDraft(setFiltersArrayDraft, i, newClassName); + }, + onChangeField: newField => { + onChange( + changeFieldDraft( + schema, + currentClassName, + filters, + i, + newField, + fields, + setFiltersArrayDraft + ) + ); + }, + onChangeConstraint: () => {}, + onChangeCompareTo: () => {}, + onKeyDown: () => {}, + onDeleteRow: () => { + deleteRowDraft(setFiltersArrayDraft, i); + }, + }); + })}
); };