Merge pull request #1765 from joaojmendes/master

This commit is contained in:
Hugo Bernier 2021-03-11 00:56:55 -05:00 committed by GitHub
commit 329f20d196
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 185 additions and 33 deletions

View File

@ -23,6 +23,8 @@ extensions:
This web part shows the current user's colleagues, and allows the user to search AD directory, The user can configure the properties to show when expand the user card.
![staff](./assets/staffdirectory.gif)
![staff](./assets/staffTeams01.png)
![staff](./assets/staffTeams02.png)
## Compatibility

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 KiB

View File

@ -49,7 +49,7 @@
"jest": "^23.6.0",
"jest-junit": "^10.0.0",
"lodash": "^4.17.15",
"spfx-uifabric-themes": "^0.8.0",
"spfx-uifabric-themes": "^0.8.5",
"typescript": "~3.7.x"
},
"jest-junit": {

View File

@ -0,0 +1,24 @@
{
"themePrimary": "#6264a7",
"themeLighterAlt": "#f7f7fb",
"themeLighter": "#e1e1f1",
"themeLight": "#c8c9e4",
"themeTertiary": "#989ac9",
"themeSecondary": "#7173b0",
"themeDarkAlt": "#585a95",
"themeDark": "#4a4c7e",
"themeDarker": "#37385d",
"neutralLighterAlt": "#0b0b0b",
"neutralLighter": "#151515",
"neutralLight": "#252525",
"neutralQuaternaryAlt": "#2f2f2f",
"neutralQuaternary": "#373737",
"neutralTertiaryAlt": "#595959",
"neutralTertiary": "#c8c8c8",
"neutralSecondary": "#d0d0d0",
"neutralPrimaryAlt": "#dadada",
"neutralPrimary": "#ffffff",
"neutralDark": "#f4f4f4",
"black": "#f8f8f8",
"white": "#000000"
}

View File

@ -0,0 +1,24 @@
{
"themePrimary": "#6264a7",
"themeLighterAlt": "#f7f7fb",
"themeLighter": "#e1e1f1",
"themeLight": "#c8c9e4",
"themeTertiary": "#989ac9",
"themeSecondary": "#7173b0",
"themeDarkAlt": "#585a95",
"themeDark": "#4a4c7e",
"themeDarker": "#37385d",
"neutralLighterAlt": "#2d2c2c",
"neutralLighter": "#2c2b2b",
"neutralLight": "#2a2929",
"neutralQuaternaryAlt": "#272626",
"neutralQuaternary": "#252525",
"neutralTertiaryAlt": "#242323",
"neutralTertiary": "#c8c8c8",
"neutralSecondary": "#d0d0d0",
"neutralPrimaryAlt": "#dadada",
"neutralPrimary": "#ffffff",
"neutralDark": "#f4f4f4",
"black": "#f8f8f8",
"white": "#2d2c2c"
}

View File

@ -0,0 +1,24 @@
{
"themePrimary": "#6264a7",
"themeLighterAlt": "#f7f7fb",
"themeLighter": "#e1e1f1",
"themeLight": "#c8c9e4",
"themeTertiary": "#989ac9",
"themeSecondary": "#7173b0",
"themeDarkAlt": "#585a95",
"themeDark": "#4a4c7e",
"themeDarker": "#37385d",
"neutralLighterAlt": "#ecebe9",
"neutralLighter": "#e8e7e6",
"neutralLight": "#dedddc",
"neutralQuaternaryAlt": "#cfcecd",
"neutralQuaternary": "#c6c5c4",
"neutralTertiaryAlt": "#bebdbc",
"neutralTertiary": "#b5b4b2",
"neutralSecondary": "#9d9c9a",
"neutralPrimaryAlt": "#868482",
"neutralPrimary": "#252423",
"neutralDark": "#565453",
"black": "#3e3d3b",
"white": "#f3f2f1"
}

View File

@ -0,0 +1,17 @@
$default-background: #f3f2f1;
$default-color: #252423;
$default-button-background: #6264a7;
$default-Button-color: #f3f2f1;
// dark theme
$dark-background: #2d2c2c;
$dark-color: #ffffff;
$dark-button-background: #6264a7;
$dark-button-color: #2d2c2c;
// contrast theme
$contrast-background: #000000;
$contrast-color: #ffffff;
$contrast-button-background: #b5c01c;
$contrast-Button-color: #000000;

View File

@ -46,7 +46,7 @@ import { AppContext } from "../../common/AppContext";
import { UserCard } from "../UserCard/UserCard";
import { useRef } from "react";
import strings from "StaffDirectoryWebPartStrings";
import {Theme} from 'spfx-uifabric-themes';
const imageNoData: string = require("../../../assets/Nodatarafiki.svg");
@ -73,7 +73,7 @@ export const StaffDirectory: React.FunctionComponent<IStaffDirectoryProps> = (
props: IStaffDirectoryProps
) => {
const { showBox, maxHeight } = props;
const _theme = window.__themeState__.theme;
const styleClasses = mergeStyleSets({
webPartTitle: {
marginBottom: 20,
@ -85,7 +85,7 @@ export const StaffDirectory: React.FunctionComponent<IStaffDirectoryProps> = (
margin: 20,
borderBottomStyle: "solid",
borderWidth: 1,
borderBottomColor: props.themeVariant.palette.themeLighter,
borderBottomColor: props.themeVariant?.palette?.themeLighter ?? _theme.themeLighter,
},
styleIcon: {
@ -93,7 +93,7 @@ export const StaffDirectory: React.FunctionComponent<IStaffDirectoryProps> = (
minWidth: 44,
minHeight: 30,
height: 30,
borderColor: props.themeVariant.palette.themePrimary,
borderColor: props.themeVariant?.palette?.themePrimary ?? _theme.themePrimary,
borderRightWidth: 0,
borderRightStyle: "none",
borderLeftWidth: 1,
@ -123,24 +123,24 @@ export const StaffDirectory: React.FunctionComponent<IStaffDirectoryProps> = (
width: "100%",
maxHeight: 32,
minHeight: 32,
borderColor: props.themeVariant.palette.themePrimary,
borderColor: props.themeVariant?.palette?.themePrimary ?? _theme.themePrimary,
},
itemsWrapper: {
borderColor: props.themeVariant.palette.themePrimary,
borderColor: props.themeVariant?.palette?.themePrimary ?? _theme.themePrimary,
},
text: {
borderLeftWidth: 0,
minHeight: 32,
borderColor: props.themeVariant.palette.themePrimary,
borderColor: props.themeVariant?.palette?.themePrimary ?? _theme.themePrimary,
selectors: {
":focus": {
borderColor: props.themeVariant.palette.themePrimary,
borderColor:props.themeVariant?.palette?.themePrimary ?? _theme.themePrimary,
},
":hover": {
borderColor: props.themeVariant.palette.themePrimary,
borderColor: props.themeVariant?.palette?.themePrimary ?? _theme.themePrimary,
},
"::after": {
borderColor: props.themeVariant.palette.themePrimary,
borderColor: props.themeVariant?.palette?.themePrimary ?? _theme.themePrimary,
borderWidth: 1,
borderLeftWidth: 0,
},
@ -151,7 +151,7 @@ export const StaffDirectory: React.FunctionComponent<IStaffDirectoryProps> = (
const nextPageStyle: ILinkStyles = {
root: {
fontWeight: 600,
fontSize: props.themeVariant.fonts.mediumPlus.fontSize,
fontSize: props.themeVariant?.fonts?.mediumPlus?.fontSize ?? window.__themeState__.theme["ms-font-mediumPlus-fontSize"],
selectors: { ":hover": { textDecoration: "underline" } },
},
};
@ -383,8 +383,8 @@ export const StaffDirectory: React.FunctionComponent<IStaffDirectoryProps> = (
iconName="Search"
style={{
verticalAlign: "center",
fontSize: props.themeVariant.fonts.mediumPlus.fontSize,
color: props.themeVariant.palette.themePrimary,
fontSize: props.themeVariant?.fonts?.mediumPlus?.fontSize ?? window.__themeState__.theme["ms-font-mediumPlus-fontSize"],
color: props.themeVariant?.palette.themePrimary ?? _theme.themePrimary,
}}
/>
</div>

View File

@ -10,6 +10,7 @@ import {
Link,
ITextFieldStyles,
IPersonaProps,
loadTheme,
} from "office-ui-fabric-react";
import { presenceStatus, IPresenceStatus } from "../../common/PresenceStatus";
import { AppContext } from "../../common/AppContext";
@ -18,13 +19,18 @@ import { IUserExtended } from "../../entites/IUserExtended";
import { IAppContext } from "../../common/IAppContext";
import { IUserCardProps } from "./IUserCardProps";
const teamsDefaultTheme = require("../../common/TeamsDefaultTheme.json");
const teamsDarkTheme = require("../../common/TeamsDarkTheme.json");
const teamsContrastTheme = require("../../common/TeamsContrastTheme.json");
export const UserCard = (props: IUserCardProps) => {
const { userData, updateUsersPresence } = props;
const _context: IAppContext = React.useContext(AppContext);
const [expandIcon, setExpandIcon] = React.useState("ChevronDownSmall");
const [isDetailsOpen, setIsDetailsOpen] = React.useState(false);
const _Theme = window.__themeState__.theme;
const styleClasses = mergeStyleSets({
separator: {
@ -33,31 +39,32 @@ export const UserCard = (props: IUserCardProps) => {
marginTop: 15,
borderBottomStyle: "solid",
borderWidth: 1,
borderBottomColor: _context.themeVariant.palette.neutralLighterAlt,
borderBottomColor: _context.themeVariant?.palette?.themeLighter ?? _Theme.themeLighter,
},
stylContainerDetails: {
marginTop: 25,
display: "grid",
justifyContent: "stretch",
alignItems: "center",
backgroundColor: _context.themeVariant.palette.themeLighter,
backgroundColor: _context.themeVariant?.palette?.neutralLighterAlt ?? _Theme.neutralLighterAlt,
gridTemplateColumns: "repeat( auto-fit, minmax(280px, 1fr) )",
gridTemplateRows: "auto",
},
styleIconDetails: {
fontSize: 16,
color: _context.themeVariant.palette.themePrimary,
color: _context.themeVariant?.palette?.themePrimary ?? _Theme.themePrimary,
},
styleFieldLabel: {
fontSize: 12,
fontWeight: 400,
paddingLeft: 3,
color: _Theme.inputText
},
styleField: {
paddingTop: 15,
color: _context.themeVariant?.palette?.themePrimary ?? _Theme.themePrimary,
},
});
@ -127,12 +134,12 @@ export const UserCard = (props: IUserCardProps) => {
root: {
height: 21,
width: 26,
color: _context.themeVariant.palette.themePrimary,
color: _context.themeVariant?.palette?.themeSecondary ?? _Theme.themeSecondary,
},
}}
iconProps={{
iconName: "CannedChat",
color: _context.themeVariant.palette.themePrimary,
color: _context.themeVariant?.palette?.themeSecondary ??_Theme.themeSecondary,
}}
allowDisabledFocus={true}
disabled={false}
@ -156,12 +163,13 @@ export const UserCard = (props: IUserCardProps) => {
root: {
height: 21,
width: 26,
color: _context.themeVariant.palette.themePrimary,
},
}}
iconProps={{
iconName: expandIcon,
color: _context.themeVariant.palette.themePrimary,
color: _Theme.themeSecondary
}}
allowDisabledFocus={true}
disabled={false}

View File

@ -13,7 +13,7 @@
// Components that allow authors to embed arbitrary script code should set this to true.
// https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f
"requiresCustomScript": false,
"supportedHosts": ["SharePointWebPart"],
"supportedHosts": ["SharePointWebPart","TeamsTab","TeamsPersonalApp"],
"preconfiguredEntries": [{
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other

View File

@ -6,16 +6,19 @@ import {
PropertyPaneTextField,
PropertyPaneSlider,
PropertyPaneToggle,
PropertyPaneHorizontalRule
PropertyPaneHorizontalRule,
PropertyPaneLabel,
PopupWindowPosition
} from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart, PropertyPaneLabel } from '@microsoft/sp-webpart-base';
import { BaseClientSideWebPart, } from '@microsoft/sp-webpart-base';
import * as strings from 'StaffDirectoryWebPartStrings';
import {StaffDirectory} from '../../components/StaffDirectory/StaffDirectory';
import { IStaffDirectoryProps } from '../../components/StaffDirectory/IStaffDirectoryProps';
import { PropertyFieldMultiSelect } from '@pnp/spfx-property-controls/lib/PropertyFieldMultiSelect';
import {Theme} from 'spfx-uifabric-themes';
import { ThemeProvider, ThemeChangedEventArgs, IReadonlyTheme } from '@microsoft/sp-component-base';
import { loadTheme } from 'office-ui-fabric-react';
export interface IStaffDirectoryWebPartProps {
title: string;
maxHeight: number;
@ -28,27 +31,77 @@ export interface IStaffDirectoryWebPartProps {
pageSize:number;
}
const teamsDefaultTheme = require("../../common/TeamsDefaultTheme.json");
const teamsDarkTheme = require("../../common/TeamsDarkTheme.json");
const teamsContrastTheme = require("../../common/TeamsContrastTheme.json");
export default class StaffDirectoryWebPart extends BaseClientSideWebPart<IStaffDirectoryWebPartProps> {
private _themeProvider: ThemeProvider;
private _themeVariant: IReadonlyTheme | undefined;
protected async onInit(): Promise<void> {
window.sessionStorage.clear();
this._themeProvider = this.context.serviceScope.consume(ThemeProvider.serviceKey);
this._themeProvider = this.context.serviceScope.consume(
ThemeProvider.serviceKey
);
// If it exists, get the theme variant
this._themeVariant = this._themeProvider.tryGetTheme();
// Register a handler to be notified if the theme variant changes
this._themeProvider.themeChangedEvent.add(this, this._handleThemeChangedEvent);
this._themeProvider.themeChangedEvent.add(
this,
this._handleThemeChangedEvent
);
if (this.context.sdks.microsoftTeams) {
// in teams ?
const context = this.context.sdks.microsoftTeams!.context;
this._applyTheme(context.theme || "default");
this.context.sdks.microsoftTeams.teamsJs.registerOnThemeChangeHandler(
this._applyTheme
);
}
return Promise.resolve();
}
/**
* Update the current theme variant reference and re-render.
*
* @param args The new theme
*/
private _handleThemeChangedEvent(args: ThemeChangedEventArgs): void {
this._themeVariant = args.theme;
this.render();
}
// Apply btheme id in Teams
private _applyTheme = (theme: string): void => {
this.context.domElement.setAttribute("data-theme", theme);
document.body.setAttribute("data-theme", theme);
if (theme == "dark") {
loadTheme({
palette: teamsDarkTheme,
});
}
if (theme == "default") {
loadTheme({
palette: teamsDefaultTheme,
});
}
if (theme == "contrast") {
loadTheme({
palette: teamsContrastTheme,
});
}
this.render();
}
public render(): void {
const element: React.ReactElement<IStaffDirectoryProps> = React.createElement(
@ -58,7 +111,7 @@ export default class StaffDirectoryWebPart extends BaseClientSideWebPart<IStaffD
context: this.context,
maxHeight: this.properties.maxHeight,
showBox: this.properties.showBox,
themeVariant: this._themeVariant,
themeVariant: this._themeVariant ,
displayMode: this.displayMode,
updateProperty: (value:string ) => {
this.properties.title = value;