Changeset View
Changeset View
Standalone View
Standalone View
src/app/createPost/createPost.component.ts
import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core'; | import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core'; | ||||
import { MatDialog, MatSnackBar } from '@angular/material'; | import { MatDialog, MatSnackBar } from '@angular/material'; | ||||
import { Router, ActivatedRoute } from '@angular/router'; | import { Router, ActivatedRoute } from '@angular/router'; | ||||
import { Subject } from 'rxjs/Subject'; | import { Subject } from 'rxjs/Subject'; | ||||
import { ConfirmDeletionDialogComponent } from '../_dialogs/confirmDeletion.dialog.component'; | import { ConfirmDeletionDialogComponent } from '../_dialogs/confirmDeletion.dialog.component'; | ||||
import { PictureDialogComponent } from '../_dialogs/picture.dialog.component'; | import { PictureDialogComponent } from '../_dialogs/picture.dialog.component'; | ||||
import { PicturesDialogComponent } from '../_dialogs/pictures.dialog.component'; | import { PicturesDialogComponent } from '../_dialogs/pictures.dialog.component'; | ||||
import { YouTubeDialogComponent } from '../_dialogs/youtube.dialog.component'; | import { YouTubeDialogComponent } from '../_dialogs/youtube.dialog.component'; | ||||
import { Area } from '../_models/area'; | import { Area } from '../_models/area'; | ||||
import * as C from '../_models/constants'; | import * as C from '../_models/constants'; | ||||
import { Image } from '../_models/image'; | import { Image } from '../_models/image'; | ||||
import { Post, PostError } from '../_models/post'; | import { Post, PostError } from '../_models/post'; | ||||
import { NavBarService } from '../_services/navBar.service'; | import { AreaService } from '../_services/area.service'; | ||||
import { PostService } from '../_services/post.service'; | import { PostService } from '../_services/post.service'; | ||||
import { RouteService } from '../_services/route.service'; | import { RouteService } from '../_services/route.service'; | ||||
@Component({ | @Component({ | ||||
templateUrl: 'createPost.component.html' | templateUrl: 'createPost.component.html', | ||||
styleUrls: ['./createPost.component.scss'] | |||||
}) | }) | ||||
export class CreatePostComponent implements OnInit, OnDestroy { | export class CreatePostComponent implements OnInit, OnDestroy { | ||||
backupPosts: { [area: string]: Post[]; } = {}; | |||||
componentDestroyed: Subject<boolean> = new Subject(); | componentDestroyed: Subject<boolean> = new Subject(); | ||||
currentArea: Area; | currentArea: Area; | ||||
errors: PostError; | errors: PostError; | ||||
imageArray: { [area: string]: string[]; } = {}; | |||||
imageData: any; | imageData: any; | ||||
index = 1; | |||||
isDraft = false; | isDraft = false; | ||||
limit = 10; | |||||
loading: boolean; | loading: boolean; | ||||
offset = 10; | |||||
post: Post = new Post(null, null, false, null, null, null, 's', null, [], []); | post: Post = new Post(null, null, false, null, null, null, 's', null, [], []); | ||||
superPosts: { [area: string]: Post[]; } = {}; | |||||
totalCount = 0; | |||||
constructor( | constructor( | ||||
private cdRef: ChangeDetectorRef, | private cdRef: ChangeDetectorRef, | ||||
private dialog: MatDialog, | private dialog: MatDialog, | ||||
private snackBar: MatSnackBar, | private snackBar: MatSnackBar, | ||||
private route: ActivatedRoute, | private route: ActivatedRoute, | ||||
private router: Router, | private router: Router, | ||||
private navBarService: NavBarService, | private areaService: AreaService, | ||||
private postService: PostService, | private postService: PostService, | ||||
private routeService: RouteService | private routeService: RouteService | ||||
) { } | ) { } | ||||
ngOnInit() { | ngOnInit() { | ||||
this.post.text = ''; | this.post.text = ''; | ||||
this.routeService.resetRoutes(); | this.routeService.resetRoutes(); | ||||
this.navBarService.currentArea | this.route.params | ||||
.takeUntil(this.componentDestroyed) | .takeUntil(this.componentDestroyed) | ||||
.subscribe((currentArea: Area) => { | .subscribe(params => { | ||||
if (currentArea.name !== '') { | if (params['area'] !== undefined) { | ||||
this.currentArea = currentArea; | this.areaService.getArea(params['area']).subscribe(area => { | ||||
this.currentArea = area; | |||||
this.route.params | this.route.params | ||||
.takeUntil(this.componentDestroyed) | .takeUntil(this.componentDestroyed) | ||||
.subscribe(params => { | .subscribe(params2 => { | ||||
if (params['id'] !== undefined) { | if (params2['id'] !== undefined) { | ||||
this.isDraft = true; | this.isDraft = true; | ||||
this.postService.getPost(this.currentArea.name, params['id'], true) | this.postService.getPost(this.currentArea.name, params2['id'], true) | ||||
.takeUntil(this.componentDestroyed) | .takeUntil(this.componentDestroyed) | ||||
.subscribe(post => { | .subscribe(post => { | ||||
this.post = post; | this.post = post; | ||||
this.loading = false; | this.loading = false; | ||||
this.cdRef.detectChanges(); | this.cdRef.detectChanges(); | ||||
}); | }); | ||||
} | } | ||||
}); | }); | ||||
}); | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
ngOnDestroy() { | ngOnDestroy() { | ||||
this.cdRef.detach(); | this.cdRef.detach(); | ||||
this.componentDestroyed.next(true); | this.componentDestroyed.next(true); | ||||
this.componentDestroyed.complete(); | this.componentDestroyed.complete(); | ||||
} | } | ||||
private addLineBreak(s: string) { | private addLineBreak(s: string) { | ||||
this.post.text = this.post.text !== '' ? this.post.text += `${s}\n` : this.post.text = `${s}\n`; | this.post.text = this.post.text !== '' ? this.post.text += `${s}\n` : this.post.text = `${s}\n`; | ||||
} | } | ||||
private imageInPosts(posts: Post[], area: string) { | |||||
this.imageArray[area] = []; | |||||
for (let i = 0; i <= posts.length - 1; i++) { | |||||
// Find image markdown data in post.text - Guarenteed by Regex | |||||
const indexOfStart = posts[i].text.search(C.WF_IMAGE_REGEX); | |||||
if (indexOfStart !== -1) { | |||||
// Start at index and parse until we find a closing ')' char | |||||
for (let j = indexOfStart; j <= posts[i].text.length; j++) { | |||||
if (posts[i].text.charAt(j) === ']') { | |||||
// Add data to image array in specific area | |||||
this.imageArray[area][i] = posts[i].text.slice(indexOfStart, j + 1); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
this.loading = false; | |||||
} | |||||
private removeMarkdown(input: string) { | |||||
input = input | |||||
// Remove horizontal rules (stripListHeaders conflict with this rule, which is why it has been moved to the top) | |||||
.replace(/^(-\s*?|\*\s*?|_\s*?){3,}\s*$/gm, '[Horizontal-Rule]') | |||||
// Remove horizontal rules | |||||
.replace(/^(-\s*?|\*\s*?|_\s*?){3,}\s*$/gm, '') | |||||
// Header | |||||
.replace(/\n={2,}/g, '\n') | |||||
// Strikethrough | |||||
.replace(/~~/g, '') | |||||
// Fenced codeblocks | |||||
.replace(/`{3}.*\n/g, '') | |||||
// Remove HTML tags | |||||
.replace(/<[^>]*>/g, '') | |||||
// Remove setext-style headers | |||||
.replace(/^[=\-]{2,}\s*$/g, '') | |||||
// Remove footnotes? | |||||
.replace(/\[\^.+?\](\: .*?$)?/g, '') | |||||
.replace(/\s{0,2}\[.*?\]: .*?$/g, '') | |||||
// Remove images | |||||
.replace(C.WF_IMAGE_REGEX, '') | |||||
// Remove wildfyre images | |||||
.replace(/(\[img: \d\])/gm, '') | |||||
// Remove inline links | |||||
.replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1') | |||||
// Remove blockquotes | |||||
.replace(/^\s{0,3}>\s?/g, '') | |||||
// Remove reference-style links? | |||||
.replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, '') | |||||
// Remove atx-style headers | |||||
.replace(/^(\n)?\s{0,}#{1,6}\s+| {0,}(\n)?\s{0,}#{0,} {0,}(\n)?\s{0,}$/gm, '$1$2$3') | |||||
// Remove emphasis (repeat the line to remove double emphasis) | |||||
.replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, '$2') | |||||
.replace(/([\*_]{1,3})(\S.*?\S{0,1})\1/g, '$2') | |||||
// Remove code blocks | |||||
.replace(/(`{3,})(.*?)\1/gm, '$2') | |||||
// Remove inline code | |||||
.replace(/`(.+?)`/g, '$1') | |||||
// Replace two or more newlines with exactly two? Not entirely sure this belongs here... | |||||
.replace(/\n{2,}/g, '\n\n'); | |||||
return input; | |||||
} | |||||
addBlockQoutes() { | addBlockQoutes() { | ||||
this.addLineBreak('> Blockquote example\n> This line is part of the same quote.\n\nQuote break.\n\n>' | this.addLineBreak('> Blockquote example\n> This line is part of the same quote.\n\nQuote break.\n\n>' | ||||
+ ' This is a very long line that will still be quoted properly when it wraps. You can *put* **Markdown** into a blockquote.'); | + ' This is a very long line that will still be quoted properly when it wraps. You can *put* **Markdown** into a blockquote.'); | ||||
} | } | ||||
addBold() { | addBold() { | ||||
this.addLineBreak('**Example**'); | this.addLineBreak('**Example**'); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | addTable() { | ||||
this.addLineBreak('| Tables | Are | Cool |\n| ------------- |:-------------:| -----:|\n' | this.addLineBreak('| Tables | Are | Cool |\n| ------------- |:-------------:| -----:|\n' | ||||
+ '| col 3 is | right-aligned | $1600 |\n| col 2 is | centered | $12 |\n| zebra stripes | are neat | $1 |'); | + '| col 3 is | right-aligned | $1600 |\n| col 2 is | centered | $12 |\n| zebra stripes | are neat | $1 |'); | ||||
} | } | ||||
addUnorderedList() { | addUnorderedList() { | ||||
this.addLineBreak('* Unordered list can use asterisks\n- Or minuses\n+ Or pluses'); | this.addLineBreak('* Unordered list can use asterisks\n- Or minuses\n+ Or pluses'); | ||||
} | } | ||||
back() { | |||||
if (this.routeService.routes.length === 0) { | |||||
this.router.navigateByUrl(''); | |||||
} else { | |||||
this.router.navigateByUrl(this.routeService.getNextRoute()); | |||||
} | |||||
} | |||||
createPost(draft: boolean) { | createPost(draft: boolean) { | ||||
this.loading = true; | this.loading = true; | ||||
this.cdRef.detectChanges(); | this.cdRef.detectChanges(); | ||||
if (this.post.text !== '' && this.runImageCheck()) { | if (this.post.text !== '' && this.runImageCheck()) { | ||||
this.postService.createPost(this.currentArea.name, this.post.text, this.post.anonym, this.imageData, draft, this.post.id) | this.postService.createPost(this.currentArea.name, this.post.text, this.post.anonym, this.imageData, draft, this.post.id) | ||||
.takeUntil(this.componentDestroyed) | .takeUntil(this.componentDestroyed) | ||||
.subscribe(result => { | .subscribe(result => { | ||||
if (!result.getError()) { | if (!result.getError()) { | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | for (let i = 0; i < this.post.additional_images.length; i++) { | ||||
this.snackBar.open('Image deleted successfully', 'Close', { | this.snackBar.open('Image deleted successfully', 'Close', { | ||||
duration: 3000 | duration: 3000 | ||||
}); | }); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
getDrafts(page: number) { | |||||
this.loading = true; | |||||
const posts: Post[] = []; | |||||
this.postService.getDrafts(this.currentArea.name, this.limit, (this.offset * page) - this.limit) | |||||
.takeUntil(this.componentDestroyed) | |||||
.subscribe(superPost => { | |||||
superPost.results.forEach((obj: any) => { | |||||
posts.push(Post.parse(obj)); | |||||
}); | |||||
// Removes binding to original 'superPost' variable | |||||
this.superPosts[this.currentArea.name] = JSON.parse(JSON.stringify(posts)); | |||||
this.backupPosts[this.currentArea.name] = posts; | |||||
this.imageInPosts(this.superPosts[this.currentArea.name], this.currentArea.name); | |||||
for (let i = 0; i <= this.backupPosts[this.currentArea.name].length - 1; i++) { | |||||
this.backupPosts[this.currentArea.name][i].text = this.removeMarkdown(this.backupPosts[this.currentArea.name][i].text); | |||||
} | |||||
this.index = page; | |||||
this.totalCount = superPost.count; | |||||
this.cdRef.detectChanges(); | |||||
this.loading = false; | |||||
}); | |||||
} | |||||
getImageMatchesByGroup(index: number, str: string, reg: RegExp): string[] { | getImageMatchesByGroup(index: number, str: string, reg: RegExp): string[] { | ||||
let match: any; | let match: any; | ||||
const matches: string[] = []; | const matches: string[] = []; | ||||
// Find any occurence of image markdown | // Find any occurence of image markdown | ||||
while ((match = reg.exec(str))) { | while ((match = reg.exec(str))) { | ||||
if (match[index] !== undefined) { | if (match[index] !== undefined) { | ||||
matches.push(match[index]); | matches.push(match[index]); | ||||
} | } | ||||
} | } | ||||
return matches; | return matches; | ||||
} | } | ||||
loadDrafts() { | |||||
this.routeService.addNextRoute('/create'); | |||||
this.router.navigateByUrl('/drafts'); | |||||
} | |||||
makeAnonymous(value: any) { | makeAnonymous(value: any) { | ||||
this.post.anonym = value.checked; | this.post.anonym = value.checked; | ||||
} | } | ||||
openDraftDeleteDialog() { | openDraftDeleteDialog() { | ||||
const dialogRef = this.dialog.open(ConfirmDeletionDialogComponent); | const dialogRef = this.dialog.open(ConfirmDeletionDialogComponent); | ||||
dialogRef.afterClosed() | dialogRef.afterClosed() | ||||
.takeUntil(this.componentDestroyed) | .takeUntil(this.componentDestroyed) | ||||
▲ Show 20 Lines • Show All 149 Lines • ▼ Show 20 Lines | dialogRef.afterClosed() | ||||
result.url = result.url | result.url = result.url | ||||
.replace('https://', '') | .replace('https://', '') | ||||
.replace('http://', '') | .replace('http://', '') | ||||
.replace('http://', '') | .replace('http://', '') | ||||
.replace('www.', '') | .replace('www.', '') | ||||
.replace('m.', '') | .replace('m.', '') | ||||
.replace('youtube.com/watch?v=', '') | .replace('youtube.com/watch?v=', '') | ||||
.replace('youtu.be/', '') | .replace('youtu.be/', '') | ||||
.replace('youtube.com/', '') | .replace('youtube.com/', ''); | ||||
if (result.url.indexOf('?') !== -1) { | if (result.url.indexOf('?') !== -1) { | ||||
result.url = result.url.slice(0, result.url.indexOf('?')); | result.url = result.url.slice(0, result.url.indexOf('?')); | ||||
} | } | ||||
this.post.text = this.post.text === undefined ? | this.post.text = this.post.text === undefined ? | ||||
`[](https://www.youtube.com/watch?v=${result.url})\n` | `[](https://www.youtube.com/watch?v=${result.url})\n` | ||||
: | : | ||||
`[](https://www.youtube.com/watch?v=${result.url})\n${this.post.text}` | `[](https://www.youtube.com/watch?v=${result.url})\n${this.post.text}`; | ||||
} | } | ||||
}); | }); | ||||
} | } | ||||
publishDraft() { | publishDraft() { | ||||
this.loading = true; | this.loading = true; | ||||
this.cdRef.detectChanges(); | this.cdRef.detectChanges(); | ||||
if (this.post.text !== '' && this.runImageCheck()) { | if (this.post.text !== '' && this.runImageCheck()) { | ||||
Show All 33 Lines | if (linkMatch.length <= 4) { | ||||
valid = false; | valid = false; | ||||
this.snackBar.open( | this.snackBar.open( | ||||
'This markdown does not work here', | 'This markdown does not work here', | ||||
'Close', { | 'Close', { | ||||
duration: 3000 | duration: 3000 | ||||
}); | }); | ||||
} else { | } else { | ||||
for (let i = 0; i < invalidMatch.length; i++) { | for (let i = 0; i < invalidMatch.length; i++) { | ||||
if (Number.parseInt(invalidMatch[i]) !== this.post.additional_images[i].num) { | if (parseInt(invalidMatch[i], 10) !== this.post.additional_images[i].num) { | ||||
valid = false; | valid = false; | ||||
this.snackBar.open( | this.snackBar.open( | ||||
'This markdown does not work here', | 'This markdown does not work here', | ||||
'Close', { | 'Close', { | ||||
duration: 3000 | duration: 3000 | ||||
}); | }); | ||||
} | } | ||||
} | } | ||||
Show All 24 Lines |