mirror of https://github.com/Squidex/squidex.git
Browse Source
* Temp * Temp * Update * Temp * Fix track-by * Build fixes * Migration to new flow. * More manual fixes. * Reformat templates. * Fix tests * Improve tests * Revert change.pull/1098/head
committed by
GitHub
527 changed files with 26559 additions and 26910 deletions
@ -1,18 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
||||
// All rights reserved. Licensed under the MIT license.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using Microsoft.AspNetCore.Builder; |
|
||||
|
|
||||
namespace Squidex.Web; |
|
||||
|
|
||||
public static class BuilderExtensions |
|
||||
{ |
|
||||
public static void UseWhenPath(this IApplicationBuilder builder, string path, Action<IApplicationBuilder> configurator) |
|
||||
{ |
|
||||
builder.UseWhen(c => c.Request.Path.StartsWithSegments(path, StringComparison.OrdinalIgnoreCase), configurator); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,20 @@ |
|||||
|
{ |
||||
|
"plugins": ["squidex-prettier-plugin-organize-attributes"], |
||||
|
"overrides": [ |
||||
|
{ |
||||
|
"files": "*.html", |
||||
|
"options": { |
||||
|
"attributeGroups": ["$ANGULAR"], |
||||
|
"attributeIgnoreChars": "[]()*", |
||||
|
"attributeSort": "ASC", |
||||
|
"parser": "angular", |
||||
|
"printWidth": 140, |
||||
|
"bracketSameLine": true, |
||||
|
"bracketSpacing": true, |
||||
|
"singleAttributePerLine": false, |
||||
|
"tabWidth": 4 |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
"tabWidth": 4 |
||||
|
} |
||||
File diff suppressed because it is too large
@ -1,27 +1,36 @@ |
|||||
<tr [class.faulted]="eventConsumer.error && eventConsumer.error && eventConsumer.error.length > 0"> |
<tr [class.faulted]="eventConsumer.error && eventConsumer.error && eventConsumer.error.length > 0"> |
||||
<td class="cell-auto"> |
<td class="cell-auto"> |
||||
<span class="truncate"> |
<span class="truncate"> |
||||
<i class="faulted-icon icon icon-bug" (click)="failure.emit()" [class.hidden]="!eventConsumer.error || eventConsumer.error.length === 0"></i> |
<i |
||||
|
class="faulted-icon icon icon-bug" |
||||
|
[class.hidden]="!eventConsumer.error || eventConsumer.error.length === 0" |
||||
|
(click)="failure.emit()"></i> |
||||
|
|
||||
{{eventConsumer.name}} |
{{ eventConsumer.name }} |
||||
</span> |
</span> |
||||
</td> |
</td> |
||||
<td class="cell-auto-right"> |
<td class="cell-auto-right"> |
||||
<span>{{eventConsumer.count}}</span> |
<span>{{ eventConsumer.count }}</span> |
||||
</td> |
</td> |
||||
<td class="cell-auto-right"> |
<td class="cell-auto-right"> |
||||
<span>{{eventConsumer.position}}</span> |
<span>{{ eventConsumer.position }}</span> |
||||
</td> |
</td> |
||||
<td class="cell-actions-lg"> |
<td class="cell-actions-lg"> |
||||
<button type="button" class="btn btn-text-secondary" (click)="reset()" *ngIf="eventConsumer.canReset" title="i18n:eventConsumers.resetTooltip"> |
@if (eventConsumer.canReset) { |
||||
<i class="icon icon-reset"></i> |
<button class="btn btn-text-secondary" (click)="reset()" title="i18n:eventConsumers.resetTooltip" type="button"> |
||||
</button> |
<i class="icon icon-reset"></i> |
||||
<button type="button" class="btn btn-text-secondary" (click)="start()" *ngIf="eventConsumer.canStart" title="i18n:eventConsumers.startTooltip"> |
</button> |
||||
<i class="icon icon-play"></i> |
} |
||||
</button> |
@if (eventConsumer.canStart) { |
||||
<button type="button" class="btn btn-text-secondary" (click)="stop()" *ngIf="eventConsumer.canStop" title="i18n:eventConsumers.stopTooltip"> |
<button class="btn btn-text-secondary" (click)="start()" title="i18n:eventConsumers.startTooltip" type="button"> |
||||
<i class="icon icon-pause"></i> |
<i class="icon icon-play"></i> |
||||
</button> |
</button> |
||||
|
} |
||||
|
@if (eventConsumer.canStop) { |
||||
|
<button class="btn btn-text-secondary" (click)="stop()" title="i18n:eventConsumers.stopTooltip" type="button"> |
||||
|
<i class="icon icon-pause"></i> |
||||
|
</button> |
||||
|
} |
||||
</td> |
</td> |
||||
</tr> |
</tr> |
||||
<tr class="spacer"></tr> |
<tr class="spacer"></tr> |
||||
|
|||||
@ -1,79 +1,104 @@ |
|||||
|
|
||||
<form [formGroup]="userForm.form" (ngSubmit)="save()"> |
<form [formGroup]="userForm.form" (ngSubmit)="save()"> |
||||
<input style="display: none;" type="password" name="foilautofill"> |
<input name="foilautofill" style="display: none" type="password" /> |
||||
|
|
||||
<sqx-layout layout="right" width="30" white="true" padding="true" overflow="true"> |
<sqx-layout layout="right" overflow="true" padding="true" white="true" width="30"> |
||||
<ng-container title> |
<ng-container title> |
||||
<ng-container *ngIf="usersState.selectedUser | async; else noUserTitle"> |
@if (usersState.selectedUser | async) { |
||||
<sqx-title message="i18n:users.editPageTitle"></sqx-title> |
<sqx-title message="i18n:users.editPageTitle"></sqx-title> |
||||
|
<h3>{{ "users.editTitle" | sqxTranslate }}</h3> |
||||
<h3>{{ 'users.editTitle' | sqxTranslate }}</h3> |
} @else { |
||||
</ng-container> |
|
||||
|
|
||||
<ng-template #noUserTitle> |
|
||||
<sqx-title message="i18n:users.createPageTitle"></sqx-title> |
<sqx-title message="i18n:users.createPageTitle"></sqx-title> |
||||
|
<h3>{{ "users.createTitle" | sqxTranslate }}</h3> |
||||
<h3>{{ 'users.createTitle' | sqxTranslate }}</h3> |
} |
||||
</ng-template> |
|
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container menu> |
<ng-container menu> |
||||
<ng-container *ngIf="usersState.selectedUser | async; let user; else noUserMenu"> |
@if (usersState.selectedUser | async; as user) { |
||||
<button type="submit" class="btn btn-primary" shortcut="CTRL + SHIFT + S" *ngIf="isEditable"> |
@if (isEditable) { |
||||
{{ 'common.save' | sqxTranslate }} |
<button class="btn btn-primary" shortcut="CTRL + SHIFT + S" type="submit"> |
||||
</button> |
{{ "common.save" | sqxTranslate }} |
||||
</ng-container> |
</button> |
||||
|
} |
||||
<ng-template #noUserMenu> |
} @else { |
||||
<button type="submit" class="btn btn-primary" shortcut="CTRL + SHIFT + S"> |
<button class="btn btn-primary" shortcut="CTRL + SHIFT + S" type="submit"> |
||||
{{ 'common.save' | sqxTranslate }} |
{{ "common.save" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</ng-template> |
} |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container > |
<ng-container> |
||||
<sqx-form-error [error]="userForm.error | async"></sqx-form-error> |
<sqx-form-error [error]="userForm.error | async"></sqx-form-error> |
||||
|
|
||||
<div class="form-group"> |
<div class="form-group"> |
||||
<label for="email">{{ 'common.email' | sqxTranslate }} <small class="hint">({{ 'common.requiredHint' | sqxTranslate }})</small></label> |
<label for="email"> |
||||
|
{{ "common.email" | sqxTranslate }} |
||||
|
<small class="hint">({{ "common.requiredHint" | sqxTranslate }})</small> |
||||
|
</label> |
||||
|
|
||||
<sqx-control-errors for="email"></sqx-control-errors> |
<sqx-control-errors for="email"></sqx-control-errors> |
||||
|
|
||||
<input type="email" class="form-control" id="email" maxlength="100" formControlName="email" autocomplete="off"> |
<input class="form-control" id="email" autocomplete="off" formControlName="email" maxlength="100" type="email" /> |
||||
</div> |
</div> |
||||
<div class="form-group"> |
<div class="form-group"> |
||||
<label for="displayName">{{ 'common.displayName' | sqxTranslate }} <small class="hint">({{ 'common.requiredHint' | sqxTranslate }})</small></label> |
<label for="displayName"> |
||||
|
{{ "common.displayName" | sqxTranslate }} |
||||
|
<small class="hint">({{ "common.requiredHint" | sqxTranslate }})</small> |
||||
|
</label> |
||||
|
|
||||
<sqx-control-errors for="displayName"></sqx-control-errors> |
<sqx-control-errors for="displayName"></sqx-control-errors> |
||||
|
|
||||
<input class="form-control" id="displayName" maxlength="100" formControlName="displayName" autocomplete="off" spellcheck="false"> |
<input |
||||
|
class="form-control" |
||||
|
id="displayName" |
||||
|
autocomplete="off" |
||||
|
formControlName="displayName" |
||||
|
maxlength="100" |
||||
|
spellcheck="false" /> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="form-group form-group-section"> |
<div class="form-group form-group-section"> |
||||
<div class="form-group"> |
<div class="form-group"> |
||||
<label for="password">{{ 'common.password' | sqxTranslate }}</label> |
<label for="password">{{ "common.password" | sqxTranslate }}</label> |
||||
|
|
||||
<sqx-control-errors for="password"></sqx-control-errors> |
<sqx-control-errors for="password"></sqx-control-errors> |
||||
|
|
||||
<input type="password" class="form-control" id="password" maxlength="100" formControlName="password" autocomplete="off"> |
<input |
||||
|
class="form-control" |
||||
|
id="password" |
||||
|
autocomplete="off" |
||||
|
formControlName="password" |
||||
|
maxlength="100" |
||||
|
type="password" /> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="form-group"> |
<div class="form-group"> |
||||
<label for="password">{{ 'common.passwordConfirm' | sqxTranslate }}</label> |
<label for="password">{{ "common.passwordConfirm" | sqxTranslate }}</label> |
||||
|
|
||||
<sqx-control-errors for="passwordConfirm"></sqx-control-errors> |
<sqx-control-errors for="passwordConfirm"></sqx-control-errors> |
||||
|
|
||||
<input type="password" class="form-control" id="passwordConfirm" maxlength="100" formControlName="passwordConfirm" autocomplete="off"> |
<input |
||||
|
class="form-control" |
||||
|
id="passwordConfirm" |
||||
|
autocomplete="off" |
||||
|
formControlName="passwordConfirm" |
||||
|
maxlength="100" |
||||
|
type="password" /> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="form-group form-group-section"> |
<div class="form-group form-group-section"> |
||||
<label for="permissions">{{ 'common.permissions' | sqxTranslate }}</label> |
<label for="permissions">{{ "common.permissions" | sqxTranslate }}</label> |
||||
|
|
||||
<sqx-control-errors for="permissions"></sqx-control-errors> |
<sqx-control-errors for="permissions"></sqx-control-errors> |
||||
|
|
||||
<textarea class="form-control" id="permissions" formControlName="permissions" placeholder="{{ 'common.separateByLine' | sqxTranslate }}" autocomplete="off" spellcheck="false"></textarea> |
<textarea |
||||
|
class="form-control" |
||||
|
id="permissions" |
||||
|
autocomplete="off" |
||||
|
formControlName="permissions" |
||||
|
placeholder="{{ 'common.separateByLine' | sqxTranslate }}" |
||||
|
spellcheck="false"></textarea> |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-layout> |
</sqx-layout> |
||||
</form> |
</form> |
||||
|
|||||
@ -1,29 +1,36 @@ |
|||||
<tr [routerLink]="user.id" queryParamsHandling="preserve" routerLinkActive="active"> |
<tr queryParamsHandling="preserve" [routerLink]="user.id" routerLinkActive="active"> |
||||
<td class="cell-user"> |
<td class="cell-user"> |
||||
<img class="user-picture" title="{{user.displayName}}" [src]="user | sqxUserDtoPicture"> |
<img class="user-picture" [src]="user | sqxUserDtoPicture" title="{{ user.displayName }}" /> |
||||
</td> |
</td> |
||||
<td class="cell-auto"> |
<td class="cell-auto"> |
||||
<span class="user-name table-cell">{{user.displayName}}</span> |
<span class="user-name table-cell">{{ user.displayName }}</span> |
||||
</td> |
</td> |
||||
<td class="cell-auto"> |
<td class="cell-auto"> |
||||
<span class="user-email table-cell">{{user.email}}</span> |
<span class="user-email table-cell">{{ user.email }}</span> |
||||
</td> |
</td> |
||||
<td class="cell-actions-lg"> |
<td class="cell-actions-lg"> |
||||
<button type="button" class="btn btn-text-secondary" (click)="lock()" sqxStopClick *ngIf="user.canLock" title="i18n:users.lockTooltip"> |
@if (user.canLock) { |
||||
<i class="icon icon-unlocked"></i> |
<button class="btn btn-text-secondary" (click)="lock()" sqxStopClick title="i18n:users.lockTooltip" type="button"> |
||||
</button> |
<i class="icon icon-unlocked"></i> |
||||
<button type="button" class="btn btn-text-secondary" (click)="unlock()" sqxStopClick *ngIf="user.canUnlock" title="i18n:users.unlockTooltip"> |
</button> |
||||
<i class="icon icon-lock"></i> |
} |
||||
</button> |
@if (user.canUnlock) { |
||||
|
<button class="btn btn-text-secondary" (click)="unlock()" sqxStopClick title="i18n:users.unlockTooltip" type="button"> |
||||
|
<i class="icon icon-lock"></i> |
||||
|
</button> |
||||
|
} |
||||
|
|
||||
<button type="button" class="btn btn-text-danger" [disabled]="!user.canDelete" |
<button |
||||
(sqxConfirmClick)="delete()" |
class="btn btn-text-danger" |
||||
confirmTitle="i18n:users.deleteConfirmTitle" |
|
||||
confirmText="i18n:users.deleteConfirmText" |
|
||||
confirmRememberKey="deleteUser" |
confirmRememberKey="deleteUser" |
||||
sqxStopClick> |
confirmText="i18n:users.deleteConfirmText" |
||||
|
confirmTitle="i18n:users.deleteConfirmTitle" |
||||
|
[disabled]="!user.canDelete" |
||||
|
(sqxConfirmClick)="delete()" |
||||
|
sqxStopClick |
||||
|
type="button"> |
||||
<i class="icon-bin2"></i> |
<i class="icon-bin2"></i> |
||||
</button> |
</button> |
||||
</td> |
</td> |
||||
</tr> |
</tr> |
||||
<tr class="spacer"></tr> |
<tr class="spacer"></tr> |
||||
|
|||||
@ -1,29 +1,29 @@ |
|||||
<sqx-title message="i18n:api.pageTitle"></sqx-title> |
<sqx-title message="i18n:api.pageTitle"></sqx-title> |
||||
|
|
||||
<sqx-layout layout="left" titleText="i18n:api.title" titleIcon="api" width="16" white="true" overflow="true" padding="true"> |
<sqx-layout layout="left" overflow="true" padding="true" titleIcon="api" titleText="i18n:api.title" white="true" width="16"> |
||||
<ng-container> |
<ng-container> |
||||
<ul class="nav nav-light flex-column"> |
<ul class="nav nav-light flex-column"> |
||||
<li class="nav-item" sqxTourStep="graphql"> |
<li class="nav-item" sqxTourStep="graphql"> |
||||
<a class="nav-link" routerLink="graphql" routerLinkActive="active"> |
<a class="nav-link" routerLink="graphql" routerLinkActive="active"> |
||||
{{ 'api.graphql' | sqxTranslate }} |
{{ "api.graphql" | sqxTranslate }} |
||||
</a> |
</a> |
||||
</li> |
</li> |
||||
|
|
||||
<li class="nav-item nav-heading"> |
<li class="nav-item nav-heading"> |
||||
{{ 'common.openAPI' | sqxTranslate }} |
{{ "common.openAPI" | sqxTranslate }} |
||||
</li> |
</li> |
||||
<li class="nav-item" sqxTourStep="contentApi"> |
<li class="nav-item" sqxTourStep="contentApi"> |
||||
<a class="nav-link" href="/api/content/{{appsState.appName}}/docs" sqxExternalLink> |
<a class="nav-link" href="/api/content/{{ appsState.appName }}/docs" sqxExternalLink> |
||||
{{ 'api.contentApi' | sqxTranslate }} |
{{ "api.contentApi" | sqxTranslate }} |
||||
</a> |
</a> |
||||
</li> |
</li> |
||||
<li class="nav-item" sqxTourStep="generalAPi"> |
<li class="nav-item" sqxTourStep="generalAPi"> |
||||
<a class="nav-link" href="/api/docs" sqxExternalLink> |
<a class="nav-link" href="/api/docs" sqxExternalLink> |
||||
{{ 'api.generalApi' | sqxTranslate }} |
{{ "api.generalApi" | sqxTranslate }} |
||||
</a> |
</a> |
||||
</li> |
</li> |
||||
</ul> |
</ul> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-layout> |
</sqx-layout> |
||||
|
|
||||
<router-outlet></router-outlet> |
<router-outlet></router-outlet> |
||||
|
|||||
@ -1,38 +1,40 @@ |
|||||
<sqx-title message="i18n:api.graphqlPageTitle"></sqx-title> |
<sqx-title message="i18n:api.graphqlPageTitle"></sqx-title> |
||||
|
|
||||
<sqx-layout layout="main" hideHeader="true" hideSidebar="true"> |
<sqx-layout hideHeader="true" hideSidebar="true" layout="main"> |
||||
<div inner #graphiQLContainer sqxTourStep="graphQLExplorer"></div> |
<div #graphiQLContainer inner sqxTourStep="graphQLExplorer"></div> |
||||
|
|
||||
<button class="btn btn-simple btn-options" *ngIf="clientsReadable" (click)="clientsDialog.show()"> |
@if (clientsReadable) { |
||||
<i class="icon-clients"></i> |
<button class="btn btn-simple btn-options" (click)="clientsDialog.show()"> |
||||
</button> |
<i class="icon-clients"></i> |
||||
|
</button> |
||||
|
} |
||||
</sqx-layout> |
</sqx-layout> |
||||
|
|
||||
<sqx-modal-dialog *sqxModal="clientsDialog" (dialogClose)="clientsDialog.hide()"> |
<sqx-modal-dialog (dialogClose)="clientsDialog.hide()" *sqxModal="clientsDialog"> |
||||
<ng-container title> |
<ng-container title> |
||||
{{ 'api.selectClient' | sqxTranslate }} |
{{ "api.selectClient" | sqxTranslate }} |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container content> |
<ng-container content> |
||||
<sqx-form-hint> |
<sqx-form-hint> |
||||
{{ 'api.selectClientDescription' | sqxTranslate }} |
{{ "api.selectClientDescription" | sqxTranslate }} |
||||
</sqx-form-hint> |
</sqx-form-hint> |
||||
|
|
||||
<div class="form-group"> |
<div class="form-group"> |
||||
<label for="client">{{ 'common.client' | sqxTranslate }}</label> |
<label for="client">{{ "common.client" | sqxTranslate }}</label> |
||||
|
|
||||
<select class="form-control" id="client" |
<select class="form-control" id="client" [ngModel]="clientSelected" (ngModelChange)="selectClient($event)"> |
||||
[ngModel]="clientSelected" |
<option [ngValue]="null">{{ "api.noClient" | sqxTranslate }}</option> |
||||
(ngModelChange)="selectClient($event)"> |
@for (client of clientsState.clients | async; track client) { |
||||
<option [ngValue]="null">{{ 'api.noClient' | sqxTranslate }}</option> |
<option [ngValue]="client">{{ client.id }}</option> |
||||
<option *ngFor="let client of clientsState.clients | async" [ngValue]="client">{{client.id}}</option> |
} |
||||
</select> |
</select> |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container footer> |
<ng-container footer> |
||||
<button type="button" class="btn btn-text-secondary" (click)="clientsDialog.hide()"> |
<button class="btn btn-text-secondary" (click)="clientsDialog.hide()" type="button"> |
||||
{{ 'common.close' | sqxTranslate }} |
{{ "common.close" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-modal-dialog> |
</sqx-modal-dialog> |
||||
|
|||||
@ -1,79 +1,77 @@ |
|||||
<sqx-title message="i18n:apps.listPageTitle"></sqx-title> |
<sqx-title message="i18n:apps.listPageTitle"></sqx-title> |
||||
|
|
||||
<div class="panel-container page" *ngIf="authState.userChanges | async; let user"> |
@if (authState.userChanges | async; as user) { |
||||
<div class="apps-section"> |
<div class="panel-container page"> |
||||
<h1 class="apps-title">{{ 'apps.welcomeTitle' | sqxTranslate: { user: user.displayName } }}</h1> |
<div class="apps-section"> |
||||
|
<h1 class="apps-title">{{ "apps.welcomeTitle" | sqxTranslate: { user: user.displayName } }}</h1> |
||||
<div class="subtext"> |
<div class="subtext"> |
||||
{{ 'apps.welcomeSubtitle' | sqxTranslate }} |
{{ "apps.welcomeSubtitle" | sqxTranslate }} |
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<ng-container *ngIf="groupedApps | async; let groups"> |
|
||||
<div class="apps-section" sqxTourStep="allApps"> |
|
||||
<div class="empty" *ngIf="groups.length === 0"> |
|
||||
<h3 class="empty-headline">{{ 'apps.empty' | sqxTranslate }}</h3> |
|
||||
</div> |
|
||||
|
|
||||
<div class="team" *ngFor="let group of groups; trackBy: trackByGroup"> |
|
||||
<div class="team-header" *ngIf="group.team"> |
|
||||
<sqx-team [team]="group.team" (leave)="leaveTeam($event)"></sqx-team> |
|
||||
</div> |
|
||||
|
|
||||
<div class="team-body" [class.padded]="group.team"> |
|
||||
<sqx-app *ngFor="let app of group.apps; trackBy: trackByApp" [app]="app" (leave)="leaveApp($event)"></sqx-app> |
|
||||
|
|
||||
<small class="team-empty" *ngIf="group.apps.length === 0"> |
|
||||
{{ 'teams.empty' | sqxTranslate }} |
|
||||
</small> |
|
||||
</div> |
|
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</ng-container> |
@if (groupedApps | async; as groups) { |
||||
|
<div class="apps-section" sqxTourStep="allApps"> |
||||
<div class="apps-section" *ngIf="(uiState.settings | async)?.canCreateApps"> |
@for (group of groups; track trackByGroup($index, group)) { |
||||
<div class="card card-template card-href" data-testid="new-app" (click)="createNewApp()" sqxTourStep="addApp"> |
<div class="team"> |
||||
<div class="card-body"> |
@if (group.team) { |
||||
<div class="card-image"> |
<div class="team-header"> |
||||
<img src="./images/add-app.svg"> |
<sqx-team (leave)="leaveTeam($event)" [team]="group.team"></sqx-team> |
||||
</div> |
</div> |
||||
|
} |
||||
<h3 class="card-title">{{ 'apps.createBlankApp' | sqxTranslate }}</h3> |
<div class="team-body" [class.padded]="group.team"> |
||||
|
@for (app of group.apps; track app.id) { |
||||
<sqx-form-hint> |
<sqx-app [app]="app" (leave)="leaveApp($event)"></sqx-app> |
||||
{{ 'apps.createBlankAppDescription' | sqxTranslate }} |
} @empty { |
||||
</sqx-form-hint> |
<small class="team-empty"> |
||||
|
{{ "teams.empty" | sqxTranslate }} |
||||
|
</small> |
||||
|
} |
||||
|
</div> |
||||
|
</div> |
||||
|
} @empty { |
||||
|
<div class="empty"> |
||||
|
<h3 class="empty-headline">{{ "apps.empty" | sqxTranslate }}</h3> |
||||
|
</div> |
||||
|
} |
||||
</div> |
</div> |
||||
</div> |
} |
||||
|
@if ((uiState.settings | async)?.canCreateApps) { |
||||
<div class="card card-template card-href" *ngFor="let template of templates | async" (click)="createNewApp(template)"> |
<div class="apps-section"> |
||||
<div class="card-body"> |
<div class="card card-template card-href" (click)="createNewApp()" data-testid="new-app" sqxTourStep="addApp"> |
||||
<div class="card-image"> |
<div class="card-body"> |
||||
<img src="./images/add-template.svg"> |
<div class="card-image"> |
||||
|
<img src="./images/add-app.svg" /> |
||||
|
</div> |
||||
|
<h3 class="card-title">{{ "apps.createBlankApp" | sqxTranslate }}</h3> |
||||
|
<sqx-form-hint> |
||||
|
{{ "apps.createBlankAppDescription" | sqxTranslate }} |
||||
|
</sqx-form-hint> |
||||
|
</div> |
||||
</div> |
</div> |
||||
|
@for (template of templates | async; track template) { |
||||
<h3 class="card-title">{{template.title}}</h3> |
<div class="card card-template card-href" (click)="createNewApp(template)"> |
||||
|
<div class="card-body"> |
||||
<sqx-form-hint> |
<div class="card-image"> |
||||
{{template.description}} |
<img src="./images/add-template.svg" /> |
||||
</sqx-form-hint> |
</div> |
||||
|
<h3 class="card-title">{{ template.title }}</h3> |
||||
|
<sqx-form-hint> |
||||
|
{{ template.description }} |
||||
|
</sqx-form-hint> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
</div> |
</div> |
||||
</div> |
} |
||||
</div> |
@if (info) { |
||||
|
<div class="apps-section"> |
||||
<div *ngIf="info" class="apps-section"> |
<small class="info">{{ info }}</small> |
||||
<small class="info">{{info}}</small> |
</div> |
||||
|
} |
||||
</div> |
</div> |
||||
</div> |
} |
||||
|
|
||||
<sqx-app-form *sqxModal="addAppDialog" |
<sqx-app-form (dialogClose)="addAppDialog.hide()" *sqxModal="addAppDialog" [template]="addAppTemplate"></sqx-app-form> |
||||
(dialogClose)="addAppDialog.hide()" [template]="addAppTemplate"> |
|
||||
</sqx-app-form> |
|
||||
|
|
||||
<sqx-onboarding-dialog *sqxModal="onboardingDialog" |
<sqx-onboarding-dialog (dialogClose)="onboardingDialog.hide()" *sqxModal="onboardingDialog"></sqx-onboarding-dialog> |
||||
(dialogClose)="onboardingDialog.hide()"> |
|
||||
</sqx-onboarding-dialog> |
|
||||
|
|
||||
<sqx-news-dialog *sqxModal="newsDialog" [features]="newsFeatures!" |
<sqx-news-dialog (dialogClose)="newsDialog.hide()" [features]="newsFeatures!" *sqxModal="newsDialog"></sqx-news-dialog> |
||||
(dialogClose)="newsDialog.hide()"> |
|
||||
</sqx-news-dialog> |
|
||||
|
|||||
@ -1,19 +1,19 @@ |
|||||
<sqx-modal-dialog size="lg" (dialogClose)="dialogClose.emit()"> |
<sqx-modal-dialog (dialogClose)="dialogClose.emit()" size="lg"> |
||||
<ng-container title> |
<ng-container title> |
||||
{{ 'news.title' | sqxTranslate }} |
{{ "news.title" | sqxTranslate }} |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container content> |
<ng-container content> |
||||
<div class="help"> |
<div class="help"> |
||||
<h1>{{ 'news.headline' | sqxTranslate }}</h1> |
<h1>{{ "news.headline" | sqxTranslate }}</h1> |
||||
|
|
||||
<div *ngFor="let feature of features; trackBy: trackByFeature; let last = last"> |
@for (feature of features; track feature; let last = $last) { |
||||
<h4>{{feature.name}}</h4> |
<div> |
||||
|
<h4>{{ feature.name }}</h4> |
||||
<div [innerHTML]="feature.text | sqxHelpMarkdown"></div> |
<div [innerHTML]="feature.text | sqxHelpMarkdown"></div> |
||||
|
<hr [class.hidden]="last" /> |
||||
<hr [class.hidden]="last" /> |
</div> |
||||
</div> |
} |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-modal-dialog> |
</sqx-modal-dialog> |
||||
|
|||||
@ -1,100 +1,95 @@ |
|||||
<sqx-modal-dialog showHeader="false"> |
<sqx-modal-dialog showHeader="false"> |
||||
<ng-container tabs> |
<ng-container tabs> |
||||
<div class="squid d-flex align-items-center justify-content-center"> |
<div class="squid d-flex align-items-center justify-content-center"> |
||||
<img src="./images/squid.svg"> |
<img src="./images/squid.svg" /> |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container content> |
<ng-container content> |
||||
<a class="header-right modal-close force" (click)="cancel()">{{ 'tour.skip' | sqxTranslate }}</a> |
<a class="header-right modal-close force" (click)="cancel()">{{ "tour.skip" | sqxTranslate }}</a> |
||||
|
|
||||
<div class="onboarding-step " *ngIf="step === 0"> |
@if (step === 0) { |
||||
<img @fade class="header-left" src="./images/logo-white-small.png"> |
<div class="onboarding-step"> |
||||
|
<img class="header-left" @fade src="./images/logo-white-small.png" /> |
||||
<div @slide class="onboarding-enter-leave text-center"> |
<div class="onboarding-enter-leave text-center" @slide> |
||||
<h1>{{ 'tour.welcome' | sqxTranslate }} <span class="header-focus">{{ 'tour.welcomeProduct' | sqxTranslate }}</span></h1> |
<h1> |
||||
|
{{ "tour.welcome" | sqxTranslate }} |
||||
<div [innerHTML]="'tour.stepIntroText' | sqxTranslate | sqxMarkdown | sqxSafeHtml"></div> |
<span class="header-focus">{{ "tour.welcomeProduct" | sqxTranslate }}</span> |
||||
|
</h1> |
||||
<div class="mt-4"> |
<div [innerHTML]="'tour.stepIntroText' | sqxTranslate | sqxMarkdown | sqxSafeHtml"></div> |
||||
<button (click)="next()" class="btn btn-success"> |
<div class="mt-4"> |
||||
{{ 'tour.stepIntroNext' | sqxTranslate }} |
<button class="btn btn-success" (click)="next()"> |
||||
</button> |
{{ "tour.stepIntroNext" | sqxTranslate }} |
||||
|
</button> |
||||
|
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
} |
||||
|
|
||||
<div *ngIf="step === 1"> |
@if (step === 1) { |
||||
<img @fade class="header-left" src="./images/logo-white-small.png"> |
<div> |
||||
|
<img class="header-left" @fade src="./images/logo-white-small.png" /> |
||||
<div @slide class="onboarding-enter-leave"> |
<div class="onboarding-enter-leave" @slide> |
||||
<form [formGroup]="answersForm" (ngSubmit)="submitAnswers()"> |
<form [formGroup]="answersForm" (ngSubmit)="submitAnswers()"> |
||||
<h2>{{ 'tour.stepDataTitle' | sqxTranslate }}</h2> |
<h2>{{ "tour.stepDataTitle" | sqxTranslate }}</h2> |
||||
|
<div [innerHTML]="'tour.stepDataText' | sqxTranslate | sqxMarkdown | sqxSafeHtml"></div> |
||||
<div [innerHTML]="'tour.stepDataText' | sqxTranslate | sqxMarkdown | sqxSafeHtml"></div> |
<div class="form-group mt-4"> |
||||
|
<label for="role">{{ "tour.stepDataCompanyRole" | sqxTranslate }}</label> |
||||
<div class="form-group mt-4"> |
<select class="form-select" id="companyRole" formControlName="companyRole"> |
||||
<label for="role">{{ 'tour.stepDataCompanyRole' | sqxTranslate }}</label> |
<option [ngValue]="'RoleEmployee'">{{ "tour.roleEmployee" | sqxTranslate }}</option> |
||||
|
<option [ngValue]="'RoleBusinessOwner'">{{ "tour.roleBusinessOwner" | sqxTranslate }}</option> |
||||
<select class="form-select" id="companyRole" formControlName="companyRole"> |
<option [ngValue]="'RoleProductManager'">{{ "tour.roleProductManager" | sqxTranslate }}</option> |
||||
<option [ngValue]="'RoleEmployee'">{{ 'tour.roleEmployee' | sqxTranslate }}</option> |
<option [ngValue]="'RoleContentCreator'">{{ "tour.roleContentCreator" | sqxTranslate }}</option> |
||||
<option [ngValue]="'RoleBusinessOwner'">{{ 'tour.roleBusinessOwner' | sqxTranslate }}</option> |
<option [ngValue]="'RoleSoftwareDeveloper'">{{ "tour.roleSoftwareDeveloper" | sqxTranslate }}</option> |
||||
<option [ngValue]="'RoleProductManager'">{{ 'tour.roleProductManager' | sqxTranslate }}</option> |
<option [ngValue]="'RoleBusinessAnalyst'">{{ "tour.roleBusinessAnalyst" | sqxTranslate }}</option> |
||||
<option [ngValue]="'RoleContentCreator'">{{ 'tour.roleContentCreator' | sqxTranslate }}</option> |
</select> |
||||
<option [ngValue]="'RoleSoftwareDeveloper'">{{ 'tour.roleSoftwareDeveloper' | sqxTranslate }}</option> |
</div> |
||||
<option [ngValue]="'RoleBusinessAnalyst'">{{ 'tour.roleBusinessAnalyst' | sqxTranslate }}</option> |
<div class="form-group"> |
||||
</select> |
<label for="companySize">{{ "tour.stepDataCompanySize" | sqxTranslate }}</label> |
||||
</div> |
<select class="form-select" id="companySize" formControlName="companySize"> |
||||
|
<option [ngValue]="'SizeSingle'">{{ "tour.sizeSingle" | sqxTranslate }}</option> |
||||
<div class="form-group"> |
<option [ngValue]="'SizeSmall'">{{ "tour.sizeSmall" | sqxTranslate }}</option> |
||||
<label for="companySize">{{ 'tour.stepDataCompanySize' | sqxTranslate }}</label> |
<option [ngValue]="'SizeMedium'">{{ "tour.sizeMedium" | sqxTranslate }}</option> |
||||
|
<option [ngValue]="'SizeLarge'">{{ "tour.sizeLarge" | sqxTranslate }}</option> |
||||
<select class="form-select" id="companySize" formControlName="companySize"> |
<option [ngValue]="'SizeVeryLarge'">{{ "tour.sizeVeryLarge" | sqxTranslate }}</option> |
||||
<option [ngValue]="'SizeSingle'">{{ 'tour.sizeSingle' | sqxTranslate }}</option> |
</select> |
||||
<option [ngValue]="'SizeSmall'">{{ 'tour.sizeSmall' | sqxTranslate }}</option> |
</div> |
||||
<option [ngValue]="'SizeMedium'">{{ 'tour.sizeMedium' | sqxTranslate }}</option> |
<div class="form-group"> |
||||
<option [ngValue]="'SizeLarge'">{{ 'tour.sizeLarge' | sqxTranslate }}</option> |
<label for="project">{{ "tour.stepDataProject" | sqxTranslate }}</label> |
||||
<option [ngValue]="'SizeVeryLarge'">{{ 'tour.sizeVeryLarge' | sqxTranslate }}</option> |
<select class="form-select" id="project" formControlName="project"> |
||||
</select> |
<option [ngValue]="'ProjectNewsMagazine'">{{ "tour.projectNewsMagazine" | sqxTranslate }}</option> |
||||
</div> |
<option [ngValue]="'ProjectPersonalBlog'">{{ "tour.projectPersonalBlog" | sqxTranslate }}</option> |
||||
|
<option [ngValue]="'ProjectSmallBusiness'">{{ "tour.projectSmallBusiness" | sqxTranslate }}</option> |
||||
<div class="form-group"> |
<option [ngValue]="'ProjectCommerce'">{{ "tour.projectCommerce" | sqxTranslate }}</option> |
||||
<label for="project">{{ 'tour.stepDataProject' | sqxTranslate }}</label> |
<option [ngValue]="'ProjectMobileApp'">{{ "tour.projectMobileApp" | sqxTranslate }}</option> |
||||
|
<option [ngValue]="'ProjectBackend'">{{ "tour.projectBackend" | sqxTranslate }}</option> |
||||
<select class="form-select" id="project" formControlName="project"> |
<option [ngValue]="'ProjectLearning'">{{ "tour.projectLearning" | sqxTranslate }}</option> |
||||
<option [ngValue]="'ProjectNewsMagazine'">{{ 'tour.projectNewsMagazine' | sqxTranslate }}</option> |
</select> |
||||
<option [ngValue]="'ProjectPersonalBlog'">{{ 'tour.projectPersonalBlog' | sqxTranslate }}</option> |
</div> |
||||
<option [ngValue]="'ProjectSmallBusiness'">{{ 'tour.projectSmallBusiness' | sqxTranslate }}</option> |
<button class="btn btn-success" type="submit"> |
||||
<option [ngValue]="'ProjectCommerce'">{{ 'tour.projectCommerce' | sqxTranslate }}</option> |
{{ "tour.stepDataNext" | sqxTranslate }} |
||||
<option [ngValue]="'ProjectMobileApp'">{{ 'tour.projectMobileApp' | sqxTranslate }}</option> |
</button> |
||||
<option [ngValue]="'ProjectBackend'">{{ 'tour.projectBackend' | sqxTranslate }}</option> |
</form> |
||||
<option [ngValue]="'ProjectLearning'">{{ 'tour.projectLearning' | sqxTranslate }}</option> |
</div> |
||||
</select> |
|
||||
</div> |
|
||||
|
|
||||
<button type="submit" class="btn btn-success">{{ 'tour.stepDataNext' | sqxTranslate }}</button> |
|
||||
</form> |
|
||||
</div> |
</div> |
||||
</div> |
} |
||||
|
|
||||
<div class="onboarding-step" *ngIf="step === 2"> |
|
||||
<img @fade class="header-left" src="./images/logo-white-small.png"> |
|
||||
|
|
||||
<div @slide class="onboarding-enter-leave text-center"> |
|
||||
<h2>{{ 'tour.stepTourTitle' | sqxTranslate }}</h2> |
|
||||
|
|
||||
<div [innerHTML]="'tour.stepTourText' | sqxTranslate | sqxMarkdown | sqxSafeHtml"></div> |
@if (step === 2) { |
||||
|
<div class="onboarding-step"> |
||||
<div class="mt-4"> |
<img class="header-left" @fade src="./images/logo-white-small.png" /> |
||||
<button (click)="start()" class="btn btn-success"> |
<div class="onboarding-enter-leave text-center" @slide> |
||||
{{ 'tour.startYes' | sqxTranslate }} |
<h2>{{ "tour.stepTourTitle" | sqxTranslate }}</h2> |
||||
</button> |
<div [innerHTML]="'tour.stepTourText' | sqxTranslate | sqxMarkdown | sqxSafeHtml"></div> |
||||
|
<div class="mt-4"> |
||||
<button (click)="cancel()" class="btn btn-outline-secondary ms-2"> |
<button class="btn btn-success" (click)="start()"> |
||||
{{ 'tour.startNo' | sqxTranslate }} |
{{ "tour.startYes" | sqxTranslate }} |
||||
</button> |
</button> |
||||
|
<button class="btn btn-outline-secondary ms-2" (click)="cancel()"> |
||||
|
{{ "tour.startNo" | sqxTranslate }} |
||||
|
</button> |
||||
|
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
} |
||||
</ng-container> |
</ng-container> |
||||
</sqx-modal-dialog> |
</sqx-modal-dialog> |
||||
|
|||||
@ -1,26 +1,27 @@ |
|||||
<div class="team-header"> |
<div class="team-header"> |
||||
<div class="row align-items-center"> |
<div class="row align-items-center"> |
||||
<div class="col"> |
<div class="col"> |
||||
<h3>{{team.name}}</h3> |
<h3>{{ team.name }}</h3> |
||||
</div> |
</div> |
||||
<div class="col-auto"> |
<div class="col-auto"> |
||||
<a class="link" [routerLink]="['/app/teams', team.id]" sqxStopClick>{{ 'common.edit' | sqxTranslate }}</a> |
<a class="link" [routerLink]="['/app/teams', team.id]" sqxStopClick>{{ "common.edit" | sqxTranslate }}</a> |
||||
</div> |
</div> |
||||
<div class="col-auto"> |
<div class="col-auto"> |
||||
<button type="button" class="btn btn-sm btn-text-secondary" (click)="dropdown.toggle()" sqxStopClick #buttonOptions> |
<button class="btn btn-sm btn-text-secondary" #buttonOptions (click)="dropdown.toggle()" sqxStopClick type="button"> |
||||
<span class="hidden">{{ 'common.options' | sqxTranslate }}</span> |
<span class="hidden">{{ "common.options" | sqxTranslate }}</span> |
||||
<i class="icon-dots"></i> |
<i class="icon-dots"></i> |
||||
</button> |
</button> |
||||
|
|
||||
<sqx-dropdown-menu *sqxModal="dropdown;closeAlways:true" [sqxAnchoredTo]="buttonOptions" scrollY="true"> |
<sqx-dropdown-menu scrollY="true" [sqxAnchoredTo]="buttonOptions" *sqxModal="dropdown; closeAlways: true"> |
||||
<a class="dropdown-item dropdown-item-delete" |
<a |
||||
(sqxConfirmClick)="leave.emit(team)" |
class="dropdown-item dropdown-item-delete" |
||||
confirmTitle="i18n:teams.leaveConfirmTitle" |
confirmRememberKey="leaveApp" |
||||
confirmText="i18n:teams.leaveConfirmText" |
confirmText="i18n:teams.leaveConfirmText" |
||||
confirmRememberKey="leaveApp"> |
confirmTitle="i18n:teams.leaveConfirmTitle" |
||||
{{ 'teams.leave' | sqxTranslate }} |
(sqxConfirmClick)="leave.emit(team)"> |
||||
|
{{ "teams.leave" | sqxTranslate }} |
||||
</a> |
</a> |
||||
</sqx-dropdown-menu> |
</sqx-dropdown-menu> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|||||
@ -1,29 +1,32 @@ |
|||||
<form [formGroup]="editForm.form" (ngSubmit)="renameAssetTag()"> |
<form [formGroup]="editForm.form" (ngSubmit)="renameAssetTag()"> |
||||
<sqx-modal-dialog (dialogClose)="emitClose()"> |
<sqx-modal-dialog (dialogClose)="emitClose()"> |
||||
<ng-container title> |
<ng-container title> |
||||
{{ 'common.renameTag' | sqxTranslate }} |
{{ "common.renameTag" | sqxTranslate }} |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container content> |
<ng-container content> |
||||
<sqx-form-error [error]="editForm.error | async"></sqx-form-error> |
<sqx-form-error [error]="editForm.error | async"></sqx-form-error> |
||||
|
|
||||
<div class="form-group"> |
<div class="form-group"> |
||||
<label for="tagName">{{ 'common.name' | sqxTranslate }} <small class="hint">({{ 'common.requiredHint' | sqxTranslate }})</small></label> |
<label for="tagName"> |
||||
|
{{ "common.name" | sqxTranslate }} |
||||
|
<small class="hint">({{ "common.requiredHint" | sqxTranslate }})</small> |
||||
|
</label> |
||||
|
|
||||
<sqx-control-errors for="tagName"></sqx-control-errors> |
<sqx-control-errors for="tagName"></sqx-control-errors> |
||||
|
|
||||
<input class="form-control" id="tagName" formControlName="tagName" autocomplete="off" sqxFocusOnInit> |
<input class="form-control" id="tagName" autocomplete="off" formControlName="tagName" sqxFocusOnInit /> |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container footer> |
<ng-container footer> |
||||
<button type="button" class="btn btn-text-secondary" (click)="emitClose()"> |
<button class="btn btn-text-secondary" (click)="emitClose()" type="button"> |
||||
{{ 'common.cancel' | sqxTranslate }} |
{{ "common.cancel" | sqxTranslate }} |
||||
</button> |
</button> |
||||
|
|
||||
<button type="submit" class="btn btn-success"> |
<button class="btn btn-success" type="submit"> |
||||
{{ 'common.rename' | sqxTranslate }} |
{{ "common.rename" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-modal-dialog> |
</sqx-modal-dialog> |
||||
</form> |
</form> |
||||
|
|||||
@ -1,28 +1,32 @@ |
|||||
<div class="nav nav-light flex-column"> |
<div class="nav nav-light flex-column"> |
||||
<div class="nav-item"> |
<div class="nav-item"> |
||||
<a class="nav-link" (click)="tagsReset.emit()" [class.active]="isEmpty()"> |
<a class="nav-link" [class.active]="isEmpty()" (click)="tagsReset.emit()"> |
||||
{{ 'common.tagsAll' | sqxTranslate }} |
{{ "common.tagsAll" | sqxTranslate }} |
||||
</a> |
</a> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="nav-item" *ngFor="let tag of tags; trackBy: trackByTag"> |
@for (tag of tags; track tag.name) { |
||||
<a class="nav-link" (click)="toggle.emit(tag.name)" [class.active]="isSelected(tag)"> |
<div class="nav-item"> |
||||
<div class="row g-0"> |
<a class="nav-link" [class.active]="isSelected(tag)" (click)="toggle.emit(tag.name)"> |
||||
<div class="col"> |
<div class="row g-0"> |
||||
<span class="truncate">{{tag.name}}</span> |
<div class="col"> |
||||
|
<span class="truncate">{{ tag.name }}</span> |
||||
|
</div> |
||||
|
<div class="col-auto"> |
||||
|
<div class="badge badge-secondary rounded-pill">{{ tag.count }}</div> |
||||
|
@if (canRename) { |
||||
|
<a class="btn-sm btn-text-secondary btn-rename" (click)="renameTag(tag)" sqxStopClick> |
||||
|
<i class="icon-pencil"></i> |
||||
|
</a> |
||||
|
} |
||||
|
</div> |
||||
</div> |
</div> |
||||
<div class="col-auto"> |
</a> |
||||
<div class="badge badge-secondary rounded-pill">{{tag.count}}</div> |
</div> |
||||
|
} |
||||
<a class="btn-sm btn-text-secondary btn-rename" (click)="renameTag(tag)" *ngIf="canRename" sqxStopClick> |
|
||||
<i class="icon-pencil"></i> |
|
||||
</a> |
|
||||
</div> |
|
||||
</div> |
|
||||
</a> |
|
||||
</div> |
|
||||
</div> |
</div> |
||||
|
|
||||
<sqx-asset-tag-dialog *sqxModal="tagRenameDialog" |
<sqx-asset-tag-dialog |
||||
(dialogClose)="tagRenameDialog.hide()" [tagName]="tagRenaming!.name"> |
(dialogClose)="tagRenameDialog.hide()" |
||||
</sqx-asset-tag-dialog> |
*sqxModal="tagRenameDialog" |
||||
|
[tagName]="tagRenaming!.name"></sqx-asset-tag-dialog> |
||||
|
|||||
@ -1,20 +1,18 @@ |
|||||
<sqx-layout layout="right" titleText="i18n:common.filters" width="20" white="true" padding="true" overflow="true"> |
<sqx-layout layout="right" overflow="true" padding="true" titleText="i18n:common.filters" white="true" width="20"> |
||||
<h3>{{ 'common.tags' | sqxTranslate }}</h3> |
<h3>{{ "common.tags" | sqxTranslate }}</h3> |
||||
|
|
||||
<sqx-asset-tags |
<sqx-asset-tags |
||||
[canRename]="(assetsState.canRenameTag | async)!" |
[canRename]="(assetsState.canRenameTag | async)!" |
||||
[tags]="(assetsState.tags | async)!" |
[tags]="(assetsState.tags | async)!" |
||||
(tagsReset)="resetTags()" |
(tagsReset)="resetTags()" |
||||
[tagsSelected]="(assetsState.tagsSelected | async)!" |
[tagsSelected]="(assetsState.tagsSelected | async)!" |
||||
(toggle)="toggleTag($event)"> |
(toggle)="toggleTag($event)"></sqx-asset-tags> |
||||
</sqx-asset-tags> |
|
||||
|
|
||||
<hr> |
<hr /> |
||||
|
|
||||
<sqx-shared-queries |
<sqx-shared-queries |
||||
[types]="'common.assets' | sqxTranslate" |
|
||||
[queryUsed]="assetsState.query | async" |
|
||||
[queries]="assetsQueries" |
[queries]="assetsQueries" |
||||
(search)="search($event)"> |
[queryUsed]="assetsState.query | async" |
||||
</sqx-shared-queries> |
(search)="search($event)" |
||||
</sqx-layout> |
[types]="'common.assets' | sqxTranslate"></sqx-shared-queries> |
||||
|
</sqx-layout> |
||||
|
|||||
@ -1,3 +1,3 @@ |
|||||
<sqx-layout layout="right" titleText="i18n:comments.title" width="20" white="true"> |
<sqx-layout layout="right" titleText="i18n:comments.title" white="true" width="20"> |
||||
<sqx-comments [commentsId]="commentsId | async"></sqx-comments> |
<sqx-comments [commentsId]="commentsId | async"></sqx-comments> |
||||
</sqx-layout> |
</sqx-layout> |
||||
|
|||||
@ -1,21 +1,21 @@ |
|||||
<div class="event row g-0"> |
<div class="event row g-0"> |
||||
<div class="col-auto"> |
<div class="col-auto"> |
||||
<img class="user-picture" title="{{event.actor | sqxUserNameRef}}" [src]="event.actor | sqxUserPictureRef"> |
<img class="user-picture" [src]="event.actor | sqxUserPictureRef" title="{{ event.actor | sqxUserNameRef }}" /> |
||||
</div> |
</div> |
||||
<div class="col ps-2 event-right"> |
<div class="col ps-2 event-right"> |
||||
<div class="event-message"> |
<div class="event-message"> |
||||
<span class="event-actor user-ref me-1" [title]="event.actor | sqxUserNameRef:null">{{event.actor | sqxUserNameRef:null}}</span> |
<span class="event-actor user-ref me-1" [title]="event.actor | sqxUserNameRef: null"> |
||||
|
{{ event.actor | sqxUserNameRef: null }} |
||||
|
</span> |
||||
<span [innerHTML]="event | sqxHistoryMessage"></span> |
<span [innerHTML]="event | sqxHistoryMessage"></span> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="event-created">{{event.created | sqxFromNow}}</div> |
<div class="event-created">{{ event.created | sqxFromNow }}</div> |
||||
|
|
||||
<ng-container *ngIf="canLoadOrCompare"> |
@if (canLoadOrCompare) { |
||||
<a class="event-load force" (click)="dataLoad.emit()">{{ 'contents.loadContent' | sqxTranslate }}</a> |
<a class="event-load force" (click)="dataLoad.emit()">{{ "contents.loadContent" | sqxTranslate }}</a> |
||||
|
· |
||||
· |
<a class="event-load force" (click)="dataCompare.emit()">{{ "contents.versionCompare" | sqxTranslate }}</a> |
||||
|
} |
||||
<a class="event-load force" (click)="dataCompare.emit()">{{ 'contents.versionCompare' | sqxTranslate }}</a> |
|
||||
</ng-container> |
|
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|||||
@ -1,141 +1,154 @@ |
|||||
<sqx-layout layout="right" titleText="i18n:common.workflow" width="20" white="true" overflow="true" padding="true"> |
<sqx-layout layout="right" overflow="true" padding="true" titleText="i18n:common.workflow" white="true" width="20"> |
||||
<ng-container> |
<ng-container> |
||||
<div class="section mb-2"> |
<div class="section mb-2"> |
||||
<label for="id">{{ 'common.id' | sqxTranslate }}</label> |
<label for="id">{{ "common.id" | sqxTranslate }}</label> |
||||
|
|
||||
<div class="input-group"> |
<div class="input-group"> |
||||
<input readonly class="form-control" name="id" id="id" value="{{content.id}}" #inputId> |
<input class="form-control" id="id" #inputId name="id" readonly value="{{ content.id }}" /> |
||||
|
|
||||
<button type="button" class="btn btn-outline-secondary" [sqxCopy]="inputId"> |
<button class="btn btn-outline-secondary" [sqxCopy]="inputId" type="button"> |
||||
<i class="icon-copy"></i> |
<i class="icon-copy"></i> |
||||
</button> |
</button> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
<div class="section mb-4"> |
<div class="section mb-4"> |
||||
<label for="version">{{ 'common.version' | sqxTranslate }}</label>: <span id="version">{{content.version}}</span> |
<label for="version">{{ "common.version" | sqxTranslate }}</label>: <span id="version">{{ content.version }}</span> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="section mb-4" *ngIf="content.canDraftCreate || content.canDraftDelete"> |
@if (content.canDraftCreate || content.canDraftDelete) { |
||||
<ng-container *ngIf="!content.newStatus; else newVersion"> |
<div class="section mb-4"> |
||||
<button class="btn btn-success btn-block" (click)="createDraft()"> |
@if (!content.newStatus) { |
||||
{{ 'contents.draftNew' | sqxTranslate }} |
<button class="btn btn-success btn-block" (click)="createDraft()"> |
||||
</button> |
{{ "contents.draftNew" | sqxTranslate }} |
||||
</ng-container> |
</button> |
||||
|
} @else { |
||||
<ng-template #newVersion> |
<label>{{ "contents.draftStatus" | sqxTranslate }}</label> |
||||
<label>{{ 'contents.draftStatus' | sqxTranslate }}</label> |
<button |
||||
|
class="btn btn-outline-secondary btn-block btn-status" |
||||
<button type="button" class="btn btn-outline-secondary btn-block btn-status" (click)="dropdownNew.toggle()" #buttonOptions sqxTourStep="status"> |
#buttonOptions |
||||
<sqx-content-status |
(click)="dropdownNew.toggle()" |
||||
layout="multiline" |
sqxTourStep="status" |
||||
[status]="content.newStatus!" |
type="button"> |
||||
[statusColor]="content.newStatusColor!" |
<sqx-content-status |
||||
[scheduled]="content.scheduleJob"> |
layout="multiline" |
||||
</sqx-content-status> |
[scheduled]="content.scheduleJob" |
||||
</button> |
[status]="content.newStatus!" |
||||
|
[statusColor]="content.newStatusColor!"></sqx-content-status> |
||||
<sqx-dropdown-menu *sqxModal="dropdownNew;closeAlways:true" [sqxAnchoredTo]="buttonOptions" scrollY="true"> |
</button> |
||||
<ng-container *ngIf="content.statusUpdates.length > 0"> |
<sqx-dropdown-menu scrollY="true" [sqxAnchoredTo]="buttonOptions" *sqxModal="dropdownNew; closeAlways: true"> |
||||
<a class="dropdown-item" *ngFor="let info of content.statusUpdates" (click)="changeStatus(info.status)"> |
@if (content.statusUpdates.length > 0) { |
||||
{{ 'common.statusChangeTo' | sqxTranslate }} <i class="icon-circle icon-sm" [style.color]="info.color"></i> {{info.status}} |
@for (info of content.statusUpdates; track info) { |
||||
|
<a class="dropdown-item" (click)="changeStatus(info.status)"> |
||||
|
{{ "common.statusChangeTo" | sqxTranslate }} |
||||
|
<i class="icon-circle icon-sm" [style.color]="info.color"></i> |
||||
|
{{ info.status }} |
||||
|
</a> |
||||
|
} |
||||
|
<div class="dropdown-divider"></div> |
||||
|
} |
||||
|
<a |
||||
|
class="dropdown-item dropdown-item-delete" |
||||
|
[class.disabled]="!content.canDraftDelete" |
||||
|
confirmRememberKey="deleteDraft" |
||||
|
confirmText="i18n:contents.deleteVersionConfirmText" |
||||
|
confirmTitle="i18n:contents.deleteConfirmTitle" |
||||
|
(sqxConfirmClick)="deleteDraft()"> |
||||
|
{{ "contents.versionDelete" | sqxTranslate }} |
||||
</a> |
</a> |
||||
|
|
||||
<div class="dropdown-divider"></div> |
<div class="dropdown-divider"></div> |
||||
</ng-container> |
<a |
||||
|
class="dropdown-item dropdown-item-delete" |
||||
<a class="dropdown-item dropdown-item-delete" [class.disabled]="!content.canDraftDelete" |
[class.disabled]="!content.canDelete" |
||||
(sqxConfirmClick)="deleteDraft()" |
confirmRememberKey="deleteContent" |
||||
confirmTitle="i18n:contents.deleteConfirmTitle" |
confirmText="i18n:contents.deleteConfirmText" |
||||
confirmText="i18n:contents.deleteVersionConfirmText" |
confirmTitle="i18n:contents.deleteConfirmTitle" |
||||
confirmRememberKey="deleteDraft"> |
(sqxConfirmClick)="delete()"> |
||||
{{ 'contents.versionDelete' | sqxTranslate }} |
{{ "common.delete" | sqxTranslate }} |
||||
</a> |
</a> |
||||
|
</sqx-dropdown-menu> |
||||
<div class="dropdown-divider"></div> |
} |
||||
|
</div> |
||||
<a class="dropdown-item dropdown-item-delete" [class.disabled]="!content.canDelete" |
} |
||||
(sqxConfirmClick)="delete()" |
|
||||
confirmTitle="i18n:contents.deleteConfirmTitle" |
|
||||
confirmText="i18n:contents.deleteConfirmText" |
|
||||
confirmRememberKey="deleteContent"> |
|
||||
{{ 'common.delete' | sqxTranslate }} |
|
||||
</a> |
|
||||
</sqx-dropdown-menu> |
|
||||
</ng-template> |
|
||||
</div> |
|
||||
|
|
||||
<div class="section"> |
<div class="section"> |
||||
<label>{{ 'contents.currentStatusLabel' | sqxTranslate }}</label> |
<label>{{ "contents.currentStatusLabel" | sqxTranslate }}</label> |
||||
|
|
||||
<div *ngIf="!content.newStatus; else newStatusOld"> |
@if (!content.newStatus) { |
||||
<button type="button" class="btn btn-outline-secondary btn-block btn-status" (click)="dropdown.toggle()" #buttonOptions sqxTourStep="status"> |
<div> |
||||
|
<button |
||||
|
class="btn btn-outline-secondary btn-block btn-status" |
||||
|
#buttonOptions |
||||
|
(click)="dropdown.toggle()" |
||||
|
sqxTourStep="status" |
||||
|
type="button"> |
||||
|
<sqx-content-status |
||||
|
layout="multiline" |
||||
|
[scheduled]="content.scheduleJob" |
||||
|
small="true" |
||||
|
[status]="content.status" |
||||
|
[statusColor]="content.statusColor"></sqx-content-status> |
||||
|
</button> |
||||
|
<sqx-dropdown-menu scrollY="true" [sqxAnchoredTo]="buttonOptions" *sqxModal="dropdown; closeAlways: true"> |
||||
|
@if (content.statusUpdates.length > 0) { |
||||
|
@for (info of content.statusUpdates; track info) { |
||||
|
<a class="dropdown-item" (click)="changeStatus(info.status)"> |
||||
|
{{ "common.statusChangeTo" | sqxTranslate }} |
||||
|
<sqx-content-status |
||||
|
layout="text" |
||||
|
small="true" |
||||
|
[status]="info.status" |
||||
|
[statusColor]="info.color"></sqx-content-status> |
||||
|
</a> |
||||
|
} |
||||
|
<div class="dropdown-divider"></div> |
||||
|
} |
||||
|
<a |
||||
|
class="dropdown-item dropdown-item-delete" |
||||
|
[class.disabled]="!content.canCancelStatus" |
||||
|
confirmRememberKey="cancelStatus" |
||||
|
confirmText="i18n:contents.cancelStatusConfirmText" |
||||
|
confirmTitle="i18n:contents.cancelStatusConfirmTitle" |
||||
|
(sqxConfirmClick)="cancelStatus()"> |
||||
|
{{ "contents.cancelStatus" | sqxTranslate }} |
||||
|
</a> |
||||
|
<div class="dropdown-divider"></div> |
||||
|
<a |
||||
|
class="dropdown-item dropdown-item-delete" |
||||
|
[class.disabled]="!content.canDelete" |
||||
|
confirmRememberKey="deleteContent" |
||||
|
confirmText="i18n:contents.deleteConfirmText" |
||||
|
confirmTitle="i18n:contents.deleteConfirmTitle" |
||||
|
(sqxConfirmClick)="delete()"> |
||||
|
{{ "common.delete" | sqxTranslate }} |
||||
|
</a> |
||||
|
</sqx-dropdown-menu> |
||||
|
</div> |
||||
|
} @else { |
||||
|
<button class="btn btn-outline-secondary btn-block btn-status" type="button"> |
||||
<sqx-content-status |
<sqx-content-status |
||||
layout="multiline" |
layout="multiline" |
||||
[status]="content.status" |
[status]="content.status" |
||||
[statusColor]="content.statusColor" |
[statusColor]="content.statusColor"></sqx-content-status> |
||||
[scheduled]="content.scheduleJob" |
|
||||
small="true"> |
|
||||
</sqx-content-status> |
|
||||
</button> |
|
||||
|
|
||||
<sqx-dropdown-menu *sqxModal="dropdown;closeAlways:true" [sqxAnchoredTo]="buttonOptions" scrollY="true"> |
|
||||
<ng-container *ngIf="content.statusUpdates.length > 0"> |
|
||||
<a class="dropdown-item" *ngFor="let info of content.statusUpdates" (click)="changeStatus(info.status)"> |
|
||||
{{ 'common.statusChangeTo' | sqxTranslate }} |
|
||||
|
|
||||
<sqx-content-status |
|
||||
layout="text" |
|
||||
[status]="info.status" |
|
||||
[statusColor]="info.color" |
|
||||
small="true"> |
|
||||
</sqx-content-status> |
|
||||
</a> |
|
||||
|
|
||||
<div class="dropdown-divider"></div> |
|
||||
</ng-container> |
|
||||
|
|
||||
<a class="dropdown-item dropdown-item-delete" [class.disabled]="!content.canCancelStatus" |
|
||||
(sqxConfirmClick)="cancelStatus()" |
|
||||
confirmTitle="i18n:contents.cancelStatusConfirmTitle" |
|
||||
confirmText="i18n:contents.cancelStatusConfirmText" |
|
||||
confirmRememberKey="cancelStatus"> |
|
||||
{{ 'contents.cancelStatus' | sqxTranslate }} |
|
||||
</a> |
|
||||
|
|
||||
<div class="dropdown-divider"></div> |
|
||||
|
|
||||
<a class="dropdown-item dropdown-item-delete" [class.disabled]="!content.canDelete" |
|
||||
(sqxConfirmClick)="delete()" |
|
||||
confirmTitle="i18n:contents.deleteConfirmTitle" |
|
||||
confirmText="i18n:contents.deleteConfirmText" |
|
||||
confirmRememberKey="deleteContent"> |
|
||||
{{ 'common.delete' | sqxTranslate }} |
|
||||
</a> |
|
||||
</sqx-dropdown-menu> |
|
||||
</div> |
|
||||
|
|
||||
<ng-template #newStatusOld> |
|
||||
<button type="button" class="btn btn-outline-secondary btn-block btn-status"> |
|
||||
<sqx-content-status [status]="content.status" [statusColor]="content.statusColor" layout="multiline"></sqx-content-status> |
|
||||
</button> |
</button> |
||||
</ng-template> |
} |
||||
|
|
||||
<sqx-form-hint marginTop="1"> |
<sqx-form-hint marginTop="1"> |
||||
{{ 'contents.lastUpdatedLabel' | sqxTranslate }}: {{content.lastModified | sqxFromNow}} |
{{ "contents.lastUpdatedLabel" | sqxTranslate }}: {{ content.lastModified | sqxFromNow }} |
||||
</sqx-form-hint> |
</sqx-form-hint> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="section"> |
<div class="section"> |
||||
<h3 class="bordered">{{ 'common.history' | sqxTranslate }}</h3> |
<h3 class="bordered">{{ "common.history" | sqxTranslate }}</h3> |
||||
|
|
||||
<sqx-content-event *ngFor="let event of contentEvents | async; trackBy: trackByEvent" |
@for (event of contentEvents | async; track event.eventId) { |
||||
[content]="content" |
<sqx-content-event |
||||
[event]="event" |
[content]="content" |
||||
(dataLoad)="loadVersion(event)" |
(dataCompare)="compareVersion(event)" |
||||
(dataCompare)="compareVersion(event)"> |
(dataLoad)="loadVersion(event)" |
||||
</sqx-content-event> |
[event]="event"></sqx-content-event> |
||||
|
} |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-layout> |
</sqx-layout> |
||||
|
|
||||
<sqx-due-time-selector [disabled]="disableScheduler" #dueTimeSelector></sqx-due-time-selector> |
<sqx-due-time-selector #dueTimeSelector [disabled]="disableScheduler"></sqx-due-time-selector> |
||||
|
|||||
@ -1,47 +1,60 @@ |
|||||
<sqx-form-error bubble="true" closeable="true" [error]="(contentForm.error | async)"></sqx-form-error> |
<sqx-form-error bubble="true" closeable="true" [error]="contentForm.error | async"></sqx-form-error> |
||||
|
|
||||
<sqx-list-view noPadding="true"> |
<sqx-list-view noPadding="true"> |
||||
<ng-container topHeader> |
<ng-container topHeader> |
||||
<div class="alert alert-danger" *ngIf="!contentVersion && isDeleted"> |
@if (!contentVersion && isDeleted) { |
||||
{{ 'contents.deleted' | sqxTranslate }} |
<div class="alert alert-danger"> |
||||
</div> |
{{ "contents.deleted" | sqxTranslate }} |
||||
|
|
||||
<div class="alert alert-danger" *ngIf="contentVersion"> |
|
||||
<div class="float-end"> |
|
||||
<a (click)="loadLatest.emit()">{{ 'contents.viewLatest' | sqxTranslate }}</a> |
|
||||
</div> |
</div> |
||||
|
} |
||||
|
|
||||
<div *ngIf="isDeleted" |
@if (contentVersion) { |
||||
[innerHTML]="'contents.versionViewingDeleted' | sqxTranslate: { version: contentVersion } | sqxMarkdownInline | sqxSafeHtml"> |
<div class="alert alert-danger"> |
||||
|
<div class="float-end"> |
||||
|
<a (click)="loadLatest.emit()">{{ "contents.viewLatest" | sqxTranslate }}</a> |
||||
|
</div> |
||||
|
@if (isDeleted) { |
||||
|
<div |
||||
|
[innerHTML]=" |
||||
|
'contents.versionViewingDeleted' | sqxTranslate: { version: contentVersion } | sqxMarkdownInline | sqxSafeHtml |
||||
|
"></div> |
||||
|
} |
||||
|
@if (!isDeleted) { |
||||
|
<div |
||||
|
[innerHTML]=" |
||||
|
'contents.versionViewing' | sqxTranslate: { version: contentVersion } | sqxMarkdownInline | sqxSafeHtml |
||||
|
"></div> |
||||
|
} |
||||
</div> |
</div> |
||||
|
} |
||||
<div *ngIf="!isDeleted" |
|
||||
[innerHTML]="'contents.versionViewing' | sqxTranslate: { version: contentVersion } | sqxMarkdownInline | sqxSafeHtml"> |
@if (isNew && showIdInput) { |
||||
|
<div> |
||||
|
<input |
||||
|
class="form-control" |
||||
|
[ngModel]="contentId" |
||||
|
(ngModelChange)="contentIdChange.emit($event)" |
||||
|
placeholder="{{ 'contents.idPlaceholder' | sqxTranslate }}" /> |
||||
</div> |
</div> |
||||
</div> |
} |
||||
|
|
||||
<div *ngIf="isNew && showIdInput"> |
|
||||
<input class="form-control" placeholder="{{ 'contents.idPlaceholder' | sqxTranslate }}" |
|
||||
[ngModel]="contentId" |
|
||||
(ngModelChange)="contentIdChange.emit($event)" /> |
|
||||
</div> |
|
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container> |
<ng-container> |
||||
<div class="cursors" sqxCursors> |
<div class="cursors" sqxCursors> |
||||
<sqx-cursors></sqx-cursors> |
<sqx-cursors></sqx-cursors> |
||||
|
|
||||
<sqx-content-section *ngFor="let section of contentForm.sections; trackBy: trackBySection" |
@for (section of contentForm.sections; track section.separator?.fieldId) { |
||||
[form]="contentForm" |
<sqx-content-section |
||||
[formCompare]="contentFormCompare" |
[form]="contentForm" |
||||
[formContext]="formContext" |
[formCompare]="contentFormCompare" |
||||
[formLevel]="0" |
[formContext]="formContext" |
||||
[formSection]="section" |
[formLevel]="0" |
||||
[language]="language" |
[formSection]="section" |
||||
(languageChange)="languageChange.emit($event)" |
[language]="language" |
||||
[languages]="languages" |
(languageChange)="languageChange.emit($event)" |
||||
[schema]="schema"> |
[languages]="languages" |
||||
</sqx-content-section> |
[schema]="schema"></sqx-content-section> |
||||
|
} |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-list-view> |
</sqx-list-view> |
||||
|
|||||
@ -1,30 +1,27 @@ |
|||||
<sqx-form-error bubble="true" closeable="true" [error]="contentError"></sqx-form-error> |
<sqx-form-error bubble="true" closeable="true" [error]="contentError"></sqx-form-error> |
||||
|
|
||||
<div class="inner-menu"> |
<div class="inner-menu"> |
||||
<ul class="nav nav-tabs2" *ngIf="mode | async; let currentMode"> |
@if (mode | async; as currentMode) { |
||||
<li class="nav-item"> |
<ul class="nav nav-tabs2"> |
||||
<a class="nav-link" [class.active]="currentMode === 'Content'" (click)="setMode('Content')"> |
<li class="nav-item"> |
||||
{{ 'contents.inspectContent' | sqxTranslate }} |
<a class="nav-link" [class.active]="currentMode === 'Content'" (click)="setMode('Content')"> |
||||
</a> |
{{ "contents.inspectContent" | sqxTranslate }} |
||||
</li> |
</a> |
||||
<li class="nav-item"> |
</li> |
||||
<a class="nav-link" [class.active]="currentMode === 'Data'" (click)="setMode('Data')"> |
<li class="nav-item"> |
||||
{{ 'contents.inspectData' | sqxTranslate }} |
<a class="nav-link" [class.active]="currentMode === 'Data'" (click)="setMode('Data')"> |
||||
</a> |
{{ "contents.inspectData" | sqxTranslate }} |
||||
</li> |
</a> |
||||
<li class="nav-item"> |
</li> |
||||
<a class="nav-link" [class.active]="currentMode === 'FlatData'" (click)="setMode('FlatData')"> |
<li class="nav-item"> |
||||
{{ 'contents.inspectFlatData' | sqxTranslate }} |
<a class="nav-link" [class.active]="currentMode === 'FlatData'" (click)="setMode('FlatData')"> |
||||
</a> |
{{ "contents.inspectFlatData" | sqxTranslate }} |
||||
</li> |
</a> |
||||
</ul> |
</li> |
||||
|
</ul> |
||||
|
} |
||||
</div> |
</div> |
||||
|
|
||||
<div class="inner-main"> |
<div class="inner-main"> |
||||
<sqx-code-editor |
<sqx-code-editor borderless="true" [ngModel]="actualData | async" (ngModelChange)="setData($event)" valueMode="Json"></sqx-code-editor> |
||||
borderless="true" |
|
||||
[ngModel]="actualData | async" |
|
||||
(ngModelChange)="setData($event)" |
|
||||
valueMode="Json"> |
|
||||
</sqx-code-editor> |
|
||||
</div> |
</div> |
||||
|
|||||
@ -1,32 +1,40 @@ |
|||||
<sqx-list-view [isLoading]="contentsState.isLoading | async" table="true"> |
<sqx-list-view [isLoading]="contentsState.isLoading | async" table="true"> |
||||
<ng-container> |
<ng-container> |
||||
<table class="table table-items table-fixed" *ngIf="contentsState.contents | async; let contents"> |
@if (contentsState.contents | async; as contents) { |
||||
<tbody *ngFor="let content of contents; trackBy: trackByContent" |
<table class="table table-items table-fixed"> |
||||
[sqxReferenceItem]="content" |
@for (content of contents; track content.id) { |
||||
[canRemove]="false" |
<tbody |
||||
[columns]="contents | sqxContentsColumns" |
[canRemove]="false" |
||||
[isCompact]="false" |
[columns]="contents | sqxContentsColumns" |
||||
[isDisabled]="false" |
[isCompact]="false" |
||||
[language]="language" |
[isDisabled]="false" |
||||
[languages]="languages" |
[language]="language" |
||||
[validations]="(contentsState.validationResults | async)!" |
[languages]="languages" |
||||
[validityVisible]="true"> |
[sqxReferenceItem]="content" |
||||
</tbody> |
[validations]="(contentsState.validationResults | async)!" |
||||
|
[validityVisible]="true"></tbody> |
||||
<tbody *ngIf="(contentsState.isLoaded | async) && contents.length === 0"> |
} |
||||
<tr> |
@if ((contentsState.isLoaded | async) && contents.length === 0) { |
||||
<td class="table-items-row-empty" *ngIf="mode === 'references'"> |
<tbody> |
||||
{{ 'contents.noReferences' | sqxTranslate }} |
<tr> |
||||
</td> |
@if (mode === "references") { |
||||
<td class="table-items-row-empty" *ngIf="mode === 'referencing'"> |
<td class="table-items-row-empty"> |
||||
{{ 'contents.noReferencing' | sqxTranslate }} |
{{ "contents.noReferences" | sqxTranslate }} |
||||
</td> |
</td> |
||||
</tr> |
} |
||||
</tbody> |
@if (mode === "referencing") { |
||||
</table> |
<td class="table-items-row-empty"> |
||||
|
{{ "contents.noReferencing" | sqxTranslate }} |
||||
|
</td> |
||||
|
} |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
} |
||||
|
</table> |
||||
|
} |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container footer> |
<ng-container footer> |
||||
<sqx-pager [paging]="contentsState.paging | async" (pagingChange)="contentsState.page($event)"></sqx-pager> |
<sqx-pager [paging]="contentsState.paging | async" (pagingChange)="contentsState.page($event)"></sqx-pager> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-list-view> |
</sqx-list-view> |
||||
|
|||||
@ -1,10 +1,16 @@ |
|||||
<sqx-layout layout="main" titleText="i18n:common.contents" titleIcon="contents" hideHeader="true" hideSidebar="true" white="true" overflow="true"> |
<sqx-layout |
||||
<ng-container *ngIf="schema | async; let schema"> |
hideHeader="true" |
||||
<sqx-content-extension |
hideSidebar="true" |
||||
[editorUrl]="schema.properties.contentsListUrl" |
layout="main" |
||||
|
overflow="true" |
||||
|
titleIcon="contents" |
||||
|
titleText="i18n:common.contents" |
||||
|
white="true"> |
||||
|
@if (schema | async; as schema) { |
||||
|
<sqx-content-extension |
||||
[contentItem]="undefined" |
[contentItem]="undefined" |
||||
[contentSchema]="schema" |
[contentSchema]="schema" |
||||
scrollable="true"> |
[editorUrl]="schema.properties.contentsListUrl" |
||||
</sqx-content-extension> |
scrollable="true"></sqx-content-extension> |
||||
</ng-container> |
} |
||||
</sqx-layout> |
</sqx-layout> |
||||
|
|||||
@ -1,32 +1,24 @@ |
|||||
<sqx-layout layout="right" titleText="i18n:common.filters" width="20" white="true" padding="true" overflow="true"> |
<sqx-layout layout="right" overflow="true" padding="true" titleText="i18n:common.filters" white="true" width="20"> |
||||
<ng-container *ngIf="schemaQueries | async; let queries"> |
@if (schemaQueries | async; as queries) { |
||||
<sqx-query-list |
<sqx-query-list |
||||
[types]="'common.contents' | sqxTranslate" |
|
||||
[queryUsed]="contentsState.query | async" |
|
||||
[queries]="queries.defaultQueries" |
[queries]="queries.defaultQueries" |
||||
(search)="search($event)"> |
[queryUsed]="contentsState.query | async" |
||||
</sqx-query-list> |
(search)="search($event)" |
||||
|
[types]="'common.contents' | sqxTranslate"></sqx-query-list> |
||||
<hr> |
<hr /> |
||||
|
|
||||
<div class="sidebar-section"> |
<div class="sidebar-section"> |
||||
<h3>{{ 'contents.statusQueries' | sqxTranslate }}</h3> |
<h3>{{ "contents.statusQueries" | sqxTranslate }}</h3> |
||||
|
|
||||
<sqx-query-list |
<sqx-query-list |
||||
[types]="'common.contents' | sqxTranslate" |
|
||||
[queryUsed]="contentsState.query | async" |
|
||||
[queries]="contentsState.statusQueries | async" |
[queries]="contentsState.statusQueries | async" |
||||
(search)="search($event)"> |
[queryUsed]="contentsState.query | async" |
||||
</sqx-query-list> |
(search)="search($event)" |
||||
|
[types]="'common.contents' | sqxTranslate"></sqx-query-list> |
||||
</div> |
</div> |
||||
|
<hr /> |
||||
<hr> |
|
||||
|
|
||||
<sqx-shared-queries |
<sqx-shared-queries |
||||
[types]="'common.contents' | sqxTranslate" |
|
||||
[queryUsed]="contentsState.query | async" |
|
||||
[queries]="queries" |
[queries]="queries" |
||||
(search)="search($event)"> |
[queryUsed]="contentsState.query | async" |
||||
</sqx-shared-queries> |
(search)="search($event)" |
||||
</ng-container> |
[types]="'common.contents' | sqxTranslate"></sqx-shared-queries> |
||||
</sqx-layout> |
} |
||||
|
</sqx-layout> |
||||
|
|||||
@ -1,177 +1,211 @@ |
|||||
<sqx-title [message]="schema.displayName"></sqx-title> |
<sqx-title [message]="schema.displayName"></sqx-title> |
||||
|
|
||||
<sqx-layout layout="main" titleText="i18n:common.contents" titleIcon="contents"> |
<sqx-layout layout="main" titleIcon="contents" titleText="i18n:common.contents"> |
||||
<ng-container menu> |
<ng-container menu> |
||||
<div class="row flex-nowrap flex-grow-1 gx-2"> |
<div class="row flex-nowrap flex-grow-1 gx-2"> |
||||
<div class="col-auto ms-8"> |
<div class="col-auto ms-8"> |
||||
<sqx-notifo topic="apps/{{contentsState.appId}}/schemas/{{schema.id}}/contents" position="bottom-left"></sqx-notifo> |
<sqx-notifo position="bottom-left" topic="apps/{{ contentsState.appId }}/schemas/{{ schema.id }}/contents"></sqx-notifo> |
||||
|
|
||||
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="i18n:contents.refreshTooltip" shortcut="CTRL + B"> |
<button |
||||
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }} |
class="btn btn-text-secondary" |
||||
|
(click)="reload()" |
||||
|
shortcut="CTRL + B" |
||||
|
title="i18n:contents.refreshTooltip" |
||||
|
type="button"> |
||||
|
<i class="icon-reset"></i> |
||||
|
{{ "common.refresh" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</div> |
</div> |
||||
<div class="col"> |
<div class="col"> |
||||
<sqx-search-form formClass="form" placeholder="{{ 'contents.searchPlaceholder' | sqxTranslate }}" |
<sqx-search-form |
||||
enableShortcut="true" |
enableShortcut="true" |
||||
|
formClass="form" |
||||
[language]="(languagesState.isoMasterLanguage | async)!" |
[language]="(languagesState.isoMasterLanguage | async)!" |
||||
[languages]="languages" |
[languages]="languages" |
||||
|
placeholder="{{ 'contents.searchPlaceholder' | sqxTranslate }}" |
||||
[queries]="queries | async" |
[queries]="queries | async" |
||||
[queriesTypes]="'common.contents' | sqxTranslate" |
[queriesTypes]="'common.contents' | sqxTranslate" |
||||
(queryChange)="search($event)" |
|
||||
[query]="contentsState.query | async" |
[query]="contentsState.query | async" |
||||
|
(queryChange)="search($event)" |
||||
[queryModel]="queryModel | async" |
[queryModel]="queryModel | async" |
||||
[statuses]="contentsState.statuses | async"> |
[statuses]="contentsState.statuses | async"></sqx-search-form> |
||||
</sqx-search-form> |
|
||||
</div> |
|
||||
<div class="col-auto" *ngIf="languages.length > 1"> |
|
||||
<sqx-language-selector class="languages-buttons" |
|
||||
(languageChange)="changeLanguage($event)" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[percents]="translationStatus"> |
|
||||
</sqx-language-selector> |
|
||||
</div> |
</div> |
||||
|
@if (languages.length > 1) { |
||||
|
<div class="col-auto"> |
||||
|
<sqx-language-selector |
||||
|
class="languages-buttons" |
||||
|
[language]="language" |
||||
|
(languageChange)="changeLanguage($event)" |
||||
|
[languages]="languages" |
||||
|
[percents]="translationStatus"></sqx-language-selector> |
||||
|
</div> |
||||
|
} |
||||
<div class="col-auto"> |
<div class="col-auto"> |
||||
<button type="button" class="btn btn-success" routerLink="new" title="i18n:contents.createContentTooltip" shortcut="CTRL + U" [disabled]="(contentsState.canCreateAny | async) === false" sqxTourStep="addContent"> |
<button |
||||
<i class="icon-plus"></i> {{ 'contents.create' | sqxTranslate }} |
class="btn btn-success" |
||||
|
[disabled]="(contentsState.canCreateAny | async) === false" |
||||
|
routerLink="new" |
||||
|
shortcut="CTRL + U" |
||||
|
sqxTourStep="addContent" |
||||
|
title="i18n:contents.createContentTooltip" |
||||
|
type="button"> |
||||
|
<i class="icon-plus"></i> |
||||
|
{{ "contents.create" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container> |
<ng-container> |
||||
<ng-container *ngIf="tableSettings | async; let tableSettings"> |
@if (tableSettings | async; as tableSettings) { |
||||
<ng-container *ngIf="tableSettings.listFields | async; let tableFields"> |
@if (tableSettings.listFields | async; as tableFields) { |
||||
<sqx-list-view [isLoading]="contentsState.isLoading | async" syncedHeader="true" tableNoPadding="true"> |
<sqx-list-view [isLoading]="contentsState.isLoading | async" syncedHeader="true" tableNoPadding="true"> |
||||
<ng-container topHeader> |
<ng-container topHeader> |
||||
<div class="selection" *ngIf="selectionCount > 0"> |
@if (selectionCount > 0) { |
||||
{{ 'contents.selectionCount' | sqxTranslate: { count: selectionCount } }} |
<div class="selection"> |
||||
|
{{ "contents.selectionCount" | sqxTranslate: { count: selectionCount } }} |
||||
<button type="button" class="btn btn-outline-secondary btn-status me-2" *ngFor="let status of selectionStatuses | sqxKeys" (click)="changeSelectedStatus(status)"> |
@for (status of selectionStatuses | sqxKeys; track status) { |
||||
<sqx-content-status layout="text" |
<button |
||||
[status]="status" |
class="btn btn-outline-secondary btn-status me-2" |
||||
[statusColor]="selectionStatuses[status]"> |
(click)="changeSelectedStatus(status)" |
||||
</sqx-content-status> |
type="button"> |
||||
</button> |
<sqx-content-status |
||||
|
layout="text" |
||||
<button type="button" class="btn btn-danger" *ngIf="selectionCanDelete" |
[status]="status" |
||||
(sqxConfirmClick)="deleteSelected()" |
[statusColor]="selectionStatuses[status]"></sqx-content-status> |
||||
confirmTitle="i18n:contents.deleteConfirmTitle" |
</button> |
||||
confirmText="i18n:contents.deleteManyConfirmText" |
} |
||||
confirmRememberKey="deleteContents"> |
@if (selectionCanDelete) { |
||||
{{ 'common.delete' | sqxTranslate }} |
<button |
||||
</button> |
class="btn btn-danger" |
||||
</div> |
confirmRememberKey="deleteContents" |
||||
|
confirmText="i18n:contents.deleteManyConfirmText" |
||||
|
confirmTitle="i18n:contents.deleteConfirmTitle" |
||||
|
(sqxConfirmClick)="deleteSelected()" |
||||
|
type="button"> |
||||
|
{{ "common.delete" | sqxTranslate }} |
||||
|
</button> |
||||
|
} |
||||
|
</div> |
||||
|
} |
||||
<div class="settings-container"> |
<div class="settings-container"> |
||||
<button type="button" class="btn btn-sm settings-button" (click)="tableViewModal.toggle()" #buttonSettings> |
<button class="btn btn-sm settings-button" #buttonSettings (click)="tableViewModal.toggle()" type="button"> |
||||
<span class="hidden">{{ 'common.settings' | sqxTranslate }}</span> |
<span class="hidden">{{ "common.settings" | sqxTranslate }}</span> |
||||
<i class="icon-settings"></i> |
<i class="icon-settings"></i> |
||||
</button> |
</button> |
||||
|
<sqx-dropdown-menu |
||||
<sqx-dropdown-menu *sqxModal="tableViewModal" [sqxAnchoredTo]="buttonSettings" scrollY="true" position="bottom-end"> |
position="bottom-end" |
||||
|
scrollY="true" |
||||
|
[sqxAnchoredTo]="buttonSettings" |
||||
|
*sqxModal="tableViewModal"> |
||||
<sqx-custom-view-editor |
<sqx-custom-view-editor |
||||
[allFields]="tableSettings.schemaFields" |
[allFields]="tableSettings.schemaFields" |
||||
|
[listFields]="$any(tableFields)" |
||||
(listFieldsChange)="tableSettings.updateFields($event)" |
(listFieldsChange)="tableSettings.updateFields($event)" |
||||
(listFieldsReset)="tableSettings.reset()" |
(listFieldsReset)="tableSettings.reset()"></sqx-custom-view-editor> |
||||
[listFields]="$any(tableFields)"> |
|
||||
</sqx-custom-view-editor> |
|
||||
</sqx-dropdown-menu> |
</sqx-dropdown-menu> |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container header> |
<ng-container header> |
||||
<table class="table table-items table-fixed" [sqxContentListWidth]="tableFields" [fields]="tableSettings" #header> |
<table class="table table-items table-fixed" #header [fields]="tableSettings" [sqxContentListWidth]="tableFields"> |
||||
<thead> |
<thead> |
||||
<tr> |
<tr> |
||||
<th class="cell-select"> |
<th class="cell-select"> |
||||
<div class="form-check"> |
<div class="form-check"> |
||||
<input class="form-check-input" type="checkbox" id="all_selected" |
<input |
||||
[ngModel]="selectedAll" |
class="form-check-input" |
||||
(ngModelChange)="selectAll($event)"> |
id="all_selected" |
||||
|
[ngModel]="selectedAll" |
||||
|
(ngModelChange)="selectAll($event)" |
||||
|
type="checkbox" /> |
||||
<label class="form-check-label" for="all_selected"></label> |
<label class="form-check-label" for="all_selected"></label> |
||||
</div> |
</div> |
||||
</th> |
</th> |
||||
<th class="cell-actions cell-actions-left"> |
<th class="cell-actions cell-actions-left"> |
||||
<span class="truncate">{{ 'common.actions' | sqxTranslate }}</span> |
<span class="truncate">{{ "common.actions" | sqxTranslate }}</span> |
||||
</th> |
|
||||
<th *ngFor="let field of tableFields" |
|
||||
sqxContentListCell |
|
||||
sqxContentListCellResize |
|
||||
[field]="field" |
|
||||
[fields]="tableSettings"> |
|
||||
<sqx-content-list-header |
|
||||
[field]="field" |
|
||||
(queryChange)="search($event)" |
|
||||
[query]="(contentsState.query | async)!" |
|
||||
[language]="language"> |
|
||||
</sqx-content-list-header> |
|
||||
</th> |
</th> |
||||
|
@for (field of tableFields; track field) { |
||||
|
<th [field]="field" [fields]="tableSettings" sqxContentListCell sqxContentListCellResize> |
||||
|
<sqx-content-list-header |
||||
|
[field]="field" |
||||
|
[language]="language" |
||||
|
[query]="(contentsState.query | async)!" |
||||
|
(queryChange)="search($event)"></sqx-content-list-header> |
||||
|
</th> |
||||
|
} |
||||
<th></th> |
<th></th> |
||||
</tr> |
</tr> |
||||
</thead> |
</thead> |
||||
</table> |
</table> |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container> |
<ng-container> |
||||
<div class="table-container"> |
<div class="table-container"> |
||||
<table class="table table-center table-fixed" [sqxContentListWidth]="tableFields" [fields]="tableSettings" [sqxSyncWidth]="header"> |
<table |
||||
<tbody *ngFor="let content of contentsState.contents | async; trackBy: trackByContent" |
class="table table-center table-fixed" |
||||
[sqxContent]="content" |
[fields]="tableSettings" |
||||
(clone)="clone(content)" |
[sqxContentListWidth]="tableFields" |
||||
[cloneable]="contentsState.snapshot.canCreate" |
[sqxSyncWidth]="header"> |
||||
(delete)="delete(content)" |
@for (content of contentsState.contents | async; track content.id) { |
||||
[language]="language" |
<tbody |
||||
[languages]="languages" |
(clone)="clone(content)" |
||||
[link]="[content.id, 'history']" |
[cloneable]="contentsState.snapshot.canCreate" |
||||
[schema]="schema" |
(delete)="delete(content)" |
||||
[selected]="isItemSelected(content)" |
[language]="language" |
||||
(selectedChange)="selectItem(content, $event)" |
[languages]="languages" |
||||
(statusChange)="changeStatus(content, $event)" |
[link]="[content.id, 'history']" |
||||
[tableFields]="tableFields" |
[schema]="schema" |
||||
[tableSettings]="tableSettings"> |
[selected]="isItemSelected(content)" |
||||
</tbody> |
(selectedChange)="selectItem(content, $event)" |
||||
|
[sqxContent]="content" |
||||
|
(statusChange)="changeStatus(content, $event)" |
||||
|
[tableFields]="tableFields" |
||||
|
[tableSettings]="tableSettings"></tbody> |
||||
|
} |
||||
</table> |
</table> |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container footer> |
<ng-container footer> |
||||
<sqx-pager (loadTotal)="reloadTotal()" [paging]="contentsState.paging | async" (pagingChange)="contentsState.page($event)"></sqx-pager> |
<sqx-pager |
||||
|
(loadTotal)="reloadTotal()" |
||||
|
[paging]="contentsState.paging | async" |
||||
|
(pagingChange)="contentsState.page($event)"></sqx-pager> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-list-view> |
</sqx-list-view> |
||||
</ng-container> |
} |
||||
</ng-container> |
} |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-template sidebarMenu> |
<ng-template sidebarMenu> |
||||
<div class="panel-nav"> |
<div class="panel-nav"> |
||||
<a class="panel-link" |
<a |
||||
|
class="panel-link" |
||||
|
queryParamsHandling="preserve" |
||||
replaceUrl="true" |
replaceUrl="true" |
||||
routerLink="filters" |
routerLink="filters" |
||||
routerLinkActive="active" |
routerLinkActive="active" |
||||
queryParamsHandling="preserve" |
sqxTourStep="filters" |
||||
title="i18n:common.filters" |
title="i18n:common.filters" |
||||
titlePosition="left" |
titlePosition="left"> |
||||
sqxTourStep="filters"> |
|
||||
<i class="icon-filter"></i> |
<i class="icon-filter"></i> |
||||
</a> |
</a> |
||||
|
|
||||
<a class="panel-link" |
@if (schema.properties.contentsSidebarUrl) { |
||||
replaceUrl="true" |
<a |
||||
routerLink="sidebar" |
class="panel-link" |
||||
routerLinkActive="active" |
queryParamsHandling="preserve" |
||||
queryParamsHandling="preserve" |
replaceUrl="true" |
||||
title="i18n:common.sidebar" |
routerLink="sidebar" |
||||
titlePosition="left" |
routerLinkActive="active" |
||||
sqxTourStep="plugin" |
sqxTourStep="plugin" |
||||
*ngIf="schema.properties.contentsSidebarUrl"> |
title="i18n:common.sidebar" |
||||
<i class="icon-plugin"></i> |
titlePosition="left"> |
||||
</a> |
<i class="icon-plugin"></i> |
||||
|
</a> |
||||
|
} |
||||
</div> |
</div> |
||||
</ng-template> |
</ng-template> |
||||
</sqx-layout> |
</sqx-layout> |
||||
|
|
||||
<router-outlet></router-outlet> |
<router-outlet></router-outlet> |
||||
|
|
||||
<sqx-due-time-selector [disabled]="disableScheduler" #dueTimeSelector></sqx-due-time-selector> |
<sqx-due-time-selector #dueTimeSelector [disabled]="disableScheduler"></sqx-due-time-selector> |
||||
|
|||||
@ -1,52 +1,62 @@ |
|||||
<div class="container"> |
<div class="container"> |
||||
<div class="header"> |
<div class="header"> |
||||
<button type="button" class="btn btn-secondary btn-sm" (click)="resetDefault()"> |
<button class="btn btn-secondary btn-sm" (click)="resetDefault()" type="button"> |
||||
{{ 'contents.viewReset' | sqxTranslate }} |
{{ "contents.viewReset" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</div> |
</div> |
||||
|
|
||||
<hr> |
|
||||
|
|
||||
<div |
<hr /> |
||||
cdkDropList |
|
||||
[cdkDropListData]="listFields" |
<div cdkDropList [cdkDropListData]="listFields" (cdkDropListDropped)="drop($event)"> |
||||
(cdkDropListDropped)="drop($event)"> |
@for (field of listFields; track field) { |
||||
<div *ngFor="let field of listFields" cdkDrag> |
<div cdkDrag> |
||||
<i class="icon-drag2 drag-handle"></i> |
<i class="icon-drag2 drag-handle"></i> |
||||
|
|
||||
<div class="form-check"> |
|
||||
<input class="form-check-input" type="checkbox" checked (click)="removeField(field)" id="field_{{field}}" [disabled]="!field"> |
|
||||
<label class="form-check-label" for="field_{{field}}"> |
|
||||
<span *ngIf="field.name"> |
|
||||
{{(field.title || field.label) | sqxTranslate}}: <code>{{field.name}}</code> |
|
||||
</span> |
|
||||
<span class="text-muted" *ngIf="!field.name"> |
|
||||
- Placeholder - |
|
||||
</span> |
|
||||
</label> |
|
||||
</div> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
<ng-container *ngIf="fieldsNotAdded.length > 0"> |
|
||||
<hr> |
|
||||
|
|
||||
<div > |
|
||||
<div *ngFor="let field of fieldsNotAdded"> |
|
||||
<i class="icon-drag2 drag-handle invisible"></i> |
|
||||
|
|
||||
<div class="form-check"> |
<div class="form-check"> |
||||
<input class="form-check-input" type="checkbox" (click)="addField(field)" id="field_{{field}}"> |
<input |
||||
<label class="form-check-label" for="field_{{field}}"> |
class="form-check-input" |
||||
<span *ngIf="field.name"> |
id="field_{{ field }}" |
||||
{{(field.title || field.label) | sqxTranslate}}: <code>{{field.name}}</code> |
checked |
||||
</span> |
(click)="removeField(field)" |
||||
<span class="text-muted" *ngIf="!field.name"> |
[disabled]="!field" |
||||
- Placeholder - |
type="checkbox" /> |
||||
</span> |
<label class="form-check-label" for="field_{{ field }}"> |
||||
|
@if (field.name) { |
||||
|
<span> |
||||
|
{{ field.title || field.label | sqxTranslate }}: |
||||
|
<code>{{ field.name }}</code> |
||||
|
</span> |
||||
|
} |
||||
|
@if (!field.name) { |
||||
|
<span class="text-muted">- Placeholder -</span> |
||||
|
} |
||||
</label> |
</label> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
} |
||||
|
</div> |
||||
|
|
||||
|
@if (fieldsNotAdded.length > 0) { |
||||
|
<hr /> |
||||
|
<div> |
||||
|
@for (field of fieldsNotAdded; track field) { |
||||
|
<div> |
||||
|
<i class="icon-drag2 drag-handle invisible"></i> |
||||
|
<div class="form-check"> |
||||
|
<input class="form-check-input" id="field_{{ field }}" (click)="addField(field)" type="checkbox" /> |
||||
|
<label class="form-check-label" for="field_{{ field }}"> |
||||
|
@if (field.name) { |
||||
|
<span> |
||||
|
{{ field.title || field.label | sqxTranslate }}: |
||||
|
<code>{{ field.name }}</code> |
||||
|
</span> |
||||
|
} |
||||
|
@if (!field.name) { |
||||
|
<span class="text-muted">- Placeholder -</span> |
||||
|
} |
||||
|
</label> |
||||
|
</div> |
||||
|
</div> |
||||
|
} |
||||
</div> |
</div> |
||||
</ng-container> |
} |
||||
</div> |
</div> |
||||
|
|||||
@ -1,52 +1,64 @@ |
|||||
<sqx-title message="i18n:common.references"></sqx-title> |
<sqx-title message="i18n:common.references"></sqx-title> |
||||
|
|
||||
<sqx-layout layout="main" titleText="i18n:common.references" titleIcon="contents"> |
<sqx-layout layout="main" titleIcon="contents" titleText="i18n:common.references"> |
||||
<ng-container menu> |
<ng-container menu> |
||||
<div class="row flex-nowrap flex-grow-1 gx-2"> |
<div class="row flex-nowrap flex-grow-1 gx-2"> |
||||
<div class="col-auto ms-8"> |
<div class="col-auto ms-8"> |
||||
<button type="button" class="btn btn-text-secondary" (click)="reload()" title="i18n:contents.refreshTooltip" shortcut="CTRL + B"> |
<button |
||||
<i class="icon-reset"></i> {{ 'common.refresh' | sqxTranslate }} |
class="btn btn-text-secondary" |
||||
|
(click)="reload()" |
||||
|
shortcut="CTRL + B" |
||||
|
title="i18n:contents.refreshTooltip" |
||||
|
type="button"> |
||||
|
<i class="icon-reset"></i> |
||||
|
{{ "common.refresh" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</div> |
</div> |
||||
<div class="col-auto" *ngIf="languages.length > 1"> |
@if (languages.length > 1) { |
||||
<sqx-language-selector class="languages-buttons" |
<div class="col-auto"> |
||||
(languageChange)="changeLanguage($event)" |
<sqx-language-selector |
||||
[language]="language" |
class="languages-buttons" |
||||
[languages]="languages"> |
[language]="language" |
||||
</sqx-language-selector> |
(languageChange)="changeLanguage($event)" |
||||
</div> |
[languages]="languages"></sqx-language-selector> |
||||
|
</div> |
||||
|
} |
||||
</div> |
</div> |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container> |
<ng-container> |
||||
<sqx-list-view [isLoading]="contentsState.isLoading | async" table="true"> |
<sqx-list-view [isLoading]="contentsState.isLoading | async" table="true"> |
||||
<ng-container> |
<ng-container> |
||||
<table class="table table-items table-fixed" *ngIf="contentsState.contents | async; let contents"> |
@if (contentsState.contents | async; as contents) { |
||||
<tbody *ngFor="let content of contents; trackBy: trackByContent" |
<table class="table table-items table-fixed"> |
||||
[sqxReferenceItem]="content" |
@for (content of contents; track content.id) { |
||||
[canRemove]="false" |
<tbody |
||||
[columns]="contents | sqxContentsColumns" |
[canRemove]="false" |
||||
[isCompact]="false" |
[columns]="contents | sqxContentsColumns" |
||||
[isDisabled]="false" |
[isCompact]="false" |
||||
[language]="language" |
[isDisabled]="false" |
||||
[languages]="languages" |
[language]="language" |
||||
[validations]="(contentsState.validationResults | async)!" |
[languages]="languages" |
||||
[validityVisible]="true"> |
[sqxReferenceItem]="content" |
||||
</tbody> |
[validations]="(contentsState.validationResults | async)!" |
||||
|
[validityVisible]="true"></tbody> |
||||
<tbody *ngIf="(contentsState.isLoaded | async) && contents.length === 0"> |
} |
||||
<tr> |
@if ((contentsState.isLoaded | async) && contents.length === 0) { |
||||
<td class="table-items-row-empty"> |
<tbody> |
||||
{{ 'contents.noReferencing' | sqxTranslate }} |
<tr> |
||||
</td> |
<td class="table-items-row-empty"> |
||||
</tr> |
{{ "contents.noReferencing" | sqxTranslate }} |
||||
</tbody> |
</td> |
||||
</table> |
</tr> |
||||
|
</tbody> |
||||
|
} |
||||
|
</table> |
||||
|
} |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container footer> |
<ng-container footer> |
||||
<sqx-pager [paging]="contentsState.paging | async" (pagingChange)="contentsState.page($event)"></sqx-pager> |
<sqx-pager [paging]="contentsState.paging | async" (pagingChange)="contentsState.page($event)"></sqx-pager> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-list-view> |
</sqx-list-view> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-layout> |
</sqx-layout> |
||||
|
|||||
@ -1,30 +1,31 @@ |
|||||
<sqx-title message="i18n:contents.schemasPageTitle"></sqx-title> |
<sqx-title message="i18n:contents.schemasPageTitle"></sqx-title> |
||||
|
|
||||
<sqx-layout layout="left" titleCollapsed="i18n:common.schemas" width="18" white="true" padding="true" overflow="true" *ngIf="!isEmbedded"> |
@if (!isEmbedded) { |
||||
<ng-container menu> |
<sqx-layout layout="left" overflow="true" padding="true" titleCollapsed="i18n:common.schemas" white="true" width="18"> |
||||
<div class="search-form"> |
<ng-container menu> |
||||
<input class="form-control" [formControl]="schemasFilter" placeholder="{{ 'contents.searchSchemasPlaceholder' | sqxTranslate }}"> |
<div class="search-form"> |
||||
|
<input |
||||
<i class="icon-search"></i> |
class="form-control" |
||||
</div> |
[formControl]="schemasFilter" |
||||
</ng-container> |
placeholder="{{ 'contents.searchSchemasPlaceholder' | sqxTranslate }}" /> |
||||
|
<i class="icon-search"></i> |
||||
<ng-container> |
</div> |
||||
<ul class="nav nav-light mb-2 flex-column"> |
</ng-container> |
||||
<li class="nav-item"> |
|
||||
<a class="nav-link" routerLink="__calendar" routerLinkActive="active"> |
|
||||
{{ 'contents.calendar' | sqxTranslate }} |
|
||||
</a> |
|
||||
</li> |
|
||||
</ul> |
|
||||
|
|
||||
<ng-container> |
<ng-container> |
||||
<sqx-schema-category *ngFor="let category of categories | async; trackBy: trackByCategory" |
<ul class="nav nav-light mb-2 flex-column"> |
||||
[schemaCategory]="category" |
<li class="nav-item"> |
||||
[schemaTarget]="'Contents'"> |
<a class="nav-link" routerLink="__calendar" routerLinkActive="active"> |
||||
</sqx-schema-category> |
{{ "contents.calendar" | sqxTranslate }} |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
<ng-container> |
||||
|
@for (category of categories | async; track category.name) { |
||||
|
<sqx-schema-category [schemaCategory]="category" [schemaTarget]="'Contents'"></sqx-schema-category> |
||||
|
} |
||||
|
</ng-container> |
||||
</ng-container> |
</ng-container> |
||||
</ng-container> |
</sqx-layout> |
||||
</sqx-layout> |
} |
||||
|
|
||||
<router-outlet></router-outlet> |
<router-outlet></router-outlet> |
||||
|
|||||
@ -1 +1 @@ |
|||||
<iframe #iframe [attr.scrollable]="scrollable ? 'yes' : 'no'" width="100%" [attr.src]="computedUrl | sqxSafeResourceUrl"></iframe> |
<iframe #iframe [attr.scrollable]="scrollable ? 'yes' : 'no'" [attr.src]="computedUrl | sqxSafeResourceUrl" width="100%"></iframe> |
||||
|
|||||
@ -1,33 +1,49 @@ |
|||||
<sqx-modal-dialog *sqxModal="dueTimeDialog" (dialogClose)="cancelStatusChange()"> |
<sqx-modal-dialog (dialogClose)="cancelStatusChange()" *sqxModal="dueTimeDialog"> |
||||
<ng-container title> |
<ng-container title> |
||||
{{ 'contents.changeStatusTo' | sqxTranslate: { action: dueTimeAction } }} |
{{ "contents.changeStatusTo" | sqxTranslate: { action: dueTimeAction } }} |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container content> |
<ng-container content> |
||||
<div class="form-check"> |
<div class="form-check"> |
||||
<input class="form-check-input" type="radio" [(ngModel)]="dueTimeMode" value="Immediately" id="immediately" name="dueTimeMode"> |
<input |
||||
|
class="form-check-input" |
||||
|
id="immediately" |
||||
|
name="dueTimeMode" |
||||
|
[(ngModel)]="dueTimeMode" |
||||
|
type="radio" |
||||
|
value="Immediately" /> |
||||
<label class="form-check-label" for="immediately"> |
<label class="form-check-label" for="immediately"> |
||||
{{ 'contents.changeStatusToImmediately' | sqxTranslate: { action: dueTimeAction } }} |
{{ "contents.changeStatusToImmediately" | sqxTranslate: { action: dueTimeAction } }} |
||||
</label> |
</label> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="form-check"> |
<div class="form-check"> |
||||
<input class="form-check-input" type="radio" [(ngModel)]="dueTimeMode" value="Scheduled" id="scheduled" name="dueTimeMode"> |
<input class="form-check-input" id="scheduled" name="dueTimeMode" [(ngModel)]="dueTimeMode" type="radio" value="Scheduled" /> |
||||
<label class="form-check-label" for="scheduled"> |
<label class="form-check-label" for="scheduled"> |
||||
{{ 'contents.changeStatusToLater' | sqxTranslate: { action: dueTimeAction } }} |
{{ "contents.changeStatusToLater" | sqxTranslate: { action: dueTimeAction } }} |
||||
</label> |
</label> |
||||
</div> |
</div> |
||||
|
|
||||
<sqx-date-time-editor [disabled]="dueTimeMode === 'Immediately'" enforceTime="true" mode="DateTime" hideClear="true" [(ngModel)]="dueTime"></sqx-date-time-editor> |
<sqx-date-time-editor |
||||
|
[disabled]="dueTimeMode === 'Immediately'" |
||||
|
enforceTime="true" |
||||
|
hideClear="true" |
||||
|
mode="DateTime" |
||||
|
[(ngModel)]="dueTime"></sqx-date-time-editor> |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container footer> |
<ng-container footer> |
||||
<button type="button" class="btn btn-text-secondary" (click)="cancelStatusChange()"> |
<button class="btn btn-text-secondary" (click)="cancelStatusChange()" type="button"> |
||||
{{ 'common.cancel' | sqxTranslate }} |
{{ "common.cancel" | sqxTranslate }} |
||||
</button> |
</button> |
||||
|
|
||||
<button type="button" class="btn btn-primary" [disabled]="dueTimeMode === 'Scheduled' && !dueTime" (click)="confirmStatusChange()" sqxFocusOnInit> |
<button |
||||
{{ 'common.confirm' | sqxTranslate }} |
class="btn btn-primary" |
||||
|
(click)="confirmStatusChange()" |
||||
|
[disabled]="dueTimeMode === 'Scheduled' && !dueTime" |
||||
|
sqxFocusOnInit |
||||
|
type="button"> |
||||
|
{{ "common.confirm" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</ng-container> |
</ng-container> |
||||
</sqx-modal-dialog> |
</sqx-modal-dialog> |
||||
|
|||||
@ -1,122 +1,139 @@ |
|||||
<ng-container *ngIf="formModel.itemChanges | async; let items"> |
@if (formModel.itemChanges | async; as items) { |
||||
<div class="array-container static" [class.expanded]="isExpanded" *ngIf="items.length > 0 && items.length <= 20;" |
@if (items.length > 0 && items.length <= 20) { |
||||
cdkDropList |
<div |
||||
[cdkDropListSortingDisabled]="isDisabled | async" |
class="array-container static" |
||||
[cdkDropListDisabled]="isDisabled | async" |
cdkDropList |
||||
[cdkDropListData]="items" |
[cdkDropListData]="items" |
||||
(cdkDropListDropped)="sort($event)"> |
[cdkDropListDisabled]="isDisabled | async" |
||||
<div *ngFor="let itemForm of items; index as i; last as isLast; first as isFirst;" class="table-drag item" |
(cdkDropListDropped)="sort($event)" |
||||
cdkDrag |
[cdkDropListSortingDisabled]="isDisabled | async" |
||||
cdkDragLockAxis="y" |
[class.expanded]="isExpanded"> |
||||
[class.first]="isFirst" |
@for (itemForm of items; track itemForm; let i = $index; let isLast = $last; let isFirst = $first) { |
||||
[class.last]="isLast"> |
<div class="table-drag item" cdkDrag cdkDragLockAxis="y" [class.first]="isFirst" [class.last]="isLast"> |
||||
<sqx-array-item |
<sqx-array-item |
||||
(clone)="addCopy(itemForm)" |
(clone)="addCopy(itemForm)" |
||||
[form]="form" |
[form]="form" |
||||
[formContext]="formContext" |
[formContext]="formContext" |
||||
[formLevel]="formLevel + 1" |
[formLevel]="formLevel + 1" |
||||
[formModel]="itemForm" |
[formModel]="itemForm" |
||||
[index]="i" |
[hasChatBot]="hasChatBot" |
||||
[isComparing]="isComparing" |
[index]="i" |
||||
[isCollapsedInitial]="isCollapsedInitial" |
[isCollapsedInitial]="isCollapsedInitial" |
||||
[isDisabled]="isDisabled | async" |
[isComparing]="isComparing" |
||||
[isFirst]="isFirst" |
[isDisabled]="isDisabled | async" |
||||
[isLast]="isLast" |
[isFirst]="isFirst" |
||||
(itemRemove)="removeItem(i)" |
[isLast]="isLast" |
||||
(itemMove)="move(itemForm, $event)" |
(itemMove)="move(itemForm, $event)" |
||||
[hasChatBot]="hasChatBot" |
(itemRemove)="removeItem(i)" |
||||
[language]="language" |
[language]="language" |
||||
[languages]="languages"> |
[languages]="languages"> |
||||
<i cdkDragHandle class="icon-drag2" [class.disabled]="isDisabled | async"></i> |
<i class="icon-drag2" cdkDragHandle [class.disabled]="isDisabled | async"></i> |
||||
</sqx-array-item> |
</sqx-array-item> |
||||
|
</div> |
||||
|
} |
||||
</div> |
</div> |
||||
</div> |
} |
||||
|
@if (items.length > 20) { |
||||
<div class="array-container" [class.expanded]="isExpanded" *ngIf="items.length > 20"> |
<div class="array-container" [class.expanded]="isExpanded"> |
||||
<virtual-scroller #scroll [items]="$any(items)" [enableUnequalChildrenSizes]="true"> |
<virtual-scroller #scroll [enableUnequalChildrenSizes]="true" [items]="$any(items)"> |
||||
<div *ngFor="let itemForm of scroll.viewPortItems; index as i" class="item" |
@for (itemForm of scroll.viewPortItems; track itemForm; let i = $index) { |
||||
[class.first]="scroll.viewPortInfo.startIndexWithBuffer + i === 0" |
<div |
||||
[class.last]="scroll.viewPortInfo.startIndexWithBuffer + i === items.length - 1"> |
class="item" |
||||
<sqx-array-item |
[class.first]="scroll.viewPortInfo.startIndexWithBuffer + i === 0" |
||||
(clone)="addCopy(itemForm)" |
[class.last]="scroll.viewPortInfo.startIndexWithBuffer + i === items.length - 1"> |
||||
[form]="form" |
<sqx-array-item |
||||
[formContext]="formContext" |
(clone)="addCopy(itemForm)" |
||||
[formLevel]="formLevel + 1" |
[form]="form" |
||||
[formModel]="itemForm" |
[formContext]="formContext" |
||||
[index]="scroll.viewPortInfo.startIndexWithBuffer + i" |
[formLevel]="formLevel + 1" |
||||
[isCollapsedInitial]="isCollapsedInitial" |
[formModel]="itemForm" |
||||
[isComparing]="isComparing" |
[hasChatBot]="hasChatBot" |
||||
[isDisabled]="isDisabled | async" |
[index]="scroll.viewPortInfo.startIndexWithBuffer + i" |
||||
[isFirst]="scroll.viewPortInfo.startIndexWithBuffer + i === 0" |
[isCollapsedInitial]="isCollapsedInitial" |
||||
[isLast]="scroll.viewPortInfo.startIndexWithBuffer + i === items.length - 1" |
[isComparing]="isComparing" |
||||
(itemExpanded)="scroll.invalidateCachedMeasurementAtIndex(scroll.viewPortInfo.startIndexWithBuffer + i)" |
[isDisabled]="isDisabled | async" |
||||
(itemRemove)="removeItem(scroll.viewPortInfo.startIndexWithBuffer + i)" |
[isFirst]="scroll.viewPortInfo.startIndexWithBuffer + i === 0" |
||||
(itemMove)="move(itemForm, $event)" |
[isLast]="scroll.viewPortInfo.startIndexWithBuffer + i === items.length - 1" |
||||
[hasChatBot]="hasChatBot" |
(itemExpanded)="scroll.invalidateCachedMeasurementAtIndex(scroll.viewPortInfo.startIndexWithBuffer + i)" |
||||
[language]="language" |
(itemMove)="move(itemForm, $event)" |
||||
[languages]="languages"> |
(itemRemove)="removeItem(scroll.viewPortInfo.startIndexWithBuffer + i)" |
||||
</sqx-array-item> |
[language]="language" |
||||
</div> |
[languages]="languages"></sqx-array-item> |
||||
</virtual-scroller> |
</div> |
||||
</div> |
} |
||||
|
</virtual-scroller> |
||||
|
</div> |
||||
|
} |
||||
<div class="array-buttons row g-0 align-items-center" [class.expanded]="isExpanded"> |
<div class="array-buttons row g-0 align-items-center" [class.expanded]="isExpanded"> |
||||
<div class="col-auto"> |
<div class="col-auto"> |
||||
<ng-container *ngIf="isArray; else component"> |
@if (isArray) { |
||||
<ng-container *ngIf="hasField"> |
@if (hasField) { |
||||
<button type="button" class="btn btn-outline-success" [disabled]="isDisabledOrFull | async" (click)="addItem()"> |
<button class="btn btn-outline-success" (click)="addItem()" [disabled]="isDisabledOrFull | async" type="button"> |
||||
{{ 'contents.arrayAddItem' | sqxTranslate }} |
{{ "contents.arrayAddItem" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</ng-container> |
} |
||||
<ng-container *ngIf="!hasField"> |
@if (!hasField) { |
||||
<sqx-form-hint> |
<sqx-form-hint> |
||||
{{ 'contents.arrayNoFields' | sqxTranslate }} |
{{ "contents.arrayNoFields" | sqxTranslate }} |
||||
</sqx-form-hint> |
</sqx-form-hint> |
||||
</ng-container> |
} |
||||
</ng-container> |
} @else { |
||||
|
@if (schemasList.length > 1) { |
||||
<ng-template #component> |
<button |
||||
<ng-container *ngIf="schemasList.length > 1"> |
class="btn btn-outline-success dropdown-toggle" |
||||
<button type="button" class="btn btn-outline-success dropdown-toggle" [disabled]="isDisabledOrFull | async" (click)="schemasDropdown.show()" #buttonSelect> |
#buttonSelect |
||||
{{ 'contents.addComponent' | sqxTranslate}} |
(click)="schemasDropdown.show()" |
||||
|
[disabled]="isDisabledOrFull | async" |
||||
|
type="button"> |
||||
|
{{ "contents.addComponent" | sqxTranslate }} |
||||
</button> |
</button> |
||||
|
<sqx-dropdown-menu scrollY="true" [sqxAnchoredTo]="buttonSelect" *sqxModal="schemasDropdown; closeAlways: true"> |
||||
<sqx-dropdown-menu *sqxModal="schemasDropdown;closeAlways:true" [sqxAnchoredTo]="buttonSelect" scrollY="true"> |
@for (schema of schemasList; track schema) { |
||||
<a class="dropdown-item" *ngFor="let schema of schemasList" (click)="addComponent(schema)"> |
<a class="dropdown-item" (click)="addComponent(schema)"> |
||||
{{schema.displayName}} |
{{ schema.displayName }} |
||||
</a> |
</a> |
||||
|
} |
||||
</sqx-dropdown-menu> |
</sqx-dropdown-menu> |
||||
</ng-container> |
} |
||||
<ng-container *ngIf="schemasList.length === 1"> |
@if (schemasList.length === 1) { |
||||
<button type="button" class="btn btn-outline-success" [disabled]="isDisabledOrFull | async" (click)="addComponent(schemasList[0])"> |
<button |
||||
{{ 'contents.addComponent' | sqxTranslate}} |
class="btn btn-outline-success" |
||||
|
(click)="addComponent(schemasList[0])" |
||||
|
[disabled]="isDisabledOrFull | async" |
||||
|
type="button"> |
||||
|
{{ "contents.addComponent" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</ng-container> |
} |
||||
<ng-container *ngIf="schemasList.length === 0"> |
@if (schemasList.length === 0) { |
||||
<sqx-form-hint> |
<sqx-form-hint> |
||||
{{ 'contents.componentsNoSchema' | sqxTranslate }} |
{{ "contents.componentsNoSchema" | sqxTranslate }} |
||||
</sqx-form-hint> |
</sqx-form-hint> |
||||
</ng-container> |
} |
||||
</ng-template> |
} |
||||
</div> |
|
||||
|
|
||||
<div class="col"> |
|
||||
<button type="button" class="btn btn-text-danger ms-2" *ngIf="items.length > 0" [disabled]="isDisabled | async" |
|
||||
(sqxConfirmClick)="clear()" |
|
||||
confirmTitle="i18n:contents.arrayClearConfirmTitle" |
|
||||
confirmText="i18n:contents.arrayClearConfirmText" |
|
||||
confirmRememberKey="leaveApp"> |
|
||||
{{ 'contents.arrayClear' | sqxTranslate }} |
|
||||
</button> |
|
||||
</div> |
</div> |
||||
|
<div class="col"> |
||||
<div class="col-auto" *ngIf="items.length > 0"> |
@if (items.length > 0) { |
||||
<button type="button" class="btn btn-text-secondary" (click)="expandAll()" title="i18n:contents.arrayExpandAll"> |
<button |
||||
<i class="icon-plus-square"></i> |
class="btn btn-text-danger ms-2" |
||||
</button> |
confirmRememberKey="leaveApp" |
||||
<button type="button" class="btn btn-text-secondary" (click)="collapseAll()" title="i18n:contents.arrayCollapseAll"> |
confirmText="i18n:contents.arrayClearConfirmText" |
||||
<i class="icon-minus-square"></i> |
confirmTitle="i18n:contents.arrayClearConfirmTitle" |
||||
</button> |
[disabled]="isDisabled | async" |
||||
|
(sqxConfirmClick)="clear()" |
||||
|
type="button"> |
||||
|
{{ "contents.arrayClear" | sqxTranslate }} |
||||
|
</button> |
||||
|
} |
||||
</div> |
</div> |
||||
|
@if (items.length > 0) { |
||||
|
<div class="col-auto"> |
||||
|
<button class="btn btn-text-secondary" (click)="expandAll()" title="i18n:contents.arrayExpandAll" type="button"> |
||||
|
<i class="icon-plus-square"></i> |
||||
|
</button> |
||||
|
<button class="btn btn-text-secondary" (click)="collapseAll()" title="i18n:contents.arrayCollapseAll" type="button"> |
||||
|
<i class="icon-minus-square"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
} |
||||
</div> |
</div> |
||||
</ng-container> |
} |
||||
|
|||||
@ -1,28 +1,34 @@ |
|||||
<ng-container *ngIf="!(formSection.hiddenChanges | async)"> |
@if (!(formSection.hiddenChanges | async)) { |
||||
<div class="header" *ngIf="formSection.separator; let separator"> |
@if (formSection.separator; as separator) { |
||||
<h3>{{separator!.displayName}}</h3> |
<div class="header"> |
||||
|
<h3>{{ separator!.displayName }}</h3> |
||||
<sqx-form-hint *ngIf="separator.properties.hints && separator.properties.hints.length > 0"> |
@if (separator.properties.hints && separator.properties.hints.length > 0) { |
||||
<span [sqxMarkdown]="separator.properties.hints" optional="true" inline="true"></span> |
<sqx-form-hint> |
||||
</sqx-form-hint> |
<span inline="true" optional="true" [sqxMarkdown]="separator.properties.hints"></span> |
||||
</div> |
</sqx-form-hint> |
||||
|
} |
||||
<div class="row"> |
|
||||
<div class="form-group" *ngFor="let child of formSection.fields; trackBy: trackByField" |
|
||||
[class.col-12]="isComparing || !child.field.properties.isHalfWidth" |
|
||||
[class.col-6]="!isComparing && child.field.properties.isHalfWidth"> |
|
||||
<sqx-field-editor *ngIf="!(child.hiddenChanges | async)" |
|
||||
[comments]="null" |
|
||||
[form]="form" |
|
||||
[formContext]="formContext" |
|
||||
[formLevel]="formLevel" |
|
||||
[formModel]="child" |
|
||||
[index]="index" |
|
||||
[isComparing]="isComparing" |
|
||||
[hasChatBot]="hasChatBot" |
|
||||
[language]="language" |
|
||||
[languages]="languages"> |
|
||||
</sqx-field-editor> |
|
||||
</div> |
</div> |
||||
|
} |
||||
|
<div class="row"> |
||||
|
@for (child of formSection.fields; track child.field.fieldId) { |
||||
|
<div |
||||
|
class="form-group" |
||||
|
[class.col-12]="isComparing || !child.field.properties.isHalfWidth" |
||||
|
[class.col-6]="!isComparing && child.field.properties.isHalfWidth"> |
||||
|
@if (!(child.hiddenChanges | async)) { |
||||
|
<sqx-field-editor |
||||
|
[comments]="null" |
||||
|
[form]="form" |
||||
|
[formContext]="formContext" |
||||
|
[formLevel]="formLevel" |
||||
|
[formModel]="child" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[index]="index" |
||||
|
[isComparing]="isComparing" |
||||
|
[language]="language" |
||||
|
[languages]="languages"></sqx-field-editor> |
||||
|
} |
||||
|
</div> |
||||
|
} |
||||
</div> |
</div> |
||||
</ng-container> |
} |
||||
|
|||||
@ -1,44 +1,50 @@ |
|||||
<div class="component"> |
<div class="component"> |
||||
<div *ngIf="formModel.schemaChanges | async; let schema; else noSchema"> |
@if (formModel.schemaChanges | async; as schema) { |
||||
<sqx-form-hint> |
<div> |
||||
{{schema.displayName}} |
<sqx-form-hint> |
||||
</sqx-form-hint> |
{{ schema.displayName }} |
||||
|
</sqx-form-hint> |
||||
<div class="form-group" *ngFor="let section of formModel.sectionsChanges | async"> |
@for (section of formModel.sectionsChanges | async; track section) { |
||||
<sqx-component-section |
<div class="form-group"> |
||||
[form]="form" |
<sqx-component-section |
||||
[formContext]="formContext" |
[form]="form" |
||||
[formLevel]="formLevel + 1" |
[formContext]="formContext" |
||||
[formSection]="$any(section)" |
[formLevel]="formLevel + 1" |
||||
[isComparing]="isComparing" |
[formSection]="$any(section)" |
||||
[hasChatBot]="hasChatBot" |
[hasChatBot]="hasChatBot" |
||||
[language]="language" |
[isComparing]="isComparing" |
||||
[languages]="languages"> |
[language]="language" |
||||
</sqx-component-section> |
[languages]="languages"></sqx-component-section> |
||||
|
</div> |
||||
|
} |
||||
</div> |
</div> |
||||
</div> |
} @else { |
||||
|
@if (schemasList.length > 1) { |
||||
<ng-template #noSchema> |
<button |
||||
<ng-container *ngIf="schemasList.length > 1"> |
class="btn btn-outline-success dropdown-toggle" |
||||
<button type="button" class="btn btn-outline-success dropdown-toggle" [disabled]="isDisabled | async" (click)="schemasDropdown.show()" #buttonSelect> |
#buttonSelect |
||||
{{ 'contents.addComponent' | sqxTranslate}} |
(click)="schemasDropdown.show()" |
||||
|
[disabled]="isDisabled | async" |
||||
|
type="button"> |
||||
|
{{ "contents.addComponent" | sqxTranslate }} |
||||
</button> |
</button> |
||||
|
<sqx-dropdown-menu scrollY="true" [sqxAnchoredTo]="buttonSelect" *sqxModal="schemasDropdown; closeAlways: true"> |
||||
<sqx-dropdown-menu *sqxModal="schemasDropdown;closeAlways:true" [sqxAnchoredTo]="buttonSelect" scrollY="true"> |
@for (schema of schemasList; track schema) { |
||||
<a class="dropdown-item" *ngFor="let schema of schemasList" (click)="setSchema(schema)"> |
<a class="dropdown-item" (click)="setSchema(schema)"> |
||||
{{schema.displayName}} |
{{ schema.displayName }} |
||||
</a> |
</a> |
||||
|
} |
||||
</sqx-dropdown-menu> |
</sqx-dropdown-menu> |
||||
</ng-container> |
} |
||||
<ng-container *ngIf="schemasList.length === 1"> |
@if (schemasList.length === 1) { |
||||
<button type="button" class="btn btn-outline-success" [disabled]="isDisabled | async" (click)="setSchema(schemasList[0])"> |
<button class="btn btn-outline-success" (click)="setSchema(schemasList[0])" [disabled]="isDisabled | async" type="button"> |
||||
{{ 'contents.addComponent' | sqxTranslate}} |
{{ "contents.addComponent" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</ng-container> |
} |
||||
<ng-container *ngIf="schemasList.length === 0"> |
@if (schemasList.length === 0) { |
||||
<sqx-form-hint> |
<sqx-form-hint> |
||||
{{ 'contents.componentNoSchema' | sqxTranslate }} |
{{ "contents.componentNoSchema" | sqxTranslate }} |
||||
</sqx-form-hint> |
</sqx-form-hint> |
||||
</ng-container> |
} |
||||
</ng-template> |
} |
||||
</div> |
</div> |
||||
|
|||||
@ -1,113 +1,120 @@ |
|||||
<div class="row g-0" [class.compare]="formModelCompare"> |
<div class="row g-0" [class.compare]="formModelCompare"> |
||||
<div [class.col-12]="!formModelCompare" [class.col-6]="formModelCompare"> |
<div [class.col-12]="!formModelCompare" [class.col-6]="formModelCompare"> |
||||
<sqx-focus-marker [controlId]="formModel.fieldPath"> |
<sqx-focus-marker [controlId]="formModel.fieldPath"> |
||||
<div class="table-items-row table-items-row-summary" [class.field-invalid]="isInvalid | async" *ngIf="!(formModel.hiddenChanges | async)"> |
@if (!(formModel.hiddenChanges | async)) { |
||||
<div class="languages-container"> |
<div class="table-items-row table-items-row-summary" [class.field-invalid]="isInvalid | async"> |
||||
<div class="languages-buttons"> |
<div class="languages-container"> |
||||
<div class="languages-inner"> |
<div class="languages-buttons"> |
||||
<sqx-field-languages |
<div class="languages-inner"> |
||||
[formModel]="formModel" |
<sqx-field-languages |
||||
(languageChange)="languageChange.emit($event)" |
[formModel]="formModel" |
||||
[language]="language" |
[language]="language" |
||||
[languages]="languages" |
(languageChange)="languageChange.emit($event)" |
||||
[showAllControls]="showAllControls" |
[languages]="languages" |
||||
(showAllControlsChange)="changeShowAllControls($event)"> |
[showAllControls]="showAllControls" |
||||
</sqx-field-languages> |
(showAllControlsChange)="changeShowAllControls($event)"></sqx-field-languages> |
||||
|
<sqx-field-copy-button [formModel]="formModel" [languages]="languages"></sqx-field-copy-button> |
||||
<sqx-field-copy-button [formModel]="formModel" [languages]="languages"></sqx-field-copy-button> |
@if (isTranslatable) { |
||||
|
<button |
||||
<button *ngIf="isTranslatable" type="button" [disabled]="formModel.field.isDisabled" class="btn btn-sm btn-outline-secondary force no-focus-shadow ms-1" title="i18n:contents.autotranslate" (click)="translate()" tabindex="-1"> |
class="btn btn-sm btn-outline-secondary force no-focus-shadow ms-1" |
||||
<i class="icon-translate"></i> |
(click)="translate()" |
||||
</button> |
[disabled]="formModel.field.isDisabled" |
||||
|
tabindex="-1" |
||||
|
title="i18n:contents.autotranslate" |
||||
|
type="button"> |
||||
|
<i class="icon-translate"></i> |
||||
|
</button> |
||||
|
} |
||||
|
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
@if (showAllControls) { |
||||
|
@for (language of languages; track language) { |
||||
<ng-container *ngIf="showAllControls; else singleControl"> |
<div class="form-group"> |
||||
<div class="form-group" *ngFor="let language of languages"> |
<sqx-field-editor |
||||
|
[comments]="commentsState" |
||||
|
[displaySuffix]="prefix(language)" |
||||
|
[form]="form" |
||||
|
[formContext]="formContext" |
||||
|
[formLevel]="formLevel" |
||||
|
[formModel]="formModel.get(language)" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[isComparing]="!!formModelCompare" |
||||
|
[language]="language" |
||||
|
[languages]="languages"></sqx-field-editor> |
||||
|
</div> |
||||
|
} |
||||
|
} @else { |
||||
<sqx-field-editor |
<sqx-field-editor |
||||
[comments]="commentsState" |
[comments]="commentsState" |
||||
[displaySuffix]="prefix(language)" |
|
||||
[form]="form" |
[form]="form" |
||||
[formContext]="formContext" |
[formContext]="formContext" |
||||
[formLevel]="formLevel" |
[formLevel]="formLevel" |
||||
[formModel]="formModel.get(language)" |
[formModel]="getControl()" |
||||
[isComparing]="!!formModelCompare" |
|
||||
[hasChatBot]="hasChatBot" |
[hasChatBot]="hasChatBot" |
||||
|
[isComparing]="!!formModelCompare" |
||||
[language]="language" |
[language]="language" |
||||
[languages]="languages"> |
[languages]="languages"></sqx-field-editor> |
||||
</sqx-field-editor> |
} |
||||
</div> |
</div> |
||||
</ng-container> |
} |
||||
|
|
||||
<ng-template #singleControl> |
|
||||
<sqx-field-editor |
|
||||
[comments]="commentsState" |
|
||||
[form]="form" |
|
||||
[formContext]="formContext" |
|
||||
[formLevel]="formLevel" |
|
||||
[formModel]="getControl()" |
|
||||
[isComparing]="!!formModelCompare" |
|
||||
[hasChatBot]="hasChatBot" |
|
||||
[language]="language" |
|
||||
[languages]="languages"> |
|
||||
</sqx-field-editor> |
|
||||
</ng-template> |
|
||||
</div> |
|
||||
</sqx-focus-marker> |
</sqx-focus-marker> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="col-6 col-right" *ngIf="formModelCompare && formCompare"> |
@if (formModelCompare && formCompare) { |
||||
<div class="copy-button-container" *ngIf="!(isDisabled | async)"> |
<div class="col-6 col-right"> |
||||
<button type="button" class="btn btn-primary btn-sm field-copy" (click)="copy()" *ngIf="isDifferent | async"> |
@if (!(isDisabled | async)) { |
||||
<i class="icon-arrow_back"></i> |
<div class="copy-button-container"> |
||||
</button> |
@if (isDifferent | async) { |
||||
</div> |
<button class="btn btn-primary btn-sm field-copy" (click)="copy()" type="button"> |
||||
|
<i class="icon-arrow_back"></i> |
||||
<div class="table-items-row table-items-row-summary" *ngIf="!(formModelCompare!.hiddenChanges | async)"> |
</button> |
||||
<div class="languages-container"> |
} |
||||
<div class="languages-buttons-compare"> |
|
||||
<div class="languages-inner"> |
|
||||
<sqx-field-languages |
|
||||
[formModel]="formModelCompare!" |
|
||||
(languageChange)="languageChange.emit($event)" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[showAllControls]="showAllControls" |
|
||||
(showAllControlsChange)="changeShowAllControls($event)"> |
|
||||
</sqx-field-languages> |
|
||||
</div> |
|
||||
</div> |
</div> |
||||
</div> |
} |
||||
|
@if (!(formModelCompare!.hiddenChanges | async)) { |
||||
<ng-container *ngIf="showAllControls; else singleControlCompare"> |
<div class="table-items-row table-items-row-summary"> |
||||
<div class="form-group" *ngFor="let language of languages"> |
<div class="languages-container"> |
||||
<sqx-field-editor |
<div class="languages-buttons-compare"> |
||||
[displaySuffix]="prefix(language)" |
<div class="languages-inner"> |
||||
[form]="formCompare" |
<sqx-field-languages |
||||
[formContext]="formContext" |
[formModel]="formModelCompare!" |
||||
[formLevel]="formLevel" |
[language]="language" |
||||
[formModel]="formModelCompare.get(language)" |
(languageChange)="languageChange.emit($event)" |
||||
[isComparing]="!!formModelCompare" |
[languages]="languages" |
||||
[hasChatBot]="hasChatBot" |
[showAllControls]="showAllControls" |
||||
[language]="language" |
(showAllControlsChange)="changeShowAllControls($event)"></sqx-field-languages> |
||||
[languages]="languages"> |
</div> |
||||
</sqx-field-editor> |
</div> |
||||
|
</div> |
||||
|
@if (showAllControls) { |
||||
|
@for (language of languages; track language) { |
||||
|
<div class="form-group"> |
||||
|
<sqx-field-editor |
||||
|
[displaySuffix]="prefix(language)" |
||||
|
[form]="formCompare" |
||||
|
[formContext]="formContext" |
||||
|
[formLevel]="formLevel" |
||||
|
[formModel]="formModelCompare.get(language)" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[isComparing]="!!formModelCompare" |
||||
|
[language]="language" |
||||
|
[languages]="languages"></sqx-field-editor> |
||||
|
</div> |
||||
|
} |
||||
|
} @else { |
||||
|
<sqx-field-editor |
||||
|
[form]="formCompare" |
||||
|
[formContext]="formContext" |
||||
|
[formLevel]="formLevel" |
||||
|
[formModel]="getControlCompare()!" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[isComparing]="!!formModelCompare" |
||||
|
[language]="language" |
||||
|
[languages]="languages"></sqx-field-editor> |
||||
|
} |
||||
</div> |
</div> |
||||
</ng-container> |
} |
||||
|
|
||||
<ng-template #singleControlCompare> |
|
||||
<sqx-field-editor |
|
||||
[form]="formCompare" |
|
||||
[formContext]="formContext" |
|
||||
[formLevel]="formLevel" |
|
||||
[formModel]="getControlCompare()!" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[isComparing]="!!formModelCompare" |
|
||||
[hasChatBot]="hasChatBot"> |
|
||||
</sqx-field-editor> |
|
||||
</ng-template> |
|
||||
</div> |
</div> |
||||
</div> |
} |
||||
</div> |
</div> |
||||
|
|||||
@ -1,34 +1,38 @@ |
|||||
<ng-container *ngIf="(formSection.visibleChanges | async) || formCompare"> |
@if ((formSection.visibleChanges | async) || formCompare) { |
||||
<div class="header" *ngIf="formSection.separator; let separator"> |
@if (formSection.separator; as separator) { |
||||
<div class="row g-0 align"> |
<div class="header"> |
||||
<div class="col-auto"> |
<div class="row g-0 align"> |
||||
<button type="button" class="btn btn-sm btn-text-secondary" (click)="toggle()"> |
<div class="col-auto"> |
||||
<i [class.icon-caret-right]="snapshot.isCollapsed" [class.icon-caret-down]="!snapshot.isCollapsed"></i> |
<button class="btn btn-sm btn-text-secondary" (click)="toggle()" type="button"> |
||||
</button> |
<i [class.icon-caret-down]="!snapshot.isCollapsed" [class.icon-caret-right]="snapshot.isCollapsed"></i> |
||||
</div> |
</button> |
||||
<div class="col"> |
</div> |
||||
<h3>{{separator.displayName}}</h3> |
<div class="col"> |
||||
|
<h3>{{ separator.displayName }}</h3> |
||||
<sqx-form-hint *ngIf="separator.properties.hints && separator.properties.hints.length > 0"> |
@if (separator.properties.hints && separator.properties.hints.length > 0) { |
||||
<span [sqxMarkdown]="separator.properties.hints" optional="true" inline="true"></span> |
<sqx-form-hint> |
||||
</sqx-form-hint> |
<span inline="true" optional="true" [sqxMarkdown]="separator.properties.hints"></span> |
||||
|
</sqx-form-hint> |
||||
|
} |
||||
|
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
} |
||||
</ng-container> |
} |
||||
|
|
||||
<div class="row gx-1" [class.hidden]="snapshot.isCollapsed && !formCompare"> |
<div class="row gx-1" [class.hidden]="snapshot.isCollapsed && !formCompare"> |
||||
<sqx-content-field *ngFor="let field of formSection.fields; trackBy: trackByField" |
@for (field of formSection.fields; track field.field.fieldId) { |
||||
(languageChange)="languageChange.emit($event)" |
<sqx-content-field |
||||
[form]="form" |
[form]="form" |
||||
[formCompare]="formCompare" |
[formCompare]="formCompare" |
||||
[formContext]="formContext" |
[formContext]="formContext" |
||||
[formLevel]="formLevel" |
[formLevel]="formLevel" |
||||
[formModel]="field" |
[formModel]="field" |
||||
[formModelCompare]="getFieldFormCompare(field)" |
[formModelCompare]="getFieldFormCompare(field)" |
||||
[isCompact]="isCompact" |
[isCompact]="isCompact" |
||||
[language]="language" |
[language]="language" |
||||
[languages]="languages" |
(languageChange)="languageChange.emit($event)" |
||||
[schema]="schema"> |
[languages]="languages" |
||||
</sqx-content-field> |
[schema]="schema"></sqx-content-field> |
||||
</div> |
} |
||||
|
</div> |
||||
|
|||||
@ -1,37 +1,36 @@ |
|||||
<ng-container *ngIf="isLocalized"> |
@if (isLocalized) { |
||||
<button type="button" class="btn btn-outline-secondary btn-sm ms-1 dropdown-toggle" title="{{ 'common.copy' | sqxTranslate }}" (click)="dropdown.toggle()" #button tabindex="-1"> |
<button |
||||
|
class="btn btn-outline-secondary btn-sm ms-1 dropdown-toggle" |
||||
|
#button |
||||
|
(click)="dropdown.toggle()" |
||||
|
tabindex="-1" |
||||
|
title="{{ 'common.copy' | sqxTranslate }}" |
||||
|
type="button"> |
||||
<i class="icon-copy"></i> |
<i class="icon-copy"></i> |
||||
</button> |
</button> |
||||
|
<sqx-dropdown-menu scrollY="true" [sqxAnchoredTo]="button" *sqxModal="dropdown"> |
||||
<sqx-dropdown-menu *sqxModal="dropdown" [sqxAnchoredTo]="button" scrollY="true"> |
|
||||
<div class="section d-flex justify-content-end"> |
<div class="section d-flex justify-content-end"> |
||||
<button type="button" class="btn btn-primary" (click)="copy()" tabindex="-1"> |
<button class="btn btn-primary" (click)="copy()" tabindex="-1" type="button"> |
||||
{{ 'common.copy' | sqxTranslate }} |
{{ "common.copy" | sqxTranslate }} |
||||
</button> |
</button> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="dropdown-divider"></div> |
<div class="dropdown-divider"></div> |
||||
|
|
||||
<div class="section"> |
<div class="section"> |
||||
<div class="row"> |
<div class="row"> |
||||
<label class="col-auto col-form-label" for="languageSource">{{ 'common.from' | sqxTranslate }}</label> |
<label class="col-auto col-form-label" for="languageSource">{{ "common.from" | sqxTranslate }}</label> |
||||
|
|
||||
<div class="col"> |
<div class="col"> |
||||
<select class="form-select" id="languagesSource" |
<select class="form-select" id="languagesSource" [ngModel]="copySource" (ngModelChange)="setCopySource($event)"> |
||||
[ngModel]="copySource" |
@for (language of languages; track language) { |
||||
(ngModelChange)="setCopySource($event)"> |
<option [ngValue]="language.iso2Code">{{ language.iso2Code }}</option> |
||||
<option *ngFor="let language of languages" [ngValue]="language.iso2Code">{{language.iso2Code}}</option> |
} |
||||
</select> |
</select> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="dropdown-divider"></div> |
<div class="dropdown-divider"></div> |
||||
|
|
||||
<div class="section"> |
<div class="section"> |
||||
<label>{{ 'common.to' | sqxTranslate }}</label> |
<label>{{ "common.to" | sqxTranslate }}</label> |
||||
|
<sqx-checkbox-group layout="Multiline" [(ngModel)]="copyTargets" [values]="languageCodes"></sqx-checkbox-group> |
||||
<sqx-checkbox-group [(ngModel)]="copyTargets" [values]="languageCodes" layout="Multiline"></sqx-checkbox-group> |
|
||||
</div> |
</div> |
||||
</sqx-dropdown-menu> |
</sqx-dropdown-menu> |
||||
</ng-container> |
} |
||||
|
|||||
@ -1,297 +1,345 @@ |
|||||
<div class="field" [class.expanded]="isExpanded" *ngIf="formModel"> |
@if (formModel) { |
||||
<fieldset class="buttons-container" [disabled]="isDisabled | async"> |
<div class="field" [class.expanded]="isExpanded"> |
||||
<div class="buttons"> |
<fieldset class="buttons-container" [disabled]="isDisabled | async"> |
||||
<button type="button" class="btn btn-sm btn-outline-secondary force no-focus-shadow" (click)="chatDialog.show()" [disabled]="!hasChatBot || !isString" tabindex="-1"> |
<div class="buttons"> |
||||
AI |
<button |
||||
</button> |
class="btn btn-sm btn-outline-secondary force no-focus-shadow" |
||||
|
(click)="chatDialog.show()" |
||||
<button type="button" class="btn btn-sm btn-outline-secondary force no-focus-shadow ms-1" title="i18n:contents.fieldFullscreen" (click)="toggleExpanded()" tabindex="-1"> |
[disabled]="!hasChatBot || !isString" |
||||
<i class="icon-fullscreen"></i> |
tabindex="-1" |
||||
</button> |
type="button"> |
||||
|
AI |
||||
<button type="button" class="btn btn-sm btn-outline-secondary btn-clear force no-focus-shadow ms-1" [disabled]="isEmpty | async" tabindex="-1" |
</button> |
||||
(sqxConfirmClick)="unset()" |
<button |
||||
confirmTitle="i18n:contents.unsetValueConfirmTitle" |
class="btn btn-sm btn-outline-secondary force no-focus-shadow ms-1" |
||||
confirmText="i18n:contents.unsetValueConfirmText" |
(click)="toggleExpanded()" |
||||
confirmRememberKey="unsetValue" |
tabindex="-1" |
||||
title="i18n:contents.unsetValue"> |
title="i18n:contents.fieldFullscreen" |
||||
<i class="icon-close"></i> |
type="button"> |
||||
</button> |
<i class="icon-fullscreen"></i> |
||||
|
</button> |
||||
|
<button |
||||
|
class="btn btn-sm btn-outline-secondary btn-clear force no-focus-shadow ms-1" |
||||
|
confirmRememberKey="unsetValue" |
||||
|
confirmText="i18n:contents.unsetValueConfirmText" |
||||
|
confirmTitle="i18n:contents.unsetValueConfirmTitle" |
||||
|
[disabled]="isEmpty | async" |
||||
|
(sqxConfirmClick)="unset()" |
||||
|
tabindex="-1" |
||||
|
title="i18n:contents.unsetValue" |
||||
|
type="button"> |
||||
|
<i class="icon-close"></i> |
||||
|
</button> |
||||
|
</div> |
||||
|
</fieldset> |
||||
|
<label> |
||||
|
{{ field.displayName }} {{ displaySuffix }} |
||||
|
<span class="field-required" [class.hidden]="!field.properties.isRequired">*</span> |
||||
|
</label> |
||||
|
@if (field.isDisabled) { |
||||
|
<small class="field-disabled ps-1">Disabled</small> |
||||
|
} |
||||
|
@if (form) { |
||||
|
<sqx-control-errors [fieldName]="field.displayName" [for]="$any(fieldForm)"></sqx-control-errors> |
||||
|
} |
||||
|
<div> |
||||
|
@if (field.properties.editorUrl) { |
||||
|
<sqx-iframe-editor |
||||
|
#editor |
||||
|
[context]="formContext" |
||||
|
[formControlBinding]="$any(fieldForm)" |
||||
|
[formField]="formModel.field.name" |
||||
|
[formIndex]="index" |
||||
|
[formValue]="form.valueChanges | async" |
||||
|
[isExpanded]="isExpanded" |
||||
|
(isExpandedChange)="toggleExpanded()" |
||||
|
[language]="language" |
||||
|
[languages]="languages" |
||||
|
[schemaIds]="field.rawProperties.schemaIds" |
||||
|
[url]="field.properties.editorUrl"></sqx-iframe-editor> |
||||
|
} @else { |
||||
|
@switch (field.properties.fieldType) { |
||||
|
@case ("Array") { |
||||
|
<sqx-array-editor |
||||
|
[form]="form" |
||||
|
[formContext]="formContext" |
||||
|
[formLevel]="formLevel" |
||||
|
[formModel]="$any(formModel)" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[isComparing]="isComparing" |
||||
|
[isExpanded]="isExpanded" |
||||
|
[language]="language" |
||||
|
[languages]="languages"></sqx-array-editor> |
||||
|
} |
||||
|
@case ("Assets") { |
||||
|
<sqx-assets-editor |
||||
|
[folderId]="field.rawProperties.folderId" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[isExpanded]="isExpanded"></sqx-assets-editor> |
||||
|
} |
||||
|
@case ("Boolean") { |
||||
|
@switch (field.rawProperties.editor) { |
||||
|
@case ("Toggle") { |
||||
|
<sqx-toggle [formControl]="$any(fieldForm)" [threeStates]="!field.properties.isRequired"></sqx-toggle> |
||||
|
} |
||||
|
@case ("Checkbox") { |
||||
|
<div class="form-check"> |
||||
|
<input |
||||
|
class="form-check-input" |
||||
|
id="{{ uniqueId }}" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
sqxIndeterminateValue |
||||
|
[threeStates]="!field.properties.isRequired" |
||||
|
type="checkbox" /> |
||||
|
<label class="form-check-label" for="{{ uniqueId }}"></label> |
||||
|
</div> |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
@case ("Component") { |
||||
|
<sqx-component |
||||
|
[form]="form" |
||||
|
[formContext]="formContext" |
||||
|
[formLevel]="formLevel" |
||||
|
[formModel]="$any(formModel)" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[isComparing]="isComparing" |
||||
|
[language]="language" |
||||
|
[languages]="languages"></sqx-component> |
||||
|
} |
||||
|
@case ("Components") { |
||||
|
<sqx-array-editor |
||||
|
[form]="form" |
||||
|
[formContext]="formContext" |
||||
|
[formLevel]="formLevel" |
||||
|
[formModel]="$any(formModel)" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[isComparing]="isComparing" |
||||
|
[isExpanded]="isExpanded" |
||||
|
[language]="language" |
||||
|
[languages]="languages"></sqx-array-editor> |
||||
|
} |
||||
|
@case ("DateTime") { |
||||
|
<sqx-date-time-editor |
||||
|
enforceTime="true" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[mode]="field.rawProperties.editor"></sqx-date-time-editor> |
||||
|
} |
||||
|
@case ("Geolocation") { |
||||
|
<sqx-geolocation-editor [formControl]="$any(fieldForm)"></sqx-geolocation-editor> |
||||
|
} |
||||
|
@case ("Json") { |
||||
|
<sqx-code-editor [formControl]="$any(fieldForm)" [height]="350" valueMode="Json"></sqx-code-editor> |
||||
|
} |
||||
|
@case ("Number") { |
||||
|
@switch (field.rawProperties.editor) { |
||||
|
@case ("Input") { |
||||
|
<input |
||||
|
class="form-control" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[placeholder]="field.displayPlaceholder" |
||||
|
type="number" /> |
||||
|
} |
||||
|
@case ("Stars") { |
||||
|
<sqx-stars [formControl]="$any(fieldForm)" [maximumStars]="field.rawProperties.maxValue"></sqx-stars> |
||||
|
} |
||||
|
@case ("Radio") { |
||||
|
<sqx-radio-group |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
unsorted="true" |
||||
|
[values]="field.rawProperties.allowedValues"></sqx-radio-group> |
||||
|
} |
||||
|
@case ("Dropdown") { |
||||
|
<select class="form-select" [formControl]="$any(fieldForm)"> |
||||
|
<option [ngValue]="null"></option> |
||||
|
@for (value of field.rawProperties.allowedValues; track value) { |
||||
|
<option [ngValue]="value">{{ value }}</option> |
||||
|
} |
||||
|
</select> |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
@case ("References") { |
||||
|
@switch (field.rawProperties.editor) { |
||||
|
@case ("List") { |
||||
|
<sqx-references-editor |
||||
|
[allowDuplicates]="field.rawProperties.allowDuplicated" |
||||
|
[formContext]="formContext" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[isExpanded]="isExpanded" |
||||
|
[language]="language" |
||||
|
[languages]="languages" |
||||
|
[query]="field.rawProperties.query" |
||||
|
[schemaIds]="field.rawProperties.schemaIds"></sqx-references-editor> |
||||
|
} |
||||
|
@case ("Dropdown") { |
||||
|
<sqx-reference-dropdown |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[language]="language" |
||||
|
[languages]="languages" |
||||
|
mode="Array" |
||||
|
[schemaId]="field.rawProperties.singleId"></sqx-reference-dropdown> |
||||
|
} |
||||
|
@case ("Input") { |
||||
|
<sqx-reference-input |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[language]="language" |
||||
|
[languages]="languages" |
||||
|
mode="Array" |
||||
|
[query]="field.rawProperties.query" |
||||
|
[schemaIds]="field.rawProperties.schemaIds"></sqx-reference-input> |
||||
|
} |
||||
|
@case ("Tags") { |
||||
|
<sqx-references-tags |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[language]="language" |
||||
|
[languages]="languages" |
||||
|
[schemaId]="field.rawProperties.singleId"></sqx-references-tags> |
||||
|
} |
||||
|
@case ("Checkboxes") { |
||||
|
<sqx-references-checkboxes |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[language]="language" |
||||
|
[schemaId]="field.rawProperties.singleId"></sqx-references-checkboxes> |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
@case ("String") { |
||||
|
@switch (field.rawProperties.editor) { |
||||
|
@case ("Input") { |
||||
|
<input class="form-control" [formControl]="$any(fieldForm)" [placeholder]="field.displayPlaceholder" /> |
||||
|
} |
||||
|
@case ("Slug") { |
||||
|
<input |
||||
|
class="form-control" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[placeholder]="field.displayPlaceholder" |
||||
|
sqxTransformInput="Slugify" /> |
||||
|
} |
||||
|
@case ("TextArea") { |
||||
|
<textarea |
||||
|
class="form-control" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[placeholder]="field.displayPlaceholder" |
||||
|
rows="5"></textarea> |
||||
|
} |
||||
|
@case ("RichText") { |
||||
|
<sqx-rich-editor |
||||
|
#editor |
||||
|
[annotations]="annotations | async" |
||||
|
(annotationsCreate)="annotationCreate($event)" |
||||
|
(annotationsSelect)="annotationsSelect($event)" |
||||
|
(annotationsUpdate)="annotationsUpdate($event)" |
||||
|
[classNames]="field.rawProperties.classNames" |
||||
|
[folderId]="field.rawProperties.folderId" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[hasAnnotations]="!!comments" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[language]="language" |
||||
|
[languages]="languages" |
||||
|
mode="Html" |
||||
|
[schemaIds]="field.rawProperties.schemaIds"></sqx-rich-editor> |
||||
|
} |
||||
|
@case ("Html") { |
||||
|
<sqx-code-editor |
||||
|
#editor |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[height]="350" |
||||
|
mode="ace/mode/html"></sqx-code-editor> |
||||
|
} |
||||
|
@case ("Markdown") { |
||||
|
<sqx-rich-editor |
||||
|
#editor |
||||
|
[annotations]="annotations | async" |
||||
|
(annotationsCreate)="annotationCreate($event)" |
||||
|
(annotationsSelect)="annotationsSelect($event)" |
||||
|
(annotationsUpdate)="annotationsUpdate($event)" |
||||
|
[classNames]="undefined" |
||||
|
[folderId]="field.rawProperties.folderId" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[hasAnnotations]="!!comments" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[language]="language" |
||||
|
[languages]="languages" |
||||
|
mode="Markdown" |
||||
|
[schemaIds]="field.rawProperties.schemaIds"></sqx-rich-editor> |
||||
|
} |
||||
|
@case ("StockPhoto") { |
||||
|
<sqx-stock-photo-editor [formControl]="$any(fieldForm)"></sqx-stock-photo-editor> |
||||
|
} |
||||
|
@case ("Dropdown") { |
||||
|
<select class="form-select" [formControl]="$any(fieldForm)"> |
||||
|
<option [ngValue]="null"></option> |
||||
|
@for (value of field.rawProperties.allowedValues; track value) { |
||||
|
<option [ngValue]="value">{{ value }}</option> |
||||
|
} |
||||
|
</select> |
||||
|
} |
||||
|
@case ("Radio") { |
||||
|
<sqx-radio-group |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
unsorted="true" |
||||
|
[values]="field.rawProperties.allowedValues"></sqx-radio-group> |
||||
|
} |
||||
|
@case ("Color") { |
||||
|
<sqx-color-picker |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[placeholder]="field.displayPlaceholder"></sqx-color-picker> |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
@case ("RichText") { |
||||
|
<sqx-rich-editor |
||||
|
#editor |
||||
|
[annotations]="annotations | async" |
||||
|
(annotationsCreate)="annotationCreate($event)" |
||||
|
(annotationsSelect)="annotationsSelect($event)" |
||||
|
(annotationsUpdate)="annotationsUpdate($event)" |
||||
|
[classNames]="field.rawProperties.classNames" |
||||
|
[folderId]="field.rawProperties.folderId" |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[hasAnnotations]="!!comments" |
||||
|
[hasChatBot]="hasChatBot" |
||||
|
[language]="language" |
||||
|
[languages]="languages" |
||||
|
mode="State" |
||||
|
[schemaIds]="field.rawProperties.schemaIds"></sqx-rich-editor> |
||||
|
} |
||||
|
@case ("Tags") { |
||||
|
@switch (field.rawProperties.editor) { |
||||
|
@case ("Tags") { |
||||
|
<sqx-tag-editor |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[itemsSource]="field.rawProperties.allowedValues" |
||||
|
[placeholder]="field.displayPlaceholder"></sqx-tag-editor> |
||||
|
} |
||||
|
@case ("Checkboxes") { |
||||
|
<sqx-checkbox-group |
||||
|
[formControl]="$any(fieldForm)" |
||||
|
[values]="field.rawProperties.allowedValues"></sqx-checkbox-group> |
||||
|
} |
||||
|
@case ("Dropdown") { |
||||
|
<select class="form-select" [formControl]="$any(fieldForm)" multiple> |
||||
|
@for (value of field.rawProperties.allowedValues; track value) { |
||||
|
<option [ngValue]="value">{{ value }}</option> |
||||
|
} |
||||
|
</select> |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
@case ("UI") { |
||||
|
<h4 class="ui-separator">{{ field.displayName }}</h4> |
||||
|
} |
||||
|
} |
||||
|
} |
||||
</div> |
</div> |
||||
</fieldset> |
@if (field.properties.hints && field.properties.hints.length > 0) { |
||||
|
<sqx-form-hint> |
||||
<label> |
<span inline="true" optional="true" [sqxMarkdown]="field.properties.hints"></span> |
||||
{{field.displayName}} {{displaySuffix}} <span class="field-required" [class.hidden]="!field.properties.isRequired">*</span> |
</sqx-form-hint> |
||||
</label> |
} |
||||
|
|
||||
<small class="field-disabled ps-1" *ngIf="field.isDisabled">Disabled</small> |
|
||||
|
|
||||
<sqx-control-errors *ngIf="form" [for]="$any(fieldForm)" [fieldName]="field.displayName"></sqx-control-errors> |
|
||||
|
|
||||
<div> |
|
||||
<ng-container *ngIf="field.properties.editorUrl; else noEditor"> |
|
||||
<sqx-iframe-editor [url]="field.properties.editorUrl" #editor |
|
||||
[context]="formContext" |
|
||||
[isExpanded]="isExpanded" |
|
||||
(isExpandedChange)="toggleExpanded()" |
|
||||
[formControlBinding]="$any(fieldForm)" |
|
||||
[formValue]="form.valueChanges | async" |
|
||||
[formIndex]="index" |
|
||||
[formField]="formModel.field.name" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[schemaIds]="field.rawProperties.schemaIds"> |
|
||||
</sqx-iframe-editor> |
|
||||
</ng-container> |
|
||||
|
|
||||
<ng-template #noEditor> |
|
||||
<ng-container [ngSwitch]="field.properties.fieldType"> |
|
||||
<ng-container *ngSwitchCase="'Array'"> |
|
||||
<sqx-array-editor |
|
||||
[form]="form" |
|
||||
[formLevel]="formLevel" |
|
||||
[formModel]="$any(formModel)" |
|
||||
[formContext]="formContext" |
|
||||
[isComparing]="isComparing" |
|
||||
[isExpanded]="isExpanded" |
|
||||
[hasChatBot]="hasChatBot" |
|
||||
[language]="language" |
|
||||
[languages]="languages"> |
|
||||
</sqx-array-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Assets'"> |
|
||||
<sqx-assets-editor |
|
||||
[formControl]="$any(fieldForm)" |
|
||||
[folderId]="field.rawProperties.folderId" |
|
||||
[hasChatBot]="hasChatBot" |
|
||||
[isExpanded]="isExpanded"> |
|
||||
</sqx-assets-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Boolean'"> |
|
||||
<ng-container [ngSwitch]="field.rawProperties.editor"> |
|
||||
<ng-container *ngSwitchCase="'Toggle'"> |
|
||||
<sqx-toggle [formControl]="$any(fieldForm)" [threeStates]="!field.properties.isRequired"></sqx-toggle> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Checkbox'"> |
|
||||
<div class="form-check"> |
|
||||
<input class="form-check-input" type="checkbox" [formControl]="$any(fieldForm)" id="{{uniqueId}}" sqxIndeterminateValue [threeStates]="!field.properties.isRequired"> |
|
||||
<label class="form-check-label" for="{{uniqueId}}"></label> |
|
||||
</div> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Component'"> |
|
||||
<sqx-component |
|
||||
[form]="form" |
|
||||
[formContext]="formContext" |
|
||||
[formLevel]="formLevel" |
|
||||
[formModel]="$any(formModel)" |
|
||||
[isComparing]="isComparing" |
|
||||
[hasChatBot]="hasChatBot" |
|
||||
[language]="language" |
|
||||
[languages]="languages"> |
|
||||
</sqx-component> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Components'"> |
|
||||
<sqx-array-editor |
|
||||
[form]="form" |
|
||||
[formLevel]="formLevel" |
|
||||
[formModel]="$any(formModel)" |
|
||||
[formContext]="formContext" |
|
||||
[isComparing]="isComparing" |
|
||||
[isExpanded]="isExpanded" |
|
||||
[hasChatBot]="hasChatBot" |
|
||||
[language]="language" |
|
||||
[languages]="languages"> |
|
||||
</sqx-array-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'DateTime'"> |
|
||||
<sqx-date-time-editor [formControl]="$any(fieldForm)" [mode]="field.rawProperties.editor" enforceTime="true"></sqx-date-time-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Geolocation'"> |
|
||||
<sqx-geolocation-editor [formControl]="$any(fieldForm)"></sqx-geolocation-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Json'"> |
|
||||
<sqx-code-editor [formControl]="$any(fieldForm)" valueMode="Json" [height]="350"></sqx-code-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Number'"> |
|
||||
<ng-container [ngSwitch]="field.rawProperties.editor"> |
|
||||
<ng-container *ngSwitchCase="'Input'"> |
|
||||
<input class="form-control" type="number" [formControl]="$any(fieldForm)" [placeholder]="field.displayPlaceholder"> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Stars'"> |
|
||||
<sqx-stars [formControl]="$any(fieldForm)" [maximumStars]="field.rawProperties.maxValue"></sqx-stars> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Radio'"> |
|
||||
<sqx-radio-group [formControl]="$any(fieldForm)" [values]="field.rawProperties.allowedValues" unsorted="true"></sqx-radio-group> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Dropdown'"> |
|
||||
<select class="form-select" [formControl]="$any(fieldForm)"> |
|
||||
<option [ngValue]="null"></option> |
|
||||
<option *ngFor="let value of field.rawProperties.allowedValues" [ngValue]="value">{{value}}</option> |
|
||||
</select> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'References'"> |
|
||||
<ng-container [ngSwitch]="field.rawProperties.editor"> |
|
||||
<ng-container *ngSwitchCase="'List'"> |
|
||||
<sqx-references-editor |
|
||||
[allowDuplicates]="field.rawProperties.allowDuplicated" |
|
||||
[formContext]="formContext" |
|
||||
[formControl]="$any(fieldForm)" |
|
||||
[isExpanded]="isExpanded" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[query]="field.rawProperties.query" |
|
||||
[schemaIds]="field.rawProperties.schemaIds"> |
|
||||
</sqx-references-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Dropdown'"> |
|
||||
<sqx-reference-dropdown |
|
||||
mode="Array" |
|
||||
[formControl]="$any(fieldForm)" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[schemaId]="field.rawProperties.singleId"> |
|
||||
</sqx-reference-dropdown> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Input'"> |
|
||||
<sqx-reference-input |
|
||||
mode="Array" |
|
||||
[formControl]="$any(fieldForm)" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[query]="field.rawProperties.query" |
|
||||
[schemaIds]="field.rawProperties.schemaIds"> |
|
||||
</sqx-reference-input> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Tags'"> |
|
||||
<sqx-references-tags |
|
||||
[formControl]="$any(fieldForm)" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[schemaId]="field.rawProperties.singleId"> |
|
||||
</sqx-references-tags> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Checkboxes'"> |
|
||||
<sqx-references-checkboxes |
|
||||
[formControl]="$any(fieldForm)" |
|
||||
[language]="language" |
|
||||
[schemaId]="field.rawProperties.singleId"> |
|
||||
</sqx-references-checkboxes> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'String'"> |
|
||||
<ng-container [ngSwitch]="field.rawProperties.editor"> |
|
||||
<ng-container *ngSwitchCase="'Input'"> |
|
||||
<input class="form-control" [formControl]="$any(fieldForm)" [placeholder]="field.displayPlaceholder"> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Slug'"> |
|
||||
<input class="form-control" [formControl]="$any(fieldForm)" [placeholder]="field.displayPlaceholder" sqxTransformInput="Slugify"> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'TextArea'"> |
|
||||
<textarea class="form-control" [formControl]="$any(fieldForm)" [placeholder]="field.displayPlaceholder" rows="5"></textarea> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'RichText'"> |
|
||||
<sqx-rich-editor #editor |
|
||||
mode="Html" |
|
||||
[annotations]="annotations | async" |
|
||||
(annotationsCreate)="annotationCreate($event)" |
|
||||
(annotationsSelect)="annotationsSelect($event)" |
|
||||
(annotationsUpdate)="annotationsUpdate($event)" |
|
||||
[classNames]="field.rawProperties.classNames" |
|
||||
[formControl]="$any(fieldForm)" |
|
||||
[folderId]="field.rawProperties.folderId" |
|
||||
[hasAnnotations]="!!comments" |
|
||||
[hasChatBot]="hasChatBot" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[schemaIds]="field.rawProperties.schemaIds"> |
|
||||
</sqx-rich-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Html'"> |
|
||||
<sqx-code-editor [formControl]="$any(fieldForm)" #editor mode="ace/mode/html" [height]="350" ></sqx-code-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Markdown'"> |
|
||||
<sqx-rich-editor #editor |
|
||||
mode="Markdown" |
|
||||
[annotations]="annotations | async" |
|
||||
(annotationsCreate)="annotationCreate($event)" |
|
||||
(annotationsSelect)="annotationsSelect($event)" |
|
||||
(annotationsUpdate)="annotationsUpdate($event)" |
|
||||
[classNames]="undefined" |
|
||||
[formControl]="$any(fieldForm)" |
|
||||
[folderId]="field.rawProperties.folderId" |
|
||||
[hasAnnotations]="!!comments" |
|
||||
[hasChatBot]="hasChatBot" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[schemaIds]="field.rawProperties.schemaIds"> |
|
||||
</sqx-rich-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'StockPhoto'"> |
|
||||
<sqx-stock-photo-editor [formControl]="$any(fieldForm)"></sqx-stock-photo-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Dropdown'"> |
|
||||
<select class="form-select" [formControl]="$any(fieldForm)"> |
|
||||
<option [ngValue]="null"></option> |
|
||||
<option *ngFor="let value of field.rawProperties.allowedValues" [ngValue]="value">{{value}}</option> |
|
||||
</select> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Radio'"> |
|
||||
<sqx-radio-group [formControl]="$any(fieldForm)" [values]="field.rawProperties.allowedValues" unsorted="true"></sqx-radio-group> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Color'"> |
|
||||
<sqx-color-picker [formControl]="$any(fieldForm)" [placeholder]="field.displayPlaceholder"></sqx-color-picker> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'RichText'"> |
|
||||
<sqx-rich-editor #editor |
|
||||
mode="State" |
|
||||
[annotations]="annotations | async" |
|
||||
(annotationsCreate)="annotationCreate($event)" |
|
||||
(annotationsSelect)="annotationsSelect($event)" |
|
||||
(annotationsUpdate)="annotationsUpdate($event)" |
|
||||
[classNames]="field.rawProperties.classNames" |
|
||||
[formControl]="$any(fieldForm)" |
|
||||
[folderId]="field.rawProperties.folderId" |
|
||||
[hasAnnotations]="!!comments" |
|
||||
[hasChatBot]="hasChatBot" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
[schemaIds]="field.rawProperties.schemaIds"> |
|
||||
</sqx-rich-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Tags'"> |
|
||||
<ng-container [ngSwitch]="field.rawProperties.editor"> |
|
||||
<ng-container *ngSwitchCase="'Tags'"> |
|
||||
<sqx-tag-editor [formControl]="$any(fieldForm)" [placeholder]="field.displayPlaceholder" [itemsSource]="field.rawProperties.allowedValues"></sqx-tag-editor> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Checkboxes'"> |
|
||||
<sqx-checkbox-group [formControl]="$any(fieldForm)" [values]="field.rawProperties.allowedValues"></sqx-checkbox-group> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'Dropdown'"> |
|
||||
<select multiple class="form-select" [formControl]="$any(fieldForm)"> |
|
||||
<option *ngFor="let value of field.rawProperties.allowedValues" [ngValue]="value">{{value}}</option> |
|
||||
</select> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
<ng-container *ngSwitchCase="'UI'"> |
|
||||
<h4 class="ui-separator">{{field.displayName}}</h4> |
|
||||
</ng-container> |
|
||||
</ng-container> |
|
||||
</ng-template> |
|
||||
</div> |
</div> |
||||
|
} |
||||
|
|
||||
<sqx-form-hint *ngIf="field.properties.hints && field.properties.hints.length > 0"> |
<sqx-chat-dialog (contentSelect)="setValue($event)" *sqxModal="chatDialog"></sqx-chat-dialog> |
||||
<span [sqxMarkdown]="field.properties.hints" optional="true" inline="true"></span> |
|
||||
</sqx-form-hint> |
|
||||
</div> |
|
||||
|
|
||||
<sqx-chat-dialog *sqxModal="chatDialog" |
|
||||
(contentSelect)="setValue($event)"> |
|
||||
</sqx-chat-dialog> |
|
||||
|
|||||
@ -1,27 +1,25 @@ |
|||||
<ng-container *ngIf="formModel.field.isLocalizable && languages.length > 1"> |
@if (formModel.field.isLocalizable && languages.length > 1) { |
||||
<button *ngIf="!formModel.field.properties.isComplexUI" type="button" class="btn btn-sm btn-outline-secondary force no-focus-shadow" (click)="toggleShowAllControls()"> |
@if (!formModel.field.properties.isComplexUI) { |
||||
<ng-container *ngIf="showAllControls; else singleLanguage"> |
<button class="btn btn-sm btn-outline-secondary force no-focus-shadow" (click)="toggleShowAllControls()" type="button"> |
||||
<span>{{ 'contents.languageModeSingle' | sqxTranslate }}</span> |
@if (showAllControls) { |
||||
</ng-container> |
<span>{{ "contents.languageModeSingle" | sqxTranslate }}</span> |
||||
|
} @else { |
||||
<ng-template #singleLanguage> |
<span>{{ "contents.languageModeAll" | sqxTranslate }}</span> |
||||
<span>{{ 'contents.languageModeAll' | sqxTranslate }}</span> |
} |
||||
</ng-template> |
</button> |
||||
</button> |
} |
||||
|
@if (formModel.field.properties.isComplexUI || !showAllControls) { |
||||
<ng-container *ngIf="formModel.field.properties.isComplexUI || !showAllControls"> |
|
||||
<div class="button-container ms-1"> |
<div class="button-container ms-1"> |
||||
<sqx-language-selector |
<sqx-language-selector |
||||
size="sm" |
|
||||
[exists]="formModel.translationStatus | async" |
[exists]="formModel.translationStatus | async" |
||||
(languageChange)="languageChange.emit($event)" |
|
||||
[language]="language" |
|
||||
[languages]="languages" |
|
||||
hintText="i18n:contents.validationHint" |
|
||||
hintAfter="120000" |
hintAfter="120000" |
||||
hintPosition="top-end" |
hintPosition="top-end" |
||||
sqxTourStep="languages"> |
hintText="i18n:contents.validationHint" |
||||
</sqx-language-selector> |
[language]="language" |
||||
|
(languageChange)="languageChange.emit($event)" |
||||
|
[languages]="languages" |
||||
|
size="sm" |
||||
|
sqxTourStep="languages"></sqx-language-selector> |
||||
</div> |
</div> |
||||
</ng-container> |
} |
||||
</ng-container> |
} |
||||
|
|||||
@ -1,18 +1,21 @@ |
|||||
<div #container> |
<div #container> |
||||
<div #inner [class.fullscreen]="snapshot.isFullscreen" [class.expanded]="isExpanded"> |
<div #inner [class.expanded]="isExpanded" [class.fullscreen]="snapshot.isFullscreen"> |
||||
<iframe #iframe [scrolling]="!isExpanded ? 'no' : 'yes'" width="100%" [style.height]="0" [attr.src]="computedUrl | sqxSafeResourceUrl"></iframe> |
<iframe |
||||
|
#iframe |
||||
|
[attr.src]="computedUrl | sqxSafeResourceUrl" |
||||
|
[scrolling]="!isExpanded ? 'no' : 'yes'" |
||||
|
[style.height]="0" |
||||
|
width="100%"></iframe> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
<sqx-asset-selector *sqxModal="assetsDialog" |
<sqx-asset-selector (assetSelect)="pickAssets($event)" *sqxModal="assetsDialog"></sqx-asset-selector> |
||||
(assetSelect)="pickAssets($event)"> |
|
||||
</sqx-asset-selector> |
|
||||
|
|
||||
<sqx-content-selector *sqxModal="contentsDialog" |
<sqx-content-selector |
||||
(contentSelect)="pickContents($event)" |
|
||||
[alreadySelectedIds]="contentsSelectedIds" |
[alreadySelectedIds]="contentsSelectedIds" |
||||
[query]="contentsQuery" |
(contentSelect)="pickContents($event)" |
||||
[language]="language" |
[language]="language" |
||||
[languages]="languages" |
[languages]="languages" |
||||
[schemaIdentifiers]="contentsSchemas"> |
[query]="contentsQuery" |
||||
</sqx-content-selector> |
[schemaIdentifiers]="contentsSchemas" |
||||
|
*sqxModal="contentsDialog"></sqx-content-selector> |
||||
|
|||||
@ -1,50 +1,64 @@ |
|||||
|
|
||||
<div class="input-group"> |
<div class="input-group"> |
||||
<button type="button" class="btn btn-outline-secondary" (click)="reset()" [disabled]="!valueControl.value"> |
<button class="btn btn-outline-secondary" (click)="reset()" [disabled]="!valueControl.value" type="button"> |
||||
<i class="icon-close"></i> |
<i class="icon-close"></i> |
||||
</button> |
</button> |
||||
|
|
||||
<button type="button" class="btn btn-outline-secondary" (click)="searchDialog.show()"> |
<button class="btn btn-outline-secondary" (click)="searchDialog.show()" type="button"> |
||||
<i class="icon-search"></i> |
<i class="icon-search"></i> |
||||
</button> |
</button> |
||||
|
|
||||
<input readonly [disabled]="true" class="form-control" [formControl]="valueControl"> |
<input class="form-control" [disabled]="true" [formControl]="valueControl" readonly /> |
||||
</div> |
</div> |
||||
|
|
||||
<div *ngIf="stockPhotoThumbnail | async; let url;" class="preview mt-1" [class.hidden-important]="snapshot.thumbnailStatus === 'Failed'"> |
@if (stockPhotoThumbnail | async; as url) { |
||||
<img [src]="url" (error)="onThumbnailFailed()" (load)="onThumbnailLoaded()"> |
<div class="preview mt-1" [class.hidden-important]="snapshot.thumbnailStatus === 'Failed'"> |
||||
|
<img (error)="onThumbnailFailed()" (load)="onThumbnailLoaded()" [src]="url" /> |
||||
<sqx-loader color="white" *ngIf="snapshot.thumbnailStatus !== 'Loaded'"></sqx-loader> |
@if (snapshot.thumbnailStatus !== "Loaded") { |
||||
</div> |
<sqx-loader color="white"></sqx-loader> |
||||
|
} |
||||
|
</div> |
||||
|
} |
||||
|
|
||||
<sqx-modal-dialog *sqxModal="searchDialog" size="lg" fullHeight="true" (dialogClose)="searchDialog.hide()"> |
<sqx-modal-dialog (dialogClose)="searchDialog.hide()" fullHeight="true" size="lg" *sqxModal="searchDialog"> |
||||
<ng-container title> |
<ng-container title> |
||||
<input class="form-control search" [formControl]="stockPhotoSearch" sqxFocusOnInit placeholder="{{ 'contents.stockPhotoSearch' | sqxTranslate }}"> |
<input |
||||
|
class="form-control search" |
||||
<sqx-loader *ngIf="snapshot.isLoading"></sqx-loader> |
[formControl]="stockPhotoSearch" |
||||
|
placeholder="{{ 'contents.stockPhotoSearch' | sqxTranslate }}" |
||||
|
sqxFocusOnInit /> |
||||
|
|
||||
|
@if (snapshot.isLoading) { |
||||
|
<sqx-loader></sqx-loader> |
||||
|
} |
||||
</ng-container> |
</ng-container> |
||||
|
|
||||
<ng-container content> |
<ng-container content> |
||||
<div class="photos"> |
<div class="photos"> |
||||
<div *ngFor="let photo of snapshot.stockPhotos; trackBy: trackByPhoto" class="photo" [class.selected]="isSelected(photo)" (click)="selectPhoto(photo)"> |
@for (photo of snapshot.stockPhotos; track photo.thumbUrl) { |
||||
<img [src]="photo.thumbUrl"> |
<div class="photo" [class.selected]="isSelected(photo)" (click)="selectPhoto(photo)"> |
||||
|
<img [src]="photo.thumbUrl" /> |
||||
<div class="photo-user"> |
<div class="photo-user"> |
||||
<a class="photo-user-link" [href]="photo.userProfileUrl" sqxExternalLink sqxStopClick> |
<a class="photo-user-link" [href]="photo.userProfileUrl" sqxExternalLink sqxStopClick> |
||||
{{photo.user}} |
{{ photo.user }} |
||||
</a> |
</a> |
||||
|
</div> |
||||
</div> |
</div> |
||||
</div> |
} @empty { |
||||
</div> |
<div class="empty small text-muted text-center"> |
||||
|
{{ "contents.stockPhotoSearchEmpty" | sqxTranslate }} |
||||
<div class="empty small text-muted text-center" *ngIf="snapshot.stockPhotos.length === 0"> |
</div> |
||||
{{ 'contents.stockPhotoSearchEmpty' | sqxTranslate }} |
} |
||||
</div> |
</div> |
||||
|
|
||||
<div class="mt-4 text-center" *ngIf="snapshot.hasMore"> |
@if (snapshot.hasMore) { |
||||
<button class="btn btn-outline-secondary" type="button" (click)="loadMore()" [disabled]="snapshot.isLoading"> |
<div class="mt-4 text-center"> |
||||
{{ 'common.loadMore' | sqxTranslate }} <sqx-loader *ngIf="snapshot.isLoading"></sqx-loader> |
<button class="btn btn-outline-secondary" (click)="loadMore()" [disabled]="snapshot.isLoading" type="button"> |
||||
</button> |
{{ "common.loadMore" | sqxTranslate }} |
||||
</div> |
@if (snapshot.isLoading) { |
||||
|
<sqx-loader></sqx-loader> |
||||
|
} |
||||
|
</button> |
||||
|
</div> |
||||
|
} |
||||
</ng-container> |
</ng-container> |
||||
</sqx-modal-dialog> |
</sqx-modal-dialog> |
||||
|
|||||
@ -1,79 +1,82 @@ |
|||||
<tr [sqxTabRouterLink]="link"> |
<tr [sqxTabRouterLink]="link"> |
||||
<td class="cell-select inline-edit" sqxStopClick> |
<td class="cell-select inline-edit" sqxStopClick> |
||||
<div class="form-check"> |
<div class="form-check"> |
||||
<input class="form-check-input" type="checkbox" id="{{content.id}}_selected" |
<input |
||||
|
class="form-check-input" |
||||
|
id="{{ content.id }}_selected" |
||||
[ngModel]="selected" |
[ngModel]="selected" |
||||
(ngModelChange)="selectedChange.emit($event)" /> |
(ngModelChange)="selectedChange.emit($event)" |
||||
|
type="checkbox" /> |
||||
|
|
||||
<label class="form-check-label" for="{{content.id}}_selected" ></label> |
<label class="form-check-label" for="{{ content.id }}_selected"></label> |
||||
</div> |
</div> |
||||
|
|
||||
<ng-container *ngIf="isDirty"> |
@if (isDirty) { |
||||
<div class="edit-menu"> |
<div class="edit-menu"> |
||||
<button type="button" class="btn btn-text-secondary btn-cancel me-2" (click)="cancel()" sqxStopClick> |
<button class="btn btn-text-secondary btn-cancel me-2" (click)="cancel()" sqxStopClick type="button"> |
||||
<i class="icon-close"></i> |
<i class="icon-close"></i> |
||||
</button> |
</button> |
||||
|
<button class="btn btn-success" (click)="save()" sqxStopClick type="button"> |
||||
<button type="button" class="btn btn-success" (click)="save()" sqxStopClick> |
|
||||
<i class="icon-checkmark"></i> |
<i class="icon-checkmark"></i> |
||||
</button> |
</button> |
||||
</div> |
</div> |
||||
</ng-container> |
} |
||||
</td> |
</td> |
||||
|
|
||||
<td class="cell-actions cell-actions-left" sqxStopClick> |
<td class="cell-actions cell-actions-left" sqxStopClick> |
||||
<button type="button" class="btn btn-text-secondary" attr.aria-label="{{ 'common.options' | sqxTranslate }}" (click)="dropdown.toggle()" #buttonOptions> |
<button |
||||
|
class="btn btn-text-secondary" |
||||
|
#buttonOptions |
||||
|
attr.aria-label="{{ 'common.options' | sqxTranslate }}" |
||||
|
(click)="dropdown.toggle()" |
||||
|
type="button"> |
||||
<i class="icon-dots"></i> |
<i class="icon-dots"></i> |
||||
</button> |
</button> |
||||
|
|
||||
<sqx-dropdown-menu *sqxModal="dropdown;closeAlways:true" [sqxAnchoredTo]="buttonOptions" scrollY="true" position="bottom-start"> |
<sqx-dropdown-menu position="bottom-start" scrollY="true" [sqxAnchoredTo]="buttonOptions" *sqxModal="dropdown; closeAlways: true"> |
||||
<a class="dropdown-item" [routerLink]="link" target="_blank" sqxExternalLink> |
<a class="dropdown-item" [routerLink]="link" sqxExternalLink target="_blank"> |
||||
{{ 'common.editInNewTab' | sqxTranslate }} |
{{ "common.editInNewTab" | sqxTranslate }} |
||||
</a> |
</a> |
||||
|
|
||||
<a class="dropdown-item" *ngFor="let info of content.statusUpdates" (click)="statusChange.emit(info.status)"> |
@for (info of content.statusUpdates; track info) { |
||||
{{ 'common.statusChangeTo' | sqxTranslate }} |
<a class="dropdown-item" (click)="statusChange.emit(info.status)"> |
||||
|
{{ "common.statusChangeTo" | sqxTranslate }} |
||||
|
<sqx-content-status layout="text" small="true" [status]="info.status" [statusColor]="info.color"></sqx-content-status> |
||||
|
</a> |
||||
|
} |
||||
|
@if (cloneable) { |
||||
|
<a class="dropdown-item" (click)="clone.emit(); dropdown.hide()"> |
||||
|
{{ "common.clone" | sqxTranslate }} |
||||
|
</a> |
||||
|
} |
||||
|
|
||||
<sqx-content-status |
|
||||
layout="text" |
|
||||
[status]="info.status" |
|
||||
[statusColor]="info.color" |
|
||||
small="true"> |
|
||||
</sqx-content-status> |
|
||||
</a> |
|
||||
<a class="dropdown-item" (click)="clone.emit(); dropdown.hide()" *ngIf="cloneable"> |
|
||||
{{ 'common.clone' | sqxTranslate }} |
|
||||
</a> |
|
||||
|
|
||||
<div class="dropdown-divider"></div> |
<div class="dropdown-divider"></div> |
||||
|
|
||||
<a class="dropdown-item dropdown-item-delete" [class.disabled]="!content.canDelete" |
<a |
||||
(sqxConfirmClick)="delete.emit()" |
class="dropdown-item dropdown-item-delete" |
||||
confirmTitle="i18n:contents.deleteConfirmTitle" |
[class.disabled]="!content.canDelete" |
||||
|
confirmRememberKey="deleteContent" |
||||
confirmText="i18n:contents.deleteConfirmText" |
confirmText="i18n:contents.deleteConfirmText" |
||||
confirmRememberKey="deleteContent"> |
confirmTitle="i18n:contents.deleteConfirmTitle" |
||||
{{ 'common.delete' | sqxTranslate }} |
(sqxConfirmClick)="delete.emit()"> |
||||
|
{{ "common.delete" | sqxTranslate }} |
||||
</a> |
</a> |
||||
</sqx-dropdown-menu> |
</sqx-dropdown-menu> |
||||
</td> |
</td> |
||||
|
|
||||
<td *ngFor="let field of tableFields" |
@for (field of tableFields; track field) { |
||||
sqxContentListCell |
<td [field]="field" [fields]="tableSettings" sqxContentListCell sqxContentListCellResize [sqxStopClick]="shouldStop(field)"> |
||||
sqxContentListCellResize |
<sqx-content-list-field |
||||
[field]="field" |
[content]="content" |
||||
[fields]="tableSettings" |
[field]="field" |
||||
[sqxStopClick]="shouldStop(field)"> |
[fields]="tableSettings" |
||||
<sqx-content-list-field |
[language]="language" |
||||
[content]="content" |
[languages]="languages" |
||||
[field]="field" |
[patchAllowed]="patchAllowed" |
||||
[fields]="tableSettings" |
[patchForm]="patchForm?.form" |
||||
[language]="language" |
[schema]="schema"></sqx-content-list-field> |
||||
[languages]="languages" |
</td> |
||||
[patchAllowed]="patchAllowed" |
} |
||||
[patchForm]="patchForm?.form" |
|
||||
[schema]="schema"> |
|
||||
</sqx-content-list-field> |
|
||||
</td> |
|
||||
|
|
||||
<td></td> |
<td></td> |
||||
</tr> |
</tr> |
||||
|
|||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue