Skip to content

Commit

Permalink
feat: further work on default variable values (alerts, saving, user c…
Browse files Browse the repository at this point in the history
…ontrol) [DAT-1403]
  • Loading branch information
Thomas Zemp committed Jul 20, 2022
1 parent 67f0b33 commit 9e16649
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 58 deletions.
16 changes: 14 additions & 2 deletions i18n/en.pot
Original file line number Diff line number Diff line change
Expand Up @@ -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: 2022-07-19T12:54:33.188Z\n"
"PO-Revision-Date: 2022-07-19T12:54:33.188Z\n"
"POT-Creation-Date: 2022-07-20T16:52:08.431Z\n"
"PO-Revision-Date: 2022-07-20T16:52:08.431Z\n"

msgid "Search within results"
msgstr "Search within results"
Expand Down Expand Up @@ -56,6 +56,15 @@ msgstr "Reset"
msgid "undefined"
msgstr "undefined"

msgid "Variables have been reset. Refresh query to refresh data."
msgstr "Variables have been reset. Refresh query to refresh data."

msgid "Default variables could not be updated."
msgstr "Default variables could not be updated."

msgid "Default variables updated."
msgstr "Default variables updated."

msgid "Back"
msgstr "Back"

Expand Down Expand Up @@ -97,3 +106,6 @@ msgstr "Next"

msgid "Rows to display"
msgstr "Rows to display"

msgid "Defaults are invalid. Please save new defaults or fill out manually."
msgstr "Defaults are invalid. Please save new defaults or fill out manually."
4 changes: 2 additions & 2 deletions src/components/ConfigProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const ConfigProviderCtx = createContext({})

