Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dash: support app blocking canary testing #423

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ jobs:
start: pnpm --filter @dash/app preview
project: dash/app
- name: upload-videos
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: failure()
with:
name: cypress-videos
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: run smoke tests
run: just smoke-run
- name: upload-videos
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: failure()
with:
name: smoke-videos
Expand Down
2 changes: 1 addition & 1 deletion dash/app/cypress/e2e/create-key.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe(`create key flow`, () => {
id: `app-123`,
name: `Brave`,
slug: `brave`,
selectable: true,
launchable: true,
bundleIds: [],
},
]);
Expand Down
8 changes: 8 additions & 0 deletions dash/app/src/components/routes/User.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const UserRoute: React.FC = () => {
showSuspensionActivity: user.draft.showSuspensionActivity,
downtime: user.draft.downtime,
keychains: user.draft.keychains.map(({ id, schedule }) => ({ id, schedule })),
blockedApps: user.draft.blockedApps,
}),
{
onSuccess: () => dispatch({ type: `userSaved` }),
Expand Down Expand Up @@ -147,6 +148,13 @@ const UserRoute: React.FC = () => {
setAssignedKeychainSchedule={(id, schedule) =>
dispatch({ type: `setKeychainSchedule`, id, schedule })
}
blockedApps={draft.blockedApps}
newBlockedAppIdentifier={state.newBlockedAppIdentifier ?? ``}
updateNewBlockedAppIdentifier={(identifier) =>
dispatch({ type: `updateNewBlockedAppIdentifier`, identifier })
}
addNewBlockedApp={() => dispatch({ type: `addNewBlockedApp` })}
removeBlockedApp={(id) => dispatch({ type: `removeBlockedApp`, id })}
/>
);
};
Expand Down
2 changes: 1 addition & 1 deletion dash/app/src/reducers/__tests__/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function identifiedApp(
id: uuid(),
name: `Brave Browser`,
slug: `brave`,
selectable: true,
launchable: true,
bundleIds: [{ id: uuid(), bundleId: `com.brave.Browser` }],
...override,
};
Expand Down
28 changes: 25 additions & 3 deletions dash/app/src/reducers/user-reducer.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { v4 as uuid } from 'uuid';
import { produce } from 'immer';
import { defaults } from '@dash/types';
import type {
UserKeychainSummary,
PlainTimeWindow,
User,
KeychainSchedule,
RuleSchedule,
} from '@dash/types';
import { commit, editable } from '../lib/helpers';

type State = {
user?: Editable<User>;
addingKeychain?: UserKeychainSummary | null;
newBlockedAppIdentifier?: string;
};

export type Action =
Expand All @@ -25,9 +27,12 @@ export type Action =
| { type: 'setDowntime'; downtime: PlainTimeWindow }
| { type: 'setShowSuspensionActivity'; show: boolean }
| { type: 'removeKeychain'; id: UUID }
| { type: 'setKeychainSchedule'; id: UUID; schedule?: KeychainSchedule }
| { type: 'updateNewBlockedAppIdentifier'; identifier: string }
| { type: 'removeBlockedApp'; id: UUID }
| { type: 'addNewBlockedApp' }
| { type: 'setKeychainSchedule'; id: UUID; schedule?: RuleSchedule }
| { type: 'addKeychain'; keychain: UserKeychainSummary }
| { type: 'setAddingKeychainSchedule'; schedule?: KeychainSchedule }
| { type: 'setAddingKeychainSchedule'; schedule?: RuleSchedule }
| { type: 'setAddingKeychain'; keychain?: UserKeychainSummary | null };

