Skip to content

Commit

Permalink
feat(web): Powerbi richtext embed slice (#8703)
Browse files Browse the repository at this point in the history
* Add powerbi library and component

* Add powerbi slice code

* Allow powerbi slice on project pages

* Add powerbi slice to project subpages

* Add support for forms on project pages while we're at it

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
RunarVestmann and kodiakhq[bot] authored Oct 18, 2022
1 parent da9c333 commit 6bf6221
Show file tree
Hide file tree
Showing 13 changed files with 181 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { style } from '@vanilla-extract/css'

export const container = style({
height: '500px',
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { PowerBIEmbed } from 'powerbi-client-react'
import { Embed } from 'powerbi-client'
import { PowerBiSlice as PowerBiSliceSchema } from '@island.is/web/graphql/schema'
import * as styles from './PowerBiSlice.css'

interface PowerBiSliceProps {
slice: PowerBiSliceSchema
}

export const PowerBiSlice = ({ slice }: PowerBiSliceProps) => {
const getEmbeddedComponent = (embed: Embed) => {
if (slice?.powerBiEmbedProps?.height) {
embed.element.style.height = slice.powerBiEmbedProps.height
}
}

const embedProps = slice?.powerBiEmbedProps ?? {}
return (
<PowerBIEmbed
embedConfig={{ type: 'report', ...embedProps }}
cssClassName={styles.container}
getEmbeddedComponent={getEmbeddedComponent}
/>
)
}

export default PowerBiSlice
4 changes: 4 additions & 0 deletions apps/web/components/Organization/Slice/PowerBiSlice/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import dynamic from 'next/dynamic'
export const PowerBiSlice = dynamic(() => import('./PowerBiSlice'), {
ssr: false,
})
1 change: 1 addition & 0 deletions apps/web/components/Organization/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ export * from './Slice/EventSlice/EventSlice'
export * from './SearchBox/SearchBox'
export * from './Slice/MailingListSignupSlice/MailingListSignupSlice'
export * from './Slice/LifeEventPageListSlice/LifeEventPageListSlice'
export * from './Slice/PowerBiSlice'
5 changes: 5 additions & 0 deletions apps/web/screens/Organization/SubPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
import { withMainLayout } from '@island.is/web/layouts/main'
import {
ContentLanguage,
PowerBiSlice as PowerBiSliceSchema,
Query,
QueryGetNamespaceArgs,
QueryGetOrganizationPageArgs,
Expand All @@ -35,6 +36,7 @@ import {
SliceDropdown,
Form,
OneColumnTextSlice,
PowerBiSlice,
} from '@island.is/web/components'
import { CustomNextError } from '@island.is/web/units/errors'
import useContentfulId from '@island.is/web/hooks/useContentfulId'
Expand Down Expand Up @@ -178,6 +180,9 @@ const SubPage: Screen<SubPageProps> = ({
OneColumnText: (slice) => (
<OneColumnTextSlice slice={slice} />
),
PowerBiSlice: (slice: PowerBiSliceSchema) => (
<PowerBiSlice slice={slice} />
),
},
})}
</GridColumn>
Expand Down
13 changes: 11 additions & 2 deletions apps/web/screens/Project/Project.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
Stepper,
stepperUtils,
Form,
PowerBiSlice,
} from '@island.is/web/components'
import {
Box,
Expand Down Expand Up @@ -74,8 +75,9 @@ const ProjectPage: Screen<PageProps> = ({
>(undefined)

let content: SliceType[] = []
if (!!subpage && renderSlicesAsTabs)
if (!!subpage && renderSlicesAsTabs) {
content = selectedSliceTab?.content as SliceType[]
}
if (!subpage) content = projectPage?.content as SliceType[]

useEffect(() => {
Expand Down Expand Up @@ -136,6 +138,7 @@ const ProjectPage: Screen<PageProps> = ({
richText(subpage.content as SliceType[], {
renderComponent: {
Form: (slice) => <Form form={slice} namespace={namespace} />,
PowerBiSlice: (slice) => <PowerBiSlice slice={slice} />,
},
})}
</Box>
Expand Down Expand Up @@ -168,7 +171,13 @@ const ProjectPage: Screen<PageProps> = ({
{selectedSliceTab.title}
</Text>
)}
{content && richText(content)}
{content &&
richText(content, {
renderComponent: {
Form: (slice) => <Form form={slice} namespace={namespace} />,
PowerBiSlice: (slice) => <PowerBiSlice slice={slice} />,
},
})}
{!subpage && projectPage.stepper && (
<Box marginTop={6}>
<Stepper
Expand Down
8 changes: 8 additions & 0 deletions apps/web/screens/queries/fragments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,13 @@ export const slices = gql`
}
}
fragment PowerBiSliceFields on PowerBiSlice {
__typename
id
title
powerBiEmbedProps
}
fragment BaseSlices on Slice {
...TimelineFields
...MailingListSignupFields
Expand Down Expand Up @@ -626,6 +633,7 @@ export const slices = gql`
...GraphCardFields
...LifeEventPageListSliceFields
...SidebarCardFields
...PowerBiSliceFields
}
fragment AllSlices on Slice {
Expand Down
1 change: 1 addition & 0 deletions libs/cms/src/lib/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export default {
'form',
'formField',
'graphCard',
'powerBiSlice',
],
contentful: {
space: process.env.CONTENTFUL_SPACE || '8k0h54kbe6bj',
Expand Down
29 changes: 29 additions & 0 deletions libs/cms/src/lib/generated/contentfulTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2256,6 +2256,7 @@ export interface IOrganizationSubpageFields {
| IMultipleStatistics
| IOneColumnText
| IOverviewLinks
| IPowerBiSlice
| ISliceConnectedComponent
| ITabSection
| ITeamList
Expand Down Expand Up @@ -2385,6 +2386,33 @@ export interface IPageHeader extends Entry<IPageHeaderFields> {
}
}

export interface IPowerBiSliceFields {
/** Title */
title?: string | undefined

/** Config */
config: Record<string, any>
}

/** A Slice that embeds a Power BI report */

export interface IPowerBiSlice extends Entry<IPowerBiSliceFields> {
sys: {
id: string
type: string
createdAt: string
updatedAt: string
locale: string
contentType: {
sys: {
id: 'powerBiSlice'
linkType: 'ContentType'
type: 'Link'
}
}
}
}

export interface IProcessEntryFields {
/** Type */
type:
Expand Down Expand Up @@ -3819,6 +3847,7 @@ export type CONTENT_TYPE =
| 'organizationTag'
| 'overviewLinks'
| 'pageHeader'
| 'powerBiSlice'
| 'processEntry'
| 'projectPage'
| 'projectSubpage'
Expand Down
28 changes: 28 additions & 0 deletions libs/cms/src/lib/models/powerBiSlice.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Field, ID, ObjectType } from '@nestjs/graphql'
import graphqlTypeJson from 'graphql-type-json'
import { SystemMetadata } from '@island.is/shared/types'
import { IPowerBiSlice } from '../generated/contentfulTypes'

@ObjectType()
export class PowerBiSlice {
@Field(() => ID)
id!: string

@Field()
title?: string

@Field(() => graphqlTypeJson, { nullable: true })
powerBiEmbedProps?: Record<string, unknown>
}

export const mapPowerBiSlice = ({
fields,
sys,
}: IPowerBiSlice): SystemMetadata<PowerBiSlice> => {
return {
typename: 'PowerBiSlice',
id: sys.id,
title: fields.title ?? '',
powerBiEmbedProps: fields.config ?? null,
}
}
6 changes: 6 additions & 0 deletions libs/cms/src/lib/unions/slice.union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
IGraphCard,
ILifeEventPageListSlice,
ISidebarCard,
IPowerBiSlice,
} from '../generated/contentfulTypes'
import { Image, mapImage } from '../models/image.model'
import { Asset, mapAsset } from '../models/asset.model'
Expand Down Expand Up @@ -96,6 +97,7 @@ import {
mapLifeEventPageListSlice,
} from '../models/lifeEventPageListSlice.model'
import { mapSidebarCard, SidebarCard } from '../models/sidebarCard.model'
import { PowerBiSlice, mapPowerBiSlice } from '../models/powerBiSlice.model'

type SliceTypes =
| ITimeline
Expand Down Expand Up @@ -129,6 +131,7 @@ type SliceTypes =
| IGraphCard
| ILifeEventPageListSlice
| ISidebarCard
| IPowerBiSlice

export const SliceUnion = createUnionType({
name: 'Slice',
Expand Down Expand Up @@ -167,6 +170,7 @@ export const SliceUnion = createUnionType({
GraphCard,
LifeEventPageListSlice,
SidebarCard,
PowerBiSlice,
],
resolveType: (document) => document.typename, // typename is appended to request on indexing
})
Expand Down Expand Up @@ -236,6 +240,8 @@ export const mapSliceUnion = (slice: SliceTypes): typeof SliceUnion => {
return mapLifeEventPageListSlice(slice as ILifeEventPageListSlice)
case 'sidebarCard':
return mapSidebarCard(slice as ISidebarCard)
case 'powerBiSlice':
return mapPowerBiSlice(slice as IPowerBiSlice)
default:
throw new ApolloError(`Can not convert to slice: ${contentType}`)
}
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@
"pdfkit": "0.11.0",
"pg": "8.1.0",
"pg-hstore": "2.3.3",
"powerbi-client": "2.21.1",
"powerbi-client-react": "1.3.5",
"prom-client": "12.0.0",
"pubsub-js": "1.8.0",
"react": "17.0.2",
Expand Down
Loading

0 comments on commit 6bf6221

Please sign in to comment.