Merge pull request #5277 from ValerasNarbutas/feature/verionupgradeReactBirthday
|
@ -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.16.1",
|
||||
"image": "docker.io/m365pnp/spfx:1.16.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
|
||||
],
|
||||
"portsAttributes": {
|
||||
"4321": {
|
||||
"protocol": "https",
|
||||
"label": "Manifest",
|
||||
"onAutoForward": "silent",
|
||||
"requireLocalPort": true
|
||||
},
|
||||
// Not needed for SPFx>= 1.12.1
|
||||
// "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.20.0",
|
||||
"image": "docker.io/m365pnp/spfx:1.20.0",
|
||||
"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"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,319 @@
|
|||
require('@rushstack/eslint-config/patch/modern-module-resolution');
|
||||
module.exports = {
|
||||
extends: ['@microsoft/eslint-config-spfx/lib/profiles/react'],
|
||||
parserOptions: { tsconfigRootDir: __dirname }
|
||||
};
|
||||
parserOptions: { tsconfigRootDir: __dirname },
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
'parserOptions': {
|
||||
'project': './tsconfig.json',
|
||||
'ecmaVersion': 2018,
|
||||
'sourceType': 'module'
|
||||
},
|
||||
rules: {
|
||||
// Prevent usage of the JavaScript null value, while allowing code to access existing APIs that may require null. https://www.npmjs.com/package/@rushstack/eslint-plugin
|
||||
'@rushstack/no-new-null': 1,
|
||||
// Require Jest module mocking APIs to be called before any other statements in their code block. https://www.npmjs.com/package/@rushstack/eslint-plugin
|
||||
'@rushstack/hoist-jest-mock': 1,
|
||||
// Require regular expressions to be constructed from string constants rather than dynamically building strings at runtime. https://www.npmjs.com/package/@rushstack/eslint-plugin-security
|
||||
'@rushstack/security/no-unsafe-regexp': 1,
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
'@typescript-eslint/adjacent-overload-signatures': 1,
|
||||
// RATIONALE: Code is more readable when the type of every variable is immediately obvious.
|
||||
// Even if the compiler may be able to infer a type, this inference will be unavailable
|
||||
// to a person who is reviewing a GitHub diff. This rule makes writing code harder,
|
||||
// but writing code is a much less important activity than reading it.
|
||||
//
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
'@typescript-eslint/explicit-function-return-type': [
|
||||
1,
|
||||
{
|
||||
'allowExpressions': true,
|
||||
'allowTypedFunctionExpressions': true,
|
||||
'allowHigherOrderFunctions': false
|
||||
}
|
||||
],
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
// Rationale to disable: although this is a recommended rule, it is up to dev to select coding style.
|
||||
// Set to 1 (warning) or 2 (error) to enable.
|
||||
'@typescript-eslint/explicit-member-accessibility': 0,
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
'@typescript-eslint/no-array-constructor': 1,
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
//
|
||||
// RATIONALE: The "any" keyword disables static type checking, the main benefit of using TypeScript.
|
||||
// This rule should be suppressed only in very special cases such as JSON.stringify()
|
||||
// where the type really can be anything. Even if the type is flexible, another type
|
||||
// may be more appropriate such as "unknown", "{}", or "Record<k,V>".
|
||||
'@typescript-eslint/no-explicit-any': 1,
|
||||
// RATIONALE: The #1 rule of promises is that every promise chain must be terminated by a catch()
|
||||
// handler. Thus wherever a Promise arises, the code must either append a catch handler,
|
||||
// or else return the object to a caller (who assumes this responsibility). Unterminated
|
||||
// promise chains are a serious issue. Besides causing errors to be silently ignored,
|
||||
// they can also cause a NodeJS process to terminate unexpectedly.
|
||||
'@typescript-eslint/no-floating-promises': 2,
|
||||
// RATIONALE: Catches a common coding mistake.
|
||||
'@typescript-eslint/no-for-in-array': 2,
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
'@typescript-eslint/no-misused-new': 2,
|
||||
// RATIONALE: The "namespace" keyword is not recommended for organizing code because JavaScript lacks
|
||||
// a "using" statement to traverse namespaces. Nested namespaces prevent certain bundler
|
||||
// optimizations. If you are declaring loose functions/variables, it's better to make them
|
||||
// static members of a class, since classes support property getters and their private
|
||||
// members are accessible by unit tests. Also, the exercise of choosing a meaningful
|
||||
// class name tends to produce more discoverable APIs: for example, search+replacing
|
||||
// the function "reverse()" is likely to return many false matches, whereas if we always
|
||||
// write "Text.reverse()" is more unique. For large scale organization, it's recommended
|
||||
// to decompose your code into separate NPM packages, which ensures that component
|
||||
// dependencies are tracked more conscientiously.
|
||||
//
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
'@typescript-eslint/no-namespace': [
|
||||
1,
|
||||
{
|
||||
'allowDeclarations': false,
|
||||
'allowDefinitionFiles': false
|
||||
}
|
||||
],
|
||||
// RATIONALE: Parameter properties provide a shorthand such as "constructor(public title: string)"
|
||||
// that avoids the effort of declaring "title" as a field. This TypeScript feature makes
|
||||
// code easier to write, but arguably sacrifices readability: In the notes for
|
||||
// "@typescript-eslint/member-ordering" we pointed out that fields are central to
|
||||
// a class's design, so we wouldn't want to bury them in a constructor signature
|
||||
// just to save some typing.
|
||||
//
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
// Set to 1 (warning) or 2 (error) to enable the rule
|
||||
'@typescript-eslint/parameter-properties': 0,
|
||||
// RATIONALE: When left in shipping code, unused variables often indicate a mistake. Dead code
|
||||
// may impact performance.
|
||||
//
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
'@typescript-eslint/no-unused-vars': [
|
||||
1,
|
||||
{
|
||||
'vars': 'all',
|
||||
// Unused function arguments often indicate a mistake in JavaScript code. However in TypeScript code,
|
||||
// the compiler catches most of those mistakes, and unused arguments are fairly common for type signatures
|
||||
// that are overriding a base class method or implementing an interface.
|
||||
'args': 'none'
|
||||
}
|
||||
],
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
'@typescript-eslint/no-use-before-define': [
|
||||
2,
|
||||
{
|
||||
'functions': false,
|
||||
'classes': true,
|
||||
'variables': true,
|
||||
'enums': true,
|
||||
'typedefs': true
|
||||
}
|
||||
],
|
||||
// Disallows require statements except in import statements.
|
||||
// In other words, the use of forms such as var foo = require("foo") are banned. Instead use ES6 style imports or import foo = require("foo") imports.
|
||||
'@typescript-eslint/no-var-requires': 'error',
|
||||
// RATIONALE: The "module" keyword is deprecated except when describing legacy libraries.
|
||||
//
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
'@typescript-eslint/prefer-namespace-keyword': 1,
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
// Rationale to disable: it's up to developer to decide if he wants to add type annotations
|
||||
// Set to 1 (warning) or 2 (error) to enable the rule
|
||||
'@typescript-eslint/no-inferrable-types': 0,
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
// Rationale to disable: declaration of empty interfaces may be helpful for generic types scenarios
|
||||
'@typescript-eslint/no-empty-interface': 0,
|
||||
// RATIONALE: This rule warns if setters are defined without getters, which is probably a mistake.
|
||||
'accessor-pairs': 1,
|
||||
// RATIONALE: In TypeScript, if you write x["y"] instead of x.y, it disables type checking.
|
||||
'dot-notation': [
|
||||
1,
|
||||
{
|
||||
'allowPattern': '^_'
|
||||
}
|
||||
],
|
||||
// RATIONALE: Catches code that is likely to be incorrect
|
||||
'eqeqeq': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'for-direction': 1,
|
||||
// RATIONALE: Catches a common coding mistake.
|
||||
'guard-for-in': 2,
|
||||
// RATIONALE: If you have more than 2,000 lines in a single source file, it's probably time
|
||||
// to split up your code.
|
||||
'max-lines': ['warn', { max: 2000 }],
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-async-promise-executor': 2,
|
||||
// RATIONALE: Deprecated language feature.
|
||||
'no-caller': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-compare-neg-zero': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-cond-assign': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-constant-condition': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-control-regex': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-debugger': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-delete-var': 2,
|
||||
// RATIONALE: Catches code that is likely to be incorrect
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-duplicate-case': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-empty': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-empty-character-class': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-empty-pattern': 1,
|
||||
// RATIONALE: Eval is a security concern and a performance concern.
|
||||
'no-eval': 1,
|
||||
// RATIONALE: Catches code that is likely to be incorrect
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-ex-assign': 2,
|
||||
// RATIONALE: System types are global and should not be tampered with in a scalable code base.
|
||||
// If two different libraries (or two versions of the same library) both try to modify
|
||||
// a type, only one of them can win. Polyfills are acceptable because they implement
|
||||
// a standardized interoperable contract, but polyfills are generally coded in plain
|
||||
// JavaScript.
|
||||
'no-extend-native': 1,
|
||||
// Disallow unnecessary labels
|
||||
'no-extra-label': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-fallthrough': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-func-assign': 1,
|
||||
// RATIONALE: Catches a common coding mistake.
|
||||
'no-implied-eval': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-invalid-regexp': 2,
|
||||
// RATIONALE: Catches a common coding mistake.
|
||||
'no-label-var': 2,
|
||||
// RATIONALE: Eliminates redundant code.
|
||||
'no-lone-blocks': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-misleading-character-class': 2,
|
||||
// RATIONALE: Catches a common coding mistake.
|
||||
'no-multi-str': 2,
|
||||
// RATIONALE: It's generally a bad practice to call "new Thing()" without assigning the result to
|
||||
// a variable. Either it's part of an awkward expression like "(new Thing()).doSomething()",
|
||||
// or else implies that the constructor is doing nontrivial computations, which is often
|
||||
// a poor class design.
|
||||
'no-new': 1,
|
||||
// RATIONALE: Obsolete language feature that is deprecated.
|
||||
'no-new-func': 2,
|
||||
// RATIONALE: Obsolete language feature that is deprecated.
|
||||
'no-new-object': 2,
|
||||
// RATIONALE: Obsolete notation.
|
||||
'no-new-wrappers': 1,
|
||||
// RATIONALE: Catches code that is likely to be incorrect
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-octal': 2,
|
||||
// RATIONALE: Catches code that is likely to be incorrect
|
||||
'no-octal-escape': 2,
|
||||
// RATIONALE: Catches code that is likely to be incorrect
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-regex-spaces': 2,
|
||||
// RATIONALE: Catches a common coding mistake.
|
||||
'no-return-assign': 2,
|
||||
// RATIONALE: Security risk.
|
||||
'no-script-url': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-self-assign': 2,
|
||||
// RATIONALE: Catches a common coding mistake.
|
||||
'no-self-compare': 2,
|
||||
// RATIONALE: This avoids statements such as "while (a = next(), a && a.length);" that use
|
||||
// commas to create compound expressions. In general code is more readable if each
|
||||
// step is split onto a separate line. This also makes it easier to set breakpoints
|
||||
// in the debugger.
|
||||
'no-sequences': 1,
|
||||
// RATIONALE: Catches code that is likely to be incorrect
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-shadow-restricted-names': 2,
|
||||
// RATIONALE: Obsolete language feature that is deprecated.
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-sparse-arrays': 2,
|
||||
// RATIONALE: Although in theory JavaScript allows any possible data type to be thrown as an exception,
|
||||
// such flexibility adds pointless complexity, by requiring every catch block to test
|
||||
// the type of the object that it receives. Whereas if catch blocks can always assume
|
||||
// that their object implements the "Error" contract, then the code is simpler, and
|
||||
// we generally get useful additional information like a call stack.
|
||||
'no-throw-literal': 2,
|
||||
// RATIONALE: Catches a common coding mistake.
|
||||
'no-unmodified-loop-condition': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-unsafe-finally': 2,
|
||||
// RATIONALE: Catches a common coding mistake.
|
||||
'no-unused-expressions': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-unused-labels': 1,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-useless-catch': 1,
|
||||
// RATIONALE: Avoids a potential performance problem.
|
||||
'no-useless-concat': 1,
|
||||
// RATIONALE: The "var" keyword is deprecated because of its confusing "hoisting" behavior.
|
||||
// Always use "let" or "const" instead.
|
||||
//
|
||||
// STANDARDIZED BY: @typescript-eslint\eslint-plugin\dist\configs\recommended.json
|
||||
'no-var': 2,
|
||||
// RATIONALE: Generally not needed in modern code.
|
||||
'no-void': 1,
|
||||
// RATIONALE: Obsolete language feature that is deprecated.
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'no-with': 2,
|
||||
// RATIONALE: Makes logic easier to understand, since constants always have a known value
|
||||
// @typescript-eslint\eslint-plugin\dist\configs\eslint-recommended.js
|
||||
'prefer-const': 1,
|
||||
// RATIONALE: Catches a common coding mistake where "resolve" and "reject" are confused.
|
||||
'promise/param-names': 2,
|
||||
// RATIONALE: Catches code that is likely to be incorrect
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'require-atomic-updates': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'require-yield': 1,
|
||||
// "Use strict" is redundant when using the TypeScript compiler.
|
||||
'strict': [
|
||||
2,
|
||||
'never'
|
||||
],
|
||||
// RATIONALE: Catches code that is likely to be incorrect
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
'use-isnan': 2,
|
||||
// STANDARDIZED BY: eslint\conf\eslint-recommended.js
|
||||
// Set to 1 (warning) or 2 (error) to enable.
|
||||
// Rationale to disable: !!{}
|
||||
'no-extra-boolean-cast': 0,
|
||||
// ====================================================================
|
||||
// @microsoft/eslint-plugin-spfx
|
||||
// ====================================================================
|
||||
'@microsoft/spfx/import-requires-chunk-name': 1,
|
||||
'@microsoft/spfx/no-require-ensure': 2,
|
||||
'@microsoft/spfx/pair-react-dom-render-unmount': 1
|
||||
}
|
||||
},
|
||||
{
|
||||
// For unit tests, we can be a little bit less strict. The settings below revise the
|
||||
// defaults specified in the extended configurations, as well as above.
|
||||
files: [
|
||||
// Test files
|
||||
'*.test.ts',
|
||||
'*.test.tsx',
|
||||
'*.spec.ts',
|
||||
'*.spec.tsx',
|
||||
|
||||
// Facebook convention
|
||||
'**/__mocks__/*.ts',
|
||||
'**/__mocks__/*.tsx',
|
||||
'**/__tests__/*.ts',
|
||||
'**/__tests__/*.tsx',
|
||||
|
||||
// Microsoft convention
|
||||
'**/test/*.ts',
|
||||
'**/test/*.tsx'
|
||||
],
|
||||
rules: {}
|
||||
}
|
||||
]
|
||||
};
|
|
@ -9,9 +9,9 @@ node_modules
|
|||
# Build generated files
|
||||
dist
|
||||
lib
|
||||
release
|
||||
solution
|
||||
temp
|
||||
release
|
||||
*.sppkg
|
||||
.heft
|
||||
|
||||
|
|
|
@ -13,4 +13,4 @@ tslint.json
|
|||
*.log
|
||||
|
||||
.yo-rc.json
|
||||
.vscode
|
||||
.vscode
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
{
|
||||
"@microsoft/generator-sharepoint": {
|
||||
"version": "1.16.1",
|
||||
"nodeVersion": "14.18.1",
|
||||
"plusBeta": false,
|
||||
"isCreatingSolution": true,
|
||||
"nodeVersion": "18.17.1",
|
||||
"sdksVersions": {
|
||||
"@microsoft/microsoft-graph-client": "3.0.2",
|
||||
"@microsoft/teams-js": "2.24.0"
|
||||
},
|
||||
"version": "1.20.0",
|
||||
"libraryName": "happy-birthday",
|
||||
"libraryId": "57890dd1-b655-4ec8-85ec-e47a9b696e7c",
|
||||
"libraryId": "474e78f8-113f-4057-a9a9-640241137620",
|
||||
"environment": "spo",
|
||||
"packageManager": "npm",
|
||||
"isCreatingSolution": true,
|
||||
"solutionName": "happy-birthday",
|
||||
"solutionShortDescription": "happy-birthday description",
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false,
|
||||
"componentType": "webpart",
|
||||
"sdkVersions": {
|
||||
"@microsoft/microsoft-graph-client": "3.0.2",
|
||||
"@microsoft/teams-js": "2.4.1"
|
||||
}
|
||||
|
||||
"componentType": "webpart"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ Now is possible to the user select an image for the background in the properties
|
|||
|
||||
|
||||
There is an Azure function available that get AAD user birthdays, this function creates a list on the tenant root site, if it does not exist.
|
||||
See the local.settings.json for details on the required application variable located in SyncUsersBirthdaysFunction folder.
|
||||
See the `local.settings.json` for details on the required application variable located in SyncUsersBirthdaysFunction folder.
|
||||
|
||||
But you can synchronize the Birthdays list with other applications HR Systems, or other sources
|
||||
|
||||
|
@ -25,8 +25,8 @@ But you can synchronize the Birthdays list with other applications HR Systems, o
|
|||
|
||||
This sample is optimally compatible with the following environment configuration:
|
||||
|
||||
![SPFx 1.16.1](https://img.shields.io/badge/SPFx-1.16.1-green.svg)
|
||||
![Node.js v16 | v14 | v12](https://img.shields.io/badge/Node.js-v16%20%7C%20v14%20%7C%20v12-green.svg)
|
||||
![SPFx 1.20.0](https://img.shields.io/badge/SPFx-1.20.0-green.svg)
|
||||
![Node.js v18](https://img.shields.io/badge/Node.js-v18-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")
|
||||
|
@ -60,6 +60,7 @@ email | Text | true
|
|||
|
||||
* [João Mendes](https://github.com/joaojmendes)
|
||||
* [Sajal Maity](https://github.com/smaity)
|
||||
* [Valeras Narbutas](https://github.com/ValerasNarbutas)
|
||||
|
||||
## Version history
|
||||
|
||||
|
@ -70,6 +71,7 @@ Version|Date|Comments
|
|||
2.0.0|June 16, 2021 | Upgraded to SPFx 1.12.1
|
||||
3.0.0|April 7, 2022 | Upgraded to SPFx 1.14.0
|
||||
4.0.0|March 6, 2023 | Upgraded to SPFx 1.16.1
|
||||
5.0.0|October 2, 2024 | Upgraded to SPFx 1.20.0
|
||||
|
||||
## Minimal Path to Awesome
|
||||
|
||||
|
@ -86,9 +88,11 @@ Version|Date|Comments
|
|||
|
||||
|
||||
## Features
|
||||
|
||||
This project contains sample Birthday web parts built on the SharePoint Framework using React
|
||||
and an Azure Function to get user Birthdays from AAD.
|
||||
This sample illustrates the following concepts on top of the SharePoint Framework:
|
||||
|
||||
- using React for building SharePoint Framework client-side web parts
|
||||
- using React components for building Birthday web part
|
||||
- using MSGraph API to get data from SharePoint Lists
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"The Web Part Birthdays shows the upcoming birthdays in the company, the web part reads birthdays from a list located on the tenant\u0027s root site with title \u0022Birthdays.\u0022"
|
||||
],
|
||||
"creationDateTime": "2019-07-23",
|
||||
"updateDateTime": "2023-03-06",
|
||||
"updateDateTime": "2024-10-02",
|
||||
"products": [
|
||||
"SharePoint"
|
||||
],
|
||||
|
@ -20,7 +20,7 @@
|
|||
},
|
||||
{
|
||||
"key": "SPFX-VERSION",
|
||||
"value": "1.16.1"
|
||||
"value": "1.20.2"
|
||||
},
|
||||
{
|
||||
"key": "SPFX-TEAMSTAB",
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
"happy-birthday-web-part": {
|
||||
"components": [
|
||||
{
|
||||
"entrypoint": "./lib/webparts/Birthdays/BirthdaysWebPart.js",
|
||||
"manifest": "./src/webparts/Birthdays/BirthdaysWebPart.manifest.json"
|
||||
"entrypoint": "./lib/webparts/birthdays/BirthdaysWebPart.js",
|
||||
"manifest": "./src/webparts/birthdays/BirthdaysWebPart.manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"externals": {},
|
||||
"localizedResources": {
|
||||
"ControlStrings": "lib/controls/HappyBirthdayCard/loc/{locale}.js",
|
||||
"BirthdaysWebPartStrings": "lib/webparts/Birthdays/loc/{locale}.js",
|
||||
"PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js"
|
||||
"BirthdaysWebPartStrings": "lib/webparts/birthdays/loc/{locale}.js",
|
||||
"PropertyControlStrings": "node_modules/@pnp/spfx-property-controls/lib/loc/{locale}.js",
|
||||
"ControlStrings": "lib/controls/HappyBirthdayCard/loc/{locale}.js"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"includeExtensions": [
|
||||
"png",
|
||||
"jpg",
|
||||
"svg"
|
||||
]
|
||||
}
|
|
@ -4,4 +4,4 @@
|
|||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "happy-birthday",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
||||
}
|
|
@ -3,16 +3,16 @@
|
|||
"solution": {
|
||||
"name": "happy-birthday-anniversary-client-side-solution",
|
||||
"id": "474e78f8-113f-4057-a9a9-640241137620",
|
||||
"version": "4.0.0.0",
|
||||
"version": "5.0.0.0",
|
||||
"includeClientSideAssets": true,
|
||||
"skipFeatureDeployment": true,
|
||||
"isDomainIsolated": false,
|
||||
"developer": {
|
||||
"name": "",
|
||||
"websiteUrl": "",
|
||||
"privacyUrl": "",
|
||||
"termsOfUseUrl": "",
|
||||
"websiteUrl": "",
|
||||
"mpnId": "Undefined-1.16.1"
|
||||
"mpnId": "Undefined-1.20.0"
|
||||
},
|
||||
"metadata": {
|
||||
"shortDescription": {
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/core-build/sass.schema.json"
|
||||
}
|
||||
}
|
|
@ -2,5 +2,5 @@
|
|||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/spfx-serve.schema.json",
|
||||
"port": 4321,
|
||||
"https": true,
|
||||
"initialPage": "https://enter-your-SharePoint-site/_layouts/workbench.aspx"
|
||||
"initialPage": "https://{tenantDomain}/_layouts/workbench.aspx"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/write-manifests.schema.json",
|
||||
"cdnBasePath": "<!-- PATH TO CDN -->"
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
|
||||
const gulp = require('gulp');
|
||||
const build = require('@microsoft/sp-build-web');
|
||||
|
||||
build.addSuppression(`Warning - [sass] The local CSS class 'ms-Grid' is not camelCase and will not be type-safe.`);
|
||||
|
||||
var getTasks = build.rig.getTasks;
|
||||
|
@ -14,4 +14,12 @@ build.rig.getTasks = function () {
|
|||
return result;
|
||||
};
|
||||
|
||||
// Custom task to copy assets
|
||||
gulp.task('copy-assets', function () {
|
||||
return gulp.src('src/assets/**/*')
|
||||
.pipe(gulp.dest('lib/assets'))
|
||||
.pipe(gulp.dest('dist/assets'));
|
||||
});
|
||||
build.task('pre-copy', gulp.series('copy-assets'));
|
||||
// build.rig.addPostBuildTask(gulp.task('copy-assets'));
|
||||
build.initialize(require('gulp'));
|
||||
|
|
|
@ -1,58 +1,47 @@
|
|||
{
|
||||
"name": "birthdays-anniversary",
|
||||
"version": "2.0.0",
|
||||
"name": "happy-birthday",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=18.17.1 <19.0.0"
|
||||
},
|
||||
"main": "lib/index.js",
|
||||
"scripts": {
|
||||
"build": "gulp bundle",
|
||||
"clean": "gulp clean",
|
||||
"test": "gulp test"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.13.0 <17.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@microsoft/loader-set-webpack-public-path": "^3.4.5",
|
||||
"@microsoft/sp-adaptive-card-extension-base": "1.16.1",
|
||||
"@microsoft/sp-core-library": "1.16.1",
|
||||
"@microsoft/sp-http": "^1.16.1",
|
||||
"@microsoft/sp-lodash-subset": "1.16.1",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.16.1",
|
||||
"@microsoft/sp-property-pane": "1.16.1",
|
||||
"@microsoft/sp-webpart-base": "1.16.1",
|
||||
"@pnp/common": "^1.3.11",
|
||||
"@pnp/graph": "^1.3.11",
|
||||
"@pnp/logging": "^1.3.11",
|
||||
"@pnp/odata": "^1.3.11",
|
||||
"@pnp/sp": "^1.3.11",
|
||||
"@pnp/spfx-controls-react": "3.7.2",
|
||||
"@pnp/spfx-property-controls": "1.12.0",
|
||||
"moment": "^2.29.1",
|
||||
"office-ui-fabric-react": "7.199.1",
|
||||
"@fluentui/react": "^8.106.4",
|
||||
"@microsoft/sp-component-base": "1.20.0",
|
||||
"@microsoft/sp-core-library": "1.20.0",
|
||||
"@microsoft/sp-lodash-subset": "1.20.0",
|
||||
"@microsoft/sp-office-ui-fabric-core": "1.20.0",
|
||||
"@microsoft/sp-property-pane": "1.20.0",
|
||||
"@microsoft/sp-webpart-base": "1.20.0",
|
||||
"@pnp/spfx-controls-react": "^3.19.0",
|
||||
"@pnp/spfx-property-controls": "^3.18.0",
|
||||
"moment": "^2.30.1",
|
||||
"office-ui-fabric-react": "^7.204.0",
|
||||
"react": "17.0.1",
|
||||
"react-dom": "17.0.1",
|
||||
"tslib": "2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/eslint-config-spfx": "1.16.1",
|
||||
"@microsoft/eslint-plugin-spfx": "1.16.1",
|
||||
"@microsoft/rush-stack-compiler-3.9": "0.4.48",
|
||||
"@microsoft/rush-stack-compiler-4.5": "0.2.2",
|
||||
"@microsoft/set-webpack-public-path-plugin": "^2.4.0",
|
||||
"@microsoft/sp-build-web": "1.16.1",
|
||||
"@microsoft/sp-module-interfaces": "1.16.1",
|
||||
"@rushstack/eslint-config": "2.5.1",
|
||||
"@types/es6-promise": "0.0.33",
|
||||
"@microsoft/eslint-config-spfx": "1.20.2",
|
||||
"@microsoft/eslint-plugin-spfx": "1.20.2",
|
||||
"@microsoft/rush-stack-compiler-4.7": "0.1.0",
|
||||
"@microsoft/sp-build-web": "1.20.2",
|
||||
"@microsoft/sp-module-interfaces": "1.20.2",
|
||||
"@rushstack/eslint-config": "4.0.1",
|
||||
"@types/react": "17.0.45",
|
||||
"@types/react-dom": "17.0.17",
|
||||
"@types/webpack-env": "1.15.2",
|
||||
"ajv": "6.12.5",
|
||||
"eslint": "8.7.0",
|
||||
"@types/webpack-env": "~1.15.2",
|
||||
"ajv": "^6.12.5",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-plugin-react-hooks": "4.3.0",
|
||||
"gulp": "4.0.2",
|
||||
"typescript": "4.5.5"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "16.8.8"
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-copy": "^5.0.0",
|
||||
"typescript": "4.7.4"
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 292 KiB After Width: | Height: | Size: 292 KiB |
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 137 KiB |
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 270 KiB |
After Width: | Height: | Size: 4.2 MiB |
After Width: | Height: | Size: 218 KiB |
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 96 KiB |
Before Width: | Height: | Size: 245 KiB After Width: | Height: | Size: 245 KiB |
Before Width: | Height: | Size: 170 KiB After Width: | Height: | Size: 170 KiB |
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 228 KiB |
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 142 KiB |
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 86 KiB |
Before Width: | Height: | Size: 183 KiB After Width: | Height: | Size: 183 KiB |
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 342 KiB After Width: | Height: | Size: 342 KiB |
Before Width: | Height: | Size: 100 KiB After Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 263 KiB After Width: | Height: | Size: 263 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 354 KiB After Width: | Height: | Size: 354 KiB |
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 113 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
@ -0,0 +1,257 @@
|
|||
[
|
||||
{
|
||||
"name": "pnp-sp-dev-spfx-web-parts-react-birthdays",
|
||||
"source": "pnp",
|
||||
"title": "Birthdays Web Part",
|
||||
"shortDescription": "The Web Part Birthdays shows the upcoming birthdays in the company, the web part reads birthdays from a list located on the tenant\u0027s root site with title \u0022Birthdays.\u0022",
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/tree/main/samples/react-birthdays",
|
||||
"longDescription": [
|
||||
"The Web Part Birthdays shows the upcoming birthdays in the company, the web part reads birthdays from a list located on the tenant\u0027s root site with title \u0022Birthdays.\u0022"
|
||||
],
|
||||
"creationDateTime": "2019-07-23",
|
||||
"updateDateTime": "2024-10-02",
|
||||
"products": [
|
||||
"SharePoint"
|
||||
],
|
||||
"metadata": [
|
||||
{
|
||||
"key": "CLIENT-SIDE-DEV",
|
||||
"value": "React"
|
||||
},
|
||||
{
|
||||
"key": "SPFX-VERSION",
|
||||
"value": "1.20.0"
|
||||
},
|
||||
{
|
||||
"key": "SPFX-TEAMSTAB",
|
||||
"value": "true"
|
||||
},
|
||||
{
|
||||
"key": "PNPCONTROLS",
|
||||
"value": "PropertyFieldNumber, WebPartTitle"
|
||||
}
|
||||
],
|
||||
"thumbnails": [
|
||||
{
|
||||
"type": "image",
|
||||
"order": 100,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/raw/main/samples/react-birthdays/assets/birthdays.gif",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 101,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/ballonsBackgroud.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 102,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/baloons.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 103,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/birthdays.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 104,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/birthdays2.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 105,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 106,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof1.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 107,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof10.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 108,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof11.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 109,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof12.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 110,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof14.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 111,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof14_1.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 112,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof17.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 113,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof18.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 114,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof181.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 115,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof19.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 116,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof2.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 117,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof20.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 118,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof21.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 119,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof22.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 120,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof24.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 121,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof28.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 122,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof29.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 123,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof3.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 124,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof30.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 125,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof4.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 126,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof5.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 127,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof6.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 128,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof7.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 129,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof8.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"order": 130,
|
||||
"url": "https://github.com/pnp/sp-dev-fx-webparts/blob/main/samples/react-birthdays/assets/cof9.png?raw=true",
|
||||
"alt": "Birthdays Web Part"
|
||||
}
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"gitHubAccount": "ValerasNarbutas",
|
||||
"company": "Macaw",
|
||||
"pictureUrl": "https://github.com/ValerasNarbutas.png",
|
||||
"name": "Valeras Narbutas",
|
||||
"twitter": "ValerasNarbutas"
|
||||
},
|
||||
{
|
||||
"gitHubAccount": "joaojmendes",
|
||||
"company": "Storm Technology Ltd",
|
||||
"pictureUrl": "https://github.com/joaojmendes.png",
|
||||
"name": "Jo\u00E3o Mendes",
|
||||
"twitter": "joaojmendes"
|
||||
},
|
||||
{
|
||||
"gitHubAccount": "smaity",
|
||||
"company": "JP Morgan Chase",
|
||||
"pictureUrl": "https://github.com/smaity.png",
|
||||
"name": "Sajal Maity"
|
||||
}
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"name": "Build your first SharePoint client-side web part",
|
||||
"description": "Client-side web parts are client-side components that run in the context of a SharePoint page. Client-side web parts can be deployed to SharePoint environments that support the SharePoint Framework. You can also use modern JavaScript web frameworks, tools, and libraries to build them.",
|
||||
"url": "https://learn.microsoft.com/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part"
|
||||
},
|
||||
{
|
||||
"name": "Building Microsoft Teams Tabs using SharePoint Framework",
|
||||
"description": "Starting with SharePoint Framework v1.8, you can build tabs for Microsoft Teams with the SharePoint Framework tooling and use SharePoint as a host for your solutions. As part of the SharePoint Framework v1.10 you can also publish your solution as Microsoft Teams personal app.",
|
||||
"url": "https://learn.microsoft.com/sharepoint/dev/spfx/integrate-with-teams-introduction"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -8,10 +8,10 @@ import { Label } from 'office-ui-fabric-react/lib/Label';
|
|||
import * as strings from 'ControlStrings';
|
||||
import { Icon } from 'office-ui-fabric-react/lib/Icon';
|
||||
import * as moment from 'moment';
|
||||
|
||||
import {
|
||||
DocumentCardActions,
|
||||
} from 'office-ui-fabric-react/lib/DocumentCard';
|
||||
const img: string = require('../../../assets/cof11.png');
|
||||
|
||||
const IMG_WIDTH: number = 200;
|
||||
const IMG_HEIGTH: number = 190;
|
||||
|
@ -22,72 +22,32 @@ interface IImageTemplate {
|
|||
}
|
||||
}
|
||||
|
||||
const imageTemplate: IImageTemplate[] = [{
|
||||
imageUrl: require('.../../../assets/cof.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof5.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof1.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof3.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof8.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/baloons.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof2.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof10.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof11.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof12.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof14.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof14_1.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof18.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof17.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof19.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof20.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof22.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof24.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof28.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof29.png')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof30.png')
|
||||
}
|
||||
const imageTemplate: IImageTemplate[] = [
|
||||
{ imageUrl: require('../../assets/cof.png') },
|
||||
{ imageUrl: require('../../assets/cof5.png') },
|
||||
{ imageUrl: require('../../assets/cof1.png') },
|
||||
{ imageUrl: require('../../assets/cof3.png') },
|
||||
{ imageUrl: require('../../assets/cof8.png') },
|
||||
{ imageUrl: require('../../assets/baloons.png') },
|
||||
{ imageUrl: require('../../assets/cof2.png') },
|
||||
{ imageUrl: require('../../assets/cof10.png') },
|
||||
{ imageUrl: require('../../assets/cof11.png') },
|
||||
{ imageUrl: require('../../assets/cof12.png') },
|
||||
{ imageUrl: require('../../assets/cof14.png') },
|
||||
{ imageUrl: require('../../assets/cof14_1.png') },
|
||||
{ imageUrl: require('../../assets/cof18.png') },
|
||||
{ imageUrl: require('../../assets/cof17.png') },
|
||||
{ imageUrl: require('../../assets/cof19.png') },
|
||||
{ imageUrl: require('../../assets/cof20.png') },
|
||||
{ imageUrl: require('../../assets/cof22.png') },
|
||||
{ imageUrl: require('../../assets/cof24.png') },
|
||||
{ imageUrl: require('../../assets/cof28.png') },
|
||||
{ imageUrl: require('../../assets/cof29.png') },
|
||||
{ imageUrl: require('../../assets/cof30.png') }
|
||||
];
|
||||
|
||||
|
||||
|
||||
export class HappyBirthdayCard extends React.Component<IHappyBirthdayCardProps, IHappyBirthdayCardPState> {
|
||||
private _Persona: IPersonaSharedProps;
|
||||
private _birthdayMsg: string = '';
|
||||
|
@ -183,7 +143,10 @@ export class HappyBirthdayCard extends React.Component<IHappyBirthdayCardProps,
|
|||
return _retvalue;
|
||||
}
|
||||
// Get Initials
|
||||
private _getInitial(userName: string): string {
|
||||
private _getInitial(userName: string | undefined): string {
|
||||
if (!userName) {
|
||||
return '';
|
||||
}
|
||||
const _arr = userName.split(' ');
|
||||
const _initial = _arr[0].charAt(0).toUpperCase() + (_arr[1] ? _arr[1].charAt(0).toLocaleUpperCase() : "");
|
||||
return _initial;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export interface IHappyBirthdayCardProps {
|
||||
userName?:string;
|
||||
userName?:string | undefined;
|
||||
jobDescription?: string;
|
||||
birthday: string;
|
||||
anniversary: boolean;
|
||||
|
|
|
@ -1 +1 @@
|
|||
// A file is required to be in the root of the /src directory by the TypeScript compiler
|
||||
// A file is required to be in the root of the /src directory by the TypeScript compiler
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { WebPartContext } from "@microsoft/sp-webpart-base";
|
||||
import { MSGraphClientV3 } from "@microsoft/sp-http";
|
||||
import * as moment from 'moment';
|
||||
import { version } from "react";
|
||||
|
||||
export class SPService {
|
||||
private graphClient: MSGraphClientV3 = null;
|
||||
// private graphClient: MSGraphClientV3 = null;
|
||||
private graphClient: MSGraphClientV3;
|
||||
private birthdayListTitle: string = "Birthdays";
|
||||
constructor(private _context: WebPartContext) {
|
||||
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
// 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", "SharePointFullPage", "TeamsTab"],
|
||||
"supportedHosts": ["SharePointWebPart", "TeamsPersonalApp", "TeamsTab", "SharePointFullPage"],
|
||||
"supportsThemeVariants": true,
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "d91dd629-2857-4944-be9c-7cf65bcc693d",
|
||||
"group": { "default": "Other" },
|
||||
|
|
|
@ -22,67 +22,67 @@ export interface IBirthdaysWebPartProps {
|
|||
|
||||
|
||||
const imageTemplate: { imageUrl: string }[] = [{
|
||||
imageUrl: require('.../../../assets/cof.svg')
|
||||
imageUrl: require('../../assets/cof.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof5.svg')
|
||||
imageUrl: require('../../assets/cof5.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof1.svg')
|
||||
imageUrl: require('../../assets/cof1.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof3.svg')
|
||||
imageUrl: require('../../assets/cof3.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof8.svg')
|
||||
imageUrl: require('../../assets/cof8.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/ballons.svg')
|
||||
imageUrl: require('../../assets/ballons.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof2.svg')
|
||||
imageUrl: require('../../assets/cof2.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof10.svg')
|
||||
imageUrl: require('../../assets/cof10.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof11.svg')
|
||||
imageUrl: require('../../assets/cof11.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof12.svg')
|
||||
imageUrl: require('../../assets/cof12.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof14.svg')
|
||||
imageUrl: require('../../assets/cof14.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof14_1.svg')
|
||||
imageUrl: require('../../assets/cof14_1.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof18.svg')
|
||||
imageUrl: require('../../assets/cof18.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof17.svg')
|
||||
imageUrl: require('../../assets/cof17.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof19.svg')
|
||||
imageUrl: require('../../assets/cof19.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof20.svg')
|
||||
imageUrl: require('../../assets/cof20.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof22.svg')
|
||||
imageUrl: require('../../assets/cof22.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof24.svg')
|
||||
imageUrl: require('../../assets/cof24.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof28.svg')
|
||||
imageUrl: require('../../assets/cof28.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof29.svg')
|
||||
imageUrl: require('../../assets/cof29.svg')
|
||||
},
|
||||
{
|
||||
imageUrl: require('.../../../assets/cof30.svg')
|
||||
imageUrl: require('../../assets/cof30.svg')
|
||||
},
|
||||
];
|
||||
|
||||
|
|
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 12 KiB |
|
@ -6,7 +6,7 @@ import * as moment from 'moment';
|
|||
import { IBirthdayState } from './IBirthdaysState';
|
||||
import SPService from '../../../services/SPService';
|
||||
import { WebPartTitle } from "@pnp/spfx-controls-react/lib/WebPartTitle";
|
||||
const imgBackgroundBallons: string = require('../../../../assets/ballonsBackgroud.png');
|
||||
const imgBackgroundBallons: string = require('../../../assets/ballonsBackgroud.png');
|
||||
import { Image, ImageFit } from 'office-ui-fabric-react/lib/Image';
|
||||
import { Label } from 'office-ui-fabric-react/lib/Label';
|
||||
import * as strings from 'ControlStrings';
|
||||
|
|
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 249 B |
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"extends": "./node_modules/@microsoft/rush-stack-compiler-4.5/includes/tsconfig-web.json",
|
||||
"extends": "./node_modules/@microsoft/rush-stack-compiler-4.7/includes/tsconfig-web.json",
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
@ -11,10 +11,9 @@
|
|||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "lib",
|
||||
"noUnusedLocals": false,
|
||||
"inlineSources": false,
|
||||
"strictNullChecks": false,
|
||||
"noImplicitAny": true,
|
||||
|
||||
"typeRoots": [
|
||||
"./node_modules/@types",
|
||||
"./node_modules/@microsoft"
|
||||
|
|