6
0

project-open-window.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <template>
  2. <div class="project-open-window">
  3. <project-creation-window v-if="create"
  4. @cancel="create = false"></project-creation-window>
  5. <template v-else>
  6. <div class="projects">
  7. <div class="title">
  8. <h1>Open Project</h1>
  9. <div class="text">
  10. Click a project to open it or create a new one.
  11. </div>
  12. </div>
  13. <div class="project"
  14. v-for="project in sortedProjects"
  15. :key="project.identifier"
  16. @click="load(project)">
  17. <h2>{{ project.name }}</h2>
  18. <div class="description">{{ project.description }}</div>
  19. <div>
  20. {{ project.created }}
  21. </div>
  22. </div>
  23. <div v-if="sortedProjects.length === 0"
  24. @click="create = true"
  25. class="project">
  26. <h2>There are no projects available.</h2>
  27. <div class="description">Please use the button at the bottom of the page to create a new one.</div>
  28. </div>
  29. </div>
  30. <div class="footer">
  31. <button-input @click="create = true" type="primary">
  32. New Project
  33. </button-input>
  34. </div>
  35. </template>
  36. </div>
  37. </template>
  38. <script>
  39. import ButtonInput from "@/components/base/button-input";
  40. import ProjectCreationWindow from "@/components/projects/project-creation-window";
  41. export default {
  42. name: "project-open-window",
  43. components: {ProjectCreationWindow, ButtonInput},
  44. created: function () {
  45. // get projects
  46. this.getProjects();
  47. // subscribe to changes
  48. this.$root.socket.on('connect', this.getProjects);
  49. this.$root.socket.on('create-project', this.addProject);
  50. this.$root.socket.on('remove-project', this.removeProject);
  51. this.$root.socket.on('edit-project', this.editProject);
  52. },
  53. destroyed: function () {
  54. this.$root.socket.off('connect', this.getProjects);
  55. this.$root.socket.off('create-project', this.addProject);
  56. this.$root.socket.off('remove-project', this.removeProject);
  57. this.$root.socket.off('edit-project', this.editProject);
  58. },
  59. data: function () {
  60. return {
  61. create: false,
  62. projects: []
  63. }
  64. },
  65. computed: {
  66. sortedProjects: function () {
  67. return [...this.projects]
  68. .sort((a, b) => a.name.toLowerCase() < b.name.toLowerCase() ? -1 : 1);
  69. }
  70. },
  71. methods: {
  72. getProjects: function () {
  73. this.$root.socket.get('/projects')
  74. .then(response => response.json())
  75. .then(projects => {
  76. this.projects = [];
  77. projects.forEach(this.addProject)
  78. });
  79. },
  80. addProject: function (project) {
  81. for (let p of this.projects)
  82. if (p.identifier === project.identifier)
  83. return;
  84. this.projects.push(project);
  85. },
  86. removeProject: function (project) {
  87. for (let i = 0; i < this.projects.length; i++) {
  88. if (this.projects[i].identifier === project.identifier) {
  89. this.projects.splice(i, 1);
  90. return;
  91. }
  92. }
  93. },
  94. editProject: function (project) {
  95. for (let i = 0; i < this.projects.length; i++) {
  96. if (this.projects[i].identifier === project.identifier) {
  97. this.$set(this.projects, i, project);
  98. return;
  99. }
  100. }
  101. },
  102. load: function (project) {
  103. this.$root.project = project;
  104. },
  105. datetime: function (timestamp) {
  106. const date = new Date(timestamp * 1000);
  107. const da = date.getDate();
  108. const mo = date.getMonth() + 1;
  109. const ye = date.getFullYear();
  110. const ho = date.getHours();
  111. const mi = date.getMinutes();
  112. return [
  113. [
  114. da < 10 ? '0' + da : da,
  115. mo < 10 ? '0' + mo : mo,
  116. ye
  117. ].join('.'),
  118. [
  119. ho < 10 ? '0' + ho : ho,
  120. mi < 10 ? '0' + mi : mi
  121. ].join(':')
  122. ].join(' ');
  123. }
  124. }
  125. }
  126. </script>
  127. <style scoped>
  128. .project-open-window {
  129. display: flex;
  130. flex-direction: column;
  131. }
  132. h1 {
  133. margin: 0 0 0.4rem 0;
  134. }
  135. h2 {
  136. margin: 0;
  137. font-size: 120%;
  138. font-family: "Roboto Condensed", sans-serif;
  139. }
  140. .projects {
  141. overflow: auto;
  142. flex-grow: 1;
  143. }
  144. .title {
  145. margin: 0;
  146. padding: 1rem 2rem 0.5rem;
  147. border-bottom: 1px solid rgba(0, 0, 0, 0.2);
  148. }
  149. .title .text {
  150. font-size: 90%;
  151. }
  152. .project:not(:last-child) {
  153. border-bottom: 1px solid rgba(0, 0, 0, 0.2);
  154. }
  155. .project {
  156. padding: 1rem 2rem;
  157. cursor: pointer;
  158. }
  159. h2, .description {
  160. text-overflow: ellipsis;
  161. white-space: nowrap;
  162. overflow: hidden;
  163. }
  164. .footer {
  165. padding: 2rem;
  166. display: flex;
  167. justify-content: flex-end;
  168. }
  169. </style>