Skip to content

Commit 5b84912

Browse files
committed
feat(diff/changelog): support basic change tracking for included documents
Related to: #1564
1 parent a0d9b4f commit 5b84912

File tree

20 files changed

+167
-156
lines changed

20 files changed

+167
-156
lines changed

docs/strictdoc_04_release_notes.sdoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ The legacy ``@sdoc`` marker has been removed from the codebase. From now on, onl
5858

5959
An edge case has been fixed where StrictDoc’s FileFinder was detecting Linux pipe files that could not be processed meaningfully by StrictDoc’s source file generator. With this release, such files are now ignored.
6060

61+
The Diff/Changelog feature has been extended to better support change tracking of included documents. Previously, only the contents of included documents were visualized, but not the root nodes of the documents themselves. Now, changes to included documents, such as their UID or TITLE, are displayed correctly.
62+
6163
The ReqIF-to-SDoc converter has been improved to handle integer fields by treating them as string grammar fields. Since StrictDoc does not yet support INTEGER fields, they are converted to STRING fields during import. This workaround was sufficient to support the user’s use case.
6264
Thanks to @kerfallaCisse for reporting this issue.
6365

strictdoc/backend/sdoc/models/model.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ def iterate_included_documents_depth_first(
145145
) -> Generator["SDocDocumentIF", None, None]:
146146
raise NotImplementedError
147147

148+
def document_is_included(self) -> bool:
149+
raise NotImplementedError
150+
148151
@abstractmethod
149152
def get_display_title(self, include_toc_number: bool = True) -> str:
150153
raise NotImplementedError

