Skip to content

Commit

Permalink
Sharedialog New Control (#1897)
Browse files Browse the repository at this point in the history
* commitc hanges

* commit chnages

* commit changes ShareDialog

* commit changes fixed comments docs and code.
  • Loading branch information
joaojmendes authored Dec 12, 2024
1 parent 4bc2eaa commit eba3fe7
Show file tree
Hide file tree
Showing 7 changed files with 271 additions and 0 deletions.
Binary file added docs/documentation/docs/assets/ShareDialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 73 additions & 0 deletions docs/documentation/docs/controls/ShareDialog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# ShareDialog Control

The `ShareDialog` control is a convenient way to integrate Office Online's share dialog into your solution, allowing users to share content such as documents, lists, directly from your application.

## Example Usage

Here is how you can use the `ShareDialog` control in your application.

### Share Button

![ShareDialog](../assets/ShareDialog.png)

## How to Use This Control

### 1. Install the Dependency

Ensure you have installed the `@pnp/spfx-controls-react` dependency. Refer to the [getting started](../../#getting-started) page for more details on installing the dependency.

### 2. Import the Control

Import the `ShareDialog` control into your component:

```typescript
import { ShareDialog } from "@pnp/spfx-controls-react/lib/ShareDialog";

<ShareDialog
context={this.props.context}
siteUrl={'https://contoso.sharepoint.com/sites/sitecollection'}
listId={'list-id'}
itemId={123}
name={'Document Name'}
onClose={() => { console.log('Dialog closed'); }}
/>
```

## Implementation

The `ShareDialog` control can be configured with the following properties:

| Property | Type | Required | Description |
|-----------|----------------|----------|---------------------------------------------------------|
| isOpen | boolean | yes | open or close Dialog |
| options | IDialogOptions | yes | ShareDialog Options |
| onClose | function | yes | Callback function executed when the dialog is closed. |

### Interface `IDialogOptions`

| Property | Type | Required | Description |
|----------|----------------|----------|-------------------------------------------|
| siteUrl | string | yes | URL of the site where the item is located.|
| listId | string | yes | ID of the list containing the item. |
| itemId | string/number | yes | ID of the item to be shared. |
| name | string | yes | Name of the item to be shared. |

### Example `IDialogOptions` Usage

```typescript
const dialogOptions: IDialogOptions = {
siteUrl: 'https://contoso.sharepoint.com/sites/sitecollection',
listId: 'list-id',
itemId: 123,
name: 'Document Name'
};

<ShareDialog
isOpen: true,
options: dialogOptions.
onClose={() => { console.log('Dialog closed'); }}
/>

```

![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/ShareDialog)
1 change: 1 addition & 0 deletions src/ShareDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './controls/shareDialog/index';
121 changes: 121 additions & 0 deletions src/controls/shareDialog/ShareDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import * as React from 'react';
import {
useCallback,
useEffect,
useRef,
useState,
} from 'react';

import { css } from '@emotion/css';

import { RenderDialog } from './renderDialog';

const useStyles = (iFrameHeight: number) => {
const styles = {
iframe: css({
width: "100%",
height: iFrameHeight,
border: "none",
}),
};
return { styles };
};

interface IEventData {
name: string;
command: string;
width: number;
height: number;
}

interface IDialogOptions {
siteUrl: string;
listId: string;
itemId: string | number;
name: string;
}

interface ShareDialogProps {
isOpen: boolean;
options: IDialogOptions;
onClose: () => void;
}

export const ShareDialog: React.FC<ShareDialogProps> = ({ isOpen, options, onClose }) => {
const [dialogUrl, setDialogUrl] = useState<string | undefined>(undefined);
const iframeRef = useRef<HTMLIFrameElement>(null);
const [iFrameHeight, setIFrameHeight] = useState<number>(400);

const { siteUrl, listId, itemId, name } = options;
const { styles } = useStyles(iFrameHeight);

const closeDialog = useCallback(() => {
onClose();
}, [onClose]);

const handleIframeMessage = useCallback(
(event: MessageEvent) => {
const { name, height } = JSON.parse(event.data) as IEventData;
switch (name) {
case "share_dismiss":
closeDialog();
break;
case "share_resize":
setIFrameHeight(height);
break;
case "share_scriptsLoaded":
break;
case "share_uiReady":
break;
case "share_ready":
break;
default:
break;
}
},
[closeDialog]
);

useEffect(() => {
window.addEventListener("message", handleIframeMessage);
return () => {
window.removeEventListener("message", handleIframeMessage);
};
}, [handleIframeMessage]);

useEffect(() => {
if (isOpen) {
const clientId = "sharePoint";
const policyTip = 0;
const folderColor = "";
const clickTime = new Date().getTime();
const fullScreenMode = false;
const origin = encodeURIComponent(window.location.origin);
const encodeName = encodeURIComponent(name as string);

const url =
`${siteUrl}/_layouts/15/sharedialog.aspx` +
`?listId=${listId}` +
`&listItemId=${itemId}` +
`&clientId=${clientId}` +
`&policyTip=${policyTip}` +
`&folderColor=${folderColor}` +
`&clickTime=${clickTime}` +
`&ma=0` +
`&fullScreenMode=${fullScreenMode}` +
`&itemName= ${encodeName}` +
`&channelId=` +
`&origin=${origin}`;
setDialogUrl(url);
} else {
setDialogUrl(undefined);
}
}, [isOpen, siteUrl, listId, itemId]);

return (
<RenderDialog isOpen={isOpen} onDismiss={closeDialog} maxHeight={"fit-content"}>
<iframe ref={iframeRef} src={dialogUrl || ""} className={styles.iframe} />
</RenderDialog>
);
};
1 change: 1 addition & 0 deletions src/controls/shareDialog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './ShareDialog';
74 changes: 74 additions & 0 deletions src/controls/shareDialog/renderDialog/RenderDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */
import * as React from 'react';

import { css } from '@emotion/css';
import {
Dialog,
DialogActions,
DialogBody,
DialogContent,
DialogSurface,
DialogTitle,
} from '@fluentui/react-components';

export interface IRenderDialogProps {
isOpen: boolean;
dialogTitle?: string | React.ReactNode;
dialogActions?: JSX.Element;
onDismiss?: (open?: boolean) => void;
minWidth?: number | string;
maxWidth?: number | string;
className?: string;
minHeight?: number | string;
maxHeight?: number | string;
}

const DEFAULT_MIN_WIDTH = 200;

const DEFAULT_MIN_HEIGHT = 200;

const useStyles = (props:IRenderDialogProps) => {
const styles = {
dialog: css({
width: "100%",
height: "100%",
overflow: "hidden" as never,
maxHeight: "600px",
padding: 0 as never,
}),
dialogBody: css({
height: "calc(100% - 200px)",
}),
};
return { styles };
};

export const RenderDialog: React.FunctionComponent<IRenderDialogProps> = (
props: React.PropsWithChildren<IRenderDialogProps>
) => {
const { isOpen, dialogTitle, dialogActions, children, maxWidth, className, minHeight, minWidth, maxHeight } = props;
const {styles} = useStyles(props);
if (!isOpen) return <></>;
return (
<Dialog open={isOpen} modalType="modal">
<DialogSurface
className={css(styles.dialog, className)}
style={{
maxWidth: maxWidth,
minWidth: minWidth ?? DEFAULT_MIN_WIDTH,
minHeight: minHeight ?? DEFAULT_MIN_HEIGHT,
height: "fit-content",
maxHeight: maxHeight ?? "",
}}
>
<DialogTitle>{dialogTitle}</DialogTitle>
<DialogBody className={styles.dialogBody}>
<DialogContent>{children}</DialogContent>
</DialogBody>
<DialogActions fluid position="end">
{dialogActions}
</DialogActions>
</DialogSurface>
</Dialog>
);
};
1 change: 1 addition & 0 deletions src/controls/shareDialog/renderDialog/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './RenderDialog';

0 comments on commit eba3fe7

Please sign in to comment.