Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: Separated Add Resources to checklist #6386

Merged
merged 11 commits into from
Mar 18, 2021
4 changes: 3 additions & 1 deletion extensions/azurePublish/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,13 @@
"@azure/ms-rest-js": "^2.0.7",
"@azure/ms-rest-nodeauth": "3.0.3",
"@bfc/built-in-functions": "../../Composer/packages/tools/built-in-functions",
"@bfc/ui-shared": "../../Composer/packages/lib/ui-shared",
"@bfc/code-editor": "../../Composer/packages/lib/code-editor",
"@bfc/extension-client": "file:../../Composer/packages/extension-client",
"@bfc/indexers": "../../Composer/packages/lib/indexers",
"@bfc/shared": "../../Composer/packages/lib/shared",
"@bfc/ui-shared": "../../Composer/packages/lib/ui-shared",
"@emotion/core": "^10.0.27",
"@emotion/styled": "^10.0.27",
"adal-node": "0.2.1",
"archiver": "^5.0.2",
"axios": "^0.21.1",
Expand Down
161 changes: 161 additions & 0 deletions extensions/azurePublish/src/components/ChooseResourcesList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import * as React from 'react';
import styled from '@emotion/styled';
import { Stack } from 'office-ui-fabric-react/lib/Stack';
import { Text } from 'office-ui-fabric-react/lib/Text';
import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
import { FluentTheme, NeutralColors } from '@uifabric/fluent-theme';
import { FocusZone, FocusZoneDirection } from 'office-ui-fabric-react/lib/FocusZone';
import { List } from 'office-ui-fabric-react/lib/List';

import { ResourcesItem } from '../types';

// ---------- Styles ---------- //

const ItemCheckbox = styled(Checkbox)`
margin: 4px 10px 0 0;
padding: 5px;
`;

const checkBoxStyle = {
label: {
alignItems: 'flex-start',
},
};

const ItemLabel = styled(Stack)`
margin-left: 15px !important;
GeoffCoxMSFT marked this conversation as resolved.
Show resolved Hide resolved
`;

const ItemHeader = styled(Stack)``;

const ImageIcon = styled.img`
width: 16px;
height: 16px;
margin: 4px 0 0 0;
user-select: none;
`;

const ImageIconPlacholder = styled.div`
width: 16px;
height: 16px;
margin: 4px 0 0 0;
user-select: none;
`;

const ItemText = styled(Text)`
font-size: ${FluentTheme.fonts.mediumPlus.fontSize};
margin-left: 4px !important;
GeoffCoxMSFT marked this conversation as resolved.
Show resolved Hide resolved
`;

const ItemTier = styled(Text)`
font-size: ${FluentTheme.fonts.small.fontSize};
margin: 4px 0 0 22px;
color: ${NeutralColors.gray130};
`;

const ItemDescription = styled(Text)`
font-size: ${FluentTheme.fonts.medium.fontSize};
margin: 4px 2px 0 22px;
color: ${NeutralColors.gray190};
max-width: 500px;
`;

// ---------- ChooseResourcesList ---------- //

type ResourceListItem = ResourcesItem & { icon?: string };

type Props = {
/**
* The resources to list in order.
*/
items: ResourceListItem[];
/**
* The keys of the resources that should be selected.
*/
selectedKeys?: string[];
/**
* Raised whenever the selection of keys changes.
*/
onSelectionChanged?: (selectedKeys: string[]) => void;
};

/**
* Provides a selectable list control of resources.
* Displays the text, tier, description, and optional icon.
* Raises a callback of the selected keys.
* Allows for uncontrolled or controlled selected keys.
*/
export const ChooseResourcesList = (props: Props) => {
const { items, selectedKeys: controlledSelectedKeys, onSelectionChanged } = props;

// ----- Hooks

const getInitialSelectedKeys = () => {
return controlledSelectedKeys || items.filter((item) => item.required).map((item) => item.key);
GeoffCoxMSFT marked this conversation as resolved.
Show resolved Hide resolved
};

const [selectedKeys, setSelectedKeys] = React.useState<string[]>(getInitialSelectedKeys);

// When the items or controlled selection changes, update selection state.
React.useEffect(() => {
setSelectedKeys(getInitialSelectedKeys());
}, [items, controlledSelectedKeys]);

// ----- Handlers

const onCheckboxChanged = (ev: React.FormEvent<HTMLElement>, checked: boolean, item: ResourceListItem): void => {
let newSelectedKeys = undefined;
if (item.required || checked) {
if (!selectedKeys.includes(item.ke)) {
newSelectedKeys = [...selectedKeys, item.key];
}
} else {
newSelectedKeys = selectedKeys.filter((i: string) => i !== item.key);
}

setSelectedKeys(newSelectedKeys);

if (onSelectionChanged) {
onSelectionChanged(newSelectedKeys);
}
};

// ----- Render

const renderItemLabel = (item: ResourceListItem) => {
return (
<ItemLabel>
<ItemHeader horizontal>
{item.icon ? <ImageIcon height="16" src={item.icon} width="16" /> : <ImageIconPlacholder />}
<ItemText>{item.text}</ItemText>
</ItemHeader>
<ItemTier>{item.tier}</ItemTier>
<ItemDescription>{item.description}</ItemDescription>
</ItemLabel>
);
};

const renderItem = (item: ResourceListItem) => {
const checked = item.required || !!selectedKeys.includes(item.key);
return (
<ItemCheckbox
key={item.key}
data-is-focusable
checked={checked}
disabled={item.required}
styles={checkBoxStyle}
onChange={(e, c) => onCheckboxChanged(e, c, item)}
onRenderLabel={() => renderItemLabel(item)}
/>
);
};

return (
<FocusZone direction={FocusZoneDirection.vertical}>
<List items={items} onRenderCell={renderItem} />
</FocusZone>
);
};
11 changes: 10 additions & 1 deletion extensions/azurePublish/src/components/api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,19 @@ export const getResourceList = async (projectId: string, type: string): Promise<
}
};

/**
* A resource item that could be chosen by the user for provisioning.
*/
export type PreviewResourcesItem = {
name: string;
icon: string;
key: string;
};

/**
* Get preview and description of resources
*/
export const getPreview = (hostname: string) => {
export const getPreview = (hostname: string): PreviewResourcesItem[] => {
const azureWebAppName = `${hostname}`;
const azureServicePlanName = `${hostname}`;
const botServiceName = `${hostname}`;
Expand Down
Loading