2
0
sleepytaco 3 жил өмнө
parent
commit
c471662597

+ 26 - 0
apps/main/models.py

@@ -1214,3 +1214,29 @@ class Video(models.Model):
     video_details_modified = models.BooleanField(
         default=False)  # is true for videos whose details changed after playlist update
     video_details_modified_at = models.DateTimeField(auto_now_add=True)  # to set the above false after a day
+
+
+class PlaylistItem(models.Model):
+    playlist = models.ForeignKey(Playlist, related_name="playlist_items",
+                                 on_delete=models.CASCADE)  # playlist this pl item belongs to
+    video = models.ForeignKey(Video, related_name="playlists", on_delete=models.CASCADE)
+
+    # details
+    playlist_item_id = models.CharField(max_length=100)  # the item id of the playlist this video beo
+    video_position = models.IntegerField(blank=True)  # video position in the playlist
+    user_notes = models.CharField(max_length=420, default="")  # i.e user can take notes on the video and save them
+    is_duplicate = models.BooleanField(default=False)  # True if the same video exists more than once in the playlist
+    is_marked_as_watched = models.BooleanField(default=False, blank=True)  # mark video as watched
+    is_favorite = models.BooleanField(default=False, blank=True)  # mark video as favorite
+    num_of_accesses = models.CharField(max_length=69,
+                                       default="0")  # tracks num of times this video was clicked on by user
+    user_label = models.CharField(max_length=100, default="")  # custom user given name for this video
+
+    # for new videos added/modified/deleted in the playlist
+    video_details_modified = models.BooleanField(
+        default=False)  # is true for videos whose details changed after playlist update
+    video_details_modified_at = models.DateTimeField(auto_now_add=True)  # to set the above false after a day
+
+    created_at = models.DateTimeField(auto_now_add=True)
+    updated_at = models.DateTimeField(auto_now=True)
+

+ 34 - 34
apps/main/templates/all_playlists.html

@@ -2,12 +2,12 @@
 {% extends 'base.html' %}
 {% block content %}
 
-        {% if playlists %}
     <div id="search-results">
 
-        <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
-            <h1 class="h2">{{ playlist_type_display|title }} <span class="badge bg-primary rounded-pill">{{ playlists.count }}</span></h1>
+        <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 mb-3">
+            <h1 class="h2"><span style="border-bottom: 3px #ffffff dashed;">{{ playlist_type_display|title }}</span> <span class="badge bg-primary rounded-pill">{{ playlists.count }}</span></h1>
 
+            {% if playlists %}
             <div class="btn-toolbar mb-2 mb-md-0">
                 <!--
                 <div class="btn-group me-2">
@@ -16,20 +16,22 @@
                 </div>
                 -->
                 <div class="btn-group">
-                  <button type="button" class="btn btn-outline-success dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
+                  <button type="button" class="btn btn-success dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
                     Sort By
                   </button>
                   <ul class="dropdown-menu">
-                    <li><a class="dropdown-item" hx-get="{% url 'order_playlists_by' playlist_type 'playlist-duration-in-seconds' %}" hx-trigger="click" hx-target="#search-results">Duration</a></li>
-                    <li><a class="dropdown-item" hx-get="{% url 'order_playlists_by' playlist_type 'video-count' %}" hx-trigger="click" hx-target="#search-results"># Videos</a></li>
-                    <li><a class="dropdown-item" hx-get="{% url 'order_playlists_by' playlist_type 'recently-accessed' %}" hx-trigger="click" hx-target="#search-results">Recently Accessed</a></li>
+                    <li class="dropdown-item"><a hx-get="{% url 'order_playlists_by' playlist_type 'playlist-duration-in-seconds' %}" hx-trigger="click" hx-target="#search-results">Duration</a></li>
+                    <li class="dropdown-item"><a hx-get="{% url 'order_playlists_by' playlist_type 'video-count' %}" hx-trigger="click" hx-target="#search-results"># Videos</a></li>
+                    <li class="dropdown-item"><a hx-get="{% url 'order_playlists_by' playlist_type 'recently-accessed' %}" hx-trigger="click" hx-target="#search-results">Recently Accessed</a></li>
                   </ul>
                 </div>
 
             </div>
+            {% endif %}
 
         </div>
 
+        {% if playlists %}
         <div class="">
             <input   class="form-control border border-secondary" type="text"
        name="search" placeholder="Begin to search playlists..."
@@ -71,39 +73,37 @@
 
 
         </div>
-
-        <br>
-
-    </div>
         {% else %}
-            <div class="container-fluid">
-            <div class="d-flex justify-content-between align-items-center pt-3 pb-2 mb-3 border-bottom">
-            <h1 class="h2">{{ playlist_type_display|title }} <span class="badge bg-primary rounded-pill">{{ playlists.count }}</span></h1>
-
-            <div class="btn-toolbar mb-2 mb-md-0">
-                <!--
-                <div class="btn-group me-2">
-                    <button type="button" class="btn btn-outline-info">Grid</button>
-                    <button type="button" class="btn btn-outline-info">List</button>
+              <div class="card bg-dark text-white mb-3">
+            <div class="card-body">
+                <div class="d-flex justify-content-center h3">
+                    Nothing here!
                 </div>
-                -->
-                <div class="btn-group">
-                  <button type="button" class="btn btn-outline-success dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
-                    Sort By
-                  </button>
-                  <ul class="dropdown-menu">
-                    <li><a class="dropdown-item" hx-get="{% url 'order_playlists_by' playlist_type 'playlist-duration-in-seconds' %}" hx-trigger="click" hx-target="#search-results">Duration</a></li>
-                    <li><a class="dropdown-item" hx-get="{% url 'order_playlists_by' playlist_type 'video-count' %}" hx-trigger="click" hx-target="#search-results"># Videos</a></li>
-                    <li><a class="dropdown-item" hx-get="{% url 'order_playlists_by' playlist_type 'recently-accessed' %}" hx-trigger="click" hx-target="#search-results">Recently Accessed</a></li>
-                  </ul>
+                <div class="d-flex justify-content-center h5">
+                    {% if playlist_type == "watching" %}
+                        You can mark a playlist as watching by heading over to the playlist and marking it from the dropdown.
+                    {% elif playlist_type == "imported" %}
+                        To import public playlists into your UnTube collection you can head over to <a href="{% url 'manage_playlists' %}" class="btn btn-sm btn-primary ms-2">Manage</a>
+                    {% elif playlist_type == "plan-to-watch" %}
+                        You can mark a playlist as plan to watch by heading over to the playlist and marking it from the dropdown.
+                    {% elif playlist_type == "user-owned" %}
+                        {% if user.profile.imported_yt_playlists %}
+                            Looks like you have no playlists on YouTube.
+                        {% else %}
+                            You can always head over to your <a href="{% url 'profile' %}" class="btn btn-sm btn-primary">Profile</a> to import all of your public/private YouTube playlists.
+                        {% endif %}
+                    {% else %}
+                        {{ playlist_type }}
+                    {% endif %}
                 </div>
-
             </div>
-
-        </div>
-            <h5 class="text-white align-content-center">Nothing to see here. Add something!</h5>
             </div>
+
         {% endif %}
+        <br>
+
+    </div>
+
 
 
 {% endblock %}

+ 70 - 0
apps/main/templates/all_playlists_with_tag.html

