Add a model for router and change
Also adds a change-service, which maintains the change model.
The new router model is maintained by gr-router, which will eventually
be moved and renamed to router-service.
Change-Id: I15fcf39d1de21dea975a687fb6efb6823d658c22
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
index c0b6074..2a607a7 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view.ts
@@ -39,7 +39,6 @@
import {getBaseUrl} from '../../../utils/url-util';
import {
GerritNav,
- GerritView,
GroupDetailView,
RepoDetailView,
} from '../../core/gr-navigation/gr-navigation';
@@ -66,6 +65,7 @@
import {ValueChangeDetail} from '../../shared/gr-dropdown-list/gr-dropdown-list';
import {GrJsApiInterface} from '../../shared/gr-js-api-interface/gr-js-api-interface-element';
import {appContext} from '../../../services/app-context';
+import {GerritView} from '../../../services/router/router-model';
const INTERNAL_GROUP_REGEX = /^[\da-f]{40}$/;
diff --git a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.js b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.js
index 15211cf..cac409d 100644
--- a/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.js
+++ b/polygerrit-ui/app/elements/admin/gr-admin-view/gr-admin-view_test.js
@@ -18,9 +18,10 @@
import '../../../test/common-test-setup-karma.js';
import './gr-admin-view.js';
import {dom} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {GerritNav, GerritView} from '../../core/gr-navigation/gr-navigation.js';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader.js';
import {stubBaseUrl} from '../../../test/test-utils.js';
+import {GerritView} from '../../../services/router/router-model.js';
const basicFixture = fixtureFromElement('gr-admin-view');
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
index 26368ec..973ccc8 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
@@ -25,7 +25,7 @@
import {PolymerElement} from '@polymer/polymer/polymer-element';
import {htmlTemplate} from './gr-change-list-view_html';
import {page} from '../../../utils/page-wrapper-utils';
-import {GerritNav, GerritView} from '../../core/gr-navigation/gr-navigation';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {customElement, property} from '@polymer/decorators';
import {AppElementParams} from '../../gr-app-types';
import {
@@ -41,6 +41,7 @@
import {ChangeListViewState} from '../../../types/types';
import {fireTitleChange} from '../../../utils/event-util';
import {appContext} from '../../../services/app-context';
+import {GerritView} from '../../../services/router/router-model';
const LookupQueryPatterns = {
CHANGE_ID: /^\s*i?[0-9a-f]{7,40}\s*$/i,
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
index f3ed408..0a87503 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
@@ -29,7 +29,6 @@
import {htmlTemplate} from './gr-dashboard-view_html';
import {
GerritNav,
- GerritView,
UserDashboard,
YOUR_TURN,
} from '../../core/gr-navigation/gr-navigation';
@@ -57,6 +56,7 @@
import {ChangeStarToggleStarDetail} from '../../shared/gr-change-star/gr-change-star';
import {DashboardViewState} from '../../../types/types';
import {firePageError, fireTitleChange} from '../../../utils/event-util';
+import {GerritView} from '../../../services/router/router-model';
const PROJECT_PLACEHOLDER_PATTERN = /\$\{project\}/g;
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
index 1fa24ba..1f5d519 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view_test.js
@@ -18,7 +18,8 @@
import '../../../test/common-test-setup-karma.js';
import './gr-dashboard-view.js';
import {isHidden} from '../../../test/test-utils.js';
-import {GerritNav, GerritView} from '../../core/gr-navigation/gr-navigation.js';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation.js';
+import {GerritView} from '../../../services/router/router-model.js';
import {changeIsOpen} from '../../../utils/change-util.js';
import {ChangeStatus} from '../../../constants/constants.js';
import {createAccountWithId} from '../../../test/test-data-generators.js';
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index df52323..950fbf3 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -55,7 +55,7 @@
import {GrEditConstants} from '../../edit/gr-edit-constants';
import {pluralize} from '../../../utils/string-util';
import {getComputedStyleValue} from '../../../utils/dom-util';
-import {GerritNav, GerritView} from '../../core/gr-navigation/gr-navigation';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {getPluginEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {RevisionInfo as RevisionInfoClass} from '../../shared/revision-info/revision-info';
@@ -152,6 +152,7 @@
import {fireAlert, fireEvent, firePageError} from '../../../utils/event-util';
import {KnownExperimentId} from '../../../services/flags/flags';
import {fireTitleChange} from '../../../utils/event-util';
+import {GerritView} from '../../../services/router/router-model';
const CHANGE_ID_ERROR = {
MISMATCH: 'mismatch',
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
index 5b4e65d..5cb84b4 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view_test.ts
@@ -30,7 +30,7 @@
import {GrEditConstants} from '../../edit/gr-edit-constants';
import {_testOnly_resetEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
import {getComputedStyleValue} from '../../../utils/dom-util';
-import {GerritNav, GerritView} from '../../core/gr-navigation/gr-navigation';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit';
import {EventType, PluginApi} from '../../plugins/gr-plugin-types';
@@ -102,6 +102,7 @@
import 'lodash/lodash';
import {ParsedChangeInfo} from '../../shared/gr-rest-api-interface/gr-reviewer-updates-parser';
import {ChangeComments} from '../../diff/gr-comment-api/gr-comment-api';
+import {GerritView} from '../../../services/router/router-model';
const pluginApi = _testOnly_initGerritPluginApi();
const fixture = fixtureFromElement('gr-change-view');
diff --git a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
index 8470611..83bf3ca 100644
--- a/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
+++ b/polygerrit-ui/app/elements/core/gr-navigation/gr-navigation.ts
@@ -16,23 +16,24 @@
*/
import {
BranchName,
+ ChangeConfigInfo,
ChangeInfo,
+ CommentLinks,
+ CommitId,
+ DashboardId,
+ EditPatchSetNum,
+ GroupId,
+ Hashtag,
+ NumericChangeId,
+ ParentPatchSetNum,
PatchSetNum,
RepoName,
- TopicName,
- GroupId,
- DashboardId,
- NumericChangeId,
- EditPatchSetNum,
- ChangeConfigInfo,
- CommitId,
- Hashtag,
- UrlEncodedCommentId,
- CommentLinks,
- ParentPatchSetNum,
ServerInfo,
+ TopicName,
+ UrlEncodedCommentId,
} from '../../../types/common';
import {ParsedChangeInfo} from '../../shared/gr-rest-api-interface/gr-reviewer-updates-parser';
+import {GerritView} from '../../../services/router/router-model';
// Navigation parameters object format:
//
@@ -396,22 +397,6 @@
url?: string;
}
-export enum GerritView {
- ADMIN = 'admin',
- AGREEMENTS = 'agreements',
- CHANGE = 'change',
- DASHBOARD = 'dashboard',
- DIFF = 'diff',
- DOCUMENTATION_SEARCH = 'documentation-search',
- EDIT = 'edit',
- GROUP = 'group',
- PLUGIN_SCREEN = 'plugin-screen',
- REPO = 'repo',
- ROOT = 'root',
- SEARCH = 'search',
- SETTINGS = 'settings',
-}
-
export enum GroupDetailView {
MEMBERS = 'members',
LOG = 'log',
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
index 0665cca..07045cd 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -26,6 +26,7 @@
import {encodeURL, getBaseUrl} from '../../../utils/url-util';
import {
DashboardSection,
+ GeneratedWebLink,
GenerateUrlChangeViewParameters,
GenerateUrlDashboardViewParameters,
GenerateUrlDiffViewParameters,
@@ -38,18 +39,16 @@
GenerateWebLinksFileParameters,
GenerateWebLinksParameters,
GenerateWebLinksPatchsetParameters,
- GerritView,
+ GerritNav,
+ GroupDetailView,
isGenerateUrlDiffViewParameters,
RepoDetailView,
WeblinkType,
- GroupDetailView,
- GerritNav,
- GeneratedWebLink,
} from '../gr-navigation/gr-navigation';
import {appContext} from '../../../services/app-context';
import {
- patchNumEquals,
convertToPatchSetNum,
+ patchNumEquals,
} from '../../../utils/patch-set-util';
import {customElement, property} from '@polymer/decorators';
import {assertNever} from '../../../utils/common-util';
@@ -64,10 +63,11 @@
} from '../../../types/common';
import {
AppElement,
- AppElementParams,
AppElementAgreementParam,
+ AppElementParams,
} from '../../gr-app-types';
import {LocationChangeEventDetail} from '../../../types/events';
+import {GerritView, updateState} from '../../../services/router/router-model';
const RoutePattern = {
ROOT: '/',
@@ -308,8 +308,13 @@
private readonly restApiService = appContext.restApiService;
+ private readonly changeService = appContext.changeService;
+
constructor() {
super();
+ // TODO: This is just an artificical dependdency such that the service is
+ // instantiated and its observables subscribed. Remove this later.
+ this.changeService.dontDoAnything();
}
start() {
@@ -320,6 +325,11 @@
}
_setParams(params: AppElementParams | GenerateUrlParameters) {
+ updateState(
+ params.view,
+ 'changeNum' in params ? params.changeNum : undefined,
+ 'patchNum' in params ? params.patchNum ?? undefined : undefined
+ );
this._appElement().params = params;
}
@@ -1535,8 +1545,7 @@
// Parameter order is based on the regex group number matched.
const params: GenerateUrlChangeViewParameters = {
project: ctx.params[0] as RepoName,
- // TODO(TS): remove as unknown
- changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ changeNum: Number(ctx.params[1]) as NumericChangeId,
basePatchNum: convertToPatchSetNum(ctx.params[4]),
patchNum: convertToPatchSetNum(ctx.params[6]),
view: GerritView.CHANGE,
@@ -1550,7 +1559,7 @@
_handleCommentRoute(ctx: PageContextWithQueryMap) {
const params: GenerateUrlDiffViewParameters = {
project: ctx.params[0] as RepoName,
- changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ changeNum: Number(ctx.params[1]) as NumericChangeId,
commentId: ctx.params[2] as UrlEncodedCommentId,
view: GerritView.DIFF,
commentLink: true,
@@ -1563,7 +1572,7 @@
// Parameter order is based on the regex group number matched.
const params: GenerateUrlDiffViewParameters = {
project: ctx.params[0] as RepoName,
- changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ changeNum: Number(ctx.params[1]) as NumericChangeId,
basePatchNum: convertToPatchSetNum(ctx.params[4]),
patchNum: convertToPatchSetNum(ctx.params[6]),
path: ctx.params[8],
@@ -1581,7 +1590,7 @@
_handleChangeLegacyRoute(ctx: PageContextWithQueryMap) {
// Parameter order is based on the regex group number matched.
const params: GenerateUrlLegacyChangeViewParameters = {
- changeNum: (ctx.params[0] as unknown) as NumericChangeId,
+ changeNum: Number(ctx.params[0]) as NumericChangeId,
basePatchNum: convertToPatchSetNum(ctx.params[3]),
patchNum: convertToPatchSetNum(ctx.params[5]),
view: GerritView.CHANGE,
@@ -1598,8 +1607,7 @@
_handleDiffLegacyRoute(ctx: PageContextWithQueryMap) {
// Parameter order is based on the regex group number matched.
const params: GenerateUrlLegacyDiffViewParameters = {
- // TODO(TS): remove "as unknown"
- changeNum: (ctx.params[0] as unknown) as NumericChangeId,
+ changeNum: Number(ctx.params[0]) as NumericChangeId,
basePatchNum: convertToPatchSetNum(ctx.params[2]),
patchNum: convertToPatchSetNum(ctx.params[4]),
path: ctx.params[5],
@@ -1620,7 +1628,7 @@
const project = ctx.params[0] as RepoName;
this._redirectOrNavigate({
project,
- changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ changeNum: Number(ctx.params[1]) as NumericChangeId,
// for edit view params, patchNum cannot be undefined
patchNum: convertToPatchSetNum(ctx.params[2])!,
path: ctx.params[3],
@@ -1635,8 +1643,7 @@
const project = ctx.params[0] as RepoName;
this._redirectOrNavigate({
project,
- // TODO(TS): remove "as unknown"
- changeNum: (ctx.params[1] as unknown) as NumericChangeId,
+ changeNum: Number(ctx.params[1]) as NumericChangeId,
patchNum: convertToPatchSetNum(ctx.params[3]),
view: GerritView.CHANGE,
edit: true,
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js
index cdec405..ff8f8df 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.js
@@ -1540,7 +1540,7 @@
]);
assertDataToParams({params: groups.slice(1)}, '_handleCommentRoute', {
project: 'gerrit',
- changeNum: '264833',
+ changeNum: 264833,
commentId: '00049681_f34fd6a9',
commentLink: true,
view: GerritNav.View.DIFF,
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
index 853d3c6..36317db 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.ts
@@ -40,7 +40,7 @@
Shortcut,
} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
import {pluralize} from '../../../utils/string-util';
-import {GerritNav, GerritView} from '../../core/gr-navigation/gr-navigation';
+import {GerritNav} from '../../core/gr-navigation/gr-navigation';
import {appContext} from '../../../services/app-context';
import {
computeAllPatchSets,
@@ -97,6 +97,7 @@
import {fireAlert, fireTitleChange} from '../../../utils/event-util';
import {KnownExperimentId} from '../../../services/flags/flags';
+import {GerritView} from '../../../services/router/router-model';
const ERR_REVIEW_STATUS = 'Couldn’t change file review status.';
const MSG_LOADING_BLAME = 'Loading blame...';
const MSG_LOADED_BLAME = 'Blame loaded';
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
index 1cb22e8..92494c2 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view_test.js
@@ -23,7 +23,7 @@
import {SPECIAL_PATCH_SET_NUM} from '../../../utils/patch-set-util.js';
import {Shortcut} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin.js';
import {_testOnly_findCommentById} from '../gr-comment-api/gr-comment-api.js';
-import {GerritView} from '../../core/gr-navigation/gr-navigation.js';
+import {GerritView} from '../../../services/router/router-model.js';
import {
createChange,
createRevisions,
diff --git a/polygerrit-ui/app/elements/gr-app-element.ts b/polygerrit-ui/app/elements/gr-app-element.ts
index feca35c..1d42bba 100644
--- a/polygerrit-ui/app/elements/gr-app-element.ts
+++ b/polygerrit-ui/app/elements/gr-app-element.ts
@@ -48,7 +48,7 @@
Shortcut,
SPECIAL_SHORTCUT,
} from '../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
-import {GerritNav, GerritView} from './core/gr-navigation/gr-navigation';
+import {GerritNav} from './core/gr-navigation/gr-navigation';
import {appContext} from '../services/app-context';
import {flush} from '@polymer/polymer/lib/utils/flush';
import {customElement, observe, property} from '@polymer/decorators';
@@ -78,6 +78,7 @@
} from '../types/events';
import {ViewState} from '../types/types';
import {EventType} from '../utils/event-util';
+import {GerritView} from '../services/router/router-model';
interface ErrorInfo {
text: string;
diff --git a/polygerrit-ui/app/elements/gr-app-types.ts b/polygerrit-ui/app/elements/gr-app-types.ts
index b05117f..4809562 100644
--- a/polygerrit-ui/app/elements/gr-app-types.ts
+++ b/polygerrit-ui/app/elements/gr-app-types.ts
@@ -16,7 +16,6 @@
*/
import {
GenerateUrlParameters,
- GerritView,
GroupDetailView,
RepoDetailView,
} from './core/gr-navigation/gr-navigation';
@@ -28,6 +27,7 @@
RepoName,
UrlEncodedCommentId,
} from '../types/common';
+import {GerritView} from '../services/router/router-model';
export interface AppElement extends HTMLElement {
params: AppElementParams | GenerateUrlParameters;
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
index e428a0a..e5e8537 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
@@ -63,11 +63,11 @@
} from '../../../types/common';
import {GrSshEditor} from '../gr-ssh-editor/gr-ssh-editor';
import {GrGpgEditor} from '../gr-gpg-editor/gr-gpg-editor';
-import {GerritView} from '../../core/gr-navigation/gr-navigation';
import {GrEmailEditor} from '../gr-email-editor/gr-email-editor';
import {CustomKeyboardEvent} from '../../../types/events';
import {fireAlert, fireTitleChange} from '../../../utils/event-util';
import {appContext} from '../../../services/app-context';
+import {GerritView} from '../../../services/router/router-model';
const PREFS_SECTION_FIELDS: Array<keyof PreferencesInput> = [
'changes_per_page',
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js
index a01edac..62e2a9e 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.js
@@ -19,7 +19,7 @@
import {getComputedStyleValue} from '../../../utils/dom-util.js';
import './gr-settings-view.js';
import {flush} from '@polymer/polymer/lib/legacy/polymer.dom.js';
-import {GerritView} from '../../core/gr-navigation/gr-navigation.js';
+import {GerritView} from '../../../services/router/router-model.js';
const basicFixture = fixtureFromElement('gr-settings-view');
const blankFixture = fixtureFromElement('div');
diff --git a/polygerrit-ui/app/services/app-context-init.ts b/polygerrit-ui/app/services/app-context-init.ts
index cb389bd4..290fba4 100644
--- a/polygerrit-ui/app/services/app-context-init.ts
+++ b/polygerrit-ui/app/services/app-context-init.ts
@@ -20,6 +20,7 @@
import {EventEmitter} from './gr-event-interface/gr-event-interface_impl';
import {Auth} from './gr-auth/gr-auth_impl';
import {GrRestApiInterface} from '../elements/shared/gr-rest-api-interface/gr-rest-api-interface';
+import {ChangeService} from './change/change-service';
type ServiceName = keyof AppContext;
type ServiceCreator<T> = () => T;
@@ -67,5 +68,6 @@
eventEmitter: () => new EventEmitter(),
authService: () => new Auth(appContext.eventEmitter),
restApiService: () => new GrRestApiInterface(appContext.authService),
+ changeService: () => new ChangeService(appContext.restApiService),
});
}
diff --git a/polygerrit-ui/app/services/app-context.ts b/polygerrit-ui/app/services/app-context.ts
index 720e489..869201e 100644
--- a/polygerrit-ui/app/services/app-context.ts
+++ b/polygerrit-ui/app/services/app-context.ts
@@ -19,6 +19,7 @@
import {ReportingService} from './gr-reporting/gr-reporting';
import {AuthService} from './gr-auth/gr-auth';
import {RestApiService} from './services/gr-rest-api/gr-rest-api';
+import {ChangeService} from './change/change-service';
export interface AppContext {
flagsService: FlagsService;
@@ -26,6 +27,7 @@
eventEmitter: EventEmitterService;
authService: AuthService;
restApiService: RestApiService;
+ changeService: ChangeService;
}
/**
diff --git a/polygerrit-ui/app/services/change/change-model.ts b/polygerrit-ui/app/services/change/change-model.ts
new file mode 100644
index 0000000..d02535c
--- /dev/null
+++ b/polygerrit-ui/app/services/change/change-model.ts
@@ -0,0 +1,106 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {PatchSetNum} from '../../types/common';
+import {BehaviorSubject, combineLatest, Observable} from 'rxjs';
+import {
+ map,
+ filter,
+ withLatestFrom,
+ distinctUntilChanged,
+} from 'rxjs/operators';
+import {routerPatchNum$, routerState$} from '../router/router-model';
+import {
+ computeAllPatchSets,
+ computeLatestPatchNum,
+} from '../../utils/patch-set-util';
+import {ParsedChangeInfo} from '../../elements/shared/gr-rest-api-interface/gr-reviewer-updates-parser';
+
+interface ChangeState {
+ change?: ParsedChangeInfo;
+}
+
+// TODO: Figure out how to best enforce immutability of all states. Use Immer?
+// Use DeepReadOnly?
+const initialState: ChangeState = {};
+
+const privateState$ = new BehaviorSubject(initialState);
+
+// Re-exporting as Observable so that you can only subscribe, but not emit.
+export const changeState$: Observable<ChangeState> = privateState$;
+
+// Must only be used by the change service or whatever is in control of this
+// model.
+export function updateState(change?: ParsedChangeInfo) {
+ privateState$.next({
+ ...privateState$.getValue(),
+ change,
+ });
+}
+
+/**
+ * If you depend on both, router and change state, then you want to filter out
+ * inconsistent state, e.g. router changeNum already updated, change not yet
+ * reset to undefined.
+ */
+export const changeAndRouterConsistent$ = combineLatest([
+ routerState$,
+ changeState$,
+]).pipe(
+ filter(([routerState, changeState]) => {
+ const changeNum = changeState.change?._number;
+ const routerChangeNum = routerState.changeNum;
+ return changeNum === undefined || changeNum === routerChangeNum;
+ }),
+ distinctUntilChanged()
+);
+
+export const change$ = changeState$.pipe(
+ map(changeState => changeState.change),
+ distinctUntilChanged()
+);
+
+export const changeNum$ = change$.pipe(
+ map(change => change?._number),
+ distinctUntilChanged()
+);
+
+export const latestPatchNum$ = change$.pipe(
+ map(change => computeLatestPatchNum(computeAllPatchSets(change))),
+ distinctUntilChanged()
+);
+
+/**
+ * Emits the current patchset number. If the route does not define the current
+ * patchset num, then this selector waits for the change to be defined and
+ * returns the number of the latest patchset.
+ *
+ * Note that this selector can emit a patchNum without the change being
+ * available!
+ *
+ * TODO: It would be good to assert/enforce somehow that currentPatchNum$ cannot
+ * emit 'PARENT'.
+ */
+export const currentPatchNum$: Observable<
+ PatchSetNum | undefined
+> = changeAndRouterConsistent$.pipe(
+ withLatestFrom(routerPatchNum$, latestPatchNum$),
+ map(([_, routerPatchNum, latestPatchNum]) => {
+ return routerPatchNum || latestPatchNum;
+ }),
+ distinctUntilChanged()
+);
diff --git a/polygerrit-ui/app/services/change/change-service.ts b/polygerrit-ui/app/services/change/change-service.ts
new file mode 100644
index 0000000..a510855
--- /dev/null
+++ b/polygerrit-ui/app/services/change/change-service.ts
@@ -0,0 +1,41 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {routerChangeNum$} from '../router/router-model';
+import {updateState} from './change-model';
+import {RestApiService} from '../services/gr-rest-api/gr-rest-api';
+import {switchMap, tap} from 'rxjs/operators';
+import {of, from} from 'rxjs';
+
+export class ChangeService {
+ private routerChangeNumEffect = routerChangeNum$.pipe(
+ switchMap(changeNum => {
+ if (!changeNum) return of(undefined);
+ return from(this.restApiService.getChangeDetail(changeNum));
+ }),
+ tap(change => {
+ updateState(change ?? undefined);
+ })
+ );
+
+ constructor(private readonly restApiService: RestApiService) {
+ this.routerChangeNumEffect.subscribe();
+ }
+
+ // TODO: Remove.
+ dontDoAnything() {}
+}
diff --git a/polygerrit-ui/app/services/router/router-model.ts b/polygerrit-ui/app/services/router/router-model.ts
new file mode 100644
index 0000000..b2d99480
--- /dev/null
+++ b/polygerrit-ui/app/services/router/router-model.ts
@@ -0,0 +1,76 @@
+/**
+ * @license
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {NumericChangeId, PatchSetNum} from '../../types/common';
+import {BehaviorSubject, Observable} from 'rxjs';
+import {distinctUntilChanged, map} from 'rxjs/operators';
+
+export enum GerritView {
+ ADMIN = 'admin',
+ AGREEMENTS = 'agreements',
+ CHANGE = 'change',
+ DASHBOARD = 'dashboard',
+ DIFF = 'diff',
+ DOCUMENTATION_SEARCH = 'documentation-search',
+ EDIT = 'edit',
+ GROUP = 'group',
+ PLUGIN_SCREEN = 'plugin-screen',
+ REPO = 'repo',
+ ROOT = 'root',
+ SEARCH = 'search',
+ SETTINGS = 'settings',
+}
+
+interface RouterState {
+ view?: GerritView;
+ changeNum?: NumericChangeId;
+ patchNum?: PatchSetNum;
+}
+
+// TODO: Figure out how to best enforce immutability of all states. Use Immer?
+// Use DeepReadOnly?
+const initialState: RouterState = {};
+
+const privateState$ = new BehaviorSubject<RouterState>(initialState);
+
+// Re-exporting as Observable so that you can only subscribe, but not emit.
+export const routerState$: Observable<RouterState> = privateState$;
+
+// Must only be used by the router service or whatever is in control of this
+// model.
+export function updateState(
+ view?: GerritView,
+ changeNum?: NumericChangeId,
+ patchNum?: PatchSetNum
+) {
+ privateState$.next({
+ ...privateState$.getValue(),
+ view,
+ changeNum,
+ patchNum,
+ });
+}
+
+export const routerChangeNum$ = routerState$.pipe(
+ map(state => state.changeNum),
+ distinctUntilChanged()
+);
+
+export const routerPatchNum$ = routerState$.pipe(
+ map(state => state.patchNum),
+ distinctUntilChanged()
+);
diff --git a/polygerrit-ui/app/test/test-data-generators.ts b/polygerrit-ui/app/test/test-data-generators.ts
index 1d07cf3..eed31b7 100644
--- a/polygerrit-ui/app/test/test-data-generators.ts
+++ b/polygerrit-ui/app/test/test-data-generators.ts
@@ -83,7 +83,6 @@
import {formatDate} from '../utils/date-util';
import {GetDiffCommentsOutput} from '../services/services/gr-rest-api/gr-rest-api';
import {AppElementChangeViewParams} from '../elements/gr-app-types';
-import {GerritView} from '../elements/core/gr-navigation/gr-navigation';
import {
EditRevisionInfo,
ParsedChangeInfo,
@@ -91,6 +90,7 @@
import {CommitInfoWithRequiredCommit} from '../elements/change/gr-change-metadata/gr-change-metadata';
import {WebLinkInfo} from '../types/diff';
import {UIComment, UIDraft} from '../utils/comment-util';
+import {GerritView} from '../services/router/router-model';
export function dateToTimestamp(date: Date): Timestamp {
const nanosecondSuffix = '.000000000';
diff --git a/polygerrit-ui/app/types/common.ts b/polygerrit-ui/app/types/common.ts
index 1628134..5574add 100644
--- a/polygerrit-ui/app/types/common.ts
+++ b/polygerrit-ui/app/types/common.ts
@@ -262,7 +262,6 @@
deletions: number; // Number of deleted lines
total_comment_count?: number;
unresolved_comment_count?: number;
- // TODO(TS): Use changed_id everywhere in code instead of (legacy) _number
_number: NumericChangeId;
owner: AccountInfo;
actions?: ActionNameToActionInfoMap;
diff --git a/polygerrit-ui/app/utils/admin-nav-util.ts b/polygerrit-ui/app/utils/admin-nav-util.ts
index 06f4e3a..b144313 100644
--- a/polygerrit-ui/app/utils/admin-nav-util.ts
+++ b/polygerrit-ui/app/utils/admin-nav-util.ts
@@ -16,7 +16,6 @@
*/
import {
GerritNav,
- GerritView,
RepoDetailView,
GroupDetailView,
} from '../elements/core/gr-navigation/gr-navigation';
@@ -28,6 +27,7 @@
} from '../types/common';
import {MenuLink} from '../elements/plugins/gr-admin-api/gr-admin-api';
import {hasOwnProperty} from './common-util';
+import {GerritView} from '../services/router/router-model';
const ADMIN_LINKS: NavLink[] = [
{
diff --git a/polygerrit-ui/app/utils/patch-set-util.ts b/polygerrit-ui/app/utils/patch-set-util.ts
index d063168..fda302b 100644
--- a/polygerrit-ui/app/utils/patch-set-util.ts
+++ b/polygerrit-ui/app/utils/patch-set-util.ts
@@ -198,11 +198,9 @@
* above
*/
export function computeAllPatchSets(
- change: ChangeInfo | ParsedChangeInfo
+ change: ChangeInfo | ParsedChangeInfo | undefined
): PatchSet[] {
- if (!change) {
- return [];
- }
+ if (!change) return [];
let patchNums: PatchSet[] = [];
if (change.revisions && Object.keys(change.revisions).length) {