增加我的留言布局

从我的留言-好友验证、个人信息-我的帮助,查看志愿者、个人信息-我的好友,可点击用户图标查看个人信息,并发起好友申请/同意好友邀请
master
pan 5 years ago
parent 8284bfa0fe
commit 8830296ba7
  1. 2
      src/Address.tsx
  2. 13
      src/App.tsx
  3. 22
      src/Main.tsx
  4. 2
      src/Page.tsx
  5. 2
      src/bootstrap/InputGroup.tsx
  6. 12
      src/entity.ts
  7. 1
      src/index.css
  8. 3
      src/my/CloseDialog.tsx
  9. 16
      src/my/MyDialog.tsx
  10. 211
      src/my/MyFriend.tsx
  11. 3
      src/my/MyHelp.tsx
  12. 37
      src/my/MyInfo.tsx
  13. 27
      src/my/MyLeaveWord.tsx
  14. 8
      src/my/MyMessage.tsx
  15. 25
      src/my/SeekHelp.tsx
  16. 2
      src/sub/IndexMenu.tsx
  17. 2
      src/sub/SendHelp.tsx
  18. 14
      src/sub/Volunteer.tsx

@ -5,7 +5,7 @@ import React from "react";
/**
*
*/
export class Address extends React.Component<OnChangeAddress, any>{
export class Address extends React.Component<OnChangeAddress, { addressList:Array<any> }>{
constructor(props: Readonly<OnChangeAddress>) {

@ -2,12 +2,12 @@ import React from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
import {Login} from './account/Login';
import {withCookies} from 'react-cookie';
import {Cookies, withCookies} from 'react-cookie';
import {Main} from "./Main";
import {Register} from "./account/Register";
import {user_cookie} from "./account/PropCookie";
class App extends React.Component<any, any> {
class App extends React.Component<{ allCookies:any;cookies:Cookies }, { page?:JSX.Element }> {
constructor(props: Readonly<any>) {
@ -27,11 +27,9 @@ class App extends React.Component<any, any> {
}
}
//注销登录
//注销登录
logout(){
const { cookies } = this.props
cookies.remove(user_cookie)
this.props.cookies.remove(user_cookie)
this.toLogin()
}
@ -47,9 +45,8 @@ class App extends React.Component<any, any> {
//登录
login(user:string,password:string){
const { cookies } = this.props
console.debug("user_cookie="+user)
cookies.set(user_cookie,user)
this.props.cookies.set(user_cookie,user)
this.setState({
page:<Main user={user} logout={()=>this.logout()}/>

@ -7,6 +7,7 @@ import {MyFriend} from "./my/MyFriend";
import {MyDialog} from "./my/MyDialog";
import {MyLeaveWord} from "./my/MyLeaveWord";
import {MyMessage} from "./my/MyMessage";
import {User} from "./entity";
/**
*
@ -29,7 +30,18 @@ enum DialogType {
/**
*
*/
export class Main extends React.Component<any, any>{
export class Main extends React.Component<{ user:string,logout:Function },
{
menu:Menu;
subMenu:JSX.Element;
friendList:Array<User>;
my:{
menuName:string;
content:JSX.Element|null;
open:boolean;
}
}
>{
constructor(props: Readonly<any>) {
super(props);
@ -91,7 +103,7 @@ export class Main extends React.Component<any, any>{
*
*/
closeDialog(){
this.setState({my:{...this.state.my,...{menuName: "",content:null,open:false}}})
this.setState({ my:{...this.state.my,...{menuName:"",content:null,open:false}}})
console.debug(this.state.my)
}
@ -108,12 +120,12 @@ export class Main extends React.Component<any, any>{
break;
case DialogType.leaveWord:
this.setState({
my:{menuName:dialogType,content:<MyLeaveWord/>,open:true}
my:{menuName:dialogType,content:<MyLeaveWord user={this.props.user}/>,open:true}
})
break;
case DialogType.message:
this.setState({
my:{menuName:dialogType,content:<MyMessage/>,open:true}
my:{menuName:dialogType,content:<MyMessage user={this.props.user}/>,open:true}
})
break;
}
@ -149,7 +161,7 @@ export class Main extends React.Component<any, any>{
<Navbar.Brand className="ml-3"></Navbar.Brand>
<MyDialog menuName={this.state.my.menuName} content={this.state.my.content} open={this.state.my.open} onClose={()=>this.closeDialog()}/>
<MyDialog titleId="my-dialog" menuName={this.state.my.menuName} content={this.state.my.content} open={this.state.my.open} onClose={()=>this.closeDialog()}/>
</Nav>
</Navbar>

@ -5,7 +5,7 @@ import {Pagination} from "react-bootstrap";
/**
*
*/
export class Page extends React.Component<PageProps, any>{
export class Page extends React.Component<PageProps, { undefined?:undefined }>{
render() {
return (

@ -11,7 +11,7 @@ const defaultValid={
/**
* bootstrap InputGroup组件封装
*/
export class Input extends React.Component<FormInputProps, any>{
export class Input extends React.Component<FormInputProps, { undefined?:undefined }>{
merge(){
return {...defaultValid,...this.props.valid}

@ -151,9 +151,9 @@ export interface CloseDialogProps extends BaseDialogProps{
/**
*
*/
export interface MyDialogProps extends BaseDialogProps{
export interface MyDialogProps extends CloseDialogProps{
//弹窗内容
content:React.Component;
content:JSX.Element|null;
//弹窗状态
open:boolean;
}
@ -203,14 +203,12 @@ export interface UserEdit extends User{
/**
*
*/
export interface Chat {
//发送人名称
name:string;
//发送人头像
headImg:string;
export interface Chat extends User{
//发送内容
content:string;
//发送时间
time:number;
//是否我发送的信息
flag:boolean;
}

@ -122,3 +122,4 @@
.volunteer{
width: 1400px;
}

@ -5,7 +5,8 @@ import {CloseDialogProps} from "../entity";
/**
*
*/
export class CloseDialog extends React.Component<CloseDialogProps, any>{
export class CloseDialog extends React.Component<CloseDialogProps, {undefined?:undefined}>{
render() {
return (

@ -8,30 +8,22 @@ import {CloseDialog} from "./CloseDialog";
/**
*
*/
export class MyDialog extends React.Component<MyDialogProps, any>{
export class MyDialog extends React.Component<MyDialogProps, { undefined?:undefined }>{
constructor(props: Readonly<MyDialogProps>) {
super(props);
this.state={
titleId:"my-dialog"
}
}
render() {
return (
<Dialog
hideBackdrop={true}
open={this.props.open}
PaperComponent={(props)=>
<Draggable handle={"#"+this.state.titleId} cancel={'[class*="MuiDialogContent-root"]'}>
<Draggable handle={"#"+this.props.titleId} cancel={'[class*="MuiDialogContent-root"]'}>
<Paper {...props} />
</Draggable>}
aria-labelledby={this.state.titleId}
aria-labelledby={this.props.titleId}
classes={{paper:"w-100"}}
>
<CloseDialog menuName={this.props.menuName} onClose={()=>this.props.onClose()} titleId={this.state.titleId}/>
<CloseDialog menuName={this.props.menuName} onClose={()=>this.props.onClose()} titleId={this.props.titleId}/>
<div className="p-3">
{this.props.content}

@ -3,61 +3,34 @@ import {Button, Col, Container, FormControl, Image, ListGroup, Row,} from "react
import {Chat, User} from "../entity";
import {Tooltip} from "@material-ui/core";
import moment from "moment";
import {MyInfo} from "./MyInfo";
import {MyDialog} from "./MyDialog";
/**
*
* @param props
* @constructor
*/
function UserPart(props:Readonly<any>) {
return (
<Col xs={4}>
<Image roundedCircle={true} src={props.headImg} className="chat-headImg"/>
<span className="d-block text-center user-name">{props.name}</span>
</Col>
)
}
/**
*
* @param props
* @constructor
*/
function ContentPart(props:Readonly<any>) {
return (
<Col xs={7}>
<h6 className="text-center">{moment(props.time).format("YYYY-MM-DD HH:mm:ss")}</h6>
<p>{props.content}</p>
</Col>
)
}
/**
*
* @param props
* @constructor
*/
function GroupPart(props:Readonly<any>) {
if(props.flag){
return (
<Row>
<UserPart name={props.name} headImg={props.headImg}/>
<ContentPart content={props.content}/>
</Row>)
}else{
return (
<Row>
<ContentPart content={props.content}/>
<UserPart name={props.name} headImg={props.headImg}/>
</Row>)
}
}
const maxLength=150
/**
*
*/
export class MyFriend extends React.Component<any,any>{
export class MyFriend extends React.Component<{ user:string },
{
//好友列表
friendList:Array<User>;
//查找好友关键字
queryFriend:string;
//用户列表
userList:Array<User>;
//聊天记录
chatList:Array<Chat>;
//当前选中好友
friendIndex:number|null;
//发送内容
sendContent:String;
//查看用户信息
openUserInfo:boolean;
//查看用户ID
userId?:string;
}
>{
constructor(props: Readonly<any>) {
@ -73,9 +46,11 @@ export class MyFriend extends React.Component<any,any>{
//聊天记录
chatList:[],
//当前选中好友
friendIndex:-1,
friendIndex:null,
//发送内容
sendContent:''
sendContent:'',
//查看用户信息
openUserInfo:false
}
}
@ -90,34 +65,34 @@ export class MyFriend extends React.Component<any,any>{
queryUser(keyword:string){
this.setState({
userList:[{
//用户姓名
headImg:"logo512.png",
userId:"admin",
name:"张三",
//用户年龄
age:Math.floor(Math.random()*100)+1,
//用户电话
mobile:15920722180,
//发送时间
time:new Date().getTime()
age:Math.ceil(Math.random()*100)+1,
mobile:1234567879,
email:"admin@qq.com",
address:"上海高新区",
info:"个人简介",
},
{
//用户姓名
name:"李四",
//用户年龄
age:Math.floor(Math.random()*100)+1,
//用户电话
mobile:15920722180,
//发送时间
time:new Date().getTime()
headImg:"logo512.png",
userId:"admin",
name:"张三",
age:Math.ceil(Math.random()*100)+1,
mobile:1234567879,
email:"admin@qq.com",
address:"上海高新区",
info:"个人简介",
},
{
//用户姓名
name:"王五",
//用户年龄
age:Math.floor(Math.random()*100)+1,
//用户电话
mobile:15920722180,
//发送时间
time:new Date().getTime()
headImg:"logo512.png",
userId:"admin",
name:"张三",
age:Math.ceil(Math.random()*100)+1,
mobile:1234567879,
email:"admin@qq.com",
address:"上海高新区",
info:"个人简介",
}]
})
}
@ -126,15 +101,36 @@ export class MyFriend extends React.Component<any,any>{
loadMyFriend(keyword:string){
this.setState({
friendList:[{
name:"好友1",
headImg:"logo512.png",
userId:"admin",
name:"张三",
age:Math.ceil(Math.random()*100)+1,
mobile:1234567879,
email:"admin@qq.com",
address:"上海高新区",
info:"个人简介",
status:true
},
{
name:"好友2",
headImg:"logo512.png",
userId:"admin",
name:"张三",
age:Math.ceil(Math.random()*100)+1,
mobile:1234567879,
email:"admin@qq.com",
address:"上海高新区",
info:"个人简介",
status:false
},
{
name:"好友3",
headImg:"logo512.png",
userId:"admin",
name:"张三",
age:Math.ceil(Math.random()*100)+1,
mobile:1234567879,
email:"admin@qq.com",
address:"上海高新区",
info:"个人简介",
status:false
}]
})
@ -149,7 +145,16 @@ export class MyFriend extends React.Component<any,any>{
//发送人头像
headImg:"logo512.png",
//发送内容
content:"发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容"
content:"发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容",
//发送时间
time:new Date().getTime(),
userId:"admin",
age:Math.ceil(Math.random()*100)+1,
mobile:1234567879,
email:"admin@qq.com",
address:"上海高新区",
info:"个人简介",
flag:false
},
{
//发送人名称
@ -157,7 +162,16 @@ export class MyFriend extends React.Component<any,any>{
//发送人头像
headImg:"logo512.png",
//发送内容
content:"发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容"
content:"发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容",
//发送时间
time:new Date().getTime(),
userId:"admin",
age:Math.ceil(Math.random()*100)+1,
mobile:1234567879,
email:"admin@qq.com",
address:"上海高新区",
info:"个人简介",
flag:false
},
{
//发送人名称
@ -165,7 +179,16 @@ export class MyFriend extends React.Component<any,any>{
//发送人头像
headImg:"logo512.png",
//发送内容
content:"发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容"
content:"发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容发送内容",
//发送时间
time:new Date().getTime(),
userId:"admin",
age:Math.ceil(Math.random()*100)+1,
mobile:1234567879,
email:"admin@qq.com",
address:"上海高新区",
info:"个人简介",
flag:true
}]
})
}
@ -205,7 +228,7 @@ export class MyFriend extends React.Component<any,any>{
<ListGroup.Item key={"list"+index} className="d-flex justify-content-between" variant="info">
<span>{user.name}</span>
<Tooltip title="查看用户信息" placement="right">
<img src="user.svg" alt="查看用户信息" className="userIcon"/>
<img src="user.svg" alt="查看用户信息" className="userIcon" onClick={()=>this.setState({openUserInfo:true,userId:user.userId})}/>
</Tooltip>
</ListGroup.Item>)}
</ListGroup>
@ -215,7 +238,27 @@ export class MyFriend extends React.Component<any,any>{
<Col xs={8}>
<Container className="bg-light chat-history overflow-auto">
{this.state.chatList.map((chat:Chat,index:number)=>
<GroupPart key={"group"+index} name={chat.name} headImg={chat.headImg} content={chat.content} flag={this.props.user===chat.name}/>
this.props.user===chat.userId?
<Row>
<Col xs={4}>
<Image roundedCircle={true} src={chat.headImg} className="chat-headImg"/>
<span className="d-block text-center user-name">{chat.name}</span>
</Col>
<Col xs={7}>
<h6 className="text-center">{moment(chat.time).format("YYYY-MM-DD HH:mm:ss")}</h6>
<p>{chat.content}</p>
</Col>
</Row>:
<Row>
<Col xs={7}>
<h6 className="text-center">{moment(chat.time).format("YYYY-MM-DD HH:mm:ss")}</h6>
<p>{chat.content}</p>
</Col>
<Col xs={4}>
<Image roundedCircle={true} src={chat.headImg} className="chat-headImg"/>
<span className="d-block text-center user-name">{chat.name}</span>
</Col>
</Row>
)}
</Container>
<Container className={"bg-white chat-send p-3 border-info border "+(this.state.friendIndex!==-1?"":"d-none")}>
@ -242,6 +285,10 @@ export class MyFriend extends React.Component<any,any>{
</Container>
</Col>
</Row>
<MyDialog titleId="view-user" menuName="用户信息"
content={<MyInfo ownUserId={this.props.user} isOwn={false} isMyFriend={false} isAdd={true} userId={this.state.userId}/>}
open={this.state.openUserInfo} onClose={()=>this.setState({openUserInfo:false})}/>
</Container>
);
}

@ -8,7 +8,7 @@ const classList="border-info border d-flex justify-content-center align-items-ce
/**
*
*/
export class MyHelp extends React.Component<any, { data:Array<MyHelpState> }>{
export class MyHelp extends React.Component<{ undefined?:undefined }, { data:Array<MyHelpState> }>{
constructor(props: Readonly<any>) {
@ -181,6 +181,7 @@ export class MyHelp extends React.Component<any, { data:Array<MyHelpState> }>{
</Container>
</div>
)}
</div>
)
}

@ -3,10 +3,18 @@ import {Button, Col, Container, Form, FormControl, Image, Row} from "react-boots
import {UserEdit} from "../entity";
import {Input} from "../bootstrap/InputGroup";
/**
*
*/
export class MyInfo extends React.Component<any, UserEdit>{
export class MyInfo extends React.Component<
{
isOwn:boolean;
ownUserId:string;
userId?:string;
isMyFriend:boolean;
isAdd:boolean;
}, UserEdit>{
constructor(props: Readonly<any>) {
@ -96,8 +104,23 @@ export class MyInfo extends React.Component<any, UserEdit>{
}
/**
*
*/
addFriend(){
}
/**
*
*/
agreeFriend(){
}
render() {
return (
<Container>
<Row>
@ -157,6 +180,7 @@ export class MyInfo extends React.Component<any, UserEdit>{
:null
}
{this.props.isOwn?
<Row className="p-3">
<Col className="text-center">
{this.state.contentEditable?
@ -168,7 +192,18 @@ export class MyInfo extends React.Component<any, UserEdit>{
<Button variant={"light"} onClick={()=>this.modifyPwd()}></Button>:
<Button variant={"light"} onClick={()=>this.openModifyPwd()} disabled={this.state.contentEditable}></Button>}
</Col>
</Row>:
<Row className="p-3">
<Col className="text-center">
{this.props.isMyFriend?null:this.props.isAdd?
<Button variant={"primary"} onClick={()=>this.addFriend()}></Button>
:
<Button variant={"primary"} onClick={()=>this.agreeFriend()}></Button>
}
</Col>
</Row>
}
</Container>
)
}

@ -1,6 +1,9 @@
import React from "react";
import {Button, Col, Container, Image, Row} from "react-bootstrap";
import {ActiveDetail, User} from "../entity";
import {Tooltip} from "@material-ui/core";
import {MyDialog} from "./MyDialog";
import {MyInfo} from "./MyInfo";
enum LeaveWordType {
recommend,
@ -24,15 +27,17 @@ interface Type2 {
/**
*
*/
export class MyLeaveWord extends React.Component<any, {
export class MyLeaveWord extends React.Component<{ user:string }, {
data:Array<Type1|Type2>;
openUserInfo:boolean;
userId?:string;
}>{
constructor(props: Readonly<any>) {
super(props);
this.state={data:[]}
this.state={data:[],openUserInfo:false}
}
componentDidMount() {
@ -115,8 +120,9 @@ export class MyLeaveWord extends React.Component<any, {
/**
*
* @param data
* @param index
*/
getData(data:Type1|Type2){
getData(data:Type1|Type2,index:number){
let body
if("active" in data ){
body=<Col>
@ -147,7 +153,7 @@ export class MyLeaveWord extends React.Component<any, {
}
return (
<Container className="mt-3 pt-2 pb-2 border-info border rounded-pill">
<Container key={"Container"+index} className="mt-3 pt-2 pb-2 border-info border rounded-pill">
<Row>
<Col>
<h3 className="text-center">{this.getType(data.type)}</h3>
@ -156,10 +162,16 @@ export class MyLeaveWord extends React.Component<any, {
<Row>
<Col xs={3}>
<Image src={data.user.headImg} className="leave-word-headImg"/>
<span className="d-block text-center user-name">{data.user.name}</span>
<span className="text-center user-name ml-3">{data.user.name}</span>
{data.type===LeaveWordType.friend?
<Tooltip title="查看用户信息" placement="right">
<Image src="user.svg" className="ml-1 mb-1 userIcon" onClick={()=>this.setState({openUserInfo:true,userId:data.user.userId})}/>
</Tooltip>:null}
</Col>
{body}
</Row>
</Container>
)
}
@ -168,7 +180,10 @@ export class MyLeaveWord extends React.Component<any, {
render() {
return (
<div className="overflow-auto my-leave-world-height">
{this.state.data.map(data =>this.getData(data))}
{this.state.data.map((data,index) =>this.getData(data,index))}
<MyDialog titleId="view-user" menuName="用户信息"
content={<MyInfo ownUserId={this.props.user} isOwn={false} isMyFriend={false} isAdd={false} userId={this.state.userId}/>}
open={this.state.openUserInfo} onClose={()=>this.setState({openUserInfo:false})}/>
</div>
);
}

@ -13,7 +13,7 @@ enum Menu {
/**
*
*/
export class MyMessage extends React.Component<any, any>{
export class MyMessage extends React.Component<{ user:string }, { subMenu:Menu,page:JSX.Element }>{
constructor(props: Readonly<any>) {
@ -21,7 +21,7 @@ export class MyMessage extends React.Component<any, any>{
this.state={
subMenu:Menu.info,
page:<MyInfo/>
page:<MyInfo ownUserId={this.props.user} isMyFriend={false} isOwn={true} isAdd={false}/>
}
}
@ -30,13 +30,13 @@ export class MyMessage extends React.Component<any, any>{
this.setState({subMenu:menu})
switch (menu) {
case Menu.info:
this.setState({page:<MyInfo/>})
this.setState({page:<MyInfo ownUserId={this.props.user} isMyFriend={false} isOwn={true} isAdd={false}/>})
break
case Menu.help:
this.setState({page:<MyHelp/>})
break
case Menu.seekHelp:
this.setState({page:<SeekHelp/>})
this.setState({page:<SeekHelp user={this.props.user}/>})
break
}
}

@ -6,6 +6,8 @@ import Dialog from "@material-ui/core/Dialog";
import {CloseDialog} from "./CloseDialog";
import {Paper, Tooltip} from "@material-ui/core";
import Draggable from "react-draggable";
import {MyDialog} from "./MyDialog";
import {MyInfo} from "./MyInfo";
/**
*
@ -21,11 +23,15 @@ const titleId="seek-help-dialog"
/**
*
*/
export class SeekHelp extends React.Component<any,{
data:Array<SeekHelpState>,
open:boolean,
status?:VolunteerStatus,
volunteerList?:Array<User>}>{
export class SeekHelp extends React.Component<{ user:string },
{
data:Array<SeekHelpState>;
open:boolean;
status?:VolunteerStatus;
volunteerList?:Array<User>;
openUserInfo:boolean;
userId?:string;
}>{
constructor(props: Readonly<any>) {
@ -33,7 +39,8 @@ export class SeekHelp extends React.Component<any,{
this.state={
data:[],
open:false
open:false,
openUserInfo:false
}
}
@ -142,12 +149,16 @@ export class SeekHelp extends React.Component<any,{
<ListGroup.Item key={"list"+index} className="d-flex justify-content-between" variant="info">
<span>{user.name}</span>
<Tooltip title="查看用户信息" placement="right">
<img src="user.svg" alt="查看用户信息" className="userIcon"/>
<img src="user.svg" alt="查看用户信息" className="userIcon" onClick={()=>this.setState({openUserInfo:true,userId:user.userId})}/>
</Tooltip>
</ListGroup.Item>
)}
</ListGroup>
</Dialog>
<MyDialog titleId="view-user" menuName="用户信息"
content={<MyInfo ownUserId={this.props.user} isOwn={false} isMyFriend={false} isAdd={true} userId={this.state.userId}/>}
open={this.state.openUserInfo} onClose={()=>this.setState({openUserInfo:false})}/>
</div>
)
}

@ -6,7 +6,7 @@ import {Page} from "../Page";
/**
*
*/
export class IndexMenu extends React.Component<any, any>{
export class IndexMenu extends React.Component<{ undefined?:undefined }, any>{

@ -28,7 +28,7 @@ const recommendType=[RecommendType.no, RecommendType.choose,RecommendType.auto]
/**
*
*/
export class SendHelp extends React.Component<any, SendHelpState>{
export class SendHelp extends React.Component<{ undefined?:undefined }, SendHelpState>{
//存放活动背景图
private fileImg: RefObject<any>;
//当前选中的好友索引

@ -8,7 +8,19 @@ import {Address} from "../Address";
/**
*
*/
export class Volunteer extends React.Component<any, any>{
export class Volunteer extends React.Component<{ undefined?:undefined }, {
form:{
keyword:string;
address:string;
};
addressList:Array<{address:string}>;
volunteerList:Array<Array<VolunteerProps>>;
page:{
currentPage:number;
totalPage:number;
pageSize:number;
}
}>{
constructor(props: Readonly<any>) {

Loading…
Cancel
Save