Updated linting warnings, container, readme, sample manifest
This commit is contained in:
parent
298ee7c40b
commit
d463d11d78
|
@ -1,39 +1,38 @@
|
|||
// For more information on how to run this SPFx project in a VS Code Remote Container, please visit https://aka.ms/spfx-devcontainer
|
||||
{
|
||||
"name": "SPFx 1.4.1",
|
||||
"image": "docker.io/m365pnp/spfx:1.4.1",
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {},
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
],
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729,
|
||||
5432
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
"5432": {
|
||||
"protocol": "https",
|
||||
"label": "Workbench",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
||||
"name": "SPFx 1.18.2",
|
||||
"image": "docker.io/m365pnp/spfx:1.18.2",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
},
|
||||
"forwardPorts": [
|
||||
4321,
|
||||
35729,
|
||||
5432
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
"5432": {
|
||||
"protocol": "https",
|
||||
"label": "Workbench",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"35729": {
|
||||
"protocol": "https",
|
||||
"label": "LiveReload",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
}
|
||||
},
|
||||
"postCreateCommand": "bash .devcontainer/spfx-startup.sh",
|
||||
"remoteUser": "node"
|
||||
}
|
||||
|
|
|
@ -7,9 +7,11 @@ echo
|
|||
echo -e "\e[1;94mGenerating dev certificate\e[0m"
|
||||
gulp trust-dev-cert
|
||||
|
||||
# Convert the generated PEM certificate to a CER certificate
|
||||
openssl x509 -inform PEM -in ~/.rushstack/rushstack-serve.pem -outform DER -out ./spfx-dev-cert.cer
|
||||
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.cer
|
||||
cp ~/.gcb-serve-data/gcb-serve.cer ./spfx-dev-cert.pem
|
||||
# Copy the PEM ecrtificate for non-Windows hosts
|
||||
cp ~/.rushstack/rushstack-serve.pem ./spfx-dev-cert.pem
|
||||
|
||||
## add *.cer to .gitignore to prevent certificates from being saved in repo
|
||||
if ! grep -Fxq '*.cer' ./.gitignore
|
||||
|
|
|
@ -14,14 +14,18 @@ This web part shows an organization chart based on specified user, and user can
|
|||
|
||||
| :warning: Important |
|
||||
|:---------------------------|
|
||||
| Every SPFx version is only compatible with specific version(s) of Node.js. In order to be able to build this sample, please ensure that the version of Node on your workstation matches one of the versions listed in this section. This sample will not work on a different version of Node.|
|
||||
| Every SPFx version is optimally compatible with specific versions of Node.js. In order to be able to build this sample, you need to ensure that the version of Node on your workstation matches one of the versions listed in this section. This sample will not work on a different version of Node.|
|
||||
|Refer to <https://aka.ms/spfx-matrix> for more information on SPFx compatibility. |
|
||||
|
||||
![SPFx 1.4.1](https://img.shields.io/badge/SPFx-1.4.1-green.svg)
|
||||
![Node.js v6 | v8](https://img.shields.io/badge/Node.js-LTS%206.x%20%7C%20v8-green.svg)
|
||||
![SharePoint 2019 | Online](https://img.shields.io/badge/SharePoint-2019%20%7C%20Online-yellow.svg)
|
||||
![Teams No: Not designed for Microsoft Teams](https://img.shields.io/badge/Teams-No-red.svg "Not designed for Microsoft Teams")
|
||||
![Workbench Hosted: Does not work with local workbench](https://img.shields.io/badge/Workbench-Hosted-yellow.svg "Does not work with local workbench")
|
||||
This sample is optimally compatible with the following environment configuration:
|
||||
|
||||
![SPFx 1.18.2](https://img.shields.io/badge/SPFx-1.18.2-green.svg)
|
||||
![Node.js v16 | v18](https://img.shields.io/badge/Node.js-v16%20%7C%20v18-green.svg)
|
||||
![Compatible with SharePoint Online](https://img.shields.io/badge/SharePoint%20Online-Compatible-green.svg)
|
||||
![Does not work with SharePoint 2019](https://img.shields.io/badge/SharePoint%20Server%202019-Incompatible-red.svg "SharePoint Server 2019 requires SPFx 1.4.1 or lower")
|
||||
![Does not work with SharePoint 2016 (Feature Pack 2)](https://img.shields.io/badge/SharePoint%20Server%202016%20(Feature%20Pack%202)-Incompatible-red.svg "SharePoint Server 2016 Feature Pack 2 requires SPFx 1.1")
|
||||
![Local Workbench Unsupported](https://img.shields.io/badge/Local%20Workbench-Unsupported-red.svg "Local workbench is no longer available as of SPFx 1.13 and above")
|
||||
![Hosted Workbench Compatible](https://img.shields.io/badge/Hosted%20Workbench-Compatible-green.svg)
|
||||
![Compatible with Remote Containers](https://img.shields.io/badge/Remote%20Containers-Compatible-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
@ -30,14 +34,14 @@ This web part shows an organization chart based on specified user, and user can
|
|||
|
||||
## Contributors
|
||||
|
||||
- [João Mendes](https://github.com/joaojmendes), Storm Technology, ([@joaojmendes](https://twitter.com/joaojmendes))
|
||||
- [Passoli Mirko](https://github.com/Paxol), Sicim S.p.A., ([Linkedin](https://www.linkedin.com/in/mirko-passoli))
|
||||
- [João Mendes](https://github.com/joaojmendes)
|
||||
- [Passoli Mirko](https://github.com/Paxol)
|
||||
|
||||
## Version history
|
||||
|
||||
|Version|Date|Comments|
|
||||
|-------|----|--------|
|
||||
|1.1|Feb, 2024|Guest user filter + update to latest sharepoint template|
|
||||
|1.1|Feb, 2024|Guest user filter + update to SPFx 1.18.2|
|
||||
|1.0|May, 2021|Initial release|
|
||||
|
||||
## Prerequisites
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"Can be installed on SharePoint Server 2019, and SharePoint Online."
|
||||
],
|
||||
"creationDateTime": "2021-05-03",
|
||||
"updateDateTime": "2021-05-03",
|
||||
"updateDateTime": "2024-02-25",
|
||||
"products": [
|
||||
"SharePoint"
|
||||
],
|
||||
|
@ -21,7 +21,7 @@
|
|||
},
|
||||
{
|
||||
"key": "SPFX-VERSION",
|
||||
"value": "1.4.1"
|
||||
"value": "1.18.2"
|
||||
}
|
||||
],
|
||||
"thumbnails": [
|
||||
|
@ -51,6 +51,10 @@
|
|||
"pictureUrl": "https://github.com/joaojmendes.png",
|
||||
"name": "João Mendes",
|
||||
"twitter": "joaojmendes"
|
||||
},
|
||||
{
|
||||
"gitHubAccount": "Paxol",
|
||||
"pictureUrl": "https://github.com/Paxol.png"
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
|
|
|
@ -18,8 +18,10 @@ export const getUserPhoto = async (userId: string): Promise<string> => {
|
|||
const personaImgUrl = PROFILE_IMAGE_URL + userId;
|
||||
|
||||
// tslint:disable-next-line: no-use-before-declare
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
const url: string = await getImageBase64(personaImgUrl);
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
const newHash = await getMd5HashForUrl(url);
|
||||
|
||||
if (
|
||||
|
@ -37,7 +39,7 @@ export const getUserPhoto = async (userId: string): Promise<string> => {
|
|||
* @param url
|
||||
*/
|
||||
export const getMd5HashForUrl = async (url: string): Promise<Maybe<string>> => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-use-before-define
|
||||
const library : any = await loadSPComponentById(MD5_MODULE_ID) ;
|
||||
try {
|
||||
const md5Hash = library.Md5Hash;
|
||||
|
@ -71,6 +73,7 @@ export const getImageBase64 = async (pictureUrl: string): Promise<string> => {
|
|||
const image = new Image();
|
||||
image.addEventListener("load", () => {
|
||||
const tempCanvas = document.createElement("canvas");
|
||||
// eslint-disable-next-line no-unused-expressions, no-sequences
|
||||
(tempCanvas.width = image.width),
|
||||
(tempCanvas.height = image.height),
|
||||
tempCanvas.getContext("2d")?.drawImage(image, 0, 0);
|
||||
|
|
|
@ -34,6 +34,7 @@ export const ExpandedCard: React.FunctionComponent<IExpandedCardProps> = (
|
|||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
(async () => {
|
||||
if (!user.manager) return;
|
||||
|
||||
|
@ -67,7 +68,7 @@ export const ExpandedCard: React.FunctionComponent<IExpandedCardProps> = (
|
|||
<Text variant="smallPlus">{user.email}</Text>
|
||||
</Link>
|
||||
</Stack>
|
||||
<div className={hoverCardStyles.separatorHorizontal}></div>
|
||||
<div className={hoverCardStyles.separatorHorizontal} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -90,7 +91,7 @@ export const ExpandedCard: React.FunctionComponent<IExpandedCardProps> = (
|
|||
<Text variant="smallPlus">{user.workPhone}</Text>
|
||||
</Link>
|
||||
</Stack>
|
||||
<div className={hoverCardStyles.separatorHorizontal}></div>
|
||||
<div className={hoverCardStyles.separatorHorizontal} />
|
||||
</>
|
||||
)}
|
||||
{user.location && (
|
||||
|
@ -133,7 +134,7 @@ export const ExpandedCard: React.FunctionComponent<IExpandedCardProps> = (
|
|||
pictureUrl={manager.pictureUrl}
|
||||
text={manager.displayName}
|
||||
secondaryText={manager.title}
|
||||
></Person>
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { IButtonStyles, IDocumentCardActionsStyles, IStackStyles, mergeStyles, m
|
|||
import type { Theme } from "spfx-uifabric-themes";
|
||||
const currentTheme: Theme = window.__themeState__.theme;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type
|
||||
export const useHoverCardStyles = () => {
|
||||
|
||||
const stackPersonaStyles: Partial<IStackStyles> = {
|
||||
|
|
|
@ -99,11 +99,11 @@ export const OrgChart: React.FunctionComponent<IOrgChartProps> = (
|
|||
onUserSelected={onUserSelected}
|
||||
selectedUser={currentUser}
|
||||
showActionsBar={showActionsBar}
|
||||
></PersonCard>
|
||||
/>
|
||||
<div
|
||||
key={getGUID()}
|
||||
className={orgChartClasses.separatorVertical}
|
||||
></div>
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ export const OrgChart: React.FunctionComponent<IOrgChartProps> = (
|
|||
onUserSelected={onUserSelected}
|
||||
selectedUser={currentUser}
|
||||
showActionsBar={showActionsBar}
|
||||
></PersonCard>
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -158,6 +158,7 @@ export const OrgChart: React.FunctionComponent<IOrgChartProps> = (
|
|||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
(async () => {
|
||||
try {
|
||||
if (startFromUserId === undefined) return;
|
||||
|
@ -177,6 +178,7 @@ export const OrgChart: React.FunctionComponent<IOrgChartProps> = (
|
|||
}
|
||||
const profileResponse = await getUserProfile(startFromUserId);
|
||||
const wCurrentUser: IUserInfo = await manpingUserProperties(
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
profileResponse!.currentUserProfile
|
||||
);
|
||||
dispatch({
|
||||
|
@ -205,6 +207,7 @@ export const OrgChart: React.FunctionComponent<IOrgChartProps> = (
|
|||
}, [getUserProfile, startFromUserId]);
|
||||
|
||||
React.useEffect(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
(async () => {
|
||||
if (!currentUser || !currentUser.id) return;
|
||||
dispatch({
|
||||
|
@ -251,7 +254,7 @@ export const OrgChart: React.FunctionComponent<IOrgChartProps> = (
|
|||
size={SpinnerSize.large}
|
||||
label={"loading Organization Chart..."}
|
||||
labelPosition={"bottom"}
|
||||
></Spinner>
|
||||
/>
|
||||
</Stack>
|
||||
</Overlay>
|
||||
);
|
||||
|
@ -284,15 +287,16 @@ export const OrgChart: React.FunctionComponent<IOrgChartProps> = (
|
|||
{renderManagers}
|
||||
<PersonCard
|
||||
key={getGUID()}
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
userInfo={currentUser!}
|
||||
onUserSelected={onUserSelected}
|
||||
selectedUser={currentUser}
|
||||
showActionsBar={showActionsBar}
|
||||
></PersonCard>
|
||||
/>
|
||||
{renderDirectReports.length && (
|
||||
<>
|
||||
<div className={orgChartClasses.separatorVertical}></div>
|
||||
<div className={orgChartClasses.separatorHorizontal}></div>
|
||||
<div className={orgChartClasses.separatorVertical} />
|
||||
<div className={orgChartClasses.separatorHorizontal} />
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { mergeStyles, mergeStyleSets } from "@fluentui/react";
|
|||
|
||||
const currentTheme = window.__themeState__.theme;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type
|
||||
export const useOrgChartStyles = () => {
|
||||
|
||||
const orgChartClasses = mergeStyleSets({
|
||||
|
|
|
@ -2,7 +2,7 @@ import { IButtonStyles, IDocumentCardActionsStyles, IStackStyles, mergeStyles, m
|
|||
import type { Theme } from "spfx-uifabric-themes";
|
||||
const currentTheme: Theme = window.__themeState__.theme;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/explicit-function-return-type
|
||||
export const usePersonaCardStyles = () => {
|
||||
|
||||
const stackPersonaStyles: Partial<IStackStyles> = {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import { sp, SPBatch } from "@pnp/sp/";
|
||||
import { IUserInfo } from "../models/IUserInfo";
|
||||
import * as React from "react";
|
||||
|
@ -57,10 +58,12 @@ export const useGetUserProperties = (): {
|
|||
|
||||
// Get Direct Reports if exists
|
||||
if (wDirectReports && wDirectReports.length > 0) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
reportsLists = await getDirectReports(wDirectReports, showGuestUsers);
|
||||
}
|
||||
// Get Managers if exists
|
||||
if (startUser && wExtendedManagers && wExtendedManagers.length > 0) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
managersList = await getExtendedManagers(
|
||||
wExtendedManagers,
|
||||
loginNameStartUser!,
|
||||
|
@ -88,10 +91,12 @@ const getDirectReports = async (
|
|||
`${userReport}__orgchart__`
|
||||
);
|
||||
if (!cacheDirectReport) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
sp.profiles
|
||||
.inBatch(batch)
|
||||
.getPropertiesFor(userReport)
|
||||
.then(async (directReport: IPersonProperties) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
const userInfo = await manpingUserProperties(directReport);
|
||||
if (!showGuestUsers && userInfo.userType === "Guest") return;
|
||||
|
||||
|
@ -99,6 +104,7 @@ const getDirectReports = async (
|
|||
await set(`${userReport}__orgchart__`, directReport);
|
||||
});
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
const userInfo = await manpingUserProperties(cacheDirectReport);
|
||||
if (!showGuestUsers && userInfo.userType === "Guest") continue;
|
||||
|
||||
|
@ -126,10 +132,12 @@ const getExtendedManagers = async (
|
|||
`${manager}__orgchart__`
|
||||
);
|
||||
if (!cacheManager) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
sp.profiles
|
||||
.inBatch(batch)
|
||||
.getPropertiesFor(manager)
|
||||
.then(async (_profile: IPersonProperties) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
const userInfo = await manpingUserProperties(_profile);
|
||||
if (!showGuestUsers && userInfo.userType === "Guest") return;
|
||||
|
||||
|
@ -137,6 +145,7 @@ const getExtendedManagers = async (
|
|||
await set(`${manager}__orgchart__`, _profile);
|
||||
});
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
const userInfo = await manpingUserProperties(cacheManager);
|
||||
if (!showGuestUsers && userInfo.userType === "Guest") continue;
|
||||
|
||||
|
@ -147,6 +156,7 @@ const getExtendedManagers = async (
|
|||
return wManagers;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
function userTypeMapper(userType: string) {
|
||||
switch (userType) {
|
||||
case "0":
|
||||
|
|
Loading…
Reference in New Issue