diff --git a/README.md b/README.md index ab8a87d..b5b8356 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,6 @@ This is the repo that you will use during the Web Academy exercises. Please fork Before participating, make sure you have gone through [the pre-requisites](https://dhis2.github.io/academy-web-app-dev/docs/before-academy/) for the academy. -For more information about the academy and the topics taught, check the website: https://dhis2.github.io/academy-web-app-dev/ \ No newline at end of file +For more information about the academy and the topics taught, check the website: https://dhis2.github.io/academy-web-app-dev/ + +Edited by Matthew Edor diff --git a/i18n/en.pot b/i18n/en.pot new file mode 100644 index 0000000..4050eb5 --- /dev/null +++ b/i18n/en.pot @@ -0,0 +1,52 @@ +msgid "" +msgstr "" +"Project-Id-Version: i18next-conv\n" +"MIME-Version: 1.0\n" +"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-04-17T09:33:24.538Z\n" +"PO-Revision-Date: 2024-04-17T09:33:24.538Z\n" + +msgid "Home" +msgstr "Maison" +msgid "API_VERSION" +msgstr "Exécution sur la version API {{apiVersion}}" +msgid "ATTR_INFO" +msgstr "Attributs visibles par {{name}} ({{email}})" +msgid "YES" +msgstr "Oui" + +msgid "NO" +msgstr "Non" + +msgid "ADD_ATTRIBUTE" +msgstr "Ajouter un attribut" + +msgid "ATTR_TYPE" +msgstr "Type de valeur" + +msgid "ATTR_NAME" +msgstr "Nom d'attribut" + +msgid "ATTR_NAME_SHORT" +msgstr "Nom" + +msgid "ATTR_UNIQUE" +msgstr "Unique" + +msgid "ATTR_TYPE_TEXT" +msgstr "Texte" + +msgid "ATTR_TYPE_NUMBER" +msgstr "Nombre" + +msgid "ATTR_CREATED" +msgstr "Un attribut avec l'ID {{ID}} a été créé" + +msgid "SAVE" +msgstr "Sauvegarder" + +msgid "ATTR_ACTIONS" +msgstr "Actions" + diff --git a/i18n/fr.po b/i18n/fr.po new file mode 100644 index 0000000..4050eb5 --- /dev/null +++ b/i18n/fr.po @@ -0,0 +1,52 @@ +msgid "" +msgstr "" +"Project-Id-Version: i18next-conv\n" +"MIME-Version: 1.0\n" +"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-04-17T09:33:24.538Z\n" +"PO-Revision-Date: 2024-04-17T09:33:24.538Z\n" + +msgid "Home" +msgstr "Maison" +msgid "API_VERSION" +msgstr "Exécution sur la version API {{apiVersion}}" +msgid "ATTR_INFO" +msgstr "Attributs visibles par {{name}} ({{email}})" +msgid "YES" +msgstr "Oui" + +msgid "NO" +msgstr "Non" + +msgid "ADD_ATTRIBUTE" +msgstr "Ajouter un attribut" + +msgid "ATTR_TYPE" +msgstr "Type de valeur" + +msgid "ATTR_NAME" +msgstr "Nom d'attribut" + +msgid "ATTR_NAME_SHORT" +msgstr "Nom" + +msgid "ATTR_UNIQUE" +msgstr "Unique" + +msgid "ATTR_TYPE_TEXT" +msgstr "Texte" + +msgid "ATTR_TYPE_NUMBER" +msgstr "Nombre" + +msgid "ATTR_CREATED" +msgstr "Un attribut avec l'ID {{ID}} a été créé" + +msgid "SAVE" +msgstr "Sauvegarder" + +msgid "ATTR_ACTIONS" +msgstr "Actions" + diff --git a/package.json b/package.json index 0c33cfc..d6cc739 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "private": true, "scripts": { "build": "d2-app-scripts build", - "start": "d2-app-scripts start", + "start": "d2-app-scripts start --proxy https://dev.im.dhis2.org/academy-web --proxyPort 8082", "test": "d2-app-scripts test", "deploy": "d2-app-scripts deploy", "lint": "d2-style check", diff --git a/src/App.js b/src/App.js index be72803..e8be8c0 100644 --- a/src/App.js +++ b/src/App.js @@ -3,6 +3,7 @@ import { HashRouter, Navigate, Route, Routes } from 'react-router-dom' import styles from './App.module.css' import { Navigation } from './navigation/index.js' import { Form, Home, Attributes } from './views/index.js' +import './locales/index.js'; const MyApp = () => ( { // function to navigate to different route @@ -16,8 +16,7 @@ const NavigationItem = ({ path, label }) => { // eslint-disable-next-line no-unused-vars const onClick = () => navigate(path) - // @TODO: Use the `MenuItem` component instead of the `div` - return
{label}
+ return } NavigationItem.propTypes = { @@ -26,8 +25,7 @@ NavigationItem.propTypes = { } export const Navigation = () => ( - // @TODO: Use the `Menu` components instead of the `div` -
+ ( label="Form" path="/form" /> -
+ ) diff --git a/src/views/Attributes.js b/src/views/Attributes.js index 87b6a40..d0bef98 100644 --- a/src/views/Attributes.js +++ b/src/views/Attributes.js @@ -1,24 +1,187 @@ +import { useAlert, useDataMutation, useDataQuery } from '@dhis2/app-runtime' +import i18n from '@dhis2/d2-i18n' +import { + Button, + CenteredContent, + CircularLoader, + DataTable, + DataTableCell, + DataTableColumnHeader, + DataTableRow, + hasValue, + InputFieldFF, + NoticeBox, + ReactFinalForm, + SingleSelectFieldFF, + TableBody, + TableHead, + Pagination +} from '@dhis2/ui' import React from 'react' -import { useGetAttributes } from '../hooks/index.js' +import styles from './Form.module.css' + +const query = { + attributes: { + resource: 'attributes', + params: { + order: 'created:desc', + pageSize: 5, + fields: ['displayName', 'unique', 'id', 'valueType'] + }, + }, + users: { + resource: 'me', + params: { + fields: ['name', 'email'] + } + } +} + +const mutation = { + resource: 'attributes', + type: 'create', + data: ({value}) => value +} + +const deleteMutation = { + resource: 'attributes', + type: 'delete', + id: ({id}) => id +} + +const {Field, Form: RFForm} = ReactFinalForm export const Attributes = () => { + + const [mutate, {loading: saving, error: mutateError, data: response}] = useDataMutation(mutation) + const [delMutation, {loading: deleteLoading}] = useDataMutation(deleteMutation, { + onComplete: () => refetch() + }) + + const {show} = useAlert( + ({message}) => message, + ({type = 'info'}) => + type === 'error' ? {critical: true} : {success: true} + ) + + const deleteAttribute = (id) => { + delMutation({id}) + } + + const saveAttribute = (value) => { + console.log('Response', mutateError, response) + mutate({value}) + let type = 'info'; + let message = i18n.t('ATTR_CREATED', {ID: response?.uid}) + if (mutateError) { + type = 'error'; + message = mutateError + } + + show({message, type}) + refetch() + } // we get the data using a custom hook // we will update this implementation after learning about app-runtime - const { loading, error, data } = useGetAttributes() - + const {loading, error, data, refetch} = useDataQuery(query) + if (loading) { + return + + + } + if (error) { + return {error} + } + const user = data?.users; + const name = user?.name; + const email = user?.email; return (

Attributes

-

loading: {JSON.stringify(loading)}

-

error message: {error?.message}

- { - // if there is any data available - data?.attributes?.attributes && ( -
-                        {JSON.stringify(data.attributes.attributes, null, 4)}
-                    
- ) - } +

{i18n.t('ATTR_INFO', {name, email})}

+ + + + {i18n.t('ATTR_NAME_SHORT')} + + + {i18n.t('ATTR_UNIQUE')} + + + {i18n.t('ATTR_TYPE')} + + + {i18n.t('ATTR_ACTIONS')} + + + {data?.attributes?.attributes && ( + + {data.attributes.attributes.map((attribute) => { + const {id, displayName, unique, valueType} = attribute; + return + {displayName} + {unique ? i18n.t('YES') : i18n.t('NO')} + {valueType} + + + + + })} + + )} + +
+
+

{i18n.t('ADD_ATTRIBUTE')}

+ {saving && ( + + + + )} + + {({handleSubmit}) => ( +
+
+ +
+
+ +
+
+ +
+
+ )} +
) } diff --git a/src/views/Form.js b/src/views/Form.js index 1713331..e23c5a8 100644 --- a/src/views/Form.js +++ b/src/views/Form.js @@ -1,7 +1,20 @@ -import { ReactFinalForm } from '@dhis2/ui' +import { useAlert } from '@dhis2/app-runtime'; +import { + createEqualTo, + composeValidators, + email, + Button, + InputFieldFF, + ReactFinalForm, + SingleSelectFieldFF, + SwitchFieldFF, + hasValue, + dhis2Username +} from '@dhis2/ui' import React from 'react' import styles from './Form.module.css' + /** * This is just a function to demonstrate the values when the form is submitted * It takes the form's values (which is an object), transforms it into readable JSON, @@ -15,31 +28,142 @@ import styles from './Form.module.css' * @param {string} values.email-confirmation * @param {bool} values.newsletter */ -const alertValues = (values) => { - const formattedValuesString = JSON.stringify(values, null, 2) - alert(formattedValuesString) -} -const { Field, Form: RFForm } = ReactFinalForm +const {Field, Form: RFForm} = ReactFinalForm + +export const Form = () => { + const {show} = useAlert( + ({message}) => message, + ({type}) => + type === 'error' ? {critical: true} : {success: true} + ) -export const Form = () => ( -
-

Form

+ const alertValues = (values) => { + const value = JSON.stringify(values, null, 2) + let type = 'info'; + if (values.title === 'Professor') { + type = 'error' + } + show({message: value, type}) + } - - {({ handleSubmit }) => ( -
-
+ return ( +
+

Form

+ + + {({handleSubmit}) => ( + +
+ +
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
-
- - )} - -
-) +
+ +
+ + )} +
+
+ ) +} diff --git a/src/views/Form.module.css b/src/views/Form.module.css index e2b6665..3e36386 100644 --- a/src/views/Form.module.css +++ b/src/views/Form.module.css @@ -22,3 +22,12 @@ .email { flex-grow: 1; } + +.half { + width: 50% !important; +} + +.full { + width: 100% !important; + padding: 2px; +} diff --git a/src/views/Home.js b/src/views/Home.js index 76ef507..970559d 100644 --- a/src/views/Home.js +++ b/src/views/Home.js @@ -1,9 +1,17 @@ +import { useConfig } from '@dhis2/app-runtime'; +import i18n from '@dhis2/d2-i18n' +import { Tag } from '@dhis2/ui' import React from 'react' -export const Home = () => ( -
-

Home

+export const Home = () => { + const {apiVersion} = useConfig(); + return ( +
+

{i18n.t('Home')}

-

DHIS2 Web App Academy 2024

-
-) +

DHIS2 Web App Academy 2024

+ + {i18n.t('API_VERSION', {apiVersion})} +
+ ) +}