Przeglądaj źródła

minor semantic bugs fixed

sleepytaco 3 lat temu
rodzic
commit
299498939b

+ 6 - 1
apps/main/models.py

@@ -975,11 +975,12 @@ class PlaylistManager(models.Manager):
 
                 try:
                     pl_response = pl_request.execute()
-                except googleapiclient.errors.HttpError:  # failed to delete playlist item
+                except googleapiclient.errors.HttpError as e:  # failed to delete playlist item
                     # possible causes:
                     # playlistItemsNotAccessible (403)
                     # playlistItemNotFound (404)
                     # playlistOperationUnsupported (400)
+                    print(e, e.error_details, e.status_code)
                     continue
 
                 # playlistItem was successfully deleted if no HttpError, so delete it from db
@@ -1042,6 +1043,7 @@ class Tag(models.Model):
     name = models.CharField(max_length=69)
     created_by = models.ForeignKey(User, related_name="playlist_tags", on_delete=models.CASCADE)
 
+    times_viewed = models.IntegerField(default=0)
     # type = models.CharField(max_length=10)  # either 'playlist' or 'video'
 
     created_at = models.DateTimeField(auto_now_add=True)
@@ -1109,6 +1111,9 @@ class Playlist(models.Model):
     def __str__(self):
         return str(self.playlist_id)
 
+    def get_unavailable_videos_count(self):
+        return self.video_count - self.get_watchable_videos_count()
+
     # return count of watchable videos, i.e # videos that are not private or deleted in the playlist
     def get_watchable_videos_count(self):
         return self.videos.filter(Q(is_unavailable_on_yt=False) & Q(was_deleted_on_yt=False)).count()

+ 1 - 11
apps/main/templates/home.html

@@ -1,17 +1,7 @@
 
 {% extends 'base.html' %}
 {% block content %}
-
-            {% if messages %}
-                {% for message in messages %}
-                  <div class="alert alert-success alert-dismissible fade show" role="alert">
-                      {{ message }}
-                      <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
-                  </div>
-                {% endfor %}
-            {% else %}
-                <br>
-            {% endif %}
+        <br>
         {% if user.profile.playlists.all.count == 0 %}
             <div class="alert alert-success" role="alert">
               <h4 class="alert-heading">It's empty in here</h4>

+ 1 - 1
apps/main/templates/intercooler/playlist_watch_message.html

@@ -13,7 +13,7 @@
             {% endif %}
           <span style="color: #2c9c2c">{{ playlist.get_watched_videos_count }}</span>
               /
-              <span {% if percent_complete == 100 %}style="color: #2c9c2c"{% endif %}>{{ playlist.get_watchable_videos_count }}</span> <span {% if percent_complete == 100 %}style="color: #2c9c2c"{% endif %}> watched!</span>
+              <span {% if percent_complete == 100 %}style="color: #2c9c2c"{% endif %}>{{ playlist.get_watchable_videos_count }}</span> (<span style="color: #2c9c2c">{{ percent_complete }}%</span>) <span {% if percent_complete == 100 %}style="color: #2c9c2c"{% endif %}> watched!</span>
           {% if percent_complete != 100 %}<span class="text-dark" style="border-bottom: 3px #e760f1 dashed; {% if percent_complete >= 70 and percent_complete != 100 %}background: linear-gradient(-45deg, #AE876B, #ABA27B, #A7BC8A, #A3D69A);
                         background-size: 400% 400%; animation: gradient 7s ease infinite;{% endif %}">{{ playlist.get_watch_time_left }}</span> left to go!{% endif %}
 

+ 37 - 17
apps/main/templates/view_playlist.html

@@ -69,7 +69,14 @@
             <span class="badge bg-light text-black-50">{{ playlist.playlist_duration }} </span>
             <span class="badge bg-light text-black-50">{% if playlist.is_private_on_yt %}PRIVATE{% else %}PUBLIC{% endif %}</span>
             {% if playlist.has_unavailable_videos %}
