Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ exports[`Applications index test snapshots loading 1`] = `
padding: 24px;
background-color: #fff;
border-radius: 8px 8px 0 0;
height: 100%;
}

.c2 {
Expand Down Expand Up @@ -976,6 +977,7 @@ exports[`Applications index test snapshots success 1`] = `
padding: 24px;
background-color: #fff;
border-radius: 8px 8px 0 0;
height: 100%;
}

.c2 {
Expand Down
1 change: 1 addition & 0 deletions ui-cra/src/components/Layout/ContentWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const contentCss = css`
padding: ${medium};
background-color: ${white};
border-radius: ${xs} ${xs} 0 0;
height: 100%;
`;

export const Content = styled.div<{ backgroundColor?: string }>`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ exports[`PipelineDetails snapshots renders 1`] = `
padding: 24px;
background-color: #fff;
border-radius: 8px 8px 0 0;
height: 100%;
}

.c2 {
Expand Down
44 changes: 44 additions & 0 deletions ui-cra/src/components/Secrets/SecretDetails/Events/EventsTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { DataTable } from '@weaveworks/weave-gitops';
import moment from 'moment';
import { Event } from '../../../../cluster-services/cluster_services.pb';
import { TableWrapper } from '../../../Shared';

export const EventsTable = ({ events }: { events: Event[] }) => {
return (
<TableWrapper id="events-list">
<DataTable
rows={events}
fields={[
{
label: 'Reason',
value: 'reason',
textSearchable: true,
},
{
label: 'Message',
value: (e: Event) => (
<span
style={{
whiteSpace: 'normal',
}}
>
{e.message}
</span>
),
maxWidth: 600,
},
{
label: 'Age',
value: (e: Event) => moment(e.timestamp).fromNow() || '--',
defaultSort: true,
sortValue: (e: Event) => {
const t = e.timestamp && new Date(e.timestamp);
// Invert the timestamp so the default sort shows the most recent first
return e.timestamp ? (Number(t) * -1).toString() : '';
},
},
]}
/>
</TableWrapper>
);
};
20 changes: 20 additions & 0 deletions ui-cra/src/components/Secrets/SecretDetails/Events/ListEvents.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Alert } from '@material-ui/lab';
import { LoadingPage } from '@weaveworks/weave-gitops';
import { ListEventsRequest } from '../../../../cluster-services/cluster_services.pb';
import { useListEvents } from '../../../../contexts/ProgressiveDelivery';
import { EventsTable } from './EventsTable';

type Props = ListEventsRequest;

const ListEvents = (props: Props) => {
const { error, data, isLoading } = useListEvents(props);
return (
<>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think if we can make use of WorkspaceTabsWrapper that we did in workspaces to use it here as well & maybe we can change the name to LoadingWrapper as it'll save us some duplicate code 🤔 ?

<WorkspaceTabsWrapper loading={isLoading} errorMessage={error?.message}>
      <TableWrapper id="...">
         <EventsTable events={data.events} />
         ...

{isLoading && <LoadingPage />}
{error && <Alert severity="error">{error.message}</Alert>}
{data?.events && <EventsTable events={data.events} />}
</>
);
};

export default ListEvents;
92 changes: 92 additions & 0 deletions ui-cra/src/components/Secrets/SecretDetails/SecretDetailsTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { RouterTab } from '@weaveworks/weave-gitops';
import { GetExternalSecretResponse } from '../../../cluster-services/cluster_services.pb';
import styled from 'styled-components';
import { generateRowHeaders, SectionRowHeader } from '../../RowHeader';
import { Routes } from '../../../utils/nav';
import { CustomSubRouterTabs } from '../../Workspaces/WorkspaceStyles';
import ListEvents from './Events/ListEvents';

const ListEventsWrapper = styled.div`
width: 100%;
`;
const DetailsHeadersWrapper = styled.div`
div {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it nested div > div to use it this way ?. If no, we can remove the div {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes i want to apply the style for the nested div div > div

margin-top: 0px !important;
}
`;

