diff --git a/i18n/en.pot b/i18n/en.pot
index 2dc9dcc..bc65235 100644
--- a/i18n/en.pot
+++ b/i18n/en.pot
@@ -5,27 +5,39 @@ msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
-"POT-Creation-Date: 2024-12-18T09:41:03.249Z\n"
-"PO-Revision-Date: 2024-12-18T09:41:03.250Z\n"
+"POT-Creation-Date: 2024-12-19T16:36:13.574Z\n"
+"PO-Revision-Date: 2024-12-19T16:36:13.575Z\n"
msgid "An error has occurred"
msgstr "An error has occurred"
+msgid "404 Page Not Found"
+msgstr "404 Page Not Found"
+
msgid "Back to datastore"
msgstr "Back to datastore"
-msgid "Back to all namespaces"
-msgstr "Back to all namespaces"
+msgid "An error has occurred. Try again"
+msgstr "An error has occurred. Try again"
-msgid "Search namespaces"
-msgstr "Search namespaces"
+msgid "Cancel"
+msgstr "Cancel"
-msgid "New Namespace"
-msgstr "New Namespace"
+msgid "Add"
+msgstr "Add"
+
+msgid "Key"
+msgstr "Key"
msgid "Namespace"
msgstr "Namespace"
+msgid "Back to all namespaces"
+msgstr "Back to all namespaces"
+
+msgid "Configure Namespaces"
+msgstr "Configure Namespaces"
+
msgid "Close"
msgstr "Close"
@@ -38,8 +50,14 @@ msgstr "Save changes"
msgid "Choose a key to start editing"
msgstr "Choose a key to start editing"
-msgid "Keys"
-msgstr "Keys"
+msgid "DataStore"
+msgstr "DataStore"
+
+msgid "UserDataStore"
+msgstr "UserDataStore"
+
+msgid "keys"
+msgstr "keys"
msgid "New Key"
msgstr "New Key"
@@ -47,14 +65,17 @@ msgstr "New Key"
msgid "Search keys"
msgstr "Search keys"
-msgid "Key"
-msgstr "Key"
+msgid "Add New Key"
+msgstr "Add New Key"
-msgid "DataStore"
-msgstr "DataStore"
+msgid "Search namespaces"
+msgstr "Search namespaces"
-msgid "UserDataStore"
-msgstr "UserDataStore"
+msgid "New Namespace"
+msgstr "New Namespace"
+
+msgid "Add New Namespace"
+msgstr "Add New Namespace"
msgid "Search"
msgstr "Search"
diff --git a/src/components/modals/CreateModal.tsx b/src/components/modals/CreateModal.tsx
new file mode 100644
index 0000000..b0ddb2e
--- /dev/null
+++ b/src/components/modals/CreateModal.tsx
@@ -0,0 +1,61 @@
+import {
+ Modal,
+ ModalTitle,
+ ModalContent,
+ ModalActions,
+ Button,
+ ButtonStrip,
+ ReactFinalForm,
+} from '@dhis2/ui'
+import React from 'react'
+import i18n from '../../locales'
+
+const { Form } = ReactFinalForm
+
+interface FieldValues {
+ key: string
+ namespace?: string
+}
+
+interface CreateModalProps {
+ closeModal: () => void
+ handleCreate: ({ key, namespace }: FieldValues) => void
+ children: React.ReactNode
+ title: string
+}
+
+const CreateModal = ({
+ handleCreate,
+ closeModal,
+ children,
+ title,
+}: CreateModalProps) => {
+ const onSubmit = (values) => {
+ handleCreate(values)
+ }
+
+ return (
+
+
+ )}
+
+
+ )
+}
+
+export default CreateModal
diff --git a/src/components/modals/Fields.tsx b/src/components/modals/Fields.tsx
new file mode 100644
index 0000000..80a8873
--- /dev/null
+++ b/src/components/modals/Fields.tsx
@@ -0,0 +1,41 @@
+import {
+ ReactFinalForm,
+ InputFieldFF,
+ hasValue,
+ composeValidators,
+ alphaNumeric,
+} from '@dhis2/ui'
+import React from 'react'
+import i18n from '../../locales'
+
+const { Field } = ReactFinalForm
+
+export const KeysField = ({ initialFocus }: { initialFocus?: boolean }) => {
+ return (
+
+ )
+}
+
+export const NamespaceField = ({
+ initialFocus,
+}: {
+ initialFocus?: boolean
+}) => {
+ return (
+
+ )
+}
diff --git a/src/components/pages/Namespaces.tsx b/src/components/pages/Namespaces.tsx
index a7494bb..c1ec27d 100644
--- a/src/components/pages/Namespaces.tsx
+++ b/src/components/pages/Namespaces.tsx
@@ -18,11 +18,6 @@ const dataStoreNamespacesQuery = {
},
}
-export type FieldValues = {
- namespace?: string
- key?: string
-}
-
const NamespacesPage = () => {
const navigate = useNavigate()
const { store } = useParams()
diff --git a/src/components/sections/KeysDataSection.tsx b/src/components/sections/KeysDataSection.tsx
index 0de43c6..a05a934 100644
--- a/src/components/sections/KeysDataSection.tsx
+++ b/src/components/sections/KeysDataSection.tsx
@@ -1,12 +1,15 @@
-import { useDataQuery } from '@dhis2/app-runtime'
+import { useDataEngine, useDataQuery } from '@dhis2/app-runtime'
import { IconAdd16, colors } from '@dhis2/ui'
-import React, { useEffect } from 'react'
+import React, { useEffect, useState } from 'react'
import { useParams } from 'react-router-dom'
import classes from '../../App.module.css'
+import useCustomAlert from '../../hooks/useCustomAlert'
import i18n from '../../locales'
import ErrorNotice from '../error/ErrorNotice'
import PanelHeader from '../header/PanelHeader'
import CenteredLoader from '../loader/Loader'
+import CreateModal from '../modals/CreateModal'
+import { KeysField } from '../modals/Fields'
import ItemsTable from '../table/ItemsTable'
import CreateButton from './CreateButton'
import SearchField from './SearchField'
@@ -16,7 +19,12 @@ interface QueryResults {
}
const KeysDataSection = ({ query }) => {
- const { namespace: currentNamespace } = useParams()
+ const engine = useDataEngine()
+ const { store, namespace: currentNamespace } = useParams()
+
+ const [openCreateModal, setOpenCreateModal] = useState(false)
+
+ const { showError, showSuccess } = useCustomAlert()
const { error, loading, data, refetch } = useDataQuery(
query,
@@ -27,6 +35,38 @@ const KeysDataSection = ({ query }) => {
}
)
+ const handleCreate = async ({ key }) => {
+ await engine.mutate(
+ {
+ type: 'create',
+ resource: `${store}/${currentNamespace}/${key}`,
+ data: () => ({}),
+ },
+ {
+ onComplete() {
+ setOpenCreateModal(false)
+ showSuccess(
+ i18n.t("Key '{{key}}' added successfully", {
+ key,
+ })
+ )
+ refetch({ id: currentNamespace })
+ },
+ onError(error) {
+ showError(
+ i18n.t(
+ 'There was a problem adding this key - {{error}}',
+ {
+ error: error.message,
+ interpolation: { escapeValue: false },
+ }
+ )
+ )
+ },
+ }
+ )
+ }
+
useEffect(() => {
refetch({ id: currentNamespace })
}, [currentNamespace])
@@ -47,7 +87,7 @@ const KeysDataSection = ({ query }) => {
console.log('create new key')}
+ handleClick={() => setOpenCreateModal(true)}
icon={}
/>
@@ -57,6 +97,15 @@ const KeysDataSection = ({ query }) => {
{data && }
+ {openCreateModal && (
+ setOpenCreateModal(false)}
+ handleCreate={handleCreate}
+ >
+
+
+ )}
>
)
}
diff --git a/src/components/sections/NamespaceDataSection.tsx b/src/components/sections/NamespaceDataSection.tsx
index 56eed5d..34a6a4d 100644
--- a/src/components/sections/NamespaceDataSection.tsx
+++ b/src/components/sections/NamespaceDataSection.tsx
@@ -1,10 +1,14 @@
-import { useDataQuery } from '@dhis2/app-runtime'
+import { useDataEngine, useDataQuery } from '@dhis2/app-runtime'
import { IconAdd24, colors } from '@dhis2/ui'
-import React from 'react'
+import React, { useState } from 'react'
+import { useNavigate, useParams } from 'react-router-dom'
import classes from '../../App.module.css'
+import useCustomAlert from '../../hooks/useCustomAlert'
import i18n from '../../locales'
import ErrorNotice from '../error/ErrorNotice'
import CenteredLoader from '../loader/Loader'
+import CreateModal from '../modals/CreateModal'
+import { KeysField, NamespaceField } from '../modals/Fields'
import ItemsTable from '../table/ItemsTable'
import CreateButton from './CreateButton'
import SearchField from './SearchField'
@@ -14,7 +18,51 @@ interface QueryResults {
}
const NamespaceDataSection = ({ query }) => {
- const { error, loading, data } = useDataQuery(query)
+ const engine = useDataEngine()
+ const navigate = useNavigate()
+ const { store } = useParams()
+ const [openCreateModal, setOpenCreateModal] = useState(false)
+
+ const { showError, showSuccess } = useCustomAlert()
+
+ const { error, loading, data, refetch } = useDataQuery(query)
+
+ const handleCreate = async (values) => {
+ await engine.mutate(
+ {
+ type: 'create',
+ resource: `${store}/${values?.namespace}/${values?.key}`,
+ data: () => ({}),
+ },
+ {
+ onComplete() {
+ showSuccess(
+ i18n.t(
+ "Namespace '{{namespace}}' and key '{{key}}' added successfully!",
+ {
+ namespace: values.namespace,
+ key: values.key,
+ }
+ )
+ )
+ refetch()
+ navigate(`edit/${values?.namespace}`)
+ setOpenCreateModal(false)
+ },
+ onError(error) {
+ showError(
+ i18n.t(
+ 'There was a problem adding this namespace - {{error}}',
+ {
+ error: error.message,
+ interpolation: { escapeValue: false },
+ }
+ )
+ )
+ },
+ }
+ )
+ }
if (error) {
return
@@ -30,13 +78,23 @@ const NamespaceDataSection = ({ query }) => {
console.log('create new namespace')}
+ handleClick={() => setOpenCreateModal(true)}
icon={}
/>
{data && }
+ {openCreateModal && (
+ setOpenCreateModal(false)}
+ handleCreate={handleCreate}
+ >
+
+
+
+ )}
>
)
}
diff --git a/src/hooks/useCustomAlert.tsx b/src/hooks/useCustomAlert.tsx
new file mode 100644
index 0000000..4b01b94
--- /dev/null
+++ b/src/hooks/useCustomAlert.tsx
@@ -0,0 +1,15 @@
+import { useAlert } from '@dhis2/app-runtime'
+
+const useCustomAlert = () => {
+ const { show } = useAlert(
+ ({ message }) => message,
+ ({ isError }) =>
+ isError ? { critical: true } : { success: true, duration: 3000 }
+ )
+ return {
+ showSuccess: (message) => show({ message }),
+ showError: (message) => show({ message, isError: true }),
+ }
+}
+
+export default useCustomAlert