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>
</div>
<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 class="col-auto cell-actions">
<button type="button" class="btn btn-text-danger"
@ -80,8 +80,6 @@
</div>
</div>
<sqx-modal-dialog *sqxModalView="connectDialog;onRoot:true" large="true" (closed)="connectDialog.hide()">
<ng-container title>
Connect
@ -96,21 +94,37 @@
<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 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 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 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 class="help-section">
Use the following token for testing
<ng-container *ngIf="connectToken">
<textarea class="form-control access-token" readonly>{{connectToken.accessToken}}</textarea>
</ng-container>
<div class="copy-container">
<button type="button" class="btn-copy" [sqxCopy]="connectTokenInput">
<i class="icon-copy"></i>
</button>
<textarea class="form-control access-token" #connectTokenInput readonly>{{connectToken?.accessToken}}</textarea>
</div>
</div>
<h3>Using the command line interface (CLI)</h3>
@ -121,14 +135,26 @@
<div class="help-section">
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 class="help-section">
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>
<h3>Using the C# Client Library</h3>
@ -139,8 +165,14 @@
<div class="help-section">
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>
</ng-container>

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

@ -7,7 +7,8 @@ $color-editor: #eceeef;
& {
@include border-radius(0);
border-bottom-width: 2px;
border-top-width: 1px;
border-top-width: 0;
margin-bottom: .25rem;
}
&-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`;
}
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 }) {
const url = apiUrl.value;
@ -47,14 +55,6 @@ function connectLibrary(apiUrl: ApiUrlConfig, app: string, client: { id: string,
"${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({
selector: 'sqx-client',
styleUrls: ['./client.component.scss'],
@ -77,7 +77,7 @@ export class ClientComponent implements OnChanges {
public connectHttpText: string;
public connectCLINixText: string;
public connectCLIWinText: string;
public connectLibrary: string;
public connectLibraryText: string;
constructor(
public readonly appsState: AppsState,
@ -97,7 +97,7 @@ export class ClientComponent implements OnChanges {
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);
this.connectLibraryText = connectLibrary(this.apiUrl, app, this.client);
}
public revoke() {
@ -135,10 +135,10 @@ export class ClientComponent implements OnChanges {
}
}
public createToken(client: AppClientDto) {
public connect() {
this.connectDialog.show();
this.appClientsService.createToken(this.appsState.appName, client)
this.appClientsService.createToken(this.appsState.appName, this.client)
.subscribe(dto => {
this.connectToken = dto;
}, error => {

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

@ -5,7 +5,7 @@
* 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 {
DialogService,
@ -21,7 +21,8 @@ export class CopyDirective {
public inputElement: any;
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) {
const currentFocus: any = document.activeElement;
private copyToClipbord(element: HTMLElement) {
if (Types.is(element, HTMLInputElement) || Types.is(element, HTMLTextAreaElement)) {
const currentFocus: any = document.activeElement;
const prevSelectionStart = element.selectionStart;
const prevSelectionEnd = element.selectionEnd;
const prevSelectionStart = element.selectionStart;
const prevSelectionEnd = element.selectionEnd;
element.focus();
if (Types.is(element, HTMLInputElement)) {
element.focus();
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 {
document.execCommand('copy');
@ -51,13 +74,5 @@ export class CopyDirective {
} catch (e) {
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
//

Loading…
Cancel
Save