Skip to content

Commit

Permalink
Change how monitored entities are computed (#677)
Browse files Browse the repository at this point in the history
* ci: attach correct label to image

* refactor(backend): change input for media monitor

* fix(frontend): adapt to new gql schema

* feat(backend): param to force media monitor value

* feat(frontend): monitor media if it was added to watchlist

* feat(database): migration to monitor media

* chore(backend): change query to get monitored metadata

* fix(frontend): default value for select input

* feat: add basic changes for remix pwa

feat: add more pwa config

* Revert "feat: add basic changes for remix pwa"

This reverts commit b09968e.

* fix(frontend): use correct check for rest timer

* build(backend): bump version

* docs: add additonal plugins

* chore(backend): remove useless line

* refactor(backend): change order of functions

* feat(backend): start monitoring media when show in progress

* feat(backend): stop monitoring non shows/podcasts after then are complete
  • Loading branch information
IgnisDa committed Mar 5, 2024
1 parent d61058e commit 7696efa
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 67 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ COPY . .
RUN ./apps/backend/ci/build-app.sh

FROM $NODE_BASE_IMAGE
LABEL org.opencontainers.image.source="https://github.com/IgnisDa/ryot"
COPY --from=caddy:2.7.5 /usr/bin/caddy /usr/local/bin/caddy
RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && rm -rf /var/lib/apt/lists/*
RUN npm install --global [email protected] && concurrently --version
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ryot"
version = "4.2.13"
version = "4.2.14"
edition = "2021"
repository = "https://github.com/IgnisDa/ryot"
license = "GPL-3.0"
Expand Down
122 changes: 72 additions & 50 deletions apps/backend/src/miscellaneous/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,13 @@ struct PresignedPutUrlInput {
prefix: String,
}

#[derive(Debug, Serialize, Deserialize, InputObject, Clone, Default)]
struct ToggleMediaMonitorInput {
metadata_id: Option<i32>,
person_id: Option<i32>,
force_value: Option<bool>,
}

fn get_password_hasher() -> Argon2<'static> {
Argon2::default()
}
Expand Down Expand Up @@ -1224,14 +1231,11 @@ impl MiscellaneousMutation {
async fn toggle_media_monitor(
&self,
gql_ctx: &Context<'_>,
metadata_id: Option<i32>,
person_id: Option<i32>,
input: ToggleMediaMonitorInput,
) -> Result<bool> {
let service = gql_ctx.data_unchecked::<Arc<MiscellaneousService>>();
let user_id = service.user_id_from_ctx(gql_ctx).await?;
service
.toggle_media_monitor(user_id, metadata_id, person_id)
.await
service.toggle_media_monitor(user_id, input).await
}

/// Create or update a reminder on a media for a user.
Expand Down Expand Up @@ -1385,6 +1389,34 @@ impl MiscellaneousService {
}
}

fn get_review_export_item(rev: ReviewItem) -> ImportOrExportItemRating {
let (show_season_number, show_episode_number) = match rev.show_extra_information {
Some(d) => (Some(d.season), Some(d.episode)),
None => (None, None),
};
let podcast_episode_number = rev.podcast_extra_information.map(|d| d.episode);
let anime_episode_number = rev.anime_extra_information.and_then(|d| d.episode);
let manga_chapter_number = rev.manga_extra_information.and_then(|d| d.chapter);
ImportOrExportItemRating {
review: Some(ImportOrExportItemReview {
visibility: Some(rev.visibility),
date: Some(rev.posted_on),
spoiler: Some(rev.spoiler),
text: rev.text_original,
}),
rating: rev.rating,
show_season_number,
show_episode_number,
podcast_episode_number,
anime_episode_number,
manga_chapter_number,
comments: match rev.comments.is_empty() {
true => None,
false => Some(rev.comments),
},
}
}

impl MiscellaneousService {
async fn core_details(&self) -> Result<CoreDetails> {
Ok(CoreDetails {
Expand Down Expand Up @@ -5805,6 +5837,15 @@ impl MiscellaneousService {
)
.await
.ok();
self.toggle_media_monitor(
seen.user_id,
ToggleMediaMonitorInput {
metadata_id: Some(seen.metadata_id),
force_value: Some(true),
..Default::default()
},
)
.await?;
}
SeenState::Dropped | SeenState::OnAHold => {
self.remove_entity_from_collection(
Expand Down Expand Up @@ -5889,13 +5930,15 @@ impl MiscellaneousService {
)
.await
.ok();
let is_monitored = self
.get_metadata_monitored_status(seen.user_id, seen.metadata_id)
.await?;
if !is_monitored {
self.toggle_media_monitor(seen.user_id, Some(seen.metadata_id), None)
.await?;
}
self.toggle_media_monitor(
seen.user_id,
ToggleMediaMonitorInput {
metadata_id: Some(seen.metadata_id),
force_value: Some(true),
..Default::default()
},
)
.await?;
}
} else {
self.remove_entity_from_collection(
Expand All @@ -5908,6 +5951,15 @@ impl MiscellaneousService {
)
.await
.ok();
self.toggle_media_monitor(
seen.user_id,
ToggleMediaMonitorInput {
metadata_id: Some(seen.metadata_id),
force_value: Some(false),
..Default::default()
},
)
.await?;
};
}
};
Expand Down Expand Up @@ -5956,11 +6008,8 @@ FROM
metadata m
LEFT JOIN user_to_entity ute ON m.id = ute.metadata_id
LEFT JOIN "user" u ON ute.user_id = u.id
LEFT JOIN collection_to_entity cte ON m.id = cte.metadata_id
LEFT JOIN collection c ON cte.collection_id = c.id
LEFT JOIN "user" uc ON c.user_id = uc.id
WHERE
((ute.media_monitored = true) OR (c.name IN ('Watchlist', 'In Progress')))
ute.media_monitored = true
GROUP BY
m.id;
"#,
Expand Down Expand Up @@ -6068,12 +6117,15 @@ GROUP BY
async fn toggle_media_monitor(
&self,
user_id: i32,
metadata_id: Option<i32>,
person_id: Option<i32>,
input: ToggleMediaMonitorInput,
) -> Result<bool> {
let metadata =
associate_user_with_entity(&user_id, metadata_id, person_id, &self.db).await?;
let new_monitored_value = !metadata.media_monitored.unwrap_or_default();
associate_user_with_entity(&user_id, input.metadata_id, input.person_id, &self.db)
.await?;
let mut new_monitored_value = !metadata.media_monitored.unwrap_or_default();
if let Some(force_value) = input.force_value {
new_monitored_value = force_value;
}
let mut metadata: user_to_entity::ActiveModel = metadata.into();
metadata.media_monitored = ActiveValue::Set(Some(new_monitored_value));
metadata.save(&self.db).await?;
Expand Down Expand Up @@ -7002,36 +7054,6 @@ GROUP BY

#[cfg(debug_assertions)]
async fn development_mutation(&self) -> Result<bool> {
self.update_monitored_people_and_send_notifications()
.await?;
Ok(true)
}
}

fn get_review_export_item(rev: ReviewItem) -> ImportOrExportItemRating {
let (show_season_number, show_episode_number) = match rev.show_extra_information {
Some(d) => (Some(d.season), Some(d.episode)),
None => (None, None),
};
let podcast_episode_number = rev.podcast_extra_information.map(|d| d.episode);
let anime_episode_number = rev.anime_extra_information.and_then(|d| d.episode);
let manga_chapter_number = rev.manga_extra_information.and_then(|d| d.chapter);
ImportOrExportItemRating {
review: Some(ImportOrExportItemReview {
visibility: Some(rev.visibility),
date: Some(rev.posted_on),
spoiler: Some(rev.spoiler),
text: rev.text_original,
}),
rating: rev.rating,
show_season_number,
show_episode_number,
podcast_episode_number,
anime_episode_number,
manga_chapter_number,
comments: match rev.comments.is_empty() {
true => None,
false => Some(rev.comments),
},
}
}
7 changes: 4 additions & 3 deletions apps/frontend/app/lib/workout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,10 @@ export const addExerciseToWorkout = async (
// biome-ignore lint/suspicious/noExplicitAny: required here
statistic: s.statistic as any,
})) || [],
restTimer: defaultTimer
? { duration: defaultTimer, enabled: true }
: null,
restTimer:
typeof defaultTimer === "number"
? { duration: defaultTimer, enabled: true }
: null,
notes: [],
images: [],
videos: [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,12 @@ const searchParamsSchema = z.object({

export type SearchParams = z.infer<typeof searchParamsSchema>;

const defaultTimeSpan = TimeSpan.Last30Days;

export const loader = async ({ request }: LoaderFunctionArgs) => {
const query = zx.parseQuery(request, searchParamsSchema);
const now = dayjsLib();
const [startTime, endTime] = match(query.timeSpan || TimeSpan.Last30Days)
const [startTime, endTime] = match(query.timeSpan || defaultTimeSpan)
.with(TimeSpan.Last7Days, () => [now, now.subtract(7, "days")])
.with(TimeSpan.Last30Days, () => [now, now.subtract(30, "days")])
.with(TimeSpan.Last90Days, () => [now, now.subtract(90, "days")])
Expand Down Expand Up @@ -252,7 +254,7 @@ export default function Page() {
<SimpleGrid cols={{ base: 1, md: 2 }}>
<Select
label="Time span"
defaultValue={loaderData.query.timeSpan}
defaultValue={loaderData.query.timeSpan || defaultTimeSpan}
data={Object.values(TimeSpan)}
onChange={(v) => {
if (v) setP("timeSpan", v);
Expand Down
15 changes: 14 additions & 1 deletion apps/frontend/app/routes/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@ export const action = async ({ request }: ActionFunctionArgs) => {
const [submission, input] =
getChangeCollectionToEntityVariables(formData);
for (const collectionName of submission.collectionName) {
if (collectionName === "Watchlist") {
await gqlClient.request(
ToggleMediaMonitorDocument,
{
input: {
forceValue: true,
metadataId: input.metadataId,
personId: input.personId,
},
},
await getAuthorizationHeader(request),
);
}
await gqlClient.request(
AddEntityToCollectionDocument,
{ input: { ...input, collectionName } },
Expand Down Expand Up @@ -160,7 +173,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
const submission = processSubmission(formData, metadataOrPersonIdSchema);
await gqlClient.request(
ToggleMediaMonitorDocument,
submission,
{ input: submission },
await getAuthorizationHeader(request),
);
headers = await createToastHeaders({
Expand Down
2 changes: 2 additions & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ theme:
- navigation.instant
- navigation.tracking
- content.code.copy
- search.highlight
- search.share

plugins:
- awesome-pages
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use sea_orm_migration::prelude::*;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
let db = manager.get_connection();
db.execute_unprepared(
r#"
UPDATE user_to_entity
SET media_monitored = true
FROM collection_to_entity cte
JOIN collection c ON cte.collection_id = c.id
WHERE (c.name = 'In Progress' OR c.name = 'Watchlist')
AND (user_to_entity.metadata_id = cte.metadata_id OR user_to_entity.person_id = cte.person_id);
"#,
)
.await?;
Ok(())
}

async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> {
Ok(())
}
}
2 changes: 2 additions & 0 deletions libs/database/src/migrations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ mod m20240225_1_change_metadata_reminder_to_media_reminder;
mod m20240226_add_needs_to_be_updated_field;
mod m20240227_add_user_to_entity_constraint;
mod m20240229_change_user_notifications_data_storage;
mod m20240302_monitor_media_in_progress_or_watchlist;

pub use m20230410_create_metadata::Metadata as AliasedMetadata;
pub use m20230413_create_person::Person as AliasedPerson;
Expand Down Expand Up @@ -131,6 +132,7 @@ impl MigratorTrait for Migrator {
Box::new(m20240226_add_needs_to_be_updated_field::Migration),
Box::new(m20240227_add_user_to_entity_constraint::Migration),
Box::new(m20240229_change_user_notifications_data_storage::Migration),
Box::new(m20240302_monitor_media_in_progress_or_watchlist::Migration),
]
}
}
4 changes: 2 additions & 2 deletions libs/generated/src/graphql/backend/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const documents = {
"mutation RegisterUser($input: UserInput!) {\n registerUser(input: $input) {\n __typename\n ... on RegisterError {\n error\n }\n ... on IdObject {\n id\n }\n }\n}": types.RegisterUserDocument,
"mutation RemoveEntityFromCollection($input: ChangeCollectionToEntityInput!) {\n removeEntityFromCollection(input: $input) {\n id\n }\n}": types.RemoveEntityFromCollectionDocument,
"mutation TestUserNotificationPlatforms {\n testUserNotificationPlatforms\n}": types.TestUserNotificationPlatformsDocument,
"mutation ToggleMediaMonitor($metadataId: Int, $personId: Int) {\n toggleMediaMonitor(metadataId: $metadataId, personId: $personId)\n}": types.ToggleMediaMonitorDocument,
"mutation ToggleMediaMonitor($input: ToggleMediaMonitorInput!) {\n toggleMediaMonitor(input: $input)\n}": types.ToggleMediaMonitorDocument,
"mutation ToggleMediaOwnership($metadataId: Int!, $ownedOn: NaiveDate) {\n toggleMediaOwnership(metadataId: $metadataId, ownedOn: $ownedOn)\n}": types.ToggleMediaOwnershipDocument,
"mutation UpdateUser($input: UpdateUserInput!) {\n updateUser(input: $input) {\n id\n }\n}": types.UpdateUserDocument,
"mutation UpdateUserPreference($input: UpdateUserPreferenceInput!) {\n updateUserPreference(input: $input)\n}": types.UpdateUserPreferenceDocument,
Expand Down Expand Up @@ -265,7 +265,7 @@ export function graphql(source: "mutation TestUserNotificationPlatforms {\n tes
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "mutation ToggleMediaMonitor($metadataId: Int, $personId: Int) {\n toggleMediaMonitor(metadataId: $metadataId, personId: $personId)\n}"): (typeof documents)["mutation ToggleMediaMonitor($metadataId: Int, $personId: Int) {\n toggleMediaMonitor(metadataId: $metadataId, personId: $personId)\n}"];
export function graphql(source: "mutation ToggleMediaMonitor($input: ToggleMediaMonitorInput!) {\n toggleMediaMonitor(input: $input)\n}"): (typeof documents)["mutation ToggleMediaMonitor($input: ToggleMediaMonitorInput!) {\n toggleMediaMonitor(input: $input)\n}"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
Expand Down
Loading

0 comments on commit 7696efa

Please sign in to comment.