const SecretDetailsTabs = ({
clusterName,
namespace,
externalSecretName,
secretDetails,
}: {
clusterName: string;
namespace: string;
externalSecretName: string;
secretDetails: GetExternalSecretResponse;
}) => {
const path = Routes.SecretDetails;

const secretDetailsHeaders: Array<SectionRowHeader> = [
{
rowkey: 'External Secret',
value: externalSecretName,
},
{
rowkey: 'K8s Secret',
value: secretDetails.secretName,
},
{
rowkey: 'Cluster',
value: clusterName,
},
{
rowkey: 'Secret Store',
value: secretDetails.secretStore,
},
{
rowkey: 'Secret Store Type',
value: secretDetails.secretStoreType,
},
{
rowkey: 'Secret path',
value: secretDetails.secretPath,
},
{
rowkey: 'Property',
value: secretDetails.property,
},
{
rowkey: 'Version',
value: secretDetails.version,
},
];

return (
<div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dev not needed here as CustomSubRouterTabs wrap what we need to return

<CustomSubRouterTabs rootPath={`${path}/secretDetails`}>
<RouterTab name="Details" path={`${path}/secretDetails`}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we change secretDetails to just details, or it may breaks something ?

<DetailsHeadersWrapper>
{generateRowHeaders(secretDetailsHeaders)}
</DetailsHeadersWrapper>
</RouterTab>

<RouterTab name="Events" path={`${path}/events`}>
<ListEventsWrapper>
<ListEvents
involvedObject={{
name: externalSecretName,
namespace: namespace || '',
kind: 'ExternalSecret',
}}
clusterName={clusterName}
/>
</ListEventsWrapper>
</RouterTab>
</CustomSubRouterTabs>
</div>
);
};

export default SecretDetailsTabs;
62 changes: 62 additions & 0 deletions ui-cra/src/components/Secrets/SecretDetails/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useGetSecretDetails } from '../../../contexts/Secrets';
import { Routes } from '../../../utils/nav';
import { generateRowHeaders, SectionRowHeader } from '../../RowHeader';
import { ContentWrapper } from '../../Layout/ContentWrapper';
import { PageTemplate } from '../../Layout/PageTemplate';
import moment from 'moment';
import SecretDetailsTabs from './SecretDetailsTabs';

const SecretDetails = ({
externalSecretName,
clusterName,
namespace,
}: {
externalSecretName: string;
clusterName: string;
namespace: string;
}) => {
const { data: secretDetails, isLoading: isSecretDetailsLoading } =
useGetSecretDetails({
externalSecretName,
clusterName,
namespace,
});
const defaultHeaders: Array<SectionRowHeader> = [
{
rowkey: 'Status',
value:
secretDetails?.status === 'NotReady'
? 'Not Ready'
: secretDetails?.status,
},
{
rowkey: 'Last Updated',
value: moment(secretDetails?.timestamp).fromNow(),
},
];

console.log(secretDetails);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

console.log 😉

return (
<>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<> not needed here as well

<PageTemplate
documentTitle="Secrets"
path={[
{ label: 'Secrets', url: Routes.Secrets },
{ label: secretDetails?.externalSecretName || '' },
]}
>
<ContentWrapper loading={isSecretDetailsLoading}>
{generateRowHeaders(defaultHeaders)}
<SecretDetailsTabs
externalSecretName={externalSecretName}
clusterName={clusterName}
namespace={namespace}
secretDetails={secretDetails || {}}
/>
</ContentWrapper>
</PageTemplate>
</>
);
};

export default SecretDetails;
17 changes: 15 additions & 2 deletions ui-cra/src/components/Secrets/Table/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { FC } from 'react';
import {
DataTable,
formatURL,
KubeStatusIndicator,
Link,
} from '@weaveworks/weave-gitops';
import { TableWrapper } from '../../Shared';
import { ExternalSecretItem } from '../../../cluster-services/cluster_services.pb';
import moment from 'moment';
import { Routes } from '../../../utils/nav';

