Skip to content

Commit

Permalink
Add option to omit issue activities
Browse files Browse the repository at this point in the history
Retrieving past issue activities is the most time-consuming part of
retrieving all project plan data from YouTrack. This commit introduces
an option to omit the issue activities if they are not needed.

Release as 0.9.2.
  • Loading branch information
fschopp committed Jul 18, 2019
1 parent c70b338 commit d951a21
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 142 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Project planning for YouTrack. Reconstruct past project schedule from YouTrack activity log, and compute future schedule from YouTrack issue data plus a list of available contributors.
Library for project planning from YouTrack data. Retrieve past project schedule from activity log, and compute future schedule from unresolved issues and the available contributors.

## Status

Expand Down Expand Up @@ -31,7 +31,7 @@ Install with `npm install @fschopp/project-planning-for-you-track` or `yarn add
import {
ProgressCallback,
ProjectPlan,
reconstructProjectPlan,
retrieveProjectPlan,
YouTrackConfig,
} from '@fschopp/project-planning-for-you-track';
const baseUrl: string = 'https://<name>.myjetbrains.com/';
Expand All @@ -43,7 +43,7 @@ const youTrackConfig: YouTrackConfig = {
/* ... */
};
const promise: Promise<ProjectPlan> =
reconstructProjectPlan(baseUrl, youTrackConfig, progressUpdate);
retrieveProjectPlan(baseUrl, youTrackConfig, progressUpdate);
```

