Skip to content

Commit

Permalink
Add the ability to customize app name (#379)
Browse files Browse the repository at this point in the history
  • Loading branch information
czgu authored Jan 19, 2021
1 parent ee1b141 commit 727e764
Show file tree
Hide file tree
Showing 29 changed files with 169 additions and 133 deletions.
10 changes: 10 additions & 0 deletions .storybook/webpack.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const postcssPresetEnv = require('postcss-preset-env');
const path = require('path');
const webpack = require('webpack');

module.exports = async (config) => {
config.module.rules.push({
Expand Down Expand Up @@ -39,5 +40,14 @@ module.exports = async (config) => {
path.resolve('./querybook/webapp'),
];

config.plugins.push(
new webpack.DefinePlugin({
__VERSION__: JSON.stringify(require('../package.json').version),
__APPNAME__: JSON.stringify(
process.env.QUERYBOOK_APPNAME ?? 'Querybook'
),
})
);

return config;
};
19 changes: 19 additions & 0 deletions docs/admin_guide/custom_app_name.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
id: custom_app_name
title: Custom App Name
sidebar_label: Custom App Name
---

By default, the frontend website displays the application name as `Querybook`. However, you may want to use another name that aligns with your backend systems. This name change is for frontend display only and does not impact the backend configurations.

To do so, rebuild the Webpack files with the environment variable `QUERYBOOK_APPNAME`. For example, you can have a Dockerfile as such:

```Dockerfile
FROM querybook:latest

RUN QUERYBOOK_APPNAME=Example ./node_modules/.bin/webpack --env.NODE_ENV=production
```

The website served by this docker image will show "Welcome to Example" on the homepage with the browser title as "Example".

You can use any utf8 characters but it’s recommended to keep the length to be roughly shorter than 15 English characters to prevent text-overflow.
4 changes: 4 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ const config = {
rootDir: './querybook/webapp/',
modulePaths: ['<rootDir>'],
globalSetup: '<rootDir>/__tests__/setup/jest-global-setup.js',
globals: {
__VERSION__: '1.0.0',
__APPNAME__: 'Querybook',
},
};

module.exports = config;
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,7 @@ exports[`matches enzyme snapshots matches snapshot - size 1`] = `
<span
className="querybook-wordmark"
>
<span
className="querybook-title-first-part"
>
Query
</span>
<span
className="querybook-title-last-part"
>
book
</span>
Querybook
</span>
</styled.span>
`;
Expand All @@ -28,38 +19,20 @@ exports[`matches enzyme snapshots matches snapshot 1`] = `
<span
className="querybook-wordmark"
>
<span
className="querybook-title-first-part"
>
Query
</span>
<span
className="querybook-title-last-part"
>
book
</span>
Querybook
</span>
</styled.span>
`;

exports[`matches test renderer snapshot serializes the styles 1`] = `
<span
className="sc-bdfBwQ krGXPh"
className="sc-bdfBwQ fCJyE"
size={2}
>
<span
className="querybook-wordmark"
>
<span
className="querybook-title-first-part"
>
Query
</span>
<span
className="querybook-title-last-part"
>
book
</span>
Querybook
</span>
</span>
`;
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { IconButton } from 'ui/Button/IconButton';

import './AdminAppEntitySidebar.scss';
import { QuerybookLogo } from 'ui/QuerybookLogo/QuerybookLogo';
import { getAppName } from 'lib/utils/global';

interface IAdminAppEntitySidebarProps {
selectedEntity: AdminEntity;
Expand Down Expand Up @@ -70,12 +71,11 @@ export const AdminAppEntitySidebar: React.FunctionComponent<IAdminAppEntitySideb
>
<IconButton
icon="log-out"
tooltip="Back to Querybook"
tooltipPos="right"
active={false}
/>
<span className="AdminAppEntitySidebar-title">
Back to Querybook
Back to {getAppName()}
</span>
</div>
</div>
Expand Down
27 changes: 0 additions & 27 deletions querybook/webapp/components/App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,12 @@ import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { Provider } from 'react-redux';

import {
IColumnStatsAnalyzer,
IColumnDetector,
IColumnTransformer,
} from 'lib/query-result/types';
import { AppRouter } from 'components/AppRouter/AppRouter';
import { ConfirmationManager } from 'components/ConfirmationManager/ConfirmationManager';
import { ToastManager } from 'ui/ToastManager/ToastManager';

import { reduxStore } from 'redux/store';

// TODO: decouple this with App.tsx
declare global {
/* eslint-disable @typescript-eslint/naming-convention */
interface Window {
reduxStore?: typeof reduxStore;
receiveChildMessage?: () => void;

// Web Plugin Variables
NO_ENVIRONMENT_MESSAGE?: string;
CUSTOM_LANDING_PAGE?: {
// Two modes of custom landing page
// replace: replace the entire landing page with custom content
// not specified: add the custom content to the middle of the
// landing page
mode?: 'replace';
renderer: () => React.ReactElement;
};
CUSTOM_COLUMN_STATS_ANALYZERS?: IColumnStatsAnalyzer[];
CUSTOM_COLUMN_DETECTORS?: IColumnDetector[];
CUSTOM_COLUMN_TRANSFORMERS?: IColumnTransformer[];
}
}
// Make debugging easier
window.reduxStore = reduxStore;

Expand Down
5 changes: 3 additions & 2 deletions querybook/webapp/components/AppAdmin/AppAdmin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useSelector } from 'react-redux';
import { Route, Switch, useParams } from 'react-router-dom';

import history from 'lib/router-history';
import { getAppName } from 'lib/utils/global';
import { IStoreState } from 'redux/store/types';
import { AdminEntity } from './types';
import { useDataFetch } from 'hooks/useDataFetch';

import { AdminAppEntitySidebar } from 'components/AdminAppSidebar/AdminAppEntitySidebar';
Expand All @@ -25,6 +25,7 @@ import { FourOhThree } from 'ui/ErrorPage/FourOhThree';
import { Icon } from 'ui/Icon/Icon';
import { Sidebar } from 'ui/Sidebar/Sidebar';

import { AdminEntity } from './types';
import './AppAdmin.scss';

const ENTITY_SIDEBAR_WIDTH = 200;
Expand Down Expand Up @@ -122,7 +123,7 @@ export const AppAdmin: React.FunctionComponent = () => {
<div className="AdminLanding">
<div className="AdminLanding-top">
<div className="AdminLanding-title">
Welcome to the Querybook Admin App
Welcome to the {getAppName()} Admin App
</div>
<div className="AdminLanding-desc">
All your settings are here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from 'const/metastore';
import { navigateWithinEnv } from 'lib/utils/query-string';
import { generateFormattedDate } from 'lib/utils/datetime';
import { getAppName } from 'lib/utils/global';
import { titleize } from 'lib/utils';
import { getHumanReadableByteSize } from 'lib/utils/number';

Expand Down Expand Up @@ -135,7 +136,7 @@ export class DataTableViewOverview extends React.PureComponent<
<DataTableViewOverviewSection title="Meta info">
<div>
<p>
First created in Querybook at{' '}
First created in {getAppName()} at{' '}
{generateFormattedDate(table.created_at)}.
</p>
<p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect, useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';

import { getAppName } from 'lib/utils/global';
import { IStoreState, Dispatch } from 'redux/store/types';
import { fetchTopQueryUsersIfNeeded } from 'redux/dataSources/action';

Expand Down Expand Up @@ -41,7 +42,7 @@ export const DataTableViewQueryUsers: React.FC<{
const viewersDOM = loading ? (
<Loading />
) : !topQueryUsers?.length ? (
<div>No user has queried this table on Querybook.</div>
<div>No user has queried this table on {getAppName()}.</div>
) : (
<UserAvatarList
users={topQueryUsers.map((topQueryUser) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ILineageCollection,
} from 'const/metastore';
import { getWithinEnvUrl } from 'lib/utils/query-string';
import { getAppName } from 'lib/utils/global';
import { Loading } from 'ui/Loading/Loading';
import { Table } from 'ui/Table/Table';
import { CodeHighlight } from 'ui/CodeHighlight/CodeHighlight';
Expand Down Expand Up @@ -126,7 +127,7 @@ const DataJobMetadataInfo: React.FC<{
) {
const queryExecutionId = dataJobMetadata.job_info['query_execution_id'];
queryExecutionUrlRows.push({
name: `Created in Querybook`,
name: `Created in ${getAppName()}`,
value: (
<Link
to={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const InfoMenuRoute: React.FunctionComponent<RouteComponentProps> = ({
infoType === 'shortcut'
? 'Keyboard Shortcuts'
: infoType === 'tour'
? 'Querybook Tutorials'
? 'Tutorials'
: 'Frequently Asked Questions';

return isModal ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const UserSettingsMenuRoute: React.FunctionComponent<RouteComponentProps>
onHide={
isModalRoute ? history.goBack : () => navigateWithinEnv('/')
}
title="Querybook User Settings"
title="User Settings"
className="with-padding"
>
{contentDOM}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ import {
} from 'redux/environment/selector';
import { IStoreState, Dispatch } from 'redux/store/types';

import { EnvironmentAppRouter } from '../EnvironmentAppRouter/EnvironmentAppRouter';

import { getAppName } from 'lib/utils/global';
import { SetUp } from 'components/SetUp/SetUp';
import { Loading } from 'ui/Loading/Loading';
import { FourOhFour } from 'ui/ErrorPage/FourOhFour';
import { FourOhThree } from 'ui/ErrorPage/FourOhThree';

import { EnvironmentAppRouter } from '../EnvironmentAppRouter/EnvironmentAppRouter';

type DispatchProps = ReturnType<typeof mapDispatchToProps>;
type StateProps = ReturnType<typeof mapStateToProps>;
type IEnvironmentsRouterProps = DispatchProps &
Expand All @@ -39,7 +40,7 @@ interface IEnvironmentsRouterState {
const blank: React.FunctionComponent = () => {
const message =
window.NO_ENVIRONMENT_MESSAGE ??
'No Environment Available. Please contact Querybook Admin for more info.';
`No Environment Available. Please contact ${getAppName()} Admin for more info.`;
return <div className="empty-message">{message}</div>;
};

Expand Down
7 changes: 4 additions & 3 deletions querybook/webapp/components/Info/Tours.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Dispatch, IStoreState } from 'redux/store/types';
import { queryEngineSelector } from 'redux/queryEngine/selector';

import history from 'lib/router-history';
import { getAppName } from 'lib/utils/global';
import { getQueryEngineId } from 'lib/utils';
import { navigateWithinEnv } from 'lib/utils/query-string';

Expand Down Expand Up @@ -41,17 +42,17 @@ export const Tours: React.FunctionComponent = () => {
return (
<div className="Tours m12">
<Title subtitle className="mb12">
Welcome to the Querybook Tutorial!
Welcome to the {getAppName()} Tutorial!
</Title>
<Title subtitle size={5}>
Click on a card to start the tutorial.
</Title>
<div className="Tours-cards flex-center mv24">
<Card
title="Querybook Tour"
title={`${getAppName()} Tour`}
onClick={() => navigateWithinEnv('/?tour=true')}
>
General overview of Querybook functionalities
General overview of {getAppName()} functionalities
</Card>
<Card title="DataDoc Tour" onClick={handleDataDocTour}>
Overview of DataDoc functionalities
Expand Down
19 changes: 3 additions & 16 deletions querybook/webapp/components/InfoMenuButton/QuerybookVersion.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,4 @@
import React, { useEffect } from 'react';
import { useGlobalState } from 'hooks/redux/useGlobalState';
import ds from 'lib/datasource';
import React from 'react';
import { getAppVersion } from 'lib/utils/global';

export const QuerybookVersion: React.FC = () => {
const [version, setVersion] = useGlobalState('querybookVersion', null);

useEffect(() => {
if (version == null) {
ds.fetch<string>(`/version/`).then(({ data }) => {
setVersion(data);
});
}
}, []);

return <span>{version}</span>;
};
export const QuerybookVersion: React.FC = () => <span>{getAppVersion()}</span>;
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React, { useCallback, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';

import { titleize } from 'lib/utils';
import { getAppName } from 'lib/utils/global';

import { generateFormattedDate } from 'lib/utils/datetime';
import { fetchSystemStatus } from 'redux/queryEngine/action';
import { IStoreState } from 'redux/store/types';
Expand Down Expand Up @@ -78,7 +80,7 @@ export const QueryEngineStatusViewer: React.FC<IProps> = ({ engineId }) => {
infoMessage = `Your query may take longer than expected.`;
} else if (data.status === QueryEngineStatus.ERROR) {
messageType = 'error';
infoTitle = 'Querybook cannot connect to engine.';
infoTitle = `${getAppName()} cannot connect to engine.`;
infoMessage =
'Running queries on this engine will most likely result in failure.';
}
Expand Down
9 changes: 5 additions & 4 deletions querybook/webapp/components/QueryExecution/QueryError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@ import {
} from 'lib/sql-helper/sql-lexer';

import { IQueryEngine } from 'const/queryEngine';
import { getAppName } from 'lib/utils/global';
import { fetchQueryError } from 'redux/queryExecutions/action';
import { IStoreState } from 'redux/store/types';
import { queryEngineByIdEnvSelector } from 'redux/queryEngine/selector';

import { ErrorSuggestion } from '../DataDocStatementExecution/ErrorSuggestion';
import { ExecutedQueryCell, IHighlightRange } from './ExecutedQueryCell';
import { ErrorSuggestion } from 'components/DataDocStatementExecution/ErrorSuggestion';
import { Icon } from 'ui/Icon/Icon';
import { Message } from 'ui/Message/Message';
import { ShowMoreText } from 'ui/ShowMoreText/ShowMoreText';
import { Tabs } from 'ui/Tabs/Tabs';
import { Loader } from 'ui/Loader/Loader';

import { ExecutedQueryCell, IHighlightRange } from './ExecutedQueryCell';
import './QueryError.scss';
import { queryEngineByIdEnvSelector } from 'redux/queryEngine/selector';

interface IProps {
queryError: IQueryError;
Expand All @@ -36,7 +37,7 @@ interface IProps {
}

const queryErrorTypeToString: Record<number, string> = {
[QueryExecutionErrorType.INTERNAL]: 'Error from Querybook worker',
[QueryExecutionErrorType.INTERNAL]: `Error from ${getAppName()} worker`,
[QueryExecutionErrorType.ENGINE]: 'Error from Query Engine',
[QueryExecutionErrorType.SYNTAX]: 'Syntax Error',
};
Expand Down
Loading

0 comments on commit 727e764

Please sign in to comment.