aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/ReportManager.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util/ReportManager.tsx')
-rw-r--r--src/client/util/ReportManager.tsx235
1 files changed, 156 insertions, 79 deletions
diff --git a/src/client/util/ReportManager.tsx b/src/client/util/ReportManager.tsx
index 4c1020455..a08ef9979 100644
--- a/src/client/util/ReportManager.tsx
+++ b/src/client/util/ReportManager.tsx
@@ -17,12 +17,14 @@ import { GroupManager } from './GroupManager';
import './SettingsManager.scss';
import './ReportManager.scss';
import { undoBatch } from './UndoManager';
-import { Octokit } from "@octokit/core";
+import { Octokit } from '@octokit/core';
import { CheckBox } from '../views/search/CheckBox';
import ReactLoading from 'react-loading';
import ReactMarkdown from 'react-markdown';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
+import { Button, MenuItem, Select, SelectChangeEvent, TextField } from '@mui/material';
+import { FormControl, InputLabel } from '@material-ui/core';
const higflyout = require('@hig/flyout');
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
@@ -35,21 +37,25 @@ export class ReportManager extends React.Component<{}> {
private octokit: Octokit;
@observable public issues: any[] = [];
- @action setIssues = action((issues: any[]) => { this.issues = issues; });
-
+ @action setIssues = action((issues: any[]) => {
+ this.issues = issues;
+ });
+
// undefined is the default - null is if the user is making an issue
@observable public selectedIssue: any = undefined;
- @action setSelectedIssue = action((issue: any) => { this.selectedIssue = issue; });
+ @action setSelectedIssue = action((issue: any) => {
+ this.selectedIssue = issue;
+ });
// only get the open issues
@observable public shownIssues = this.issues.filter(issue => issue.state === 'open');
-
+
public updateIssueSearch = action((query: string = '') => {
if (query === '') {
this.shownIssues = this.issues.filter(issue => issue.state === 'open');
return;
}
- this.shownIssues = this.issues.filter(issue => issue.title.toLowerCase().includes(query.toLowerCase()));
+ this.shownIssues = this.issues.filter(issue => issue.title.toLowerCase().includes(query.toLowerCase()));
});
constructor(props: {}) {
@@ -57,7 +63,7 @@ export class ReportManager extends React.Component<{}> {
ReportManager.Instance = this;
this.octokit = new Octokit({
- auth: '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'
+ auth: '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',
});
}
@@ -72,25 +78,33 @@ export class ReportManager extends React.Component<{}> {
})
.catch(err => console.log(err));
}
- (this.isOpen = true)
+ this.isOpen = true;
});
@observable private bugTitle = '';
- @action setBugTitle = action((title: string) => { this.bugTitle = title; });
+ @action setBugTitle = action((title: string) => {
+ this.bugTitle = title;
+ });
@observable private bugDescription = '';
- @action setBugDescription = action((description: string) => { this.bugDescription = description; });
+ @action setBugDescription = action((description: string) => {
+ this.bugDescription = description;
+ });
@observable private bugType = '';
- @action setBugType = action((type: string) => { this.bugType = type; });
+ @action setBugType = action((type: string) => {
+ this.bugType = type;
+ });
@observable private bugPriority = '';
- @action setBugPriority = action((priortiy: string) => { this.bugPriority = priortiy; });
+ @action setBugPriority = action((priortiy: string) => {
+ this.bugPriority = priortiy;
+ });
// private toGithub = false;
// will always be set to true - no alterntive option yet
private toGithub = true;
- private formatTitle = (title: string, userEmail: string) => `${title} - ${userEmail.replace('@brown.edu', '')}`;
+ private formatTitle = (title: string, userEmail: string) => `${title} - ${userEmail.replace('@brown.edu', '')}`;
- public async getAllIssues() : Promise<any[]> {
+ public async getAllIssues(): Promise<any[]> {
const res = await this.octokit.request('GET /repos/{owner}/{repo}/issues', {
owner: 'brown-dash',
repo: 'Dash-Web',
@@ -105,40 +119,34 @@ export class ReportManager extends React.Component<{}> {
}
// turns an upload link into a servable link
- // ex:
+ // ex:
// C: /Users/dash/Documents/GitHub/Dash-Web/src/server/public/files/images/upload_8008dbc4b6424fbff14da7345bb32eb2.png
// -> http://localhost:1050/files/images/upload_8008dbc4b6424fbff14da7345bb32eb2_l.png
private fileLinktoServerLink = (fileLink: string) => {
const serverUrl = 'https://browndash.com/';
- const regex = 'public'
+ const regex = 'public';
const publicIndex = fileLink.indexOf(regex) + regex.length;
const finalUrl = `${serverUrl}${fileLink.substring(publicIndex + 1).replace('.', '_l.')}`;
return finalUrl;
- }
+ };
public async reportIssue() {
- if (this.bugTitle === '' || this.bugDescription === ''
- || this.bugType === '' || this.bugPriority === '') {
+ if (this.bugTitle === '' || this.bugDescription === '' || this.bugType === '' || this.bugPriority === '') {
alert('Please fill out all required fields to report an issue.');
return;
}
if (this.toGithub) {
+ const formattedLinks = (this.fileLinks ?? []).map(this.fileLinktoServerLink);
- const formattedLinks = (this.fileLinks ?? []).map(this.fileLinktoServerLink)
-
const req = await this.octokit.request('POST /repos/{owner}/{repo}/issues', {
owner: 'brown-dash',
repo: 'Dash-Web',
title: this.formatTitle(this.bugTitle, Doc.CurrentUserEmail),
body: `${this.bugDescription} \n\nfiles:\n${formattedLinks.join('\n')}`,
- labels: [
- 'from-dash-app',
- this.bugType,
- this.bugPriority
- ]
+ labels: ['from-dash-app', this.bugType, this.bugPriority],
});
// 201 status means success
@@ -147,8 +155,7 @@ export class ReportManager extends React.Component<{}> {
// on error, don't close the modal
return;
}
- }
- else {
+ } else {
// if not going to github issues, not sure what to do yet...
}
@@ -163,9 +170,13 @@ export class ReportManager extends React.Component<{}> {
}
@observable public fileLinks: any = [];
- @action setFileLinks = action((links: any) => { this.fileLinks = links; });
+ @action setFileLinks = action((links: any) => {
+ this.fileLinks = links;
+ });
- private getServerPath = (link: any) => { return link.result.accessPaths.agnostic.server }
+ private getServerPath = (link: any) => {
+ return link.result.accessPaths.agnostic.server;
+ };
private uploadFiles = (input: any) => {
// keep null while uploading
@@ -173,112 +184,177 @@ export class ReportManager extends React.Component<{}> {
// upload the files to the server
if (input.files && input.files.length !== 0) {
const fileArray: File[] = Array.from(input.files);
- (Networking.UploadFilesToServer(fileArray.map(file =>({file})))).then(links => {
+ Networking.UploadFilesToServer(fileArray.map(file => ({ file }))).then(links => {
console.log('finshed uploading', links.map(this.getServerPath));
this.setFileLinks((links ?? []).map(this.getServerPath));
- })
+ });
}
-
- }
+ };
+ @observable private age = '';
- private renderIssue = (issue: any) => {
+ @action private setAge = (e: SelectChangeEvent) => {
+ this.age = e.target.value as string;
+ };
+
+ private reportIssueComponent = () => {
+ return (
+ <div className="report-issue">
+ <h2>Report an issue</h2>
+ <TextField
+ fullWidth
+ type="text"
+ label="Please leave a title for the bug"
+ placeholder="Title..."
+ required
+ sx={{
+ '& .MuiInputBase-input': {
+ fontSize: 'inherit',
+ },
+ }}
+ onChange={e => this.setBugTitle(e.target.value)}
+ />
+ <label>Please leave a description for the bug and how it can be recreated.</label>
+ <textarea value={this.bugDescription} placeholder="description" onChange={e => this.setBugDescription(e.target.value as string)} required />
+ <FormControl fullWidth>
+ <InputLabel id="demo-simple-select-label">Age</InputLabel>
+ <Select labelId="demo-simple-select-label" id="demo-simple-select" value={this.age} label="Age" onChange={this.setAge}>
+ <MenuItem value={10}>Ten</MenuItem>
+ <MenuItem value={20}>Twenty</MenuItem>
+ <MenuItem value={30}>Thirty</MenuItem>
+ </Select>
+ </FormControl>
+ <FormControl fullWidth>
+ <InputLabel>Bug Type</InputLabel>
+ <Select value={this.bugType} label="Bug Type" onChange={e => this.setBugType(e.target.value)}>
+ <MenuItem value="bug">Bug</MenuItem>
+ <MenuItem value="Poor design or cosmetic">Poor design or cosmetic</MenuItem>
+ <MenuItem value="Poor documentation">Poor documentation</MenuItem>
+ </Select>
+ </FormControl>
+ <FormControl>
+ <InputLabel>Bug Priority</InputLabel>
+ <Select fullWidth value={this.bugPriority} label="Bug Priority" onChange={e => this.setBugPriority(e.target.value as string)}>
+ <MenuItem value="bug">Bug</MenuItem>
+ <MenuItem value="Poor design or cosmetic">Poor design or cosmetic</MenuItem>
+ <MenuItem value="Poor documentation">Poor documentation</MenuItem>
+ </Select>
+ </FormControl>
+ <Button variant="contained">Submit</Button>
+ </div>
+ );
+ };
+ private renderIssue = (issue: any) => {
const isReportingIssue = issue === null;
- return isReportingIssue ?
+ return isReportingIssue ? (
// report issue
- (<div className="settings-content">
- <h3 style={{ 'textDecoration': 'underline'}}>Report an Issue</h3>
- <label>Please leave a title for the bug.</label><br />
- <input type="text" placeholder='title' onChange={(e) => this.setBugTitle(e.target.value)} required/>
+ <div className="settings-content">
+ <h3 style={{ textDecoration: 'underline' }}>Report an Issue</h3>
+ <label>Please leave a title for the bug.</label>
+ <br />
+ <input value={this.bugTitle} type="text" placeholder="title" onChange={e => this.setBugTitle(e.target.value)} required />
+ {/* <TextField fullWidth type="text" placeholder="Title..." required onChange={e => this.setBugTitle(e.target.value)} /> */}
<br />
<label>Please leave a description for the bug and how it can be recreated.</label>
- <textarea placeholder='description' onChange={(e) => this.setBugDescription(e.target.value)} required/>
+ <textarea value={this.bugDescription} placeholder="description" onChange={e => this.setBugDescription(e.target.value)} required />
<br />
{/* {<label>Send to github issues? </label>
<input type="checkbox" onChange={(e) => this.toGithub = e.target.checked} />
<br /> } */}
<label>Please label the issue</label>
- <div className='flex-select'>
- <select name="bugType" onChange={e => this.bugType = e.target.value}>
- <option value="" disabled selected>Type</option>
- <option value="bug">Bug</option>
- <option value="cosmetic">Poor Design or Cosmetic</option>
- <option value="documentation">Poor Documentation</option>
+ <div className="flex-select">
+ <select name="bugType" onChange={e => (this.bugType = e.target.value)}>
+ <option value="" disabled selected>
+ Type
+ </option>
+ <option value="priority-low">Bug</option>
+ <option value="priority-medium">Poor Design or Cosmetic</option>
+ <option value="priority-high">Poor Documentation</option>
</select>
- <select name="bigPriority" onChange={e => this.bugPriority = e.target.value}>
- <option value="" disabled selected>Priority</option>
+ <select name="bigPriority" onChange={e => (this.bugPriority = e.target.value)}>
+ <option value="" disabled selected>
+ Priority
+ </option>
<option value="priority-low">Low</option>
<option value="priority-medium">Medium</option>
<option value="priority-high">High</option>
</select>
</div>
-
<div>
<label>Upload media that shows the bug (optional)</label>
- <input type="file" name="file" multiple accept='audio/*, video/*, image/*' onChange={e => this.uploadFiles(e.target)}/>
+ <input type="file" name="file" multiple accept="audio/*, video/*, image/*" onChange={e => this.uploadFiles(e.target)} />
</div>
<br />
- <button onClick={() => this.reportIssue()} disabled={this.fileLinks === null} style={{ backgroundColor: this.fileLinks === null ? 'grey' : '' }}>{this.fileLinks === null ? 'Uploading...' : 'Submit'}</button>
- </div>)
- :
+ <button onClick={() => this.reportIssue()} disabled={this.fileLinks === null} style={{ backgroundColor: this.fileLinks === null ? 'grey' : '' }}>
+ {this.fileLinks === null ? 'Uploading...' : 'Submit'}
+ </button>
+ </div>
+ ) : (
// view issue
- (
- <div className='issue-container'>
- <h5 style={{'textAlign': "left"}}><a href={issue.html_url} target="_blank">Issue #{issue.number}</a></h5>
- <div className='issue-title'>
- {issue.title}
- </div>
- <ReactMarkdown children={issue.body} className='issue-body' linkTarget={"_blank"} remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]} />
+ <div className="issue-container">
+ <h5 style={{ textAlign: 'left' }}>
+ <a href={issue.html_url} target="_blank">
+ Issue #{issue.number}
+ </a>
+ </h5>
+ <div className="issue-title">{issue.title}</div>
+ <ReactMarkdown children={issue.body} className="issue-body" linkTarget={'_blank'} remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]} />
</div>
);
- }
+ };
private showReportIssueScreen = () => {
this.setSelectedIssue(null);
- }
+ };
private closeReportIssueScreen = () => {
this.setSelectedIssue(undefined);
- }
+ };
private get reportInterface() {
-
const isReportingIssue = this.selectedIssue === null;
return (
<div className="settings-interface">
- <div className='issue-list-wrapper'>
+ <div className="issue-list-wrapper">
<h3>Current Issues</h3>
- <input type="text" placeholder='search issues' onChange={(e => this.updateIssueSearch(e.target.value))}></input><br />
- {this.issues.length === 0 ? <ReactLoading className='loading-center'/> : this.shownIssues.map(issue => <div className='issue-list' key={issue.number} onClick={() => this.setSelectedIssue(issue)}>{issue.title}</div>)}
+ <input type="text" placeholder="search issues" onChange={e => this.updateIssueSearch(e.target.value)}></input>
+ <br />
+ {this.issues.length === 0 ? (
+ <ReactLoading className="loading-center" />
+ ) : (
+ this.shownIssues.map(issue => (
+ <div className="issue-list" key={issue.number} onClick={() => this.setSelectedIssue(issue)}>
+ {issue.title}
+ </div>
+ ))
+ )}
{/* <div className="settings-user">
<button onClick={() => this.getAllIssues().then(issues => this.issues = issues)}>Poll Issues</button>
</div> */}
</div>
-
+
<div className="close-button" onClick={this.close}>
<FontAwesomeIcon icon={'times'} color="black" size={'lg'} />
</div>
- <div className="issue-content" style={{'paddingTop' : this.selectedIssue === undefined ? '50px' : 'inherit'}}>
- {this.selectedIssue === undefined ? "no issue selected" : this.renderIssue(this.selectedIssue)}
+ <div className="issue-content" style={{ paddingTop: this.selectedIssue === undefined ? '50px' : 'inherit' }}>
+ {this.selectedIssue === undefined ? 'no issue selected' : this.renderIssue(this.selectedIssue)}
</div>
- <div className='report-issue-fab'>
- <span className='report-disclaimer' hidden={!isReportingIssue}>Note: issue reporting is not anonymous.</span>
- <button
- onClick={() => isReportingIssue ? this.closeReportIssueScreen() : this.showReportIssueScreen()}
- >{isReportingIssue ? 'Cancel' : 'Report New Issue'}</button>
+ <div className="report-issue-fab">
+ <span className="report-disclaimer" hidden={!isReportingIssue}>
+ Note: issue reporting is not anonymous.
+ </span>
+ <button onClick={() => (isReportingIssue ? this.closeReportIssueScreen() : this.showReportIssueScreen())}>{isReportingIssue ? 'Cancel' : 'Report New Issue'}</button>
</div>
-
-
</div>
);
}
@@ -286,7 +362,8 @@ export class ReportManager extends React.Component<{}> {
render() {
return (
<MainViewModal
- contents={this.reportInterface}
+ // contents={this.reportInterface}
+ contents={this.reportIssueComponent()}
isDisplayed={this.isOpen}
interactive={true}
closeOnExternalClick={this.close}