### Browser
Expand All @@ -56,7 +56,7 @@ Include the minified sources from the [jsDelivr CDN](https://www.jsdelivr.com/pa
Of course, the two occurrences of `...` need to be replaced by the current version and its corresponding [subresource integrity (SRI)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) hash. Then, in a subsequent script:
```javascript
/* baseUrl, youTrackConfig, and progressUpdate defined as above */
const promise = ProjectPlanningForYouTrack.reconstructProjectPlan(
const promise = ProjectPlanningForYouTrack.retrieveProjectPlan(
baseUrl, youTrackConfig, progressUpdate);
```

Expand Down
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@fschopp/project-planning-for-you-track",
"version": "0.9.2-SNAPSHOT",
"description": "Project planning for YouTrack. Reconstruct past project schedule from YouTrack activity log, and compute future schedule from YouTrack issue data plus a list of available contributors.",
"version": "0.9.2",
"description": "Library for project planning from YouTrack data. Retrieve past project schedule from activity log, and compute future schedule from unresolved issues and the available contributors.",
"keywords": [
"Gantt",
"YouTrack",
Expand Down Expand Up @@ -49,20 +49,20 @@
"@fschopp/project-planning-js": "^1.1.1"
},
"devDependencies": {
"@babel/core": "^7.4.5",
"@babel/preset-env": "^7.4.5",
"@types/jest": "^24.0.13",
"@babel/core": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@types/jest": "^24.0.15",
"babel-plugin-unassert": "^3.0.1",
"jest": "^24.8.0",
"parcel-bundler": "^1.12.3",
"rollup": "^1.13.1",
"rollup-plugin-babel": "^4.3.2",
"rollup": "^1.17.0",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-sourcemaps": "^0.4.2",
"rollup-plugin-terser": "^5.0.0",
"rollup-plugin-terser": "^5.1.1",
"ts-jest": "^24.0.2",
"tslint": "^5.17.0",
"tslint": "^5.18.0",
"typedoc": "^0.14.2",
"typescript": "^3.5.1"
"typescript": "^3.5.3"
},
"jest": {
"collectCoverageFrom": [
Expand Down
4 changes: 2 additions & 2 deletions src/demo/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
IssueActivity,
ProgressCallback,
ProjectPlan,
reconstructProjectPlan,
retrieveProjectPlan,
Schedule,
scheduleUnresolved,
SchedulingOptions,
Expand Down Expand Up @@ -342,7 +342,7 @@ async function computePastProjectPlanAndPrediction(baseUrl: string, youTrackConf
divProgressBar.setAttribute('aria-valuenow', rounded.toString());
divProgressBar.style.width = `${rounded}%`;
};
lastProjectPlan = await reconstructProjectPlan(baseUrl, youTrackConfig, progressUpdate);
lastProjectPlan = await retrieveProjectPlan(baseUrl, youTrackConfig, progressUpdate);
btnFuture.disabled = false;
} catch (exception) {
if (isFailure(exception)) {
Expand Down
59 changes: 43 additions & 16 deletions src/main/api-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,54 @@ export interface ProjectPlanWarning {
issueId?: string;
}

/**
* Options for retrieving YouTrack issue data and building a project plan.
*/
export interface RetrieveProjectPlanOptions {
/**
* Callback for progress updates.
*
* By default, there is no callback.
*/
progressCallback?: ProgressCallback;

/**
* Whether issue activities should be omitted, in which case {@link YouTrackIssue.issueActivities} will be the empty
* array for all issues.
*
* Retrieving past issue activities is the most time-consuming part of reconstructing a project plan. If the activity
* information is not required, this option should therefore be set to `true`.
*
* By default, this is `false`; that is, issue activities *are* retrieved.
*/
omitIssueActivities?: boolean;

/**
* Interval (in milliseconds) in which progress updates will be provided to the callback.
*
* By default, this is 200 milliseconds.
*/
progressUpdateIntervalMs?: number;

/**
* Number of elements per HTTP request to array resources. See also {@link httpGetAll}().
*
* By default, this is 100.
*/
restBatchSize?: number;
}

/**
* An issue with remaining effort or wait time.
*
* This interface contains all issue information relevant to its (future) scheduling.
*/
export interface SchedulableIssue {
/**
* Identifier of this issue.
* Identifier.
*
* This corresponds to property `idReadable` of YouTrack REST API entity
* [Issue](https://www.jetbrains.com/help/youtrack/standalone/api-entity-Issue.html).
*/
id: string;

Expand Down Expand Up @@ -165,7 +205,8 @@ export interface SchedulableIssue {
dependencies?: string[];

/**
* Identifier of the assignee of this issue.
* YouTrack-internal ID of the current assignee (YouTrack REST API entity name
* [User](https://www.jetbrains.com/help/youtrack/standalone/api-entity-User.html)), or empty string if none.
*/
assignee?: string;
}
Expand Down Expand Up @@ -408,14 +449,6 @@ export interface YouTrackConfig {
* interpret the extends clause of this class).
*/
export interface YouTrackIssue extends Required<SchedulableIssue> {
/**
* Identifier.
*
* This corresponds to property `idReadable` of YouTrack REST API entity
* [Issue](https://www.jetbrains.com/help/youtrack/standalone/api-entity-Issue.html).
*/
id: string;

/**
* The issue summary (that is, title).
*/
Expand Down Expand Up @@ -448,12 +481,6 @@ export interface YouTrackIssue extends Required<SchedulableIssue> {
*/
state: string;

/**
* YouTrack-internal ID of the current assignee (YouTrack REST API entity name
* [User](https://www.jetbrains.com/help/youtrack/standalone/api-entity-User.html)), or empty string if none.
*/
assignee: string;

/**
* Issue identifier (see {@link id}) of the parent issue, if any, or empty string if the issue has no parent.
*/
Expand Down
9 changes: 6 additions & 3 deletions src/main/scheduling.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import * as ProjectPlanningJs from '@fschopp/project-planning-js';
import {
Contributor, Failure,
IssueActivity, ProjectPlan,
Contributor,
Failure,
IssueActivity,
ProjectPlan,
SchedulableIssue,
Schedule,
SchedulingOptions, YouTrackIssue,
SchedulingOptions,
YouTrackIssue,
} from './api-types';
import { assignDefined, coalesce, deepClone, OnlyOptionals } from './util';

Expand Down
24 changes: 13 additions & 11 deletions src/main/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,29 @@ export type OnlyOptionals<T extends {}> = {[K in OptionalPropertyNames<T>]: Defi
*
* Note the differences to
* [`Object.assign()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign):
* - Only String properties are copied.
* - A property of the source value that has the value undefined is copied only if the property key is not yet in the
* - Only properties with `string` keys are copied.
* - A property of the source value that has the value `undefined` is copied only if the property key is not yet in the
* target. (The check is performed using the `in` operator.)
*
* @param target the target object
* @param source the source object
* @return the target object
*/
export function assignDefined<T extends {[key: string]: any}, U extends {[key: string]: any}>(
target: T, source: U): T & U {
target: T, source: U | undefined): T & U {
const typedTarget: T & U = target as T & U;
// Object.entries() returns “a given object's own enumerable string-keyed property [key, value] pairs,”
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
for (const [key, value] of Object.entries(source)) {
if (!(key in target) || value !== undefined) {
// Casting of key necessary for type soundness:
// https://github.com/microsoft/TypeScript/issues/31661#issuecomment-497474815
typedTarget[key as keyof U] = source[key];
if (source !== undefined) {
// Object.entries() returns “a given object's own enumerable string-keyed property [key, value] pairs,”
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries
for (const [key, value] of Object.entries(source)) {
if (!(key in target) || value !== undefined) {
// Casting of key necessary for type soundness:
// https://github.com/microsoft/TypeScript/issues/31661#issuecomment-497474815
typedTarget[key as keyof U] = source[key];
}
}
}
return target as T & U;
return typedTarget;
}

/**
Expand Down
Loading

0 comments on commit d951a21

Please sign in to comment.