Loggest thine Stuff
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
5.6 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. <script lang="ts" context="module">
  2. interface DeletionSideEffect {
  3. name: string
  4. op: string
  5. }
  6. </script>
  7. <script lang="ts">
  8. import { goto } from "$app/navigation";
  9. import { getStores } from "$app/stores";
  10. import { sl3 } from "$lib/clients/sl3";
  11. import Modal from "$lib/components/common/Modal.svelte";
  12. import ModalBody from "$lib/components/common/ModalBody.svelte";
  13. import { getItemListContext } from "$lib/components/contexts/ItemListContext.svelte";
  14. import { getItemMultiListContext } from "$lib/components/contexts/ItemMultiListContext.svelte";
  15. import { getModalContext } from "$lib/components/contexts/ModalContext.svelte";
  16. import { getProjectContext } from "$lib/components/contexts/ProjectContext.svelte";
  17. import { getProjectListContext } from "$lib/components/contexts/ProjectListContext.svelte";
  18. import { getScopeContext } from "$lib/components/contexts/ScopeContext.svelte";
  19. import { getSprintListContext } from "$lib/components/contexts/SprintListContext.svelte";
  20. import type Stat from "$lib/models/stat";
  21. import { scopePrettyId } from "$lib/utils/prettyIds";
  22. const {currentModal, closeModal} = getModalContext();
  23. const {scope, deleteStat} = getScopeContext();
  24. const {project, reloadProject} = getProjectContext();
  25. const {reloadProjectList} = getProjectListContext();
  26. const {reloadSprintList} = getSprintListContext();
  27. const {reloadItemList} = getItemListContext();
  28. const {reloadItemLists} = getItemMultiListContext();
  29. const {page} = getStores();
  30. let endpoint: string;
  31. let error: string
  32. let loading: boolean;
  33. let show: boolean;
  34. let noun: string;
  35. let sideEffects: DeletionSideEffect[];
  36. let name: string;
  37. let dangerZone: boolean;
  38. let dangerZoneConfirm: string;
  39. let navigate: string;
  40. $: switch ($currentModal.name) {
  41. case "scope.delete":
  42. init("", [{op: "Delete", name: "everything under the scope."}])
  43. noun = "Scope";
  44. name = $currentModal.scope.name;
  45. dangerZone = true;
  46. navigate = "/";
  47. break;
  48. case "item.delete":
  49. init(`items/${$currentModal.item.id}`, [], $currentModal.item.scopeId)
  50. noun = "Item";
  51. name = $currentModal.item.name;
  52. break;
  53. case "stat.delete":
  54. init(`stats/${$currentModal.stat.id}`)
  55. noun = "Stat";
  56. name = $currentModal.stat.name;
  57. dangerZone = true;
  58. break;
  59. case "sprint.delete":
  60. init(`sprints/${$currentModal.sprint.id}`, [], $currentModal.sprint.scopeId)
  61. noun = "Sprint";
  62. name = $currentModal.sprint.name;
  63. break;
  64. case "requirement.delete":
  65. init(`projects/${$project.id}/requirements/${$currentModal.requirement.id}`,
  66. $currentModal.requirement.items.map(i => ({
  67. op: "Detach item",
  68. name: i.name,
  69. })),
  70. );
  71. noun = "Requirement";
  72. name = $currentModal.requirement.name;
  73. break;
  74. case "project.delete":
  75. init(`projects/${$currentModal.project.id}`,
  76. $currentModal.project.requirements.flatMap(r => ([{
  77. op: "Delete requirement",
  78. name: `${r.name} (${r.statusName})`,
  79. }, ...r.items.map(i => ({
  80. op: "Detach item",
  81. name: i.name,
  82. }))]))
  83. )
  84. noun = "Project";
  85. name = $currentModal.project.name;
  86. dangerZone = true;
  87. navigate = `/${scopePrettyId($scope)}`;
  88. break;
  89. default:
  90. loading = false;
  91. error = null;
  92. show = false;
  93. }
  94. function init(newEndpoint: string, newSideEffects: DeletionSideEffect[] = [], overrideScopeId?: number) {
  95. let scopeId = $scope.id;
  96. if (overrideScopeId != null) {
  97. scopeId = overrideScopeId;
  98. }
  99. endpoint = `scopes/${scopeId}/${newEndpoint}`;
  100. if (endpoint.endsWith("/")) {
  101. endpoint = endpoint.slice(0, -1);
  102. }
  103. sideEffects = newSideEffects;
  104. show = true;
  105. error = null;
  106. dangerZone = false;
  107. dangerZoneConfirm = "";
  108. navigate = null;
  109. }
  110. async function submit() {
  111. error = null;
  112. loading = true;
  113. try {
  114. const res = await sl3(fetch, $page.stuff.idToken).fetch("DELETE", endpoint);
  115. if (navigate) {
  116. if (noun === "Project") {
  117. await reloadProjectList();
  118. }
  119. goto(navigate);
  120. } else {
  121. // Wait for project reload if it's updating a project
  122. await reloadProject();
  123. if (noun === "Stat") {
  124. reloadItemLists();
  125. deleteStat((res as {stat: Stat}).stat);
  126. }
  127. if (noun === "Sprint") {
  128. await reloadSprintList();
  129. }
  130. if (noun === "Item") {
  131. reloadItemLists();
  132. await reloadItemList();
  133. }
  134. // TODO: History context upsert
  135. }
  136. closeModal();
  137. } catch(err) {
  138. if (err.statusCode != null) {
  139. error = err.statusMessage;
  140. } else {
  141. error = err
  142. }
  143. } finally {
  144. loading = false;
  145. }
  146. }
  147. let disabled;
  148. $: disabled = loading || (!!dangerZone && name !== dangerZoneConfirm)
  149. </script>
  150. <form on:submit|preventDefault={submit}>
  151. <Modal closable show={show} verb="Delete" noun={noun} disabled={disabled} error={error}>
  152. <ModalBody>
  153. <p>Are you sure you want to delete this {noun.toLocaleLowerCase()}?</p>
  154. {#if sideEffects.length > 0}
  155. <p>There are side-effects to this deletion.</p>
  156. <ul>
  157. {#each sideEffects as sideEffect}
  158. <li>{sideEffect.op} {sideEffect.name}</li>
  159. {/each}
  160. </ul>
  161. {/if}
  162. <label for="name">{noun} name</label>
  163. <input type="text" disabled name="name" value={name} />
  164. {#if dangerZone}
  165. <label for="confirm">Re-type name to confirm</label>
  166. <input type="text" name="confirm" bind:value={dangerZoneConfirm} />
  167. {/if}
  168. </ModalBody>
  169. </Modal>
  170. </form>