Render terms of service as a widget

This commit is contained in:
Travis Ralston 2019-07-06 15:40:32 -06:00
parent 1c8b523114
commit 6c6ae5c5ed
8 changed files with 88 additions and 1 deletions

View File

@ -1,4 +1,4 @@
import { GET, Path, QueryParam } from "typescript-rest";
import { GET, Path, PathParam, QueryParam } from "typescript-rest";
import { LogService } from "matrix-js-snippets";
import * as url from "url";
import { ApiError } from "../ApiError";
@ -6,17 +6,43 @@ import * as dns from "dns-then";
import config from "../../config";
import { Netmask } from "netmask";
import * as request from "request";
import { VERSION_DRAFT } from "../controllers/TermsController";
import TermsRecord from "../../db/models/TermsRecord";
import TermsTextRecord from "../../db/models/TermsTextRecord";
interface EmbedCapabilityResponse {
canEmbed: boolean;
}
interface MinimalTermsResponse {
name: string;
text: string;
}
/**
* API for widgets
*/
@Path("/api/v1/dimension/widgets")
export class DimensionWidgetService {
@GET
@Path("/terms/:shortcode/:language/:version")
public async getPolicy(@PathParam("shortcode") shortcode: string, @PathParam("language") language: string, @PathParam("version") version: string): Promise<MinimalTermsResponse> {
if (version === VERSION_DRAFT) {
throw new ApiError(401, "Cannot access draft versions of policies", "M_UNAUTHORIZED");
}
const terms = await TermsRecord.findOne({where: {shortcode, version}, include: [TermsTextRecord]});
if (!terms) throw new ApiError(404, "Not found", "M_NOT_FOUND");
const text = terms.texts.find(t => t.language === language);
return {
name: text.name,
text: text.text,
};
}
@GET
@Path("embeddable")
public async isEmbeddable(@QueryParam("url") checkUrl: string): Promise<EmbedCapabilityResponse> {

View File

@ -117,6 +117,7 @@ import { AdminTermsComponent } from "./admin/terms/terms.component";
import { CKEditorModule } from "@ckeditor/ckeditor5-angular";
import { AdminNewEditTermsComponent } from "./admin/terms/new-edit/new-edit.component";
import { AdminTermsNewEditPublishDialogComponent } from "./admin/terms/new-edit/publish/publish.component";
import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.component";
@NgModule({
imports: [
@ -213,6 +214,7 @@ import { AdminTermsNewEditPublishDialogComponent } from "./admin/terms/new-edit/
AdminTermsComponent,
AdminNewEditTermsComponent,
AdminTermsNewEditPublishDialogComponent,
TermsWidgetWrapperComponent,
// Vendor
],

View File

@ -46,6 +46,7 @@ import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-ex
import { ManagerTestWidgetWrapperComponent } from "./widget-wrappers/manager-test/manager-test.component";
import { AdminTermsComponent } from "./admin/terms/terms.component";
import { AdminNewEditTermsComponent } from "./admin/terms/new-edit/new-edit.component";
import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.component";
const routes: Routes = [
{path: "", component: HomeComponent},
@ -280,6 +281,7 @@ const routes: Routes = [
{
path: "widgets",
children: [
{path: "terms/:shortcode/:lang/:version", component: TermsWidgetWrapperComponent},
{path: "generic", component: GenericWidgetWrapperComponent},
{path: "video", component: VideoWidgetWrapperComponent},
{path: "jitsi", component: JitsiWidgetWrapperComponent},

View File

@ -8,4 +8,9 @@ export interface FE_TermsEditable {
text?: string;
};
};
}
export interface FE_MinimalTerms {
name: string;
text: string;
}

View File

@ -3,6 +3,7 @@ import { AuthedApi } from "../authed-api";
import { FE_Widget } from "../../models/integration";
import { IntegrationsApiService } from "./integrations-api.service";
import { HttpClient } from "@angular/common/http";
import { FE_MinimalTerms } from "../../models/terms";
@Injectable()
export class WidgetApiService extends AuthedApi {
@ -17,4 +18,8 @@ export class WidgetApiService extends AuthedApi {
public isEmbeddable(url: string): Promise<any> { // 200 = success, anything else = error
return this.http.get("/api/v1/dimension/widgets/embeddable", {params: {url: url}}).toPromise();
}
public getTerms(shortcode: string, language: string, version: string): Promise<FE_MinimalTerms> {
return this.http.get<FE_MinimalTerms>(`/api/v1/dimension/widgets/terms/${shortcode}/${language}/${version}`).toPromise();
}
}

View File

@ -0,0 +1,4 @@
<div *ngIf="isLoading">
<my-spinner></my-spinner>
</div>
<div *ngIf="!isLoading" [innerHTML]="html" class="terms"></div>

View File

@ -0,0 +1,9 @@
.terms {
width: 90%;
max-width: 1000px;
margin: 70px auto;
background-color: white;
box-shadow: #7d7d7d 10px 10px 20px;
padding: 20px;
border: 1px solid #909090;
}

View File

@ -0,0 +1,34 @@
import { Component, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { WidgetApiService } from "../../shared/services/integrations/widget-api.service";
import { DomSanitizer, SafeHtml } from "@angular/platform-browser";
import { ToasterService } from "angular2-toaster";
@Component({
selector: "my-terms-widget-wrapper",
templateUrl: "terms.component.html",
styleUrls: ["terms.component.scss"],
})
export class TermsWidgetWrapperComponent implements OnInit {
public isLoading = true;
public html: SafeHtml;
constructor(private activatedRoute: ActivatedRoute,
private sanitizer: DomSanitizer,
private toaster: ToasterService,
private widgetApi: WidgetApiService) {
}
public ngOnInit(): void {
const params: any = this.activatedRoute.snapshot.params;
this.widgetApi.getTerms(params.shortcode, params.lang, params.version).then(terms => {
this.html = this.sanitizer.bypassSecurityTrustHtml(terms.text);
this.isLoading = false;
}).catch(err => {
console.error(err);
this.toaster.pop("error", "Error loading policy");
});
}
}