mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-09-29 20:25:58 +00:00
Early mockup of admin management for policies
This commit is contained in:
parent
e8d876b5d2
commit
77d34197c9
21
package-lock.json
generated
21
package-lock.json
generated
@ -912,6 +912,21 @@
|
|||||||
"to-fast-properties": "^2.0.0"
|
"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": {
|
"@fortawesome/fontawesome": {
|
||||||
"version": "1.1.8",
|
"version": "1.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome/-/fontawesome-1.1.8.tgz",
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome/-/fontawesome-1.1.8.tgz",
|
||||||
@ -6139,6 +6154,12 @@
|
|||||||
"integrity": "sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ=",
|
"integrity": "sha1-ojR7o2DeGeM9D/1ZD933dVy/LmQ=",
|
||||||
"dev": true
|
"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": {
|
"isobject": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||||
|
@ -70,6 +70,8 @@
|
|||||||
"@angularclass/hmr-loader": "^3.0.4",
|
"@angularclass/hmr-loader": "^3.0.4",
|
||||||
"@babel/core": "^7.4.5",
|
"@babel/core": "^7.4.5",
|
||||||
"@babel/preset-env": "^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": "^1.1.8",
|
||||||
"@fortawesome/fontawesome-free-brands": "^5.0.13",
|
"@fortawesome/fontawesome-free-brands": "^5.0.13",
|
||||||
"@fortawesome/fontawesome-free-regular": "^5.0.13",
|
"@fortawesome/fontawesome-free-regular": "^5.0.13",
|
||||||
@ -92,6 +94,7 @@
|
|||||||
"goby": "^1.1.2",
|
"goby": "^1.1.2",
|
||||||
"html-loader": "^0.5.5",
|
"html-loader": "^0.5.5",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
|
"iso-639-1": "^2.0.5",
|
||||||
"jquery": "^3.4.1",
|
"jquery": "^3.4.1",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"mini-css-extract-plugin": "^0.7.0",
|
"mini-css-extract-plugin": "^0.7.0",
|
||||||
|
70
web/app/admin/terms/new/new.component.html
Normal file
70
web/app/admin/terms/new/new.component.html
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<div *ngIf="isLoading">
|
||||||
|
<my-spinner></my-spinner>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!isLoading">
|
||||||
|
<my-ibox boxTitle="Policy information">
|
||||||
|
<div class="my-ibox-content">
|
||||||
|
<label class="label-block">
|
||||||
|
Name
|
||||||
|
<span class="text-muted ">The name of your policy, in English. Example: "Terms of Service"</span>
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
placeholder="My Policy" (keyup)="onNameKeyUp()"
|
||||||
|
[(ngModel)]="languages['en'].name" [disabled]="isUpdating"/>
|
||||||
|
</label>
|
||||||
|
<label class="label-block">
|
||||||
|
Shortcode
|
||||||
|
<span class="text-muted ">This is automatically generated to give the policy a unique identifier.</span>
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
[(ngModel)]="shortcode" [disabled]="true"/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</my-ibox>
|
||||||
|
<my-ibox>
|
||||||
|
<div class="my-ibox-title">
|
||||||
|
<h5>English version</h5>
|
||||||
|
</div>
|
||||||
|
<div class="my-ibox-content">
|
||||||
|
<label class="label-block">
|
||||||
|
Policy text
|
||||||
|
<span class="text-muted ">This is where you put your policy's content.</span>
|
||||||
|
</label>
|
||||||
|
<ckeditor [editor]="Editor" [(ngModel)]="languages['en'].text"></ckeditor>
|
||||||
|
</div>
|
||||||
|
</my-ibox>
|
||||||
|
<my-ibox *ngFor="let code of otherLanguageCodes">
|
||||||
|
<div class="my-ibox-title">
|
||||||
|
<h5>{{languages[code].langName}} version</h5>
|
||||||
|
</div>
|
||||||
|
<div class="my-ibox-content">
|
||||||
|
<label class="label-block">
|
||||||
|
Name
|
||||||
|
<span class="text-muted ">The translated name of your policy</span>
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
placeholder="My Policy"
|
||||||
|
[(ngModel)]="languages[code].name" [disabled]="isUpdating"/>
|
||||||
|
</label>
|
||||||
|
<label class="label-block">
|
||||||
|
Policy text
|
||||||
|
<span class="text-muted ">This is where you put your policy's content.</span>
|
||||||
|
</label>
|
||||||
|
<ckeditor [editor]="Editor" [(ngModel)]="languages[code].text" [disabled]="isUpdating"></ckeditor>
|
||||||
|
</div>
|
||||||
|
</my-ibox>
|
||||||
|
<my-ibox [hasTitle]="false">
|
||||||
|
<div class="my-ibox-content buttons">
|
||||||
|
<select [(ngModel)]="chosenLanguage" [disabled]="isUpdating" class="form-control form-control-sm">
|
||||||
|
<option *ngFor="let lang of availableLanguages" [ngValue]="lang.code">{{lang.name}}</option>
|
||||||
|
</select>
|
||||||
|
<button type="button" (click)="addLanguage()" title="save" class="btn btn-outline-success btn-sm">
|
||||||
|
<i class="fa fa-plus"></i> Add language
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</my-ibox>
|
||||||
|
<my-ibox [hasTitle]="false">
|
||||||
|
<div class="my-ibox-content buttons">
|
||||||
|
<button type="button" (click)="create()" title="save" class="btn btn-primary btn-sm">
|
||||||
|
<i class="far fa-save"></i> Create draft
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</my-ibox>
|
||||||
|
</div>
|
8
web/app/admin/terms/new/new.component.scss
Normal file
8
web/app/admin/terms/new/new.component.scss
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.buttons button {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons select {
|
||||||
|
max-width: 200px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
95
web/app/admin/terms/new/new.component.ts
Normal file
95
web/app/admin/terms/new/new.component.ts
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -15,7 +15,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Policy Name</th>
|
<th>Policy Name</th>
|
||||||
<th>Published Version</th>
|
<th>Version</th>
|
||||||
<th class="text-center" style="width: 120px;">Actions</th>
|
<th class="text-center" style="width: 120px;">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -35,6 +35,9 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
<button type="button" class="btn btn-success btn-sm" (click)="createPolicy()">
|
||||||
|
<i class="fa fa-plus"></i> New draft policy
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</my-ibox>
|
</my-ibox>
|
||||||
</div>
|
</div>
|
@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core";
|
|||||||
import { ToasterService } from "angular2-toaster";
|
import { ToasterService } from "angular2-toaster";
|
||||||
import { FE_TermsEditable } from "../../shared/models/terms";
|
import { FE_TermsEditable } from "../../shared/models/terms";
|
||||||
import { AdminTermsApiService } from "../../shared/services/admin/admin-terms-api.service";
|
import { AdminTermsApiService } from "../../shared/services/admin/admin-terms-api.service";
|
||||||
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: "./terms.component.html",
|
templateUrl: "./terms.component.html",
|
||||||
@ -13,12 +14,17 @@ export class AdminTermsComponent implements OnInit {
|
|||||||
public policies: FE_TermsEditable[];
|
public policies: FE_TermsEditable[];
|
||||||
|
|
||||||
constructor(private adminTerms: AdminTermsApiService,
|
constructor(private adminTerms: AdminTermsApiService,
|
||||||
private toaster: ToasterService) {
|
private toaster: ToasterService,
|
||||||
|
private router: Router,
|
||||||
|
private activatedRoute: ActivatedRoute) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.adminTerms.getAllPolicies().then(policies => {
|
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;
|
this.isLoading = false;
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@ -26,4 +32,8 @@ export class AdminTermsComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public createPolicy() {
|
||||||
|
this.router.navigate(["new"], {relativeTo: this.activatedRoute});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -114,6 +114,8 @@ 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";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -128,6 +130,7 @@ import { AdminTermsComponent } from "./admin/terms/terms.component";
|
|||||||
ModalModule.forRoot(),
|
ModalModule.forRoot(),
|
||||||
BootstrapModalModule,
|
BootstrapModalModule,
|
||||||
BreadcrumbsModule,
|
BreadcrumbsModule,
|
||||||
|
CKEditorModule,
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
@ -207,6 +210,7 @@ import { AdminTermsComponent } from "./admin/terms/terms.component";
|
|||||||
ReauthExampleWidgetWrapperComponent,
|
ReauthExampleWidgetWrapperComponent,
|
||||||
ManagerTestWidgetWrapperComponent,
|
ManagerTestWidgetWrapperComponent,
|
||||||
AdminTermsComponent,
|
AdminTermsComponent,
|
||||||
|
AdminNewTermsComponent,
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
],
|
],
|
||||||
|
@ -45,6 +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";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: "", component: HomeComponent},
|
{path: "", component: HomeComponent},
|
||||||
@ -155,6 +156,11 @@ const routes: Routes = [
|
|||||||
path: "",
|
path: "",
|
||||||
component: AdminTermsComponent,
|
component: AdminTermsComponent,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "new",
|
||||||
|
component: AdminNewTermsComponent,
|
||||||
|
data: {breadcrumb: "New policy", name: "New policy"},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<div class="ibox">
|
<div class="ibox">
|
||||||
<div class="ibox-title" (click)="isCollapsible ? (collapsed = !collapsed) : false"
|
<div class="ibox-title" (click)="isCollapsible ? (collapsed = !collapsed) : false"
|
||||||
[ngClass]="[isCollapsible ? 'ibox-title-collapsible' : '']">
|
[ngClass]="[isCollapsible ? 'ibox-title-collapsible' : '']"
|
||||||
|
*ngIf="hasTitle">
|
||||||
<h5 *ngIf="boxTitle">
|
<h5 *ngIf="boxTitle">
|
||||||
{{ boxTitle }}
|
{{ boxTitle }}
|
||||||
</h5>
|
</h5>
|
||||||
|
@ -11,6 +11,7 @@ export class IboxComponent implements OnInit {
|
|||||||
@Input() boxTitle: string;
|
@Input() boxTitle: string;
|
||||||
@Input() isCollapsible: boolean;
|
@Input() isCollapsible: boolean;
|
||||||
@Input() defaultCollapsed: boolean;
|
@Input() defaultCollapsed: boolean;
|
||||||
|
@Input() hasTitle = true;
|
||||||
|
|
||||||
public collapsed = false;
|
public collapsed = false;
|
||||||
|
|
||||||
|
@ -2,7 +2,21 @@ import { FE_Integration } from "./models/integration";
|
|||||||
|
|
||||||
export class SessionStorage {
|
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 userId: string;
|
||||||
public static roomId: string;
|
public static roomId: string;
|
||||||
public static isAdmin: boolean;
|
public static isAdmin: boolean;
|
||||||
|
Loading…
Reference in New Issue
Block a user