django-spire 0.17.11__py3-none-any.whl → 0.18.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. django_spire/consts.py +1 -1
  2. django_spire/contrib/seeding/model/base.py +1 -1
  3. django_spire/knowledge/entry/services/automation_service.py +7 -4
  4. django_spire/knowledge/entry/services/transformation_services.py +2 -2
  5. django_spire/knowledge/entry/version/block/choices.py +1 -2
  6. django_spire/knowledge/entry/version/block/data/data.py +33 -0
  7. django_spire/knowledge/entry/version/block/data/heading_data.py +15 -0
  8. django_spire/knowledge/entry/version/block/data/list/choices.py +17 -0
  9. django_spire/knowledge/entry/version/block/data/list/data.py +102 -0
  10. django_spire/knowledge/entry/version/block/data/list/maps.py +14 -0
  11. django_spire/knowledge/entry/version/block/data/list/meta.py +15 -0
  12. django_spire/knowledge/entry/version/block/data/maps.py +23 -0
  13. django_spire/knowledge/entry/version/block/data/text_data.py +13 -0
  14. django_spire/knowledge/entry/version/block/models.py +22 -14
  15. django_spire/knowledge/entry/version/block/querysets.py +17 -7
  16. django_spire/knowledge/entry/version/block/seeding/constants.py +271 -188
  17. django_spire/knowledge/entry/version/block/services/factory_service.py +14 -47
  18. django_spire/knowledge/entry/version/block/services/service.py +2 -12
  19. django_spire/knowledge/entry/version/block/tests/factories.py +18 -2
  20. django_spire/knowledge/entry/version/converters/markdown_converter.py +180 -105
  21. django_spire/knowledge/entry/version/maps.py +1 -1
  22. django_spire/knowledge/entry/version/models.py +1 -0
  23. django_spire/knowledge/entry/version/querysets.py +11 -1
  24. django_spire/knowledge/entry/version/seeding/seeder.py +4 -2
  25. django_spire/knowledge/entry/version/services/processor_service.py +18 -0
  26. django_spire/knowledge/entry/version/services/tests/test_processor_service.py +0 -0
  27. django_spire/knowledge/entry/version/tests/test_urls/test_json_urls.py +7 -24
  28. django_spire/knowledge/entry/version/urls/__init__.py +0 -3
  29. django_spire/knowledge/entry/version/urls/json_urls.py +5 -13
  30. django_spire/knowledge/entry/version/views/json_views.py +8 -76
  31. django_spire/knowledge/entry/version/views/page_views.py +10 -5
  32. django_spire/knowledge/migrations/0005_entryversionblock__tunes_data_and_more.py +23 -0
  33. django_spire/knowledge/migrations/0006_alter_entryversionblock_type.py +18 -0
  34. django_spire/knowledge/static/django_spire/knowledge/css/navigation_items.css +1 -1
  35. django_spire/knowledge/static/django_spire/knowledge/entry/version/js/editor.js +87 -0
  36. django_spire/knowledge/static/django_spire/knowledge/entry/version/js/null_paragraph.js +15 -0
  37. django_spire/knowledge/templates/django_spire/knowledge/entry/file/page/list_page.html +1 -1
  38. django_spire/knowledge/templates/django_spire/knowledge/entry/version/container/detail_container.html +43 -12
  39. django_spire/knowledge/templates/django_spire/knowledge/entry/version/page/detail_page.html +17 -1
  40. django_spire/knowledge/templates/django_spire/knowledge/navigation/page/full_page.html +1 -1
  41. {django_spire-0.17.11.dist-info → django_spire-0.18.1.dist-info}/METADATA +2 -1
  42. {django_spire-0.17.11.dist-info → django_spire-0.18.1.dist-info}/RECORD +48 -60
  43. django_spire/knowledge/entry/version/block/blocks/block.py +0 -51
  44. django_spire/knowledge/entry/version/block/blocks/heading_block.py +0 -14
  45. django_spire/knowledge/entry/version/block/blocks/list_block.py +0 -31
  46. django_spire/knowledge/entry/version/block/blocks/sub_heading_block.py +0 -14
  47. django_spire/knowledge/entry/version/block/blocks/text_block.py +0 -14
  48. django_spire/knowledge/entry/version/block/maps.py +0 -16
  49. django_spire/knowledge/entry/version/block/services/processor_service.py +0 -33
  50. django_spire/knowledge/entry/version/block/services/transformation_service.py +0 -35
  51. django_spire/knowledge/entry/version/block/tests/test_urls/test_json_urls.py +0 -28
  52. django_spire/knowledge/entry/version/block/urls/__init__.py +0 -13
  53. django_spire/knowledge/entry/version/block/urls/json_urls.py +0 -9
  54. django_spire/knowledge/entry/version/block/views/json_views.py +0 -30
  55. django_spire/knowledge/entry/version/tests/test_urls/test_form_urls.py +0 -28
  56. django_spire/knowledge/entry/version/urls/form_urls.py +0 -10
  57. django_spire/knowledge/entry/version/views/form_views.py +0 -63
  58. django_spire/knowledge/templates/django_spire/knowledge/entry/version/block/detail/component/heading_component.html +0 -3
  59. django_spire/knowledge/templates/django_spire/knowledge/entry/version/block/detail/component/list_item_component.html +0 -38
  60. django_spire/knowledge/templates/django_spire/knowledge/entry/version/block/detail/component/sub_heading_component.html +0 -3
  61. django_spire/knowledge/templates/django_spire/knowledge/entry/version/block/detail/component/text_component.html +0 -3
  62. django_spire/knowledge/templates/django_spire/knowledge/entry/version/block/dropdown/add_dropdown.html +0 -25
  63. django_spire/knowledge/templates/django_spire/knowledge/entry/version/block/update/component/heading_component.html +0 -3
  64. django_spire/knowledge/templates/django_spire/knowledge/entry/version/block/update/component/list_item_component.html +0 -13
  65. django_spire/knowledge/templates/django_spire/knowledge/entry/version/block/update/component/sub_heading_component.html +0 -3
  66. django_spire/knowledge/templates/django_spire/knowledge/entry/version/block/update/component/text_component.html +0 -50
  67. django_spire/knowledge/templates/django_spire/knowledge/entry/version/container/form_container.html +0 -129
  68. /django_spire/knowledge/entry/version/block/{blocks → data}/__init__.py +0 -0
  69. /django_spire/knowledge/entry/version/block/{tests/test_urls → data/list}/__init__.py +0 -0
  70. /django_spire/knowledge/entry/version/{block/views → services/tests}/__init__.py +0 -0
  71. {django_spire-0.17.11.dist-info → django_spire-0.18.1.dist-info}/WHEEL +0 -0
  72. {django_spire-0.17.11.dist-info → django_spire-0.18.1.dist-info}/licenses/LICENSE.md +0 -0
  73. {django_spire-0.17.11.dist-info → django_spire-0.18.1.dist-info}/top_level.txt +0 -0
