diff --git a/.github/workflows/build-api.yml b/.github/workflows/build-api.yml deleted file mode 100644 index 0b18874..0000000 --- a/.github/workflows/build-api.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Build and test api - -on: - workflow_dispatch: - push: - branches: [ main, develop ] - pull_request: - branches: [ main, develop ] - -env: - CARGO_TERM_COLOR: always - -jobs: - - build: - - defaults: - run: - shell: bash - working-directory: mediarepo-api - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v2 - if: ${{ !env.ACT }} - - - name: Cache build data - if: ${{ !env.ACT }} - uses: actions/cache@v2 - with: - path: | - target - ~/.cargo/ - key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo- - - - name: Install OS-specific dependencies - uses: knicknic/os-specific-run@v1.0.3 - with: - linux: | - sudo apt-get update - DEBIAN_FRONTEND=noninteractive sudo apt-get install libwebkit2gtk-4.0-dev libgtk-3-dev libappindicator3-dev -y - - - name: Build - run: cargo build - - - name: Build API - run: cargo build --features=client-api - - - name: Build Plugin - run: cargo build --features=tauri-plugin - - - name: Test - run: cargo test --all-features \ No newline at end of file diff --git a/.github/workflows/build-daemon.yml b/.github/workflows/build-daemon.yml deleted file mode 100644 index dd5be49..0000000 --- a/.github/workflows/build-daemon.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Build daemon - -on: - workflow_dispatch: - push: - branches: [ main, develop ] - pull_request: - branches: [ main, develop ] - -env: - CARGO_TERM_COLOR: always - -jobs: - - build: - - defaults: - run: - shell: bash - working-directory: mediarepo-daemon - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v2 - if: ${{ !env.ACT }} - - - name: Cache build data - if: ${{ !env.ACT }} - uses: actions/cache@v2 - with: - path: | - target - ~/.cargo/ - key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }} - restore-keys: | - ${{ runner.os }}-cargo- - - - name: Build - run: cargo build --release --no-default-features - - - name: Upload artifacts - if: ${{ !env.ACT }} - uses: actions/upload-artifact@v2 - with: - name: mediarepo-daemon-${{ runner.os }} - path: | - target/release/mediarepo-daemon* \ No newline at end of file diff --git a/.github/workflows/build-ui.yml b/.github/workflows/build-ui.yml deleted file mode 100644 index 63d65ab..0000000 --- a/.github/workflows/build-ui.yml +++ /dev/null @@ -1,150 +0,0 @@ -name: Build ui - -on: - workflow_dispatch: - push: - branches: - - main - - develop - pull_request: - branches: - - main - - develop - -jobs: - - build-debug: - defaults: - run: - shell: bash - working-directory: mediarepo-ui - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - - steps: - - uses: actions/checkout@v2 - if: ${{ !env.ACT }} - - - name: Cache Dependencies - if: ${{ !env.ACT }} - id: cache-dependencies - uses: actions/cache@v2 - with: - path: | - node_modules - src-tauri/target/**/deps - /home/runner/.cargo/bin - ~/.cargo - key: ${{ runner.os }}-dependencies-${{ hashFiles('src-tauri/Cargo.lock') }}-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-dependencies- - ${{ runner.os }}-release-dependencies- - - - name: Use Node.js 16 - uses: actions/setup-node@v1 - with: - node-version: 16 - - - name: Install Tauri - run: cargo install tauri-cli --git https://github.com/tauri-apps/tauri - - - name: Install Angular CLI - run: npm install -g @angular/cli - - - name: Install yarn - run: npm install -g yarn - - - name: Install dependencies - run: yarn install - - - name: Install OS-specific dependencies - uses: knicknic/os-specific-run@v1.0.3 - with: - linux: | - sudo apt-get update - DEBIAN_FRONTEND=noninteractive sudo apt-get install libwebkit2gtk-4.0-dev libgtk-3-dev libappindicator3-dev -y - - - name: Build project - run: cargo tauri build --debug - - - name: Upload artifacts - if: ${{ !env.ACT }} - uses: actions/upload-artifact@v2 - with: - name: mediarepo-ui-${{ runner.os }}-debug - path: | - src-tauri/target/debug/bundle - src-tauri/target/debug/mediarepo-ui* - - build-release: - - defaults: - run: - shell: bash - working-directory: mediarepo-ui - - runs-on: ${{ matrix.os }} - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, macos-latest, windows-latest] - - steps: - - uses: actions/checkout@v2 - if: ${{ !env.ACT }} - - - name: Cache Dependencies - if: ${{ !env.ACT }} - id: cache-dependencies - uses: actions/cache@v2 - with: - path: | - node_modules - src-tauri/target - /home/runner/.cargo - ~/.cargo - key: ${{ runner.os }}-release-dependencies-${{ hashFiles('src-tauri/Cargo.lock') }}-${{ hashFiles('yarn.lock') }} - restore-keys: | - ${{ runner.os }}-release-dependencies- - ${{ runner.os }}-dependencies- - - - name: Use Node.js 16 - uses: actions/setup-node@v1 - with: - node-version: 16 - - - name: Install Tauri - run: cargo install tauri-cli --git https://github.com/tauri-apps/tauri - - - name: Install Angular CLI - run: npm install -g @angular/cli - - - name: Install yarn - run: npm install -g yarn - - - name: Install dependencies - run: yarn install - - - name: Install OS-specific dependencies - uses: knicknic/os-specific-run@v1.0.3 - with: - linux: | - sudo apt-get update - DEBIAN_FRONTEND=noninteractive sudo apt-get install libwebkit2gtk-4.0-dev libgtk-3-dev libappindicator3-dev -y - - - name: Build project - run: cargo tauri build - - - name: Upload artifacts - if: ${{ !env.ACT }} - uses: actions/upload-artifact@v2 - with: - name: mediarepo-ui-${{ runner.os }}-release - path: | - src-tauri/target/release/bundle - src-tauri/target/release/mediarepo-ui* diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..26f53de --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,174 @@ +name: Build and test + +on: + workflow_dispatch: + push: + branches: [ main, gh-actions ] + pull_request: + branches: [ main ] + +env: + CARGO_TERM_COLOR: always + +jobs: + + build-api: + + defaults: + run: + shell: bash + working-directory: mediarepo-api + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + if: ${{ !env.ACT }} + + - name: Cache build data + if: ${{ !env.ACT }} + uses: actions/cache@v2 + with: + path: | + target + ~/.cargo/ + key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Install OS-specific dependencies + uses: knicknic/os-specific-run@v1.0.3 + with: + linux: | + sudo apt-get update + DEBIAN_FRONTEND=noninteractive sudo apt-get install libwebkit2gtk-4.0-dev libgtk-3-dev libappindicator3-dev -y + + - name: Build + run: cargo build + + - name: Build API + run: cargo build --features=client-api + + - name: Build Plugin + run: cargo build --features=tauri-plugin + + - name: Test + run: cargo test --all-features + + build-daemon: + + # to run fewer steps in parallel + needs: build-api + + defaults: + run: + shell: bash + working-directory: mediarepo-daemon + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + if: ${{ !env.ACT }} + + - name: Cache build data + if: ${{ !env.ACT }} + uses: actions/cache@v2 + with: + path: | + target + ~/.cargo/ + key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }} + restore-keys: | + ${{ runner.os }}-cargo- + + - name: Build + run: cargo build --release --no-default-features + + - name: Upload artifacts + if: ${{ !env.ACT }} + uses: actions/upload-artifact@v2 + with: + name: mediarepo-daemon-${{ runner.os }} + path: | + target/release/mediarepo-daemon* + + build-ui: + + # to run fewer steps in parallel + needs: build-api + + defaults: + run: + shell: bash + working-directory: mediarepo-ui + + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + steps: + - uses: actions/checkout@v2 + if: ${{ !env.ACT }} + + - name: Cache Dependencies + if: ${{ !env.ACT }} + id: cache-dependencies + uses: actions/cache@v2 + with: + path: | + node_modules + src-tauri/target + /home/runner/.cargo + ~/.cargo + key: ${{ runner.os }}-release-dependencies-${{ hashFiles('src-tauri/Cargo.lock') }}-${{ hashFiles('yarn.lock') }} + restore-keys: | + ${{ runner.os }}-release-dependencies- + ${{ runner.os }}-dependencies- + + - name: Use Node.js 16 + uses: actions/setup-node@v1 + with: + node-version: 16 + + - name: Install Tauri + run: cargo install tauri-cli --git https://github.com/tauri-apps/tauri + + - name: Install Angular CLI + run: npm install -g @angular/cli + + - name: Install yarn + run: npm install -g yarn + + - name: Install dependencies + run: yarn install + + - name: Install OS-specific dependencies + uses: knicknic/os-specific-run@v1.0.3 + with: + linux: | + sudo apt-get update + DEBIAN_FRONTEND=noninteractive sudo apt-get install libwebkit2gtk-4.0-dev libgtk-3-dev libappindicator3-dev -y + + - name: Build project + run: cargo tauri build + + - name: Upload artifacts + if: ${{ !env.ACT }} + uses: actions/upload-artifact@v2 + with: + name: mediarepo-ui-${{ runner.os }}-release + path: | + src-tauri/target/release/bundle + src-tauri/target/release/mediarepo-ui* diff --git a/README.md b/README.md index 4188192..0e922fd 100644 --- a/README.md +++ b/README.md @@ -2,34 +2,43 @@ mediarepo

