Skip to content

Commit fb8790c

Browse files
committed
fix: enhance PluginScorecardList actions and improve sharing logic
- Added loading state handling to `Button` and `useManagePluginConfig` for better feedback during actions. - Improved sharing configuration logic to align `dashboardItem` sharing with the related scorecard. - Updated `MenuItem` to include `key` property to resolve React warnings. - Refined translation keys and updated corresponding `.pot` file.
1 parent 3f81744 commit fb8790c

File tree

3 files changed

+75
-24
lines changed

3 files changed

+75
-24
lines changed

i18n/en.pot

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ msgstr ""
55
"Content-Type: text/plain; charset=utf-8\n"
66
"Content-Transfer-Encoding: 8bit\n"
77
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
8-
"POT-Creation-Date: 2025-06-28T11:04:45.997Z\n"
9-
"PO-Revision-Date: 2025-06-28T11:04:45.997Z\n"
8+
"POT-Creation-Date: 2025-07-03T08:16:48.925Z\n"
9+
"PO-Revision-Date: 2025-07-03T08:16:48.927Z\n"
1010

1111
msgid "Scorecard deleted successfully"
1212
msgstr "Scorecard deleted successfully"
@@ -508,6 +508,25 @@ msgstr "Show Data in Rows"
508508
msgid "Reset"
509509
msgstr "Reset"
510510

511+
msgid "Welcome to the scorecard plugin"
512+
msgstr "Welcome to the scorecard plugin"
513+
514+
msgid ""
515+
"It seems you do not have any scorecards configured. Create a scorecard "
516+
"first in the Interactive scorecard app first."
517+
msgstr ""
518+
"It seems you do not have any scorecards configured. Create a scorecard "
519+
"first in the Interactive scorecard app first."
520+
521+
msgid "Go to scorecard app"
522+
msgstr "Go to scorecard app"
523+
524+
msgid "Select a scorecard"
525+
msgstr "Select a scorecard"
526+
527+
msgid "Select scorecard"
528+
msgstr "Select scorecard"
529+
511530
msgid "Are you sure you want to delete this entity?"
512531
msgstr "Are you sure you want to delete this entity?"
513532

@@ -940,25 +959,6 @@ msgstr "User Sub-x2-units"
940959
msgid "This group does not have any configured data sources"
941960
msgstr "This group does not have any configured data sources"
942961

943-
msgid "Welcome to the scorecard plugin"
944-
msgstr "Welcome to the scorecard plugin"
945-
946-
msgid ""
947-
"It seems you do not have any scorecards configured. Create a scorecard "
948-
"first in the Interactive scorecard app first."
949-
msgstr ""
950-
"It seems you do not have any scorecards configured. Create a scorecard "
951-
"first in the Interactive scorecard app first."
952-
953-
msgid "Go to scorecard app"
954-
msgstr "Go to scorecard app"
955-
956-
msgid "Select a scorecard"
957-
msgstr "Select a scorecard"
958-
959-
msgid "Select scorecard"
960-
msgstr "Select scorecard"
961-
962962
msgctxt "Application title"
963963
msgid "__MANIFEST_APP_TITLE"
964964
msgstr "Interactive Scorecard"

src/plugin/hooks/config.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { DATASTORE_WIDGET_NAMESPACE } from "../constants/scorecard";
22
import { useDataEngine, useDataQuery } from "@dhis2/app-runtime";
33
import { useCallback } from "react";
4+
import { DATASTORE_NAMESPACE } from "../../shared";
5+
import { useBoolean } from "usehooks-ts";
46

57
export interface ScorecardPluginConfig {
68
dashboardItemId: string;
@@ -48,21 +50,66 @@ const deleteMutation = {
4850

4951
export function useManagePluginConfig(dashboardItemId: string) {
5052
const engine = useDataEngine();
53+
const { value: loading, setTrue, setFalse } = useBoolean();
5154
const addConfig = useCallback(
5255
async (config: ScorecardPluginConfig) => {
5356
try {
57+
setTrue();
5458
const mutation = getCreateMutation(dashboardItemId);
5559
//@ts-expect-error app runtime mutation errors
56-
return await engine.mutate(mutation, {
60+
await engine.mutate(mutation, {
5761
variables: {
5862
data: config,
5963
},
6064
});
65+
//Updating sharing settings to match the scorecard's
66+
const sharingConfig = (await engine.query({
67+
scorecardSharing: {
68+
resource: `dataStore/${DATASTORE_NAMESPACE}/${config.scorecardId}/metaData`,
69+
},
70+
dashboardItemMeta: {
71+
resource: `dataStore/${DATASTORE_WIDGET_NAMESPACE}/${dashboardItemId}/metaData`,
72+
},
73+
})) as {
74+
scorecardSharing: {
75+
sharing: {
76+
users: Record<string, unknown>;
77+
userGroups: Record<string, unknown>;
78+
public: string;
79+
};
80+
};
81+
dashboardItemMeta: {
82+
sharing: {
83+
users: Record<string, unknown>;
84+
userGroups: Record<string, unknown>;
85+
public: string;
86+
};
87+
id: string;
88+
};
89+
};
90+
const newSharing = {
91+
...sharingConfig.dashboardItemMeta.sharing,
92+
users: sharingConfig.scorecardSharing.sharing.users,
93+
userGroups:
94+
sharingConfig.scorecardSharing.sharing.userGroups,
95+
public: sharingConfig.scorecardSharing.sharing.public,
96+
};
97+
await engine.mutate({
98+
type: "create",
99+
resource: "sharing",
100+
params: {
101+
id: sharingConfig.dashboardItemMeta.id,
102+
type: "dataStore",
103+
},
104+
data: newSharing,
105+
});
61106
} catch (error) {
62107
console.error(
63108
`Could not save configuration for dashboardItemId ${dashboardItemId}`
64109
);
65110
throw error;
111+
} finally {
112+
setFalse();
66113
}
67114
},
68115
[engine]
@@ -79,6 +126,7 @@ export function useManagePluginConfig(dashboardItemId: string) {
79126

80127
return {
81128
addConfig,
129+
loading,
82130
deleteConfig,
83131
};
84132
}

src/plugin/modules/ScorecardList/components/PluginScorecardList.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export function PluginScorecardList() {
2323
const {
2424
props: { dashboardItemId },
2525
} = usePluginConfig();
26-
const { addConfig } = useManagePluginConfig(dashboardItemId);
26+
const { addConfig, loading: saving } =
27+
useManagePluginConfig(dashboardItemId);
2728
const navigate = useNavigate();
2829
const [selectedScorecard, setSelectedScorecard] = useState<
2930
string | undefined
@@ -87,6 +88,7 @@ export function PluginScorecardList() {
8788
<Menu>
8889
{scorecards.map((scorecard) => (
8990
<MenuItem
91+
key={scorecard.id}
9092
active={isChecked(scorecard.id)}
9193
icon={<IconVisualizationPivotTable24 />}
9294
onClick={() => {
@@ -116,11 +118,12 @@ export function PluginScorecardList() {
116118
</Menu>
117119
</div>
118120
<Button
121+
loading={saving}
119122
onClick={onSelect}
120123
primary
121124
disabled={selectedScorecard === undefined}
122125
>
123-
{i18n.t("Select scorecard")}
126+
{saving ? i18n.t("Saving...") : i18n.t("Select scorecard")}
124127
</Button>
125128
</div>
126129
);

0 commit comments

Comments
 (0)