1、打包:
gulp clean
gulp bundle --ship
gulp package-solution --ship
2、layout(下拉框)编辑状态
在webpart中配置layout
//xxxWebPart.ts
export interface IRemarkHistoryWebPartProps{
Iayout:string,
}
//
public render(): void {
const element: React.ReactElement<IRemarkHistoryProps > = React.createElement(
RemarkHistory,
{
layout: LayoutEnum[this.properties.layout],
}
);
ReactDom.render(element, this.domElement);
}
//PropertPaneDropDown配置一个下拉框
//PropertyPaneTextField配置一个输入框
protected getPropertyPaneConfiguration(){
return{
pages:[
groups:[
PropertyPaneDropdown('layout', {
label: strings.RemarkLayoutLabel,
options: [
{
key: LayoutEnum.STANDARD,
text: strings.RemarkLayoutStandard
},
{
key: LayoutEnum.CUSTOMIZE,
text: strings.RemarkLayoutCustomize
}
]
}),
]
]
}
}
在loc中添加RemarkLayoutLable
// loc/mystrings.d.ts
declare interface IremarkHistoryWebPartStrings{
RemarkLayoutLable:string
}
declare module 'RemarkHistoryWebPartStrings'{
const strings:IRemarkHistoryWebPartStrings;
export=strings;
}
// loc/en-us.js
define([],function(){
return{
"RemarkLayoutLable":"Layout",
}
})
在所有传递的组件的props中注册
定义一个枚举类型LayoutEnum.ts
在webpart引入
export enum LayoutEnum {
STANDARD,
CUSTOMIZE
}
结果:
3、history(文本框)编辑状态
const historyRemarks: RemarkItem[] = this.getHistoryRemarksFromConfiguration(this.properties.historyRemarks);
在所有传递的组件的props中注册
并在 loc/en-us.js & loc/mystrings.d.ts中声明
//枚举类型 RemarkItem.ts
export type RemarkItem = {
title: string;
text: string;
time: string;
types: string
}
//xxxWebPart.ts
export interface IRemarkHistoryWebPartProps {
historyRemarks: string;
}
export default class RemarkHistoryWebPart extends BaseClientSideWebPart<IRemarkHistoryWebPartProps> {
public render(): void {
const historyRemarks: RemarkItem[] = this.getHistoryRemarksFromConfiguration(this.properties.historyRemarks);
const element: React.ReactElement<IRemarkHistoryProps > = React.createElement(
RemarkHistory,
{
historyRemarks: historyRemarks,
}
);
ReactDom.render(element, this.domElement);
}
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneDropdown('layout', {
label: strings.RemarkLayoutLabel,
options: [
{
key: LayoutEnum.STANDARD,
text: strings.RemarkLayoutStandard
},
{
key: LayoutEnum.CUSTOMIZE,
text: strings.RemarkLayoutCustomize
}
]
});
PropertyPaneTextField('historyRemarks', {
label: strings.HistoryRemarkItems,
multiline: true
}),
]
}
]
}
]
};
}
//字符串转数组
//输入样例{"title":"No data","text":"No data","time":"No data","picture":"information"}
private getHistoryRemarksFromConfiguration(remarks: string): RemarkItem[] {
if(remarks==="") {
console.log("invalid remarks");
return [{title: 'No data', text: 'No data', time: 'No data', picture: 'information'}];
}
else {
let remarkItems: RemarkItem[] = [];
try
{
remarkItems = JSON.parse('[' + remarks + ']');
}
catch(err) {
console.log(err);
}
return remarkItems;
}
}
//图片选择 History.ts
val.picture?
<img className={styles['icon-xs'] + ' ' + styles['hide-on-fallback'] + ' ' + styles['event-icon']} src={require('./RemarkHistoryImg/'+val.picture)} alt=""/>
:
<img className={styles['icon-xs'] + ' ' + styles['hide-on-fallback'] + ' ' + styles['event-icon']} src={require("./RemarkHistoryImg/green.png")} alt=""/>
//
PropertyPaneTextField('historyRemarks', {
label: strings.HistoryRemarkItems,
multiline: true,
})
4、测试
import * as React from 'react';
import { configure, mount, ReactWrapper } from 'enzyme';
import * as Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
import { HistoryProps } from '../components/History/HistoryProps';
import History from '../components/History/History';
import { LayoutEnum } from '../LayoutEnum';
describe('History Remark Test', () => {
let reactComponent: ReactWrapper<HistoryProps>;
beforeEach(() => {
reactComponent = mount(React.createElement(
History,
{
historySectionTitleTips: "History Section Title Tips",
historySectionTitle: "History Section Title",
//historyRemarks: []
}
));
});
afterEach(() => {
reactComponent.unmount();
});
it('should history root web part element exists', () => {
// define the css selector
let cssSelector: string = 'h3';
// find the element using css selector
const element = reactComponent.find(cssSelector);
expect(element.length).toBeGreaterThan(0);
});
it('should history section has the correct title', () => {
// Arrange
// define contains/like css selector
let cssSelector: string = 'h3';
// Act
// find the elemet using css selector
const text = reactComponent.find(cssSelector).text();
// Assert
expect(text).toBe("History Section Title");
});
//样式切换
private showmore() {
this.setState({
name: this.state.name == 'ShowMore' ? 'ShowLess' : 'ShowMore',
isShowMore: !this.state.isShowMore,
})
}
style={{ width: '100%', height: this.props.historyRemarks.length<=3? 'auto' : !this.state.isShowMore? '561px': '100%',}}
//
{
arr.length >= 3 && key == arr.length - 1 ?
<img className={styles['icon-xs'] + ' ' + styles['hide-on-fallback'] + ' ' + styles['event-icon']} src={require("./RemarkHistoryImg/green.png")}></img>
: arr.length >= 3 && key == arr.length - 2 ?
<img className={styles['icon-xs'] + ' ' + styles['hide-on-fallback'] + ' ' + styles['event-icon']} src={require("./RemarkHistoryImg/yellow.png")}></img>
: arr.length >= 3 && key == arr.length - 3 ?
<img className={styles['icon-xs'] + ' ' + styles['hide-on-fallback'] + ' ' + styles['event-icon']} src={require("./RemarkHistoryImg/red.png")}></img>
:
<img className={styles['icon-xs'] + ' ' + styles['hide-on-fallback'] + ' ' + styles['event-icon']} src={require("./RemarkHistoryImg/green.png")}></img>
}
UI库
https://developer.microsoft.com/en-us/fabric#/controls/web/textfield
import { TextField } from 'office-ui-fabric-react/lib/TextField';
引用TextField 添加multiline输入框将更改为多行文字
<TextField multiline rows={9} cols={20} className={styles['margin-bottom-l']} placeholder={this.props.placeholder} value={this.state.value} onChange={() => { this.ChangeValue(event) }}></TextField>
如果样式在 ctrl styles中
请求方式className={styles['icon-xs'] + ' ' + styles['hide-on-fallback']}