Skip to content

Instantly share code, notes, and snippets.

View lydemann's full-sized avatar

Christian Lüdemann lydemann

View GitHub Profile
@lydemann
lydemann / graphql-helpers.ts
Created March 7, 2021 11:01
graphql-helpers.ts
export function createInCache<ReadQueryResponseT>(
toCreate: EntityObject,
readQuery: DocumentNode,
cache: ApolloCache<any>,
entityName: keyof ReadQueryResponseT
) {
const existingEntities = cache.readQuery<
Record<keyof ReadQueryResponseT, EntityObject[]>
>({
query: readQuery,
@lydemann
lydemann / graphql-helpers.ts
Created March 7, 2021 11:00
graphql-helpers.ts
export interface EntityObject {
id: string;
}
@lydemann
lydemann / graphql-helpers.ts
Created March 7, 2021 11:00
graphql-helpers.ts
import { ApolloCache } from '@apollo/client/core';
import { DocumentNode } from 'graphql';
export interface EntityObject {
id: string;
}
export function createInCache<ReadQueryResponseT>(
toCreate: EntityObject,
readQuery: DocumentNode,
@lydemann
lydemann / category-transaction-list.component.ts
Created March 2, 2021 11:57
category-transaction-list.component.ts
/*
For avoiding clicks on mouse up after HammerJS long press.
This event is triggered right before (click) to ensure we will not trigger click on long press.
*/
preventClickAfterLongPress(event: MouseEvent) {
const element = event.target as HTMLElement;
// needs to add class directly so it is applied before click event
element.classList.add('prevent-pointer-events');
setTimeout(() => {
element.classList.remove('prevent-pointer-events');
@lydemann
lydemann / course-content.component.ts
Created February 23, 2021 17:12
course-content.component.ts
private getTrustedVideoUrl(url: string): SafeResourceUrl {
// Url domains are whitelisted using CSP header
// Content-Security-Policy: frame-src <source> <source>;
const sanitizedUrl = this.sanitizer.sanitize(
SecurityContext.URL,
url
);
return this.sanitizer.bypassSecurityTrustResourceUrl(sanitizedUrl);
}
@lydemann
lydemann / course-content.component.ts
Created February 22, 2021 17:21
course-content.component.ts
private getTrustedVideoUrl(url: string): SafeResourceUrl {
// Url domains are whitelisted using CSP header
// Content-Security-Policy: frame-src <source> <source>;
const sanitizedUrl = this.sanitizer.sanitize(
SecurityContext.RESOURCE_URL,
url
);
return this.sanitizer.bypassSecurityTrustResourceUrl(sanitizedUrl);
}
@lydemann
lydemann / school-id.resolver.ts
Created December 29, 2020 17:57
school-id.resolver.ts
@Injectable({ providedIn: 'root' })
export class SchoolIdResolver implements Resolve<null> {
constructor(private courseFacadeService: CourseFacadeService) {}
resolve(
route: ActivatedRouteSnapshot
): Observable<null> | Promise<null> | null {
const schoolId = route.params.schoolId;
auth().tenantId = schoolId;
return;
@lydemann
lydemann / user-resolvers.ts
Created December 29, 2020 17:52
user-resolvers.ts
setLessonCompleted: (
parent,
{ uid, lessonId, isCompleted },
context: RequestContext
) => {
if (!context.auth.admin && uid !== context.auth.uid) {
throw new AuthenticationError('User is not admin or user');
}
return firestoreDB
@lydemann
lydemann / app.routing.ts
Last active December 29, 2020 18:01
app.routing.ts
const routes: Routes = [
{
path: ':schoolId',
resolve: [SchoolIdResolver],
children: [
{
path: '',
pathMatch: 'full',
redirectTo: 'courses'
},
@lydemann
lydemann / set-token.interceptor.ts
Created December 28, 2020 18:40
set-token.interceptor.ts
@Injectable({ providedIn: 'root' })
export class SetTokenInterceptor implements HttpInterceptor {
constructor(private userService: UserService) {}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (!this.userService.currentUser$.value) {
return next.handle(req);