@@ -0,0 +1,70 @@
+
+{% extends 'base.html' %}
+{% block content %}
+
+    <div id="search-results">
+
+        <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 mb-3">
+            <h1 class="h2"> <span style="border-bottom: 3px #ffffff dashed;" class="pt-3">Playlists Tagged as</span> <kbd>{{ tag.name }}</kbd> <span class="badge bg-warning rounded-pill">{{ playlists.count }}</span></h1>
+
+        </div>
+
+        {% if playlists %}
+        <div class="">
+            <input   class="form-control border border-secondary" type="text"
+       name="search" placeholder="Begin to search playlists..."
+       hx-post="{% url 'search_tagged_playlists' tag.name %}"
+       hx-trigger="keyup changed delay:500ms"
+       hx-target="#search-results"
+       hx-indicator=".htmx-indicator">
+          <br>
+        </div>
+
+        <div class="row row-cols-1 row-cols-md-3 g-4">
+                {% for playlist in playlists %}
+                <div class="col">
+                    <div class="card" style="background-color: #515355;">
+                        <a style="background-color: #1A4464;" href="{% url 'playlist' playlist.playlist_id %}" class="list-group-item list-group-item-action text-white-50" aria-current="true">
+
+                            <div class="card-body">
+
+                                <h5 class="card-title text-white">
+                                    {{ playlist.name }}
+
+                                </h5>
+                                <p class="card-text">
+                                    {% if playlist.is_user_owned %}<small><span class="badge bg-light text-black-50">OWNED</span></small>{% else %}<small><span class="badge bg-light text-black-50">IMPORTED</span></small>{% endif %}
+
+                                    {% if playlist.is_private_on_yt %}<small><span class="badge bg-secondary text-white">Private</span></small> {% endif %}
+                                    {% if playlist.is_from_yt %}<small><span class="badge bg-danger text-black-50">YT</span></small> {% endif %}
+
+                                </p>
+                                <small>
+                                    <span class="badge bg-primary rounded-pill">{{ playlist.video_count }} videos</span>
+                                    <span class="badge bg-primary rounded-pill">{{ playlist.playlist_duration }} </span>
+                                </small>
+                            </div>
+                        </a>
+                    </div>
+                </div>
+                {% endfor %}
+
+
+        </div>
+        {% else %}
+              <div class="card bg-dark text-white mb-3">
+            <div class="card-body">
+                <div class="d-flex justify-content-center h3">
+                    Nothing here!
+                </div>
+                <div class="d-flex justify-content-center h5">
+                    You did create this tag but none of the playlists in your collection are currently tagged with this.
+                </div>
+            </div>
+            </div>
+
+        {% endif %}
+        <br>
+    </div>
+
+{% endblock %}

+ 2 - 4
apps/main/templates/intercooler/playlist_tags.html

@@ -1,10 +1,8 @@
 {% for tag in playlist_tags %}
 <span id="tag-{{ tag.name|slugify }}">
     <span class="badge rounded-pill bg-info mb-lg-1">
-        {{ tag.name }}
-        <a hx-post="{% url 'remove_playlist_tag' playlist_id tag.name %}" hx-trigger="click" hx-target="#tag-{{ tag.name|slugify }}">
-            <i class="fas fa-times-circle"></i>
-        </a>
+        <a href="{% url 'tagged_playlists' tag.name %}" style="text-decoration: none; color: white">{{ tag.name }} </a>
+        <a class="ms-1" hx-post="{% url 'remove_playlist_tag' playlist_id tag.name %}" hx-trigger="click" hx-target="#tag-{{ tag.name|slugify }}"><i class="fas fa-times-circle"></i></a>
     </span>
 </span>
 {% endfor %}

+ 0 - 137
apps/main/templates/intercooler/search_untube.html

