From 63fde16686acef2362f4a633e2b4c4c84ac12249 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Fri, 8 Sep 2023 13:38:40 -0500 Subject: [PATCH 01/17] remove unneeded if else --- moped-editor/src/libs/GQLAbstract.js | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/moped-editor/src/libs/GQLAbstract.js b/moped-editor/src/libs/GQLAbstract.js index a5e0e38e20..df586a76cb 100644 --- a/moped-editor/src/libs/GQLAbstract.js +++ b/moped-editor/src/libs/GQLAbstract.js @@ -8,6 +8,7 @@ class GQLAbstract { * @param {Object} The initial configuration of the abstract */ constructor(initConfig) { + console.log("constructor") this.config = initConfig; this.configInit = JSON.parse(JSON.stringify(initConfig)); this.config.filterStack = { @@ -138,6 +139,7 @@ class GQLAbstract { * Resets the value of where and or to empty */ cleanWhere() { + console.log("clean where") this.config.where = { ...this.configInit.where }; this.config.or = null; this.config.and = null; @@ -226,20 +228,9 @@ class GQLAbstract { * @param {string} syntax - either 'asc' or 'desc' */ setOrder(key, syntax) { - if (this.config && this.config.order_by) { - // First, RESET the order_by value, with the assumption - // that there should only by 1 order_by at a time. - // This assumption is a self-imposed subset of the GraphQL syntax - // which happens to make the removal of implicit ordering - // of order directives as implemented by Hasura in graphql-engine - // 2.0+ a non-issue for this app. + console.log("set order") this.config.order_by = {}; - // Now, set new key, syntax pair for order_by this.config.order_by[key] = syntax; - } else { - this.config.order_by = {}; - this.config.order_by[key] = syntax; - } } /** @@ -400,6 +391,7 @@ class GQLAbstract { * @returns {string} */ generateFilters(aggregate = false) { + console.log("how often is this?", aggregate) const output = []; const where = []; const or = []; @@ -482,6 +474,7 @@ class GQLAbstract { * @returns {string} */ get query() { + console.log("get query") // First copy the abstract and work from the copy let query = this.abstractStructure; @@ -647,6 +640,7 @@ class GQLAbstract { * @returns {Object} gql object */ get gql() { + console.log(this.query) return gql` ${this.query} `; From 294142219a396c06fa1c96cf352ef2454daeb90f Mon Sep 17 00:00:00 2001 From: chiaberry Date: Fri, 8 Sep 2023 13:38:56 -0500 Subject: [PATCH 02/17] remove weird index thing i added --- .../projectsListView/ProjectsListViewTable.js | 51 ++++++++----------- 1 file changed, 20 insertions(+), 31 deletions(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index ba1519b67c..2fba844103 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -15,7 +15,7 @@ import ProjectStatusBadge from "./../projectView/ProjectStatusBadge"; import ExternalLink from "../../../components/ExternalLink"; import RenderSignalLink from "../signalProjectTable/RenderSignalLink"; -import MaterialTable, { MTableBody, MTableHeader } from "@material-table/core"; +import MaterialTable, { MTableHeader } from "@material-table/core"; import { filterProjectTeamMembers as renderProjectTeamMembers } from "./helpers.js"; import { getSearchValue } from "../../../utils/gridTableHelpers"; import { formatDateType, formatTimeStampTZType } from "src/utils/dateAndTime"; @@ -102,6 +102,7 @@ const handleColumnChange = ({ field }, hidden) => { */ const ProjectsListViewTable = ({ query, searchTerm }) => { const classes = useStyles(); + console.log(query); /** * @type {Object} pagination @@ -192,17 +193,21 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { * Query Management */ // Manage the ORDER BY clause of our query - query.setOrder(sort.column, sort.order); - - // Set limit, offset based on pagination state - if (query.config.showPagination) { - query.limit = pagination.limit; - query.offset = pagination.offset; - } else { - query.limit = 0; - } + useEffect(() => { + query.setOrder(sort.column, sort.order); + }, [sort.column, sort.order, query]); + + useEffect(() => { + // Set limit, offset based on pagination state + if (query.config.showPagination) { + query.limit = pagination.limit; + query.offset = pagination.offset; + } else { + query.limit = 0; + } + }, [pagination.limit, pagination.offset, query]); - // Resets the value of "where" "and" "or" to empty + // Resets the value of "where" "and" "or" to empty -- make this only happen when needed query.cleanWhere(); // If we have a search value in state, initiate search @@ -271,6 +276,8 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { ); // Data Management + + // console.log(query.config.options.useQuery) const { data, loading, error } = useQuery( query.gql, query.config.options.useQuery @@ -534,8 +541,8 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { title: "Interim MPD (Access) ID", field: "interim_project_id", hidden: hiddenColumns["interim_project_id"], - emptyValue: "-" - } + emptyValue: "-", + }, ]; /** @@ -652,24 +659,6 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { orderDirection={sort.order} /> ), - Body: (props) => { - // see PR #639 https://github.com/cityofaustin/atd-moped/pull/639 for context - // we have configured MT to use local data but are technically using remote data - // this results in inconsistencies with how MT displays filtered data - const indexedData = data["project_list_view"].map( - (row, index) => ({ - tableData: { id: index, uuid: row.project_id }, - ...row, - }) - ); - return ( - - ); - }, }} /> From 8ba65a1e7fee4d8806134b775f7717472a021f51 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Mon, 11 Sep 2023 09:06:34 -0500 Subject: [PATCH 03/17] remove unused methods --- .../components/GridTable/GridTableSearch.js | 13 ++-- moped-editor/src/libs/GQLAbstract.js | 71 ------------------- .../ProjectsListViewQueryConf.js | 1 - .../projectsListView/ProjectsListViewTable.js | 1 - 4 files changed, 4 insertions(+), 82 deletions(-) diff --git a/moped-editor/src/components/GridTable/GridTableSearch.js b/moped-editor/src/components/GridTable/GridTableSearch.js index 762905e51f..5fe9363e41 100644 --- a/moped-editor/src/components/GridTable/GridTableSearch.js +++ b/moped-editor/src/components/GridTable/GridTableSearch.js @@ -23,7 +23,6 @@ import GridTableNewItem from "./GridTableNewItem"; import makeStyles from '@mui/styles/makeStyles'; import { useLazyQuery } from "@apollo/client"; import { format } from "date-fns"; -import { get } from "lodash"; const useStyles = makeStyles((theme) => ({ root: { @@ -193,19 +192,15 @@ const GridTableSearch = ({ const entry = {}; // For each column in the export configuration Object.keys(query.config.export).forEach((column) => { - // Extract the label, filter, and path - const { label, filter, path } = query.config.export[column]; + // Extract the label, filter + const { label, filter } = query.config.export[column]; // Determine the new column name, if available. const newColumnName = label ? label : column; - // If it's a nested graphql expression, use lodash get and - // the path to get to the value, otherwise, assign the value. - const value = query.isNestedKey(column) - ? get(record, path) - : record[column]; + const value = record[column]; + // If there is a filter, use it. Assign the value to the new column name. entry[newColumnName] = filter ? filter(value) : value; }); - // Return new object return entry; }; diff --git a/moped-editor/src/libs/GQLAbstract.js b/moped-editor/src/libs/GQLAbstract.js index df586a76cb..cedcc8f249 100644 --- a/moped-editor/src/libs/GQLAbstract.js +++ b/moped-editor/src/libs/GQLAbstract.js @@ -8,7 +8,6 @@ class GQLAbstract { * @param {Object} The initial configuration of the abstract */ constructor(initConfig) { - console.log("constructor") this.config = initConfig; this.configInit = JSON.parse(JSON.stringify(initConfig)); this.config.filterStack = { @@ -139,7 +138,6 @@ class GQLAbstract { * Resets the value of where and or to empty */ cleanWhere() { - console.log("clean where") this.config.where = { ...this.configInit.where }; this.config.or = null; this.config.and = null; @@ -228,7 +226,6 @@ class GQLAbstract { * @param {string} syntax - either 'asc' or 'desc' */ setOrder(key, syntax) { - console.log("set order") this.config.order_by = {}; this.config.order_by[key] = syntax; } @@ -251,15 +248,6 @@ class GQLAbstract { return this.config.columns[columnName].hidden || false; } - /** - * Returns true if a column is defined as searchable in the config, assumes false if not found. - * @param {string} columnName - The name of the column in the config - * @returns {boolean} - */ - isSearchable(columnName) { - return this.config.columns[columnName].searchable || false; - } - /** * Returns true if a column is defined as primary key in the config, assumes false if not found. * @param {string} columnName - The name of the column in the config @@ -287,15 +275,6 @@ class GQLAbstract { return !!this.config.columns[columnName].filter; } - /** - * Returns the default value when value is null - * @param {string} columnName - The name of the column in the config - * @returns {string} - */ - getDefault(columnName) { - return this.config.columns[columnName].default; - } - /** * Attempts to format value based on configuration specification `format` * @param {string} columnName - The column to read the configuration from @@ -341,17 +320,6 @@ class GQLAbstract { } } - /** - * Returns the label for a column as specified in the config, either a 'table' label or 'search' label. - * Returns null if the label is not found. Assumes type as 'table'. - * @param {string} columnName - The name of the column. - * @param {string} type - Type type: 'table' or 'search' - * @returns {string|null} - */ - getLabel(columnName, type = "table") { - return this.config.columns[columnName]["label_" + type] || null; - } - /** * Returns an array with key-value pairs * @param {string} section - the 'key' name of the section in the config object @@ -377,13 +345,6 @@ class GQLAbstract { return this.config.single_item || null; } - /** - * Returns the showDateRange configuration value as a boolean. - * @return {boolean} - */ - get showDateRange() { - return this.config.showDateRange || false; - } /** * Generates the filters section and injects the abstract with finished GraphQL syntax. @@ -391,7 +352,6 @@ class GQLAbstract { * @returns {string} */ generateFilters(aggregate = false) { - console.log("how often is this?", aggregate) const output = []; const where = []; const or = []; @@ -474,7 +434,6 @@ class GQLAbstract { * @returns {string} */ get query() { - console.log("get query") // First copy the abstract and work from the copy let query = this.abstractStructure; @@ -606,41 +565,11 @@ class GQLAbstract { }`; } - /** - * Sets the options for Apollo query methods - * @param {string} optionType - The method in question: useQuery, useMutation, etc. - * @param {object} optionsObject - A key value pair with Apollo config stipulations. - */ - setOption(optionType, optionsObject) { - this.config.options[optionType] = optionsObject; - } - - /** - * Returns an apollo query option by type - * @param {string} optionType - The option type name being retrieved: useQuery, useMutation, etc. - */ - getOption(optionType) { - try { - return this.config.options[optionType]; - } catch { - return {}; - } - } - - /** - * Returns a key-value object with options for the Apollo useQuery method - * @returns {object} - The options object - */ - get useQueryOptions() { - return this.getOption("useQuery") || {}; - } - /** * Returns a GQL object based on the current state of the configuration. * @returns {Object} gql object */ get gql() { - console.log(this.query) return gql` ${this.query} `; diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js index 77edc58c80..d3fae34082 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js @@ -24,7 +24,6 @@ export const ProjectsListViewQueryConf = { single_item: "/moped/projects", new_item: "/moped/projects/new", new_item_label: "New Project", - showDateRange: false, showSearchBar: true, showFilters: false, showExport: true, diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index 2fba844103..e7da92608b 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -277,7 +277,6 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { ); // Data Management - // console.log(query.config.options.useQuery) const { data, loading, error } = useQuery( query.gql, query.config.options.useQuery From e750ffe02064c7dd8f6bec54d76e7fc12094e9b6 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Mon, 11 Sep 2023 15:44:53 -0500 Subject: [PATCH 04/17] deleted grid table and its parts --- .../src/components/GridTable/GridTable.js | 517 ------------------ .../GridTable/GridTableListHeader.js | 105 ---- moped-editor/src/libs/GQLAbstract.js | 99 +--- .../ProjectsListViewQueryConf.js | 12 - .../projectsListView/ProjectsListViewTable.js | 8 +- 5 files changed, 8 insertions(+), 733 deletions(-) delete mode 100644 moped-editor/src/components/GridTable/GridTable.js delete mode 100644 moped-editor/src/components/GridTable/GridTableListHeader.js diff --git a/moped-editor/src/components/GridTable/GridTable.js b/moped-editor/src/components/GridTable/GridTable.js deleted file mode 100644 index d8825ea8b7..0000000000 --- a/moped-editor/src/components/GridTable/GridTable.js +++ /dev/null @@ -1,517 +0,0 @@ -import React, { useState } from "react"; -import { NavLink as RouterLink, useLocation } from "react-router-dom"; - -/** - * Material UI - */ -import { - Box, - Card, - CircularProgress, - Container, - Icon, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableRow, - Typography, -} from "@mui/material"; - -import makeStyles from '@mui/styles/makeStyles'; - -// Abstract & GridTable -import { useQuery } from "@apollo/client"; -import GridTableToolbar from "./GridTableToolbar"; -import GridTableListHeader from "./GridTableListHeader"; -import GridTablePagination from "./GridTablePagination"; -import GridTableSearch from "./GridTableSearch"; -import ApolloErrorHandler from "../ApolloErrorHandler"; -import { getSearchValue } from "../../utils/gridTableHelpers"; - -/** - * GridTable Style - */ -const useStyles = makeStyles((theme) => ({ - root: { - width: "100%", - }, - paper: { - width: "100%", - marginBottom: theme.spacing(1), - }, - title: { - position: "relative", - top: "1.2rem", - left: "0.3rem", - "text-shadow": "1px 1px 0px white", - }, - table: { - minWidth: 750, - }, - tableCell: { - "text-transform": "capitalize", - "white-space": "pre-wrap", - }, - noResults: { - paddingTop: "25px", - paddingBottom: "16px", - }, -})); - -/** - * GridTable Component for Material UI - * @param {string} title - The title header of the component - * @param {Object} query - The GraphQL query configuration - * @param {String} searchTerm - The initial term - * @param {Object} referenceData - optional, static data used in presentation - * @param {Object} customComponents - An object containing custom components - * @return {JSX.Element} - * @constructor - */ -const GridTable = ({ - title, - query, - searchTerm, - referenceData, - customComponents, -}) => { - const classes = useStyles(); - - /** - * State Management for pagination - * @type {Object} pagination - * @property {integer} limit - The limit of records to be shown in a single page (default: query.limit) - * @property {integer} offset - The number of records to be skipped in GraphQL (default: query.limit) - * @property {integer} page - Current page being shown (0 to N) where 0 is the first page (default: 0) - * @function setPagination - Sets the state of pagination - * @default {{limit: query.limit, offset: query.offset, page: 0}} - */ - const [pagination, setPagination] = useState({ - limit: query.limit, - offset: query.offset, - page: 0, - }); - - /** - * Stores the column name and the order to order by - * @type {Object} sort - * @property {string} column - The column name in graphql to sort by - * @property {string} order - Either "asc" or "desc" or "" (default: "") - * @function setSort - Sets the state of sort - * @default {{value: "", column: ""}} - */ - const [sort, setSort] = useState({ - column: "", - order: "", - }); - - /** - * Stores the string to search for and the column to search against - * @type {Object} search - * @property {string} value - The string to be searched for - * @property {string} column - The name of the column to search against - * @function setSearch - Sets the state of search - * @default {{value: "", column: ""}} - */ - const [search, setSearch] = useState({ - value: searchTerm ?? "", - column: "", - }); - - // anchor element for advanced search popper in GridTableSearch to "attach" to - // State is handled here so we could listen for changes in a useeffect in this component - const [advancedSearchAnchor, setAdvancedSearchAnchor] = useState(null); - - // create URLSearchParams from url - const filterQuery = new URLSearchParams(useLocation().search); - - /** - * if filter exists in url, decodes base64 string and returns as object - * Used to initialize filter state - * @return Object if valid JSON otherwise false - */ - const getFilterQuery = () => { - if (Array.from(filterQuery).length > 0) { - try { - return JSON.parse(atob(filterQuery.get("filter"))); - } catch { - return false; - } - } - return false; - }; - - /** - * Stores objects storing a random id, column, operator, and value. - * @type {Object} filters - * @function setFilter - Sets the state of filters - * @default {if filter in url, use those params, otherwise {}} - */ - const [filters, setFilter] = useState(getFilterQuery() || {}); - - /** - * Query Management - */ - // Manage the ORDER BY clause of our query - if (sort.column !== "" && sort.order !== "") { - query.setOrder(sort.column, sort.order); - } - - // Set limit, offset and clear any 'Where' filters - if (query.config.showPagination) { - query.limit = pagination.limit; - query.offset = pagination.offset; - } else { - query.limit = 0; - } - - query.cleanWhere(); - - // If we have a search value in state, initiate search - // GridTableSearchBar in GridTableSearch updates search value - if (search.value && search.value !== "") { - /** - * Iterate through all column keys, if they are searchable - * add the to the Or list. - */ - Object.keys(query.config.columns) - .filter((column) => query.config.columns[column]?.searchable) - .forEach((column) => { - const { operator, quoted, envelope } = - query.config.columns[column].search; - const searchValue = getSearchValue(query, column, search.value); - const graphqlSearchValue = quoted - ? `"${envelope.replace("{VALUE}", searchValue)}"` - : searchValue; - - query.setOr(column, `${operator}: ${graphqlSearchValue}`); - }); - } - - // For each filter added to state, add a where clause in GraphQL - // Advanced Search - Object.keys(filters).forEach((filter) => { - let { envelope, field, gqlOperator, value, type, specialNullValue } = - filters[filter]; - - // If we have no operator, then there is nothing we can do. - if (field === null || gqlOperator === null) { - return; - } - - // If the operator includes "is_null", we check for empty strings - if (gqlOperator.includes("is_null")) { - gqlOperator = envelope === "true" ? "_eq" : "_neq"; - value = specialNullValue ? specialNullValue : '""'; - } else { - if (value !== null) { - // If there is an envelope, insert value in envelope. - value = envelope ? envelope.replace("{VALUE}", value) : value; - - // If it is a number or boolean, it does not need quotation marks - // Otherwise, add quotation marks for the query to identify as string - value = type in ["number", "boolean"] ? value : `"${value}"`; - } else { - // We don't have a value - return; - } - } - query.setWhere(field, `${gqlOperator}: ${value}`); - }); - - /** - * Handles the header click for sorting asc/desc. - * @param {string} columnName - The name of the column - **/ - const handleTableHeaderClick = (columnName) => { - // Before anything, let's clear all current conditions - query.clearOrderBy(); - - // If both column and order are empty... - if (sort.order === "" && sort.column === "") { - // First time sort is applied - setSort({ - order: "asc", - column: columnName, - }); - } else if (sort.column === columnName) { - // Else if the current sortColumn is the same as the new - // then invert values and repeat sort on column - setSort({ - order: sort.order === "desc" ? "asc" : "desc", - column: columnName, - }); - } else if (sort.column !== columnName) { - // Sort different column after initial sort, then reset - setSort({ - order: "desc", - column: columnName, - }); - } - }; - - /** - * Returns true if the input string is a valid alphanumeric object key - * @param {string} input - The string to be tested - * @returns {boolean} - */ - const isAlphanumeric = (input) => input.match(/^[0-9a-zA-Z\-_]+$/) !== null; - - /** - * Extracts a list of keys in a graphql expression - * @param {string} exp - The expression - * @returns {Array} - */ - const listKeys = (exp) => - exp.split(/[{} ]+/).filter((n) => isAlphanumeric(n) && n !== ""); - - /** - * Returns the value of a data structure based on the list of keys provided - * @param {object} obj - the item from the row section - * @param {Array} keys - the list of keys - * @returns {*} - */ - const responseValue = (obj, keys) => { - for (let k = 1; k < keys.length; k++) { - try { - obj = obj[keys[k]]; - } catch { - obj = null; - } - } - return obj; - }; - - /** - * Extracts the value (or summary of values) for nested field names - * @param {object} obj - The dataset current object (the table row) - * @param {string} exp - The graphql expression (from the column name) - * @returns {string} - */ - const getSummary = (obj, exp) => { - let result = []; - let map = new Map(); - const keys = listKeys(exp); - - // First we need to get to the specific section of the dataset object - // The first key is the outermost nested part of the graphql query - const section = obj[keys[0]]; - - // Bypass value extraction if column value should be "stringified" - if (query.config.columns[exp]?.stringify) { - return JSON.stringify(section); - } - - // If not an array, resolve its value - if (!Array.isArray(section)) { - // Return direct value - return responseValue(section, keys); - } - - // If it is an array, resolve each and aggregate - for (let item of section) { - let val = responseValue(item, keys); - - if (val !== null) { - map.set(val, true); - result.push(val); - } - } - // Merge all into a string - return result.join(", "); - }; - - /** - * Returns a stringified object with information to format link. - * @param {string} row - row from data - * @param {Object} column - column with link attribute - * @return {string} - */ - const buildLinkData = (row, column) => - JSON.stringify({ - singleItem: query.singleItem, - data: row[column], - link: row[query.config.columns[column].link], - state: { - filters: Object.keys(filters).length - ? btoa(JSON.stringify(filters)) - : false, - }, - }); - - /** - * Data Management - */ - const { data, loading, error } = useQuery( - query.gql, - query.config.options.useQuery - ); - - return ( - - - {/*Title*/} - - {title} - - {/*Toolbar Space*/} - - {customComponents?.toolbar?.before} - - {customComponents?.toolbar?.after} - - {/*Main Table Body*/} - {customComponents?.table?.before} - - - {loading ? ( - - ) : data ? ( - - - - - - {data[query.table].length < 1 ? ( - - - - {query.config.noResultsMessage ?? - "No results found"} - - - - ) : ( - data[query.table].map((row, rowIndex) => { - return ( - - {query.columns.map( - (column, columnIndex) => - // If column is hidden, don't render
- !query.isHidden(column) && ( - - {query.isPK(column) ? ( - // If there is custom JSX for the PK single item button, render it - (query.config.customSingleItemButton && - query.config.customSingleItemButton( - row[column] - )) || ( - - {query.config.columns[ - column - ].hasOwnProperty("icon") ? ( - - { - query.config.columns[column] - .icon.name - } - - ) : ( - row[column] - )} - - ) - ) : query.config.columns[column]?.link ? ( - query.getFormattedValue( - column, - buildLinkData(row, column) - ) - ) : isAlphanumeric(column) ? ( - <> - {query.getFormattedValue( - column, - row[column] - )} - - ) : ( - // if column is not alphanumeric - // it is formatted like a nested query - query.getFormattedValue( - column, - getSummary(row, column.trim()) - ) - )} - - ) - )} - - ); - }) - )} - -
-
- - {/*Pagination Management*/} - {query.config.showPagination && ( - - )} -
- ) : ( - {error ? error : "Could not fetch data"} - )} -
-
- {customComponents?.table?.after} -
-
- ); -}; - -export default GridTable; diff --git a/moped-editor/src/components/GridTable/GridTableListHeader.js b/moped-editor/src/components/GridTable/GridTableListHeader.js deleted file mode 100644 index 1ee5b7985c..0000000000 --- a/moped-editor/src/components/GridTable/GridTableListHeader.js +++ /dev/null @@ -1,105 +0,0 @@ -import React from "react"; - -import { TableHead, TableRow, TableCell, Icon, Grid } from "@mui/material"; -import makeStyles from '@mui/styles/makeStyles'; - -/** - * GridTableListHeader Styles - */ -const useStyles = makeStyles(theme => ({ - columnTitle: { - "font-weight": "bold", - }, - columnTitleSortable: { - paddingTop: "8px", - "font-weight": "bold", - }, - columnCell: { - "user-select": "none", - backgroundColor: theme.palette.background.paper, - }, - columnCellCursor: { - cursor: "pointer", - "user-select": "none", - backgroundColor: theme.palette.background.paper, - }, -})); - -/** - * GridTableListHeader Component - * @param {GQLAbstract} query - The GQLAbstract class passed down for reference - * @param {function} handleTableHeaderClick - A handler for table header clicks - * @param {string} sortColumn - The name of the column to sort by - * @param {string} sortOrder - The order in which the sorting is made: asc, desc - * @return {JSX.Element} - * @constructor - */ -const GridTableListHeader = ({ - query, - handleTableHeaderClick, - sortColumn, - sortOrder, -}) => { - const classes = useStyles(); - - /** - * Renders a label with sorting icons going up or down - * @param {string} col - The name of the column (label) - * @param {boolean} sortable - True if the column is sortable - * @param {boolean} ascending - True if ordering in ascending mode - * @returns {object} jsx component - */ - const renderLabel = (col, sortable = false, ascending = false) => { - return ( - - {col}  - {sortable && ( - - arrow_{ascending ? "up" : "down"}ward - - )} - - ); - }; - - return ( - - - {query.columns.map( - (column, index) => - // If column is hidden, don't render - !query.isHidden(column) && ( - handleTableHeaderClick(column) - : null - } - key={`th-${index}`} - size="small" - > - {renderLabel( - // Get a human-readable label string - query.config.columns[column].label, - // If it is sortable, render as such - query.isSortable(column), - // If sort column is defined, use sort order, or false as default - sortColumn === column ? sortOrder === "asc" : false - )} - - ) - )} - - - ); -}; - -export default GridTableListHeader; diff --git a/moped-editor/src/libs/GQLAbstract.js b/moped-editor/src/libs/GQLAbstract.js index cedcc8f249..aa6282b380 100644 --- a/moped-editor/src/libs/GQLAbstract.js +++ b/moped-editor/src/libs/GQLAbstract.js @@ -230,96 +230,6 @@ class GQLAbstract { this.config.order_by[key] = syntax; } - /** - * Returns true if a column is defined as sortable in the config, assumes false if not found. - * @param {string} columnName - The name of the column in the config - * @returns {boolean} - */ - isSortable(columnName) { - return this.config.columns[columnName].sortable || false; - } - - /** - * Returns true if a column is defined as hidden in the config, assumes false if not found. - * @param {string} columnName - The name of the column in the config - * @returns {boolean} - */ - isHidden(columnName) { - return this.config.columns[columnName].hidden || false; - } - - /** - * Returns true if a column is defined as primary key in the config, assumes false if not found. - * @param {string} columnName - The name of the column in the config - * @returns {boolean} - */ - isPK(columnName) { - return this.config.columns[columnName].primary_key || false; - } - - /** - * Returns the type of a column as defined in the config, assumes string if not found. - * @param {string} columnName - The name of the column in the config - * @returns {string} - */ - getType(columnName) { - return (this.config.columns[columnName].type || "string").toLowerCase(); - } - - /** - * Returns true if the column contains a filter - * @param {string} columnName - The name of the column in the config - * @return {boolean} - */ - hasFilter(columnName) { - return !!this.config.columns[columnName].filter; - } - - /** - * Attempts to format value based on configuration specification `format` - * @param {string} columnName - The column to read the configuration from - * @param {object} value - The actual value to be presented to the component - */ - getFormattedValue(columnName, value) { - const type = this.getType(columnName); - - if (value === null) { - return "-"; - } else { - value = String(value); - } - - if (this.hasFilter(columnName)) { - return this.config.columns[columnName].filter(value); - } - - switch (type) { - case "string": { - if (typeof value === "object") return JSON.stringify(value); - else return `${value}`; - } - case "date_iso": { - let dateValue = ""; - try { - dateValue = new Date(Date.parse(value)).toLocaleString(); - } catch { - dateValue = "n/a"; - } - return `${dateValue}`; - } - case "currency": { - return `$${value.toLocaleString()}`; - } - case "boolean": { - return value ? "True" : "False"; - } - // Integers, Decimals - default: { - return `${value}`; - } - } - } - /** * Returns an array with key-value pairs * @param {string} section - the 'key' name of the section in the config object @@ -337,14 +247,6 @@ class GQLAbstract { return this.getEntries("columns").map((k) => k[0]); } - /** - * Returns the url path for a single item, or null if ot does not exist. - * @returns {string|null} - */ - get singleItem() { - return this.config.single_item || null; - } - /** * Generates the filters section and injects the abstract with finished GraphQL syntax. @@ -465,6 +367,7 @@ class GQLAbstract { * @returns {Object} gql Object */ queryCSV(string) { + console.log("querycsv") // First copy the abstract and work from the copy and clear offset to request all records let query = this.abstractStructure; this.offset = 0; diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js index d3fae34082..46272b4e26 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js @@ -74,18 +74,6 @@ export const ProjectsListViewQueryConf = { }, width: "*", type: "String", - filter: (values) => { - const jsonValues = JSON.parse(values); - return ( - - {jsonValues.data} - - ); - }, }, project_description: { hidden: true, diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index e7da92608b..fdb2a06080 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -102,7 +102,7 @@ const handleColumnChange = ({ field }, hidden) => { */ const ProjectsListViewTable = ({ query, searchTerm }) => { const classes = useStyles(); - console.log(query); + // console.log(query); /** * @type {Object} pagination @@ -189,6 +189,10 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { JSON.parse(localStorage.getItem("mopedColumnConfig")) ?? DEFAULT_HIDDEN_COLS ); + useEffect(()=> { + console.log("the query has changed") + }, [query]) + /** * Query Management */ @@ -592,6 +596,8 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { } }, [data, advancedSearchAnchor]); + // console.log(query.query) + return ( From 5177b99f51cc9ed9f2c74a1015ebb533f0167555 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Mon, 11 Sep 2023 16:33:54 -0500 Subject: [PATCH 05/17] remove more stuff that isnt used --- moped-editor/src/libs/GQLAbstract.js | 13 ------------- .../projectsListView/ProjectsListViewQueryConf.js | 2 -- 2 files changed, 15 deletions(-) diff --git a/moped-editor/src/libs/GQLAbstract.js b/moped-editor/src/libs/GQLAbstract.js index aa6282b380..31c701c559 100644 --- a/moped-editor/src/libs/GQLAbstract.js +++ b/moped-editor/src/libs/GQLAbstract.js @@ -122,18 +122,6 @@ class GQLAbstract { return this.config.offset; } - /** - * Returns an array of searchable columns - * @returns {Array} - */ - get searchableFields() { - const columns = []; - for (const [key, value] of this.getEntries("columns")) { - if (value.searchable) columns.push(key); - } - return columns; - } - /** * Resets the value of where and or to empty */ @@ -367,7 +355,6 @@ class GQLAbstract { * @returns {Object} gql Object */ queryCSV(string) { - console.log("querycsv") // First copy the abstract and work from the copy and clear offset to request all records let query = this.abstractStructure; this.offset = 0; diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js index 46272b4e26..2cd52f4eaf 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewQueryConf.js @@ -2,10 +2,8 @@ import React from "react"; import { ProjectsListViewFiltersConf } from "./ProjectsListViewFiltersConf"; import { ProjectsListViewExportConf } from "./ProjectsListViewExportConf"; import ExternalLink from "../../../components/ExternalLink"; -import { NavLink as RouterLink } from "react-router-dom"; import { filterProjectTeamMembers } from "./helpers.js"; import { formatTimeStampTZType } from "src/utils/dateAndTime"; -import theme from "src/theme/index"; /** * The Query configuration (now also including filters) From b89c27244ccd00aa26d7abf0f558b5ed0a875627 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Wed, 13 Sep 2023 14:07:21 -0500 Subject: [PATCH 06/17] the toolbar does nothing --- .../components/GridTable/GridTableToolbar.js | 27 ------------------- .../projectsListView/ProjectsListViewTable.js | 4 --- 2 files changed, 31 deletions(-) delete mode 100644 moped-editor/src/components/GridTable/GridTableToolbar.js diff --git a/moped-editor/src/components/GridTable/GridTableToolbar.js b/moped-editor/src/components/GridTable/GridTableToolbar.js deleted file mode 100644 index 63223f0915..0000000000 --- a/moped-editor/src/components/GridTable/GridTableToolbar.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from "react"; -import clsx from "clsx"; - -import makeStyles from '@mui/styles/makeStyles'; - - -const useStyles = makeStyles(theme => ({ - root: {}, - importButton: { - marginRight: theme.spacing(1), - }, - exportButton: { - marginRight: theme.spacing(1), - }, -})); - -const GridTableToolbar = ({ children, change, className, ...rest }) => { - const classes = useStyles(); - - return ( -
- {children} -
- ); -}; - -export default GridTableToolbar; diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index fdb2a06080..a30976fe51 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -7,7 +7,6 @@ import makeStyles from "@mui/styles/makeStyles"; import typography from "../../../theme/typography"; import { useQuery } from "@apollo/client"; -import GridTableToolbar from "../../../components/GridTable/GridTableToolbar"; import GridTableSearch from "../../../components/GridTable/GridTableSearch"; import GridTablePagination from "../../../components/GridTable/GridTablePagination"; import ApolloErrorHandler from "../../../components/ApolloErrorHandler"; @@ -601,8 +600,6 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { return ( - {/*Toolbar Space*/} - { advancedSearchAnchor={advancedSearchAnchor} setAdvancedSearchAnchor={setAdvancedSearchAnchor} /> - {/*Main Table Body*/} From 4ec5048848fef88fd90c1b1866e08633c8bb3a36 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Wed, 13 Sep 2023 14:12:16 -0500 Subject: [PATCH 07/17] we dont need the grid table new item --- .../components/GridTable/GridTableNewItem.js | 35 ------------------- .../components/GridTable/GridTableSearch.js | 2 -- 2 files changed, 37 deletions(-) delete mode 100644 moped-editor/src/components/GridTable/GridTableNewItem.js diff --git a/moped-editor/src/components/GridTable/GridTableNewItem.js b/moped-editor/src/components/GridTable/GridTableNewItem.js deleted file mode 100644 index 81880e42d4..0000000000 --- a/moped-editor/src/components/GridTable/GridTableNewItem.js +++ /dev/null @@ -1,35 +0,0 @@ -import React from "react"; -import PropTypes from "prop-types"; - -import { Box, Button, Icon } from "@mui/material"; -import { NavLink as RouterLink } from "react-router-dom"; - -/** - * Based on GQLAbstract configuration, renders add new Item button - * @param {GQLAbstract} query - The GQLAbstract query object that provides the configuration - * @return {JSX.Element} - * @constructor - */ -const GridTableNewItem = ({ query }) => { - return ( - - {query.config.customNewItemButton || ( - - )} - - ); -}; - -GridTableNewItem.propTypes = { - className: PropTypes.string, -}; - -export default GridTableNewItem; diff --git a/moped-editor/src/components/GridTable/GridTableSearch.js b/moped-editor/src/components/GridTable/GridTableSearch.js index 5fe9363e41..9f684f781c 100644 --- a/moped-editor/src/components/GridTable/GridTableSearch.js +++ b/moped-editor/src/components/GridTable/GridTableSearch.js @@ -19,7 +19,6 @@ import { import SaveAltIcon from "@mui/icons-material/SaveAlt"; import GridTableFilters from "./GridTableFilters"; import GridTableSearchBar from "./GridTableSearchBar"; -import GridTableNewItem from "./GridTableNewItem"; import makeStyles from '@mui/styles/makeStyles'; import { useLazyQuery } from "@apollo/client"; import { format } from "date-fns"; @@ -294,7 +293,6 @@ const GridTableSearch = ({ return (
- {query.config.showNewItemButton && } {children} From 2cbc89b9421900238ae88cefd737f9f76a22a2b8 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Wed, 13 Sep 2023 15:15:55 -0500 Subject: [PATCH 08/17] move the queryFilter out --- .../projectsListView/ProjectsListViewTable.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index a30976fe51..e831995667 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useMemo } from "react"; import { NavLink as RouterLink, useLocation } from "react-router-dom"; import { Box, Card, CircularProgress, Container, Paper } from "@mui/material"; @@ -92,6 +92,15 @@ const handleColumnChange = ({ field }, hidden) => { localStorage.setItem("mopedColumnConfig", JSON.stringify(storedConfig)); }; + +// hook which keeps available subphase options in sync +const useFilterQuery = ({ locationSearch }) => + useMemo(() => { + return new URLSearchParams(locationSearch) + }, [locationSearch]); + + + /** * GridTable Search Capability plus Material Table * @param {Object} query - The GraphQL query configuration @@ -158,7 +167,7 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { const [advancedSearchAnchor, setAdvancedSearchAnchor] = useState(null); // create URLSearchParams from url - const filterQuery = new URLSearchParams(useLocation().search); + const filterQuery = useFilterQuery(useLocation().search) /** * if filter exists in url, decodes base64 string and returns as object @@ -188,10 +197,6 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { JSON.parse(localStorage.getItem("mopedColumnConfig")) ?? DEFAULT_HIDDEN_COLS ); - useEffect(()=> { - console.log("the query has changed") - }, [query]) - /** * Query Management */ @@ -278,7 +283,6 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { const buildStatusBadge = ({ phaseName, phaseKey }) => ( ); - // Data Management const { data, loading, error } = useQuery( query.gql, From e7d45810a94a91ef07a35e77f80396545f7a826d Mon Sep 17 00:00:00 2001 From: chiaberry Date: Wed, 13 Sep 2023 15:17:22 -0500 Subject: [PATCH 09/17] remove wrong comment --- .../views/projects/projectsListView/ProjectsListViewTable.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index e831995667..dcd873e21a 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -93,14 +93,12 @@ const handleColumnChange = ({ field }, hidden) => { }; -// hook which keeps available subphase options in sync const useFilterQuery = ({ locationSearch }) => useMemo(() => { return new URLSearchParams(locationSearch) }, [locationSearch]); - /** * GridTable Search Capability plus Material Table * @param {Object} query - The GraphQL query configuration From 78e0de5413a34731d9409a906fddb88c51642ada Mon Sep 17 00:00:00 2001 From: chiaberry Date: Wed, 13 Sep 2023 15:21:28 -0500 Subject: [PATCH 10/17] more cleanup --- .../projects/projectsListView/ProjectsListViewTable.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index dcd873e21a..93d835e45c 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -108,7 +108,6 @@ const useFilterQuery = ({ locationSearch }) => */ const ProjectsListViewTable = ({ query, searchTerm }) => { const classes = useStyles(); - // console.log(query); /** * @type {Object} pagination @@ -213,7 +212,8 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { } }, [pagination.limit, pagination.offset, query]); - // Resets the value of "where" "and" "or" to empty -- make this only happen when needed + // Resets the value of "where" "and" "or" to empty + // todo: -- make this only happen when needed query.cleanWhere(); // If we have a search value in state, initiate search @@ -597,8 +597,6 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { } }, [data, advancedSearchAnchor]); - // console.log(query.query) - return ( From df382faa7c075dc5b962d610275e6dde7cb7e536 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Fri, 15 Sep 2023 12:06:42 -0500 Subject: [PATCH 11/17] add useEffect to search value filter query --- .../components/GridTable/GridTableSearch.js | 2 - .../projectsListView/ProjectsListViewTable.js | 113 +++++++++--------- 2 files changed, 56 insertions(+), 59 deletions(-) diff --git a/moped-editor/src/components/GridTable/GridTableSearch.js b/moped-editor/src/components/GridTable/GridTableSearch.js index 9f684f781c..1f8ac06810 100644 --- a/moped-editor/src/components/GridTable/GridTableSearch.js +++ b/moped-editor/src/components/GridTable/GridTableSearch.js @@ -83,7 +83,6 @@ const GridTableSearch = ({ query, searchState, filterState, - children, filterQuery, parentData = null, advancedSearchAnchor, @@ -293,7 +292,6 @@ const GridTableSearch = ({ return (
- {children} diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index 93d835e45c..df8f3b28c4 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -92,12 +92,27 @@ const handleColumnChange = ({ field }, hidden) => { localStorage.setItem("mopedColumnConfig", JSON.stringify(storedConfig)); }; - const useFilterQuery = ({ locationSearch }) => useMemo(() => { - return new URLSearchParams(locationSearch) + return new URLSearchParams(locationSearch); }, [locationSearch]); +/** + * if filter exists in url, decodes base64 string and returns as object + * Used to initialize filter state + * @return Object + */ +const useMakeFilterState = (filterQuery) => + useMemo(() => { + if (Array.from(filterQuery).length > 0) { + try { + return JSON.parse(atob(filterQuery.get("filter"))); + } catch { + return {}; + } + } + return {}; + }, [filterQuery]); /** * GridTable Search Capability plus Material Table @@ -164,23 +179,8 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { const [advancedSearchAnchor, setAdvancedSearchAnchor] = useState(null); // create URLSearchParams from url - const filterQuery = useFilterQuery(useLocation().search) - - /** - * if filter exists in url, decodes base64 string and returns as object - * Used to initialize filter state - * @return Object if valid JSON otherwise false - */ - const getFilterQuery = () => { - if (Array.from(filterQuery).length > 0) { - try { - return JSON.parse(atob(filterQuery.get("filter"))); - } catch { - return false; - } - } - return false; - }; + const filterQuery = useFilterQuery(useLocation().search); + const initialFilterState = useMakeFilterState(filterQuery); /** * Stores objects storing a random id, column, operator, and value. @@ -188,22 +188,19 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { * @function setFilter - Sets the state of filters * @default {if filter in url, use those params, otherwise {}} */ - const [filters, setFilter] = useState(getFilterQuery() || {}); + const [filters, setFilter] = useState(initialFilterState); const [hiddenColumns, setHiddenColumns] = useState( JSON.parse(localStorage.getItem("mopedColumnConfig")) ?? DEFAULT_HIDDEN_COLS ); - /** - * Query Management - */ // Manage the ORDER BY clause of our query useEffect(() => { query.setOrder(sort.column, sort.order); }, [sort.column, sort.order, query]); + // Set limit, offset based on pagination state useEffect(() => { - // Set limit, offset based on pagination state if (query.config.showPagination) { query.limit = pagination.limit; query.offset = pagination.offset; @@ -218,24 +215,26 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { // If we have a search value in state, initiate search // GridTableSearchBar in GridTableSearch updates search value - if (search.value && search.value !== "") { - /** - * Iterate through all column keys, if they are searchable - * add the to the Or list. - */ - Object.keys(query.config.columns) - .filter((column) => query.config.columns[column]?.searchable) - .forEach((column) => { - const { operator, quoted, envelope } = - query.config.columns[column].search; - const searchValue = getSearchValue(query, column, search.value); - const graphqlSearchValue = quoted - ? `"${envelope.replace("{VALUE}", searchValue)}"` - : searchValue; - - query.setOr(column, `${operator}: ${graphqlSearchValue}`); - }); - } + useEffect(() => { + if (search.value && search.value !== "") { + /** + * Iterate through all column keys, if they are searchable + * add the to the Or list. + */ + Object.keys(query.config.columns) + .filter((column) => query.config.columns[column]?.searchable) + .forEach((column) => { + const { operator, quoted, envelope } = + query.config.columns[column].search; + const searchValue = getSearchValue(query, column, search.value); + const graphqlSearchValue = quoted + ? `"${envelope.replace("{VALUE}", searchValue)}"` + : searchValue; + + query.setOr(column, `${operator}: ${graphqlSearchValue}`); + }); + } + }, [search.value, query]); // For each filter added to state, add a where clause in GraphQL // Advanced Search @@ -600,21 +599,21 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { return ( - + {/*Main Table Body*/} From d03634c03621e84d66bd8548b47526706aaa7e2d Mon Sep 17 00:00:00 2001 From: chiaberry Date: Fri, 15 Sep 2023 13:50:02 -0500 Subject: [PATCH 12/17] add another useeffect --- .../projectsListView/ProjectsListViewTable.js | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index df8f3b28c4..9f2ff5d7e7 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -92,7 +92,7 @@ const handleColumnChange = ({ field }, hidden) => { localStorage.setItem("mopedColumnConfig", JSON.stringify(storedConfig)); }; -const useFilterQuery = ({ locationSearch }) => +const useFilterQuery = (locationSearch) => useMemo(() => { return new URLSearchParams(locationSearch); }, [locationSearch]); @@ -238,38 +238,40 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { // For each filter added to state, add a where clause in GraphQL // Advanced Search - Object.keys(filters).forEach((filter) => { - let { envelope, field, gqlOperator, value, type, specialNullValue } = - filters[filter]; - - // If we have no operator, then there is nothing we can do. - if (field === null || gqlOperator === null) { - return; - } + useEffect(() => { + Object.keys(filters).forEach((filter) => { + let { envelope, field, gqlOperator, value, type, specialNullValue } = + filters[filter]; - if (gqlOperator.includes("is_null")) { - // Some fields when empty are not null but rather an empty string or "None" - if (specialNullValue) { - gqlOperator = envelope === "true" ? "_eq" : "_neq"; - value = specialNullValue; - } else { - value = envelope; + // If we have no operator, then there is nothing we can do. + if (field === null || gqlOperator === null) { + return; } - } else { - if (value !== null) { - // If there is an envelope, insert value in envelope. - value = envelope ? envelope.replace("{VALUE}", value) : value; - // If it is a number or boolean, it does not need quotation marks - // Otherwise, add quotation marks for the query to identify as string - value = type in ["number", "boolean"] ? value : `"${value}"`; + if (gqlOperator.includes("is_null")) { + // Some fields when empty are not null but rather an empty string or "None" + if (specialNullValue) { + gqlOperator = envelope === "true" ? "_eq" : "_neq"; + value = specialNullValue; + } else { + value = envelope; + } } else { - // We don't have a value - return; + if (value !== null) { + // If there is an envelope, insert value in envelope. + value = envelope ? envelope.replace("{VALUE}", value) : value; + + // If it is a number or boolean, it does not need quotation marks + // Otherwise, add quotation marks for the query to identify as string + value = type in ["number", "boolean"] ? value : `"${value}"`; + } else { + // We don't have a value + return; + } } - } - query.setWhere(field, `${gqlOperator}: ${value}`); - }); + query.setWhere(field, `${gqlOperator}: ${value}`); + }); + }, [filters, query]); /** * Returns a ProjectStatusBadge component based on the status and phase of project From f7afd71f1d27006f82b569632f98eed1238f5cd0 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Fri, 15 Sep 2023 14:39:05 -0500 Subject: [PATCH 13/17] use effect didnt work --- .../projectsListView/ProjectsListViewTable.js | 38 +++++++++---------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index 9f2ff5d7e7..65d0650115 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -215,26 +215,24 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { // If we have a search value in state, initiate search // GridTableSearchBar in GridTableSearch updates search value - useEffect(() => { - if (search.value && search.value !== "") { - /** - * Iterate through all column keys, if they are searchable - * add the to the Or list. - */ - Object.keys(query.config.columns) - .filter((column) => query.config.columns[column]?.searchable) - .forEach((column) => { - const { operator, quoted, envelope } = - query.config.columns[column].search; - const searchValue = getSearchValue(query, column, search.value); - const graphqlSearchValue = quoted - ? `"${envelope.replace("{VALUE}", searchValue)}"` - : searchValue; - - query.setOr(column, `${operator}: ${graphqlSearchValue}`); - }); - } - }, [search.value, query]); + if (search.value && search.value !== "") { + /** + * Iterate through all column keys, if they are searchable + * add the to the Or list. + */ + Object.keys(query.config.columns) + .filter((column) => query.config.columns[column]?.searchable) + .forEach((column) => { + const { operator, quoted, envelope } = + query.config.columns[column].search; + const searchValue = getSearchValue(query, column, search.value); + const graphqlSearchValue = quoted + ? `"${envelope.replace("{VALUE}", searchValue)}"` + : searchValue; + + query.setOr(column, `${operator}: ${graphqlSearchValue}`); + }); + } // For each filter added to state, add a where clause in GraphQL // Advanced Search From 52f572490b161fc82a6dd58caa347f949963d4bf Mon Sep 17 00:00:00 2001 From: chiaberry Date: Mon, 18 Sep 2023 09:41:04 -0500 Subject: [PATCH 14/17] doesnt work without it --- .../views/projects/projectsListView/ProjectsListViewTable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index 65d0650115..5e62f147a0 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -236,7 +236,7 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { // For each filter added to state, add a where clause in GraphQL // Advanced Search - useEffect(() => { + //useEffect(() => { Object.keys(filters).forEach((filter) => { let { envelope, field, gqlOperator, value, type, specialNullValue } = filters[filter]; @@ -269,7 +269,7 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { } query.setWhere(field, `${gqlOperator}: ${value}`); }); - }, [filters, query]); + //}, [filters, query]); /** * Returns a ProjectStatusBadge component based on the status and phase of project From cab95eb5140659ac5ef174246e453ded728db001 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Mon, 18 Sep 2023 10:31:32 -0500 Subject: [PATCH 15/17] removing the use effects --- .../projectsListView/ProjectsListViewTable.js | 69 +++++++++---------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index 5e62f147a0..ac1030d7bd 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -200,17 +200,14 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { }, [sort.column, sort.order, query]); // Set limit, offset based on pagination state - useEffect(() => { - if (query.config.showPagination) { - query.limit = pagination.limit; - query.offset = pagination.offset; - } else { - query.limit = 0; - } - }, [pagination.limit, pagination.offset, query]); + if (query.config.showPagination) { + query.limit = pagination.limit; + query.offset = pagination.offset; + } else { + query.limit = 0; + } // Resets the value of "where" "and" "or" to empty - // todo: -- make this only happen when needed query.cleanWhere(); // If we have a search value in state, initiate search @@ -237,38 +234,38 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { // For each filter added to state, add a where clause in GraphQL // Advanced Search //useEffect(() => { - Object.keys(filters).forEach((filter) => { - let { envelope, field, gqlOperator, value, type, specialNullValue } = - filters[filter]; + Object.keys(filters).forEach((filter) => { + let { envelope, field, gqlOperator, value, type, specialNullValue } = + filters[filter]; - // If we have no operator, then there is nothing we can do. - if (field === null || gqlOperator === null) { - return; - } + // If we have no operator, then there is nothing we can do. + if (field === null || gqlOperator === null) { + return; + } - if (gqlOperator.includes("is_null")) { - // Some fields when empty are not null but rather an empty string or "None" - if (specialNullValue) { - gqlOperator = envelope === "true" ? "_eq" : "_neq"; - value = specialNullValue; - } else { - value = envelope; - } + if (gqlOperator.includes("is_null")) { + // Some fields when empty are not null but rather an empty string or "None" + if (specialNullValue) { + gqlOperator = envelope === "true" ? "_eq" : "_neq"; + value = specialNullValue; } else { - if (value !== null) { - // If there is an envelope, insert value in envelope. - value = envelope ? envelope.replace("{VALUE}", value) : value; + value = envelope; + } + } else { + if (value !== null) { + // If there is an envelope, insert value in envelope. + value = envelope ? envelope.replace("{VALUE}", value) : value; - // If it is a number or boolean, it does not need quotation marks - // Otherwise, add quotation marks for the query to identify as string - value = type in ["number", "boolean"] ? value : `"${value}"`; - } else { - // We don't have a value - return; - } + // If it is a number or boolean, it does not need quotation marks + // Otherwise, add quotation marks for the query to identify as string + value = type in ["number", "boolean"] ? value : `"${value}"`; + } else { + // We don't have a value + return; } - query.setWhere(field, `${gqlOperator}: ${value}`); - }); + } + query.setWhere(field, `${gqlOperator}: ${value}`); + }); //}, [filters, query]); /** From 8a2f2c2ae7176d380aaf7a48ff7c737ceae685cf Mon Sep 17 00:00:00 2001 From: chiaberry Date: Thu, 21 Sep 2023 09:32:57 -0500 Subject: [PATCH 16/17] add a note --- .../views/projects/projectsListView/ProjectsListViewTable.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index ac1030d7bd..bdc6667f3c 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -233,7 +233,9 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { // For each filter added to state, add a where clause in GraphQL // Advanced Search - //useEffect(() => { + // I tried putting useEffect around this to only update the where clause when the filters were updated + // however the component does not refresh to display new data + // useEffect(() => { Object.keys(filters).forEach((filter) => { let { envelope, field, gqlOperator, value, type, specialNullValue } = filters[filter]; From bb9d30d2abc7b721f776114440aa1aeadf38d323 Mon Sep 17 00:00:00 2001 From: chiaberry Date: Thu, 28 Sep 2023 11:30:09 -0500 Subject: [PATCH 17/17] remove my note --- .../views/projects/projectsListView/ProjectsListViewTable.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js index 0a822ded44..d79b1f656d 100644 --- a/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js +++ b/moped-editor/src/views/projects/projectsListView/ProjectsListViewTable.js @@ -237,9 +237,6 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { // For each filter added to state, add a where clause in GraphQL // Advanced Search - // I tried putting useEffect around this to only update the where clause when the filters were updated - // however the component does not refresh to display new data - // useEffect(() => { Object.keys(filters).forEach((filter) => { let { envelope, field, gqlOperator, value, type, specialNullValue } = filters[filter]; @@ -272,7 +269,6 @@ const ProjectsListViewTable = ({ query, searchTerm }) => { } query.setWhere(field, `${gqlOperator}: ${value}`); }); - //}, [filters, query]); /** * Returns a ProjectStatusBadge component based on the status and phase of project