diff --git a/.drone.yml b/.drone.yml index a507e342a..b72edbb34 100644 --- a/.drone.yml +++ b/.drone.yml @@ -21,6 +21,7 @@ pipeline: secrets: [ docker_username, docker_password ] when: event: push + branch: [master] build_release: image: docker diff --git a/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs b/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs index 3a6cd3d90..001e63229 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Schemas/Schema.cs @@ -213,7 +213,7 @@ namespace Squidex.Domain.Apps.Core.Schemas if (fieldsByName.ContainsKey(field.Name) || fieldsById.ContainsKey(field.Id)) { - throw new ArgumentException($"A field with name '{field.Name}' already exists.", nameof(field)); + throw new ArgumentException($"A field with name '{field.Name}' and id {field.Id} already exists.", nameof(field)); } return Clone(clone => diff --git a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLModel.cs b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLModel.cs index 6b6621aeb..292cc138b 100644 --- a/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLModel.cs +++ b/src/Squidex.Domain.Apps.Read/Contents/GraphQL/GraphQLModel.cs @@ -71,6 +71,10 @@ namespace Squidex.Domain.Apps.Read.Contents.GraphQL typeof(JsonField), field => ResolveDefault("Json") }, + { + typeof(TagsField), + field => ResolveDefault("String") + }, { typeof(GeolocationField), field => ResolveDefault("Geolocation") diff --git a/src/Squidex/Controllers/Api/Ping/PingController.cs b/src/Squidex/Controllers/Api/Ping/PingController.cs index 6dc65d9c6..730569034 100644 --- a/src/Squidex/Controllers/Api/Ping/PingController.cs +++ b/src/Squidex/Controllers/Api/Ping/PingController.cs @@ -25,6 +25,7 @@ namespace Squidex.Controllers.Api.Ping /// /// Get ping status. /// + /// The name of the app. /// /// 204 => Service ping successful. /// @@ -34,7 +35,7 @@ namespace Squidex.Controllers.Api.Ping [HttpGet] [Route("ping/{app}/")] [ApiCosts(0)] - public IActionResult GetPing() + public IActionResult GetPing(string app) { return NoContent(); } diff --git a/src/Squidex/Squidex.csproj b/src/Squidex/Squidex.csproj index a4bd55f55..e31771650 100644 --- a/src/Squidex/Squidex.csproj +++ b/src/Squidex/Squidex.csproj @@ -15,15 +15,15 @@ - + - + - + PreserveNewest @@ -60,7 +60,7 @@ - + @@ -88,9 +88,9 @@ - + ..\..\Squidex.ruleset - - + + \ No newline at end of file diff --git a/src/Squidex/app/features/api/pages/graphql/graphql-page.component.scss b/src/Squidex/app/features/api/pages/graphql/graphql-page.component.scss index 00a5cbf4a..f1563c37b 100644 --- a/src/Squidex/app/features/api/pages/graphql/graphql-page.component.scss +++ b/src/Squidex/app/features/api/pages/graphql/graphql-page.component.scss @@ -9,4 +9,8 @@ .graphiql-container > * { box-sizing: content-box; -} + + & .editorWrap { + overflow: hidden; + } +} \ No newline at end of file diff --git a/src/Squidex/app/features/settings/pages/languages/language.component.ts b/src/Squidex/app/features/settings/pages/languages/language.component.ts index d87f60111..25ac3b704 100644 --- a/src/Squidex/app/features/settings/pages/languages/language.component.ts +++ b/src/Squidex/app/features/settings/pages/languages/language.component.ts @@ -130,7 +130,7 @@ export class LanguageComponent implements OnInit, OnChanges, OnDestroy { this.allLanguages.filter(l => this.language.iso2Code !== l.iso2Code && this.language.fallback.indexOf(l.iso2Code) < 0); - this.otherLanguage = this.otherLanguages.values[0]; + this.otherLanguage = this.otherLanguages[0]; } if (this.language) { diff --git a/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts b/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts index 40b82b236..cb23a9962 100644 --- a/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts +++ b/src/Squidex/app/features/settings/pages/languages/languages-page.component.ts @@ -106,16 +106,7 @@ export class LanguagesPageComponent implements OnInit { this.appLanguages = new AppLanguagesDto( - appLanguages.languages.map(l => { - const isMaster = masterId ? l.iso2Code === masterId : l.isMaster; - - return new AppLanguageDto( - l.iso2Code, - l.englishName, isMaster, - l.isOptional, - l.fallback.filter(f => !!appLanguages.languages.find(l2 => l2.iso2Code === f)) - ); - }).sort((a, b) => { + appLanguages.languages.sort((a, b) => { if (a.isMaster === b.isMaster) { return a.iso2Code.localeCompare(b.iso2Code); } else { diff --git a/src/Squidex/app/framework/angular/panel-container.directive.ts b/src/Squidex/app/framework/angular/panel-container.directive.ts index 6414af63d..28abbfcc0 100644 --- a/src/Squidex/app/framework/angular/panel-container.directive.ts +++ b/src/Squidex/app/framework/angular/panel-container.directive.ts @@ -25,7 +25,7 @@ export class PanelContainerDirective implements AfterViewInit, OnDestroy { @HostListener('window:resize') public onResize() { - this.invalidate(); + this.invalidate(true); } public ngOnDestroy() { @@ -33,7 +33,7 @@ export class PanelContainerDirective implements AfterViewInit, OnDestroy { } public ngAfterViewInit() { - this.invalidate({ force: true, resize: true }); + this.invalidate(true); } public push(panel: PanelComponent) { @@ -48,14 +48,8 @@ export class PanelContainerDirective implements AfterViewInit, OnDestroy { this.invalidate(); } - public invalidate(params?: { force: boolean, resize: boolean }) { - this.isInit = this.isInit || (params && params.force) === true; - - if (!this.isInit) { - return; - } - - if (params && params.resize) { + public invalidate(resize = false) { + if (resize) { this.containerWidth = this.element.nativeElement.getBoundingClientRect().width; } @@ -67,21 +61,22 @@ export class PanelContainerDirective implements AfterViewInit, OnDestroy { for (let panel of this.panels) { const panelRoot = panel.panel.nativeElement; - let width = panel.desiredWidth; + let layoutWidth = ''; if (panel.desiredWidth === '*' && panel === last) { - panel.actualWidth = this.containerWidth - currentPosition; - - panel.desiredWidth = width + 'px'; + layoutWidth = (this.containerWidth - currentPosition) + 'px'; + } else { + layoutWidth = panel.desiredWidth; } this.renderer.setElementStyle(panelRoot, 'top', '0px'); this.renderer.setElementStyle(panelRoot, 'left', currentPosition + 'px'); + this.renderer.setElementStyle(panelRoot, 'width', layoutWidth); this.renderer.setElementStyle(panelRoot, 'bottom', '0px'); this.renderer.setElementStyle(panelRoot, 'position', 'absolute'); this.renderer.setElementStyle(panelRoot, 'z-index', currentLayer.toString()); - currentPosition += panel.actualWidth; + currentPosition += panel.renderWidth; currentLayer -= 10; } diff --git a/src/Squidex/app/framework/angular/panel.component.ts b/src/Squidex/app/framework/angular/panel.component.ts index 1a2fc8790..984050933 100644 --- a/src/Squidex/app/framework/angular/panel.component.ts +++ b/src/Squidex/app/framework/angular/panel.component.ts @@ -14,7 +14,7 @@ import { PanelContainerDirective } from './panel-container.directive'; @Component({ selector: 'sqx-panel', template: ` -
+
@@ -24,7 +24,7 @@ import { PanelContainerDirective } from './panel-container.directive'; ] }) export class PanelComponent implements AfterViewInit, OnDestroy, OnInit { - public actualWidth = 0; + public renderWidth = 0; @Input() public theme = 'light'; @@ -32,9 +32,6 @@ export class PanelComponent implements AfterViewInit, OnDestroy, OnInit { @Input() public desiredWidth = '10rem'; - @Input() - public expand = false; - @ViewChild('panel') public panel: ElementRef; @@ -52,7 +49,7 @@ export class PanelComponent implements AfterViewInit, OnDestroy, OnInit { } public ngAfterViewInit() { - this.actualWidth = this.panel.nativeElement.getBoundingClientRect().width; + this.renderWidth = this.panel.nativeElement.getBoundingClientRect().width; this.container.invalidate(); } diff --git a/src/Squidex/app/shared/services/app-languages.service.spec.ts b/src/Squidex/app/shared/services/app-languages.service.spec.ts index 9b249ae45..b9f8b1c03 100644 --- a/src/Squidex/app/shared/services/app-languages.service.spec.ts +++ b/src/Squidex/app/shared/services/app-languages.service.spec.ts @@ -20,34 +20,56 @@ import { } from './../'; describe('AppLanguageDto', () => { - const language1 = new AppLanguageDto('de', 'English', false, false, []); - const language2 = new AppLanguageDto('en', 'English', false, false, []); - const language2_new = new AppLanguageDto('en', 'English (United States)', false, false, []); const version = new Version('1'); const newVersion = new Version('2'); it('should update languages when adding language', () => { - const languages_1 = new AppLanguagesDto([language1], version); - const languages_2 = languages_1.addLanguage(language2, newVersion); + const language1_1 = new AppLanguageDto('de', 'English', true, false, []); + const language2_1 = new AppLanguageDto('it', 'Italien', false, false, []); - expect(languages_2.languages).toEqual([language1, language2]); + const languages_1 = new AppLanguagesDto([language1_1], version); + const languages_2 = languages_1.addLanguage(language2_1, newVersion); + + expect(languages_2.languages).toEqual([language1_1, language2_1]); expect(languages_2.version).toEqual(newVersion); }); it('should update languages when removing language', () => { - const languages_1 = new AppLanguagesDto([language1, language2], version); - const languages_2 = languages_1.removeLanguage(language1, newVersion); + const language1_1 = new AppLanguageDto('de', 'English', true, false, ['it']); + const language1_2 = new AppLanguageDto('de', 'English', true, false, []); + const language2_1 = new AppLanguageDto('it', 'Italien', false, false, []); + + const languages_1 = new AppLanguagesDto([language1_1, language2_1], version); + const languages_2 = languages_1.removeLanguage(language2_1, newVersion); - expect(languages_2.languages).toEqual([language2]); + expect(languages_2.languages).toEqual([language1_2]); expect(languages_2.version).toEqual(newVersion); }); it('should update languages when updating language', () => { - const languages_1 = new AppLanguagesDto([language1, language2], version); - const languages_2 = languages_1.updateLanguage(language2_new, newVersion); + const language1_1 = new AppLanguageDto('de', 'English', true, false, ['it']); + const language2_1 = new AppLanguageDto('it', 'Italien', false, false, []); + const language2_2 = new AppLanguageDto('it', 'Italien', false, false, ['de']); + + const languages_1 = new AppLanguagesDto([language1_1, language2_1], version); + const languages_2 = languages_1.updateLanguage(language2_2, newVersion); + + expect(languages_2.languages).toEqual([language1_1, language2_2]); + expect(languages_2.version).toEqual(newVersion); + }); + + it('should update master language when updating language', () => { + const language1_1 = new AppLanguageDto('de', 'English', true, false, ['it']); + const language1_2 = new AppLanguageDto('de', 'English', false, false, ['it']); + const language2_1 = new AppLanguageDto('it', 'Italien', false, false, []); + const language2_2 = new AppLanguageDto('it', 'Italien', true, false, ['de']); + + const languages_1 = new AppLanguagesDto([language1_1, language2_1], version); + const languages_2 = languages_1.updateLanguage(language2_2, newVersion); - expect(languages_2.languages).toEqual([language1, language2_new]); + expect(languages_2.languages).toEqual([language1_2, language2_2]); expect(languages_2.version).toEqual(newVersion); + expect(languages_2.languages[0].isMaster).toBeFalsy(); }); }); diff --git a/src/Squidex/app/shared/services/app-languages.service.ts b/src/Squidex/app/shared/services/app-languages.service.ts index f5da2e4fb..78f6bc6e9 100644 --- a/src/Squidex/app/shared/services/app-languages.service.ts +++ b/src/Squidex/app/shared/services/app-languages.service.ts @@ -30,12 +30,29 @@ export class AppLanguagesDto { return new AppLanguagesDto([...this.languages, language], version); } - public updateLanguage(language: AppLanguageDto, version: Version) { - return new AppLanguagesDto(this.languages.map(l => l.iso2Code === language.iso2Code ? language : l), version); + public removeLanguage(language: AppLanguageDto, version: Version) { + return new AppLanguagesDto( + this.languages.filter(l => l.iso2Code !== language.iso2Code).map(l => { + return new AppLanguageDto( + l.iso2Code, + l.englishName, + l.isMaster, + l.isOptional, + l.fallback.filter(f => f !== language.iso2Code)); + }), version); } - public removeLanguage(language: AppLanguageDto, version: Version) { - return new AppLanguagesDto(this.languages.filter(l => l.iso2Code !== language.iso2Code), version); + public updateLanguage(language: AppLanguageDto, version: Version) { + return new AppLanguagesDto( + this.languages.map(l => { + if (l.iso2Code === language.iso2Code) { + return language; + } else if (l.isMaster && language.isMaster) { + return new AppLanguageDto(l.iso2Code, l.englishName, false, l.isOptional, l.fallback); + } else { + return l; + } + }), version); } } diff --git a/src/Squidex/app/shell/pages/internal/apps-menu.component.html b/src/Squidex/app/shell/pages/internal/apps-menu.component.html index 27315a568..6e8ccfa47 100644 --- a/src/Squidex/app/shell/pages/internal/apps-menu.component.html +++ b/src/Squidex/app/shell/pages/internal/apps-menu.component.html @@ -1,8 +1,8 @@ -