From d256691ac0e4d2e1cd41ef1c1d9ce3c310e77dc6 Mon Sep 17 00:00:00 2001 From: Alex Tatiyants Date: Fri, 29 Jan 2016 21:05:29 -0800 Subject: fix #12 --- app/components/plan-list/plan-list.html | 34 ++++++++++++++++----------------- app/components/plan-list/plan-list.ts | 7 +++++-- 2 files changed, 22 insertions(+), 19 deletions(-) (limited to 'app/components') diff --git a/app/components/plan-list/plan-list.html b/app/components/plan-list/plan-list.html index 28c95af..09e9262 100644 --- a/app/components/plan-list/plan-list.html +++ b/app/components/plan-list/plan-list.html @@ -5,26 +5,26 @@ + +
+ + +
+ -
{{plan.name}} created on {{plan.createdOn | momentDate }} - -
- - - -
diff --git a/app/components/plan-list/plan-list.ts b/app/components/plan-list/plan-list.ts index 888e2e2..32583a3 100644 --- a/app/components/plan-list/plan-list.ts +++ b/app/components/plan-list/plan-list.ts @@ -20,6 +20,7 @@ export class PlanList { newPlanContent: any; newPlanId: string; openDialog: boolean = false; + planToDelete: IPlan; constructor(private _planService: PlanService) { } @@ -27,13 +28,15 @@ export class PlanList { this.plans = this._planService.getPlans(); } - requestDelete() { + requestDelete(plan) { this.openDialog = true; + this.planToDelete = plan; } deletePlan(plan) { this.openDialog = false; - this._planService.deletePlan(plan); + console.log(this.planToDelete); + this._planService.deletePlan(this.planToDelete); this.plans = this._planService.getPlans(); } -- cgit v1.2.3 From 7e0665204c5931a8fa47d835a4799030a960c354 Mon Sep 17 00:00:00 2001 From: Alex Tatiyants Date: Fri, 29 Jan 2016 21:21:35 -0800 Subject: add usage hints/disclaimer. close #11, #6 --- app/components/plan-new/plan-new.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'app/components') diff --git a/app/components/plan-new/plan-new.html b/app/components/plan-new/plan-new.html index f74529d..f27037d 100644 --- a/app/components/plan-new/plan-new.html +++ b/app/components/plan-new/plan-new.html @@ -1,6 +1,9 @@
- For best results, use EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON) - + + + For best results, use EXPLAIN (ANALYZE, COSTS, VERBOSE, BUFFERS, FORMAT JSON)
+ Psql users can export the plan to a file using psql -qAt -f explain.sql > analyze.json
+

DISCLAIMER: Pev stores your plans locally (localStorage) and will not send them anywhere.

-- cgit v1.2.3 From 781479ea7f793c8d075caee53f6413a1d2e85307 Mon Sep 17 00:00:00 2001 From: Alex Tatiyants Date: Fri, 29 Jan 2016 21:33:19 -0800 Subject: add plan validation --- app/components/plan-new/plan-new.html | 1 + app/components/plan-new/plan-new.ts | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'app/components') diff --git a/app/components/plan-new/plan-new.html b/app/components/plan-new/plan-new.html index f27037d..f150969 100644 --- a/app/components/plan-new/plan-new.html +++ b/app/components/plan-new/plan-new.html @@ -9,6 +9,7 @@
+

{{validationMessage}}

