Browse Source

Connect screen

pull/342/head
Sebastian Stehle 8 years ago
parent
commit
c8318775fd
  1. 12
      src/Squidex.Domain.Apps.Entities/Apps/AppHistoryEventsCreator.cs
  2. 16
      src/Squidex/app/features/rules/pages/rules/triggers/asset-changed-trigger.component.scss
  3. 20
      src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.scss
  4. 2
      src/Squidex/app/features/settings/module.ts
  5. 68
      src/Squidex/app/features/settings/pages/clients/client.component.html
  6. 22
      src/Squidex/app/features/settings/pages/clients/client.component.scss
  7. 53
      src/Squidex/app/features/settings/pages/clients/client.component.ts
  8. 4
      src/Squidex/app/features/settings/pages/plans/plans-page.component.html
  9. 45
      src/Squidex/app/theme/_common.scss

12
src/Squidex.Domain.Apps.Entities/Apps/AppHistoryEventsCreator.cs

@ -43,6 +43,9 @@ namespace Squidex.Domain.Apps.Entities.Apps
AddEventMessage<AppClientRenamed>( AddEventMessage<AppClientRenamed>(
"renamed client {[Id]} to {[Name]}"); "renamed client {[Id]} to {[Name]}");
AddEventMessage<AppPlanChanged>(
"changed plan to {[Plan]}");
AddEventMessage<AppLanguageAdded>( AddEventMessage<AppLanguageAdded>(
"added language {[Language]}"); "added language {[Language]}");
@ -200,6 +203,15 @@ namespace Squidex.Domain.Apps.Entities.Apps
.AddParameter("Name", @event.Name)); .AddParameter("Name", @event.Name));
} }
protected Task<HistoryEvent> On(AppPlanChanged @event)
{
const string channel = "settings.plan";
return Task.FromResult(
ForEvent(@event, channel)
.AddParameter("Plan", @event.PlanId));
}
protected Task<HistoryEvent> On(AppRoleDeleted @event) protected Task<HistoryEvent> On(AppRoleDeleted @event)
{ {
const string channel = "settings.roles"; const string channel = "settings.roles";

16
src/Squidex/app/features/rules/pages/rules/triggers/asset-changed-trigger.component.scss

@ -3,20 +3,4 @@
textarea { textarea {
height: 100px; height: 100px;
}
.help {
& {
font-size: .9rem;
}
&-example {
margin-top: .375rem;
}
&-examples {
margin-top: 0;
margin-bottom: 0;
padding-left: 1.5rem;
}
} }

20
src/Squidex/app/features/rules/pages/rules/triggers/content-changed-trigger.component.scss

@ -9,24 +9,4 @@
.form-check { .form-check {
margin-top: 1rem; margin-top: 1rem;
}
textarea {
height: 100px;
}
.help {
& {
font-size: .9rem;
}
&-example {
margin-top: .375rem;
}
&-examples {
margin-top: 0;
margin-bottom: 0;
padding-left: 1.5rem;
}
} }

2
src/Squidex/app/features/settings/module.ts

@ -66,7 +66,7 @@ const routes: Routes = [
path: 'history', path: 'history',
component: HistoryComponent, component: HistoryComponent,
data: { data: {
channel: 'settings.plans' channel: 'settings.plan'
} }
} }
] ]

68
src/Squidex/app/features/settings/pages/clients/client.component.html

@ -24,11 +24,9 @@
<i class="client-edit icon-pencil" (click)="toggleRename()"></i> <i class="client-edit icon-pencil" (click)="toggleRename()"></i>
</ng-container> </ng-container>
</div> </div>
<div class="client-expires">Access tokens expire after 30 days</div>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<button class="btn btn-secondary" (click)="createToken(client)">Create Token</button> <button class="btn btn-secondary" (click)="createToken(client)">Connect</button>
</div> </div>
<div class="col-auto cell-actions"> <div class="col-auto cell-actions">
<button type="button" class="btn btn-text-danger" <button type="button" class="btn btn-text-danger"
@ -47,7 +45,7 @@
<input readonly class="form-control" value="{{appsState.appName}}:{{client.id}}" #inputName /> <input readonly class="form-control" value="{{appsState.appName}}:{{client.id}}" #inputName />
</div> </div>
<div class="col-auto cell-actions"> <div class="col-auto cell-actions">
<button type="button" class="btn btn-primary btn-text" [sqxCopy]="inputName"> <button type="button" class="btn btn-text" [sqxCopy]="inputName">
<i class="icon-copy"></i> <i class="icon-copy"></i>
</button> </button>
</div> </div>
@ -60,7 +58,7 @@
<input readonly class="form-control" [attr.value]="client.secret" #inputSecret /> <input readonly class="form-control" [attr.value]="client.secret" #inputSecret />
</div> </div>
<div class="col-auto cell-actions"> <div class="col-auto cell-actions">
<button type="button" class="btn btn-primary btn-text" [sqxCopy]="inputSecret"> <button type="button" class="btn btn-text" [sqxCopy]="inputSecret">
<i class="icon-copy"></i> <i class="icon-copy"></i>
</button> </button>
</div> </div>
@ -79,12 +77,66 @@
</div> </div>
</div> </div>
<sqx-modal-dialog *sqxModalView="tokenDialog;onRoot:true" (closed)="tokenDialog.hide()"> <sqx-modal-dialog *sqxModalView="connectDialog;onRoot:true" large="true" (closed)="connectDialog.hide()">
<ng-container title> <ng-container title>
Access token Connect
</ng-container> </ng-container>
<ng-container content> <ng-container content>
<textarea readonly class="form-control access-token">{{token.tokenType}} {{token.accessToken}}</textarea> <div class="help">
<h2>How to connect to this client</h2>
<h3>Using HTTP</h3>
<div class="help-section">
1. Make the following request to get an access token. It will be valid for 30 days.
<pre class="code code-block">{{connectHttpText}}</pre>
</div>
<div class="help-section">
2. Add the bearer token as authorization header to all requests:
<pre class="code code-block">Authorization: Bearer [YOUR_TOKEN]</pre>
</div>
<div class="help-section">
Use the following token for testing
<ng-container *ngIf="connectToken">
<textarea class="form-control access-token" readonly>{{connectToken.tokenType}} {{connectToken.accessToken}}</textarea>
</ng-container>
</div>
<h3>Using the command line interface (CLI)</h3>
<div class="help-section">
Download the CLI here: <a href="https://github.com/Squidex/squidex-samples/releases" target="_blank">CLI Releases (Linux, OS X, Windows)</a>
</div>
<div class="help-section">
Connect with windows:
<pre class="code code-block">{{connectCLIWinText}}</pre>
</div>
<div class="help-section">
Connect with Linux / OS X
<pre class="code code-block">{{connectCLINixText}}</pre>
</div>
<h3>Using the C# Client Library</h3>
<div class="help-section">
Get the nuget library from <a href="https://www.nuget.org/packages/Squidex.ClientLibrary/" target="_blank">nuget.org</a>
</div>
<div class="help-section">
Create a client manager
<pre class="code code-block">{{connectLibrary}}</pre>
</div>
</div>
</ng-container> </ng-container>
</sqx-modal-dialog> </sqx-modal-dialog>

22
src/Squidex/app/features/settings/pages/clients/client.component.scss

@ -12,12 +12,6 @@ $color-editor: #eceeef;
vertical-align: top; vertical-align: top;
} }
&-expires {
font-size: .8rem;
font-weight: normal;
margin-bottom: .75rem;
}
&-edit { &-edit {
color: $color-border-dark; color: $color-border-dark;
display: none; display: none;
@ -35,11 +29,17 @@ $color-editor: #eceeef;
font-size: 1.2rem; font-size: 1.2rem;
font-weight: normal; font-weight: normal;
line-height: 1.5rem; line-height: 1.5rem;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
display: inline-block; display: inline-block;
margin: 0; margin: 0;
} }
&-header { &-header {
& {
margin-bottom: .5rem;
}
&:hover { &:hover {
.client-edit { .client-edit {
display: inline-block; display: inline-block;
@ -48,13 +48,6 @@ $color-editor: #eceeef;
} }
} }
h3 {
&.client-name {
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
}
}
.col-form-label { .col-form-label {
text-align: left; text-align: left;
} }
@ -68,8 +61,9 @@ h3 {
} }
.access-token { .access-token {
height: 18rem; height: 10rem;
font-size: 1rem; font-size: 1rem;
font-weight: normal; font-weight: normal;
font-family: monospace; font-family: monospace;
resize: none;
} }

53
src/Squidex/app/features/settings/pages/clients/client.component.ts

@ -11,6 +11,7 @@ import { onErrorResumeNext } from 'rxjs/operators';
import { import {
AccessTokenDto, AccessTokenDto,
ApiUrlConfig,
AppClientDto, AppClientDto,
AppClientsService, AppClientsService,
AppRoleDto, AppRoleDto,
@ -24,6 +25,36 @@ import {
const ESCAPE_KEY = 27; const ESCAPE_KEY = 27;
function connectHttpText(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) {
const url = apiUrl.buildUrl('identity-server/connect/token');
return `$ curl
-X POST '${url}'
-H 'Content-Type: application/x-www-form-urlencoded'
-d 'grant_type=client_credentials&
client_id=${app}:${client.id}&
client_secret=${client.secret}&
scope=squidex-api`;
}
function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) {
const url = apiUrl.value;
return `var clientManager = new SquidexClientManager(
"${url}",
"${app}",
"${app}:${client.id}",
"${client.secret}")`;
}
function connectCLIWinText(app: string, client: { id: string, secret: string }) {
return `.\\sq.exe config add ${app} ${app}:${client.id} ${client.secret};.\\sq.exe config use ${app}`;
}
function connectCLINixText(app: string, client: { id: string, secret: string }) {
return `sq config add ${app} ${app}:${client.id} ${client.secret} && sq config use ${app}`;
}
@Component({ @Component({
selector: 'sqx-client', selector: 'sqx-client',
styleUrls: ['./client.component.scss'], styleUrls: ['./client.component.scss'],
@ -38,13 +69,19 @@ export class ClientComponent implements OnChanges {
public isRenaming = false; public isRenaming = false;
public token: AccessTokenDto; public connectToken: AccessTokenDto;
public tokenDialog = new DialogModel(); public connectDialog = new DialogModel();
public renameForm = new RenameClientForm(this.formBuilder); public renameForm = new RenameClientForm(this.formBuilder);
public connectHttpText: string;
public connectCLINixText: string;
public connectCLIWinText: string;
public connectLibrary: string;
constructor( constructor(
public readonly appsState: AppsState, public readonly appsState: AppsState,
private readonly apiUrl: ApiUrlConfig,
private readonly appClientsService: AppClientsService, private readonly appClientsService: AppClientsService,
private readonly clientsState: ClientsState, private readonly clientsState: ClientsState,
private readonly dialogs: DialogService, private readonly dialogs: DialogService,
@ -54,6 +91,13 @@ export class ClientComponent implements OnChanges {
public ngOnChanges() { public ngOnChanges() {
this.renameForm.load(this.client); this.renameForm.load(this.client);
const app = this.appsState.appName;
this.connectHttpText = connectHttpText(this.apiUrl, app, this.client);
this.connectCLINixText = connectCLINixText(app, this.client);
this.connectCLIWinText = connectCLIWinText(app, this.client);
this.connectLibrary = connectLibrary(this.apiUrl, app, this.client);
} }
public revoke() { public revoke() {
@ -92,10 +136,11 @@ export class ClientComponent implements OnChanges {
} }
public createToken(client: AppClientDto) { public createToken(client: AppClientDto) {
this.connectDialog.show();
this.appClientsService.createToken(this.appsState.appName, client) this.appClientsService.createToken(this.appsState.appName, client)
.subscribe(dto => { .subscribe(dto => {
this.token = dto; this.connectToken = dto;
this.tokenDialog.show();
}, error => { }, error => {
this.dialogs.notifyError(error); this.dialogs.notifyError(error);
}); });

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

@ -79,8 +79,8 @@
</ng-container> </ng-container>
<ng-container sidebar> <ng-container sidebar>
<a class="panel-link" routerLink="help" routerLinkActive="active"> <a class="panel-link" routerLink="history" routerLinkActive="active">
<i class="icon-help"></i> <i class="icon-time"></i>
</a> </a>
</ng-container> </ng-container>
</sqx-panel> </sqx-panel>

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

@ -62,6 +62,51 @@ pre {
padding: .25rem .5rem; padding: .25rem .5rem;
margin: 0; margin: 0;
} }
&.code-block {
display: block;
}
}
//
// Help texts
//
.help {
& {
font-size: .9rem;
}
pre {
font-size: 100%;
}
h2 {
margin-top: 1rem;
}
h3 {
margin-top: 2rem;
margin-bottom: .25rem;
font-size: 1.1rem;
}
.code-block {
margin: .25rem 0;
}
&-section {
padding-top: .5rem;
}
&-example {
margin-top: .375rem;
}
&-examples {
margin-top: 0;
margin-bottom: 0;
padding-left: 1.5rem;
}
} }
// //

Loading…
Cancel
Save