Skip to content

Commit

Permalink
Merge pull request #560 from Lexpedite/project_slug
Browse files Browse the repository at this point in the history
Project slug
  • Loading branch information
Gauntlet173 authored Jun 26, 2023
2 parents 29a4c70 + f0b817e commit ada3c1b
Show file tree
Hide file tree
Showing 19 changed files with 193 additions and 125 deletions.
17 changes: 14 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@ As of v0.2-alpha, this project is attempting to adhere to [Semantic Versioning](
While alpha, however, any version may include breaking changes that may not be specifically noted as such,
and breaking changes will not necessarily result in changes to the main version number.


## [v1.6.16-alpha](https://github.com/Lexpedite/blawx/releases/tag/v1.6.16-alpha) 2023-06-26

`.blawx` files created in previous versions will work with this version, but **please note that the majority of URLs are now different**.

### Added
* Projects now have a path slug based on their name, which must be unique per user. The slug can be changed in the admin interface.

### Changed
* All URLS that previously began with `/{rule_id}/` now start with `/{owner}/{rule_slug}/`
For example `/1/test/who_won` would now be `/jason/rock-paper-scissors-act/test/who_won`.
This is intended to give some predictability to the location of the API endpoints for a loaded `.blawx` file to simplify development using
Blawx as a legal reasoner.

## [v1.6.15-alpha](https://github.com/Lexpedite/blawx/releases/tag/v1.6.15-alpha) 2023-05-23

### Added
Expand All @@ -15,9 +29,6 @@ and breaking changes will not necessarily result in changes to the main version
### Changed
* Disclaimer has been added to the GCWeb styled version of the scenario editor.

### TODO
* Update the documentation for the scenario editor.

## [v1.6.14-alpha](https://github.com/Lexpedite/blawx/releases/tag/v1.6.14-alpha) 2023-05-12

### Added
Expand Down
2 changes: 1 addition & 1 deletion blawx/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class WorkspaceAdmin(GuardedModelAdmin):
fields = ['ruledoc','workspace_name','xml_content','scasp_encoding']

class RuleDocAdmin(GuardedModelAdmin):
fields = ['ruledoc_name','scasp_encoding','tutorial','akoma_ntoso','rule_text','navtree','owner','published']
fields = ['ruledoc_name','rule_slug','scasp_encoding','tutorial','akoma_ntoso','rule_text','navtree','owner','published']

class BlawxTestAdmin(GuardedModelAdmin):
fields = ['ruledoc','test_name','xml_content','scasp_encoding', 'tutorial', 'view', 'fact_scenario']
Expand Down
6 changes: 6 additions & 0 deletions blawx/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
from cobalt.hierarchical import Act
from clean.clean import generate_akn
from preferences.models import Preferences
from django.utils.text import slugify

# Create your models here.
class RuleDoc(models.Model):
ruledoc_name = models.CharField(max_length=200)
rule_text = models.TextField(default="Default Act")
rule_slug = models.TextField()
akoma_ntoso = models.TextField(default="",blank=True)
navtree = models.TextField(default="",blank=True)
scasp_encoding = models.TextField(default="",blank=True)
Expand All @@ -22,6 +24,9 @@ def __str__(self):
return self.ruledoc_name

class Meta:
constraints = [
models.UniqueConstraint(fields=['rule_slug','owner'],name='unique_owner_and_rule_slug')
]
permissions = [
('add_blawxtest_to_ruledoc', 'Can add Test to RuleDoc'),
('add_workspace_to_ruledoc', 'Can add Workspace to RuleDoc'),
Expand All @@ -31,6 +36,7 @@ class Meta:
def update_an_nav(sender, instance, **kwargs):
instance.akoma_ntoso = generate_akn(instance.rule_text)
instance.navtree = generate_tree(Act(instance.akoma_ntoso).act)
instance.rule_slug = slugify(instance.ruledoc_name)

class Workspace(models.Model):
ruledoc = models.ForeignKey(RuleDoc, related_name='workspaces', on_delete=models.CASCADE)
Expand Down
42 changes: 24 additions & 18 deletions blawx/reasoner.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.http import Http404, HttpResponseNotFound, HttpResponseForbidden
from django.contrib.auth.models import User

from rest_framework.decorators import api_view, permission_classes, authentication_classes
from rest_framework.response import Response
Expand Down Expand Up @@ -85,9 +86,9 @@ def convertVariables(param):
else:
return param

def even_newer_json_2_scasp(payload,ruledoc,testname):
def even_newer_json_2_scasp(payload,user,rule,testname):
output = ""
ontology = get_ontology_internal(ruledoc,testname)
ontology = get_ontology_internal(user,rule,testname)
# Basically, we need to know what the predicate is, what the parameters are, whether the parameters have category types, and if they are variables.
# So get the predicate, look up the typing, modify for negation if required, and generate the fact, testing for categories if required.

Expand Down Expand Up @@ -469,17 +470,18 @@ def format_statement_value(value,attribute_type):
@api_view(['POST'])
@authentication_classes([SessionAuthentication])
@permission_classes([AllowAny])
def run_test(request,ruledoc,test_name):
def run_test(request,user,rule,test_name):
# Get the data (test, facts, and workspaces)
# ruledoctest = RuleDoc.objects.filter(pk=ruledoc,owner=request.user)
test = BlawxTest.objects.get(ruledoc=RuleDoc.objects.get(pk=ruledoc),test_name=test_name)
owner = User.objects.get(username=user)
test = BlawxTest.objects.get(ruledoc=RuleDoc.objects.get(rule_slug=rule,owner=owner),test_name=test_name)
if request.user.has_perm('blawx.run',test):
translated_facts = ""
if request.data:
translated_facts = even_newer_json_2_scasp(request.data,ruledoc,test_name)
translated_facts = even_newer_json_2_scasp(request.data,user,rule,test_name)
# print("Facts Generated for Run Request:\n")
# print(translated_facts)
wss = Workspace.objects.filter(ruledoc=RuleDoc.objects.get(pk=ruledoc))
wss = Workspace.objects.filter(ruledoc=RuleDoc.objects.get(rule_slug=rule,owner=owner))
ruleset = ""
# for ws in wss:
# ruleset += "\n\n" + ws.scasp_encoding
Expand Down Expand Up @@ -633,9 +635,10 @@ def run_test(request,ruledoc,test_name):
else:
return HttpResponseForbidden()

def get_ontology_internal(ruledoc,test_name):
wss = Workspace.objects.filter(ruledoc=RuleDoc.objects.get(pk=ruledoc))
test = BlawxTest.objects.get(ruledoc=RuleDoc.objects.get(pk=ruledoc),test_name=test_name)
def get_ontology_internal(user,rule,test_name):
owner = User.objects.get(username=user)
wss = Workspace.objects.filter(ruledoc=RuleDoc.objects.get(rule_slug=rule,owner=owner))
test = BlawxTest.objects.get(ruledoc=RuleDoc.objects.get(rule_slug=rule,owner=owner),test_name=test_name)
ruleset = ""
for ws in wss:
ruleset += "\n\n" + ws.scasp_encoding
Expand Down Expand Up @@ -1011,11 +1014,12 @@ def get_ontology_internal(ruledoc,test_name):
@api_view(['GET'])
@authentication_classes([SessionAuthentication])
@permission_classes([IsAuthenticatedOrReadOnly])
def get_ontology(request,ruledoc,test_name):
ruledoctest = RuleDoc.objects.get(pk=ruledoc)
def get_ontology(request,user,rule,test_name):
owner = User.objects.get(username=user)
ruledoctest = RuleDoc.objects.get(rule_slug=rule,owner=owner)
if request.user.has_perm('blawx.view_ruledoc',ruledoctest):
test = BlawxTest.objects.get(ruledoc=ruledoc,test_name=test_name)
result = get_ontology_internal(ruledoc,test_name)
test = BlawxTest.objects.get(ruledoc=RuleDoc.objects.get(rule_slug=rule,owner=owner),test_name=test_name)
result = get_ontology_internal(user,rule,test_name)
if test.view == "":
result['View'] = test.view
else:
Expand All @@ -1041,9 +1045,10 @@ def simplify_rule(rule):
@api_view(['POST'])
@authentication_classes([SessionAuthentication])
@permission_classes([AllowAny])
def interview(request,ruledoc,test_name):
def interview(request,user,rule,test_name):
#print("Dealing with interview request.\n")
test = BlawxTest.objects.get(ruledoc=RuleDoc.objects.get(pk=ruledoc),test_name=test_name)
owner = User.objects.get(username=user)
test = BlawxTest.objects.get(ruledoc=RuleDoc.objects.get(rule_slug=rule,owner=owner),test_name=test_name)
if request.user.has_perm('blawx.run',test):


Expand Down Expand Up @@ -1167,10 +1172,11 @@ def interview(request,ruledoc,test_name):
# Effectively, we're going to start over.
translated_facts = ""
if request.data:
translated_facts = even_newer_json_2_scasp(request.data, ruledoc, test_name) #Generate answers INCLUDING assumptions in the submitted data
translated_facts = even_newer_json_2_scasp(request.data, user, rule, test_name) #Generate answers INCLUDING assumptions in the submitted data

wss = Workspace.objects.filter(ruledoc=RuleDoc.objects.get(pk=ruledoc))
test = BlawxTest.objects.get(ruledoc=RuleDoc.objects.get(pk=ruledoc),test_name=test_name)
owner = User.objects.get(username=user)
wss = Workspace.objects.filter(ruledoc=RuleDoc.objects.get(rule_slug=rule,owner=owner))
test = BlawxTest.objects.get(ruledoc=RuleDoc.objects.get(rule_slug=rule,owner=owner),test_name=test_name)
ruleset = ""
unique_rules = []
for ws in wss:
Expand Down
2 changes: 1 addition & 1 deletion blawx/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from pathlib import Path

# For adding a version identifier
BLAWX_VERSION = "v1.6.15-alpha"
BLAWX_VERSION = "v1.6.16-alpha"


# Build paths inside the project like this: BASE_DIR / 'subdir'.
Expand Down
2 changes: 1 addition & 1 deletion blawx/templates/blawx/blawx.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><i class="bi bi-house pe-2"></i><a href="/">Home</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' ruledoc.id %}">{{ ruledoc.ruledoc_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' ruledoc.owner ruledoc.rule_slug %}">{{ ruledoc.ruledoc_name }}</a></li>
<li class="breadcrumb-item">
<a class="dropdown-toggle" data-bs-toggle="collapse" href="#ruleNav" role="button"
aria-expanded="false" aria-controls="ruleNav">
Expand Down
4 changes: 2 additions & 2 deletions blawx/templates/blawx/blawxtest_confirm_delete.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><i class="bi bi-house pe-2"></i><a href="/">Home</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' blawxtest.ruledoc.id %}">{{ blawxtest.ruledoc.ruledoc_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-clipboard-check pe-2"></i><a href="{% url 'test' blawxtest.ruledoc.id blawxtest.test_name%}">{{ blawxtest.test_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' blawxtest.ruledoc.owner blawxtest.ruledoc.rule_slug %}">{{ blawxtest.ruledoc.ruledoc_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-clipboard-check pe-2"></i><a href="{% url 'test' blawxtest.ruledoc.owner blawxtest.ruledoc.rule_slug blawxtest.test_name%}">{{ blawxtest.test_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-pencil-square pe-2"></i>Test Confirm Delete</li>
</ul>
</nav>
Expand Down
2 changes: 1 addition & 1 deletion blawx/templates/blawx/blawxtest_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><i class="bi bi-house pe-2"></i><a href="/">Home</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' ruledoc.id %}">{{ ruledoc.ruledoc_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' ruledoc.owner ruledoc.rule_slug %}">{{ ruledoc.ruledoc_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-clipboard-check pe-2"></i>New Test</li>
</ul>
</nav>
Expand Down
6 changes: 3 additions & 3 deletions blawx/templates/blawx/bot.html
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
</svg>
<span class="text">Help</span>
</a>
<a href="{% url 'test' blawxtest.ruledoc.id blawxtest %}" class="btn btn-secondary">
<a href="{% url 'test' blawxtest.ruledoc.owner blawxtest.ruledoc.rule_slug blawxtest %}" class="btn btn-secondary">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor"
class="bi bi-x-square" viewBox="0 0 16 16">
<path
Expand Down Expand Up @@ -532,7 +532,7 @@ <h5 class="card-title">Test Facts</h5>
return;
}
}
interview_request.open("POST", "{% url 'test_interview' blawxtest.ruledoc.id blawxtest %}");
interview_request.open("POST", "{% url 'test_interview' blawxtest.ruledoc.owner blawxtest.ruledoc.rule_slug blawxtest %}");
interview_request.setRequestHeader("Content-Type", "application/json");
console.log("Sending interview request")
interview_request.setRequestHeader('X-CSRFToken', csrftoken);
Expand Down Expand Up @@ -686,7 +686,7 @@ <h5 class="card-title">Test Facts</h5>
test_fact_element.innerHTML = output_html;

}
ontology_request.open("GET", "{% url 'test_onto' blawxtest.ruledoc.id blawxtest %}", false); // This is asynchronous because the interview request doesn't work until we have the ontology.
ontology_request.open("GET", "{% url 'test_onto' blawxtest.ruledoc.owner blawxtest.ruledoc.rule_slug blawxtest %}", false); // This is asynchronous because the interview request doesn't work until we have the ontology.
ontology_request.setRequestHeader('X-CSRFToken', csrftoken);
ontology_request.send();

