aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/util/ReportManager.tsx168
-rw-r--r--src/client/views/MainView.tsx2
-rw-r--r--src/client/views/topbar/TopBar.tsx6
3 files changed, 176 insertions, 0 deletions
diff --git a/src/client/util/ReportManager.tsx b/src/client/util/ReportManager.tsx
new file mode 100644
index 000000000..be58da29a
--- /dev/null
+++ b/src/client/util/ReportManager.tsx
@@ -0,0 +1,168 @@
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { action, computed, observable, runInAction } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { ColorState, SketchPicker } from 'react-color';
+import { Doc } from '../../fields/Doc';
+import { Id } from '../../fields/FieldSymbols';
+import { BoolCast, Cast, StrCast } from '../../fields/Types';
+import { addStyleSheet, addStyleSheetRule, Utils } from '../../Utils';
+import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
+import { DocServer } from '../DocServer';
+import { Networking } from '../Network';
+import { MainViewModal } from '../views/MainViewModal';
+import { FontIconBox } from '../views/nodes/button/FontIconBox';
+import { DragManager } from './DragManager';
+import { GroupManager } from './GroupManager';
+import './SettingsManager.scss';
+import { undoBatch } from './UndoManager';
+import { Octokit } from "@octokit/core";
+import { CheckBox } from '../views/search/CheckBox';
+const higflyout = require('@hig/flyout');
+export const { anchorPoints } = higflyout;
+export const Flyout = higflyout.default;
+
+@observer
+export class ReportManager extends React.Component<{}> {
+ public static Instance: ReportManager;
+ @observable private isOpen = false;
+
+ private octokit: Octokit;
+
+ @observable public issues: any[] = [];
+ @action setIssues = action((issues: any[]) => { this.issues = 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()));
+ });
+
+ constructor(props: {}) {
+ super(props);
+ ReportManager.Instance = this;
+
+ this.octokit = new Octokit({
+ auth: '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'
+ });
+ }
+
+ public close = action(() => (this.isOpen = false));
+ public open = action(() => {
+ if (this.issues.length === 0) {
+ // load in the issues if not already loaded
+ this.getAllIssues()
+ .then(issues => {
+ this.setIssues(issues);
+ this.updateIssueSearch();
+ })
+ .catch(err => console.log(err));
+ }
+ (this.isOpen = true)
+ });
+
+ private bugTitle = '';
+ private bugDescription = '';
+
+ // 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', '')}`;
+
+ public async getAllIssues() : Promise<any[]> {
+ const res = await this.octokit.request('GET /repos/{owner}/{repo}/issues', {
+ owner: 'brown-dash',
+ repo: 'Dash-Web',
+ });
+
+ // 200 status means success
+ if (res.status === 200) {
+ return res.data;
+ } else {
+ throw new Error('Error getting issues');
+ }
+ }
+
+ public async reportIssue() {
+ if (this.toGithub) {
+ 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,
+ labels: [
+ 'from-dash-app',
+ ]
+ });
+
+ // 201 status means success
+ if (req.status !== 201) {
+ alert('Error creating issue on github.');
+ // on error, don't close the modal
+ return;
+ }
+ }
+ else {
+ // if not going to github issues, not sure what to do yet...
+ }
+
+ // if we're down here, then we're good to go.
+ this.bugTitle = '';
+ this.bugDescription = '';
+ this.toGithub = false;
+ this.close();
+ }
+
+ private get reportInterface() {
+
+ return (
+ <div className="settings-interface">
+ <div className="settings-panel">
+ <input type="text" placeholder='issue name' onChange={(e => this.updateIssueSearch(e.target.value))}></input>
+ <h3>Previous Issues</h3>
+ {this.issues.length === 0 ? <div>loading</div> : this.shownIssues.map(issue => <div key={issue.number}>{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="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.bugTitle = 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.bugDescription = e.target.value}/>
+ <br /><br />
+ {/* <label>Send to github issues? </label>
+ <input type="checkbox" onChange={(e) => this.toGithub = e.target.checked} />
+ <br /> */}
+ <button onClick={() => this.reportIssue()}>Submit</button>
+ </div>
+
+
+ </div>
+ );
+ }
+
+ render() {
+ return (
+ <MainViewModal
+ contents={this.reportInterface}
+ isDisplayed={this.isOpen}
+ interactive={true}
+ closeOnExternalClick={this.close}
+ dialogueBoxStyle={{ width: '500px', height: '500px', background: Cast(Doc.SharingDoc().userColor, 'string', null) }}
+ />
+ );
+ }
+}
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index e96f65548..a8c8fedaa 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -20,6 +20,7 @@ import { DocumentManager } from '../util/DocumentManager';
import { GroupManager } from '../util/GroupManager';
import { HistoryUtil } from '../util/History';
import { Hypothesis } from '../util/HypothesisUtils';
+import { ReportManager } from '../util/ReportManager';
import { ScriptingGlobals } from '../util/ScriptingGlobals';
import { SelectionManager } from '../util/SelectionManager';
import { ColorScheme, SettingsManager } from '../util/SettingsManager';
@@ -974,6 +975,7 @@ export class MainView extends React.Component {
<DictationOverlay />
<SharingManager />
<SettingsManager />
+ <ReportManager />
<CaptureManager />
<GroupManager />
<GoogleAuthenticationManager />
diff --git a/src/client/views/topbar/TopBar.tsx b/src/client/views/topbar/TopBar.tsx
index 3fc0a237e..cbcfed06f 100644
--- a/src/client/views/topbar/TopBar.tsx
+++ b/src/client/views/topbar/TopBar.tsx
@@ -1,5 +1,6 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
+import { MdBugReport } from 'react-icons/md';
import { action } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -18,6 +19,7 @@ import { DashboardView } from '../DashboardView';
import { Borders, Colors } from '../global/globalEnums';
import { MainView } from '../MainView';
import './TopBar.scss';
+import { ReportManager } from '../../util/ReportManager';
/**
* ABOUT: This is the topbar in Dash, which included the current Dashboard as well as access to information on the user
@@ -31,6 +33,7 @@ export class TopBar extends React.Component {
DashboardView.closeActiveDashboard(); // bcz: if we do this, we need some other way to keep track, for user convenience, of the last dashboard in use
});
};
+
render() {
const activeDashboard = Doc.ActiveDashboard;
return (
@@ -92,6 +95,9 @@ export class TopBar extends React.Component {
{GetEffectiveAcl(Doc.GetProto(Doc.ActiveDashboard)) === AclAdmin ? 'Share' : 'view original'}
</div>
) : null}
+ <div className="topbar-button-icon" onClick={() => ReportManager.Instance.open()}>
+ <MdBugReport />
+ </div>
<div className="topbar-button-icon" onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/', '_blank')}>
<FontAwesomeIcon icon="question-circle" />
</div>