Skip to content
This repository was archived by the owner on Aug 5, 2022. It is now read-only.

Commit c770da4

Browse files
committed
### Version 0.50.0 (Help > Give feedback (YouTrack))
#### Feature - Allow user to select Feedback type (Bug Report or Feature Request) - Submit feedback to "Digital Bible Library Support" YouTrack group - Add user to "All relevant emails" lists in YouTrack issue - Add `Nathanael` tag to youtrack issues (Merge branch 'youtrack_issue_reporting')
2 parents 0734c40 + ab69f4a commit c770da4

File tree

4 files changed

+145
-25
lines changed

4 files changed

+145
-25
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
### Version 0.50.0 (Help > Give feedback (YouTrack))
2+
3+
#### Feature
4+
5+
- Allow user to select Feedback type (Bug Report or Feature Request)
6+
- Submit feedback to "Digital Bible Library Support" YouTrack group
7+
- Add user to "All relevant emails" lists in YouTrack issue
8+
- Add `Nathanael` tag to youtrack issues
9+
110
### Version 0.49.0 (Help > Give feedback (YouTrack))
211

312
#### Feature

app/components/SubmitHelpTicket.js

+100-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { compose } from 'recompose';
22
import { connect } from 'react-redux';
33
import { withStyles } from '@material-ui/core/styles';
4+
import FormControl from '@material-ui/core/FormControl';
5+
import InputLabel from '@material-ui/core/InputLabel';
6+
import Select from '@material-ui/core/Select';
7+
import MenuItem from '@material-ui/core/MenuItem';
48
import log from 'electron-log';
59
import got from 'got';
610
import FormData from 'form-data';
@@ -60,7 +64,11 @@ const config = {
6064
};
6165
const youtrack = new Youtrack(config);
6266

63-
const DBL_PROJECT_ID = '0-30';
67+
const DBL_SUPPORT_PROJECT_ID = '0-31'; // Digital Bible Library Support (DBLS)
68+
69+
function splitCamelCaseToSpaced(str) {
70+
return str.split(/(?=[A-Z])/).join(' ');
71+
}
6472

