diff --git a/cypress/integration/preferences/notifications.ts b/cypress/integration/preferences/notifications.ts index 51c077f32a..26215be3cc 100644 --- a/cypress/integration/preferences/notifications.ts +++ b/cypress/integration/preferences/notifications.ts @@ -24,17 +24,65 @@ describe("global subscription settings", () => { }); describe("user subscriptions table", () => { - it("shows all of a user's subscriptions and expands with details", () => { + beforeEach(() => { cy.visit(pageRoute); + }); + + it("shows all of a user's subscriptions and expands with details", () => { cy.dataCy("subscription-row").should("have.length", 3); cy.dataCy("regex-selectors").should("not.be.visible"); cy.dataCy("trigger-data").should("not.be.visible"); - cy.get("tr button").first().click(); + cy.dataCy("subscription-row") + .eq(0) + .within(() => { + cy.get("button").first().click(); + }); cy.dataCy("regex-selectors").should("be.visible"); cy.dataCy("trigger-data").should("not.be.visible"); - cy.get("tr button").last().click(); + cy.dataCy("subscription-row") + .eq(2) + .within(() => { + cy.get("button").first().click(); + }); cy.dataCy("regex-selectors").should("be.visible"); cy.dataCy("trigger-data").should("be.visible"); }); + + it("Shows the selected count in the 'Delete' button", () => { + cy.dataCy("subscription-row") + .eq(0) + .within(() => { + cy.get("input[type=checkbox]").check({ force: true }); + }); + cy.dataCy("delete-some-button").contains("Delete (1)"); + + cy.get("thead").within(() => { + cy.get("input[type=checkbox]").check({ force: true }); + }); + cy.dataCy("delete-some-button").contains("Delete (3)"); + + cy.get("thead").within(() => { + cy.get("input[type=checkbox]").uncheck({ force: true }); + }); + cy.dataCy("delete-some-button").contains("Delete"); + cy.dataCy("delete-some-button").should( + "have.attr", + "aria-disabled", + "true" + ); + }); + + describe("Deleting subscriptions", { testIsolation: false }, () => { + it("Deletes a single subscription", () => { + cy.dataCy("subscription-row") + .eq(0) + .within(() => { + cy.get("input[type=checkbox]").check({ force: true }); + }); + cy.dataCy("delete-some-button").click(); + cy.validateToast("success", "Deleted 1 subscription."); + cy.dataCy("subscription-row").should("have.length", 2); + }); + }); }); diff --git a/package.json b/package.json index 030f02dba7..757829aaf4 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "@leafygreen-ui/menu": "20.0.0", "@leafygreen-ui/modal": "14.0.1", "@leafygreen-ui/number-input": "1.0.4", + "@leafygreen-ui/pagination": "1.0.7", "@leafygreen-ui/palette": "3.4.4", "@leafygreen-ui/popover": "11.0.1", "@leafygreen-ui/radio-box-group": "12.0.1", diff --git a/src/components/Table/BaseTable.tsx b/src/components/Table/BaseTable.tsx new file mode 100644 index 0000000000..08b28c7543 --- /dev/null +++ b/src/components/Table/BaseTable.tsx @@ -0,0 +1,51 @@ +import { + Cell, + ExpandedContent, + flexRender, + HeaderCell, + HeaderRow, + type LGRowData, + Row, + Table, + TableBody, + type TableProps, + TableHead, +} from "@leafygreen-ui/table/new"; + +type SpruceTableProps = { + "data-cy-row"?: string; + "data-cy-table"?: string; +}; + +export const BaseTable = ({ + "data-cy-row": dataCyRow, + "data-cy-table": dataCyTable, + table, + ...args +}: SpruceTableProps & TableProps) => ( + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + {flexRender(header.column.columnDef.header, header.getContext())} + + ))} + + ))} + + + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + {row.original.renderExpandedContent && } + + ))} + +
+); diff --git a/src/components/Table/LGFilters.tsx b/src/components/Table/LGFilters.tsx new file mode 100644 index 0000000000..28bfcff65d --- /dev/null +++ b/src/components/Table/LGFilters.tsx @@ -0,0 +1,46 @@ +import { LeafyGreenTableRow } from "@leafygreen-ui/table/new"; +import { TableFilterPopover } from "components/TablePopover"; +import { TreeDataEntry } from "components/TreeSelect"; + +type TreeSelectFilterProps = { + "data-cy"?: string; + tData: TreeDataEntry[]; + title: React.ReactNode; +}; + +export const getColumnTreeSelectFilterProps = ({ + "data-cy": dataCy, + tData, + title, +}: TreeSelectFilterProps) => ({ + header: ({ column }) => { + // Only present options that appear in the table + const options = tData.filter( + ({ value }) => !!column.getFacetedUniqueValues().get(value) + ); + return ( + <> + {title} + { + column.setFilterValue(value); + }} + data-cy={dataCy} + /> + + ); + }, + filterFn: ( + row: LeafyGreenTableRow, + columnId: string, + filterValue: string[] + ) => { + // If no filter is specified, show all rows + if (!filterValue.length) { + return true; + } + return filterValue.includes(row.getValue(columnId)); + }, +}); diff --git a/src/components/TreeSelect/TreeSelect.tsx b/src/components/TreeSelect/TreeSelect.tsx index b641e5706b..1f98db242d 100644 --- a/src/components/TreeSelect/TreeSelect.tsx +++ b/src/components/TreeSelect/TreeSelect.tsx @@ -136,12 +136,11 @@ const renderCheckboxesHelper = ({ state: string[]; tData: TreeDataEntry[]; }): void => { - const ParentCheckboxWrapper = getCheckboxWrapper(0); // push parent const onChangeFn = (): void => handleOnChange({ state, value: data.value, onChange, tData }); rows.push( - + - + ); // then examine children - const ChildCheckboxWrapper = getCheckboxWrapper(1); if (data.children) { data.children.forEach((child) => { const onChangeChildFn = (): void => handleOnChange({ state, value: child.value, onChange, tData }); rows.push( - + - + ); }); } @@ -317,15 +319,11 @@ const getAllValues = (tData: TreeDataEntry[]): string[] => return accum.concat([currNode.value]).concat(childrenValues); }, []); -const getCheckboxWrapper = ( - level: number -): React.VFC<{ children: React.ReactNode }> => styled.div` - padding-left: ${level}em; +const CheckboxWrapper = styled.div<{ level: number; isAll: boolean }>` + padding-left: ${({ level }) => `${level}em`}; padding-top: ${size.xxs}; padding-bottom: ${size.xxs}; - :first-of-type { - border-bottom: 1px solid ${gray.light2}; - } + ${({ isAll }) => isAll && `border-bottom: 1px solid ${gray.light2};`} `; const OptionsWrapper = styled.div` diff --git a/src/components/TreeSelect/__snapshots__/TreeSelect.stories.storyshot b/src/components/TreeSelect/__snapshots__/TreeSelect.stories.storyshot index 43ceb10e65..dd8a5050fd 100644 --- a/src/components/TreeSelect/__snapshots__/TreeSelect.stories.storyshot +++ b/src/components/TreeSelect/__snapshots__/TreeSelect.stories.storyshot @@ -7,7 +7,7 @@ exports[`storybook Storyshots components/TreeSelect Default 1`] = ` data-cy="tree-select-options" >
{ + switch (trigger) { + case TriggerType.FAMILY_OUTCOME: + return TriggerType.OUTCOME; + case TriggerType.FAMILY_FAILURE: + return TriggerType.FAILURE; + case TriggerType.FAMILY_SUCCESS: + return TriggerType.SUCCESS; + default: + return trigger; + } +}; + +export const triggerTreeData: TreeDataEntry[] = Object.entries( + triggerToCopy +).map(([key, value]) => ({ + title: value, + value: key, + key, +})); + export const allowedSelectors = new Set([ "object", "id", @@ -410,3 +452,20 @@ export const allowedSelectors = new Set([ "in-version", "in-build", ]); + +export const resourceTypeToCopy = { + [ResourceType.Build]: "Build", + [ResourceType.CommitQueue]: "Commit Queue", + [ResourceType.Host]: "Host", + [ResourceType.Patch]: "Patch", + [ResourceType.Task]: "Task", + [ResourceType.Version]: "Version", +}; + +export const resourceTypeTreeData: TreeDataEntry[] = Object.entries( + resourceTypeToCopy +).map(([key, value]) => ({ + title: value, + value: key, + key, +})); diff --git a/src/gql/generated/types.ts b/src/gql/generated/types.ts index 8f52561b40..cfb2504396 100644 --- a/src/gql/generated/types.ts +++ b/src/gql/generated/types.ts @@ -4057,6 +4057,15 @@ export type DeleteProjectMutation = { deleteProject: boolean; }; +export type DeleteSubscriptionsMutationVariables = Exact<{ + subscriptionIds: Array; +}>; + +export type DeleteSubscriptionsMutation = { + __typename?: "Mutation"; + deleteSubscriptions: number; +}; + export type DetachProjectFromRepoMutationVariables = Exact<{ projectId: Scalars["String"]; }>; diff --git a/src/gql/mutations/delete-subscriptions.graphql b/src/gql/mutations/delete-subscriptions.graphql new file mode 100644 index 0000000000..11d320d90d --- /dev/null +++ b/src/gql/mutations/delete-subscriptions.graphql @@ -0,0 +1,3 @@ +mutation DeleteSubscriptions($subscriptionIds: [String!]!) { + deleteSubscriptions(subscriptionIds: $subscriptionIds) +} diff --git a/src/gql/mutations/index.ts b/src/gql/mutations/index.ts index aa36f70f70..8043e181ce 100644 --- a/src/gql/mutations/index.ts +++ b/src/gql/mutations/index.ts @@ -11,6 +11,7 @@ import CREATE_PUBLIC_KEY from "./create-public-key.graphql"; import DEACTIVATE_STEPBACK_TASK from "./deactivate-stepback-task.graphql"; import DEFAULT_SECTION_TO_REPO from "./default-section-to-repo.graphql"; import DELETE_PROJECT from "./delete-project.graphql"; +import DELETE_SUBSCRIPTIONS from "./delete-subscriptions.graphql"; import DETACH_PROJECT_FROM_REPO from "./detach-project-from-repo.graphql"; import DETACH_VOLUME from "./detach-volume.graphql"; import EDIT_ANNOTATION_NOTE from "./edit-annotation-note.graphql"; @@ -64,6 +65,7 @@ export { DEACTIVATE_STEPBACK_TASK, DEFAULT_SECTION_TO_REPO, DELETE_PROJECT, + DELETE_SUBSCRIPTIONS, DETACH_PROJECT_FROM_REPO, DETACH_VOLUME, EDIT_ANNOTATION_NOTE, diff --git a/src/pages/preferences/preferencesTabs/NotificationsTab.tsx b/src/pages/preferences/preferencesTabs/NotificationsTab.tsx index 678a26a533..66c7812fd5 100644 --- a/src/pages/preferences/preferencesTabs/NotificationsTab.tsx +++ b/src/pages/preferences/preferencesTabs/NotificationsTab.tsx @@ -16,7 +16,6 @@ import { import { UPDATE_USER_SETTINGS } from "gql/mutations"; import { useUserSettings } from "hooks"; import { string } from "utils"; -import { ClearSubscriptionsCard } from "./notificationTab/ClearSubscriptionsCard"; import { NotificationField } from "./notificationTab/NotificationField"; import { UserSubscriptions } from "./notificationTab/UserSubscriptions"; @@ -116,7 +115,6 @@ export const NotificationsTab: React.VFC = () => { - ); }; diff --git a/src/pages/preferences/preferencesTabs/notificationTab/ClearSubscriptionsCard.tsx b/src/pages/preferences/preferencesTabs/notificationTab/ClearSubscriptions.tsx similarity index 68% rename from src/pages/preferences/preferencesTabs/notificationTab/ClearSubscriptionsCard.tsx rename to src/pages/preferences/preferencesTabs/notificationTab/ClearSubscriptions.tsx index eb39b0ba4f..6dfb09ce2b 100644 --- a/src/pages/preferences/preferencesTabs/notificationTab/ClearSubscriptionsCard.tsx +++ b/src/pages/preferences/preferencesTabs/notificationTab/ClearSubscriptions.tsx @@ -1,12 +1,8 @@ import { useState } from "react"; import { useMutation } from "@apollo/client"; -import styled from "@emotion/styled"; import Button, { Variant } from "@leafygreen-ui/button"; -import { Body } from "@leafygreen-ui/typography"; import { usePreferencesAnalytics } from "analytics"; import { ConfirmationModal } from "components/ConfirmationModal"; -import { SettingsCard } from "components/SettingsCard"; -import { size } from "constants/tokens"; import { useToastContext } from "context/toast"; import { ClearMySubscriptionsMutation, @@ -14,7 +10,7 @@ import { } from "gql/generated/types"; import { CLEAR_MY_SUBSCRIPTIONS } from "gql/mutations"; -export const ClearSubscriptionsCard: React.VFC = () => { +export const ClearSubscriptions: React.VFC = () => { const [showModal, setShowModal] = useState(false); const { sendEvent } = usePreferencesAnalytics(); const dispatchToast = useToastContext(); @@ -42,19 +38,13 @@ export const ClearSubscriptionsCard: React.VFC = () => { return ( <> - - - Clear all subscriptions you have made on individual Version and Task - pages: - - setShowModal(true)} - > - Clear all previous subscriptions - - + { submitDisabled={loading} > Are you sure you want to clear all subscriptions you have made on - individual Version and Task pages? + individual version, task, and project pages? ); }; - -const StyledClearSubscriptionButton = styled(Button)` - margin-top: ${size.m}; -`; diff --git a/src/pages/preferences/preferencesTabs/notificationTab/UserSubscriptions.tsx b/src/pages/preferences/preferencesTabs/notificationTab/UserSubscriptions.tsx index 42df027ad8..6c69d82888 100644 --- a/src/pages/preferences/preferencesTabs/notificationTab/UserSubscriptions.tsx +++ b/src/pages/preferences/preferencesTabs/notificationTab/UserSubscriptions.tsx @@ -1,70 +1,94 @@ -import { useMemo, useRef } from "react"; -import { useQuery } from "@apollo/client"; +import { useRef, useState } from "react"; +import { useMutation } from "@apollo/client"; +import styled from "@emotion/styled"; +import Button from "@leafygreen-ui/button"; +import Pagination from "@leafygreen-ui/pagination"; +import { palette } from "@leafygreen-ui/palette"; +import { useLeafyGreenTable } from "@leafygreen-ui/table/new"; import { - Cell, - ExpandedContent, - flexRender, - HeaderCell, - HeaderRow, - Row, - Table, - TableBody, - TableHead, - useLeafyGreenTable, -} from "@leafygreen-ui/table/new"; + getFacetedUniqueValues, + getFilteredRowModel, +} from "@tanstack/react-table"; +import Icon from "components/Icon"; import { SettingsCard, SettingsCardTitle } from "components/SettingsCard"; import { ShortenedRouterLink } from "components/styles"; +import { BaseTable } from "components/Table/BaseTable"; +import { getColumnTreeSelectFilterProps } from "components/Table/LGFilters"; import { getSubscriberText } from "constants/subscription"; +import { size } from "constants/tokens"; import { + resourceTypeToCopy, + resourceTypeTreeData, + triggerToCopy, + triggerTreeData, +} from "constants/triggers"; +import { useToastContext } from "context/toast"; +import { + DeleteSubscriptionsMutation, + DeleteSubscriptionsMutationVariables, GeneralSubscription, Selector, - UserSubscriptionsQuery, - UserSubscriptionsQueryVariables, } from "gql/generated/types"; -import { USER_SUBSCRIPTIONS } from "gql/queries"; +import { DELETE_SUBSCRIPTIONS } from "gql/mutations"; import { notificationMethodToCopy } from "types/subscription"; -import { resourceTypeToCopy, triggerToCopy } from "types/triggers"; -import { getResourceRoute, processSubscriptionData } from "./utils"; +import { ClearSubscriptions } from "./ClearSubscriptions"; +import { getResourceRoute, useSubscriptionData } from "./utils"; + +const { gray } = palette; export const UserSubscriptions: React.VFC<{}> = () => { - const { data } = useQuery< - UserSubscriptionsQuery, - UserSubscriptionsQueryVariables - >(USER_SUBSCRIPTIONS); + const dispatchToast = useToastContext(); - const globalSubscriptionIds = useMemo(() => { - const { - buildBreakId, - commitQueueId, - patchFinishId, - patchFirstFailureId, - spawnHostExpirationId, - spawnHostOutcomeId, - } = data?.userSettings?.notifications ?? {}; - return new Set([ - buildBreakId, - commitQueueId, - patchFinishId, - patchFirstFailureId, - spawnHostExpirationId, - spawnHostOutcomeId, - ]); - }, [data?.userSettings?.notifications]); + const [deleteSubscriptions] = useMutation< + DeleteSubscriptionsMutation, + DeleteSubscriptionsMutationVariables + >(DELETE_SUBSCRIPTIONS, { + refetchQueries: ["UserSubscriptions"], + onCompleted: (result) => { + dispatchToast.success( + `Deleted ${result.deleteSubscriptions} subscription${ + result.deleteSubscriptions === 1 ? "" : "s" + }.` + ); + }, + onError: (e) => { + dispatchToast.error( + `Error attempting to delete subscriptions: ${e.message}` + ); + }, + }); - const subscriptions = useMemo( - () => - processSubscriptionData(data?.user?.subscriptions, globalSubscriptionIds), - [data?.user?.subscriptions, globalSubscriptionIds] - ); + const subscriptions = useSubscriptionData(); + + const [columnFilters, setColumnFilters] = useState([]); + const [rowSelection, setRowSelection] = useState({}); const tableContainerRef = useRef(null); const table = useLeafyGreenTable({ columns, containerRef: tableContainerRef, data: subscriptions ?? [], + getFacetedUniqueValues: getFacetedUniqueValues(), + getFilteredRowModel: getFilteredRowModel(), + hasSelectableRows: true, + onColumnFiltersChange: setColumnFilters, + onRowSelectionChange: setRowSelection, + state: { + columnFilters, + rowSelection, + }, + withPagination: true, }); - const { rows } = table.getRowModel(); + const onDeleteSubscriptions = () => { + const subscriptionIds = table + .getSelectedRowModel() + .rows.map(({ original }) => original.id); + + deleteSubscriptions({ variables: { subscriptionIds } }); + + table.resetRowSelection(); + }; return ( <> @@ -73,39 +97,45 @@ export const UserSubscriptions: React.VFC<{}> = () => { {!subscriptions?.length ? ( "No subscriptions found." ) : ( - - - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => ( - - {flexRender( - header.column.columnDef.header, - header.getContext() - )} - - ))} - - ))} - - - {rows.map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender( - cell.column.columnDef.cell, - cell.getContext() - )} - - ))} - {row.original.renderExpandedContent && ( - - )} - - ))} - -
+ <> + + + + { + table.setPageSize(Number(value)); + }} + numTotalItems={subscriptions.length} + currentPage={table.getState().pagination.pageIndex + 1} + onCurrentPageOptionChange={(value: string) => { + table.setPageIndex(Number(value) - 1); + }} + onBackArrowClick={() => table.previousPage()} + onForwardArrowClick={() => table.nextPage()} + /> + + + + + + + )} @@ -114,12 +144,16 @@ export const UserSubscriptions: React.VFC<{}> = () => { const columns = [ { - header: "Type", accessorKey: "resourceType", cell: ({ getValue }) => { const resourceType = getValue(); return resourceTypeToCopy?.[resourceType] ?? resourceType; }, + ...getColumnTreeSelectFilterProps({ + "data-cy": "status-filter-popover", + tData: resourceTypeTreeData, + title: "Type", + }), }, { header: "ID", @@ -145,8 +179,12 @@ const columns = [ }, }, { - header: "Event", accessorKey: "trigger", + ...getColumnTreeSelectFilterProps({ + "data-cy": "trigger-filter-popover", + tData: triggerTreeData, + title: "Event", + }), cell: ({ getValue }) => { const trigger = getValue(); return triggerToCopy?.[trigger] ?? trigger; @@ -166,3 +204,21 @@ const columns = [ cell: ({ getValue }) => getSubscriberText(getValue()), }, ]; + +const InteractiveWrapper = styled.div` + display: flex; + justify-content: space-between; + margin-bottom: ${size.s}; +`; + +const PaginationWrapper = styled.div` + width: 50%; +`; + +const TableFooter = styled.div` + box-shadow: 0 -4px ${gray.light2}; + display: flex; + justify-content: flex-end; + margin-top: ${size.s}; + padding-top: ${size.s}; +`; diff --git a/src/pages/preferences/preferencesTabs/notificationTab/utils.tsx b/src/pages/preferences/preferencesTabs/notificationTab/utils.tsx index d87b70dd4b..9ca32cff51 100644 --- a/src/pages/preferences/preferencesTabs/notificationTab/utils.tsx +++ b/src/pages/preferences/preferencesTabs/notificationTab/utils.tsx @@ -1,3 +1,5 @@ +import { useMemo } from "react"; +import { useQuery } from "@apollo/client"; import styled from "@emotion/styled"; import { LeafyGreenTableRow } from "@leafygreen-ui/table/new"; import { @@ -7,10 +9,51 @@ import { getVersionRoute, } from "constants/routes"; import { size } from "constants/tokens"; -import { GeneralSubscription, Selector } from "gql/generated/types"; +import { convertFamilyTrigger } from "constants/triggers"; +import { + GeneralSubscription, + Selector, + UserSubscriptionsQuery, + UserSubscriptionsQueryVariables, +} from "gql/generated/types"; +import { USER_SUBSCRIPTIONS } from "gql/queries"; import { ResourceType } from "types/triggers"; -export const processSubscriptionData = ( +export const useSubscriptionData = () => { + const { data } = useQuery< + UserSubscriptionsQuery, + UserSubscriptionsQueryVariables + >(USER_SUBSCRIPTIONS); + + const globalSubscriptionIds = useMemo(() => { + const { + buildBreakId, + commitQueueId, + patchFinishId, + patchFirstFailureId, + spawnHostExpirationId, + spawnHostOutcomeId, + } = data?.userSettings?.notifications ?? {}; + return new Set([ + buildBreakId, + commitQueueId, + patchFinishId, + patchFirstFailureId, + spawnHostExpirationId, + spawnHostOutcomeId, + ]); + }, [data?.userSettings?.notifications]); + + const subscriptions = useMemo( + () => + processSubscriptionData(data?.user?.subscriptions, globalSubscriptionIds), + [data?.user?.subscriptions, globalSubscriptionIds] + ); + + return subscriptions; +}; + +const processSubscriptionData = ( subscriptions: GeneralSubscription[], globalSubscriptionIds: Set ) => { @@ -22,6 +65,11 @@ export const processSubscriptionData = ( subscriptions // Filter out a user's global subscriptions for tasks, spawn hosts, etc. .filter(({ id }) => !globalSubscriptionIds.has(id)) + // For this table's purposes, FAMILY_TRIGGER = TRIGGER. Convert all family triggers to their base type. + .map(({ trigger, ...subscription }) => ({ + ...subscription, + trigger: convertFamilyTrigger(trigger), + })) // For subscriptions that contain regex selectors or additional trigger data, append an expandable section .map((subscription) => { const hasTriggerData = !!Object.entries(subscription.triggerData ?? {}) diff --git a/src/pages/projectSettings/tabs/NotificationsTab/transformers.ts b/src/pages/projectSettings/tabs/NotificationsTab/transformers.ts index dc352f93ac..be99af9c58 100644 --- a/src/pages/projectSettings/tabs/NotificationsTab/transformers.ts +++ b/src/pages/projectSettings/tabs/NotificationsTab/transformers.ts @@ -1,12 +1,11 @@ import { ProjectSettingsTabRoutes } from "constants/routes"; import { getSubscriberText } from "constants/subscription"; -import { projectTriggers } from "constants/triggers"; +import { convertFamilyTrigger, projectTriggers } from "constants/triggers"; import { BannerTheme, ProjectInput, SubscriptionInput, } from "gql/generated/types"; -import { TriggerType } from "types/triggers"; import { string } from "utils"; import { FormToGqlFunction, GqlToFormFunction } from "../types"; import { ProjectType } from "../utils"; @@ -17,19 +16,6 @@ type Tab = ProjectSettingsTabRoutes.Notifications; const { toSentenceCase } = string; -const convertFamilyTrigger = (trigger: string) => { - switch (trigger) { - case TriggerType.FAMILY_OUTCOME: - return TriggerType.OUTCOME; - case TriggerType.FAMILY_FAILURE: - return TriggerType.FAILURE; - case TriggerType.FAMILY_SUCCESS: - return TriggerType.SUCCESS; - default: - return trigger; - } -}; - const getTriggerText = (trigger: string, resourceType: string) => { const convertedTrigger = convertFamilyTrigger(trigger); const triggerText = diff --git a/src/types/triggers.ts b/src/types/triggers.ts index 7c2d8ec460..ad5396eb13 100644 --- a/src/types/triggers.ts +++ b/src/types/triggers.ts @@ -7,15 +7,6 @@ export enum ResourceType { Version = "VERSION", } -export const resourceTypeToCopy = { - [ResourceType.Build]: "Build", - [ResourceType.CommitQueue]: "Commit Queue", - [ResourceType.Host]: "Host", - [ResourceType.Patch]: "Patch", - [ResourceType.Task]: "Task", - [ResourceType.Version]: "Version", -}; - export enum ProjectTriggerLevel { TASK = "task", BUILD = "build", @@ -39,26 +30,6 @@ export enum TriggerType { FIRST_FAILURE_VERSION_NAME = "first-failure-in-version-with-name", } -export const triggerToCopy = { - [TriggerType.OUTCOME]: "Outcome", - [TriggerType.FAILURE]: "Failure", - [TriggerType.SUCCESS]: "Success", - [TriggerType.FAMILY_OUTCOME]: "Outcome", - [TriggerType.FAMILY_FAILURE]: "Failure", - [TriggerType.FAMILY_SUCCESS]: "Success", - [TriggerType.RUNTIME_CHANGE]: "Runtime changes by %", - [TriggerType.EXCEEDS_DURATION]: "Runtime exceeds duration", - [TriggerType.TASK_STARTED]: "Task started", - [TriggerType.TASK_FAILED_OR_BLOCKED]: "Task failed or blocked", - [TriggerType.REGRESSION]: "Regression", - [TriggerType.TEST_REGRESSION]: "Test regression", - [TriggerType.FIRST_FAILURE_BUILD]: "First failure", - [TriggerType.FIRST_FAILURE_BUILD]: "First failure in build", - [TriggerType.FIRST_FAILURE_VERSION]: "First failure in version", - [TriggerType.FIRST_FAILURE_VERSION_NAME]: - "First failure in version with name", -}; - export enum TaskTriggers { TASK_STARTS = "task-starts", TASK_FINISHES = "task-finishes", diff --git a/yarn.lock b/yarn.lock index b5f8baafa1..c806ee40b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4259,7 +4259,7 @@ "@leafygreen-ui/palette" "^4.0.0" "@leafygreen-ui/tokens" "^2.0.1" -"@leafygreen-ui/icon-button@^15.0.10": +"@leafygreen-ui/icon-button@^15.0.10", "@leafygreen-ui/icon-button@^15.0.9": version "15.0.10" resolved "https://registry.yarnpkg.com/@leafygreen-ui/icon-button/-/icon-button-15.0.10.tgz#eda3ee2b799452d907c374806232dd7fd2bfc019" integrity sha512-GbMxbPLEIUVOSmzJkVJrpQAfvrKjTgjkM9TSkL06sJ0f7ghcIO6mOpoonML6BLFqOTFXuyUZ/3C0jQQDvO+Glw== @@ -4442,6 +4442,21 @@ "@leafygreen-ui/typography" "^16.4.0" lodash "^4.17.21" +"@leafygreen-ui/pagination@1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@leafygreen-ui/pagination/-/pagination-1.0.7.tgz#2edb56416b8affa1a6a794aff6d20309e053e063" + integrity sha512-3UPXd185AowfmoYPj2aen8CFVeDULCcwcKoP6XZ0zM5VO5wIaFEvXjpcnTvtV5SdAQRMvWqP3vggpg4f8kwVyw== + dependencies: + "@leafygreen-ui/emotion" "^4.0.4" + "@leafygreen-ui/hooks" "^7.7.3" + "@leafygreen-ui/icon" "^11.15.0" + "@leafygreen-ui/icon-button" "^15.0.9" + "@leafygreen-ui/lib" "^10.3.2" + "@leafygreen-ui/select" "^10.3.4" + "@leafygreen-ui/tokens" "^2.1.0" + "@leafygreen-ui/typography" "^16.4.0" + lodash "^4.17.21" + "@leafygreen-ui/palette@3.4.4": version "3.4.4" resolved "https://registry.yarnpkg.com/@leafygreen-ui/palette/-/palette-3.4.4.tgz#d5a8fd85b4eaa27d8a61ffa70288f8f3451e5670"