diff --git a/.github/workflows/dhis2-deploy-netlify.yml b/.github/workflows/dhis2-deploy-netlify.yml index 14210c991f..9c6f7676a3 100644 --- a/.github/workflows/dhis2-deploy-netlify.yml +++ b/.github/workflows/dhis2-deploy-netlify.yml @@ -13,6 +13,8 @@ on: push: branches: - master + paths: + - '/_redirects' # only rebuild and deploy when redirects file changes concurrency: group: ${{ github.workflow}}-${{ github.ref }} @@ -28,10 +30,12 @@ jobs: with: node-version: 20.x - - uses: c-hive/gha-yarn-cache@v1 - - run: yarn install --frozen-lockfile + # We use Netlify only for deploy previews, production docs are hosted at developers.dhis2.org + # Don't build anything, just copy the _redirects file into the dist directory - - run: yarn build + - run: | + mkdir dist + cp _redirects dist/_redirects - uses: nwtgck/actions-netlify@v1.1 with: diff --git a/_redirects b/_redirects new file mode 100644 index 0000000000..e24ec0dfb4 --- /dev/null +++ b/_redirects @@ -0,0 +1,5 @@ +# Redirect legacy ui.dhis2.nu netlify site to the developer portal +/demo https://developers.dhis2.org/demo +/components/* https://developers.dhis2.org/docs/ui/components/:splat +/recipes/* https://developers.dhis2.org/docs/ui/recipes/:splat +/* https://developers.dhis2.org/design-system/:splat \ No newline at end of file diff --git a/collections/forms/API.md b/collections/forms/API.md index fe9090915c..7a9bdf029d 100644 --- a/collections/forms/API.md +++ b/collections/forms/API.md @@ -69,7 +69,7 @@ import { FileInputFieldFF } from '@dhis2/ui' |showValidStatus|boolean|||| |valid|boolean|||| |validationText|string|||| -|value|arrayOf(instanceOf(File)) │ ''|||| +|value|`arrayOf(instanceOf(File)) │ ''`|||| ### InputFieldFF @@ -118,7 +118,7 @@ import { MultiSelectFieldFF } from '@dhis2/ui' |meta|custom|||`meta` props provided by Final Form `Field`| |error|boolean|||| |loading|boolean|||| -|options|arrayOf({
"label": "string",
"value": "string"
})|`[]`||| +|options|`arrayOf({
"label": "string",
"value": "string"
})`|``[]``||| |showLoadingStatus|boolean|||| |showValidStatus|boolean|||| |valid|boolean|||| @@ -169,7 +169,7 @@ import { SingleSelectFieldFF } from '@dhis2/ui' |---|---|---|---|---| |input|custom|||`input` props received from Final Form `Field`| |meta|custom|||`meta` props received from Final Form `Field`| -|options|arrayOf({
"label": "string",
"value": "string"
})||*|| +|options|`arrayOf({
"label": "string",
"value": "string"
})`||*|| |error|boolean|||| |loading|boolean|||| |showLoadingStatus|boolean|||| diff --git a/collections/forms/i18n/en.pot b/collections/forms/i18n/en.pot index bffb1bd6f0..b373318fc2 100644 --- a/collections/forms/i18n/en.pot +++ b/collections/forms/i18n/en.pot @@ -5,8 +5,8 @@ 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-09-26T14:15:11.940Z\n" -"PO-Revision-Date: 2024-09-26T14:15:11.941Z\n" +"POT-Creation-Date: 2024-11-29T06:54:11.622Z\n" +"PO-Revision-Date: 2024-11-29T06:54:11.622Z\n" msgid "Upload file" msgstr "Upload file" diff --git a/collections/ui/API.md b/collections/ui/API.md index a6dc338e07..a3d40ec4de 100644 --- a/collections/ui/API.md +++ b/collections/ui/API.md @@ -18,10 +18,10 @@ import { AlertBar } from '@dhis2/ui' |children|string|||The message string for the alert| |className|string|||| |critical|custom|||Alert bars with `critical` will not autohide| -|dataTest|string|`'dhis2-uicore-alertbar'`||| -|duration|number|`8000`||How long you want the notification to display, in `ms`, when it's not permanent| +|dataTest|string|``'dhis2-uicore-alertbar'``||| +|duration|number|``8000``||How long you want the notification to display, in `ms`, when it's not permanent| |hidden|boolean|||AlertBar will be hidden on creation when this is set to true| -|icon|custom|`true`||A specific icon to override the default icon in the bar.
If `false` is provided, no icon will be shown.| +|icon|custom|``true``||A specific icon to override the default icon in the bar.
If `false` is provided, no icon will be shown.| |permanent|boolean|||When set, AlertBar will not autohide| |success|custom|||| |warning|custom|||Alert bars with `warning` will not autohide| @@ -45,7 +45,7 @@ import { AlertStack } from '@dhis2/ui' |---|---|---|---|---| |children|node|||| |className|string|||| -|dataTest|string|`'dhis2-uicore-alertstack'`||| +|dataTest|string|``'dhis2-uicore-alertstack'``||| ### Box @@ -65,7 +65,7 @@ import { Box } from '@dhis2/ui' |---|---|---|---|---| |children|node|||| |className|string|||| -|dataTest|string|`'dhis2-uicore-box'`||| +|dataTest|string|``'dhis2-uicore-box'``||| |height|string|||| |marginTop|string|||| |maxHeight|string|||| @@ -93,7 +93,7 @@ import { Button } from '@dhis2/ui' |---|---|---|---|---| |children|node|||Component to render inside the button| |className|string|||A className that will be passed to the ` - - - + + + + + + + + ```jsx
@@ -188,12 +201,10 @@ Buttons are available in different sizes. Use the size that matches the usage gu ### Icon - -
- - -
-
+ ```jsx
@@ -210,9 +221,10 @@ Buttons are available in different sizes. Use the size that matches the usage gu ### State: Disabled - - - + ```jsx @@ -225,9 +237,10 @@ Buttons are available in different sizes. Use the size that matches the usage gu ### State: Loading - - - + ```jsx diff --git a/docs/docs/components/calendar-input.md b/docs/docs/components/calendar-input.md index 9fa231668c..eaf65b1c2d 100644 --- a/docs/docs/components/calendar-input.md +++ b/docs/docs/components/calendar-input.md @@ -4,6 +4,8 @@ title: Calendar Input import { Demo } from '@site/src/components/DemoComponent.jsx' import API from '../../../components/calendar/API.md' +import Tabs from '@theme/Tabs' +import TabItem from '@theme/TabItem' ## Calendar Input diff --git a/docs/docs/components/calendar.md b/docs/docs/components/calendar.md new file mode 100644 index 0000000000..5b1937b98b --- /dev/null +++ b/docs/docs/components/calendar.md @@ -0,0 +1,184 @@ +--- +title: Calendar +--- + +import { Demo } from '@site/src/components/DemoComponent.jsx' +import Tabs from '@theme/Tabs' +import TabItem from '@theme/TabItem' + +import API from '../../../components/calendar/API.md' + +# Calendar + +The Calendar is a component to display a calendar to pick a day in multiple calendar systems, such as: Gregorian, Ethiopic, Nepali and many other calendrical systems. + +The component is built on top of [multi-calendar-dates](https://github.com/dhis2/multi-calendar-dates/tree/beta) which is an internal library to abstract date-related operations (i.e. calendars, period selectors, date math etc..). The library itself relies on the [Temporal proposal](https://tc39.es/proposal-temporal/#sec-temporal-intro). The proposal (currently at Stage 3 draft) aims to improve built-in support for dates and times in browsers, addressing challenges such as support for timezones, DST-safe artithemtic, string serialization and interoperability via standardized formats, and full support for non-Gregorian calendars. + +Here are some sample calendars built with this UI component. Check [StoryBook](pathname:///demo/?path=/story/calendar--with-ethiopic) to play with all the options available for building a Calendar. + +## Ethiopic calendar + +Ethiopic calendar with narrow day names, short day names and localised to English. + +### Narrow day names + + + +To display the calendar with short day names, use the codeblock below. For the narrow day names remove the `weekDayFormat` prop. For the English locale, use the `en` locale and the short `weekDayFormat`. + +```jsx + +``` + +## Nepali calendar + +:::note +Nepali is a custom calendar not natively implemented in Temporal and Nepali locale is not natively supported by browsers' Internationalization standard. We are providing a custom implementation for the calendar, as well as the localised values. The only two locales allowed are: `ne-NP` (nepali) and `en-NP` (nepali transliterated in latin characters). +::: + +Nepali calendar with Napali characters. + + + +```jsx +// Napali + +``` + +Nepali calendar transliterated into latin characters. + + +```jsx +// Nepali transliterated in latin characters + +``` + +## Gregorian calendar + +Gregorian calendar localised in English, Arabic (Tunisia), Arabic (Sudan), Arabic (Iraq) and Amharic. + + + + + + + + + + + + + + + + + + + +To display the calendar with a specific locale, use the codeblock below. Adjust the locale to the desired language. + +```jsx + +``` + +## Other calendars + +Some other calendars: Islamic in Arabic, Indian in English and Persian in Farsi + + + + + + + + + + + + + +Each of the calendars above can be displayed with the following code. + +```jsx + +``` + +:::note +Additionally the component supports a number of other calendars that are not currently used in DHIS2, since they're implemented in the [Temporal API](https://tc39.es/proposal-temporal/)). These other calendars are: `hebrew`, `islamic`, `islamic-umalqura`, `islamic-tbla`, `islamic-civil`, `islamic-rgsa`, `persian`, `ethioaa`, `coptic`, `chinese`, `dangi`, `roc`, `indian`, `buddhist`, `japanese`. +::: + +## Usage + +### When to use + +To display a calendar for the user to pick a day in any supported calendar system, localised to any of the 90+ languages supported by [The Unicode Common Locale Data Repository (CLDR)](https://cldr.unicode.org/index) supported natively in all modern browsers. Supported DHIS2 calendars are: `iso8601` (i.e. the Gregorian calendar common in most of the world),`ethiopic`, `nepali` (custom implementation). + +### When not to use + +- This is just a Day Picker (for now). It does not allow picking periods, date ranges, or date with times. + +## API Reference + + + +## Links + +- [Design document](https://docs.google.com/document/d/19zjyB45oBbqC5KeubaU8E7cw9fGhFc3tOXY0GkzZKqc/edit#) +- [ADR for decision to use Temporal API](https://github.com/dhis2/multi-calendar-dates/blob/beta/doc/architecture/decisions/0002-use-temporal-api-as-the-backbone-for-the-engine.md) +- [multi-calendar-dates](https://github.com/dhis2/multi-calendar-dates) is the library that this component is built on top of. +- [Temporal API standard propsal](https://tc39.es/proposal-temporal/): the standard powering the multi-calendar-dates library diff --git a/docs/docs/components/inputfield.md b/docs/docs/components/inputfield.md index 1b21ca1c65..7204814f41 100644 --- a/docs/docs/components/inputfield.md +++ b/docs/docs/components/inputfield.md @@ -132,12 +132,12 @@ Inputs width should reflect the expected content. ``` - Use a `Textarea` if more than a single sentence of content is expected. -- [`Textarea`](https://ui.dhis2.nu/demo/?path=/story/forms-text-area-text-area-field--no-placeholder-no-value) is available as a standalone component. +- [`Textarea`](pathname:///demo/?path=/story/forms-text-area-text-area-field--no-placeholder-no-value) is available as a standalone component. ### Validation - Validating the type of data entered isn't part of the components themselves. -- Read more about [form handling in DHIS2](../utilities/forms/react-final-form.md). +- Read more about [form handling in DHIS2](/design-system/utilities/forms/react-final-form). ### Read-only @@ -174,7 +174,7 @@ Inputs width should reflect the expected content. - Use an error state if there's a problem with the content of the input, or if it's required but empty. - Don't show an error too early, give the user a chance to finish entering data. -- The error text should help the user fix the problem. Refer to the [error writing guidelines](../principles/content-communication.md) for examples. +- The error text should help the user fix the problem. Refer to the [error writing guidelines](/design-system/principles/content-communication) for examples. ### State: Disabled diff --git a/docs/docs/components/menu.md b/docs/docs/components/menu.md index 3e5411e243..1d26e19586 100644 --- a/docs/docs/components/menu.md +++ b/docs/docs/components/menu.md @@ -32,7 +32,7 @@ A menu gives access to menu items, through a panel that opens from a trigger ele - Menu item labels should be short and easy to understand. - One or two words is often enough to explain the action. -- Refer to the [writing guidelines](../patterns/writing.md) and [glossary](../patterns/glossary.md) for more information about writing useful labels. +- Refer to the [writing guidelines](/design-system/patterns/writing) and [glossary](/design-system/patterns/glossary) for more information about writing useful labels. ##### Order and grouping diff --git a/docs/docs/components/modal.md b/docs/docs/components/modal.md index 041ce0d9d7..5c404f8d7e 100755 --- a/docs/docs/components/modal.md +++ b/docs/docs/components/modal.md @@ -2,7 +2,7 @@ title: Modal --- -import { Demo } from '../../src/components/DemoComponent.jsx' +import { Demo } from '@site/src/components/DemoComponent.jsx' import API from '../../../components/modal/API.md' # Modal diff --git a/docs/docs/components/notice-box.md b/docs/docs/components/notice-box.md index 81633b53d1..cda77868bb 100644 --- a/docs/docs/components/notice-box.md +++ b/docs/docs/components/notice-box.md @@ -111,7 +111,7 @@ A notice box shows important information about a situation. - Notice box titles should be a short summary to help the user scan elements the page. - Notice box text should be clear and informative. Explain what the situation is and, if relevant, offer a solution. -- Check the [writing guidelines](../patterns/writing.md) for more information. +- Check the [writing guidelines](/design-system/patterns/writing) for more information. ## Options diff --git a/docs/docs/components/popover.md b/docs/docs/components/popover.md index 7dec45c7fc..3c32e0ba42 100644 --- a/docs/docs/components/popover.md +++ b/docs/docs/components/popover.md @@ -29,7 +29,7 @@ A popover is used to show more information when a user interacts with a trigger ### Format - A popover doesn't offer any default content styling. -- Include padding between the popover frame and the content inside. The amount of padding depends on the content and density of the interface. Use a [spacer constant](../utilities/constants.md) for a consistent visual experience. +- Include padding between the popover frame and the content inside. The amount of padding depends on the content and density of the interface. Use a [spacer constant](/design-system/utilities/constants) for a consistent visual experience. ## API Reference diff --git a/docs/docs/components/select.md b/docs/docs/components/select.md index fed1bd5b92..6b976a5a42 100644 --- a/docs/docs/components/select.md +++ b/docs/docs/components/select.md @@ -221,7 +221,7 @@ Selects are used to choose one or more items from a list of options. - Use an error state if there's a problem with the chosen option, or if it's required but empty. - Don't show an error too early, give the user a chance to make a choice. -- The error text should help the user fix the problem. Refer to the [error writing guidelines](../principles/content-communication.md) for examples. +- The error text should help the user fix the problem. Refer to the [error writing guidelines](/design-system/principles/content-communication) for examples. ### State: Disabled diff --git a/docs/docs/components/transfer.md b/docs/docs/components/transfer.md index d3648bb982..8383f108fe 100644 --- a/docs/docs/components/transfer.md +++ b/docs/docs/components/transfer.md @@ -150,7 +150,7 @@ The footer component is as follows: - Different types of data will need different loading strategies. - Use a [`Loader`](loading.md) to block interaction if using the transfer while loading is taking place can cause problems. -- A common pattern is loading more options as a user scrolls. See the [Transfer: Infinite Loading recipe](../recipes/transfer-infinite-loading-all-options-selected.md) for more information. +- A common pattern is loading more options as a user scrolls. See the [Transfer: Infinite Loading recipe](/docs/ui/recipes/transfer-infinite-loading-all-options-selected) for more information. ## API Reference diff --git a/docs/docs/help/migrating.md b/docs/docs/help/migrating.md index 4a23d2d5aa..086e384aa5 100644 --- a/docs/docs/help/migrating.md +++ b/docs/docs/help/migrating.md @@ -2,7 +2,7 @@ ## Migrating from < v5 -A number of important changes were introduced in UI version 5.0.0. To see more about these changes and how to migrate from older versions, see [this blog post](https://developers.dhis2.org/blog/ui-5-release) at the developer portal. +A number of important changes were introduced in UI version 5.0.0. To see more about these changes and how to migrate from older versions, see [this blog post](/blog/2020/05/ui-5-release/) at the developer portal. ## Migrating from < v6 diff --git a/docs/docs/principles-index.md b/docs/docs/principles-index.md deleted file mode 100644 index 2b65ddbad4..0000000000 --- a/docs/docs/principles-index.md +++ /dev/null @@ -1,10 +0,0 @@ -# Design Principles - - - -- [Content & Communication](design-system/principles/content-communication) -- [Layout, Spacing, Stacking](design-system/principles/layout) -- [Forms](design-system/principles/forms) -- [Color](design-system/principles/color) -- [Typography](design-system/principles/typography) -- [Icons](design-system/principles/icons) diff --git a/docs/docs/principles/forms.md b/docs/docs/principles/forms.md index 072ec23ba8..ddee20e52a 100644 --- a/docs/docs/principles/forms.md +++ b/docs/docs/principles/forms.md @@ -44,19 +44,19 @@ Provide feedback for users where this is needed. Feedback can be in the form of Forms are made up of different types of inputs. There are various inputs available in the DHIS2 Design System. The documentation for each input covers when it should and should not be used in detail. The table below summarizes the correct usage of each input type. -| Input | Usage | Notes | -| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [Text](../components/inputfield.md) | Enter free text input | There are multiple types of text input that accept different formats. See the input documentation for details. | -| [Single select](../components/select.md) | Select a single option from a list of many | A select should be used when there are more than 5-7 options instead of radio buttons. | -| [Multi select](../components/select.md) | Select multiple options from a list of many | A select should be used when there are more than 5-7 options instead of checkboxes | -| [Checkbox](../components/checkbox.md) | Single: toggle an option between yes/no, true/false, on/off. Multiple: select multiple options from a list of few. | Single checkboxes must never be a required input as there is no neutral state. Do not use a list of checkboxes for many (7+) options, use a multi select instead. | -| [Radio](../components/radio.md) | Select a single option from a list of few | Do not use a list of radio buttons for many (7+) options, use a single select instead. | -| [File input](../components/fileinput.md) | Select a file | Accepted file type and size should be made clear to the user before uploading | -| [Transfer](../components/transfer.md) | Select and order multiple options from a list of many in different categories. | Use for complex selections that require specific ordering and filtering of categories. | +| Input | Usage | Notes | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Text](/docs/ui/components/inputfield) | Enter free text input | There are multiple types of text input that accept different formats. See the input documentation for details. | +| [Single select](/docs/ui/components/select) | Select a single option from a list of many | A select should be used when there are more than 5-7 options instead of radio buttons. | +| [Multi select](/docs/ui/components/select) | Select multiple options from a list of many | A select should be used when there are more than 5-7 options instead of checkboxes | +| [Checkbox](/docs/ui/components/checkbox) | Single: toggle an option between yes/no, true/false, on/off. Multiple: select multiple options from a list of few. | Single checkboxes must never be a required input as there is no neutral state. Do not use a list of checkboxes for many (7+) options, use a multi select instead. | +| [Radio](/docs/ui/components/radio) | Select a single option from a list of few | Do not use a list of radio buttons for many (7+) options, use a single select instead. | +| [File input](/docs/ui/components/fileinput) | Select a file | Accepted file type and size should be made clear to the user before uploading | +| [Transfer](/docs/ui/components/transfer) | Select and order multiple options from a list of many in different categories. | Use for complex selections that require specific ordering and filtering of categories. | ## Form actions -A form should always have a single, clear primary action. Often this action is 'Submit' or 'Save data'. Make sure the user understands what will happen when they submit a form. Additional options, like 'Save and add another', can be offered, but only a single primary action should be included. Make sure the action button label accurately describes the action. See the [content and communication section](../principles/content-communication.md) for more information of writing effective button labels. +A form should always have a single, clear primary action. Often this action is 'Submit' or 'Save data'. Make sure the user understands what will happen when they submit a form. Additional options, like 'Save and add another', can be offered, but only a single primary action should be included. Make sure the action button label accurately describes the action. See the [content and communication section](/design-system/principles/content-communication) for more information of writing effective button labels. ![example of clear form actions](/images/forms/actions.png) diff --git a/docs/docs/principles/icons.md b/docs/docs/principles/icons.md index ee74540c1b..a1a9660fee 100644 --- a/docs/docs/principles/icons.md +++ b/docs/docs/principles/icons.md @@ -3,15 +3,13 @@ title: Icons --- import { Demo } from '@site/src/components/DemoComponent.jsx' -import {Box } from '@dhis2/ui' # Icons - - -

