Skip to content

Commit

Permalink
Add tags to plan snapshots
Browse files Browse the repository at this point in the history
  • Loading branch information
AaronPlave committed Sep 27, 2023
1 parent 33716dc commit 109b591
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 15 deletions.
35 changes: 31 additions & 4 deletions src/components/modals/CreatePlanSnapshotModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,35 @@

<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { tags } from '../../stores/tags';
import type { User } from '../../types/app';
import type { Plan } from '../../types/plan';
import type { Tag, TagsChangeEvent } from '../../types/tags';
import effects from '../../utilities/effects';
import TagsInput from '../ui/Tags/TagsInput.svelte';
import Modal from './Modal.svelte';
import ModalContent from './ModalContent.svelte';
import ModalFooter from './ModalFooter.svelte';
import ModalHeader from './ModalHeader.svelte';
export let height: number = 270;
export let width: number = 280;
export let height: number | string = 'unset';
export let width: number = 380;
export let plan: Plan;
export let user: User | null = null;
const dispatch = createEventDispatcher();
let createButtonDisabled: boolean = true;
let snapshotName: string = `${plan.name} - Snapshot`;
let snapshotDescription: string = '';
let createButtonDisabled: boolean = true;
let snapshotTags: Tag[] = [];
/* TODO tie this into featurePermissions? */
$: createButtonDisabled = snapshotName === '';
function create() {
if (!createButtonDisabled) {
dispatch('create', { description: snapshotDescription, name: snapshotName, plan });
dispatch('create', { description: snapshotDescription, name: snapshotName, plan, tags: snapshotTags });
}
}
Expand All @@ -33,6 +41,21 @@
create();
}
}
async function onTagsInputChange(event: TagsChangeEvent) {
const {
detail: { tag, type },
} = event;
if (type === 'remove') {
snapshotTags = snapshotTags.filter(t => t.name !== tag.name);
} else if (type === 'create' || type === 'select') {
let tagsToAdd: Tag[] = [tag];
if (type === 'create') {
tagsToAdd = (await effects.createTags([{ color: tag.color, name: tag.name }], user)) || [];
}
snapshotTags = snapshotTags.concat(tagsToAdd);
}
}
</script>

<svelte:window on:keydown={onKeydown} />
Expand Down Expand Up @@ -62,6 +85,10 @@
name="description"
/>
</fieldset>
<fieldset>
<label for="plan-duration">Tags</label>
<TagsInput options={$tags} selected={snapshotTags} on:change={onTagsInputChange} />
</fieldset>
</ModalContent>
<ModalFooter>
<button class="st-button secondary" on:click={() => dispatch('close')}> Cancel </button>
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/DatePicker/DatePicker.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@
background: #ffffff;
border: 1px solid var(--st-gray-20);
border-radius: 10px;
box-shadow: 0px 8px 16px 0px var(--st-gray-20);
box-shadow: var(--st-shadow-popover);
min-height: 100px;
min-width: 150px;
user-select: none;
Expand Down
1 change: 1 addition & 0 deletions src/css/stellar.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
/* TODO add to stellar */
--st-utility-blue: #2f80ed;
--st-utility-red: #db5139;
--st-shadow-popover: 0px 4px 16px 0px rgba(0, 0, 0, 0.08);
}

