From 97df724ed4da9f502e6b3947d56616a4a7f85650 Mon Sep 17 00:00:00 2001 From: Bloom Date: Tue, 3 Oct 2023 15:19:19 +0200 Subject: [PATCH] =?UTF-8?q?Visuelt=20l=C3=B8ft=20p=C3=A5=20redigeringspane?= =?UTF-8?q?l=20for=20prosjektinformasjon=20(#1272)=20[skip-ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ole Martin Pettersen --- .../RiskActionFieldValue.tsx | 10 +- .../useRiskActionFieldValue.ts | 3 +- .../MigrateRiskActionsDialog.tsx | 2 +- .../src/riskAction/dataAdapter.ts | 2 +- .../ProjectExtensions/src/riskAction/types.ts | 8 +- .../ProjectWebParts/package.json | 3 +- .../BasePanel/BasePanel.module.scss | 6 + .../BasePanel/ClosePanelButton.tsx | 13 +- .../ProjectInformation/BasePanel/index.tsx | 10 +- .../ProjectInformation/BasePanel/types.ts | 6 +- .../EditPropertiesPanel.module.scss | 43 + .../EditPropertiesPanelFooter.module.scss | 2 + .../EditPropertiesPanelFooter/index.tsx | 20 +- .../EditPropertiesPanelFooter/types.ts | 4 +- .../EditPropertiesPanel/useFieldElements.tsx | 186 +- .../EditPropertiesPanel/useModel.ts | 3 +- .../ProjectWebParts/src/loc/_/en-us.js | 2 - .../ProjectWebParts/src/loc/mystrings.d.ts | 13 +- .../ProjectWebParts/src/loc/nb-no.js | 13 +- .../FieldContainer/IconLabel/IconLabel.tsx | 2 +- .../shared-library/src/components/index.ts | 2 +- .../shared-library/src/icons/iconCatalog.ts | 20 +- .../src/models/ProjectInformationField.ts | 7 +- common/config/rush/pnpm-lock.yaml | 3434 +++++++++-------- 24 files changed, 2029 insertions(+), 1785 deletions(-) create mode 100644 SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/BasePanel.module.scss diff --git a/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionFieldValue/RiskActionFieldValue.tsx b/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionFieldValue/RiskActionFieldValue.tsx index 899c5f4a1..523c2e233 100644 --- a/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionFieldValue/RiskActionFieldValue.tsx +++ b/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionFieldValue/RiskActionFieldValue.tsx @@ -14,13 +14,17 @@ import { useRiskActionFieldValue } from './useRiskActionFieldValue' */ export const RiskActionFieldValue: FC = () => { const context = useRiskActionFieldCustomizerContext() - const { isFieldValueSet, isHiddenFieldValueSet, tasks, horizontalLayout, gap } = useRiskActionFieldValue() + const { isFieldValueSet, isHiddenFieldValueSet, tasks, horizontalLayout, gap } = + useRiskActionFieldValue() let element: ReactElement = null if (isHiddenFieldValueSet) { element = ( -
+
{tasks.map((task, index) => ( - + ))}
) diff --git a/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionFieldValue/useRiskActionFieldValue.ts b/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionFieldValue/useRiskActionFieldValue.ts index 5aefafb7a..33c7a110d 100644 --- a/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionFieldValue/useRiskActionFieldValue.ts +++ b/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionFieldValue/useRiskActionFieldValue.ts @@ -11,7 +11,8 @@ export function useRiskActionFieldValue() { const hiddenFieldValue = itemContext.hiddenFieldValue const isFieldValueSet = !stringIsNullOrEmpty(itemContext.fieldValue) const isHiddenFieldValueSet = !stringIsNullOrEmpty(hiddenFieldValue?.data) - const horizontalLayout = dataAdapter.globalSettings.get('RiskActionPlannerHorizontalLayout') === '1' + const horizontalLayout = + dataAdapter.globalSettings.get('RiskActionPlannerHorizontalLayout') === '1' const gap = dataAdapter.globalSettings.get('RiskActionPlannerGap') ?? '0px' return { isFieldValueSet, diff --git a/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionPopover/MigrateRiskActionsDialog/MigrateRiskActionsDialog.tsx b/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionPopover/MigrateRiskActionsDialog/MigrateRiskActionsDialog.tsx index 1f482d2a9..317d0d117 100644 --- a/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionPopover/MigrateRiskActionsDialog/MigrateRiskActionsDialog.tsx +++ b/SharePointFramework/ProjectExtensions/src/riskAction/components/RiskAction/RiskActionPopover/MigrateRiskActionsDialog/MigrateRiskActionsDialog.tsx @@ -23,7 +23,7 @@ import { getFluentIcon } from 'pp365-shared-library' * Migrate risk actions dialog. This dialog is used to migrate risk actions to planner tasks. */ export const MigrateRiskActionsDialog: FC = (props) => { - const { tasks, itemContext, onMigrate, open, setOpen, isMigrating, separator,setSeparator } = + const { tasks, itemContext, onMigrate, open, setOpen, isMigrating, separator, setSeparator } = useMigrateRiskActionsDialog() return ( setOpen(open)}> diff --git a/SharePointFramework/ProjectExtensions/src/riskAction/dataAdapter.ts b/SharePointFramework/ProjectExtensions/src/riskAction/dataAdapter.ts index a07d1822b..cc9097494 100644 --- a/SharePointFramework/ProjectExtensions/src/riskAction/dataAdapter.ts +++ b/SharePointFramework/ProjectExtensions/src/riskAction/dataAdapter.ts @@ -210,7 +210,7 @@ export class DataAdapter extends SPDataAdapterBase { const updatedItemContext = itemContext.update(tasks) await listItem.update({ GtRiskAction: updatedItemContext.fieldValue, - [this.hiddenDataFieldName]: updatedItemContext.hiddenFieldValue.data, + [this.hiddenDataFieldName]: updatedItemContext.hiddenFieldValue.data }) return updatedItemContext } diff --git a/SharePointFramework/ProjectExtensions/src/riskAction/types.ts b/SharePointFramework/ProjectExtensions/src/riskAction/types.ts index e0fee8ccd..a171b1a2d 100644 --- a/SharePointFramework/ProjectExtensions/src/riskAction/types.ts +++ b/SharePointFramework/ProjectExtensions/src/riskAction/types.ts @@ -44,9 +44,9 @@ export class RiskActionItemContext { /** * Updates the current RiskActionItemContext with the provided tasks. - * + * * @param tasks An array of RiskActionPlannerTaskReference objects to update the context with. - * + * * @returns The updated RiskActionItemContext object. */ public update(tasks: RiskActionPlannerTaskReference[]): RiskActionItemContext { @@ -61,11 +61,11 @@ export class RiskActionItemContext { /** * Creates a new instance of the RiskActionItemContext class. - * + * * @param event - The field customizer cell event parameters. * @param pageContext - The SharePoint page context. * @param hiddenFieldValues - The hidden field values. - * + * * @returns A new instance of the RiskActionItemContext class. */ public static create( diff --git a/SharePointFramework/ProjectWebParts/package.json b/SharePointFramework/ProjectWebParts/package.json index fc87258c0..505783994 100644 --- a/SharePointFramework/ProjectWebParts/package.json +++ b/SharePointFramework/ProjectWebParts/package.json @@ -62,7 +62,8 @@ "@fluentui/react-icons": "2.0.215", "@fluentui/react-search-preview": "0.1.16", "@fluentui/react-tags-preview": "0.2.9", - "usehooks-ts": "~2.9.1" + "usehooks-ts": "~2.9.1", + "@fluentui/react-datepicker-compat": "~0.3.15" }, "devDependencies": { "@microsoft/eslint-config-spfx": "1.17.4", diff --git a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/BasePanel.module.scss b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/BasePanel.module.scss new file mode 100644 index 000000000..7fe13820c --- /dev/null +++ b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/BasePanel.module.scss @@ -0,0 +1,6 @@ +.root { + display: flex; + flex-direction: column; + gap: 16px; + padding: 20px 24px; +} diff --git a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/ClosePanelButton.tsx b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/ClosePanelButton.tsx index 4688cd0ce..b7c97b64d 100644 --- a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/ClosePanelButton.tsx +++ b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/ClosePanelButton.tsx @@ -1,21 +1,20 @@ -import { DefaultButton } from '@fluentui/react' import strings from 'ProjectWebPartsStrings' import React, { FC } from 'react' import { useProjectInformationContext } from '../context' import { CLOSE_PANEL } from '../reducer' -import { IClosePanelButtonProps } from './types' +import { Button, ButtonProps } from '@fluentui/react-components' -export const ClosePanelButton: FC = (props) => { +export const ClosePanelButton: FC = (props) => { const context = useProjectInformationContext() return ( - { props.onClick && props.onClick(e) context.dispatch(CLOSE_PANEL()) }} - /> + > + {strings.CancelText} + ) } diff --git a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/index.tsx b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/index.tsx index bc32a8b39..30b3e0bfe 100644 --- a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/index.tsx +++ b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/index.tsx @@ -4,10 +4,10 @@ import React, { FC } from 'react' import { useProjectInformationContext } from '../context' import { CLOSE_PANEL } from '../reducer' import { IBasePanelProps } from './types' -import { FluentProvider, useId, webLightTheme } from '@fluentui/react-components' +import { FluentProvider, webLightTheme } from '@fluentui/react-components' +import styles from './BasePanel.module.scss' export const BasePanel: FC = (props) => { - const fluentProviderId = useId('fluent-provider') const context = useProjectInformationContext() return ( @@ -17,11 +17,7 @@ export const BasePanel: FC = (props) => { onRenderBody={() => { if (!props.onRenderBody) return null return ( - + {props.onRenderBody()} ) diff --git a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/types.ts b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/types.ts index ee78b67ae..39f6a9c17 100644 --- a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/types.ts +++ b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/BasePanel/types.ts @@ -1,4 +1,4 @@ -import { IButtonProps, IPanelProps } from '@fluentui/react' +import { IPanelProps } from '@fluentui/react' import { ProjectInformationPanelType } from '../types' export interface IBasePanelProps extends IPanelProps { @@ -8,7 +8,3 @@ export interface IBasePanelProps extends IPanelProps { */ $type?: ProjectInformationPanelType } - -export interface IClosePanelButtonProps extends IButtonProps { - noMargin?: boolean -} diff --git a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanel.module.scss b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanel.module.scss index 06586020a..c6132d4d4 100644 --- a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanel.module.scss +++ b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanel.module.scss @@ -1,3 +1,46 @@ .root { margin: 0; + + .field { + min-height: 32px; + border-radius: var(--borderRadiusMedium); + position: relative; + box-sizing: border-box; + padding: 0 var(--pacingHorizontalMNudge); + background-color: var(--colorNeutralBackground1); + border: 1px solid var(--colorNeutralStroke1); + border-bottom-color: var(--colorNeutralStrokeAccessible); + + &::after { + box-sizing: border-box; + content: ''; + position: absolute; + left: -1px; + bottom: -1px; + right: -1px; + border-bottom-left-radius: var(--borderRadiusMedium); + border-bottom-right-radius: var(--borderRadiusMedium); + border-bottom: 2px solid var(--colorCompoundBrandStroke); + clip-path: inset(calc(100% - 2px) 0px 0px); + transform: scaleX(0); + transition-property: transform; + transition-duration: var(--durationUltraFast); + transition-delay: var(--curveAccelerateMid); + } + + &:focus-within::after { + transform: scaleX(1); + transition-property: transform; + transition-duration: var(--durationNormal); + transition-delay: var(curveDecelerateMid); + } + + &:focus-within:active::after { + border-bottom-color: (--colorCompoundBrandStrokePressed); + } + + &:focus-within { + outline: 2px solid transparent; + } + } } diff --git a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/EditPropertiesPanelFooter.module.scss b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/EditPropertiesPanelFooter.module.scss index 334d1c0c0..c528f7138 100644 --- a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/EditPropertiesPanelFooter.module.scss +++ b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/EditPropertiesPanelFooter.module.scss @@ -1,9 +1,11 @@ .root { margin: 0; + padding: 12px 0; .container { display: flex; flex-direction: row; + gap: 12px; } .saveStatusSpinner { diff --git a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/index.tsx b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/index.tsx index 57270c502..2c062233f 100644 --- a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/index.tsx +++ b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/index.tsx @@ -1,10 +1,10 @@ -import { PrimaryButton, Spinner, SpinnerSize } from '@fluentui/react' import strings from 'ProjectWebPartsStrings' import React, { FC } from 'react' import { ClosePanelButton } from '../../BasePanel' import { IEditPropertiesPanelFooterProps } from './types' import styles from './EditPropertiesPanelFooter.module.scss' import { UserMessage } from 'pp365-shared-library/lib/components' +import { Button, FluentProvider, Spinner, useId, webLightTheme } from '@fluentui/react-components' /** * Renders the footer for the `EditPropertiesPanel` with a `` for saving the changes, @@ -14,20 +14,24 @@ import { UserMessage } from 'pp365-shared-library/lib/components' * @param props The component props. */ export const EditPropertiesPanelFooter: FC = (props) => { + const fluentProviderId = useId('fluent-provider') const isSaving = !!props.submit.saveStatus + return ( -
+ {props.submit.error && (
)}
- + > + {strings.SaveText} + { props.model.reset() @@ -40,13 +44,13 @@ export const EditPropertiesPanelFooter: FC = (p
)}
-
+ ) } EditPropertiesPanelFooter.defaultProps = { spinner: { - labelPosition: 'right', - size: SpinnerSize.medium + labelPosition: 'after', + size: 'medium' } } diff --git a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/types.ts b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/types.ts index 9d60dafee..e16398e22 100644 --- a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/types.ts +++ b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/EditPropertiesPanelFooter/types.ts @@ -1,6 +1,6 @@ -import { ISpinnerProps } from '@fluentui/react' import { UseModelReturnType } from '../useModel' import { UseSubmitReturnType } from '../useSubmit' +import { SpinnerProps } from '@fluentui/react-components' export interface IEditPropertiesPanelFooterProps { /** @@ -16,5 +16,5 @@ export interface IEditPropertiesPanelFooterProps { /** * Spinner props. */ - spinner?: ISpinnerProps + spinner?: SpinnerProps } diff --git a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/useFieldElements.tsx b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/useFieldElements.tsx index b513b9d1d..5de1fbae3 100644 --- a/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/useFieldElements.tsx +++ b/SharePointFramework/ProjectWebParts/src/components/ProjectInformation/EditPropertiesPanel/useFieldElements.tsx @@ -1,20 +1,13 @@ -import { - DatePicker, - DayOfWeek, - Dropdown, - IPersonaProps, - ITag, - Label, - NormalPeoplePicker, - TagPicker, - TextField, - Toggle -} from '@fluentui/react' +import { IPersonaProps, ITag, NormalPeoplePicker, TagPicker } from '@fluentui/react' +import { Combobox, Input, Option, Switch, Textarea } from '@fluentui/react-components' +import { DatePicker, DayOfWeek } from '@fluentui/react-datepicker-compat' import strings from 'ProjectWebPartsStrings' -import { FieldDescription } from 'pp365-shared-library/lib/components' +import _ from 'lodash' +import { FieldContainer } from 'pp365-shared-library' import { ProjectInformationField } from 'pp365-shared-library/lib/models' import React from 'react' import SPDataAdapter from '../../../data' +import styles from './EditPropertiesPanel.module.scss' import { UseModelReturnType } from './useModel' /** @@ -38,14 +31,16 @@ import { UseModelReturnType } from './useModel' export function useFieldElements(model: UseModelReturnType) { const fieldElements: Record JSX.Element> = { Boolean: (field) => ( - <> - + (field)} - onChange={(_, checked) => model.set(field, checked)} + onChange={(_, data) => model.set(field, data.checked)} /> - - + ), URL: (field) => { const value = model.get<{ @@ -53,89 +48,114 @@ export function useFieldElements(model: UseModelReturnType) { description: string }>(field, { url: '', description: '' }) return ( - <> - - + model.set(field, { url, description: value.description })} + onChange={(_, data) => + model.set(field, { url: data.value, description: value.description }) + } + placeholder={strings.Placeholder.UrlField} /> - model.set(field, { url: value.url, description })} - styles={{ root: { marginTop: 6 } }} + onChange={(_, data) => model.set(field, { url: value.url, description: data.value })} + placeholder={strings.Placeholder.UrlFieldAlternative} + style={{ marginTop: 6 }} /> - - + ) }, Text: (field) => ( - (field)} - onChange={(_, value) => model.set(field, value)} - /> + > + (field)} + onChange={(_, data) => model.set(field, data.value)} + placeholder={strings.Placeholder.TextField} + /> + ), Note: (field) => ( - (field)} - onChange={(_, value) => model.set(field, value)} - /> + > +