Skip to content

Commit

Permalink
Merge pull request #1127 from IgnisDa/issue-966
Browse files Browse the repository at this point in the history
Allow importing workouts from Hevy
  • Loading branch information
IgnisDa authored Dec 12, 2024
2 parents b84789c + 52cb158 commit 315fd78
Show file tree
Hide file tree
Showing 33 changed files with 346 additions and 100 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion apps/backend/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub async fn create_app_services(
s3_client,
config.file_storage.s3_bucket_name.clone(),
));
let cache_service = CacheService::new(&db);
let cache_service = CacheService::new(&db, config.clone());
let supporting_service = Arc::new(
SupportingService::new(
&db,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -539,25 +539,25 @@ export default function Page() {
};
});
invariant(data);
return (
return data.filter((d) => d.value).length > 0 ? (
<Paper key={best} withBorder py="md" radius="md">
<Stack>
<Title order={3} ta="center">
{changeCase(best)}
</Title>
<LineChart
ml={-15}
connectNulls
h={300}
ml={-15}
data={data}
connectNulls
dataKey="name"
series={[
{ name: "value", label: changeCase(best) },
]}
dataKey="name"
/>
</Stack>
</Paper>
);
) : null;
})}
</Stack>
</Tabs.Panel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,11 @@ export const action = async ({ request }: ActionFunctionArgs) => {
formData.delete("source");
const values = await match(source)
.with(
ImportSource.Storygraph,
ImportSource.Hevy,
ImportSource.Imdb,
ImportSource.Goodreads,
ImportSource.OpenScale,
ImportSource.Goodreads,
ImportSource.Storygraph,
() => ({
genericCsv: processSubmission(formData, genericCsvImportFormSchema),
}),
Expand Down Expand Up @@ -270,9 +271,10 @@ export default function Page() {
),
)
.with(
ImportSource.Hevy,
ImportSource.Imdb,
ImportSource.OpenScale,
ImportSource.Goodreads,
ImportSource.Imdb,
ImportSource.Storygraph,
() => (
<>
Expand Down
17 changes: 9 additions & 8 deletions crates/enums/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ pub enum ImportSource {
Igdb,
Imdb,
Plex,
Hevy,
Trakt,
Movary,
Jellyfin,
Expand Down Expand Up @@ -565,17 +566,17 @@ pub enum IntegrationProvider {
}

#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
EnumIter,
DeriveActiveEnum,
Deserialize,
Serialize,
Enum,
Copy,
Clone,
Debug,
Display,
EnumIter,
PartialEq,
Serialize,
Deserialize,
DeriveActiveEnum,
)]
#[sea_orm(
rs_type = "String",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use sea_orm_migration::prelude::*;

use crate::m20231017_create_user_to_entity::CONSTRAINT_SQL;
use super::m20231017_create_user_to_entity::CONSTRAINT_SQL;

#[derive(DeriveMigrationName)]
pub struct Migration;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use sea_orm_migration::prelude::*;

use crate::{
use super::{
m20231016_create_collection_to_entity::{CONSTRAINT_SQL, ENTITY_ID_SQL, ENTITY_LOT_SQL},
m20240904_create_monitored_entity::MONITORED_ENTITY_VIEW_CREATION_SQL,
};
Expand Down
2 changes: 1 addition & 1 deletion crates/migrations/src/m20241019_changes_for_issue_929.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use sea_orm_migration::prelude::*;

use crate::m20240904_create_monitored_entity::MONITORED_ENTITY_VIEW_CREATION_SQL;
use super::m20240904_create_monitored_entity::MONITORED_ENTITY_VIEW_CREATION_SQL;

#[derive(DeriveMigrationName)]
pub struct Migration;
Expand Down
2 changes: 1 addition & 1 deletion crates/migrations/src/m20241126_changes_for_issue_1113.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use sea_orm_migration::prelude::*;

use crate::{
use super::{
m20230822_create_exercise::EXERCISE_NAME_INDEX,
m20240827_create_daily_user_activity::create_daily_user_activity_table,
};
Expand Down
2 changes: 1 addition & 1 deletion crates/models/database/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use sea_orm::{
ActiveModelTrait, ActiveValue, ColumnTrait, ConnectionTrait, EntityTrait, QueryFilter,
};

use crate::{prelude::UserToEntity, user_to_entity};
use super::{prelude::UserToEntity, user_to_entity};

pub async fn get_user_to_entity_association<C>(
db: &C,
Expand Down
2 changes: 1 addition & 1 deletion crates/models/database/src/review.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rust_decimal::Decimal;
use sea_orm::{entity::prelude::*, ActiveValue};
use serde::{Deserialize, Serialize};

use crate::functions::associate_user_with_entity;
use super::functions::associate_user_with_entity;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)]
#[sea_orm(table_name = "review")]
Expand Down
2 changes: 1 addition & 1 deletion crates/models/database/src/seen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use rust_decimal_macros::dec;
use sea_orm::{entity::prelude::*, ActiveValue};
use serde::{Deserialize, Serialize};

use crate::functions::associate_user_with_entity;
use super::functions::associate_user_with_entity;

#[derive(Clone, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize, SimpleObject, Educe)]
#[graphql(name = "Seen")]
Expand Down
6 changes: 4 additions & 2 deletions crates/models/media/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,12 +611,14 @@ pub struct ImportOrExportPersonItem {
#[derive(Debug, Serialize, Deserialize, Clone, Schematic)]
#[serde(rename_all = "snake_case")]
pub struct ImportOrExportExerciseItem {
/// The unique identifier of the exercise.
pub id: String,
/// The name of the exercise.
pub name: String,
/// The review history for the user.
pub reviews: Vec<ImportOrExportItemRating>,
/// The collections this entity was added to.
pub collections: Vec<String>,
/// The review history for the user.
pub reviews: Vec<ImportOrExportItemRating>,
}

#[derive(
Expand Down
1 change: 0 additions & 1 deletion crates/providers/src/igdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,6 @@ impl IgdbService {
let access_token = self.get_access_token().await;
cc.set_with_expiry(
ApplicationCacheKey::IgdbSettings,
None,
ApplicationCacheValue::IgdbSettings {
access_token: access_token.clone(),
},
Expand Down
1 change: 0 additions & 1 deletion crates/providers/src/listennotes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ impl ListennotesService {
}
cc.set_with_expiry(
ApplicationCacheKey::ListennotesSettings,
None,
ApplicationCacheValue::ListennotesSettings {
genres: genres.clone(),
},
Expand Down
1 change: 0 additions & 1 deletion crates/providers/src/tmdb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1345,7 +1345,6 @@ async fn get_settings(
};
cc.set_with_expiry(
ApplicationCacheKey::TmdbSettings,
None,
ApplicationCacheValue::TmdbSettings(settings.clone()),
)
.await
Expand Down
1 change: 1 addition & 0 deletions crates/services/cache/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ async-graphql = { workspace = true }
chrono = { workspace = true }
common-models = { path = "../../models/common" }
common-utils = { path = "../../utils/common" }
config = { path = "../../config" }
database-models = { path = "../../models/database" }
sea-orm = { workspace = true }
sea-query = { workspace = true }
Expand Down
27 changes: 24 additions & 3 deletions crates/services/cache/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::sync::Arc;

use async_graphql::Result;
use chrono::{Duration, Utc};
use common_models::{ApplicationCacheKey, ApplicationCacheValue};
Expand All @@ -9,22 +11,41 @@ use uuid::Uuid;

pub struct CacheService {
db: DatabaseConnection,
config: Arc<config::AppConfig>,
}

impl CacheService {
pub fn new(db: &DatabaseConnection) -> Self {
Self { db: db.clone() }
pub fn new(db: &DatabaseConnection, config: Arc<config::AppConfig>) -> Self {
Self {
config,
db: db.clone(),
}
}
}

impl CacheService {
fn get_expiry_for_key(&self, key: &ApplicationCacheKey) -> Option<i64> {
match key {
ApplicationCacheKey::UserAnalyticsParameters { .. } => Some(8),
ApplicationCacheKey::UserAnalytics { .. } => Some(2),
ApplicationCacheKey::IgdbSettings
| ApplicationCacheKey::ListennotesSettings
| ApplicationCacheKey::ServerKeyValidated
| ApplicationCacheKey::TmdbSettings => None,
ApplicationCacheKey::MetadataRecentlyConsumed { .. } => Some(1),
ApplicationCacheKey::ProgressUpdateCache { .. } => {
Some(self.config.server.progress_update_threshold)
}
}
}

pub async fn set_with_expiry(
&self,
key: ApplicationCacheKey,
expiry_hours: Option<i64>,
value: ApplicationCacheValue,
) -> Result<Uuid> {
let now = Utc::now();
let expiry_hours = self.get_expiry_for_key(&key);
let to_insert = application_cache::ActiveModel {
key: ActiveValue::Set(key),
value: ActiveValue::Set(value),
Expand Down
1 change: 1 addition & 0 deletions crates/services/exporter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ database-models = { path = "../../models/database" }
database-utils = { path = "../../utils/database" }
dependent-models = { path = "../../models/dependent" }
enums = { path = "../../enums" }
itertools = { workspace = true }
fitness-models = { path = "../../models/fitness" }
media-models = { path = "../../models/media" }
mime_guess = { workspace = true }
Expand Down
29 changes: 20 additions & 9 deletions crates/services/exporter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use database_utils::{
use dependent_models::{ImportOrExportWorkoutItem, ImportOrExportWorkoutTemplateItem};
use enums::EntityLot;
use fitness_models::UserMeasurementsListInput;
use itertools::Itertools;
use media_models::{
ImportOrExportExerciseItem, ImportOrExportItemRating, ImportOrExportItemReview,
ImportOrExportMetadataGroupItem, ImportOrExportMetadataItem, ImportOrExportMetadataItemSeen,
Expand Down Expand Up @@ -373,27 +374,37 @@ impl ExporterService {
user_id: &String,
writer: &mut JsonStreamWriter<StdFile>,
) -> Result<()> {
let exercises = Exercise::find()
.filter(exercise::Column::CreatedByUserId.eq(user_id))
let exercises = UserToEntity::find()
.select_only()
.column(exercise::Column::Id)
.column(exercise::Column::Name)
.filter(user_to_entity::Column::UserId.eq(user_id))
.filter(user_to_entity::Column::ExerciseId.is_not_null())
.left_join(Exercise)
.into_tuple::<(String, String)>()
.all(&self.0.db)
.await
.unwrap();
for e in exercises {
let reviews = item_reviews(user_id, &e.id, EntityLot::Exercise, false, &self.0)
for (exercise_id, exercise_name) in exercises {
let reviews = item_reviews(user_id, &exercise_id, EntityLot::Exercise, false, &self.0)
.await?
.into_iter()
.map(|r| self.get_review_export_item(r))
.collect();
.collect_vec();
let collections =
entity_in_collections(&self.0.db, user_id, &e.id, EntityLot::Exercise)
entity_in_collections(&self.0.db, user_id, &exercise_id, EntityLot::Exercise)
.await?
.into_iter()
.map(|c| c.name)
.collect();
.collect_vec();
if reviews.is_empty() && collections.is_empty() {
continue;
}
let exp = ImportOrExportExerciseItem {
name: e.name,
collections,
reviews,
collections,
id: exercise_id,
name: exercise_name,
};
writer.serialize_value(&exp).unwrap();
}
Expand Down
4 changes: 1 addition & 3 deletions crates/services/importer/src/audiobookshelf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ use reqwest::{
use serde_json::json;
use specific_models::audiobookshelf as audiobookshelf_models;

use crate::utils;

use super::{ImportFailStep, ImportFailedItem};
use super::{utils, ImportFailStep, ImportFailedItem};

pub async fn import<F>(
input: DeployUrlAndKeyImportInput,
Expand Down
4 changes: 1 addition & 3 deletions crates/services/importer/src/goodreads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ use rust_decimal::Decimal;
use rust_decimal_macros::dec;
use serde::Deserialize;

use crate::utils;

use super::{ImportFailStep, ImportFailedItem};
use super::{utils, ImportFailStep, ImportFailedItem};

#[derive(Debug, Deserialize)]
struct Book {
Expand Down
Loading

0 comments on commit 315fd78

Please sign in to comment.