project.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. {% extends "layout.html" %}
  2. {% block title %}{% if project.name.len() > 0 %}{{project.name}}{%else%}Create Project{% endif %}{% endblock %}
  3. {% block description %}{{project.description}} {% endblock %}
  4. {% block head %}
  5. <link rel="stylesheet" href="/fs/css/calendar.js.min.css">
  6. <script src="/fs/js/calendar.min.js"></script>
  7. {% endblock %}
  8. {% block content %}
  9. <div class="container">
  10. <div class="row justified">
  11. <div class="center">
  12. <div class="backed col-sm-12 col-md-12 col-lg-12">
  13. <h1> {% if project.name.len() > 0 %}{{project.name}}{%else%}Project{% endif %}</h1>
  14. {% if project.key.to_string() != "00000000-0000-0000-0000-000000000000" %}
  15. <a class="button center" target="_blank"
  16. href="https://matrix.to/#/!JzZKoqLxgzTnmZkeKm:matrix.org?via=matrix.org">Discussion
  17. 🗫</a>
  18. <a class="button center" href="/task/add/{{project.key}}">➕ Add Task</a>
  19. <a class="button center" href="/milestone/add/{{project.key}}">➕ Add Milestone</a>
  20. <a class="button center" href="/note/add/Project/{{project.key}}">➕ Add Note</a>
  21. <a class="button center" href="/file/add/Project/{{project.key}}">➕ Attach File</a>
  22. <button id="delete" class="delete_button center">🗑️ Delete</button>
  23. {% endif %}
  24. <div class="tabbed">
  25. <input type="radio" id="tab1" name="css-tabs" checked>
  26. <input type="radio" id="tab2" name="css-tabs">
  27. <input type="radio" id="tab3" name="css-tabs">
  28. <input type="radio" id="tab4" name="css-tabs">
  29. <input type="radio" id="tab5" name="css-tabs">
  30. <input type="radio" id="tab6" name="css-tabs">
  31. <ul class="tabs">
  32. <li class="tab"><label for="tab1">Details</label></li>
  33. {% if project.key.to_string() != "00000000-0000-0000-0000-000000000000" %}
  34. <li class="tab"><label for="tab2">Tasks</label></li>
  35. <li class="tab"><label for="tab3">Milestones</label></li>
  36. <li class="tab"><label for="tab4">Notes & Files</label></li>
  37. <li class="tab"><label for="tab5">Gantt</label></li>
  38. <li class="tab"><label for="tab6">Calendar</label></li>
  39. {% endif %}
  40. </ul>
  41. <div class="tab-content">
  42. <div class="backed col-sm-12 col-md-12 col-lg-12">
  43. <div class="row justified">
  44. <div class+="content">
  45. <form id="add_project_form">
  46. <div>
  47. <label for="name">Name</label>
  48. <input type="text" name="name" id="name" placeholder="Name" value="{{project.name}}" />
  49. </div>
  50. <div>
  51. <label for="description">Description</label>
  52. <input type="text" name="description" id="description" placeholder="Description"
  53. value="{{project.description}}" />
  54. </div>
  55. <div>
  56. <label for="tags">Tags</label>
  57. <input type="text" name="tags" id="tags" placeholder="Tags,seperated,by,commas"
  58. value="{{project.tags}}" />
  59. </div>
  60. <label for="estimated_quarter_days">Estimated Quarter Work Days</label>
  61. <input type="number" id="estimated_quarter_days" name="estimated_quarter_days" min="1" max="1000"
  62. value="{{project.estimated_quarter_days}}">
  63. <label for="start">Start Date</label>
  64. <input id="start" type="date" name="start" />
  65. <label for="due">Due Date</label>
  66. <input id="due" type="date" name="due" />
  67. <div>
  68. <input type="submit" class="add_button"
  69. value="{% if project.name.len() == 0 %}Create Project!{%else%}Update Project{% endif %}" />
  70. </div>
  71. </form>
  72. </div>
  73. </div>
  74. </div>
  75. </div>
  76. <div class="tab-content">
  77. {% if project.key.to_string() != "00000000-0000-0000-0000-000000000000" %}
  78. {% if tasks.len() > 0 %}
  79. <div class="backed">
  80. <h2>Task List</h2>
  81. <label for="filter">Filter Tasks</label>
  82. <input type="text" name="filter" id="task_filter" placeholder="" value="" />
  83. {% for task in tasks %}
  84. <div class="white-backed bump col-sm-12 col-md-4 col-lg-3">
  85. <a href="/task/{{task.key}}">
  86. <p><b>{{task.name}}</b></p>
  87. <hr />
  88. <p>{{task.description}}</p>
  89. </a>
  90. </div>
  91. {%endfor %}
  92. </ul>
  93. </div>
  94. {% else %}
  95. <div class="row white-backed">
  96. <div class="col-sm-12 col-md-12 col-lg-12">
  97. <h3>Create your first task</h3>
  98. <h4>Items of work, meetings to schedule, phone calls to make and schedule service visits.</h4>
  99. <h4>Breaking your projects down into tasks no matter how granular you need them, can help you schedule,
  100. visualize, estimate and execute without the chaos.</h4>
  101. </div>
  102. <div class="col-sm-12 col-md-12col-lg-12">
  103. <a class="button" href="/task/add/{{project.key}}">Add New Task</a>
  104. </div>
  105. </div>
  106. {% endif %}
  107. {% endif %}
  108. </div>
  109. <div class="tab-content">
  110. {% if project.key.to_string() != "00000000-0000-0000-0000-000000000000" %}
  111. {% if milestones.len() > 0 %}
  112. <div class="backed">
  113. <h2>Milestones</h2>
  114. <label for="filter">Filter Milestones</label>
  115. <input type="text" name="filter" id="task_filter" placeholder="" value="" />
  116. {% for milestone in milestones %}
  117. <div class="white-backed bump col-sm-12 col-md-4 col-lg-3">
  118. <a href="/milestone/{{milestone.key}}">
  119. <p><b>{{milestone.name}}</b></p>
  120. <hr />
  121. <p>{{milestone.description}}</p>
  122. </a>
  123. </div>
  124. {%endfor %}
  125. </div>
  126. {% else %}
  127. <div class="row white-backed">
  128. <div class="col-sm-12 col-md-12 col-lg-12">
  129. <h3>Create your Milestone</h3>
  130. <h4>Define a set of tasks that can comprise your projects milestones</h4>
  131. <h4>Besides knowing you're that much closer to completion, automation of invoicing, reporting and even
  132. sending a congratulatory gif to team channels is all at your finger tips.</h4>
  133. </div>
  134. <div class="col-sm-12 col-md-12col-lg-12">
  135. <a class="button" href="/milestone/add/{{project.key}}">Add New Milestone</a>
  136. </div>
  137. </div>
  138. {% endif %}
  139. {% endif %}
  140. </div>
  141. <div class="tab-content">
  142. <div class="row justified ">
  143. <div class="col-sm-12 col-md-6 col-lg-6">
  144. {% if notes.len() > 0 %}
  145. <h3>Notes & Docs</h3>
  146. {% for note in notes %}
  147. <div class="white-backed bump col-sm-12 col-md-4 col-lg-3">
  148. <a href="/note/{{note.key}}">
  149. <p><b>{{note.title}}</b></p>
  150. </a>
  151. </div>
  152. {% endfor %}
  153. {%else%}
  154. <div class="white-backed">
  155. <div class="col-sm-12 col-md-12 col-lg-12">
  156. <h3>Add Your First Note</h3>
  157. <h4>Create a note at the project level, project onboarding, project style guides and any project
  158. notes that you want organized under this project</h4>
  159. </div>
  160. <div class="col-sm-12 col-md-12 col-lg-12">
  161. <a class="button" href="/note/add/Project/{{project.key}}">Add Note</a>
  162. </div>
  163. </div>
  164. {% endif %}
  165. </div>
  166. <div class="col-sm-12 col-md-6 col-lg-6">
  167. {% if files.len() > 0 %}
  168. <h3>Files</h3>
  169. {% for file in files %}
  170. <div class="white-backed bump col-sm-12 col-md-4 col-lg-3">
  171. <a href="/file/{{file.key}}">
  172. <p><b>{{file.name}}</b></p>
  173. <hr />
  174. <p>{{file.description}}</p>
  175. </a>
  176. </div>
  177. {% endfor %}
  178. {%else%}
  179. <div class="white-backed">
  180. <div class="col-sm-12 col-md-12 col-lg-12">
  181. <h3>Attach Your First File</h3>
  182. <h4>Attach a file to be visible for the project. Easily share and access files you store here.</h4>
  183. </div>
  184. <div class="col-sm-12 col-md-12 col-lg-12">
  185. <a class="button" href="/file/add/Project/{{project.key}}">Add File</a>
  186. </div>
  187. </div>
  188. {% endif %}
  189. </div>
  190. </div>
  191. </div>
  192. <div class="tab-content">
  193. <div class="row white-backed">
  194. <div class="col-sm-12 col-md-12 col-lg-12">
  195. <div class="dots">
  196. {% for status in crate::task::TaskStatus::iter() %}
  197. <span class="dot"
  198. style="background-color: {{ Self::get_task_background_color(self, status) }};">{{status.to_string()}}</span>
  199. {% endfor %}
  200. </div>
  201. <div class="gantt">
  202. <div class="head">Mon</div>
  203. <div class="head">Tue</div>
  204. <div class="head">Wed</div>
  205. <div class="head">Thur</div>
  206. <div class="head">Fri</div>
  207. <div class="head">Sat</div>
  208. <div class="head">Sun</div>
  209. {% for task in tasks %}
  210. <div
  211. style="background: {{ Self::get_task_background_color(self, task.status) }}; grid-row: {{loop.index+1}}; grid-column: {{Self::get_grid_column(self, task.start, task.due)}}">
  212. <a href="/task/{{task.key}}">{{task.name}}</a>
  213. </div>
  214. {% endfor %}
  215. </div>
  216. </div>
  217. </div>
  218. </div>
  219. <div class="tab-content">
  220. <div class="row white-backed">
  221. <div class="col-sm-12 col-md-12 col-lg-12">
  222. <div id="calendar"></div>
  223. </div>
  224. </div>
  225. </div>
  226. </div>
  227. </div>
  228. </div>
  229. </div>
  230. </div>
  231. <script>
  232. window.addEventListener('load', function () {
  233. {% if !project.key.is_nil() %}
  234. send_delete("delete", "/project/{{project.key}}", (deleted, res) => {
  235. if (deleted) {
  236. window.location.href = `/`
  237. }
  238. })
  239. {% endif %}
  240. let due = parseInt("{{project.due}}");
  241. document.getElementById("due").value = (due == 0 ? new Date() : new Date(due * 1000)).toISOString().split('T')[0]
  242. let start = parseInt("{{project.start}}");
  243. document.getElementById("start").value = (start == 0 ? new Date() : new Date(start * 1000)).toISOString().split('T')[0]
  244. post_form("add_project_form", "/project", data => {
  245. const key = "{{project.key}}"
  246. data.key = key == "" ? "00000000-0000-0000-0000-000000000000" : key
  247. data.organization_key = "{{user.organization_key}}"
  248. data.owner_key = "{{user.key}}"
  249. data.estimated_quarter_days = num_from_string(data.estimated_quarter_days)
  250. data.start = Math.floor(new Date(data.start).getTime() / 1000);
  251. data.due = Math.floor(new Date(data.due).getTime() / 1000);
  252. data.name = data.name || "";
  253. data.description = data.description || "";
  254. data.tags = data.tags || "";
  255. data.created = data.created || 0;
  256. data.updated = data.updated || 0;
  257. return data;
  258. }, (response_text) => {
  259. const object = JSON.parse(response_text);
  260. window.location.href = `/project/${object.key}`
  261. });
  262. var calendarElement = document.getElementById("calendar");
  263. var cal = new calendarJs(calendarElement);
  264. {% for task in tasks %}
  265. cal.addEvent({
  266. from: new Date({{ task.start * 1000 }}),
  267. to: new Date({{ task.due * 1000 }}),
  268. title: "{{task.name}}",
  269. description: "{{task.description}}"
  270. });
  271. {% endfor %}
  272. });
  273. </script>
  274. {% endblock %}