Skip to content

Commit

Permalink
feat: add coreApp property (#522)
Browse files Browse the repository at this point in the history
* fix(verifybundle): ignore name-check for dashboard_widget

* feat(coreapp): add coreApp-attribute to models and format

* feat(coreapp): add coreApp to createApp-handler

* feat(coreapp): add UI for coreApp

* fix(apps): update core-filter to use core_app column

* fix(appview): add core-app tag

* fix(editApp): dont set coreApp to false if no manager

* fix: fix core-app filter

* fix(verifybundle): return manifest when no d2-config

* fix: add core-app migration

* refactor: check for bool instead of 2 ifs
  • Loading branch information
Birkbjo authored Aug 9, 2021
1 parent 7b58317 commit e22dafd
Show file tree
Hide file tree
Showing 21 changed files with 229 additions and 91 deletions.
12 changes: 11 additions & 1 deletion client/src/pages/AppView/AppView.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Card,
Divider,
Button,
Tag,
} from '@dhis2/ui'
import classnames from 'classnames'
import PropTypes from 'prop-types'
Expand All @@ -17,7 +18,13 @@ import Screenshots from 'src/components/Screenshots/Screenshots'
import Versions from 'src/components/Versions/Versions'
import { renderDhisVersionsCompatibility } from 'src/lib/render-dhis-versions-compatibility'

const HeaderSection = ({ appName, appDeveloper, appType, logoSrc }) => (
const HeaderSection = ({
appName,
appDeveloper,
appType,
logoSrc,
isCoreApp,
}) => (
<section
className={classnames(styles.appCardSection, styles.appCardHeader)}
>
Expand All @@ -27,13 +34,15 @@ const HeaderSection = ({ appName, appDeveloper, appType, logoSrc }) => (
<span className={styles.appCardDeveloper}>by {appDeveloper}</span>
<span className={styles.appCardType}>{appType}</span>
</div>
{isCoreApp && <Tag>Core App</Tag>}
</section>
)

HeaderSection.propTypes = {
appDeveloper: PropTypes.string.isRequired,
appName: PropTypes.string.isRequired,
appType: PropTypes.string.isRequired,
isCoreApp: PropTypes.bool,
logoSrc: PropTypes.string,
}

Expand Down Expand Up @@ -111,6 +120,7 @@ const AppView = ({ match }) => {
appDeveloper={appDeveloper}
appType={config.ui.appTypeToDisplayName[app.appType]}
logoSrc={logoSrc}
isCoreApp={app.coreApp}
/>
<Divider />
<AboutSection
Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/AppView/AppView.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

.appCardHeader {
display: grid;
grid-template-columns: 72px auto;
grid-template-columns: 72px auto 67px;
grid-gap: var(--spacers-dp12);
}

Expand Down
13 changes: 12 additions & 1 deletion client/src/pages/Apps/AppCards/AppCardItem/AppCardItem.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Tag } from '@dhis2/ui'
import PropTypes from 'prop-types'
import React from 'react'
import { Link } from 'react-router-dom'
Expand All @@ -13,7 +14,15 @@ const summarise = text => {
return text
}

const AppCardItem = ({ id, name, developer, type, description, images }) => {
const AppCardItem = ({
id,
name,
developer,
type,
description,
images,
isCoreApp,
}) => {
const logo = images.find(elem => elem.logo)

return (
Expand All @@ -29,6 +38,7 @@ const AppCardItem = ({ id, name, developer, type, description, images }) => {
{config.ui.appTypeToDisplayName[type]}
</span>
</div>
{isCoreApp && <Tag>Core App</Tag>}
</header>

<p className={styles.appCardDescription}>
Expand All @@ -48,6 +58,7 @@ AppCardItem.propTypes = {
type: PropTypes.string.isRequired,
description: PropTypes.string,
images: PropTypes.array,
isCoreApp: PropTypes.bool,
}

export default AppCardItem
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

.appCardHeader {
display: grid;
grid-template-columns: 72px auto;
grid-template-columns: 72px auto 67px;
grid-gap: var(--spacers-dp12);
}

Expand Down Expand Up @@ -50,3 +50,7 @@
font-size: 15px;
line-height: 21px;
}

.coreAppIcon {
width: 25px
}
1 change: 1 addition & 0 deletions client/src/pages/Apps/AppCards/AppCards.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const AppCards = ({ isLoading, error, apps }) => {
type={app.appType}
description={app.description}
images={app.images}
isCoreApp={app.coreApp}
/>
))}
</div>
Expand Down
3 changes: 2 additions & 1 deletion client/src/pages/UserApp/DetailsCard/DetailsCard.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Card, Button, Divider } from '@dhis2/ui'
import { Card, Button, Divider, Tag } from '@dhis2/ui'
import PropTypes from 'prop-types'
import { useState, useRef } from 'react'
import { Link } from 'react-router-dom'
Expand Down Expand Up @@ -92,6 +92,7 @@ const DetailsCard = ({ app, mutate }) => {
</span>
<span className={styles.detailsCardType}>{appType}</span>
</div>
{app.coreApp && <Tag>Core App</Tag>}
</section>
<Divider />
<section>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.detailsCardHeader {
display: grid;
grid-template-columns: 120px auto;
grid-template-columns: 120px auto 67px;
grid-gap: var(--spacers-dp12);
margin-bottom: var(--spacers-dp8);
}
Expand Down
16 changes: 16 additions & 0 deletions client/src/pages/UserAppEdit/UserAppEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,26 @@ import {
ReactFinalForm,
InputFieldFF,
TextAreaFieldFF,
SwitchFieldFF,
hasValue,
url,
} from '@dhis2/ui'
import PropTypes from 'prop-types'
import { useSelector } from 'react-redux'
import { useHistory } from 'react-router-dom'
import styles from './UserAppEdit.module.css'
import { useQueryV1 } from 'src/api'
import * as api from 'src/api'
import { useSuccessAlert, useErrorAlert } from 'src/lib/use-alert'
import { isManager as isManagerSelector } from 'src/selectors/userSelectors'

const UserAppEdit = ({ match }) => {
const { appId } = match.params
const { data: app, error } = useQueryV1(`apps/${appId}`, { auth: true })
const history = useHistory()
const successAlert = useSuccessAlert()
const errorAlert = useErrorAlert()
const isManager = useSelector(isManagerSelector)

const handleSubmit = async values => {
try {
Expand Down Expand Up @@ -101,6 +105,18 @@ const UserAppEdit = ({ match }) => {
className={styles.field}
validate={url}
/>
{isManager && (
<ReactFinalForm.Field
name="coreApp"
label="Core App"
type="checkbox"
placeholder="e.g. https://github.com/user/app"
helpText="Set the app as an Core app, normally this is set from the manifest when uploading an app."
initialValue={app.coreApp}
component={SwitchFieldFF}
className={styles.field}
/>
)}
<Button
primary
type="submit"
Expand Down
96 changes: 96 additions & 0 deletions server/migrations/20210705145813_core-app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
exports.up = async function (knex) {
await knex.schema.table('app', table => {
table.boolean('core_app').defaultTo(false)
})
await knex.raw('DROP VIEW apps_view')
// update app-view with column
await knex.raw(`
CREATE VIEW apps_view AS
SELECT app.id AS app_id,
app.type,
app.core_app,
appver.version, appver.id AS version_id, appver.created_at AS version_created_at, appver.source_url, appver.demo_url,
media.app_media_id AS media_id, media.original_filename, media.created_at AS media_created_at, media.media_type,
localisedapp.language_code, localisedapp.name, localisedapp.description, localisedapp.slug AS appver_slug,
s.status, s.created_at AS status_created_at,
ac.min_dhis2_version, ac.max_dhis2_version,
c.name AS channel_name, c.id AS channel_id,
app.contact_email AS contact_email,
users.id as owner_id, users.name as owner_name, users.email as owner_email,
org.name AS organisation, org.slug AS organisation_slug, org.email as organisation_email
FROM app
INNER JOIN app_status AS s
ON s.app_id = app.id
INNER JOIN app_version AS appver
ON appver.app_id = s.app_id
LEFT JOIN app_media_view AS media
ON media.app_id = s.app_id
INNER JOIN app_version_localised AS localisedapp
ON localisedapp.app_version_id = appver.id
INNER JOIN app_channel AS ac
ON ac.app_version_id = appver.id
INNER JOIN channel AS c
ON c.id = ac.channel_id
INNER JOIN users
ON users.id = app.created_by_user_id
INNER JOIN organisation AS org
ON org.id = app.organisation_id
`)
}

exports.down = async function (knex) {
await knex.raw('DROP VIEW apps_view')
await knex.schema.table('app', table => {
table.dropColumn('core_app')
})

await knex.raw(`
CREATE VIEW apps_view AS
SELECT app.id AS app_id,
app.type,
appver.version, appver.id AS version_id, appver.created_at AS version_created_at, appver.source_url, appver.demo_url,
media.app_media_id AS media_id, media.original_filename, media.created_at AS media_created_at, media.media_type,
localisedapp.language_code, localisedapp.name, localisedapp.description, localisedapp.slug AS appver_slug,
s.status, s.created_at AS status_created_at,
ac.min_dhis2_version, ac.max_dhis2_version,
c.name AS channel_name, c.id AS channel_id,
app.contact_email AS contact_email,
users.id as owner_id, users.name as owner_name, users.email as owner_email,
org.name AS organisation, org.slug AS organisation_slug, org.email as organisation_email
FROM app
INNER JOIN app_status AS s
ON s.app_id = app.id
INNER JOIN app_version AS appver
ON appver.app_id = s.app_id
LEFT JOIN app_media_view AS media
ON media.app_id = s.app_id
INNER JOIN app_version_localised AS localisedapp
ON localisedapp.app_version_id = appver.id
INNER JOIN app_channel AS ac
ON ac.app_version_id = appver.id
INNER JOIN channel AS c
ON c.id = ac.channel_id
INNER JOIN users
ON users.id = app.created_by_user_id
INNER JOIN organisation AS org
ON org.id = app.organisation_id
`)
}
16 changes: 5 additions & 11 deletions server/src/data/createApp.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
const joi = require('@hapi/joi')

const debug = require('debug')('apphub:server:data:createApp')

const { AppTypes } = require('../enums')

const paramsSchema = joi
.object()
.keys({
userId: joi
.string()
.uuid()
.required(),
userId: joi.string().uuid().required(),
contactEmail: joi.string().email(),
orgId: joi
.string()
.uuid()
.required(),
orgId: joi.string().uuid().required(),
appType: joi
.string()
.required()
.valid(...AppTypes),
coreApp: joi.bool(),
})
.options({ allowUnknown: true })

Expand Down Expand Up @@ -48,7 +41,7 @@ const createApp = async (params, knex) => {
}

debug('params: ', params)
const { userId, contactEmail, orgId, appType } = params
const { userId, contactEmail, orgId, appType, coreApp } = params

//generate a new uuid to insert

Expand All @@ -60,6 +53,7 @@ const createApp = async (params, knex) => {
contact_email: contactEmail,
organisation_id: orgId,
type: appType,
core_app: coreApp,
})
.returning('id')

Expand Down
7 changes: 2 additions & 5 deletions server/src/data/getApps.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,8 @@ const getApps = (
})
}

if (coreApp) {
builder.where('organisation', 'DHIS2')
}
if (coreApp === false) {
builder.whereNot('organisation', 'DHIS2')
if (typeof coreApp === 'boolean') {
builder.where('core_app', coreApp)
}

if (query) {
Expand Down
20 changes: 7 additions & 13 deletions server/src/data/updateApp.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
const joi = require('@hapi/joi')
const { slugify } = require('../utils/slugify')
const { AppTypes } = require('../enums')
const { slugify } = require('../utils/slugify')

const paramsSchema = joi
.object()
.keys({
id: joi
.string()
.uuid()
.required(),
userId: joi
.string()
.uuid()
.required(),
id: joi.string().uuid().required(),
userId: joi.string().uuid().required(),
name: joi.string().max(100),
description: joi.string().allow(''),
appType: joi.string().valid(...AppTypes),
Expand All @@ -23,10 +17,8 @@ const paramsSchema = joi
.uri({
scheme: ['http', 'https'],
}),
languageCode: joi
.string()
.max(2)
.required(),
languageCode: joi.string().max(2).required(),
coreApp: joi.bool(),
})
.options({ allowUnknown: true })

Expand Down Expand Up @@ -71,6 +63,7 @@ const updateApp = async (params, knex) => {
appType,
description,
languageCode,
coreApp,
} = params

try {
Expand All @@ -85,6 +78,7 @@ const updateApp = async (params, knex) => {
type: appType,
updated_at: knex.fn.now(),
updated_by_user_id: userId,
core_app: coreApp,
})
.where({
id,
Expand Down
Loading

0 comments on commit e22dafd

Please sign in to comment.