Browse Source

Fixes (#992)

* Exception handling for scheduler.

* Image hover

* Fix transfer.
pull/995/head
Sebastian Stehle 3 years ago
committed by GitHub
parent
commit
9dfee4dc06
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      backend/src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerProcess.cs
  2. 4
      frontend/src/app/features/settings/pages/more/more-page.component.html
  3. 10
      frontend/src/app/framework/angular/long-hover.directive.ts
  4. 15
      frontend/src/app/shared/components/contents/content-value.component.html
  5. 9
      frontend/src/app/shared/components/contents/content-value.component.scss
  6. 19
      frontend/src/app/shared/components/contents/content-value.component.ts
  7. 4
      frontend/src/app/shared/state/apps.forms.ts
  8. 10
      frontend/src/app/shared/state/contents.forms.visitors.ts

14
backend/src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerProcess.cs

@ -7,6 +7,7 @@
using Microsoft.Extensions.Logging;
using NodaTime;
using Squidex.ClientLibrary;
using Squidex.Domain.Apps.Entities.Contents.Commands;
using Squidex.Domain.Apps.Entities.Contents.Repositories;
using Squidex.Hosting;
@ -52,11 +53,18 @@ public sealed class ContentSchedulerProcess : IBackgroundProcess
public async Task PublishAsync(
CancellationToken ct = default)
{
var now = Clock.GetCurrentInstant();
try
{
var now = Clock.GetCurrentInstant();
await foreach (var content in contentRepository.StreamScheduledWithoutDataAsync(now, SearchScope.All, ct))
await foreach (var content in contentRepository.StreamScheduledWithoutDataAsync(now, SearchScope.All, ct))
{
await TryPublishAsync(content);
}
}
catch (Exception ex)
{
await TryPublishAsync(content);
log.LogError(ex, "Failed to query scheduled status changes-");
}
}

4
frontend/src/app/features/settings/pages/more/more-page.component.html

@ -90,7 +90,7 @@
<div class="col-6">
<h5>{{ 'apps.transferTitle' | sqxTranslate }}</h5>
<small>{{ 'apps.transferWarning' | sqxTranslate }}</small>
<sqx-form-hint>{{ 'apps.transferWarning' | sqxTranslate }}</sqx-form-hint>
</div>
<div class="col">
<select class="form-select" formControlName="teamId">
@ -112,7 +112,7 @@
<div class="col">
<h5>{{ 'apps.delete' | sqxTranslate }}</h5>
<small>{{ 'apps.deleteWarning' | sqxTranslate }}</small>
<sqx-form-hint>{{ 'apps.deleteWarning' | sqxTranslate }}</sqx-form-hint>
</div>
<div class="col-auto">
<button type="button" class="btn btn-danger" [disabled]="!isDeletable"

10
frontend/src/app/framework/angular/long-hover.directive.ts

@ -13,6 +13,7 @@ import { Directive, EventEmitter, HostListener, Input, Output, Renderer2 } from
export class LongHoverDirective {
private timerOut: Function | null = null;
private timer?: any;
private wasHovering = false;
@Output('sqxLongHover')
public hover = new EventEmitter();
@ -49,7 +50,11 @@ export class LongHoverDirective {
return;
}
this.wasHovering = false;
this.timer = setTimeout(() => {
this.wasHovering = true;
this.hover.emit();
}, this.duration);
@ -60,8 +65,11 @@ export class LongHoverDirective {
private clearTimer() {
if (this.timer) {
if (this.wasHovering) {
this.cancelled.emit();
}
clearTimeout(this.timer);
this.cancelled.emit();
this.timer = null;
this.timerOut?.();
this.timerOut = null;

15
frontend/src/app/shared/components/contents/content-value.component.html

@ -8,5 +8,18 @@
</button>
</ng-container>
<ng-template #html>
<div class="html-value" [innerHTML]="value.html"></div>
<div #htmlValue
(sqxLongHover)="show()"
(longHoverCancelled)="hide()"
[longHoverSelector]="'img'"
[longHoverDuration]="1500"
[innerHTML]="value.html"
class="html-value" >
</div>
<ng-container *sqxModal="previewModal;closeAuto:false">
<div class="preview" [sqxAnchoredTo]="htmlValue" anchorX="left-to-left">
<img [src]="value.preview" />
</div>
</ng-container>
</ng-template>

9
frontend/src/app/shared/components/contents/content-value.component.scss

@ -47,6 +47,15 @@
}
}
.preview {
img {
@include box-shadow-outer(0, 3px, 16px, 0.2);
background-image: $asset-background;
max-width: 300px;
max-height: 300px;
}
}
.value-container {
cursor: default;
max-height: 10rem;

19
frontend/src/app/shared/components/contents/content-value.component.ts

@ -5,8 +5,8 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
import { StatefulComponent, TypedSimpleChanges } from '@app/framework';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input } from '@angular/core';
import { ModalModel, StatefulComponent, TypedSimpleChanges } from '@app/framework';
import { HtmlValue, TableField, TableSettings, Types } from '@app/shared/internal';
interface State {
@ -29,8 +29,7 @@ export class ContentValueComponent extends StatefulComponent<State> {
@Input()
public fields?: TableSettings;
@Output()
public preview = new EventEmitter<string>();
public previewModal = new ModalModel();
public get title() {
return this.isString && this.isPlain ? this.value : undefined;
@ -68,4 +67,16 @@ export class ContentValueComponent extends StatefulComponent<State> {
this.fields?.toggleWrapping(this.field?.name);
}
public show() {
if (!Types.is(this.value, HtmlValue) || !this.value.preview) {
return;
}
this.previewModal.show();
}
public hide() {
this.previewModal.hide();
}
}

4
frontend/src/app/shared/state/apps.forms.ts

@ -26,9 +26,7 @@ export class CreateAppForm extends Form<ExtendedFormGroup, CreateAppDto> {
export class TransferAppForm extends Form<ExtendedFormGroup, TransferToTeamDto, AppDto> {
constructor() {
super(new ExtendedFormGroup({
teamId: new UntypedFormControl('',
Validators.required,
),
teamId: new UntypedFormControl(''),
}));
}
}

10
frontend/src/app/shared/state/contents.forms.visitors.ts

@ -52,10 +52,14 @@ export function getContentValue(content: ContentDto, language: LanguageDto, fiel
if (value.length === 2) {
const previewMode = field.properties['previewMode'];
const buildImage = (src: string) => {
return `<img src="${src}?width=50&height=50&mode=Pad" />`;
};
if (previewMode === 'ImageAndFileName') {
formatted = new HtmlValue(`<img src="${value[0]}?width=50&height=50&mode=Pad" /> <span>${value[1]}</span>`, value[0]);
formatted = new HtmlValue(buildImage(value[0]) + ` <span>${value[1]}</span>`, value[0]);
} else if (previewMode === 'Image') {
formatted = new HtmlValue(`<img src="${value[0]}?width=50&height=50&mode=Pad" />`, value[0]);
formatted = new HtmlValue(buildImage(value[0]), value[0]);
} else {
formatted = value[1];
}
@ -207,7 +211,7 @@ export class FieldFormatter implements FieldPropertiesVisitor<FieldValue> {
}
if (properties.editor === 'StockPhoto' && this.allowHtml && this.value) {
return new HtmlValue(`<img src="${thumbnail(this.value, undefined, 50)}" />`);
return new HtmlValue(`<img src="${thumbnail(this.value, undefined, 50)}" />`, this.value);
}
return this.value;

Loading…
Cancel
Save