-                    <span class="badge bg-light text-black-50">SOME VIDEOS ARE UNAVAILABLE</span>
+                    <span class="badge bg-light text-black-50">
+                        {% if playlist.get_watchable_videos_count == 0 %}
+                            ALL
+                        {% else %}
+                            {{ playlist.get_unavailable_videos_count }}
+                        {% endif %}
+                         VIDEOS ARE UNAVAILABLE
+                    </span>
             {% endif %}
             {% if playlist.has_duplicate_videos %}
                     <span class="badge bg-light text-black-50">DUPLICATE VIDEOS</span>
@@ -249,8 +256,8 @@
                     -->
                     {% if playlist.is_user_owned %}
                     <div class="btn-group me-2">
-                        <button hx-post="{% url 'delete_videos' playlist.playlist_id 'confirm' %}" hx-include="[id='video-checkboxes']" hx-target="#delete-videos-confirm-box" type="button" id="delete-vids-btn" class="btn btn-danger" data-bs-toggle="collapse" data-bs-target="#deleteItemsCollapse" aria-expanded="false" aria-controls="deleteItemsCollapse">
-                            Delete Selected Videos
+                        <button class="btn btn-danger" data-bs-toggle="collapse" data-bs-target="#deleteItemsCollapse" aria-expanded="false" aria-controls="deleteItemsCollapse">
+                            Delete Videos
                         </button>
                     </div>
                     {% endif %}
@@ -315,22 +322,35 @@
     <div id="row4" style="background-color: #0f5132">
           <div class="collapse border-danger" id="deleteItemsCollapse">
               <div class="card card-body bg-dark text-white-50">
-
                   <div id="delete-videos-confirm-box">
-                  <h5>Are you sure you want to delete these 40 items from your YouTube playlist? This cannot be undone.</h5>
-                </div>
+                    </div>
+                <br>
                   <div class="d-flex justify-content-start">
-                      <div class="btn-group ms-2">
-                        <button hx-post="{% url 'delete_videos' playlist.playlist_id 'confirmed' %}" hx-include="[id='video-checkboxes']" type="button" class="btn btn-danger" id="select-all-btn">Yes!</button>
+                      <div class="btn-group me-2">
+                        <button hx-post="{% url 'delete_videos' playlist.playlist_id 'confirm' %}" hx-include="[id='video-checkboxes']" hx-target="#delete-videos-confirm-box" type="button" class="btn btn-primary">
+                            Delete Selected
+                        </button>
+                      </div>
+
+                      {% if playlist.has_unavailable_videos %}
+                      <div class="btn-group me-2">
+                        <button hx-post="#" hx-include="[id='video-checkboxes']" type="button" class="btn btn-info">
+                            Delete {{ playlist.get_unavailable_videos_count }} Unavailable Videos
+                        </button>
                       </div>
-                      <div class="btn-group ms-2">
-                        <button type="button" class="btn btn-secondary" id="select-all-btn">Nvm</button>
+                      {% endif %}
+                        {% if playlist.has_duplicate_videos %}
+                      <div class="btn-group me-2">
+                        <button hx-post="#" hx-include="[id='video-checkboxes']" type="button" class="btn btn-warning">
+                            Delete Duplicate Videos
+                        </button>
                       </div>
-                      <div class="btn-group ms-2">
-                        <button hx-post="{% url 'delete_videos' playlist.playlist_id 'confirm' %}" hx-include="[id='video-checkboxes']" hx-target="#delete-videos-confirm-box" type="button" class="btn btn-primary">
-                            <i class="fas fa-sync"></i>
+                        {% endif %}
+                    <div class="btn-group me-2">
+                        <button hx-post="{% url 'delete_videos' playlist.playlist_id 'confirm' %}" hx-include="[id='video-checkboxes']" hx-target="#delete-videos-confirm-box" type="button" class="btn btn-danger">
+                            Empty this Playlist
                         </button>
-                    </div>
+                      </div>
                   </div>
 
               </div>
@@ -345,7 +365,7 @@
         <div class="list-group" id="video-checkboxes">
           {% for video in videos|slice:"0:50" %}
 
-            <li {% if forloop.last and videos.count > 50 %}hx-get="{% url 'load_more_videos' playlist.playlist_id order_by|default:"all" page|default:"1" %}"
+            <li id="{{ video.playlist_item_id }}" onclick="selectVideo(this);" {% if forloop.last and videos.count > 50 %}hx-get="{% url 'load_more_videos' playlist.playlist_id order_by|default:"all" page|default:"1" %}"
     hx-trigger="revealed"
     hx-swap="afterend" hx-indicator="#load-more-videos-spinner" {% endif %} class="list-group-item d-flex justify-content-between align-items-center bg-transparent" style="background-color: #40B3A2">
 
@@ -353,7 +373,7 @@
 
             <div class="d-flex justify-content-between align-items-center">
                 <div>
-                    <input class="video-checkboxes" style="display: none" type="checkbox" value="{{ video.playlist_item_id }}" name="video-id">
+                    <input class="video-checkboxes" style="display: none" type="checkbox" value="{{ video.playlist_item_id }}" id="video-{{ video.playlist_item_id }}" name="video-id">
                 </div>
                   <div class="ms-4" style="max-width: 115px; max-height: 100px;">
                       <img src="https://i.ytimg.com/vi/9219YrnwDXE/maxresdefault.jpg" class="img-fluid" alt="">
@@ -369,7 +389,7 @@
 
             <div class="d-flex justify-content-between align-items-center" >
                 <div>
-                    <input class="video-checkboxes" style="display: none" type="checkbox" value="{{ video.playlist_item_id }}" name="video-id">
+                    <input class="video-checkboxes" style="display: none" type="checkbox" value="{{ video.playlist_item_id }}" id="video-{{ video.playlist_item_id }}" name="video-id">
                 </div>
                   <div class="ms-4" style="max-width: 115px; max-height: 100px;">
 

+ 18 - 7
apps/main/views.py

@@ -142,6 +142,10 @@ def view_playlist(request, playlist_id):
     user_created_tags = Tag.objects.filter(created_by=request.user)
     playlist_tags = playlist.tags.all()
 
+    for tag in playlist_tags:
+        tag.times_viewed += 1
+        tag.save(update_fields=['times_viewed'])
+
     unused_tags = user_created_tags.difference(playlist_tags)
 
     all_videos_unavailable = False
@@ -206,7 +210,7 @@ def all_playlists(request, playlist_type):
 
             if playlists.count() == 0:
                 messages.warning(request, f"No playlists in {playlists_type}")
-                return redirect('home')
+                return redirect('/playlists/home')
             random_playlist = random.choice(playlists)
             return redirect(f'/playlist/{random_playlist.playlist_id}')
         return render(request, 'playlists_home.html')
@@ -393,14 +397,18 @@ def delete_videos(request, playlist_id, command):
         num_vids = len(video_ids)
         extra_text = " "
         if num_vids == 0:
