diff --git a/package-lock.json b/package-lock.json
index d072a83..c7cd652 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -912,6 +912,21 @@
"to-fast-properties": "^2.0.0"
}
},
+ "@ckeditor/ckeditor5-angular": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-angular/-/ckeditor5-angular-1.1.0.tgz",
+ "integrity": "sha512-6b9NX/PhFuQKo/mR0tSpCVNGU1fhg1Y8ju5OBWxCPpIbdDZIIoqjHlhWL76EmfztteouYLACsnfrnqVQGC0utA==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.9.0"
+ }
+ },
+ "@ckeditor/ckeditor5-build-classic": {
+ "version": "12.2.0",
+ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-build-classic/-/ckeditor5-build-classic-12.2.0.tgz",
+ "integrity": "sha512-En64jC5ImZoa+XLa2JrZYCKpq2iNXhdf17xgmpJoAXp+m36EqSHd6/4x0XT/pjrZSDxrcLUZxyZJlQCRtSaeHw==",
+ "dev": true
+ },
"@fortawesome/fontawesome": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome/-/fontawesome-1.1.8.tgz",
@@ -6139,6 +6154,12 @@
"integrity": "sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ=",
"dev": true
},
+ "iso-639-1": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/iso-639-1/-/iso-639-1-2.0.5.tgz",
+ "integrity": "sha512-2TcJ8AcsqM4AXLi92eFZX3xa7X6Eno/chq9yOR0AvSgb15Smmoh1miXyYJVWCkSmbzDimds3Ix2M4efhnOuxOg==",
+ "dev": true
+ },
"isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
diff --git a/package.json b/package.json
index 26044eb..65e54bf 100644
--- a/package.json
+++ b/package.json
@@ -70,6 +70,8 @@
"@angularclass/hmr-loader": "^3.0.4",
"@babel/core": "^7.4.5",
"@babel/preset-env": "^7.4.5",
+ "@ckeditor/ckeditor5-angular": "^1.1.0",
+ "@ckeditor/ckeditor5-build-classic": "^12.2.0",
"@fortawesome/fontawesome": "^1.1.8",
"@fortawesome/fontawesome-free-brands": "^5.0.13",
"@fortawesome/fontawesome-free-regular": "^5.0.13",
@@ -92,6 +94,7 @@
"goby": "^1.1.2",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
+ "iso-639-1": "^2.0.5",
"jquery": "^3.4.1",
"json-loader": "^0.5.7",
"mini-css-extract-plugin": "^0.7.0",
diff --git a/web/app/admin/terms/new/new.component.html b/web/app/admin/terms/new/new.component.html
new file mode 100644
index 0000000..6460c0d
--- /dev/null
+++ b/web/app/admin/terms/new/new.component.html
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
English version
+
+
+
+
+
+
+
+
+
{{languages[code].langName}} version
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web/app/admin/terms/new/new.component.scss b/web/app/admin/terms/new/new.component.scss
new file mode 100644
index 0000000..d469ccf
--- /dev/null
+++ b/web/app/admin/terms/new/new.component.scss
@@ -0,0 +1,8 @@
+.buttons button {
+ margin-right: 5px;
+}
+
+.buttons select {
+ max-width: 200px;
+ margin-bottom: 5px;
+}
\ No newline at end of file
diff --git a/web/app/admin/terms/new/new.component.ts b/web/app/admin/terms/new/new.component.ts
new file mode 100644
index 0000000..2ffd22e
--- /dev/null
+++ b/web/app/admin/terms/new/new.component.ts
@@ -0,0 +1,95 @@
+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";
+
+@Component({
+ templateUrl: "./new.component.html",
+ styleUrls: ["./new.component.scss"],
+})
+export class AdminNewTermsComponent implements OnInit {
+
+ public Editor = ClassicEditor;
+
+ public isLoading = true;
+ public isUpdating = false;
+ public shortcode: string;
+ public takenShortcodes: string[];
+ public chosenLanguage: string = ISO6391.getAllCodes()[0];
+ public languages: {
+ [languageCode: string]: {
+ name: string,
+ text: string,
+ langName: string,
+ url: string,
+ isExternal: boolean,
+ externalUrl: string,
+ }
+ } = {
+ "en": {
+ name: "",
+ text: "",
+ langName: "English",
+ url: "", // TODO: Calculate
+ isExternal: false,
+ externalUrl: "",
+ },
+ };
+
+ public get otherLanguageCodes(): string[] {
+ return Object.keys(this.languages).filter(c => c !== "en");
+ }
+
+ public get availableLanguages(): { name: string, code: string }[] {
+ return ISO6391.getAllCodes()
+ .filter(c => !this.otherLanguageCodes.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 onNameKeyUp() {
+ 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}`;
+ }
+ this.shortcode = shortcode;
+ }
+
+ public create() {
+ this.router.navigate([".."], {relativeTo: this.activatedRoute});
+ }
+
+ 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;
+ }
+
+}
diff --git a/web/app/admin/terms/terms.component.html b/web/app/admin/terms/terms.component.html
index e2dd1e3..eb841c7 100644
--- a/web/app/admin/terms/terms.component.html
+++ b/web/app/admin/terms/terms.component.html
@@ -15,7 +15,7 @@
Policy Name |
- Published Version |
+ Version |
Actions |
@@ -35,6 +35,9 @@
+
\ No newline at end of file
diff --git a/web/app/admin/terms/terms.component.ts b/web/app/admin/terms/terms.component.ts
index bbd312c..ef16e92 100644
--- a/web/app/admin/terms/terms.component.ts
+++ b/web/app/admin/terms/terms.component.ts
@@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core";
import { ToasterService } from "angular2-toaster";
import { FE_TermsEditable } from "../../shared/models/terms";
import { AdminTermsApiService } from "../../shared/services/admin/admin-terms-api.service";
+import { ActivatedRoute, Router } from "@angular/router";
@Component({
templateUrl: "./terms.component.html",
@@ -13,12 +14,17 @@ export class AdminTermsComponent implements OnInit {
public policies: FE_TermsEditable[];
constructor(private adminTerms: AdminTermsApiService,
- private toaster: ToasterService) {
+ private toaster: ToasterService,
+ private router: Router,
+ private activatedRoute: ActivatedRoute) {
}
public ngOnInit() {
this.adminTerms.getAllPolicies().then(policies => {
- this.policies = policies;
+ this.policies = [
+ ...policies.filter(p => p.version === "draft"),
+ ...policies.filter(p => p.version !== "draft"),
+ ];
this.isLoading = false;
}).catch(err => {
console.error(err);
@@ -26,4 +32,8 @@ export class AdminTermsComponent implements OnInit {
});
}
+ public createPolicy() {
+ this.router.navigate(["new"], {relativeTo: this.activatedRoute});
+ }
+
}
diff --git a/web/app/app.module.ts b/web/app/app.module.ts
index 7c2aa81..cb301f9 100644
--- a/web/app/app.module.ts
+++ b/web/app/app.module.ts
@@ -114,6 +114,8 @@ import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-ex
import { ManagerTestWidgetWrapperComponent } from "./widget-wrappers/manager-test/manager-test.component";
import { AdminTermsApiService } from "./shared/services/admin/admin-terms-api.service";
import { AdminTermsComponent } from "./admin/terms/terms.component";
+import { AdminNewTermsComponent } from "./admin/terms/new/new.component";
+import { CKEditorModule } from "@ckeditor/ckeditor5-angular";
@NgModule({
imports: [
@@ -128,6 +130,7 @@ import { AdminTermsComponent } from "./admin/terms/terms.component";
ModalModule.forRoot(),
BootstrapModalModule,
BreadcrumbsModule,
+ CKEditorModule,
],
declarations: [
AppComponent,
@@ -207,6 +210,7 @@ import { AdminTermsComponent } from "./admin/terms/terms.component";
ReauthExampleWidgetWrapperComponent,
ManagerTestWidgetWrapperComponent,
AdminTermsComponent,
+ AdminNewTermsComponent,
// Vendor
],
diff --git a/web/app/app.routing.ts b/web/app/app.routing.ts
index 8fa3bea..4d629f7 100644
--- a/web/app/app.routing.ts
+++ b/web/app/app.routing.ts
@@ -45,6 +45,7 @@ import { SlackBridgeConfigComponent } from "./configs/bridge/slack/slack.bridge.
import { ReauthExampleWidgetWrapperComponent } from "./widget-wrappers/reauth-example/reauth-example.component";
import { ManagerTestWidgetWrapperComponent } from "./widget-wrappers/manager-test/manager-test.component";
import { AdminTermsComponent } from "./admin/terms/terms.component";
+import { AdminNewTermsComponent } from "./admin/terms/new/new.component";
const routes: Routes = [
{path: "", component: HomeComponent},
@@ -155,6 +156,11 @@ const routes: Routes = [
path: "",
component: AdminTermsComponent,
},
+ {
+ path: "new",
+ component: AdminNewTermsComponent,
+ data: {breadcrumb: "New policy", name: "New policy"},
+ },
],
},
],
diff --git a/web/app/elements/ibox/ibox.component.html b/web/app/elements/ibox/ibox.component.html
index 990e203..ce82a88 100644
--- a/web/app/elements/ibox/ibox.component.html
+++ b/web/app/elements/ibox/ibox.component.html
@@ -1,6 +1,7 @@
+ [ngClass]="[isCollapsible ? 'ibox-title-collapsible' : '']"
+ *ngIf="hasTitle">
{{ boxTitle }}
diff --git a/web/app/elements/ibox/ibox.component.ts b/web/app/elements/ibox/ibox.component.ts
index c705eb4..a16f0ba 100644
--- a/web/app/elements/ibox/ibox.component.ts
+++ b/web/app/elements/ibox/ibox.component.ts
@@ -11,6 +11,7 @@ export class IboxComponent implements OnInit {
@Input() boxTitle: string;
@Input() isCollapsible: boolean;
@Input() defaultCollapsed: boolean;
+ @Input() hasTitle = true;
public collapsed = false;
diff --git a/web/app/shared/SessionStorage.ts b/web/app/shared/SessionStorage.ts
index e03477d..ce77dcf 100644
--- a/web/app/shared/SessionStorage.ts
+++ b/web/app/shared/SessionStorage.ts
@@ -2,7 +2,21 @@ import { FE_Integration } from "./models/integration";
export class SessionStorage {
- public static scalarToken: string;
+ private static _scalarToken: string;
+
+ public static get scalarToken(): string {
+ if (this._scalarToken) return this._scalarToken;
+ this.scalarToken = localStorage.getItem("dimension_scalar_token");
+ return this._scalarToken;
+ }
+
+ public static set scalarToken(val: string) {
+ this._scalarToken = val;
+ if (val) {
+ localStorage.setItem("dimension_scalar_token", val);
+ }
+ }
+
public static userId: string;
public static roomId: string;
public static isAdmin: boolean;