mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-10-01 01:05:53 -04:00
Support editing and publishing terms
This commit is contained in:
parent
b9e616639e
commit
1c8b523114
@ -1,4 +1,4 @@
|
|||||||
import { GET, Path, PathParam, POST, Security } from "typescript-rest";
|
import { GET, Path, PathParam, POST, PUT, Security } from "typescript-rest";
|
||||||
import TermsController, { ITerms } from "../controllers/TermsController";
|
import TermsController, { ITerms } from "../controllers/TermsController";
|
||||||
import { AutoWired, Inject } from "typescript-ioc/es6";
|
import { AutoWired, Inject } from "typescript-ioc/es6";
|
||||||
import { ROLE_MSC_ADMIN, ROLE_MSC_USER } from "../security/MSCSecurity";
|
import { ROLE_MSC_ADMIN, ROLE_MSC_USER } from "../security/MSCSecurity";
|
||||||
@ -39,4 +39,18 @@ export class AdminTermsService {
|
|||||||
public async createDraftPolicy(@PathParam("shortcode") shortcode: string, request: CreatePolicyObject): Promise<ITerms> {
|
public async createDraftPolicy(@PathParam("shortcode") shortcode: string, request: CreatePolicyObject): Promise<ITerms> {
|
||||||
return this.termsController.createDraftPolicy(request.name, shortcode, request.text, request.url);
|
return this.termsController.createDraftPolicy(request.name, shortcode, request.text, request.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path(":shortcode/publish/:version")
|
||||||
|
@Security([ROLE_MSC_USER, ROLE_MSC_ADMIN])
|
||||||
|
public async publishDraftPolicy(@PathParam("shortcode") shortcode: string, @PathParam("version") version: string): Promise<ITerms> {
|
||||||
|
return this.termsController.publishPolicy(shortcode, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path(":shortcode/:version")
|
||||||
|
@Security([ROLE_MSC_USER, ROLE_MSC_ADMIN])
|
||||||
|
public async updatePolicy(@PathParam("shortcode") shortcode: string, @PathParam("version") version: string, request: CreatePolicyObject): Promise<ITerms> {
|
||||||
|
return this.termsController.updatePolicy(request.name, shortcode, version, request.text, request.url);
|
||||||
|
}
|
||||||
}
|
}
|
@ -68,6 +68,32 @@ export default class TermsController {
|
|||||||
return this.mapPolicy(true, terms);
|
return this.mapPolicy(true, terms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async updatePolicy(name: string, shortcode: string, version: string, text: string, url: string): Promise<ITerms> {
|
||||||
|
const terms = await TermsRecord.findOne({where: {shortcode, version}, include: [TermsTextRecord]});
|
||||||
|
const termsText = terms.texts.find(e => e.language === "en");
|
||||||
|
|
||||||
|
termsText.url = url;
|
||||||
|
termsText.text = text;
|
||||||
|
termsText.name = name;
|
||||||
|
|
||||||
|
await termsText.save();
|
||||||
|
|
||||||
|
return this.mapPolicy(true, terms);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async publishPolicy(shortcode: string, targetVersion: string): Promise<ITerms> {
|
||||||
|
const terms = await TermsRecord.findOne({
|
||||||
|
where: {shortcode, version: VERSION_DRAFT},
|
||||||
|
include: [TermsTextRecord],
|
||||||
|
});
|
||||||
|
if (!terms) throw new Error("Missing terms");
|
||||||
|
|
||||||
|
terms.version = targetVersion;
|
||||||
|
await terms.save();
|
||||||
|
|
||||||
|
return this.mapPolicy(true, terms);
|
||||||
|
}
|
||||||
|
|
||||||
private mapPolicy(withText: boolean, policy: TermsRecord): ITerms {
|
private mapPolicy(withText: boolean, policy: TermsRecord): ITerms {
|
||||||
const languages = {};
|
const languages = {};
|
||||||
policy.texts.forEach(pt => languages[pt.language] = {
|
policy.texts.forEach(pt => languages[pt.language] = {
|
||||||
|
@ -31,9 +31,15 @@
|
|||||||
<!-- </my-ibox>-->
|
<!-- </my-ibox>-->
|
||||||
<my-ibox [hasTitle]="false">
|
<my-ibox [hasTitle]="false">
|
||||||
<div class="my-ibox-content buttons">
|
<div class="my-ibox-content buttons">
|
||||||
<button type="button" (click)="create()" title="save" class="btn btn-primary btn-sm">
|
<button type="button" (click)="create()" title="save" class="btn btn-primary btn-sm" *ngIf="!isEditing">
|
||||||
<i class="far fa-save"></i> Create draft
|
<i class="far fa-save"></i> Create draft
|
||||||
</button>
|
</button>
|
||||||
|
<button type="button" (click)="create()" title="save" class="btn btn-primary btn-sm" *ngIf="isEditing">
|
||||||
|
<i class="far fa-save"></i> Save draft
|
||||||
|
</button>
|
||||||
|
<button type="button" (click)="publish()" title="save" class="btn btn-primary btn-sm" *ngIf="isEditing">
|
||||||
|
<i class="fas fa-upload"></i> Publish
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</my-ibox>
|
</my-ibox>
|
||||||
</div>
|
</div>
|
213
web/app/admin/terms/new-edit/new-edit.component.ts
Normal file
213
web/app/admin/terms/new-edit/new-edit.component.ts
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { ToasterService } from "angular2-toaster";
|
||||||
|
import { AdminTermsApiService } from "../../../shared/services/admin/admin-terms-api.service";
|
||||||
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
|
||||||
|
import ISO6391 from "iso-639-1";
|
||||||
|
import { Modal, overlayConfigFactory } from "ngx-modialog";
|
||||||
|
import {
|
||||||
|
AdminTermsNewEditPublishDialogComponent,
|
||||||
|
AdminTermsNewEditPublishDialogContext
|
||||||
|
} from "./publish/publish.component";
|
||||||
|
|
||||||
|
interface ILanguage {
|
||||||
|
name: string,
|
||||||
|
text: string,
|
||||||
|
langName: string,
|
||||||
|
url: string,
|
||||||
|
isExternal: boolean,
|
||||||
|
externalUrl: string,
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "./new-edit.component.html",
|
||||||
|
styleUrls: ["./new-edit.component.scss"],
|
||||||
|
})
|
||||||
|
export class AdminNewEditTermsComponent implements OnInit {
|
||||||
|
|
||||||
|
// TODO: Multiple language support
|
||||||
|
// TODO: Support external URLs
|
||||||
|
|
||||||
|
private shortcode: string;
|
||||||
|
|
||||||
|
public Editor = ClassicEditor;
|
||||||
|
|
||||||
|
public isLoading = true;
|
||||||
|
public isUpdating = false;
|
||||||
|
public takenShortcodes: string[];
|
||||||
|
public chosenLanguage: string = ISO6391.getAllCodes()[0];
|
||||||
|
public languages: {
|
||||||
|
[languageCode: string]: ILanguage;
|
||||||
|
} = {
|
||||||
|
"en": {
|
||||||
|
name: "",
|
||||||
|
text: "",
|
||||||
|
langName: "English",
|
||||||
|
url: "", // TODO: Calculate
|
||||||
|
isExternal: false,
|
||||||
|
externalUrl: "",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
public isEditing = false;
|
||||||
|
|
||||||
|
public get chosenLanguageCodes(): string[] {
|
||||||
|
return Object.keys(this.languages);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get availableLanguages(): { name: string, code: string }[] {
|
||||||
|
return ISO6391.getAllCodes()
|
||||||
|
.filter(c => !this.chosenLanguageCodes.includes(c))
|
||||||
|
.map(c => {
|
||||||
|
return {code: c, name: ISO6391.getName(c)};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private adminTerms: AdminTermsApiService,
|
||||||
|
private toaster: ToasterService,
|
||||||
|
private router: Router,
|
||||||
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private modal: Modal) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit() {
|
||||||
|
let params = this.activatedRoute.snapshot.params;
|
||||||
|
this.shortcode = params.shortcode;
|
||||||
|
this.isEditing = !!this.shortcode;
|
||||||
|
|
||||||
|
if (this.isEditing) {
|
||||||
|
this.adminTerms.getDraft(this.shortcode).then(policy => {
|
||||||
|
this.shortcode = policy.shortcode;
|
||||||
|
this.languages = {};
|
||||||
|
|
||||||
|
for (const code in policy.languages) {
|
||||||
|
const i18nPolicy = policy.languages[code];
|
||||||
|
this.languages[code] = {
|
||||||
|
text: i18nPolicy.text,
|
||||||
|
url: i18nPolicy.url,
|
||||||
|
name: i18nPolicy.name,
|
||||||
|
isExternal: false,
|
||||||
|
langName: ISO6391.getName(code),
|
||||||
|
externalUrl: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isLoading = false;
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
this.toaster.pop("error", "Failed to load policy");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.adminTerms.getAllPolicies().then(policies => {
|
||||||
|
this.takenShortcodes = policies.map(p => p.shortcode);
|
||||||
|
this.isLoading = false;
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
this.toaster.pop("error", "Failed to load policies");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async publish() {
|
||||||
|
this.isUpdating = true;
|
||||||
|
|
||||||
|
await this.adminTerms.updateDraft(this.shortcode, {
|
||||||
|
name: this.languages['en'].name,
|
||||||
|
text: this.languages['en'].text,
|
||||||
|
url: `${window.location.origin}/widgets/terms/${this.shortcode}/en/draft`,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
this.modal.open(AdminTermsNewEditPublishDialogComponent, overlayConfigFactory({
|
||||||
|
isBlocking: true,
|
||||||
|
size: 'sm',
|
||||||
|
}, AdminTermsNewEditPublishDialogContext)).result.then(async (val) => {
|
||||||
|
if (!val) return; // closed without publish
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Change the URL of the draft
|
||||||
|
// TODO: Don't track URLs for drafts
|
||||||
|
await this.adminTerms.updateDraft(this.shortcode, {
|
||||||
|
name: this.languages['en'].name,
|
||||||
|
text: this.languages['en'].text,
|
||||||
|
url: `${window.location.origin}/widgets/terms/${this.shortcode}/en/${val}`,
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.adminTerms.publishDraft(this.shortcode, val);
|
||||||
|
this.toaster.pop("success", "Policy published");
|
||||||
|
this.router.navigate(["../.."], {relativeTo: this.activatedRoute});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
this.toaster.pop("error", "Error publishing policy");
|
||||||
|
this.isUpdating = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async create() {
|
||||||
|
for (const languageCode in this.languages) {
|
||||||
|
if (this.languages[languageCode].name.trim().length <= 0) {
|
||||||
|
this.toaster.pop("warning", "Please enter a name for all policies");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.languages[languageCode].text.trim().length <= 0) {
|
||||||
|
this.toaster.pop("warning", "Please enter text for all policies");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isUpdating = true;
|
||||||
|
|
||||||
|
if (this.isEditing) {
|
||||||
|
try {
|
||||||
|
await this.adminTerms.updateDraft(this.shortcode, {
|
||||||
|
name: this.languages['en'].name,
|
||||||
|
text: this.languages['en'].text,
|
||||||
|
url: `${window.location.origin}/widgets/terms/${this.shortcode}/en/draft`,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.toaster.pop("success", "Draft saved");
|
||||||
|
this.router.navigate(["../.."], {relativeTo: this.activatedRoute});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
this.toaster.pop("error", "Error saving policy");
|
||||||
|
this.isUpdating = false;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const startShortcode = this.languages['en'].name.toLowerCase().replace(/[^a-z0-9]/gi, '_');
|
||||||
|
let shortcode = startShortcode;
|
||||||
|
let i = 0;
|
||||||
|
while (this.takenShortcodes.includes(shortcode)) {
|
||||||
|
shortcode = `${startShortcode}_${++i}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.adminTerms.createDraft(shortcode, {
|
||||||
|
name: this.languages['en'].name,
|
||||||
|
text: this.languages['en'].text,
|
||||||
|
url: `${window.location.origin}/widgets/terms/${shortcode}/en/draft`,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.toaster.pop("success", "Draft created");
|
||||||
|
this.router.navigate([".."], {relativeTo: this.activatedRoute});
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
this.toaster.pop("error", "Error creating document");
|
||||||
|
this.isUpdating = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public addLanguage() {
|
||||||
|
this.languages[this.chosenLanguage] = {
|
||||||
|
name: "",
|
||||||
|
text: "",
|
||||||
|
url: "", // TODO: Calculate
|
||||||
|
isExternal: false,
|
||||||
|
externalUrl: "",
|
||||||
|
langName: ISO6391.getName(this.chosenLanguage),
|
||||||
|
};
|
||||||
|
this.chosenLanguage = this.availableLanguages[0].code;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
web/app/admin/terms/new-edit/publish/publish.component.html
Normal file
20
web/app/admin/terms/new-edit/publish/publish.component.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<div class="dialog">
|
||||||
|
<div class="dialog-header">
|
||||||
|
<h4>Publish policy</h4>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-content">
|
||||||
|
<label class="label-block">
|
||||||
|
Version number
|
||||||
|
<span class="text-muted ">The version number of this policy</span>
|
||||||
|
<input type="text" class="form-control" placeholder="eg: 1.1.0" [(ngModel)]="version"/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<button type="button" (click)="publish()" title="close" class="btn btn-primary btn-sm">
|
||||||
|
<i class="fas fa-upload"></i> Publish
|
||||||
|
</button>
|
||||||
|
<button type="button" (click)="dialog.close()" title="save" class="btn btn-secondary btn-sm">
|
||||||
|
<i class="far fa-times-circle"></i> Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,3 @@
|
|||||||
|
button {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
27
web/app/admin/terms/new-edit/publish/publish.component.ts
Normal file
27
web/app/admin/terms/new-edit/publish/publish.component.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { Component } from "@angular/core";
|
||||||
|
import { DialogRef, ModalComponent } from "ngx-modialog";
|
||||||
|
import { BSModalContext } from "ngx-modialog/plugins/bootstrap";
|
||||||
|
import { ToasterService } from "angular2-toaster";
|
||||||
|
|
||||||
|
export class AdminTermsNewEditPublishDialogContext extends BSModalContext {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "./publish.component.html",
|
||||||
|
styleUrls: ["./publish.component.scss"],
|
||||||
|
})
|
||||||
|
export class AdminTermsNewEditPublishDialogComponent implements ModalComponent<AdminTermsNewEditPublishDialogContext> {
|
||||||
|
|
||||||
|
public version: string;
|
||||||
|
|
||||||
|
constructor(public dialog: DialogRef<AdminTermsNewEditPublishDialogContext>, private toaster: ToasterService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public publish() {
|
||||||
|
if (!this.version || !this.version.trim()) {
|
||||||
|
this.toaster.pop("warning", "Please enter a version number");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.dialog.close(this.version);
|
||||||
|
}
|
||||||
|
}
|
@ -1,122 +0,0 @@
|
|||||||
import { Component, OnInit } from "@angular/core";
|
|
||||||
import { ToasterService } from "angular2-toaster";
|
|
||||||
import { AdminTermsApiService } from "../../../shared/services/admin/admin-terms-api.service";
|
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
|
||||||
import * as ClassicEditor from '@ckeditor/ckeditor5-build-classic';
|
|
||||||
import ISO6391 from "iso-639-1";
|
|
||||||
|
|
||||||
interface ILanguage {
|
|
||||||
name: string,
|
|
||||||
text: string,
|
|
||||||
langName: string,
|
|
||||||
url: string,
|
|
||||||
isExternal: boolean,
|
|
||||||
externalUrl: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
templateUrl: "./new.component.html",
|
|
||||||
styleUrls: ["./new.component.scss"],
|
|
||||||
})
|
|
||||||
export class AdminNewTermsComponent implements OnInit {
|
|
||||||
|
|
||||||
// TODO: Multiple language support
|
|
||||||
// TODO: Support external URLs
|
|
||||||
|
|
||||||
public Editor = ClassicEditor;
|
|
||||||
|
|
||||||
public isLoading = true;
|
|
||||||
public isUpdating = false;
|
|
||||||
public takenShortcodes: string[];
|
|
||||||
public chosenLanguage: string = ISO6391.getAllCodes()[0];
|
|
||||||
public languages: {
|
|
||||||
[languageCode: string]: ILanguage;
|
|
||||||
} = {
|
|
||||||
"en": {
|
|
||||||
name: "",
|
|
||||||
text: "",
|
|
||||||
langName: "English",
|
|
||||||
url: "", // TODO: Calculate
|
|
||||||
isExternal: false,
|
|
||||||
externalUrl: "",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
public get chosenLanguageCodes(): string[] {
|
|
||||||
return Object.keys(this.languages);
|
|
||||||
}
|
|
||||||
|
|
||||||
public get availableLanguages(): { name: string, code: string }[] {
|
|
||||||
return ISO6391.getAllCodes()
|
|
||||||
.filter(c => !this.chosenLanguageCodes.includes(c))
|
|
||||||
.map(c => {
|
|
||||||
return {code: c, name: ISO6391.getName(c)};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(private adminTerms: AdminTermsApiService,
|
|
||||||
private toaster: ToasterService,
|
|
||||||
private router: Router,
|
|
||||||
private activatedRoute: ActivatedRoute) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public ngOnInit() {
|
|
||||||
this.adminTerms.getAllPolicies().then(policies => {
|
|
||||||
this.takenShortcodes = policies.map(p => p.shortcode);
|
|
||||||
this.isLoading = false;
|
|
||||||
}).catch(err => {
|
|
||||||
console.error(err);
|
|
||||||
this.toaster.pop("error", "Failed to load policies");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async create() {
|
|
||||||
for (const languageCode in this.languages) {
|
|
||||||
if (this.languages[languageCode].name.trim().length <= 0) {
|
|
||||||
this.toaster.pop("warning", "Please enter a name for all policies");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (this.languages[languageCode].text.trim().length <= 0) {
|
|
||||||
this.toaster.pop("warning", "Please enter text for all policies");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isUpdating = true;
|
|
||||||
|
|
||||||
const startShortcode = this.languages['en'].name.toLowerCase().replace(/[^a-z0-9]/gi, '_');
|
|
||||||
let shortcode = startShortcode;
|
|
||||||
let i = 0;
|
|
||||||
while (this.takenShortcodes.includes(shortcode)) {
|
|
||||||
shortcode = `${startShortcode}_${++i}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.adminTerms.createDraft(shortcode, {
|
|
||||||
name: this.languages['en'].name,
|
|
||||||
text: this.languages['en'].text,
|
|
||||||
url: `${window.location.origin}/terms/${shortcode}/en/draft`,
|
|
||||||
});
|
|
||||||
|
|
||||||
this.toaster.pop("success", "Draft created");
|
|
||||||
this.router.navigate([".."], {relativeTo: this.activatedRoute});
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
this.toaster.pop("error", "Error creating document");
|
|
||||||
this.isUpdating = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public addLanguage() {
|
|
||||||
this.languages[this.chosenLanguage] = {
|
|
||||||
name: "",
|
|
||||||
text: "",
|
|
||||||
url: "", // TODO: Calculate
|
|
||||||
isExternal: false,
|
|
||||||
externalUrl: "",
|
|
||||||
langName: ISO6391.getName(this.chosenLanguage),
|
|
||||||
};
|
|
||||||
this.chosenLanguage = this.availableLanguages[0].code;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -28,7 +28,7 @@
|
|||||||
<td>{{ policy.version }}</td>
|
<td>{{ policy.version }}</td>
|
||||||
|
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<span class="previewButton" title="edit draft" *ngIf="policy.version == 'draft'">
|
<span class="editButton" [routerLink]="['edit', policy.shortcode]" title="edit draft" *ngIf="policy.version == 'draft'">
|
||||||
<i class="fa fa-pencil-alt"></i>
|
<i class="fa fa-pencil-alt"></i>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
.editButton {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
@ -10,6 +10,9 @@ import { ActivatedRoute, Router } from "@angular/router";
|
|||||||
})
|
})
|
||||||
export class AdminTermsComponent implements OnInit {
|
export class AdminTermsComponent implements OnInit {
|
||||||
|
|
||||||
|
// TODO: "New draft" per policy button
|
||||||
|
// TODO: Delete button
|
||||||
|
|
||||||
public isLoading = true;
|
public isLoading = true;
|
||||||
public policies: FE_TermsEditable[];
|
public policies: FE_TermsEditable[];
|
||||||
|
|
||||||
|
@ -114,8 +114,9 @@ import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-ex
|
|||||||
import { ManagerTestWidgetWrapperComponent } from "./widget-wrappers/manager-test/manager-test.component";
|
import { ManagerTestWidgetWrapperComponent } from "./widget-wrappers/manager-test/manager-test.component";
|
||||||
import { AdminTermsApiService } from "./shared/services/admin/admin-terms-api.service";
|
import { AdminTermsApiService } from "./shared/services/admin/admin-terms-api.service";
|
||||||
import { AdminTermsComponent } from "./admin/terms/terms.component";
|
import { AdminTermsComponent } from "./admin/terms/terms.component";
|
||||||
import { AdminNewTermsComponent } from "./admin/terms/new/new.component";
|
|
||||||
import { CKEditorModule } from "@ckeditor/ckeditor5-angular";
|
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";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -210,7 +211,8 @@ import { CKEditorModule } from "@ckeditor/ckeditor5-angular";
|
|||||||
ReauthExampleWidgetWrapperComponent,
|
ReauthExampleWidgetWrapperComponent,
|
||||||
ManagerTestWidgetWrapperComponent,
|
ManagerTestWidgetWrapperComponent,
|
||||||
AdminTermsComponent,
|
AdminTermsComponent,
|
||||||
AdminNewTermsComponent,
|
AdminNewEditTermsComponent,
|
||||||
|
AdminTermsNewEditPublishDialogComponent,
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
],
|
],
|
||||||
@ -266,6 +268,7 @@ import { CKEditorModule } from "@ckeditor/ckeditor5-angular";
|
|||||||
AdminAddCustomBotComponent,
|
AdminAddCustomBotComponent,
|
||||||
AdminSlackBridgeManageSelfhostedComponent,
|
AdminSlackBridgeManageSelfhostedComponent,
|
||||||
AdminLogoutConfirmationDialogComponent,
|
AdminLogoutConfirmationDialogComponent,
|
||||||
|
AdminTermsNewEditPublishDialogComponent,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
|
@ -45,7 +45,7 @@ import { SlackBridgeConfigComponent } from "./configs/bridge/slack/slack.bridge.
|
|||||||
import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-example/reauth-example.component";
|
import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-example/reauth-example.component";
|
||||||
import { ManagerTestWidgetWrapperComponent } from "./widget-wrappers/manager-test/manager-test.component";
|
import { ManagerTestWidgetWrapperComponent } from "./widget-wrappers/manager-test/manager-test.component";
|
||||||
import { AdminTermsComponent } from "./admin/terms/terms.component";
|
import { AdminTermsComponent } from "./admin/terms/terms.component";
|
||||||
import { AdminNewTermsComponent } from "./admin/terms/new/new.component";
|
import { AdminNewEditTermsComponent } from "./admin/terms/new-edit/new-edit.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: "", component: HomeComponent},
|
{path: "", component: HomeComponent},
|
||||||
@ -158,9 +158,14 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "new",
|
path: "new",
|
||||||
component: AdminNewTermsComponent,
|
component: AdminNewEditTermsComponent,
|
||||||
data: {breadcrumb: "New policy", name: "New policy"},
|
data: {breadcrumb: "New policy", name: "New policy"},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "edit/:shortcode",
|
||||||
|
component: AdminNewEditTermsComponent,
|
||||||
|
data: {breadcrumb: "Edit policy", name: "Edit policy"},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -16,4 +16,16 @@ export class AdminTermsApiService extends AuthedApi {
|
|||||||
public createDraft(shortcode: string, policyInfo: { name: string, text: string, url: string }): Promise<FE_TermsEditable> {
|
public createDraft(shortcode: string, policyInfo: { name: string, text: string, url: string }): Promise<FE_TermsEditable> {
|
||||||
return this.authedPost<FE_TermsEditable>(`/api/v1/dimension/admin/terms/${shortcode}/draft`, policyInfo).toPromise();
|
return this.authedPost<FE_TermsEditable>(`/api/v1/dimension/admin/terms/${shortcode}/draft`, policyInfo).toPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getDraft(shortcode: string): Promise<FE_TermsEditable> {
|
||||||
|
return this.authedGet<FE_TermsEditable>(`/api/v1/dimension/admin/terms/${shortcode}/draft`).toPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateDraft(shortcode: string, policyInfo: { name: string, text: string, url: string }): Promise<FE_TermsEditable> {
|
||||||
|
return this.authedPut<FE_TermsEditable>(`/api/v1/dimension/admin/terms/${shortcode}/draft`, policyInfo).toPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
public publishDraft(shortcode: string, newVersion: string): Promise<FE_TermsEditable> {
|
||||||
|
return this.authedPost<FE_TermsEditable>(`/api/v1/dimension/admin/terms/${shortcode}/publish/${newVersion}`).toPromise();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,12 @@ export class AuthedApi {
|
|||||||
return this.http.post<T>(url, body, opts);
|
return this.http.post<T>(url, body, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected authedPut<T>(url: string, body?: any): Observable<T> {
|
||||||
|
if (!body) body = {};
|
||||||
|
const opts = this.fillAuthOptions(null, null, null);
|
||||||
|
return this.http.put<T>(url, body, opts);
|
||||||
|
}
|
||||||
|
|
||||||
protected authedDelete<T>(url: string, qs?: any): Observable<T> {
|
protected authedDelete<T>(url: string, qs?: any): Observable<T> {
|
||||||
const opts = this.fillAuthOptions(null, qs, null);
|
const opts = this.fillAuthOptions(null, qs, null);
|
||||||
return this.http.delete<T>(url, opts);
|
return this.http.delete<T>(url, opts);
|
||||||
|
Loading…
Reference in New Issue
Block a user