Browse Source

Clipboard improvements.

pull/342/head
Sebastian Stehle 7 years ago
parent
commit
b6d8bd5490
  1. 60
      src/Squidex/app/features/settings/pages/clients/client.component.html
  2. 3
      src/Squidex/app/features/settings/pages/clients/client.component.scss
  3. 24
      src/Squidex/app/features/settings/pages/clients/client.component.ts
  4. 49
      src/Squidex/app/framework/angular/forms/copy.directive.ts
  5. 23
      src/Squidex/app/theme/_common.scss

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

@ -25,7 +25,7 @@
</ng-container> </ng-container>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<button class="btn btn-primary" (click)="createToken(client)">Connect</button> <button class="btn btn-primary" (click)="connect()">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"
@ -80,8 +80,6 @@
</div> </div>
</div> </div>
<sqx-modal-dialog *sqxModalView="connectDialog;onRoot:true" large="true" (closed)="connectDialog.hide()"> <sqx-modal-dialog *sqxModalView="connectDialog;onRoot:true" large="true" (closed)="connectDialog.hide()">
<ng-container title> <ng-container title>
Connect Connect
@ -96,21 +94,37 @@
<div class="help-section"> <div class="help-section">
1. Make the following request to get an access token. It will be valid for 30 days. 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 class="copy-container">
<button type="button" class="btn-copy" [sqxCopy]="connectHttpBlock">
<i class="icon-copy"></i>
</button>
<pre class="code code-block" #connectHttpBlock>{{connectHttpText}}</pre>
</div>
</div> </div>
<div class="help-section"> <div class="help-section">
2. Add the bearer token as authorization header to all requests: 2. Add the bearer token as authorization header to all requests:
<pre class="code code-block">Authorization: Bearer [YOUR_TOKEN]</pre> <div class="copy-container">
<button type="button" class="btn-copy" [sqxCopy]="headerBlock">
<i class="icon-copy"></i>
</button>
<pre class="code code-block" #headerBlock>Authorization: Bearer [YOUR_TOKEN]</pre>
</div>
</div> </div>
<div class="help-section"> <div class="help-section">
Use the following token for testing Use the following token for testing
<ng-container *ngIf="connectToken"> <div class="copy-container">
<textarea class="form-control access-token" readonly>{{connectToken.accessToken}}</textarea> <button type="button" class="btn-copy" [sqxCopy]="connectTokenInput">
</ng-container> <i class="icon-copy"></i>
</button>
<textarea class="form-control access-token" #connectTokenInput readonly>{{connectToken?.accessToken}}</textarea>
</div>
</div> </div>
<h3>Using the command line interface (CLI)</h3> <h3>Using the command line interface (CLI)</h3>
@ -121,14 +135,26 @@
<div class="help-section"> <div class="help-section">
Connect with windows: Connect with windows:
<pre class="code code-block">{{connectCLIWinText}}</pre> <div class="copy-container">
<button type="button" class="btn-copy" [sqxCopy]="connectCLIWinBlock">
<i class="icon-copy"></i>
</button>
<pre class="code code-block" #connectCLIWinBlock>{{connectCLIWinText}}</pre>
</div>
</div> </div>
<div class="help-section"> <div class="help-section">
Connect with Linux / OS X Connect with Linux / OS X
<pre class="code code-block">{{connectCLINixText}}</pre> <div class="copy-container">
<button type="button" class="btn-copy" [sqxCopy]="connectCLINixBlock">
<i class="icon-copy"></i>
</button>
<pre class="code code-block" #connectCLINixBlock>{{connectCLINixText}}</pre>
</div>
</div> </div>
<h3>Using the C# Client Library</h3> <h3>Using the C# Client Library</h3>
@ -139,8 +165,14 @@
<div class="help-section"> <div class="help-section">
Create a client manager Create a client manager
<pre class="code code-block">{{connectLibrary}}</pre> <div class="copy-container">
<button type="button" class="btn-copy" [sqxCopy]="connectLibraryBlock">
<i class="icon-copy"></i>
</button>
<pre class="code code-block" #connectLibraryBlock>{{connectLibraryText}}</pre>
</div>
</div> </div>
</div> </div>
</ng-container> </ng-container>

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

@ -7,7 +7,8 @@ $color-editor: #eceeef;
& { & {
@include border-radius(0); @include border-radius(0);
border-bottom-width: 2px; border-bottom-width: 2px;
border-top-width: 1px; border-top-width: 0;
margin-bottom: .25rem;
} }
&-header { &-header {

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

@ -37,6 +37,14 @@ function connectHttpText(apiUrl: ApiUrlConfig, app: string, client: { id: string
scope=squidex-api`; scope=squidex-api`;
} }
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}`;
}
function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) { function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string, secret: string }) {
const url = apiUrl.value; const url = apiUrl.value;
@ -47,14 +55,6 @@ function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string,
"${client.secret}")`; "${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'],
@ -77,7 +77,7 @@ export class ClientComponent implements OnChanges {
public connectHttpText: string; public connectHttpText: string;
public connectCLINixText: string; public connectCLINixText: string;
public connectCLIWinText: string; public connectCLIWinText: string;
public connectLibrary: string; public connectLibraryText: string;
constructor( constructor(
public readonly appsState: AppsState, public readonly appsState: AppsState,
@ -97,7 +97,7 @@ export class ClientComponent implements OnChanges {
this.connectHttpText = connectHttpText(this.apiUrl, app, this.client); this.connectHttpText = connectHttpText(this.apiUrl, app, this.client);
this.connectCLINixText = connectCLINixText(app, this.client); this.connectCLINixText = connectCLINixText(app, this.client);
this.connectCLIWinText = connectCLIWinText(app, this.client); this.connectCLIWinText = connectCLIWinText(app, this.client);
this.connectLibrary = connectLibrary(this.apiUrl, app, this.client); this.connectLibraryText = connectLibrary(this.apiUrl, app, this.client);
} }
public revoke() { public revoke() {
@ -135,10 +135,10 @@ export class ClientComponent implements OnChanges {
} }
} }
public createToken(client: AppClientDto) { public connect() {
this.connectDialog.show(); this.connectDialog.show();
this.appClientsService.createToken(this.appsState.appName, client) this.appClientsService.createToken(this.appsState.appName, this.client)
.subscribe(dto => { .subscribe(dto => {
this.connectToken = dto; this.connectToken = dto;
}, error => { }, error => {

49
src/Squidex/app/framework/angular/forms/copy.directive.ts

@ -5,7 +5,7 @@
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/ */
import { Directive, HostListener, Input } from '@angular/core'; import { Directive, HostListener, Input, Renderer2 } from '@angular/core';
import { import {
DialogService, DialogService,
@ -21,7 +21,8 @@ export class CopyDirective {
public inputElement: any; public inputElement: any;
constructor( constructor(
private readonly dialogs: DialogService private readonly dialogs: DialogService,
private readonly renderer: Renderer2
) { ) {
} }
@ -32,18 +33,40 @@ export class CopyDirective {
} }
} }
private copyToClipbord(element: HTMLInputElement | HTMLTextAreaElement) { private copyToClipbord(element: HTMLElement) {
const currentFocus: any = document.activeElement; if (Types.is(element, HTMLInputElement) || Types.is(element, HTMLTextAreaElement)) {
const currentFocus: any = document.activeElement;
const prevSelectionStart = element.selectionStart; const prevSelectionStart = element.selectionStart;
const prevSelectionEnd = element.selectionEnd; const prevSelectionEnd = element.selectionEnd;
element.focus(); element.focus();
if (Types.is(element, HTMLInputElement)) {
element.setSelectionRange(0, element.value.length); element.setSelectionRange(0, element.value.length);
this.copy();
element.setSelectionRange(prevSelectionStart!, prevSelectionEnd!);
if (currentFocus && Types.isFunction(currentFocus.focus)) {
currentFocus.focus();
}
} else {
const input = this.renderer.createElement('textarea');
this.renderer.setStyle(input, 'position', 'absolute');
this.renderer.setStyle(input, 'right', '-1000px');
this.renderer.appendChild(document.body, input);
input.value = element.innerText;
input.select();
this.copy();
this.renderer.removeChild(document.body, input);
} }
}
private copy() {
try { try {
document.execCommand('copy'); document.execCommand('copy');
@ -51,13 +74,5 @@ export class CopyDirective {
} catch (e) { } catch (e) {
console.log('Copy failed'); console.log('Copy failed');
} }
if (currentFocus && Types.isFunction(currentFocus.focus)) {
currentFocus.focus();
}
if (Types.is(element, HTMLInputElement)) {
element.setSelectionRange(prevSelectionStart!, prevSelectionEnd!);
}
} }
} }

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

@ -118,6 +118,29 @@ pre {
} }
} }
//
// Copy buttons
//
.copy-container {
& {
position: relative;
}
.btn-copy {
& {
@include absolute(0, 0, auto, auto);
border: 0;
background: darken($color-border-dark, 30%);
padding: 2px 6px;
color: $color-dark-foreground;
}
&:focus {
background: darken($color-border-dark, 40%);
}
}
}
// //
// Profile picture in circle // Profile picture in circle
// //

Loading…
Cancel
Save