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.

161 lines
5.2 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. <script lang="ts">
  2. import stuffLogClient from "../clients/stufflog";
  3. import type { ProjectResult, ProjectUpdate } from "../models/project";
  4. import type { TaskResult } from "../models/task";
  5. import markStale from "../stores/markStale";
  6. import type { ModalData } from "../stores/modal";
  7. import IS_MOBILE from "../utils/phone-check";
  8. import Icon from "./Icon.svelte";
  9. import Option from "./Option.svelte";
  10. import OptionRow from "./OptionRow.svelte";
  11. import ParentEntry from "./ParentEntry.svelte";
  12. import ProgressNumbers from "./ProgressNumbers.svelte";
  13. import StatusColor from "./StatusColor.svelte";
  14. import TagList from "./TagList.svelte";
  15. import TaskList from "./TaskList.svelte";
  16. export let project: ProjectResult = null;
  17. export let showAllOptions: boolean = false;
  18. export let hideInactive: boolean = false;
  19. export let hideProgress: boolean = false;
  20. export let linkProject: boolean = false;
  21. export let hideIcon: boolean = false;
  22. export let isFake: boolean = false;
  23. export let removeHook: boolean = false;
  24. let mdAddTask: ModalData;
  25. let mdProjectEdit: ModalData;
  26. let mdProjectDelete: ModalData;
  27. let mdLinkTask: ModalData;
  28. let linkTarget: string = "";
  29. let activeTasks: TaskResult[] = [];
  30. let inactiveTasks: TaskResult[] = [];
  31. let todoTasks: TaskResult[] = [];
  32. let completedTasks: TaskResult[] = [];
  33. let onholdTasks: TaskResult[] = [];
  34. let failedTasks: TaskResult[] = [];
  35. let nonHiddenTasks: TaskResult[] = [];
  36. let toggling = false;
  37. let canComplete = false;
  38. function updateProject(update: ProjectUpdate) {
  39. if (toggling) {
  40. return
  41. }
  42. toggling = true
  43. stuffLogClient.updateProject(project.id, {...update}).then(() => {
  44. markStale("project");
  45. }).catch(err => {
  46. console.warn("Failed to toggle favorite:", err);
  47. }).finally(() => {
  48. toggling = false;
  49. })
  50. }
  51. function toggleFavorite() {
  52. updateProject({
  53. favorite: !project.favorite,
  54. });
  55. }
  56. function markCompleted() {
  57. updateProject({
  58. statusTag: "completed",
  59. active: false,
  60. })
  61. }
  62. function markFailed() {
  63. updateProject({
  64. statusTag: "failed",
  65. active: false,
  66. })
  67. }
  68. $: mdAddTask = {name:"task.add", project};
  69. $: mdLinkTask = {name:"tasklink.add", project};
  70. $: mdProjectEdit = {name:"project.edit", project};
  71. $: mdProjectDelete = {name:"project.delete", project};
  72. $: {
  73. activeTasks = project.tasks.filter(t => t.active);
  74. inactiveTasks = project.tasks.filter(t => !t.active);
  75. todoTasks = inactiveTasks.filter(t => t.statusTag === "to do" || t.statusTag === "idea");
  76. onholdTasks = inactiveTasks.filter(t => t.statusTag === "on hold");
  77. completedTasks = inactiveTasks.filter(t => t.statusTag === "completed" || t.statusTag == null);
  78. failedTasks = inactiveTasks.filter(t => t.statusTag === "failed" || t.statusTag === "declined");
  79. nonHiddenTasks = [...activeTasks, ...todoTasks, ...onholdTasks];
  80. }
  81. $: canComplete = project.active && completedTasks.length + failedTasks.length === project.tasks.length;
  82. $: linkTarget = IS_MOBILE ? `/projects#${project.id}` : `/questlog#${project.id}`
  83. </script>
  84. <StatusColor affects="project" entry={project}>
  85. <ParentEntry
  86. full={showAllOptions}
  87. entry={project}
  88. headerLink={linkProject ? linkTarget : ""}
  89. hideProgress={hideProgress}
  90. hideIcon={hideIcon}
  91. showTimeProgress={!hideProgress}
  92. removeHook={removeHook}
  93. >
  94. <div slot="pre-annotation" class="favorite" class:enabled={project.favorite} class:toggling on:click={toggleFavorite}>
  95. {#if !isFake}
  96. <Icon block name="star" />
  97. {/if}
  98. </div>
  99. <div slot="post-seprator">
  100. <ProgressNumbers project={project} />
  101. </div>
  102. <div slot="above-description">
  103. {#if showAllOptions}
  104. <TagList tags={project.tags} />
  105. {/if}
  106. </div>
  107. {#if showAllOptions}
  108. <OptionRow>
  109. <Option open={mdAddTask}>Add Task</Option>
  110. <Option open={mdLinkTask}>Link Task</Option>
  111. <Option open={mdProjectEdit}>Edit</Option>
  112. <Option open={mdProjectDelete}>Delete</Option>
  113. {#if canComplete}
  114. <Option disabled={!toggling} color="green" on:click={markCompleted}>Complete Project</Option>
  115. <Option disabled={!toggling} color="red" on:click={markFailed}>Fail Project</Option>
  116. {/if}
  117. </OptionRow>
  118. {/if}
  119. {#if hideInactive}
  120. <TaskList header="" tasks={nonHiddenTasks} project={project} showAllOptions={showAllOptions} />
  121. {:else}
  122. <TaskList header="Active" tasks={activeTasks} project={project} showAllOptions={showAllOptions} />
  123. <TaskList header="To Do" tasks={todoTasks} project={project} showAllOptions={showAllOptions} />
  124. <TaskList header="On Hold" tasks={onholdTasks} project={project} showAllOptions={showAllOptions} />
  125. <TaskList header="Completed" tasks={completedTasks} project={project} showAllOptions={showAllOptions} />
  126. <TaskList header="Failed" tasks={failedTasks} project={project} showAllOptions={showAllOptions} />
  127. {/if}
  128. </ParentEntry>
  129. </StatusColor>
  130. <style>
  131. div.favorite {
  132. margin: auto 0;
  133. padding: 0 0.5ch;
  134. line-height: 0em;
  135. color: #333;
  136. cursor: pointer;
  137. }
  138. div.favorite.enabled {
  139. color: #e7e55e
  140. }
  141. div.favorite.toggling {
  142. opacity: 0.5;
  143. }
  144. </style>