Storybook demo: List of all icons.

-
-
+ Icons are used to help communicate information to users. Icons can provide supporting information and help users to recognize common ideas, concepts and actions. Icons are visual cues and should not be used alone, they are supporting elements. diff --git a/docs/docs/principles/layout.md b/docs/docs/principles/layout.md index 4eaa9596f7..609e05ebe9 100644 --- a/docs/docs/principles/layout.md +++ b/docs/docs/principles/layout.md @@ -128,12 +128,12 @@ The DHIS2 design system defines fives stack layers: ![example of stacking layers](/images/stacking.png) -| Layer | Description | -| ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Base Application Layer (0–1999) | Contains all components, controls and data for the main application. The application can define its own layering from 0 to 1999. | -| Application Top Layer (2000) | Protected components that always layer over the top of the base application layer. This layer is reserved for controls such as dropdowns and popovers that functionally must always display above the application content. | -| Blocking Layer (3000) | Blocks the application and its controls. Only use for actions that are intentionally interrupting. This layer contains a screen cover that blocks the layers beneath. Child elements, such as [modals](../components/modal.md) or loaders, can be added to this layer. | -| Reserved (4000–9998) | Reserved for future development. | -| Alert Layer (9999) | The top layer is reserved for displaying [alert bars](../components/alertbar.md). Alert bars can contain critical information and so must always be displayed above all other content. | +| Layer | Description | +| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Base Application Layer (0–1999) | Contains all components, controls and data for the main application. The application can define its own layering from 0 to 1999. | +| Application Top Layer (2000) | Protected components that always layer over the top of the base application layer. This layer is reserved for controls such as dropdowns and popovers that functionally must always display above the application content. | +| Blocking Layer (3000) | Blocks the application and its controls. Only use for actions that are intentionally interrupting. This layer contains a screen cover that blocks the layers beneath. Child elements, such as [modals](/docs/ui/components/modal) or loaders, can be added to this layer. | +| Reserved (4000–9998) | Reserved for future development. | +| Alert Layer (9999) | The top layer is reserved for displaying [alert bars](/docs/ui/components/alertbar). Alert bars can contain critical information and so must always be displayed above all other content. | Note: the stacking system is not a technical implementation of `z-index` values. See the DHIS2 ui library for implementation details. diff --git a/docs/docs/recipes/assets/ui-table.png b/docs/docs/recipes/assets/ui-table.png new file mode 100644 index 0000000000..aa52f7cd87 Binary files /dev/null and b/docs/docs/recipes/assets/ui-table.png differ diff --git a/docs/docs/recipes/recipes.md b/docs/docs/recipes/recipes.md deleted file mode 100644 index 691cc91381..0000000000 --- a/docs/docs/recipes/recipes.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Overview ---- - -# Recipes - -Recipes in this section are guides for composing components from the UI library to achieve a desired result that may be too specific to create a dedicated component for it in the UI library. - -- [**Transfer: Infinite loading - All loaded options are already selected**](recipes/transfer-infinite-loading-all-options-selected) diff --git a/docs/docs/recipes/transfer-infinite-loading-all-options-selected.jsx b/docs/docs/recipes/transfer-infinite-loading-all-options-selected.jsx deleted file mode 100644 index b29e1f3084..0000000000 --- a/docs/docs/recipes/transfer-infinite-loading-all-options-selected.jsx +++ /dev/null @@ -1,96 +0,0 @@ -import { Transfer } from '@dhis2/ui' -import React, { useState, useEffect } from 'react' - -const optionsPool = [ - { value: '0', label: 'Option 0' }, - { value: '1', label: 'Option 1' }, - { value: '2', label: 'Option 2' }, - { value: '3', label: 'Option 3' }, - { value: '4', label: 'Option 4' }, - { value: '5', label: 'Option 5' }, - { value: '6', label: 'Option 6' }, - { value: '7', label: 'Option 7' }, - { value: '8', label: 'Option 8' }, - { value: '9', label: 'Option 9' }, - { value: '10', label: 'Option 10' }, - { value: '11', label: 'Option 11' }, - { value: '12', label: 'Option 12' }, -] - -const pageSize = 5 - -/* - * The page size is: 5 - * To keep the code as small as possible, handling selecting items is not - included - */ -export const InfiniteLoading = () => { - // state for whether the next page's options are being loaded - const [loading, setLoading] = useState(false) - // captures the current page - const [page, setPage] = useState(0) - // all options (incl. available AND selected options) - const [options, setOptions] = useState([]) - // selected options - const [selected] = useState( - // second page is already selected - optionsPool.slice(pageSize, pageSize * 2).map(({ value }) => value) - ) - - const onEndReached = () => { - // do nothing when loading already - if (loading) { - return - } - setPage(page + 1) - } - - // fake fetch request - const fetchOptions = (nextPage) => - new Promise((resolve) => - setTimeout(() => { - const nextOptions = optionsPool.slice( - options.length, - nextPage * pageSize - ) - resolve(nextOptions) - }, 2000) - ) - - const loadNextOptions = async () => { - setLoading(true) - - const nextOptions = await fetchOptions(page) - setOptions([...options, ...nextOptions]) - - setLoading(false) - - const allAlreadySelected = - nextOptions.length !== 0 && - nextOptions.every((nextOption) => { - const { value } = nextOption - return selected.includes(value) - }) - - if (allAlreadySelected) { - onEndReached() - } - } - - useEffect(() => { - // prevent initial call - if (page > 0) { - loadNextOptions() - } - }, [page]) - - return ( - null /* noop */} - onEndReached={onEndReached} - /> - ) -} diff --git a/docs/docs/recipes/transfer-infinite-loading-all-options-selected.md b/docs/docs/recipes/transfer-infinite-loading-all-options-selected.md index be1eb654c2..5450ff6342 100644 --- a/docs/docs/recipes/transfer-infinite-loading-all-options-selected.md +++ b/docs/docs/recipes/transfer-infinite-loading-all-options-selected.md @@ -2,7 +2,7 @@ title: Transfer – infinite loading --- -import { InfiniteLoading } from './transfer-infinite-loading-all-options-selected.jsx' +import { Demo } from '@site/src/components/DemoComponent.jsx' # Transfer: Infinite loading - All loaded options are already selected @@ -366,6 +366,11 @@ export const InfiniteLoading = () => { } ``` +### Demo + This is how it looks: - + diff --git a/docs/docs/recipes/ui-table.md b/docs/docs/recipes/ui-table.md new file mode 100644 index 0000000000..88ce75de7f --- /dev/null +++ b/docs/docs/recipes/ui-table.md @@ -0,0 +1,109 @@ +--- +id: ui-table +title: How to add a Table component +--- + +Follow this quick guide to add a `Table` component to your application using the [DHIS2 UI Library](/design-system). + +## Prerequisites + +This guide assumes that you're developing an application using the [DHIS2 Application Platform](/docs/app-platform/getting-started) and its tools. To know more or get started, please follow this tutorial: [Environment Setup](/docs/tutorials/setup-env). + +## 1. Import `Table` + +First, let's import the [Table](pathname:///demo/?path=/docs/table--static-layout) component as well as its child components: + +```js +import { + Table, + TableBody, + TableCell, + TableCellHead, + TableHead, + TableRow, + TableRowHead, +} from '@dhis2/ui' +``` + +## 2. Use components + +In this example, we are using the [DHIS2 App Runtime](/docs/app-runtime/hooks/useDataQuery) to fetch and display the `programs` resource from the DHIS2 Web API (as you can see in the `query` object defined in the `src/App.js` file below). + +See the highlighted lines of code - this is how we can represent the programs data in a `Table` component: + +```jsx {43-60} title="src/App.js" +import { useDataQuery } from '@dhis2/app-runtime' +import React from 'react' +import classes from './App.module.css' +import { + Table, + TableBody, + TableCell, + TableCellHead, + TableHead, + TableRow, + TableRowHead, +} from '@dhis2/ui' + +const query = { + results: { + resource: 'programs', + params: { + pageSize: 5, + fields: ['id', 'created', 'displayName'], + }, + }, +} + +const MyApp = () => { + const { loading, error, data } = useDataQuery(query) + + if (error) { + return ERROR: {error.message} + } + + if (loading) { + return Loading... + } + + return ( +
+
+

