Add route for navigating to the topic page

Change-Id: Iadc651198c3642abc6adc081a889c52913086239
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 65ac9df..243af95 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -82,6 +82,8 @@
   ROOT: '/',
 
   DASHBOARD: /^\/dashboard\/(.+)$/,
+  // TODO(dhruvsri): remove /c once Change 322894 lands
+  TOPIC: /^\/c\/topic\/(\w+)\/?$/,
   CUSTOM_DASHBOARD: /^\/dashboard\/?$/,
   PROJECT_DASHBOARD: /^\/p\/(.+)\/\+\/dashboard\/(.+)/,
   LEGACY_PROJECT_DASHBOARD: /^\/projects\/(.+),dashboards\/(.+)/,
@@ -893,6 +895,8 @@
 
     this._mapRoute(RoutePattern.DASHBOARD, '_handleDashboardRoute');
 
+    this._mapRoute(RoutePattern.TOPIC, '_handleTopicRoute');
+
     this._mapRoute(
       RoutePattern.CUSTOM_DASHBOARD,
       '_handleCustomDashboardRoute'
@@ -1217,6 +1221,13 @@
     });
   }
 
+  _handleTopicRoute(data: PageContextWithQueryMap) {
+    this._setParams({
+      view: GerritView.TOPIC,
+      topic: data.params[0],
+    });
+  }
+
   /**
    * Handle custom dashboard routes.
    *
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 7f1a40b..bf71aec 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
@@ -214,6 +214,7 @@
       '_handleTagListFilterOffsetRoute',
       '_handleTagListFilterRoute',
       '_handleTagListOffsetRoute',
+      '_handleTopicRoute',
       '_handlePluginScreen',
     ];
 
@@ -1230,6 +1231,19 @@
       });
     });
 
+    suite('topic routes', () => {
+      test('_handleTopicRoute', () => {
+        const url = '/c/topic/random/';
+        const groups = url.match(_testOnly_RoutePattern.TOPIC);
+
+        const data = {params: groups.slice(1)};
+        assertDataToParams(data, '_handleTopicRoute', {
+          view: GerritView.TOPIC,
+          topic: 'random',
+        });
+      });
+    });
+
     suite('plugin routes', () => {
       test('_handlePluginListOffsetRoute', () => {
         const data = {params: {}};
diff --git a/polygerrit-ui/app/elements/gr-app-element.ts b/polygerrit-ui/app/elements/gr-app-element.ts
index 7f7749a..be26fcd 100644
--- a/polygerrit-ui/app/elements/gr-app-element.ts
+++ b/polygerrit-ui/app/elements/gr-app-element.ts
@@ -21,6 +21,7 @@
 import './documentation/gr-documentation-search/gr-documentation-search';
 import './change-list/gr-change-list-view/gr-change-list-view';
 import './change-list/gr-dashboard-view/gr-dashboard-view';
+import './topic/gr-topic-view';
 import './change/gr-change-view/gr-change-view';
 import './core/gr-error-manager/gr-error-manager';
 import './core/gr-keyboard-shortcuts-dialog/gr-keyboard-shortcuts-dialog';
@@ -140,6 +141,9 @@
   _showDashboardView?: boolean;
 
   @property({type: Boolean})
+  _showTopicView?: boolean;
+
+  @property({type: Boolean})
   _showChangeView?: boolean;
 
   @property({type: Boolean})
@@ -355,6 +359,7 @@
     this.$.errorView.classList.remove('show');
     this._showChangeListView = view === GerritView.SEARCH;
     this._showDashboardView = view === GerritView.DASHBOARD;
+    this._showTopicView = view === GerritView.TOPIC;
     this._showChangeView = view === GerritView.CHANGE;
     this._showDiffView = view === GerritView.DIFF;
     this._showSettingsView = view === GerritView.SETTINGS;
diff --git a/polygerrit-ui/app/elements/gr-app-element_html.ts b/polygerrit-ui/app/elements/gr-app-element_html.ts
index a1e6ac9..fcc742c 100644
--- a/polygerrit-ui/app/elements/gr-app-element_html.ts
+++ b/polygerrit-ui/app/elements/gr-app-element_html.ts
@@ -131,6 +131,9 @@
         view-state="{{_viewState.dashboardView}}"
       ></gr-dashboard-view>
     </template>
+    <template is="dom-if" if="[[_showTopicView]]" restamp="true">
+      <gr-topic-view params="[[params]]"></gr-topic-view>
+    </template>
     <!-- Note that the change view does not have restamp="true" set, because we
          want to re-use it as long as the change number does not change. -->
     <template id="dom-if-change-view" is="dom-if" if="[[_showChangeView]]">
diff --git a/polygerrit-ui/app/elements/gr-app-types.ts b/polygerrit-ui/app/elements/gr-app-types.ts
index 39070bd..8ff7734 100644
--- a/polygerrit-ui/app/elements/gr-app-types.ts
+++ b/polygerrit-ui/app/elements/gr-app-types.ts
@@ -46,6 +46,11 @@
   title?: string;
 }
 
+export interface AppElementTopicParams {
+  view: GerritView.TOPIC;
+  topic?: string;
+}
+
 export interface AppElementGroupParams {
   view: GerritView.GROUP;
   detail?: GroupDetailView;
@@ -141,6 +146,7 @@
 
 export type AppElementParams =
   | AppElementDashboardParams
+  | AppElementTopicParams
   | AppElementGroupParams
   | AppElementAdminParams
   | AppElementChangeViewParams
diff --git a/polygerrit-ui/app/elements/topic/gr-topic-view.ts b/polygerrit-ui/app/elements/topic/gr-topic-view.ts
index 5dcbe99..de5ee84 100644
--- a/polygerrit-ui/app/elements/topic/gr-topic-view.ts
+++ b/polygerrit-ui/app/elements/topic/gr-topic-view.ts
@@ -1,5 +1,9 @@
-import {customElement, property} from 'lit/decorators';
-import {LitElement, html} from 'lit';
+import {customElement, property, state} from 'lit/decorators';
+import {LitElement, html, PropertyValues} from 'lit';
+import {AppElementTopicParams} from '../gr-app-types';
+import {appContext} from '../../services/app-context';
+import {KnownExperimentId} from '../../services/flags/flags';
+import {GerritNav} from '../core/gr-navigation/gr-navigation';
 
 /**
  * @license
@@ -21,9 +25,30 @@
 @customElement('gr-topic-view')
 export class GrTopicView extends LitElement {
   @property()
+  params?: AppElementTopicParams;
+
+  @state()
   topic?: string;
 
+  private readonly flagsService = appContext.flagsService;
+
+  override updated(changedProperties: PropertyValues) {
+    if (changedProperties.has('params')) {
+      this.paramsChanged();
+    }
+  }
+
   override render() {
     return html`<div>Topic page for ${this.topic ?? ''}</div>`;
   }
+
+  paramsChanged() {
+    this.topic = this.params?.topic;
+    if (
+      !this.flagsService.isEnabled(KnownExperimentId.TOPICS_PAGE) &&
+      this.topic
+    ) {
+      GerritNav.navigateToSearchQuery(`topic:${this.topic}`);
+    }
+  }
 }
diff --git a/polygerrit-ui/app/services/router/router-model.ts b/polygerrit-ui/app/services/router/router-model.ts
index ae3d848..b8b385a 100644
--- a/polygerrit-ui/app/services/router/router-model.ts
+++ b/polygerrit-ui/app/services/router/router-model.ts
@@ -33,6 +33,7 @@
   ROOT = 'root',
   SEARCH = 'search',
   SETTINGS = 'settings',
+  TOPIC = 'topic',
 }
 
 export interface RouterState {