@@ -1,31 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING
4
-
5
- from django_spire.knowledge.entry.version.block.blocks.block import BaseBlock
6
- from django_spire.knowledge.entry.version.block.choices import BlockTypeChoices
7
- from django_spire.knowledge.entry.version.block.constants import SPACES_PER_INDENT
8
-
9
- if TYPE_CHECKING:
10
- from django_spire.knowledge.entry.version.block.models import EntryVersionBlock
11
-
12
-
13
- class ListItemBlock(BaseBlock):
14
- value: str
15
- type: BlockTypeChoices = BlockTypeChoices.LIST_ITEM
16
- detail_template: str = 'django_spire/knowledge/entry/version/block/detail/component/list_item_component.html'
17
- update_template: str = 'django_spire/knowledge/entry/version/block/update/component/list_item_component.html'
18
- indent_level: int = 0
19
- bullet: str = '-'
20
- ordered: bool = False
21
-
22
- def render_to_text(self) -> str:
23
- indent = ' ' * self.indent_level * SPACES_PER_INDENT
24
- return f'{indent}{self.bullet} {self.value}\n'
25
-
26
- def to_dict(self, version_block: EntryVersionBlock):
27
- return super().to_dict(version_block) | {
28
- 'indent_level': self.indent_level,
29
- 'bullet': self.bullet,
30
- 'ordered': self.ordered,
31
- }
@@ -1,14 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from django_spire.knowledge.entry.version.block.choices import BlockTypeChoices
4
- from django_spire.knowledge.entry.version.block.blocks.block import BaseBlock
5
-
6
-
7
- class SubHeadingBlock(BaseBlock):
8
- value: str
9
- type: BlockTypeChoices = BlockTypeChoices.SUB_HEADING
10
- detail_template: str = 'django_spire/knowledge/entry/version/block/detail/component/sub_heading_component.html'
11
- update_template: str = 'django_spire/knowledge/entry/version/block/update/component/sub_heading_component.html'
12
-
13
- def render_to_text(self) -> str:
14
- return f'{self.value}\n'
@@ -1,14 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from django_spire.knowledge.entry.version.block.choices import BlockTypeChoices
4
- from django_spire.knowledge.entry.version.block.blocks.block import BaseBlock
5
-
6
-
7
- class TextBlock(BaseBlock):
8
- value: str
9
- type: BlockTypeChoices = BlockTypeChoices.TEXT
10
- detail_template: str = 'django_spire/knowledge/entry/version/block/detail/component/text_component.html'
11
- update_template: str = 'django_spire/knowledge/entry/version/block/update/component/text_component.html'
12
-
13
- def render_to_text(self) -> str:
14
- return f'{self.value}\n'
@@ -1,16 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from django_spire.knowledge.entry.version.block.blocks.list_block import ListItemBlock
4
- from django_spire.knowledge.entry.version.block.choices import BlockTypeChoices
5
- from django_spire.knowledge.entry.version.block.blocks.heading_block import HeadingBlock
6
- from django_spire.knowledge.entry.version.block.blocks.sub_heading_block import \
7
- SubHeadingBlock
8
- from django_spire.knowledge.entry.version.block.blocks.text_block import TextBlock
9
-
10
-
11
- ENTRY_BLOCK_MAP = {
12
- BlockTypeChoices.TEXT: TextBlock,
13
- BlockTypeChoices.HEADING: HeadingBlock,
14
- BlockTypeChoices.SUB_HEADING: SubHeadingBlock,
15
- BlockTypeChoices.LIST_ITEM: ListItemBlock,
16
- }
@@ -1,33 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from copy import deepcopy
4
-
5
- from django_spire.contrib.service import BaseDjangoModelService
6
-
7
- from typing import TYPE_CHECKING, Any
8
-
9
- from django_spire.knowledge.entry.version.block.choices import BlockTypeChoices
10
-
11
- if TYPE_CHECKING:
12
- from django_spire.knowledge.entry.version.block.models import EntryVersionBlock
13
-
14
-
15
- class EntryVersionBlockProcessorService(BaseDjangoModelService['EntryVersionBlock']):
16
- obj: EntryVersionBlock
17
-
18
- def set_deleted(self):
19
- self.obj.ordering_services.processor.remove_from_objects(
20
- destination_objects=self.obj.version.blocks.active()
21
- )
22
-
23
- self.obj.set_deleted()
24
-
25
- def update_block(self, value: Any, block_type: BlockTypeChoices):
26
- block = deepcopy(self.obj.block)
27
- block.value = value
28
- block.type = block_type
29
-
30
- self.obj.block = block
31
- self.obj.save()
32
-
33
- return self.obj
@@ -1,35 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
-
5
- from django.db.models import QuerySet
6
- from django.template.loader import render_to_string
7
-
8
- from django_spire.contrib.service import BaseDjangoModelService
9
-
10
- from typing import TYPE_CHECKING, Iterable
11
-
12
- if TYPE_CHECKING:
13
- from django_spire.knowledge.entry.version.block.models import EntryVersionBlock
14
-
15
-
16
- class EntryVersionBlockTransformationService(BaseDjangoModelService['EntryVersionBlock']):
17
- obj: EntryVersionBlock
18
-
19
- def to_dict(self) -> dict:
20
- return {
21
- 'id': self.obj.id,
22
- 'type': self.obj.type,
23
- 'order': self.obj.order,
24
- 'block': self.obj.block.to_dict(self.obj)
25
- }
26
-
27
- def to_json(self) -> str:
28
- return json.dumps(self.obj.services.transformation.to_dict())
29
-
30
- @staticmethod
31
- def objects_to_json(objects: Iterable[EntryVersionBlock]) -> str:
32
- return json.dumps([
33
- block.services.transformation.to_dict()
34
- for block in objects
35
- ])
@@ -1,28 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
-
5
- from django.urls import reverse
6
-
7
- from django_spire.core.tests.test_cases import BaseTestCase
8
- from django_spire.knowledge.entry.version.block.tests.factories import create_test_version_block
9
-
10
-
11
- class EntryVersionBlockJsonUrlsTests(BaseTestCase):
12
- def setUp(self):
13
- super().setUp()
14
-
15
- self.test_version_block = create_test_version_block()
16
-
17
- def test_update_text_view_url_path(self):
18
- response = self.client.post(
19
- reverse('django_spire:knowledge:entry:version:block:json:update_text'),
20
- data=json.dumps({
21
- 'pk': self.test_version_block.pk,
22
- 'value': '',
23
- 'block_type': 'text'
24
- }),
25
- content_type='application/json'
26
- )
27
-
28
- self.assertEqual(response.status_code, 200)
@@ -1,13 +0,0 @@
1
- from django.urls import include, path
2
-
3
- app_name = 'block'
4
-
5
- urlpatterns = [
6
- path(
7
- 'json/',
8
- include(
9
- 'django_spire.knowledge.entry.version.block.urls.json_urls',
10
- namespace='json'
11
- )
12
- ),
13
- ]
@@ -1,9 +0,0 @@
1
- from django.urls import path
2
-
3
- from django_spire.knowledge.entry.version.block.views import json_views
4
-
5
- app_name = 'json'
6
-
7
- urlpatterns = [
8
- path('update_text/', json_views.update_text_view, name='update_text'),
9
- ]
@@ -1,30 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
-
5
- from django.core.handlers.wsgi import WSGIRequest
6
- from django.http import JsonResponse
7
-
8
- from django_spire.core.decorators import valid_ajax_request_required
9
- from django_spire.knowledge.entry.version.block.models import EntryVersionBlock
10
-
11
-
12
- @valid_ajax_request_required
13
- def update_text_view(request: WSGIRequest) -> JsonResponse:
14
- body_data = json.loads(request.body.decode('utf-8'))
15
- pk = body_data.get('pk')
16
-
17
- try:
18
- version_block = EntryVersionBlock.objects.get(pk=pk)
19
- except EntryVersionBlock.DoesNotExist:
20
- return JsonResponse({'type': 'error', 'message': 'Block Not Found'})
21
-
22
- value = body_data.get('value')
23
- block_type = body_data.get('block_type')
24
-
25
- if value is None or block_type is None:
26
- return JsonResponse({'type': 'error', 'message': 'Missing Required Data'})
27
-
28
- version_block.services.processor.update_block(value=value, block_type=block_type)
29
-
30
- return JsonResponse({'type': 'success'})
@@ -1,28 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from django.urls import reverse
4
-
5
- from django_spire.core.tests.test_cases import BaseTestCase
6
- from django_spire.knowledge.entry.tests.factories import create_test_entry
7
- from django_spire.knowledge.entry.version.tests.factories import \
8
- create_test_entry_version
9
-
10
-
11
- class EntryVersionFormUrlsTests(BaseTestCase):
12
- def setUp(self):
13
- super().setUp()
14
-
15
- self.test_entry = create_test_entry()
16
- self.test_entry_version = create_test_entry_version(entry=self.test_entry)
17
- self.test_entry.current_version = self.test_entry_version
18
- self.test_entry.save()
19
-
20
- def test_update_form_view_url_path(self):
21
- response = self.client.get(
22
- reverse(
23
- 'django_spire:knowledge:entry:version:form:update',
24
- kwargs={'pk': self.test_entry_version.pk}
25
- )
26
- )
27
-
28
- self.assertEqual(response.status_code, 200)
@@ -1,10 +0,0 @@
1
- from django.urls import path
2
-
3
- from django_spire.knowledge.entry.version.views import form_views
4
-
5
-
6
- app_name = 'form'
7
-
8
- urlpatterns = [
9
- path('<int:pk>/update/', form_views.update_form_view, name='update'),
10
- ]
@@ -1,63 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import json
4
-
5
- from django.core.handlers.wsgi import WSGIRequest
6
- from django.shortcuts import get_object_or_404
7
- from django.template.response import TemplateResponse
8
- from django.urls import reverse
9
-
10
- from django_spire.auth.controller.controller import AppAuthController
11
- from django_spire.contrib import Breadcrumbs
12
- from django_spire.contrib.generic_views import portal_views
13
- from django_spire.knowledge.entry.version.block.choices import BlockTypeChoices
14
- from django_spire.knowledge.entry.version.block.models import EntryVersionBlock
15
- from django_spire.knowledge.entry.version.models import EntryVersion
16
-
17
-
18
- @AppAuthController('knowledge').permission_required('can_change')
19
- def update_form_view(request: WSGIRequest, pk: int) -> TemplateResponse:
20
- current_version = get_object_or_404(EntryVersion, pk=pk)
21
- entry = current_version.entry
22
- version_blocks = current_version.blocks.active().order_by('order')
23
-
24
- if version_blocks.count() == 0:
25
- version_blocks = [
26
- EntryVersionBlock.services.factory.create_blank_block(
27
- entry_version=current_version,
28
- block_type=BlockTypeChoices.TEXT,
29
- order=0
30
- )
31
- ]
32
-
33
- breadcrumbs = Breadcrumbs()
34
- breadcrumbs.add_breadcrumb(name='Knowledge')
35
- breadcrumbs.add_breadcrumb(
36
- name='Collections',
37
- href=reverse('django_spire:knowledge:page:home')
38
- )
39
- breadcrumbs.add_breadcrumb(
40
- name=f'View {entry.name}',
41
- href=reverse(
42
- 'django_spire:knowledge:entry:version:page:detail',
43
- kwargs={'pk': entry.current_version_id}
44
- )
45
- )
46
- breadcrumbs.add_breadcrumb(name=f'Edit {entry.name}')
47
-
48
- return portal_views.template_view(
49
- request,
50
- page_title=f'Edit {entry.name}',
51
- page_description=f'Edit {entry.name}',
52
- breadcrumbs=breadcrumbs,
53
- context_data={
54
- 'entry': entry,
55
- 'current_version': current_version,
56
- 'version_blocks_json': EntryVersionBlock.services.transformation.objects_to_json(
57
- objects=version_blocks
58
- ),
59
- 'version_blocks': version_blocks,
60
- 'block_types': BlockTypeChoices,
61
- },
62
- template='django_spire/knowledge/entry/version/page/form_page.html',
63
- )
@@ -1,3 +0,0 @@
1
- {% load spire_knowledge_tags %}
2
-
3
- <div class="fs-2 fw-bold">{{ value|format_to_html|safe }}</div>
@@ -1,38 +0,0 @@
1
- {% load spire_knowledge_tags %}
2
-
3
- {% if version_block.block.ordered %}
4
- <div
5
- {% else %}
6
- <ol
7
- {% endif %}
8
- class="d-flex mb-1"
9
- style="
10
- padding-left: calc(20 * {{ version_block.block.indent_level }}px);
11
- {% if not version_block.block.ordered %}
12
- {% if version_block.block.indent_level|divisibleby:2 %}
13
- list-style-type: disc;
14
- list-style-position: inside;
15
- {% else %}
16
- list-style-type: circle;
17
- list-style-position: inside;
18
- {% endif %}
19
- {% endif %}
20
- "
21
- >
22
- {% if version_block.block.ordered %}
23
- <span class="col-auto" style="width: 20px">
24
- {{ version_block.block.bullet }}
25
- </span>
26
- <span class="col">
27
- {{ version_block.block.value|format_to_html|safe }}
28
- </span>
29
- {% else %}
30
- <li class="col">
31
- {{ version_block.block.value|format_to_html|safe }}
32
- </li>
33
- {% endif %}
34
- {% if version_block.block.ordered %}
35
- </div>
36
- {% else %}
37
- </ol>
38
- {% endif %}
@@ -1,3 +0,0 @@
1
- {% load spire_knowledge_tags %}
2
-
3
- <div class="fs-4 fw-bold">{{ value|format_to_html|safe }}</div>
@@ -1,3 +0,0 @@
1
- {% load spire_knowledge_tags %}
2
-
3
- <div class="fs-6 py-1">{{ value|format_to_html|safe }}</div>
@@ -1,25 +0,0 @@
1
- {% extends 'django_spire/dropdown/dropdown.html' %}
2
-
3
- {% block dropdown_trigger %}
4
- <span
5
- class="bi bi-plus-lg fs-5 p-0 cursor-pointer opacity-50"
6
- x-bind="trigger"
7
- :type="manager.block_order_focus === version_block.order ? 'button' : 'not-allowed'"
8
- >
9
- </span>
10
- {% endblock %}
11
-
12
- {% block dropdown_content %}
13
- {% for block_type in block_types %}
14
- <div
15
- class="bg-app-layer-one bg-app-layer-three-hover dropdown-item"
16
- x-data="{
17
- create_block() {
18
- create_blank_block({block_type: '{{ block_type.value }}', order: version_block.order + 1})
19
- }
20
- }"
21
- >
22
- {% include 'django_spire/dropdown/element/dropdown_link_element.html' with link_text=block_type.label x_click="create_block()" %}
23
- </div>
24
- {% endfor %}
25
- {% endblock %}
@@ -1,3 +0,0 @@
1
- {% extends 'django_spire/knowledge/entry/version/block/update/component/text_component.html' %}
2
-
3
- {% block textarea_class %}fs-2{% endblock %}
@@ -1,13 +0,0 @@
1
- {% extends 'django_spire/knowledge/entry/version/block/update/component/text_component.html' %}
2
-
3
- {% block before_text_content %}
4
- <span
5
- x-text="version_block.block.bullet"
6
- :style="`padding-left: ${20 * version_block.block.indent_level}px;`"
7
- >
8
- </span>
9
- {% endblock %}
10
-
11
- {% block shift_enter_event %}
12
- @keydown.shift.enter.prevent="create_list_item_block({previous_block: version_block})"
13
- {% endblock %}
@@ -1,3 +0,0 @@
1
- {% extends 'django_spire/knowledge/entry/version/block/update/component/text_component.html' %}
2
-
3
- {% block textarea_class %}fs-4{% endblock %}
@@ -1,50 +0,0 @@
1
- <div
2
- class="d-flex align-items-center"
3
- x-data="{
4
- is_focused: false,
5
- init() {
6
- $nextTick(() => {
7
- $refs.textarea.style.height = 'auto'
8
- $refs.textarea.style.height = $refs.textarea.scrollHeight + 'px'
9
- })
10
- },
11
- update_cursor_position({order, cursor_position}) {
12
- if (order === version_block.order) {
13
- $refs.textarea.focus()
14
- $refs.textarea.setSelectionRange(cursor_position, cursor_position)
15
- }
16
- }
17
- }"
18
- @update_cursor_position.window="
19
- update_cursor_position({order: $event.detail.order, cursor_position: $event.detail.cursor_position})
20
- "
21
- >
22
- <style>
23
- textarea:focus {
24
- outline: none;
25
- border: none;
26
- }
27
- </style>
28
- {% block before_text_content %}
29
- {% endblock %}
30
- <textarea
31
- rows="1"
32
- class="w-100 border-0 bg-transparent px-1 auto-resize overflow-y-hidden text-app-default-text-color {% block textarea_class %}fs-6{% endblock %}"
33
- style="height: 30px; resize: none;"
34
- x-ref="textarea"
35
- x-model="version_block.block.value"
36
- @input="update_height($event)"
37
- :placeholder="is_focused ? 'Write Something...' : ''"
38
- @focus="is_focused = true"
39
- @blur="is_focused = false"
40
- @beforeinput.debounce.300ms="update_value({version_block: version_block})"
41
- @keydown.backspace="delete_block_if_empty({version_block: version_block})"
42
- {% block shift_enter_event %}
43
- @keydown.shift.enter.prevent="create_blank_block({block_type: 'text', order: version_block.order + 1})"
44
- {% endblock %}
45
- @keydown.up.prevent="$dispatch('update_cursor_position', {order: version_block.order - 1, cursor_position: $event.target.selectionStart})"
46
- @keydown.down.prevent="$dispatch('update_cursor_position', {order: version_block.order + 1, cursor_position: $event.target.selectionStart})"
47
- {% block textarea_attributes %}
48
- {% endblock %}
49
- ></textarea>
50
- </div>
@@ -1,129 +0,0 @@
1
- {% extends 'django_spire/container/container.html' %}
2
-
3
- {% block container_title %}
4
- <div class="ps-3">
5
- {{ entry.name }}
6
- </div>
7
- {% endblock %}
8
-
9
- {% block container_content %}
10
- <div
11
- x-data="{
12
- first_load: true,
13
- init() {
14
- this.manager = new EntryVersionManager({
15
- id: {{ current_version.pk }},
16
- version_blocks_json: {{ version_blocks_json }}
17
- })
18
- },
19
- async create_blank_block({block_type, order, ...optional_fields}) {
20
- let response = await django_glue_fetch(
21
- '{% url "django_spire:knowledge:entry:version:json:create_blank_block" pk=current_version.pk %}',
22
- {payload: {block_type: block_type, order: order, ...optional_fields}},
23
- )
24
- if (response.type === 'error') {
25
- $dispatch('notify', {type:'error', message: response.message})
26
- } else {
27
- let block_data = JSON.parse(response.entry_version_block_json)
28
- const new_version_block = await this.manager.insert_blank_block(
29
- {
30
- id: block_data.id,
31
- block_type: block_data.type,
32
- order: block_data.order,
33
- block: block_data.block
34
- }
35
- )
36
- $dispatch('update_cursor_position', {order: new_version_block.order, cursor_position: 0})
37
- }
38
- },
39
- async create_list_item_block({previous_block}) {
40
- let bullet = null
41
- if (previous_block.block.ordered) {
42
- const number = parseInt(previous_block.block.bullet.split('.')[0]) + 1
43
- bullet = number + '.'
44
- } else {
45
- bullet = previous_block.block.bullet
46
- }
47
- await this.create_blank_block({
48
- block_type: 'list_item',
49
- order: previous_block.order + 1,
50
- bullet: bullet,
51
- indent_level: previous_block.block.indent_level,
52
- ordered: previous_block.block.ordered
53
- })
54
- },
55
- async delete_block_if_empty({version_block}) {
56
- if (version_block.block.value !== '') return
57
-
58
- const previous_order = version_block.order - 1
59
- if (previous_order === 0) return
60
-
61
- const previous_block_length = this.manager.get_block_length({order: previous_order})
62
- $dispatch(
63
- 'update_cursor_position',
64
- {order: previous_order, cursor_position: previous_block_length}
65
- )
66
-
67
- let response = await django_glue_fetch(
68
- '{% url "django_spire:knowledge:entry:version:json:delete_block" pk=current_version.pk %}',
69
- {payload: {version_block_pk: version_block.id}},
70
- )
71
- if (response.type === 'error') {
72
- $dispatch('notify', {type: 'error', message: response.message})
73
- } else {
74
- this.manager.delete_block({id: version_block.id})
75
- }
76
- },
77
- update_height(event) {
78
- event.target.style.height = 'auto'
79
- event.target.style.height = event.target.scrollHeight + 'px'
80
- },
81
- async update_value({version_block}) {
82
- let response = await django_glue_fetch(
83
- '{% url "django_spire:knowledge:entry:version:block:json:update_text" %}',
84
- {payload: {
85
- pk: version_block.id,
86
- value: version_block.block.value,
87
- block_type: version_block.block.type
88
- }},
89
- )
90
-
91
- if (response.type === 'error') {
92
- $dispatch('notify', {type: 'error', message: 'An error occurred while saving the text block.'})
93
- }
94
- },
95
- async reorder_block({block, order}){
96
- let response = null
97
- try {
98
- response = await django_glue_fetch(
99
- '{% url "django_spire:knowledge:entry:version:json:reorder" pk=current_version.pk %}',
100
- { payload: {'block_id': block, 'order': order} }
101
- )
102
- } catch (e) {
103
- window.location.reload()
104
- }
105
-
106
- if (response.type === 'error') {
107
- $dispatch('notify', {'type': response.type, 'message': response.message})
108
- }
109
- }
110
- }"
111
- x-sort="await reorder_block({block: $item, order: $position})"
112
- x-sort:config="{handle: '[x-sort\\:handle]'}"
113
- >
114
- <template x-for="(version_block, index) in manager.entry_version.version_blocks" :key="version_block.id">
115
- <div class="row align-items-center block" x-sort:item="version_block.id">
116
- <div class="col-auto action-items pe-0" x-sort:handle>
117
- <div class="row m-0 p-0 align-items-center">
118
- {% include 'django_spire/element/grabber_element.html' with grabber_class='col-auto opacity-50' %}
119
- <div class="col pe-0">
120
- {% include 'django_spire/knowledge/entry/version/block/dropdown/add_dropdown.html' %}
121
- </div>
122
- </div>
123
- </div>
124
- <div class="col" x-html="version_block.block.update_template_rendered">
125
- </div>
126
- </div>
127
- </template>
128
- </div>
129
- {% endblock %}