6573
/* eslint-disable-next-line no-useless-escape */
6674
const linkPattern = /!*\[(?<alttext>[^\]]*?)\]\((?<filename>.*?) *(?=\"|\))(?<optionalpart>\".*\")?\)/gm;
@@ -76,7 +84,13 @@ function getMarkDownLocalFileLinkMatches(markdown) {
7684
// capturing group n: match[n]
7785
const { filename } = match.groups;
7886
const decodedFilename = decodeURIComponent(filename);
79-
if (fs.existsSync(decodedFilename)) {
87+
if (
88+
decodedFilename &&
89+
!decodedFilename.startsWith('http:') &&
90+
!decodedFilename.startsWith('https:') &&
91+
!decodedFilename.startsWith('mailto:') &&
92+
fs.existsSync(decodedFilename)
93+
) {
8094
// file exists
8195
linkMatches.push({ ...match });
8296
links.push(decodedFilename);
@@ -199,6 +213,32 @@ async function postAttachmentsToIssue(
199213
.on('error', handleError);
200214
}
201215

216+
async function postTagsToIssue(issue) {
217+
const NATHANAEL_TAG_ID = '5-170';
218+
try {
219+
const json = { issues: [{ id: issue.id }] };
220+
const requestOptions = {
221+
method: 'POST',
222+
headers: {
223+
Authorization: `Bearer ${config.token}`,
224+
Accept: 'application/json',
225+
'Content-Type': 'application/json'
226+
},
227+
body: JSON.stringify(json)
228+
};
229+
const fields =
230+
'name,issues,color,untagOnResolve,owner,visibleFor,updateableBy';
231+
const query = `fields=${fields}`;
232+
const response = await fetch(
233+
`${config.baseUrl}/api/issueTags/${NATHANAEL_TAG_ID}?${query}`,
234+
requestOptions
235+
);
236+
return response;
237+
} catch (error) {
238+
log.error(error);
239+
}
240+
}
241+
202242
async function getConfigXmlSettings(appState) {
203243
const { workspace } =
204244
workspaceHelpers.getCurrentWorkspaceFullPath(appState) || {};
@@ -254,6 +294,7 @@ class SubmitHelpTicket extends React.Component<Props> {
254294
async (event, appState) => {
255295
try {
256296
await this.refreshMarkdownDescription(appState);
297+
this.setState({ appState });
257298
} catch (error) {
258299
log.error(error);
259300
}
@@ -329,7 +370,7 @@ class SubmitHelpTicket extends React.Component<Props> {
329370

330371
async removeTempFiles() {
331372
const { appStateFilePath, activeBundleFilePath } = this.state;
332-
if (await fs.exists(appStateFilePath)) {
373+
if (appStateFilePath && (await fs.exists(appStateFilePath))) {
333374
await fs.remove(appStateFilePath);
334375
}
335376
if (activeBundleFilePath && (await fs.exists(activeBundleFilePath))) {
@@ -341,6 +382,10 @@ class SubmitHelpTicket extends React.Component<Props> {
341382

342383
mdParser = null;
343384

385+
handleFeedbackTypeChange = event => {
386+
this.setState({ feedbackType: event.target.value });
387+
};
388+
344389
handleEditorChange = ({ text }) => {
345390
this.setState({
346391
description: text.replace(linkPattern, replaceEmptyAltTextWithFileName)
@@ -406,32 +451,59 @@ class SubmitHelpTicket extends React.Component<Props> {
406451
this.setState({ isUploading });
407452
};
408453

409-
handleError = (/* error, body, response */) => {
454+
handleError = (error /* , body, response */) => {
455+
log.error(error);
410456
this.setState({ isUploading: false });
411457
};
412458

459+
getFinalDescription = () => {
460+
const { description, appState, feedbackType = 'BugReport' } = this.state;
461+
const descriptionWithServerLinks = description.replace(
462+
linkPattern,
463+
replaceFilePathsWithFileNames
464+
);
465+
const app = servicesHelpers.getApp();
466+
const appName = app.getName();
467+
const appVersion = app.getVersion();
468+
const { authentication } = appState;
469+
const { whoami } = authentication;
470+
const { display_name: userName, email: userEmail } = whoami || {};
471+
const finalDescription = `${descriptionWithServerLinks}
472+
-----------
473+
\`\`\`
474+
Product Name: ${appName}
475+
Product Version: ${appVersion}
476+
Feedback Type: ${feedbackType}
477+
Email: ${userEmail || ''}
478+
Keep Informed: ${userEmail ? 'True' : ''}
479+
User: ${userName || ''}
480+
\`\`\`
481+
------------
482+
`;
483+
return finalDescription;
484+
};
485+
413486
handleClickSendFeedback = async () => {
414-
const { title, description } = this.state;
487+
const { title, description: sourceDescription } = this.state;
415488
try {
489+
const finalDescription = this.getFinalDescription();
416490
// create a new issue
417491
const issue = await youtrack.issues.create({
418492
summary: title,
419-
description: description.replace(
420-
linkPattern,
421-
replaceFilePathsWithFileNames
422-
),
493+
description: finalDescription,
423494
project: {
424-
id: DBL_PROJECT_ID
495+
id: DBL_SUPPORT_PROJECT_ID
425496
},
426497
usesMarkdown: true
427498
});
428499
// try to upload attachment
429500
await postAttachmentsToIssue(
430501
issue,
431-
description,
502+
sourceDescription,
432503
this.handleProgress,
433504
this.handleError
434505
);
506+
await postTagsToIssue(issue);
435507
const currentWindow = servicesHelpers.getCurrentWindow();
436508
currentWindow.close();
437509
} catch (error) {
@@ -440,7 +512,12 @@ class SubmitHelpTicket extends React.Component<Props> {
440512
};
441513

442514
render() {
443-
const { title, description, isUploading } = this.state;
515+
const {
516+
title,
517+
description,
518+
isUploading,
519+
feedbackType = 'BugReport'
520+
} = this.state;
444521
const { classes } = this.props;
445522
return (
446523
<React.Fragment>
@@ -454,7 +531,7 @@ class SubmitHelpTicket extends React.Component<Props> {
454531
disabled={title.trim().length < 3 || isUploading}
455532
>
456533
<CloudUpload style={{ marginRight: '10px' }} />
457-
Send
534+
Send {splitCamelCaseToSpaced(feedbackType)}
458535
{isUploading && (
459536
<CircularProgress
460537
className={classes.buttonProgress}
@@ -475,6 +552,16 @@ class SubmitHelpTicket extends React.Component<Props> {
475552
}}
476553
>
477554
<nav className="nav">
555+
<FormControl fullWidth>
556+
<InputLabel color="secondary">Type of Feedback</InputLabel>
557+
<Select
558+
value={feedbackType}
559+
onChange={this.handleFeedbackTypeChange}
560+
>
561+
<MenuItem value="BugReport">Bug Report</MenuItem>
562+
<MenuItem value="FeatureRequest">Feature Request</MenuItem>
563+
</Select>
564+
</FormControl>
478565
<TextField
479566
required
480567
id="title"

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "nathanael",
33
"productName": "nathanael",
4-
"version": "0.49.0",
4+
"version": "0.50.0",
55
"description": "Electron frontend to DBL dot Local",
66
"scripts": {
77
"build": "concurrently \"yarn build-main\" \"yarn build-renderer\"",

yarn.lock

+35-11
Original file line numberDiff line numberDiff line change
@@ -3787,16 +3787,16 @@ cache-base@^1.0.1:
37873787
unset-value "^1.0.0"
37883788

37893789
cacheable-request@^6.0.0:
3790-
version "6.0.0"
3791-
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.0.0.tgz#4a1727414e02ac4af82560c4da1b61daa3fa2b63"
3792-
integrity sha512-2N7AmszH/WPPpl5Z3XMw1HAP+8d+xugnKQAeKvxFZ/04dbT/CAznqwbl+7eSr3HkwdepNwtb2yx3CAMQWvG01Q==
3790+
version "6.1.0"
3791+
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912"
3792+
integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==
37933793
dependencies:
37943794
clone-response "^1.0.2"
3795-
get-stream "^4.0.0"
3795+
get-stream "^5.1.0"
37963796
http-cache-semantics "^4.0.0"
37973797
keyv "^3.0.0"
3798-
lowercase-keys "^1.0.1"
3799-
normalize-url "^3.1.0"
3798+
lowercase-keys "^2.0.0"
3799+
normalize-url "^4.1.0"
38003800
responselike "^1.0.2"
38013801

38023802
call-me-maybe@^1.0.1:
@@ -5082,9 +5082,9 @@ default-require-extensions@^2.0.0:
50825082
strip-bom "^3.0.0"
50835083

50845084
defer-to-connect@^1.0.1:
5085-
version "1.0.2"
5086-
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.0.2.tgz#4bae758a314b034ae33902b5aac25a8dd6a8633e"
5087-
integrity sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw==
5085+
version "1.1.0"
5086+
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.0.tgz#b41bd7efa8508cef13f8456975f7a278c72833fd"
5087+
integrity sha512-WE2sZoctWm/v4smfCAdjYbrfS55JiMRdlY9ZubFhsYbteCK9+BvAx4YV7nPjYM6ZnX5BcoVKwfmyx9sIFTgQMQ==
50885088

50895089
define-properties@^1.1.2, define-properties@^1.1.3:
50905090
version "1.1.3"
@@ -5654,13 +5654,20 @@ encoding@^0.1.11:
56545654
dependencies:
56555655
iconv-lite "~0.4.13"
56565656

5657-
end-of-stream@^1.0.0, end-of-stream@^1.1.0:
5657+
end-of-stream@^1.0.0:
56585658
version "1.4.1"
56595659
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
56605660
integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
56615661
dependencies:
56625662
once "^1.4.0"
56635663

5664+
end-of-stream@^1.1.0:
5665+
version "1.4.4"
5666+
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
5667+
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
5668+
dependencies:
5669+
once "^1.4.0"
5670+
56645671
endpoint-utils@^1.0.2:
56655672
version "1.0.2"
56665673
resolved "https://registry.yarnpkg.com/endpoint-utils/-/endpoint-utils-1.0.2.tgz#0808c3369a727cd7967a39ff34ebc926b88146a8"
@@ -6939,6 +6946,13 @@ get-stream@^4.0.0, get-stream@^4.1.0:
69396946
dependencies:
69406947
pump "^3.0.0"
69416948

6949+
get-stream@^5.1.0:
6950+
version "5.1.0"
6951+
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9"
6952+
integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==
6953+
dependencies:
6954+
pump "^3.0.0"
6955+
69426956
get-value@^2.0.3, get-value@^2.0.6:
69436957
version "2.0.6"
69446958
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@@ -9442,6 +9456,11 @@ lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
94429456
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
94439457
integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
94449458

9459+
lowercase-keys@^2.0.0:
9460+
version "2.0.0"
9461+
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
9462+
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
9463+
94459464
94469465
version "2.6.3"
94479466
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.3.tgz#51ccd0b4fc0c843587d7a5709ce4d3b7629bedc5"
@@ -10308,11 +10327,16 @@ normalize-selector@^0.2.0:
1030810327
resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03"
1030910328
integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=
1031010329

10311-
normalize-url@^3.0.0, normalize-url@^3.1.0:
10330+
normalize-url@^3.0.0:
1031210331
version "3.3.0"
1031310332
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
1031410333
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
1031510334

10335+
normalize-url@^4.1.0:
10336+
version "4.5.0"
10337+
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
10338+
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
10339+
1031610340
npm-bundled@^1.0.1:
1031710341
version "1.0.6"
1031810342
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd"

0 commit comments

Comments
 (0)