RunAside.tsx 4.8 KB
Newer Older
P
Peter Pan 已提交
1
import Aside, {AsideSection} from '~/components/Aside';
2
import React, {FunctionComponent, useCallback, useMemo, useState} from 'react';
P
Peter Pan 已提交
3
import {ellipsis, em, rem, size} from '~/utils/style';
4 5 6 7 8 9 10 11 12 13

import Checkbox from '~/components/Checkbox';
import Field from '~/components/Field';
import {Run} from '~/types';
import RunningToggle from '~/components/RunningToggle';
import SearchInput from '~/components/SearchInput';
import styled from 'styled-components';
import uniqBy from 'lodash/uniqBy';
import {useTranslation} from '~/utils/i18n';

P
Peter Pan 已提交
14 15 16 17 18 19 20
const StyledAside = styled(Aside)`
    ${AsideSection}.run-section {
        flex: auto;
        overflow-x: hidden;
        overflow-y: auto;
        display: flex;
        flex-direction: column;
21

P
Peter Pan 已提交
22 23
        .run-select {
            flex: auto;
24 25 26 27 28
            overflow-x: hidden;
            overflow-y: auto;
            display: flex;
            flex-direction: column;

P
Peter Pan 已提交
29 30
            > * {
                flex: none;
31 32
            }

P
Peter Pan 已提交
33 34 35 36 37 38
            .search-input {
                margin-bottom: ${rem(15)};
            }

            .run-list {
                flex: auto;
39 40 41
                overflow-x: hidden;
                overflow-y: auto;

P
Peter Pan 已提交
42
                margin-top: ${rem(5)};
43

P
Peter Pan 已提交
44 45
                > div {
                    margin-top: ${rem(11)};
46

P
Peter Pan 已提交
47 48 49
                    > * {
                        width: 100%;
                    }
50

P
Peter Pan 已提交
51 52 53 54
                    .run-item {
                        display: flex;
                        align-items: center;
                        ${ellipsis()}
55

P
Peter Pan 已提交
56 57 58 59 60
                        > i {
                            display: inline-block;
                            ${size(em(12), em(12))};
                            border-radius: ${em(6)};
                            margin-right: ${em(8)};
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
                        }
                    }
                }
            }
        }
    }
`;

type RunAsideProps = {
    runs?: Run[];
    selectedRuns?: Run[];
    onChangeRuns?: (runs: Run[]) => unknown;
    running?: boolean;
    onToggleRunning?: (running: boolean) => unknown;
};

const RunAside: FunctionComponent<RunAsideProps> = ({
    runs,
    selectedRuns,
    onChangeRuns,
    running,
    onToggleRunning,
    children
}) => {
    const {t} = useTranslation('common');

    const [search, setSearch] = useState('');

    const selectAll = useMemo(() => runs?.length === selectedRuns?.length, [runs, selectedRuns]);
    const toggleSelectAll = useCallback(
        (toggle: boolean) => {
            onChangeRuns?.(toggle ? runs ?? [] : []);
        },
        [onChangeRuns, runs]
    );

    const filteredRuns = useMemo(() => (search ? runs?.filter(run => run.label.indexOf(search) >= 0) : runs) ?? [], [
        runs,
        search
    ]);

    const setSelectedRuns = useCallback(
        (run: Run, toggle) => {
            let selected = selectedRuns ?? [];
            if (toggle) {
                selected = uniqBy([...selected, run], r => r.label);
            } else {
                selected = selected.filter(r => r.label !== run.label);
            }
            onChangeRuns?.(selected);
        },
        [onChangeRuns, selectedRuns]
    );

P
Peter Pan 已提交
115 116 117 118 119
    const bottom = useMemo(
        () => <RunningToggle className="running-toggle" running={running} onToggle={onToggleRunning} />,
        [running, onToggleRunning]
    );

120
    return (
P
Peter Pan 已提交
121
        <StyledAside bottom={bottom}>
122
            {children}
P
Peter Pan 已提交
123
            <AsideSection className="run-section">
P
Peter Pan 已提交
124
                <Field className="run-select" label={t('common:select-runs')}>
125 126 127 128
                    <SearchInput
                        className="search-input"
                        value={search}
                        onChange={setSearch}
P
Peter Pan 已提交
129
                        placeholder={t('common:search-runs')}
130 131 132
                        rounded
                    />
                    <Checkbox value={selectAll} onChange={toggleSelectAll}>
P
Peter Pan 已提交
133
                        {t('common:select-all')}
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
                    </Checkbox>
                    <div className="run-list">
                        {filteredRuns.map((run, index) => (
                            <div key={index}>
                                <Checkbox
                                    value={selectedRuns?.map(r => r.label)?.includes(run.label)}
                                    title={run.label}
                                    onChange={value => setSelectedRuns(run, value)}
                                >
                                    <span className="run-item">
                                        <i style={{backgroundColor: run.colors[0]}}></i>
                                        {run.label}
                                    </span>
                                </Checkbox>
                            </div>
                        ))}
                    </div>
                </Field>
P
Peter Pan 已提交
152 153
            </AsideSection>
        </StyledAside>
154 155 156 157
    );
};

export default RunAside;