]> git.localhorst.tv Git - alttp.git/commitdiff
tech relations
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 5 Jan 2023 19:41:27 +0000 (20:41 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 5 Jan 2023 19:41:27 +0000 (20:41 +0100)
app/Http/Controllers/TechniqueController.php
app/Models/Technique.php
app/Models/TechniqueRelation.php [new file with mode: 0644]
database/migrations/2023_01_05_190010_create_technique_relations_table.php [new file with mode: 0644]
resources/js/components/techniques/Detail.js
resources/js/helpers/Technique.js
resources/js/i18n/de.js
resources/js/i18n/en.js

index 268c3f6abeff765568efd68209edc79942363c81..98623259f494f701e78a8fa3dedcd21da7350ccf 100644 (file)
@@ -34,7 +34,7 @@ class TechniqueController extends Controller
 
        public function single(Request $request, Technique $tech) {
                $this->authorize('view', $tech);
-               $tech->load('chapters');
+               $tech->load(['chapters', 'relations']);
                return $tech->toJson();
        }
 
index 256afc06ea6abe051e47fa08ae39b421e43950f9..f0a29d39ec3e975bf4ff973220ab83e50da25555 100644 (file)
@@ -17,6 +17,13 @@ class Technique extends Model
                        ->using(TechniqueChapter::class);
        }
 
+       public function relations() {
+               return $this
+                       ->belongsToMany(Technique::class, 'technique_relations', 'from_id', 'to_id')
+                       ->withPivot('type')
+                       ->using(TechniqueRelation::class);
+       }
+
        public function translations() {
                return $this->hasMany(TechniqueTranslation::class);
        }
diff --git a/app/Models/TechniqueRelation.php b/app/Models/TechniqueRelation.php
new file mode 100644 (file)
index 0000000..96c73c3
--- /dev/null
@@ -0,0 +1,10 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Relations\Pivot;
+
+class TechniqueRelation extends Pivot
+{
+       //
+}
diff --git a/database/migrations/2023_01_05_190010_create_technique_relations_table.php b/database/migrations/2023_01_05_190010_create_technique_relations_table.php
new file mode 100644 (file)
index 0000000..8efdeff
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+       /**
+        * Run the migrations.
+        *
+        * @return void
+        */
+       public function up()
+       {
+               Schema::create('technique_relations', function (Blueprint $table) {
+                       $table->id();
+                       $table->foreignId('from_id')->references('id')->on('techniques')->constrained();
+                       $table->foreignId('to_id')->references('id')->on('techniques')->constrained();
+                       $table->string('type')->default('related');
+                       $table->timestamps();
+               });
+       }
+
+       /**
+        * Reverse the migrations.
+        *
+        * @return void
+        */
+       public function down()
+       {
+               Schema::dropIfExists('technique_relations');
+       }
+};
index 303921c4c919245ed5c66da8e1a7f4357d976705..488205b2e6d68ffdd374ae93d78a5b0cfe704b6b 100644 (file)
@@ -3,9 +3,15 @@ import React from 'react';
 import { Container } from 'react-bootstrap';
 import { withTranslation } from 'react-i18next';
 
+import List from './List';
 import Outline from './Outline';
 import RawHTML from '../common/RawHTML';
-import { getTranslation } from '../../helpers/Technique';
+import {
+       getRelations,
+       getTranslation,
+       hasRelations,
+       sorted,
+} from '../../helpers/Technique';
 import i18n from '../../i18n';
 
 const Detail = ({ technique }) => <Container as="article">
@@ -24,6 +30,10 @@ const Detail = ({ technique }) => <Container as="article">
                        <RawHTML html={getTranslation(chapter, 'description', i18n.language)} />
                </section>
        ) : null}
+       {hasRelations(technique, 'related') ? <>
+               <h2 className="mt-5">{i18n.t('techniques.seeAlso')}</h2>
+               <List techniques={sorted(getRelations(technique, 'related'))} />
+       </> : null}
 </Container>;
 
 Detail.propTypes = {
index 7ec22d3b90e01df1aa9b3918643d37f9200829ff..410f01595657de34f339d8c0f88b529bbdab316c 100644 (file)
@@ -1,3 +1,12 @@
+import i18n from '../i18n';
+
+export const getRelations = (tech, type) => {
+       const rs = (tech && tech.relations) || [];
+       return type ? rs.filter(r => r && r.pivot && r.pivot.type === type) : rs;
+};
+
+export const hasRelations = (tech, type) => getRelations(tech, type).length > 0;
+
 export const getTranslation = (tech, prop, lang) => {
        const direct = tech.translations.find(t => t.locale === lang);
        if (direct) {
@@ -13,6 +22,12 @@ export const getTranslation = (tech, prop, lang) => {
 export const compareTranslation = (prop, lang) => (a, b) =>
        getTranslation(a, prop, lang).localeCompare(getTranslation(b, prop, lang));
 
+export const sorted = (techs) => [...techs].sort(compareTranslation('title', i18n.language));
+
 export default {
+       compareTranslation,
+       getRelations,
        getTranslation,
+       hasRelations,
+       sorted,
 };
index c28c1b29a8a112f9b53a2132d0551481c0c5a9d2..f3fbe96d5eeaa6e0133057254ef9d856bf60d546 100644 (file)
@@ -480,6 +480,7 @@ export default {
                },
                techniques: {
                        heading: 'Techniken',
+                       seeAlso: 'Siehe auch',
                },
                tournaments: {
                        admins: 'Organisation',
index dfff38bcde155456ef09aae498364d1e43b10dbc..7088dd4b103dc413f146d2b1ccdfbef84c8efc7e 100644 (file)
@@ -480,6 +480,7 @@ export default {
                },
                techniques: {
                        heading: 'Techniques',
+                       seeAlso: 'See also',
                },
                tournaments: {
                        admins: 'Admins',