Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import re 

2from django.db import models 

3from django.utils.translation import gettext_lazy as _ 

4from django.core.exceptions import ValidationError 

5 

6from filer.fields.image import FilerImageField 

7from cms.models import CMSPlugin 

8from djangocms_link.models import AbstractLink 

9from djangocms_text_ckeditor.fields import HTMLField 

10from djangocms_picture.models import AbstractPicture 

11from cms.models.fields import PlaceholderField 

12from filer.fields.file import FilerFileField 

13 

14from .constants import TAB_TYPE_CHOICES, STAFF_LISTING_CHOICES 

15 

16class UnimelbTab(CMSPlugin): 

17 """ 

18 Creates a tab using the Unimelb theme. 

19 

20 See https://web.unimelb.edu.au/components/tabs 

21 

22 Based on https://github.com/django-cms/djangocms-bootstrap4/blob/master/djangocms_bootstrap4/contrib/bootstrap4_tabs/ 

23 """ 

24 tab_type = models.CharField( 

25 verbose_name=_('Type'), 

26 choices=TAB_TYPE_CHOICES, 

27 default=TAB_TYPE_CHOICES[0][0], 

28 max_length=255, 

29 ) 

30 tab_index = models.PositiveIntegerField( 

31 verbose_name=_('Index'), 

32 null=True, 

33 blank=True, 

34 help_text=_('Index of element to open on page load starting at 1.'), 

35 default=1, 

36 ) 

37 

38 def __str__(self): 

39 return f"{self.tab_type}" 

40 

41 def get_short_description(self): 

42 text = '({})'.format(self.tab_type) 

43 

44 return text 

45 

46 

47class UnimelbTabItem(CMSPlugin): 

48 """ 

49 Creates an item in a tab using the Unimelb theme. 

50 

51 See https://web.unimelb.edu.au/components/tabs 

52 """ 

53 tab_title = models.CharField( 

54 verbose_name=_('Tab title'), 

55 max_length=255, 

56 ) 

57 

58 def __str__(self): 

59 return self.tab_title 

60 

61 def get_short_description(self): 

62 return self.tab_title 

63 

64 

65class UnimelbStaffListing(CMSPlugin): 

66 """ 

67 Adds a listing of staff members 

68 

69 https://web.unimelb.edu.au/components/people  

70 """ 

71 listing_type = models.CharField( 

72 verbose_name=_('Type'), 

73 choices=STAFF_LISTING_CHOICES, 

74 default=STAFF_LISTING_CHOICES[0][0], 

75 max_length=255, 

76 ) 

77 

78 def __str__(self): 

79 return f"{self.pk}" 

80 

81 

82class UnimelbStaffMember(CMSPlugin): 

83 """ 

84 Adds a listing of staff members 

85 

86 https://web.unimelb.edu.au/components/people  

87 """ 

88 name = models.CharField(max_length=255) 

89 url = models.CharField( 

90 verbose_name=_('URL'), 

91 max_length=1023, 

92 blank=True, 

93 default="", 

94 ) 

95 image = FilerImageField( 

96 blank=True, 

97 null=True, 

98 default=None, 

99 on_delete=models.SET_NULL, 

100 related_name='+', 

101 help_text="An image of this staff member." 

102 ) 

103 image_external_url = models.CharField( 

104 max_length=1023, 

105 blank=True, 

106 default="", 

107 help_text="An external URL to an image for this staff member. This is only used if the 'image' field is empty.", 

108 ) 

109 title = models.CharField(max_length=255, blank=True, default="") 

110 institution = models.CharField(max_length=255, blank=True, default="", help_text="e.g. University of Melbourne") 

111 

112 def __str__(self): 

113 return self.name 

114 

115 def image_url(self): 

116 if self.image: 

117 return self.image.url 

118 return self.image_external_url 

119 

120 

121class UnimelbHeading(CMSPlugin): 

122 """ 

123 https://web.unimelb.edu.au/components/headings 

124 """ 

125 text = models.CharField(max_length=255, blank=True, help_text="If blank then it takes the title of the current page or tab item.") 

126 aligned = models.BooleanField(default=False, blank=True) 

