Browse Source

Content styling

pull/1/head
Sebastian 9 years ago
parent
commit
ca87c478bc
  1. 10
      src/Squidex/app/features/content/pages/content/content-field.component.html
  2. 6
      src/Squidex/app/features/content/pages/content/content-field.component.scss
  3. 2
      src/Squidex/app/features/content/pages/content/content-page.component.html
  4. 2
      src/Squidex/app/features/content/pages/contents/content-item.component.html
  5. 23
      src/Squidex/app/features/content/pages/contents/contents-page.component.html
  6. 29
      src/Squidex/app/features/content/pages/contents/contents-page.component.scss
  7. 61
      src/Squidex/app/features/content/pages/contents/contents-page.component.ts
  8. 5
      src/Squidex/app/features/content/pages/schemas/schemas-page.component.scss
  9. 22
      src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts
  10. 2
      src/Squidex/app/features/schemas/pages/schema/field.component.html
  11. 5
      src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.scss
  12. 12
      src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts
  13. 2
      src/Squidex/app/features/settings/pages/clients/clients-page.component.ts
  14. 2
      src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html
  15. 4
      src/Squidex/app/features/settings/pages/languages/languages-page.component.html
  16. 21
      src/Squidex/app/framework/utils/modal-view.ts
  17. 0
      src/Squidex/app/shared/components/app-component-base.ts
  18. 2
      src/Squidex/app/shared/components/app-form.component.ts
  19. 10
      src/Squidex/app/shared/components/history.component.scss
  20. 10
      src/Squidex/app/shared/components/history.component.ts
  21. 16
      src/Squidex/app/shared/components/language-selector.component.html
  22. 18
      src/Squidex/app/shared/components/language-selector.component.scss
  23. 59
      src/Squidex/app/shared/components/language-selector.component.ts
  24. 3
      src/Squidex/app/shared/declarations.ts
  25. 7
      src/Squidex/app/shared/module.ts
  26. 14
      src/Squidex/app/theme/_common.scss
  27. 9
      src/Squidex/app/theme/_panels.scss
  28. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.eot
  29. 1
      src/Squidex/app/theme/icomoon/fonts/icomoon.svg
  30. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.ttf
  31. BIN
      src/Squidex/app/theme/icomoon/fonts/icomoon.woff
  32. 32
      src/Squidex/app/theme/icomoon/selection.json
  33. 13
      src/Squidex/app/theme/icomoon/style.css

10
src/Squidex/app/features/content/pages/content/content-field.component.html

@ -1,4 +1,4 @@
<div class="table-items-row"> <div class="table-items-row" [class.invalid]="fieldForm.invalid">
<label> <label>
{{field|displayName:'properties.label':'name'}} <span class="field-required" [class.hidden]="!field.properties.isRequired">*</span> {{field|displayName:'properties.label':'name'}} <span class="field-required" [class.hidden]="!field.properties.isRequired">*</span>
</label> </label>
@ -7,13 +7,7 @@
<div [formGroup]="fieldForm"> <div [formGroup]="fieldForm">
<div *ngIf="field.properties.isLocalizable"> <div *ngIf="field.properties.isLocalizable">
<div class="btn-group btn-group-sm languages-buttons" role="group"> <sqx-language-selector size="sm" class="languages-buttons" (selectedLanguageChanged)="selectLanguage($event)" [languages]="languages"></sqx-language-selector>
<button type="button" class="btn btn-secondary" *ngFor="let language of languages" [attr.title]="language.englishName"
[class.btn-danger]="fieldForm.controls[language.iso2Code].invalid && (fieldForm.controls[language.iso2Code].touched || contentFormSubmitted)"
[class.active]="language.iso2Code == fieldLanguage" (click)="selectLanguage(language)">
{{language.iso2Code}}
</button>
</div>
</div> </div>
<div *ngFor="let language of fieldLanguages"> <div *ngFor="let language of fieldLanguages">

6
src/Squidex/app/features/content/pages/content/content-field.component.scss