Programs Table

+ + + + Name + Created + + + + {data.results.programs.map( + ({ id, created, displayName }) => ( + + {displayName} + {created} + + ) + )} + +
+
+
+ ) +} + +export default MyApp +``` + +## 3. Check your browser + +In your browser, you should be able to see the following `Table` 👇 + +![](./assets/ui-table.png) + +### More examples? + +Please check the [UI Library documentation](pathname:///demo/?path=/docs//table--static-layout) for more examples and a list of demos as well as **code snippets** that let you easily copy and paste into your application! 👌🏽 + +--- diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index f85bc00232..e6869ff3a2 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -11,7 +11,7 @@ const config = { tagline: 'React Components for DHIS2 Web Applications', url: 'https://ui.dhis2.nu', baseUrl: '/', - onBrokenLinks: 'throw', + onBrokenLinks: 'warn', onBrokenMarkdownLinks: 'warn', favicon: 'img/favicon.ico', organizationName: 'dhis2', // Usually your GitHub org/user name. diff --git a/docs/sidebars.js b/docs/sidebars.js index 13f2e954c7..24e799a7bb 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -82,10 +82,7 @@ const sidebars = { ], }, { - Recipes: [ - 'recipes/recipes', - 'recipes/transfer-infinite-loading-all-options-selected', - ], + Recipes: ['recipes/transfer-infinite-loading-all-options-selected'], }, { Help: [ diff --git a/scripts/generate-api-docs.js b/scripts/generate-api-docs.js index 7b340caa4c..ad78810712 100755 --- a/scripts/generate-api-docs.js +++ b/scripts/generate-api-docs.js @@ -116,7 +116,11 @@ import { ${toDisplayName} } from '@dhis2/ui' description, type, } of props) { - table += `|${name}|${type}|${defaultValue}|${required}|${description}|\n` + table += `|${name}|${ + type.includes('arrayOf') ? `\`${type}\`` : type + }|${ + defaultValue ? `\`${defaultValue}\`` : '' + }|${required}|${description}|\n` } }