127 padding_top = models.CharField(max_length=255, blank=True, help_text="e.g. 2.0rem") 

128 

129 def __str__(self): 

130 return self.text 

131 

132 

133class UnimelbHeader(CMSPlugin): 

134 """ 

135 https://web.unimelb.edu.au/components/headers 

136 """ 

137 heading = models.CharField(max_length=255, default="", blank=True, help_text="The heading for the banner.") 

138 subline = models.CharField(max_length=1023, default="", blank=True) 

139 image = FilerImageField( 

140 blank=True, 

141 null=True, 

142 default=None, 

143 on_delete=models.SET_NULL, 

144 related_name='+', 

145 help_text="The image to use in the background of the banner." 

146 ) 

147 tint = models.CharField( 

148 max_length=255, 

149 default="", 

150 blank=True, 

151 help_text="A colour to tint the header image. e.g. rgba(16, 41, 80, 0.7)", 

152 ) 

153 messages = models.BooleanField(default=True,help_text="Displays alert messages underneath header.") 

154 

155 def __str__(self): 

156 if self.heading: 

157 return self.heading 

158 if self.subline: 

159 return self.subline 

160 if self.image: 

161 return str(self.image) 

162 return str(self.pk) 

163 

164 

165class UnimelbFooter(CMSPlugin): 

166 light = models.BooleanField(default=False, help_text="If the background colour should be light.") 

167 

168 

169IconChoices = models.TextChoices('IconChoices', 'add bar bike bus cafe campaign car cart chat chevron-right check check-circle city clock close computer cutlery delete devices download edit ellipsis face facebook faculty flight group home hr instagram jobs library linkedin location lock mail map menu money pharmacy phone print profile rss search send share smartphone student tag train twitter vimeo walk world youtube zoom-in zoom-out question info info-outline'.title()) 

170 

171 

172class UnimelbFooterLink(AbstractLink): 

173 text = models.CharField(max_length=31, default="", blank=True, help_text="The text to accompany the link.") 

174 icon = models.CharField(max_length=31, default="", blank=True, choices=IconChoices.choices) 

175 

176 

177class UnimelbBlockListing(CMSPlugin): 

178 """ 

179 https://web.unimelb.edu.au/components/block-listing 

180 """ 

181 def __str__(self): 

182 return str(self.pk) 

183 

184 

185class MediaLink(AbstractLink): 

186 file = FilerFileField( 

187 blank=True, 

188 null=True, 

189 on_delete=models.SET_NULL, 

190 related_name='+', 

191 ) 

192 class Meta: 

193 abstract = True 

194 

195 def get_link(self): 

196 link = super().get_link() 

197 

198 if not link and self.file: 

199 link = self.file.url 

200 

201 return link 

202 

203 

204class OptionalPicture(AbstractPicture): 

205 class Meta: 

206 abstract = True 

207 

208 def clean(self): 

209 try: 

210 super().clean() 

211 except ValidationError as err: 

212 # TODO Check message 

213 pass 

214 

215 

216BlockListingCategory = models.TextChoices('BlockListingCategory', 'news newshero exhibition event instagram twitter') 

217ImageLocation = models.TextChoices('ImageLocation', 'DEFAULT TOP BACKGROUND') 

218 

219 

220class UnimelbBlockListingItem(OptionalPicture): 

221 """ 

222 https://web.unimelb.edu.au/components/block-listing 

223 

224 See parent: https://github.com/django-cms/djangocms-link/blob/master/djangocms_link/models.py 

225 """ 

226 category = models.CharField(max_length=10, default=BlockListingCategory.news, choices=BlockListingCategory.choices) 

227 heading = models.CharField(max_length=255, default="", blank=True, help_text="The heading for the block listing.") 

228 minor_heading = models.CharField(max_length=255, default="", blank=True, help_text="A secondary heading for the block listing.") 

229 text = HTMLField(default="", blank=True, help_text="The text for the block listing. Only a few lines are visible.") 

230 call_to_action = models.CharField(max_length=255, default="", blank=True, help_text="The text in a call to action button.") 

231 meta_left = models.CharField(max_length=255, default="", blank=True, help_text="The text at the bottom left.") 

