tables.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. import json
  2. import django_tables2 as tables
  3. from django.template.defaultfilters import filesizeformat
  4. from django.utils.html import format_html
  5. from django.utils.translation import gettext_lazy as _
  6. from extras.models import *
  7. from core.tables import JobTable
  8. from core.models import Job
  9. from netbox.constants import EMPTY_TABLE_TEXT
  10. from netbox.events import get_event_text
  11. from netbox.tables import BaseTable, NetBoxTable, columns
  12. from .columns import NotificationActionsColumn
  13. __all__ = (
  14. 'BookmarkTable',
  15. 'ConfigContextProfileTable',
  16. 'ConfigContextTable',
  17. 'ConfigTemplateTable',
  18. 'CustomFieldChoiceSetTable',
  19. 'CustomFieldTable',
  20. 'CustomLinkTable',
  21. 'EventRuleTable',
  22. 'ExportTemplateTable',
  23. 'ImageAttachmentTable',
  24. 'JournalEntryTable',
  25. 'NotificationGroupTable',
  26. 'NotificationTable',
  27. 'SavedFilterTable',
  28. 'ReportResultsTable',
  29. 'ScriptResultsTable',
  30. 'ScriptJobTable',
  31. 'SubscriptionTable',
  32. 'TableConfigTable',
  33. 'TaggedItemTable',
  34. 'TagTable',
  35. 'WebhookTable',
  36. )
  37. IMAGEATTACHMENT_IMAGE = """
  38. {% if record.image %}
  39. <a href="{{ record.image.url }}" target="_blank" class="image-preview" data-bs-placement="top">
  40. <i class="mdi mdi-image"></i></a>
  41. {% endif %}
  42. <a href="{{ record.get_absolute_url }}">{{ record }}</a>
  43. """
  44. NOTIFICATION_ICON = """
  45. <span class="text-{{ value.color }} fs-3"><i class="{{ value.icon }}"></i></span>
  46. """
  47. NOTIFICATION_LINK = """
  48. {% if not record.event.destructive %}
  49. <a href="{% url 'extras:notification_read' pk=record.pk %}">{{ record.object_repr }}</a>
  50. {% else %}
  51. {{ record.object_repr }}
  52. {% endif %}
  53. """
  54. class CustomFieldTable(NetBoxTable):
  55. name = tables.Column(
  56. verbose_name=_('Name'),
  57. linkify=True
  58. )
  59. object_types = columns.ContentTypesColumn(
  60. verbose_name=_('Object Types')
  61. )
  62. required = columns.BooleanColumn(
  63. verbose_name=_('Required'),
  64. false_mark=None
  65. )
  66. unique = columns.BooleanColumn(
  67. verbose_name=_('Validate Uniqueness'),
  68. false_mark=None
  69. )
  70. ui_visible = columns.ChoiceFieldColumn(
  71. verbose_name=_('Visible')
  72. )
  73. ui_editable = columns.ChoiceFieldColumn(
  74. verbose_name=_('Editable')
  75. )
  76. description = columns.MarkdownColumn(
  77. verbose_name=_('Description')
  78. )
  79. related_object_type = columns.ContentTypeColumn(
  80. verbose_name=_('Related Object Type')
  81. )
  82. choice_set = tables.Column(
  83. linkify=True,
  84. verbose_name=_('Choice Set')
  85. )
  86. choices = columns.ChoicesColumn(
  87. max_items=10,
  88. orderable=False,
  89. verbose_name=_('Choices')
  90. )
  91. is_cloneable = columns.BooleanColumn(
  92. verbose_name=_('Is Cloneable'),
  93. false_mark=None
  94. )
  95. validation_minimum = tables.Column(
  96. verbose_name=_('Minimum Value'),
  97. )
  98. validation_maximum = tables.Column(
  99. verbose_name=_('Maximum Value'),
  100. )
  101. validation_regex = tables.Column(
  102. verbose_name=_('Validation Regex'),
  103. )
  104. class Meta(NetBoxTable.Meta):
  105. model = CustomField
  106. fields = (
  107. 'pk', 'id', 'name', 'object_types', 'label', 'type', 'related_object_type', 'group_name', 'required',
  108. 'unique', 'default', 'description', 'search_weight', 'filter_logic', 'ui_visible', 'ui_editable',
  109. 'is_cloneable', 'weight', 'choice_set', 'choices', 'validation_minimum', 'validation_maximum',
  110. 'validation_regex', 'comments', 'created', 'last_updated',
  111. )
  112. default_columns = (
  113. 'pk', 'name', 'object_types', 'label', 'group_name', 'type', 'required', 'unique', 'description',
  114. )
  115. class CustomFieldChoiceSetTable(NetBoxTable):
  116. name = tables.Column(
  117. verbose_name=_('Name'),
  118. linkify=True
  119. )
  120. base_choices = columns.ChoiceFieldColumn()
  121. extra_choices = tables.TemplateColumn(
  122. template_code="""{% for k, v in value.items %}{{ v }}{% if not forloop.last %}, {% endif %}{% endfor %}"""
  123. )
  124. choices = columns.ChoicesColumn(
  125. max_items=10,
  126. orderable=False
  127. )
  128. choice_count = tables.TemplateColumn(
  129. accessor=tables.A('extra_choices'),
  130. template_code='{{ value|length }}',
  131. orderable=False,
  132. verbose_name=_('Count')
  133. )
  134. order_alphabetically = columns.BooleanColumn(
  135. verbose_name=_('Order Alphabetically'),
  136. false_mark=None
  137. )
  138. class Meta(NetBoxTable.Meta):
  139. model = CustomFieldChoiceSet
  140. fields = (
  141. 'pk', 'id', 'name', 'description', 'base_choices', 'extra_choices', 'choice_count', 'choices',
  142. 'order_alphabetically', 'created', 'last_updated',
  143. )
  144. default_columns = ('pk', 'name', 'base_choices', 'choice_count', 'description')
  145. class CustomLinkTable(NetBoxTable):
  146. name = tables.Column(
  147. verbose_name=_('Name'),
  148. linkify=True
  149. )
  150. object_types = columns.ContentTypesColumn(
  151. verbose_name=_('Object Types'),
  152. )
  153. enabled = columns.BooleanColumn(
  154. verbose_name=_('Enabled'),
  155. )
  156. new_window = columns.BooleanColumn(
  157. verbose_name=_('New Window'),
  158. false_mark=None
  159. )
  160. class Meta(NetBoxTable.Meta):
  161. model = CustomLink
  162. fields = (
  163. 'pk', 'id', 'name', 'object_types', 'enabled', 'link_text', 'link_url', 'weight', 'group_name',
  164. 'button_class', 'new_window', 'created', 'last_updated',
  165. )
  166. default_columns = ('pk', 'name', 'object_types', 'enabled', 'group_name', 'button_class', 'new_window')
  167. class ExportTemplateTable(NetBoxTable):
  168. name = tables.Column(
  169. verbose_name=_('Name'),
  170. linkify=True
  171. )
  172. object_types = columns.ContentTypesColumn(
  173. verbose_name=_('Object Types'),
  174. )
  175. mime_type = tables.Column(
  176. verbose_name=_('MIME Type')
  177. )
  178. file_name = tables.Column(
  179. verbose_name=_('File Name'),
  180. )
  181. file_extension = tables.Column(
  182. verbose_name=_('File Extension'),
  183. )
  184. as_attachment = columns.BooleanColumn(
  185. verbose_name=_('As Attachment'),
  186. false_mark=None
  187. )
  188. data_source = tables.Column(
  189. verbose_name=_('Data Source'),
  190. linkify=True
  191. )
  192. data_file = tables.Column(
  193. verbose_name=_('Data File'),
  194. linkify=True
  195. )
  196. is_synced = columns.BooleanColumn(
  197. orderable=False,
  198. verbose_name=_('Synced')
  199. )
  200. class Meta(NetBoxTable.Meta):
  201. model = ExportTemplate
  202. fields = (
  203. 'pk', 'id', 'name', 'object_types', 'description', 'mime_type', 'file_name', 'file_extension',
  204. 'as_attachment', 'data_source', 'data_file', 'data_synced', 'created', 'last_updated',
  205. )
  206. default_columns = (
  207. 'pk', 'name', 'object_types', 'description', 'mime_type', 'file_name', 'file_extension',
  208. 'as_attachment', 'is_synced',
  209. )
  210. class ImageAttachmentTable(NetBoxTable):
  211. id = tables.Column(
  212. verbose_name=_('ID'),
  213. linkify=False
  214. )
  215. image = columns.TemplateColumn(
  216. verbose_name=_('Image'),
  217. template_code=IMAGEATTACHMENT_IMAGE,
  218. attrs={'td': {'class': 'text-nowrap'}}
  219. )
  220. name = tables.Column(
  221. verbose_name=_('Name'),
  222. linkify=True,
  223. )
  224. filename = tables.Column(
  225. verbose_name=_('Filename'),
  226. linkify=lambda record: record.image.url,
  227. orderable=False,
  228. )
  229. dimensions = columns.TemplateColumn(
  230. verbose_name=_('Dimensions'),
  231. orderable=False,
  232. template_code="{{ record.image_width }}×{{ record.image_height }}",
  233. )
  234. object_type = columns.ContentTypeColumn(
  235. verbose_name=_('Object Type'),
  236. )
  237. parent = tables.Column(
  238. verbose_name=_('Object'),
  239. linkify=True,
  240. orderable=False,
  241. )
  242. size = tables.Column(
  243. orderable=False,
  244. verbose_name=_('Size')
  245. )
  246. class Meta(NetBoxTable.Meta):
  247. model = ImageAttachment
  248. fields = (
  249. 'pk', 'object_type', 'parent', 'image', 'name', 'filename', 'description', 'image_height', 'image_width',
  250. 'size', 'created', 'last_updated',
  251. )
  252. default_columns = ('image', 'parent', 'description', 'dimensions', 'size')
  253. def render_size(self, value):
  254. return filesizeformat(value)
  255. def value_size(self, value):
  256. return value
  257. class SavedFilterTable(NetBoxTable):
  258. name = tables.Column(
  259. verbose_name=_('Name'),
  260. linkify=True
  261. )
  262. object_types = columns.ContentTypesColumn(
  263. verbose_name=_('Object Types'),
  264. )
  265. enabled = columns.BooleanColumn(
  266. verbose_name=_('Enabled'),
  267. )
  268. shared = columns.BooleanColumn(
  269. verbose_name=_('Shared'),
  270. false_mark=None
  271. )
  272. def value_parameters(self, value):
  273. return json.dumps(value)
  274. class Meta(NetBoxTable.Meta):
  275. model = SavedFilter
  276. fields = (
  277. 'pk', 'id', 'name', 'slug', 'object_types', 'description', 'user', 'weight', 'enabled', 'shared',
  278. 'created', 'last_updated', 'parameters'
  279. )
  280. default_columns = (
  281. 'pk', 'name', 'object_types', 'user', 'description', 'enabled', 'shared',
  282. )
  283. class TableConfigTable(NetBoxTable):
  284. name = tables.Column(
  285. verbose_name=_('Name'),
  286. linkify=True
  287. )
  288. object_type = columns.ContentTypeColumn(
  289. verbose_name=_('Object Type'),
  290. )
  291. table = tables.Column(
  292. verbose_name=_('Table Name')
  293. )
  294. enabled = columns.BooleanColumn(
  295. verbose_name=_('Enabled'),
  296. )
  297. shared = columns.BooleanColumn(
  298. verbose_name=_('Shared'),
  299. false_mark=None
  300. )
  301. class Meta(NetBoxTable.Meta):
  302. model = TableConfig
  303. fields = (
  304. 'pk', 'id', 'name', 'object_type', 'table', 'description', 'user', 'weight', 'enabled', 'shared', 'created',
  305. 'last_updated',
  306. )
  307. default_columns = (
  308. 'pk', 'name', 'object_type', 'table', 'user', 'description', 'enabled', 'shared',
  309. )
  310. class BookmarkTable(NetBoxTable):
  311. object_type = columns.ContentTypeColumn(
  312. verbose_name=_('Object Type'),
  313. )
  314. object = tables.Column(
  315. verbose_name=_('Object'),
  316. linkify=True,
  317. orderable=False
  318. )
  319. actions = columns.ActionsColumn(
  320. actions=('delete',)
  321. )
  322. class Meta(NetBoxTable.Meta):
  323. model = Bookmark
  324. fields = ('pk', 'object', 'object_type', 'created')
  325. default_columns = ('object', 'object_type', 'created')
  326. class SubscriptionTable(NetBoxTable):
  327. object_type = columns.ContentTypeColumn(
  328. verbose_name=_('Object Type'),
  329. )
  330. object = tables.Column(
  331. verbose_name=_('Object'),
  332. linkify=True,
  333. orderable=False
  334. )
  335. user = tables.Column(
  336. verbose_name=_('User'),
  337. linkify=True
  338. )
  339. actions = columns.ActionsColumn(
  340. actions=('delete',)
  341. )
  342. class Meta(NetBoxTable.Meta):
  343. model = Subscription
  344. fields = ('pk', 'object', 'object_type', 'created', 'user')
  345. default_columns = ('object', 'object_type', 'created')
  346. class NotificationTable(NetBoxTable):
  347. icon = columns.TemplateColumn(
  348. template_code=NOTIFICATION_ICON,
  349. accessor=tables.A('event'),
  350. attrs={
  351. 'td': {'class': 'w-1'},
  352. 'th': {'class': 'w-1'},
  353. },
  354. verbose_name=''
  355. )
  356. object_type = columns.ContentTypeColumn(
  357. verbose_name=_('Object Type'),
  358. )
  359. object = columns.TemplateColumn(
  360. verbose_name=_('Object'),
  361. template_code=NOTIFICATION_LINK,
  362. orderable=False
  363. )
  364. created = columns.DateTimeColumn(
  365. timespec='minutes',
  366. verbose_name=_('Created'),
  367. )
  368. read = columns.DateTimeColumn(
  369. timespec='minutes',
  370. verbose_name=_('Read'),
  371. )
  372. user = tables.Column(
  373. verbose_name=_('User'),
  374. linkify=True
  375. )
  376. actions = NotificationActionsColumn(
  377. actions=('dismiss',)
  378. )
  379. class Meta(NetBoxTable.Meta):
  380. model = Notification
  381. fields = ('pk', 'icon', 'object', 'object_type', 'event_type', 'created', 'read', 'user')
  382. default_columns = ('icon', 'object', 'object_type', 'event_type', 'created')
  383. row_attrs = {
  384. 'data-read': lambda record: bool(record.read),
  385. }
  386. class NotificationGroupTable(NetBoxTable):
  387. name = tables.Column(
  388. linkify=True,
  389. verbose_name=_('Name')
  390. )
  391. users = columns.ManyToManyColumn(
  392. linkify_item=True
  393. )
  394. groups = columns.ManyToManyColumn(
  395. linkify_item=True
  396. )
  397. class Meta(NetBoxTable.Meta):
  398. model = NotificationGroup
  399. fields = ('pk', 'name', 'description', 'groups', 'users')
  400. default_columns = ('name', 'description', 'groups', 'users')
  401. class WebhookTable(NetBoxTable):
  402. name = tables.Column(
  403. verbose_name=_('Name'),
  404. linkify=True
  405. )
  406. ssl_validation = columns.BooleanColumn(
  407. verbose_name=_('SSL Validation')
  408. )
  409. tags = columns.TagColumn(
  410. url_name='extras:webhook_list'
  411. )
  412. class Meta(NetBoxTable.Meta):
  413. model = Webhook
  414. fields = (
  415. 'pk', 'id', 'name', 'http_method', 'payload_url', 'http_content_type', 'secret', 'ssl_verification',
  416. 'ca_file_path', 'description', 'tags', 'created', 'last_updated',
  417. )
  418. default_columns = (
  419. 'pk', 'name', 'http_method', 'payload_url', 'description',
  420. )
  421. class EventRuleTable(NetBoxTable):
  422. name = tables.Column(
  423. verbose_name=_('Name'),
  424. linkify=True
  425. )
  426. action_type = tables.Column(
  427. verbose_name=_('Type'),
  428. )
  429. action_object = tables.Column(
  430. linkify=True,
  431. verbose_name=_('Object'),
  432. )
  433. object_types = columns.ContentTypesColumn(
  434. verbose_name=_('Object Types'),
  435. )
  436. enabled = columns.BooleanColumn(
  437. verbose_name=_('Enabled'),
  438. )
  439. event_types = columns.ArrayColumn(
  440. verbose_name=_('Event Types'),
  441. func=get_event_text,
  442. orderable=False
  443. )
  444. tags = columns.TagColumn(
  445. url_name='extras:webhook_list'
  446. )
  447. class Meta(NetBoxTable.Meta):
  448. model = EventRule
  449. fields = (
  450. 'pk', 'id', 'name', 'enabled', 'description', 'action_type', 'action_object', 'object_types',
  451. 'event_types', 'tags', 'created', 'last_updated',
  452. )
  453. default_columns = (
  454. 'pk', 'name', 'enabled', 'action_type', 'action_object', 'object_types', 'event_types',
  455. )
  456. class TagTable(NetBoxTable):
  457. name = tables.Column(
  458. verbose_name=_('Name'),
  459. linkify=True
  460. )
  461. color = columns.ColorColumn(
  462. verbose_name=_('Color'),
  463. )
  464. object_types = columns.ContentTypesColumn(
  465. verbose_name=_('Object Types'),
  466. )
  467. class Meta(NetBoxTable.Meta):
  468. model = Tag
  469. fields = (
  470. 'pk', 'id', 'name', 'items', 'slug', 'color', 'weight', 'description', 'object_types',
  471. 'created', 'last_updated', 'actions',
  472. )
  473. default_columns = ('pk', 'name', 'items', 'slug', 'color', 'description')
  474. class TaggedItemTable(NetBoxTable):
  475. id = tables.Column(
  476. verbose_name=_('ID'),
  477. linkify=lambda record: record.content_object.get_absolute_url(),
  478. accessor='content_object__id'
  479. )
  480. content_type = columns.ContentTypeColumn(
  481. verbose_name=_('Type')
  482. )
  483. content_object = tables.Column(
  484. linkify=True,
  485. orderable=False,
  486. verbose_name=_('Object')
  487. )
  488. actions = columns.ActionsColumn(
  489. actions=()
  490. )
  491. class Meta(NetBoxTable.Meta):
  492. model = TaggedItem
  493. fields = ('id', 'content_type', 'content_object')
  494. class ConfigContextProfileTable(NetBoxTable):
  495. name = tables.Column(
  496. verbose_name=_('Name'),
  497. linkify=True
  498. )
  499. data_source = tables.Column(
  500. verbose_name=_('Data Source'),
  501. linkify=True
  502. )
  503. data_file = tables.Column(
  504. verbose_name=_('Data File'),
  505. linkify=True
  506. )
  507. is_synced = columns.BooleanColumn(
  508. orderable=False,
  509. verbose_name=_('Synced')
  510. )
  511. tags = columns.TagColumn(
  512. url_name='extras:configcontextprofile_list'
  513. )
  514. class Meta(NetBoxTable.Meta):
  515. model = ConfigContextProfile
  516. fields = (
  517. 'pk', 'id', 'name', 'description', 'comments', 'data_source', 'data_file', 'is_synced', 'tags', 'created',
  518. 'last_updated',
  519. )
  520. default_columns = ('pk', 'name', 'is_synced', 'description')
  521. class ConfigContextTable(NetBoxTable):
  522. profile = tables.Column(
  523. linkify=True,
  524. verbose_name=_('Profile'),
  525. )
  526. data_source = tables.Column(
  527. verbose_name=_('Data Source'),
  528. linkify=True
  529. )
  530. data_file = tables.Column(
  531. verbose_name=_('Data File'),
  532. linkify=True
  533. )
  534. name = tables.Column(
  535. verbose_name=_('Name'),
  536. linkify=True
  537. )
  538. is_active = columns.BooleanColumn(
  539. verbose_name=_('Active')
  540. )
  541. is_synced = columns.BooleanColumn(
  542. orderable=False,
  543. verbose_name=_('Synced')
  544. )
  545. tags = columns.TagColumn(
  546. url_name='extras:configcontext_list'
  547. )
  548. class Meta(NetBoxTable.Meta):
  549. model = ConfigContext
  550. fields = (
  551. 'pk', 'id', 'name', 'weight', 'profile', 'is_active', 'is_synced', 'description', 'regions', 'sites',
  552. 'locations', 'roles', 'platforms', 'cluster_types', 'cluster_groups', 'clusters', 'tenant_groups',
  553. 'tenants', 'data_source', 'data_file', 'data_synced', 'tags', 'created', 'last_updated',
  554. )
  555. default_columns = ('pk', 'name', 'weight', 'profile', 'is_active', 'is_synced', 'description')
  556. class ConfigTemplateTable(NetBoxTable):
  557. name = tables.Column(
  558. verbose_name=_('Name'),
  559. linkify=True
  560. )
  561. data_source = tables.Column(
  562. verbose_name=_('Data Source'),
  563. linkify=True
  564. )
  565. data_file = tables.Column(
  566. verbose_name=_('Data File'),
  567. linkify=True
  568. )
  569. is_synced = columns.BooleanColumn(
  570. orderable=False,
  571. verbose_name=_('Synced')
  572. )
  573. auto_sync_enabled = columns.BooleanColumn(
  574. verbose_name=_('Auto Sync Enabled'),
  575. orderable=False,
  576. )
  577. mime_type = tables.Column(
  578. verbose_name=_('MIME Type')
  579. )
  580. file_name = tables.Column(
  581. verbose_name=_('File Name'),
  582. )
  583. file_extension = tables.Column(
  584. verbose_name=_('File Extension'),
  585. )
  586. as_attachment = columns.BooleanColumn(
  587. verbose_name=_('As Attachment'),
  588. false_mark=None
  589. )
  590. tags = columns.TagColumn(
  591. url_name='extras:configtemplate_list'
  592. )
  593. role_count = columns.LinkedCountColumn(
  594. viewname='dcim:devicerole_list',
  595. url_params={'config_template_id': 'pk'},
  596. verbose_name=_('Device Roles')
  597. )
  598. platform_count = columns.LinkedCountColumn(
  599. viewname='dcim:platform_list',
  600. url_params={'config_template_id': 'pk'},
  601. verbose_name=_('Platforms')
  602. )
  603. device_count = columns.LinkedCountColumn(
  604. viewname='dcim:device_list',
  605. url_params={'config_template_id': 'pk'},
  606. verbose_name=_('Devices')
  607. )
  608. vm_count = columns.LinkedCountColumn(
  609. viewname='virtualization:virtualmachine_list',
  610. url_params={'config_template_id': 'pk'},
  611. verbose_name=_('Virtual Machines')
  612. )
  613. class Meta(NetBoxTable.Meta):
  614. model = ConfigTemplate
  615. fields = (
  616. 'pk', 'id', 'name', 'description', 'data_source', 'data_file', 'data_synced', 'as_attachment',
  617. 'mime_type', 'file_name', 'file_extension', 'role_count', 'platform_count', 'device_count',
  618. 'vm_count', 'created', 'last_updated', 'tags',
  619. )
  620. default_columns = (
  621. 'pk', 'name', 'description', 'is_synced', 'device_count', 'vm_count',
  622. )
  623. class JournalEntryTable(NetBoxTable):
  624. created = columns.DateTimeColumn(
  625. verbose_name=_('Created'),
  626. timespec='minutes',
  627. linkify=True
  628. )
  629. assigned_object_type = columns.ContentTypeColumn(
  630. verbose_name=_('Object Type')
  631. )
  632. assigned_object = tables.Column(
  633. linkify=True,
  634. orderable=False,
  635. verbose_name=_('Object')
  636. )
  637. kind = columns.ChoiceFieldColumn(
  638. verbose_name=_('Kind'),
  639. )
  640. comments = columns.MarkdownColumn(
  641. verbose_name=_('Comments'),
  642. )
  643. comments_short = tables.TemplateColumn(
  644. accessor=tables.A('comments'),
  645. template_code='{{ value|markdown|truncatewords_html:50 }}',
  646. verbose_name=_('Comments (Short)')
  647. )
  648. tags = columns.TagColumn(
  649. url_name='extras:journalentry_list'
  650. )
  651. class Meta(NetBoxTable.Meta):
  652. model = JournalEntry
  653. fields = (
  654. 'pk', 'id', 'created', 'created_by', 'assigned_object_type', 'assigned_object', 'kind', 'comments',
  655. 'comments_short', 'tags', 'actions',
  656. )
  657. default_columns = (
  658. 'pk', 'created', 'created_by', 'assigned_object_type', 'assigned_object', 'kind', 'comments'
  659. )
  660. class ScriptResultsTable(BaseTable):
  661. index = tables.Column(
  662. verbose_name=_('Line')
  663. )
  664. time = columns.DateTimeColumn(
  665. verbose_name=_('Time'),
  666. timespec='seconds'
  667. )
  668. status = tables.TemplateColumn(
  669. template_code="""{% load log_levels %}{% log_level record.status %}""",
  670. verbose_name=_('Level')
  671. )
  672. object = tables.Column(
  673. verbose_name=_('Object')
  674. )
  675. message = columns.MarkdownColumn(
  676. verbose_name=_('Message')
  677. )
  678. class Meta(BaseTable.Meta):
  679. empty_text = _(EMPTY_TABLE_TEXT)
  680. fields = (
  681. 'index', 'time', 'status', 'object', 'message',
  682. )
  683. default_columns = (
  684. 'index', 'time', 'status', 'object', 'message',
  685. )
  686. def render_object(self, value, record):
  687. return format_html("<a href='{}'>{}</a>", record['url'], value)
  688. def render_url(self, value):
  689. return format_html("<a href='{}'>{}</a>", value, value)
  690. class ScriptJobTable(JobTable):
  691. id = tables.TemplateColumn(
  692. template_code="""<a href="{% url 'extras:script_result' job_pk=record.pk %}">{{ record.id }}</a>""",
  693. verbose_name=_('ID'),
  694. )
  695. class Meta(NetBoxTable.Meta):
  696. model = Job
  697. fields = (
  698. 'pk', 'id', 'object_type', 'object', 'name', 'status', 'created', 'scheduled', 'interval', 'started',
  699. 'completed', 'user', 'error', 'job_id',
  700. )
  701. default_columns = (
  702. 'pk', 'id', 'object_type', 'object', 'name', 'status', 'created', 'started', 'completed', 'user',
  703. )
  704. class ReportResultsTable(BaseTable):
  705. index = tables.Column(
  706. verbose_name=_('Line')
  707. )
  708. method = tables.Column(
  709. verbose_name=_('Method')
  710. )
  711. time = tables.Column(
  712. verbose_name=_('Time')
  713. )
  714. status = tables.TemplateColumn(
  715. template_code="""{% load log_levels %}{% log_level record.status %}""",
  716. verbose_name=_('Level')
  717. )
  718. object = tables.Column(
  719. verbose_name=_('Object')
  720. )
  721. url = tables.Column(
  722. verbose_name=_('URL')
  723. )
  724. message = columns.MarkdownColumn(
  725. verbose_name=_('Message')
  726. )
  727. class Meta(BaseTable.Meta):
  728. empty_text = _(EMPTY_TABLE_TEXT)
  729. fields = (
  730. 'index', 'method', 'time', 'status', 'object', 'url', 'message',
  731. )
  732. def render_object(self, value, record):
  733. return format_html("<a href='{}'>{}</a>", record['url'], value)
  734. def render_url(self, value):
  735. return format_html("<a href='{}'>{}</a>", value, value)