strictdoc/export/html/templates/screens/git/changelog_content.jinja

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
11
<div class="changelog_content">
2-
{% set documents_modified = view_object.change_container.change_stats.get_changes_documents_modified() %}
3-
{% if documents_modified is not none %}
4-
{% set _documents_modified = documents_modified %}
5-
{% else %}
6-
{% set _documents_modified = "No documents were modified." %}
7-
{% endif %}
8-
92
<div class="sdoc-table_key_value">
103
{% with key_value_pair =
114
{"Section":"Compared revisions"}
@@ -46,6 +39,12 @@
4639
{% include "components/table_key_value/index.jinja" %}
4740
{% endwith %}
4841

42+
{% set documents_modified = view_object.change_container.change_stats.get_changes_documents_modified() %}
43+
{% if documents_modified > 0 %}
44+
{% set _documents_modified = documents_modified %}
45+
{% else %}
46+
{% set _documents_modified = "No documents were modified." %}
47+
{% endif %}
4948
{% with key_value_pair =
5049
{
5150
"Key":"Documents modified",
@@ -55,6 +54,18 @@
5554
{% include "components/table_key_value/index.jinja" %}
5655
{% endwith %}
5756

57+
{% set documents_included_modified = view_object.change_container.change_stats.get_changes_included_documents_modified() %}
58+
{% if documents_included_modified > 0 %}
59+
{% with key_value_pair =
60+
{
61+
"Key":"DOCUMENT (included) nodes",
62+
"Value": documents_included_modified,
63+
}
64+
%}
65+
{% include "components/table_key_value/index.jinja" %}
66+
{% endwith %}
67+
{% endif %}
68+
5869
{% for node_type_ in view_object.get_node_types() %}
5970
{% set requirements_modified = view_object.change_container.change_stats.get_changes_requirements_changed(node_type_) %}
6071
{% if requirements_modified is not none %}
@@ -91,12 +102,6 @@
91102
{% set requirement_change = view_object.change_stats.find_change(requirement) %}
92103
{% include "screens/git/fields/requirement_fields.jinja" %}
93104
{% endwith %}
94-
{% elif change.change_type == "Section removed" or change.change_type == "Section modified" %}
95-
{% assert change.lhs_section is not none, change %}
96-
{% with section=change.lhs_section, side="left", self_stats=view_object.change_container.lhs_stats, other_stats=view_object.change_container.rhs_stats, traceability_index=view_object.change_container.traceability_index_lhs %}
97-
{% set section_change = view_object.change_stats.find_change(section) %}
98-
{% include "screens/git/fields/section_fields.jinja" %}
99-
{% endwith %}
100105
{% elif change.change_type == "Document modified" %}
101106
{% if change.lhs_document is not none %}
102107
{% with document=change.lhs_document, side="left", self_stats=view_object.change_container.lhs_stats, other_stats=view_object.change_container.rhs_stats, traceability_index=view_object.change_container.traceability_index_lhs %}
@@ -117,11 +122,6 @@
117122
{% set requirement_change = view_object.change_stats.find_change(requirement) %}
118123
{% include "screens/git/fields/requirement_fields.jinja" %}
119124
{% endwith %}
120-
{% elif change.change_type == "Section added" or change.change_type == "Section modified" %}
121-
{% with section=change.rhs_section, side="right", self_stats=view_object.change_container.rhs_stats, other_stats=view_object.change_container.lhs_stats, traceability_index=view_object.change_container.traceability_index_rhs %}
122-
{% set section_change = view_object.change_stats.find_change(section) %}
123-
{% include "screens/git/fields/section_fields.jinja" %}
124-
{% endwith %}
125125
{% elif change.change_type == "Document modified" %}
126126
{% if change.rhs_document is not none %}
127127
{% with document=change.rhs_document, side="right", self_stats=view_object.change_container.rhs_stats, other_stats=view_object.change_container.lhs_stats, traceability_index=view_object.change_container.traceability_index_rhs %}

strictdoc/export/html/templates/screens/git/diff_content.jinja

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{%- if not document_tree_iterator.is_empty_tree() -%}
33
<div class="diff_content">
44
{%- for folder_or_file in document_tree_iterator.iterator_files_first(): -%}
5-
{%- if folder_or_file.is_folder(): %}
5+
{%- if folder_or_file.is_folder() %}
66
{%- if folder_or_file.files|length > 0 %}
77
<div
88
class="diff_folder"
@@ -34,14 +34,14 @@
3434

3535
{%- set document_iterator = traceability_index.get_document_iterator(document) -%}
3636
{%- for section_or_requirement, _ in document_iterator.all_content(print_fragments=True) %}
37-
{%- if section_or_requirement.is_requirement() %}
37+
{% if section_or_requirement.is_document() %}
38+
{% with document = section_or_requirement %}
39+
{% include "screens/git/node/document.jinja" %}
40+
{% endwith %}
41+
{% else %}
3842
{%- set requirement = section_or_requirement %}
39-
{% include "screens/git/node/requirement.jinja" %}
40-
41-
{%- elif section_or_requirement.is_document() %}
42-
{%- set section = section_or_requirement %}
43-
{% include "screens/git/node/section.jinja" %}
44-
{%- endif %}
43+
{% include "screens/git/node/requirement.jinja" %}
44+
{% endif %}
4545
{%- endfor -%}
4646
</details>
4747
{% endif %}

strictdoc/export/html/templates/screens/git/fields/document_fields.jinja

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,18 @@
2727
{%- include "components/badge/index.jinja" -%}
2828
{%- endwith -%}
2929

30-
{% assert document.reserved_uid is not none %}
31-
<div
32-
class="sdoc_pre_content"
33-
>{{ document.reserved_uid }}</div>
30+
{%- if uid_modified -%}
31+
{%- set colored_diff = document_change.get_colored_uid_diff(side) -%}
32+
{# Using a dummy if block to get rid of leading and trailing whitespaces #}
33+
{%- if colored_diff is not none -%}
34+
{{ colored_diff }}
35+
{%- else -%}
36+
{{ document.reserved_uid }}
37+
{%- endif -%}
38+
{%- else -%}
39+
{{ document.reserved_uid }}
40+
{%- endif -%}
41+
3442
</div>
3543

3644
{% endif %}

strictdoc/export/html/templates/screens/git/fields/section_fields.jinja

Lines changed: 0 additions & 52 deletions
This file was deleted.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{% set document_change = view_object.change_stats.find_change(document) %}
2+
3+
<details
4+
class="diff_node"
5+
{% if document_change is not none %}
6+
modified="{{ side }}"
7+
{% endif %}
8+
>
9+
<summary>
10+
{%- with badge_text = "DOCUMENT (included)" -%}
11+
{%- include "components/badge/index.jinja" -%}
12+
{%- endwith -%}
13+
<span>
14+
{{ document.context.title_number_string if document.context.title_number_string else "&nbsp;"|safe * (document.ng_level * 2 - 1) }}
15+
</span>
16+
<span>{{ document.reserved_title }}</span>
17+
{%- if tab == "diff" -%}
18+
{%- if document_change is not none -%}
19+
{%- if document_change.document_token is not none -%}
20+
{%- with uid=document_change.document_token -%}
21+
{%- include "screens/git/sync/button.jinja" -%}
22+
{%- endwith -%}
23+
{%- endif -%}
24+
{%- endif -%}
25+
{%- endif -%}
26+
</summary>
27+
28+
{% include "screens/git/fields/document_fields.jinja" %}
29+
</details>

strictdoc/export/html/templates/screens/git/node/requirement.jinja

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77
{% endif %}
88
>
99
<summary>
10-
{%- with badge_text = "TEXT" if requirement.is_text_node() else "R" -%}
10+
{#
11+
# FIXME: It would be great to write full node types but CSS must be
12+
improved so that a node type is not similar to the node fields
13+
visually.
14+
#}
15+
{%- with badge_text = requirement.node_type[0].upper() -%}
1116
{%- include "components/badge/index.jinja" -%}
1217
{%- endwith -%}
1318
<span>

strictdoc/export/html/templates/screens/git/node/section.jinja

Lines changed: 0 additions & 29 deletions
This file was deleted.

strictdoc/git/change.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,22 +31,40 @@ def __init__(
3131
rhs_document: Optional[SDocDocument],
3232
uid_modified: bool,
3333
title_modified: bool,
34+
lhs_colored_uid_diff: Optional[Markup],
35+
rhs_colored_uid_diff: Optional[Markup],
3436
lhs_colored_title_diff: Optional[Markup],
3537
rhs_colored_title_diff: Optional[Markup],
38+
document_token: str,
39+
is_included_document: bool,
3640
):
3741
assert lhs_document is not None or rhs_document is not None
3842
if matched_uid is not None:
3943
assert len(matched_uid) > 0
4044
self.matched_uid: Optional[str] = matched_uid
4145
self.uid_modified: bool = uid_modified
4246
self.title_modified: bool = title_modified
47+
48+
self.lhs_colored_uid_diff: Optional[Markup] = lhs_colored_uid_diff
49+
self.rhs_colored_uid_diff: Optional[Markup] = rhs_colored_uid_diff
50+
4351
self.lhs_colored_title_diff: Optional[Markup] = lhs_colored_title_diff
4452
self.rhs_colored_title_diff: Optional[Markup] = rhs_colored_title_diff
4553

4654
self.lhs_document: Optional[SDocDocument] = lhs_document
4755
self.rhs_document: Optional[SDocDocument] = rhs_document
4856

4957
self.change_type: ChangeType = ChangeType.DOCUMENT_MODIFIED
58+
self.document_token: str = document_token
59+
self.is_included_document: bool = is_included_document
60+
61+
def get_colored_uid_diff(self, side: str) -> Optional[Markup]:
62+
assert self.uid_modified
63+
if side == "left":
64+
return self.lhs_colored_uid_diff
65+
if side == "right":
66+
return self.rhs_colored_uid_diff
67+
raise AssertionError(f"Must not reach here: {side}")
5068

5169
def get_colored_title_diff(self, side: str) -> Optional[Markup]:
5270
assert self.title_modified

0 commit comments

Comments
 (0)