aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/theme.ts47
-rw-r--r--src/client/util/ReportManager.scss383
-rw-r--r--src/client/util/ReportManager.tsx478
-rw-r--r--src/client/util/reportManagerSchema.ts877
4 files changed, 1530 insertions, 255 deletions
diff --git a/src/client/theme.ts b/src/client/theme.ts
index 57be370cc..f0a11fe6e 100644
--- a/src/client/theme.ts
+++ b/src/client/theme.ts
@@ -4,39 +4,20 @@ import { createTheme } from '@mui/material/styles';
export const theme = createTheme({
palette: {
primary: {
- main: 'rgb(0, 149, 246)',
+ main: '#4476f7',
+ },
+ },
+ components: {
+ MuiButton: {
+ styleOverrides: {
+ root: {
+ fontSize: '14px',
+ boxShadow: 'none',
+ '&:hover': {
+ boxShadow: 'none',
+ },
+ },
+ },
},
},
- // components: {
- // MuiButton: {
- // styleOverrides: {
- // root: {
- // fontSize: '14px',
- // boxShadow: 'none',
- // '&:hover': {
- // boxShadow: 'none',
- // scale: 1,
- // },
- // },
- // },
- // },
- // MuiTextField: {
- // styleOverrides: {
- // root: {
- // '& .MuiInputBase-input': {
- // fontSize: '16px',
- // },
- // '& .MuiInputLabel-root': {
- // fontSize: '16px',
- // },
- // '& .MuiInputLabel-shrink': {
- // fontSize: '16px',
- // },
- // '& .MuiFormHelperText-root': {
- // fontSize: '16px',
- // },
- // },
- // },
- // },
- // },
});
diff --git a/src/client/util/ReportManager.scss b/src/client/util/ReportManager.scss
index 969e0de74..4ff86fd9c 100644
--- a/src/client/util/ReportManager.scss
+++ b/src/client/util/ReportManager.scss
@@ -1,102 +1,349 @@
@import '../views/global/globalCssVariables';
+// header
+
+.report-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ h2 {
+ margin: 0;
+ padding: 0;
+ font-size: 24px;
+ }
+}
+
+.report-header-vertical {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 4px;
+
+ h2 {
+ margin: 0;
+ padding: 0;
+ padding-bottom: 8px;
+ font-size: 24px;
+ }
+}
+
+// Report
+
.report-issue {
+ width: 45vw;
padding: 16px;
+ padding-top: 32px;
display: flex;
flex-direction: column;
- gap: 1rem;
+ gap: 16px;
background-color: #ffffff;
text-align: left;
+ position: relative;
- h2 {
- font-size: 24px;
+ .report-label {
+ font-size: 14px;
+ font-weight: 400;
+ color: #747474;
+ }
+
+ .report-section {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .report-textarea {
+ width: 100%;
+ height: 80px;
+ padding: 8px;
+ resize: none;
+ }
+
+ .report-selects {
+ display: flex;
+ gap: 16px;
+
+ .report-select {
+ flex: 1;
+ padding: 8px;
+ border-color: #c6c6c6;
+
+ .report-opt {
+ padding: 8px;
+ }
+ }
}
}
-// ---------------------------------------
-.issue-list-wrapper {
- position: relative;
- min-width: 250px;
- background-color: $light-blue;
- overflow-y: scroll;
+.report-input {
+ border: none;
+ outline: none;
+ border-bottom: 1px solid #c6c6c6;
+ padding: 8px;
+ padding-left: 0;
+ transition: all 0.2s ease;
+
+ &:hover {
+ border-bottom-color: #7f7f7f;
+ }
+ &:focus {
+ border-bottom-color: #4476f7;
+ }
}
-.issue-list {
+// View issues
+
+.view-issues {
+ width: 65vw;
+ min-width: 600px;
display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 5px;
- margin: 5px;
- border-radius: 5px;
- border: 1px solid grey;
- background-color: lightgoldenrodyellow;
+ gap: 16px;
+ height: 100%;
+
+ .left {
+ height: 100%;
+ flex: 1;
+ padding: 16px;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ background-color: #ffffff;
+ text-align: left;
+ position: relative;
+
+ .issues {
+ position: relative;
+ flex-grow: 1;
+ overflow-y: auto;
+ overflow-x: hidden;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ }
+ }
+
+ .right {
+ padding: 16px;
+ height: 100%;
+ overflow-y: auto;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ flex: 1;
+ }
}
-// issue should pop up when the user hover over the issue
-.issue-list:hover {
- box-shadow: 2px;
+// Issue
+
+.issue {
cursor: pointer;
- border: 3px solid #252b33;
+ padding: 16px;
+ background-color: #ffffff;
+ border: 1px solid #d3d3d3;
+ transition: all 0.1s ease;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ border-radius: 8px;
+ transition: all 0.2s ease;
+ // box-shadow: 0 0 8px #d0d0d07c;
+
+ .issue-label {
+ cursor: pointer;
+ font-size: 14px;
+ font-weight: 400;
+ letter-spacing: 1px;
+ color: #7f7f7f;
+ }
+
+ .issue-title {
+ font-size: 16px;
+ font-weight: 500;
+ padding: 0;
+ margin: 0;
+ color: #4476f7;
+ }
+
+ &:hover {
+ background-color: #4476f7;
+ border-color: #4476f7;
+ color: #ffffff;
+
+ .issue-label {
+ color: #ffffff;
+ }
+
+ .issue-title {
+ color: #ffffff;
+ }
+ }
}
-.issue-content {
- background-color: white;
- padding: 10px;
- flex: 1 1 auto;
- overflow-y: scroll;
+// Dropzone
+
+.dropzone {
+ padding: 2rem;
+ border-radius: 0.5rem;
+ border: 2px dashed #ebebeb;
+
+ .dropzone-instructions {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 16px;
+ color: #7f7f7f;
+
+ p {
+ text-align: center;
+ }
+ }
}
-.issue-title {
- font-size: 20px;
- font-weight: 600;
- color: black;
+.files {
+ font-size: 14px;
+ color: #7f7f7f;
+
+ .file-list {
+ width: 100%;
+ list-style-type: none;
+ display: flex;
+ overflow-x: auto;
+ gap: 16px;
+ margin: 0;
+ padding: 0;
+
+ .file-name {
+ padding: 8px 12px;
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ white-space: nowrap;
+ }
+ }
}
-.issue-body {
- padding: 0 10px;
+// Detailed issue view
+
+.issue-view {
+ height: 100%;
width: 100%;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+ background-color: #ffffff;
text-align: left;
-}
+ position: relative;
+ overflow: auto;
-.issue-body > * {
- margin-top: 5px;
-}
+ .issue-label {
+ color: #7f7f7f;
-.issue-body img,
-.issue-body video {
- display: block;
- max-width: 100%;
-}
+ .issue-link {
+ cursor: pointer;
+ color: #4476f7;
+ }
+ }
-.report-issue-fab {
- position: fixed;
- bottom: 20px;
- right: 20px;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
-}
+ .issue-title {
+ font-size: 24px;
+ margin: 0;
+ padding: 0;
+ }
-.loading-center {
- margin: auto 0;
+ .issue-content {
+ font-size: 14px;
+ color: #7f7f7f;
+ }
}
-.settings-content label {
- margin-top: 10px;
-}
+// Old code
-.report-disclaimer {
- font-size: 8px;
- color: grey;
- padding-right: 50px;
- font-style: italic;
- text-align: left;
-}
+// <---------------------------------------------------------------------------->
-.flex-select {
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 10px;
-}
+// .issue-list-wrapper {
+// position: relative;
+// min-width: 250px;
+// background-color: $light-blue;
+// overflow-y: scroll;
+// }
+
+// .issue-list {
+// display: flex;
+// align-items: center;
+// justify-content: space-between;
+// padding: 5px;
+// margin: 5px;
+// border-radius: 5px;
+// border: 1px solid grey;
+// background-color: lightgoldenrodyellow;
+// }
+
+// // issue should pop up when the user hover over the issue
+// .issue-list:hover {
+// box-shadow: 2px;
+// cursor: pointer;
+// border: 3px solid #252b33;
+// }
+
+// .issue-content {
+// background-color: white;
+// padding: 10px;
+// flex: 1 1 auto;
+// overflow-y: scroll;
+// }
+
+// .issue-title {
+// font-size: 20px;
+// font-weight: 600;
+// color: black;
+// }
+
+// .issue-body {
+// padding: 0 10px;
+// width: 100%;
+// text-align: left;
+// }
+
+// .issue-body > * {
+// margin-top: 5px;
+// }
+
+// .issue-body img,
+// .issue-body video {
+// display: block;
+// max-width: 100%;
+// }
+
+// .report-issue-fab {
+// position: fixed;
+// bottom: 20px;
+// right: 20px;
+// display: flex;
+// align-items: center;
+// justify-content: center;
+// cursor: pointer;
+// }
+
+// .loading-center {
+// margin: auto 0;
+// }
+
+// .settings-content label {
+// margin-top: 10px;
+// }
+
+// .report-disclaimer {
+// font-size: 8px;
+// color: grey;
+// padding-right: 50px;
+// font-style: italic;
+// text-align: left;
+// }
+
+// .flex-select {
+// display: flex;
+// align-items: center;
+// justify-content: center;
+// gap: 10px;
+// }
diff --git a/src/client/util/ReportManager.tsx b/src/client/util/ReportManager.tsx
index a08ef9979..3eebb8f15 100644
--- a/src/client/util/ReportManager.tsx
+++ b/src/client/util/ReportManager.tsx
@@ -1,62 +1,82 @@
-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 { CheckBox } from '../views/search/CheckBox';
+import { undoBatch } from './UndoManager';
+import * as React from 'react';
import './SettingsManager.scss';
import './ReportManager.scss';
-import { undoBatch } from './UndoManager';
+import { action, computed, observable, runInAction } from 'mobx';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { BsX } from 'react-icons/bs';
+import { BiX } from 'react-icons/bi';
+import { AiOutlineUpload } from 'react-icons/ai';
+import { HiOutlineArrowLeft } from 'react-icons/hi';
+import { Issue } from './reportManagerSchema';
+import { observer } from 'mobx-react';
+import { Doc } from '../../fields/Doc';
+import { Networking } from '../Network';
+import { MainViewModal } from '../views/MainViewModal';
import { Octokit } from '@octokit/core';
-import { CheckBox } from '../views/search/CheckBox';
+import { Button, IconButton } from '@mui/material';
+import { Oval } from 'react-loader-spinner';
+import Dropzone from 'react-dropzone';
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';
+import { theme } from '../theme';
const higflyout = require('@hig/flyout');
export const { anchorPoints } = higflyout;
export const Flyout = higflyout.default;
+enum ViewState {
+ VIEW,
+ CREATE,
+}
+
@observer
export class ReportManager extends React.Component<{}> {
public static Instance: ReportManager;
@observable private isOpen = false;
+ @observable private query = '';
+ @action private setQuery = (q: string) => {
+ this.query = q;
+ };
+
private octokit: Octokit;
- @observable public issues: any[] = [];
- @action setIssues = action((issues: any[]) => {
- this.issues = issues;
+ @observable viewState: ViewState = ViewState.VIEW;
+ @action private setViewState = (state: ViewState) => {
+ this.viewState = state;
+ };
+ @observable submitting: boolean = false;
+ @action private setSubmitting = (submitting: boolean) => {
+ this.submitting = submitting;
+ };
+
+ @observable
+ public shownIssues: Issue[] = [];
+ @action setShownIssues = action((issues: Issue[]) => {
+ this.shownIssues = issues;
});
- // undefined is the default - null is if the user is making an issue
- @observable public selectedIssue: any = undefined;
- @action setSelectedIssue = action((issue: any) => {
+ @observable selectedIssue: Issue | undefined = undefined;
+ @action setSelectedIssue = action((issue: Issue | undefined) => {
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()));
- });
+ @observable private mediaFiles: File[] = [];
+ @action private setMediaFiles = (files: File[]) => {
+ this.mediaFiles = files;
+ };
constructor(props: {}) {
super(props);
@@ -68,17 +88,18 @@ export class ReportManager extends React.Component<{}> {
}
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));
- }
+ public open = action(async () => {
this.isOpen = true;
+ if (this.shownIssues.length === 0) {
+ try {
+ // load in the issues if not already loaded
+ const issues = (await this.getAllIssues()) as Issue[];
+ this.setShownIssues(issues.filter(issue => issue.state === 'open'));
+ // this.updateIssueSearch();
+ } catch (err) {
+ console.log(err);
+ }
+ }
});
@observable private bugTitle = '';
@@ -98,6 +119,14 @@ export class ReportManager extends React.Component<{}> {
this.bugPriority = priortiy;
});
+ private showReportIssueScreen = () => {
+ this.setSelectedIssue(undefined);
+ };
+
+ private closeReportIssueScreen = () => {
+ this.setSelectedIssue(undefined);
+ };
+
// private toGithub = false;
// will always be set to true - no alterntive option yet
private toGithub = true;
@@ -133,30 +162,31 @@ export class ReportManager extends React.Component<{}> {
};
public async reportIssue() {
+ console.log(this.bugTitle);
+ console.log('reporting issue');
if (this.bugTitle === '' || this.bugDescription === '' || this.bugType === '' || this.bugPriority === '') {
alert('Please fill out all required fields to report an issue.');
return;
}
+ this.setSubmitting(true);
- if (this.toGithub) {
- const formattedLinks = (this.fileLinks ?? []).map(this.fileLinktoServerLink);
+ console.log('to github');
+ const links = await this.uploadFilesToServer();
+ const formattedLinks = (links ?? []).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],
- });
+ 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],
+ });
- // 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...
+ // 201 status means success
+ if (req.status !== 201) {
+ alert('Error creating issue on github.');
+ // on error, don't close the modal
+ return;
}
// if we're down here, then we're good to go. reset the fields.
@@ -166,7 +196,9 @@ export class ReportManager extends React.Component<{}> {
this.setFileLinks([]);
this.setBugType('');
this.setBugPriority('');
- this.close();
+ this.setSubmitting(false);
+ alert('Successfully submitted issue.');
+ // this.close();
}
@observable public fileLinks: any = [];
@@ -191,61 +223,216 @@ export class ReportManager extends React.Component<{}> {
}
};
- @observable private age = '';
+ private uploadFilesToServer = async () => {
+ const links = await Networking.UploadFilesToServer(this.mediaFiles.map(file => ({ file })));
+ console.log('finshed uploading', links.map(this.getServerPath));
+ return (links ?? []).map(this.getServerPath);
+ // this.setFileLinks((links ?? []).map(this.getServerPath));
+ };
- @action private setAge = (e: SelectChangeEvent) => {
- this.age = e.target.value as string;
+ private onDrop = (files: File[]) => {
+ this.setMediaFiles(files);
+ };
+
+ private reportComponent = () => {
+ if (this.viewState === ViewState.VIEW) {
+ return this.viewIssuesComponent();
+ } else {
+ return this.reportIssueComponent();
+ }
+ };
+
+ private viewIssuesComponent = () => {
+ return (
+ <div className="view-issues">
+ <div className="left">
+ <div className="report-header">
+ <h2>Open Issues</h2>
+ <Button
+ variant="contained"
+ onClick={() => {
+ this.setViewState(ViewState.CREATE);
+ }}>
+ report issue
+ </Button>
+ </div>
+ <input
+ className="report-input"
+ type="text"
+ placeholder="Filter..."
+ onChange={e => {
+ this.setQuery(e.target.value);
+ }}
+ required
+ />
+ <div className="issues">
+ {this.shownIssues
+ .filter(issue => issue.title.toLowerCase().includes(this.query))
+ .map(issue => (
+ <IssueCard
+ key={issue.number}
+ issue={issue}
+ onSelect={() => {
+ this.setSelectedIssue(issue);
+ }}
+ />
+ ))}
+ </div>
+ </div>
+ <div className="right">{this.selectedIssue ? <IssueView issue={this.selectedIssue} /> : <div>No issue selected</div>}</div>
+ <IconButton sx={{ position: 'absolute', top: '4px', right: '4px' }} onClick={this.close}>
+ <BiX size="16px" />
+ </IconButton>
+ </div>
+ );
};
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 className="report-header-vertical">
+ <Button
+ variant="text"
+ onClick={() => {
+ this.setViewState(ViewState.VIEW);
+ }}
+ sx={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
+ <HiOutlineArrowLeft color={theme.palette.primary.main} />
+ back to view
+ </Button>
+ <h2>Report an Issue</h2>
+ </div>
+ <div className="report-section">
+ <label className="report-label">Please provide a title for the bug</label>
+ <input className="report-input" value={this.bugTitle} type="text" placeholder="Title..." onChange={e => this.setBugTitle(e.target.value)} required />
+ </div>
+ <div className="report-section">
+ <label className="report-label">Please leave a description for the bug and how it can be recreated</label>
+ <textarea className="report-textarea" value={this.bugDescription} placeholder="Description..." onChange={e => this.setBugDescription(e.target.value)} required />
+ </div>
+ <div className="report-selects">
+ <select className="report-select" name="bugType" onChange={e => (this.bugType = e.target.value)}>
+ <option value="" disabled selected>
+ Type
+ </option>
+ <option className="report-opt" value="priority-low">
+ Bug
+ </option>
+ <option className="report-opt" value="priority-medium">
+ Poor Design or Cosmetic
+ </option>
+ <option className="report-opt" value="priority-high">
+ Poor Documentation
+ </option>
+ </select>
+ <select className="report-select" name="bigPriority" onChange={e => (this.bugPriority = e.target.value)}>
+ <option className="report-opt" 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>
+ <Dropzone
+ onDrop={this.onDrop}
+ accept={{
+ 'image/png': ['.png'],
+ 'image/jpg': ['.jpg'],
+ 'image/jpeg': ['.jpeg'],
+ 'video/mp4': ['.mp4'],
+ 'video/mpeg': ['.mpeg'],
+ 'video/webm': ['.webm'],
+ 'audio/mpeg': ['.mp3'],
+ 'audio/wav': ['.wav'],
+ 'audio/ogg': ['.ogg'],
+ }}>
+ {({ getRootProps, getInputProps }) => (
+ <div {...getRootProps({ className: 'dropzone' })}>
+ <input {...getInputProps()} />
+ <div className="dropzone-instructions">
+ <AiOutlineUpload size={25} />
+ <p>Drop or select media that shows the bug (optional)</p>
+ </div>
+ </div>
+ )}
+ </Dropzone>
+ {this.mediaFiles.length > 0 && (
+ <div className="files">
+ <ul className="file-list">
+ {this.mediaFiles.map((file, i) => (
+ <li key={file.name} className="file-name">
+ {file.name}
+ <IconButton
+ onClick={() => {
+ this.setMediaFiles(this.mediaFiles.filter(f => f !== file));
+ }}>
+ <BiX />
+ </IconButton>
+ </li>
+ ))}
+ </ul>
+ </div>
+ )}
+
+ <Button
+ variant="contained"
+ sx={{ fontSize: '14px', display: 'flex', alignItems: 'center', gap: '1rem' }}
+ onClick={() => {
+ this.reportIssue();
+ }}>
+ Submit
+ {this.submitting && <Oval height={20} width={20} color="#ffffff" visible={true} ariaLabel="oval-loading" secondaryColor="#ffffff87" strokeWidth={3} strokeWidthSecondary={3} />}
+ </Button>
+ <IconButton sx={{ position: 'absolute', top: '4px', right: '4px' }} onClick={this.close}>
+ <BiX size={'16px'} />
+ </IconButton>
</div>
);
};
- private renderIssue = (issue: any) => {
+ private get reportInterface() {
+ const isReportingIssue = this.selectedIssue === null;
+
+ return (
+ <div className="settings-interface">
+ <div className="issue-list-wrapper">
+ <h3>Current Issues</h3>
+ <input type="text" placeholder="search issues" onChange={e => this.setQuery(e.target.value)}></input>
+ <br />
+ {this.shownIssues.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>
+
+ <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>
+ );
+ }
+
+ private renderIssue = (issue: Issue) => {
const isReportingIssue = issue === null;
return isReportingIssue ? (
@@ -275,7 +462,7 @@ export class ReportManager extends React.Component<{}> {
<option value="priority-high">Poor Documentation</option>
</select>
- <select name="bigPriority" onChange={e => (this.bugPriority = e.target.value)}>
+ <select name="priority" onChange={e => (this.bugPriority = e.target.value)}>
<option value="" disabled selected>
Priority
</option>
@@ -304,71 +491,54 @@ export class ReportManager extends React.Component<{}> {
</a>
</h5>
<div className="issue-title">{issue.title}</div>
- <ReactMarkdown children={issue.body} className="issue-body" linkTarget={'_blank'} remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]} />
+ <ReactMarkdown children={issue.body as string} 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">
- <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>
- ))
- )}
-
- {/* <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>
-
- <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>
- );
- }
-
render() {
return (
<MainViewModal
// contents={this.reportInterface}
- contents={this.reportIssueComponent()}
+ contents={this.reportComponent()}
isDisplayed={this.isOpen}
interactive={true}
closeOnExternalClick={this.close}
- dialogueBoxStyle={{ width: 'auto', height: '500px', background: Cast(Doc.SharingDoc().userColor, 'string', null) }}
+ dialogueBoxStyle={{ width: 'auto', minWidth: '400px', height: '85vh', maxHeight: '90vh', background: '#ffffff', borderRadius: '8px' }}
/>
);
}
}
+
+interface IssueCardProps {
+ issue: Issue;
+ onSelect: () => void;
+}
+const IssueCard = ({ issue, onSelect }: IssueCardProps) => {
+ return (
+ <div className="issue" onClick={onSelect}>
+ <label className="issue-label">#{issue.number}</label>
+ <h3 className="issue-title">{issue.title}</h3>
+ </div>
+ );
+};
+
+interface IssueViewProps {
+ issue: Issue;
+}
+
+const IssueView = ({ issue }: IssueViewProps) => {
+ return (
+ <div className="issue-view">
+ <span className="issue-label">
+ Issue{' '}
+ <a className="issue-link" href={issue.html_url} target="_blank">
+ #{issue.number}
+ </a>
+ </span>
+ <h2 className="issue-title">{issue.title}</h2>
+ <ReactMarkdown children={issue.body as string} className="issue-content" linkTarget={'_blank'} remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]} />
+ {/* <p className="issue-content">{issue.body}</p> */}
+ </div>
+ );
+};
diff --git a/src/client/util/reportManagerSchema.ts b/src/client/util/reportManagerSchema.ts
new file mode 100644
index 000000000..28ce6411d
--- /dev/null
+++ b/src/client/util/reportManagerSchema.ts
@@ -0,0 +1,877 @@
+/**
+ * Issues are a great way to keep track of tasks, enhancements, and bugs for your projects.
+ */
+export interface Issue {
+ active_lock_reason?: null | string;
+ assignee: null | PurpleSimpleUser;
+ assignees?: AssigneeElement[] | null;
+ /**
+ * How the author is associated with the repository.
+ */
+ author_association: AuthorAssociation;
+ /**
+ * Contents of the issue
+ */
+ body?: null | string;
+ body_html?: string;
+ body_text?: string;
+ closed_at: Date | null;
+ closed_by?: null | FluffySimpleUser;
+ comments: number;
+ comments_url: string;
+ created_at: Date;
+ draft?: boolean;
+ events_url: string;
+ html_url: string;
+ id: number;
+ /**
+ * Labels to associate with this issue; pass one or more label names to replace the set of
+ * labels on this issue; send an empty array to clear all labels from the issue; note that
+ * the labels are silently dropped for users without push access to the repository
+ */
+ labels: Array<LabelObject | string>;
+ labels_url: string;
+ locked: boolean;
+ milestone: null | Milestone;
+ node_id: string;
+ /**
+ * Number uniquely identifying the issue within its repository
+ */
+ number: number;
+ performed_via_github_app?: null | GitHubApp;
+ pull_request?: PullRequest;
+ reactions?: ReactionRollup;
+ /**
+ * A repository on GitHub.
+ */
+ repository?: Repository;
+ repository_url: string;
+ /**
+ * State of the issue; either 'open' or 'closed'
+ */
+ state: string;
+ /**
+ * The reason for the current state
+ */
+ state_reason?: StateReason | null;
+ timeline_url?: string;
+ /**
+ * Title of the issue
+ */
+ title: string;
+ updated_at: Date;
+ /**
+ * URL for the issue
+ */
+ url: string;
+ user: null | TentacledSimpleUser;
+ [property: string]: any;
+}
+
+/**
+ * A GitHub user.
+ */
+export interface PurpleSimpleUser {
+ avatar_url: string;
+ email?: null | string;
+ events_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ gravatar_id: null | string;
+ html_url: string;
+ id: number;
+ login: string;
+ name?: null | string;
+ node_id: string;
+ organizations_url: string;
+ received_events_url: string;
+ repos_url: string;
+ site_admin: boolean;
+ starred_at?: string;
+ starred_url: string;
+ subscriptions_url: string;
+ type: string;
+ url: string;
+ [property: string]: any;
+}
+
+/**
+ * A GitHub user.
+ */
+export interface AssigneeElement {
+ avatar_url: string;
+ email?: null | string;
+ events_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ gravatar_id: null | string;
+ html_url: string;
+ id: number;
+ login: string;
+ name?: null | string;
+ node_id: string;
+ organizations_url: string;
+ received_events_url: string;
+ repos_url: string;
+ site_admin: boolean;
+ starred_at?: string;
+ starred_url: string;
+ subscriptions_url: string;
+ type: string;
+ url: string;
+ [property: string]: any;
+}
+
+/**
+ * How the author is associated with the repository.
+ */
+export enum AuthorAssociation {
+ Collaborator = 'COLLABORATOR',
+ Contributor = 'CONTRIBUTOR',
+ FirstTimeContributor = 'FIRST_TIME_CONTRIBUTOR',
+ FirstTimer = 'FIRST_TIMER',
+ Mannequin = 'MANNEQUIN',
+ Member = 'MEMBER',
+ None = 'NONE',
+ Owner = 'OWNER',
+}
+
+/**
+ * A GitHub user.
+ */
+export interface FluffySimpleUser {
+ avatar_url: string;
+ email?: null | string;
+ events_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ gravatar_id: null | string;
+ html_url: string;
+ id: number;
+ login: string;
+ name?: null | string;
+ node_id: string;
+ organizations_url: string;
+ received_events_url: string;
+ repos_url: string;
+ site_admin: boolean;
+ starred_at?: string;
+ starred_url: string;
+ subscriptions_url: string;
+ type: string;
+ url: string;
+ [property: string]: any;
+}
+
+export interface LabelObject {
+ color?: null | string;
+ default?: boolean;
+ description?: null | string;
+ id?: number;
+ name?: string;
+ node_id?: string;
+ url?: string;
+ [property: string]: any;
+}
+
+/**
+ * A collection of related issues and pull requests.
+ */
+export interface Milestone {
+ closed_at: Date | null;
+ closed_issues: number;
+ created_at: Date;
+ creator: null | MilestoneSimpleUser;
+ description: null | string;
+ due_on: Date | null;
+ html_url: string;
+ id: number;
+ labels_url: string;
+ node_id: string;
+ /**
+ * The number of the milestone.
+ */
+ number: number;
+ open_issues: number;
+ /**
+ * The state of the milestone.
+ */
+ state: State;
+ /**
+ * The title of the milestone.
+ */
+ title: string;
+ updated_at: Date;
+ url: string;
+ [property: string]: any;
+}
+
+/**
+ * A GitHub user.
+ */
+export interface MilestoneSimpleUser {
+ avatar_url: string;
+ email?: null | string;
+ events_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ gravatar_id: null | string;
+ html_url: string;
+ id: number;
+ login: string;
+ name?: null | string;
+ node_id: string;
+ organizations_url: string;
+ received_events_url: string;
+ repos_url: string;
+ site_admin: boolean;
+ starred_at?: string;
+ starred_url: string;
+ subscriptions_url: string;
+ type: string;
+ url: string;
+ [property: string]: any;
+}
+
+/**
+ * The state of the milestone.
+ */
+export enum State {
+ Closed = 'closed',
+ Open = 'open',
+}
+
+/**
+ * GitHub apps are a new way to extend GitHub. They can be installed directly on
+ * organizations and user accounts and granted access to specific repositories. They come
+ * with granular permissions and built-in webhooks. GitHub apps are first class actors
+ * within GitHub.
+ */
+export interface GitHubApp {
+ client_id?: string;
+ client_secret?: string;
+ created_at: Date;
+ description: null | string;
+ /**
+ * The list of events for the GitHub app
+ */
+ events: string[];
+ external_url: string;
+ html_url: string;
+ /**
+ * Unique identifier of the GitHub app
+ */
+ id: number;
+ /**
+ * The number of installations associated with the GitHub app
+ */
+ installations_count?: number;
+ /**
+ * The name of the GitHub app
+ */
+ name: string;
+ node_id: string;
+ owner: null | GitHubAppSimpleUser;
+ pem?: string;
+ /**
+ * The set of permissions for the GitHub app
+ */
+ permissions: GitHubAppPermissions;
+ /**
+ * The slug name of the GitHub app
+ */
+ slug?: string;
+ updated_at: Date;
+ webhook_secret?: null | string;
+ [property: string]: any;
+}
+
+/**
+ * A GitHub user.
+ */
+export interface GitHubAppSimpleUser {
+ avatar_url: string;
+ email?: null | string;
+ events_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ gravatar_id: null | string;
+ html_url: string;
+ id: number;
+ login: string;
+ name?: null | string;
+ node_id: string;
+ organizations_url: string;
+ received_events_url: string;
+ repos_url: string;
+ site_admin: boolean;
+ starred_at?: string;
+ starred_url: string;
+ subscriptions_url: string;
+ type: string;
+ url: string;
+ [property: string]: any;
+}
+
+/**
+ * The set of permissions for the GitHub app
+ */
+export interface GitHubAppPermissions {
+ checks?: string;
+ contents?: string;
+ deployments?: string;
+ issues?: string;
+ metadata?: string;
+}
+
+export interface PullRequest {
+ diff_url: null | string;
+ html_url: null | string;
+ merged_at?: Date | null;
+ patch_url: null | string;
+ url: null | string;
+ [property: string]: any;
+}
+
+export interface ReactionRollup {
+ '+1': number;
+ '-1': number;
+ confused: number;
+ eyes: number;
+ heart: number;
+ hooray: number;
+ laugh: number;
+ rocket: number;
+ total_count: number;
+ url: string;
+ [property: string]: any;
+}
+
+/**
+ * A repository on GitHub.
+ */
+export interface Repository {
+ /**
+ * Whether to allow Auto-merge to be used on pull requests.
+ */
+ allow_auto_merge?: boolean;
+ /**
+ * Whether to allow forking this repo
+ */
+ allow_forking?: boolean;
+ /**
+ * Whether to allow merge commits for pull requests.
+ */
+ allow_merge_commit?: boolean;
+ /**
+ * Whether to allow rebase merges for pull requests.
+ */
+ allow_rebase_merge?: boolean;
+ /**
+ * Whether to allow squash merges for pull requests.
+ */
+ allow_squash_merge?: boolean;
+ /**
+ * Whether or not a pull request head branch that is behind its base branch can always be
+ * updated even if it is not required to be up to date before merging.
+ */
+ allow_update_branch?: boolean;
+ /**
+ * Whether anonymous git access is enabled for this repository
+ */
+ anonymous_access_enabled?: boolean;
+ archive_url: string;
+ /**
+ * Whether the repository is archived.
+ */
+ archived: boolean;
+ assignees_url: string;
+ blobs_url: string;
+ branches_url: string;
+ clone_url: string;
+ collaborators_url: string;
+ comments_url: string;
+ commits_url: string;
+ compare_url: string;
+ contents_url: string;
+ contributors_url: string;
+ created_at: Date | null;
+ /**
+ * The default branch of the repository.
+ */
+ default_branch: string;
+ /**
+ * Whether to delete head branches when pull requests are merged
+ */
+ delete_branch_on_merge?: boolean;
+ deployments_url: string;
+ description: null | string;
+ /**
+ * Returns whether or not this repository disabled.
+ */
+ disabled: boolean;
+ downloads_url: string;
+ events_url: string;
+ fork: boolean;
+ forks: number;
+ forks_count: number;
+ forks_url: string;
+ full_name: string;
+ git_commits_url: string;
+ git_refs_url: string;
+ git_tags_url: string;
+ git_url: string;
+ /**
+ * Whether discussions are enabled.
+ */
+ has_discussions?: boolean;
+ /**
+ * Whether downloads are enabled.
+ */
+ has_downloads: boolean;
+ /**
+ * Whether issues are enabled.
+ */
+ has_issues: boolean;
+ has_pages: boolean;
+ /**
+ * Whether projects are enabled.
+ */
+ has_projects: boolean;
+ /**
+ * Whether the wiki is enabled.
+ */
+ has_wiki: boolean;
+ homepage: null | string;
+ hooks_url: string;
+ html_url: string;
+ /**
+ * Unique identifier of the repository
+ */
+ id: number;
+ /**
+ * Whether this repository acts as a template that can be used to generate new repositories.
+ */
+ is_template?: boolean;
+ issue_comment_url: string;
+ issue_events_url: string;
+ issues_url: string;
+ keys_url: string;
+ labels_url: string;
+ language: null | string;
+ languages_url: string;
+ license: null | LicenseSimple;
+ master_branch?: string;
+ /**
+ * The default value for a merge commit message.
+ *
+ * - `PR_TITLE` - default to the pull request's title.
+ * - `PR_BODY` - default to the pull request's body.
+ * - `BLANK` - default to a blank commit message.
+ */
+ merge_commit_message?: MergeCommitMessage;
+ /**
+ * The default value for a merge commit title.
+ *
+ * - `PR_TITLE` - default to the pull request's title.
+ * - `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull
+ * request #123 from branch-name).
+ */
+ merge_commit_title?: MergeCommitTitle;
+ merges_url: string;
+ milestones_url: string;
+ mirror_url: null | string;
+ /**
+ * The name of the repository.
+ */
+ name: string;
+ network_count?: number;
+ node_id: string;
+ notifications_url: string;
+ open_issues: number;
+ open_issues_count: number;
+ organization?: null | RepositorySimpleUser;
+ /**
+ * A GitHub user.
+ */
+ owner: OwnerObject;
+ permissions?: RepositoryPermissions;
+ /**
+ * Whether the repository is private or public.
+ */
+ private: boolean;
+ pulls_url: string;
+ pushed_at: Date | null;
+ releases_url: string;
+ /**
+ * The size of the repository. Size is calculated hourly. When a repository is initially
+ * created, the size is 0.
+ */
+ size: number;
+ /**
+ * The default value for a squash merge commit message:
+ *
+ * - `PR_BODY` - default to the pull request's body.
+ * - `COMMIT_MESSAGES` - default to the branch's commit messages.
+ * - `BLANK` - default to a blank commit message.
+ */
+ squash_merge_commit_message?: SquashMergeCommitMessage;
+ /**
+ * The default value for a squash merge commit title:
+ *
+ * - `PR_TITLE` - default to the pull request's title.
+ * - `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull
+ * request's title (when more than one commit).
+ */
+ squash_merge_commit_title?: SquashMergeCommitTitle;
+ ssh_url: string;
+ stargazers_count: number;
+ stargazers_url: string;
+ starred_at?: string;
+ statuses_url: string;
+ subscribers_count?: number;
+ subscribers_url: string;
+ subscription_url: string;
+ svn_url: string;
+ tags_url: string;
+ teams_url: string;
+ temp_clone_token?: string;
+ template_repository?: null | TemplateRepository;
+ topics?: string[];
+ trees_url: string;
+ updated_at: Date | null;
+ url: string;
+ /**
+ * Whether a squash merge commit can use the pull request title as default. **This property
+ * has been deprecated. Please use `squash_merge_commit_title` instead.
+ */
+ use_squash_pr_title_as_default?: boolean;
+ /**
+ * The repository visibility: public, private, or internal.
+ */
+ visibility?: string;
+ watchers: number;
+ watchers_count: number;
+ /**
+ * Whether to require contributors to sign off on web-based commits
+ */
+ web_commit_signoff_required?: boolean;
+ [property: string]: any;
+}
+
+/**
+ * License Simple
+ */
+export interface LicenseSimple {
+ html_url?: string;
+ key: string;
+ name: string;
+ node_id: string;
+ spdx_id: null | string;
+ url: null | string;
+ [property: string]: any;
+}
+
+/**
+ * The default value for a merge commit message.
+ *
+ * - `PR_TITLE` - default to the pull request's title.
+ * - `PR_BODY` - default to the pull request's body.
+ * - `BLANK` - default to a blank commit message.
+ */
+export enum MergeCommitMessage {
+ Blank = 'BLANK',
+ PRBody = 'PR_BODY',
+ PRTitle = 'PR_TITLE',
+}
+
+/**
+ * The default value for a merge commit title.
+ *
+ * - `PR_TITLE` - default to the pull request's title.
+ * - `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull
+ * request #123 from branch-name).
+ */
+export enum MergeCommitTitle {
+ MergeMessage = 'MERGE_MESSAGE',
+ PRTitle = 'PR_TITLE',
+}
+
+/**
+ * A GitHub user.
+ */
+export interface RepositorySimpleUser {
+ avatar_url: string;
+ email?: null | string;
+ events_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ gravatar_id: null | string;
+ html_url: string;
+ id: number;
+ login: string;
+ name?: null | string;
+ node_id: string;
+ organizations_url: string;
+ received_events_url: string;
+ repos_url: string;
+ site_admin: boolean;
+ starred_at?: string;
+ starred_url: string;
+ subscriptions_url: string;
+ type: string;
+ url: string;
+ [property: string]: any;
+}
+
+/**
+ * A GitHub user.
+ */
+export interface OwnerObject {
+ avatar_url: string;
+ email?: null | string;
+ events_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ gravatar_id: null | string;
+ html_url: string;
+ id: number;
+ login: string;
+ name?: null | string;
+ node_id: string;
+ organizations_url: string;
+ received_events_url: string;
+ repos_url: string;
+ site_admin: boolean;
+ starred_at?: string;
+ starred_url: string;
+ subscriptions_url: string;
+ type: string;
+ url: string;
+ [property: string]: any;
+}
+
+export interface RepositoryPermissions {
+ admin: boolean;
+ maintain?: boolean;
+ pull: boolean;
+ push: boolean;
+ triage?: boolean;
+ [property: string]: any;
+}
+
+/**
+ * The default value for a squash merge commit message:
+ *
+ * - `PR_BODY` - default to the pull request's body.
+ * - `COMMIT_MESSAGES` - default to the branch's commit messages.
+ * - `BLANK` - default to a blank commit message.
+ */
+export enum SquashMergeCommitMessage {
+ Blank = 'BLANK',
+ CommitMessages = 'COMMIT_MESSAGES',
+ PRBody = 'PR_BODY',
+}
+
+/**
+ * The default value for a squash merge commit title:
+ *
+ * - `PR_TITLE` - default to the pull request's title.
+ * - `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull
+ * request's title (when more than one commit).
+ */
+export enum SquashMergeCommitTitle {
+ CommitOrPRTitle = 'COMMIT_OR_PR_TITLE',
+ PRTitle = 'PR_TITLE',
+}
+
+export interface TemplateRepository {
+ allow_auto_merge?: boolean;
+ allow_merge_commit?: boolean;
+ allow_rebase_merge?: boolean;
+ allow_squash_merge?: boolean;
+ allow_update_branch?: boolean;
+ archive_url?: string;
+ archived?: boolean;
+ assignees_url?: string;
+ blobs_url?: string;
+ branches_url?: string;
+ clone_url?: string;
+ collaborators_url?: string;
+ comments_url?: string;
+ commits_url?: string;
+ compare_url?: string;
+ contents_url?: string;
+ contributors_url?: string;
+ created_at?: string;
+ default_branch?: string;
+ delete_branch_on_merge?: boolean;
+ deployments_url?: string;
+ description?: string;
+ disabled?: boolean;
+ downloads_url?: string;
+ events_url?: string;
+ fork?: boolean;
+ forks_count?: number;
+ forks_url?: string;
+ full_name?: string;
+ git_commits_url?: string;
+ git_refs_url?: string;
+ git_tags_url?: string;
+ git_url?: string;
+ has_downloads?: boolean;
+ has_issues?: boolean;
+ has_pages?: boolean;
+ has_projects?: boolean;
+ has_wiki?: boolean;
+ homepage?: string;
+ hooks_url?: string;
+ html_url?: string;
+ id?: number;
+ is_template?: boolean;
+ issue_comment_url?: string;
+ issue_events_url?: string;
+ issues_url?: string;
+ keys_url?: string;
+ labels_url?: string;
+ language?: string;
+ languages_url?: string;
+ /**
+ * The default value for a merge commit message.
+ *
+ * - `PR_TITLE` - default to the pull request's title.
+ * - `PR_BODY` - default to the pull request's body.
+ * - `BLANK` - default to a blank commit message.
+ */
+ merge_commit_message?: MergeCommitMessage;
+ /**
+ * The default value for a merge commit title.
+ *
+ * - `PR_TITLE` - default to the pull request's title.
+ * - `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull
+ * request #123 from branch-name).
+ */
+ merge_commit_title?: MergeCommitTitle;
+ merges_url?: string;
+ milestones_url?: string;
+ mirror_url?: string;
+ name?: string;
+ network_count?: number;
+ node_id?: string;
+ notifications_url?: string;
+ open_issues_count?: number;
+ owner?: Owner;
+ permissions?: TemplateRepositoryPermissions;
+ private?: boolean;
+ pulls_url?: string;
+ pushed_at?: string;
+ releases_url?: string;
+ size?: number;
+ /**
+ * The default value for a squash merge commit message:
+ *
+ * - `PR_BODY` - default to the pull request's body.
+ * - `COMMIT_MESSAGES` - default to the branch's commit messages.
+ * - `BLANK` - default to a blank commit message.
+ */
+ squash_merge_commit_message?: SquashMergeCommitMessage;
+ /**
+ * The default value for a squash merge commit title:
+ *
+ * - `PR_TITLE` - default to the pull request's title.
+ * - `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull
+ * request's title (when more than one commit).
+ */
+ squash_merge_commit_title?: SquashMergeCommitTitle;
+ ssh_url?: string;
+ stargazers_count?: number;
+ stargazers_url?: string;
+ statuses_url?: string;
+ subscribers_count?: number;
+ subscribers_url?: string;
+ subscription_url?: string;
+ svn_url?: string;
+ tags_url?: string;
+ teams_url?: string;
+ temp_clone_token?: string;
+ topics?: string[];
+ trees_url?: string;
+ updated_at?: string;
+ url?: string;
+ use_squash_pr_title_as_default?: boolean;
+ visibility?: string;
+ watchers_count?: number;
+ [property: string]: any;
+}
+
+export interface Owner {
+ avatar_url?: string;
+ events_url?: string;
+ followers_url?: string;
+ following_url?: string;
+ gists_url?: string;
+ gravatar_id?: string;
+ html_url?: string;
+ id?: number;
+ login?: string;
+ node_id?: string;
+ organizations_url?: string;
+ received_events_url?: string;
+ repos_url?: string;
+ site_admin?: boolean;
+ starred_url?: string;
+ subscriptions_url?: string;
+ type?: string;
+ url?: string;
+ [property: string]: any;
+}
+
+export interface TemplateRepositoryPermissions {
+ admin?: boolean;
+ maintain?: boolean;
+ pull?: boolean;
+ push?: boolean;
+ triage?: boolean;
+ [property: string]: any;
+}
+
+export enum StateReason {
+ Completed = 'completed',
+ NotPlanned = 'not_planned',
+ Reopened = 'reopened',
+}
+
+/**
+ * A GitHub user.
+ */
+export interface TentacledSimpleUser {
+ avatar_url: string;
+ email?: null | string;
+ events_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ gravatar_id: null | string;
+ html_url: string;
+ id: number;
+ login: string;
+ name?: null | string;
+ node_id: string;
+ organizations_url: string;
+ received_events_url: string;
+ repos_url: string;
+ site_admin: boolean;
+ starred_at?: string;
+ starred_url: string;
+ subscriptions_url: string;
+ type: string;
+ url: string;
+ [property: string]: any;
+}