Update odlux table filters 93/115993/1
authorAijana Schumann <aijana.schumann@highstreet-technologies.com>
Wed, 2 Dec 2020 10:29:32 +0000 (11:29 +0100)
committerAijana Schumann <aijana.schumann@highstreet-technologies.com>
Wed, 2 Dec 2020 10:29:32 +0000 (11:29 +0100)
Update string and number filter and add date filter

Issue-ID: CCSDK-2891
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Change-Id: If7af4adbbb0159cbd489627404d94b17e0d3c1c0

sdnr/wt/odlux/framework/src/components/material-table/columnModel.ts
sdnr/wt/odlux/framework/src/components/material-table/index.tsx

index c051420..8124e45 100644 (file)
@@ -1,20 +1,20 @@
-/**
- * ============LICENSE_START========================================================================
- * ONAP : ccsdk feature sdnr wt odlux
- * =================================================================================================
- * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
- * =================================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
- * ============LICENSE_END==========================================================================
- */
+/**\r
+ * ============LICENSE_START========================================================================\r
+ * ONAP : ccsdk feature sdnr wt odlux\r
+ * =================================================================================================\r
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.\r
+ * =================================================================================================\r
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
+ * in compliance with the License. You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software distributed under the License\r
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
+ * or implied. See the License for the specific language governing permissions and limitations under\r
+ * the License.\r
+ * ============LICENSE_END==========================================================================\r
+ */\r
 \r
 import * as React from 'react';\r
 \r
@@ -22,6 +22,7 @@ export enum ColumnType {
   text,\r
   numeric,\r
   boolean,\r
+  date,\r
   custom\r
 }\r
 \r
@@ -34,7 +35,7 @@ type CustomControl<TData> = {
 export type ColumnModel<TData> = {\r
   title?: string;\r
   disablePadding?: boolean;\r
-  width?: string | number;\r
+  width?: string | number ;\r
   className?: string;\r
   style?: React.CSSProperties;\r
   align?: 'inherit' | 'left' | 'center' | 'right' | 'justify';\r
@@ -50,5 +51,5 @@ export type ColumnModel<TData> = {
   labels?: { "true": string, "false": string };\r
 } | {\r
     property: keyof TData;\r
-    type?: ColumnType.numeric | ColumnType.text;\r
+    type?: ColumnType.numeric | ColumnType.text | ColumnType.date;\r
 });
\ No newline at end of file
index f6d0b0d..7d4633b 100644 (file)
@@ -47,6 +47,20 @@ type resultType<TData = dataType> = { page: number, total: number, rows: TData[]
 
 export type DataCallback<TData = dataType> = (page?: number, rowsPerPage?: number, orderBy?: string | null, order?: 'asc' | 'desc' | null, filter?: { [property: string]: string }) => resultType<TData> | Promise<resultType<TData>>;
 
+function regExpEscape(s: string) {
+  return s.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&');
+};
+
+function wildcardCheck(input: string, pattern: string) {
+   if (!pattern) return true; 
+   const regex = new RegExp(
+     (!pattern.startsWith('*') ? '^' : '') + 
+     pattern.split(/\*+/).map(p => p.split(/\?+/).map(regExpEscape).join('.')).join('.*') + 
+     (!pattern.endsWith('*') ? '$' : '')
+   );
+   return input.match(regex) !== null && input.match(regex)!.length >= 1;
+};
+
 function desc(a: dataType, b: dataType, orderBy: string) {
   if ((b[orderBy] || "") < (a[orderBy] || "")) {
     return -1;
@@ -324,64 +338,94 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
 
   private static updateRows(props: MaterialTableComponentPropsWithRows, state: MaterialTableComponentState): { rows: {}[], total: number, page: number } {
 
+    let data = [...props.rows as dataType[] || []];
+    const columns = props.columns;
+
     const { page, rowsPerPage, order, orderBy, filter } = state;
 
     try {
-      let data: dataType[] = props.rows || [];
-      let filtered = false;
       if (state.showFilter) {
         Object.keys(filter).forEach(prop => {
-          const exp = filter[prop];
-          filtered = filtered || exp !== undefined;
-          data = exp !== undefined ? data.filter((val) => {
-            const value = val[prop];
-
-            if (value) {
-
-              if (typeof exp === 'boolean') {
-                return value == exp;
-
-              } else if (typeof exp === 'string') {
-
-                const valueAsString = value.toString();
-                if (exp.length === 0) return value;
-
-                const regex = new RegExp("\\*", "g");
-                const regex2 = new RegExp("\\?", "g");
-
-                const countStar = (exp.match(regex) || []).length;
-                const countQuestionmarks = (exp.match(regex2) || []).length;
-
-                if (countStar > 0 || countQuestionmarks > 0) {
-                  let editableExpression = exp;
-
-                  if (!exp.startsWith('*')) {
-                    editableExpression = '^' + exp;
+          const column = columns.find(c => c.property === prop);
+          const filterExpression = filter[prop];
+
+          if (!column) throw new Error("Filter for not existing column found.");
+
+          if (filterExpression != null) {
+            data = data.filter((val) => {
+              const dataValue = val[prop];
+
+              if (dataValue != null) {
+
+                if (column.type === ColumnType.boolean) {
+
+                  const boolDataValue = JSON.parse(String(dataValue).toLowerCase());
+                  const boolFilterExpression = JSON.parse(String(filterExpression).toLowerCase());
+                  return boolDataValue == boolFilterExpression;
+
+                } else if (column.type === ColumnType.text) {
+
+                  const valueAsString = String(dataValue);
+                  const filterExpressionAsString = String(filterExpression).trim();
+                  if (filterExpressionAsString.length === 0) return true;
+                  return wildcardCheck(valueAsString, filterExpressionAsString);
+
+                } else if (column.type === ColumnType.numeric){
+                  
+                  const valueAsNumber = Number(dataValue);
+                  const filterExpressionAsString = String(filterExpression).trim();
+                  if (filterExpressionAsString.length === 0 || isNaN(valueAsNumber)) return true;
+                  
+                  if (filterExpressionAsString.startsWith('>=')) {
+                    return valueAsNumber >= Number(filterExpressionAsString.substr(2).trim());
+                  } else if (filterExpressionAsString.startsWith('<=')) {
+                    return valueAsNumber <= Number(filterExpressionAsString.substr(2).trim());
+                  } else if (filterExpressionAsString.startsWith('>')) {
+                    return valueAsNumber > Number(filterExpressionAsString.substr(1).trim());
+                  } else if (filterExpressionAsString.startsWith('<')) {
+                    return valueAsNumber < Number(filterExpressionAsString.substr(1).trim());
                   }
-
-                  if (!exp.endsWith('*')) {
-                    editableExpression = editableExpression + '$';
+                } else if (column.type === ColumnType.date){
+                   const valueAsString = String(dataValue);
+
+                   const convertToDate = (valueAsString: string) => {
+                    // time value needs to be padded   
+                    const hasTimeValue = /T\d{2,2}/.test(valueAsString);
+                    const indexCollon =  valueAsString.indexOf(':');
+                        if (hasTimeValue && (indexCollon === -1 || indexCollon >= valueAsString.length-2)) {
+                            valueAsString = indexCollon === -1 
+                            ? valueAsString + ":00"
+                            : indexCollon === valueAsString.length-1
+                                ? valueAsString + "00"
+                                : valueAsString += "0"
+                        }
+                     return new Date(Date.parse(valueAsString));   
+                   };
+                   
+                   // @ts-ignore
+                   const valueAsDate = new Date(Date.parse(dataValue));
+                   const filterExpressionAsString = String(filterExpression).trim();             
+
+                   if (filterExpressionAsString.startsWith('>=')) {
+                    return valueAsDate >= convertToDate(filterExpressionAsString.substr(2).trim());
+                  } else if (filterExpressionAsString.startsWith('<=')) {
+                    return valueAsDate <= convertToDate(filterExpressionAsString.substr(2).trim());
+                  } else if (filterExpressionAsString.startsWith('>')) {
+                    return valueAsDate > convertToDate(filterExpressionAsString.substr(1).trim());
+                  } else if (filterExpressionAsString.startsWith('<')) {
+                    return valueAsDate < convertToDate(filterExpressionAsString.substr(1).trim());
                   }
 
-                  const expressionAsRegex = editableExpression.replace(/\*/g, ".*").replace(/\?/g, ".");
+                  
+                  if (filterExpressionAsString.length === 0) return true;
+                  return wildcardCheck(valueAsString, filterExpressionAsString);
 
-                  return valueAsString.match(new RegExp(expressionAsRegex, "g"));
                 }
-                else if (exp.includes('>=')) {
-                  return Number(valueAsString) >= Number(exp.replace('>=', ''));
-                } else if (exp.includes('<=')) {
-                  return Number(valueAsString) <= Number(exp.replace('<=', ''));
-                } else
-                  if (exp.includes('>')) {
-                    return Number(valueAsString) > Number(exp.replace('>', ''));
-                  } else if (exp.includes('<')) {
-                    return Number(valueAsString) < Number(exp.replace('<', ''));
-                  }
               }
-            }
 
-            return (value == exp)
-          }) : data;
+              return (dataValue == filterExpression)
+            });
+          };
         });
       }