Skip to content

Commit

Permalink
feat: ✨ Allow editing of all onboarding pages (#471)
Browse files Browse the repository at this point in the history
* fix: 🐝 Only pass value to Custom page

* refactor: 📦 Move onboarding interface under api folder

* feat: 🎉 Add backend for fixed onboarding page

* feat: ✨ Add variable functionality to markdown editor

* feat: 🎊 Update onboarding store to handle fixed onboarding pages

* feat: 🚀 Replace static onboarding page with markdown ones

* refactor: 📦 Remove unused download buttons

* fix: 🐛 Error inte onboarding api for fixed pages

* fix: 🐝 Variable replacement in help pages

* fix: 🚑 Don't make Request help page editable

* feat: 🎉 Create migration file for fixed onboarding pages

* feat: 🎊 Make it possible to reorder all onboarding pages

* fix: 🩹 Fix onboarding migration

* fix: 🐛 Correct onboarding model

* refactor: 🔧 Simplify onboarding page creation logic

* Revert "refactor: 📦 Remove unused download buttons"

This reverts commit 5bb4059.

* feat: 🚀 Add property editable to onboarding page
feat: 🚀 Make it possible to show/hide onboarding pages

* refactor: 📦 Remove unused download buttons

* feat: 🎉 Add Download component to onboarding pages

* fix: 🚑 Fix migration for onboarding pages

* feat: ✨ Make "open server"-button a link

* fix: 🩹 Error when adding request service
  • Loading branch information
albinmedoc authored Aug 4, 2024
1 parent 2edf951 commit 3d4c06a
Show file tree
Hide file tree
Showing 28 changed files with 492 additions and 654 deletions.
6 changes: 6 additions & 0 deletions apps/wizarr-backend/wizarr_backend/api/routes/requests_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from datetime import datetime

from app.models.database.requests import Requests
from helpers.onboarding import showRequest

api = Namespace("Requests", description="Requests related operations", path="/requests")

Expand All @@ -27,6 +28,7 @@ def post(self) -> tuple[dict[str, str], int]:
# Create the request
request_db = Requests.create(**request.form)
request_db.created = datetime.utcnow()
showRequest(True)

# Return the request
return loads(dumps(model_to_dict(request_db), indent=4, sort_keys=True, default=str)), 200
Expand All @@ -51,6 +53,10 @@ def delete(self, requests_id: str) -> tuple[dict[str, str], int]:
# Delete the request
request.delete_instance()

# Check if there are no more requests in the database
if Requests.select().count() == 0:
showRequest(False)

# Responnse
response = { "message": f"Request { requests_id } has been deleted" }

Expand Down
23 changes: 20 additions & 3 deletions apps/wizarr-backend/wizarr_backend/api/routes/settings_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from app.models.database.users import Users
from app.models.database.invitations import Invitations
from app.models.database.requests import Requests
from helpers.onboarding import populateForServerType, showDiscord


api = Namespace("Settings", description="Settings related operations", path="/settings")
Expand Down Expand Up @@ -53,6 +54,14 @@ def post(self):
for key, value in settings.items():
Settings.update(key=key, value=value)

# Get the value of the 'setup' query parameter
initial_setup = request.args.get('setup') == "true"
if initial_setup and "server_type" in settings:
populateForServerType(settings["server_type"])

if "server_discord_id" in settings:
showDiscord(bool(settings["server_discord_id"]))

response = { key: value for key, value in settings.items() }

return response, 200
Expand All @@ -71,11 +80,19 @@ def put(self):
data = SettingsModel(**form)

# Extract the data from the model to a dictionary
response = data.model_dump()
settings = data.model_dump()

# Get the value of the 'setup' query parameter
initial_setup = request.args.get('setup') == "true"
if initial_setup and "server_type" in settings:
populateForServerType(settings["server_type"])

if "server_discord_id" in settings:
showDiscord(settings["server_discord_id"] != "")

# FIXME: This will send many queries to the database
# Insert the settings into the database
for key, value in response.items():
for key, value in settings.items():
setting = Settings.get_or_none(Settings.key == key)
if not setting:
Settings.create(key=key, value=value)
Expand All @@ -92,7 +109,7 @@ def put(self):
elif value == "jellyfin" or value == "emby":
Requests.delete().where(Requests.service == "overseerr").execute()

return response, 200
return settings, 200


@api.route('/<string:setting_id>')
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#
# CREATED ON VERSION: V4.1.1
# MIGRATION: 2024-08-02_22-27-11
# CREATED: Fri Aug 02 2024
#

from peewee import *
from playhouse.migrate import *

from app import db

# Do not change the name of this file,
# migrations are run in order of their filenames date and time

def run():
# Use migrator to perform actions on the database
migrator = SqliteMigrator(db)

# update onboarding table with columns (needs to be recreated)
with db.transaction():
# Step 1: Create a new table with the desired structure
db.execute_sql("""
CREATE TABLE "onboarding_temp" (
"id" INTEGER NOT NULL UNIQUE,
"value" TEXT,
"order" INTEGER NOT NULL,
"enabled" INTEGER NOT NULL DEFAULT 1,
"template" INTEGER,
"editable" INTEGER NOT NULL DEFAULT 1,
PRIMARY KEY("id")
)
""")

# Step 2: Copy data from the existing table to the new table
db.execute_sql("""
INSERT INTO onboarding_temp ("value", "order", "enabled")
SELECT "value", "order", "enabled" FROM onboarding;
""")

# Step 3: Drop the old table
db.execute_sql("DROP TABLE onboarding;")

# Step 4: Rename the new table to match the old table's name
db.execute_sql("ALTER TABLE onboarding_temp RENAME TO onboarding;")


# populate onboarding with default values
with db.transaction():

add_requests = bool(db.execute_sql("SELECT EXISTS(SELECT 1 FROM requests)").fetchone()[0])
add_discord = bool(db.execute_sql("SELECT key FROM settings WHERE key = 'server_discord_id' AND value IS NOT NULL").fetchone())

# Increment the order column by 2 for each onboarding row
db.execute_sql(f"UPDATE onboarding SET 'order' = 'order' + {2 + int(add_requests) + int(add_discord)}")
# Check if server_type is set in the settings table
if db.execute_sql("SELECT key FROM settings WHERE key = 'server_type'").fetchone():
# Get the server_type
server_type = db.execute_sql("SELECT value FROM settings WHERE key = 'server_type'").fetchone()[0]
if(server_type == "plex"):
db.execute_sql("""
INSERT INTO onboarding ("order", "template", "value") VALUES
(0, NULL, '## ℹ️ Eh, So, What is Plex exactly?
Great question! Plex is a software that allows individuals to share their media collections with others. If you''ve received this invitation, it means someone wants to share their library with you.
With Plex, you''ll have access to all of the movies, TV shows, music, and photos that are stored on their server!
So let''s see how to get started!'),
(1, 3, '## Join & Download Plex
So you now have access to our server''s media collection. Let''s make sure you know how to use it with Plex.
Planning on watching movies on this device?')
""")
if(server_type == "jellyfin"):
db.execute_sql("""
INSERT INTO onboarding ("order", "template", "value") VALUES
(0, NULL, '## ℹ️ Eh, So, What is Jellyfin exactly?
Jellyfin is a platform that lets you stream all your favorite movies, TV shows, and music in one place. It''s like having your own personal movie theater right at your fingertips! Think of it as a digital library of your favorite content that you can access from anywhere, on any device - your phone, tablet, laptop, smart TV, you name it.?
## 🍿 Right, so how do I watch stuff?
It couldn''t be simpler! Jellyfin is available on a wide variety of devices including laptops, tablets, smartphones, and TVs. All you need to do is download the Jellyfin app on your device, sign in with your account, and you''re ready to start streaming your media. It''s that easy!'),
(1, 3, '## Join & Download Jellyfin
So you now have access to our server''s media collection. Let''s make sure you know how to use it with Jellyfin.
Planning on watching movies on this device?')
""")
if(server_type == "emby"):
db.execute_sql("""
INSERT INTO onboarding ("order", "template", "value") VALUES
(0, NULL, '## ℹ️ Eh, So, What is Emby exactly?
Emby is a platform that lets you stream all your favorite movies, TV shows, and music in one place. It''s like having your own personal movie theater right at your fingertips! Think of it as a digital library of your favorite content that you can access from anywhere, on any device - your phone, tablet, laptop, smart TV, you name it.
## 🍿 Right, so how do I watch stuff?
It couldn''t be simpler! Emby is available on a wide variety of devices including laptops, tablets, smartphones, and TVs. All you need to do is download the Emby app on your device, sign in with your account, and you''re ready to start streaming your media. It''s that easy!'),
(1, 3, '## Join & Download Emby
Great news! You now have access to our server''s media collection. Let''s make sure you know how to use it with Emby.
Planning on watching movies on this device?')
""")

if add_discord:
db.execute_sql("""INSERT INTO onboarding ("order", "template", "editable") VALUES (2, 1, 0)""")
if add_requests:
db.execute_sql("""INSERT INTO onboarding ("order", "template", "editable") VALUES (3, 2, 0)""")

elif add_requests:
db.execute_sql("""INSERT INTO onboarding ("order", "template", "editable") VALUES (2, 2, 0)""")
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

class Onboarding(BaseModel):
id = IntegerField(primary_key=True, unique=True)
value = CharField(null=False)
value = CharField()
order = IntegerField(null=False, unique=True)
enabled = BooleanField(default=False)
enabled = BooleanField(default=True)
template = IntegerField()
editable = BooleanField(default=True)
1 change: 1 addition & 0 deletions apps/wizarr-backend/wizarr_backend/helpers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
from .settings import *
from .accounts import *
from .universal import *
from .onboarding import *
45 changes: 45 additions & 0 deletions apps/wizarr-backend/wizarr_backend/helpers/onboarding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from enum import Enum
from peewee import fn
from app.models.database.settings import Settings
from app.models.database.onboarding import Onboarding

class TemplateType(Enum):
Discord = 1
Request = 2
Download = 3

def getNextOrder():
return (Onboarding.select(fn.MAX(Onboarding.order)).scalar() or -1) + 1

def populateForServerType(server_type: str):
next_order = getNextOrder()
if(server_type == "plex"):
Onboarding.create(id=1, order=next_order, value="## ℹ️ Eh, So, What is Plex exactly?\n\nGreat question! Plex is a software that allows individuals to share their media collections with others. If you've received this invitation, it means someone wants to share their library with you.\n\nWith Plex, you'll have access to all of the movies, TV shows, music, and photos that are stored on their server!\n\nSo let's see how to get started!")
Onboarding.create(id=2, order=next_order + 1, template=TemplateType.Download.value, value="## Join & Download Plex\n\nSo you now have access to our server's media collection. Let's make sure you know how to use it with Plex.\n\nPlanning on watching movies on this device?")
elif(server_type == "jellyfin"):
Onboarding.create(id=3, order=next_order, value="## ℹ️ Eh, So, What is Jellyfin exactly?\n\nJellyfin is a platform that lets you stream all your favorite movies, TV shows, and music in one place. It's like having your own personal movie theater right at your fingertips! Think of it as a digital library of your favorite content that you can access from anywhere, on any device - your phone, tablet, laptop, smart TV, you name it.?\n\n## 🍿 Right, so how do I watch stuff??\n\nIt couldn't be simpler! Jellyfin is available on a wide variety of devices including laptops, tablets, smartphones, and TVs. All you need to do is download the Jellyfin app on your device, sign in with your account, and you're ready to start streaming your media. It's that easy!")
Onboarding.create(id=4, order=next_order + 1, template=TemplateType.Download.value, value="## Join & Download Jellyfin\n\nSo you now have access to our server's media collection. Let's make sure you know how to use it with Jellyfin.\n\nPlanning on watching movies on this device?")
elif(server_type == "emby"):
Onboarding.create(id=5, order=next_order, value="## ℹ️ Eh, So, What is Emby exactly?\n\nEmby is a platform that lets you stream all your favorite movies, TV shows, and music in one place. It's like having your own personal movie theater right at your fingertips! Think of it as a digital library of your favorite content that you can access from anywhere, on any device - your phone, tablet, laptop, smart TV, you name it.\n\n## 🍿 Right, so how do I watch stuff?\n\nIt couldn't be simpler! Emby is available on a wide variety of devices including laptops, tablets, smartphones, and TVs. All you need to do is download the Emby app on your device, sign in with your account, and you're ready to start streaming your media. It's that easy!")
Onboarding.create(id=6, order=next_order + 1, template=TemplateType.Download.value, value="## Join & Download Emby\n\nGreat news! You now have access to our server's media collection. Let's make sure you know how to use it with Emby.\n\nPlanning on watching movies on this device?")

def showStatic(template: int, show: bool):
static_row = Onboarding.get_or_none(template=template)
if show:
if not static_row:
Onboarding.create(order=getNextOrder(), template=template, editable=False)
elif static_row.enabled == False:
static_row.enabled = True
static_row.save()
else:
if static_row and static_row.enabled == True:
static_row.enabled = False
static_row.save()


def showRequest(show: bool):
showStatic(TemplateType.Request.value, show)

def showDiscord(show: bool):
showStatic(TemplateType.Discord.value, show)

This file was deleted.

Loading

0 comments on commit 3d4c06a

Please sign in to comment.