Adding the workload selection (low-perf)
This commit is contained in:
Родитель
41cefe79b9
Коммит
8a730797cd
|
@ -1,63 +1,62 @@
|
|||
[
|
||||
{
|
||||
"id": "AAD",
|
||||
"title": "Azure AD",
|
||||
"iconName": "AADLogo",
|
||||
"thumbnailUrl": "https://raw.githubusercontent.com/microsoft/Microsoft365DSC/Dev/Modules/Microsoft365DSC/Dependencies/Images/AzureAD.jpg",
|
||||
"key": "AAD",
|
||||
"extractionModes": {
|
||||
"full": ["AADMSGroup", "AADServicePrincipal"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "EXO",
|
||||
"title": "Exchange",
|
||||
"key": "EXO",
|
||||
"iconName": "ExchangeLogo",
|
||||
"extractionModes": {
|
||||
"full": ["EXOMailboxSettings", "EXOManagementRole"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "Intune",
|
||||
"title": "Intune",
|
||||
"key": "Intune",
|
||||
"iconName": "Devices2"
|
||||
},
|
||||
{
|
||||
"id": "O365",
|
||||
"title": "Office 365",
|
||||
"key": "O365",
|
||||
"iconName": "OfficeLogo",
|
||||
"extractionModes": {
|
||||
"full": ["O365Group", "O365User"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "OD",
|
||||
"title": "OneDrive",
|
||||
"key": "OD",
|
||||
"iconName": "OneDriveLogo"
|
||||
},
|
||||
{
|
||||
"id": "Planner",
|
||||
"title": "Planner",
|
||||
"key": "Planner",
|
||||
"iconName": "PlannerLogo",
|
||||
"extractionModes": {
|
||||
"full": ["PlannerPlan", "PlannerBucket", "PlannerTask"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "PP",
|
||||
"title": "Power Platform",
|
||||
"key": "PP",
|
||||
"iconName": "PowerAppsLogo",
|
||||
"extractionModes": {
|
||||
"full": ["PPPowerAppsEnvironment"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "SC",
|
||||
"title": "Security & Compliance",
|
||||
"key": "SC",
|
||||
"iconName": "Encryption"
|
||||
},
|
||||
{
|
||||
"id": "SPO",
|
||||
"title": "SharePoint",
|
||||
"key": "SPO",
|
||||
"iconName": "SharepointLogo",
|
||||
"extractionModes": {
|
||||
"default": ["SPOApp", "SPOSiteDesign"],
|
||||
|
@ -65,8 +64,8 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"id": "Teams",
|
||||
"title": "Teams",
|
||||
"key": "Teams",
|
||||
"iconName": "TeamsLogo",
|
||||
"extractionModes": {
|
||||
"full": ["TeamsTeam", "TeamsUser", "TeamsChannelTab"]
|
||||
|
|
|
@ -1,20 +1,63 @@
|
|||
import { DefaultEffects, Icon, IStyle, mergeStyles } from '@fluentui/react';
|
||||
import { Checkbox, DefaultEffects, Icon, IStyle, mergeStyles } from '@fluentui/react';
|
||||
import * as React from 'react';
|
||||
import { useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { getTheme } from '@fluentui/react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { selectedWorkloadState } from '../../state/selectedWorkloadState';
|
||||
import { selectedResourcesState } from '../../state/resourcesState';
|
||||
import { Workload } from '../../models/Workload';
|
||||
|
||||
export interface IContentCardProps {
|
||||
title?: string;
|
||||
iconName?: string;
|
||||
workload: Workload;
|
||||
}
|
||||
export const ContentCard: React.FunctionComponent<IContentCardProps> = (props) => {
|
||||
const history = useHistory();
|
||||
const [isHovered, setIsHovered] = useState(false);
|
||||
const [isChecked, setIsChecked] = useState(false);
|
||||
const [isInderminate, setIsInderminate] = useState(false);
|
||||
const theme = getTheme();
|
||||
const setSelectedWorkload = useSetRecoilState(selectedWorkloadState);
|
||||
const [selectedResources, setSelectedResources] = useRecoilState(selectedResourcesState);
|
||||
|
||||
React.useEffect(() => {
|
||||
let workloadResources = _getWorkloadResources();
|
||||
|
||||
if(workloadResources.map((r) => r.checked).every((checked) => { return checked === true; })) {
|
||||
setIsChecked(true);
|
||||
} else if(workloadResources.map((r) => r.checked).every((checked) => { return checked === false; })) {
|
||||
setIsChecked(false)
|
||||
} else {
|
||||
setIsChecked(false);
|
||||
setIsInderminate(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const _onSelectAll = (workload: Workload, checked?: boolean) => {
|
||||
if(isInderminate || checked) {
|
||||
setSelectedResources((selectedResources) => {
|
||||
return selectedResources.map((resource) => {
|
||||
const updatedResource = resource.workload === workload.id ? { ...resource, checked: true } : resource;
|
||||
return updatedResource;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
setSelectedResources((selectedResources) => {
|
||||
return selectedResources.map((resource) => {
|
||||
const updatedResource = resource.workload === workload.id ? { ...resource, checked: false } : resource;
|
||||
return updatedResource;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const _getWorkloadResources = () => {
|
||||
return selectedResources.filter((r) => r.workload === props.workload.id);
|
||||
}
|
||||
|
||||
const _getCheckedWorkloadResources = () => {
|
||||
return _getWorkloadResources().filter((r) => r.checked === true);
|
||||
}
|
||||
|
||||
const contentCardStyles: IStyle = {
|
||||
backgroundColor: theme.palette.white,
|
||||
|
@ -49,25 +92,33 @@ export const ContentCard: React.FunctionComponent<IContentCardProps> = (props) =
|
|||
return (
|
||||
<div className={`${mergeStyles(contentCardStyles)} section-title`}>
|
||||
<div>
|
||||
{props.title && (
|
||||
{props.workload && (
|
||||
<h2
|
||||
className={mergeStyles(titleStyles)}
|
||||
id={props.title}
|
||||
id={props.workload.title}
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}>
|
||||
{props.iconName && <Icon iconName={props.iconName} className={iconStyles} />}
|
||||
{props.title}
|
||||
{props.workload.iconName && <Icon iconName={props.workload.iconName} className={iconStyles} />}
|
||||
{props.workload.title}
|
||||
{isHovered && (
|
||||
<Icon
|
||||
iconName={"Link"}
|
||||
className={linkIconStyles}
|
||||
onClick={(ev?: React.MouseEvent<HTMLElement>) => {
|
||||
let hash = `#${props.title}`;
|
||||
let hash = "#" + props.workload.title;
|
||||
window.location.hash = hash;
|
||||
history.push(hash);
|
||||
setSelectedWorkload(props.title);
|
||||
setSelectedWorkload(props.workload.title);
|
||||
}} />
|
||||
)}
|
||||
<Checkbox
|
||||
id={`chkSelectAll-${props.workload.id}`}
|
||||
label={isInderminate ? `${_getCheckedWorkloadResources().length} selected` : isChecked ? "Unselect all" : "Select all" }
|
||||
styles={{ root: {right: 0, marginRight: '80px', position: 'absolute'}}}
|
||||
checked={isChecked}
|
||||
indeterminate={isInderminate}
|
||||
onChange={(ev, checked) => _onSelectAll(props.workload, checked)}
|
||||
/>
|
||||
</h2>
|
||||
)}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ const SideNavigationComponent: React.FunctionComponent<ISideNavigationProps> = (
|
|||
selectedKey={selectedWorkload}
|
||||
onLinkClick={(ev?: React.MouseEvent<HTMLElement>, item?: INavLink) => {
|
||||
history.push(item!.url);
|
||||
setSelectedWorkload(item!.key);
|
||||
setSelectedWorkload(item?.key);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -44,10 +44,10 @@ export const WorkloadOptions: React.FunctionComponent<IWorkloadOptionsProps> = (
|
|||
return (
|
||||
<>
|
||||
{workloads?.map((workload: Workload) => (
|
||||
<ContentCard title={workload.title} iconName={workload.iconName}>
|
||||
<ContentCard workload={workload} key={workload.id}>
|
||||
<Stack horizontal wrap styles={stackStyles} tokens={wrapStackTokens}>
|
||||
{resources
|
||||
?.filter((resource) => resource.workload === workload.key)
|
||||
?.filter((resource) => resource.workload === workload.id)
|
||||
.map((resource: Resource) => (
|
||||
<StackItem styles={stackItemStyles}>
|
||||
<Checkbox
|
||||
|
|
|
@ -4,6 +4,6 @@ import { Resource } from './Resource';
|
|||
export interface Workload {
|
||||
title: string;
|
||||
iconName: string;
|
||||
key: string;
|
||||
id: string;
|
||||
extractionModes: ExtractionModes;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export const GeneratorPage: React.FunctionComponent = () => {
|
|||
|
||||
const _isResourceChecked = React.useCallback(
|
||||
(resource: Resource) => {
|
||||
const workload = workloads.find((workload) => workload.key === resource.workload);
|
||||
const workload = workloads.find((workload) => workload.id === resource.workload);
|
||||
|
||||
if (workload !== undefined) {
|
||||
switch (extractionType) {
|
||||
|
@ -72,7 +72,7 @@ export const GeneratorPage: React.FunctionComponent = () => {
|
|||
workloads.forEach((workload: Workload) => {
|
||||
navigation[0].links.push({
|
||||
name: workload.title,
|
||||
key: workload.title,
|
||||
key: workload.id,
|
||||
url: `#${workload.title}`,
|
||||
icon: workload.iconName
|
||||
});
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
import { mergeStyles } from '@fluentui/merge-styles';
|
||||
import { IStyle, Stack } from '@fluentui/react';
|
||||
import * as React from 'react';
|
||||
import { ContentCard } from '../../components/ContentCard/ContentCard';
|
||||
|
||||
export const HomePage: React.FunctionComponent = () => {
|
||||
const sectionStyles: IStyle = {
|
||||
paddingBottom: '30px',
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<header>
|
||||
<h1>What is Microsoft365DSC?</h1>
|
||||
</header>
|
||||
Microsoft365DSC is an Open-Source initiative hosted on GitHub, lead by Microsoft engineers and maintained by the
|
||||
community. It allows you to write a definition for how your Microsoft 365 tenant should be configured, automate
|
||||
the deployment of that configuration, and ensures the monitoring of the defined configuration, notifying and
|
||||
acting on detected configuration drifts. It also allows you to extract a full-fidelity configuration out of any
|
||||
existing Microsoft 365 tenant. The tool covers all major Microsoft 365 workloads such as Exchange Online, Teams,
|
||||
Power Platforms, SharePoint and Security and Compliance.
|
||||
<Stack tokens={{ childrenGap: 30 }} className={mergeStyles({ paddingTop: '30px' })}>
|
||||
<ContentCard title="Automate" iconName="AutomateFlow">
|
||||
<div className={mergeStyles(sectionStyles)}>
|
||||
365 tenant to be configured. The Microsoft365DSC module allows Microsoft 365 administrators to define how
|
||||
the configuration of the various workloads (SharePoint, Exchange, Security & Compliance, Teams, etc.), and
|
||||
apply the configuration in an automated way. For example, administrator that which to deploy a new Search
|
||||
Managed Property to their SharePoint Online workload, can do so with similar lines of code (all code
|
||||
examples can be found on the Resources List wiki page):
|
||||
</div>
|
||||
<div className={mergeStyles(sectionStyles)}>
|
||||
Using PowerShell Desired State Configuration (DSC) syntax, write a complete definition of how you want your
|
||||
Microsoft Just like any other normal PowerShell DSC configuration, your Microsoft365DSC file will need to be
|
||||
compiled into a .MOF file for the Local Configuration Manager to be able to apply it. Once your
|
||||
configuration file has been compiled, you can execute the configuration process by calling into the
|
||||
Start-DSCConfiguration PowerShell cmdlet. All configuration resources defined by Microsoft365DSC will make
|
||||
remote calls back to the Microsoft 365 tenant using various underlying frameworks and components (Microsoft
|
||||
Teams PowerShell Module, SharePoint PnP, Azure Active Directory, etc.). It is therefore important that the
|
||||
machine that executes the configuration has internet connectivity back to the Microsoft 365 tenant you are
|
||||
trying to configure. For additional information on how to get started with PowerShell Desired State
|
||||
Configuration, you can refer to the Introduction to PowerShell Desired State Configuraton training video.
|
||||
</div>
|
||||
</ContentCard>
|
||||
|
||||
<ContentCard title={'Export'}>
|
||||
Microsoft365DSC is the very first PowerShell project that natively supports ReverseDSC. This means that by
|
||||
simply installing the module, you are able to leverage ReverseDSC to extract the entire configuration of any
|
||||
existing tenants. The module exposes a cmdlet called Export-M365DSCConfiguration which launches a Graphical
|
||||
User Interface (GUI) that allows you to pick and choose what configuration components you wish to extract in a
|
||||
granular fashion.
|
||||
</ContentCard>
|
||||
|
||||
<ContentCard title={'Synchronize'}>
|
||||
Microsoft365DSC makes it very easy for users to keep multiple tenants' configuration synchronized. With the
|
||||
tool you can export the configuration from any existing tenant and re-apply it onto multiple other tenants,
|
||||
keeping their configuration synchronized.
|
||||
</ContentCard>
|
||||
|
||||
<ContentCard title={'Assess'}>
|
||||
<div className={mergeStyles(sectionStyles)}>
|
||||
Assess any Microsoft 365 tenant against a known good configuration and generate a discrepency report.
|
||||
Microsoft365DSC makes it feasible for organizations to validate the configuration of their existing
|
||||
Microsoft 365 tenant against industry's best practices with a single line command. You can assess any tenant
|
||||
against any baseline configuration that you and your team developed or use official Blueprints.
|
||||
</div>
|
||||
|
||||
<div className={mergeStyles(sectionStyles)}>
|
||||
Microsoft365DSC also allows you to compare two configuration files and obtain the delta between the two.
|
||||
Whether you wish to compare the configuration between 2 tenants or two point-in-time exports of the same
|
||||
tenant, we've got you covered!
|
||||
</div>
|
||||
</ContentCard>
|
||||
|
||||
<ContentCard title={'Assess'}>
|
||||
<div className={mergeStyles(sectionStyles)}>
|
||||
Automatic monitoring of configuration drifts in your tenant and notification about detected drifts with
|
||||
in-depth details for troubleshooting. Microsoft365DSC will perform regular checks to detect configuration
|
||||
drifts (every 15 minutes by default) and can take one of the following 3 actions when drifts are detected:
|
||||
<ul>
|
||||
<li>Fix the drift automatically by re-applying the desired configuration;</li>
|
||||
<li>Log detailed information about the drifts detected in Event Viewer;</li>
|
||||
<li>
|
||||
Notify administrators via emails when drifts are detected, providing them with a detailed report as to
|
||||
what the drifts are (requires the use of Azure DevOPS pipelines);
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</ContentCard>
|
||||
|
||||
<ContentCard title={'Report'}>
|
||||
<div className={mergeStyles(sectionStyles)}>
|
||||
Take any Microsoft365DSC configuration and generate a user friendly report from it in an Excel or HTML
|
||||
format. With a single command you can convert any Microsoft365DSC configuration
|
||||
</div>
|
||||
</ContentCard>
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
};
|
Загрузка…
Ссылка в новой задаче