function reducer(state: State, action: Action): State | undefined {
Expand Down Expand Up @@ -63,6 +68,23 @@ function reducer(state: State, action: Action): State | undefined {
case `setShowSuspensionActivity`:
state.user.draft.showSuspensionActivity = action.show;
return;
case `updateNewBlockedAppIdentifier`:
state.newBlockedAppIdentifier = action.identifier;
return;
case `addNewBlockedApp`:
if (state.newBlockedAppIdentifier) {
state.user.draft.blockedApps = [
...(state.user.draft.blockedApps ?? []),
{ id: uuid(), identifier: state.newBlockedAppIdentifier },
];
state.newBlockedAppIdentifier = ``;
}
return;
case `removeBlockedApp`:
state.user.draft.blockedApps = state.user.draft.blockedApps?.filter(
(app) => app.id !== action.id,
);
return;
case `removeKeychain`:
state.user.draft.keychains = state.user.draft.keychains.filter(
(keychain) => keychain.id !== action.id,
Expand Down
4 changes: 2 additions & 2 deletions dash/components/src/Keychains/KeychainCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { inflect } from '@shared/string';
import { Button, Badge } from '@shared/components';
import { ChevronDownIcon, ClockIcon, TrashIcon } from '@heroicons/react/24/outline';
import { UsersIcon } from '@heroicons/react/24/solid';
import { defaults, type KeychainSchedule as Schedule } from '@dash/types';
import { defaults, type RuleSchedule as Schedule } from '@dash/types';
import GradientIcon from '../GradientIcon';
import KeychainSchedule from './schedule/KeychainSchedule';

Expand Down Expand Up @@ -118,7 +118,7 @@ const KeychainCard: React.FC<Props> = ({
{props.mode === `assign_to_child` && !props.schedule && (
<button
onClick={() => {
props.setSchedule(defaults.keychainSchedule());
props.setSchedule(defaults.ruleSchedule());
setShowSchedule(true);
}}
className={cx(
Expand Down
6 changes: 3 additions & 3 deletions dash/components/src/Keychains/schedule/KeychainSchedule.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react';
import cx from 'classnames';
import type { KeychainSchedule } from '@dash/types';
import type { RuleSchedule } from '@dash/types';
import SpecifyingActiveOrInactive from './SpecifyingActiveOrInactive';
import WhatDays from './WhatDays';
import WhatTime from './WhatTime';

interface Props {
schedule: KeychainSchedule;
setSchedule(schedule: KeychainSchedule): void;
schedule: RuleSchedule;
setSchedule(schedule: RuleSchedule): void;
}

const KeychainSchedule: React.FC<Props> = ({ schedule, setSchedule }) => (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import cx from 'classnames';
import { ArrowsRightLeftIcon } from '@heroicons/react/24/outline';
import type { KeychainSchedule } from '@dash/types';
import type { RuleSchedule } from '@dash/types';

const SpecifyingActiveOrInactive: React.FC<{
schedule: KeychainSchedule;
setSchedule(schedule: KeychainSchedule): void;
schedule: RuleSchedule;
setSchedule(schedule: RuleSchedule): void;
isTouchDevice: boolean;
}> = ({ schedule, setSchedule, isTouchDevice }) => (
<button
Expand Down
6 changes: 3 additions & 3 deletions dash/components/src/Keychains/schedule/WhatDays.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import React from 'react';
import cx from 'classnames';
import { typesafe } from '@shared/ts-utils';
import { CheckIcon } from '@heroicons/react/24/outline';
import type { KeychainSchedule } from '@dash/types';
import type { RuleSchedule } from '@dash/types';
import DropdownCustomizationPoint from './DropdownCustomizationPoint';

const WhatDays: React.FC<{
schedule: KeychainSchedule;
setSchedule(schedule: KeychainSchedule): void;
schedule: RuleSchedule;
setSchedule(schedule: RuleSchedule): void;
isTouchDevice: boolean;
}> = ({ schedule, setSchedule, isTouchDevice }) => (
<DropdownCustomizationPoint
Expand Down
6 changes: 3 additions & 3 deletions dash/components/src/Keychains/schedule/WhatTime.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import React from 'react';
import cx from 'classnames';
import type { KeychainSchedule } from '@dash/types';
import type { RuleSchedule } from '@dash/types';
import TimeInput from '../../Forms/TimeInput';
import DropdownCustomizationPoint from './DropdownCustomizationPoint';

const WhatTime: React.FC<{
schedule: KeychainSchedule;
setSchedule(schedule: KeychainSchedule): void;
schedule: RuleSchedule;
setSchedule(schedule: RuleSchedule): void;
isTouchDevice: boolean;
}> = ({ schedule, setSchedule, isTouchDevice }) => {
const isInvalid = (() => {
Expand Down
4 changes: 2 additions & 2 deletions dash/components/src/Users/AddKeychainDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { Badge, Button, Loading } from '@shared/components';
import { inflect } from '@shared/string';
import { defaults, type KeychainSummary as Keychain } from '@dash/types';
import type { KeychainSchedule as Schedule, RequestState } from '@dash/types';
import type { RuleSchedule as Schedule, RequestState } from '@dash/types';
import KeychainSchedule from '../Keychains/schedule/KeychainSchedule';

interface Props {
Expand Down Expand Up @@ -318,7 +318,7 @@ const AddKeychainDrawer: React.FC<Props> = ({
</>
) : (
<button
onClick={() => selected && setSchedule(defaults.keychainSchedule())}
onClick={() => selected && setSchedule(defaults.ruleSchedule())}
className={cx(
`flex items-center px-2 py-1 rounded-full transition-[background-color,transform] duration-200 active:scale-90 gap-1.5 bg-slate-200/50 hover:bg-slate-200 active:bg-slate-300`,
)}
Expand Down
75 changes: 70 additions & 5 deletions dash/components/src/Users/EditUser.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import cx from 'classnames';
import { inflect } from '@shared/string';
import { TextInput, Button, Toggle, Label } from '@shared/components';
import type { KeychainSchedule, PlainTimeWindow } from '@dash/types';
import { TextInput, Button, Badge, Toggle, Label } from '@shared/components';
import type { RuleSchedule, PlainTimeWindow, BlockedApp } from '@dash/types';
import type { Subcomponents, ConfirmableEntityAction, RequestState } from '@dash/types';
import type { UserKeychainSummary as Keychain } from '@dash/types';
import KeychainCard from '../Keychains/KeychainCard';
Expand Down Expand Up @@ -49,9 +49,14 @@ interface Props {
onDismissAddKeychain(): unknown;
addingKeychain?: Keychain | null;
fetchSelectableKeychainsRequest?: RequestState<{ own: Keychain[]; public: Keychain[] }>;
keychainSchedule?: KeychainSchedule;
setAddingKeychainSchedule(schedule?: KeychainSchedule): unknown;
setAssignedKeychainSchedule(id: UUID, schedule?: KeychainSchedule): unknown;
keychainSchedule?: RuleSchedule;
setAddingKeychainSchedule(schedule?: RuleSchedule): unknown;
setAssignedKeychainSchedule(id: UUID, schedule?: RuleSchedule): unknown;
blockedApps?: BlockedApp[];
newBlockedAppIdentifier: string;
updateNewBlockedAppIdentifier(identifier: string): unknown;
addNewBlockedApp(): unknown;
removeBlockedApp(id: UUID): unknown;
}

const EditUser: React.FC<Props> = ({
Expand Down Expand Up @@ -92,6 +97,11 @@ const EditUser: React.FC<Props> = ({
keychainSchedule,
setAddingKeychainSchedule,
setAssignedKeychainSchedule,
blockedApps,
newBlockedAppIdentifier,
updateNewBlockedAppIdentifier,
addNewBlockedApp,
removeBlockedApp,
}) => {
if (isNew) {
return (
Expand Down Expand Up @@ -317,6 +327,61 @@ const EditUser: React.FC<Props> = ({
</div>
</div>
</div>
{/* /downtime */}

{/* blocked apps */}
{blockedApps && (
<div className="mt-12 max-w-3xl mb-12">
<h2 className="text-lg font-bold text-slate-700 flex">
Blocked Apps{` `}
<Badge className="ml-2" size="small" type="green">
Beta
</Badge>
</h2>
{blockedApps.length === 0 ? (
<p className="text-center italic hidden text-slate-500 text-sm antialiased mt-2 mb-4">
No apps are currently blocked
</p>
) : (
<div className="gap-1.5 my-2 flex flex-col">
{blockedApps.map((app) => (
<div
className="text-slate-600 flex items-center font-bold px-3 py-2.5 border border-slate-200 bg-white rounded-lg"
key={app.id}
>
<i className="fa text-red-500 fa-ban mr-2 p-1.5 bg-red-100/80 rounded-md" />
<span className="grow">{app.identifier}</span>
<i
className="fa fa-trash text-slate-500 ml-2 mr-1 cursor-pointer hover:text-red-700"
onClick={() => removeBlockedApp(app.id)}
/>
</div>
))}
</div>
)}
<div className="flex gap-2 mt-4">
<TextInput
key={`new-blocked-app-${blockedApps.length}`}
type="text"
value={newBlockedAppIdentifier}
setValue={updateNewBlockedAppIdentifier}
placeholder="App name or bundle id"
/>
<Button
size="small"
className="whitespace-nowrap"
color="secondary"
type="button"
disabled={!newBlockedAppIdentifier}
onClick={addNewBlockedApp}
>
<i className="fa fa-plus mr-2" />
Add new
</Button>
</div>
</div>
)}
{/* /blocked apps */}

{/* keychains */}
<div className="mt-12 max-w-3xl">
Expand Down
4 changes: 2 additions & 2 deletions dash/types/src/defaults.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { PlainTimeWindow, KeychainSchedule } from './pairql/shared';
import type { PlainTimeWindow, RuleSchedule } from './pairql/shared';

export function timeWindow(): PlainTimeWindow {
return {
Expand All @@ -7,7 +7,7 @@ export function timeWindow(): PlainTimeWindow {
};
}

export function keychainSchedule(): KeychainSchedule {
export function ruleSchedule(): RuleSchedule {
return {
mode: `active`,
days: {
Expand Down
2 changes: 1 addition & 1 deletion dash/types/src/pairql/pairs/GetIdentifiedApps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export namespace GetIdentifiedApps {
id: UUID;
name: string;
slug: string;
selectable: boolean;
launchable: boolean;
bundleIds: Array<{
id: UUID;
bundleId: string;
Expand Down
5 changes: 3 additions & 2 deletions dash/types/src/pairql/pairs/SaveUser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// auto-generated, do not edit
import type { KeychainSchedule, SuccessOutput, PlainTimeWindow } from '../shared';
import type { PlainTimeWindow, BlockedApp, SuccessOutput, RuleSchedule } from '../shared';

export namespace SaveUser {
export interface Input {
Expand All @@ -14,8 +14,9 @@ export namespace SaveUser {
downtime?: PlainTimeWindow;
keychains: Array<{
id: UUID;
schedule?: KeychainSchedule;
schedule?: RuleSchedule;
}>;
blockedApps?: BlockedApp[];
}

export type Output = SuccessOutput;
Expand Down
Loading
Loading