Skip to content

Commit

Permalink
DEVPROD-8659 Move analytics utils to shared lib directory (#301)
Browse files Browse the repository at this point in the history
  • Loading branch information
khelif96 authored Aug 14, 2024
1 parent 3b60a0d commit 9a61ec6
Show file tree
Hide file tree
Showing 61 changed files with 559 additions and 622 deletions.
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ The new home of [Spruce](/apps/spruce) and [Parsley](/apps/parsley).

## Monorepo Tips & Tricks

Check out the [Yarn Workspaces documentation](https://classic.yarnpkg.com/lang/en/docs/workspaces/) for more.
Learn about our monorepo shared library [here](packages/lib/README.md).

Check out the
[Yarn Workspaces documentation](https://classic.yarnpkg.com/lang/en/docs/workspaces/)
for more.

### Upgrades

Expand All @@ -27,18 +31,22 @@ For example, `yarn workspace spruce run storybook`.
### Testing

To run all unit tests across the repository, from root:

```bash
yarn test
```

To run a particular workspace's unit tests from root:

```bash
yarn test --project [workspace-name]
```

### Storybook

Spruce, Parsley, and @evg-ui/lib all have their own storybooks, but there's also a shared storybook that combines them into one interface. From root, just run:
Spruce, Parsley, and @evg-ui/lib all have their own storybooks, but there's also
a shared storybook that combines them into one interface. From root, just run:

```bash
yarn storybook
```
57 changes: 0 additions & 57 deletions apps/parsley/src/analytics/addPageAction.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useAnalyticsRoot } from "analytics/useAnalyticsRoot";
import { useAnalyticsRoot } from "@evg-ui/lib/analytics/hooks";
import { AnalyticsIdentifier } from "analytics/types";
import { LogTypes } from "constants/enums";

type Action =
Expand All @@ -22,4 +23,4 @@ type Action =
};

export const useLogDownloadAnalytics = () =>
useAnalyticsRoot<Action>("LoadingPage");
useAnalyticsRoot<Action, AnalyticsIdentifier>("LoadingPage");
6 changes: 4 additions & 2 deletions apps/parsley/src/analytics/logDrop/useLogDropAnalytics.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useAnalyticsRoot } from "analytics/useAnalyticsRoot";
import { useAnalyticsRoot } from "@evg-ui/lib/analytics/hooks";
import { AnalyticsIdentifier } from "analytics/types";
import { LogTypes } from "constants/enums";

type Action =
Expand All @@ -10,4 +11,5 @@ type Action =
fileSize?: number;
};

export const useLogDropAnalytics = () => useAnalyticsRoot<Action>("LogDrop");
export const useLogDropAnalytics = () =>
useAnalyticsRoot<Action, AnalyticsIdentifier>("LogDrop");
5 changes: 3 additions & 2 deletions apps/parsley/src/analytics/logWindow/useLogWindowAnalytics.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useAnalyticsRoot } from "analytics/useAnalyticsRoot";
import { useAnalyticsRoot } from "@evg-ui/lib/analytics/hooks";
import { AnalyticsIdentifier } from "analytics/types";
import { DIRECTION } from "context/LogContext/types";
import { Filter } from "types/logs";

Expand Down Expand Up @@ -38,4 +39,4 @@ type Action =
};

export const useLogWindowAnalytics = () =>
useAnalyticsRoot<Action>("LogWindow");
useAnalyticsRoot<Action, AnalyticsIdentifier>("LogWindow");
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useAnalyticsRoot } from "analytics/useAnalyticsRoot";
import { useAnalyticsRoot } from "@evg-ui/lib/analytics/hooks";
import { AnalyticsIdentifier } from "analytics/types";
import { FilterLogic, WordWrapFormat } from "constants/enums";

type Action =
Expand All @@ -19,4 +20,4 @@ type Action =
| { name: "Toggled sections"; on: boolean };

export const usePreferencesAnalytics = () =>
useAnalyticsRoot<Action>("Preferences");
useAnalyticsRoot<Action, AnalyticsIdentifier>("Preferences");
6 changes: 4 additions & 2 deletions apps/parsley/src/analytics/shortcuts/useShortcutAnalytics.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useAnalyticsRoot } from "analytics/useAnalyticsRoot";
import { useAnalyticsRoot } from "@evg-ui/lib/analytics/hooks";
import { AnalyticsIdentifier } from "analytics/types";

type Action = { name: "Used shortcut"; keys: string };

export const useShortcutAnalytics = () => useAnalyticsRoot<Action>("Shortcut");
export const useShortcutAnalytics = () =>
useAnalyticsRoot<Action, AnalyticsIdentifier>("Shortcut");
6 changes: 6 additions & 0 deletions apps/parsley/src/analytics/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export type AnalyticsIdentifier =
| "LogDrop"
| "LogWindow"
| "Preferences"
| "LoadingPage"
| "Shortcut";
23 changes: 0 additions & 23 deletions apps/parsley/src/analytics/useAnalyticsRoot.ts

This file was deleted.

2 changes: 1 addition & 1 deletion apps/parsley/src/constants/externalURLTemplates.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { stringifyQuery } from "@evg-ui/lib/utils/query-string";
import { evergreenURL, spruceURL } from "utils/environmentVariables";
import { stringifyQuery } from "utils/query-string";

