diff options
author | Chocobozzz <me@florianbigard.com> | 2021-12-10 15:01:12 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2021-12-10 15:01:12 +0100 |
commit | d63e6d4604dfbe4938c7d66832c9202364c5bb64 (patch) | |
tree | 6bd444be722276ff214d911284a400e374bdddc8 /client/src/app | |
parent | 03a65456f44a6152bb68975e29e076c8c5754cd6 (diff) | |
download | PeerTube-d63e6d4604dfbe4938c7d66832c9202364c5bb64.tar.gz PeerTube-d63e6d4604dfbe4938c7d66832c9202364c5bb64.tar.zst PeerTube-d63e6d4604dfbe4938c7d66832c9202364c5bb64.zip |
Add ability for plugins to register client routes
Diffstat (limited to 'client/src/app')
-rw-r--r-- | client/src/app/+plugin-pages/index.ts | 3 | ||||
-rw-r--r-- | client/src/app/+plugin-pages/plugin-pages-routing.module.ts | 19 | ||||
-rw-r--r-- | client/src/app/+plugin-pages/plugin-pages.component.html | 1 | ||||
-rw-r--r-- | client/src/app/+plugin-pages/plugin-pages.component.ts | 31 | ||||
-rw-r--r-- | client/src/app/+plugin-pages/plugin-pages.module.ts | 21 | ||||
-rw-r--r-- | client/src/app/app-routing.module.ts | 6 | ||||
-rw-r--r-- | client/src/app/core/plugins/plugin.service.ts | 31 | ||||
-rw-r--r-- | client/src/app/core/routing/custom-reuse-strategy.ts | 2 |
8 files changed, 109 insertions, 5 deletions
diff --git a/client/src/app/+plugin-pages/index.ts b/client/src/app/+plugin-pages/index.ts new file mode 100644 index 000000000..b988f13f6 --- /dev/null +++ b/client/src/app/+plugin-pages/index.ts | |||
@@ -0,0 +1,3 @@ | |||
1 | export * from './plugin-pages-routing.module' | ||
2 | export * from './plugin-pages.component' | ||
3 | export * from './plugin-pages.module' | ||
diff --git a/client/src/app/+plugin-pages/plugin-pages-routing.module.ts b/client/src/app/+plugin-pages/plugin-pages-routing.module.ts new file mode 100644 index 000000000..b47a787e0 --- /dev/null +++ b/client/src/app/+plugin-pages/plugin-pages-routing.module.ts | |||
@@ -0,0 +1,19 @@ | |||
1 | import { NgModule } from '@angular/core' | ||
2 | import { RouterModule, Routes } from '@angular/router' | ||
3 | import { PluginPagesComponent } from './plugin-pages.component' | ||
4 | |||
5 | const pluginPagesRoutes: Routes = [ | ||
6 | { | ||
7 | path: '**', | ||
8 | component: PluginPagesComponent, | ||
9 | data: { | ||
10 | reloadOnSameNavigation: true | ||
11 | } | ||
12 | } | ||
13 | ] | ||
14 | |||
15 | @NgModule({ | ||
16 | imports: [ RouterModule.forChild(pluginPagesRoutes) ], | ||
17 | exports: [ RouterModule ] | ||
18 | }) | ||
19 | export class PluginPagesRoutingModule {} | ||
diff --git a/client/src/app/+plugin-pages/plugin-pages.component.html b/client/src/app/+plugin-pages/plugin-pages.component.html new file mode 100644 index 000000000..cf62d1bd7 --- /dev/null +++ b/client/src/app/+plugin-pages/plugin-pages.component.html | |||
@@ -0,0 +1 @@ | |||
<div #root></div> | |||
diff --git a/client/src/app/+plugin-pages/plugin-pages.component.ts b/client/src/app/+plugin-pages/plugin-pages.component.ts new file mode 100644 index 000000000..5f294ee13 --- /dev/null +++ b/client/src/app/+plugin-pages/plugin-pages.component.ts | |||
@@ -0,0 +1,31 @@ | |||
1 | import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core' | ||
2 | import { ActivatedRoute, Router } from '@angular/router' | ||
3 | import { PluginService } from '@app/core' | ||
4 | |||
5 | @Component({ | ||
6 | templateUrl: './plugin-pages.component.html' | ||
7 | }) | ||
8 | export class PluginPagesComponent implements AfterViewInit { | ||
9 | @ViewChild('root') root: ElementRef | ||
10 | |||
11 | constructor ( | ||
12 | private route: ActivatedRoute, | ||
13 | private router: Router, | ||
14 | private pluginService: PluginService | ||
15 | ) { | ||
16 | |||
17 | } | ||
18 | |||
19 | ngAfterViewInit () { | ||
20 | const path = '/' + this.route.snapshot.url.map(u => u.path).join('/') | ||
21 | |||
22 | const registered = this.pluginService.getRegisteredClientRoute(path) | ||
23 | if (!registered) { | ||
24 | console.log('Could not find registered route %s.', path, this.pluginService.getAllRegisteredClientRoutes()) | ||
25 | |||
26 | return this.router.navigate([ '/404' ], { skipLocationChange: true }) | ||
27 | } | ||
28 | |||
29 | registered.onMount({ rootEl: this.root.nativeElement }) | ||
30 | } | ||
31 | } | ||
diff --git a/client/src/app/+plugin-pages/plugin-pages.module.ts b/client/src/app/+plugin-pages/plugin-pages.module.ts new file mode 100644 index 000000000..86f86c752 --- /dev/null +++ b/client/src/app/+plugin-pages/plugin-pages.module.ts | |||
@@ -0,0 +1,21 @@ | |||
1 | import { NgModule } from '@angular/core' | ||
2 | import { PluginPagesRoutingModule } from './plugin-pages-routing.module' | ||
3 | import { PluginPagesComponent } from './plugin-pages.component' | ||
4 | |||
5 | @NgModule({ | ||
6 | imports: [ | ||
7 | PluginPagesRoutingModule | ||
8 | ], | ||
9 | |||
10 | declarations: [ | ||
11 | PluginPagesComponent | ||
12 | ], | ||
13 | |||
14 | exports: [ | ||
15 | PluginPagesComponent | ||
16 | ], | ||
17 | |||
18 | providers: [ | ||
19 | ] | ||
20 | }) | ||
21 | export class PluginPagesModule { } | ||
diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts index 438cb6512..42328d83d 100644 --- a/client/src/app/app-routing.module.ts +++ b/client/src/app/app-routing.module.ts | |||
@@ -58,6 +58,12 @@ const routes: Routes = [ | |||
58 | }, | 58 | }, |
59 | 59 | ||
60 | { | 60 | { |
61 | path: 'p', | ||
62 | loadChildren: () => import('./+plugin-pages/plugin-pages.module').then(m => m.PluginPagesModule), | ||
63 | canActivateChild: [ MetaGuard ] | ||
64 | }, | ||
65 | |||
66 | { | ||
61 | path: 'about', | 67 | path: 'about', |
62 | loadChildren: () => import('./+about/about.module').then(m => m.AboutModule), | 68 | loadChildren: () => import('./+about/about.module').then(m => m.AboutModule), |
63 | canActivateChild: [ MetaGuard ] | 69 | canActivateChild: [ MetaGuard ] |
diff --git a/client/src/app/core/plugins/plugin.service.ts b/client/src/app/core/plugins/plugin.service.ts index 89391c2c5..fdbbd2d56 100644 --- a/client/src/app/core/plugins/plugin.service.ts +++ b/client/src/app/core/plugins/plugin.service.ts | |||
@@ -20,7 +20,8 @@ import { | |||
20 | PluginType, | 20 | PluginType, |
21 | PublicServerSetting, | 21 | PublicServerSetting, |
22 | RegisterClientFormFieldOptions, | 22 | RegisterClientFormFieldOptions, |
23 | RegisterClientSettingsScript, | 23 | RegisterClientSettingsScriptOptions, |
24 | RegisterClientRouteOptions, | ||
24 | RegisterClientVideoFieldOptions, | 25 | RegisterClientVideoFieldOptions, |
25 | ServerConfigPlugin | 26 | ServerConfigPlugin |
26 | } from '@shared/models' | 27 | } from '@shared/models' |
@@ -48,7 +49,8 @@ export class PluginService implements ClientHook { | |||
48 | private formFields: FormFields = { | 49 | private formFields: FormFields = { |
49 | video: [] | 50 | video: [] |
50 | } | 51 | } |
51 | private settingsScripts: { [ npmName: string ]: RegisterClientSettingsScript } = {} | 52 | private settingsScripts: { [ npmName: string ]: RegisterClientSettingsScriptOptions } = {} |
53 | private clientRoutes: { [ route: string ]: RegisterClientRouteOptions } = {} | ||
52 | 54 | ||
53 | private pluginsManager: PluginsManager | 55 | private pluginsManager: PluginsManager |
54 | 56 | ||
@@ -67,7 +69,8 @@ export class PluginService implements ClientHook { | |||
67 | this.pluginsManager = new PluginsManager({ | 69 | this.pluginsManager = new PluginsManager({ |
68 | peertubeHelpersFactory: this.buildPeerTubeHelpers.bind(this), | 70 | peertubeHelpersFactory: this.buildPeerTubeHelpers.bind(this), |
69 | onFormFields: this.onFormFields.bind(this), | 71 | onFormFields: this.onFormFields.bind(this), |
70 | onSettingsScripts: this.onSettingsScripts.bind(this) | 72 | onSettingsScripts: this.onSettingsScripts.bind(this), |
73 | onClientRoute: this.onClientRoute.bind(this) | ||
71 | }) | 74 | }) |
72 | } | 75 | } |
73 | 76 | ||
@@ -123,6 +126,14 @@ export class PluginService implements ClientHook { | |||
123 | return this.settingsScripts[npmName] | 126 | return this.settingsScripts[npmName] |
124 | } | 127 | } |
125 | 128 | ||
129 | getRegisteredClientRoute (route: string) { | ||
130 | return this.clientRoutes[route] | ||
131 | } | ||
132 | |||
133 | getAllRegisteredClientRoutes () { | ||
134 | return Object.keys(this.clientRoutes) | ||
135 | } | ||
136 | |||
126 | translateBy (npmName: string, toTranslate: string) { | 137 | translateBy (npmName: string, toTranslate: string) { |
127 | const helpers = this.helpers[npmName] | 138 | const helpers = this.helpers[npmName] |
128 | if (!helpers) { | 139 | if (!helpers) { |
@@ -140,12 +151,20 @@ export class PluginService implements ClientHook { | |||
140 | }) | 151 | }) |
141 | } | 152 | } |
142 | 153 | ||
143 | private onSettingsScripts (pluginInfo: PluginInfo, options: RegisterClientSettingsScript) { | 154 | private onSettingsScripts (pluginInfo: PluginInfo, options: RegisterClientSettingsScriptOptions) { |
144 | const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType) | 155 | const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType) |
145 | 156 | ||
146 | this.settingsScripts[npmName] = options | 157 | this.settingsScripts[npmName] = options |
147 | } | 158 | } |
148 | 159 | ||
160 | private onClientRoute (options: RegisterClientRouteOptions) { | ||
161 | const route = options.route.startsWith('/') | ||
162 | ? options.route | ||
163 | : `/${options.route}` | ||
164 | |||
165 | this.clientRoutes[route] = options | ||
166 | } | ||
167 | |||
149 | private buildPeerTubeHelpers (pluginInfo: PluginInfo): RegisterClientHelpers { | 168 | private buildPeerTubeHelpers (pluginInfo: PluginInfo): RegisterClientHelpers { |
150 | const { plugin } = pluginInfo | 169 | const { plugin } = pluginInfo |
151 | const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType) | 170 | const npmName = this.nameToNpmName(pluginInfo.plugin.name, pluginInfo.pluginType) |
@@ -161,6 +180,10 @@ export class PluginService implements ClientHook { | |||
161 | return environment.apiUrl + `${pathPrefix}/${plugin.name}/${plugin.version}/router` | 180 | return environment.apiUrl + `${pathPrefix}/${plugin.name}/${plugin.version}/router` |
162 | }, | 181 | }, |
163 | 182 | ||
183 | getBasePluginClientPath: () => { | ||
184 | return '/p' | ||
185 | }, | ||
186 | |||
164 | getSettings: () => { | 187 | getSettings: () => { |
165 | const path = PluginService.BASE_PLUGIN_API_URL + '/' + npmName + '/public-settings' | 188 | const path = PluginService.BASE_PLUGIN_API_URL + '/' + npmName + '/public-settings' |
166 | 189 | ||
diff --git a/client/src/app/core/routing/custom-reuse-strategy.ts b/client/src/app/core/routing/custom-reuse-strategy.ts index 1498e221f..5d3ad2e67 100644 --- a/client/src/app/core/routing/custom-reuse-strategy.ts +++ b/client/src/app/core/routing/custom-reuse-strategy.ts | |||
@@ -58,7 +58,7 @@ export class CustomReuseStrategy implements RouteReuseStrategy { | |||
58 | 58 | ||
59 | // Reuse the route if we're going to and from the same route | 59 | // Reuse the route if we're going to and from the same route |
60 | shouldReuseRoute (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { | 60 | shouldReuseRoute (future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { |
61 | return future.routeConfig === curr.routeConfig | 61 | return future.routeConfig === curr.routeConfig && future.routeConfig?.data?.reloadOnSameNavigation !== true |
62 | } | 62 | } |
63 | 63 | ||
64 | private gb () { | 64 | private gb () { |