From ba6719a9eefe0a98444f1631f0ac4c1c40d86557 Mon Sep 17 00:00:00 2001 From: eirikhaugstulen Date: Thu, 7 Dec 2023 12:41:43 +0100 Subject: [PATCH] refactor: [TECH-1541] Replace Material UI Dialog (#3460) --- cypress/e2e/SearchPage/index.js | 1 - .../WidgetsForEventSchedule.feature | 4 +- .../WidgetsForEventSchedule/index.js | 2 +- .../EventWorkingListsUser/index.js | 4 +- .../TeiWorkingListsUser.feature | 22 +++--- .../TeiWorkingListsUser/index.js | 47 +++++++----- .../ExistingTEIContents.component.js | 17 ++--- .../ExistingTEIDialog.component.js | 14 ++-- .../DataEntry/withAskToCreateNew.js | 76 ++++++++++--------- .../ErrorAndWarningDialog.component.js | 22 ++---- .../ErrorDialog.component.js | 24 +++--- .../WarningDialog.component.js | 22 ++---- .../withSaveHandler/withSaveHandler.js | 57 +++++++------- .../Dialogs/DiscardDialog.component.js | 48 +++++++----- .../FeedbackBar/FeedbackBar.component.js | 42 +++++----- .../CoordinateField.component.js | 12 +-- .../PolygonField/PolygonField.component.js | 9 ++- .../ColumnSelectorDialog.component.js | 28 ++++--- .../DialogLoadingMask.component.js | 14 ++-- .../PossibleDuplicatesDialog.component.js | 32 +++----- .../ReviewDialogContents.component.js | 11 ++- .../DataEntry/withDeleteButton.js | 61 ++++++++------- .../DownloadDialog.component.js | 26 ++++--- .../DeleteConfirmationDialog.component.js | 27 +++---- .../ExistingTemplateContents.component.js | 11 ++- .../ExistingTemplateDialog.component.js | 15 ++-- .../NewTemplateContents.component.js | 13 ++-- .../NewTemplateDialog.component.js | 15 ++-- .../SharingDialog.component.js | 3 +- .../TemplateMaintenance.component.js | 1 + .../sharingDialog.types.js | 1 + .../CoordinateField.component.js | 23 ++++-- .../coordinateField.module.css | 8 +- .../PolygonField/PolygonField.component.js | 37 +++++++-- .../PolygonField/polygonField.module.css | 5 +- 35 files changed, 400 insertions(+), 354 deletions(-) diff --git a/cypress/e2e/SearchPage/index.js b/cypress/e2e/SearchPage/index.js index b322ef00bc..644ff73111 100644 --- a/cypress/e2e/SearchPage/index.js +++ b/cypress/e2e/SearchPage/index.js @@ -81,7 +81,6 @@ When('you can close the modal', () => { .contains('Back to search') .click(); cy.get('[data-test="dhis2-uicore-modal"]') - .contains('No results found') .should('not.exist'); }); diff --git a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEventSchedule.feature b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEventSchedule.feature index 277fcb0191..6f021d0886 100644 --- a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEventSchedule.feature +++ b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEventSchedule.feature @@ -1,8 +1,10 @@ Feature: The user interacts with the widgets Schedule tab + # Blocked by DHIS2-16229 + @skip Scenario: User cancel after choose a schedule date in schedule tab Given you land on the enrollment add event page by having typed #/enrollmentEventNew?programId=IpHINAT79UW&orgUnitId=DiszpKrYNg8&teiId=EaOyKGOIGRp&enrollmentId=wBU0RAsYjKE&stageId=A03MvHHogjR&tab=SCHEDULE Then you should see Schedule tab Then you choose a schedule date When you click cancel in Schedule tab - Then you should see confirm dialog \ No newline at end of file + Then you should see confirm dialog diff --git a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEventSchedule/index.js b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEventSchedule/index.js index 1b606aa3c0..3896685c41 100644 --- a/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEventSchedule/index.js +++ b/cypress/e2e/WidgetsForEnrollmentPages/WidgetsForEventSchedule/index.js @@ -18,7 +18,7 @@ When('you click cancel in Schedule tab', () => { }); Then('you should see confirm dialog', () => { - cy.get('[role="dialog"]') + cy.get('aside[role="dialog"]') .find('[data-test="dhis2-uicore-modaltitle"]') .contains('Discard unsaved changes?') .should('exist'); diff --git a/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsUser/index.js b/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsUser/index.js index d16c2a84d7..79dd1acad6 100644 --- a/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsUser/index.js +++ b/cypress/e2e/WorkingLists/EventWorkingLists/EventWorkingListsUser/index.js @@ -148,12 +148,12 @@ When('you open the column selector', () => { }); When('you select Household location and save from the column selector', () => { - cy.get('div[role="dialog"]') + cy.get('aside[role="dialog"]') .contains('Household location') .find('input') .click(); - cy.get('div[role="dialog"]') + cy.get('aside[role="dialog"]') .contains('Save') .click(); }); diff --git a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser.feature b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser.feature index b0bdfef1e0..73b30f7668 100644 --- a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser.feature +++ b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser.feature @@ -1,5 +1,13 @@ Feature: User interacts with tei working lists + Scenario: The TEI custom working can be shared + Given you open the main page with Ngelehun and Malaria focus investigation context + And you see the custom TEI working lists + And you can load the view with the name Events assigned to me + And you create a copy of the working list + When you change the sharing settings + Then you see the new sharing settings + Scenario: User opens the default working list for a tracker program Given you open the main page with Ngelehun and child programme context Then the default working list should be displayed @@ -81,7 +89,7 @@ When you change rows per page to 10 Then the list should display 10 rows of data And for a tracker program the page navigation should show that you are on the first page -Scenario: Show teis ordered ascendingly by first name +Scenario: Show teis ordered ascendingly by first name Given you open the main page with Ngelehun and child programme context When you click the first name column header Then the sort arrow should indicate ascending order @@ -93,13 +101,7 @@ Given you open the main page with Ngelehun and Malaria focus investigation conte Then you see the custom TEI working lists And you can load the view with the name Events assigned to me -Scenario: The TEI custom working can be shared -Given you open the main page with Ngelehun and Malaria focus investigation context -And you see the custom TEI working lists -And you can load the view with the name Events assigned to me -And you create a copy of the working list -When you change the sharing settings -Then you see the new sharing settings + Scenario: The user creates, updates and deletes a TEI custom working list Given you open the main page with Ngelehun and Malaria case diagnosis context @@ -139,7 +141,7 @@ And you select a data element columns and save from the column selector Then you see data elements specific filters and columns @v>=39 -Scenario: While in a program stage working list, the user can filter by both TEA and data elements +Scenario: While in a program stage working list, the user can filter by both TEA and data elements Given you open the main page with Ngelehun, WHO RMNCH Tracker and First antenatal care visit context When you set the enrollment status filter to active And you apply the current filter @@ -152,7 +154,7 @@ And you apply the current filter Then the list should display 1 row of data @v>=39 -Scenario: While in a program stage working list, the user can sort by both TEA and data elements +Scenario: While in a program stage working list, the user can sort by both TEA and data elements Given you open the main page with Ngelehun, WHO RMNCH Tracker and First antenatal care visit context And you set the first name filter to u And you apply the current filter diff --git a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/index.js b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/index.js index 1c1574e25d..c6adb4c683 100644 --- a/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/index.js +++ b/cypress/e2e/WorkingLists/TeiWorkingLists/TeiWorkingListsUser/index.js @@ -246,12 +246,12 @@ When('you open the column selector', () => { }); When('you select the registering unit and save from the column selector', () => { - cy.get('div[role="dialog"]') + cy.get('aside[role="dialog"]') .contains('Registering unit') .find('input') .click(); - cy.get('div[role="dialog"]') + cy.get('aside[role="dialog"]') .contains('Save') .click(); }); @@ -544,27 +544,32 @@ Then('you see the new sharing settings', () => { .click(); }); -When('you create a copy of the working list', () => { - cy.get('[data-test="list-view-menu-button"]') - .click(); +When('you create a copy of the working list', + () => { + cy.get('[data-test="list-view-menu-button"]') + .click(); - cy.contains('Save current view as') - .click(); + cy.contains('Save current view as') + .click(); - const id = uuid(); - cy.get('[data-test="view-name-content"]') - .type(id); + const id = uuid(); + cy.get('[data-test="view-name-content"]') + .type(id); - cy.intercept('POST', '**/trackedEntityInstanceFilters**').as('newTrackerFilter'); + cy.intercept('POST', '**/trackedEntityInstanceFilters**') + .as('newTrackerFilter'); - cy.get('button') - .contains('Save') - .click(); + cy.get('[data-test="new-template-dialog"]') + .within(() => { + cy.get('[data-test="dhis2-uicore-button"]') + .contains('Save') + .click(); + }); - cy.wait('@newTrackerFilter', { timeout: 30000 }); + cy.wait('@newTrackerFilter', { timeout: 30000 }); - cy.reload(); -}); + cy.reload(); + }); When('you open the program stage filters from the more filters dropdown menu', () => { cy.get('[data-test="tei-working-lists"]') @@ -602,12 +607,12 @@ When('you select the Foci response program stage', () => { }); When('you select a data element columns and save from the column selector', () => { - cy.get('div[role="dialog"]') + cy.get('aside[role="dialog"]') .contains('People included') .find('input') .click(); - cy.get('div[role="dialog"]') + cy.get('aside[role="dialog"]') .contains('Save') .click(); }); @@ -663,12 +668,12 @@ Then('you see scheduledAt filter', () => { }); When('you select a scheduledAt column and save from the column selector', () => { - cy.get('div[role="dialog"]') + cy.get('aside[role="dialog"]') .contains('Appointment date') .find('input') .click(); - cy.get('div[role="dialog"]') + cy.get('aside[role="dialog"]') .contains('Save') .click(); }); diff --git a/src/core_modules/capture-core/components/DataEntries/withErrorMessagePostProcessor/UniqueTEADuplicate/ExistingTEIContents.component.js b/src/core_modules/capture-core/components/DataEntries/withErrorMessagePostProcessor/UniqueTEADuplicate/ExistingTEIContents.component.js index 8d919e73e2..7bfed86fa6 100644 --- a/src/core_modules/capture-core/components/DataEntries/withErrorMessagePostProcessor/UniqueTEADuplicate/ExistingTEIContents.component.js +++ b/src/core_modules/capture-core/components/DataEntries/withErrorMessagePostProcessor/UniqueTEADuplicate/ExistingTEIContents.component.js @@ -2,10 +2,7 @@ import React, { type ComponentType } from 'react'; import { withStyles } from '@material-ui/core/styles'; import i18n from '@dhis2/d2-i18n'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogTitle from '@material-ui/core/DialogTitle'; -import DialogActions from '@material-ui/core/DialogActions'; -import { Button } from '@dhis2/ui'; +import { Button, ModalContent, ModalTitle, ModalActions } from '@dhis2/ui'; import { CardList } from '../../../CardList'; import type { Props } from './existingTeiContents.types'; @@ -35,18 +32,18 @@ const ExistingTEIContentsComponentPlain = ({ return ( - - + + {i18n.t('Registered person')} - + - - + + - - - - - ) + renderAskToCreateNewModal = () => { + if (!this.state.isOpen) { + return null; + } + + return ( + + + {i18n.t('Generate new event')} + + + {i18n.t('Do you want to create another event?')} + + + + + + + + + ); + } render() { const { onSave, ...passOnProps } = this.props; diff --git a/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/ErrorAndWarningDialog.component.js b/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/ErrorAndWarningDialog.component.js index 203faee0b5..0b92900d0b 100644 --- a/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/ErrorAndWarningDialog.component.js +++ b/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/ErrorAndWarningDialog.component.js @@ -1,12 +1,8 @@ // @flow import * as React from 'react'; import { withStyles } from '@material-ui/core'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogContentText from '@material-ui/core/DialogContentText'; -import DialogTitle from '@material-ui/core/DialogTitle'; import i18n from '@dhis2/d2-i18n'; -import { Button } from '@dhis2/ui'; +import { Button, ModalTitle, ModalContent, ModalActions } from '@dhis2/ui'; const getStyles = (theme: Theme) => ({ errors: { @@ -134,17 +130,15 @@ class ErrorAndWarningDialogPlain extends React.Component { render() { return ( - + {i18n.t('Validation errors and warnings')} - - - - {this.getContents()} - - - + + + {this.getContents()} + + {this.getButtons()} - + ); } diff --git a/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/ErrorDialog.component.js b/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/ErrorDialog.component.js index 8d17307161..25d60ad5f2 100644 --- a/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/ErrorDialog.component.js +++ b/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/ErrorDialog.component.js @@ -1,11 +1,7 @@ // @flow import * as React from 'react'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogContentText from '@material-ui/core/DialogContentText'; -import DialogTitle from '@material-ui/core/DialogTitle'; import i18n from '@dhis2/d2-i18n'; -import { Button } from '@dhis2/ui'; +import { Button, ModalTitle, ModalContent, ModalActions } from '@dhis2/ui'; import { withStyles } from '@material-ui/core'; type Props = { @@ -52,7 +48,7 @@ class ErrorDialogPlain extends React.Component { const { onAbort, onSave, saveEnabled, classes } = this.props; return ( -
+
@@ -73,17 +69,15 @@ class ErrorDialogPlain extends React.Component { render() { return ( - + {i18n.t('Validation errors')} - - - - {this.getContents()} - - - + + + {this.getContents()} + + {this.getButtons()} - + ); } diff --git a/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/WarningDialog.component.js b/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/WarningDialog.component.js index 4510553cca..ff95f00ee1 100644 --- a/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/WarningDialog.component.js +++ b/src/core_modules/capture-core/components/DataEntry/withSaveHandler/MessagesDialogContents/WarningDialog.component.js @@ -1,11 +1,7 @@ // @flow import * as React from 'react'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogContentText from '@material-ui/core/DialogContentText'; -import DialogTitle from '@material-ui/core/DialogTitle'; import i18n from '@dhis2/d2-i18n'; -import { Button } from '@dhis2/ui'; +import { Button, ModalTitle, ModalContent, ModalActions } from '@dhis2/ui'; import { withStyles } from '@material-ui/core'; type Props = { @@ -51,15 +47,13 @@ class WarningDialogPlain extends React.Component { const { onAbort, onSave, classes } = this.props; return ( - + {i18n.t('Validation warnings')} - - - - {this.getContents()} - - - + + + {this.getContents()} + +
-
+
); } diff --git a/src/core_modules/capture-core/components/DataEntry/withSaveHandler/withSaveHandler.js b/src/core_modules/capture-core/components/DataEntry/withSaveHandler/withSaveHandler.js index d8e90bfc3c..a58549fd2b 100644 --- a/src/core_modules/capture-core/components/DataEntry/withSaveHandler/withSaveHandler.js +++ b/src/core_modules/capture-core/components/DataEntry/withSaveHandler/withSaveHandler.js @@ -1,10 +1,7 @@ // @flow import * as React from 'react'; import log from 'loglevel'; -import Dialog from '@material-ui/core/Dialog'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogContentText from '@material-ui/core/DialogContentText'; -import DialogTitle from '@material-ui/core/DialogTitle'; +import { Modal, ModalContent, ModalTitle } from '@dhis2/ui'; import { connect } from 'react-redux'; import i18n from '@dhis2/d2-i18n'; import { errorCreator } from 'capture-core-utils'; @@ -248,32 +245,34 @@ const getSaveHandler = ( onSave={this.handleSaveAttempt} {...filteredProps} /> - - - - - - {i18n.t('Operations running')} - - - + {this.state.messagesDialogOpen && ( + + + + )} + {this.state.waitForPromisesDialogOpen && ( + + + {i18n.t('Operations running')} + + {this.getDialogWaitForUploadContents()} - - - + + + )}
); } diff --git a/src/core_modules/capture-core/components/Dialogs/DiscardDialog.component.js b/src/core_modules/capture-core/components/Dialogs/DiscardDialog.component.js index 257852c7d8..926637ec0a 100644 --- a/src/core_modules/capture-core/components/Dialogs/DiscardDialog.component.js +++ b/src/core_modules/capture-core/components/Dialogs/DiscardDialog.component.js @@ -5,24 +5,32 @@ import type { Props } from './discardDialog.types'; export const DiscardDialog = ({ open, header, text, cancelText, onCancel, destructiveText, onDestroy, -}: Props) => ( - - - {header} - - - {text} - - - - - - - - -); +}: Props) => { + if (!open) { + return null; + } + + return ( + + + {header} + + +
+ {text} +
+
+ + + + + + +
+ ); +}; diff --git a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.js b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.js index c6b1fe0a49..f4406742cc 100644 --- a/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.js +++ b/src/core_modules/capture-core/components/FeedbackBar/FeedbackBar.component.js @@ -1,13 +1,9 @@ // @flow import * as React from 'react'; import SnackBar from '@material-ui/core/Snackbar'; -import Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogTitle from '@material-ui/core/DialogTitle'; import { withStyles } from '@material-ui/core/styles'; import { IconButton } from 'capture-ui'; -import { IconCross24, Button } from '@dhis2/ui'; +import { IconCross24, Button, Modal, ModalTitle, ModalContent, ModalActions } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; import isDefined from 'd2-utilizr/lib/isDefined'; @@ -100,25 +96,27 @@ class Index extends React.Component { message={{message}} action={this.getAction()} /> - - - { + {isDialogOpen && ( + + + { // $FlowFixMe[prop-missing] automated comment - isDialogOpen ? message && message.title : ''} - - - { + isDialogOpen ? message && message.title : ''} + + + { // $FlowFixMe[prop-missing] automated comment - isDialogOpen ? message && message.content : ''} - - - - - + isDialogOpen ? message && message.content : ''} + + + + + + )} ); } diff --git a/src/core_modules/capture-core/components/FormFields/New/Fields/CoordinateField/CoordinateField.component.js b/src/core_modules/capture-core/components/FormFields/New/Fields/CoordinateField/CoordinateField.component.js index 9ac8d6931c..992b6b069d 100644 --- a/src/core_modules/capture-core/components/FormFields/New/Fields/CoordinateField/CoordinateField.component.js +++ b/src/core_modules/capture-core/components/FormFields/New/Fields/CoordinateField/CoordinateField.component.js @@ -2,8 +2,7 @@ import * as React from 'react'; import withStyles from '@material-ui/core/styles/withStyles'; import { CoordinateField as UICoordinateField } from 'capture-ui'; -import Dialog from '@material-ui/core/Dialog'; -import DialogTitle from '@material-ui/core/DialogTitle'; +import { Modal, ModalTitle } from '@dhis2/ui'; import { typeof orientations } from '../../../New'; const getStyles = (theme: Theme) => ({ @@ -80,11 +79,12 @@ class CoordinateFieldPlain extends React.Component { // $FlowFixMe[cannot-spread-inexact] automated comment - {dialogLabel} - + {dialogLabel} + } {...passOnProps} classes={this.passOnClasses} diff --git a/src/core_modules/capture-core/components/FormFields/New/Fields/PolygonField/PolygonField.component.js b/src/core_modules/capture-core/components/FormFields/New/Fields/PolygonField/PolygonField.component.js index 058d82c9c9..47831a9a47 100644 --- a/src/core_modules/capture-core/components/FormFields/New/Fields/PolygonField/PolygonField.component.js +++ b/src/core_modules/capture-core/components/FormFields/New/Fields/PolygonField/PolygonField.component.js @@ -2,7 +2,7 @@ import * as React from 'react'; import withStyles from '@material-ui/core/styles/withStyles'; import { PolygonField as UIPolygonField } from 'capture-ui'; -import { Dialog, DialogTitle } from '@material-ui/core'; +import { Modal, ModalTitle } from '@dhis2/ui'; import { typeof orientations } from '../../../New'; const getStyles = () => ({ @@ -44,11 +44,12 @@ class PolygonFieldPlain extends React.Component { // $FlowFixMe[cannot-spread-inexact] automated comment - {dialogLabel} - + {dialogLabel} + } {...passOnProps} /> diff --git a/src/core_modules/capture-core/components/ListView/ColumnSelector/ColumnSelectorDialog.component.js b/src/core_modules/capture-core/components/ListView/ColumnSelector/ColumnSelectorDialog.component.js index 6cbe5aa034..ff0bad9c19 100644 --- a/src/core_modules/capture-core/components/ListView/ColumnSelector/ColumnSelectorDialog.component.js +++ b/src/core_modules/capture-core/components/ListView/ColumnSelector/ColumnSelectorDialog.component.js @@ -1,11 +1,7 @@ // @flow import React, { useState, useEffect } from 'react'; import { isEqual } from 'lodash'; -import { Button } from '@dhis2/ui'; -import Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogTitle from '@material-ui/core/DialogTitle'; +import { Modal, ModalTitle, ModalContent, ModalActions, Button } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; import { DragDropList } from './DragDropList'; @@ -40,23 +36,31 @@ export const ColumnSelectorDialog = ({ columns, open, onClose, onSave }: Props) setColumnList(sortedList); }; + if (!open) { + return null; + } + return ( - - {i18n.t('Columns to show in table')} - + + {i18n.t('Columns to show in table')} + - - + + - - + + ); }; diff --git a/src/core_modules/capture-core/components/LoadingMasks/DialogLoadingMask.component.js b/src/core_modules/capture-core/components/LoadingMasks/DialogLoadingMask.component.js index 0366b2b095..1acc9e6a1c 100644 --- a/src/core_modules/capture-core/components/LoadingMasks/DialogLoadingMask.component.js +++ b/src/core_modules/capture-core/components/LoadingMasks/DialogLoadingMask.component.js @@ -1,8 +1,6 @@ // @flow import React, { Component } from 'react'; -import { CircularLoader } from '@dhis2/ui'; -import Dialog from '@material-ui/core/Dialog'; -import DialogContent from '@material-ui/core/DialogContent'; +import { CircularLoader, Modal, ModalContent } from '@dhis2/ui'; type Props = { }; @@ -10,13 +8,13 @@ type Props = { export class DialogLoadingMask extends Component { render() { return ( - - + - - + + ); } } diff --git a/src/core_modules/capture-core/components/PossibleDuplicatesDialog/PossibleDuplicatesDialog.component.js b/src/core_modules/capture-core/components/PossibleDuplicatesDialog/PossibleDuplicatesDialog.component.js index 5a35b3ff34..85a1fccc19 100644 --- a/src/core_modules/capture-core/components/PossibleDuplicatesDialog/PossibleDuplicatesDialog.component.js +++ b/src/core_modules/capture-core/components/PossibleDuplicatesDialog/PossibleDuplicatesDialog.component.js @@ -1,8 +1,6 @@ // @flow import * as React from 'react'; -import { withStyles } from '@material-ui/core'; -import Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; +import { Modal, ModalActions } from '@dhis2/ui'; import { ReviewDialogContents } from './ReviewDialogContents/ReviewDialogContents.container'; import type { RenderCustomCardActions } from '../CardList/CardList.types'; @@ -15,37 +13,29 @@ type Props = {| selectedScopeId: string |}; -const StyledDialogActions = withStyles({ - root: { margin: 24 }, -})(DialogActions); - class ReviewDialogClass extends React.Component { - static paperProps = { - style: { - maxHeight: 'calc(100% - 100px)', - }, - }; - render() { const { open, onCancel, extraActions, selectedScopeId, dataEntryId, renderCardActions } = this.props; + if (!open) { + return null; + } + return ( - - + {extraActions} - - + + ); } } diff --git a/src/core_modules/capture-core/components/PossibleDuplicatesDialog/ReviewDialogContents/ReviewDialogContents.component.js b/src/core_modules/capture-core/components/PossibleDuplicatesDialog/ReviewDialogContents/ReviewDialogContents.component.js index 99c01c200c..d5146481cb 100644 --- a/src/core_modules/capture-core/components/PossibleDuplicatesDialog/ReviewDialogContents/ReviewDialogContents.component.js +++ b/src/core_modules/capture-core/components/PossibleDuplicatesDialog/ReviewDialogContents/ReviewDialogContents.component.js @@ -1,8 +1,7 @@ // @flow import React, { type ComponentType, useContext } from 'react'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogTitle from '@material-ui/core/DialogTitle'; import { withStyles } from '@material-ui/core/styles'; +import { ModalTitle, ModalContent } from '@dhis2/ui'; import i18n from '@dhis2/d2-i18n'; import { CardList } from '../../CardList'; import { ReviewDialogContentsPager } from './ReviewDialogContentsPager.container'; @@ -30,10 +29,10 @@ const ReviewDialogContentsPlain = ({ const { resultsPageSize } = useContext(ResultsPageSizeContext); return ( - - + + {i18n.t('Possible duplicates found')} - + - + ); }; diff --git a/src/core_modules/capture-core/components/WidgetEventEdit/DataEntry/withDeleteButton.js b/src/core_modules/capture-core/components/WidgetEventEdit/DataEntry/withDeleteButton.js index 14efa04273..1c55b9ed1b 100644 --- a/src/core_modules/capture-core/components/WidgetEventEdit/DataEntry/withDeleteButton.js +++ b/src/core_modules/capture-core/components/WidgetEventEdit/DataEntry/withDeleteButton.js @@ -39,33 +39,40 @@ const getDeleteButton = (InnerComponent: React.ComponentType) => {i18n.t('Delete')} - - - {i18n.t('Delete event')} - - - {i18n.t('Deleting an event is permanent and cannot be undone.' + ' ' + - 'Are you sure you want to delete this event? ')} - - - - - - - - + {this.state.isOpen && ( + + + {i18n.t('Delete event')} + + + {i18n.t('Deleting an event is permanent and cannot be undone.' + ' ' + + 'Are you sure you want to delete this event? ')} + + + + + + + + + )}
) : null ) diff --git a/src/core_modules/capture-core/components/WorkingLists/EventWorkingLists/ViewMenuSetup/DownloadDialog/DownloadDialog.component.js b/src/core_modules/capture-core/components/WorkingLists/EventWorkingLists/ViewMenuSetup/DownloadDialog/DownloadDialog.component.js index fc79445ce2..0ed117534b 100644 --- a/src/core_modules/capture-core/components/WorkingLists/EventWorkingLists/ViewMenuSetup/DownloadDialog/DownloadDialog.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/EventWorkingLists/ViewMenuSetup/DownloadDialog/DownloadDialog.component.js @@ -3,8 +3,7 @@ import React, { PureComponent, type ComponentType } from 'react'; import i18n from '@dhis2/d2-i18n'; import { withStyles } from '@material-ui/core/styles'; -import { Dialog, DialogTitle, DialogContent, DialogActions } from '@material-ui/core'; -import { Button } from '@dhis2/ui'; +import { Button, Modal, ModalTitle, ModalContent, ModalActions } from '@dhis2/ui'; import type { Props } from './downloadDialog.types'; const getStyles = () => ({ @@ -80,23 +79,28 @@ class DownloadDialogPlain extends PureComponent { } render() { const { open, onClose } = this.props; + + if (!open) { + return null; + } + return ( - - {i18n.t('Download with current filters')} - + {i18n.t('Download with current filters')} + {this.renderButtons()} - - + + - - + + ); } diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/DeleteConfirmationDialog.component.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/DeleteConfirmationDialog.component.js index 137dab9b63..635bac6d3e 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/DeleteConfirmationDialog.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/DeleteConfirmationDialog.component.js @@ -2,8 +2,7 @@ import * as React from 'react'; import { withStyles } from '@material-ui/core/styles'; import i18n from '@dhis2/d2-i18n'; -import { Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions } from '@material-ui/core'; -import { Button } from '@dhis2/ui'; +import { Button, Modal, ModalTitle, ModalContent, ModalActions } from '@dhis2/ui'; const getStyles = () => ({ buttonContainer: { @@ -29,18 +28,20 @@ const DeleteConfirmationDialogPlain = (props: Props) => { classes, } = props; + if (!open) { + return null; + } + return ( - - {i18n.t('Delete view')} - - - {i18n.t('Do you really want to delete the \'{{templateName}}\' view?', { templateName })} - - - {i18n.t('Delete view')} + + {i18n.t('Do you really want to delete the \'{{templateName}}\' view?', { templateName })} + + - - + + ); }; diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/ExistingTemplateContents.component.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/ExistingTemplateContents.component.js index 28b526c2cb..0efef529f0 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/ExistingTemplateContents.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/ExistingTemplateContents.component.js @@ -2,8 +2,7 @@ import * as React from 'react'; import { withStyles } from '@material-ui/core/styles'; import i18n from '@dhis2/d2-i18n'; -import { DialogTitle, DialogContent, DialogActions } from '@material-ui/core'; -import { Button } from '@dhis2/ui'; +import { Button, ModalTitle, ModalContent, ModalActions } from '@dhis2/ui'; const getStyles = () => ({ buttonContainer: { @@ -22,9 +21,9 @@ const ExistingTemplateContentsPlain = (props: Props) => { const { onSaveTemplate, onClose, classes } = props; return ( - {i18n.t('Save')} - - {i18n.t('Save')} + + - + ); }; diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/ExistingTemplateDialog.component.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/ExistingTemplateDialog.component.js index e8e1af626e..da394131b6 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/ExistingTemplateDialog.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/ExistingTemplateDialog.component.js @@ -1,6 +1,6 @@ // @flow import * as React from 'react'; -import { Dialog } from '@material-ui/core'; +import { Modal } from '@dhis2/ui'; import { ExistingTemplateContents } from './ExistingTemplateContents.component'; type Props = { @@ -16,16 +16,21 @@ export const ExistingTemplateDialog = (props: Props) => { onSaveTemplate, } = props; + if (!open) { + return null; + } + return ( - - + ); }; diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateContents.component.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateContents.component.js index 460069e359..c064f74893 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateContents.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateContents.component.js @@ -1,9 +1,8 @@ // @flow import * as React from 'react'; -import { colors, Button } from '@dhis2/ui'; +import { colors, Button, ModalTitle, ModalContent, ModalActions } from '@dhis2/ui'; import { withStyles } from '@material-ui/core/styles'; import i18n from '@dhis2/d2-i18n'; -import { DialogTitle, DialogContent, DialogActions } from '@material-ui/core'; import { NewTemplateTextField } from './NewTemplateTextField.component'; const getStyles = (theme: Theme) => ({ @@ -46,8 +45,8 @@ const NewTemplateContentsPlain = (props: Props) => { return ( - {i18n.t('Save As view')} - + {i18n.t('Save As view')} + { > {error} - - + - + ); }; diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateDialog.component.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateDialog.component.js index d10a394168..60859c6f5a 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateDialog.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/NewTemplateDialog.component.js @@ -1,6 +1,6 @@ // @flow import * as React from 'react'; -import { Dialog } from '@material-ui/core'; +import { Modal } from '@dhis2/ui'; import { NewTemplateContents } from './NewTemplateContents.component'; type Props = { @@ -16,16 +16,21 @@ export const NewTemplateDialog = (props: Props) => { onSaveTemplate, } = props; + if (!open) { + return null; + } + return ( - - + ); }; diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/SharingDialog.component.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/SharingDialog.component.js index 173f3ebfd2..9434601bea 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/SharingDialog.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/SharingDialog.component.js @@ -12,7 +12,7 @@ const styles = { }, }; -const SharingDialogPlain = ({ onClose, open, templateId, classes, templateSharingType }: Props) => { +const SharingDialogPlain = ({ onClose, open, templateId, classes, templateSharingType, dataTest }: Props) => { const { refetch } = useDataQuery( useMemo( () => ({ @@ -61,6 +61,7 @@ const SharingDialogPlain = ({ onClose, open, templateId, classes, templateSharin id={templateId} onClose={handleClose} className={classes.dialog} + dataTest={dataTest} /> : null ); }; diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/TemplateMaintenance.component.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/TemplateMaintenance.component.js index 6167966094..714ff7177a 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/TemplateMaintenance.component.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/TemplateMaintenance.component.js @@ -65,6 +65,7 @@ const TemplateMaintenancePlain = (props: Props, ref) => { templateId={currentTemplate.id} onClose={handleSetSharingSettings} templateSharingType={templateSharingType} + dataTest={'sharing-dialog'} /> ); diff --git a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/sharingDialog.types.js b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/sharingDialog.types.js index d2abcf26b2..9eed85d346 100644 --- a/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/sharingDialog.types.js +++ b/src/core_modules/capture-core/components/WorkingLists/WorkingListsBase/TemplateMaintenance/sharingDialog.types.js @@ -6,5 +6,6 @@ export type Props = {| open: boolean, templateId: string, templateSharingType: string, + dataTest: string, ...CssClasses, |}; diff --git a/src/core_modules/capture-ui/CoordinateField/CoordinateField.component.js b/src/core_modules/capture-ui/CoordinateField/CoordinateField.component.js index 48eecdaca7..568cb0cedc 100644 --- a/src/core_modules/capture-ui/CoordinateField/CoordinateField.component.js +++ b/src/core_modules/capture-ui/CoordinateField/CoordinateField.component.js @@ -4,7 +4,7 @@ import classNames from 'classnames'; import i18n from '@dhis2/d2-i18n'; import { Map, TileLayer, Marker, withLeaflet } from 'react-leaflet'; import { ReactLeafletSearch } from 'react-leaflet-search-unpolyfilled'; -import { IconCross24, Button } from '@dhis2/ui'; +import { IconCross24, Button, ModalActions, ModalContent } from '@dhis2/ui'; import { IconButton } from 'capture-ui'; import { AddLocationIcon } from '../Icons'; import { CoordinateInput } from '../internal/CoordinateInput/CoordinateInput.component'; @@ -56,6 +56,13 @@ export class CoordinateField extends React.Component { }; } + componentDidUpdate() { + // Invalidate map size to fix rendering bug + if (this.mapInstance && this.state.showMap) { + this.mapInstance.leafletElement.invalidateSize(); + } + } + toSixDecimal = (value: string) => (parseFloat(value) ? parseFloat(value).toFixed(6) : null) handleBlur = (key: string, value: any) => { @@ -139,13 +146,15 @@ export class CoordinateField extends React.Component { const clonedDialog = React.cloneElement( this.props.mapDialog, - { open: this.state.showMap, onClose: this.closeMap }, + { hide: !this.state.showMap, onClose: this.closeMap }, [...React.Children.toArray(this.props.mapDialog.props.children), ( -
- {this.renderMap()} + <> + + {this.renderMap()} + {this.renderDialogActions()} -
+ )], ); return clonedDialog; @@ -185,7 +194,7 @@ export class CoordinateField extends React.Component { } renderDialogActions = () => ( -
+
{/* $FlowFixMe[prop-missing] automated comment */}
-
+ ); renderLatitude = () => { diff --git a/src/core_modules/capture-ui/CoordinateField/coordinateField.module.css b/src/core_modules/capture-ui/CoordinateField/coordinateField.module.css index d73c64bcf2..9f5709617c 100644 --- a/src/core_modules/capture-ui/CoordinateField/coordinateField.module.css +++ b/src/core_modules/capture-ui/CoordinateField/coordinateField.module.css @@ -3,7 +3,7 @@ display: flex; flex-direction: column; } - + .coordinateFieldsHorizontal { position: relative; display: flex; @@ -64,6 +64,8 @@ .mapContainer { flex-grow: 1; position: relative; + height: 100%; + width: 100%; } .leafletContainer { @@ -73,13 +75,11 @@ } .dialogContent { - flex-grow: 1; display: flex; + height: 600px; flex-direction: column; - padding: 0px 24px 24px 24px; } .buttonsContainerVertical { display: flex; } - \ No newline at end of file diff --git a/src/core_modules/capture-ui/PolygonField/PolygonField.component.js b/src/core_modules/capture-ui/PolygonField/PolygonField.component.js index fd2bfe043a..7ef585a16c 100644 --- a/src/core_modules/capture-ui/PolygonField/PolygonField.component.js +++ b/src/core_modules/capture-ui/PolygonField/PolygonField.component.js @@ -1,7 +1,7 @@ // @flow import * as React from 'react'; import i18n from '@dhis2/d2-i18n'; -import { IconCheckmark16, IconLocation16, colors, Button } from '@dhis2/ui'; +import { IconCheckmark16, IconLocation16, colors, Button, ModalContent, ModalActions } from '@dhis2/ui'; import L from 'leaflet'; import { Map, TileLayer, FeatureGroup, withLeaflet } from 'react-leaflet'; import { ReactLeafletSearch } from 'react-leaflet-search-unpolyfilled'; @@ -62,6 +62,8 @@ function coordsToFeatureCollection(coordinates): ?FeatureCollection { } export class PolygonField extends React.Component { + mapInstance: ?any; + static defaultProps = { mapCenter: [51.505, -0.09], } @@ -75,6 +77,13 @@ export class PolygonField extends React.Component { }; } + componentDidUpdate() { + // Invalidate map size to fix rendering bug + if (this.mapInstance && this.state.showMap) { + this.mapInstance.leafletElement.invalidateSize(); + } + } + onFeatureGroupReady = (reactFGref: any, featureCollection: ?FeatureCollection) => { if (featureCollection) { const leafletGeoJSON = new L.GeoJSON(featureCollection); @@ -134,19 +143,25 @@ export class PolygonField extends React.Component { this.closeMap(); } + setMapInstance = (mapInstance: any) => { + this.mapInstance = mapInstance; + } + renderMapDialog = () => { const clonedDialog = React.cloneElement( // $FlowFixMe[incompatible-type] automated comment this.props.mapDialog, - { open: this.state.showMap, onClose: this.closeMap }, + { hide: !this.state.showMap, onClose: this.closeMap }, // $FlowFixMe[incompatible-use] automated comment [...React.Children.toArray(this.props.mapDialog.props.children), ( -
- {this.renderMap()} + <> + + {this.renderMap()} + {this.renderDialogActions()} -
+ )], ); return clonedDialog; @@ -159,7 +174,13 @@ export class PolygonField extends React.Component { const center = this.getCenter(featureCollection); return (
- + { this.setMapInstance(mapInstance); }} + > { } renderDialogActions = () => ( -
+
{/* $FlowFixMe[prop-missing] automated comment */}
-
+ ); render() { diff --git a/src/core_modules/capture-ui/PolygonField/polygonField.module.css b/src/core_modules/capture-ui/PolygonField/polygonField.module.css index 3aa0c0454f..f4fa6c640e 100644 --- a/src/core_modules/capture-ui/PolygonField/polygonField.module.css +++ b/src/core_modules/capture-ui/PolygonField/polygonField.module.css @@ -21,6 +21,8 @@ .mapContainer { flex-grow: 1; position: relative; + width: 100%; + height: 100%; } .map { @@ -30,9 +32,8 @@ } .dialogContent { - flex-grow: 1; display: flex; flex-direction: column; - padding: 0px 24px 24px 24px; + height: 600px; }