@@ -1,137 +0,0 @@
-{% load humanize %}
-
-        <div>
-            <div class="d-flex justify-content-center">
-               <h1> Search all of UnTube
-                {% if user.profile.open_search_new_tab %}
-                    <h6>Press <kbd>Esc</kbd> to close.</h6>
-                {% endif %}
-               </h1>
-            </div>
-
-            <input class="form-control me-lg-2" type="text"
-                name="search" placeholder="Search UnTube"
-                value="{{ search_query }}"
-                hx-post="{% url 'search_UnTube' %}"
-                hx-trigger="keyup changed delay:750ms"
-                hx-target="#untube-searchbar-results"
-                hx-include="[id='searchbar-radio-form']"
-                hx-indicator=".htmx-indicator" autofocus onfocus="this.setSelectionRange(this.value.length,this.value.length);">
-            <br>
-
-              <div id="searchbar-radio-form">
-
-                  <div class="d-flex justify-content-center">
-
-                          <div class="form-check me-5">
-                      <input class="form-check-input" type="radio" name="search-settings" value="starts-with" id="starts-with-cb" {% if starts_with %} checked {% endif %}>
-                      <label class="form-check-label" for="starts-with-cb">
-                        Starts with
-                      </label>
-                    </div>
-                         <div class="form-check">
-                      <input class="form-check-input" type="radio" name="search-settings" value="contains" id="contains-cb" {% if contains %} checked {% endif %}>
-                      <label class="form-check-label" for="contains-cb">
-                        Contains
-                      </label>
-                    </div>
-                      </div>
-                  </div>
-
-        </div>
-
-        <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
-            <h1 class="h2">Playlists <span class="badge bg-primary rounded-pill">{{ playlists.count|default:"0" }}</span></h1>
-        </div>
-
-        <div>
-            <div class="row row-cols-1 row-cols-md-3 g-4">
-                {% if playlists %}
-                {% for playlist in playlists %}
-                <div class="col">
-                    <div class="card" style="background-color: #1A4464;">
-                        <a style="background-color: #1A4464;" href="{% url 'playlist' playlist.playlist_id %}" class="list-group-item list-group-item-action" aria-current="true">
-
-                            <div class="card-body text-white">
-
-                                <h5 class="card-title">
-                                    {{ playlist.name|truncatewords:"15" }}
-                                    {% if playlist.is_private_on_yt %}<small><span class="badge bg-light text-dark">Private</span></small> {% endif %}
-                                    {% if playlist.is_from_yt %}<small><span class="badge bg-danger text-dark">YT</span></small> {% endif %}
-                                </h5>
-                                <p class="card-text">
-                                    {% if playlist.description %}
-                                        {{ playlist.description|truncatewords:"15" }}
-                                    {% else %}
-                                        No description
-                                    {% endif %}
-                                </p>
-                                <small>
-                                    <span class="badge bg-primary rounded-pill">{{ playlist.video_count }} views</span>
-                                    <span class="badge bg-primary rounded-pill">{{ playlist.playlist_duration }} </span>
-                                </small>
-                            </div>
-                        </a>
-                    </div>
-                </div>
-                {% endfor %}
-
-                {% else %}
-                <h5 class="text-white align-content-center">Nothing found :(</h5>
-                {% endif %}
-            </div>
-        </div>
-
-        <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
-            <h1 class="h2">Videos <span class="badge bg-primary rounded-pill">{{ videos_count }}</span></h1>
-        </div>
-
-                <div>
-            <div class="row row-cols-1 row-cols-md-3 g-4">
-                {% if videos %}
-                {% for video in videos %}
-                <div class="col">
-                    <div class="card" style="background-color: #1A4464;">
-
-                    <div class="card-body">
-                        <h5 class="card-title text-light">
-                            {{ video.name|truncatewords:"15" }}<br>
-
-                            <small>
-                                <a class="badge bg-white text-black-50" href="{% url 'playlist' video.playlist.playlist_id %}">{{ video.playlist.name }}</a>
-
-                                <span class="badge bg-dark text-white-50">{{ video.duration }}</span>
-                            </small>
-                            {% if video.is_unavailable_on_yt %}<small><span class="badge bg-light text-dark">Private</span></small> {% endif %}
-                            {% if video.has_cc %}<small><span class="badge bg-danger text-dark">CC</span></small> {% endif %}
-                        </h5>
-                                                        <br>
-
-                        <span class="d-flex justify-content-center">
-                            <a href="https://www.youtube.com/watch?v={{ video.video_id }}" class="btn btn-info me-1" target="_blank" id="share_link" style=""><i class="fas fa-external-link-alt" aria-hidden="true"></i></a>
-                            <input class="form-control me-1 visually-hidden" id="video-{{ video.video_id }}" value="https://www.youtube.com/watch?v={{ video.video_id }}">
-                            <button class="copy-btn btn btn-success  me-1" data-clipboard-target="#video-{{ video.video_id }}">
-                                <i class="far fa-copy" aria-hidden="true"></i>
-                            </button>
-                            <button class="btn btn-dark" type="button" hx-get="{% url 'mark_video_favorite' video.playlist.playlist_id video.video_id %}" hx-target="#video-{{ forloop.counter }}-fav">
-                                <div id="video-{{ forloop.counter }}-fav">
-                                    {% if video.is_favorite %}
-                                        <i class="fas fa-heart"></i>
-                                    {% else %}
-                                        <i class="far fa-heart"></i>
-                                    {% endif %}
-                                </div>
-                            </button>
-                        </span>
-                    </div>
-                    </div>
-                </div>
-                {% endfor %}
-
-                {% else %}
-                <h5 class="text-white align-content-center">Nothing found :(</h5>
-                {% endif %}
-            </div>
-        </div>
-
-    <br>

+ 96 - 0
apps/main/templates/intercooler/search_untube_results.html

@@ -0,0 +1,96 @@
+{% load humanize %}
+<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
+    <h1 class="h2">Playlists <span class="badge bg-primary rounded-pill">{{ playlists.count|default:"0" }}</span></h1>
+</div>
+
+<div>
+    <div class="row row-cols-1 row-cols-md-3 g-4">
+        {% if playlists %}
+        {% for playlist in playlists %}
+        <div class="col">
+            <div class="card" style="background-color: #1A4464;">
+                <a style="background-color: #1A4464;" href="{% url 'playlist' playlist.playlist_id %}" class="list-group-item list-group-item-action" aria-current="true">
+
+                    <div class="card-body text-white">
+
+                        <h5 class="card-title">
+                            {{ playlist.name|truncatewords:"15" }}
+                            {% if playlist.is_private_on_yt %}<small><span class="badge bg-light text-dark">Private</span></small> {% endif %}
+                            {% if playlist.is_from_yt %}<small><span class="badge bg-danger text-dark">YT</span></small> {% endif %}
+                        </h5>
+                        <p class="card-text">
+                            {% if playlist.description %}
+                                {{ playlist.description|truncatewords:"15" }}
+                            {% else %}
+                                No description
+                            {% endif %}
+                        </p>
+                        <small>
+                            <span class="badge bg-primary rounded-pill">{{ playlist.video_count }} views</span>
+                            <span class="badge bg-primary rounded-pill">{{ playlist.playlist_duration }} </span>
+                        </small>
+                    </div>
+                </a>
+            </div>
+        </div>
+        {% endfor %}
+
+        {% else %}
+        <h5 class="text-white align-content-center">Nothing found :(</h5>
+        {% endif %}
+    </div>
+</div>
+
+<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
+    <h1 class="h2">Videos <span class="badge bg-primary rounded-pill">{{ videos_count }}</span></h1>
+</div>
+
+        <div>
+    <div class="row row-cols-1 row-cols-md-3 g-4">
+        {% if videos %}
+        {% for video in videos %}
+        <div class="col">
+            <div class="card" style="background-color: #1A4464;">
+
+            <div class="card-body">
+                <h5 class="card-title text-light">
+                    {{ video.name|truncatewords:"15" }}<br>
+
+                    <small>
+                        <a class="badge bg-white text-black-50" href="{% url 'playlist' video.playlist.playlist_id %}">{{ video.playlist.name }}</a>
+
+                        <span class="badge bg-dark text-white-50">{{ video.duration }}</span>
+                    </small>
+                    {% if video.is_unavailable_on_yt %}<small><span class="badge bg-light text-dark">Private</span></small> {% endif %}
+                    {% if video.has_cc %}<small><span class="badge bg-danger text-dark">CC</span></small> {% endif %}
+                </h5>
+                                                <br>
+
+                <span class="d-flex justify-content-center">
+                    <a href="https://www.youtube.com/watch?v={{ video.video_id }}" class="btn btn-info me-1" target="_blank" id="share_link" style=""><i class="fas fa-external-link-alt" aria-hidden="true"></i></a>
+                    <input class="form-control me-1 visually-hidden" id="video-{{ video.video_id }}" value="https://www.youtube.com/watch?v={{ video.video_id }}">
+                    <button class="copy-btn btn btn-success  me-1" data-clipboard-target="#video-{{ video.video_id }}">
+                        <i class="far fa-copy" aria-hidden="true"></i>
+                    </button>
+                    <button class="btn btn-dark" type="button" hx-get="{% url 'mark_video_favorite' video.playlist.playlist_id video.video_id %}" hx-target="#video-{{ forloop.counter }}-fav">
+                        <div id="video-{{ forloop.counter }}-fav">
+                            {% if video.is_favorite %}
+                                <i class="fas fa-heart"></i>
+                            {% else %}
+                                <i class="far fa-heart"></i>
+                            {% endif %}
+                        </div>
+                    </button>
+                </span>
+            </div>
+            </div>
+        </div>
+        {% endfor %}
+
+        {% else %}
+        <h5 class="text-white align-content-center">Nothing found :(</h5>
+        {% endif %}
+    </div>
+</div>
+
+<br>

+ 5 - 2
apps/main/templates/playlists_home.html

@@ -107,6 +107,7 @@
     </div>
 </div>
 <br>
+    {% if user.playlist_tags.all %}
     <div class="card bg-dark text-white">
             <div class="card-header">
                 <div class="d-flex justify-content-center">
@@ -117,7 +118,9 @@
                 <div class="d-flex justify-content-evenly h4">
                     <div class="w-75">
                     {% for tag in user.playlist_tags.all %}
-                        <span class="badge rounded-pill bg-warning bg-gradient mb-lg-1 text-black-50">{{ tag.name }}</span>
+                        <a href="{% url 'tagged_playlists' tag.name %}" style="text-decoration: none">
+                        <span class="badge rounded-pill bg-warning bg-gradient mb-lg-1 text-black-50">{{ tag.name }} <span class="badge bg-dark text-white">{{ tag.playlists.all.count }}</span> </span>
+                        </a>
                     {% endfor %}
                     </div>
                 </div>
@@ -133,5 +136,5 @@
             </div>
 
     </div>
-
+    {% endif %}
 {% endblock %}

+ 45 - 17
apps/main/templates/search_untube_page.html

@@ -11,44 +11,72 @@
         }
     };
     </script>
-<div id="untube-searchbar-results">
 
     <div class="d-flex justify-content-center">
         <h1> Search all of UnTube
             {% if user.profile.open_search_new_tab %}<h6>Press <kbd>Esc</kbd> to close.</h6>{% endif %}
         </h1>
     </div>
-<input class="form-control me-lg-2" type="text"
-       id="untubeSearchBar"
-        name="search" placeholder="Search UnTube"
-        hx-post="{% url 'search_UnTube' %}"
-        hx-trigger="keyup changed delay:700ms"
-        hx-target="#untube-searchbar-results"
-        hx-include="[id='searchbar-radio-form']"
-        hx-indicator=".htmx-indicator" autofocus>
+        <div id="search-playlist-form">
+
+        <input class="form-control me-lg-2" type="text"
+               id="untubeSearchBar"
+                name="search" placeholder="Search UnTube"
+                hx-post="{% url 'search_UnTube' %}"
+                hx-trigger="keyup changed delay:700ms"
+                hx-target="#untube-searchbar-results"
+                hx-include="[id='search-playlist-form']"
+                hx-indicator="#spinner" autofocus>
 
-<br>
+        <br>
 
-<div id="searchbar-radio-form">
+        <div class="row d-flex justify-content-center">
+            <div class="col-md-6">
+
+                <select hx-trigger="click[enterKey]"
+                    hx-target="#untube-searchbar-results"
+                    hx-include="[id='search-playlist-form']"
+                    hx-indicator="#spinner" id="choices-multiple-remove-button" name="playlist-tags" placeholder="Add playlist tags" multiple>
+                    {% for tag in user.playlist_tags.all %}
+                    <option value="{{ tag.name }}" hx-post="{% url 'search_UnTube' %}">{{ tag.name }}</option>
+                    {% endfor %}
+                </select>
+            </div>
+        </div>
+        <br>
     <div class="d-flex justify-content-center">
         <div class="form-check me-5">
-            <input class="form-check-input" type="radio" name="search-settings" value="starts-with" id="starts-with-cb" checked>
+            <input hx-post="{% url 'search_UnTube' %}"
+        hx-trigger="click"
+        hx-target="#untube-searchbar-results"
+        hx-include="[id='search-playlist-form']"
+        hx-indicator="#spinner"
+                           class="form-check-input" type="radio" name="search-settings" value="starts-with" id="starts-with-cb" checked>
             <label class="form-check-label" for="starts-with-cb">
                     Starts with
             </label>
         </div>
          <div class="form-check">
-            <input class="form-check-input" type="radio" name="search-settings" value="contains" id="contains-cb">
+            <input hx-post="{% url 'search_UnTube' %}"
+        hx-trigger="click"
+        hx-target="#untube-searchbar-results"
+        hx-include="[id='search-playlist-form']"
+        hx-indicator="#spinner"
+                    class="form-check-input" type="radio" name="search-settings" value="contains" id="contains-cb">
                   <label class="form-check-label" for="contains-cb">
                     Contains
                   </label>
         </div>
     </div>
 </div>
-</div>
+
+    <div id="untube-searchbar-results">
+    </div>
+
+
 <div id="spinner" class="htmx-indicator d-flex justify-content-center">
-                <div class="spinner-border text-light" role="status">
-                </div>
-                </div>
+    <div class="spinner-border text-light" role="status">
+    </div>
+</div>
 
 {% endblock %}

+ 3 - 1
apps/main/templates/view_playlist.html

@@ -69,7 +69,9 @@
                 <span id="playlist-tags">
                 {% for tag in playlist_tags %}
                     <span id="tag-{{ tag.name|slugify }}">
-                    <span class="badge rounded-pill bg-info mb-lg-1">{{ tag.name }} <a hx-post="{% url 'remove_playlist_tag' playlist.playlist_id tag.name %}" hx-trigger="click" hx-target="#tag-{{ tag.name|slugify }}"><i class="fas fa-times-circle"></i></a></span>
+                    <span class="badge rounded-pill bg-info mb-lg-1">
+                        <a href="{% url 'tagged_playlists' tag.name %}" style="text-decoration: none; color: white">{{ tag.name }} </a>
+                        <a class="ms-1" hx-post="{% url 'remove_playlist_tag' playlist.playlist_id tag.name %}" hx-trigger="click" hx-target="#tag-{{ tag.name|slugify }}"><i class="fas fa-times-circle"></i></a></span>
                     </span>
                 {% endfor %}
                 </span>

+ 2 - 0
apps/main/urls.py

@@ -37,6 +37,8 @@ urlpatterns = [
     path("search/playlists/<slug:playlist_type>", views.search_playlists, name="search_playlists"),
     path("playlists/<slug:playlist_type>", views.all_playlists, name='all_playlists'),
     path("playlists/<slug:playlist_type>/order-by/<slug:order_by>", views.order_playlists_by, name='order_playlists_by'),
+    path("search/tagged-playlists/<str:tag>", views.search_tagged_playlists, name="search_tagged_playlists"),
+    path("playlists/tag/<str:tag>", views.tagged_playlists, name='tagged_playlists'),
 
     ### STUFF RELATED TO MANAGING A PLAYLIST
     path("manage", views.manage_playlists, name='manage_playlists'),

+ 27 - 17
apps/main/views.py

@@ -3,7 +3,7 @@ import datetime
 import pytz
 from django.db.models import Q
 from django.http import HttpResponse, HttpResponseRedirect
-from django.shortcuts import render, redirect
+from django.shortcuts import render, redirect, get_object_or_404
 from apps.main.models import Playlist, Tag
 from django.contrib.auth.decorators import login_required  # redirects user to settings.LOGIN_URL
 from allauth.socialaccount.models import SocialToken
@@ -142,6 +142,12 @@ def view_playlist(request, playlist_id):
                                                   "unused_tags": unused_tags,
                                                   "videos": videos})
 
+@login_required
+def tagged_playlists(request, tag):
+    tag = get_object_or_404(Tag, created_by=request.user, name=tag)
+    playlists = tag.playlists.all()
+
+    return render(request, 'all_playlists_with_tag.html', {"playlists": playlists, "tag": tag})
 
 @login_required
 def all_playlists(request, playlist_type):
@@ -329,11 +335,18 @@ Done! Playlist on UnTube will update in 3s...
         </div>
         """)
 
+@login_required
+@require_POST
+def search_tagged_playlists(request, tag):
+    tag = get_object_or_404(Tag, created_by=request.user, name=tag)
+    playlists = tag.playlists.all()
+
+    return HttpResponse("yay")
 
 @login_required
 @require_POST
 def search_playlists(request, playlist_type):
-    print(request.POST)  # prints <QueryDict: {'search': ['aa']}>
+    # print(request.POST)  # prints <QueryDict: {'search': ['aa']}>
 
     search_query = request.POST["search"]
 
@@ -410,43 +423,40 @@ def search_UnTube(request):
     search_query = request.POST["search"]
 
     all_playlists = request.user.profile.playlists.filter(is_in_db=True)
+    if 'playlist-tags' in request.POST:
+        tags = request.POST.getlist('playlist-tags')
+        print(type(tags), tags)
+        all_playlists = all_playlists.filter(tags__name__in=tags)
+
     videos = []
-    starts_with = False
-    contains = False
 
     if request.POST['search-settings'] == 'starts-with':
-        playlists = request.user.profile.playlists.filter(
-            Q(name__startswith=search_query) & Q(is_in_db=True)) if search_query != "" else []
+        playlists = all_playlists.filter(name__istartswith=search_query) if search_query != "" else all_playlists.none()
 
         if search_query != "":
             for playlist in all_playlists:
-                pl_videos = playlist.videos.filter(name__startswith=search_query)
+                pl_videos = playlist.videos.filter(name__istartswith=search_query)
 
                 if pl_videos.count() != 0:
                     for v in pl_videos.all():
                         videos.append(v)
 
-        starts_with = True
     else:
-        playlists = request.user.profile.playlists.filter(
-            Q(name__contains=search_query) & Q(is_in_db=True)) if search_query != "" else []
+        playlists = all_playlists.filter(name__icontains=search_query) if search_query != "" else all_playlists.none()
 
         if search_query != "":
             for playlist in all_playlists:
-                pl_videos = playlist.videos.filter(name__contains=search_query)
+                pl_videos = playlist.videos.filter(name__icontains=search_query)
 
                 if pl_videos.count() != 0:
                     for v in pl_videos.all():
                         videos.append(v)
 
-        contains = True
-    return HttpResponse(loader.get_template("intercooler/search_untube.html")
+
+    return HttpResponse(loader.get_template("intercooler/search_untube_results.html")
                         .render({"playlists": playlists,
                                  "videos": videos,
-                                 "videos_count": len(videos),
-                                 "search_query": search_query,
-                                 "starts_with": starts_with,
-                                 "contains": contains}))
+                                 "videos_count": len(videos)}))
 
 
 @login_required

+ 10 - 7
templates/base.html

@@ -46,8 +46,9 @@
         <link href="https://fonts.googleapis.com/css2?family=Fredoka+One&family=Open+Sans&display=swap" rel="stylesheet">
 
         <link href="{% static 'fontawesome-free-5.15.3-web/css/all.min.css' %}" rel="stylesheet">
-        <link href="{% static 'jquery-toast-plugin/dist/jquery.toast.min.css' %}" rel="stylesheet">
         <link href="{% static 'bootstrap5.0.1/css/bootstrap.min.css' %}" rel="stylesheet">
+        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/bbbootstrap/libraries@main/choices.min.css">
+
 
     </head>
     <body class="text-dark" style="font-family: 'Fredoka One', monospace; filter: contrast(80%);">
@@ -136,19 +137,21 @@
         <script src="{% static 'htmx/htmx.min.js' %}" type="application/javascript"></script>
         <script src="{% static 'clipboard.js/clipboard.min.js' %}" type="application/javascript"></script>
         <script src="{% static 'jquery3.6.0/js/jquery-3.6.0.min.js' %}" type="application/javascript"></script>
-        <script src="{% static 'jquery-toast-plugin/dist/jquery.toast.min.js' %}" type="application/javascript"></script>
         <script src="{% static 'bootstrap5.0.1/js/bootstrap.bundle.js' %}" type="application/javascript"></script>
+        <script src="https://cdn.jsdelivr.net/gh/bbbootstrap/libraries@main/choices.min.js"></script>
         <!-- <script src="{% static 'htmx/extensions/class-tools.js' %}" type="application/javascript"></script> -->
 
 
         <script type="application/javascript">
-              $( document ).ready(function() {
-                  var msg = "Small Message";
-                 // var msg = "Lengthy Message is here. MMMMMmmmmmmmmmmmM";
-                  $(".msgText").text(msg);
-                    $(".alert").show();
+            $(document).ready(function(){
+
+                var multipleCancelButton = new Choices('#choices-multiple-remove-button', {
+                removeItemButton: true,
                 });
 
+
+            });
+
             document.body.addEventListener('htmx:configRequest', (event) => {
             event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
           })