Skip to content

Commit

Permalink
[Workplace Search] Update personal dashboard (#91136)
Browse files Browse the repository at this point in the history
* Remove "Add a private content source" sidebar link

* Update groupsSentence to cover different number of groups

Different cases:
1 group: You have access to the following sources through the group Default.
2 groups: You have access to the following sources through the groups Default and Engineering. (no comma before 'and')
3+ groups: You have access to the following sources through the groups Default, Marketing, and Engineering. (comma before 'and')

* Create PrivateSourcesLayout as a copy of Layout

In this commit PrivateSourcesLayout is a full copy of Layout.
It's going to be updated in later commits.

* Remove unused code from PrivateSourcesLayout

* Update read-only mode warning copy for end-users

* Move copy to constants file

* Add width styles to new sidebar

Also moved private_sources_layout styles to sources.scss file. Having separate files for that little amount of custom styles is unnecessary.

* Move top-level header to sidebar

* Add missing padding to sidebar

* Replace ViewContentHeader with ContentSection props

* Move variables over the components

* Remove unused classnames

* DRY out privateSourcesTable and privateSourcesEmptyState

by extracting privateSourcesSection that contains common markup.

* DRY out sharedSourcesTable and sharedSourcesEmptyState

by extracting sharedSourcesSection that contains common markup.

* Reorder code blocks inside the file

To match the order the components appear in UI

* Add newline to the groups enumeration sentence

So it looks good with any number of groups

* Update x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/private_sources_layout.tsx

Co-authored-by: Scotty Bollinger <scotty.bollinger@elastic.co>

Co-authored-by: Scotty Bollinger <scotty.bollinger@elastic.co>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
3 people authored Feb 11, 2021
1 parent 90049b0 commit 7da7b10
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
} from './routes';
import { SourcesRouter } from './views/content_sources';
import { SourceSubNav } from './views/content_sources/components/source_sub_nav';
import { PrivateSourcesLayout } from './views/content_sources/private_sources_layout';
import { ErrorState } from './views/error_state';
import { GroupsRouter } from './views/groups';
import { GroupSubNav } from './views/groups/components/group_sub_nav';
Expand Down Expand Up @@ -83,10 +84,9 @@ export const WorkplaceSearchConfigured: React.FC<InitialAppData> = (props) => {
{errorConnecting ? <ErrorState /> : <OverviewMVP />}
</Route>
<Route path={PERSONAL_SOURCES_PATH}>
{/* TODO: replace Layout with PrivateSourcesLayout (needs to be created) */}
<Layout navigation={<></>} restrictWidth readOnlyMode={readOnlyMode}>
<PrivateSourcesLayout restrictWidth readOnlyMode={readOnlyMode}>
<SourcesRouter />
</Layout>
</PrivateSourcesLayout>
</Route>
<Route path={SOURCES_PATH}>
<Layout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,3 +466,11 @@ export const UNDERSTAND_BUTTON = i18n.translate(
defaultMessage: 'I understand',
}
);

