export function SloListCompactView()

in x-pack/solutions/observability/plugins/slo/public/pages/slos/components/compact_view/slo_list_compact_view.tsx [60:477]


export function SloListCompactView({ sloList, loading, error }: Props) {
  const { services } = useKibana();
  const {
    application: { navigateToUrl },
    http: { basePath },
    uiSettings,
    share: {
      url: { locators },
    },
    triggersActionsUi: { ruleTypeRegistry, actionTypeRegistry },
  } = services;
  const spaceId = useSpace();

  const percentFormat = uiSettings.get('format:percent:defaultPattern');
  const sloIdsAndInstanceIds = sloList.map((slo) => [slo.id, slo.instanceId] as [string, string]);

  const { data: permissions } = usePermissions();
  const filteredRuleTypes = useGetFilteredRuleTypes();
  const queryClient = useQueryClient();
  const { triggerAction } = useActionModal();

  const [sloToAddRule, setSloToAddRule] = useState<SLOWithSummaryResponse | undefined>(undefined);

  const handleSavedRule = () => {
    queryClient.invalidateQueries({ queryKey: sloKeys.rules(), exact: false });
    setSloToAddRule(undefined);
  };

  const { data: activeAlertsBySlo } = useFetchActiveAlerts({ sloIdsAndInstanceIds });
  const { data: rulesBySlo } = useFetchRulesForSlo({
    sloIds: sloIdsAndInstanceIds.map((item) => item[0]),
  });
  const { isLoading: historicalSummaryLoading, data: historicalSummaries = [] } =
    useFetchHistoricalSummary({
      sloList,
    });

  const isRemote = (slo: SLOWithSummaryResponse) => !!slo.remote;
  const hasRemoteKibanaUrl = (slo: SLOWithSummaryResponse) =>
    !!slo.remote && slo.remote.kibanaUrl !== '';

  const buildActionName = (actionName: string) => (slo: SLOWithSummaryResponse) =>
    isRemote(slo) ? (
      <>
        {actionName}
        <EuiIcon
          type="popout"
          size="s"
          css={{
            marginLeft: '10px',
          }}
        />
      </>
    ) : (
      actionName
    );

  const actions: Array<DefaultItemAction<SLOWithSummaryResponse>> = [
    {
      type: 'icon',
      icon: 'inspect',
      name: i18n.translate('xpack.slo.item.actions.details', {
        defaultMessage: 'Details',
      }),
      description: i18n.translate('xpack.slo.item.actions.details', {
        defaultMessage: 'Details',
      }),
      onClick: (slo: SLOWithSummaryResponse) => {
        const sloDetailsUrl = basePath.prepend(
          paths.sloDetails(slo.id, slo.instanceId, slo.remote?.remoteName)
        );
        navigateToUrl(sloDetailsUrl);
      },
    },
    {
      type: 'icon',
      icon: 'pencil',
      name: buildActionName(
        i18n.translate('xpack.slo.item.actions.edit', {
          defaultMessage: 'Edit',
        })
      ),
      description: i18n.translate('xpack.slo.item.actions.edit', {
        defaultMessage: 'Edit',
      }),
      'data-test-subj': 'sloActionsEdit',
      enabled: (slo) =>
        (permissions?.hasAllWriteRequested && !isRemote(slo)) || hasRemoteKibanaUrl(slo),
      onClick: (slo: SLOWithSummaryResponse) => {
        const remoteEditUrl = createRemoteSloEditUrl(slo, spaceId);
        if (!!remoteEditUrl) {
          window.open(remoteEditUrl, '_blank');
        } else {
          navigateToUrl(basePath.prepend(paths.sloEdit(slo.id)));
        }
      },
    },
    {
      type: 'icon',
      icon: 'bell',
      name: i18n.translate('xpack.slo.item.actions.createRule', {
        defaultMessage: 'Create new alert rule',
      }),
      description: i18n.translate('xpack.slo.item.actions.createRule', {
        defaultMessage: 'Create new alert rule',
      }),
      'data-test-subj': 'sloActionsCreateRule',
      enabled: (slo: SLOWithSummaryResponse) =>
        !!permissions?.hasAllWriteRequested && !isRemote(slo),
      onClick: (slo: SLOWithSummaryResponse) => {
        setSloToAddRule(slo);
      },
    },
    {
      type: 'icon',
      icon: 'gear',
      name: i18n.translate('xpack.slo.item.actions.manageRules', {
        defaultMessage: 'Manage rules',
      }),
      description: i18n.translate('xpack.slo.item.actions.manageRules', {
        defaultMessage: 'Manage rules',
      }),
      'data-test-subj': 'sloActionsManageRules',
      enabled: (slo: SLOWithSummaryResponse) =>
        !!permissions?.hasAllWriteRequested && !isRemote(slo),
      onClick: (slo: SLOWithSummaryResponse) => {
        const locator = locators.get<RulesParams>(rulesLocatorID);
        locator?.navigate({ params: { sloId: slo.id } }, { replace: false });
      },
    },
    {
      type: 'icon',
      icon: (slo: SLOWithSummaryResponse) => (slo.enabled ? 'stop' : 'play'),
      name: (slo: SLOWithSummaryResponse) =>
        buildActionName(
          slo.enabled
            ? i18n.translate('xpack.slo.item.actions.disable', {
                defaultMessage: 'Disable',
              })
            : i18n.translate('xpack.slo.item.actions.enable', {
                defaultMessage: 'Enable',
              })
        )(slo),
      description: (slo: SLOWithSummaryResponse) =>
        slo.enabled
          ? i18n.translate('xpack.slo.item.actions.disable', {
              defaultMessage: 'Disable',
            })
          : i18n.translate('xpack.slo.item.actions.enable', {
              defaultMessage: 'Enable',
            }),
      'data-test-subj': 'sloActionsManage',
      enabled: (slo: SLOWithSummaryResponse) =>
        (permissions?.hasAllWriteRequested && !isRemote(slo)) || hasRemoteKibanaUrl(slo),
      onClick: (slo: SLOWithSummaryResponse) => {
        const isEnabled = slo.enabled;
        const remoteUrl = isEnabled
          ? createRemoteSloDisableUrl(slo, spaceId)
          : createRemoteSloEnableUrl(slo, spaceId);
        if (!!remoteUrl) {
          window.open(remoteUrl, '_blank');
        } else {
          triggerAction({ item: slo, type: isEnabled ? 'disable' : 'enable' });
        }
      },
    },
    {
      type: 'icon',
      icon: 'copy',
      name: buildActionName(
        i18n.translate('xpack.slo.item.actions.clone', {
          defaultMessage: 'Clone',
        })
      ),
      description: i18n.translate('xpack.slo.item.actions.clone', {
        defaultMessage: 'Clone',
      }),
      'data-test-subj': 'sloActionsClone',
      enabled: (slo: SLOWithSummaryResponse) =>
        (permissions?.hasAllWriteRequested && !isRemote(slo)) || hasRemoteKibanaUrl(slo),
      onClick: (slo: SLOWithSummaryResponse) => {
        triggerAction({ item: slo, type: 'clone' });
      },
    },
    {
      type: 'icon',
      icon: 'trash',
      name: buildActionName(
        i18n.translate('xpack.slo.item.actions.delete', {
          defaultMessage: 'Delete',
        })
      ),
      description: i18n.translate('xpack.slo.item.actions.delete', {
        defaultMessage: 'Delete',
      }),
      'data-test-subj': 'sloActionsDelete',
      enabled: (slo: SLOWithSummaryResponse) =>
        (permissions?.hasAllWriteRequested && !isRemote(slo)) || hasRemoteKibanaUrl(slo),
      onClick: (slo: SLOWithSummaryResponse) => {
        const remoteDeleteUrl = createRemoteSloDeleteUrl(slo, spaceId);
        if (!!remoteDeleteUrl) {
          window.open(remoteDeleteUrl, '_blank');
        } else {
          triggerAction({ item: slo, type: 'delete' });
        }
      },
    },
    {
      type: 'icon',
      icon: 'refresh',
      name: buildActionName(
        i18n.translate('xpack.slo.item.actions.reset', {
          defaultMessage: 'Reset',
        })
      ),
      description: i18n.translate('xpack.slo.item.actions.reset', {
        defaultMessage: 'Reset',
      }),
      'data-test-subj': 'sloActionsReset',
      enabled: (slo: SLOWithSummaryResponse) =>
        (permissions?.hasAllWriteRequested && !isRemote(slo)) || hasRemoteKibanaUrl(slo),
      onClick: (slo: SLOWithSummaryResponse) => {
        const remoteResetUrl = createRemoteSloResetUrl(slo, spaceId);
        if (!!remoteResetUrl) {
          window.open(remoteResetUrl, '_blank');
        } else {
          triggerAction({ item: slo, type: 'reset' });
        }
      },
    },
  ];

  const columns: Array<EuiBasicTableColumn<SLOWithSummaryResponse>> = [
    {
      field: 'status',
      name: 'Status',
      render: (_, slo: SLOWithSummaryResponse) => (
        <EuiFlexGroup direction="row" gutterSize="s">
          <SloStatusBadge slo={slo} />
          <SloStateBadge slo={slo} />
          <SloRemoteBadge slo={slo} />
        </EuiFlexGroup>
      ),
    },
    {
      field: 'alerts',
      name: 'Alerts',
      truncateText: true,
      width: '5%',
      render: (_, slo: SLOWithSummaryResponse) => (
        <>
          <SloRulesBadge
            rules={rulesBySlo?.[slo.id]}
            onClick={() => setSloToAddRule(slo)}
            isRemote={!!slo.remote}
          />
          <SloActiveAlertsBadge
            slo={slo}
            activeAlerts={activeAlertsBySlo.get(slo)}
            viewMode="compact"
          />
        </>
      ),
    },
    {
      field: 'name',
      name: 'Name',
      width: '15%',
      truncateText: { lines: 2 },
      'data-test-subj': 'sloItem',
      render: (_, slo: SLOWithSummaryResponse) => {
        const sloDetailsUrl = basePath.prepend(
          paths.sloDetails(slo.id, slo.instanceId, slo.remote?.remoteName)
        );
        return (
          <EuiToolTip position="top" content={slo.name} display="block">
            <EuiText size="s">
              <a data-test-subj="o11ySloListItemLink" href={sloDetailsUrl}>
                {slo.name}
              </a>
            </EuiText>
          </EuiToolTip>
        );
      },
    },
    {
      field: 'tags',
      name: 'Tags',
      render: (tags: string[]) => <SloTagsList tags={tags} color="default" />,
    },
    {
      field: 'instance',
      name: 'Instance',
      render: (_, slo: SLOWithSummaryResponse) => {
        const groups = [slo.groupBy].flat();
        return !groups.includes(ALL_VALUE) ? (
          <SLOGroupings slo={slo} direction="column" gutterSize={'none'} />
        ) : (
          <span>{NOT_AVAILABLE_LABEL}</span>
        );
      },
    },
    {
      field: 'objective',
      name: 'Objective',
      render: (_, slo: SLOWithSummaryResponse) => numeral(slo.objective.target).format('0.00%'),
    },
    {
      field: 'sli',
      name: 'SLI value',
      truncateText: true,
      render: (_, slo: SLOWithSummaryResponse) =>
        slo.summary.status === 'NO_DATA'
          ? NOT_AVAILABLE_LABEL
          : numeral(slo.summary.sliValue).format(percentFormat),
    },
    {
      field: 'historicalSli',
      name: 'Historical SLI',
      render: (_, slo: SLOWithSummaryResponse) => {
        const isSloFailed = ['VIOLATED', 'DEGRADING'].includes(slo.summary.status);
        const historicalSliData = formatHistoricalData(
          historicalSummaries.find(
            (historicalSummary) =>
              historicalSummary.sloId === slo.id && historicalSummary.instanceId === slo.instanceId
          )?.data,
          'sli_value'
        );
        return (
          <SloSparkline
            chart="line"
            id="sli_history"
            size="compact"
            state={isSloFailed ? 'error' : 'success'}
            data={historicalSliData}
            isLoading={historicalSummaryLoading}
          />
        );
      },
    },
    {
      field: 'errorBudgetRemaining',
      name: 'Budget remaining',
      truncateText: true,
      render: (_, slo: SLOWithSummaryResponse) =>
        slo.summary.status === 'NO_DATA'
          ? NOT_AVAILABLE_LABEL
          : numeral(slo.summary.errorBudget.remaining).format(percentFormat),
    },
    {
      field: 'historicalErrorBudgetRemaining',
      name: 'Historical budget remaining',
      render: (_, slo: SLOWithSummaryResponse) => {
        const isSloFailed = ['VIOLATED', 'DEGRADING'].includes(slo.summary.status);
        const errorBudgetBurnDownData = formatHistoricalData(
          historicalSummaries.find(
            (historicalSummary) =>
              historicalSummary.sloId === slo.id && historicalSummary.instanceId === slo.instanceId
          )?.data,
          'error_budget_remaining'
        );
        return (
          <SloSparkline
            chart="area"
            id="error_budget_burn_down"
            state={isSloFailed ? 'error' : 'success'}
            size="compact"
            data={errorBudgetBurnDownData}
            isLoading={historicalSummaryLoading}
          />
        );
      },
    },

    {
      name: 'Actions',
      actions,
      width: '5%',
    },
  ];

  if (!loading && !error && sloList.length === 0) {
    return <SloListEmpty />;
  }

  if (!loading && error) {
    return <SloListError />;
  }

  return (
    <>
      <EuiBasicTable<SLOWithSummaryResponse>
        items={sloList}
        columns={columns}
        loading={loading}
        noItemsMessage={loading ? LOADING_SLOS_LABEL : NO_SLOS_FOUND}
        tableLayout="auto"
      />
      {sloToAddRule ? (
        <RuleFormFlyout
          plugins={{ ...services, ruleTypeRegistry, actionTypeRegistry }}
          consumer={sloFeatureId}
          filteredRuleTypes={filteredRuleTypes}
          ruleTypeId={SLO_BURN_RATE_RULE_TYPE_ID}
          initialValues={{
            name: `${sloToAddRule.name} burn rate rule`,
            params: { sloId: sloToAddRule.id },
          }}
          onSubmit={handleSavedRule}
          onCancel={() => {
            setSloToAddRule(undefined);
          }}
          shouldUseRuleProducer
        />
      ) : null}
    </>
  );
}