-            return HttpResponse("<h5>Select some videos first!</h5>")
+            return HttpResponse("<h5>Select some videos first!</h5><hr>")
         elif num_vids == request.user.profile.playlists.get(playlist_id=playlist_id).videos.all().count():
             delete_text = "ALL VIDEOS"
             extra_text = " This will not delete the playlist itself, will only make the playlist empty. "
         else:
             delete_text = f"{num_vids} videos"
         return HttpResponse(
-            f"<h5>Are you sure you want to delete {delete_text} from your YouTube playlist?{extra_text}This cannot be undone.</h5>")
+            f"""<h5>
+                Are you sure you want to delete {delete_text} from your YouTube playlist?{extra_text}This cannot be undone.</h5>
+                <button hx-post="/from/{playlist_id}/delete-videos/confirmed" hx-include="[id='video-checkboxes']" hx-target="#delete-videos-confirm-box" type="button" class="btn btn-outline-danger btn-sm" id="select-all-btn">Confirm</button>
+                <hr>
+            """)
     elif command == "confirmed":
         print(video_ids)
         return HttpResponse(
@@ -411,9 +419,10 @@ def delete_videos(request, playlist_id, command):
         # playlist.has_playlist_changed = True
         # playlist.save(update_fields=['has_playlist_changed'])
         return HttpResponse(f"""
-        <div hx-get="/playlist/{playlist_id}/update/checkforupdates" hx-trigger="load delay:3s" hx-target="#checkforupdates" class="sticky-top" style="top: 0.5rem;">
-            Done! Playlist on UnTube will update in soon...
-        </div>
+        <h5 hx-get="/playlist/{playlist_id}/update/checkforupdates" hx-trigger="load delay:3s" hx-target="#checkforupdates">
+            Done deleting videos from your playlist on YouTube. Playlist on UnTube will update soon.
+        </h5>
+        <hr>
         """)
 
 
@@ -529,7 +538,9 @@ def search_UnTube(request):
     all_playlists = request.user.profile.playlists.filter(is_in_db=True)
     if 'playlist-tags' in request.POST:
         tags = request.POST.getlist('playlist-tags')
-        all_playlists = all_playlists.filter(tags__name__in=tags)
+        for tag in tags:
+            all_playlists = all_playlists.filter(tags__name=tag)
+        #all_playlists = all_playlists.filter(tags__name__in=tags)
 
     videos = []
 

+ 7 - 6
apps/users/templates/index.html

@@ -1,17 +1,18 @@
-
 {% load crispy_forms_tags %}
-
 {% load socialaccount %}
-
 {% load static %}
 
 <!doctype html>
 <html lang="en">
   <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-    <link rel="icon" href="/docs/4.0/assets/img/favicons/favicon.ico">
+    <!-- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=yes"> -->
+    <link rel="icon" href="{% static 'fontawesome-free-5.15.3-web/svgs/solid/underline.svg' %}">
 
+    <meta charset="utf-8">
+    <meta name="keywords" content="youtube, playlists, videos, delete videos, delete playlists, delete multiple videos, move multiple videos, merge playlists, video manager, playlist manager, youtube playlists, untube, google">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="description" content="UnTube is a simple Youtube playlist manager. Modify and keep track of your YouTube playlists with ease.">
+    <meta name="author" content="Mohammed Abu Bakar Khan">
     <title>UnTube</title>
 
       <style type="text/css">

+ 20 - 1
templates/base.html

@@ -3,6 +3,8 @@
 <!doctype html>
 <html lang="en">
     <head>
+        <link rel="icon" href="{% static 'fontawesome-free-5.15.3-web/svgs/solid/underline.svg' %}">
+
         <meta charset="utf-8">
         <meta name="keywords" content="youtube, playlists, videos, delete videos, delete playlists, delete multiple videos, move multiple videos, merge playlists, video manager, playlist manager, youtube playlists, untube, google">
         <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -131,6 +133,14 @@
 
             <div class="row">
                 <main class="ms-lg-auto px-lg-5">
+                {% if messages %}
+                    {% for message in messages %}
+                      <div class="alert alert-success alert-dismissible fade show" role="alert">
+                          {{ message }}
+                          <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
+                      </div>
+                    {% endfor %}
+                {% endif %}
                 {% block content %}
                 {% endblock %}
                 </main>
@@ -157,6 +167,13 @@
 
             });
 
+            function selectVideo(video) {
+                console.log(video.id);
+                console.log("video-" + video.id);
+                var videoCB = document.getElementById("video-" + video.id);
+                videoCB.checked = !videoCB.checked;  // uncheck video if check and vice versa
+            }
+
             function triggerSubmit() {
                 var startsWithCB = document.getElementById("starts-with-cb");
                 var containsCB = document.getElementById("contains-cb");
@@ -189,7 +206,8 @@
             });
 
 
-            document.getElementById('manageBtn').addEventListener('click', function () {
+            document.getElementById('manageBtn').addEventListener('click', function () {                document.getElementById("delete-videos-confirm-box").innerHTML = "";
+                document.getElementById("delete-videos-confirm-box").innerHTML = "";
                 bsMoveCopyCollapse.hide();
                 bsDeleteCollapse.hide();
             });
@@ -228,6 +246,7 @@
                  for(var i=0, len=checkboxes.length; i<len; i++)
                 {
                     checkboxes[i].style.display = "block";
+                    checkboxes[i].checked = false;
                 }
                  document.getElementById("row2").style.display = "block";
              }