Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ux improvements
Browse files Browse the repository at this point in the history
GnsP committed Dec 8, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent f40ea5b commit afe28ce
Showing 16 changed files with 887 additions and 358 deletions.
Original file line number Diff line number Diff line change
@@ -26,14 +26,14 @@ import TableBody from 'components/shared/Table/TableBody';
import { useSelector } from 'react-redux';
import ActionsPopover from 'components/shared/ActionsPopover';
import { UnlinkSourceControlModal } from './UnlinkSourceControlModal';
import StyledPasswordWrapper from 'components/AbstractWidget/FormInputs/Password';
import { ISourceControlManagementConfig } from './types';
import SourceControlManagementForm from './SourceControlManagementForm';
import PrimaryTextButton from 'components/shared/Buttons/PrimaryTextButton';
import { getCurrentNamespace } from 'services/NamespaceStore';
import { getSourceControlManagement } from '../store/ActionCreator';
import Alert from 'components/shared/Alert';
import ButtonLoadingHoc from 'components/shared/Buttons/ButtonLoadingHoc';
import { useHistory } from 'react-router';

const PrimaryTextLoadingButton = ButtonLoadingHoc(PrimaryTextButton);

@@ -55,6 +55,8 @@ export const SourceControlManagement = () => {
const sourceControlManagementConfig: ISourceControlManagementConfig = useSelector(
(state) => state.sourceControlManagementConfig
);
const history = useHistory();

const toggleForm = () => {
setIsFormOpen(!isFormOpen);
};
@@ -85,11 +87,16 @@ export const SourceControlManagement = () => {
];

const validateConfigAndRedirect = () => {
setLoading(true);
const namespace = getCurrentNamespace();
if (sourceControlManagementConfig) {
history.push(`/ns/${namespace}/scm/sync`);
return;
}

setLoading(true);
getSourceControlManagement(namespace).subscribe(
() => {
window.location.href = `/ns/${namespace}/scm/sync`;
history.push(`/ns/${namespace}/scm/sync`);
},
(err) => {
setErrorMessage(err.message);
Original file line number Diff line number Diff line change
@@ -80,7 +80,7 @@ export const PullPipelineWizard = ({ isOpen, error, dispatch }: IPullPipelineWiz
toggle={() => dispatch({ type: 'TOGGLE_MODAL' })}
>
<Provider store={SourceControlManagementSyncStore}>
<RemotePipelineListView redirectOnSubmit={true} />
<RemotePipelineListView redirectOnSubmit={true} singlePipelineMode={true} />
</Provider>
</StandardModal>
</>
Original file line number Diff line number Diff line change
@@ -14,11 +14,19 @@
* the License.
*/

import React from 'react';
import { Checkbox, Table, TableBody, TableCell, TableRow, TableHead } from '@material-ui/core';
import React, { useState } from 'react';
import {
Checkbox,
Table,
TableBody,
TableCell,
TableRow,
TableHead,
TableSortLabel,
} from '@material-ui/core';
import InfoIcon from '@material-ui/icons/Info';
import { setSelectedPipelines } from '../store/ActionCreator';
import { IRepositoryPipeline } from '../types';
import { IRepositoryPipeline, TSyncStatusFilter } from '../types';
import T from 'i18n-react';
import StatusButton from 'components/StatusButton';
import { SUPPORT } from 'components/StatusButton/constants';
@@ -30,34 +38,45 @@ import {
StyledFixedWidthCell,
StyledPopover,
} from '../styles';
import { compareSyncStatus, filterOnSyncStatus, stableSort } from '../helpers';
import LoadingSVG from 'components/shared/LoadingSVG';

const PREFIX = 'features.SourceControlManagement.table';

interface IRepositoryPipelineTableProps {
localPipelines: IRepositoryPipeline[];
selectedPipelines: string[];
showFailedOnly: boolean;
enableMultipleSelection?: boolean;
multiPushEnabled?: boolean;
disabled?: boolean;
syncStatusFilter?: TSyncStatusFilter;
}

export const LocalPipelineTable = ({
localPipelines,
selectedPipelines,
showFailedOnly,
enableMultipleSelection = false,
multiPushEnabled = false,
disabled = false,
syncStatusFilter = 'all',
}: IRepositoryPipelineTableProps) => {
const isSelected = (name: string) => selectedPipelines.indexOf(name) !== -1;
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('asc');

const filteredPipelines = filterOnSyncStatus(localPipelines, syncStatusFilter);
const filteredPipelineNames = filteredPipelines.map((pipeline) => pipeline.name);
const selectedPipelinesSet = new Set(selectedPipelines);
const isAllFilteredPipelinesSelected = filteredPipelineNames.reduce((acc, pipelineName) => {
return acc && selectedPipelinesSet.has(pipelineName);
}, true);

const handleSelectAllClick = (event: React.ChangeEvent<HTMLInputElement>) => {
if (disabled) {
return;
}

if (event.target.checked) {
const allSelected = localPipelines.map((pipeline) => pipeline.name);
setSelectedPipelines(allSelected);
setSelectedPipelines(filteredPipelineNames);
return;
}
setSelectedPipelines([]);
@@ -68,7 +87,7 @@ export const LocalPipelineTable = ({
return;
}

if (enableMultipleSelection) {
if (multiPushEnabled) {
handleMultipleSelection(name);
return;
}
@@ -97,82 +116,117 @@ export const LocalPipelineTable = ({
setSelectedPipelines(newSelected);
};

const handleSort = () => {
const isAsc = sortOrder === 'asc';
setSortOrder(isAsc ? 'desc' : 'asc');
};

const syncStatusComparator = (a: IRepositoryPipeline, b: IRepositoryPipeline) => {
return sortOrder === 'desc' ? compareSyncStatus(a, b) : -compareSyncStatus(a, b);
};

return (
<TableBox>
<Table stickyHeader data-testid="local-pipelines-table">
<TableHead>
<TableRow>
<TableCell padding="checkbox">
{enableMultipleSelection && (
{multiPushEnabled && (
<Checkbox
color="primary"
indeterminate={
selectedPipelines.length > 0 && selectedPipelines.length < localPipelines.length
}
checked={selectedPipelines.length === localPipelines.length}
indeterminate={selectedPipelines.length > 0 && !isAllFilteredPipelinesSelected}
checked={isAllFilteredPipelinesSelected}
onChange={handleSelectAllClick}
disabled={disabled}
/>
)}
</TableCell>
<TableCell></TableCell>
<StyledTableCell>{T.translate(`${PREFIX}.pipelineName`)}</StyledTableCell>
<StyledFixedWidthCell>
<div>
{T.translate(`${PREFIX}.gitStatus`)}
<StyledPopover target={() => <InfoIcon />} showOn="Hover">
{T.translate(`${PREFIX}.gitStatusHelperText`)}
</StyledPopover>
</div>
</StyledFixedWidthCell>
{multiPushEnabled && (
<StyledFixedWidthCell>
<TableSortLabel active={true} direction={sortOrder} onClick={handleSort}>
{T.translate(`${PREFIX}.gitSyncStatus`)}
</TableSortLabel>
</StyledFixedWidthCell>
)}
{!multiPushEnabled && (
<StyledFixedWidthCell>
<div>
{T.translate(`${PREFIX}.gitStatus`)}
<StyledPopover target={() => <InfoIcon />} showOn="Hover">
{T.translate(`${PREFIX}.gitStatusHelperText`)}
</StyledPopover>
</div>
</StyledFixedWidthCell>
)}
</TableRow>
</TableHead>
<TableBody>
{localPipelines.map((pipeline: IRepositoryPipeline) => {
if (showFailedOnly && !pipeline.error) {
// only render pipelines that failed to push
return;
}
const isPipelineSelected = isSelected(pipeline.name);
return (
<StyledTableRow
hover
aria-checked={isPipelineSelected}
key={pipeline.name}
selected={isPipelineSelected}
onClick={(e) => handleClick(e, pipeline.name)}
data-testid={`local-${pipeline.name}`}
disabled={disabled}
>
<TableCell padding="checkbox">
<Checkbox color="primary" checked={isPipelineSelected} disabled={disabled} />
</TableCell>
<StatusCell
data-testid={
pipeline.status === SUPPORT.yes ? 'push-success-status' : 'push-failure-status'
}
{stableSort(filteredPipelines, syncStatusComparator).map(
(pipeline: IRepositoryPipeline) => {
if (showFailedOnly && !pipeline.error) {
// only render pipelines that failed to push
return;
}
const isPipelineSelected = isSelected(pipeline.name);
return (
<StyledTableRow
hover
aria-checked={isPipelineSelected}
key={pipeline.name}
selected={isPipelineSelected}
onClick={(e) => handleClick(e, pipeline.name)}
data-testid={`local-${pipeline.name}`}
disabled={disabled}
>
{pipeline.status !== null && (
<StatusButton
status={pipeline.status}
message={pipeline.status === SUPPORT.yes ? null : pipeline.error}
title={
pipeline.status === SUPPORT.yes
? T.translate(`${PREFIX}.pushSuccess`, {
pipelineName: pipeline.name,
}).toLocaleString()
: T.translate(`${PREFIX}.pushFail`).toLocaleString()
}
/>
<TableCell padding="checkbox">
<Checkbox color="primary" checked={isPipelineSelected} disabled={disabled} />
</TableCell>
<StatusCell
data-testid={
pipeline.status === SUPPORT.yes
? 'push-success-status'
: 'push-failure-status'
}
>
{pipeline.status !== null && (
<StatusButton
status={pipeline.status}
message={pipeline.status === SUPPORT.yes ? null : pipeline.error}
title={
pipeline.status === SUPPORT.yes
? T.translate(`${PREFIX}.pushSuccess`, {
pipelineName: pipeline.name,
}).toLocaleString()
: T.translate(`${PREFIX}.pushFail`).toLocaleString()
}
/>
)}
</StatusCell>
<StyledTableCell>{pipeline.name}</StyledTableCell>
{multiPushEnabled && (
<StyledFixedWidthCell>
{pipeline.syncStatus === undefined ||
pipeline.syncStatus === 'not_available' ? (
<LoadingSVG height="18px" />
) : pipeline.syncStatus === 'not_connected' ||
pipeline.syncStatus === 'out_of_sync' ? (
T.translate(`${PREFIX}.gitSyncStatusUnsynced`)
) : (
T.translate(`${PREFIX}.gitSyncStatusSynced`)
)}
</StyledFixedWidthCell>
)}
</StatusCell>
<StyledTableCell>{pipeline.name}</StyledTableCell>
<StyledFixedWidthCell>
{pipeline.fileHash ? T.translate(`${PREFIX}.connected`) : '--'}
</StyledFixedWidthCell>
</StyledTableRow>
);
})}
{!multiPushEnabled && (
<StyledFixedWidthCell>
{pipeline.fileHash ? T.translate(`${PREFIX}.connected`) : '--'}
</StyledFixedWidthCell>
)}
</StyledTableRow>
);
}
)}
</TableBody>
</Table>
</TableBox>
Loading

0 comments on commit afe28ce

Please sign in to comment.