Expand Down
4 changes: 2 additions & 2 deletions blawx/templates/blawx/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ <h3>Your Projects</h3>
<ul>
{% for ruledoc in ruledoc_list %}
{% if user == ruledoc.owner %}
<li><a href="{% url 'ruledoc' ruledoc.id %}">{{ ruledoc.ruledoc_name }}</a></li>
<li><a href="{% url 'ruledoc' ruledoc.owner ruledoc.rule_slug %}">{{ ruledoc.ruledoc_name }}</a></li>
{% endif %}
{% endfor %}
</ul>
Expand All @@ -83,7 +83,7 @@ <h3>Published Projects</h3>
{% for ruledoc in ruledoc_list %}
{% get_obj_perms request.user for ruledoc as "ruledoc_perms" %}
{% if user != ruledoc.owner and ruledoc.published and 'view_ruledoc' in ruledoc_perms %}
<li><a href="{% url 'ruledoc' ruledoc.id %}">{{ ruledoc.ruledoc_name }}</a></li>
<li><a href="{% url 'ruledoc' ruledoc.owner ruledoc.rule_slug %}">{{ ruledoc.ruledoc_name }}</a></li>
{% endif %}
{% endfor %}
</ul>
Expand Down
12 changes: 6 additions & 6 deletions blawx/templates/blawx/ruledoc.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><i class="bi bi-house pe-2"></i><a href="/">Home</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' ruledoc.id %}">{{ ruledoc.ruledoc_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' ruledoc.owner ruledoc.rule_slug %}">{{ ruledoc.ruledoc_name }}</a></li>
</ul>
</nav>
{% endblock %}
Expand All @@ -17,21 +17,21 @@
<h1>{{ ruledoc.ruledoc_name }}</h1>
<div>

