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.

100 lines
3.0 KiB

  1. <script lang="ts">
  2. import type Project from "../models/project";
  3. import projectStore from "../stores/project";
  4. import projectGroupStore from "../stores/projectGroup";
  5. interface OptGroup {
  6. status: string
  7. projects: Project[]
  8. }
  9. export let value = "";
  10. export let name = "";
  11. export let groupId = "";
  12. export let placeholder = "None";
  13. export let disabled = false;
  14. export let optional = false;
  15. export let forceGroup = false;
  16. let optGroups: OptGroup[]
  17. $: {
  18. let projects = $projectStore.projects;
  19. let labels = {};
  20. if (groupId != "") {
  21. const group = $projectGroupStore.groups.find(g => g.id === groupId);
  22. if (group != null) {
  23. projects = group.projects;
  24. labels = group.categoryNames;
  25. if (forceGroup && !group.projects.find(p => p.id === value)) {
  26. value = "";
  27. }
  28. }
  29. } else if (forceGroup) {
  30. value = "";
  31. }
  32. optGroups = [
  33. {
  34. status: labels["deadlines"] || "Deadlines",
  35. projects: projects.filter(p => p.active && p.endTime)
  36. },
  37. {
  38. status: labels["active"] || "Active",
  39. projects: projects.filter(p => p.active && !p.endTime)
  40. },
  41. {
  42. status: labels["progress"] || "Progress",
  43. projects: projects.filter(p => !p.active && p.statusTag === "progress")
  44. },
  45. {
  46. status: labels["background"] || "Background",
  47. projects: projects.filter(p => !p.active && p.statusTag === "background")
  48. },
  49. {
  50. status: labels["to do"] || "To Do",
  51. projects: projects.filter(p => !p.active && p.statusTag === "to do")
  52. },
  53. {
  54. status: labels["on hold"] || "On Hold",
  55. projects: projects.filter(p => !p.active && p.statusTag === "on hold")
  56. },
  57. {
  58. status: labels["completed"] || "Completed",
  59. projects: projects.filter(p => !p.active && p.statusTag === "completed")
  60. },
  61. {
  62. status: labels["failed"] || "Failed",
  63. projects: projects.filter(p => !p.active && p.statusTag === "failed")
  64. },
  65. ]
  66. for (const group of optGroups) {
  67. group.projects.sort((a,b) => a.name.localeCompare(b.name));
  68. }
  69. }
  70. $: {
  71. if (optGroups.length > 0 && value === "" && !optional) {
  72. const nonEmpty = optGroups.find(g => g.projects.length > 0);
  73. if (nonEmpty != null) {
  74. value = nonEmpty.projects[0].id;
  75. }
  76. }
  77. }
  78. </script>
  79. <select name={name} bind:value={value} disabled={disabled || $projectStore.loading}>
  80. {#if optional}
  81. <option value={""} selected={"" === value}>{$projectStore.loading ? "Loading..." : placeholder}</option>
  82. {/if}
  83. {#each optGroups as group (group.status)}
  84. {#if group.projects.length > 0}
  85. <optgroup label={group.status}>
  86. {#each group.projects as project (project.id)}
  87. <option value={project.id} selected={project.id === value}>{project.tags.length ? `${project.tags[0]}: ${project.name}` : project.name}</option>
  88. {/each}
  89. </optgroup>
  90. {/if}
  91. {/each}
  92. </select>