interface Props {
secrets: ExternalSecretItem[];
Expand All @@ -20,8 +23,18 @@ export const SecretsTable: FC<Props> = ({ secrets }) => {
fields={[
{
label: 'Name',
value: 'externalSecretName',
defaultSort: true,
value: (s: ExternalSecretItem) => (
<Link
to={formatURL(Routes.SecretDetails, {
externalSecretName: s.externalSecretName,
clusterName: s.clusterName,
namespace: s.namespace,
})}
data-secret-name={s.externalSecretName}
>
{s.externalSecretName}
</Link>
),
textSearchable: true,
sortValue: ({ externalSecretName }) => externalSecretName,
},
Expand Down
1 change: 1 addition & 0 deletions ui-cra/src/components/Workspaces/WorkspaceStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const useWorkspaceStyle = makeStyles(() =>
);
export const CustomSubRouterTabs = styled(SubRouterTabs)(props => ({
'.MuiTabs-root': {
marginTop:medium,
width: '100%',
'.MuiTab-root': {
minWidth: 'fit-content',
Expand Down
15 changes: 15 additions & 0 deletions ui-cra/src/contexts/Secrets/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
GetExternalSecretResponse,
ListExternalSecretsRequest,
ListExternalSecretsResponse,
ListExternalSecretStoresRequest,
ListExternalSecretStoresResponse,
} from '../../cluster-services/cluster_services.pb';
import { formatError } from '../../utils/formatters';
import { EnterpriseClientContext } from '../EnterpriseClient';
Expand Down Expand Up @@ -36,3 +38,16 @@ export function useGetSecretDetails(req: GetExternalSecretRequest) {
{ onError },
);
}

const GET_SECRET_STORE_QUERY_KEY = 'secret-store-details';

export function useGetSecretStoreDetails(req: ListExternalSecretStoresRequest) {
const { api } = useContext(EnterpriseClientContext);
const { setNotifications } = useNotifications();
const onError = (error: Error) => setNotifications(formatError(error));
return useQuery<ListExternalSecretStoresResponse, Error>(
[GET_SECRET_STORE_QUERY_KEY, req],
() => api.ListExternalSecretStores(req),
{ onError },
);
}
7 changes: 5 additions & 2 deletions ui-cra/src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { Routes } from './utils/nav';
import OAuthCallback from './components/GithubAuth/OAuthCallback';
import { GitProvider } from './api/gitauth/gitauth.pb';
import SecretsList from './components/Secrets';
import SecretDetails from './components/Secrets/SecretDetails';

function withSearchParams(Cmp: any) {
return ({ location: { search }, ...rest }: any) => {
Expand Down Expand Up @@ -252,9 +253,11 @@ const AppRoutes = () => {
path={Routes.WorkspaceDetails}
component={withSearchParams(WorkspaceDetails)}
/>

<Route exact path={Routes.Secrets} component={SecretsList} />

<Route
path={Routes.SecretDetails}
component={withSearchParams(SecretDetails)}
/>
<Route
path={Routes.TerraformDetail}
component={withSearchParams(TerraformObjectDetail)}
Expand Down
8 changes: 5 additions & 3 deletions ui-cra/src/utils/nav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export function getKindRoute(k: Kind | string): string {
}
}


export enum Routes {
Applications = '/applications',
AddApplication = '/applications/create',
Expand Down Expand Up @@ -59,8 +60,9 @@ export enum Routes {

Templates = '/templates',

Workspaces= '/workspaces',
WorkspaceDetails= '/workspaces/details',
Workspaces = '/workspaces',
WorkspaceDetails = '/workspaces/details',

Secrets= '/secrets',
Secrets = '/secrets',
SecretDetails = '/details'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/details can we change it /secrets/details or what do you think ?

}