tables.py 24 KB

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