.st-button.ellipsis {
Expand Down
5 changes: 5 additions & 0 deletions src/types/tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export type PlanTagsInsertInput = {
tag_id: number;
};

export type PlanSnapshotTagsInsertInput = {
snapshot_id: number;
tag_id: number;
};

export type Tag = {
color: string | null;
created_at: string;
Expand Down
44 changes: 42 additions & 2 deletions src/utilities/effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ import type {
ActivityDirectiveTagsInsertInput,
ConstraintTagsInsertInput,
ExpansionRuleTagsInsertInput,
PlanSnapshotTagsInsertInput,
PlanTagsInsertInput,
SchedulingGoalTagsInsertInput,
Tag,
Expand Down Expand Up @@ -850,10 +851,10 @@ const effects = {
throwPermissionError('create a snapshot');
}

const { confirm, value = null } = await showCreatePlanSnapshotModal(plan);
const { confirm, value = null } = await showCreatePlanSnapshotModal(plan, user);

if (confirm && value) {
const { description, name, plan } = value;
const { description, name, plan, tags } = value;
const data = await reqHasura<{ snapshot_id: number }>(
gql.CREATE_PLAN_SNAPSHOT,
{ plan_id: plan.id, /* snapshot_description: description, */ snapshot_name: name },
Expand All @@ -866,6 +867,13 @@ const effects = {
const updates = { description };
await reqHasura(gql.UPDATE_PLAN_SNAPSHOT, { planSnapshot: updates, snapshot_id }, user);

// Associate tags with the snapshot
const newPlanSnapshotTags: PlanSnapshotTagsInsertInput[] = tags.map(({ id: tag_id }) => ({
snapshot_id,
tag_id,
}));
await effects.createPlanSnapshotTags(newPlanSnapshotTags, user, false);

showSuccessToast('Snapshot Created Successfully');
} else {
throw Error('');
Expand All @@ -877,6 +885,38 @@ const effects = {
}
},

async createPlanSnapshotTags(
tags: PlanSnapshotTagsInsertInput[],
user: User | null,
notify: boolean = true,
): Promise<number | null> {
try {
if (!queryPermissions.CREATE_PLAN_SNAPSHOT_TAGS(user)) {
throwPermissionError('create plan tags');
}

const data = await reqHasura<{ affected_rows: number }>(gql.CREATE_PLAN_SNAPSHOT_TAGS, { tags }, user);
const { insert_plan_snapshot_tags } = data;
if (insert_plan_snapshot_tags != null) {
const { affected_rows } = insert_plan_snapshot_tags;

if (affected_rows !== tags.length) {
throw Error('Some plan snapshot tags were not successfully created');
}
if (notify) {
showSuccessToast('Plan Snapshot Updated Successfully');
}
return affected_rows;
} else {
throw Error('Unable to create plan snapshot tags');
}
} catch (e) {
catchError('Create Plan Snapshot Tags Failed', e as Error);
showFailureToast('Create Plan Snapshot Tags Failed');
return null;
}
},

async createPlanTags(tags: PlanTagsInsertInput[], user: User | null, notify: boolean = true): Promise<number | null> {
try {
if (!queryPermissions.CREATE_PLAN_TAGS(user)) {
Expand Down
11 changes: 11 additions & 0 deletions src/utilities/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,17 @@ const gql = {
}
`,

CREATE_PLAN_SNAPSHOT_TAGS: `#graphql
mutation CreatePlanSnapshotTags($tags: [plan_snapshot_tags_insert_input!]!) {
insert_plan_snapshot_tags(objects: $tags, on_conflict: {
constraint: plan_snapshot_tags_pkey,
update_columns: []
}) {
affected_rows
}
}
`,

CREATE_PLAN_TAGS: `#graphql
mutation CreatePlanTags($tags: [plan_tags_insert_input!]!) {
insert_plan_tags(objects: $tags, on_conflict: {
Expand Down
21 changes: 13 additions & 8 deletions src/utilities/modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type { ExpansionSequence } from '../types/expansion';
import type { ModalElement, ModalElementValue } from '../types/modal';
import type { Plan, PlanBranchRequestAction, PlanMergeRequestStatus, PlanMergeRequestTypeFilter } from '../types/plan';
import type { PlanSnapshot } from '../types/plan-snapshot';
import type { Tag } from '../types/tags';
import type { ViewDefinition } from '../types/view';

/**
Expand Down Expand Up @@ -233,13 +234,14 @@ export async function showCreatePlanBranchModal(plan: Plan): Promise<ModalElemen
*/
export async function showCreatePlanSnapshotModal(
plan: Plan,
): Promise<ModalElementValue<{ description: string; name: string; plan: Plan }>> {
user: User | null,
): Promise<ModalElementValue<{ description: string; name: string; plan: Plan; tags: Tag[] }>> {
return new Promise(resolve => {
if (browser) {
const target: ModalElement | null = document.querySelector('#svelte-modal');

if (target) {
const createPlanSnapshotModal = new CreatePlanSnapshotModal({ props: { plan }, target });
const createPlanSnapshotModal = new CreatePlanSnapshotModal({ props: { plan, user }, target });
target.resolve = resolve;

createPlanSnapshotModal.$on('close', () => {
Expand All @@ -249,12 +251,15 @@ export async function showCreatePlanSnapshotModal(
createPlanSnapshotModal.$destroy();
});

createPlanSnapshotModal.$on('create', (e: CustomEvent<{ description: string; name: string; plan: Plan }>) => {
target.replaceChildren();
target.resolve = null;
resolve({ confirm: true, value: e.detail });
createPlanSnapshotModal.$destroy();
});
createPlanSnapshotModal.$on(
'create',
(e: CustomEvent<{ description: string; name: string; plan: Plan; tags: Tag[] }>) => {
target.replaceChildren();
target.resolve = null;
resolve({ confirm: true, value: e.detail });
createPlanSnapshotModal.$destroy();
},
);
}
} else {
resolve({ confirm: false });
Expand Down
3 changes: 3 additions & 0 deletions src/utilities/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ const queryPermissions = {
CREATE_PLAN_SNAPSHOT: (user: User | null): boolean => {
return getPermission(['create_snapshot'], user);
},
CREATE_PLAN_SNAPSHOT_TAGS: (user: User | null): boolean => {
return getPermission(['insert_plan_snapshot_tags'], user);
},
CREATE_PLAN_TAGS: (user: User | null): boolean => {
return getPermission(['insert_plan_tags'], user);
},
Expand Down

0 comments on commit 109b591

Please sign in to comment.