<a href="{% url 'ruledoc_edit' ruledoc.id %}" class="btn btn-success {% if 'change_ruledoc' not in ruledoc_perms %} disabled{% endif %}" {% if 'change_ruledoc' not in ruledoc_perms %} aria-disabled="true"{% endif %}>
<a href="{% url 'ruledoc_edit' ruledoc.owner ruledoc.rule_slug %}" class="btn btn-success {% if 'change_ruledoc' not in ruledoc_perms %} disabled{% endif %}" {% if 'change_ruledoc' not in ruledoc_perms %} aria-disabled="true"{% endif %}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-text" viewBox="0 0 16 16">
<path d="M5 4a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1H5zm-.5 2.5A.5.5 0 0 1 5 6h6a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zM5 8a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1H5zm0 2a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1H5z"/>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2zm10-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1z"/>
</svg>
<span class="text">Rule Editor</span>
</a>
<a href="{% url 'code' ruledoc.pk %}" class="btn btn-success">
<a href="{% url 'code' ruledoc.owner ruledoc.rule_slug %}" class="btn btn-success">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-code" viewBox="0 0 16 16">
<path d="M6.646 5.646a.5.5 0 1 1 .708.708L5.707 8l1.647 1.646a.5.5 0 0 1-.708.708l-2-2a.5.5 0 0 1 0-.708l2-2zm2.708 0a.5.5 0 1 0-.708.708L10.293 8 8.646 9.646a.5.5 0 0 0 .708.708l2-2a.5.5 0 0 0 0-.708l-2-2z"/>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2zm10-1H4a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1z"/>
</svg>
<span class="text">Code Editor</span>
</a>
<a href="{% url 'new_test' ruledoc.pk %}" class="btn btn-success{% if 'add_blawxtest_to_ruledoc' not in ruledoc_perms %} disabled{% endif %}" {% if 'add_blawxtest_to_ruledoc' not in ruledoc_perms %} aria-disabled="true"{% endif %}>
<a href="{% url 'new_test' ruledoc.owner ruledoc.rule_slug %}" class="btn btn-success{% if 'add_blawxtest_to_ruledoc' not in ruledoc_perms %} disabled{% endif %}" {% if 'add_blawxtest_to_ruledoc' not in ruledoc_perms %} aria-disabled="true"{% endif %}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-plus-circle" viewBox="0 0 16 16">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
Expand All @@ -45,7 +45,7 @@ <h1>{{ ruledoc.ruledoc_name }}</h1>
</svg>
<span class="text">Export</span>
</a>
<a href="{% url 'ruledoc_delete' ruledoc.id %}" class="btn btn-danger {% if 'delete_ruledoc' not in ruledoc_perms %} disabled{% endif %}" {% if 'disabled_ruledoc' not in ruledoc_perms %} aria-disabled="true"{% endif %}>
<a href="{% url 'ruledoc_delete' ruledoc.owner ruledoc.rule_slug %}" class="btn btn-danger {% if 'delete_ruledoc' not in ruledoc_perms %} disabled{% endif %}" {% if 'disabled_ruledoc' not in ruledoc_perms %} aria-disabled="true"{% endif %}>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
Expand All @@ -64,7 +64,7 @@ <h2>Tests</h2>
{% for t in tests %}
{% get_obj_perms request.user for t as 'test_perms' %}
{% if 'view_blawxtest' in test_perms %}
<li><a href="{% url 'test' ruledoc.pk t.test_name %}">{{ t.test_name }}</a></li>
<li><a href="{% url 'test' ruledoc.owner ruledoc.rule_slug t.test_name %}">{{ t.test_name }}</a></li>
{% endif %}
{% endfor %}
</ul>
Expand Down
2 changes: 1 addition & 1 deletion blawx/templates/blawx/ruledoc_confirm_delete.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><i class="bi bi-house pe-2"></i><a href="/">Home</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' ruledoc.id %}">{{ ruledoc.ruledoc_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-journal pe-2"></i><a href="{% url 'ruledoc' ruledoc.owner ruledoc.rule_slug %}">{{ ruledoc.ruledoc_name }}</a></li>
<li class="breadcrumb-item"><i class="bi bi-pencil-square pe-2"></i>Rule Delete Confirmation</li>
</ul>
</nav>
Expand Down
Loading

0 comments on commit ada3c1b

Please # to comment.