cv_view.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. const { form, button, div, h2, p, section, textarea, label, input, br, img, a, select, option } = require("../server/node_modules/hyperaxe");
  2. const { template, i18n } = require('./main_views');
  3. const { renderUrl } = require('../backend/renderUrl');
  4. const generateCVBox = (label, content, className) => {
  5. return div({ class: `cv-box ${className}` },
  6. h2(label),
  7. content
  8. );
  9. };
  10. const generateTags = (tags) => {
  11. return tags && tags.length
  12. ? div(
  13. tags.map(tag =>
  14. a({
  15. href: `/search?query=%23${encodeURIComponent(tag)}`,
  16. class: "tag-link",
  17. style: "margin-right:0.8em;margin-bottom:0.5em;"
  18. }, `#${tag}`)
  19. )
  20. )
  21. : null;
  22. };
  23. exports.createCVView = async (cv = {}, editMode = false) => {
  24. const title = editMode ? i18n.cvEditSectionTitle : i18n.cvCreateSectionTitle;
  25. return template(
  26. title,
  27. section(
  28. div({ class: "tags-header" },
  29. h2(title),
  30. p(i18n.cvDescription)
  31. ),
  32. div({ class: "cv-form" },
  33. form({
  34. method: "POST",
  35. action: editMode ? `/cv/update/${encodeURIComponent(cv.id)}` : "/cv/upload",
  36. enctype: "multipart/form-data"
  37. },
  38. generateCVBox(i18n.cvPersonal, [
  39. label(i18n.cvNameLabel), br(),
  40. input({ type: "text", name: "name", required: true, value: cv.name || "" }), br(),
  41. label(i18n.cvDescriptionLabel), br(),
  42. textarea({ name: "description", required: true, rows: 4 }, cv.description || ""), br(),
  43. label(i18n.cvLanguagesLabel), br(),
  44. input({ type: "text", name: "languages", value: cv.languages || "" }), br(),
  45. label(i18n.cvPhotoLabel), br(),
  46. input({ type: "file", name: "image" }), br(), br(),
  47. label(i18n.cvPersonalExperiencesLabel), br(),
  48. textarea({ name: "personalExperiences", rows: 4 }, cv.personalExperiences || ""), br(),
  49. label(i18n.cvPersonalSkillsLabel), br(),
  50. input({ type: "text", name: "personalSkills", required: true, value: (cv.personalSkills || []).join(", ") }), br()
  51. ], "personal"),
  52. generateCVBox(i18n.cvOasis, [
  53. label(i18n.cvOasisExperiencesLabel), br(),
  54. textarea({ name: "oasisExperiences", rows: 4 }, cv.oasisExperiences || ""), br(),
  55. label(i18n.cvOasisSkillsLabel), br(),
  56. input({ type: "text", name: "oasisSkills", value: (cv.oasisSkills || []).join(", ") }), br()
  57. ], "oasis"),
  58. generateCVBox(i18n.cvEducational, [
  59. label(i18n.cvEducationExperiencesLabel), br(),
  60. textarea({ name: "educationExperiences", rows: 4 }, cv.educationExperiences || ""), br(),
  61. label(i18n.cvEducationalSkillsLabel), br(),
  62. input({ type: "text", name: "educationalSkills", value: (cv.educationalSkills || []).join(", ") }), br()
  63. ], "education"),
  64. generateCVBox(i18n.cvProfessional, [
  65. label(i18n.cvProfessionalExperiencesLabel), br(),
  66. textarea({ name: "professionalExperiences", rows: 4 }, cv.professionalExperiences || ""), br(),
  67. label(i18n.cvProfessionalSkillsLabel), br(),
  68. input({ type: "text", name: "professionalSkills", value: (cv.professionalSkills || []).join(", ") }), br()
  69. ], "professional"),
  70. generateCVBox(i18n.cvAvailability, [
  71. label(i18n.cvLocationLabel), br(),
  72. input({ type: "text", name: "location", required: true, value: cv.location || "UNKNOWN" }), br(),
  73. label(i18n.cvStatusLabel), br(),
  74. select({ name: "status", required: true },
  75. option({ value: "AVAILABLE", selected: cv.status === "AVAILABLE FOR COLLABORATION" }, "AVAILABLE FOR COLLABORATION"),
  76. option({ value: "UNAVAILABLE", selected: cv.status === "NOT CURRENTLY AVAILABLE" }, "NOT CURRENTLY AVAILABLE"),
  77. option({ value: "LOOKING FOR WORK", selected: !cv.status || cv.status === "LOOKING FOR WORK" }, "LOOKING FOR WORK")
  78. ), br(), br(),
  79. label(i18n.cvPreferencesLabel), br(),
  80. select({ name: "preferences", required: true },
  81. option({ value: "IN PERSON", selected: cv.preferences === "IN-PERSON ONLY" }, "IN-PERSON ONLY"),
  82. option({ value: "REMOTE WORKING", selected: !cv.preferences || cv.preferences === "REMOTE WORKING" }, "REMOTE-WORKING")
  83. ), br()
  84. ], "availability"),
  85. button({ type: "submit" }, editMode ? i18n.cvUpdateButton : i18n.cvCreateButton)
  86. )
  87. )
  88. )
  89. )
  90. };
  91. exports.cvView = async (cv) => {
  92. const title = i18n.cvTitle;
  93. if (!cv) {
  94. return template(
  95. title,
  96. section(
  97. div({ class: "tags-header" },
  98. h2(title),
  99. p(i18n.cvDescription)
  100. ),
  101. div({ class: "no-cv" },
  102. p(i18n.cvNoCV),
  103. form({ method: "GET", action: "/cv/create" },
  104. button({ type: "submit" }, i18n.cvCreateButton)
  105. )
  106. )
  107. )
  108. )
  109. }
  110. const hasPersonal = cv.contact || cv.name || cv.description || cv.photo || typeof cv.oasisContributor === "boolean" || (cv.personalSkills && cv.personalSkills.length);
  111. const hasPersonalExp = cv.personalExperiences;
  112. const hasOasis = cv.oasisExperiences || (cv.oasisSkills && cv.oasisSkills.length);
  113. const hasEducational = cv.educationExperiences || cv.languages || (cv.educationalSkills && cv.educationalSkills.length);
  114. const hasProfessional = cv.professionalExperiences || (cv.professionalSkills && cv.professionalSkills.length);
  115. const hasAvailability = cv.location || cv.status || cv.preferences;
  116. return template(
  117. title,
  118. section(
  119. div({ class: "tags-header" },
  120. h2(title),
  121. p(i18n.cvDescription)
  122. ),
  123. div({ class: "cv-section" },
  124. div({ class: "cv-item" }, ...[
  125. div({ class: "cv-actions" },
  126. form({ method: "GET", action: `/cv/edit/${encodeURIComponent(cv.id)}` },
  127. button({ type: "submit" }, i18n.cvEditButton)
  128. ),
  129. form({ method: "POST", action: `/cv/delete/${encodeURIComponent(cv.id)}` },
  130. button({ type: "submit" }, i18n.cvDeleteButton)
  131. )
  132. ),
  133. div({ class: "cv-meta" },
  134. p(`${i18n.cvCreatedAt}: ${new Date(cv.createdAt).toLocaleString()}`),
  135. cv.updatedAt ? p(`${i18n.cvUpdatedAt}: ${new Date(cv.updatedAt).toLocaleString()}`) : null
  136. ),
  137. hasPersonal ? div({ class: "cv-box personal" }, ...[
  138. cv.photo
  139. ? img({
  140. src: `/blob/${encodeURIComponent(cv.photo)}`,
  141. class: "cv-photo"
  142. })
  143. : null,
  144. cv.name ? h2(`${cv.name}`) : null,
  145. cv.contact ? p(a({ class: "user-link", href: `/author/${encodeURIComponent(cv.contact)}` }, cv.contact)) : null,
  146. cv.description ? p(...renderUrl(`${cv.description}`)) : null,
  147. (cv.personalSkills && cv.personalSkills.length)
  148. ? div(
  149. cv.personalSkills.map(tag =>
  150. a({
  151. href: `/search?query=%23${encodeURIComponent(tag)}`,
  152. class: "tag-link",
  153. style: "margin-right:0.8em;margin-bottom:0.5em;"
  154. }, `#${tag}`)
  155. )
  156. )
  157. : null
  158. ]) : null,
  159. hasPersonal ? div({ class: "cv-box personal" }, ...[
  160. h2(i18n.cvLanguagesLabel),
  161. cv.languages ? p(`${cv.languages.toUpperCase()}`) : null
  162. ]) : null,
  163. hasEducational ? div({ class: "cv-box education" }, ...[
  164. h2(i18n.cvEducationalView),
  165. cv.educationExperiences ? p(...renderUrl(`${cv.educationExperiences}`)) : null,
  166. (cv.educationalSkills && cv.educationalSkills.length)
  167. ? div(
  168. cv.educationalSkills.map(tag =>
  169. a({
  170. href: `/search?query=%23${encodeURIComponent(tag)}`,
  171. class: "tag-link",
  172. style: "margin-right:0.8em;margin-bottom:0.5em;"
  173. }, `#${tag}`)
  174. )
  175. )
  176. : null
  177. ]) : null,
  178. hasProfessional ? div({ class: "cv-box professional" }, ...[
  179. h2(i18n.cvProfessionalView),
  180. cv.professionalExperiences ? p(...renderUrl(`${cv.professionalExperiences}`)) : null,
  181. (cv.professionalSkills && cv.professionalSkills.length)
  182. ? div(
  183. cv.professionalSkills.map(tag =>
  184. a({
  185. href: `/search?query=%23${encodeURIComponent(tag)}`,
  186. class: "tag-link",
  187. style: "margin-right:0.8em;margin-bottom:0.5em;"
  188. }, `#${tag}`)
  189. )
  190. )
  191. : null
  192. ]) : null,
  193. hasOasis ? div({ class: "cv-box oasis" }, ...[
  194. h2(i18n.cvOasisContributorView),
  195. p(...renderUrl(`${cv.oasisExperiences}`)),
  196. (cv.oasisSkills && cv.oasisSkills.length)
  197. ? div(
  198. cv.oasisSkills.map(tag =>
  199. a({
  200. href: `/search?query=%23${encodeURIComponent(tag)}`,
  201. class: "tag-link",
  202. style: "margin-right:0.8em;margin-bottom:0.5em;"
  203. }, `#${tag}`)
  204. )
  205. )
  206. : null
  207. ]) : null,
  208. hasAvailability ? div({ class: "cv-box availability" }, ...[
  209. h2(i18n.cvAvailabilityView),
  210. cv.location ? p(`${i18n.cvLocationLabel}: ${cv.location}`) : null,
  211. cv.status ? p(`${i18n.cvStatusLabel}: ${cv.status}`) : null,
  212. cv.preferences ? p(`${i18n.cvPreferencesLabel}: ${cv.preferences}`) : null
  213. ]) : null
  214. ])
  215. )
  216. )
  217. );
  218. };