review changes

This commit is contained in:
Harminder Singh 2023-02-19 06:13:50 +05:30
parent 9a317edf17
commit 407b2f6904
9 changed files with 170 additions and 163 deletions

View File

@ -1,4 +1,4 @@
# Microsoft 365 Services Health
# Service Health for Microsoft 365
## Summary
@ -38,7 +38,18 @@ For more information about SPFx compatibility, please refer to <https://aka.ms/s
## Prerequisites
> Any special pre-requisites?
- SharePoint Online tenant
- You have to provide permission in SharePoint admin for accessing Graph API on behalf of your solution. You can do it before deployment as proactive steps, or after deployment. You can refer to [steps about how to do this post-deployment](https://learn.microsoft.com/sharepoint/dev/spfx/use-aad-tutorial#deploy-the-solution-and-grant-permissions). You have to use API Access Page of SharePoint admin and add below permission for our use case.
```
"webApiPermissionRequests": [
{
"resource": "Microsoft Graph",
"scope": "ServiceHealth.Read.All"
}
]
```
## Contributors

View File

@ -2,12 +2,12 @@
{
"name": "pnp-sp-dev-spfx-web-parts-react-m365-services-health",
"source": "pnp",
"title": "Microsoft 365 Services Health",
"shortDescription": "M365 Services Health solution show the health status for all the Microsoft 365 services",
"title": "Service Health for Microsoft 365",
"shortDescription": "Service Health for Microsoft 365 solution show the health status for all the Microsoft 365 services",
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-m365-services-health",
"downloadUrl": "https://pnp.github.io/download-partial/?url=https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-m365-services-health",
"longDescription": [
"M365 Services Health solution show the health status for all the M365 services"
"Service Health for Microsoft 365 solution show the health status for all the M365 services"
],
"creationDateTime": "2023-02-03",
"updateDateTime": "2023-02-03",

View File

@ -1,7 +1,7 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/package-solution.schema.json",
"solution": {
"name": "M365 Services Health",
"name": "Service Health for Microsoft 365",
"id": "f4d4b329-f1c6-49c9-a2fa-12a9816ac717",
"version": "1.0.0.0",
"includeClientSideAssets": true,
@ -22,10 +22,10 @@
],
"metadata": {
"shortDescription": {
"default": "M365 Services health"
"default": "Service Health for Microsoft 365"
},
"longDescription": {
"default": "M365 Services health"
"default": "Service Health for Microsoft 365"
},
"screenshotPaths": [],
"videoUrl": "",
@ -34,7 +34,7 @@
},
"features": [
{
"title": "M365 Services Health Feature",
"title": "Service Health for Microsoft 365 Feature",
"description": "The feature that activates elements of the react-m-365-services-health solution.",
"id": "9d9e7584-45be-4df4-8023-5c271402cf87",
"version": "1.0.0.0"

View File

@ -1,3 +1,4 @@
import { ServiceHealth } from "@microsoft/microsoft-graph-types";
import { MSGraphClientV3, GraphRequest } from "@microsoft/sp-http-msgraph";
import { WebPartContext } from "@microsoft/sp-webpart-base";
@ -12,11 +13,10 @@ export class GraphService {
return await this.context.msGraphClientFactory.getClient("3");
};
public getHealthOverviews = async (): Promise<any> => {
public getHealthOverviews = async (): Promise<ServiceHealth[]> => {
const client = await this.getClient();
const request: GraphRequest = client.api("/admin/serviceAnnouncement/healthOverviews");
const response = await request.expand("issues").get();
return Promise.resolve(response.value);
return Promise.resolve(response.value as ServiceHealth[]);
};
}

View File

@ -1,93 +1,91 @@
export namespace HelperService {
export const getFormattedDateTime = (value: string): string => {
const date = new Date(value);
const dateString = date.toLocaleDateString("en-US", {
month: "long",
day: "numeric",
year: "numeric",
});
const timeString = date.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "numeric",
hour12: true,
});
return `${dateString} ${timeString}`;
};
export const getFormattedDateTime = (value: string): string => {
const date = new Date(value);
const dateString = date.toLocaleDateString("en-US", {
month: "long",
day: "numeric",
year: "numeric",
});
const timeString = date.toLocaleTimeString("en-US", {
hour: "numeric",
minute: "numeric",
hour12: true,
});
return `${dateString} ${timeString}`;
};
export const getProductIcon = (value: string): string => {
let icon: string = "Product";
switch (value?.toLowerCase()) {
case "microsoft intune":
case "mobile device management for office 365":
case "identity service":
case "microsoft 365 apps":
case "microsoft 365 defender":
case "microsoft 365 for the web":
case "microsoft mefender for cloud apps":
case "privileged access":
icon = "Product";
break;
case "exchange online":
icon = "ExchangeLogo";
break;
case "microsoft 365 suite":
icon = "AdminALogoInverse32";
break;
case "microsoft teams":
icon = "TeamsLogo";
break;
case "sharepoint online":
case "microsoft viva":
icon = "SharepointLogo";
break;
case "azure information protection":
icon = "AzureLogo";
break;
case "dynamics 365 apps":
icon = "Dynamics365Logo";
break;
case "microsoft bookings":
icon = "BookingsLogo";
break;
case "microsoft forms":
icon = "OfficeFormsLogo";
break;
case "microsoft power automate":
case "microsoft power automate in microsoft 365":
icon = "MicrosoftFlowLogo";
break;
case "microsoft staffHub":
icon = "MicrosoftStaffhubLogo";
break;
case "microsoft stream":
icon = "StreamLogo";
break;
case "onedrive for business":
icon = "OneDriveLogo";
break;
case "planner":
icon = "PlannerLogo";
break;
case "power apps":
case "power apps in microsoft 365":
icon = "PowerAppsLogo";
break;
case "power bi":
icon = "PowerBILogo";
break;
case "project for the web":
icon = "ProjectLogoInverse";
break;
case "skype for Business":
icon = "SkypeForBusinessLogo";
break;
case "sway":
icon = "SwayLogoInverse";
break;
case "Yammer Enterprise":
icon = "YammerLogo";
break;
}
return icon;
};
}
export const getProductIcon = (value: string): string => {
let icon: string = "Product";
switch (value?.toLowerCase()) {
case "microsoft intune":
case "mobile device management for office 365":
case "identity service":
case "microsoft 365 apps":
case "microsoft 365 defender":
case "microsoft 365 for the web":
case "microsoft defender for cloud apps":
case "privileged access":
icon = "Product";
break;
case "exchange online":
icon = "ExchangeLogo";
break;
case "microsoft 365 suite":
icon = "AdminALogoInverse32";
break;
case "microsoft teams":
icon = "TeamsLogo";
break;
case "sharepoint online":
case "microsoft viva":
icon = "SharepointLogo";
break;
case "azure information protection":
icon = "AzureLogo";
break;
case "dynamics 365 apps":
icon = "Dynamics365Logo";
break;
case "microsoft bookings":
icon = "BookingsLogo";
break;
case "microsoft forms":
icon = "OfficeFormsLogo";
break;
case "microsoft power automate":
case "microsoft power automate in microsoft 365":
icon = "MicrosoftFlowLogo";
break;
case "microsoft staffHub":
icon = "MicrosoftStaffhubLogo";
break;
case "microsoft stream":
icon = "StreamLogo";
break;
case "onedrive for business":
icon = "OneDriveLogo";
break;
case "planner":
icon = "PlannerLogo";
break;
case "power apps":
case "power apps in microsoft 365":
icon = "PowerAppsLogo";
break;
case "power bi":
icon = "PowerBILogo";
break;
case "project for the web":
icon = "ProjectLogoInverse";
break;
case "skype for Business":
icon = "SkypeForBusinessLogo";
break;
case "sway":
icon = "SwayLogoInverse";
break;
case "Yammer Enterprise":
icon = "YammerLogo";
break;
}
return icon;
};

View File

@ -18,7 +18,7 @@
"preconfiguredEntries": [{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Advanced
"group": { "default": "Advanced" },
"title": { "default": "M365 Services Health" },
"title": { "default": "Service Health for Microsoft 365" },
"description": { "default": "m365-services-health description" },
"officeFabricIconFontName": "HealthSolid",
"properties": {

View File

@ -1,7 +1,7 @@
import { ServiceHealthIssuePost } from "@microsoft/microsoft-graph-types";
import Style from "./IssueDetail.module.scss";
import * as React from "react";
import { HelperService } from "../../../../../common/services/HelperService";
import * as HelperService from "../../../../../common/services/HelperService";
import { Icon, Label } from "@fluentui/react";
import { IIssueDetailProps } from "../../../interfaces/ServiceHealthModels";

View File

@ -2,7 +2,7 @@ import { DefaultButton, DetailsList, IColumn, IPanelProps, IRenderFunction, Pane
import { ServiceHealth, ServiceHealthIssue } from "@microsoft/microsoft-graph-types";
import * as React from "react";
import { IServiceHealthOverviewItem, IServiceHealthOverviewProps, IServiceHealthOverviewState } from "../../interfaces/ServiceHealthModels";
import { ListViewHelperService } from "../../services/ListViewHelperService";
import * as ListViewHelperService from "../../services/ListViewHelperService";
import { backButtonStyles, cancelButtonStyle, issueDetailPanelStyles, issueListPanelStyles } from "./Constant";
import { IssueDetail } from "./IssueDetail/IssueDetail";
import { IssueList } from "./IssueList/IssueList";

View File

@ -2,64 +2,62 @@ import { IServiceHealthOverviewItem } from "./../interfaces/ServiceHealthModels"
import { IColumn } from "@fluentui/react";
import { ServiceHealth, ServiceHealthIssue } from "@microsoft/microsoft-graph-types";
export namespace ListViewHelperService {
export const getOverviewListViewColumns = (): IColumn[] => {
const viewColumnsSchema: IColumn[] = [
{
key: "Service",
name: "Service",
fieldName: "Service",
minWidth: 80,
maxWidth: 300,
isResizable: true,
},
{
key: "Status",
name: "Status",
fieldName: "Status",
minWidth: 120,
},
];
return viewColumnsSchema;
};
export const getOverviewListViewColumns = (): IColumn[] => {
const viewColumnsSchema: IColumn[] = [
{
key: "Service",
name: "Service",
fieldName: "Service",
minWidth: 80,
maxWidth: 300,
isResizable: true,
},
{
key: "Status",
name: "Status",
fieldName: "Status",
minWidth: 120,
},
];
return viewColumnsSchema;
};
export const getListViewItemsForOverview = (response: ServiceHealth[]): IServiceHealthOverviewItem[] => {
const overviewItems: IServiceHealthOverviewItem[] = [];
for (let i = 0; i < response.length; i++) {
const value = response[i];
const overviewItem = {} as IServiceHealthOverviewItem;
overviewItem.Service = value.service;
const inProgressIssues: ServiceHealthIssue[] = value.issues.filter((issue) => !issue.isResolved);
if (inProgressIssues.length > 0) {
const counts = inProgressIssues.reduce(
(acc, curr) => {
if (curr.classification === "advisory") {
acc.advisoryCount++;
} else if (curr.classification === "incident" || curr.classification === "unknownFutureValue") {
acc.incidentCount++;
}
return acc;
},
{ advisoryCount: 0, incidentCount: 0 }
);
export const getListViewItemsForOverview = (response: ServiceHealth[]): IServiceHealthOverviewItem[] => {
const overviewItems: IServiceHealthOverviewItem[] = [];
for (let i = 0; i < response.length; i++) {
const value = response[i];
const overviewItem = {} as IServiceHealthOverviewItem;
overviewItem.Service = value.service;
const inProgressIssues: ServiceHealthIssue[] = value.issues.filter((issue) => !issue.isResolved);
if (inProgressIssues.length > 0) {
const counts = inProgressIssues.reduce(
(acc, curr) => {
if (curr.classification === "advisory") {
acc.advisoryCount++;
} else if (curr.classification === "incident" || curr.classification === "unknownFutureValue") {
acc.incidentCount++;
}
return acc;
},
{ advisoryCount: 0, incidentCount: 0 }
);
const status: string[] = [];
if (counts.advisoryCount > 0) {
status.push(`${counts.advisoryCount} ${counts.advisoryCount === 1 ? "advisory" : "advisories"}`);
}
if (counts.incidentCount > 0) {
status.push(`${counts.incidentCount} ${counts.incidentCount === 1 ? "incident" : "incidents"}`);
}
overviewItem.Status = status.join(",");
overviewItem.InProgressItems = inProgressIssues;
} else {
overviewItem.Status = "Healthy";
overviewItem.InProgressItems = [];
const status: string[] = [];
if (counts.advisoryCount > 0) {
status.push(`${counts.advisoryCount} ${counts.advisoryCount === 1 ? "advisory" : "advisories"}`);
}
overviewItems.push(overviewItem);
if (counts.incidentCount > 0) {
status.push(`${counts.incidentCount} ${counts.incidentCount === 1 ? "incident" : "incidents"}`);
}
overviewItem.Status = status.join(",");
overviewItem.InProgressItems = inProgressIssues;
} else {
overviewItem.Status = "Healthy";
overviewItem.InProgressItems = [];
}
overviewItems.push(overviewItem);
}
overviewItems.sort((a, b) => a.Status.localeCompare(b.Status));
return overviewItems;
};
}
overviewItems.sort((a, b) => a.Status.localeCompare(b.Status));
return overviewItems;
};