@@ -1,5 +1,5 @@
|
||||
import {gql} from "@apollo/client";
|
||||
import {parse, print, visit, Kind} from "graphql";
|
||||
import {parse, print} from "graphql";
|
||||
import jsreport from "@jsreport/browser-client";
|
||||
import {notification} from "antd";
|
||||
import axios from "axios";
|
||||
@@ -10,6 +10,7 @@ import {store} from "../redux/store";
|
||||
import client from "../utils/GraphQLClient";
|
||||
import cleanAxios from "./CleanAxios";
|
||||
import {TemplateList} from "./TemplateConstants";
|
||||
import {applyFilters, applySorters, wrapFiltersInAnd} from "./graphQLmodifier";
|
||||
|
||||
const server = process.env.REACT_APP_REPORTS_SERVER_URL;
|
||||
|
||||
@@ -17,53 +18,6 @@ jsreport.serverUrl = server;
|
||||
|
||||
const Templates = TemplateList();
|
||||
|
||||
|
||||
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,
|
||||
@@ -395,7 +349,7 @@ export const fetchFilterData = async ({name}) => {
|
||||
if (generalTemplate) parsedFilterData = atob(generalTemplate.content);
|
||||
}
|
||||
|
||||
return { data: JSON.parse(parsedFilterData), useShopSpecificTemplate};
|
||||
return {data: JSON.parse(parsedFilterData), useShopSpecificTemplate};
|
||||
};
|
||||
|
||||
const fetchContextData = async (templateObject, jsrAuth) => {
|
||||
@@ -444,7 +398,33 @@ const fetchContextData = async (templateObject, jsrAuth) => {
|
||||
console.dir(templateObject);
|
||||
|
||||
|
||||
const ast = applyFilters(parse(templateQueryToExecute), templateObject.filters);
|
||||
if ((!templateObject?.filters && !templateObject?.filters?.length && !templateObject?.sorters && !templateObject?.sorters?.length)) {
|
||||
console.log('No filters or sorters');
|
||||
let contextData = {};
|
||||
if (templateQueryToExecute) {
|
||||
const {data} = await client.query({
|
||||
query: gql(templateQueryToExecute),
|
||||
variables: {...templateObject.variables},
|
||||
});
|
||||
contextData = data;
|
||||
}
|
||||
|
||||
return {contextData, useShopSpecificTemplate};
|
||||
}
|
||||
|
||||
const ast = parse(templateQueryToExecute);
|
||||
let filterFields = [];
|
||||
|
||||
if (templateObject?.filters && templateObject?.filters?.length) {
|
||||
console.log('Applying filters')
|
||||
applyFilters(ast, templateObject.filters, filterFields);
|
||||
wrapFiltersInAnd(ast, filterFields);
|
||||
}
|
||||
if (templateObject?.sorters && templateObject?.sorters?.length) {
|
||||
console.log('Applying sorters')
|
||||
applySorters(ast, templateObject.sorters);
|
||||
}
|
||||
|
||||
const finalQuery = print(ast);
|
||||
console.log(finalQuery);
|
||||
|
||||
|
||||
114
client/src/utils/graphQLmodifier.js
Normal file
114
client/src/utils/graphQLmodifier.js
Normal file
@@ -0,0 +1,114 @@
|
||||
import {Kind, visit} from "graphql";
|
||||
|
||||
/**
|
||||
* Apply sorters to the AST
|
||||
* @param ast
|
||||
* @param sorters
|
||||
*/
|
||||
export function applySorters(ast, sorters) {
|
||||
sorters.forEach((sorter) => {
|
||||
const [table, field] = sorter.field.split('.');
|
||||
visit(ast, {
|
||||
OperationDefinition: {
|
||||
enter(node) {
|
||||
node.selectionSet.selections.forEach((selection) => {
|
||||
if (selection.name.value === table) {
|
||||
let orderByArg = selection.arguments.find(arg => arg.name.value === 'order_by');
|
||||
if (!orderByArg) {
|
||||
orderByArg = {
|
||||
kind: Kind.ARGUMENT,
|
||||
name: {kind: Kind.NAME, value: 'order_by'},
|
||||
value: {kind: Kind.OBJECT, fields: []}
|
||||
};
|
||||
selection.arguments.push(orderByArg);
|
||||
}
|
||||
|
||||
const sorterField = {
|
||||
kind: Kind.OBJECT_FIELD,
|
||||
name: {kind: Kind.NAME, value: field},
|
||||
value: {kind: Kind.ENUM, value: sorter.direction} // 'asc' for ascending order, 'desc' for descending order
|
||||
};
|
||||
|
||||
orderByArg.value.fields.push(sorterField);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply filters to the AST
|
||||
* @param ast
|
||||
* @param filters
|
||||
* @param filterFields
|
||||
*/
|
||||
export function applyFilters(ast, filters, filterFields) {
|
||||
filters.forEach((filter) => {
|
||||
const struct = filter.field.split('.');
|
||||
visit(ast, {
|
||||
OperationDefinition: {
|
||||
enter(node) {
|
||||
node.selectionSet.selections.forEach((selection) => {
|
||||
if (selection.name.value === struct[0]) {
|
||||
let whereArg = selection.arguments.find(arg => arg.name.value === 'where');
|
||||
|
||||
if (!whereArg) {
|
||||
whereArg = {
|
||||
kind: Kind.ARGUMENT,
|
||||
name: {kind: Kind.NAME, value: 'where'},
|
||||
value: {kind: Kind.OBJECT, fields: []}
|
||||
};
|
||||
selection.arguments.push(whereArg);
|
||||
}
|
||||
|
||||
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},
|
||||
value: {kind: Kind.STRING, value: filter.value}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
filterFields.push({kind: Kind.OBJECT, fields: [filterField]});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap filters in an 'and' object
|
||||
* @param ast
|
||||
* @param filterFields
|
||||
*/
|
||||
export function wrapFiltersInAnd(ast, filterFields) {
|
||||
visit(ast, {
|
||||
OperationDefinition: {
|
||||
enter(node) {
|
||||
node.selectionSet.selections.forEach((selection) => {
|
||||
let whereArg = selection.arguments.find(arg => arg.name.value === 'where');
|
||||
if (filterFields.length > 1) {
|
||||
const andFilter = {
|
||||
kind: Kind.OBJECT_FIELD,
|
||||
name: {kind: Kind.NAME, value: '_and'},
|
||||
value: {kind: Kind.LIST, values: filterFields}
|
||||
};
|
||||
whereArg.value.fields.push(andFilter);
|
||||
} else if (filterFields.length === 1) {
|
||||
whereArg.value.fields.push(filterFields[0].fields[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user