@multiplatform.one/backoffice 7.28.1 → 7.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/desk/DeskSurface.native.js.map +1 -1
- package/dist/cjs/form/DocFormScreen.cjs +167 -224
- package/dist/cjs/form/DocFormScreen.native.js +182 -259
- package/dist/cjs/form/DocFormScreen.native.js.map +1 -1
- package/dist/cjs/i18n/en.cjs +1 -0
- package/dist/cjs/i18n/en.native.js +1 -0
- package/dist/cjs/i18n/en.native.js.map +1 -1
- package/dist/cjs/list/ListBulkActionsBar.cjs +30 -18
- package/dist/cjs/list/ListBulkActionsBar.native.js +43 -31
- package/dist/cjs/list/ListBulkActionsBar.native.js.map +1 -1
- package/dist/cjs/list/sidebar-section.cjs +15 -7
- package/dist/cjs/list/sidebar-section.native.js +16 -7
- package/dist/cjs/list/sidebar-section.native.js.map +1 -1
- package/dist/cjs/report/DoctypeReportView.cjs +20 -374
- package/dist/cjs/report/DoctypeReportView.native.js +23 -455
- package/dist/cjs/report/DoctypeReportView.native.js.map +1 -1
- package/dist/cjs/report/QueryReportScreen.cjs +33 -23
- package/dist/cjs/report/QueryReportScreen.native.js +33 -23
- package/dist/cjs/report/QueryReportScreen.native.js.map +1 -1
- package/dist/cjs/report/queryReportColumns.cjs +3 -105
- package/dist/cjs/report/queryReportColumns.native.js +2 -129
- package/dist/cjs/report/queryReportColumns.native.js.map +1 -1
- package/dist/cjs/report/queryReportFilterBar.cjs +3 -4
- package/dist/cjs/report/queryReportFilterBar.native.js +3 -4
- package/dist/cjs/report/queryReportFilterBar.native.js.map +1 -1
- package/dist/cjs/report/queryReportUrlState.cjs +2 -2
- package/dist/cjs/report/queryReportUrlState.native.js +2 -2
- package/dist/cjs/report/queryReportUrlState.native.js.map +1 -1
- package/dist/cjs/report/report-grid.cjs +2 -426
- package/dist/cjs/report/report-grid.native.js +1 -479
- package/dist/cjs/report/report-grid.native.js.map +1 -1
- package/dist/cjs/report/report-toolbar.cjs +2 -228
- package/dist/cjs/report/report-toolbar.native.js +1 -274
- package/dist/cjs/report/report-toolbar.native.js.map +1 -1
- package/dist/cjs/report/reportShapes.cjs +12 -383
- package/dist/cjs/report/reportShapes.native.js +12 -501
- package/dist/cjs/report/reportShapes.native.js.map +1 -1
- package/dist/cjs/report/reportViewModel.cjs +20 -360
- package/dist/cjs/report/reportViewModel.native.js +19 -627
- package/dist/cjs/report/reportViewModel.native.js.map +1 -1
- package/dist/cjs/report/savedReports.cjs +2 -106
- package/dist/cjs/report/savedReports.native.js +1 -132
- package/dist/cjs/report/savedReports.native.js.map +1 -1
- package/dist/cjs/report/useQueryReport.cjs +11 -219
- package/dist/cjs/report/useQueryReport.native.js +11 -244
- package/dist/cjs/report/useQueryReport.native.js.map +1 -1
- package/dist/cjs/shared/measures.cjs +3 -5
- package/dist/cjs/shared/measures.native.js +3 -5
- package/dist/cjs/shared/measures.native.js.map +1 -1
- package/dist/cjs/views/ReportView.cjs +3 -256
- package/dist/cjs/views/ReportView.native.js +3 -382
- package/dist/cjs/views/ReportView.native.js.map +1 -1
- package/dist/cjs/views/report-controls.cjs +6 -6
- package/dist/cjs/views/report-controls.native.js +6 -6
- package/dist/cjs/views/report-controls.native.js.map +1 -1
- package/dist/esm/desk/DeskSurface.mjs.map +1 -1
- package/dist/esm/desk/DeskSurface.native.js.map +1 -1
- package/dist/esm/form/DocFormScreen.mjs +169 -226
- package/dist/esm/form/DocFormScreen.mjs.map +1 -1
- package/dist/esm/form/DocFormScreen.native.js +184 -261
- package/dist/esm/form/DocFormScreen.native.js.map +1 -1
- package/dist/esm/i18n/en.mjs +1 -0
- package/dist/esm/i18n/en.mjs.map +1 -1
- package/dist/esm/i18n/en.native.js +1 -0
- package/dist/esm/i18n/en.native.js.map +1 -1
- package/dist/esm/list/ListBulkActionsBar.mjs +31 -19
- package/dist/esm/list/ListBulkActionsBar.mjs.map +1 -1
- package/dist/esm/list/ListBulkActionsBar.native.js +37 -25
- package/dist/esm/list/ListBulkActionsBar.native.js.map +1 -1
- package/dist/esm/list/sidebar-section.mjs +16 -8
- package/dist/esm/list/sidebar-section.mjs.map +1 -1
- package/dist/esm/list/sidebar-section.native.js +17 -8
- package/dist/esm/list/sidebar-section.native.js.map +1 -1
- package/dist/esm/report/DoctypeReportView.mjs +21 -375
- package/dist/esm/report/DoctypeReportView.mjs.map +1 -1
- package/dist/esm/report/DoctypeReportView.native.js +24 -456
- package/dist/esm/report/DoctypeReportView.native.js.map +1 -1
- package/dist/esm/report/QueryReportScreen.mjs +26 -16
- package/dist/esm/report/QueryReportScreen.mjs.map +1 -1
- package/dist/esm/report/QueryReportScreen.native.js +26 -16
- package/dist/esm/report/QueryReportScreen.native.js.map +1 -1
- package/dist/esm/report/queryReportColumns.mjs +1 -103
- package/dist/esm/report/queryReportColumns.mjs.map +1 -1
- package/dist/esm/report/queryReportColumns.native.js +1 -117
- package/dist/esm/report/queryReportColumns.native.js.map +1 -1
- package/dist/esm/report/queryReportFilterBar.mjs +1 -2
- package/dist/esm/report/queryReportFilterBar.mjs.map +1 -1
- package/dist/esm/report/queryReportFilterBar.native.js +1 -2
- package/dist/esm/report/queryReportFilterBar.native.js.map +1 -1
- package/dist/esm/report/queryReportUrlState.mjs +1 -1
- package/dist/esm/report/queryReportUrlState.native.js +1 -1
- package/dist/esm/report/report-grid.mjs +1 -425
- package/dist/esm/report/report-grid.mjs.map +1 -1
- package/dist/esm/report/report-grid.native.js +1 -468
- package/dist/esm/report/report-grid.native.js.map +1 -1
- package/dist/esm/report/report-toolbar.mjs +2 -228
- package/dist/esm/report/report-toolbar.mjs.map +1 -1
- package/dist/esm/report/report-toolbar.native.js +2 -264
- package/dist/esm/report/report-toolbar.native.js.map +1 -1
- package/dist/esm/report/reportShapes.mjs +2 -373
- package/dist/esm/report/reportShapes.mjs.map +1 -1
- package/dist/esm/report/reportShapes.native.js +2 -491
- package/dist/esm/report/reportShapes.native.js.map +1 -1
- package/dist/esm/report/reportViewModel.mjs +2 -342
- package/dist/esm/report/reportViewModel.mjs.map +1 -1
- package/dist/esm/report/reportViewModel.native.js +2 -610
- package/dist/esm/report/reportViewModel.native.js.map +1 -1
- package/dist/esm/report/savedReports.mjs +1 -105
- package/dist/esm/report/savedReports.mjs.map +1 -1
- package/dist/esm/report/savedReports.native.js +1 -132
- package/dist/esm/report/savedReports.native.js.map +1 -1
- package/dist/esm/report/useQueryReport.mjs +2 -210
- package/dist/esm/report/useQueryReport.mjs.map +1 -1
- package/dist/esm/report/useQueryReport.native.js +2 -235
- package/dist/esm/report/useQueryReport.native.js.map +1 -1
- package/dist/esm/shared/measures.mjs +1 -3
- package/dist/esm/shared/measures.mjs.map +1 -1
- package/dist/esm/shared/measures.native.js +1 -3
- package/dist/esm/shared/measures.native.js.map +1 -1
- package/dist/esm/views/ReportView.mjs +3 -256
- package/dist/esm/views/ReportView.mjs.map +1 -1
- package/dist/esm/views/ReportView.native.js +3 -382
- package/dist/esm/views/ReportView.native.js.map +1 -1
- package/dist/esm/views/report-controls.mjs +3 -3
- package/dist/esm/views/report-controls.mjs.map +1 -1
- package/dist/esm/views/report-controls.native.js +3 -3
- package/dist/esm/views/report-controls.native.js.map +1 -1
- package/dist/jsx/desk/DeskSurface.mjs.map +1 -1
- package/dist/jsx/desk/DeskSurface.native.js.map +1 -1
- package/dist/jsx/form/DocFormScreen.mjs +169 -226
- package/dist/jsx/form/DocFormScreen.mjs.map +1 -1
- package/dist/jsx/form/DocFormScreen.native.js +182 -259
- package/dist/jsx/form/DocFormScreen.native.js.map +1 -1
- package/dist/jsx/i18n/en.mjs +1 -0
- package/dist/jsx/i18n/en.mjs.map +1 -1
- package/dist/jsx/i18n/en.native.js +1 -0
- package/dist/jsx/i18n/en.native.js.map +1 -1
- package/dist/jsx/list/ListBulkActionsBar.mjs +31 -19
- package/dist/jsx/list/ListBulkActionsBar.mjs.map +1 -1
- package/dist/jsx/list/ListBulkActionsBar.native.js +43 -31
- package/dist/jsx/list/ListBulkActionsBar.native.js.map +1 -1
- package/dist/jsx/list/sidebar-section.mjs +16 -8
- package/dist/jsx/list/sidebar-section.mjs.map +1 -1
- package/dist/jsx/list/sidebar-section.native.js +16 -7
- package/dist/jsx/list/sidebar-section.native.js.map +1 -1
- package/dist/jsx/report/DoctypeReportView.mjs +21 -375
- package/dist/jsx/report/DoctypeReportView.mjs.map +1 -1
- package/dist/jsx/report/DoctypeReportView.native.js +23 -455
- package/dist/jsx/report/DoctypeReportView.native.js.map +1 -1
- package/dist/jsx/report/QueryReportScreen.mjs +26 -16
- package/dist/jsx/report/QueryReportScreen.mjs.map +1 -1
- package/dist/jsx/report/QueryReportScreen.native.js +33 -23
- package/dist/jsx/report/QueryReportScreen.native.js.map +1 -1
- package/dist/jsx/report/queryReportColumns.mjs +1 -103
- package/dist/jsx/report/queryReportColumns.mjs.map +1 -1
- package/dist/jsx/report/queryReportColumns.native.js +2 -129
- package/dist/jsx/report/queryReportColumns.native.js.map +1 -1
- package/dist/jsx/report/queryReportFilterBar.mjs +1 -2
- package/dist/jsx/report/queryReportFilterBar.mjs.map +1 -1
- package/dist/jsx/report/queryReportFilterBar.native.js +3 -4
- package/dist/jsx/report/queryReportFilterBar.native.js.map +1 -1
- package/dist/jsx/report/queryReportUrlState.mjs +1 -1
- package/dist/jsx/report/queryReportUrlState.native.js +2 -2
- package/dist/jsx/report/queryReportUrlState.native.js.map +1 -1
- package/dist/jsx/report/report-grid.mjs +1 -425
- package/dist/jsx/report/report-grid.mjs.map +1 -1
- package/dist/jsx/report/report-grid.native.js +1 -479
- package/dist/jsx/report/report-grid.native.js.map +1 -1
- package/dist/jsx/report/report-toolbar.mjs +2 -228
- package/dist/jsx/report/report-toolbar.mjs.map +1 -1
- package/dist/jsx/report/report-toolbar.native.js +1 -274
- package/dist/jsx/report/report-toolbar.native.js.map +1 -1
- package/dist/jsx/report/reportShapes.mjs +2 -373
- package/dist/jsx/report/reportShapes.mjs.map +1 -1
- package/dist/jsx/report/reportShapes.native.js +12 -501
- package/dist/jsx/report/reportShapes.native.js.map +1 -1
- package/dist/jsx/report/reportViewModel.mjs +2 -342
- package/dist/jsx/report/reportViewModel.mjs.map +1 -1
- package/dist/jsx/report/reportViewModel.native.js +19 -627
- package/dist/jsx/report/reportViewModel.native.js.map +1 -1
- package/dist/jsx/report/savedReports.mjs +1 -105
- package/dist/jsx/report/savedReports.mjs.map +1 -1
- package/dist/jsx/report/savedReports.native.js +1 -132
- package/dist/jsx/report/savedReports.native.js.map +1 -1
- package/dist/jsx/report/useQueryReport.mjs +2 -210
- package/dist/jsx/report/useQueryReport.mjs.map +1 -1
- package/dist/jsx/report/useQueryReport.native.js +11 -244
- package/dist/jsx/report/useQueryReport.native.js.map +1 -1
- package/dist/jsx/shared/measures.mjs +1 -3
- package/dist/jsx/shared/measures.mjs.map +1 -1
- package/dist/jsx/shared/measures.native.js +3 -5
- package/dist/jsx/shared/measures.native.js.map +1 -1
- package/dist/jsx/views/ReportView.mjs +3 -256
- package/dist/jsx/views/ReportView.mjs.map +1 -1
- package/dist/jsx/views/ReportView.native.js +3 -382
- package/dist/jsx/views/ReportView.native.js.map +1 -1
- package/dist/jsx/views/report-controls.mjs +3 -3
- package/dist/jsx/views/report-controls.mjs.map +1 -1
- package/dist/jsx/views/report-controls.native.js +6 -6
- package/dist/jsx/views/report-controls.native.js.map +1 -1
- package/package.json +12 -12
- package/src/backofficeScreens.designLaw.spec.ts +0 -5
- package/src/desk/DeskSurface.tsx +4 -7
- package/src/form/DocFormScreen.chrome.spec.ts +77 -0
- package/src/form/DocFormScreen.guest.screen.spec.tsx +175 -0
- package/src/form/DocFormScreen.rights.spec.tsx +7 -3
- package/src/form/DocFormScreen.tsx +214 -315
- package/src/i18n/en.ts +1 -0
- package/src/list/ListBulkActionsBar.rights.spec.tsx +134 -0
- package/src/list/ListBulkActionsBar.screen.spec.tsx +7 -1
- package/src/list/ListBulkActionsBar.tsx +76 -57
- package/src/list/ListFilterBar.screen.spec.tsx +14 -13
- package/src/list/sidebar-section.tsx +11 -3
- package/src/report/DoctypeReportView.tsx +28 -550
- package/src/report/QueryReportScreen.spec.tsx +75 -1
- package/src/report/QueryReportScreen.tsx +38 -22
- package/src/report/queryReportColumns.tsx +4 -123
- package/src/report/queryReportFilterBar.tsx +3 -5
- package/src/report/queryReportUrlState.ts +1 -1
- package/src/report/report-grid.tsx +4 -529
- package/src/report/report-toolbar.tsx +4 -308
- package/src/report/reportShapes.ts +25 -613
- package/src/report/reportShim.spec.ts +162 -0
- package/src/report/reportViewModel.ts +32 -605
- package/src/report/savedReports.ts +4 -161
- package/src/report/useQueryReport.ts +9 -347
- package/src/shared/measures.ts +3 -11
- package/src/views/ReportView.screen.spec.tsx +25 -20
- package/src/views/ReportView.tsx +7 -439
- package/src/views/report-controls.tsx +12 -20
- package/types/desk/DeskSurface.d.ts.map +1 -1
- package/types/form/DocFormScreen.d.ts +2 -2
- package/types/form/DocFormScreen.d.ts.map +1 -1
- package/types/i18n/en.d.ts +1 -0
- package/types/i18n/en.d.ts.map +1 -1
- package/types/list/ListBulkActionsBar.d.ts.map +1 -1
- package/types/list/sidebar-section.d.ts.map +1 -1
- package/types/report/DoctypeReportView.d.ts.map +1 -1
- package/types/report/QueryReportScreen.d.ts +1 -1
- package/types/report/QueryReportScreen.d.ts.map +1 -1
- package/types/report/queryReportColumns.d.ts +2 -11
- package/types/report/queryReportColumns.d.ts.map +1 -1
- package/types/report/queryReportFilterBar.d.ts +1 -1
- package/types/report/queryReportFilterBar.d.ts.map +1 -1
- package/types/report/queryReportUrlState.d.ts +1 -1
- package/types/report/queryReportUrlState.d.ts.map +1 -1
- package/types/report/report-grid.d.ts +2 -19
- package/types/report/report-grid.d.ts.map +1 -1
- package/types/report/report-toolbar.d.ts +2 -29
- package/types/report/report-toolbar.d.ts.map +1 -1
- package/types/report/reportShapes.d.ts +2 -115
- package/types/report/reportShapes.d.ts.map +1 -1
- package/types/report/reportViewModel.d.ts +2 -135
- package/types/report/reportViewModel.d.ts.map +1 -1
- package/types/report/savedReports.d.ts +2 -18
- package/types/report/savedReports.d.ts.map +1 -1
- package/types/report/useQueryReport.d.ts +2 -35
- package/types/report/useQueryReport.d.ts.map +1 -1
- package/types/shared/measures.d.ts +1 -2
- package/types/shared/measures.d.ts.map +1 -1
- package/types/views/ReportView.d.ts +3 -22
- package/types/views/ReportView.d.ts.map +1 -1
- package/types/views/report-controls.d.ts +2 -5
- package/types/views/report-controls.d.ts.map +1 -1
- package/src/report/report-grid.spec.tsx +0 -175
- package/src/report/report-toolbar.spec.tsx +0 -90
- package/src/report/reportShapes.spec.ts +0 -391
- package/src/report/reportViewModel.spec.ts +0 -393
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { renderWithProviders } from "@multiplatform.one/test-utils";
|
|
6
6
|
import { fireEvent, screen, waitFor } from "@testing-library/react";
|
|
7
7
|
import React from "react";
|
|
8
|
-
import { describe, expect, it } from "vitest";
|
|
8
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
9
9
|
import { BackofficeProvider } from "../config/BackofficeProvider";
|
|
10
10
|
import { createMemoryNavigator } from "../navigation/navigator";
|
|
11
11
|
import { QueryReportScreen } from "./QueryReportScreen";
|
|
@@ -72,3 +72,77 @@ describe("QueryReportScreen filter URL round-trip", () => {
|
|
|
72
72
|
expect(screen.getByRole("button", { name: /export csv/i })).toBeTruthy();
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
|
+
|
|
76
|
+
// LC-96: a report the session may not run is a permission state, not an error
|
|
77
|
+
// whose retry cannot succeed. The bench refuses the Report doc, its script and
|
|
78
|
+
// the run the way Frappe refuses a user without the report's role.
|
|
79
|
+
describe("QueryReportScreen refused run", () => {
|
|
80
|
+
afterEach(() => {
|
|
81
|
+
vi.unstubAllGlobals();
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
function stubRefusingBench(message = "You don't have access to Report: Team Workload") {
|
|
85
|
+
vi.stubGlobal(
|
|
86
|
+
"fetch",
|
|
87
|
+
async () =>
|
|
88
|
+
new Response(
|
|
89
|
+
JSON.stringify({
|
|
90
|
+
exc_type: "PermissionError",
|
|
91
|
+
_server_messages: JSON.stringify([JSON.stringify({ message })]),
|
|
92
|
+
}),
|
|
93
|
+
{ status: 403, headers: { "content-type": "application/json" } },
|
|
94
|
+
),
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let run = 0;
|
|
99
|
+
function renderRefused() {
|
|
100
|
+
run += 1;
|
|
101
|
+
const navigation = createMemoryNavigator("/backoffice/query-report/Team%20Workload");
|
|
102
|
+
return renderWithProviders(
|
|
103
|
+
<BackofficeProvider
|
|
104
|
+
frappe={{ baseURL: `https://backoffice-query-report-refused-${run}.mock.test` }}
|
|
105
|
+
navigation={navigation}
|
|
106
|
+
>
|
|
107
|
+
<QueryReportScreen reportName="Team Workload" />
|
|
108
|
+
</BackofficeProvider>,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
it("says the reader can't run the report, with the server's reason and no retry", async () => {
|
|
113
|
+
stubRefusingBench();
|
|
114
|
+
renderRefused();
|
|
115
|
+
|
|
116
|
+
const state = await screen.findByTestId("frappe-report-not-permitted", {}, { timeout: 8000 });
|
|
117
|
+
expect(state.textContent).toContain(`You can't run "Team Workload"`);
|
|
118
|
+
expect(state.textContent).toContain("You don't have access to Report: Team Workload");
|
|
119
|
+
expect(screen.queryByRole("button", { name: /retry|refresh/i })).toBeNull();
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// MPO-473: a refused run has nothing to export, and never will.
|
|
123
|
+
it("offers no Export CSV", async () => {
|
|
124
|
+
stubRefusingBench();
|
|
125
|
+
renderRefused();
|
|
126
|
+
|
|
127
|
+
await screen.findByTestId("frappe-report-not-permitted", {}, { timeout: 8000 });
|
|
128
|
+
expect(screen.queryByRole("button", { name: /export csv/i })).toBeNull();
|
|
129
|
+
expect(screen.queryByText("Export CSV")).toBeNull();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// Verbatim from pokemon's bench signed out: is_whitelisted refuses Guest with
|
|
133
|
+
// one message, a <details> summary and body, which rendered glued as
|
|
134
|
+
// "Login to accessFunction frappe.desk.query_report.run …".
|
|
135
|
+
it("renders each line of the server's reason on its own", async () => {
|
|
136
|
+
stubRefusingBench(
|
|
137
|
+
"<details><summary>You are not permitted to access this resource. Login to access</summary>Function <strong>frappe.desk.query_report.run</strong> is not whitelisted.</details>",
|
|
138
|
+
);
|
|
139
|
+
renderRefused();
|
|
140
|
+
|
|
141
|
+
const state = await screen.findByTestId("frappe-report-not-permitted", {}, { timeout: 8000 });
|
|
142
|
+
const lines = Array.from(state.querySelectorAll("p")).map((node) => node.textContent);
|
|
143
|
+
expect(lines).toEqual([
|
|
144
|
+
"You are not permitted to access this resource. Login to access",
|
|
145
|
+
"Function frappe.desk.query_report.run is not whitelisted.",
|
|
146
|
+
]);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
@@ -31,22 +31,23 @@ import {
|
|
|
31
31
|
useBackofficeNavigator,
|
|
32
32
|
useBackofficePaths,
|
|
33
33
|
} from "../config/BackofficeProvider";
|
|
34
|
+
import {
|
|
35
|
+
buildQueryReportColumns,
|
|
36
|
+
buildQueryReportCsv,
|
|
37
|
+
defaultFilterValues,
|
|
38
|
+
isEmptyFilterValue,
|
|
39
|
+
scrubFieldname,
|
|
40
|
+
stripReportHtml as stripHtml,
|
|
41
|
+
useQueryReport,
|
|
42
|
+
type QueryReportFilters,
|
|
43
|
+
type QueryReportFixture,
|
|
44
|
+
} from "@multiplatform.one/frappe-ui";
|
|
34
45
|
import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
|
|
35
|
-
import { buildQueryReportColumns, buildQueryReportCsv } from "./queryReportColumns";
|
|
36
46
|
import { QueryReportFilterBar, queryReportFilterLabel } from "./queryReportFilterBar";
|
|
37
47
|
import {
|
|
38
48
|
parseQueryReportFiltersParam,
|
|
39
49
|
serializeQueryReportFiltersParam,
|
|
40
50
|
} from "./queryReportUrlState";
|
|
41
|
-
import {
|
|
42
|
-
defaultFilterValues,
|
|
43
|
-
isEmptyFilterValue,
|
|
44
|
-
type QueryReportFilters,
|
|
45
|
-
type QueryReportFixture,
|
|
46
|
-
scrubFieldname,
|
|
47
|
-
stripHtml,
|
|
48
|
-
useQueryReport,
|
|
49
|
-
} from "./useQueryReport";
|
|
50
51
|
|
|
51
52
|
export interface QueryReportScreenProps {
|
|
52
53
|
/** Report document name (proper-cased, e.g. "Permitted Documents For User"). */
|
|
@@ -217,6 +218,17 @@ export function QueryReportScreen({
|
|
|
217
218
|
)}
|
|
218
219
|
/>
|
|
219
220
|
);
|
|
221
|
+
} else if (report.error && report.refused) {
|
|
222
|
+
body = (
|
|
223
|
+
<EmptyState
|
|
224
|
+
testID="frappe-report-not-permitted"
|
|
225
|
+
title={t("queryReport.notPermitted", {
|
|
226
|
+
defaultValue: 'You can\'t run "{{report}}"',
|
|
227
|
+
report: title,
|
|
228
|
+
})}
|
|
229
|
+
description={report.error.message}
|
|
230
|
+
/>
|
|
231
|
+
);
|
|
220
232
|
} else if (report.error) {
|
|
221
233
|
body = (
|
|
222
234
|
<YStack flex={1} gap="$2">
|
|
@@ -303,18 +315,22 @@ export function QueryReportScreen({
|
|
|
303
315
|
actions={
|
|
304
316
|
<XStack gap="$2" alignItems="center">
|
|
305
317
|
{report.running && !report.loading ? <Spinner size="small" /> : null}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
+
{report.refused ? null : (
|
|
319
|
+
<>
|
|
320
|
+
<Button size="$2" chromeless onPress={report.reload} disabled={report.loading}>
|
|
321
|
+
{t("queryReport.refresh", "Refresh")}
|
|
322
|
+
</Button>
|
|
323
|
+
<Button
|
|
324
|
+
size="$2"
|
|
325
|
+
chromeless
|
|
326
|
+
icon={DownloadSimpleIcon}
|
|
327
|
+
onPress={handleExport}
|
|
328
|
+
disabled={report.loading || report.rows.length === 0}
|
|
329
|
+
>
|
|
330
|
+
{t("queryReport.exportCsv", "Export CSV")}
|
|
331
|
+
</Button>
|
|
332
|
+
</>
|
|
333
|
+
)}
|
|
318
334
|
</XStack>
|
|
319
335
|
}
|
|
320
336
|
/>
|
|
@@ -1,123 +1,4 @@
|
|
|
1
|
-
// Query-report
|
|
2
|
-
//
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import React from "react";
|
|
6
|
-
import { Text } from "@multiplatform.one/components";
|
|
7
|
-
import type { DataTableColumn } from "@multiplatform.one/table";
|
|
8
|
-
import { formatDateCell } from "@multiplatform.one/frappe-ui";
|
|
9
|
-
import { type QueryReportColumn, type QueryReportRow, stripHtml } from "./useQueryReport";
|
|
10
|
-
|
|
11
|
-
const NUMERIC_FIELDTYPES = new Set(["Currency", "Float", "Int", "Percent", "Duration"]);
|
|
12
|
-
|
|
13
|
-
export interface BuildQueryReportColumnsArgs {
|
|
14
|
-
columns: readonly QueryReportColumn[];
|
|
15
|
-
/** Open a Link cell's target document (doctype comes from column options). */
|
|
16
|
-
onOpenLink?: (doctype: string, name: string) => void;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function queryReportCell(
|
|
20
|
-
column: QueryReportColumn,
|
|
21
|
-
onOpenLink?: (doctype: string, name: string) => void,
|
|
22
|
-
) {
|
|
23
|
-
return ({ getValue }: { getValue: () => unknown }) => {
|
|
24
|
-
const raw = getValue();
|
|
25
|
-
if (raw === null || raw === undefined || raw === "") {
|
|
26
|
-
return (
|
|
27
|
-
<Text fontSize="$3" color="$color8">
|
|
28
|
-
—
|
|
29
|
-
</Text>
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
if (column.fieldtype === "Check") {
|
|
33
|
-
return (
|
|
34
|
-
<Text fontSize="$3" color={raw ? "$green11" : "$color8"}>
|
|
35
|
-
{raw ? "✓" : "—"}
|
|
36
|
-
</Text>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
const value = String(raw);
|
|
40
|
-
if (NUMERIC_FIELDTYPES.has(column.fieldtype)) {
|
|
41
|
-
return (
|
|
42
|
-
<Text fontSize="$3" color="$color12" textAlign="right">
|
|
43
|
-
{value}
|
|
44
|
-
</Text>
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
switch (column.fieldtype) {
|
|
48
|
-
case "Date":
|
|
49
|
-
case "Datetime":
|
|
50
|
-
return (
|
|
51
|
-
<Text fontSize="$3" color="$color11">
|
|
52
|
-
{formatDateCell(value)}
|
|
53
|
-
</Text>
|
|
54
|
-
);
|
|
55
|
-
case "Link": {
|
|
56
|
-
const doctype = column.options;
|
|
57
|
-
if (doctype && onOpenLink) {
|
|
58
|
-
return (
|
|
59
|
-
<Text
|
|
60
|
-
fontSize="$3"
|
|
61
|
-
color="$color11"
|
|
62
|
-
textDecorationLine="underline"
|
|
63
|
-
cursor="pointer"
|
|
64
|
-
numberOfLines={1}
|
|
65
|
-
role="link"
|
|
66
|
-
onPress={(event) => {
|
|
67
|
-
event?.stopPropagation?.();
|
|
68
|
-
onOpenLink(doctype, value);
|
|
69
|
-
}}
|
|
70
|
-
>
|
|
71
|
-
{value}
|
|
72
|
-
</Text>
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
return (
|
|
76
|
-
<Text fontSize="$3" color="$color11" numberOfLines={1}>
|
|
77
|
-
{value}
|
|
78
|
-
</Text>
|
|
79
|
-
);
|
|
80
|
-
}
|
|
81
|
-
default:
|
|
82
|
-
return (
|
|
83
|
-
<Text fontSize="$3" color="$color11" numberOfLines={1}>
|
|
84
|
-
{stripHtml(value)}
|
|
85
|
-
</Text>
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/** Build DataTable columns for a query-report run result. */
|
|
92
|
-
export function buildQueryReportColumns({
|
|
93
|
-
columns,
|
|
94
|
-
onOpenLink,
|
|
95
|
-
}: BuildQueryReportColumnsArgs): DataTableColumn<QueryReportRow>[] {
|
|
96
|
-
return columns.map((column) => ({
|
|
97
|
-
id: column.fieldname,
|
|
98
|
-
header: column.label,
|
|
99
|
-
// accessorFn (not accessorKey): report fieldnames may contain path-y
|
|
100
|
-
// characters like "assigned_to/owner" that key-based access mangles.
|
|
101
|
-
accessorFn: (row: QueryReportRow) => row[column.fieldname],
|
|
102
|
-
...(NUMERIC_FIELDTYPES.has(column.fieldtype) ? { align: "right" as const } : {}),
|
|
103
|
-
...(column.width ? { width: column.width } : {}),
|
|
104
|
-
cell: queryReportCell(column, onOpenLink),
|
|
105
|
-
}));
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function escapeCsvCell(value: unknown): string {
|
|
109
|
-
if (value === null || value === undefined) return "";
|
|
110
|
-
const text = stripHtml(String(value));
|
|
111
|
-
return /[",\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/** CSV over the full run result (Desk Export, not just the current page). */
|
|
115
|
-
export function buildQueryReportCsv(
|
|
116
|
-
columns: readonly QueryReportColumn[],
|
|
117
|
-
rows: readonly QueryReportRow[],
|
|
118
|
-
): string {
|
|
119
|
-
return [
|
|
120
|
-
columns.map((column) => escapeCsvCell(column.label)).join(","),
|
|
121
|
-
...rows.map((row) => columns.map((column) => escapeCsvCell(row[column.fieldname])).join(",")),
|
|
122
|
-
].join("\n");
|
|
123
|
-
}
|
|
1
|
+
// Query-report columns live in @multiplatform.one/frappe-ui (MPO-15, GL-28);
|
|
2
|
+
// this path keeps handing out the same names.
|
|
3
|
+
export { buildQueryReportColumns, buildQueryReportCsv } from "@multiplatform.one/frappe-ui";
|
|
4
|
+
export type { BuildQueryReportColumnsArgs } from "@multiplatform.one/frappe-ui";
|
|
@@ -25,18 +25,16 @@ import { useCallback, useEffect, useRef, useState } from "react";
|
|
|
25
25
|
import { useTranslation } from "react-i18next";
|
|
26
26
|
import { BACKOFFICE_I18N_NAMESPACE } from "../i18n";
|
|
27
27
|
import {
|
|
28
|
+
compactQueryReportFilters,
|
|
28
29
|
Date as DateField,
|
|
29
30
|
fieldKind,
|
|
30
31
|
fieldLabelFor,
|
|
32
|
+
isEmptyFilterValue,
|
|
31
33
|
Link as LinkField,
|
|
32
34
|
selectOptionsFromField,
|
|
33
|
-
} from "@multiplatform.one/frappe-ui";
|
|
34
|
-
import {
|
|
35
|
-
compactQueryReportFilters,
|
|
36
|
-
isEmptyFilterValue,
|
|
37
35
|
type QueryReportFilterMeta,
|
|
38
36
|
type QueryReportFilters,
|
|
39
|
-
} from "
|
|
37
|
+
} from "@multiplatform.one/frappe-ui";
|
|
40
38
|
|
|
41
39
|
export function queryReportFilterLabel(filter: QueryReportFilterMeta): string {
|
|
42
40
|
return filter.label || fieldLabelFor([], filter.fieldname);
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* `setParams` (history REPLACE, no remount) and adopts inbound param changes
|
|
13
13
|
* (deep links, back/forward), so reload and shared links reproduce the run.
|
|
14
14
|
*/
|
|
15
|
-
import { isEmptyFilterValue, type QueryReportFilters } from "
|
|
15
|
+
import { isEmptyFilterValue, type QueryReportFilters } from "@multiplatform.one/frappe-ui";
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Parse the `?filters=` deep-link value. The router usually decodes the
|