Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

<section *ngIf="model" class="row text-center my-3">
<div>
<h1>Online Indenter</h1>
Expand All @@ -14,7 +13,7 @@ <h1>Online Indenter</h1>
</section>

<section *ngIf="model" class="row my-3">
<div class="col-lg-6 accordion">
<div class="col-lg-6 my-1 accordion">

<!-- Indent Options -->
<div class="card my-2">
Expand Down Expand Up @@ -411,24 +410,24 @@ <h4 class="card-title">Looking for a programmatic approach?</h4>
<div class="card-body">
Try the API:
<ol>
<li>Request (GET) <code>api.rubberduckvba.com/indenter/defaults</code> to get a JSON object for the model (or copy it from below);</li>
<li>Request (GET) <code>{{apiBaseUrl}}indenter/defaults</code> to get a JSON object for the model (or copy it from below);</li>
<li>Provide the code to be indented in the 'Code' property; use <code>\n</code> for newline characters;</li>
<li>Post (POST) the JSON object to <code>api.rubberduckvba.com/indenter/indent</code> to get the indented code back as an array of strings.</li>
<li>Post (POST) the JSON object to <code>{{apiBaseUrl}}indenter/indent</code> to get the indented code back as an array of strings.</li>
</ol>
<textarea id="template-json" class="code-area form-control font-monospace" rows="15" readonly [innerHTML]="asJson"></textarea>
</div>

<div class="card-footer">
<button id="copy-template" class="btn btn-secondary mx-1" type="button">
<span><i class="fa fa-clipboard"></i>&nbsp;Copy</span>
<button id="copy-template" class="btn mx-1" [ngClass]="wasTemplateCopied ? 'btn-success' : 'btn-secondary'" type="button" (click)="copyTemplate()">
<span><fa-icon [icon]="wasTemplateCopied ? 'check' : 'clipboard'"></fa-icon>&nbsp;{{wasTemplateCopied ? 'Copied!' : 'Copy'}}</span>
</button>
</div>
</div>
</div>

</div>

<div class="col-lg-6">
<div class="col-lg-6 my-1">
<div class="card">
<div class="card-header">
<h4>Try it right here!</h4>
Expand All @@ -444,20 +443,30 @@ <h4>Try it right here!</h4>
<span id="indent-button-text">Indent</span>
</button>
<button id="copy-code" class="btn mx-1" [ngClass]="wasCopied ? 'btn-success' : 'btn-secondary'" type="button" [disabled]="model.code.length == 0" (click)="copy()">
<span><fa-icon [icon]="'clipboard'"></fa-icon>&nbsp;{{wasCopied ? 'Copied!' : 'Copy'}}</span>
<span><fa-icon [icon]="wasCopied ? 'check' : 'clipboard'"></fa-icon>&nbsp;{{wasCopied ? 'Copied!' : 'Copy'}}</span>
</button>
</div>
</div>
</div>

<!-- <div class="row"> -->
<!-- <div class="col-12"> -->
<!-- <img class="ducky my-2 w-10 hover-enlarge" alt="Rubberduck logo" src="../../assets/vector-ducky-dark.svg" /> -->
<!-- </div> -->
<!-- </div> -->

<hr />
<div class="row">
<!-- TODO -->
<div class="form-group col-6">
<div role="button" class="btn btn-primary" (click)="getDefaults()"><fa-icon [icon]="'rotate-left'"></fa-icon>&nbsp;Reset to defaults</div>
</div>
<div class="form-group col-6">
<div class="form-check">
<label class="form-check-label" for="vspaceBox">
<input id="localstorageBox" type="checkbox" [(ngModel)]="isLocalStorageOK" />
Remember configuration
</label>
</div>
</div>
</div>
</section>

<section class="row my-3 text-center">
<div class="col-12">
<img class="ducky my-2 w-10 hover-enlarge" alt="Rubberduck logo" src="../../assets/vector-ducky-dark.svg" />
</div>
</section>
166 changes: 150 additions & 16 deletions rubberduckvba.client/src/app/routes/indenter/indenter.component.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,165 @@
import { Component, OnInit } from "@angular/core";
import { FaIconLibrary } from "@fortawesome/angular-fontawesome";
import { fas } from "@fortawesome/free-solid-svg-icons";
import { IndenterViewModel } from "../../model/indenter.model";
import { IndenterViewModel, IndenterViewModelClass } from "../../model/indenter.model";
import { ApiClientService } from "../../services/api-client.service";
import { environment } from "../../../environments/environment";

export interface IndenterOptionGroups {
isExpanded: boolean;
isIndentOptionsExpanded: boolean;
isOutdentOptionsExpanded: boolean;
isAlignmentOptionsExpanded: boolean;
isCommentOptionsExpanded: boolean;
isVerticalOptionsExpanded: boolean;
isApiAboutBoxExpanded: boolean;
}

