Skip to content

Commit 0ab61fb

Browse files
CreateTicketForm working submit.
1 parent 09309fd commit 0ab61fb

File tree

4 files changed

+203
-56
lines changed

4 files changed

+203
-56
lines changed

src/components/TicketsWithSFormsBoard.js

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,81 @@ import React from "react";
22
import {CategorizedTicketsList} from "./ticket/CategorizedTicketsList";
33
import {SFormsDisplay} from "./SFormsDisplay";
44
import {CreateTicketForm} from "./ticket/CreateTicketForm";
5+
import Button from "react-bootstrap/Button";
6+
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
7+
import {faCaretDown} from "@fortawesome/free-solid-svg-icons/faCaretDown";
8+
import Collapse from "react-bootstrap/Collapse";
59

610
export class TicketsWithSFormsBoard extends React.Component {
711

812
constructor() {
913
super();
14+
this.state = {
15+
createTicketCollapseOpen: false,
16+
relatedTicketsCollapseOpen: false,
17+
displayFormCollapseOpen: true
18+
}
1019
}
1120

1221
render() {
1322
return <div>
14-
<h5>Tickets</h5>
15-
<CategorizedTicketsList projectName={this.props.projectName} contextUri={this.props.contextUri}/>
23+
<h5>
24+
Related Tickets
25+
<Button
26+
variant="link" size="sm"
27+
onClick={() => this.setState({relatedTicketsCollapseOpen: !this.state.relatedTicketsCollapseOpen})}
28+
aria-controls="related-tickets-collapse"
29+
aria-expanded={this.state.relatedTicketsCollapseOpen}
30+
>
31+
<FontAwesomeIcon color="black" icon={faCaretDown}/>
32+
</Button>
33+
</h5>
34+
<Collapse in={this.state.relatedTicketsCollapseOpen}>
35+
<div id="related-tickets-collapse">
36+
<CategorizedTicketsList projectName={this.props.projectName} contextUri={this.props.contextUri}
37+
displayed={this.state.relatedTicketsCollapseOpen}/>
38+
</div>
39+
</Collapse>
40+
41+
<br/>
42+
<h5>
43+
Create Ticket
44+
<Button
45+
variant="link" size="sm"
46+
onClick={() => this.setState({createTicketCollapseOpen: !this.state.createTicketCollapseOpen})}
47+
aria-controls="create-ticket-collapse"
48+
aria-expanded={this.state.createTicketCollapseOpen}
49+
>
50+
<FontAwesomeIcon color="black" icon={faCaretDown}/>
51+
</Button>
52+
</h5>
53+
<Collapse in={this.state.createTicketCollapseOpen}>
54+
<div id="create-ticket-collapse">
55+
<CreateTicketForm projectName={this.props.projectName}
56+
contextUri={this.props.contextUri}/>
57+
</div>
58+
</Collapse>
59+
1660
<br/>
17-
<CreateTicketForm/>
61+
<h5>
62+
Form display
63+
<Button
64+
variant="link" size="sm"
65+
onClick={() => this.setState({displayFormCollapseOpen: !this.state.displayFormCollapseOpen})}
66+
aria-controls="form-display-collapse"
67+
aria-expanded={this.state.displayFormCollapseOpen}
68+
>
69+
<FontAwesomeIcon color="black" icon={faCaretDown}/>
70+
</Button>
71+
</h5>
72+
<Collapse in={this.state.displayFormCollapseOpen}>
73+
<div id="form-display-collapse">
74+
<SFormsDisplay projectName={this.props.projectName} contextUri={this.props.contextUri}/>
75+
</div>
76+
</Collapse>
1877
<br/>
19-
<h5>Form display</h5>
20-
<SFormsDisplay projectName={this.props.projectName} contextUri={this.props.contextUri}/>
21-
</div>;
78+
</div>
79+
;
2280
}
2381
}
2482

