Cleanup contact form with URL

Parent component still have the responsability to explicitely open the
modal
Rely on data router param to open or not the modal
This commit is contained in:
Chocobozzz 2021-06-15 11:57:15 +02:00 committed by Chocobozzz
parent 089cfa6569
commit 5c16e6bc97
8 changed files with 61 additions and 86 deletions

View File

@ -4,7 +4,7 @@
<div class="about-instance-title"> <div class="about-instance-title">
<h1 i18n class="title">About {{ instanceName }}</h1> <h1 i18n class="title">About {{ instanceName }}</h1>
<a routerLink="contact" i18n *ngIf="isContactFormEnabled" class="contact-admin">Contact administrator</a> <a routerLink="/about/contact" i18n *ngIf="isContactFormEnabled" class="contact-admin">Contact administrator</a>
</div> </div>
<div class="instance-badges" *ngIf="categories.length !== 0 || languages.length !== 0"> <div class="instance-badges" *ngIf="categories.length !== 0 || languages.length !== 0">
@ -218,4 +218,4 @@
</div> </div>
</div> </div>
<my-contact-admin-modal></my-contact-admin-modal> <my-contact-admin-modal #contactAdminModal></my-contact-admin-modal>

View File

@ -11,15 +11,10 @@
} }
.contact-admin { .contact-admin {
@include peertube-button; @include peertube-button-link;
@include orange-button; @include orange-button;
height: fit-content; height: fit-content;
&:hover,
&:active {
text-decoration: none;
}
} }
} }
@ -59,6 +54,10 @@
font-size: 15px; font-size: 15px;
} }
.short-description {
margin-top: 10px;
}
.short-description .dedicated-to-nsfw { .short-description .dedicated-to-nsfw {
margin-top: 20px; margin-top: 20px;
font-weight: $font-semibold; font-weight: $font-semibold;

View File

@ -1,13 +1,12 @@
import { ViewportScroller } from '@angular/common' import { ViewportScroller } from '@angular/common'
import { AfterViewChecked, Component, ElementRef, OnInit, ViewChild } from '@angular/core' import { AfterViewChecked, Component, ElementRef, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute } from '@angular/router' import { ActivatedRoute } from '@angular/router'
import { ContactAdminModalComponent } from '@app/+about/about-instance/contact-admin-modal.component'
import { Notifier, ServerService } from '@app/core' import { Notifier, ServerService } from '@app/core'
import { CustomMarkupService } from '@app/shared/shared-custom-markup'
import { InstanceService } from '@app/shared/shared-instance' import { InstanceService } from '@app/shared/shared-instance'
import { About, HTMLServerConfig, ServerConfig } from '@shared/models' import { copyToClipboard } from '@root-helpers/utils'
import { copyToClipboard } from '../../../root-helpers/utils' import { HTMLServerConfig } from '@shared/models/server'
import { ResolverData } from './about-instance.resolver' import { ResolverData } from './about-instance.resolver'
import { ContactAdminModalComponent } from './contact-admin-modal.component'
@Component({ @Component({
selector: 'my-about-instance', selector: 'my-about-instance',
@ -16,6 +15,7 @@ import { ResolverData } from './about-instance.resolver'
}) })
export class AboutInstanceComponent implements OnInit, AfterViewChecked { export class AboutInstanceComponent implements OnInit, AfterViewChecked {
@ViewChild('descriptionWrapper') descriptionWrapper: ElementRef<HTMLInputElement> @ViewChild('descriptionWrapper') descriptionWrapper: ElementRef<HTMLInputElement>
@ViewChild('contactAdminModal', { static: true }) contactAdminModal: ContactAdminModalComponent
shortDescription = '' shortDescription = ''
descriptionContent: string descriptionContent: string
@ -65,6 +65,14 @@ export class AboutInstanceComponent implements OnInit, AfterViewChecked {
this.serverConfig = this.serverService.getHTMLConfig() this.serverConfig = this.serverService.getHTMLConfig()
this.route.data.subscribe(data => {
if (!data?.isContact) return
const prefill = this.route.snapshot.queryParams
this.contactAdminModal.show(prefill)
})
this.languages = languages this.languages = languages
this.categories = categories this.categories = categories

View File

@ -6,7 +6,7 @@
<div class="modal-body"> <div class="modal-body">
<form novalidate [formGroup]="form" (ngSubmit)="sendForm()"> <form *ngIf="isContactFormEnabled()" novalidate [formGroup]="form" (ngSubmit)="sendForm()">
<div class="form-group"> <div class="form-group">
<label i18n for="fromName">Your name</label> <label i18n for="fromName">Your name</label>
<input <input
@ -53,5 +53,7 @@
</div> </div>
</form> </form>
<div *ngIf="!isContactFormEnabled()" class="alert alert-error" i18n>The contact form is not enabled on this instance.</div>
</div> </div>
</ng-template> </ng-template>

View File

@ -1,21 +1,16 @@
@import 'variables'; @import 'variables';
@import 'mixins'; @import 'mixins';
.modal-body {
text-align: left;
}
input[type=text] { input[type=text] {
@include peertube-input-text(340px); @include peertube-input-text(340px);
display: block;
@media screen and (max-width: #{map-get($container-max-widths, sm)}) { display: block;
width: 100%;
}
} }
textarea { textarea {
@include peertube-textarea(100%, 200px); @include peertube-textarea(100%, 200px);
} }
@media screen and (max-width: breakpoint(md)) {
.modal-body {
text-align: left;
}
}

View File

@ -1,7 +1,5 @@
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core' import { Component, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router' import { Router } from '@angular/router'
import { Subject } from 'rxjs'
import { takeUntil, filter } from 'rxjs/operators'
import { Notifier, ServerService } from '@app/core' import { Notifier, ServerService } from '@app/core'
import { import {
BODY_VALIDATOR, BODY_VALIDATOR,
@ -16,30 +14,31 @@ import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
import { HTMLServerConfig } from '@shared/models' import { HTMLServerConfig } from '@shared/models'
type Prefill = {
subject?: string
body?: string
}
@Component({ @Component({
selector: 'my-contact-admin-modal', selector: 'my-contact-admin-modal',
templateUrl: './contact-admin-modal.component.html', templateUrl: './contact-admin-modal.component.html',
styleUrls: [ './contact-admin-modal.component.scss' ] styleUrls: [ './contact-admin-modal.component.scss' ]
}) })
export class ContactAdminModalComponent extends FormReactive implements OnInit, OnDestroy { export class ContactAdminModalComponent extends FormReactive implements OnInit {
@ViewChild('modal', { static: true }) modal: NgbModal @ViewChild('modal', { static: true }) modal: NgbModal
error: string error: string
destroy = new Subject<any>()
subject: string
private openedModal: NgbModalRef private openedModal: NgbModalRef
private serverConfig: HTMLServerConfig private serverConfig: HTMLServerConfig
constructor ( constructor (
protected formValidatorService: FormValidatorService, protected formValidatorService: FormValidatorService,
private router: Router,
private modalService: NgbModal, private modalService: NgbModal,
private instanceService: InstanceService, private instanceService: InstanceService,
private serverService: ServerService, private serverService: ServerService,
private notifier: Notifier, private notifier: Notifier
private route: ActivatedRoute,
private router: Router
) { ) {
super() super()
} }
@ -48,10 +47,6 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit,
return this.serverConfig.instance.name return this.serverConfig.instance.name
} }
get isContactFormEnabled () {
return this.serverConfig.email.enabled && this.serverConfig.contactForm.enabled
}
ngOnInit () { ngOnInit () {
this.serverConfig = this.serverService.getHTMLConfig() this.serverConfig = this.serverService.getHTMLConfig()
@ -61,46 +56,17 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit,
subject: SUBJECT_VALIDATOR, subject: SUBJECT_VALIDATOR,
body: BODY_VALIDATOR body: BODY_VALIDATOR
}) })
// Direct access
if (/^\/about\/instance\/contact/.test(this.router.url)) {
this.show()
this.prefillForm()
}
// Router access
this.router.events
.pipe(
takeUntil(this.destroy),
filter(event => event instanceof NavigationEnd)
)
.subscribe((event: NavigationEnd) => {
if (/^\/about\/instance\/contact/.test(event.url)) {
this.show()
this.prefillForm()
}
})
} }
ngOnDestroy () { isContactFormEnabled () {
this.destroy.next() return this.serverConfig.email.enabled && this.serverConfig.contactForm.enabled
} }
show () { show (prefill: Prefill = {}) {
// If contactForm not enabled redirect to 404
if (!this.isContactFormEnabled) {
return this.router.navigate([ '/404' ], { state: { type: 'other', obj: { status: 404 } }, skipLocationChange: true })
}
// Open modal
this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false }) this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false })
// Go back to /about/instance after the modal is closed this.openedModal.shown.subscribe(() => this.prefillForm(prefill))
this.openedModal.result.then(() => { this.openedModal.result.finally(() => this.router.navigateByUrl('/about/instance'))
this.router.navigateByUrl('/about/instance')
}, () => {
this.router.navigateByUrl('/about/instance')
})
} }
hide () { hide () {
@ -132,15 +98,13 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit,
) )
} }
private prefillForm () { private prefillForm (prefill: Prefill) {
const { subject, body } = this.route.snapshot.queryParams if (prefill.subject) {
this.form.get('subject').setValue(prefill.subject)
if (subject) {
this.form.get('subject').setValue(subject)
} }
if (body) { if (prefill.body) {
this.form.get('body').setValue(body) this.form.get('body').setValue(prefill.body)
} }
} }
} }

View File

@ -27,13 +27,20 @@ const aboutRoutes: Routes = [
}, },
resolve: { resolve: {
instanceData: AboutInstanceResolver instanceData: AboutInstanceResolver
}
},
{
path: 'contact',
component: AboutInstanceComponent,
data: {
meta: {
title: $localize`Contact`
},
isContact: true
}, },
children: [ resolve: {
{ instanceData: AboutInstanceResolver
path: 'contact', }
component: ContactAdminModalComponent
}
]
}, },
{ {
path: 'peertube', path: 'peertube',

View File

@ -102,7 +102,7 @@
opacity: 0.7; opacity: 0.7;
} }
@media screen and (max-width: $width) { @media screen and (max-width: calc(#{$width} + 40px)) {
width: 100%; width: 100%;
} }
} }