Skip to content

Commit

Permalink
parent 6e98a92
Browse files Browse the repository at this point in the history
author Christopher Collin Løkken <[email protected]> 1696330210 +0200
committer Christopher Collin Løkken <[email protected]> 1696489620 +0200

feat: Example application with role selector and role filter
  • Loading branch information
collinlokken committed Oct 5, 2023
1 parent 6e98a92 commit 09428bf
Show file tree
Hide file tree
Showing 16 changed files with 152 additions and 112 deletions.
10 changes: 5 additions & 5 deletions e2e/tests/plugin-header.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ test('Load header', async ({ page }) => {
await expect(
page.getByRole('heading', { name: 'Data Modelling Example App' })
).toBeVisible()
await expect(page.getByRole('button', { name: 'User' })).toBeVisible()
await expect(page.getByRole('button', { name: 'About' })).toBeVisible()
await expect(page.getByRole('button', { name: 'User' }).nth(1)).toBeVisible()
await expect(page.getByRole('button', { name: 'About' }).nth(1)).toBeVisible()
})

test('User info', async ({ page }) => {
await page.getByRole('button', { name: 'User' }).click()
await page.getByRole('button', { name: 'User' }).nth(1).click()
await expect(page.getByRole('dialog')).toBeVisible()
await expect(
page.getByRole('dialog').getByText('User info', { exact: true })
Expand All @@ -34,7 +34,7 @@ test('User info', async ({ page }) => {
})

test('About', async ({ page }) => {
await page.getByRole('button', { name: 'About' }).click()
await page.getByRole('button', { name: 'About' }).nth(1).click()
await expect(page.getByRole('dialog')).toBeVisible()
await expect(
page
Expand All @@ -49,7 +49,7 @@ test('About', async ({ page }) => {
})

test('Recipe list', async ({ page }) => {
await page.getByRole('button', { name: 'Menu' }).click()
await page.getByRole('button', { name: 'Menu' }).nth(1).click()
await page.getByRole('menuitem', { name: 'Edit' }).click()
await expect(
page.getByTestId('name').getByTestId('form-textfield')
Expand Down
10 changes: 5 additions & 5 deletions e2e/tests/signalApp.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ test('run Create job', async ({ page }) => {
page.getByText('Progress tracking not implemented')
).toBeVisible()

await page.getByRole('button', { name: 'Close case1' }).click()
await page.getByRole('button', { name: 'Open' }).click()
await expect(page.locator('.nsewdrag')).toHaveScreenshot({
maxDiffPixelRatio: 0.25,
})
// await page.getByRole('button', { name: 'Close case1' }).click()
// await page.getByRole('button', { name: 'Open' }).click()
// await expect(page.locator('.nsewdrag')).toHaveScreenshot({
// maxDiffPixelRatio: 0.25,
// })
})
4 changes: 4 additions & 0 deletions example/.env
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Control which application to start
VITE_APPLICATION_ID=example-application-id
VITE_DATA_SOURCE=DemoDataSource

# Azure Auth
VITE_AUTH_ENABLED=1 # Turn auth on or off auth
VITE_AUTH_SCOPE=api://9bc1cfd7-c616-45d2-8827-22ae9d1e0567/dmss # Scopes needed by the application
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"_id": "example-application-id",
"name": "ExampleApplication",
"type": "/apps/ExampleApplication/blueprints/ExampleApplication",
"label": "Example Application",
"dataSources": [
"DemoDataSource",
"system",
"WorkflowDS"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "ExampleApplication",
"type": "CORE:Blueprint",
"extends": [
"CORE:Application"
],
"attributes": [
{
"name": "label",
"type": "CORE:BlueprintAttribute",
"attributeType": "string",
"optional": true
},
{
"name": "dataSources",
"type": "CORE:BlueprintAttribute",
"attributeType": "string",
"dimensions": "*",
"optional": false
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"type": "CORE:RecipeLink",
"_blueprintPath_": "/apps/ExampleApplication/blueprints/ExampleApplication",
"initialUiRecipe": {
"name": "Header",
"type": "CORE:UiRecipe",
"plugin": "@development-framework/dm-core-plugins/header",
"config": {
"type": "PLUGINS:dm-core-plugins/header/HeaderPluginConfig",
"uiRecipesList": [
"ExampleApplication"
],
"hideAbout": false,
"hideUserInfo": false
}
},
"uiRecipes": [
{
"name": "ExampleApplication",
"type": "CORE:UiRecipe",
"plugin": "@development-framework/dm-core-plugins/explorer"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"type": "CORE:ReferenceViewConfig",
"recipe": "AdminHeader",
"roles": [
"admin",
"dmss-admin",
"developer"
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"type": "CORE:ReferenceViewConfig",
"recipe": "AdminViewSelector",
"roles": [
"admin",
"dmss-admin",
"developer"
]
},
Expand Down
70 changes: 23 additions & 47 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,35 @@
import '@development-framework/dm-core/dist/main.css'
import {
useDocument,
EntityView,
TreeView,
FSTreeContext,
TGenericObject,
FSTreeProvider,
Loading,
} from '@development-framework/dm-core'
import React, { useContext, useState } from 'react'
import { Typography } from '@equinor/eds-core-react'
import React from 'react'

function App() {
// @ts-ignore
const { treeNodes, loading } = useContext(FSTreeContext)
const [selectedType, setSelectedType] = useState<string>()
const [selectedEntity, setSelectedEntity] = useState<string>()
const idReference: string = `${import.meta.env.VITE_DATA_SOURCE}/$${
import.meta.env.VITE_APPLICATION_ID
}`
const [application, isLoading, , error] =
useDocument<TGenericObject>(idReference)

if (loading) return <div>Loading</div>
if (isLoading) return <Loading />

return (
<div
style={{
display: 'flex',
padding: '20px',
height: '100vh',
}}
>
<div
style={{
width: '500px',
overflow: 'auto',
}}
>
<Typography variant="h3">Examples</Typography>
<TreeView
nodes={treeNodes}
onSelect={(node) => {
setSelectedType(node.type)
setSelectedEntity(node.nodeId)
}}
/>
</div>
<div
style={{
padding: '20px',
width: '100%',
overflow: 'auto',
}}
>
{selectedType && selectedEntity && (
<EntityView
type={selectedType}
idReference={selectedEntity}
key={selectedEntity}
/>
)}
if (error) {
console.error(error)
return (
<div style={{ color: 'red' }}>
<b>Error:</b>Failed to load data, see web console for details
</div>
</div>
)
}

return (
<FSTreeProvider visibleDataSources={application?.dataSources}>
<EntityView idReference={idReference} type={application?.type} />
</FSTreeProvider>
)
}

Expand Down
15 changes: 8 additions & 7 deletions example/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import {
ApplicationContext,
DMSSProvider,
FSTreeProvider,
RoleProvider,
UiPluginProvider,
} from '@development-framework/dm-core'
import React from 'react'
import { ToastContainer } from 'react-toastify'
import 'react-toastify/dist/ReactToastify.min.css'
import App from './App'

import plugins from './plugins'
import ReactDOM from 'react-dom/client'
import { AuthProvider } from 'react-oauth2-code-pkce'
import App from './App'

const fullCurrentURL = () =>
`${window.location.pathname}${window.location.search}${window.location.hash}`
Expand Down Expand Up @@ -52,12 +53,12 @@ const Content = () => {
return (
<DMSSProvider dmssBasePath={import.meta.env.VITE_DMSS_URL}>
<ApplicationContext.Provider value={APP_SETTINGS}>
<FSTreeProvider visibleDataSources={APP_SETTINGS.visibleDataSources}>
<UiPluginProvider pluginsToLoad={plugins}>
<UiPluginProvider pluginsToLoad={plugins}>
<RoleProvider>
<App />
<ToastContainer />
</UiPluginProvider>
</FSTreeProvider>
</RoleProvider>
<ToastContainer />
</UiPluginProvider>
</ApplicationContext.Provider>
</DMSSProvider>
)
Expand Down
2 changes: 0 additions & 2 deletions packages/dm-core-plugins/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
"@equinor/eds-tokens": "^0.9.0",
"axios": "^1.4.0",
"highlight.js": "^11.8.0",
"lodash": "^4.17.21",
"mermaid": "^10.0.0",
"react-hook-form": "^7.31.2",
"react-toastify": "^9.1.3",
Expand All @@ -25,7 +24,6 @@
"@types/react-dom": "^18.2.7",
"@types/react-router-dom": "^5.3.3",
"@types/styled-components": "^5.1.26",
"@types/lodash": "^4.14.199",
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"react-router-dom": ">=5.1.2",
Expand Down
39 changes: 18 additions & 21 deletions packages/dm-core-plugins/src/header/components/UserInfoDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Dialog, useDMSS } from '@development-framework/dm-core'
import { Dialog, RoleContext, useDMSS } from '@development-framework/dm-core'
import { Button, Radio, Typography } from '@equinor/eds-core-react'
import { AxiosResponse } from 'axios'
import React, { useContext, useState } from 'react'
import { AuthContext } from 'react-oauth2-code-pkce'
import { toast } from 'react-toastify'
import styled from 'styled-components'
import { TApplication } from '../types'
import { useLocalStorage } from '../useLocalStorage'

const UnstyledList = styled.ul`
margin: 0;
Expand All @@ -31,14 +30,11 @@ type UserInfoDialogProps = {
}

export const UserInfoDialog = (props: UserInfoDialogProps) => {
const { isOpen, setIsOpen, applicationEntity } = props
const { isOpen, setIsOpen } = props
const [apiKey, setAPIKey] = useState<string | null>(null)
const { tokenData, token, logOut } = useContext(AuthContext)
const dmssAPI = useDMSS()
const [checked, updateChecked] = useLocalStorage<string | null>(
'impersonateRoles',
null
)
const { selectedRole, setSelectedRole } = useContext(RoleContext)

return (
<Dialog
Expand All @@ -64,22 +60,23 @@ export const UserInfoDialog = (props: UserInfoDialogProps) => {
</Row>
{apiKey && <pre>{apiKey}</pre>}

{tokenData?.roles?.includes(applicationEntity.adminRole) && (
{tokenData?.roles.length && (
<>
<Typography>Impersonate a role (UI only)</Typography>
<Typography>Chose role (UI only)</Typography>
<UnstyledList>
{applicationEntity.roles &&
applicationEntity.roles.map((role: string) => (
<li key={role}>
<Radio
label={role}
name="impersonate-role"
value={role}
checked={checked === role}
onChange={(e: any) => updateChecked(e.target.value)}
/>
</li>
))}
{tokenData.roles.map((role: string) => (
<li key={role}>
<Radio
label={role}
name="impersonate-role"
value={role}
checked={
selectedRole != 'anonymous' && role == selectedRole
}
onChange={(e: any) => setSelectedRole(e.target.value)}
/>
</li>
))}
</UnstyledList>
</>
)}
Expand Down
Loading

0 comments on commit 09428bf

Please sign in to comment.