export const PRIVATE_DASHBOARD_READ_ONLY_MODE_WARNING = i18n.translate(
'xpack.enterpriseSearch.workplaceSearch.privateDashboard.readOnlyMode.warning',
{
defaultMessage:
'Workplace Search is currently available for search only, due to regular maintenance. Contact your system administrator for more information.',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@

export { Overview } from './components/overview';
export { SourcesRouter } from './sources_router';
export { PrivateSourcesLayout } from './private_sources_layout';
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import React, { useEffect } from 'react';
import { useActions, useValues } from 'kea';

import { EuiCallOut, EuiEmptyPrompt, EuiSpacer, EuiPanel } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';

import { LicensingLogic } from '../../../shared/licensing';
import { Loading } from '../../../shared/loading';
Expand All @@ -19,16 +19,11 @@ import { AppLogic } from '../../app_logic';
import noSharedSourcesIcon from '../../assets/share_circle.svg';
import { ContentSection } from '../../components/shared/content_section';
import { SourcesTable } from '../../components/shared/sources_table';
import { ViewContentHeader } from '../../components/shared/view_content_header';
import { ADD_SOURCE_PATH, getSourcesPath } from '../../routes';

import {
AND,
PRIVATE_LINK_TITLE,
PRIVATE_CAN_CREATE_PAGE_TITLE,
PRIVATE_VIEW_ONLY_PAGE_TITLE,
PRIVATE_VIEW_ONLY_PAGE_DESCRIPTION,
PRIVATE_CAN_CREATE_PAGE_DESCRIPTION,
PRIVATE_HEADER_TITLE,
PRIVATE_HEADER_DESCRIPTION,
PRIVATE_SHARED_SOURCES_TITLE,
Expand All @@ -41,17 +36,6 @@ import {
import { SourcesLogic } from './sources_logic';
import { SourcesView } from './sources_view';

// TODO: Remove this after links in Kibana sidenav
interface SidebarLink {
title: string;
path?: string;
disabled?: boolean;
iconType?: string;
otherActivePath?: string;
dataTestSubj?: string;
onClick?(): void;
}

export const PrivateSources: React.FC = () => {
const { hasPlatinumLicense } = useValues(LicensingLogic);
const { initializeSources, setSourceSearchability, resetSourcesState } = useActions(SourcesLogic);
Expand All @@ -71,16 +55,19 @@ export const PrivateSources: React.FC = () => {

if (dataLoading) return <Loading />;

const sidebarLinks = [] as SidebarLink[];
const hasConfiguredConnectors = serviceTypes.some(({ configured }) => configured);
const canAddSources = canCreatePersonalSources && hasConfiguredConnectors;
if (canAddSources) {
sidebarLinks.push({
title: PRIVATE_LINK_TITLE,
iconType: 'plusInCircle',
path: getSourcesPath(ADD_SOURCE_PATH, false),
});
}
const hasPrivateSources = privateContentSources?.length > 0;
const hasSharedSources = contentSources.length > 0;

const licenseCallout = (
<>
<EuiCallOut title={LICENSE_CALLOUT_TITLE} iconType="iInCircle">
<p>{LICENSE_CALLOUT_DESCRIPTION}</p>
</EuiCallOut>
<EuiSpacer />
</>
);

const headerAction = (
<EuiButtonTo
Expand All @@ -93,98 +80,77 @@ export const PrivateSources: React.FC = () => {
</EuiButtonTo>
);

const sourcesHeader = (
<ViewContentHeader
title={PRIVATE_HEADER_TITLE}
action={headerAction}
description={PRIVATE_HEADER_DESCRIPTION}
alignItems="flexStart"
/>
const privateSourcesEmptyState = (
<EuiPanel>
<EuiSpacer size="xxl" />
<EuiEmptyPrompt iconType="lock" title={<h2>{PRIVATE_EMPTY_TITLE}</h2>} />
<EuiSpacer size="xxl" />
</EuiPanel>
);

const privateSourcesTable = (
<ContentSection>
<SourcesTable
showDetails
onSearchableToggle={setSourceSearchability}
sources={privateContentSources}
/>
</ContentSection>
<SourcesTable
showDetails
onSearchableToggle={setSourceSearchability}
sources={privateContentSources}
/>
);

const privateSourcesEmptyState = (
<ContentSection className="zero-state__private-sources">
<EuiPanel className="euiPanel--inset">
<EuiSpacer size="xxl" />
<EuiEmptyPrompt iconType="lock" title={<h2>{PRIVATE_EMPTY_TITLE}</h2>} />
<EuiSpacer size="xxl" />
</EuiPanel>
const privateSourcesSection = (
<ContentSection
title={PRIVATE_HEADER_TITLE}
description={PRIVATE_HEADER_DESCRIPTION}
action={canAddSources && headerAction}
>
{hasPrivateSources ? privateSourcesTable : privateSourcesEmptyState}
</ContentSection>
);

const sharedSourcesEmptyState = (
<ContentSection className="zero-state__private-sources">
<EuiPanel className="euiPanel--inset">
<EuiSpacer size="xxl" />
<EuiEmptyPrompt
iconType={noSharedSourcesIcon}
title={<h2>{SHARED_EMPTY_TITLE}</h2>}
body={<p>{SHARED_EMPTY_DESCRIPTION}</p>}
/>
<EuiSpacer size="xxl" />
</EuiPanel>
</ContentSection>
<EuiPanel>
<EuiSpacer size="xxl" />
<EuiEmptyPrompt
iconType={noSharedSourcesIcon}
title={<h2>{SHARED_EMPTY_TITLE}</h2>}
body={<p>{SHARED_EMPTY_DESCRIPTION}</p>}
/>
<EuiSpacer size="xxl" />
</EuiPanel>
);

const hasPrivateSources = privateContentSources?.length > 0;
const privateSources = hasPrivateSources ? privateSourcesTable : privateSourcesEmptyState;
const sharedSourcesTable = (
<SourcesTable showDetails={false} isOrganization={false} sources={contentSources} />
);

const groupsSentence = `${groups.slice(0, groups.length - 1).join(', ')}, ${AND} ${groups.slice(
-1
)}`;
const groupsSentence =
groups.length === 1
? `${groups}`
: `${groups.slice(0, groups.length - 1).join(', ')}${
groups.length === 2 ? '' : ','
} ${AND} ${groups.slice(-1)}`;

const sharedSources = (
const sharedSourcesSection = (
<ContentSection
title={PRIVATE_SHARED_SOURCES_TITLE}
description={i18n.translate(
'xpack.enterpriseSearch.workplaceSearch.sources.private.privateShared.header.description',
{
defaultMessage:
'You have access to the following sources through the {groups, plural, one {group} other {groups}} {groupsSentence}.',
values: { groups: groups.length, groupsSentence },
}
)}
description={
hasSharedSources && (
<FormattedMessage
id="xpack.enterpriseSearch.workplaceSearch.sources.private.privateShared.header.description"
defaultMessage="You have access to the following sources through {newline}the {groups, plural, one {group} other {groups}} {groupsSentence}."
values={{ groups: groups.length, groupsSentence, newline: <br /> }}
/>
)
}
>
<SourcesTable showDetails={false} isOrganization={false} sources={contentSources} />
{hasSharedSources ? sharedSourcesTable : sharedSourcesEmptyState}
</ContentSection>
);

const licenseCallout = (
<>
<EuiCallOut title={LICENSE_CALLOUT_TITLE} iconType="iInCircle">
<p>{LICENSE_CALLOUT_DESCRIPTION}</p>
</EuiCallOut>
<EuiSpacer />
</>
);

const PAGE_TITLE = canCreatePersonalSources
? PRIVATE_CAN_CREATE_PAGE_TITLE
: PRIVATE_VIEW_ONLY_PAGE_TITLE;
const PAGE_DESCRIPTION = canCreatePersonalSources
? PRIVATE_CAN_CREATE_PAGE_DESCRIPTION
: PRIVATE_VIEW_ONLY_PAGE_DESCRIPTION;

const pageHeader = <ViewContentHeader title={PAGE_TITLE} description={PAGE_DESCRIPTION} />;

return (
<SourcesView>
{/* TODO: Figure out with design how to make this look better w/o 2 ViewContentHeaders */}
{pageHeader}
{hasPrivateSources && !hasPlatinumLicense && licenseCallout}
{canAddSources && sourcesHeader}
{canCreatePersonalSources && privateSources}
{contentSources.length > 0 ? sharedSources : sharedSourcesEmptyState}
{canCreatePersonalSources && privateSourcesSection}
{sharedSourcesSection}
</SourcesView>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React from 'react';

import { useValues } from 'kea';

import { EuiPage, EuiPageSideBar, EuiPageBody, EuiCallOut } from '@elastic/eui';

import { AppLogic } from '../../app_logic';
import { ViewContentHeader } from '../../components/shared/view_content_header';

import {
PRIVATE_DASHBOARD_READ_ONLY_MODE_WARNING,
PRIVATE_CAN_CREATE_PAGE_TITLE,
PRIVATE_VIEW_ONLY_PAGE_TITLE,
PRIVATE_VIEW_ONLY_PAGE_DESCRIPTION,
PRIVATE_CAN_CREATE_PAGE_DESCRIPTION,
} from './constants';

import './sources.scss';

interface LayoutProps {
restrictWidth?: boolean;
readOnlyMode?: boolean;
}

export const PrivateSourcesLayout: React.FC<LayoutProps> = ({
children,
restrictWidth,
readOnlyMode,
}) => {
const {
account: { canCreatePersonalSources },
} = useValues(AppLogic);

const PAGE_TITLE = canCreatePersonalSources
? PRIVATE_CAN_CREATE_PAGE_TITLE
: PRIVATE_VIEW_ONLY_PAGE_TITLE;
const PAGE_DESCRIPTION = canCreatePersonalSources
? PRIVATE_CAN_CREATE_PAGE_DESCRIPTION
: PRIVATE_VIEW_ONLY_PAGE_DESCRIPTION;

return (
<EuiPage className="enterpriseSearchLayout privateSourcesLayout">
<EuiPageSideBar className="enterpriseSearchLayout__sideBar privateSourcesLayout__sideBar">
<ViewContentHeader title={PAGE_TITLE} description={PAGE_DESCRIPTION} />
</EuiPageSideBar>
<EuiPageBody className="enterpriseSearchLayout__body" restrictWidth={restrictWidth}>
{readOnlyMode && (
<EuiCallOut
className="enterpriseSearchLayout__readOnlyMode"
color="warning"
iconType="lock"
title={PRIVATE_DASHBOARD_READ_ONLY_MODE_WARNING}
/>
)}
{children}
</EuiPageBody>
</EuiPage>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,16 @@
}
}
}

.privateSourcesLayout {
$sideBarWidth: $euiSize * 30;

left: $sideBarWidth;
width: calc(100% - #{$sideBarWidth});

&__sideBar {
padding: 32px 40px 40px;
width: $sideBarWidth;
margin-left: -$sideBarWidth;
}
}

0 comments on commit 7da7b10

Please sign in to comment.