const ConfigProvider = ({ children }) => {
const [config, setConfig] = useState({})
const [waiting, setWaiting] = useState(true)
const [configWaiting, setWaiting] = useState(true)
const engine = useDataEngine()

useEffect(() => {
Expand All @@ -36,7 +36,7 @@ const ConfigProvider = ({ children }) => {
<ConfigProviderCtx.Provider
value={{
config: config,
waiting: waiting,
configWaiting: configWaiting,
}}
>
{children}
Expand Down
16 changes: 13 additions & 3 deletions src/components/Data/VariablesDrawerMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const VariablesDrawerMenu = ({
refreshQuery,
resetDefaults,
defaultsAvailable,
defaultsConfigured,
saveDefaults,
allowSave,
}) => {
const handleRefresh = () => {
refreshQuery(variables)
Expand Down Expand Up @@ -67,7 +70,7 @@ const VariablesDrawerMenu = ({
</Button>
</div>
)}
{defaultsAvailable && (
{defaultsConfigured && (
<div className="rightButtonOuterLast">
<div className="buttonStripWrapper">
<span>{i18n.t('Defaults')}</span>
Expand All @@ -80,23 +83,27 @@ const VariablesDrawerMenu = ({
)}
>
<Button
dataTest="refresh-query-left"
dataTest="save-defaults-button"
icon={<IconSave24 />}
small
onClick={saveDefaults}
disabled={!allowSave}
>
{i18n.t('Save')}
</Button>
</Tooltip>

<Tooltip
content={i18n.t(
'Reset the values to the default values saved for this SQL view'
)}
>
<Button
dataTest="refresh-query-left"
dataTest="reset-defaults-button"
icon={<IconRedo24 />}
small
onClick={resetDefaults}
disabled={!defaultsAvailable}
>
{i18n.t('Reset')}
</Button>
Expand Down Expand Up @@ -153,9 +160,12 @@ const VariablesDrawerMenu = ({
}

VariablesDrawerMenu.propTypes = {
allowSave: PropTypes.bool,
defaultsAvailable: PropTypes.bool,
defaultsConfigured: PropTypes.bool,
refreshQuery: PropTypes.func,
resetDefaults: PropTypes.func,
saveDefaults: PropTypes.func,
toggleVariableDrawer: PropTypes.func,
updateVariable: PropTypes.func,
variables: PropTypes.object,
Expand Down
142 changes: 110 additions & 32 deletions src/components/Data/ViewData.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { useConfig, useDataEngine } from '@dhis2/app-runtime'
import { useAlert, useConfig, useDataEngine } from '@dhis2/app-runtime'
import i18n from '@dhis2/d2-i18n'
import { Button, CircularLoader, IconArrowLeft24, IconMore24 } from '@dhis2/ui'
import PropTypes from 'prop-types'
import React, { useEffect, useState, createRef } from 'react'
import { Link } from 'react-router-dom'
import { executeQuery } from '../../api/miscellaneous'
import {
checkIfAllNull,
extractVariables,
getVariablesLink,
populateDefaultVariables,
} from '../../services/extractVariables'
import { useQuery } from '../../services/useQuery'
import { useDataStoreConfig } from '../ConfigProvider'
import { useUserInfo } from '../UserInfoProvider'
import Layout from '../Layout'
import DataWrapper from './DataWrapper'
import ErrorMessage from './ErrorMessage'
Expand All @@ -23,10 +25,31 @@ const sqlViewDetail = {
sqlView: {
resource: 'sqlViews',
id: ({ id }) => id,
params: {
paging: 'false',
fields: 'id,name,type,sqlQuery,attributeValues',
},
},
}

const sqlUpdate = {
resource: 'sqlViews',
id: ({ id }) => id,
type: 'update',
partial: false,
params: { mergeMode: 'REPLACE' },
data: ({ data }) => data,
}

const ALERT_MESSAGES = {
resetSuccess: {
msg: i18n.t(
'Variables have been reset. Refresh query to refresh data.'
),
},
saveFail: {
msg: i18n.t('Default variables could not be updated.'),
options: { warning: true },
},
saveSuccess: {
msg: i18n.t('Default variables updated.'),
options: { success: true },
},
}

Expand Down Expand Up @@ -58,7 +81,8 @@ const BackButton = () => (

const ViewData = ({ match }) => {
const { baseUrl } = useConfig()
const { config, waiting } = useDataStoreConfig()
const { config, configWaiting } = useDataStoreConfig()
const { userInfo, userWaiting } = useUserInfo()
const query = useQuery()
const engine = useDataEngine()
const id = match.params.id
Expand All @@ -71,13 +95,18 @@ const ViewData = ({ match }) => {
const [data, setData] = useState(null)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(null)
const [defaultsAvailable, setDefaultsAvailable] = useState(false)
const { show: showAlert } = useAlert(
({ msg }) => msg,
({ options }) => ({ ...options, duration: 3000 })
)

const toggleLinksMenu = () => {
setLinksMenuOpen(!linksMenuOpen)
}

useEffect(() => {
if (!waiting) {
if (!configWaiting) {
const getEngineResults = async id => {
try {
const { sqlView } = await engine.query(sqlViewDetail, {
Expand All @@ -92,15 +121,27 @@ const ViewData = ({ match }) => {
}
getEngineResults(id)
}
}, [config, waiting, id])
}, [config, configWaiting, id])

const prepView = async d => {
let extractedVariables = extractVariables(d.sqlView.sqlQuery)
extractedVariables = populateDefaultVariables(
extractedVariables,
d.sqlView.attributeValues,
config?.defaultsAttributeId
)
if (config?.defaultsAttributeId) {
try {
extractedVariables = populateDefaultVariables(
extractedVariables,
d.sqlView.attributeValues,
config?.defaultsAttributeId
)
if (!checkIfAllNull(extractedVariables)) {
setDefaultsAvailable(true)
}
} catch (e) {
showAlert({
msg: e.message,
options: { warning: true, duration: 3000 },
})
}
}

if (
d.sqlView.type !== QUERY_TYPE ||
Expand Down Expand Up @@ -146,26 +187,57 @@ const ViewData = ({ match }) => {
}

const resetDefaults = () => {
const tempVariables = populateDefaultVariables(
variables,
data.sqlView.attributeValues,
config?.defaultsAttributeId
)
try {
const tempVariables = populateDefaultVariables(
variables,
data.sqlView.attributeValues,
config?.defaultsAttributeId
)

const linkVariables = Object.keys(tempVariables).reduce((linkV, v) => {
if (tempVariables[v]) {
linkV[v] = tempVariables[v]
}
return linkV
}, {})
window.history.pushState(
null,
null,
getVariablesLink({ id, variables: tempVariables, baseUrl })
)

window.history.pushState(
null,
null,
getVariablesLink({ id, variables: linkVariables, baseUrl })
)
setVariables(tempVariables)
showAlert(ALERT_MESSAGES.resetSuccess)
} catch (e) {
showAlert({ msg: e.message, options: { warning: true } })
}
}

const saveDefaults = async () => {
try {
const filteredAttributeValues = data.sqlView.attributeValues.filter(
av => av.attribute.id !== config?.defaultsAttributeId
)
let newVariables = {
attribute: { id: config?.defaultsAttributeId },
value: JSON.stringify(variables),
}
let newSQLView = { ...data.sqlView }
newSQLView.attributeValues = [
...filteredAttributeValues,
newVariables,
]

setVariables(tempVariables)
let response = await engine.mutate(sqlUpdate, {
variables: { id: data.sqlView.id, data: newSQLView },
})
if (
response?.httpStatusCode === undefined ||
response?.httpStatusCode < 200 ||
response?.httpStatusCode >= 400
) {
showAlert(ALERT_MESSAGES.saveFail)
} else {
showAlert(ALERT_MESSAGES.saveSuccess)
setData({ sqlView: newSQLView })
}
} catch (e) {
showAlert(ALERT_MESSAGES.saveFail)
}
}

const toggleVariableDrawer = () => {
Expand All @@ -186,7 +258,7 @@ const ViewData = ({ match }) => {
<ErrorMessage error={error} />
</>
)}
{data && queryExecuted && (
{userInfo && data && queryExecuted && (
<div className="container">
<div
className={
Expand All @@ -201,9 +273,15 @@ const ViewData = ({ match }) => {
updateVariable={updateVariable}
refreshQuery={refreshQuery}
resetDefaults={resetDefaults}
defaultsAvailable={
defaultsConfigured={
config?.defaultsAttributeId !== undefined
}
defaultsAvailable={defaultsAvailable}
saveDefaults={saveDefaults}
allowSave={
userInfo.superuser ||
data?.sharing?.owner === userInfo?.id
}
/>
<div className="main">
<div className="marginWrap">
Expand Down
35 changes: 19 additions & 16 deletions src/components/Main.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react'
import { HashRouter as Router, Switch, Route } from 'react-router-dom'
import ConfigProvider from './ConfigProvider'
import UserInfoProvider from './UserInfoProvider'
import ViewData from './Data/ViewData'
import Layout from './Layout'
import SelectQuery from './Selection/SelectQuery'
Expand All @@ -9,24 +10,26 @@ import '../locales'
const Main = () => {
return (
<ConfigProvider>
<Router>
<Switch>
<Route
exact
path="/view/:id"
render={props => (
<UserInfoProvider>
<Router>
<Switch>
<Route
exact
path="/view/:id"
render={props => (
<Layout>
<ViewData {...props} />
</Layout>
)}
/>
<Route path="/">
<Layout>
<ViewData {...props} />
<SelectQuery />
</Layout>
)}
/>
<Route path="/">
<Layout>
<SelectQuery />
</Layout>
</Route>
</Switch>
</Router>
</Route>
</Switch>
</Router>
</UserInfoProvider>
</ConfigProvider>
)
}
Expand Down
Loading

0 comments on commit 9e16649

Please sign in to comment.