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.

155 lines
5.0 KiB

  1. <script lang="ts">
  2. import { getStores } from "$app/stores";
  3. import { sl3 } from "$lib/clients/sl3";
  4. import Modal from "$lib/components/common/Modal.svelte";
  5. import ModalBody from "$lib/components/common/ModalBody.svelte";
  6. import { getModalContext } from "$lib/components/contexts/ModalContext.svelte";
  7. import { getProjectContext } from "$lib/components/contexts/ProjectContext.svelte";
  8. import { getScopeContext } from "$lib/components/contexts/ScopeContext.svelte";
  9. import ProjectSelect from "$lib/components/controls/ProjectSelect.svelte";
  10. import StatInput from "$lib/components/controls/StatInput.svelte";
  11. import StatusSelect from "$lib/components/controls/StatusSelect.svelte";
  12. import TagInput from "$lib/components/controls/TagInput.svelte";
  13. import Checkbox from "$lib/components/layout/Checkbox.svelte";
  14. import type { ProjectEntry, Requirement, RequirementInput } from "$lib/models/project";
  15. import Status from "$lib/models/status";
  16. import { statDiff } from "$lib/utils/stat";
  17. const {currentModal, closeModal} = getModalContext();
  18. const {scope} = getScopeContext();
  19. const {project, reloadProject} = getProjectContext();
  20. const {page} = getStores();
  21. let requirement: RequirementInput
  22. let projectId: number
  23. let requirementId: number
  24. let oldStats: RequirementInput["stats"]
  25. let showAggregateRequired: boolean
  26. let oldTags: string[]
  27. let error: string
  28. let loading: boolean
  29. let show: boolean
  30. let op: "Create" | "Edit" | "Delete"
  31. $: switch ($currentModal.name) {
  32. case "requirement.create":
  33. initCreate($currentModal.project);
  34. op = "Create";
  35. break;
  36. case "requirement.edit":
  37. initEdit($currentModal.requirement, $project);
  38. op = "Edit";
  39. break;
  40. default:
  41. loading = false;
  42. error = null;
  43. show = false;
  44. }
  45. $: showAggregateRequired = requirement?.stats?.find(s => s.required > 0) == null;
  46. function initCreate(project: ProjectEntry) {
  47. requirement = {
  48. name: "",
  49. description: "",
  50. stats: [],
  51. status: Status.Available,
  52. isCoarse: false,
  53. aggregateRequired: 0,
  54. tags: [],
  55. projectId: project.id,
  56. }
  57. projectId = project.id;
  58. show = true;
  59. }
  60. function initEdit(current: Requirement, project: ProjectEntry) {
  61. requirement = {
  62. name: current.name,
  63. description: current.description,
  64. status: current.status,
  65. stats: current.stats.map(s => ({acquired: s.acquired, required: s.required, statId: s.id})),
  66. isCoarse: current.isCoarse,
  67. aggregateRequired: current.aggregateRequired,
  68. tags: [...current.tags],
  69. projectId: project.id,
  70. }
  71. oldTags = [...current.tags];
  72. oldStats = [...requirement.stats];
  73. projectId = project.id;
  74. requirementId = current.id;
  75. show = true;
  76. }
  77. async function submit() {
  78. error = null;
  79. loading = true;
  80. if (requirement.stats.find(s => s.required > 0)) {
  81. requirement.aggregateRequired = 0;
  82. }
  83. try {
  84. switch (op) {
  85. case "Create":
  86. await sl3(fetch).createRequirement($scope.id, projectId, requirement);
  87. break;
  88. case "Edit":
  89. const submission: Partial<RequirementInput> = {
  90. ...requirement,
  91. stats: statDiff(oldStats, requirement.stats, -1),
  92. addTags: requirement.tags.filter(t => !oldTags.includes(t)),
  93. removeTags: oldTags.filter(t => !requirement.tags.includes(t)),
  94. projectId: requirement.projectId !== projectId ? requirement.projectId : void(0),
  95. };
  96. await sl3(fetch).updateRequirement($scope.id, projectId, requirementId, submission);
  97. break;
  98. }
  99. // Wait for project to reload
  100. await reloadProject();
  101. closeModal();
  102. } catch(err) {
  103. if (err.statusCode != null) {
  104. error = err.statusMessage;
  105. } else {
  106. error = err
  107. }
  108. } finally {
  109. loading = false;
  110. }
  111. }
  112. </script>
  113. <form on:submit|preventDefault={submit}>
  114. <Modal show={show} wide closable verb={op} noun="Requirement" disabled={loading} error={error}>
  115. <ModalBody>
  116. <label for="name">Name</label>
  117. <input name="name" type="text" bind:value={requirement.name} />
  118. <label for="description">Description</label>
  119. <textarea name="description" bind:value={requirement.description} />
  120. {#if showAggregateRequired}
  121. <label for="aggregateRequired">Aggregate Required (Zero for old behavior)</label>
  122. <input name="aggregateRequired" type="number" bind:value={requirement.aggregateRequired} />
  123. {/if}
  124. <TagInput bind:value={requirement.tags} />
  125. </ModalBody>
  126. <ModalBody>
  127. <label for="req">Project Requirement</label>
  128. <ProjectSelect disabled={op === "Create"} bind:value={requirement.projectId} />
  129. <label for="stats">Status</label>
  130. <StatusSelect bind:status={requirement.status} />
  131. <label for="stats">Stats</label>
  132. <StatInput showRequired bind:value={requirement.stats} />
  133. <Checkbox bind:checked={requirement.isCoarse} label="Hide 0-requirement stats." />
  134. </ModalBody>
  135. </Modal>
  136. </form>