@Component({
selector: 'app-indenter',
templateUrl: './indenter.component.html',
})
export class IndenterComponent implements OnInit {
export class IndenterComponent implements OnInit, IndenterOptionGroups {
private _model!: IndenterViewModel;
public wasCopied: boolean = false;
public wasTemplateCopied: boolean = false;


constructor(fa: FaIconLibrary, private service: ApiClientService) {
fa.addIconPacks(fas);
}

ngOnInit(): void {
const localModel = localStorage.getItem('indenter.model');
if (localModel) {
this.model = <IndenterViewModel>JSON.parse(localModel);
}

const localOptionGroups = localStorage.getItem('indenter.options');
if (localOptionGroups) {
const optionGroups = <IndenterOptionGroups>JSON.parse(localOptionGroups);
this.isExpanded = optionGroups.isExpanded;
this.isIndentOptionsExpanded = optionGroups.isIndentOptionsExpanded;
this.isOutdentOptionsExpanded = optionGroups.isOutdentOptionsExpanded;
this.isAlignmentOptionsExpanded = optionGroups.isAlignmentOptionsExpanded;
this.isCommentOptionsExpanded = optionGroups.isCommentOptionsExpanded;
this.isVerticalOptionsExpanded = optionGroups.isVerticalOptionsExpanded;
this.isApiAboutBoxExpanded = optionGroups.isApiAboutBoxExpanded;
}

this.isLocalStorageOK = localModel != null || localOptionGroups != null;
if (!this.isLocalStorageOK) {
this.getDefaults();
}
}

public getDefaults(): void {
this.service.getIndenterDefaults().subscribe(model => {
this._model = model;
this.model = model;
});
}

public isExpanded: boolean = false;
public isIndentOptionsExpanded: boolean = true;
public isOutdentOptionsExpanded: boolean = false;
public isAlignmentOptionsExpanded: boolean = false;
public isCommentOptionsExpanded: boolean = false;
public isVerticalOptionsExpanded: boolean = false;
public isApiAboutBoxExpanded: boolean = true;
private _isExpanded: boolean = false;
private _isIndentOptionsExpanded: boolean = true;
private _isOutdentOptionsExpanded: boolean = false;
private _isAlignmentOptionsExpanded: boolean = false;
private _isCommentOptionsExpanded: boolean = false;
private _isVerticalOptionsExpanded: boolean = false;
private _isApiAboutBoxExpanded: boolean = false;

public isIndenterBusy: boolean = false;
public isLocalStorageOK: boolean = false;

public get model(): IndenterViewModel {
return this._model;
}

private set model(value: IndenterViewModel) {
this._model = value;
this.invalidateClipboard();
if (this.isLocalStorageOK) {
localStorage.setItem('indenter.model', JSON.stringify(this.model))
};
}

public get asJson(): string {
return JSON.stringify(this._model);
const copy = new IndenterViewModelClass(this._model);
copy.indentedCode = '';
return JSON.stringify(copy);
}

public get isExpanded(): boolean {
return this._isExpanded;
}
public set isExpanded(value: boolean) {
this._isExpanded = value;
this.saveOptions();
}
public get isIndentOptionsExpanded(): boolean {
return this._isIndentOptionsExpanded;
}

public set isIndentOptionsExpanded(value: boolean) {
this._isIndentOptionsExpanded = value;
this.saveOptions();
}
public get isCommentOptionsExpanded(): boolean {
return this._isCommentOptionsExpanded;
}
public set isCommentOptionsExpanded(value: boolean) {
this._isCommentOptionsExpanded = value;
this.saveOptions();
}
public get isVerticalOptionsExpanded(): boolean {
return this._isVerticalOptionsExpanded;
}
public set isVerticalOptionsExpanded(value: boolean) {
this._isVerticalOptionsExpanded = value;
this.saveOptions();
}

public get isApiAboutBoxExpanded(): boolean {
return this._isApiAboutBoxExpanded;
}
public set isApiAboutBoxExpanded(value: boolean) {
this._isApiAboutBoxExpanded = value;
this.saveOptions();
}

public get isOutdentOptionsExpanded(): boolean {
return this._isOutdentOptionsExpanded;
}
public set isOutdentOptionsExpanded(value: boolean) {
this._isOutdentOptionsExpanded = value;
this.saveOptions();
}
public get isAlignmentOptionsExpanded(): boolean {
return this._isAlignmentOptionsExpanded;
}
public set isAlignmentOptionsExpanded(value: boolean) {
this._isAlignmentOptionsExpanded = value;
this.saveOptions();
}

private get asOptionGroups(): IndenterOptionGroups {
return {
isExpanded: this.isExpanded,
isIndentOptionsExpanded: this.isIndentOptionsExpanded,
isAlignmentOptionsExpanded: this.isAlignmentOptionsExpanded,
isApiAboutBoxExpanded: this.isApiAboutBoxExpanded,
isCommentOptionsExpanded: this.isCommentOptionsExpanded,
isOutdentOptionsExpanded: this.isOutdentOptionsExpanded,
isVerticalOptionsExpanded: this.isVerticalOptionsExpanded
};
}

private saveModel(): void {
if (this.isLocalStorageOK) {
localStorage.setItem('indenter.model', JSON.stringify(this.model));
}
}
private saveOptions(): void {
localStorage.setItem('indenter.options', JSON.stringify(this.asOptionGroups));
}

public indent(): void {
Expand All @@ -47,19 +168,32 @@ export class IndenterComponent implements OnInit {
this.model.indentedCode = vm.indentedCode;
this.model.code = vm.indentedCode;
this.isIndenterBusy = false;
});
}

public clear(): void {
this.model.code = '';
this.invalidateClipboard();
this.saveModel();
this.saveOptions();
});
}

public copy(): void {
navigator.clipboard.writeText(this.model.code).then(e => this.wasCopied = true);
}
public copyTemplate(): void {
navigator.clipboard.writeText(this.asJson).then(e => this.wasTemplateCopied = true);
}

private invalidateClipboard(): void {
this.wasCopied = false;
this.wasTemplateCopied = false;
}

public get apiBaseUrl(): string {
return environment.apiBaseUrl.replace('https://', '');
}

public onModelChanged(code: string): void {
this.model.code = code;
this.wasCopied = false;
this.invalidateClipboard();
this.saveModel();
}
}