Skip to content

Commit

Permalink
Merge branch 'release/2.5.13'
Browse files Browse the repository at this point in the history
  • Loading branch information
ilya-lopukhin committed Feb 27, 2018
2 parents bfb96ea + f65d8d0 commit c2d3a2f
Show file tree
Hide file tree
Showing 30 changed files with 823 additions and 288 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
<a name="2.5.13"></a>
## [2.5.13](https://github.com/web-pal/chronos-timetracker/compare/v2.5.12...v2.5.13) (2018-02-27)


### Bug Fixes

* new issue window didn't closed on windows ([bc50b17](https://github.com/web-pal/chronos-timetracker/commit/bc50b17))
* **Browsing Issues:** request timeout + infiniteloader improvment ([e1fd51e](https://github.com/web-pal/chronos-timetracker/commit/e1fd51e))


### Features

* new issue modal with Jira JS API ([d313feb](https://github.com/web-pal/chronos-timetracker/commit/d313feb))
* webview for create new issue ([5ad9555](https://github.com/web-pal/chronos-timetracker/commit/5ad9555))
* **Issue Detail View:** edit issue ([a31c77a](https://github.com/web-pal/chronos-timetracker/commit/a31c77a))



<a name="2.5.12"></a>
## [2.5.12](https://github.com/web-pal/chronos-timetracker/compare/v2.5.11...v2.5.12) (2018-02-22)

Expand Down
3 changes: 3 additions & 0 deletions app/actions/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@ export const clearResourceList = ({
export const setResourceMeta = ({
meta,
resourceName,
resources,
}: {|
meta: any,
resourceName: string,
resources?: Array<string | number>,
|}): ResourcesAction => ({
type: actionTypes.SET_RESOURCES_META,
meta,
resourceName,
resources,
});
39 changes: 38 additions & 1 deletion app/containers/IssueView/IssueViewHeader/IssueViewHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import {
import {
getStatus as getResourceStatus,
} from 'redux-resource';
import {
ipcRenderer,
} from 'electron';

import type {
StatelessFunctionalComponent,
Expand Down Expand Up @@ -34,10 +37,12 @@ import Button, {
} from '@atlaskit/button';
import Spinner from '@atlaskit/spinner';
import {
getUiState,
getTimerState,
getSelectedIssue,
getSelfKey,
getResourceMappedList,
getResourceMeta,
} from 'selectors';

import {
Expand Down Expand Up @@ -68,18 +73,24 @@ import {
type Props = {
selectedIssue: Issue,
timerRunning: boolean,
allowEdit: boolean,
transitionsIsFetching: boolean,
issueTransitions: Array<IssueStatus>,
selfKey: string,
host: string,
protocol: string,
dispatch: Dispatch,
};

const IssueViewHeader: StatelessFunctionalComponent<Props> = ({
selectedIssue,
timerRunning,
allowEdit,
transitionsIsFetching,
issueTransitions,
selfKey,
host,
protocol,
dispatch,
}: Props):Node => (
<IssueViewHeaderContainer>
Expand Down Expand Up @@ -197,15 +208,41 @@ const IssueViewHeader: StatelessFunctionalComponent<Props> = ({
Assign to me
</Button>
}
<div>
<div style={{ width: 10 }} />
<Button
isDisabled={!allowEdit}
onClick={() => {
ipcRenderer.send(
'open-issue-window',
{
url: `${protocol}://${host}/browse/${selectedIssue.key}`,
issueId: selectedIssue.id,
},
);
}}
>
Edit
</Button>
</div>
</ButtonGroup>
</Flex>
</IssueViewHeaderContainer>
);

function mapStateToProps(state) {
const selectedIssue = getSelectedIssue(state);
let allowEdit = false;
if (selectedIssue) {
const issueMeta = getResourceMeta('issues', selectedIssue.id)(state);
allowEdit = issueMeta.permissions ? issueMeta.permissions.EDIT_ISSUE.havePermission : false;
}
return {
selectedIssue: getSelectedIssue(state),
host: getUiState('host')(state),
protocol: getUiState('protocol')(state),
timerRunning: getTimerState('running')(state),
selectedIssue,
allowEdit,
issueTransitions: getResourceMappedList(
'issuesStatuses',
'issueTransitions',
Expand Down
107 changes: 107 additions & 0 deletions app/containers/Popups/IssueForm/IssueForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import React, { Component } from 'react';
import {
ipcRenderer,
} from 'electron';

import Spinner from '@atlaskit/spinner';
import {
AppWrapper,
FullPageSpinner,
} from 'styles';


class IssueForm extends Component<{}, any> {
constructor(props: {}) {
super(props);
this.state = {
show: true,
};
}

componentDidMount() {
ipcRenderer.on('url', this.onLoadUrl);
ipcRenderer.on('page-fully-loaded', () => {
setTimeout(() => {
this.setState({
show: false,
});
document.getElementById('root').style.display = 'none';
}, 500);
});
}

componentWillUnmount() {
ipcRenderer.removeListener('url', this.onLoadUrl);
}

onLoadUrl = (
ev,
{
url,
projectId,
issueId,
},
) => {
const webview = document.createElement('webview');
webview.setAttribute('preload', './preload.js');
webview.style.height = '100%';
webview.addEventListener('did-finish-load', () => {
if (process.env.NODE_ENV === 'development' || process.env.DEBUG_PROD === true) {
webview.openDevTools();
}
webview.executeJavaScript(`
document.getElementById('page').style.display = 'none';
var issueForm = JIRA.Forms
${issueId ?
`.createEditIssueForm({ issueId: ${issueId} })` :
`.createCreateIssueForm({ pid: ${projectId} })`
}
.bind('sessionComplete', function(ev, issues) {
${issueId ?
`ipcRenderer.send("issue-refetch", "${issueId}");` :
'ipcRenderer.send("issue-created", issues);'
}
ipcRenderer.send('close-page');
})
.asDialog({
windowTitle: ${issueId ? '"Edit issue"' : '"Create Issue"'}
});
issueForm.show();
var timerId = setInterval(function() {
if (issueForm.$buttonContainer) {
var cancel = issueForm.$buttonContainer[0].getElementsByClassName('cancel');
cancel[0].addEventListener('click', function (event) {
ipcRenderer.send('close-page');
});
clearInterval(timerId);
document.getElementById('qf-field-picker-trigger').remove();
var forRemove = document.getElementsByClassName('aui-blanket');
forRemove[0].remove();
var formBody = issueForm.$form.children()[0];
var jiraDialog = issueForm.$popup[0];
formBody.style.maxHeight = (parseInt(formBody.style.maxHeight.replace('px', ''), 10) + 120).toString() + 'px';
jiraDialog.style.marginTop = (parseInt(jiraDialog.style.marginTop.replace('px', ''), 10) - 65).toString() + 'px';
ipcRenderer.send('page-fully-loaded');
}
}, 500);
`);
});
webview.src = url;
document.getElementById('forWebview').appendChild(webview);
}

render() {
if (this.state.show) {
return (
<AppWrapper id="app">
<FullPageSpinner>
<Spinner size="xlarge" />
</FullPageSpinner>
</AppWrapper>
);
}
return null;
}
}

export default IssueForm;
Empty file.
5 changes: 4 additions & 1 deletion app/containers/Popups/ScreenPopup/ScreenPopup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ type State = {
export default class ScreenPopup extends Component<{}, State> {
constructor(props: {}) {
super(props);
const { lastScreenshotPath, screenshotPreviewTime } = getGlobal('sharedObj');
const {
lastScreenshotPath,
screenshotPreviewTime,
} = getGlobal('sharedObj');
remote.getCurrentWindow().flashFrame(true);
this.state = {
maxTime: screenshotPreviewTime,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
uiActions,
} from 'actions';
import {
getCurrentProjectKey,
getCurrentProjectId,
getUiState,
} from 'selectors';
Expand All @@ -43,6 +44,7 @@ type Props = {
filterStatusesIsFetched: boolean,
sidebarFiltersIsOpen: boolean,
filtersApplied: boolean,
currentProjectKey: string,
currentProjectId: string,
host: string,
protocol: string,
Expand All @@ -54,6 +56,7 @@ const IssuesHeader: StatelessFunctionalComponent<Props> = ({
filterStatusesIsFetched,
sidebarFiltersIsOpen,
filtersApplied,
currentProjectKey,
currentProjectId,
host,
protocol,
Expand Down Expand Up @@ -83,8 +86,11 @@ const IssuesHeader: StatelessFunctionalComponent<Props> = ({
size="medium"
onClick={() => {
ipcRenderer.send(
'open-create-issue-window',
`${protocol}://${host}/secure/CreateIssue.jspa?pid=${currentProjectId}`,
'open-issue-window',
{
projectId: currentProjectId,
url: `${protocol}://${host}/projects/${currentProjectKey}/issues`,
},
);
}}
/>
Expand Down Expand Up @@ -115,6 +121,7 @@ function mapStateToProps(state) {
host: getUiState('host')(state),
protocol: getUiState('protocol')(state),
currentProjectId: getCurrentProjectId(state),
currentProjectKey: getCurrentProjectKey(state),
searchValue: getUiState('issuesSearch')(state),
sidebarFiltersIsOpen: getUiState('sidebarFiltersIsOpen')(state),
filterStatusesIsFetched: getUiState('filterStatusesIsFetched')(state),
Expand Down
3 changes: 1 addition & 2 deletions app/containers/Sidebar/SidebarIssues/SidebarIssues.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ const SidebarAllItems: StatelessFunctionalComponent<Props> = ({
rowCount={totalCount}
ref={registerInfiniteNode}
minimumBatchSize={50}
threshold={20}
loadMoreRows={({ startIndex, stopIndex }) =>
new Promise((resolve) => {
dispatch(issuesActions.fetchIssuesRequest({
Expand Down Expand Up @@ -129,7 +128,7 @@ const SidebarAllItems: StatelessFunctionalComponent<Props> = ({
return (
<div style={style} key={key}>
<ErrorBoundary debugData={item}>
{item ?
{(item && item !== 'pending') ?
<IssueItem
issue={item}
active={selectedIssueId === item.id}
Expand Down
2 changes: 1 addition & 1 deletion app/idlePopup.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ render(
<div id="root">
<IdlePopup />
</div>,
document.getElementById('root') || document.createElement('div'),
document.getElementById('root'),
);
63 changes: 63 additions & 0 deletions app/issueForm.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style type="text/css">
body {
font-family: Open Sans;
margin: 0px;
padding: 0px;
background-color: white;
height: 100%;
}

html, body, #app, #root, #forWebview {
height: 100%;
overflow: hidden;
}
</style>
<script>
(() => {
if (!process.env.HOT) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = './dist/style.css';
// HACK: Writing the script path should be done with webpack
document.getElementsByTagName('head')[0].appendChild(link);
}
})();
</script>
</head>
<body>
<div id="root"></div>
<div id="forWebview"></div>
<script>
{
// Dynamically include DLL if in development
if (process.env.NODE_ENV === 'development') {
const dllScript = document.createElement('script');
dllScript.src = '../dll/vendor.dll.js';
document.body.appendChild(dllScript);
}

if (process.env.NODE_ENV === 'production') {
const commonsScript = document.createElement('script');
commonsScript.src = './dist/commons.js';
document.body.appendChild(commonsScript);
}

// Dynamically insert the renderer process
const script = document.createElement('script');
const port = process.env.PORT || 1212;

script.src = (process.env.HOT)
? 'http://localhost:' + port + '/dist/issueForm-bundle.js'
: './dist/issueForm-bundle.js';

// @HACK: Writing the script path should be done
// with HtmlWebpackPlugin
document.body.appendChild(script);
}
</script>
</body>
</html>
12 changes: 12 additions & 0 deletions app/issueForm.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// @flow
import React from 'react';
import {
render,
} from 'react-dom';

import IssueForm from './containers/Popups/IssueForm/IssueForm';

render(
<IssueForm />,
document.getElementById('root') || document.createElement('div'),
);
Loading

0 comments on commit c2d3a2f

Please sign in to comment.