diff options
8 files changed, 61 insertions, 86 deletions
diff --git a/client/src/app/+about/about-instance/about-instance.component.html b/client/src/app/+about/about-instance/about-instance.component.html index a42bda845..436d486ab 100644 --- a/client/src/app/+about/about-instance/about-instance.component.html +++ b/client/src/app/+about/about-instance/about-instance.component.html | |||
@@ -4,7 +4,7 @@ | |||
4 | <div class="about-instance-title"> | 4 | <div class="about-instance-title"> |
5 | <h1 i18n class="title">About {{ instanceName }}</h1> | 5 | <h1 i18n class="title">About {{ instanceName }}</h1> |
6 | 6 | ||
7 | <a routerLink="contact" i18n *ngIf="isContactFormEnabled" class="contact-admin">Contact administrator</a> | 7 | <a routerLink="/about/contact" i18n *ngIf="isContactFormEnabled" class="contact-admin">Contact administrator</a> |
8 | </div> | 8 | </div> |
9 | 9 | ||
10 | <div class="instance-badges" *ngIf="categories.length !== 0 || languages.length !== 0"> | 10 | <div class="instance-badges" *ngIf="categories.length !== 0 || languages.length !== 0"> |
@@ -218,4 +218,4 @@ | |||
218 | </div> | 218 | </div> |
219 | </div> | 219 | </div> |
220 | 220 | ||
221 | <my-contact-admin-modal></my-contact-admin-modal> | 221 | <my-contact-admin-modal #contactAdminModal></my-contact-admin-modal> |
diff --git a/client/src/app/+about/about-instance/about-instance.component.scss b/client/src/app/+about/about-instance/about-instance.component.scss index b7bf10995..6bbb66a58 100644 --- a/client/src/app/+about/about-instance/about-instance.component.scss +++ b/client/src/app/+about/about-instance/about-instance.component.scss | |||
@@ -11,15 +11,10 @@ | |||
11 | } | 11 | } |
12 | 12 | ||
13 | .contact-admin { | 13 | .contact-admin { |
14 | @include peertube-button; | 14 | @include peertube-button-link; |
15 | @include orange-button; | 15 | @include orange-button; |
16 | 16 | ||
17 | height: fit-content; | 17 | height: fit-content; |
18 | |||
19 | &:hover, | ||
20 | &:active { | ||
21 | text-decoration: none; | ||
22 | } | ||
23 | } | 18 | } |
24 | } | 19 | } |
25 | 20 | ||
@@ -59,6 +54,10 @@ | |||
59 | font-size: 15px; | 54 | font-size: 15px; |
60 | } | 55 | } |
61 | 56 | ||
57 | .short-description { | ||
58 | margin-top: 10px; | ||
59 | } | ||
60 | |||
62 | .short-description .dedicated-to-nsfw { | 61 | .short-description .dedicated-to-nsfw { |
63 | margin-top: 20px; | 62 | margin-top: 20px; |
64 | font-weight: $font-semibold; | 63 | font-weight: $font-semibold; |
diff --git a/client/src/app/+about/about-instance/about-instance.component.ts b/client/src/app/+about/about-instance/about-instance.component.ts index ffb4294ab..f86df5b67 100644 --- a/client/src/app/+about/about-instance/about-instance.component.ts +++ b/client/src/app/+about/about-instance/about-instance.component.ts | |||
@@ -1,13 +1,12 @@ | |||
1 | import { ViewportScroller } from '@angular/common' | 1 | import { ViewportScroller } from '@angular/common' |
2 | import { AfterViewChecked, Component, ElementRef, OnInit, ViewChild } from '@angular/core' | 2 | import { AfterViewChecked, Component, ElementRef, OnInit, ViewChild } from '@angular/core' |
3 | import { ActivatedRoute } from '@angular/router' | 3 | import { ActivatedRoute } from '@angular/router' |
4 | import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component' | ||
5 | import { Notifier, ServerService } from '@app/core' | 4 | import { Notifier, ServerService } from '@app/core' |
6 | import { CustomMarkupService } from '@app/shared/shared-custom-markup' | ||
7 | import { InstanceService } from '@app/shared/shared-instance' | 5 | import { InstanceService } from '@app/shared/shared-instance' |
8 | import { About, HTMLServerConfig, ServerConfig } from '@shared/models' | 6 | import { copyToClipboard } from '@root-helpers/utils' |
9 | import { copyToClipboard } from '../../../root-helpers/utils' | 7 | import { HTMLServerConfig } from '@shared/models/server' |
10 | import { ResolverData } from './about-instance.resolver' | 8 | import { ResolverData } from './about-instance.resolver' |
9 | import { ContactAdminModalComponent } from './contact-admin-modal.component' | ||
11 | 10 | ||
12 | @Component({ | 11 | @Component({ |
13 | selector: 'my-about-instance', | 12 | selector: 'my-about-instance', |
@@ -16,6 +15,7 @@ import { ResolverData } from './about-instance.resolver' | |||
16 | }) | 15 | }) |
17 | export class AboutInstanceComponent implements OnInit, AfterViewChecked { | 16 | export class AboutInstanceComponent implements OnInit, AfterViewChecked { |
18 | @ViewChild('descriptionWrapper') descriptionWrapper: ElementRef<HTMLInputElement> | 17 | @ViewChild('descriptionWrapper') descriptionWrapper: ElementRef<HTMLInputElement> |
18 | @ViewChild('contactAdminModal', { static: true }) contactAdminModal: ContactAdminModalComponent | ||
19 | 19 | ||
20 | shortDescription = '' | 20 | shortDescription = '' |
21 | descriptionContent: string | 21 | descriptionContent: string |
@@ -65,6 +65,14 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked { | |||
65 | 65 | ||
66 | this.serverConfig = this.serverService.getHTMLConfig() | 66 | this.serverConfig = this.serverService.getHTMLConfig() |
67 | 67 | ||
68 | this.route.data.subscribe(data => { | ||
69 | if (!data?.isContact) return | ||
70 | |||
71 | const prefill = this.route.snapshot.queryParams | ||
72 | |||
73 | this.contactAdminModal.show(prefill) | ||
74 | }) | ||
75 | |||
68 | this.languages = languages | 76 | this.languages = languages |
69 | this.categories = categories | 77 | this.categories = categories |
70 | 78 | ||
diff --git a/client/src/app/+about/about-instance/contact-admin-modal.component.html b/client/src/app/+about/about-instance/contact-admin-modal.component.html index 343e5d649..8b6b707af 100644 --- a/client/src/app/+about/about-instance/contact-admin-modal.component.html +++ b/client/src/app/+about/about-instance/contact-admin-modal.component.html | |||
@@ -6,7 +6,7 @@ | |||
6 | 6 | ||
7 | <div class="modal-body"> | 7 | <div class="modal-body"> |
8 | 8 | ||
9 | <form novalidate [formGroup]="form" (ngSubmit)="sendForm()"> | 9 | <form *ngIf="isContactFormEnabled()" novalidate [formGroup]="form" (ngSubmit)="sendForm()"> |
10 | <div class="form-group"> | 10 | <div class="form-group"> |
11 | <label i18n for="fromName">Your name</label> | 11 | <label i18n for="fromName">Your name</label> |
12 | <input | 12 | <input |
@@ -53,5 +53,7 @@ | |||
53 | </div> | 53 | </div> |
54 | </form> | 54 | </form> |
55 | 55 | ||
56 | <div *ngIf="!isContactFormEnabled()" class="alert alert-error" i18n>The contact form is not enabled on this instance.</div> | ||
57 | |||
56 | </div> | 58 | </div> |
57 | </ng-template> | 59 | </ng-template> |
diff --git a/client/src/app/+about/about-instance/contact-admin-modal.component.scss b/client/src/app/+about/about-instance/contact-admin-modal.component.scss index cd3cf85dd..cc75e8279 100644 --- a/client/src/app/+about/about-instance/contact-admin-modal.component.scss +++ b/client/src/app/+about/about-instance/contact-admin-modal.component.scss | |||
@@ -1,21 +1,16 @@ | |||
1 | @import 'variables'; | 1 | @import 'variables'; |
2 | @import 'mixins'; | 2 | @import 'mixins'; |
3 | 3 | ||
4 | .modal-body { | ||
5 | text-align: left; | ||
6 | } | ||
7 | |||
4 | input[type=text] { | 8 | input[type=text] { |
5 | @include peertube-input-text(340px); | 9 | @include peertube-input-text(340px); |
6 | display: block; | ||
7 | 10 | ||
8 | @media screen and (max-width: #{map-get($container-max-widths, sm)}) { | 11 | display: block; |
9 | width: 100%; | ||
10 | } | ||
11 | } | 12 | } |
12 | 13 | ||
13 | textarea { | 14 | textarea { |
14 | @include peertube-textarea(100%, 200px); | 15 | @include peertube-textarea(100%, 200px); |
15 | } | 16 | } |
16 | |||
17 | @media screen and (max-width: breakpoint(md)) { | ||
18 | .modal-body { | ||
19 | text-align: left; | ||
20 | } | ||
21 | } | ||
diff --git a/client/src/app/+about/about-instance/contact-admin-modal.component.ts b/client/src/app/+about/about-instance/contact-admin-modal.component.ts index 32812d9e0..a528faa20 100644 --- a/client/src/app/+about/about-instance/contact-admin-modal.component.ts +++ b/client/src/app/+about/about-instance/contact-admin-modal.component.ts | |||
@@ -1,7 +1,5 @@ | |||
1 | import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core' | 1 | import { Component, OnInit, ViewChild } from '@angular/core' |
2 | import { ActivatedRoute, Router, NavigationEnd } from '@angular/router' | 2 | import { Router } from '@angular/router' |
3 | import { Subject } from 'rxjs' | ||
4 | import { takeUntil, filter } from 'rxjs/operators' | ||
5 | import { Notifier, ServerService } from '@app/core' | 3 | import { Notifier, ServerService } from '@app/core' |
6 | import { | 4 | import { |
7 | BODY_VALIDATOR, | 5 | BODY_VALIDATOR, |
@@ -16,30 +14,31 @@ import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' | |||
16 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' | 14 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' |
17 | import { HTMLServerConfig } from '@shared/models' | 15 | import { HTMLServerConfig } from '@shared/models' |
18 | 16 | ||
17 | type Prefill = { | ||
18 | subject?: string | ||
19 | body?: string | ||
20 | } | ||
21 | |||
19 | @Component({ | 22 | @Component({ |
20 | selector: 'my-contact-admin-modal', | 23 | selector: 'my-contact-admin-modal', |
21 | templateUrl: './contact-admin-modal.component.html', | 24 | templateUrl: './contact-admin-modal.component.html', |
22 | styleUrls: [ './contact-admin-modal.component.scss' ] | 25 | styleUrls: [ './contact-admin-modal.component.scss' ] |
23 | }) | 26 | }) |
24 | export class ContactAdminModalComponent extends FormReactive implements OnInit, OnDestroy { | 27 | export class ContactAdminModalComponent extends FormReactive implements OnInit { |
25 | @ViewChild('modal', { static: true }) modal: NgbModal | 28 | @ViewChild('modal', { static: true }) modal: NgbModal |
26 | 29 | ||
27 | error: string | 30 | error: string |
28 | destroy = new Subject<any>() | ||
29 | |||
30 | subject: string | ||
31 | 31 | ||
32 | private openedModal: NgbModalRef | 32 | private openedModal: NgbModalRef |
33 | private serverConfig: HTMLServerConfig | 33 | private serverConfig: HTMLServerConfig |
34 | 34 | ||
35 | constructor ( | 35 | constructor ( |
36 | protected formValidatorService: FormValidatorService, | 36 | protected formValidatorService: FormValidatorService, |
37 | private router: Router, | ||
37 | private modalService: NgbModal, | 38 | private modalService: NgbModal, |
38 | private instanceService: InstanceService, | 39 | private instanceService: InstanceService, |
39 | private serverService: ServerService, | 40 | private serverService: ServerService, |
40 | private notifier: Notifier, | 41 | private notifier: Notifier |
41 | private route: ActivatedRoute, | ||
42 | private router: Router | ||
43 | ) { | 42 | ) { |
44 | super() | 43 | super() |
45 | } | 44 | } |
@@ -48,10 +47,6 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit, | |||
48 | return this.serverConfig.instance.name | 47 | return this.serverConfig.instance.name |
49 | } | 48 | } |
50 | 49 | ||
51 | get isContactFormEnabled () { | ||
52 | return this.serverConfig.email.enabled && this.serverConfig.contactForm.enabled | ||
53 | } | ||
54 | |||
55 | ngOnInit () { | 50 | ngOnInit () { |
56 | this.serverConfig = this.serverService.getHTMLConfig() | 51 | this.serverConfig = this.serverService.getHTMLConfig() |
57 | 52 | ||
@@ -61,46 +56,17 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit, | |||
61 | subject: SUBJECT_VALIDATOR, | 56 | subject: SUBJECT_VALIDATOR, |
62 | body: BODY_VALIDATOR | 57 | body: BODY_VALIDATOR |
63 | }) | 58 | }) |
64 | |||
65 | // Direct access | ||
66 | if (/^\/about\/instance\/contact/.test(this.router.url)) { | ||
67 | this.show() | ||
68 | this.prefillForm() | ||
69 | } | ||
70 | |||
71 | // Router access | ||
72 | this.router.events | ||
73 | .pipe( | ||
74 | takeUntil(this.destroy), | ||
75 | filter(event => event instanceof NavigationEnd) | ||
76 | ) | ||
77 | .subscribe((event: NavigationEnd) => { | ||
78 | if (/^\/about\/instance\/contact/.test(event.url)) { | ||
79 | this.show() | ||
80 | this.prefillForm() | ||
81 | } | ||
82 | }) | ||
83 | } | 59 | } |
84 | 60 | ||
85 | ngOnDestroy () { | 61 | isContactFormEnabled () { |
86 | this.destroy.next() | 62 | return this.serverConfig.email.enabled && this.serverConfig.contactForm.enabled |
87 | } | 63 | } |
88 | 64 | ||
89 | show () { | 65 | show (prefill: Prefill = {}) { |
90 | // If contactForm not enabled redirect to 404 | ||
91 | if (!this.isContactFormEnabled) { | ||
92 | return this.router.navigate([ '/404' ], { state: { type: 'other', obj: { status: 404 } }, skipLocationChange: true }) | ||
93 | } | ||
94 | |||
95 | // Open modal | ||
96 | this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false }) | 66 | this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false }) |
97 | 67 | ||
98 | // Go back to /about/instance after the modal is closed | 68 | this.openedModal.shown.subscribe(() => this.prefillForm(prefill)) |
99 | this.openedModal.result.then(() => { | 69 | this.openedModal.result.finally(() => this.router.navigateByUrl('/about/instance')) |
100 | this.router.navigateByUrl('/about/instance') | ||
101 | }, () => { | ||
102 | this.router.navigateByUrl('/about/instance') | ||
103 | }) | ||
104 | } | 70 | } |
105 | 71 | ||
106 | hide () { | 72 | hide () { |
@@ -132,15 +98,13 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit, | |||
132 | ) | 98 | ) |
133 | } | 99 | } |
134 | 100 | ||
135 | private prefillForm () { | 101 | private prefillForm (prefill: Prefill) { |
136 | const { subject, body } = this.route.snapshot.queryParams | 102 | if (prefill.subject) { |
137 | 103 | this.form.get('subject').setValue(prefill.subject) | |
138 | if (subject) { | ||
139 | this.form.get('subject').setValue(subject) | ||
140 | } | 104 | } |
141 | 105 | ||
142 | if (body) { | 106 | if (prefill.body) { |
143 | this.form.get('body').setValue(body) | 107 | this.form.get('body').setValue(prefill.body) |
144 | } | 108 | } |
145 | } | 109 | } |
146 | } | 110 | } |
diff --git a/client/src/app/+about/about-routing.module.ts b/client/src/app/+about/about-routing.module.ts index c810ca272..3974231e3 100644 --- a/client/src/app/+about/about-routing.module.ts +++ b/client/src/app/+about/about-routing.module.ts | |||
@@ -27,13 +27,20 @@ const aboutRoutes: Routes = [ | |||
27 | }, | 27 | }, |
28 | resolve: { | 28 | resolve: { |
29 | instanceData: AboutInstanceResolver | 29 | instanceData: AboutInstanceResolver |
30 | } | ||
31 | }, | ||
32 | { | ||
33 | path: 'contact', | ||
34 | component: AboutInstanceComponent, | ||
35 | data: { | ||
36 | meta: { | ||
37 | title: $localize`Contact` | ||
38 | }, | ||
39 | isContact: true | ||
30 | }, | 40 | }, |
31 | children: [ | 41 | resolve: { |
32 | { | 42 | instanceData: AboutInstanceResolver |
33 | path: 'contact', | 43 | } |
34 | component: ContactAdminModalComponent | ||
35 | } | ||
36 | ] | ||
37 | }, | 44 | }, |
38 | { | 45 | { |
39 | path: 'peertube', | 46 | path: 'peertube', |
diff --git a/client/src/sass/include/_mixins.scss b/client/src/sass/include/_mixins.scss index 0822e0ca6..a835381d6 100644 --- a/client/src/sass/include/_mixins.scss +++ b/client/src/sass/include/_mixins.scss | |||
@@ -102,7 +102,7 @@ | |||
102 | opacity: 0.7; | 102 | opacity: 0.7; |
103 | } | 103 | } |
104 | 104 | ||
105 | @media screen and (max-width: $width) { | 105 | @media screen and (max-width: calc(#{$width} + 40px)) { |
106 | width: 100%; | 106 | width: 100%; |
107 | } | 107 | } |
108 | } | 108 | } |