storing guilds first, then subscriptions
This commit is contained in:
parent
73ee984747
commit
05e90c64e4
@ -4,7 +4,7 @@ import logging
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from apps.home.models import Subscription, TrackedContent
|
||||
from apps.home.models import Subscription, SavedGuilds
|
||||
from apps.authentication.models import UserServerLink
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -106,16 +106,6 @@ class DynamicModelSerializer(serializers.ModelSerializer):
|
||||
abstract = True
|
||||
|
||||
|
||||
# class SubscriptionTargetSerializer(DynamicModelSerializer):
|
||||
# """
|
||||
# Serializer for the Subscription Target Model.
|
||||
# """
|
||||
|
||||
# class Meta:
|
||||
# model = SubscriptionTarget
|
||||
# fields = ("id", "creation_datetime")
|
||||
|
||||
|
||||
class SubscriptionSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the Subscription Model.
|
||||
@ -130,16 +120,6 @@ class SubscriptionSerializer(DynamicModelSerializer):
|
||||
fields = ("uuid", "name", "rss_url", "image", "server", "targets", "creation_datetime", "extra_notes", "active")
|
||||
|
||||
|
||||
class TrackedContentSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the TrackedContent Model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = TrackedContent
|
||||
fields = ("uuid", "content_url", "subscription", "creation_datetime")
|
||||
|
||||
|
||||
class UserServerLinkSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the UserServerLink Model.
|
||||
@ -148,3 +128,13 @@ class UserServerLinkSerializer(DynamicModelSerializer):
|
||||
class Meta:
|
||||
model = UserServerLink
|
||||
fields = ("id", "server_id", "user", "name", "icon", "icon_url", "permissions")
|
||||
|
||||
|
||||
class SavedGuildSerializer(DynamicModelSerializer):
|
||||
"""
|
||||
Serializer for the SavedGuild model.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = SavedGuilds
|
||||
fields = ("id", "guild_id", "name", "icon")
|
||||
|
@ -6,13 +6,13 @@ from rest_framework.authtoken.views import obtain_auth_token
|
||||
from .views import (
|
||||
Subscription_ListView,
|
||||
Subscription_DetailView,
|
||||
TrackedContent_ListView,
|
||||
TrackedContent_DetailView,
|
||||
UserServerLink_ListView,
|
||||
UserServerLink_DetailView
|
||||
UserServerLink_DetailView,
|
||||
SavedGuild_ListView,
|
||||
SavedGuild_DetailView
|
||||
)
|
||||
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("api-auth/", include("rest_framework.urls", namespace="rest_framework")),
|
||||
path("api-token-auth/", obtain_auth_token),
|
||||
@ -22,13 +22,13 @@ urlpatterns = [
|
||||
path("<str:pk>/", Subscription_DetailView.as_view(), name="subscription-detail")
|
||||
])),
|
||||
|
||||
path("tracked/", include([
|
||||
path("", TrackedContent_ListView.as_view(), name="tracked"),
|
||||
path("<str:pk>/", TrackedContent_DetailView.as_view(), name="tracked-detail")
|
||||
])),
|
||||
|
||||
path("serverlink/", include([
|
||||
path("", UserServerLink_ListView.as_view(), name="serverlink"),
|
||||
path("<int:pk>/", UserServerLink_DetailView.as_view(), name="serverlink-detail")
|
||||
])),
|
||||
|
||||
path("saved-guilds/", include([
|
||||
path("", SavedGuild_ListView.as_view(), name="saved-guilds"),
|
||||
path("<int:pk>/", SavedGuild_DetailView.as_view(), name="saved-guilds-detail")
|
||||
])),
|
||||
]
|
@ -11,12 +11,12 @@ from rest_framework.pagination import PageNumberPagination
|
||||
from rest_framework.authentication import SessionAuthentication, TokenAuthentication
|
||||
from rest_framework.parsers import MultiPartParser, FormParser
|
||||
|
||||
from apps.home.models import Subscription, TrackedContent
|
||||
from apps.home.models import Subscription, SavedGuilds
|
||||
from apps.authentication.models import UserServerLink
|
||||
from .serializers import (
|
||||
SubscriptionSerializer,
|
||||
TrackedContentSerializer,
|
||||
UserServerLinkSerializer
|
||||
UserServerLinkSerializer,
|
||||
SavedGuildSerializer
|
||||
)
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -92,61 +92,6 @@ class Subscription_DetailView(generics.RetrieveUpdateDestroyAPIView):
|
||||
# .order_by("-creation_datetime")
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
# Tracked Content Views
|
||||
|
||||
class TrackedContent_ListView(generics.ListCreateAPIView):
|
||||
"""
|
||||
View to provide a list of TrackedContent model instances.
|
||||
Can also be used to create a new instance.
|
||||
|
||||
Supports: GET, POST
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
pagination_class = DefaultPagination
|
||||
serializer_class = TrackedContentSerializer
|
||||
queryset = TrackedContent.objects.all().order_by("-creation_datetime")
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["uuid", "subscription", "content_url", "creation_datetime"]
|
||||
search_fields = ["name"]
|
||||
ordering_fields = ["creation_datetime"]
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
try:
|
||||
self.perform_create(serializer)
|
||||
except IntegrityError:
|
||||
return Response(
|
||||
{"detail": "Tracked content must be unique"},
|
||||
status=status.HTTP_409_CONFLICT,
|
||||
exception=True
|
||||
)
|
||||
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
|
||||
class TrackedContent_DetailView(generics.RetrieveDestroyAPIView):
|
||||
"""
|
||||
View to provide details on a particular TrackedContent model instances.
|
||||
|
||||
Supports: GET, DELETE
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = TrackedContentSerializer
|
||||
queryset = TrackedContent.objects.all().order_by("-creation_datetime")
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
# UserServerLinks Views
|
||||
|
||||
@ -224,3 +169,59 @@ class UserServerLink_DetailView(generics.RetrieveDestroyAPIView):
|
||||
|
||||
serializer_class = UserServerLinkSerializer
|
||||
queryset = UserServerLink.objects.all()
|
||||
|
||||
|
||||
# =================================================================================================
|
||||
# SavedGuild Views
|
||||
|
||||
class SavedGuild_ListView(generics.ListCreateAPIView):
|
||||
"""
|
||||
View to provide a list of SavedGuild model instances.
|
||||
Can also be used to create a new instance.
|
||||
|
||||
Supports: GET, POST
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
|
||||
pagination_class = None
|
||||
serializer_class = SavedGuildSerializer
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["id", "guild_id", "name", "icon"]
|
||||
search_fields = ["name"]
|
||||
|
||||
def get_queryset(self):
|
||||
return SavedGuilds.objects.all()
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
try:
|
||||
self.perform_create(serializer)
|
||||
except IntegrityError:
|
||||
return Response(
|
||||
{"detail": "SavedGuild must be unique"},
|
||||
status=status.HTTP_409_CONFLICT,
|
||||
exception=True
|
||||
)
|
||||
|
||||
headers = self.get_success_headers(serializer.data)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||
|
||||
|
||||
class SavedGuild_DetailView(generics.RetrieveDestroyAPIView):
|
||||
"""
|
||||
View to provide details on a particular UserServerLink model instances.
|
||||
|
||||
Supports: GET, DELETE
|
||||
"""
|
||||
|
||||
authentication_classes = [SessionAuthentication, TokenAuthentication]
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
|
||||
serializer_class = SavedGuildSerializer
|
||||
queryset = SavedGuilds.objects.all()
|
||||
|
@ -3,7 +3,7 @@
|
||||
from django.urls import path
|
||||
from django.contrib.auth.views import LogoutView
|
||||
|
||||
from .views import DiscordLoginAction, DiscordLoginRedirect, Login, GuildsView, GuildChannelsView
|
||||
from .views import DiscordLoginAction, DiscordLoginRedirect, Login, GuildsView, GuildChannelsView, SaveGuildView
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
@ -13,6 +13,7 @@ urlpatterns = [
|
||||
path("logout/", LogoutView.as_view(), name="logout"),
|
||||
|
||||
path("guilds/", GuildsView.as_view(), name="guilds"),
|
||||
path("channels/", GuildChannelsView.as_view(), name="channels")
|
||||
path("channels/", GuildChannelsView.as_view(), name="channels"),
|
||||
path("save-guild/", SaveGuildView.as_view(), name="save-guild")
|
||||
|
||||
]
|
||||
|
@ -11,6 +11,7 @@ from django.shortcuts import render, redirect
|
||||
from django.contrib.auth import authenticate, login
|
||||
|
||||
from .models import UserServerLink
|
||||
from apps.home.models import SavedGuilds
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -97,35 +98,10 @@ class GuildsView(View):
|
||||
)
|
||||
|
||||
content = response.json()
|
||||
self.create_server_links(request.user, content)
|
||||
print(response, content)
|
||||
|
||||
return JsonResponse(content, safe=False)
|
||||
|
||||
def create_server_links(self, user, content: list[dict]):
|
||||
"""
|
||||
Creates objects representing the user's discord servers, storing
|
||||
server info and the user's permissions within.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
content : list[dict]
|
||||
Raw data for the servers.
|
||||
"""
|
||||
|
||||
servers = [
|
||||
UserServerLink(
|
||||
server_id=server["id"],
|
||||
user=user,
|
||||
name=server["name"],
|
||||
permissions=server["permissions"],
|
||||
icon=server["icon"]
|
||||
)
|
||||
for server in content
|
||||
]
|
||||
|
||||
UserServerLink.objects.filter(user=user).delete()
|
||||
UserServerLink.objects.bulk_create(servers)
|
||||
|
||||
|
||||
class GuildChannelsView(View):
|
||||
|
||||
@ -139,5 +115,30 @@ class GuildChannelsView(View):
|
||||
url=f"{settings.DISCORD_API_URL}/guilds/{guild_id}/channels",
|
||||
headers={"Authorization": f"Bot {settings.BOT_TOKEN}"}
|
||||
)
|
||||
print(response, response.json())
|
||||
|
||||
return JsonResponse(response.json(), safe=False)
|
||||
|
||||
|
||||
class SaveGuildView(View):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
||||
guild_id = request.GET.get("id")
|
||||
|
||||
if guild_id:
|
||||
return SavedGuilds.objects.filter(id=guild_id)
|
||||
|
||||
return SavedGuilds.objects.all()
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
||||
data = request.POST
|
||||
|
||||
guild = SavedGuilds.objects.get_or_create(
|
||||
id=data["id"],
|
||||
name=data["name"],
|
||||
icon=data["icon"]
|
||||
)
|
||||
|
||||
return JsonResponse(data)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Subscription, TrackedContent
|
||||
from .models import Subscription, SavedGuilds
|
||||
|
||||
|
||||
@admin.register(Subscription)
|
||||
@ -13,17 +13,8 @@ class SubscriptionAdmin(admin.ModelAdmin):
|
||||
]
|
||||
|
||||
|
||||
# @admin.register(SubscriptionTarget)
|
||||
# class SubscriptionTargetAdmin(admin.ModelAdmin):
|
||||
# list_display = [
|
||||
# "id", "creation_datetime"
|
||||
# ]
|
||||
|
||||
|
||||
@admin.register(TrackedContent)
|
||||
class TrackedContentAdmin(admin.ModelAdmin):
|
||||
@admin.register(SavedGuilds)
|
||||
class SavedGuildAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"uuid", "content_url", "subscription",
|
||||
"creation_datetime"
|
||||
"id", "name", "icon"
|
||||
]
|
||||
|
@ -0,0 +1,24 @@
|
||||
# Generated by Django 5.0.1 on 2024-04-02 11:16
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0006_alter_subscription_image'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SavedGuilds',
|
||||
fields=[
|
||||
('id', models.PositiveBigIntegerField(primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=128)),
|
||||
('icon', models.CharField(max_length=128)),
|
||||
],
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='TrackedContent',
|
||||
),
|
||||
]
|
@ -0,0 +1,24 @@
|
||||
# Generated by Django 5.0.1 on 2024-04-02 16:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0007_savedguilds_delete_trackedcontent'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='savedguilds',
|
||||
name='guild_id',
|
||||
field=models.PositiveBigIntegerField(default=1),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='id',
|
||||
field=models.AutoField(primary_key=True, serialize=False),
|
||||
),
|
||||
]
|
18
apps/home/migrations/0009_alter_savedguilds_guild_id.py
Normal file
18
apps/home/migrations/0009_alter_savedguilds_guild_id.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0.1 on 2024-04-02 16:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0008_savedguilds_guild_id_alter_savedguilds_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='guild_id',
|
||||
field=models.CharField(max_length=128),
|
||||
),
|
||||
]
|
@ -39,31 +39,26 @@ class IconPathGenerator:
|
||||
return Path(instance.__class__.__name__.lower()) / str(instance.uuid) / "icon.webp"
|
||||
|
||||
|
||||
# class SubscriptionTarget(models.Model):
|
||||
# """
|
||||
# Represents a Discord TextChannel that should be subject to the content of a Subscription.
|
||||
# """
|
||||
class SavedGuilds(models.Model):
|
||||
"""
|
||||
|
||||
"""
|
||||
|
||||
# id = models.PositiveBigIntegerField(
|
||||
# verbose_name=_("id"),
|
||||
# primary_key=True,
|
||||
# help_text=_("Discord Channel ID")
|
||||
# )
|
||||
id = models.AutoField(
|
||||
primary_key=True
|
||||
)
|
||||
|
||||
# creation_datetime = models.DateTimeField(
|
||||
# verbose_name=_("creation datetime"),
|
||||
# help_text=_("when this instance was created."),
|
||||
# default=timezone.now,
|
||||
# editable=False
|
||||
# )
|
||||
guild_id = models.CharField(
|
||||
max_length=128
|
||||
)
|
||||
|
||||
# class Meta:
|
||||
# verbose_name = "subscription target"
|
||||
# verbose_name_plural = "subscription targets"
|
||||
# get_latest_by = "-creation_date"
|
||||
name = models.CharField(
|
||||
max_length=128
|
||||
)
|
||||
|
||||
# def __str__(self):
|
||||
# return str(self.id)
|
||||
icon = models.CharField(
|
||||
max_length=128
|
||||
)
|
||||
|
||||
|
||||
class Subscription(models.Model):
|
||||
@ -155,126 +150,3 @@ class Subscription(models.Model):
|
||||
log.debug("%sSubscription Saved %s", new_text, self.uuid)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
# @property
|
||||
# def channels(self):
|
||||
# """
|
||||
# Returns all SubscriptionChannel objects linked to this Subscription.
|
||||
# """
|
||||
|
||||
# return SubscriptionChannel.objects.filter(subscription=self)
|
||||
|
||||
# def save(self, *args, **kwargs):
|
||||
# if Subscription.objects.filter(server=self.server).count() >= 1:
|
||||
# raise IntegrityError(f"Subscription limit reached for server '{self.server}'")
|
||||
|
||||
# super().save(*args, **kwargs)
|
||||
|
||||
|
||||
# class SubscriptionChannel(models.Model):
|
||||
# """
|
||||
# Represents a Discord TextChannel that should be subject to the content of a Subscription.
|
||||
# """
|
||||
|
||||
# uuid = models.UUIDField(
|
||||
# primary_key=True,
|
||||
# default=uuid4,
|
||||
# editable=False
|
||||
# )
|
||||
|
||||
# # The ID is not auto generated, but rather be obtained from discord.
|
||||
# id = models.PositiveBigIntegerField(
|
||||
# verbose_name=_("id"),
|
||||
# help_text=_("Identifier of the channel, provided by Discord.")
|
||||
# )
|
||||
|
||||
# subscription = models.ForeignKey(
|
||||
# verbose_name=_("subscription"),
|
||||
# help_text=_("The subscription of this instance."),
|
||||
# to=Subscription,
|
||||
# on_delete=models.CASCADE
|
||||
# )
|
||||
|
||||
# creation_datetime = models.DateTimeField(
|
||||
# verbose_name=_("creation datetime"),
|
||||
# help_text=_("when this instance was created."),
|
||||
# default=timezone.now,
|
||||
# editable=False
|
||||
# )
|
||||
|
||||
# class Meta:
|
||||
# verbose_name = "subscription channel"
|
||||
# verbose_name_plural = "subscription channels"
|
||||
# get_latest_by = "-creation_date"
|
||||
# constraints = [
|
||||
# models.UniqueConstraint(fields=["id", "subscription"], name="unique id & sub pair")
|
||||
# ]
|
||||
|
||||
# def __str__(self):
|
||||
# return str(self.id)
|
||||
|
||||
# def save(self, *args, **kwargs):
|
||||
# if SubscriptionChannel.objects.filter(subscription=self.subscription).count() >= 4:
|
||||
# raise IntegrityError(
|
||||
# f"SubscriptionChannel limit reached for subscription '{self.subscription}'"
|
||||
# )
|
||||
|
||||
# super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class TrackedContent(models.Model):
|
||||
"""
|
||||
Tracks content shared from an RSS Feed Subscription.
|
||||
Content is tracked to help prevent duplicate content.
|
||||
"""
|
||||
|
||||
uuid = models.UUIDField(
|
||||
primary_key=True,
|
||||
default=uuid4,
|
||||
editable=False
|
||||
)
|
||||
|
||||
subscription = models.ForeignKey(
|
||||
verbose_name=_("subscription"),
|
||||
help_text=_("The subscription that this content originated from."),
|
||||
to=Subscription,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="tracked_content"
|
||||
)
|
||||
|
||||
content_url = models.URLField(
|
||||
verbose_name=_("content url"),
|
||||
help_text=_("URL of the tracked content.")
|
||||
)
|
||||
|
||||
creation_datetime = models.DateTimeField(
|
||||
verbose_name=_("creation datetime"),
|
||||
help_text=_("when this instance was created."),
|
||||
default=timezone.now,
|
||||
editable=False
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.content_url)
|
||||
|
||||
|
||||
@receiver(pre_save, sender=TrackedContent)
|
||||
def maintain_item_cap(sender, instance, **kwargs):
|
||||
""""
|
||||
Delete the latest tracked content, if the total under
|
||||
the same subscription reaches 100.
|
||||
"""
|
||||
|
||||
log.debug("checking if tracked content can be deleted.")
|
||||
|
||||
queryset = sender.objects.filter(subscription=instance.subscription)
|
||||
total_tracked = queryset.count()
|
||||
|
||||
if total_tracked < 100:
|
||||
log.debug("tracked content cannot be deleted, less than 100 items: %s", total_tracked)
|
||||
return
|
||||
|
||||
oldest = queryset.earliest()
|
||||
|
||||
log.info("tracked content limit exceeded, deleting oldest item with uuid: %s", oldest.uuid)
|
||||
|
||||
oldest.delete()
|
||||
|
@ -1,3 +1,59 @@
|
||||
function getSavedGuilds() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
$.ajax({
|
||||
url: "/api/saved-guilds/",
|
||||
type: "GET",
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader("X-CSRFToken", CSRF_MiddlewareToken);
|
||||
},
|
||||
success: function(response) {
|
||||
resolve(response);
|
||||
},
|
||||
error: function(response) {
|
||||
reject(response);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getSavedGuild(id) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
$.ajax({
|
||||
url: `/api/saved-guilds/${id}/`,
|
||||
type: "GET",
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader("X-CSRFToken", CSRF_MiddlewareToken);
|
||||
},
|
||||
success: function(response) {
|
||||
resolve(response);
|
||||
},
|
||||
error: function(response) {
|
||||
reject(response);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function newSavedGuild(formData) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
$.ajax({
|
||||
url: "/api/saved-guilds/",
|
||||
type: "POST",
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader("X-CSRFToken", CSRF_MiddlewareToken);
|
||||
},
|
||||
success: function(response) {
|
||||
resolve(response);
|
||||
},
|
||||
error: function(response) {
|
||||
reject(response);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getSubscriptions() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
|
@ -74,7 +74,7 @@ function loadGuilds() {
|
||||
for (i = 1; i < response.length; i++) {
|
||||
var guild = response[i];
|
||||
$("#editSubServer").append($("<option>", {
|
||||
value: guild.id,
|
||||
value: guild.guild_id,
|
||||
text: guild.name
|
||||
}));
|
||||
}
|
||||
|
19
apps/templates/home/includes/servermodal.html
Normal file
19
apps/templates/home/includes/servermodal.html
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
<form id="serverForm" novalidate>
|
||||
<div class="modal fade" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
test
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<select name="serverOptions" id="serverOptions" class="select-2" data-dropdownparent="#serverForm .modal"></select>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -19,34 +19,9 @@
|
||||
|
||||
<div class="peers as-s ai-s w-100">
|
||||
<div class="peer bg-body-secondary">
|
||||
<div class="p-2 layers border-end h-100">
|
||||
<div id="serverList" class="p-2 layers border-end h-100">
|
||||
<div class="layer mb-2">
|
||||
<button type="button" class="rounded-3 p-1 bg-body bd">
|
||||
<img src="https://cdn.discordapp.com/icons/136501320340209664/bc41eb01d667196c17e05c045f357268.webp?size=80" alt="" width="50">
|
||||
</button>
|
||||
</div>
|
||||
<div class="layer mb-2">
|
||||
<button type="button" class="rounded-3 p-1 bg-body bd">
|
||||
<img src="https://cdn.discordapp.com/icons/136501320340209664/bc41eb01d667196c17e05c045f357268.webp?size=80" alt="" width="50">
|
||||
</button>
|
||||
</div>
|
||||
<div class="layer mb-2">
|
||||
<button type="button" class="rounded-3 p-1 bg-body bd">
|
||||
<img src="https://cdn.discordapp.com/icons/136501320340209664/bc41eb01d667196c17e05c045f357268.webp?size=80" alt="" width="50">
|
||||
</button>
|
||||
</div>
|
||||
<div class="layer mb-2">
|
||||
<button type="button" class="rounded-3 p-1 bg-body bd">
|
||||
<img src="https://cdn.discordapp.com/icons/136501320340209664/bc41eb01d667196c17e05c045f357268.webp?size=80" alt="" width="50">
|
||||
</button>
|
||||
</div>
|
||||
<div class="layer mb-2">
|
||||
<button type="button" class="rounded-3 p-1 bg-body bd">
|
||||
<img src="https://cdn.discordapp.com/icons/136501320340209664/bc41eb01d667196c17e05c045f357268.webp?size=80" alt="" width="50">
|
||||
</button>
|
||||
</div>
|
||||
<div class="layer mb-2">
|
||||
<button type="button" class="btn btn-secondary rounded-3 p-1 bd" onclick="javascript: alert('add new server (not implemented)');">
|
||||
<button type="button" id="newServerBtn" class="btn btn-secondary rounded-3 p-1 bd" onclick="javascript: openServerModal();">
|
||||
<span class="d-flex jc-c ai-c" style="width: 50px; height: 50px;">
|
||||
<i class="bi bi-plus-lg fs-4"></i>
|
||||
</span>
|
||||
@ -55,7 +30,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="peer-greed">
|
||||
<header class="px-4 py-3 bg-body-secondary">
|
||||
<header class="px-4 py-3 border-bottom">
|
||||
<div class="peers">
|
||||
<div class="peer-greed">
|
||||
<div class="peers ai-c">
|
||||
@ -69,7 +44,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="peer d-flex as-s ai-c">
|
||||
<button type="button" class="btn btn-primary">New Subscription</button>
|
||||
<button type="button" id="newSubscriptionBtn" class="btn btn-primary">New Subscription</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@ -115,7 +90,114 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
{% include "home/includes/servermodal.html" %}
|
||||
|
||||
{% endblock content %}
|
||||
|
||||
<!-- Specific Page JS goes HERE -->
|
||||
{% block javascripts %}{% endblock javascripts %}
|
||||
{% block javascripts %}
|
||||
|
||||
<script id="serverItemTemplate" type="text/template">
|
||||
<div class="layer mb-2">
|
||||
<button type="button" class="rounded-3 p-1 bg-body bd">
|
||||
<img src="" class="rounded-3" alt="" width="50" height="50">
|
||||
<!-- https://cdn.discordapp.com/icons/136501320340209664/bc41eb01d667196c17e05c045f357268.webp?size=80 -->
|
||||
</button>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script src="{% static 'js/api.js' %}"></script>
|
||||
<script>
|
||||
function openServerModal() {
|
||||
|
||||
$("#newServerBtn").prop("disabled", true);
|
||||
|
||||
$('#serverOptions').val(null).trigger('change');
|
||||
$("#serverOptions").empty();
|
||||
|
||||
$.ajax({
|
||||
url: "/guilds",
|
||||
type: "GET",
|
||||
success: function(response) {
|
||||
for (i = 1; i < response.length; i++) {
|
||||
var guild = response[i];
|
||||
$("#serverOptions").append($("<option>", {
|
||||
value: guild.id,
|
||||
text: guild.name,
|
||||
"data-icon": guild.icon
|
||||
}));
|
||||
}
|
||||
|
||||
$("#newServerBtn").prop("disabled", false);
|
||||
$("#serverForm .modal").modal("show");
|
||||
},
|
||||
error: function(response) {
|
||||
$("#newServerBtn").prop("disabled", false);
|
||||
alert(JSON.stringify(response, null, 4));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function addServer(serverName, serverId, serverIconHash) {
|
||||
var formData = new FormData();
|
||||
formData.append("name", serverName);
|
||||
formData.append("guild_id", serverId);
|
||||
formData.append("icon", serverIconHash);
|
||||
|
||||
newSavedGuild(formData)
|
||||
.then(resp => {
|
||||
alert(JSON.stringify(resp, null, 4));
|
||||
})
|
||||
.catch(err => {
|
||||
alert(JSON.stringify(err, null, 4));
|
||||
})
|
||||
|
||||
addServerTemplate(serverId, serverIconHash);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
getSavedGuilds()
|
||||
.then(resp => {
|
||||
alert(JSON.stringify(resp, null, 4));
|
||||
for (i=0; i < resp.length; i++) {
|
||||
var guild = resp[i];
|
||||
addServerTemplate(guild.guild_id, guild.icon);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
alert(JSON.stringify(err, null, 4));
|
||||
})
|
||||
});
|
||||
|
||||
function addServerTemplate(serverId, serverIconHash) {
|
||||
template = $($("#serverItemTemplate").html());
|
||||
template.find("img").attr("src", `https://cdn.discordapp.com/icons/${serverId}/${serverIconHash}.webp?size=80`);
|
||||
$("#serverList").prepend(template);
|
||||
}
|
||||
|
||||
$("#serverForm").on("submit", function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
var selectedOption = $("#serverOptions option:selected");
|
||||
serverName = selectedOption.text();
|
||||
serverId = selectedOption.val();
|
||||
serverIconHash = selectedOption.attr("data-icon");
|
||||
|
||||
addServer(serverName, serverId, serverIconHash);
|
||||
|
||||
// $.ajax({
|
||||
// url: "",
|
||||
// type: "GET",
|
||||
// success: function(response) {
|
||||
// alert(JSON.stringify(response, null, 4));
|
||||
// },
|
||||
// error: function(response) {
|
||||
// alert(JSON.stringify(response, null, 4));
|
||||
// }
|
||||
// });
|
||||
|
||||
$("#serverForm .modal").modal("hide");
|
||||
alert(`${serverName} ${serverId} ${serverIconHash}`);
|
||||
});
|
||||
</script>
|
||||
{% endblock javascripts %}
|
||||
|
Loading…
x
Reference in New Issue
Block a user