mirror of
				https://github.com/TeamPiped/Piped.git
				synced 2024-08-14 23:57:27 +00:00 
			
		
		
		
	Add a channel page and fix some things.
This commit is contained in:
		
							parent
							
								
									14a1d96c65
								
							
						
					
					
						commit
						98640e6d92
					
				
					 9 changed files with 145 additions and 59 deletions
				
			
		
							
								
								
									
										12
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							| 
						 | 
					@ -7842,11 +7842,6 @@
 | 
				
			||||||
        "minimist": "^1.2.5"
 | 
					        "minimist": "^1.2.5"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "moment": {
 | 
					 | 
				
			||||||
      "version": "2.29.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "move-concurrently": {
 | 
					    "move-concurrently": {
 | 
				
			||||||
      "version": "1.0.1",
 | 
					      "version": "1.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz",
 | 
					      "resolved": "https://registry.npm.taobao.org/move-concurrently/download/move-concurrently-1.0.1.tgz",
 | 
				
			||||||
| 
						 | 
					@ -11495,13 +11490,6 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/videojs-hotkeys/-/videojs-hotkeys-0.2.27.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/videojs-hotkeys/-/videojs-hotkeys-0.2.27.tgz",
 | 
				
			||||||
      "integrity": "sha512-pwtm1QocRmzJy1PWQsmFVHyeldYHHpLdeATK3FsFHVMmNpz6CROkAn8TFy2UILr8Ghgq134K8jEKNue8HWpudQ=="
 | 
					      "integrity": "sha512-pwtm1QocRmzJy1PWQsmFVHyeldYHHpLdeATK3FsFHVMmNpz6CROkAn8TFy2UILr8Ghgq134K8jEKNue8HWpudQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "videojs-ttml": {
 | 
					 | 
				
			||||||
      "version": "git+https://github.com/StuffNoOneCaresAbout/videojs-ttml.git#6927bafe47752cc3d92f06f18379b6134d182941",
 | 
					 | 
				
			||||||
      "from": "git+https://github.com/StuffNoOneCaresAbout/videojs-ttml.git",
 | 
					 | 
				
			||||||
      "requires": {
 | 
					 | 
				
			||||||
        "moment": "^2.17.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "videojs-vtt.js": {
 | 
					    "videojs-vtt.js": {
 | 
				
			||||||
      "version": "0.15.2",
 | 
					      "version": "0.15.2",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.2.tgz",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,6 @@
 | 
				
			||||||
        "video.js": "^7.10.2",
 | 
					        "video.js": "^7.10.2",
 | 
				
			||||||
        "videojs-contrib-quality-levels": "^2.0.9",
 | 
					        "videojs-contrib-quality-levels": "^2.0.9",
 | 
				
			||||||
        "videojs-hotkeys": "^0.2.27",
 | 
					        "videojs-hotkeys": "^0.2.27",
 | 
				
			||||||
        "videojs-ttml": "git+https://github.com/StuffNoOneCaresAbout/videojs-ttml.git",
 | 
					 | 
				
			||||||
        "vue": "^3.0.0",
 | 
					        "vue": "^3.0.0",
 | 
				
			||||||
        "vue-router": "^4.0.0-rc.2"
 | 
					        "vue-router": "^4.0.0-rc.2"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								src/App.vue
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								src/App.vue
									
										
									
									
									
								
							| 
						 | 
					@ -15,7 +15,7 @@
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
</nav>
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="uk-container uk-light" style="background:#0b0e0f">
 | 
					<div class="uk-container uk-container-expand uk-light" style="background:#0b0e0f">
 | 
				
			||||||
    <router-view />
 | 
					    <router-view />
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
| 
						 | 
					@ -34,4 +34,29 @@ export default {
 | 
				
			||||||
#app {
 | 
					#app {
 | 
				
			||||||
    background: #0b0e0f;
 | 
					    background: #0b0e0f;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar {
 | 
				
			||||||
 | 
					    background-color: #15191a;
 | 
				
			||||||
 | 
					    color: #c5bcae;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-thumb {
 | 
				
			||||||
 | 
					    background-color: #4b4f52;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-thumb:hover {
 | 
				
			||||||
 | 
					    background-color: #5b6469;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-thumb:active {
 | 
				
			||||||
 | 
					    background-color: #485053;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-corner {
 | 
				
			||||||
 | 
					    background-color: #0b0e0f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* {
 | 
				
			||||||
 | 
					    scrollbar-color: #15191a #444a4e;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,3 @@
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
    BASE_URL: '',
 | 
					    BASE_URL: 'https://pipedapi.kavin.rocks',
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										62
									
								
								src/components/Channel.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/components/Channel.vue
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,62 @@
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					<div v-if="channel">
 | 
				
			||||||
 | 
					    <h1 class="uk-text-center"><img v-bind:src="channel.avatarUrl">{{ channel.name }}</h1>
 | 
				
			||||||
 | 
					    <img v-bind:src="channel.bannerUrl" style="width: 100%">
 | 
				
			||||||
 | 
					    <p v-html="this.channel.description.replaceAll('\n', '<br>')"></p>
 | 
				
			||||||
 | 
					    <div class="" style="width: 100%" uk-grid="parallax: 0">
 | 
				
			||||||
 | 
					        <div style="width: 260px" v-bind:key="item.url" v-for="item in this.channel.relatedStreams">
 | 
				
			||||||
 | 
					            <router-link class="uk-link-muted" v-bind:to="item.url || '/'">
 | 
				
			||||||
 | 
					                <img style="width: 100%" v-bind:src="item.thumbnail">
 | 
				
			||||||
 | 
					                <p>{{ item.title }}</p>
 | 
				
			||||||
 | 
					            </router-link>
 | 
				
			||||||
 | 
					            {{ timeFormat(item.duration) }}
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					import Constants from "@/Constants.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    data() {
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            channel: null,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    mounted() {
 | 
				
			||||||
 | 
					        this.getChannelData()
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    methods: {
 | 
				
			||||||
 | 
					        async fetchChannel() {
 | 
				
			||||||
 | 
					            return await (
 | 
				
			||||||
 | 
					                await fetch(Constants.BASE_URL + "/channels/" + this.$route.params.channelId)
 | 
				
			||||||
 | 
					            ).json();
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        async getChannelData() {
 | 
				
			||||||
 | 
					            this.fetchChannel().then(data => this.channel = data)
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        timeFormat(duration) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var pad = function (num, size) {
 | 
				
			||||||
 | 
					                return ('000' + num).slice(size * -1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var time = parseFloat(duration).toFixed(3),
 | 
				
			||||||
 | 
					                hours = Math.floor(time / 60 / 60),
 | 
				
			||||||
 | 
					                minutes = Math.floor(time / 60) % 60,
 | 
				
			||||||
 | 
					                seconds = Math.floor(time - minutes * 60);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var str = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (hours > 0)
 | 
				
			||||||
 | 
					                str += pad(hours, 2) + ":"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            str += pad(minutes, 2) + ':' + pad(seconds, 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
<h1 class="uk-text-bold uk-text-center">Trending</h1>
 | 
					<h1 class="uk-text-bold uk-text-center">Trending</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div class="" style="width: 100%" uk-grid="parallax: 0">
 | 
					<div class="" style="width: 100%" uk-grid="parallax: 0">
 | 
				
			||||||
    <div class="uk-tile-default" style="width: 350px; background: #0b0e0f" v-bind:key="video.url" v-for="video in videos">
 | 
					    <div class="uk-tile-default" style="width: 300px; background: #0b0e0f" v-bind:key="video.url" v-for="video in videos">
 | 
				
			||||||
        <div class="uk-card uk-card-default uk-card-body uk-grid-match uk-text-secondary" style="background: #0b0e0f">
 | 
					        <div class="uk-card uk-card-default uk-card-body uk-grid-match uk-text-secondary" style="background: #0b0e0f">
 | 
				
			||||||
            <router-link class="uk-text-emphasis" v-bind:to="video.url || '/'">
 | 
					            <router-link class="uk-text-emphasis" v-bind:to="video.url || '/'">
 | 
				
			||||||
                <p>{{ video.title }}</p>
 | 
					                <p>{{ video.title }}</p>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +1,12 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
 | 
					<div class="uk-container uk-container-xlarge">
 | 
				
			||||||
    <h1 class="uk-text-bold">{{ video.title }}</h1>
 | 
					    <h1 class="uk-text-bold">{{ video.title }}</h1>
 | 
				
			||||||
<video controls ref="player" class="video-js vjs-16-9"></video>
 | 
					    <video controls ref="player" class="video-js preview-player-dimensions "></video>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<div>
 | 
					 | 
				
			||||||
    <img :src="video.uploaderAvatar" />
 | 
					    <img :src="video.uploaderAvatar" />
 | 
				
			||||||
    <router-link class="uk-text-bold" v-bind:to="video.uploaderUrl || '/'">
 | 
					    <router-link class="uk-text-bold" v-bind:to="video.uploaderUrl || '/'">
 | 
				
			||||||
        <p>{{ video.uploader }}</p>
 | 
					        <a>{{ video.uploader }}</a>
 | 
				
			||||||
    </router-link>
 | 
					    </router-link>
 | 
				
			||||||
</div>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<p v-if="sponsors && sponsors.segments">Sponsors found in Video: {{ sponsors.segments.length }}</p>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <p class="uk-dark">
 | 
					    <p class="uk-dark">
 | 
				
			||||||
        <font-awesome-icon icon="thumbs-down"></font-awesome-icon>
 | 
					        <font-awesome-icon icon="thumbs-down"></font-awesome-icon>
 | 
				
			||||||
| 
						 | 
					@ -21,6 +18,9 @@
 | 
				
			||||||
        <font-awesome-icon icon="eye"></font-awesome-icon> {{ video.views }} views
 | 
					        <font-awesome-icon icon="eye"></font-awesome-icon> {{ video.views }} views
 | 
				
			||||||
    </p>
 | 
					    </p>
 | 
				
			||||||
    <p class="uk-light" v-html="video.description"></p>
 | 
					    <p class="uk-light" v-html="video.description"></p>
 | 
				
			||||||
 | 
					    <a v-if="sponsors && sponsors.segments">Sponsors Segments: {{ sponsors.segments.length }}</a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <hr>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="uk-tile-default uk-text-secondary" style="background: #0b0e0f; width: 300px" v-bind:key="related.url" v-for="related in video.relatedStreams">
 | 
					    <div class="uk-tile-default uk-text-secondary" style="background: #0b0e0f; width: 300px" v-bind:key="related.url" v-for="related in video.relatedStreams">
 | 
				
			||||||
        <router-link class="uk-link-muted" v-bind:to="related.url">
 | 
					        <router-link class="uk-link-muted" v-bind:to="related.url">
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,8 @@
 | 
				
			||||||
            {{ related.views }} views
 | 
					            {{ related.views }} views
 | 
				
			||||||
        </p>
 | 
					        </p>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script>
 | 
				
			||||||
| 
						 | 
					@ -44,7 +46,6 @@ import videojs from "video.js";
 | 
				
			||||||
import "videojs-hotkeys";
 | 
					import "videojs-hotkeys";
 | 
				
			||||||
import Constants from "@/Constants.js";
 | 
					import Constants from "@/Constants.js";
 | 
				
			||||||
require("@silvermine/videojs-quality-selector")(videojs);
 | 
					require("@silvermine/videojs-quality-selector")(videojs);
 | 
				
			||||||
//import "videojs-ttml/dist/videojs-ttml.min.js";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
    name: "App",
 | 
					    name: "App",
 | 
				
			||||||
| 
						 | 
					@ -102,14 +103,12 @@ export default {
 | 
				
			||||||
                                "progressControl",
 | 
					                                "progressControl",
 | 
				
			||||||
                                "volumePanel",
 | 
					                                "volumePanel",
 | 
				
			||||||
                                "qualitySelector",
 | 
					                                "qualitySelector",
 | 
				
			||||||
                                "subtitlesButton",
 | 
					                                "captionsButton",
 | 
				
			||||||
                                "fullscreenToggle",
 | 
					                                "fullscreenToggle",
 | 
				
			||||||
                            ],
 | 
					                            ],
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
                        plugins: {
 | 
					                        responsive: false,
 | 
				
			||||||
                            ttml: {}
 | 
					                        aspectRatio: '16:9'
 | 
				
			||||||
                        },
 | 
					 | 
				
			||||||
                        nativeTextTracks: false,
 | 
					 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    const noPrevPlayer = !this.player
 | 
					                    const noPrevPlayer = !this.player
 | 
				
			||||||
| 
						 | 
					@ -135,6 +134,14 @@ export default {
 | 
				
			||||||
                        })
 | 
					                        })
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    this.video.audioStreams.map((stream) =>
 | 
				
			||||||
 | 
					                        src.push({
 | 
				
			||||||
 | 
					                            src: stream.url,
 | 
				
			||||||
 | 
					                            type: stream.mimeType,
 | 
				
			||||||
 | 
					                            label: stream.quality,
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    this.player.src(src);
 | 
					                    this.player.src(src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (noPrevPlayer)
 | 
					                    if (noPrevPlayer)
 | 
				
			||||||
| 
						 | 
					@ -153,16 +160,16 @@ export default {
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        });
 | 
					                        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // if (!noPrevPlayer)
 | 
					                    if (!noPrevPlayer)
 | 
				
			||||||
                    //     this.player.remoteTextTracks().map(track => this.player.removeRemoteTextTrack(track));
 | 
					                        this.player.remoteTextTracks().map(track => this.player.removeRemoteTextTrack(track));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    this.video.subtitles.map(subtitle => {
 | 
					                    this.video.subtitles.map(subtitle => {
 | 
				
			||||||
                        this.player.addRemoteTextTrack({
 | 
					                        this.player.addRemoteTextTrack({
 | 
				
			||||||
                            kind: "captions",
 | 
					                            kind: "captions",
 | 
				
			||||||
                            src: subtitle.url,
 | 
					                            src: subtitle.url.replace("fmt=ttml", "fmt=vtt"),
 | 
				
			||||||
                            label: "Track",
 | 
					                            label: "Track",
 | 
				
			||||||
                            type: subtitle.mimeType
 | 
					                            type: "captions/captions.vtt"
 | 
				
			||||||
                        }, false);
 | 
					                        }, false).mode = "showing"
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    //TODO: Add sponsors on seekbar: https://github.com/ajayyy/SponsorBlock/blob/e39de9fd852adb9196e0358ed827ad38d9933e29/src/js-components/previewBar.ts#L12
 | 
					                    //TODO: Add sponsors on seekbar: https://github.com/ajayyy/SponsorBlock/blob/e39de9fd852adb9196e0358ed827ad38d9933e29/src/js-components/previewBar.ts#L12
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,8 +4,8 @@ import { faThumbsUp, faThumbsDown, faEye } from '@fortawesome/free-solid-svg-ico
 | 
				
			||||||
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
 | 
					import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
 | 
				
			||||||
library.add(faThumbsUp, faThumbsDown, faEye)
 | 
					library.add(faThumbsUp, faThumbsDown, faEye)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "uikit/src/less/uikit.less";
 | 
					require("uikit/src/less/uikit.less")
 | 
				
			||||||
import "uikit/dist/js/uikit.min.js";
 | 
					require("uikit/dist/js/uikit.min.js")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import router from '@/router/router'
 | 
					import router from '@/router/router'
 | 
				
			||||||
import App from './App.vue'
 | 
					import App from './App.vue'
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
import { createRouter, createWebHistory } from 'vue-router'
 | 
					import { createRouter, createWebHistory } from 'vue-router'
 | 
				
			||||||
import Watch from '../components/WatchVideo.vue'
 | 
					import Watch from '../components/WatchVideo.vue'
 | 
				
			||||||
import Trending from '../components/TrendingPage.vue'
 | 
					import Trending from '../components/TrendingPage.vue'
 | 
				
			||||||
 | 
					import Channel from '../components/Channel.vue'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const routes = [{
 | 
					const routes = [{
 | 
				
			||||||
    path: '/watch',
 | 
					    path: '/watch',
 | 
				
			||||||
| 
						 | 
					@ -10,6 +11,10 @@ const routes = [{
 | 
				
			||||||
    path: '/',
 | 
					    path: '/',
 | 
				
			||||||
    name: 'Trending',
 | 
					    name: 'Trending',
 | 
				
			||||||
    component: Trending
 | 
					    component: Trending
 | 
				
			||||||
 | 
					}, {
 | 
				
			||||||
 | 
					    path: '/channel/:channelId',
 | 
				
			||||||
 | 
					    name: 'Channel',
 | 
				
			||||||
 | 
					    component: Channel
 | 
				
			||||||
}]
 | 
					}]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const router = createRouter({
 | 
					const router = createRouter({
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue