Merge pull request 'v0.3.0' (#44) from staging into master
All checks were successful
Build and Push Docker Image / build (push) Successful in 24s
All checks were successful
Build and Push Docker Image / build (push) Successful in 24s
Reviewed-on: https://gitea.corbz.dev/corbz/PYRSS-Website/pulls/44
This commit is contained in:
commit
5237f6fbf9
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 0.2.2
|
||||
current_version = 0.3.0
|
||||
commit = True
|
||||
tag = True
|
||||
|
||||
|
11
CHANGELOG.md
11
CHANGELOG.md
@ -1,5 +1,14 @@
|
||||
|
||||
**unreleased**
|
||||
**breaking changes v.0.3.0**
|
||||
|
||||
- Enhancement: store guild settings in separate model
|
||||
- Breaking: server `default_embed_colour` setting will be reset due to changes on how settings are stored
|
||||
- Enhancement: moved server settinsg from tab to pop-out modal
|
||||
- Enhancement: `active` flag added as server setting, soft-toggles activeness of associated subscriptions
|
||||
- Fix: Bad text alignment for some table button links
|
||||
- Fix & Enhancement: some small clean-up/patches here and there
|
||||
- Fix: Incorrect margin on 'server settings' & 'new server' modal buttons
|
||||
- Fix: Table "X Results" text now correctly plural only if `results > 1`
|
||||
|
||||
**v0.2.2**
|
||||
|
||||
|
@ -173,7 +173,7 @@ class SavedGuildSerializer(DynamicModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = SavedGuilds
|
||||
fields = ("id", "guild_id", "name", "icon", "added_by", "permissions", "default_embed_colour", "owner")
|
||||
fields = ("id", "guild_id", "name", "icon", "added_by", "permissions", "owner")
|
||||
|
||||
|
||||
class GuildSettingsSerializer(DynamicModelSerializer):
|
||||
@ -183,7 +183,7 @@ class GuildSettingsSerializer(DynamicModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = GuildSettings
|
||||
fields = ("id", "guild_id", "default_embed_colour")
|
||||
fields = ("id", "guild_id", "default_embed_colour", "active")
|
||||
|
||||
|
||||
class TrackedContentSerializer_GET(DynamicModelSerializer):
|
||||
|
@ -405,7 +405,7 @@ class GuildSettings_ListView(generics.ListCreateAPIView):
|
||||
metadata_class = ExpandedMetadata
|
||||
|
||||
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
filterset_fields = ["id", "guild_id", "default_embed_colour"]
|
||||
filterset_fields = ["id", "guild_id", "default_embed_colour", "active"]
|
||||
|
||||
def get_queryset(self):
|
||||
if self.request.user.is_superuser:
|
||||
@ -414,9 +414,7 @@ class GuildSettings_ListView(generics.ListCreateAPIView):
|
||||
return GuildSettings.objects.filter(added_by=self.request.user)
|
||||
|
||||
def post(self, request):
|
||||
|
||||
guild_id = request.data["guild_id"]
|
||||
saved_guilds = SavedGuild.objects.filter(added_by=request.user)
|
||||
saved_guilds = SavedGuilds.objects.filter(added_by=request.user)
|
||||
|
||||
if not saved_guilds:
|
||||
return Response(
|
||||
@ -445,7 +443,7 @@ class GuildSettings_ListView(generics.ListCreateAPIView):
|
||||
return (int(permissions) & 1 << 3) == 1 << 3
|
||||
|
||||
|
||||
class GuildSettings_DetailView(generics.RetrieveDestroyAPIView):
|
||||
class GuildSettings_DetailView(generics.RetrieveUpdateDestroyAPIView):
|
||||
"""
|
||||
View to provide details on a particular GuildSettings model instances.
|
||||
|
||||
@ -462,7 +460,7 @@ class GuildSettings_DetailView(generics.RetrieveDestroyAPIView):
|
||||
if self.request.user.is_superuser:
|
||||
return GuildSettings.objects.all()
|
||||
|
||||
saved_guilds = SavedGuild.objects.filter(added_by=self.request.user)
|
||||
saved_guilds = SavedGuilds.objects.filter(added_by=self.request.user)
|
||||
guild_ids = [guild.guild_id for guild in saved_guilds]
|
||||
|
||||
return GuildSettings.objects.filter(guild_id__in=guild_ids)
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Subscription, SavedGuilds, Filter, SubChannel, TrackedContent, ArticleMutator
|
||||
from .models import Subscription, SavedGuilds, Filter, SubChannel, TrackedContent, ArticleMutator, GuildSettings
|
||||
|
||||
|
||||
@admin.register(Subscription)
|
||||
@ -44,4 +44,10 @@ class SavedGuildAdmin(admin.ModelAdmin):
|
||||
class ArticleMutatorAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id", "name", "value"
|
||||
]
|
||||
]
|
||||
|
||||
@admin.register(GuildSettings)
|
||||
class GuildSettingsAdmin(admin.ModelAdmin):
|
||||
list_display = [
|
||||
"id", "guild_id", "default_embed_colour", "active"
|
||||
]
|
||||
|
@ -0,0 +1,122 @@
|
||||
# Generated by Django 5.0.4 on 2024-08-14 20:41
|
||||
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0020_guildsettings'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='guildsettings',
|
||||
options={'get_latest_by': 'id', 'verbose_name': 'guild settings', 'verbose_name_plural': 'guild settings'},
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='savedguilds',
|
||||
name='default_embed_colour',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='guildsettings',
|
||||
name='active',
|
||||
field=models.BooleanField(default=True, help_text='Subscriptions of inactive guilds will also be treated as inactive', verbose_name='Active'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='guildsettings',
|
||||
name='guild_id',
|
||||
field=models.CharField(help_text='Discord snowflake ID for the represented guild.', max_length=128, unique=True, verbose_name='guild id'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='savedguilds',
|
||||
name='id',
|
||||
field=models.AutoField(primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='active',
|
||||
field=models.BooleanField(default=True, verbose_name='Active'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='article_fetch_image',
|
||||
field=models.BooleanField(default=True, help_text='Will the resulting article have an image?', verbose_name='Fetch Article Images'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='creation_datetime',
|
||||
field=models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Created At'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='embed_colour',
|
||||
field=models.CharField(blank=True, default='3498db', max_length=6, verbose_name='Embed Colour'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='extra_notes',
|
||||
field=models.CharField(blank=True, max_length=250, null=True, verbose_name='Extra Notes'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='guild_id',
|
||||
field=models.CharField(max_length=128, verbose_name='Guild ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='name',
|
||||
field=models.CharField(max_length=32, verbose_name='Name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='published_threshold',
|
||||
field=models.DateTimeField(blank=True, default=django.utils.timezone.now, verbose_name='Published Threshold'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='subscription',
|
||||
name='url',
|
||||
field=models.URLField(verbose_name='URL'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='blocked',
|
||||
field=models.BooleanField(default=False, verbose_name='Blocked'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='channel_id',
|
||||
field=models.CharField(max_length=128, verbose_name='Channel ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='creation_datetime',
|
||||
field=models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Created At'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='guid',
|
||||
field=models.CharField(help_text='RSS provided GUID of the content', max_length=256, verbose_name='GUID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='id',
|
||||
field=models.AutoField(primary_key=True, serialize=False, verbose_name='ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='message_id',
|
||||
field=models.CharField(max_length=128, verbose_name='Message ID'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='title',
|
||||
field=models.CharField(max_length=728, verbose_name='Title'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='trackedcontent',
|
||||
name='url',
|
||||
field=models.URLField(verbose_name='URL'),
|
||||
),
|
||||
]
|
22
apps/home/migrations/0022_populate_guild_settings.py
Normal file
22
apps/home/migrations/0022_populate_guild_settings.py
Normal file
@ -0,0 +1,22 @@
|
||||
# Generated by Django 5.0.4 on 2024-08-14 20:46
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def create_missing_guild_settings(apps, scheme_editor):
|
||||
SavedGuilds = apps.get_model("home", "SavedGuilds")
|
||||
GuildSettings = apps.get_model("home", "GuildSettings")
|
||||
|
||||
for saved_guild in SavedGuilds.objects.all():
|
||||
GuildSettings.objects.get_or_create(guild_id=saved_guild.guild_id)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('home', '0021_alter_guildsettings_options_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(create_missing_guild_settings),
|
||||
]
|
@ -23,7 +23,8 @@ class GuildSettings(models.Model):
|
||||
guild_id = models.CharField(
|
||||
verbose_name=_("guild id"),
|
||||
max_length=128,
|
||||
help_text=_("Discord snowflake ID for the represented guild.")
|
||||
help_text=_("Discord snowflake ID for the represented guild."),
|
||||
unique=True
|
||||
)
|
||||
|
||||
default_embed_colour = models.CharField(
|
||||
@ -33,6 +34,21 @@ class GuildSettings(models.Model):
|
||||
blank=True
|
||||
)
|
||||
|
||||
active = models.BooleanField(
|
||||
verbose_name=_("Active"),
|
||||
default=True,
|
||||
help_text=_("Subscriptions of inactive guilds will also be treated as inactive")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Metadata for the GuildSettings model.
|
||||
"""
|
||||
|
||||
verbose_name = "guild settings"
|
||||
verbose_name_plural = "guild settings"
|
||||
get_latest_by = "id"
|
||||
|
||||
|
||||
class SavedGuilds(models.Model):
|
||||
"""
|
||||
@ -79,12 +95,6 @@ class SavedGuilds(models.Model):
|
||||
help_text=_("Does the 'added by' user own this guild?")
|
||||
)
|
||||
|
||||
default_embed_colour = models.CharField(
|
||||
max_length=6,
|
||||
default="3498db",
|
||||
blank=True
|
||||
)
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
Metadata for the SavedGuilds Model.
|
||||
@ -109,6 +119,10 @@ class SavedGuilds(models.Model):
|
||||
def settings(self):
|
||||
return GuildSettings.objects.get(guild_id=self.guild_id)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
GuildSettings.objects.get_or_create(guild_id=self.guild_id)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
||||
class SubChannel(models.Model):
|
||||
"""
|
||||
|
@ -24,7 +24,6 @@ async function ajaxRequest(url, method, data) {
|
||||
}
|
||||
|
||||
function makeQuerystring(filters, sort) {
|
||||
console.log(JSON.stringify(filters, null, 4))
|
||||
let querystring = "?";
|
||||
for (key in filters) {
|
||||
querystring += `${key}=${filters[key]}&`;
|
||||
@ -163,4 +162,14 @@ async function getTrackedContentOptions() {
|
||||
|
||||
async function getMutators() {
|
||||
return await ajaxRequest("/api/article-mutator/?page_size=25", "GET");
|
||||
}
|
||||
}
|
||||
|
||||
// guild settings
|
||||
|
||||
async function getGuildSettings(guildId) {
|
||||
return await ajaxRequest(`/api/guild-settings/?guild_id=${guildId}`, "GET");
|
||||
}
|
||||
|
||||
async function editGuildSettings(id, formData) {
|
||||
return await ajaxRequest(`/api/guild-settings/${id}/`, "PUT", formData);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ async function initContentTable() {
|
||||
data: "title",
|
||||
className: "text-truncate",
|
||||
render: function(data, type, row) {
|
||||
return `<a href="${row.url}" class="btn btn-link text-decoration-none" target="_blank">${data}</a>`
|
||||
return `<a href="${row.url}" class="btn btn-link text-start text-decoration-none" target="_blank">${data}</a>`
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -54,7 +54,7 @@ async function initContentTable() {
|
||||
data: "subscription.name",
|
||||
className: "text-nowrap",
|
||||
render: function(data, type, row) {
|
||||
return `<button type="button" onclick="goToSubscription(${row.subscription.id})" class="btn btn-link text-decoration-none">${data}</button>`
|
||||
return `<button type="button" onclick="goToSubscription(${row.subscription.id})" class="btn btn-link text-start text-decoration-none">${data}</button>`
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -143,7 +143,7 @@ function resolveChannelNames(guildId) {
|
||||
$("<a>").text(channel.text)
|
||||
.attr("href", href)
|
||||
.attr("target", "_blank")
|
||||
.addClass("btn btn-link text-decoration-none text-nowrap")
|
||||
.addClass("btn btn-link text-start text-decoration-none text-nowrap")
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -40,7 +40,7 @@ async function initFiltersTable() {
|
||||
title: "Name",
|
||||
data: "name",
|
||||
render: function(data, type, row) {
|
||||
return `<button type="button" onclick="showEditFilterModal(${row.id})" class="btn btn-link text-decoration-none">${data}</button>`
|
||||
return `<button type="button" onclick="showEditFilterModal(${row.id})" class="btn btn-link text-start text-decoration-none">${data}</button>`
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -86,11 +86,30 @@ $(".colour-control-text").on("change", function() {
|
||||
});
|
||||
|
||||
function updateColourInput(id, hexString) {
|
||||
hexString = hexString.toUpperCase();
|
||||
hexString = normaliseHexString(hexString.toUpperCase());
|
||||
$(`#${id} .colour-picker`).val(hexString);
|
||||
$(`#${id} .colour-text`).val(hexString);
|
||||
}
|
||||
|
||||
function getColourInputVal(id, includeHashtag=true) {
|
||||
const hexString = $(`#${id}Text`).val();
|
||||
return normaliseHexString(hexString, includeHashtag);
|
||||
}
|
||||
|
||||
function normaliseHexString(hexString, includeHashtag=true) {
|
||||
console.debug(`normalising hex string '${hexString}' include hashtag '${includeHashtag}'`);
|
||||
|
||||
// Remove any non-hex characters (e.g., additional hashtags)
|
||||
hexString = hexString.replace(/[^A-F0-9]/gi, '');
|
||||
|
||||
// Ensure the hex string has a valid length of either 3, 6, or 8 characters
|
||||
if (![3, 6, 8].includes(hexString.length)) {
|
||||
throw new Error(`Invalid hex string length. Must be 3, 6, or 8 characters. hexString=${hexString}`);
|
||||
}
|
||||
|
||||
return includeHashtag ? `#${hexString}` : hexString;
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$(".colour-input").each(function() {
|
||||
let id = $(this).attr("data-id")
|
||||
|
@ -1,20 +1,59 @@
|
||||
|
||||
/** Here is how this should work
|
||||
*
|
||||
* Currently SavedGuild is created and destroyed on demand, it's not viable to store settings here
|
||||
* instead lets create a new database obj `GuildSettings` to store these, an automated job can erase
|
||||
* a `GuildSettings` instance if no matching `SavedGuilds` are found within x number of days.
|
||||
*
|
||||
* The tables will not be linked directly, but will share a common `guild_id` field to find
|
||||
* each other, or the saved guild will have a foreign key for the related `GuildSettings`.
|
||||
*/
|
||||
|
||||
$(document).on("selectedServerChange", async function() {
|
||||
server = getCurrentlyActiveServer();
|
||||
updateColourInput("defaultEmbedColour", "#" + server.default_embed_colour);
|
||||
$("#serverSettingsBtn").on("click", async function() {
|
||||
await showServerSettingsModal();
|
||||
});
|
||||
|
||||
$("#serverSettingsForm").on("submit", function(e) {
|
||||
async function showServerSettingsModal() {
|
||||
const server = getCurrentlyActiveServer();
|
||||
var guildSettings;
|
||||
|
||||
try { guildSettings = (await getGuildSettings(server.guild_id))[0] }
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
return;
|
||||
}
|
||||
|
||||
$("#guildSettingsId").val(guildSettings.id);
|
||||
$("#guildSettingsGuildId").val(guildSettings.guild_id);
|
||||
$("#guildSettingsActive").prop("checked", guildSettings.active);
|
||||
updateColourInput("guildSettingsDefaultEmbedColour", guildSettings.default_embed_colour);
|
||||
|
||||
$("#serverSettingsModal").modal("show");
|
||||
}
|
||||
|
||||
$("#serverSettingsForm").on("submit", async function(e) {
|
||||
e.preventDefault();
|
||||
alert("not implemented");
|
||||
})
|
||||
|
||||
var id = $("#guildSettingsId").val();
|
||||
guildId = $("#guildSettingsGuildId").val();
|
||||
active = $("#guildSettingsActive").prop("checked");
|
||||
defaultEmbedColour = getColourInputVal("guildSettingsDefaultEmbedColour", false);
|
||||
|
||||
const pk = await saveGuildSettings(id, guildId, defaultEmbedColour, active);
|
||||
|
||||
if (pk) {
|
||||
showToast("success", "Server Settings Saved", "Primary Key: " + pk);
|
||||
}
|
||||
|
||||
updateDefaultSubEmbedColour();
|
||||
$("#serverSettingsModal").modal("hide");
|
||||
|
||||
})
|
||||
|
||||
async function saveGuildSettings(id, guildId, defaultEmbedColour, active) {
|
||||
var formData = new FormData();
|
||||
formData.append("guild_id", guildId);
|
||||
formData.append("default_embed_colour", defaultEmbedColour);
|
||||
formData.append("active", active);
|
||||
|
||||
var response;
|
||||
try {
|
||||
response = await editGuildSettings(id, formData);
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
return false;
|
||||
}
|
||||
|
||||
return response.id;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ async function initSubscriptionTable() {
|
||||
data: "name",
|
||||
className: "text-truncate",
|
||||
render: function(data, type, row) {
|
||||
return `<button type="button" onclick="showEditSubModal(${row.id})" class="btn btn-link text-decoration-none">${data}</button>`;
|
||||
return `<button type="button" onclick="showEditSubModal(${row.id})" class="btn btn-link text-start text-decoration-none">${data}</button>`;
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -51,7 +51,7 @@ async function initSubscriptionTable() {
|
||||
data: "url",
|
||||
className: "text-truncate",
|
||||
render: function(data, type) {
|
||||
return `<a href="${data}" class="btn btn-link text-decoration-none" target="_blank">${data}</a>`;
|
||||
return `<a href="${data}" class="btn btn-link text-start text-decoration-none" target="_blank">${data}</a>`;
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -181,7 +181,6 @@ $("#addSubscriptionBtn").on("click", async function() {
|
||||
});
|
||||
|
||||
async function showEditSubModal(subId) {
|
||||
|
||||
if (subId === -1) {
|
||||
$("#subFormModal .form-create, #subAdvancedModal .form-create").show();
|
||||
$("#subFormModal .form-edit, #subAdvancedModal .form-edit").hide();
|
||||
@ -374,7 +373,7 @@ $(document).on("selectedServerChange", async function() {
|
||||
let server = getCurrentlyActiveServer();
|
||||
guildId = server.guild_id;
|
||||
|
||||
$("#subEmbedColour .colour-reset").attr("data-defaultcolour", "#" + server.default_embed_colour);
|
||||
await updateDefaultSubEmbedColour();
|
||||
|
||||
await loadSubscriptions(guildId);
|
||||
await loadChannelOptions(guildId);
|
||||
@ -382,6 +381,13 @@ $(document).on("selectedServerChange", async function() {
|
||||
await loadMutatorOptions();
|
||||
})
|
||||
|
||||
async function updateDefaultSubEmbedColour(settings=null) {
|
||||
if (!settings){
|
||||
settings = (await getGuildSettings(guildId))[0]
|
||||
}
|
||||
$("#subEmbedColour .colour-reset").attr("data-defaultcolour", "#" + settings.default_embed_colour);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
|
||||
|
@ -321,7 +321,7 @@ function createTableControls(containingSelector, pageSizeId) {
|
||||
<div class="table-controls row mb-3 px-3">
|
||||
<div class="col-lg-2">
|
||||
<div class="table-page-info d-flex justify-content-start align-items-center mx-auto">
|
||||
<span class="pageinfo-total"></span> Results
|
||||
<span class="pageinfo-total"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
@ -382,7 +382,7 @@ function updateTableContainer(containerId, page, pageSize, itemsCount, totalItem
|
||||
// Updates the pagination text for a given pageInfoId
|
||||
function updateTablePaginationInfo(pageInfoId, showing, total) {
|
||||
$(`${pageInfoId} .pageinfo-showing`).text(showing);
|
||||
$(`${pageInfoId} .pageinfo-total`).text(total);
|
||||
$(`${pageInfoId} .pageinfo-total`).text(`${total} Result${total > 1 ? "s" : ""}`);
|
||||
}
|
||||
|
||||
// Updates the pagination buttons for a given pageControlsId
|
||||
|
@ -23,7 +23,7 @@
|
||||
You must be an administrator, or own the selected server.
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="modal-footer px-4">
|
||||
<button type="submit" class="btn btn-primary rounded-1 me-0">Submit</button>
|
||||
<button type="button" class="btn btn-secondary rounded-1 ms-3" data-bs-dismiss="modal">Cancel</button>
|
||||
</div>
|
||||
|
38
apps/templates/home/includes/settingsmodal.html
Normal file
38
apps/templates/home/includes/settingsmodal.html
Normal file
@ -0,0 +1,38 @@
|
||||
<div id="serverSettingsModal" class="modal fade" data-bs-backdrop="static" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content rounded-1">
|
||||
<form id="serverSettingsForm" class="mb-0" novalidate>
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title ms-2">
|
||||
<span class="resolve-to-server-name"></span> Settings
|
||||
</h5>
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<input type="hidden" id="guildSettingsId" name="guildSettingsId">
|
||||
<input type="hidden" id="guildSettingsGuildId" name="guildSettingsGuildId">
|
||||
<div class="mb-4">
|
||||
<div class="colour-input"
|
||||
data-id="guildSettingsDefaultEmbedColour"
|
||||
data-label="Default Embed Colour"
|
||||
data-helptext="Default colour of each embed in Discord."
|
||||
data-defaultcolour="#3498db">
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="form-switch ps-0">
|
||||
<label for="guildSettingsActive" class="form-check-label mb-2">Server Active?</label>
|
||||
<br>
|
||||
<input type="checkbox" name="guildSettingsActive" id="guildSettingsActive" class="form-check-input ms-0 mt-0">
|
||||
<br>
|
||||
<div class="form-text">Is this server active?</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer px-4">
|
||||
<button type="submit" class="btn btn-primary rounded-1 ms-3 me-0">Save Changes</button>
|
||||
<button type="button" class="btn btn-secondary rounded-1 ms-3 me-0" data-bs-dismiss="modal">Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -49,7 +49,10 @@
|
||||
<h5 class="mb-0 resolve-to-server-id text-truncate text-body-secondary"></h5>
|
||||
</div>
|
||||
<div class="ms-auto">
|
||||
<button type="button" id="deleteSelectedServerBtn" class="btn btn-outline-danger rounded-1 ms-3" data-bs-toggle="tooltip" data-bs-title="Close this server">
|
||||
<button type="button" id="serverSettingsBtn" class="btn btn-outline-secondary rounded-1 ms-3" data-bs-toggle="tooltip" data-bs-title="Server settings">
|
||||
<i class="bi bi-gear"></i>
|
||||
</button>
|
||||
<button type="button" id="deleteSelectedServerBtn" class="btn btn-outline-danger rounded-1 ms-3" data-bs-toggle="tooltip" data-bs-title="Close server">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
<button type="button" id="backToSelectServer" class="btn btn-outline-secondary rounded-1 ms-3" data-bs-toggle="tooltip" data-bs-title="Go back">
|
||||
@ -82,9 +85,9 @@
|
||||
<li class="nav-item" role="presentation">
|
||||
<button id="contentTab" class="nav-link" data-bs-toggle="tab" data-bs-target="#contentTabPane" type="button" aria-controls="contentTabPane" aria-selected="false">Tracked Content</button>
|
||||
</li>
|
||||
<li class="nav-item ms-auto" role="presentation">
|
||||
<!-- <li class="nav-item ms-auto" role="presentation">
|
||||
<button id="settingsTab" class="nav-link" data-bs-toggle="tab" data-bs-target="#settingsTabPane" type="button" aria-controls="settingsTabPane" aria-selected="false">Settings</button>
|
||||
</li>
|
||||
</li> -->
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -93,7 +96,7 @@
|
||||
<div id="subscriptionsTabPane" class="tab-pane fade" role="tabpanel" aria-labelledby="subscriptionsTab" tabindex="0"></div>
|
||||
<div id="filtersTabPane" class="tab-pane fade includes-table includes-table-controls includes-table-search" role="tabpanel" aria-labelledby="filtersTab" tabindex="0"> </div>
|
||||
<div id="contentTabPane" class="tab-pane fade" role="tabpanel" aria-labelledby="contentTab" tabindex="0"></div>
|
||||
<div id="settingsTabPane" class="tab-pane fade" role="tabpanel" aria-labelledby="settingsTab" tabindex="0">{% include "home/includes/settingstab.html" %}</div>
|
||||
<!-- <div id="settingsTabPane" class="tab-pane fade" role="tabpanel" aria-labelledby="settingsTab" tabindex="0">{% include "home/includes/settingstab.html" %}</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -104,6 +107,7 @@
|
||||
{% include "home/includes/submodal.html" %}
|
||||
{% include "home/includes/filtermodal.html" %}
|
||||
{% include "home/includes/deletemodal.html" %}
|
||||
{% include "home/includes/settingsmodal.html" %}
|
||||
{% endblock content %}
|
||||
|
||||
{% block javascript %}
|
||||
|
@ -9,7 +9,7 @@ from django.utils import timezone
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
VERSION = "0.2.2"
|
||||
VERSION = "0.3.0"
|
||||
|
||||
# BASE_DIR is the root of the project, all paths should be constructed from it using pathlib
|
||||
BASE_DIR = Path(__file__).parent.parent
|
||||
|
Loading…
x
Reference in New Issue
Block a user