232 meta_right = models.CharField(max_length=255, default="", blank=True, help_text="The text at the bottom right.") 

233 double = models.BooleanField(default=False, help_text="Whether or not this block listing should take up two boxes.") 

234 image_location = models.CharField(max_length=10, default=ImageLocation.DEFAULT, choices=ImageLocation.choices, help_text="The location of the image (if present).") 

235 link_is_optional = True 

236 file = FilerFileField( 

237 blank=True, 

238 null=True, 

239 on_delete=models.SET_NULL, 

240 related_name='+', 

241 ) 

242 

243 def __str__(self): 

244 if self.heading: 

245 return self.heading 

246 if self.text: 

247 return self.text 

248 if self.meta_left: 

249 return str(self.meta_left) 

250 return str(self.pk) 

251 

252 def get_short_description(self): 

253 return str(self) 

254 

255 def image_in_backround(self): 

256 if not self.img_src: 

257 return False 

258 if self.image_location == ImageLocation.DEFAULT: 

259 return self.category in ('newshero', 'instagram') 

260 return self.image_location == ImageLocation.BACKGROUND 

261 

262 def image_at_top(self): 

263 if not self.img_src: 

264 return False 

265 return not self.image_in_backround() 

266 

267 def get_link(self): 

268 link = super().get_link() 

269 

270 if not link and self.file: 

271 link = self.file.url 

272 

273 return link 

274 

275 

276 

277class UnimelbPathfinder(CMSPlugin): 

278 """ 

279 https://web.unimelb.edu.au/components/pathfinder 

280 """ 

281 def __str__(self): 

282 return str(self.pk) 

283 

284 def number(self): 

285 return len(child_plugin_instances) 

286 

287 

288class UnimelbPathfinderBox(AbstractLink): 

289 """ 

290 https://web.unimelb.edu.au/components/pathfinder 

291 

292 See parent: https://github.com/django-cms/djangocms-link/blob/master/djangocms_link/models.py 

293 """ 

294 heading = models.CharField(max_length=255, default="", blank=True, help_text="The heading for the pathfinder box.") 

295 text = models.CharField(max_length=1023, default="", blank=True, help_text="The text for the pathfinder box.") 

296 button = models.CharField(max_length=255, default="", blank=True, help_text="The text for the button.") 

297 

298 def __str__(self): 

299 if self.heading: 

300 return self.heading 

301 if self.text: 

302 return self.text 

303 if self.button: 

304 return str(self.button) 

305 return str(self.pk) 

306 

307 def get_short_description(self): 

308 return str(self) 

309 

310 

311class UnimelbSearchForm(AbstractLink): 

312 """ 

313 https://web.unimelb.edu.au/components/search 

314 """ 

315 pass 

316 

317 

318class UnimelbSearchResults(CMSPlugin): 

319 """ 

320 https://web.unimelb.edu.au/components/search 

321 https://github.com/etianen/django-watson 

322 """ 

323 pagination = models.PositiveIntegerField(default=30) 

324 

325 def __str__(self): 

326 return str(self.pk) 

327 

328 

329class UnimelbAccordion(CMSPlugin): 

330 """ 

331 https://web.unimelb.edu.au/components/accordion 

332 https://resources.web.unimelb.edu.au/web-content/creating-content/how-to-use-accordions-well 

333 """ 

334 def __str__(self): 

335 return str(self.pk) 

336 

337 

338class UnimelbAccordionItem(CMSPlugin): 

339 """ 

340 https://web.unimelb.edu.au/components/accordion 

341 https://resources.web.unimelb.edu.au/web-content/creating-content/how-to-use-accordions-well 

342 """ 

343 title = models.CharField(max_length=255) 

344 visible = models.BooleanField(default=False, blank=True) 

345 

346 def __str__(self): 

347 return str(self.title) 

348 

349 

350class UnimelbTimeline(CMSPlugin): 

351 """ 

352 https://web.unimelb.edu.au/components/timeline 

353 https://www.w3schools.com/tags/tag_dl.asp 

354 """ 

355 def __str__(self): 

356 return str(self.pk) 

357 

358 

359class UnimelbTimelineItem(CMSPlugin): 

