mirror of https://github.com/Squidex/squidex.git
111 changed files with 1319 additions and 776 deletions
@ -1,24 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { SqxFrameworkModule } from 'shared'; |
|||
|
|||
import { |
|||
LogoutPageComponent |
|||
} from './declarations'; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule |
|||
], |
|||
declarations: [ |
|||
LogoutPageComponent |
|||
] |
|||
}) |
|||
export class SqxAuthModule { } |
|||
@ -1,11 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './auth'; |
|||
export * from './internal'; |
|||
export * from './layout'; |
|||
export * from './public'; |
|||
@ -1 +0,0 @@ |
|||
<router-outlet></router-outlet> |
|||
@ -1,17 +0,0 @@ |
|||
<sqx-title message="{app} | Dashboard" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
|
|||
<div class="layout"> |
|||
<div class="layout-left"> |
|||
<sqx-left-menu></sqx-left-menu> |
|||
</div> |
|||
<div class="layout-middle"> |
|||
<div class="layout-middle-header"> |
|||
<h1> |
|||
<i class="layout-title-icon icon-dashboard"></i> Dashboard |
|||
</h1> |
|||
</div> |
|||
<div class="layout-middle-content"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -1,6 +0,0 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.layout-title-icon { |
|||
color: $color-section-dashboard; |
|||
} |
|||
@ -1,38 +0,0 @@ |
|||
<ul class="nav"> |
|||
<li class="nav-item nav-item--dashboard"> |
|||
<a class="nav-link" routerLink="../dashboard" routerLinkActive="active"> |
|||
<i class="icon-dashboard"></i> Dashboard |
|||
</a> |
|||
</li> |
|||
<li class="nav-items nav-item--schemas" *ngIf="permission !== 'Editor'"> |
|||
<a class="nav-link" routerLink="../schemas" routerLinkActive="active"> |
|||
<i class="icon-schemas"></i> Schemas |
|||
</a> |
|||
</li> |
|||
<li class="nav-item nav-item--content"> |
|||
<a class="nav-link"> |
|||
<i class="icon-content"></i> Content |
|||
</a> |
|||
</li> |
|||
<li class="nav-item nav-item--media"> |
|||
<a class="nav-link"> |
|||
<i class="icon-media"></i> Media</a> |
|||
</li> |
|||
<li class="nav-item nav-item--settings nav-item-group" *ngIf="permission === 'Owner'"> |
|||
<a class="nav-link" (click)="toggleSettingsMenu()"> |
|||
<i class="icon-settings"></i> Settings |
|||
</a> |
|||
|
|||
<ul class="subnav" *ngIf="showSettingsMenu"> |
|||
<li class="subnav-item"> |
|||
<a class="nav-link" routerLink="../contributors" routerLinkActive="active">Contributors</a> |
|||
</li> |
|||
<li class="subnav-item"> |
|||
<a class="nav-link" routerLink="../clients" routerLinkActive="active">Clients</a> |
|||
</li> |
|||
<li class="subnav-item"> |
|||
<a class="nav-link" routerLink="../languages" routerLinkActive="active">Languages</a> |
|||
</li> |
|||
</ul> |
|||
</li> |
|||
</ul> |
|||
@ -1,121 +0,0 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
$color-selection-background: #ebf0f2; |
|||
$color-subnav-text: #818181; |
|||
$color-subnav-dot: #bdc6d0; |
|||
$color-border-left-width: 4px; |
|||
|
|||
@mixin build-item($color) { |
|||
& .nav-link { |
|||
&:hover, |
|||
&.active { |
|||
border-color: $color; |
|||
} |
|||
} |
|||
|
|||
& i { |
|||
margin-right: .5rem; |
|||
color: $color; |
|||
} |
|||
} |
|||
|
|||
.nav { |
|||
& { |
|||
list-style: none; |
|||
padding: 0; |
|||
margin-left: -$padding-layout-h - 1px; |
|||
margin-right: -$padding-layout-h; |
|||
} |
|||
|
|||
&-item { |
|||
&--media { |
|||
@include build-item($color-section-media); |
|||
} |
|||
|
|||
&--content { |
|||
@include build-item($color-section-content); |
|||
} |
|||
|
|||
&--dashboard { |
|||
@include build-item($color-section-dashboard); |
|||
} |
|||
|
|||
&--schemas { |
|||
@include build-item($color-section-schemas); |
|||
} |
|||
|
|||
&--settings { |
|||
@include build-item($color-section-settings); |
|||
} |
|||
} |
|||
|
|||
&-item-group > a { |
|||
& { |
|||
position: relative; |
|||
} |
|||
|
|||
&::after { |
|||
@include absolute(50%, 30px, auto, auto); |
|||
@include caret-bottom; |
|||
} |
|||
} |
|||
|
|||
&-link { |
|||
& { |
|||
@include transition(background .2s ease); |
|||
border-left: $color-border-left-width solid transparent; |
|||
color: $color-text; |
|||
cursor: pointer; |
|||
display: block; |
|||
font-size: 1rem; |
|||
font-weight: 450; |
|||
line-height: 3rem; |
|||
padding-left: $padding-layout-h - $color-border-left-width; |
|||
padding-right: $padding-layout-h; |
|||
} |
|||
|
|||
&:hover, |
|||
&.active { |
|||
background: $color-selection-background; |
|||
} |
|||
|
|||
&.active { |
|||
font-weight: bold; |
|||
} |
|||
|
|||
&:hover { |
|||
text-decoration: none; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.subnav { |
|||
& { |
|||
list-style: none; |
|||
margin: 0; |
|||
padding: 0; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.nav-link { |
|||
& { |
|||
color: $color-subnav-text; |
|||
padding-left: 55px; |
|||
font-size: .9rem; |
|||
font-weight: 450; |
|||
line-height: 2rem; |
|||
} |
|||
} |
|||
|
|||
&-item { |
|||
&::before { |
|||
content: '•'; |
|||
color: $color-subnav-dot; |
|||
float: left; |
|||
font-weight: bold; |
|||
line-height: 2rem; |
|||
margin-left: 35px; |
|||
} |
|||
} |
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
<div class="layout"> |
|||
<div class="layout-left"> |
|||
<sqx-left-menu></sqx-left-menu> |
|||
</div> |
|||
<div class="layout-middle"> |
|||
<div class="layout-middle-header"> |
|||
<button class="layout-new-button btn btn-success float-xs-right">Create Schema</button> |
|||
|
|||
<h1> |
|||
<i class="layout-title-icon icon-schemas"></i> Schemas |
|||
</h1> |
|||
</div> |
|||
<div class="layout-middle-content"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -1,6 +0,0 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.layout-title-icon { |
|||
color: $color-section-schemas; |
|||
} |
|||
@ -1,39 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { AppsStoreService, TitleService } from 'shared'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'sqx-schemas-page', |
|||
styles, |
|||
template |
|||
}) |
|||
export class SchemasPageComponent implements Ng2.OnInit { |
|||
private appSubscription: any | null = null; |
|||
|
|||
constructor( |
|||
private readonly titles: TitleService, |
|||
private readonly appsStore: AppsStoreService |
|||
) { |
|||
} |
|||
|
|||
public ngOnInit() { |
|||
this.appSubscription = |
|||
this.appsStore.selectedApp.subscribe(app => { |
|||
if (app) { |
|||
this.titles.setTitle('{appName} | Schemas', { appName: app.name }); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public ngOnDestroy() { |
|||
this.appSubscription.unsubscribe(); |
|||
} |
|||
} |
|||
|
|||
@ -1,47 +0,0 @@ |
|||
<sqx-title message="{app} | Clients | Settings" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="layout"> |
|||
<div class="layout-left"> |
|||
<sqx-left-menu></sqx-left-menu> |
|||
</div> |
|||
<div class="layout-middle"> |
|||
<div class="layout-middle-header"> |
|||
<h1> |
|||
<i class="layout-title-icon icon-settings"></i> Clients |
|||
</h1> |
|||
</div> |
|||
<div class="layout-middle-content"> |
|||
<div class="table-items-row" *ngIf="appClients && appClients.length === 0"> |
|||
No client created yet. |
|||
</div> |
|||
|
|||
<div *ngFor="let client of appClients"> |
|||
<sqx-client [client]="client" [appName]="appName() | async" (renamed)="renameClient(client, $event)"></sqx-client> |
|||
</div> |
|||
|
|||
<div class="table-items-footer"> |
|||
<form class="form-inline" [formGroup]="createForm" (submit)="attachClient()"> |
|||
<div class="errors-box" *ngIf="createForm.get('name').invalid && createForm.get('name').dirty"> |
|||
<div class="errors"> |
|||
<span *ngIf="createForm.get('name').hasError('required')"> |
|||
Name is required. |
|||
</span> |
|||
<span *ngIf="createForm.get('name').hasError('maxlength')"> |
|||
Name can not have more than 40 characters. |
|||
</span> |
|||
<span *ngIf="createForm.get('name').hasError('pattern')"> |
|||
Name can contain lower case letters (a-z), numbers and dashes (not at the end). |
|||
</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="form-group"> |
|||
<input type="text" class="form-control" id="app-name" formControlName="name" maxlength="40" placeholder="Enter client name" /> |
|||
</div> |
|||
|
|||
<button type="submit" class="btn btn-success" [disabled]="createForm.invalid">Add Client</button> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -1,67 +0,0 @@ |
|||
<sqx-title message="{app} | Contributors | Settings" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="layout"> |
|||
<div class="layout-left"> |
|||
<sqx-left-menu></sqx-left-menu> |
|||
</div> |
|||
<div class="layout-middle"> |
|||
<div class="layout-middle-header"> |
|||
<h1> |
|||
<i class="layout-title-icon icon-settings"></i> Contributors |
|||
</h1> |
|||
</div> |
|||
<div class="layout-middle-content"> |
|||
<table class="table table-items table-fixed"> |
|||
<colgroup> |
|||
<col style="width: 50px" /> |
|||
<col style="width: 50%" /> |
|||
<col style="width: 50%" /> |
|||
<col style="width: 150px" /> |
|||
<col style="width: 80px" /> |
|||
</colgroup> |
|||
|
|||
<tbody> |
|||
<template ngFor let-contributor [ngForOf]="appContributors"> |
|||
<tr> |
|||
<td> |
|||
<img class="user-picture" [attr.src]="userPicture(contributor.contributorId) | async" /> |
|||
</td> |
|||
<td> |
|||
<span class="user-name">{{userName(contributor.contributorId) | async}}</span> |
|||
</td> |
|||
<td> |
|||
<span class="user-email">{{userEmail(contributor.contributorId) | async}}</span> |
|||
</td> |
|||
<td> |
|||
<select class="form-control" [(ngModel)]="contributor.permission" (ngModelChange)="changePermission(contributor, $event)" [disabled]="currentUserId === contributor.contributorId"> |
|||
<option *ngFor="let permission of usersPermissions">{{permission}}</option> |
|||
</select> |
|||
</td> |
|||
<td> |
|||
<button type="button" class="btn btn-link btn-danger" [disabled]="currrentUserId === contributor.contributorId" (click)="removeContributor(contributor)"> |
|||
<i class="icon-bin"></i> |
|||
</button> |
|||
</td> |
|||
</tr> |
|||
<tr class="spacer"></tr> |
|||
</template> |
|||
</tbody> |
|||
</table> |
|||
|
|||
<div class="table-items-footer"> |
|||
<form class="form-inline" (submit)="assignContributor()" > |
|||
<div class="form-group"> |
|||
<sqx-autocomplete [source]="usersDataSource" |
|||
(ngModelChange)="selectUser($event.model)" |
|||
[ngModel]="selectedUser" |
|||
[ngModelOptions]="{standalone: true}" |
|||
[inputName]="contributor"> |
|||
</sqx-autocomplete> |
|||
</div> |
|||
|
|||
<button type="submit" class="btn btn-success" [disabled]="!selectedUser">Add Contributor</button> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -1,78 +0,0 @@ |
|||
<sqx-title message="{app} | Languages | Settings" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="layout"> |
|||
<div class="layout-left"> |
|||
<sqx-left-menu></sqx-left-menu> |
|||
</div> |
|||
<div class="layout-middle"> |
|||
<div class="layout-middle-header"> |
|||
<h1> |
|||
<i class="layout-title-icon icon-settings"></i> Languages |
|||
</h1> |
|||
</div> |
|||
<div class="layout-middle-content"> |
|||
<table class="table table-items table-fixed"> |
|||
<colgroup> |
|||
<col style="width: 60px" /> |
|||
<col style="width: 100%" /> |
|||
<col style="width: 200px" /> |
|||
<col style="width: 80px" /> |
|||
</colgroup> |
|||
|
|||
<thead> |
|||
<tr> |
|||
<th> |
|||
Code |
|||
</th> |
|||
<th> |
|||
Name |
|||
</th> |
|||
<th> |
|||
Options |
|||
</th> |
|||
</tr> |
|||
</thead> |
|||
|
|||
<tbody> |
|||
<template ngFor let-language [ngForOf]="appLanguages"> |
|||
<tr> |
|||
<td> |
|||
<span class="language-code"> |
|||
{{language.iso2Code}} |
|||
</span> |
|||
</td> |
|||
<td> |
|||
<span class="language-name"> |
|||
{{language.englishName}} |
|||
</span> |
|||
</td> |
|||
<td> |
|||
<label class="language-default"> |
|||
<input type="radio" [value]="true" [ngModel]="language.isMasterLanguage" (ngModelChange)="setMasterLanguage(language)"> Master Language |
|||
</label> |
|||
</td> |
|||
<td> |
|||
<button type="button" class="btn btn-link btn-danger" [disabled]="language.isMasterLanguage" (click)="removeLanguage(language)"> |
|||
<i class="icon-bin"></i> |
|||
</button> |
|||
</td> |
|||
</tr> |
|||
<tr class="spacer"></tr> |
|||
</template> |
|||
</tbody> |
|||
</table> |
|||
|
|||
<div class="table-items-footer"> |
|||
<form class="form-inline" (submit)="addLanguage()" name="addLanguageForm"> |
|||
<div class="form-group"> |
|||
<select class="form-control language-select" [(ngModel)]="selectedLanguage" name="newLanguage"> |
|||
<option *ngFor="let language of allLanguages" [ngValue]="language">{{language.englishName}}</option> |
|||
</select> |
|||
</div> |
|||
|
|||
<button type="submit" class="btn btn-success" [disabled]="!selectedLanguage">Add Language</button> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -1,18 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './apps/apps-page.component'; |
|||
export * from './app/app-area.component'; |
|||
export * from './app/left-menu.component'; |
|||
export * from './app/dashboard/dashboard-page.component'; |
|||
export * from './app/schemas/schemas-page.component'; |
|||
export * from './app/settings/client.component'; |
|||
export * from './app/settings/clients-page.component'; |
|||
export * from './app/settings/contributors-page.component'; |
|||
export * from './app/settings/languages-page.component'; |
|||
|
|||
export * from './internal-area.component'; |
|||
@ -1,47 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { SqxLayoutModule } from 'components/layout'; |
|||
import { SqxFrameworkModule } from 'shared'; |
|||
|
|||
import { |
|||
AppAreaComponent, |
|||
AppsPageComponent, |
|||
ClientComponent, |
|||
ClientsPageComponent, |
|||
ContributorsPageComponent, |
|||
DashboardPageComponent, |
|||
InternalAreaComponent, |
|||
LanguagesPageComponent, |
|||
LeftMenuComponent, |
|||
SchemasPageComponent |
|||
} from './declarations'; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule, |
|||
SqxLayoutModule |
|||
], |
|||
exports: [ |
|||
LeftMenuComponent |
|||
], |
|||
declarations: [ |
|||
AppAreaComponent, |
|||
AppsPageComponent, |
|||
ClientComponent, |
|||
ClientsPageComponent, |
|||
ContributorsPageComponent, |
|||
DashboardPageComponent, |
|||
InternalAreaComponent, |
|||
LanguagesPageComponent, |
|||
LeftMenuComponent, |
|||
SchemasPageComponent |
|||
] |
|||
}) |
|||
export class SqxAppModule { } |
|||
@ -1,11 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './app-form.component'; |
|||
export * from './apps-menu.component'; |
|||
export * from './profile-menu.component'; |
|||
export * from './search-form.component'; |
|||
@ -1,9 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './home-page.component'; |
|||
export * from './not-found-page.component'; |
|||
@ -1,26 +0,0 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { SqxFrameworkModule } from 'shared'; |
|||
|
|||
import { |
|||
HomePageComponent, |
|||
NotFoundPageComponent |
|||
} from './declarations'; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule |
|||
], |
|||
declarations: [ |
|||
NotFoundPageComponent, |
|||
HomePageComponent |
|||
] |
|||
}) |
|||
export class SqxPublicModule { } |
|||
@ -0,0 +1,34 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
import * as Ng2Router from '@angular/router'; |
|||
|
|||
import { SqxFrameworkModule, SqxSharedModule } from 'shared'; |
|||
|
|||
import { |
|||
AppsPageComponent |
|||
} from './declarations'; |
|||
|
|||
const routes: Ng2Router.Routes = [ |
|||
{ |
|||
path: '', |
|||
component: AppsPageComponent |
|||
} |
|||
]; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule, |
|||
SqxSharedModule, |
|||
Ng2Router.RouterModule.forChild(routes) |
|||
], |
|||
declarations: [ |
|||
AppsPageComponent |
|||
] |
|||
}) |
|||
export class SqxFeatureAppsModule { } |
|||
@ -0,0 +1,8 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './pages/content-page.component'; |
|||
@ -1,4 +1,4 @@ |
|||
/* |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
@ -0,0 +1,34 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
import * as Ng2Router from '@angular/router'; |
|||
|
|||
import { SqxFrameworkModule, SqxSharedModule } from 'shared'; |
|||
|
|||
import { |
|||
ContentPageComponent |
|||
} from './declarations'; |
|||
|
|||
const routes: Ng2Router.Routes = [ |
|||
{ |
|||
path: '', |
|||
component: ContentPageComponent |
|||
} |
|||
]; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule, |
|||
SqxSharedModule, |
|||
Ng2Router.RouterModule.forChild(routes) |
|||
], |
|||
declarations: [ |
|||
ContentPageComponent |
|||
] |
|||
}) |
|||
export class SqxFeatureContentModule { } |
|||
@ -0,0 +1,14 @@ |
|||
<sqx-title message="{app} | Content" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="panel panel-light"> |
|||
<div class="panel-header"> |
|||
<h3 class="panel-title">Content</h3> |
|||
|
|||
<a class="panel-close" dashboardLink> |
|||
<i class="icon-close"></i> |
|||
</a> |
|||
</div> |
|||
|
|||
<div class="panel-content"> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,7 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.panel { |
|||
min-width: 600px; |
|||
max-width: 600px; |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { |
|||
AppComponentBase, |
|||
AppsStoreService, |
|||
NotificationService, |
|||
UsersProviderService |
|||
} from 'shared'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'sqx-content-page', |
|||
styles, |
|||
template |
|||
}) |
|||
export class ContentPageComponent extends AppComponentBase { |
|||
constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService) { |
|||
super(apps, notifications, users); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,8 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './pages/dashboard-page.component'; |
|||
@ -1,4 +1,4 @@ |
|||
/* |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
@ -0,0 +1,33 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
import * as Ng2Router from '@angular/router'; |
|||
|
|||
import { SqxFrameworkModule } from 'shared'; |
|||
|
|||
import { |
|||
DashboardPageComponent |
|||
} from './declarations'; |
|||
|
|||
const routes: Ng2Router.Routes = [ |
|||
{ |
|||
path: '', |
|||
component: DashboardPageComponent |
|||
} |
|||
]; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule, |
|||
Ng2Router.RouterModule.forChild(routes) |
|||
], |
|||
declarations: [ |
|||
DashboardPageComponent |
|||
] |
|||
}) |
|||
export class SqxFeatureDashboardModule { } |
|||
@ -0,0 +1,10 @@ |
|||
<sqx-title message="{app} | Dashboard" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="panel panel-light"> |
|||
<div class="panel-header"> |
|||
<h3 class="panel-title">Dashboard</h3> |
|||
</div> |
|||
|
|||
<div class="panel-content"> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,7 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.panel { |
|||
min-width: 600px; |
|||
max-width: 600px; |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './pages/media-page.component'; |
|||
@ -1,4 +1,4 @@ |
|||
/* |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
@ -0,0 +1,34 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
import * as Ng2Router from '@angular/router'; |
|||
|
|||
import { SqxFrameworkModule, SqxSharedModule } from 'shared'; |
|||
|
|||
import { |
|||
MediaPageComponent |
|||
} from './declarations'; |
|||
|
|||
const routes: Ng2Router.Routes = [ |
|||
{ |
|||
path: '', |
|||
component: MediaPageComponent |
|||
} |
|||
]; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule, |
|||
SqxSharedModule, |
|||
Ng2Router.RouterModule.forChild(routes) |
|||
], |
|||
declarations: [ |
|||
MediaPageComponent |
|||
] |
|||
}) |
|||
export class SqxFeatureMediaModule { } |
|||
@ -0,0 +1,14 @@ |
|||
<sqx-title message="{app} | Media" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="panel panel-light"> |
|||
<div class="panel-header"> |
|||
<h3 class="panel-title">Media</h3> |
|||
|
|||
<a class="panel-close" dashboardLink> |
|||
<i class="icon-close"></i> |
|||
</a> |
|||
</div> |
|||
|
|||
<div class="panel-content"> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,7 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.panel { |
|||
min-width: 600px; |
|||
max-width: 600px; |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { |
|||
AppComponentBase, |
|||
AppsStoreService, |
|||
NotificationService, |
|||
UsersProviderService |
|||
} from 'shared'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'sqx-media-page', |
|||
styles, |
|||
template |
|||
}) |
|||
export class MediaPageComponent extends AppComponentBase { |
|||
constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService) { |
|||
super(apps, notifications, users); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,8 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './pages/schemas-page.component'; |
|||
@ -0,0 +1,9 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './declarations'; |
|||
export * from './module'; |
|||
@ -0,0 +1,34 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
import * as Ng2Router from '@angular/router'; |
|||
|
|||
import { SqxFrameworkModule, SqxSharedModule } from 'shared'; |
|||
|
|||
import { |
|||
SchemasPageComponent |
|||
} from './declarations'; |
|||
|
|||
const routes: Ng2Router.Routes = [ |
|||
{ |
|||
path: '', |
|||
component: SchemasPageComponent |
|||
} |
|||
]; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule, |
|||
SqxSharedModule, |
|||
Ng2Router.RouterModule.forChild(routes) |
|||
], |
|||
declarations: [ |
|||
SchemasPageComponent |
|||
] |
|||
}) |
|||
export class SqxFeatureSchemasModule { } |
|||
@ -0,0 +1,14 @@ |
|||
<sqx-title message="{app} | Schemas" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="panel panel-light"> |
|||
<div class="panel-header"> |
|||
<h3 class="panel-title">Schemas</h3> |
|||
|
|||
<a class="panel-close" dashboardLink> |
|||
<i class="icon-close"></i> |
|||
</a> |
|||
</div> |
|||
|
|||
<div class="panel-content"> |
|||
</div> |
|||
</div> |
|||
@ -0,0 +1,7 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.panel { |
|||
min-width: 600px; |
|||
max-width: 600px; |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { |
|||
AppComponentBase, |
|||
AppsStoreService, |
|||
NotificationService, |
|||
UsersProviderService |
|||
} from 'shared'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'sqx-schemas-page', |
|||
styles, |
|||
template |
|||
}) |
|||
export class SchemasPageComponent extends AppComponentBase { |
|||
constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService) { |
|||
super(apps, notifications, users); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,13 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './pages/clients/client.component'; |
|||
export * from './pages/clients/clients-page.component'; |
|||
export * from './pages/contributors/contributors-page.component'; |
|||
export * from './pages/languages/languages-page.component'; |
|||
|
|||
export * from './settings-area.component'; |
|||
@ -0,0 +1,9 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './declarations'; |
|||
export * from './module'; |
|||
@ -0,0 +1,57 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
import * as Ng2Router from '@angular/router'; |
|||
|
|||
import { SqxFrameworkModule, SqxSharedModule } from 'shared'; |
|||
|
|||
import { |
|||
ClientComponent, |
|||
ClientsPageComponent, |
|||
ContributorsPageComponent, |
|||
LanguagesPageComponent, |
|||
SettingsAreaComponent |
|||
} from './declarations'; |
|||
|
|||
const routes: Ng2Router.Routes = [ |
|||
{ |
|||
path: '', |
|||
component: SettingsAreaComponent, |
|||
children: [ |
|||
{ |
|||
path: '' |
|||
}, |
|||
{ |
|||
path: 'clients', |
|||
component: ClientsPageComponent |
|||
}, { |
|||
path: 'contributors', |
|||
component: ContributorsPageComponent |
|||
}, { |
|||
path: 'languages', |
|||
component: LanguagesPageComponent |
|||
} |
|||
] |
|||
} |
|||
]; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule, |
|||
SqxSharedModule, |
|||
Ng2Router.RouterModule.forChild(routes) |
|||
], |
|||
declarations: [ |
|||
ClientComponent, |
|||
ClientsPageComponent, |
|||
ContributorsPageComponent, |
|||
LanguagesPageComponent, |
|||
SettingsAreaComponent |
|||
] |
|||
}) |
|||
export class SqxFeatureSettingsModule { } |
|||
@ -0,0 +1,45 @@ |
|||
<sqx-title message="{app} | Clients | Settings" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="panel panel-light"> |
|||
<div class="panel-header"> |
|||
<h3 class="panel-title">Clients</h3> |
|||
|
|||
<a class="panel-close" routerLink="../"> |
|||
<i class="icon-close"></i> |
|||
</a> |
|||
</div> |
|||
|
|||
<div class="panel-content"> |
|||
<div class="table-items-row" *ngIf="appClients && appClients.length === 0"> |
|||
No client created yet. |
|||
</div> |
|||
|
|||
<div *ngFor="let client of appClients"> |
|||
<sqx-client [client]="client" [appName]="appName() | async" (renamed)="renameClient(client, $event)"></sqx-client> |
|||
</div> |
|||
|
|||
<div class="table-items-footer"> |
|||
<form class="form-inline" [formGroup]="createForm" (submit)="attachClient()"> |
|||
<div class="errors-box" *ngIf="createForm.get('name').invalid && createForm.get('name').dirty"> |
|||
<div class="errors"> |
|||
<span *ngIf="createForm.get('name').hasError('required')"> |
|||
Name is required. |
|||
</span> |
|||
<span *ngIf="createForm.get('name').hasError('maxlength')"> |
|||
Name can not have more than 40 characters. |
|||
</span> |
|||
<span *ngIf="createForm.get('name').hasError('pattern')"> |
|||
Name can contain lower case letters (a-z), numbers and dashes (not at the end). |
|||
</span> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="form-group"> |
|||
<input type="text" class="form-control" id="app-name" formControlName="name" maxlength="40" placeholder="Enter client name" /> |
|||
</div> |
|||
|
|||
<button type="submit" class="btn btn-success" [disabled]="createForm.invalid">Add Client</button> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -1,8 +1,9 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.layout-title-icon { |
|||
color: $color-section-settings; |
|||
.panel { |
|||
min-width: 600px; |
|||
max-width: 600px; |
|||
} |
|||
|
|||
.card { |
|||
@ -0,0 +1,65 @@ |
|||
<sqx-title message="{app} | Contributors | Settings" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="panel panel-light"> |
|||
<div class="panel-header"> |
|||
<h3 class="panel-title">Contributors</h3> |
|||
|
|||
<a class="panel-close" routerLink="../"> |
|||
<i class="icon-close"></i> |
|||
</a> |
|||
</div> |
|||
|
|||
<div class="panel-content"> |
|||
<table class="table table-items table-fixed"> |
|||
<colgroup> |
|||
<col style="width: 50px" /> |
|||
<col style="width: 50%" /> |
|||
<col style="width: 50%" /> |
|||
<col style="width: 150px" /> |
|||
<col style="width: 80px" /> |
|||
</colgroup> |
|||
|
|||
<tbody> |
|||
<template ngFor let-contributor [ngForOf]="appContributors"> |
|||
<tr> |
|||
<td> |
|||
<img class="user-picture" [attr.src]="userPicture(contributor.contributorId) | async" /> |
|||
</td> |
|||
<td> |
|||
<span class="user-name">{{userName(contributor.contributorId) | async}}</span> |
|||
</td> |
|||
<td> |
|||
<span class="user-email">{{userEmail(contributor.contributorId) | async}}</span> |
|||
</td> |
|||
<td> |
|||
<select class="form-control" [(ngModel)]="contributor.permission" (ngModelChange)="changePermission(contributor, $event)" [disabled]="currentUserId === contributor.contributorId"> |
|||
<option *ngFor="let permission of usersPermissions">{{permission}}</option> |
|||
</select> |
|||
</td> |
|||
<td> |
|||
<button type="button" class="btn btn-link btn-danger" [disabled]="currrentUserId === contributor.contributorId" (click)="removeContributor(contributor)"> |
|||
<i class="icon-bin"></i> |
|||
</button> |
|||
</td> |
|||
</tr> |
|||
<tr class="spacer"></tr> |
|||
</template> |
|||
</tbody> |
|||
</table> |
|||
|
|||
<div class="table-items-footer"> |
|||
<form class="form-inline" (submit)="assignContributor()" > |
|||
<div class="form-group"> |
|||
<sqx-autocomplete [source]="usersDataSource" |
|||
(ngModelChange)="selectUser($event.model)" |
|||
[ngModel]="selectedUser" |
|||
[ngModelOptions]="{standalone: true}" |
|||
[inputName]="contributor"> |
|||
</sqx-autocomplete> |
|||
</div> |
|||
|
|||
<button type="submit" class="btn btn-success" [disabled]="!selectedUser">Add Contributor</button> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -1,8 +1,9 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.layout-title-icon { |
|||
color: $color-section-settings; |
|||
.panel { |
|||
min-width: 600px; |
|||
max-width: 600px; |
|||
} |
|||
|
|||
.card { |
|||
@ -0,0 +1,76 @@ |
|||
<sqx-title message="{app} | Languages | Settings" parameter="app" value="{{appName() | async}}"></sqx-title> |
|||
|
|||
<div class="panel panel-light"> |
|||
<div class="panel-header"> |
|||
<h3 class="panel-title">Settings</h3> |
|||
|
|||
<a class="panel-close" routerLink="../"> |
|||
<i class="icon-close"></i> |
|||
</a> |
|||
</div> |
|||
|
|||
<div class="panel-content"> |
|||
<table class="table table-items table-fixed"> |
|||
<colgroup> |
|||
<col style="width: 60px" /> |
|||
<col style="width: 100%" /> |
|||
<col style="width: 200px" /> |
|||
<col style="width: 80px" /> |
|||
</colgroup> |
|||
|
|||
<thead> |
|||
<tr> |
|||
<th> |
|||
Code |
|||
</th> |
|||
<th> |
|||
Name |
|||
</th> |
|||
<th> |
|||
Options |
|||
</th> |
|||
</tr> |
|||
</thead> |
|||
|
|||
<tbody> |
|||
<template ngFor let-language [ngForOf]="appLanguages"> |
|||
<tr> |
|||
<td> |
|||
<span class="language-code"> |
|||
{{language.iso2Code}} |
|||
</span> |
|||
</td> |
|||
<td> |
|||
<span class="language-name"> |
|||
{{language.englishName}} |
|||
</span> |
|||
</td> |
|||
<td> |
|||
<label class="language-default"> |
|||
<input type="radio" [value]="true" [ngModel]="language.isMasterLanguage" (ngModelChange)="setMasterLanguage(language)"> Master Language |
|||
</label> |
|||
</td> |
|||
<td> |
|||
<button type="button" class="btn btn-link btn-danger" [disabled]="language.isMasterLanguage" (click)="removeLanguage(language)"> |
|||
<i class="icon-bin"></i> |
|||
</button> |
|||
</td> |
|||
</tr> |
|||
<tr class="spacer"></tr> |
|||
</template> |
|||
</tbody> |
|||
</table> |
|||
|
|||
<div class="table-items-footer"> |
|||
<form class="form-inline" (submit)="addLanguage()" name="addLanguageForm"> |
|||
<div class="form-group"> |
|||
<select class="form-control language-select" [(ngModel)]="selectedLanguage" name="newLanguage"> |
|||
<option *ngFor="let language of allLanguages" [ngValue]="language">{{language.englishName}}</option> |
|||
</select> |
|||
</div> |
|||
|
|||
<button type="submit" class="btn btn-success" [disabled]="!selectedLanguage">Add Language</button> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
@ -1,8 +1,9 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.layout-title-icon { |
|||
color: $color-section-settings; |
|||
.panel { |
|||
min-width: 600px; |
|||
max-width: 600px; |
|||
} |
|||
|
|||
.language { |
|||
@ -0,0 +1,31 @@ |
|||
<div class="panel panel-dark"> |
|||
<div class="panel-header"> |
|||
<h3 class="panel-title">Settings</h3> |
|||
|
|||
<a class="panel-close" dashboardLink> |
|||
<i class="icon-close"></i> |
|||
</a> |
|||
</div> |
|||
|
|||
<div class="panel-content"> |
|||
<ul class="nav nav-pills nav-stacked nav-dark"> |
|||
<li class="nav-item"> |
|||
<a class="nav-link" routerLink="clients" routerLinkActive="active"> |
|||
Clients |
|||
</a> |
|||
</li> |
|||
<li class="nav-item"> |
|||
<a class="nav-link" routerLink="contributors" routerLinkActive="active"> |
|||
Contributors |
|||
</a> |
|||
</li> |
|||
<li class="nav-item"> |
|||
<a class="nav-link" routerLink="languages" routerLinkActive="active"> |
|||
Languages |
|||
</a> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
|
|||
<router-outlet></router-outlet> |
|||
@ -0,0 +1,7 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.panel { |
|||
min-width: 180px; |
|||
max-width: 180px; |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
@Ng2.Component({ |
|||
selector: 'sqx-settings-area', |
|||
styles, |
|||
template |
|||
}) |
|||
export class SettingsAreaComponent { |
|||
|
|||
} |
|||
@ -0,0 +1,58 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { PanelService } from './../services/panel.service'; |
|||
|
|||
@Ng2.Directive({ |
|||
selector: '.panel-container' |
|||
}) |
|||
export class PanelContainerDirective implements Ng2.OnInit, Ng2.OnDestroy { |
|||
private subscription: any; |
|||
private panelsSize: number | null = null; |
|||
|
|||
constructor( |
|||
private readonly element: Ng2.ElementRef, |
|||
private readonly panels: PanelService |
|||
) { |
|||
} |
|||
|
|||
@Ng2.HostListener('window:resize') |
|||
public onResize() { |
|||
this.resize(); |
|||
} |
|||
|
|||
public ngOnInit() { |
|||
this.subscription = |
|||
this.panels.changed.subscribe(width => { |
|||
this.panelsSize = width; |
|||
|
|||
this.resize(); |
|||
}); |
|||
} |
|||
|
|||
public ngOnDestroy() { |
|||
this.subscription.unsubscribe(); |
|||
} |
|||
|
|||
private resize() { |
|||
if (!this.panelsSize) { |
|||
return; |
|||
} |
|||
|
|||
const currentWidth = this.element.nativeElement.getBoundingClientRect().width; |
|||
|
|||
const diff = this.panelsSize - currentWidth; |
|||
|
|||
if (diff > 0) { |
|||
this.element.nativeElement.scrollLeft = diff; |
|||
} else { |
|||
this.element.nativeElement.scrollLeft = 0; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,30 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { PanelService } from './../services/panel.service'; |
|||
|
|||
@Ng2.Directive({ |
|||
selector: '.panel' |
|||
}) |
|||
export class PanelDirective implements Ng2.OnInit, Ng2.OnDestroy { |
|||
constructor( |
|||
private readonly element: Ng2.ElementRef, |
|||
private readonly renderer: Ng2.Renderer, |
|||
private readonly panels: PanelService |
|||
) { |
|||
} |
|||
|
|||
public ngOnInit() { |
|||
this.panels.push(this.element.nativeElement, this.renderer); |
|||
} |
|||
|
|||
public ngOnDestroy() { |
|||
this.panels.pop(this.element.nativeElement, this.renderer); |
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { Observable, Subject } from 'rxjs'; |
|||
|
|||
export const PanelServiceFactory = () => { |
|||
return new PanelService(); |
|||
}; |
|||
|
|||
@Ng2.Injectable() |
|||
export class PanelService { |
|||
private readonly elements: any[] = []; |
|||
private readonly changed$ = new Subject<number>(); |
|||
|
|||
public get changed(): Observable<number> { |
|||
return this.changed$; |
|||
} |
|||
|
|||
public push(element: any, renderer: Ng2.Renderer) { |
|||
this.elements.push(element); |
|||
this.update(renderer); |
|||
} |
|||
|
|||
public pop(element: any, renderer: Ng2.Renderer) { |
|||
this.elements.splice(-1, 1); |
|||
this.update(renderer); |
|||
} |
|||
|
|||
private update(renderer: Ng2.Renderer) { |
|||
let currentPosition = 0; |
|||
let currentLayer = this.elements.length * 10; |
|||
|
|||
for (let element of this.elements) { |
|||
const width = element.getBoundingClientRect().width; |
|||
|
|||
renderer.setElementStyle(element, 'left', currentPosition + 'px'); |
|||
renderer.setElementStyle(element, 'z-index', currentLayer.toString()); |
|||
|
|||
currentPosition += width; |
|||
currentLayer -= 10; |
|||
} |
|||
|
|||
this.changed$.next(currentPosition); |
|||
} |
|||
} |
|||
@ -0,0 +1,43 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
import * as Ng2Router from '@angular/router'; |
|||
|
|||
import { AppsStoreService } from './../services/apps-store.service'; |
|||
|
|||
@Ng2.Directive({ |
|||
selector: '[dashboardLink]' |
|||
}) |
|||
export class DashboardLinkDirective implements Ng2.OnInit, Ng2.OnDestroy { |
|||
private appSubscription: any; |
|||
private appName: string; |
|||
|
|||
constructor( |
|||
private readonly appsStore: AppsStoreService, |
|||
private readonly router: Ng2Router.Router |
|||
) { |
|||
} |
|||
|
|||
public ngOnInit() { |
|||
this.appSubscription = |
|||
this.appsStore.selectedApp.subscribe(app => { |
|||
this.appName = app.name; |
|||
}); |
|||
} |
|||
|
|||
public ngOnDestroy() { |
|||
this.appSubscription.unsubscribe(); |
|||
} |
|||
|
|||
@Ng2.HostListener('click') |
|||
public onClick() { |
|||
if (this.appName) { |
|||
this.router.navigate(['app', this.appName]); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './components/app-form.component'; |
|||
export * from './components/dashboard-link.directive'; |
|||
|
|||
export * from './guards/app-must-exist.guard'; |
|||
export * from './guards/must-be-authenticated.guard'; |
|||
export * from './guards/must-be-not-authenticated.guard'; |
|||
|
|||
export * from './services/app-contributors.service'; |
|||
export * from './services/app-clients.service'; |
|||
export * from './services/app-languages.service'; |
|||
export * from './services/apps-store.service'; |
|||
export * from './services/apps.service'; |
|||
export * from './services/auth.service'; |
|||
export * from './services/common'; |
|||
export * from './services/languages.service'; |
|||
export * from './services/users-provider.service'; |
|||
export * from './services/users.service'; |
|||
|
|||
export * from './app-component-base'; |
|||
|
|||
export * from 'framework'; |
|||
@ -1,25 +1,9 @@ |
|||
/* |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './guards/app-must-exist.guard'; |
|||
export * from './guards/must-be-authenticated.guard'; |
|||
export * from './guards/must-be-not-authenticated.guard'; |
|||
|
|||
export * from './services/app-contributors.service'; |
|||
export * from './services/app-clients.service'; |
|||
export * from './services/app-languages.service'; |
|||
export * from './services/apps-store.service'; |
|||
export * from './services/apps.service'; |
|||
export * from './services/auth.service'; |
|||
export * from './services/common'; |
|||
export * from './services/languages.service'; |
|||
export * from './services/users-provider.service'; |
|||
export * from './services/users.service'; |
|||
|
|||
export * from './app-component-base'; |
|||
|
|||
export * from 'framework'; |
|||
export * from './declarations'; |
|||
export * from './module'; |
|||
@ -0,0 +1,20 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './pages/app/app-area.component'; |
|||
export * from './pages/app/left-menu.component'; |
|||
|
|||
export * from './pages/home/home-page.component'; |
|||
|
|||
export * from './pages/internal/apps-menu.component'; |
|||
export * from './pages/internal/internal-area.component'; |
|||
export * from './pages/internal/profile-menu.component'; |
|||
export * from './pages/internal/search-form.component'; |
|||
|
|||
export * from './pages/logout/logout-page.component'; |
|||
|
|||
export * from './pages/not-found/not-found-page.component'; |
|||
@ -0,0 +1,9 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
export * from './declarations'; |
|||
export * from './module'; |
|||
@ -0,0 +1,47 @@ |
|||
/* |
|||
* Squidex Headless CMS |
|||
* |
|||
* @license |
|||
* Copyright (c) Sebastian Stehle. All rights reserved |
|||
*/ |
|||
|
|||
import * as Ng2 from '@angular/core'; |
|||
|
|||
import { SqxFrameworkModule, SqxSharedModule } from 'shared'; |
|||
|
|||
import { |
|||
AppAreaComponent, |
|||
AppsMenuComponent, |
|||
HomePageComponent, |
|||
InternalAreaComponent, |
|||
LeftMenuComponent, |
|||
LogoutPageComponent, |
|||
NotFoundPageComponent, |
|||
ProfileMenuComponent, |
|||
SearchFormComponent |
|||
} from './declarations'; |
|||
|
|||
@Ng2.NgModule({ |
|||
imports: [ |
|||
SqxFrameworkModule, |
|||
SqxSharedModule |
|||
], |
|||
exports: [ |
|||
AppAreaComponent, |
|||
HomePageComponent, |
|||
InternalAreaComponent, |
|||
NotFoundPageComponent |
|||
], |
|||
declarations: [ |
|||
AppAreaComponent, |
|||
AppsMenuComponent, |
|||
HomePageComponent, |
|||
InternalAreaComponent, |
|||
LeftMenuComponent, |
|||
LogoutPageComponent, |
|||
NotFoundPageComponent, |
|||
ProfileMenuComponent, |
|||
SearchFormComponent |
|||
] |
|||
}) |
|||
export class SqxShellModule { } |
|||
@ -0,0 +1,7 @@ |
|||
<div class="sidebar"> |
|||
<sqx-left-menu></sqx-left-menu> |
|||
</div> |
|||
|
|||
<div class="panel-container"> |
|||
<router-outlet></router-outlet> |
|||
</div> |
|||
@ -0,0 +1,24 @@ |
|||
<div class="sidebar panel-dark"> |
|||
<ul class="nav nav-pills nav-stacked nav-dark"> |
|||
<li class="nav-item nav-item--schemas" *ngIf="permission !== 'Editor'"> |
|||
<a class="nav-link" routerLink="schemas" routerLinkActive="active"> |
|||
<i class="nav-icon icon-schemas"></i> <span class="nav-text">Schemas</span> |
|||
</a> |
|||
</li> |
|||
<li class="nav-item nav-item--content"> |
|||
<a class="nav-link" routerLink="content" routerLinkActive="active"> |
|||
<i class="nav-icon icon-content"></i> <span class="nav-text">Content</span> |
|||
</a> |
|||
</li> |
|||
<li class="nav-item nav-item--media"> |
|||
<a class="nav-link" routerLink="media" routerLinkActive="active"> |
|||
<i class="nav-icon icon-media"></i> <span class="nav-text">Media</span> |
|||
</a> |
|||
</li> |
|||
<li class="nav-item nav-item--settings" *ngIf="permission === 'Owner'"> |
|||
<a class="nav-link" routerLink="settings" routerLinkActive="active"> |
|||
<i class="nav-icon icon-settings"></i> <span class="nav-text">Settings</span> |
|||
</a> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
@ -0,0 +1,72 @@ |
|||
@import '_vars'; |
|||
@import '_mixins'; |
|||
|
|||
.sidebar { |
|||
@include fixed($size-navbar-height, auto, 0, 0); |
|||
min-width: $size-sidebar-width; |
|||
max-width: $size-sidebar-width; |
|||
z-index: 100; |
|||
} |
|||
|
|||
|
|||
@mixin build-item($color) { |
|||
.nav-link { |
|||
&.active { |
|||
& { |
|||
background: $color-dark-selected; |
|||
} |
|||
|
|||
i { |
|||
color: $color; |
|||
} |
|||
} |
|||
} |
|||
|
|||
&:hover { |
|||
i { |
|||
color: $color; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.nav { |
|||
&-link { |
|||
padding: 20px; |
|||
} |
|||
|
|||
&-icon { |
|||
font-size: 30px; |
|||
} |
|||
|
|||
&-text { |
|||
display: block; |
|||
} |
|||
|
|||
&-item { |
|||
& { |
|||
color: $color-dark-foreground; |
|||
cursor: pointer; |
|||
text-align: center; |
|||
} |
|||
|
|||
&--media { |
|||
@include build-item($color-section-media); |
|||
} |
|||
|
|||
&--content { |
|||
@include build-item($color-section-content); |
|||
} |
|||
|
|||
&--dashboard { |
|||
@include build-item($color-section-dashboard); |
|||
} |
|||
|
|||
&--schemas { |
|||
@include build-item($color-section-schemas); |
|||
} |
|||
|
|||
&--settings { |
|||
@include build-item($color-section-settings); |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue