diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..79368e997 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.yml] +indent_size = 2 + +[*.json] +indent_size = 2 \ No newline at end of file diff --git a/client/src/components/report-center-modal/test.jsx b/client/src/components/report-center-modal/test.jsx index 8217e5e5a..d1a5e3aff 100644 --- a/client/src/components/report-center-modal/test.jsx +++ b/client/src/components/report-center-modal/test.jsx @@ -23,7 +23,7 @@ function RenderFilters({ templateId }) { const fetch = async () => { const data = await fetchFilterData({ name: templateId }); console.log("🚀 ~ fetch ~ data:", data); - setState(JSON.parse(data)); + setState(data.data); }; console.log("🚀 ~ useEffect ~ templateId:", templateId); @@ -79,7 +79,20 @@ function RenderFilters({ templateId }) { }, ]} > - diff --git a/client/src/utils/RenderTemplate.js b/client/src/utils/RenderTemplate.js index a86a8c8b8..caafdfaf2 100644 --- a/client/src/utils/RenderTemplate.js +++ b/client/src/utils/RenderTemplate.js @@ -1,4 +1,5 @@ import {gql} from "@apollo/client"; +import {parse, print, visit, Kind} from "graphql"; import jsreport from "@jsreport/browser-client"; import {notification} from "antd"; import axios from "axios"; @@ -16,6 +17,120 @@ jsreport.serverUrl = server; const Templates = TemplateList(); + +function applyFilters(ast, filters) { + const struct = filters.field.split('.'); + + return visit(ast, { + OperationDefinition: { + enter(node) { + // Traverse through the operation definitions to find the correct query and its arguments + node.selectionSet.selections.forEach((selection) => { + if (selection.name.value ===struct[0]) { + // Find the existing 'where' argument, if it exists + let whereArg = selection.arguments.find(arg => arg.name.value === 'where'); + + if (!whereArg) { + // If 'where' argument doesn't exist, create it with an _and structure + whereArg = { + kind: Kind.ARGUMENT, + name: { kind: Kind.NAME, value: 'where' }, + value: { + kind: Kind.OBJECT, + fields: [{ + kind: Kind.OBJECT_FIELD, + name: { kind: Kind.NAME, value: '_and' }, + value: { kind: Kind.LIST, values: [] } // Initialize an empty list for '_and' conditions + }] + } + }; + selection.arguments.push(whereArg); // Add 'where' argument to the 'jobs' field + } else { + // Ensure the _and structure exists if the where argument already exists + let andField = whereArg.value.fields.find(field => field.name.value === '_and'); + if (!andField) { + andField = { + kind: Kind.OBJECT_FIELD, + name: { kind: Kind.NAME, value: '_and' }, + value: { kind: Kind.LIST, values: [] } + }; + whereArg.value.fields.push(andField); + } + } + + // Prepare the filter condition to be added to the _and list + const filterConditions = filters.map(filter => ({ + kind: Kind.OBJECT, + fields: [{ + kind: Kind.OBJECT_FIELD, + name: { kind: Kind.NAME, value: struct[1] }, + value: { + kind: Kind.OBJECT, + fields: [{ + kind: Kind.OBJECT_FIELD, + name: { kind: Kind.NAME, value: filter.operator }, // Adjust based on filter.operator if necessary + value: { kind: Kind.STRING, value: filter.value } // Adjust based on the type of filter.value + }] + } + }] + })); + + // Locate the _and field and add the filter conditions + const andField = whereArg.value.fields.find(field => field.name.value === '_and'); + andField.value.values.push(...filterConditions); + } + }); + } + } + }); +} + +// function applyFilters(ast, filters) { +// return filters.reduce((modifiedAst, filter) => { +// const struct = filter.field.split('.'); +// +// return visit(modifiedAst, { +// OperationDefinition: { +// enter(node) { +// // Traverse through the operation definitions to find the correct query and its arguments +// node.selectionSet.selections.forEach((selection) => { +// if (selection.name.value === struct[0]) { +// // Find the existing 'where' argument, if it exists +// let whereArg = selection.arguments.find(arg => arg.name.value === 'where'); +// +// if (!whereArg) { +// // If 'where' argument doesn't exist, create it +// whereArg = { +// kind: Kind.ARGUMENT, +// name: { kind: Kind.NAME, value: 'where' }, +// value: { kind: Kind.OBJECT, fields: [] } // Initialize an empty object for 'where' clause +// }; +// selection.arguments.push(whereArg); // Add 'where' argument to the 'jobs' field +// } +// +// // Assuming the filter should be added to the 'where' clause +// const filterField = { +// kind: Kind.OBJECT_FIELD, +// name: { kind: Kind.NAME, value: struct[1] }, +// value: { +// kind: Kind.OBJECT, +// fields: [{ +// kind: Kind.OBJECT_FIELD, +// name: { kind: Kind.NAME, value: filter.operator }, // Assuming equality operator; adjust as necessary +// value: { kind: Kind.STRING, value: filter.value } +// }] +// } +// }; +// +// // Add the filter to the 'where' argument's value +// whereArg.value.fields.push(filterField); +// } +// }); +// } +// } +// }); +// }, ast); +// } export default async function RenderTemplate( templateObject, bodyshop, @@ -23,6 +138,7 @@ export default async function RenderTemplate( renderAsExcel = false, renderAsText = false ) { + console.log(' RENDER TEMPLATE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') if (window.jsr3) { jsreport.serverUrl = "https://reports3.test.imex.online/"; } @@ -147,6 +263,7 @@ export async function RenderTemplates( templateObjects.forEach((template) => { proms.push( (async () => { + console.log(' RENDER TEMPLATE 2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') let {contextData, useShopSpecificTemplate} = await fetchContextData( template, jsrAuth @@ -306,49 +423,50 @@ export const GenerateDocuments = async (templates) => { await RenderTemplates(templates, bodyshop); }; -export const fetchFilterData = async ({ name }) => { - const bodyshop = store.getState().user.bodyshop; - const jsrAuth = (await axios.post("/utils/jsr")).data; - jsreport.headers["FirebaseAuthorization"] = - "Bearer " + (await auth.currentUser.getIdToken()); +export const fetchFilterData = async ({name}) => { + const bodyshop = store.getState().user.bodyshop; + const jsrAuth = (await axios.post("/utils/jsr")).data; + jsreport.headers["FirebaseAuthorization"] = + "Bearer " + (await auth.currentUser.getIdToken()); - const folders = await cleanAxios.get(`${server}/odata/folders`, { - headers: { Authorization: jsrAuth }, - }); - const shopSpecificFolder = folders.data.value.find( - (f) => f.name === bodyshop.imexshopid - ); - - const jsReportFilters = await cleanAxios.get( - `${server}/odata/assets?$filter=name eq '${name}.filters'`, - { headers: { Authorization: jsrAuth } } - ); - console.log("🚀 ~ fetchFilterData ~ jsReportFilters:", jsReportFilters); - - let parsedFilterData; - let useShopSpecificTemplate = false; - // let shopSpecificTemplate; - - if (shopSpecificFolder) { - let shopSpecificTemplate = jsReportFilters.data.value.find( - (f) => f?.folder?.shortid === shopSpecificFolder.shortid + const folders = await cleanAxios.get(`${server}/odata/folders`, { + headers: {Authorization: jsrAuth}, + }); + const shopSpecificFolder = folders.data.value.find( + (f) => f.name === bodyshop.imexshopid ); - if (shopSpecificTemplate) { - useShopSpecificTemplate = true; - parsedFilterData = atob(shopSpecificTemplate.content); + + const jsReportFilters = await cleanAxios.get( + `${server}/odata/assets?$filter=name eq '${name}.filters'`, + {headers: {Authorization: jsrAuth}} + ); + console.log("🚀 ~ fetchFilterData ~ jsReportFilters:", jsReportFilters); + + let parsedFilterData; + let useShopSpecificTemplate = false; + // let shopSpecificTemplate; + + if (shopSpecificFolder) { + let shopSpecificTemplate = jsReportFilters.data.value.find( + (f) => f?.folder?.shortid === shopSpecificFolder.shortid + ); + if (shopSpecificTemplate) { + useShopSpecificTemplate = true; + parsedFilterData = atob(shopSpecificTemplate.content); + } } - } - if (!parsedFilterData) { - const generalTemplate = jsReportFilters.data.value.find((f) => !f.folder); - useShopSpecificTemplate = false; - if (generalTemplate) parsedFilterData = atob(generalTemplate.content); - } + if (!parsedFilterData) { + const generalTemplate = jsReportFilters.data.value.find((f) => !f.folder); + useShopSpecificTemplate = false; + if (generalTemplate) parsedFilterData = atob(generalTemplate.content); + } - return parsedFilterData; + return { data: JSON.parse(parsedFilterData), useShopSpecificTemplate}; }; const fetchContextData = async (templateObject, jsrAuth) => { + console.log(' FETCH CONTEXT DATA !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') const bodyshop = store.getState().user.bodyshop; jsreport.headers["FirebaseAuthorization"] = @@ -388,11 +506,19 @@ const fetchContextData = async (templateObject, jsrAuth) => { // TODO: REPORT UPDATE //TemplateQueryToExecute needs to get modified based on sorters/filters set by user from modal. + console.log(' RENDER TEMPLATE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') + console.dir(templateQueryToExecute); + console.dir(templateObject); + + + const ast = applyFilters(parse(templateQueryToExecute), templateObject.filters); + const finalQuery = print(ast); + console.log(finalQuery); let contextData = {}; if (templateQueryToExecute) { const {data} = await client.query({ - query: gql(templateQueryToExecute), + query: gql(finalQuery), variables: {...templateObject.variables}, }); contextData = data;