Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/static_src/reducers/sitewide.js b/static_src/reducers/sitewide.js
new file mode 100644
index 0000000..f7e20d7
--- /dev/null
+++ b/static_src/reducers/sitewide.js
@@ -0,0 +1,167 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import * as projectV0 from 'reducers/projectV0.js';
+import {combineReducers} from 'redux';
+import {createReducer, createRequestReducer} from './redux-helpers.js';
+import {createSelector} from 'reselect';
+import {prpcClient} from 'prpc-client-instance.js';
+import {SITEWIDE_DEFAULT_CAN, parseColSpec} from 'shared/issue-fields.js';
+
+// Actions
+const SET_PAGE_TITLE = 'SET_PAGE_TITLE';
+const SET_HEADER_TITLE = 'SET_HEADER_TITLE';
+export const SET_QUERY_PARAMS = 'SET_QUERY_PARAMS';
+
+// Async actions
+const GET_SERVER_STATUS_FAILURE = 'GET_SERVER_STATUS_FAILURE';
+const GET_SERVER_STATUS_START = 'GET_SERVER_STATUS_START';
+const GET_SERVER_STATUS_SUCCESS = 'GET_SERVER_STATUS_SUCCESS';
+
+/* State Shape
+{
+ bannerMessage: String,
+ bannerTime: Number,
+ pageTitle: String,
+ headerTitle: String,
+ queryParams: Object,
+ readOnly: Boolean,
+ requests: {
+ serverStatus: Object,
+ },
+}
+*/
+
+// Reducers
+const bannerMessageReducer = createReducer('', {
+ [GET_SERVER_STATUS_SUCCESS]:
+ (_state, action) => action.serverStatus.bannerMessage || '',
+});
+
+const bannerTimeReducer = createReducer(0, {
+ [GET_SERVER_STATUS_SUCCESS]:
+ (_state, action) => action.serverStatus.bannerTime || 0,
+});
+
+/**
+ * Handle state for the current document title.
+ */
+const pageTitleReducer = createReducer('', {
+ [SET_PAGE_TITLE]: (_state, {title}) => title,
+});
+
+const headerTitleReducer = createReducer('', {
+ [SET_HEADER_TITLE]: (_state, {title}) => title,
+});
+
+const queryParamsReducer = createReducer({}, {
+ [SET_QUERY_PARAMS]: (_state, {queryParams}) => queryParams || {},
+});
+
+const readOnlyReducer = createReducer(false, {
+ [GET_SERVER_STATUS_SUCCESS]:
+ (_state, action) => action.serverStatus.readOnly || false,
+});
+
+const requestsReducer = combineReducers({
+ serverStatus: createRequestReducer(
+ GET_SERVER_STATUS_START,
+ GET_SERVER_STATUS_SUCCESS,
+ GET_SERVER_STATUS_FAILURE),
+});
+
+export const reducer = combineReducers({
+ bannerMessage: bannerMessageReducer,
+ bannerTime: bannerTimeReducer,
+ readOnly: readOnlyReducer,
+ queryParams: queryParamsReducer,
+ pageTitle: pageTitleReducer,
+ headerTitle: headerTitleReducer,
+
+ requests: requestsReducer,
+});
+
+// Selectors
+export const sitewide = (state) => state.sitewide || {};
+export const bannerMessage =
+ createSelector(sitewide, (sitewide) => sitewide.bannerMessage);
+export const bannerTime =
+ createSelector(sitewide, (sitewide) => sitewide.bannerTime);
+export const queryParams =
+ createSelector(sitewide, (sitewide) => sitewide.queryParams || {});
+export const pageTitle = createSelector(
+ sitewide, projectV0.viewedConfig,
+ (sitewide, projectConfig) => {
+ const titlePieces = [];
+
+ // If a specific page specifies its own page title, add that
+ // to the beginning of the title.
+ if (sitewide.pageTitle) {
+ titlePieces.push(sitewide.pageTitle);
+ }
+
+ // If the user is viewing a project, add the project data.
+ if (projectConfig && projectConfig.projectName) {
+ titlePieces.push(projectConfig.projectName);
+ }
+
+ return titlePieces.join(' - ') || 'Monorail';
+ });
+export const headerTitle =
+ createSelector(sitewide, (sitewide) => sitewide.headerTitle);
+export const readOnly =
+ createSelector(sitewide, (sitewide) => sitewide.readOnly);
+
+/**
+ * Computes the issue list columns from the URL parameters.
+ */
+export const currentColumns = createSelector(
+ queryParams,
+ (params = {}) => params.colspec ? parseColSpec(params.colspec) : null);
+
+/**
+* Get the default canned query for the currently viewed project.
+* Note: Projects cannot configure a per-project default canned query,
+* so there is only a sitewide default.
+*/
+export const currentCan = createSelector(queryParams,
+ (params) => params.can || SITEWIDE_DEFAULT_CAN);
+
+/**
+ * Compute the current issue search query that the user has
+ * entered for a project, based on queryParams and the default
+ * project search.
+ */
+export const currentQuery = createSelector(
+ projectV0.defaultQuery,
+ queryParams,
+ (defaultQuery, params = {}) => {
+ // Make sure entering an empty search still works.
+ if (params.q === '') return params.q;
+ return params.q || defaultQuery;
+ });
+
+export const requests = createSelector(sitewide,
+ (sitewide) => sitewide.requests || {});
+
+// Action Creators
+export const setQueryParams =
+ (queryParams) => ({type: SET_QUERY_PARAMS, queryParams});
+
+export const setPageTitle = (title) => ({type: SET_PAGE_TITLE, title});
+
+export const setHeaderTitle = (title) => ({type: SET_HEADER_TITLE, title});
+
+export const getServerStatus = () => async (dispatch) => {
+ dispatch({type: GET_SERVER_STATUS_START});
+
+ try {
+ const serverStatus = await prpcClient.call(
+ 'monorail.Sitewide', 'GetServerStatus', {});
+
+ dispatch({type: GET_SERVER_STATUS_SUCCESS, serverStatus});
+ } catch (error) {
+ dispatch({type: GET_SERVER_STATUS_FAILURE, error});
+ }
+};