360 """ 

361 https://web.unimelb.edu.au/components/timeline 

362 https://www.w3schools.com/tags/tag_dl.asp 

363 

364 Shows the 'time' string before the 'bold' string'. 

365 """ 

366 time = models.CharField(max_length=255, default="", blank=True) 

367 bold = models.CharField(max_length=255, default="", blank=True) 

368 

369 def __str__(self): 

370 return re.sub( r"\s+", " ", self.time + " " + self.bold) 

371 

372 

373class UnimelbMessages(CMSPlugin): 

374 """ 

375 https://docs.djangoproject.com/en/3.2/ref/contrib/messages/ 

376 https://web.unimelb.edu.au/components/notices 

377  

378 Displays a message 

379 """ 

380 pass 

381 

382 

383class Status(models.TextChoices): 

384 UNPUBLISHED = 'UN', 'Unpublished' 

385 PUBLISHED = 'PB', 'Published' 

386 

387 

388NoticeType = models.TextChoices('NoticeType', 'success info warning danger') 

389 

390class UnimelbNotice(CMSPlugin): 

391 """ 

392 https://web.unimelb.edu.au/components/notices 

393 """ 

394 notice_type = models.CharField(max_length=7, choices=NoticeType.choices) 

395 dismiss = models.BooleanField(default=False, help_text="Displays a button to dismiss the notice.") 

396 

397 def __str__(self): 

398 return self.notice_type 

399 

400 

401class UnimelbLead(CMSPlugin): 

402 """ 

403 https://web.unimelb.edu.au/components/text 

404 """ 

405 pass 

406 

407 

408BlockquoteStyle = models.TextChoices('BlockquoteStyle', 'classic left right') 

409 

410class UnimelbBlockquote(CMSPlugin): 

411 """ 

412 https://web.unimelb.edu.au/components/text 

413 """ 

414 text = models.CharField(max_length=1023, default="", blank=True) 

415 cite = models.CharField(max_length=255, default="", blank=True) 

416 style = models.CharField(max_length=7, choices=BlockquoteStyle.choices, blank=True, default="") 

417 

418 def __str__(self): 

419 return self.text 

420 

421 def css_class(self): 

422 if self.style == "classic": 

423 return "blockquote-classic" 

424 return self.style 

425 

426 

427class FigureSize(models.TextChoices): 

428 DEFAULT = '', 'Default' 

429 MIN = 'min', 'Min' 

430 MAX = 'max', 'Max' 

431 

432 

433class FigureInset(models.TextChoices): 

434 DEFAULT = '', 'Default' 

435 LEFT = 'left', 'Left' 

436 RIGHT = 'right', 'Right' 

437 

438 

439class UnimelbFigure(AbstractPicture, CMSPlugin): 

440 """ 

441 https://web.unimelb.edu.au/components/figure 

442 """ 

443 confined = models.BooleanField(default=False, help_text="Should the figure be confined to align with the text.") 

444 caption = HTMLField(default="", blank=True) 

445 size = models.CharField(max_length=3, choices=FigureSize.choices, blank=True, default=FigureSize.DEFAULT, help_text="If the figure should shrink to fit its content (min) or expand to its maximum width (max).") 

446 inset = models.CharField(max_length=5, choices=FigureInset.choices, blank=True, default=FigureInset.DEFAULT, help_text="If the figure should be on the left or the right.") 

447 

448 def caption_no_paragraph(self): 

449 return re.sub(r"^\<p\>(.*)\<\/p\>$", r"\1", self.caption ) 

450 

451 

452class UnimelbFigureDiv(CMSPlugin): 

453 """ 

454 https://web.unimelb.edu.au/components/figure 

455 """ 

456 clearfix = models.BooleanField(default=True, help_text="If you don't want the figures to overflow into the content that follows.") 

457 

458 

459class UnimelbArticle(models.Model): 

460 """ 

461 https://web.unimelb.edu.au/components/news 

462 """ 

463 title = models.CharField(max_length=255, help_text="The title of this article to be displayed as a heading and in the listing.") 

464 description = models.CharField(max_length=1023, help_text="A description of this article to be displayed as a summary in the listing.") 

465 content = PlaceholderField('content')