- + +

+

mediarepo is a work in progress

+

+ + + + + + + + + +

-

This repository is a work in progress

- - - Mediarepo is a tool for managing media files. It works similar to image boards (boorus) as it allows one to assign tags to media entries and -search for entries by using those tags. It is heavily inspired by [hydrus](https://github.com/hydrusnetwork/hydrus/). +search for entries by using those tags. It is inspired by [hydrus](https://github.com/hydrusnetwork/hydrus/) with the goal to provide a good looking and fast +way to organize all kinds of media. -## Usage +## Installation -1. Initialize an empty repository -``` -mediarepo --repo "where/your/repo/should/be" init -``` +In order to use mediarepo, the mediarepo daemon and UI application need to be installed. +Both can be downloaded from the [Releases](https://github.com/Trivernis/mediarepo/releases) page or the AUR. -2. Import some images +```sh +yay -S mediarepo-daemon mediarepo ``` -mediarepo --repo "path/to/your/repo" import "path/to/your/files/as/**/glob/*.png" -``` -3. Start the daemon -``` -mediarepo --repo "path/to/your/repo start -``` +When installing manually the `mediarepo-daemon` binary needs to be accessible in the `PATH` variable. + +## Usage and Further Information -4. Open the mediarepo-ui and connect to the repository +Please consult the [official website](https://mediarepo.trivernis.dev) for more information. ## License diff --git a/mediarepo-daemon/Cargo.lock b/mediarepo-daemon/Cargo.lock index 63c2385..cdedb33 100644 --- a/mediarepo-daemon/Cargo.lock +++ b/mediarepo-daemon/Cargo.lock @@ -1226,7 +1226,7 @@ dependencies = [ [[package]] name = "mediarepo-daemon" -version = "0.13.2" +version = "0.13.3" dependencies = [ "console-subscriber", "glob", diff --git a/mediarepo-daemon/Cargo.toml b/mediarepo-daemon/Cargo.toml index 208826f..81cf2ac 100644 --- a/mediarepo-daemon/Cargo.toml +++ b/mediarepo-daemon/Cargo.toml @@ -4,7 +4,7 @@ default-members = ["mediarepo-core", "mediarepo-database", "mediarepo-logic", "m [package] name = "mediarepo-daemon" -version = "0.13.2" +version = "0.13.3" edition = "2018" license = "gpl-3" repository = "https://github.com/Trivernis/mediarepo-daemon" diff --git a/mediarepo-daemon/mediarepo-logic/src/dao/tag/add.rs b/mediarepo-daemon/mediarepo-logic/src/dao/tag/add.rs index 602a7ea..e910fe5 100644 --- a/mediarepo-daemon/mediarepo-logic/src/dao/tag/add.rs +++ b/mediarepo-daemon/mediarepo-logic/src/dao/tag/add.rs @@ -132,6 +132,8 @@ fn build_tag_condition(tag: AddTagDto) -> Condition { .add(tag::Column::Name.eq(tag.name)) .add(namespace::Column::Name.eq(namespace)) } else { - Condition::all().add(tag::Column::Name.eq(tag.name)) + Condition::all() + .add(tag::Column::Name.eq(tag.name)) + .add(tag::Column::NamespaceId.is_null()) } } diff --git a/mediarepo-daemon/mediarepo-logic/src/dao/tag/all_for_cds_map.rs b/mediarepo-daemon/mediarepo-logic/src/dao/tag/all_for_cds_map.rs new file mode 100644 index 0000000..1c00084 --- /dev/null +++ b/mediarepo-daemon/mediarepo-logic/src/dao/tag/all_for_cds_map.rs @@ -0,0 +1,90 @@ +use crate::dao::tag::{map_tag_dto, TagDao}; +use crate::dto::TagDto; +use mediarepo_core::error::RepoResult; +use mediarepo_core::itertools::Itertools; +use mediarepo_database::entities::{content_descriptor, content_descriptor_tag, namespace, tag}; +use sea_orm::prelude::*; +use std::collections::HashMap; + +impl TagDao { + #[tracing::instrument(level = "debug", skip(self, cds))] + pub async fn all_for_cds_map( + &self, + cds: Vec>, + ) -> RepoResult, Vec>> { + let mut cd_tag_map = cds + .iter() + .cloned() + .map(|cd| (cd, Vec::new())) + .collect::, Vec>>(); + + let tag_cd_entries = tags_for_cds(&self.ctx.db, cds).await?; + + let tag_ids: Vec = tag_cd_entries + .iter() + .map(|(t, _)| t.tag_id) + .unique() + .collect(); + + let tags = tags_for_tag_ids(&self.ctx.db, tag_ids).await?; + + let tag_id_map = tags + .into_iter() + .map(|t| (t.id(), t)) + .collect::>(); + let existing_cds_with_tags = create_cd_tag_map(tag_cd_entries, tag_id_map); + cd_tag_map.extend(existing_cds_with_tags.into_iter()); + + Ok(cd_tag_map) + } +} + +async fn tags_for_cds( + db: &DatabaseConnection, + cds: Vec>, +) -> RepoResult< + Vec<( + content_descriptor_tag::Model, + Option, + )>, +> { + let tag_cd_entries = content_descriptor_tag::Entity::find() + .find_also_related(content_descriptor::Entity) + .filter(content_descriptor::Column::Descriptor.is_in(cds)) + .all(db) + .await?; + + Ok(tag_cd_entries) +} + +async fn tags_for_tag_ids(db: &DatabaseConnection, ids: Vec) -> RepoResult> { + let tags = tag::Entity::find() + .find_also_related(namespace::Entity) + .filter(tag::Column::Id.is_in(ids)) + .all(db) + .await? + .into_iter() + .map(map_tag_dto) + .collect(); + + Ok(tags) +} + +fn create_cd_tag_map( + tag_cd_entries: Vec<( + content_descriptor_tag::Model, + Option, + )>, + tag_id_map: HashMap, +) -> HashMap, Vec> { + let cd_tag_map = tag_cd_entries + .into_iter() + .filter_map(|(t, cd)| Some((cd?, tag_id_map.get(&t.tag_id)?.clone()))) + .sorted_by_key(|(cd, _)| cd.id) + .group_by(|(cd, _)| cd.descriptor.to_owned()) + .into_iter() + .map(|(key, group)| (key, group.map(|(_, t)| t).collect::>())) + .collect(); + + cd_tag_map +} diff --git a/mediarepo-daemon/mediarepo-logic/src/dao/tag/mod.rs b/mediarepo-daemon/mediarepo-logic/src/dao/tag/mod.rs index 0f44309..80fb2a2 100644 --- a/mediarepo-daemon/mediarepo-logic/src/dao/tag/mod.rs +++ b/mediarepo-daemon/mediarepo-logic/src/dao/tag/mod.rs @@ -5,7 +5,6 @@ use std::collections::HashMap; use std::iter::FromIterator; use mediarepo_core::error::RepoResult; -use mediarepo_core::itertools::Itertools; use mediarepo_core::utils::parse_namespace_and_tag; use mediarepo_database::entities::{content_descriptor, content_descriptor_tag, namespace, tag}; @@ -15,6 +14,7 @@ use crate::dao::{DaoContext, DaoProvider}; use crate::dto::{NamespaceDto, TagDto}; pub mod add; +pub mod all_for_cds_map; pub mod by_name; pub mod mappings; @@ -81,51 +81,6 @@ impl TagDao { Ok(tags) } - #[tracing::instrument(level = "debug", skip(self, cds))] - pub async fn all_for_cds_map( - &self, - cds: Vec>, - ) -> RepoResult, Vec>> { - let tag_cd_entries: Vec<( - content_descriptor_tag::Model, - Option, - )> = content_descriptor_tag::Entity::find() - .find_also_related(content_descriptor::Entity) - .filter(content_descriptor::Column::Descriptor.is_in(cds)) - .all(&self.ctx.db) - .await?; - - let tag_ids: Vec = tag_cd_entries - .iter() - .map(|(t, _)| t.tag_id) - .unique() - .collect(); - - let tags: Vec = tag::Entity::find() - .find_also_related(namespace::Entity) - .filter(tag::Column::Id.is_in(tag_ids)) - .all(&self.ctx.db) - .await? - .into_iter() - .map(map_tag_dto) - .collect(); - - let tag_id_map = tags - .into_iter() - .map(|t| (t.id(), t)) - .collect::>(); - let cd_tag_map = tag_cd_entries - .into_iter() - .filter_map(|(t, cd)| Some((cd?, tag_id_map.get(&t.tag_id)?.clone()))) - .sorted_by_key(|(cd, _)| cd.id) - .group_by(|(cd, _)| cd.descriptor.to_owned()) - .into_iter() - .map(|(key, group)| (key, group.map(|(_, t)| t).collect::>())) - .collect(); - - Ok(cd_tag_map) - } - #[tracing::instrument(level = "debug", skip(self))] pub async fn tags_for_cd(&self, cd_id: i64) -> RepoResult> { let tags = tag::Entity::find() diff --git a/mediarepo-ui/package.json b/mediarepo-ui/package.json index b2ec35b..1a0c882 100644 --- a/mediarepo-ui/package.json +++ b/mediarepo-ui/package.json @@ -1,6 +1,6 @@ { "name": "mediarepo-ui", - "version": "0.13.2", + "version": "0.13.3", "scripts": { "ng": "ng", "start": "ng serve", @@ -59,4 +59,4 @@ "karma-jasmine-html-reporter": "~1.7.0", "typescript": "~4.5.4" } -} +} \ No newline at end of file diff --git a/mediarepo-ui/src-tauri/Cargo.lock b/mediarepo-ui/src-tauri/Cargo.lock index 52488e0..9b93484 100644 --- a/mediarepo-ui/src-tauri/Cargo.lock +++ b/mediarepo-ui/src-tauri/Cargo.lock @@ -40,7 +40,7 @@ checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0" [[package]] name = "app" -version = "0.13.2" +version = "0.13.3" dependencies = [ "mediarepo-api", "serde", diff --git a/mediarepo-ui/src-tauri/Cargo.toml b/mediarepo-ui/src-tauri/Cargo.toml index afc9bec..28ad054 100644 --- a/mediarepo-ui/src-tauri/Cargo.toml +++ b/mediarepo-ui/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "app" -version = "0.13.2" +version = "0.13.3" description = "The UI for the mediarepo media management tool" authors = ["you"] license = "" diff --git a/mediarepo-ui/src-tauri/tauri.conf.json b/mediarepo-ui/src-tauri/tauri.conf.json index 668c202..58f9621 100644 --- a/mediarepo-ui/src-tauri/tauri.conf.json +++ b/mediarepo-ui/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "package": { "productName": "mediarepo-ui", - "version": "0.13.2" + "version": "0.13.3" }, "build": { "distDir": "../dist/mediarepo-ui", @@ -73,4 +73,4 @@ "csp": "default-src blob: data: filesystem: ws: wss: http: https: tauri: 'unsafe-eval' 'unsafe-inline' 'self' img-src: 'self' once: thumb: content:" } } -} +} \ No newline at end of file