diff --git a/app/components/plan-new/plan-new.ts b/app/components/plan-new/plan-new.ts index 93149e2..115fa82 100644 --- a/app/components/plan-new/plan-new.ts +++ b/app/components/plan-new/plan-new.ts @@ -16,19 +16,28 @@ export class PlanNew { newPlanContent: string; newPlanQuery: string; newPlan: IPlan; + validationMessage: string; - constructor( private _router: Router, private _planService: PlanService) { } + constructor(private _router: Router, private _planService: PlanService) { } submitPlan() { + // remove psql generated header + this.newPlanContent = this.newPlanContent.replace('QUERY PLAN', ''); + + if (!this._planService.isJsonString(this.newPlanContent)) { + this.validationMessage = 'The string you submitted is not valid JSON' + return; + } + this.newPlan = this._planService.createPlan(this.newPlanName, this.newPlanContent, this.newPlanQuery); - this._router.navigate( ['PlanView', { id: this.newPlan.id }] ); + this._router.navigate(['PlanView', { id: this.newPlan.id }]); } prefill() { - this.newPlanName = 'Sample plan'; - this.newPlanContent = SAMPLE_JSON; - this.newPlanQuery = SAMPLE_QUERY; - } + this.newPlanName = 'Sample plan'; + this.newPlanContent = SAMPLE_JSON; + this.newPlanQuery = SAMPLE_QUERY; + } } export var SAMPLE_JSON = `[ { -- cgit v1.2.3 From 7fc812bc761c95e508e1c540393b12b03cdf1d03 Mon Sep 17 00:00:00 2001 From: Alex Tatiyants Date: Sat, 27 Feb 2016 14:38:42 -0800 Subject: add Dot view mode to make large plans easier to view --- app/components/plan-node/plan-node.html | 22 +++++++------ app/components/plan-node/plan-node.ts | 55 +++++++++++++++++++++++++++++++-- app/components/plan-view/plan-view.html | 15 ++++----- app/components/plan-view/plan-view.ts | 6 ++-- 4 files changed, 78 insertions(+), 20 deletions(-) (limited to 'app/components') diff --git a/app/components/plan-node/plan-node.html b/app/components/plan-node/plan-node.html index 5ddf55c..60cdf50 100644 --- a/app/components/plan-node/plan-node.html +++ b/app/components/plan-node/plan-node.html @@ -1,8 +1,11 @@ -
+
+
-

{{node[_planService.NODE_TYPE_PROP] | uppercase}} -

- +

{{getNodeName()}}

+ {{node[_planService.ACTUAL_DURATION_PROP] | duration}}{{node[_planService.ACTUAL_DURATION_PROP] | durationUnit}} | {{executionTimePercent}} % @@ -10,12 +13,12 @@
- -
+
on {{node[_planService.SCHEMA_PROP]}}.{{node[_planService.RELATION_NAME_PROP]}} @@ -33,20 +36,21 @@
on {{node[_planService.HASH_CONDITION_PROP]}}
+
- {{tag}} + {{getTagName(tag)}}
- + {{viewOptions.highlightType}}: {{highlightValue | number:'.0-2'}}
-
+
over estimated rows under estimated rows by {{plannerRowEstimateValue | number}}x diff --git a/app/components/plan-node/plan-node.ts b/app/components/plan-node/plan-node.ts index 0d3c420..52590e8 100644 --- a/app/components/plan-node/plan-node.ts +++ b/app/components/plan-node/plan-node.ts @@ -1,6 +1,6 @@ import {IPlan} from '../../interfaces/iplan'; import {Component, OnInit} from 'angular2/core'; -import {HighlightType, EstimateDirection} from '../../enums'; +import {HighlightType, EstimateDirection, ViewMode} from '../../enums'; import {DurationPipe, DurationUnitPipe} from '../../pipes'; import {PlanService} from '../../services/plan-service'; @@ -23,6 +23,7 @@ export class PlanNode { // consts NORMAL_WIDTH: number = 220; COMPACT_WIDTH: number = 140; + DOT_WIDTH: number = 30; EXPANDED_WIDTH: number = 400; MIN_ESTIMATE_MISS: number = 100; @@ -58,6 +59,7 @@ export class PlanNode { // expose enum to view estimateDirections = EstimateDirection; highlightTypes = HighlightType; + viewModes = ViewMode; constructor(private _planService: PlanService, private _syntaxHighlightService: SyntaxHighlightService, @@ -122,7 +124,17 @@ export class PlanNode { } calculateBar() { - this.barContainerWidth = this.viewOptions.showCompactView ? this.COMPACT_WIDTH : this.NORMAL_WIDTH; + switch (this.viewOptions.viewMode) { + case ViewMode.DOT: + this.barContainerWidth = this.DOT_WIDTH; + break; + case ViewMode.COMPACT: + this.barContainerWidth = this.COMPACT_WIDTH; + break; + default: + this.barContainerWidth = this.NORMAL_WIDTH; + break; + } // expanded view width trumps others if (this.currentExpandedView) { @@ -184,4 +196,43 @@ export class PlanNode { getNodeTypeDescription() { return this._helpService.getNodeTypeDescription(this.node[this._planService.NODE_TYPE_PROP]); } + + getNodeName() { + if (this.viewOptions.viewMode === ViewMode.DOT && !this.showDetails) { + return this.node[this._planService.NODE_TYPE_PROP].replace(/[^A-Z]/g, '').toUpperCase(); + } + + return (this.node[this._planService.NODE_TYPE_PROP]).toUpperCase(); + } + + getTagName(tagName: String) { + if (this.viewOptions.viewMode === ViewMode.DOT && !this.showDetails) { + return tagName.charAt(0); + } + return tagName; + } + + shouldShowPlannerEstimate() { + if (this.viewOptions.showPlannerEstimate && this.showDetails) { + return true; + } + + if (this.viewOptions.viewMode === ViewMode.DOT) { + return false; + } + + return this.viewOptions.showPlannerEstimate; + } + + shouldShowNodeBarLabel() { + if (this.showDetails) { + return true; + } + + if (this.viewOptions.viewMode === ViewMode.DOT) { + return false; + } + + return true; + } } diff --git a/app/components/plan-view/plan-view.html b/app/components/plan-view/plan-view.html index 4ebb70c..70278f4 100644 --- a/app/components/plan-view/plan-view.html +++ b/app/components/plan-view/plan-view.html @@ -9,21 +9,22 @@ - -
  • - - -
  • -
  • -
  • +
  • + +
    + + + +
    +
  • diff --git a/app/components/plan-view/plan-view.ts b/app/components/plan-view/plan-view.ts index 895cccf..9ba8782 100644 --- a/app/components/plan-view/plan-view.ts +++ b/app/components/plan-view/plan-view.ts @@ -2,7 +2,7 @@ import {Component, OnInit} from 'angular2/core'; import {ROUTER_DIRECTIVES, RouteParams} from 'angular2/router'; import {IPlan} from '../../interfaces/iplan'; -import {HighlightType} from '../../enums'; +import {HighlightType, ViewMode} from '../../enums'; import {PlanNode} from '../plan-node/plan-node'; import {PlanService} from '../../services/plan-service'; import {SyntaxHighlightService} from '../../services/syntax-highlight-service'; @@ -26,13 +26,15 @@ export class PlanView { showHighlightBar: true, showPlannerEstimate: false, showTags: true, - highlightType: HighlightType.NONE + highlightType: HighlightType.NONE, + viewMode: ViewMode.FULL }; showPlannerEstimate: boolean = true; showMenu: boolean = false; highlightTypes = HighlightType; // exposing the enum to the view + viewModes = ViewMode; constructor(private _planService: PlanService, routeParams: RouteParams) { this.id = routeParams.get('id'); -- cgit v1.2.3 From cd2af1466b1c23f81c13af61fa550475f82e0227 Mon Sep 17 00:00:00 2001 From: Alex Tatiyants Date: Sat, 5 Mar 2016 11:58:52 -0800 Subject: better handle CTE scans, including correct duration calculations. fix #15 --- app/components/plan-node/plan-node.html | 3 +++ 1 file changed, 3 insertions(+) (limited to 'app/components') diff --git a/app/components/plan-node/plan-node.html b/app/components/plan-node/plan-node.html index 60cdf50..86db018 100644 --- a/app/components/plan-node/plan-node.html +++ b/app/components/plan-node/plan-node.html @@ -35,6 +35,9 @@ using {{node[_planService.INDEX_NAME_PROP]}}
  • on {{node[_planService.HASH_CONDITION_PROP]}}
    +
    + CTE {{node[_planService.CTE_NAME_PROP]}} +
    -- cgit v1.2.3 From 9b004d78b5012e4e7a3bf6e1eb086d941050425f Mon Sep 17 00:00:00 2001 From: Alex Tatiyants Date: Sat, 5 Mar 2016 12:02:08 -0800 Subject: tweak styles for new plan page --- app/components/plan-new/plan-new.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/components') diff --git a/app/components/plan-new/plan-new.html b/app/components/plan-new/plan-new.html index f150969..42bb8f6 100644 --- a/app/components/plan-new/plan-new.html +++ b/app/components/plan-new/plan-new.html @@ -10,6 +10,6 @@

    {{validationMessage}}

    - - + +
    -- cgit v1.2.3 From eae3aee1bbfb29dd31e92853664a373e3d60d6b6 Mon Sep 17 00:00:00 2001 From: Alex Tatiyants Date: Sat, 16 Apr 2016 12:54:48 -0700 Subject: sort plans in reverse chronological order --- app/components/plan-list/plan-list.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/components') diff --git a/app/components/plan-list/plan-list.html b/app/components/plan-list/plan-list.html index 09e9262..a16ffbe 100644 --- a/app/components/plan-list/plan-list.html +++ b/app/components/plan-list/plan-list.html @@ -3,7 +3,7 @@ Welcome to PEV! Please submit a plan for visualization
    - +
    -- cgit v1.2.3