airbnb/caravel

View on GitHub
superset-frontend/src/pages/ExecutionLogList/index.tsx

Summary

Maintainability
B
5 hrs
Test Coverage
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import { css, styled, t } from '@superset-ui/core';
import moment from 'moment';
import { useEffect, useMemo } from 'react';
import { Link, useParams } from 'react-router-dom';
import ListView from 'src/components/ListView';
import { Tooltip } from 'src/components/Tooltip';
import SubMenu from 'src/features/home/SubMenu';
import withToasts from 'src/components/MessageToasts/withToasts';
import { fDuration } from 'src/utils/dates';
import AlertStatusIcon from 'src/features/alerts/components/AlertStatusIcon';
import {
  useListViewResource,
  useSingleViewResource,
} from 'src/views/CRUD/hooks';
import { AlertObject, LogObject } from 'src/features/alerts/types';

const PAGE_SIZE = 25;

const StyledHeader = styled.div`
  ${({ theme }) => css`
    display: flex;
    flex-direction: row;

    a,
    Link {
      margin-left: ${theme.gridUnit * 4}px;
      font-size: ${theme.typography.sizes.s};
      font-weight: ${theme.typography.weights.normal};
      text-decoration: underline;
    }
  `}
`;

interface ExecutionLogProps {
  addDangerToast: (msg: string) => void;
  addSuccessToast: (msg: string) => void;
  isReportEnabled: boolean;
}

function ExecutionLog({
  addDangerToast,
  addSuccessToast,
  isReportEnabled,
}: ExecutionLogProps) {
  const { alertId }: any = useParams();
  const {
    state: { loading, resourceCount: logCount, resourceCollection: logs },
    fetchData,
  } = useListViewResource<LogObject>(
    `report/${alertId}/log`,
    t('log'),
    addDangerToast,
    false,
  );
  const {
    state: { loading: alertLoading, resource: alertResource },
    fetchResource,
  } = useSingleViewResource<AlertObject>(
    'report',
    t('reports'),
    addDangerToast,
  );

  useEffect(() => {
    if (alertId !== null && !alertLoading) {
      fetchResource(alertId);
    }
  }, [alertId]);

  const initialSort = [{ id: 'start_dttm', desc: true }];
  const columns = useMemo(
    () => [
      {
        Cell: ({
          row: {
            original: { state },
          },
        }: any) => (
          <AlertStatusIcon state={state} isReportEnabled={isReportEnabled} />
        ),
        accessor: 'state',
        Header: t('State'),
        size: 'xs',
        disableSortBy: true,
      },
      {
        Cell: ({
          row: {
            original: { uuid: executionId },
          },
        }: any) => (executionId ? executionId.slice(0, 6) : 'none'),
        accessor: 'uuid',
        Header: t('Execution ID'),
        size: 'xs',
        disableSortBy: true,
      },
      {
        Cell: ({
          row: {
            original: { scheduled_dttm: scheduledDttm },
          },
        }: any) =>
          moment(new Date(scheduledDttm)).format('YYYY-MM-DD hh:mm:ss a'),
        accessor: 'scheduled_dttm',
        Header: t('Scheduled at (UTC)'),
      },
      {
        Cell: ({
          row: {
            original: { start_dttm: startDttm },
          },
        }: any) => moment(new Date(startDttm)).format('YYYY-MM-DD hh:mm:ss a'),
        Header: t('Start at (UTC)'),
        accessor: 'start_dttm',
      },
      {
        Cell: ({
          row: {
            original: { start_dttm: startDttm, end_dttm: endDttm },
          },
        }: any) =>
          fDuration(new Date(startDttm).getTime(), new Date(endDttm).getTime()),
        Header: t('Duration'),
        disableSortBy: true,
      },
      {
        accessor: 'value',
        Header: t('Value'),
      },
      {
        accessor: 'error_message',
        Header: t('Error message'),
        Cell: ({
          row: {
            original: { error_message = '' },
          },
        }: any) => (
          <Tooltip title={error_message} placement="topLeft">
            <span>{error_message}</span>
          </Tooltip>
        ),
      },
    ],
    [isReportEnabled],
  );
  const path = `/${isReportEnabled ? 'report' : 'alert'}/list/`;
  const ALERT_TEXT = t('Alert');
  const REPORT_TEXT = t('Report');

  return (
    <>
      <SubMenu
        name={
          <StyledHeader>
            <span>
              {alertResource
                ? alertResource.type === 'Alert'
                  ? `${ALERT_TEXT}:`
                  : alertResource.type === 'Report'
                    ? `${REPORT_TEXT}:`
                    : null
                : null}{' '}
              {alertResource?.name}
            </span>
            <span>
              <Link to={path}>{t('Back to all')}</Link>
            </span>
          </StyledHeader>
        }
      />
      <ListView<LogObject>
        className="execution-log-list-view"
        columns={columns}
        count={logCount}
        data={logs}
        fetchData={fetchData}
        initialSort={initialSort}
        loading={loading}
        addDangerToast={addDangerToast}
        addSuccessToast={addSuccessToast}
        refreshData={() => {}}
        pageSize={PAGE_SIZE}
      />
    </>
  );
}

export default withToasts(ExecutionLog);