const getEvergreenTaskURL = (taskID: string, execution: string | number) => {
const params = {
Expand Down
2 changes: 1 addition & 1 deletion apps/parsley/src/constants/logURLTemplates.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import queryString from "query-string";
import { stringifyQuery } from "@evg-ui/lib/utils/query-string";
import { Task as TaskType } from "gql/generated/types";
import { evergreenURL, logkeeperURL } from "utils/environmentVariables";
import { stringifyQuery } from "utils/query-string";

/**
*
Expand Down
5 changes: 4 additions & 1 deletion apps/parsley/src/hooks/useQueryParam/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ import { useCallback, useMemo } from "react";
import { ParseOptions } from "query-string";
import { useNavigate, useSearchParams } from "react-router-dom";
import { conditionalToArray } from "@evg-ui/lib/utils/array";
import {
parseQueryString,
stringifyQuery,
} from "@evg-ui/lib/utils/query-string";
import { QueryParams } from "constants/queryParams";
import { parseQueryString, stringifyQuery } from "utils/query-string";

/**
* `useQueryParams` returns all of the query params that exist in the url.
Expand Down
25 changes: 0 additions & 25 deletions apps/parsley/src/utils/query-string/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,6 @@
import queryString, { ParseOptions, StringifyOptions } from "query-string";
import { CaseSensitivity, MatchType } from "constants/enums";
import { Filters } from "types/logs";

export const parseQueryString = (
search: string,
options: ParseOptions = {},
) => {
const parseOptions: ParseOptions = {
arrayFormat: "comma",
parseBooleans: true,
parseNumbers: true,
...options,
};
return queryString.parse(search, parseOptions);
};

export const stringifyQuery = (
object: { [key: string]: any },
options: StringifyOptions = {},
) =>
queryString.stringify(object, {
arrayFormat: "comma",
skipEmptyString: true,
skipNull: true,
...options,
});

export const parseFilters = (filters: string[]): Filters => {
const parsedFilters: Filters = filters.map((f) => {
// Ensure that a filter is a string before parsing it.
Expand Down
107 changes: 1 addition & 106 deletions apps/parsley/src/utils/query-string/query-string.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { CaseSensitivity, MatchType } from "constants/enums";
import {
parseFilters,
parseQueryString,
stringifyFilters,
stringifyQuery,
} from ".";
import { parseFilters, stringifyFilters } from ".";

describe("filters", () => {
describe("stringifyFilters", () => {
Expand Down Expand Up @@ -120,103 +115,3 @@ describe("filters", () => {
});
});
});

describe("query-string", () => {
describe("stringifyQuery", () => {
it("ignores null", () => {
expect(stringifyQuery({ a: "hello", b: null })).toBe("a=hello");
});
it("ignores emptyStrings", () => {
expect(stringifyQuery({ a: "hello", b: "" })).toBe("a=hello");
});
it("should preserve empty strings if skipEmptyString is passed in", () => {
let result = stringifyQuery(
{ bar: null, foo: "" },
{ skipEmptyString: false },
);
expect(result).toBe("foo=");
result = stringifyQuery({ bar: 21, foo: "" }, { skipEmptyString: false });
expect(result).toBe("bar=21&foo=");
});
it("can handle empty input", () => {
expect(stringifyQuery({})).toBe("");
});
it("stringifies a boolean correctly", () => {
expect(stringifyQuery({ exists: true })).toBe("exists=true");
});
it("stringifies a number correctly", () => {
expect(stringifyQuery({ files: 23 })).toBe("files=23");
});
it("stringifies an array correctly", () => {
expect(
stringifyQuery({ statuses: ["passed", "failed", "running"] }),
).toBe("statuses=passed,failed,running");
});
it("stringifies an object containing many fields correctly", () => {
expect(
stringifyQuery({
exists: true,
files: 23,
statuses: ["passed", "failed", "running"],
variant: [1, 3, 5],
}),
).toBe(
"exists=true&files=23&statuses=passed,failed,running&variant=1,3,5",
);
});
});

describe("parseQueryString", () => {
it("parses a single query param with a string", () => {
expect(parseQueryString("status=passed")).toMatchObject({
status: "passed",
});
});
it("parses multiple query params that are strings", () => {
expect(
parseQueryString("status=passed&variant=ubuntu1604"),
).toMatchObject({
status: "passed",
variant: "ubuntu1604",
});
});
it("parses a query param with an array as a value", () => {
expect(parseQueryString("statuses=failed,passed,ehh")).toMatchObject({
statuses: ["failed", "passed", "ehh"],
});
});
it("parses a query param with multiple arrays as value", () => {
expect(
parseQueryString(
"statuses=failed,passed,ehh&variants=ubuntu1604,GLADOS",
),
).toMatchObject({
statuses: ["failed", "passed", "ehh"],
variants: ["ubuntu1604", "GLADOS"],
});
});
it("parses a query param with a mixed array and a single string as a value", () => {
expect(
parseQueryString("status=failed&variants=ubuntu1604,GLADOS"),
).toMatchObject({
status: "failed",
variants: ["ubuntu1604", "GLADOS"],
});
});
it("parses a query param with a boolean as a value", () => {
expect(parseQueryString("status=true")).toMatchObject({
status: true,
});
});
it("parses a query param with a number as a value", () => {
expect(parseQueryString("status=1")).toMatchObject({
status: 1,
});
});
it("parses a query param with a number array as a value", () => {
expect(parseQueryString("status=1,2,3")).toMatchObject({
status: [1, 2, 3],
});
});
});
});
Loading

0 comments on commit 9a61ec6

Please sign in to comment.