Fixed spelling mistakes and updated README
|
@ -18,37 +18,51 @@ This list search web part allows the user to show data from lists or libraries.
|
|||
* Item limit to show
|
||||
* Item pagination
|
||||
* Group items by any field
|
||||
* Cache to retreive the items
|
||||
* Cache to retrieve the items
|
||||
* Get section color
|
||||
* Show item count with custom message
|
||||
|
||||
#### Merge items from different lists/libraries
|
||||
![](assets/differentSources.gif)
|
||||
|
||||
![Merge items from different lists/libraries](assets/differentSources.gif)
|
||||
|
||||
#### Select render of the selected fields
|
||||
![](assets/selectFieldRenderType.gif)
|
||||
|
||||
![Select render of the selected fields](assets/selectFieldRenderType.gif)
|
||||
|
||||
#### Open documents in modal window
|
||||
![](assets/docInModal.gif)
|
||||
|
||||
![Open documents in modal window](assets/docInModal.gif)
|
||||
|
||||
#### Open documents in new tab
|
||||
![](assets/docInNewTab.gif)
|
||||
|
||||
![Open documents in new tab](assets/docInNewTab.gif)
|
||||
|
||||
#### Use of dynamic data
|
||||
![](assets/dynamicData.gif)
|
||||
|
||||
![Use of dynamic data](assets/dynamicData.gif)
|
||||
|
||||
#### Open selected item with same data
|
||||
![](assets/itemCurrentData.gif)
|
||||
|
||||
![Open selected item with same data](assets/itemCurrentData.gif)
|
||||
|
||||
#### Open selected item with selected properties
|
||||
![](assets/itemSelectedData.gif)
|
||||
|
||||
![Open selected item with selected properties](assets/itemSelectedData.gif)
|
||||
|
||||
#### Redirect to url depends on selected item
|
||||
![](assets/redirectToUrl.gif)
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
![Redirect to url depends on selected item](assets/redirectToUrl.gif)
|
||||
|
||||
|
||||
## Compatibility
|
||||
|
||||
![SPFx 1.11](https://img.shields.io/badge/SPFx-1.11.0-green.svg)
|
||||
![Node.js LTS 10.x](https://img.shields.io/badge/Node.js-LTS%2010.x-green.svg)
|
||||
![SharePoint Online](https://img.shields.io/badge/SharePoint-Online-yellow.svg)
|
||||
![Teams N/A: Untested with Microsoft Teams](https://img.shields.io/badge/Teams-N%2FA-lightgrey.svg "Untested with Microsoft Teams")
|
||||
![Workbench Local | Hosted](https://img.shields.io/badge/Workbench-Local%20%7C%20Hosted-green.svg)
|
||||
|
||||
![SPFx 1.11.0](https://img.shields.io/badge/version-1.11.0-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
|
@ -76,28 +90,30 @@ Version|Date|Comments
|
|||
## Minimal Path to Awesome
|
||||
|
||||
### Dev Mode
|
||||
|
||||
* Clone this repository
|
||||
* In the command line run:
|
||||
* Navigate to list-search-webpart
|
||||
* Navigate to `list-search-webpart`
|
||||
* `npm install`
|
||||
* `gulp serve`
|
||||
* Open the *workbench* on your Office 365 Developer tenant
|
||||
* Test out the web part
|
||||
|
||||
### Sppkg
|
||||
* Download sppkg files from sppkg folder
|
||||
* Upload files to App Catalog
|
||||
|
||||
* Download `.sppkg` files from `sppkg` folder
|
||||
* Upload files to **App Catalog**
|
||||
|
||||
## Features
|
||||
|
||||
This Web Part illustrates the following concepts on top of the SharePoint Framework:
|
||||
|
||||
* Using react for building SharePoint Framework client-side web parts
|
||||
* Using [PnP Js](https://pnp.github.io/pnpjs) to retreive SharePoint data
|
||||
* Using [PnP Js](https://pnp.github.io/pnpjs) to retrieve SharePoint data
|
||||
* Using [PnP Js](https://pnp.github.io/pnpjs/odata/caching) to cache SharePoint data
|
||||
* Connection between SharePoint Framework components using dynamic data
|
||||
* [Support of section backgrounds color ](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/guidance/supporting-section-backgrounds)
|
||||
* [Custom property pane control](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/guidance/build-custom-property-pane-controls)
|
||||
* Use [react-js-pagination](https://www.npmjs.com/package/react-js-pagination) library
|
||||
* Use [react-js-pagination](https://www.npmjs.com/package/react-js-pagination) library
|
||||
|
||||
<img src="https://telemetry.sharepointpnp.com/sp-dev-fx-webparts/samples/react-list-search" />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/copy-assets.schema.json",
|
||||
"deployCdnPath": "temp/deploy"
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "list-search-webpart",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/deploy-azure-storage.schema.json",
|
||||
"workingDir": "./temp/deploy/",
|
||||
"account": "<!-- STORAGE ACCOUNT NAME -->",
|
||||
"container": "list-search-webpart",
|
||||
"accessKey": "<!-- ACCESS KEY -->"
|
||||
}
|
|
@ -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,36 +1,36 @@
|
|||
'use strict';
|
||||
|
||||
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.`);
|
||||
|
||||
const argv = build.rig.getYargs().argv;
|
||||
const useCustomServe = argv['custom-serve'];
|
||||
const fs = require("fs");
|
||||
const workbenchApi = require("@microsoft/sp-webpart-workbench/lib/api");
|
||||
|
||||
if (useCustomServe) {
|
||||
build.tslintCmd.enabled = false;
|
||||
|
||||
const ensureWorkbenchSubtask = build.subTask('ensure-workbench-task', function (gulp, buildOptions, done) {
|
||||
this.log('Creating workbench.html file...');
|
||||
try {
|
||||
workbenchApi.default["/workbench"]();
|
||||
} catch (e) { }
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
build.rig.addPostBuildTask(build.task('ensure-workbench', ensureWorkbenchSubtask));
|
||||
|
||||
build.configureWebpack.mergeConfig({
|
||||
additionalConfiguration: (generatedConfiguration) => {
|
||||
fs.writeFileSync("./temp/_webpack_config.json", JSON.stringify(generatedConfiguration, null, 2));
|
||||
return generatedConfiguration;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
build.initialize(require('gulp'));
|
||||
|
||||
'use strict';
|
||||
|
||||
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.`);
|
||||
|
||||
const argv = build.rig.getYargs().argv;
|
||||
const useCustomServe = argv['custom-serve'];
|
||||
const fs = require("fs");
|
||||
const workbenchApi = require("@microsoft/sp-webpart-workbench/lib/api");
|
||||
|
||||
if (useCustomServe) {
|
||||
build.tslintCmd.enabled = false;
|
||||
|
||||
const ensureWorkbenchSubtask = build.subTask('ensure-workbench-task', function (gulp, buildOptions, done) {
|
||||
this.log('Creating workbench.html file...');
|
||||
try {
|
||||
workbenchApi.default["/workbench"]();
|
||||
} catch (e) { }
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
build.rig.addPostBuildTask(build.task('ensure-workbench', ensureWorkbenchSubtask));
|
||||
|
||||
build.configureWebpack.mergeConfig({
|
||||
additionalConfiguration: (generatedConfiguration) => {
|
||||
fs.writeFileSync("./temp/_webpack_config.json", JSON.stringify(generatedConfiguration, null, 2));
|
||||
return generatedConfiguration;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
build.initialize(require('gulp'));
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
# list-search-webpart
|
||||
|
||||
## Summary
|
||||
|
||||
Short summary on functionality and used technologies.
|
||||
|
||||
[picture of the solution in action, if possible]
|
||||
|
||||
## Used SharePoint Framework Version
|
||||
|
||||
![version](https://img.shields.io/badge/version-1.11-green.svg)
|
||||
|
||||
## Applies to
|
||||
|
||||
- [SharePoint Framework](https://aka.ms/spfx)
|
||||
- [Microsoft 365 tenant](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/set-up-your-developer-tenant)
|
||||
|
||||
> Get your own free development tenant by subscribing to [Microsoft 365 developer program](http://aka.ms/o365devprogram)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
> Any special pre-requisites?
|
||||
|
||||
## Solution
|
||||
|
||||
Solution|Author(s)
|
||||
--------|---------
|
||||
folder name | Author details (name, company, twitter alias with link)
|
||||
|
||||
## Version history
|
||||
|
||||
Version|Date|Comments
|
||||
-------|----|--------
|
||||
1.1|March 10, 2021|Update comment
|
||||
1.0|January 29, 2021|Initial release
|
||||
|
||||
## Disclaimer
|
||||
|
||||
**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.**
|
||||
|
||||
---
|
||||
|
||||
## Minimal Path to Awesome
|
||||
|
||||
- Clone this repository
|
||||
- Ensure that you are at the solution folder
|
||||
- in the command-line run:
|
||||
- **npm install**
|
||||
- **gulp serve**
|
||||
|
||||
> Include any additional steps as needed.
|
||||
|
||||
## Features
|
||||
|
||||
Description of the extension that expands upon high-level summary above.
|
||||
|
||||
This extension illustrates the following concepts:
|
||||
|
||||
- topic 1
|
||||
- topic 2
|
||||
- topic 3
|
||||
|
||||
> Notice that better pictures and documentation will increase the sample usage and the value you are providing for others. Thanks for your submissions advance.
|
||||
|
||||
> Share your web part with others through Microsoft 365 Patterns and Practices program to get visibility and exposure. More details on the community, open-source projects and other activities from http://aka.ms/m365pnp.
|
||||
|
||||
## References
|
||||
|
||||
- [Getting started with SharePoint Framework](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/set-up-your-developer-tenant)
|
||||
- [Building for Microsoft teams](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/build-for-teams-overview)
|
||||
- [Use Microsoft Graph in your solution](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/using-microsoft-graph-apis)
|
||||
- [Publish SharePoint Framework applications to the Marketplace](https://docs.microsoft.com/en-us/sharepoint/dev/spfx/publish-to-marketplace-overview)
|
||||
- [Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp) - Guidance, tooling, samples and open-source controls for your Microsoft 365 development
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -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
|
|
@ -6,12 +6,12 @@ define([], function () {
|
|||
SitesSelector: "Sites to get data",
|
||||
ListSelector: "List to get the data",
|
||||
ListSelectorLabel: "Select source lists",
|
||||
ListSelectorPanelHeader: "Configure lists and queries to retreive data",
|
||||
ListSelectorPanelHeader: "Configure lists and queries to retrieve data",
|
||||
CollectionDataSiteCollectionTitle: "Site Collection",
|
||||
CollectionDataListTitle: "List",
|
||||
CollectionDataListViewNameTitle: "List View Title",
|
||||
CollectionDataListCamlQueryTitle: "Caml Query",
|
||||
CollectionDataListCamlQueryPlaceHolder: "Empty - all elemets",
|
||||
CollectionDataListCamlQueryTitle: "CAML Query",
|
||||
CollectionDataListCamlQueryPlaceHolder: "Empty - all elements",
|
||||
GeneralPropertiesShowItemCount: "Show item count",
|
||||
GeneralPropertiesRowLimitLabel: "Item limit to show",
|
||||
GeneralPropertiesRowLimitDescription: "If 0 all items are render",
|
||||
|
@ -19,9 +19,9 @@ define([], function () {
|
|||
GeneralPropertiesGroupByField: "Group elements",
|
||||
FieldPropertiesGroup: "Fields",
|
||||
CollectionDataFieldsProperties: "Lists Field Properties",
|
||||
CollectionDataFieldsToRetreive: "Fields to retreive",
|
||||
CollectionDataFieldsToRetreive: "Fields to retrieve",
|
||||
CollectionDataFieldsSelectBtn: "Select fields",
|
||||
CollectionDataFieldsHeader: "Select fields to retreive and their mapping",
|
||||
CollectionDataFieldsHeader: "Select fields to retrieve and their mapping",
|
||||
CollectionDataFieldsSiteCollection: "Site Collection",
|
||||
CollectionDataFieldsList: "List",
|
||||
CollectionDataFieldsListField: "List Field",
|
||||
|
@ -51,12 +51,12 @@ define([], function () {
|
|||
GeneralFieldsPropertiesListDisplayName: "List column display name",
|
||||
GeneralFieldsPropertiesListDisplayNameOrder: "List column display name order",
|
||||
GeneralFieldsPropertiesListDisplayNameOrderDescription: "Order of list display name column",
|
||||
GeneralFieldsPropertiesListDisplayNameSearcheable: "List title searcheable in general filter",
|
||||
GeneralFieldsPropertiesListDisplayNameSearcheable: "List title searchable in general filter",
|
||||
GeneralFieldsPropertiesSiteDisplayName: "Site column display name",
|
||||
GeneralFieldsPropertiesSiteProperty: "Site property to display",
|
||||
GeneralFieldsPropertiesSiteDisplayNameOrder: "Site column display name order",
|
||||
GeneralFieldsPropertiesSiteDisplayNameOrderDescription: "Order of site display name column",
|
||||
GeneralFieldsPropertiesSiteDisplayNameSearcheable: "Site column searcheable in general filter",
|
||||
GeneralFieldsPropertiesSiteDisplayNameSearcheable: "Site column searchable in general filter",
|
||||
FilterPropertiesGeneralFilterPlaceHolder: "General filter placeholder",
|
||||
FilterPropertiesIndividualFilterPostion: "Individual filters position",
|
||||
FilterPropertiesClearAllBtnText: "Clear all button text",
|
||||
|
@ -67,7 +67,7 @@ define([], function () {
|
|||
ListSearchLoading: "Loading...",
|
||||
StoragePropertiesGroupName: "Cache",
|
||||
UseLocalStorage: "Use cache",
|
||||
MinutesToCacheData: "Time (minutes) to cache the retreived data",
|
||||
MinutesToCacheData: "Time (minutes) to cache the retrieved data",
|
||||
OnClickEvent: "Use on click event",
|
||||
OnClickSimpleModalText: "Modal with current data",
|
||||
OnClickCompleteModalText: "Modal with all item fields",
|
||||
|
@ -82,7 +82,7 @@ define([], function () {
|
|||
CompleteModalButton: "Configure modal fields",
|
||||
CompleteModalFieldsSiteCollection: "Site Collection",
|
||||
CompleteModalFieldsList: "List",
|
||||
CompleteModalFieldsListField: "Soruce Field",
|
||||
CompleteModalFieldsListField: "Source Field",
|
||||
CompleteModalFieldsTargetField: "Display field title",
|
||||
redirectDataFieldSelector: "Select urls to redirect",
|
||||
redirectDataHeaderSelector: "For each list select the url to redirect",
|
||||
|
@ -93,7 +93,7 @@ define([], function () {
|
|||
OnClickNumberOfClickOptionsToSelect: "Trigger option",
|
||||
OneClickTriggerText: "One click",
|
||||
TwoClickTriggerText: "Two clicks",
|
||||
InformationPropertiesGroupName: "Webpart Information",
|
||||
InformationPropertiesGroupName: "Web part Information",
|
||||
AboutPropertiesGroupName: "About",
|
||||
OnClickPropertiesGroup: "On click Properties",
|
||||
GroupFieldOptionsToSelect: "Field to group by",
|
|
@ -1,27 +1,27 @@
|
|||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "306e0650-db3c-443a-a698-12be6e6de1ad",
|
||||
"alias": "ListSearchConsumerWebPartWebPart",
|
||||
"componentType": "WebPart",
|
||||
|
||||
// The "*" signifies that the version should be taken from the package.json
|
||||
"version": "*",
|
||||
"manifestVersion": 2,
|
||||
|
||||
// If true, the component can only be installed on sites where Custom Script is allowed.
|
||||
// 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"],
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||
"group": { "default": "Other" },
|
||||
"title": { "default": "ListSearchConsumerWebPart" },
|
||||
"description": { "default": "List Search consumer example" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "ListSearchConsumerWebPart"
|
||||
}
|
||||
}]
|
||||
}
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json",
|
||||
"id": "306e0650-db3c-443a-a698-12be6e6de1ad",
|
||||
"alias": "ListSearchConsumerWebPartWebPart",
|
||||
"componentType": "WebPart",
|
||||
|
||||
// The "*" signifies that the version should be taken from the package.json
|
||||
"version": "*",
|
||||
"manifestVersion": 2,
|
||||
|
||||
// If true, the component can only be installed on sites where Custom Script is allowed.
|
||||
// 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"],
|
||||
|
||||
"preconfiguredEntries": [{
|
||||
"groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other
|
||||
"group": { "default": "Other" },
|
||||
"title": { "default": "ListSearchConsumerWebPart" },
|
||||
"description": { "default": "List Search consumer example" },
|
||||
"officeFabricIconFontName": "Page",
|
||||
"properties": {
|
||||
"description": "ListSearchConsumerWebPart"
|
||||
}
|
||||
}]
|
||||
}
|
|
@ -1,98 +1,98 @@
|
|||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import {
|
||||
IPropertyPaneConfiguration,
|
||||
DynamicDataSharedDepth,
|
||||
PropertyPaneDynamicFieldSet,
|
||||
PropertyPaneDynamicField
|
||||
} from '@microsoft/sp-property-pane';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IWebPartPropertiesMetadata,
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
import * as strings from 'ListSearchConsumerWebPartWebPartStrings';
|
||||
import { DynamicProperty } from '@microsoft/sp-component-base';
|
||||
import { IListSearchConsumerProps } from './components/IListSearchConsumerProps';
|
||||
import ListSearchConsumer from './components/ListSearchConsumerWebPart';
|
||||
|
||||
|
||||
export interface IListSearchConsumerWebPartProps {
|
||||
webUrl: DynamicProperty<string>;
|
||||
listId: DynamicProperty<string>;
|
||||
itemId: DynamicProperty<number>;
|
||||
}
|
||||
|
||||
|
||||
export default class ListSearchConsumerWebPart extends BaseClientSideWebPart<IListSearchConsumerWebPartProps> {
|
||||
|
||||
public render(): void {
|
||||
|
||||
const element: React.ReactElement<IListSearchConsumerProps> = React.createElement(
|
||||
ListSearchConsumer,
|
||||
{
|
||||
webUrl: this.properties.webUrl.tryGetValue(),
|
||||
listId: this.properties.listId.tryGetValue(),
|
||||
itemId: this.properties.itemId.tryGetValue(),
|
||||
}
|
||||
);
|
||||
|
||||
ReactDom.render(element, this.domElement);
|
||||
}
|
||||
|
||||
protected onDispose(): void {
|
||||
ReactDom.unmountComponentAtNode(this.domElement);
|
||||
}
|
||||
|
||||
protected get propertiesMetadata(): IWebPartPropertiesMetadata {
|
||||
return {
|
||||
// Specify the web part properties data type to allow the address
|
||||
// information to be serialized by the SharePoint Framework.
|
||||
'webUrl': {
|
||||
dynamicPropertyType: 'string'
|
||||
},
|
||||
'listId': {
|
||||
dynamicPropertyType: 'string'
|
||||
},
|
||||
'itemId': {
|
||||
dynamicPropertyType: 'number'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: strings.PropertyPaneDescription
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneDynamicFieldSet({
|
||||
label: 'Select web Url',
|
||||
fields: [
|
||||
PropertyPaneDynamicField('webUrl', {
|
||||
label: 'Web Url'
|
||||
}),
|
||||
PropertyPaneDynamicField('listId', {
|
||||
label: 'List Id'
|
||||
}),
|
||||
PropertyPaneDynamicField('itemId', {
|
||||
label: 'Item Id'
|
||||
})
|
||||
],
|
||||
sharedConfiguration: {
|
||||
depth: DynamicDataSharedDepth.Property
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
import * as React from 'react';
|
||||
import * as ReactDom from 'react-dom';
|
||||
import {
|
||||
IPropertyPaneConfiguration,
|
||||
DynamicDataSharedDepth,
|
||||
PropertyPaneDynamicFieldSet,
|
||||
PropertyPaneDynamicField
|
||||
} from '@microsoft/sp-property-pane';
|
||||
import {
|
||||
BaseClientSideWebPart,
|
||||
IWebPartPropertiesMetadata,
|
||||
} from '@microsoft/sp-webpart-base';
|
||||
|
||||
import * as strings from 'ListSearchConsumerWebPartWebPartStrings';
|
||||
import { DynamicProperty } from '@microsoft/sp-component-base';
|
||||
import { IListSearchConsumerProps } from './components/IListSearchConsumerProps';
|
||||
import ListSearchConsumer from './components/ListSearchConsumerWebPart';
|
||||
|
||||
|
||||
export interface IListSearchConsumerWebPartProps {
|
||||
webUrl: DynamicProperty<string>;
|
||||
listId: DynamicProperty<string>;
|
||||
itemId: DynamicProperty<number>;
|
||||
}
|
||||
|
||||
|
||||
export default class ListSearchConsumerWebPart extends BaseClientSideWebPart<IListSearchConsumerWebPartProps> {
|
||||
|
||||
public render(): void {
|
||||
|
||||
const element: React.ReactElement<IListSearchConsumerProps> = React.createElement(
|
||||
ListSearchConsumer,
|
||||
{
|
||||
webUrl: this.properties.webUrl.tryGetValue(),
|
||||
listId: this.properties.listId.tryGetValue(),
|
||||
itemId: this.properties.itemId.tryGetValue(),
|
||||
}
|
||||
);
|
||||
|
||||
ReactDom.render(element, this.domElement);
|
||||
}
|
||||
|
||||
protected onDispose(): void {
|
||||
ReactDom.unmountComponentAtNode(this.domElement);
|
||||
}
|
||||
|
||||
protected get propertiesMetadata(): IWebPartPropertiesMetadata {
|
||||
return {
|
||||
// Specify the web part properties data type to allow the address
|
||||
// information to be serialized by the SharePoint Framework.
|
||||
'webUrl': {
|
||||
dynamicPropertyType: 'string'
|
||||
},
|
||||
'listId': {
|
||||
dynamicPropertyType: 'string'
|
||||
},
|
||||
'itemId': {
|
||||
dynamicPropertyType: 'number'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
|
||||
return {
|
||||
pages: [
|
||||
{
|
||||
header: {
|
||||
description: strings.PropertyPaneDescription
|
||||
},
|
||||
groups: [
|
||||
{
|
||||
groupName: strings.BasicGroupName,
|
||||
groupFields: [
|
||||
PropertyPaneDynamicFieldSet({
|
||||
label: 'Select web Url',
|
||||
fields: [
|
||||
PropertyPaneDynamicField('webUrl', {
|
||||
label: 'Web Url'
|
||||
}),
|
||||
PropertyPaneDynamicField('listId', {
|
||||
label: 'List Id'
|
||||
}),
|
||||
PropertyPaneDynamicField('itemId', {
|
||||
label: 'Item Id'
|
||||
})
|
||||
],
|
||||
sharedConfiguration: {
|
||||
depth: DynamicDataSharedDepth.Property
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
export interface IListSearchConsumerProps {
|
||||
webUrl: string;
|
||||
listId: string;
|
||||
itemId: number;
|
||||
}
|
||||
export interface IListSearchConsumerProps {
|
||||
webUrl: string;
|
||||
listId: string;
|
||||
itemId: number;
|
||||
}
|
|
@ -1,34 +1,34 @@
|
|||
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||
|
||||
.listSearchConsumerWebPart {
|
||||
margin: 5px;
|
||||
background-color: $ms-color-themePrimary;
|
||||
color: $ms-color-white;
|
||||
@include ms-Grid;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
.row {
|
||||
@include ms-Grid-row;
|
||||
}
|
||||
|
||||
.column {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg12;
|
||||
@include ms-sm12;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include ms-font-xl;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
@include ms-font-l;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include ms-font-l;
|
||||
}
|
||||
|
||||
.value {
|
||||
@include ms-font-m;
|
||||
}
|
||||
}
|
||||
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
|
||||
|
||||
.listSearchConsumerWebPart {
|
||||
margin: 5px;
|
||||
background-color: $ms-color-themePrimary;
|
||||
color: $ms-color-white;
|
||||
@include ms-Grid;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
|
||||
.row {
|
||||
@include ms-Grid-row;
|
||||
}
|
||||
|
||||
.column {
|
||||
@include ms-Grid-col;
|
||||
@include ms-lg12;
|
||||
@include ms-sm12;
|
||||
}
|
||||
|
||||
.title {
|
||||
@include ms-font-xl;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
@include ms-font-l;
|
||||
}
|
||||
|
||||
.description {
|
||||
@include ms-font-l;
|
||||
}
|
||||
|
||||
.value {
|
||||
@include ms-font-m;
|
||||
}
|
||||
}
|
|
@ -1,32 +1,32 @@
|
|||
import * as React from 'react';
|
||||
import styles from './ListSearchConsumerWebPart.module.scss';
|
||||
import { IListSearchConsumerProps } from './IListSearchConsumerProps';
|
||||
|
||||
export default class ListSearchConsumer extends React.Component<IListSearchConsumerProps, {}> {
|
||||
public render(): React.ReactElement<IListSearchConsumerProps> {
|
||||
return (
|
||||
<div className={styles.listSearchConsumerWebPart}>
|
||||
<div className={styles.row}>
|
||||
<div className={styles.column}>
|
||||
<span className={styles.title}>List search consumer webpart</span>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<div className={styles.description}>WebUrl:
|
||||
<p className={styles.value}>{this.props.webUrl}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<div className={styles.description}>ListId:
|
||||
<p className={styles.value}>{this.props.listId}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<div className={styles.description}>ItemId:
|
||||
<p className={styles.value}>{this.props.itemId}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
import * as React from 'react';
|
||||
import styles from './ListSearchConsumerWebPart.module.scss';
|
||||
import { IListSearchConsumerProps } from './IListSearchConsumerProps';
|
||||
|
||||
export default class ListSearchConsumer extends React.Component<IListSearchConsumerProps, {}> {
|
||||
public render(): React.ReactElement<IListSearchConsumerProps> {
|
||||
return (
|
||||
<div className={styles.listSearchConsumerWebPart}>
|
||||
<div className={styles.row}>
|
||||
<div className={styles.column}>
|
||||
<span className={styles.title}>List search consumer webpart</span>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<div className={styles.description}>WebUrl:
|
||||
<p className={styles.value}>{this.props.webUrl}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<div className={styles.description}>ListId:
|
||||
<p className={styles.value}>{this.props.listId}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.column}>
|
||||
<div className={styles.description}>ItemId:
|
||||
<p className={styles.value}>{this.props.itemId}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
define([], function() {
|
||||
return {
|
||||
"PropertyPaneDescription": "Description",
|
||||
"BasicGroupName": "Group Name",
|
||||
"DescriptionFieldLabel": "Description Field"
|
||||
}
|
||||
});
|
|
@ -1,10 +1,10 @@
|
|||
declare interface IListSearchConsumerWebPartWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'ListSearchConsumerWebPartWebPartStrings' {
|
||||
const strings: IListSearchConsumerWebPartWebPartStrings;
|
||||
export = strings;
|
||||
}
|
||||
declare interface IListSearchConsumerWebPartWebPartStrings {
|
||||
PropertyPaneDescription: string;
|
||||
BasicGroupName: string;
|
||||
DescriptionFieldLabel: string;
|
||||
}
|
||||
|
||||
declare module 'ListSearchConsumerWebPartWebPartStrings' {
|
||||
const strings: IListSearchConsumerWebPartWebPartStrings;
|
||||
export = strings;
|
||||
}
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 383 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 383 B |
|
@ -1,31 +1,31 @@
|
|||
{
|
||||
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
|
||||
|
||||
"rules": {
|
||||
"class-name": false,
|
||||
"export-name": false,
|
||||
"forin": false,
|
||||
"label-position": false,
|
||||
"member-access": true,
|
||||
"no-arg": false,
|
||||
"no-console": false,
|
||||
"no-construct": false,
|
||||
"no-duplicate-variable": true,
|
||||
"no-eval": false,
|
||||
"no-function-expression": true,
|
||||
"no-internal-module": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-unnecessary-semicolons": true,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": false,
|
||||
"no-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
{
|
||||
"extends": "@microsoft/sp-tslint-rules/base-tslint.json",
|
||||
|
||||
"rules": {
|
||||
"class-name": false,
|
||||
"export-name": false,
|
||||
"forin": false,
|
||||
"label-position": false,
|
||||
"member-access": true,
|
||||
"no-arg": false,
|
||||
"no-console": false,
|
||||
"no-construct": false,
|
||||
"no-duplicate-variable": true,
|
||||
"no-eval": false,
|
||||
"no-function-expression": true,
|
||||
"no-internal-module": true,
|
||||
"no-shadowed-variable": true,
|
||||
"no-switch-case-fall-through": true,
|
||||
"no-unnecessary-semicolons": true,
|
||||
"no-unused-expression": true,
|
||||
"no-use-before-declare": false,
|
||||
"no-with-statement": true,
|
||||
"semicolon": true,
|
||||
"trailing-comma": false,
|
||||
"typedef": false,
|
||||
"typedef-whitespace": false,
|
||||
"use-named-parameter": true,
|
||||
"variable-name": false,
|
||||
"whitespace": false
|
||||
}
|
||||
}
|
|
@ -1,259 +1,259 @@
|
|||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const webpack = require("webpack");
|
||||
const resolve = require("path").resolve;
|
||||
const CertStore = require("@microsoft/gulp-core-build-serve/lib/CertificateStore");
|
||||
const CertificateStore = CertStore.CertificateStore || CertStore.default;
|
||||
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
|
||||
const del = require("del");
|
||||
const port = 4321;
|
||||
const host = "https://localhost:" + port;
|
||||
|
||||
///
|
||||
// Transforms define("<guid>", ...) to web part specific define("<web part id_version", ...)
|
||||
// the same approach is used inside copyAssets SPFx build step
|
||||
///
|
||||
class DynamicLibraryPlugin {
|
||||
constructor(options) {
|
||||
this.opitons = options;
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.hooks.emit.tap("DynamicLibraryPlugin", compilation => {
|
||||
for (const assetId in this.opitons.modulesMap) {
|
||||
const moduleMap = this.opitons.modulesMap[assetId];
|
||||
|
||||
if (compilation.assets[assetId]) {
|
||||
const rawValue = compilation.assets[assetId].children[0]._value;
|
||||
compilation.assets[assetId].children[0]._value = rawValue.replace(this.opitons.libraryName, moduleMap.id + "_" + moduleMap.version);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
// Removes *.module.scss.ts on the first execution in order prevent conflicts with *.module.scss.d.ts
|
||||
// generated by css-modules-typescript-loader
|
||||
///
|
||||
class ClearCssModuleDefinitionsPlugin {
|
||||
constructor(options) {
|
||||
this.options = options || {};
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.hooks.done.tap("FixStylesPlugin", stats => {
|
||||
if (!this.options.deleted) {
|
||||
|
||||
setTimeout(() => {
|
||||
del.sync(["src/**/*.module.scss.ts"]);
|
||||
}, 3000);
|
||||
|
||||
this.options.deleted = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let baseConfig = {
|
||||
target: "web",
|
||||
mode: "development",
|
||||
devtool: "source-map",
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx", ".js"],
|
||||
modules: ["node_modules"]
|
||||
},
|
||||
context: path.resolve(__dirname),
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
loader: "ts-loader",
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
compilerOptions: {
|
||||
declarationMap: false
|
||||
}
|
||||
},
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
use: [{
|
||||
loader: "@microsoft/loader-cased-file",
|
||||
options: {
|
||||
name: "[name:lower]_[hash].[ext]"
|
||||
}
|
||||
}],
|
||||
test: /\.(jpe?g|png|woff|eot|ttf|svg|gif|dds)$/i
|
||||
},
|
||||
{
|
||||
use: [{
|
||||
loader: "html-loader"
|
||||
}],
|
||||
test: /\.html$/
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{
|
||||
loader: "@microsoft/loader-load-themed-styles",
|
||||
options: {
|
||||
async: true
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: "css-loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: function (fileName) {
|
||||
return fileName.endsWith(".module.scss"); // scss modules support
|
||||
},
|
||||
use: [
|
||||
{
|
||||
loader: "@microsoft/loader-load-themed-styles",
|
||||
options: {
|
||||
async: true
|
||||
}
|
||||
},
|
||||
"css-modules-typescript-loader",
|
||||
{
|
||||
loader: "css-loader",
|
||||
options: {
|
||||
modules: {
|
||||
localIdentName: "[local]_[hash:base64:8]"
|
||||
}
|
||||
}
|
||||
}, // translates CSS into CommonJS
|
||||
"sass-loader" // compiles Sass to CSS, using Node Sass by default
|
||||
]
|
||||
},
|
||||
{
|
||||
test: function (fileName) {
|
||||
return !fileName.endsWith(".module.scss") && fileName.endsWith(".scss"); // just regular .scss
|
||||
},
|
||||
use: [
|
||||
{
|
||||
loader: "@microsoft/loader-load-themed-styles",
|
||||
options: {
|
||||
async: true
|
||||
}
|
||||
},
|
||||
"css-loader", // translates CSS into CommonJS
|
||||
"sass-loader" // compiles Sass to CSS, using Node Sass by default
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
tslint: true
|
||||
}),
|
||||
new ClearCssModuleDefinitionsPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
|
||||
"process.env.DEBUG": JSON.stringify(true),
|
||||
"DEBUG": JSON.stringify(true)
|
||||
})],
|
||||
devServer: {
|
||||
hot: false,
|
||||
contentBase: resolve(__dirname),
|
||||
publicPath: host + "/dist/",
|
||||
host: "localhost",
|
||||
port: port,
|
||||
disableHostCheck: true,
|
||||
historyApiFallback: true,
|
||||
open: true,
|
||||
writeToDisk: false,
|
||||
openPage: host + "/temp/workbench.html",
|
||||
stats: {
|
||||
preset: "errors-only",
|
||||
colors: true,
|
||||
chunks: false,
|
||||
modules: false,
|
||||
assets: false
|
||||
},
|
||||
proxy: { // url re-write for resources to be served directly from src folder
|
||||
"/lib/**/loc/*.js": {
|
||||
target: host,
|
||||
pathRewrite: { "^/lib": "/src" },
|
||||
secure: false
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
},
|
||||
https: {
|
||||
cert: CertificateStore.instance.certificateData,
|
||||
key: CertificateStore.instance.keyData
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const createConfig = function () {
|
||||
// remove old css module TypeScript definitions
|
||||
del.sync(["dist/*.js", "dist/*.map"]);
|
||||
|
||||
// we need only "externals", "output" and "entry" from the original webpack config
|
||||
let originalWebpackConfig = require("./temp/_webpack_config.json");
|
||||
baseConfig.externals = originalWebpackConfig.externals;
|
||||
baseConfig.output = originalWebpackConfig.output;
|
||||
|
||||
baseConfig.entry = getEntryPoints(originalWebpackConfig.entry);
|
||||
|
||||
baseConfig.output.publicPath = host + "/dist/";
|
||||
|
||||
const manifest = require("./temp/manifests.json");
|
||||
const modulesMap = {};
|
||||
const originalEntries = Object.keys(originalWebpackConfig.entry);
|
||||
|
||||
for (const jsModule of manifest) {
|
||||
if (jsModule.loaderConfig
|
||||
&& jsModule.loaderConfig.entryModuleId
|
||||
&& originalEntries.indexOf(jsModule.loaderConfig.entryModuleId) !== -1) {
|
||||
modulesMap[jsModule.loaderConfig.entryModuleId + ".js"] = {
|
||||
id: jsModule.id,
|
||||
version: jsModule.version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
baseConfig.plugins.push(new DynamicLibraryPlugin({
|
||||
modulesMap: modulesMap,
|
||||
libraryName: originalWebpackConfig.output.library
|
||||
}));
|
||||
|
||||
return baseConfig;
|
||||
}
|
||||
|
||||
function getEntryPoints(entry) {
|
||||
// fix: ".js" entry needs to be ".ts"
|
||||
// also replaces the path form /lib/* to /src/*
|
||||
let newEntry = {};
|
||||
let libSearchRegexp;
|
||||
if (path.sep === "/") {
|
||||
libSearchRegexp = /\/lib\//gi;
|
||||
} else {
|
||||
libSearchRegexp = /\\lib\\/gi;
|
||||
}
|
||||
|
||||
const srcPathToReplace = path.sep + "src" + path.sep;
|
||||
|
||||
for (const key in entry) {
|
||||
let entryPath = entry[key];
|
||||
if (entryPath.indexOf("bundle-entries") === -1) {
|
||||
entryPath = entryPath.replace(libSearchRegexp, srcPathToReplace).slice(0, -3) + ".ts";
|
||||
} else {
|
||||
// replace paths and extensions in bundle file
|
||||
let bundleContent = fs.readFileSync(entryPath).toString();
|
||||
bundleContent = bundleContent.replace(libSearchRegexp, srcPathToReplace).replace(/\.js/gi, ".ts");
|
||||
fs.writeFileSync(entryPath, bundleContent);
|
||||
}
|
||||
newEntry[key] = entryPath;
|
||||
}
|
||||
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
module.exports = createConfig();
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const webpack = require("webpack");
|
||||
const resolve = require("path").resolve;
|
||||
const CertStore = require("@microsoft/gulp-core-build-serve/lib/CertificateStore");
|
||||
const CertificateStore = CertStore.CertificateStore || CertStore.default;
|
||||
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
|
||||
const del = require("del");
|
||||
const port = 4321;
|
||||
const host = "https://localhost:" + port;
|
||||
|
||||
///
|
||||
// Transforms define("<guid>", ...) to web part specific define("<web part id_version", ...)
|
||||
// the same approach is used inside copyAssets SPFx build step
|
||||
///
|
||||
class DynamicLibraryPlugin {
|
||||
constructor(options) {
|
||||
this.opitons = options;
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.hooks.emit.tap("DynamicLibraryPlugin", compilation => {
|
||||
for (const assetId in this.opitons.modulesMap) {
|
||||
const moduleMap = this.opitons.modulesMap[assetId];
|
||||
|
||||
if (compilation.assets[assetId]) {
|
||||
const rawValue = compilation.assets[assetId].children[0]._value;
|
||||
compilation.assets[assetId].children[0]._value = rawValue.replace(this.opitons.libraryName, moduleMap.id + "_" + moduleMap.version);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
// Removes *.module.scss.ts on the first execution in order prevent conflicts with *.module.scss.d.ts
|
||||
// generated by css-modules-typescript-loader
|
||||
///
|
||||
class ClearCssModuleDefinitionsPlugin {
|
||||
constructor(options) {
|
||||
this.options = options || {};
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.hooks.done.tap("FixStylesPlugin", stats => {
|
||||
if (!this.options.deleted) {
|
||||
|
||||
setTimeout(() => {
|
||||
del.sync(["src/**/*.module.scss.ts"]);
|
||||
}, 3000);
|
||||
|
||||
this.options.deleted = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let baseConfig = {
|
||||
target: "web",
|
||||
mode: "development",
|
||||
devtool: "source-map",
|
||||
resolve: {
|
||||
extensions: [".ts", ".tsx", ".js"],
|
||||
modules: ["node_modules"]
|
||||
},
|
||||
context: path.resolve(__dirname),
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
loader: "ts-loader",
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
compilerOptions: {
|
||||
declarationMap: false
|
||||
}
|
||||
},
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
use: [{
|
||||
loader: "@microsoft/loader-cased-file",
|
||||
options: {
|
||||
name: "[name:lower]_[hash].[ext]"
|
||||
}
|
||||
}],
|
||||
test: /\.(jpe?g|png|woff|eot|ttf|svg|gif|dds)$/i
|
||||
},
|
||||
{
|
||||
use: [{
|
||||
loader: "html-loader"
|
||||
}],
|
||||
test: /\.html$/
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{
|
||||
loader: "@microsoft/loader-load-themed-styles",
|
||||
options: {
|
||||
async: true
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: "css-loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: function (fileName) {
|
||||
return fileName.endsWith(".module.scss"); // scss modules support
|
||||
},
|
||||
use: [
|
||||
{
|
||||
loader: "@microsoft/loader-load-themed-styles",
|
||||
options: {
|
||||
async: true
|
||||
}
|
||||
},
|
||||
"css-modules-typescript-loader",
|
||||
{
|
||||
loader: "css-loader",
|
||||
options: {
|
||||
modules: {
|
||||
localIdentName: "[local]_[hash:base64:8]"
|
||||
}
|
||||
}
|
||||
}, // translates CSS into CommonJS
|
||||
"sass-loader" // compiles Sass to CSS, using Node Sass by default
|
||||
]
|
||||
},
|
||||
{
|
||||
test: function (fileName) {
|
||||
return !fileName.endsWith(".module.scss") && fileName.endsWith(".scss"); // just regular .scss
|
||||
},
|
||||
use: [
|
||||
{
|
||||
loader: "@microsoft/loader-load-themed-styles",
|
||||
options: {
|
||||
async: true
|
||||
}
|
||||
},
|
||||
"css-loader", // translates CSS into CommonJS
|
||||
"sass-loader" // compiles Sass to CSS, using Node Sass by default
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin({
|
||||
tslint: true
|
||||
}),
|
||||
new ClearCssModuleDefinitionsPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
|
||||
"process.env.DEBUG": JSON.stringify(true),
|
||||
"DEBUG": JSON.stringify(true)
|
||||
})],
|
||||
devServer: {
|
||||
hot: false,
|
||||
contentBase: resolve(__dirname),
|
||||
publicPath: host + "/dist/",
|
||||
host: "localhost",
|
||||
port: port,
|
||||
disableHostCheck: true,
|
||||
historyApiFallback: true,
|
||||
open: true,
|
||||
writeToDisk: false,
|
||||
openPage: host + "/temp/workbench.html",
|
||||
stats: {
|
||||
preset: "errors-only",
|
||||
colors: true,
|
||||
chunks: false,
|
||||
modules: false,
|
||||
assets: false
|
||||
},
|
||||
proxy: { // url re-write for resources to be served directly from src folder
|
||||
"/lib/**/loc/*.js": {
|
||||
target: host,
|
||||
pathRewrite: { "^/lib": "/src" },
|
||||
secure: false
|
||||
}
|
||||
},
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
},
|
||||
https: {
|
||||
cert: CertificateStore.instance.certificateData,
|
||||
key: CertificateStore.instance.keyData
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const createConfig = function () {
|
||||
// remove old css module TypeScript definitions
|
||||
del.sync(["dist/*.js", "dist/*.map"]);
|
||||
|
||||
// we need only "externals", "output" and "entry" from the original webpack config
|
||||
let originalWebpackConfig = require("./temp/_webpack_config.json");
|
||||
baseConfig.externals = originalWebpackConfig.externals;
|
||||
baseConfig.output = originalWebpackConfig.output;
|
||||
|
||||
baseConfig.entry = getEntryPoints(originalWebpackConfig.entry);
|
||||
|
||||
baseConfig.output.publicPath = host + "/dist/";
|
||||
|
||||
const manifest = require("./temp/manifests.json");
|
||||
const modulesMap = {};
|
||||
const originalEntries = Object.keys(originalWebpackConfig.entry);
|
||||
|
||||
for (const jsModule of manifest) {
|
||||
if (jsModule.loaderConfig
|
||||
&& jsModule.loaderConfig.entryModuleId
|
||||
&& originalEntries.indexOf(jsModule.loaderConfig.entryModuleId) !== -1) {
|
||||
modulesMap[jsModule.loaderConfig.entryModuleId + ".js"] = {
|
||||
id: jsModule.id,
|
||||
version: jsModule.version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
baseConfig.plugins.push(new DynamicLibraryPlugin({
|
||||
modulesMap: modulesMap,
|
||||
libraryName: originalWebpackConfig.output.library
|
||||
}));
|
||||
|
||||
return baseConfig;
|
||||
}
|
||||
|
||||
function getEntryPoints(entry) {
|
||||
// fix: ".js" entry needs to be ".ts"
|
||||
// also replaces the path form /lib/* to /src/*
|
||||
let newEntry = {};
|
||||
let libSearchRegexp;
|
||||
if (path.sep === "/") {
|
||||
libSearchRegexp = /\/lib\//gi;
|
||||
} else {
|
||||
libSearchRegexp = /\\lib\\/gi;
|
||||
}
|
||||
|
||||
const srcPathToReplace = path.sep + "src" + path.sep;
|
||||
|
||||
for (const key in entry) {
|
||||
let entryPath = entry[key];
|
||||
if (entryPath.indexOf("bundle-entries") === -1) {
|
||||
entryPath = entryPath.replace(libSearchRegexp, srcPathToReplace).slice(0, -3) + ".ts";
|
||||
} else {
|
||||
// replace paths and extensions in bundle file
|
||||
let bundleContent = fs.readFileSync(entryPath).toString();
|
||||
bundleContent = bundleContent.replace(libSearchRegexp, srcPathToReplace).replace(/\.js/gi, ".ts");
|
||||
fs.writeFileSync(entryPath, bundleContent);
|
||||
}
|
||||
newEntry[key] = entryPath;
|
||||
}
|
||||
|
||||
return newEntry;
|
||||
}
|
||||
|
||||
module.exports = createConfig();
|