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:
parent
089cfa6569
commit
5c16e6bc97
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue