Skip to content

Commit

Permalink
Readonly share dialog for shared with me items (jupyter-server#459)
Browse files Browse the repository at this point in the history
  • Loading branch information
sathishlxg authored and Zsailer committed Nov 8, 2022
1 parent cdf71f0 commit efebf2c
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 84 deletions.
43 changes: 29 additions & 14 deletions src/publish_notebooks/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,25 @@ import { AutoSuggestionInput } from './auto_suggestion';

type Props = {
author: Contact;
isReadOnly: boolean;
onChange: (v: Contact[]) => void;
client: PublishingExtensionClient;
collaborators: ICollaborators[] | undefined;
collaborators: ICollaborators[] | null;
};

export const ShareNotebooksComponent: FC<Props> = ({
onChange,
author,
client,
isReadOnly,
collaborators = []
}) => {
const [query, setQuery] = useState('');
const searchQuery = useDebounce(query, 100);
const [value, setValue] = useState<Contact[]>([]);
const [people, setPeople] = useState(collaborators);
const [people, setPeople] = useState(collaborators || []);
const [contacts, setContacts] = useState<Contact[]>([]);
const owner = useMemo(() => collaborators.find(c => c.id === author.id), []);
const owner = useMemo(() => collaborators?.find(c => c.id === author.id), []);

useEffect(() => {
const fetchContacts = async (input: string) => {
Expand Down Expand Up @@ -66,16 +68,25 @@ export const ShareNotebooksComponent: FC<Props> = ({

return (
<>
<p>
This document has been published to Data Studio's document sharing
service. You can now share this document with others.
</p>
<AutoSuggestionInput
value={value}
contacts={contacts}
onChange={handleChange}
onSearch={handleSearchQuery}
/>
{isReadOnly ? (
<p className="header-info">
You're a viewer and can't share. Please request owner to share with
others
</p>
) : (
<>
<p>
This document has been published to Data Studio's document sharing
service. You can now share this document with others.
</p>
<AutoSuggestionInput
value={value}
contacts={contacts}
onChange={handleChange}
onSearch={handleSearchQuery}
/>
</>
)}
<div className="list-header">People with access</div>
<ul className="list">
{owner && (
Expand All @@ -96,7 +107,11 @@ export const ShareNotebooksComponent: FC<Props> = ({
<div>{item.name}</div>
<div>{item.email}</div>
</div>
<button onClick={() => handleRemove(item.email)}>Remove</button>
{isReadOnly ? null : (
<button onClick={() => handleRemove(item.email)}>
Remove
</button>
)}
</li>
);
})}
Expand Down
14 changes: 6 additions & 8 deletions src/publish_notebooks/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,14 @@ function addShareNotebookCommand(
};

const handleShareExecute = async (args: ReadonlyPartialJSONObject) => {
const { isReadOnly, title: fileName } = args;
const title = `${isReadOnly ? 'View' : 'Share'} "${fileName}"`;

const dialog = new PublishDialog({
title,
buttons,
actionHandlers,
hasClose: true,
title: `Share "${args.title}"`,
body: new ShareNotebooksWidget(
(args as unknown) as IPublishedFileMetadata,
publishingClient
Expand All @@ -94,12 +97,9 @@ function addShareNotebookCommand(

const result = await dialog.launch();

if (result.value) {
if (result.value && !args.isReadOnly) {
publishingClient.updateFile(result.value.value);
}

// TODO: Send data to API
console.log(result);
};

app.commands.addCommand(CommandIDs.shareCommandID, {
Expand All @@ -117,9 +117,7 @@ function addPreviewCommand(
publishingClient: PublishingExtensionClient
) {
const handleExecute = async (args: ReadonlyPartialJSONObject) => {
// TODO: Use file ID instead of shareable_link
const widgetId = (args.shareable_link as string) || '';
// const path: string = (args.shareable_link as string) || '';
const widgetId = args.id as string;
const fileId: string = (args.id as string) || '';
const widgetExists = previewTracker.find(w => w.id === widgetId);
const title = `Preview - ${args.title}`;
Expand Down
1 change: 1 addition & 0 deletions src/publish_notebooks/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface IPublishedFileMetadata {
shareable_link: string;
collaborators?: Array<ICollaborators>;
content?: IJupyterContentsModel;
isReadOnly?: boolean;
}

export interface IShareDialogBody {
Expand Down
5 changes: 4 additions & 1 deletion src/publish_notebooks/widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class ShareNotebooksWidget extends ReactWidget {
super();
this._value = [];
this._data = data;
this._isReadOnly = Boolean(data.isReadOnly);
this.handleChange = this.handleChange.bind(this);
this._publishingClient = publishingClient;
this._author = tryParse(this._data.author);
Expand Down Expand Up @@ -90,16 +91,18 @@ export class ShareNotebooksWidget extends ReactWidget {
render(): JSX.Element {
return (
<ShareNotebooksComponent
isReadOnly={this._isReadOnly}
onChange={this.handleChange}
author={this._author}
client={this._publishingClient}
collaborators={this._data.collaborators}
collaborators={this._data.collaborators || []}
/>
);
}

_author: Contact;
_value: Contact[];
_isReadOnly = false;
_data: IPublishedFileMetadata;
private _publishingClient: PublishingExtensionClient;
}
Expand Down
2 changes: 1 addition & 1 deletion src/shared_notebooks/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export const SharedNotebooks: React.FC<SharedNotebooksProp> = ({
key={index}
name={item.title}
title={item.title}
onShare={onShare.bind(null, item)}
onPreview={onPreview.bind(null, item)}
onShare={onShare.bind(null, { ...item, isReadOnly: true })}
/>
))}
</SharedNotebooksList>
Expand Down
38 changes: 34 additions & 4 deletions src/shared_notebooks/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import { SharedNotebooksWidget } from './widget';

import { LabIcon } from '@jupyterlab/ui-components';
import shareIconSvg from '../../style/icons/share_icon.svg';
import { SharedNotebooksModel } from './model';
import { IPublishedFileMetadata, SharedNotebooksModel } from './model';
import { ReadonlyPartialJSONObject } from '@lumino/coreutils';
import { BoxLayout, Panel } from '@lumino/widgets';
import { Dialog, showErrorMessage, Spinner } from '@jupyterlab/apputils';

const shareIcon = new LabIcon({
name: 'publish:shareIcon',
Expand All @@ -22,16 +24,44 @@ async function activate(
labShell: ILabShell,
restorer: ILayoutRestorer
): Promise<void> {
const onDialogOpen = (args: unknown) =>
app.commands.execute('publishing:share', args as ReadonlyPartialJSONObject);
const model = new SharedNotebooksModel();

const onDialogOpen = async (args: unknown) => {
const box = new BoxLayout();
const { id, title: fileName, isReadOnly } = args as IPublishedFileMetadata;

box.addWidget(new Spinner());

const title = `Sharing "${fileName}"`;
const loading = new Dialog({
title,
buttons: [],
hasClose: false,
body: new Panel({ layout: box })
});

loading.launch();

try {
const data = await model.getFile(id);

app.commands.execute('publishing:share', ({
...data,
isReadOnly
} as unknown) as ReadonlyPartialJSONObject);
} catch (error) {
showErrorMessage('Sharing failed', error);
} finally {
loading.close();
}
};

const onPreviewFile = (args: unknown) =>
app.commands.execute(
'publishing:download',
args as ReadonlyPartialJSONObject
);

const model = new SharedNotebooksModel();
const sharedNotebooks = new SharedNotebooksWidget(model, {
onDialogOpen,
onPreviewFile
Expand Down
Loading

0 comments on commit efebf2c

Please sign in to comment.