@ -3,12 +3,18 @@
.table-items-row { .table-items-row {
position: relative; position: relative;
border-width: 1px;
border-left-width: 4px;
} }
.languages-buttons { .languages-buttons {
@include absolute(1rem, 1.25rem, auto, auto); @include absolute(1rem, 1.25rem, auto, auto);
} }
.invalid {
border-left-color: $color-theme-error;
}
.field { .field {
&-required { &-required {
color: $color-theme-error; color: $color-theme-error;

2
src/Squidex/app/features/content/pages/content/content-page.component.html

@ -20,7 +20,7 @@
</div> </div>
<div class="panel-main"> <div class="panel-main">
<div class="panel-content"> <div class="panel-content panel-content-scroll">
<div *ngFor="let field of schema.fields"> <div *ngFor="let field of schema.fields">
<sqx-content-field [field]="field" [fieldForm]="contentForm.controls[field.name]" [languages]="languages" [contentFormSubmitted]="contentFormSubmitted"></sqx-content-field> <sqx-content-field [field]="field" [fieldForm]="contentForm.controls[field.name]" [languages]="languages" [contentFormSubmitted]="contentFormSubmitted"></sqx-content-field>
</div> </div>

2
src/Squidex/app/features/content/pages/contents/content-item.component.html

@ -11,7 +11,7 @@
<img class="user-picture" [attr.title]="userName(content.lastModifiedBy) | async" [attr.src]="userPicture(content.lastModifiedBy, true) | async" /> <img class="user-picture" [attr.title]="userName(content.lastModifiedBy) | async" [attr.src]="userPicture(content.lastModifiedBy, true) | async" />
</td> </td>
<td> <td>
<div class="tooltip-dropdown" *ngIf="content"> <div class="dropdown dropdown-options" *ngIf="content">
<button type="button" class="btn btn-simple" (click)="dropdown.toggle(); $event.stopPropagation()" [class.active]="dropdown.isOpen | async"> <button type="button" class="btn btn-simple" (click)="dropdown.toggle(); $event.stopPropagation()" [class.active]="dropdown.isOpen | async">
<i class="icon-dots"></i> <i class="icon-dots"></i>
</button> </button>

23
src/Squidex/app/features/content/pages/contents/contents-page.component.html

@ -4,11 +4,11 @@
<div class="panel-header"> <div class="panel-header">
<div class="panel-title-row"> <div class="panel-title-row">
<div class="float-xs-right"> <div class="float-xs-right">
<div class="btn-group languages-buttons" role="group"> <form class="form-inline">
<button type="button" class="btn btn-secondary" *ngFor="let language of languages" [attr.title]="language.englishName" [class.active]="language == languageSelected" (click)="selectLanguage(language)"> <input class="form-control" [formControl]="contentsFilter" placeholder="Search for content..." />
{{language.iso2Code}} </form>
</button>
</div> <sqx-language-selector class="languages-buttons" (selectedLanguageChanged)="selectLanguage($event)" [languages]="languages"></sqx-language-selector>
<a class="btn btn-success" [routerLink]="['new']"> <a class="btn btn-success" [routerLink]="['new']">
<i class="icon-plus"></i> New <i class="icon-plus"></i> New
@ -64,6 +64,19 @@
</template> </template>
</tbody> </tbody>
</table> </table>
<div class="clearfix" *ngIf="contentTotal > 0">
<div class="float-xs-right pagination">
{{itemFirst}}-{{itemLast}} of {{contentTotal}}
<button class="btn btn-simple pagination-button" [disabled]="!canGoPrev" (click)="goPrev()">
<i class="icon-angle-left"></i>
</button>
<button class="btn btn-simple pagination-button" [disabled]="!canGoNext" (click)="goNext()">
<i class="icon-angle-right"></i>
</button>
</div>
</div>
</div> </div>
<div class="panel-sidebar"> <div class="panel-sidebar">
<a class="panel-link" routerLink="history" routerLinkActive="active"> <a class="panel-link" routerLink="history" routerLinkActive="active">

29
src/Squidex/app/features/content/pages/contents/contents-page.component.scss

@ -2,9 +2,36 @@
@import '_mixins'; @import '_mixins';
.languages-buttons { .languages-buttons {
margin-right: 1rem; margin-right: 2rem;
} }
.content { .content {
cursor: pointer; cursor: pointer;
} }
.btn-group {
margin-left: 1rem;
}
.form-inline {
display: inline-block;
}
.pagination {
& {
margin-top: 1rem;
}
&-button {
& {
color: $color-text;
font-size: 1.1rem;
font-weight: bold;
}
&:hover,
&.active {
color: darken($color-text, 20%);
}
}
}

61
src/Squidex/app/features/content/pages/contents/contents-page.component.ts

@ -6,6 +6,7 @@
*/ */
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
@ -49,8 +50,18 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
public languages: AppLanguageDto[] = []; public languages: AppLanguageDto[] = [];
public languageSelected: AppLanguageDto; public languageSelected: AppLanguageDto;
public page = 0; public contentsFilter = new FormControl();
public query = '';
public pageSize = 10;
public canGoNext = false;
public canGoPrev = false;
public itemFirst = 0;
public itemLast = 0;
public currentPage = 0;
public currentQuery = '';
public get columnWidth() { public get columnWidth() {
return 100 / this.contentFields.length; return 100 / this.contentFields.length;
@ -84,14 +95,20 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
this.route.data.map(p => p['appLanguages']).subscribe((languages: AppLanguageDto[]) => { this.route.data.map(p => p['appLanguages']).subscribe((languages: AppLanguageDto[]) => {
this.languages = languages; this.languages = languages;
this.languageSelected = languages.filter(t => t.isMasterLanguage)[0]; });
this.contentsFilter.valueChanges.debounceTime(300).subscribe(q => {
this.currentQuery = q;
if (this.schema) {
this.load();
}
}); });
this.route.data.map(p => p['schema']).subscribe(schema => { this.route.data.map(p => p['schema']).subscribe(schema => {
this.schema = schema; this.schema = schema;
this.reset(); this.reset();
this.loadFields();
this.load(); this.load();
}); });
} }
@ -133,7 +150,9 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
} }
private reset() { private reset() {
this.page = 0; this.loadFields();
this.currentPage = 0;
} }
private loadFields() { private loadFields() {
@ -146,15 +165,45 @@ export class ContentsPageComponent extends AppComponentBase implements OnDestroy
private load() { private load() {
this.appName() this.appName()
.switchMap(app => this.contentsService.getContents(app, this.schema.name, 20, this.page * 20, this.query)) .switchMap(app => this.contentsService.getContents(app, this.schema.name, this.pageSize, this.currentPage * this.pageSize, this.currentQuery))
.subscribe(dtos => { .subscribe(dtos => {
this.contentItems = ImmutableArray.of(dtos.items); this.contentItems = ImmutableArray.of(dtos.items);
this.contentTotal = dtos.total; this.contentTotal = dtos.total;
this.updatePaging();
}, error => { }, error => {
this.notifyError(error); this.notifyError(error);
}); });
} }
public goNext() {
if (this.canGoNext) {
this.currentPage++;
this.updatePaging();
this.load();
}
}
public goPrev() {
if (this.canGoPrev) {
this.currentPage--;
this.updatePaging();
this.load();
}
}
private updatePaging() {
const totalPages = Math.ceil(this.contentTotal / this.pageSize);
this.itemFirst = this.currentPage * this.pageSize + 1;
this.itemLast = Math.min(this.contentTotal, (this.currentPage + 1) * this.pageSize);
this.canGoNext = this.currentPage < totalPages - 1;
this.canGoPrev = this.currentPage > 0;
}
private createContent(id: string, data: any): ContentDto { private createContent(id: string, data: any): ContentDto {
const me = `subject:${this.authService.user!.id}`; const me = `subject:${this.authService.user!.id}`;

5
src/Squidex/app/features/content/pages/schemas/schemas-page.component.scss

@ -1,6 +1,11 @@
@import '_vars'; @import '_vars';
@import '_mixins'; @import '_mixins';
.panel-header {
min-height: 8rem;
max-height: 8rem;
}
.nav-link { .nav-link {
position: relative; position: relative;
padding-top: .6rem; padding-top: .6rem;

22
src/Squidex/app/features/content/pages/schemas/schemas-page.component.ts

@ -5,9 +5,8 @@
* Copyright (c) Sebastian Stehle. All rights reserved * Copyright (c) Sebastian Stehle. All rights reserved
*/ */
import { Component, OnInit } from '@angular/core'; import { Component } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { import {
@ -24,9 +23,13 @@ import {
styleUrls: ['./schemas-page.component.scss'], styleUrls: ['./schemas-page.component.scss'],
templateUrl: './schemas-page.component.html' templateUrl: './schemas-page.component.html'
}) })
export class SchemasPageComponent extends AppComponentBase implements OnInit { export class SchemasPageComponent extends AppComponentBase {
public schemasFilter = new FormControl();
public schemasFiltered = public schemasFiltered =
this.route.queryParams.map(q => q['schemaQuery']) Observable.of(null)
.merge(this.schemasFilter.valueChanges)
.distinctUntilChanged()
.debounceTime(300)
.combineLatest(this.loadSchemas(), .combineLatest(this.loadSchemas(),
(query, schemas) => { (query, schemas) => {
this.schemasFilter.setValue(query); this.schemasFilter.setValue(query);
@ -50,23 +53,12 @@ export class SchemasPageComponent extends AppComponentBase implements OnInit {
}); });
}); });
public schemasFilter = new FormControl();
constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService, constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService,
private readonly route: ActivatedRoute,
private readonly router: Router,
private readonly schemasService: SchemasService private readonly schemasService: SchemasService
) { ) {
super(apps, notifications, users); super(apps, notifications, users);
} }
public ngOnInit() {
this.schemasFilter.valueChanges.distinctUntilChanged().debounceTime(100)
.subscribe(f => {
this.router.navigate([], { queryParams: { schemaQuery: f }});
});
}
private loadSchemas(): Observable<SchemaDto[]> { private loadSchemas(): Observable<SchemaDto[]> {
return this.appName() return this.appName()
.switchMap(app => this.schemasService.getSchemas(app).retry(2)) .switchMap(app => this.schemasService.getSchemas(app).retry(2))

2
src/Squidex/app/features/schemas/pages/schema/field.component.html

@ -21,7 +21,7 @@
<i class="icon-settings"></i> <i class="icon-settings"></i>
</button> </button>
<div class="tooltip-dropdown"> <div class="dropdown dropdown-options">
<button type="button" class="btn btn-simple" (click)="dropdown.toggle()" [class.active]="dropdown.isOpen | async"> <button type="button" class="btn btn-simple" (click)="dropdown.toggle()" [class.active]="dropdown.isOpen | async">
<i class="icon-dots"></i> <i class="icon-dots"></i>
</button> </button>

5
src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.scss

@ -3,6 +3,11 @@
$button-size: calc(2.5rem - 2px); $button-size: calc(2.5rem - 2px);
.panel-header {
min-height: 8rem;
max-height: 8rem;
}
.subheader-button { .subheader-button {
height: $button-size; height: $button-size;
margin-right: .4rem; margin-right: .4rem;

12
src/Squidex/app/features/schemas/pages/schemas/schemas-page.component.ts

@ -7,7 +7,6 @@
import { Component, OnDestroy, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { import {
@ -46,8 +45,6 @@ export class SchemasPageComponent extends AppComponentBase implements OnDestroy,
public schemasFiltered = ImmutableArray.empty<SchemaDto>(); public schemasFiltered = ImmutableArray.empty<SchemaDto>();
constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService, constructor(apps: AppsStoreService, notifications: NotificationService, users: UsersProviderService,
private readonly route: ActivatedRoute,
private readonly router: Router,
private readonly schemasService: SchemasService, private readonly schemasService: SchemasService,
private readonly messageBus: MessageBus, private readonly messageBus: MessageBus,
private readonly authService: AuthService private readonly authService: AuthService
@ -60,12 +57,9 @@ export class SchemasPageComponent extends AppComponentBase implements OnDestroy,
} }
public ngOnInit() { public ngOnInit() {
this.schemasFilter.valueChanges.distinctUntilChanged().debounceTime(100) this.schemasFilter.valueChanges
.subscribe(q => { .distinctUntilChanged()
this.router.navigate([], { queryParams: { schemaQuery: q }}); .debounceTime(100)
});
this.route.queryParams.map(q => q['schemaQuery']).distinctUntilChanged()
.subscribe(q => { .subscribe(q => {
this.updateSchemas(this.schemas, this.schemaQuery = q); this.updateSchemas(this.schemas, this.schemaQuery = q);
}); });

2
src/Squidex/app/features/settings/pages/clients/clients-page.component.ts

@ -122,5 +122,5 @@ export class ClientsPageComponent extends AppComponentBase implements OnInit {
} }
function rename(client: AppClientDto, name: string): AppClientDto { function rename(client: AppClientDto, name: string): AppClientDto {
return new AppClientDto(client.id, client.secret, name, client.expiresUtc); return new AppClientDto(client.id, name, client.secret, client.expiresUtc);
}; };

2
src/Squidex/app/features/settings/pages/contributors/contributors-page.component.html

@ -19,7 +19,7 @@
<col style="width: 50%" /> <col style="width: 50%" />
<col style="width: 50%" /> <col style="width: 50%" />
<col style="width: 160px" /> <col style="width: 160px" />
<col style="width: 60px" /> <col style="width: 80px" />
</colgroup> </colgroup>
<thead> <thead>

4
src/Squidex/app/features/settings/pages/languages/languages-page.component.html

@ -3,7 +3,7 @@
<sqx-panel panelWidth="42rem"> <sqx-panel panelWidth="42rem">
<div class="panel-header"> <div class="panel-header">
<div class="panel-title-row"> <div class="panel-title-row">
<h3 class="panel-title">Settings</h3> <h3 class="panel-title">Languages</h3>
</div> </div>
<a class="panel-close" routerLink="../"> <a class="panel-close" routerLink="../">
@ -12,7 +12,7 @@
</div> </div>
<div class="panel-main"> <div class="panel-main">
<div class="panel-content"> <div class="panel-content panel-content-scroll">
<table class="table table-items table-fixed"> <table class="table table-items table-fixed">
<colgroup> <colgroup>
<col style="width: 60px" /> <col style="width: 60px" />

21
src/Squidex/app/framework/utils/modal-view.ts

@ -9,6 +9,7 @@ import { BehaviorSubject, Observable } from 'rxjs';
export class ModalView { export class ModalView {
private readonly isOpen$: BehaviorSubject<boolean>; private readonly isOpen$: BehaviorSubject<boolean>;
private static openView: ModalView;
public get isOpen(): Observable<boolean> { public get isOpen(): Observable<boolean> {
return this.isOpen$.distinctUntilChanged(); return this.isOpen$.distinctUntilChanged();
@ -21,20 +22,34 @@ export class ModalView {
} }
public show() { public show() {
if (ModalView.openView !== this && ModalView.openView) {
ModalView.openView.hide();
}
ModalView.openView = this;
this.isOpen$.next(true); this.isOpen$.next(true);
} }
public hide() { public hide() {
if (ModalView.openView === this) {
ModalView.openView = null;
}
this.isOpen$.next(false); this.isOpen$.next(false);
} }
public toggle() { public toggle() {
let value = false; let isOpenSnapshot = false;
this.isOpen.subscribe(v => { this.isOpen.subscribe(v => {
value = v; isOpenSnapshot = v;
}).unsubscribe(); }).unsubscribe();
this.isOpen$.next(!value); if (isOpenSnapshot) {
this.hide();
} else {
this.show();
}
} }
} }

0
src/Squidex/app/shared/app-component-base.ts → src/Squidex/app/shared/components/app-component-base.ts

2
src/Squidex/app/shared/components/app-form.component.ts

@ -11,7 +11,7 @@ import { Observable } from 'rxjs';
import { ValidatorsEx } from 'framework'; import { ValidatorsEx } from 'framework';
import { AppsStoreService } from './../services/apps-store.service'; import { AppsStoreService } from './../services/apps-store.service';
import { AppDto, CreateAppDto } from './../services/apps.service'; import { AppDto, CreateAppDto } from './../services/apps.service';
const FALLBACK_NAME = 'my-app'; const FALLBACK_NAME = 'my-app';

10
src/Squidex/app/shared/components/history.component.scss

@ -1,18 +1,10 @@
@import '_vars'; @import '_vars';
@import '_mixins'; @import '_mixins';
.user-ref {
color: $color-theme-blue-dark;
}
.marker-ref {
color: $color-theme-blue-dark;
}
.event { .event {
& { & {
@include flex-box; @include flex-box;
margin-bottom: .8rem; margin-bottom: 1rem;
} }
&-message { &-message {

10
src/Squidex/app/shared/components/history.component.ts

@ -11,11 +11,11 @@ import { Observable } from 'rxjs';
import { MessageBus, NotificationService } from 'framework'; import { MessageBus, NotificationService } from 'framework';
import { AppComponentBase } from './../app-component-base'; import { AppComponentBase } from './app-component-base';
import { AppsStoreService } from './../services/apps-store.service'; import { AppsStoreService } from './../services/apps-store.service';
import { HistoryChannelUpdated } from './../utils/messages'; import { HistoryChannelUpdated } from './../utils/messages';
import { HistoryEventDto, HistoryService } from './../services/history.service'; import { HistoryEventDto, HistoryService } from './../services/history.service';
import { UsersProviderService } from './../services/users-provider.service'; import { UsersProviderService } from './../services/users-provider.service';
const REPLACEMENT_TEMP = '$TEMP$'; const REPLACEMENT_TEMP = '$TEMP$';

16
src/Squidex/app/shared/components/language-selector.component.html

@ -0,0 +1,16 @@
<div class="btn-group btn-group-{{size}}" *ngIf="isSmallMode">
<button type="button" class="btn btn-secondary" *ngFor="let language of languages" [attr.title]="language.englishName" [class.active]="language == languageSelected" (click)="selectLanguage(language)">
<span class="iso-code">{{language.iso2Code}}</span>
</button>
</div>
<div class="dropdown-options btn-group btn-group-{{size}}" *ngIf="isLargeMode">
<button type="button" class="btn btn-secondary dropdown-toggle" [attr.title]="selectedLanguage.englishName" (click)="dropdown.toggle(); $event.stopPropagation()">
{{selectedLanguage.iso2Code}}
</button>
<div class="dropdown-menu" *sqxModalView="dropdown" closeAlways="true" [@fade]>
<div class="dropdown-item" *ngFor="let language of languages" [class.active]="language == selectedLanguage" (click)="selectLanguage(language)">
<strong class="iso-code">{{language.iso2Code}}</strong> &nbsp; &nbsp; ({{language.englishName}})
</div>
</div>
</div>

18
src/Squidex/app/shared/components/language-selector.component.scss

@ -0,0 +1,18 @@
@import '_vars';
@import '_mixins';
.btn {
font-family: monospace;
}
.active {
color: $color-accent-dark;
}
.dropdown-item {
cursor: pointer;
}
.iso-code {
font-family: monospace;
}

59
src/Squidex/app/shared/components/language-selector.component.ts

@ -0,0 +1,59 @@
/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Sebastian Stehle. All rights reserved
*/
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { fadeAnimation, ModalView } from 'framework';
export interface Language { iso2Code: string; englishName: string; isMasterLanguage: true; }
@Component({
selector: 'sqx-language-selector',
styleUrls: ['./language-selector.component.scss'],
templateUrl: './language-selector.component.html',
animations: [
fadeAnimation
]
})
export class LanguageSelectorComponent implements OnInit {
public dropdown = new ModalView(false, true);
@Input()
public size: string;
@Input()
public languages: Language[] = [];
@Input()
public selectedLanguage: Language;
@Output()
public selectedLanguageChanged = new EventEmitter<Language>();
public get isSmallMode(): boolean {
return this.languages && this.languages.length > 0 && this.languages.length <= 0;
}
public get isLargeMode(): boolean {
return this.languages && this.languages.length > 3;
}
public ngOnInit() {
if (this.languages && this.languages.length > 0 && !this.selectedLanguage) {
const selectedLanguage =
this.languages.find(l => l.isMasterLanguage) ||
this.languages[0];
this.selectLanguage(selectedLanguage);
}
}
public selectLanguage(language: Language) {
this.selectedLanguage = language;
this.selectedLanguageChanged.emit(language);
}
}

3
src/Squidex/app/shared/declarations.ts

@ -5,9 +5,11 @@
* Copyright (c) Sebastian Stehle. All rights reserved * Copyright (c) Sebastian Stehle. All rights reserved
*/ */
export * from './components/app-component-base';
export * from './components/app-form.component'; export * from './components/app-form.component';
export * from './components/dashboard-link.directive'; export * from './components/dashboard-link.directive';
export * from './components/history.component'; export * from './components/history.component';
export * from './components/language-selector.component';
export * from './guards/app-must-exist.guard'; export * from './guards/app-must-exist.guard';
export * from './guards/must-be-authenticated.guard'; export * from './guards/must-be-authenticated.guard';
@ -32,6 +34,5 @@ export * from './services/users.service';
export * from './utils/messages'; export * from './utils/messages';
export * from './app-component-base';
export * from 'framework'; export * from 'framework';

7
src/Squidex/app/shared/module.ts

@ -22,6 +22,7 @@ import {
DashboardLinkDirective, DashboardLinkDirective,
HistoryComponent, HistoryComponent,
HistoryService, HistoryService,
LanguageSelectorComponent,
LanguageService, LanguageService,
MustBeAuthenticatedGuard, MustBeAuthenticatedGuard,
MustBeNotAuthenticatedGuard, MustBeNotAuthenticatedGuard,
@ -41,12 +42,14 @@ import {
declarations: [ declarations: [
AppFormComponent, AppFormComponent,
DashboardLinkDirective, DashboardLinkDirective,
HistoryComponent HistoryComponent,
LanguageSelectorComponent
], ],
exports: [ exports: [
AppFormComponent, AppFormComponent,
DashboardLinkDirective, DashboardLinkDirective,
HistoryComponent HistoryComponent,
LanguageSelectorComponent
] ]
}) })
export class SqxSharedModule { export class SqxSharedModule {

14
src/Squidex/app/theme/_common.scss

@ -11,6 +11,14 @@ h1 {
font-size: 2rem; font-size: 2rem;
} }
.user-ref {
color: $color-theme-blue-dark;
}
.marker-ref {
color: $color-theme-blue-dark;
}
.user-picture { .user-picture {
& { & {
@include circle(2.2rem); @include circle(2.2rem);
@ -35,16 +43,16 @@ h1 {
} }
} }
.tooltip-dropdown { .dropdown-options {
& { & {
display: inline-block; display: inline-block;
} }
&-menu { .dropdown-menu {
@include absolute(100%, 0, auto, auto); @include absolute(100%, 0, auto, auto);
} }
&-item { .dropdown-item {
cursor: pointer; cursor: pointer;
} }
} }

9
src/Squidex/app/theme/_panels.scss

@ -41,7 +41,7 @@
& { & {
background: $panel-light-background; background: $panel-light-background;
min-height: $panel-header; min-height: $panel-header;
max-height: $panel-header * 3; max-height: $panel-header;
padding: $panel-padding; padding: $panel-padding;
position: relative; position: relative;
} }
@ -120,8 +120,11 @@
} }
&-title { &-title {
@include truncate;
line-height: 2rem;
font-size: 1.5rem; font-size: 1.5rem;
font-weight: 400; font-weight: 400;
padding-right: 2rem;
} }
&-row { &-row {
@ -129,11 +132,11 @@
} }
&-title-row { &-title-row {
padding-right: 2rem; padding-right: $panel-sidebar - $panel-padding;
} }
&-close { &-close {
@include absolute($panel-padding - .6rem, $panel-padding - .8rem, auto, auto); @include absolute($panel-padding - .3rem, $panel-padding - .8rem, auto, auto);
@include panel-icon; @include panel-icon;
} }
} }

BIN
src/Squidex/app/theme/icomoon/fonts/icomoon.eot

Binary file not shown.

1
src/Squidex/app/theme/icomoon/fonts/icomoon.svg

@ -27,6 +27,7 @@
<glyph unicode="&#xe90d;" glyph-name="control-radio" d="M170.667 252.952c-80.774 0-146.286-65.512-146.286-146.286s65.512-146.286 146.286-146.286c80.774 0 146.286 65.512 146.286 146.286s-65.512 146.286-146.286 146.286zM170.667 9.143c-53.858 0-97.524 43.666-97.524 97.524s43.666 97.524 97.524 97.524c53.858 0 97.524-43.666 97.524-97.524s-43.666-97.524-97.524-97.524zM390.095 764.952c-13.458 0-24.381 10.898-24.381 24.381s10.923 24.381 24.381 24.381h585.143c13.483 0 24.381-10.898 24.381-24.381s-10.898-24.381-24.381-24.381h-585.143zM975.238 472.381c13.483 0 24.381-10.898 24.381-24.381s-10.898-24.381-24.381-24.381h-585.143c-13.458 0-24.381 10.898-24.381 24.381s10.923 24.381 24.381 24.381h585.143zM170.667 935.619c-80.774 0-146.286-65.512-146.286-146.286s65.512-146.286 146.286-146.286c80.774 0 146.286 65.512 146.286 146.286s-65.512 146.286-146.286 146.286zM170.667 691.81c-53.858 0-97.524 43.666-97.524 97.524s43.666 97.524 97.524 97.524c53.858 0 97.524-43.666 97.524-97.524s-43.666-97.524-97.524-97.524zM170.667 594.286c-80.774 0-146.286-65.512-146.286-146.286s65.512-146.286 146.286-146.286c80.774 0 146.286 65.512 146.286 146.286s-65.512 146.286-146.286 146.286zM170.667 350.476c-53.858 0-97.524 43.666-97.524 97.524s43.666 97.524 97.524 97.524c53.858 0 97.524-43.666 97.524-97.524s-43.666-97.524-97.524-97.524zM170.667 838.095c26.917 0 48.762-21.845 48.762-48.762s-21.845-48.762-48.762-48.762c-26.917 0-48.762 21.845-48.762 48.762s21.845 48.762 48.762 48.762zM975.238 131.048c13.483 0 24.381-10.898 24.381-24.381s-10.898-24.381-24.381-24.381h-585.143c-13.458 0-24.381 10.898-24.381 24.381s10.923 24.381 24.381 24.381h585.143z" /> <glyph unicode="&#xe90d;" glyph-name="control-radio" d="M170.667 252.952c-80.774 0-146.286-65.512-146.286-146.286s65.512-146.286 146.286-146.286c80.774 0 146.286 65.512 146.286 146.286s-65.512 146.286-146.286 146.286zM170.667 9.143c-53.858 0-97.524 43.666-97.524 97.524s43.666 97.524 97.524 97.524c53.858 0 97.524-43.666 97.524-97.524s-43.666-97.524-97.524-97.524zM390.095 764.952c-13.458 0-24.381 10.898-24.381 24.381s10.923 24.381 24.381 24.381h585.143c13.483 0 24.381-10.898 24.381-24.381s-10.898-24.381-24.381-24.381h-585.143zM975.238 472.381c13.483 0 24.381-10.898 24.381-24.381s-10.898-24.381-24.381-24.381h-585.143c-13.458 0-24.381 10.898-24.381 24.381s10.923 24.381 24.381 24.381h585.143zM170.667 935.619c-80.774 0-146.286-65.512-146.286-146.286s65.512-146.286 146.286-146.286c80.774 0 146.286 65.512 146.286 146.286s-65.512 146.286-146.286 146.286zM170.667 691.81c-53.858 0-97.524 43.666-97.524 97.524s43.666 97.524 97.524 97.524c53.858 0 97.524-43.666 97.524-97.524s-43.666-97.524-97.524-97.524zM170.667 594.286c-80.774 0-146.286-65.512-146.286-146.286s65.512-146.286 146.286-146.286c80.774 0 146.286 65.512 146.286 146.286s-65.512 146.286-146.286 146.286zM170.667 350.476c-53.858 0-97.524 43.666-97.524 97.524s43.666 97.524 97.524 97.524c53.858 0 97.524-43.666 97.524-97.524s-43.666-97.524-97.524-97.524zM170.667 838.095c26.917 0 48.762-21.845 48.762-48.762s-21.845-48.762-48.762-48.762c-26.917 0-48.762 21.845-48.762 48.762s21.845 48.762 48.762 48.762zM975.238 131.048c13.483 0 24.381-10.898 24.381-24.381s-10.898-24.381-24.381-24.381h-585.143c-13.458 0-24.381 10.898-24.381 24.381s10.923 24.381 24.381 24.381h585.143z" />
<glyph unicode="&#xe90e;" glyph-name="media" horiz-adv-x="1152" d="M1088 832h-64v64c0 35.2-28.8 64-64 64h-896c-35.2 0-64-28.8-64-64v-768c0-35.2 28.8-64 64-64h64v-64c0-35.2 28.8-64 64-64h896c35.2 0 64 28.8 64 64v768c0 35.2-28.8 64-64 64zM128 768v-640h-63.886c-0.040 0.034-0.082 0.076-0.114 0.116v767.77c0.034 0.040 0.076 0.082 0.114 0.114h895.77c0.040-0.034 0.082-0.076 0.116-0.116v-63.884h-768c-35.2 0-64-28.8-64-64v0zM1088 0.116c-0.034-0.040-0.076-0.082-0.116-0.116h-895.77c-0.040 0.034-0.082 0.076-0.114 0.116v767.77c0.034 0.040 0.076 0.082 0.114 0.114h895.77c0.040-0.034 0.082-0.076 0.116-0.116v-767.768zM960 608c0-53.020-42.98-96-96-96s-96 42.98-96 96 42.98 96 96 96 96-42.98 96-96zM1024 64h-768v128l224 384 256-320h64l224 192z" /> <glyph unicode="&#xe90e;" glyph-name="media" horiz-adv-x="1152" d="M1088 832h-64v64c0 35.2-28.8 64-64 64h-896c-35.2 0-64-28.8-64-64v-768c0-35.2 28.8-64 64-64h64v-64c0-35.2 28.8-64 64-64h896c35.2 0 64 28.8 64 64v768c0 35.2-28.8 64-64 64zM128 768v-640h-63.886c-0.040 0.034-0.082 0.076-0.114 0.116v767.77c0.034 0.040 0.076 0.082 0.114 0.114h895.77c0.040-0.034 0.082-0.076 0.116-0.116v-63.884h-768c-35.2 0-64-28.8-64-64v0zM1088 0.116c-0.034-0.040-0.076-0.082-0.116-0.116h-895.77c-0.040 0.034-0.082 0.076-0.114 0.116v767.77c0.034 0.040 0.076 0.082 0.114 0.114h895.77c0.040-0.034 0.082-0.076 0.116-0.116v-767.768zM960 608c0-53.020-42.98-96-96-96s-96 42.98-96 96 42.98 96 96 96 96-42.98 96-96zM1024 64h-768v128l224 384 256-320h64l224 192z" />
<glyph unicode="&#xe90f;" glyph-name="angle-right" horiz-adv-x="347" d="M340 402.286c0-4.571-2.286-9.714-5.714-13.143l-266.286-266.286c-3.429-3.429-8.571-5.714-13.143-5.714s-9.714 2.286-13.143 5.714l-28.571 28.571c-3.429 3.429-5.714 8-5.714 13.143 0 4.571 2.286 9.714 5.714 13.143l224.571 224.571-224.571 224.571c-3.429 3.429-5.714 8.571-5.714 13.143s2.286 9.714 5.714 13.143l28.571 28.571c3.429 3.429 8.571 5.714 13.143 5.714s9.714-2.286 13.143-5.714l266.286-266.286c3.429-3.429 5.714-8.571 5.714-13.143z" /> <glyph unicode="&#xe90f;" glyph-name="angle-right" horiz-adv-x="347" d="M340 402.286c0-4.571-2.286-9.714-5.714-13.143l-266.286-266.286c-3.429-3.429-8.571-5.714-13.143-5.714s-9.714 2.286-13.143 5.714l-28.571 28.571c-3.429 3.429-5.714 8-5.714 13.143 0 4.571 2.286 9.714 5.714 13.143l224.571 224.571-224.571 224.571c-3.429 3.429-5.714 8.571-5.714 13.143s2.286 9.714 5.714 13.143l28.571 28.571c3.429 3.429 8.571 5.714 13.143 5.714s9.714-2.286 13.143-5.714l266.286-266.286c3.429-3.429 5.714-8.571 5.714-13.143z" />
<glyph unicode="&#xe910;" glyph-name="angle-left" horiz-adv-x="384" d="M358.286 640c0-4.571-2.286-9.714-5.714-13.143l-224.571-224.571 224.571-224.571c3.429-3.429 5.714-8.571 5.714-13.143s-2.286-9.714-5.714-13.143l-28.571-28.571c-3.429-3.429-8.571-5.714-13.143-5.714s-9.714 2.286-13.143 5.714l-266.286 266.286c-3.429 3.429-5.714 8.571-5.714 13.143s2.286 9.714 5.714 13.143l266.286 266.286c3.429 3.429 8.571 5.714 13.143 5.714s9.714-2.286 13.143-5.714l28.571-28.571c3.429-3.429 5.714-8 5.714-13.143z" />
<glyph unicode="&#xe925;" glyph-name="content" d="M917.806 602.924c-22.21 30.292-53.174 65.7-87.178 99.704s-69.412 64.964-99.704 87.178c-51.574 37.82-76.592 42.194-90.924 42.194h-368c-44.114 0-80-35.888-80-80v-736c0-44.112 35.886-80 80-80h608c44.112 0 80 35.888 80 80v496c0 14.332-4.372 39.35-42.194 90.924zM785.374 657.374c30.7-30.7 54.8-58.398 72.58-81.374h-153.954v153.946c22.982-17.78 50.678-41.878 81.374-72.572v0zM896 16c0-8.672-7.328-16-16-16h-608c-8.672 0-16 7.328-16 16v736c0 8.672 7.328 16 16 16 0 0 367.956 0.002 368 0v-224c0-17.672 14.324-32 32-32h224v-496zM602.924 917.804c-51.574 37.822-76.592 42.196-90.924 42.196h-368c-44.112 0-80-35.888-80-80v-736c0-38.632 27.528-70.958 64-78.39v814.39c0 8.672 7.328 16 16 16h486.876c-9.646 7.92-19.028 15.26-27.952 21.804z" /> <glyph unicode="&#xe925;" glyph-name="content" d="M917.806 602.924c-22.21 30.292-53.174 65.7-87.178 99.704s-69.412 64.964-99.704 87.178c-51.574 37.82-76.592 42.194-90.924 42.194h-368c-44.114 0-80-35.888-80-80v-736c0-44.112 35.886-80 80-80h608c44.112 0 80 35.888 80 80v496c0 14.332-4.372 39.35-42.194 90.924zM785.374 657.374c30.7-30.7 54.8-58.398 72.58-81.374h-153.954v153.946c22.982-17.78 50.678-41.878 81.374-72.572v0zM896 16c0-8.672-7.328-16-16-16h-608c-8.672 0-16 7.328-16 16v736c0 8.672 7.328 16 16 16 0 0 367.956 0.002 368 0v-224c0-17.672 14.324-32 32-32h224v-496zM602.924 917.804c-51.574 37.822-76.592 42.196-90.924 42.196h-368c-44.112 0-80-35.888-80-80v-736c0-38.632 27.528-70.958 64-78.39v814.39c0 8.672 7.328 16 16 16h486.876c-9.646 7.92-19.028 15.26-27.952 21.804z" />
<glyph unicode="&#xe92c;" glyph-name="copy" d="M640 704v256h-448l-192-192v-576h384v-256h640v768h-384zM192 869.49v-101.49h-101.49l101.49 101.49zM64 256v448h192v192h320v-192l-192-192v-256h-320zM576 613.49v-101.49h-101.49l101.49 101.49zM960 0h-512v448h192v192h320v-640z" /> <glyph unicode="&#xe92c;" glyph-name="copy" d="M640 704v256h-448l-192-192v-576h384v-256h640v768h-384zM192 869.49v-101.49h-101.49l101.49 101.49zM64 256v448h192v192h320v-192l-192-192v-256h-320zM576 613.49v-101.49h-101.49l101.49 101.49zM960 0h-512v448h192v192h320v-640z" />
<glyph unicode="&#xe92e;" glyph-name="schemas" d="M1024 640l-512 256-512-256 512-256 512 256zM512 811.030l342.058-171.030-342.058-171.030-342.058 171.030 342.058 171.030zM921.444 499.278l102.556-51.278-512-256-512 256 102.556 51.278 409.444-204.722zM921.444 307.278l102.556-51.278-512-256-512 256 102.556 51.278 409.444-204.722z" /> <glyph unicode="&#xe92e;" glyph-name="schemas" d="M1024 640l-512 256-512-256 512-256 512 256zM512 811.030l342.058-171.030-342.058-171.030-342.058 171.030 342.058 171.030zM921.444 499.278l102.556-51.278-512-256-512 256 102.556 51.278 409.444-204.722zM921.444 307.278l102.556-51.278-512-256-512 256 102.556 51.278 409.444-204.722z" />

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

BIN
src/Squidex/app/theme/icomoon/fonts/icomoon.ttf

Binary file not shown.

BIN
src/Squidex/app/theme/icomoon/fonts/icomoon.woff

Binary file not shown.

32
src/Squidex/app/theme/icomoon/selection.json

@ -1,6 +1,36 @@
{ {
"IcoMoonType": "selection", "IcoMoonType": "selection",
"icons": [ "icons": [
{
"icon": {
"paths": [
"M358.286 310.857c0 4.571-2.286 9.714-5.714 13.143l-224.571 224.571 224.571 224.571c3.429 3.429 5.714 8.571 5.714 13.143s-2.286 9.714-5.714 13.143l-28.571 28.571c-3.429 3.429-8.571 5.714-13.143 5.714s-9.714-2.286-13.143-5.714l-266.286-266.286c-3.429-3.429-5.714-8.571-5.714-13.143s2.286-9.714 5.714-13.143l266.286-266.286c3.429-3.429 8.571-5.714 13.143-5.714s9.714 2.286 13.143 5.714l28.571 28.571c3.429 3.429 5.714 8 5.714 13.143z"
],
"attrs": [
{}
],
"width": 384,
"isMulticolor": false,
"isMulticolor2": false,
"tags": [
"angle-left"
],
"grid": 14
},
"attrs": [
{}
],
"properties": {
"order": 1,
"id": 1,
"prevSize": 28,
"code": 59664,
"name": "angle-left"
},
"setIdx": 0,
"setId": 2,
"iconIdx": 0
},
{ {
"icon": { "icon": {
"paths": [ "paths": [
@ -29,7 +59,7 @@
}, },
"setIdx": 0, "setIdx": 0,
"setId": 2, "setId": 2,
"iconIdx": 0 "iconIdx": 1
}, },
{ {
"icon": { "icon": {

13
src/Squidex/app/theme/icomoon/style.css

@ -1,10 +1,10 @@
@font-face { @font-face {
font-family: 'icomoon'; font-family: 'icomoon';
src: url('fonts/icomoon.eot?dy118g'); src: url('fonts/icomoon.eot?n9sm4d');
src: url('fonts/icomoon.eot?dy118g#iefix') format('embedded-opentype'), src: url('fonts/icomoon.eot?n9sm4d#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?dy118g') format('truetype'), url('fonts/icomoon.ttf?n9sm4d') format('truetype'),
url('fonts/icomoon.woff?dy118g') format('woff'), url('fonts/icomoon.woff?n9sm4d') format('woff'),
url('fonts/icomoon.svg?dy118g#icomoon') format('svg'); url('fonts/icomoon.svg?n9sm4d#icomoon') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@ -24,6 +24,9 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-angle-left:before {
content: "\e910";
}
.icon-angle-right:before { .icon-angle-right:before {
content: "\e90f"; content: "\e90f";
} }

Loading…
Cancel
Save