Skip to content

Commit

Permalink
Merge branch 'main' into survey-view-testing
Browse files Browse the repository at this point in the history
  • Loading branch information
jpelay authored Nov 27, 2023
2 parents d533282 + da5a6cb commit a42f311
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 37 deletions.
21 changes: 15 additions & 6 deletions templates/customize-adventure.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,31 @@ <h3 class="text-center mt-0 mb-4">{{_('general_settings')}}</h3>

<div class="flex flex-row items-center mb-4">
<label for="tags" class="inline-block w-40 text-xl">{{_('tags')}}</label>
<div class="flex flex-row w-full">
<input type="text" name="tag" placeholder="{{_('tag_input_placeholder')}}" id="input_adventure_tags"
_="on keypress if event.keyCode == 13 then event.stopPropagation()"
<div class="flex flex-row w-full relative" id="add_tags">
<input type="text" name="tag" placeholder="{{_('tag_input_placeholder')}}" id="search_tags_input"
class="appearance-none w-full bg-gray-200 border border-gray-200 text-gray-700 py-3 px-4 ltr:pr-8 rtl:pl-8 rounded"
hx-trigger="enter"
hx-post="/tags/create/{{adventure.id}}" hx-target="#tags-list" hx-swap="outerHTML"
_="on htmx:afterRequest focus()"
class="appearance-none w-full bg-gray-200 border border-gray-200 text-gray-700 py-3 px-4 ltr:pr-8 rtl:pl-8 rounded"
_="on click event.stopPropagation()
on keypress if event.keyCode == 13 event.stopPropagation() end
on htmx:afterRequest focus()"
>
<button class="green-btn" id="add_adventure_tags"
hx-trigger="click"
hx-post="/tags/create/{{adventure.id}}"
hx-target="#tags-list"
hx-swap="outerHTML"
hx-include="[name='tag']"
_="on htmx:afterRequest set value of #input_adventure_tags to ''"
_="on htmx:afterRequest set value of #search_tags_input to ''"
>{{_('add')}}</button>

<div
id="tags-dropdown"
hx-trigger="load"
hx-get="/tags?adventure_id={{adventure.id}}"
hx-target="#tags-dropdown"
hx-swap="outerHTML"
></div>
</div>
</div>
{{ render_partial('htmx-tags-list.html', tags=adventure_tags, adventure_id=adventure.id, creator=adventure.creator) }}
Expand Down
17 changes: 17 additions & 0 deletions templates/htmx-tags-dropdown-item.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!-- Requires #search_tags_input to exist -->
<div class="relative cursor-pointer !w-full border-2 rounded-lg border-green-300 p-2 px-5 m-1 shadow"
id="tag_{{tag['name']}}" hx-post="/tags/create/{{adventure_id}}/{{tag.name}}" hx-target="#tags-list"
hx-swap="outerHTML" _="on click event.stopPropagation()
on htmx:afterRequest
if detail.xhr.status == 200
remove me
set #tags_dropdown's *display to 'none'
call #search_tags_input's focus()
end
on keyup from #search_tags_input
set v to its value
if not my innerHTML.includes(v.trim())
set my *display to 'none'
else
set my *display to 'block'
">{{tag["name"]}}</div>
12 changes: 12 additions & 0 deletions templates/htmx-tags-dropdown.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!-- Requires #search_tags_input to exist -->
<div id="tags_dropdown" class="dropdown-menu dropdown-blue z-20 min-w-full flex-wrap !border-gray-400"
style="display: none; width: 100%; opacity: 0; border: none; top: 100%; padding: 0px !important; margin: 0px; margin-top: 0.25rem;"
_="on click event.stopPropagation() end
on keyup or focus from #search_tags_input debounced at 500ms
set my *display to 'flex'
transition my *opacity to 1 over 500ms end
">
{% for tag in tags %}
{{ render_partial('htmx-tags-dropdown-item.html', tag=tag, adventure_id=adventure_id) }}
{% endfor %}
</div>
22 changes: 5 additions & 17 deletions templates/htmx-tags-list.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,23 @@
<ul id="tags-list" class="flex flex-wrap items-center mb-4 list-none">
{% for tag in tags %}
<!-- TODO: allow teacher to edit tags; not urgent, but for a better ux! -->
<!-- _="on click toggle .hidden on #update-tag-input_{{loop.index}}
set the value of #update-tag-input_{{loop.index}} to '{{tag}}'
toggle .hidden on me" -->
<li
id="tag_{{loop.index}}"
class='relative border-2 rounded-lg border-green-300 p-2 px-5 mx-2 mb-2 shadow'
>
class='relative border-2 rounded-lg border-green-300 p-2 px-5 mx-2 mb-2 shadow'>
{{tag}}
{% if not public and username == creator %}
<span class='absolute top-0.5 right-0.5 text-gray-600 hover:text-red-400 fa-regular fa-circle-xmark'
{% if adventure_id %}
hx-target="#tags_dropdown"
hx-delete="/tags/delete/{{tag}}/{{adventure_id}}"
hx-swap="none"
_="on htmx:afterRequest if detail.xhr.status == 200 then remove #tag_{{loop.index}}
if JSON.parse(detail.xhr.response).tags.length == 0 toggle .hidden on #no-tags"
hx-swap="beforeend"
_="on htmx:afterRequest
if detail.xhr.status == 200 then remove #tag_{{loop.index}} end"
{% else %}
_='on click remove #tag_{{loop.index}}'
{% endif %}
></span>
{% endif %}
</li>
<!-- <input type="text"
autofocus
id="update-tag-input_{{loop.index}}"
class='relative border-2 rounded-lg border-green-400 p-2 px-5 mx-2 mb-2 hidden'
_="on blur toggle .hidden on me then toggle .hidden on #tag_{{loop.index}}"
value="{{tag}}"
> -->
{% endfor %}
<li id="no-tags" class='border-2 rounded-lg border-green-400 p-2 px-5 mx-2 mb-2 {% if tags|length > 0 %}hidden{% endif %}'>{{_('no_tags')}}</li>
</ul>
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ describe("Tags of adventures", () => {
})

it("has tags input and button", () => {
cy.get("#input_adventure_tags")
cy.get("#search_tags_input")
.should("be.visible")
.should("be.empty")

Expand All @@ -18,26 +18,23 @@ describe("Tags of adventures", () => {

it("has no tags initially", () => {
cy.get("#tags-list")
.should("be.visible")
.get("#no-tags")
.should("be.visible")
.should("be.not.visible")
})

it("adds a tag to adventure by pressing enter within the input field", () => {
cy.get("#input_adventure_tags")
cy.get("#search_tags_input")
.should("be.empty")
.type("statements{enter}")
cy.wait(500)
cy.get("#tags-list")
.should("be.visible")
.get("#no-tags")
.should("be.hidden")

cy.get("#tags-list li")
.should("include.text", "statements")
})

it("adds a tag to adventure by pressing the add button", () => {
cy.get("#input_adventure_tags")
cy.get("#search_tags_input")
.should("be.empty")
.type("training")
cy.get("#add_adventure_tags")
Expand All @@ -46,8 +43,7 @@ describe("Tags of adventures", () => {
cy.wait(500)
cy.get("#tags-list")
.should("be.visible")
.get("#no-tags")
.should("be.hidden")

cy.get("#tags-list li")
.should("include.text", "training")
})
Expand All @@ -59,7 +55,7 @@ describe("Tags of adventures", () => {
times: 1,
}).as("createTag")

cy.get("#input_adventure_tags")
cy.get("#search_tags_input")
.should("be.empty")
.type("training{enter}")
cy.wait("@createTag").should('have.nested.property', 'response.statusCode', 400)
Expand Down
12 changes: 12 additions & 0 deletions website/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,15 @@ def read_tag(self, tag_name):
def read_tags(self, tags):
return [self.read_tag(name) for name in tags]

def read_public_tags(self):
"""Public tags are tagged within one or more public adventure or those that aren't in use."""
all_tags = TAGS.scan()
public_tags = []
for tag in all_tags:
if not tag["tagged_in"] or any([adv["public"] for adv in tag["tagged_in"]]):
public_tags.append(tag)
return public_tags

def read_tags_by_username(self, username):
tags = TAGS.get_many({"creator": username})
return tags if tags else {}
Expand Down Expand Up @@ -645,6 +654,9 @@ def get_second_teacher_adventures(self, classes, teacher):
def all_adventures(self):
return ADVENTURES.scan()

def public_adventures(self):
return ADVENTURES.get_many({"public": True})

def get_student_classes_ids(self, username):
ids = USERS.get({"username": username}).get("classes")
return list(ids) if ids else []
Expand Down
18 changes: 15 additions & 3 deletions website/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ def __init__(self, db: Database, achievements: Achievements):
self.db = db
self.achievements = achievements

@route("/<adventure_id>", methods=["GET"])
@route("/", methods=["GET"], defaults={"adventure_id": None})
@requires_teacher
def get_public_tags(self, user, adventure_id):
public_tags = self.db.read_public_tags()
adventure_id = request.args.get("adventure_id")
if adventure_id:
adventure = self.db.get_adventure(adventure_id)
# exclude current adventure's tags
public_tags = list(filter(lambda t: t["name"] not in adventure.get("tags", []), public_tags))

return jinja_partials.render_partial('htmx-tags-dropdown.html',
tags=public_tags, adventure_id=adventure_id, creator=user)

@route("/create/<adventure_id>", methods=["POST"])
@route("/create/<adventure_id>/<new_tag>", methods=["POST"])
@requires_teacher
Expand Down Expand Up @@ -91,6 +105,4 @@ def delete_from_adventure(self, user, tag, adventure_id):
adventure_tags = list(filter(lambda name: name != tag_name, adventure_tags))
self.db.update_adventure(adventure_id, {"tags": adventure_tags})

return adventure_tags, 200
# return jinja_partials.render_partial('htmx-tags-list.html', tags=adventure_tags,
# adventure_id=adventure_id, creator=user["username"])
return jinja_partials.render_partial('htmx-tags-dropdown-item.html', tag=db_tag, adventure_id=adventure_id)

0 comments on commit a42f311

Please sign in to comment.