src/components/search/IntelligentQuestionSelector.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import "intelligent-tree-select/lib/styles.css"
44
import 'bootstrap/dist/css/bootstrap.css';
55
import API from "../../api";
66
import {IntelligentTreeSelect} from 'intelligent-tree-select';
7+
import Button from "react-bootstrap/Button";
8+
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
9+
import {faCaretDown} from "@fortawesome/free-solid-svg-icons/faCaretDown";
10+
import Collapse from "react-bootstrap/Collapse";
711

812
export class IntelligentQuestionSelector extends React.Component {
913

@@ -12,7 +16,8 @@ export class IntelligentQuestionSelector extends React.Component {
1216
this.state = {
1317
activeLabel: "",
1418
activeQuestionOrigin: "",
15-
activeQuestionOriginPath: ""
19+
activeQuestionOriginPath: "",
20+
detailCollapseOpen: false,
1621
}
1722
this.getAutocompleteValues = this.getAutocompleteValues.bind();
1823
this.refSelector = React.createRef();
@@ -59,13 +64,24 @@ export class IntelligentQuestionSelector extends React.Component {
5964
return <div>
6065
{dagSelectorComponent}
6166
<div>
62-
<br/>
63-
<span>Label: <b>{this.state.activeLabel}</b></span>
64-
<br/>
65-
<span>Question origin: {this.state.activeQuestionOrigin}</span>
66-
<br/>
67-
<span>Question origin path: {this.state.activeQuestionOriginPath}</span>
68-
67+
<Button
68+
variant="link" size="sm" className="float-right"
69+
onClick={() => this.setState({detailCollapseOpen: !this.state.detailCollapseOpen})}
70+
aria-controls="example-collapse-text"
71+
aria-expanded={this.state.detailCollapseOpen}
72+
>
73+
Show detail <FontAwesomeIcon color="black" icon={faCaretDown}/>
74+
</Button>
75+
<Collapse in={this.state.detailCollapseOpen}>
76+
<div id="example-collapse-text">
77+
<br/>
78+
<span>Label: <b>{this.state.activeLabel}</b></span>
79+
<br/>
80+
<span>Question origin: {this.state.activeQuestionOrigin}</span>
81+
<br/>
82+
<span>Question origin path: {this.state.activeQuestionOriginPath}</span>
83+
</div>
84+
</Collapse>
6985
</div>
7086
</div>;
7187
}

src/components/ticket/CategorizedTicketsList.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import API from "../../api";
44
import {TicketLine} from "./TicketLine";
55
import Tabs from "react-bootstrap/Tabs";
66
import Tab from "react-bootstrap/Tab";
7+
import Button from "react-bootstrap/Button";
78

89
function createTicketLines(tickets) {
910
return (tickets && tickets.length !== 0) ? tickets.map((ticket, i) => {
@@ -23,6 +24,7 @@ export class CategorizedTicketsList extends React.Component {
2324
constructor(props) {
2425
super(props);
2526
this.state = {
27+
loading: true,
2628
formTickets: null,
2729
formVersionTickets: null,
2830
questionTickets: null
@@ -34,6 +36,7 @@ export class CategorizedTicketsList extends React.Component {
3436
}
3537

3638
requestTickets() {
39+
this.setState({loading: true})
3740
API.post("/rest/ticket/category", null, {
3841
params: {
3942
"projectName": this.props.projectName,
@@ -44,6 +47,7 @@ export class CategorizedTicketsList extends React.Component {
4447
}).then(ticketsInCategories => {
4548
console.log(ticketsInCategories)
4649
this.setState({
50+
loading: false,
4751
formTickets: ticketsInCategories.formTickets,
4852
formVersionTickets: ticketsInCategories.formVersionTickets,
4953
questionTickets: ticketsInCategories.questionTickets
@@ -52,12 +56,11 @@ export class CategorizedTicketsList extends React.Component {
5256
}
5357

5458
render() {
55-
5659
const formTickets = this.state.formTickets
5760
const formVersionTickets = this.state.formVersionTickets
5861
const questionTickets = this.state.questionTickets
5962

60-
if (!(formTickets && formVersionTickets && questionTickets)) {
63+
if (this.state.loading || !(formTickets && formVersionTickets && questionTickets)) {
6164
return <Alert variant={"light"} className={"h-10"}>
6265
Loading tickets...
6366
</Alert>
@@ -68,6 +71,7 @@ export class CategorizedTicketsList extends React.Component {
6871
const questionTicketsLines = createTicketLines(questionTickets);
6972

7073
return <div>
74+
<Button className={"float-right"} variant="link" onClick={() => this.requestTickets()}>refresh</Button>
7175
<Tabs defaultActiveKey="#" transition={false} id="ticket-tabs">
7276
<Tab eventKey="form" title={"Form related (" + formTickets.length + ")"}>
7377
<br/>

src/components/ticket/CreateTicketForm.js

Lines changed: 109 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,66 +5,115 @@ import Col from "react-bootstrap/Col";
55
import Card from "react-bootstrap/Card";
66
import Form from "react-bootstrap/Form";
77
import ToggleButton from "react-bootstrap/ToggleButton";
8+
import {IntelligentQuestionSelector} from "../search/IntelligentQuestionSelector";
9+
import Button from "react-bootstrap/Button";
10+
import API from "../../api";
11+
import Alert from "react-bootstrap/Alert";
812

913
export class CreateTicketForm extends React.Component {
1014

1115
constructor() {
1216
super();
1317
this.state = {
18+
name: "",
19+
description: "",
1420
relateToForm: false,
1521
relateToFormVersion: false,
1622
relateToQuestion: false
1723
}
24+
this.onChangeSetState = this.onChangeSetState.bind(this);
25+
this.onSubmitProject = this.onSubmitProject.bind(this);
26+
this.errorMessage = this.errorMessage.bind(this);
27+
this.questionSelectorRef = React.createRef();
1828
}
1929

20-
render() {
2130

31+
onChangeSetState(e) {
32+
const {name, value} = e.target;
33+
this.setState(prevState => ({...prevState, [name]: value}));
34+
}
35+
36+
onSubmitProject(e) {
37+
e.preventDefault();
38+
API.post("/rest/ticket", {
39+
projectName: this.props.projectName,
40+
recordContextUri: this.props.contextUri,
41+
name: this.state.name,
42+
description: this.state.description,
43+
relateToForm: this.state.relateToForm,
44+
relateToFormVersion: this.state.relateToFormVersion,
45+
relateToQuestion: this.state.relateToQuestion,
46+
questionOriginPath: this.questionSelectorRef?.current?.state.activeQuestionOriginPath,
47+
}).then((response) => {
48+
this.ticketForm.reset();
49+
this.setState({
50+
showError: false,
51+
showSuccess: true,
52+
ticketLink: response.data,
53+
relateToForm: false,
54+
relateToFormVersion: false,
55+
relateToQuestion: false
56+
});
57+
}).catch((error) => {
58+
console.log(error)
59+
this.setState({showError: true, showSuccess: false}); // todo: improve handling individual messages
60+
}
61+
);
62+
}
63+
64+
render() {
2265
return <Card>
2366
<ListGroup variant="flush">
2467
<ListGroup.Item>
2568
<div>
2669
<Row>
2770
<Col>
2871
<div>
29-
<Form.Group controlId="ticketName">
30-
<Form.Label>Name</Form.Label>
31-
<Form.Control type="text" placeholder="ticket name"/>
32-
</Form.Group>
33-
<Form.Group controlId="ticketName">
34-
<Form.Label>Description</Form.Label>
35-
<Form.Control as="textarea"
36-
placeholder="ticket description"
37-
name="ticketDescription" rows={3}
38-
onChange={this.onChangeSetState}/>
39-
</Form.Group>
40-
<ToggleButton variant="light" style={{marginBottom: "0"}} type="checkbox"
41-
checked={this.state.relateToForm}
42-
value="1"
43-
onChange={e => this.setState({relateToForm: e.currentTarget.checked})}>
44-
{' '} Relate to form
45-
</ToggleButton>
46-
{' '}
47-
<ToggleButton variant="light" style={{marginBottom: "0"}} type="checkbox"
48-
checked={this.state.relateToFormVersion}
49-
value="1"
50-
onChange={e => this.setState({relateToFormVersion: e.currentTarget.checked})}>
51-
{' '} Relate to form version
52-
</ToggleButton>
53-
{' '}
54-
<ToggleButton variant="light" style={{marginBottom: "0"}} type="checkbox"
55-
checked={this.state.relateToQuestion}
56-
value="1"
57-
onChange={e => this.setState({relateToQuestion: e.currentTarget.checked})}>
58-
{' '} Relate to question (origin path)
59-
</ToggleButton>
60-
<br/>
61-
{/*<Form.Group controlId="questionOrigin">*/}
62-
{/* <Form.Label>Question-Origin</Form.Label>*/}
63-
{/* <Form.Control as="text"*/}
64-
{/* placeholder={"question origin path"}*/}
65-
{/* name="questionOriginPath" // TODO: DAG select*/}
66-
{/* onChange={this.onChangeSetState}/>*/}
67-
{/*</Form.Group>*/}
72+
<Form onSubmit={this.onSubmitProject} ref={form => this.ticketForm = form}>
73+
<Form.Group controlId="nameControl">
74+
<Form.Label>Name</Form.Label>
75+
<Form.Control type="text"
76+
placeholder="ticket name"
77+
name="name"
78+
onChange={this.onChangeSetState}/>
79+
</Form.Group>
80+
<Form.Group controlId="descriptionControl">
81+
<Form.Label>Description</Form.Label>
82+
<Form.Control as="textarea"
83+
placeholder="ticket description"
84+
name="description" rows={3}
85+
onChange={this.onChangeSetState}/>
86+
</Form.Group>
87+
<ToggleButton variant="light" style={{marginBottom: "0"}} type="checkbox"
88+
checked={this.state.relateToForm}
89+
value="1"
90+
onChange={e => this.setState({relateToForm: e.currentTarget.checked})}>
91+
{' '} Relate to form
92+
</ToggleButton>
93+
{' '}
94+
<ToggleButton variant="light" style={{marginBottom: "0"}} type="checkbox"
95+
checked={this.state.relateToFormVersion}
96+
value="1"
97+
onChange={e => this.setState({relateToFormVersion: e.currentTarget.checked})}>
98+
{' '} Relate to form version
99+
</ToggleButton>
100+
{' '}
101+
<ToggleButton variant="light" style={{marginBottom: "0"}} type="checkbox"
102+
checked={this.state.relateToQuestion}
103+
value="1"
104+
onChange={e => this.setState({relateToQuestion: e.currentTarget.checked})}>
105+
{' '} Relate to question (origin path)
106+
</ToggleButton>
107+
{this.state.relateToQuestion ?
108+
<IntelligentQuestionSelector projectName={this.props.projectName}
109+
ref={this.questionSelectorRef}/> : <div/>}
110+
<br/>
111+
<Button variant="primary" type="submit">
112+
Submit
113+
</Button>
114+
{this.state.showError === true && this.errorMessage()}
115+
{this.state.showSuccess === true && this.successMessage()}
116+
</Form>
68117
</div>
69118
</Col>
70119
</Row>
@@ -74,4 +123,24 @@ export class CreateTicketForm extends React.Component {
74123
</Card>;
75124
}
76125

126+
errorMessage() {
127+
return <div>
128+
<br/>
129+
<Alert variant="danger" onClose={() => this.setState({showError: false})} dismissible>
130+
<Alert.Heading>Warning!</Alert.Heading>
131+
<p>Creating project was not successful.</p>
132+
</Alert>
133+
</div>
134+
}
135+
136+
successMessage() {
137+
return <div>
138+
<br/>
139+
<Alert variant="success" onClose={() => this.setState({showSuccess: false})} dismissible>
140+
<Alert.Heading>Success!</Alert.Heading>
141+
Creating ticket was successful. <a target={"_blank"} href={this.state.ticketLink}>ticket link</a>
142+
</Alert>
143+
</div>
144+
}
145+
77146
}

0 commit comments

Comments
 (0)