Skip to content

Commit

Permalink
Bestillingsløsning (Provisjonering) (#1541)
Browse files Browse the repository at this point in the history
* Initial webpart

* Linting

* Add inital Drawer with mvp content

* Add correct config file

* Add dialog with privision status

* Improvements to provision status dialog + actions

* Finish the barebones

* Restructure, add context and state machine

* More restructuring

* Minor adjustments

* Add setColumn functionality for the fields in the drawer

* Finish all the different types of input fields

* Add validation check for guest emails

* Add ability to create provision request from any given provision site

* Run rush after rebase...

* Add function to ensure users from the provision site

* Add remaining fields for onSave

* Minor adjustments

* Dynamically get siteTypes

* Add toaster

* Add strings locale + minor adjustments

* Finishing touches

* Add "Teamify" option

* Rebase with latest 1.10
  • Loading branch information
Remi749 authored Jun 10, 2024
1 parent 52ce3e4 commit ec2f2e1
Show file tree
Hide file tree
Showing 47 changed files with 3,783 additions and 1,536 deletions.
4 changes: 2 additions & 2 deletions SharePointFramework/.tasks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
"yargs": "17.7.2",
"glob": "10.2.6",
"colors": "1.4.0",
"@fluentui/react-components": "~9.50.0",
"@fluentui/react-icons": "~2.0.239"
"@fluentui/react-components": "~9.52.0",
"@fluentui/react-icons": "~2.0.240"
},
"devDependencies": {
"@types/lodash": "4.14.195",
Expand Down
4 changes: 2 additions & 2 deletions SharePointFramework/PortfolioExtensions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
"underscore": "~1.13.6",
"@pnp/queryable": "3.17.0",
"sp-entityportal-service": "2.3.0",
"@fluentui/react-components": "~9.50.0",
"@fluentui/react-icons": "~2.0.239"
"@fluentui/react-components": "~9.52.0",
"@fluentui/react-icons": "~2.0.240"
},
"devDependencies": {
"@microsoft/eslint-config-spfx": "1.17.4",
Expand Down
8 changes: 8 additions & 0 deletions SharePointFramework/PortfolioWebParts/config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@
"manifest": "./src/webparts/portfolioAggregation/manifest.json"
}
]
},
"project-provision-web-part": {
"components": [
{
"entrypoint": "./lib/webparts/projectProvision/index.js",
"manifest": "./src/webparts/projectProvision/manifest.json"
}
]
}
},
"externals": {},
Expand Down
7 changes: 4 additions & 3 deletions SharePointFramework/PortfolioWebParts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,14 @@
"@pnp/core": "3.17.0",
"@pnp/queryable": "3.17.0",
"sp-entityportal-service": "2.3.0",
"@fluentui/react-components": "~9.50.0",
"@fluentui/react-icons": "~2.0.239",
"@fluentui/react-components": "~9.52.0",
"@fluentui/react-icons": "~2.0.240",
"use-image-color": "~0.0.9",
"react-error-boundary": "~4.0.11",
"react-window": "~1.8.10",
"react-virtualized-auto-sizer": "~1.0.24",
"@fluentui/react-datepicker-compat": "~0.4.36"
"@fluentui/react-datepicker-compat": "~0.4.38",
"@fluentui/react-motion-preview": "~0.5.20"
},
"devDependencies": {
"@microsoft/eslint-config-spfx": "1.17.4",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import {
Menu,
MenuButtonProps,
MenuItem,
MenuList,
MenuPopover,
MenuTrigger,
Skeleton,
SkeletonItem,
SplitButton,
Toaster,
useId,
useRestoreFocusTarget,
useToastController
} from '@fluentui/react-components'
import React, { FC } from 'react'
import { IProjectProvisionProps } from './types'
import { getFluentIcon } from 'pp365-shared-library'
import { ProvisionStatus } from './ProvisionStatus'
import { useProjectProvision } from './useProjectProvision'
import { ProjectProvisionContext } from './context'
import { ProvisionDrawer } from './ProvisionDrawer'
import strings from 'PortfolioWebPartsStrings'

export const ProjectProvision: FC<IProjectProvisionProps> = (props) => {
const { state, setState, column, setColumn } = useProjectProvision(props)
const restoreFocusTargetAttribute = useRestoreFocusTarget()
const toasterId = useId('saveToaster')
const { dispatchToast } = useToastController(toasterId)

if (state.loading) {
return (
<Skeleton>
<SkeletonItem style={{ width: '192px', height: '40px' }} />
</Skeleton>
)
}

return (
<ProjectProvisionContext.Provider value={{ props, state, setState, column, setColumn }}>
<ProvisionDrawer toast={dispatchToast} />
<Menu positioning='below-end'>
<MenuTrigger disableButtonEnhancement>
{(triggerProps: MenuButtonProps) => (
<SplitButton
menuButton={triggerProps}
primaryActionButton={{
onClick: () => setState({ showProvisionDrawer: true })
}}
icon={getFluentIcon('Add')}
appearance='primary'
size='large'
>
{strings.Provision.ProvisionButtonLabel}
</SplitButton>
)}
</MenuTrigger>
<MenuPopover>
<MenuList>
<MenuItem
{...restoreFocusTargetAttribute}
onClick={() => {
setState({ showProvisionStatus: true })
}}
>
{strings.Provision.StatusMenuLabel}
</MenuItem>
<MenuItem>{strings.Provision.IdeaMenuLabel}</MenuItem>
</MenuList>
</MenuPopover>
</Menu>
<ProvisionStatus />
<Toaster toasterId={toasterId} />
</ProjectProvisionContext.Provider>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { FC } from 'react'
import { useProjectProvisionContext } from '../context'

/**
* Shows `model.properties` in a `pre` tag.
*/
export const DebugModel: FC = () => {
const context = useProjectProvisionContext()
return (
<div>
<pre
style={{
whiteSpace: 'pre-wrap',
wordWrap: 'break-word',
background: 'rgba(0,0,0,0.1)',
padding: 10,
borderRadius: 5
}}
>
{JSON.stringify(context.state.properties, null, 2)}
</pre>
</div>
)
}

DebugModel.displayName = 'DebugModel'
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {
TagPickerProps,
useTagPickerFilter,
TagPickerOption,
Avatar,
Tag,
TagPicker,
TagPickerControl,
TagPickerGroup,
TagPickerInput,
TagPickerList
} from '@fluentui/react-components'
import strings from 'PortfolioWebPartsStrings'
import { useProjectProvisionContext } from 'components/ProjectProvision/context'
import React, { useState } from 'react'

export const Guest = (props: { disabled?: boolean }) => {
const context = useProjectProvisionContext()
const [query, setQuery] = useState<string>('')
const [selectedGuests, setSelectedGuests] = useState<string[]>(context.column.get('guest') || [])
const options = [query]

const onOptionSelect: TagPickerProps['onOptionSelect'] = (_, data) => {
if (data.value === 'no-matches') {
return
}

if (query && (!query.includes('@') || !query.includes('.'))) {
return
}

if (!data.selectedOptions.find((option) => option === data.value)) {
context.setColumn(
'guest',
context.column.get('guest').filter((guest) => guest !== data.value)
)
} else {
context.setColumn('guest', [...context.column.get('guest'), data.value])
}

if (!data.selectedOptions) {
context.setColumn('guest', [])
}

setSelectedGuests(data.selectedOptions)
setQuery('')
}

const children = useTagPickerFilter({
query,
options,
noOptionsElement: (
<TagPickerOption value='no-matches'>
{strings.Provision.GuestFieldNoOptionsText}
</TagPickerOption>
),
renderOption: (guest) => {
return (
<TagPickerOption
key={guest}
value={guest}
media={<Avatar aria-hidden name={guest} color='colorful' />}
>
{guest}
</TagPickerOption>
)
},
filter: (option) =>
!selectedGuests.includes(option) && option.toLowerCase().includes(query.toLowerCase())
})

return (
<div>
<TagPicker
onOptionSelect={onOptionSelect}
selectedOptions={selectedGuests}
disabled={props.disabled}
>
<TagPickerControl>
<TagPickerGroup>
{selectedGuests.map((guest) => (
<Tag
key={guest}
media={<Avatar aria-hidden name={guest} color='colorful' />}
value={guest}
>
{guest}
</Tag>
))}
</TagPickerGroup>
<TagPickerInput
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder={strings.Placeholder.GuestField}
/>
</TagPickerControl>
<TagPickerList>{children}</TagPickerList>
</TagPicker>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './Guest'
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.toolbar {
justify-content: space-between;
}

.body {
flex: 1;
width: 100%;
max-width: 100%;
position: relative;

.content {
display: flex;
flex-direction: column;
gap: 16px;

.sitetypes {
display: flex;
gap: 12px;
flex-wrap: wrap;
}

.ignoreGap {
margin-top: 0;
margin-bottom: 0;
}

.footer {
margin: 12px 0 0 0;
}

.flexContent {
display: flex;
flex-direction: row;
gap: 16px;
}
}

.level {
position: "absolute";
top: 0;
left: 0;
right: 0;
bottom: 0;

&:first-child {
padding-top: 0;
}

&:last-child {
padding-bottom: 0;
}
}
}

.footer {
justify-content: space-between;
}
Loading

0 comments on commit ec2f2e1

Please sign in to comment.