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"
|
||||
}
|
||||
},
|
||||
"@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",
|
||||
|
@ -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",
|
||||
|
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>
|
||||
<tr>
|
||||
<th>Policy Name</th>
|
||||
<th>Published Version</th>
|
||||
<th>Version</th>
|
||||
<th class="text-center" style="width: 120px;">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -35,6 +35,9 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<button type="button" class="btn btn-success btn-sm" (click)="createPolicy()">
|
||||
<i class="fa fa-plus"></i> New draft policy
|
||||
</button>
|
||||
</div>
|
||||
</my-ibox>
|
||||
</div>
|
@ -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});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
],
|
||||
|
@ -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"},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
@ -1,6 +1,7 @@
|
||||
<div class="ibox">
|
||||
<div class="ibox-title" (click)="isCollapsible ? (collapsed = !collapsed) : false"
|
||||
[ngClass]="[isCollapsible ? 'ibox-title-collapsible' : '']">
|
||||
[ngClass]="[isCollapsible ? 'ibox-title-collapsible' : '']"
|
||||
*ngIf="hasTitle">
|
||||
<h5 *ngIf="boxTitle">
|
||||
{{ boxTitle }}
|
||||
</h5>
|
||||
|
@ -11,6 +11,7 @@ export class IboxComponent implements OnInit {
|
||||
@Input() boxTitle: string;
|
||||
@Input() isCollapsible: boolean;
|
||||
@Input() defaultCollapsed: boolean;
|
||||
@Input() hasTitle = true;
|
||||
|
||||
public collapsed = false;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user