fixes: U4-10540 Make it possible to run custom logic for a tour step

This commit is contained in:
Mads Rasmussen
2017-10-18 08:46:13 +02:00
parent b891b18b20
commit 49f17be9df
23 changed files with 446 additions and 67 deletions

View File

@@ -126,13 +126,13 @@
function _position() {
var element = $(scope.currentStep.element);
var offset = element.offset();
var width = element.outerWidth(true);
var height = element.outerHeight(true);
$timeout(function () {
var element = $(scope.currentStep.element);
var offset = element.offset();
var width = element.outerWidth(true);
var height = element.outerHeight(true);
var popoverWidth = popover.outerWidth(true);
var popoverHeight = popover.outerHeight(true);
var popoverOffset = popover.offset();
@@ -140,65 +140,49 @@
var documentHeight = $(document).height();
var position;
var css = {};
// messure available space on each side of the target element
var space = {
"top": offset.top,
"right": documentWidth - (offset.left + width),
"bottom": documentHeight - (offset.top + height),
"left": offset.left
};
console.log("SPACE", space);
console.log("document width", documentWidth);
console.log("document height", documentHeight);
// If no specific position is set - find the position with most available space
if(scope.currentStep.placement) {
position = scope.currentStep.placement;
} else {
var space = {
"top": offset.top,
"right": documentWidth - (offset.left + width),
"bottom": documentHeight - (offset.top + height),
"left": offset.left
};
position = findMax(space);
}
// get the posistion with most available space
position = findMax(space);
if(position === "top") {
if (offset.left < documentWidth/2) {
css = {top: offset.top - popoverHeight, left: offset.left};
css = {top: offset.top - popoverHeight, left: offset.left};
} else {
css = {top: offset.top - popoverHeight, left: offset.left - popoverWidth + width};
}
}
if(position === "right") {
if (offset.top < documentHeight/2) {
css = {top: offset.top, left: offset.left + width};
css = {top: offset.top, left: offset.left + width};
} else {
css = {top: offset.top + height - popoverHeight, left: offset.left + width};
}
}
if(position === "bottom") {
if (offset.left < documentWidth/2) {
css = {top: offset.top + height, left: offset.left};
css = {top: offset.top + height, left: offset.left};
} else {
css = {top: offset.top + height, left: offset.left - popoverWidth + width};
}
}
if(position === "left") {
if (offset.top < documentHeight/2) {
css = {top: offset.top, left: offset.left - popoverWidth};
} else {
css = {top: offset.top + height - popoverHeight, left: offset.left - popoverWidth};
}
@@ -228,8 +212,8 @@
function bindEvent() {
var eventName = scope.currentStep.event + ".step-" + scope.currentStepIndex;
if(scope.currentStep.clickElement) {
$(scope.currentStep.clickElement).on(eventName, handleEvent);
if(scope.currentStep.eventElement) {
$(scope.currentStep.eventElement).on(eventName, handleEvent);
console.log("bind", eventName);
} else {
$(scope.currentStep.element).on(eventName, handleEvent);
@@ -239,17 +223,17 @@
function unbindEvent() {
var eventName = scope.currentStep.event + ".step-" + scope.currentStepIndex;
if(scope.currentStep.clickElement) {
$(scope.currentStep.clickElement).off(eventName);
if(scope.currentStep.eventElement) {
$(scope.currentStep.eventElement).off(eventName);
console.log("unbind", eventName);
} else {
$(scope.currentStep.element).off(eventName);
console.log("unbind", eventName);
console.log("unbind", eventName);
}
}
function handleEvent() {
alert("event happened");
//alert("event happened");
unbindEvent();
nextStep();
}

View File

@@ -0,0 +1,19 @@
(function() {
'use strict';
function TourStepDirective() {
var directive = {
restrict: 'E',
replace: true,
transclude: true,
templateUrl: 'views/components/application/umbtour/umb-tour-step.html'
};
return directive;
}
angular.module('umbraco.directives').directive('umbTourStep', TourStepDirective);
})();

View File

@@ -0,0 +1,22 @@
(function() {
'use strict';
function TourStepContentDirective() {
var directive = {
restrict: 'E',
replace: true,
transclude: true,
templateUrl: 'views/components/application/umbtour/umb-tour-step-content.html',
scope: {
content: "="
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbTourStepContent', TourStepContentDirective);
})();

View File

@@ -0,0 +1,22 @@
(function() {
'use strict';
function TourStepCounterDirective() {
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/application/umbtour/umb-tour-step-counter.html',
scope: {
currentStep: "=",
totalSteps: "="
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbTourStepCounter', TourStepCounterDirective);
})();

View File

@@ -0,0 +1,19 @@
(function() {
'use strict';
function TourStepFooterDirective() {
var directive = {
restrict: 'E',
replace: true,
transclude: true,
templateUrl: 'views/components/application/umbtour/umb-tour-step-footer.html'
};
return directive;
}
angular.module('umbraco.directives').directive('umbTourStepFooter', TourStepFooterDirective);
})();

View File

@@ -0,0 +1,21 @@
(function() {
'use strict';
function TourStepHeaderDirective() {
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/application/umbtour/umb-tour-step-header.html',
scope: {
title: "="
}
};
return directive;
}
angular.module('umbraco.directives').directive('umbTourStepHeader', TourStepHeaderDirective);
})();

View File

@@ -22,7 +22,7 @@
title: "Create document type",
content: "<p>Hover the document types tree and click the <b>three small dots</b> to open the context menu</p>",
event: "click",
clickElement: "#tree [data-element='tree-item-documentTypes'] [data-element='tree-item-options']"
eventElement: "#tree [data-element='tree-item-documentTypes'] [data-element='tree-item-options']"
},
{
element: "#dialog [data-element='action-documentType']",
@@ -33,7 +33,8 @@
{
element: "[data-element='editor-name-field']",
title: "Enter a name",
content: "<p>Our document type needs a name. Enter <b>Home</b> in the field and click <i>Next</i></p>"
content: "<p>Our document type needs a name. Enter <b>Home</b> in the field and click <i>Next</i></p>",
view: "doctypename"
},
{
element: "[data-element='editor-description']",
@@ -60,7 +61,8 @@
{
element: "[data-element~='overlay-property-settings'] [data-element='property-name']",
title: "Enter a name",
content: "Enter <b>Welcome Text</b> as name for the property"
content: "Enter <b>Welcome Text</b> as name for the property",
view: "propertyname"
},
{
element: "[data-element~='overlay-property-settings'] [data-element='property-description']",
@@ -119,7 +121,7 @@
title: "Open context menu",
content: "<p>Open the context menu by hovering the root of the content section.</p><p>Now click the <b>three small dots</b> to the right</p>",
event: "click",
clickElement: "[data-element='tree-root'] [data-element='tree-item-options']"
eventElement: "[data-element='tree-root'] [data-element='tree-item-options']"
},
{
element: "[data-element='action-create-home']",
@@ -130,7 +132,8 @@
{
element: "[data-element='editor-content'] [data-element='editor-name-field']",
title: "Give your new page a name",
content: "<p>Our new page needs a name. Enter <b>Home</b> in the field and click <b>Next</b></p>"
content: "<p>Our new page needs a name. Enter <b>Home</b> in the field and click <i>Next</i></p>",
view: "nodename"
},
{
element: "[data-element='editor-content'] [data-element='property-welcomeText']",
@@ -161,7 +164,8 @@
title: "Expand the Templates node",
content: "<p>To see all our templates click the <b>small triangle</b> to the left of the templates node</p>",
event: "click",
clickElement: "#tree [data-element='tree-item-templates'] [data-element='tree-item-expand']"
eventElement: "#tree [data-element='tree-item-templates'] [data-element='tree-item-expand']",
view: "templatetree"
},
{
element: "#tree [data-element='tree-item-templates'] [data-element='tree-item-Home']",
@@ -204,7 +208,7 @@
title: "Open page",
content: "<p>Click the <b>Link</b> to view your page.</p><p>Tip: Click the preview button in the bottom right corner to preview changes without publishing them</p>",
event: "click",
clickElement: "[data-element='editor-content'] [data-element='property-_umb_urls'] a[target='_blank']"
eventElement: "[data-element='editor-content'] [data-element='property-_umb_urls'] a[target='_blank']"
}
]
},
@@ -224,7 +228,7 @@
title: "Create a new folder",
content: "<p>Hover the media root and click the <b>three small dots</b> on the right side of the item</p>",
event: "click",
clickElement: "#tree [data-element='tree-root'] [data-element='tree-item-options']"
eventElement: "#tree [data-element='tree-root'] [data-element='tree-item-options']"
},
{
element: "#dialog [data-element='action-Folder']",
@@ -246,14 +250,15 @@
{
element: "[data-element='editor-media'] [data-element='dropzone']",
title: "Upload images",
content: "<p>In the upload area you can upload your media items.</p><p>Click the <b>Upload button</b> and select some images on your computer and upload them.</p>"
content: "<p>In the upload area you can upload your media items.</p><p>Click the <b>Upload button</b> and select some images on your computer and upload them.</p>",
view: "uploadimages"
},
{
element: "[data-element='editor-media'] [data-element='media-grid-item-0']",
title: "View media item details",
content: "Hover the media item and <b>Click the purple bar</b> to view details about the media item",
event: "click",
clickElement: "[data-element='editor-media'] [data-element='media-grid-item-0'] [data-element='media-grid-item-edit']"
eventElement: "[data-element='editor-media'] [data-element='media-grid-item-0'] [data-element='media-grid-item-edit']"
},
{
element: "[data-element='editor-media'] [data-element='property-umbracoFile']",

View File

@@ -0,0 +1,24 @@
(function () {
"use strict";
function NodeNameController($scope) {
var vm = this;
var element = angular.element($scope.model.currentStep.element);
vm.error = false;
vm.initNextStep = initNextStep;
function initNextStep() {
if(element.val() === 'Home') {
$scope.model.nextStep();
} else {
vm.error = true;
}
}
}
angular.module("umbraco").controller("Umbraco.Tours.umbIntroCreateDocType.NodeNameController", NodeNameController);
})();

View File

@@ -0,0 +1,26 @@
<umb-tour-step ng-controller="Umbraco.Tours.umbIntroCreateDocType.NodeNameController as vm">
<umb-tour-step-header
title="currentStep.title">
</umb-tour-step-header>
<umb-tour-step-content
content="currentStep.content">
<div ng-if="vm.error" class="color-red" style="margin-top: 5px;">Please enter <b>Home</b> in the field</div>
</umb-tour-step-content>
<umb-tour-step-footer class="flex justify-between items-center">
<umb-tour-step-counter
current-step="currentStepIndex + 1"
total-steps="tour.steps.length">
</umb-tour-step-counter>
<div>
<umb-button size="xs" button-style="link" type="button" action="endTour()" label="End tour"></umb-button>
<umb-button size="xs" button-style="success" type="button" action="vm.initNextStep()" label="Next"></umb-button>
</div>
</umb-tour-step-footer>
</umb-tour-step>

View File

@@ -0,0 +1,24 @@
(function () {
"use strict";
function DocTypeNameController($scope) {
var vm = this;
var element = angular.element($scope.currentStep.element);
vm.error = false;
vm.initNextStep = initNextStep;
function initNextStep() {
if(element.val() === 'Home') {
$scope.nextStep();
} else {
vm.error = true;
}
}
}
angular.module("umbraco").controller("Umbraco.Tours.UmbIntroCreateDocType.DocTypeNameController", DocTypeNameController);
})();

View File

@@ -0,0 +1,26 @@
<umb-tour-step ng-controller="Umbraco.Tours.UmbIntroCreateDocType.DocTypeNameController as vm">
<umb-tour-step-header
title="currentStep.title">
</umb-tour-step-header>
<umb-tour-step-content
content="currentStep.content">
<div ng-if="vm.error" class="color-red" style="margin-top: 5px;">Please enter <b>Home</b> in the field</div>
</umb-tour-step-content>
<umb-tour-step-footer class="flex justify-between items-center">
<umb-tour-step-counter
current-step="currentStepIndex + 1"
total-steps="tour.steps.length">
</umb-tour-step-counter>
<div>
<umb-button size="xs" button-style="link" type="button" action="endTour()" label="End tour"></umb-button>
<umb-button size="xs" button-style="success" type="button" action="vm.initNextStep()" label="Next"></umb-button>
</div>
</umb-tour-step-footer>
</umb-tour-step>

View File

@@ -0,0 +1,24 @@
(function () {
"use strict";
function PropertyNameController($scope) {
var vm = this;
var element = angular.element($scope.currentStep.element);
vm.error = false;
vm.initNextStep = initNextStep;
function initNextStep() {
if(element.val() === 'Welcome Text') {
$scope.nextStep();
} else {
vm.error = true;
}
}
}
angular.module("umbraco").controller("Umbraco.Tours.UmbIntroCreateDocType.PropertyNameController", PropertyNameController);
})();

View File

@@ -0,0 +1,26 @@
<umb-tour-step ng-controller="Umbraco.Tours.UmbIntroCreateDocType.PropertyNameController as vm">
<umb-tour-step-header
title="currentStep.title">
</umb-tour-step-header>
<umb-tour-step-content
content="currentStep.content">
<div ng-if="vm.error" class="color-red" style="margin-top: 5px;">Please enter <b>Welcome Text</b> in the field</div>
</umb-tour-step-content>
<umb-tour-step-footer class="flex justify-between items-center">
<umb-tour-step-counter
current-step="currentStepIndex + 1"
total-steps="tour.steps.length">
</umb-tour-step-counter>
<div>
<umb-button size="xs" button-style="link" type="button" action="endTour()" label="End tour"></umb-button>
<umb-button size="xs" button-style="success" type="button" action="vm.initNextStep()" label="Next"></umb-button>
</div>
</umb-tour-step-footer>
</umb-tour-step>

View File

@@ -0,0 +1,41 @@
(function () {
"use strict";
function UploadImagesController($scope, editorState, mediaResource) {
var vm = this;
var element = angular.element($scope.currentStep.element);
vm.error = false;
vm.initNextStep = initNextStep;
function initNextStep() {
vm.error = false;
vm.buttonState = "busy";
var currentNode = editorState.getCurrent();
// make sure we have uploaded at least one image
mediaResource.getChildren(currentNode.id)
.then(function (data) {
var children = data;
if(children.items && children.items.length > 0) {
$scope.nextStep();
} else {
vm.error = true;
}
vm.buttonState = "init";
});
}
}
angular.module("umbraco").controller("Umbraco.Tours.UmbIntroMediaSection.UploadImagesController", UploadImagesController);
})();

View File

@@ -0,0 +1,26 @@
<umb-tour-step ng-controller="Umbraco.Tours.UmbIntroMediaSection.UploadImagesController as vm">
<umb-tour-step-header
title="currentStep.title">
</umb-tour-step-header>
<umb-tour-step-content
content="currentStep.content">
<div ng-if="vm.error" class="color-red" style="margin-top: 5px;">Please upload an image</div>
</umb-tour-step-content>
<umb-tour-step-footer class="flex justify-between items-center">
<umb-tour-step-counter
current-step="currentStepIndex + 1"
total-steps="tour.steps.length">
</umb-tour-step-counter>
<div>
<umb-button size="xs" button-style="link" type="button" action="endTour()" label="End tour"></umb-button>
<umb-button size="xs" button-style="success" type="button" action="vm.initNextStep()" label="Next" state="vm.buttonState"></umb-button>
</div>
</umb-tour-step-footer>
</umb-tour-step>

View File

@@ -0,0 +1,21 @@
(function () {
"use strict";
function TemplatesTreeController($scope) {
var vm = this;
var eventElement = angular.element($scope.currentStep.eventElement);
function onInit() {
// check if tree is already open - if it is - go to next step
if(eventElement.hasClass("icon-navigation-down")) {
$scope.nextStep();
}
}
onInit();
}
angular.module("umbraco").controller("Umbraco.Tours.UmbIntroRenderInTemplate.TemplatesTreeController", TemplatesTreeController);
})();

View File

@@ -0,0 +1,24 @@
<umb-tour-step ng-controller="Umbraco.Tours.UmbIntroRenderInTemplate.TemplatesTreeController as vm">
<umb-tour-step-header
title="currentStep.title">
</umb-tour-step-header>
<umb-tour-step-content
content="currentStep.content">
</umb-tour-step-content>
<umb-tour-step-footer class="flex justify-between items-center">
<umb-tour-step-counter
current-step="currentStepIndex + 1"
total-steps="tour.steps.length">
</umb-tour-step-counter>
<div>
<umb-button size="xs" button-style="link" type="button" action="endTour()" label="End tour"></umb-button>
</div>
</umb-tour-step-footer>
</umb-tour-step>

View File

@@ -10,27 +10,44 @@
<umb-load-indicator></umb-load-indicator>
</div>
<div ng-if="currentStepIndex < tour.steps.length && !loadingStep">
<div class="umb-tour__title">{{ currentStep.title }}</div>
<div class="umb-tour__content" ng-bind-html="currentStep.content"></div>
<div class="flex justify-between items-center">
<div class="umb-tour__step-counter">Step {{ currentStepIndex + 1 }} of {{ tour.steps.length }}</div>
<div>
<umb-button size="xs" button-style="link" type="button" action="endTour()" label="End tour"></umb-button>
<umb-button size="xs" ng-if="!currentStep.event" button-style="success" type="button" action="nextStep()" label="Next"></umb-button>
<div ng-if="!configuredView && !loadingStep">
<!-- Regular steps -->
<umb-tour-step ng-if="currentStepIndex < tour.steps.length">
<umb-tour-step-header
title="currentStep.title">
</umb-tour-step-header>
<umb-tour-step-content
content="currentStep.content">
</umb-tour-step-content>
<umb-tour-step-footer class="flex justify-between items-center">
<umb-tour-step-counter
current-step="currentStepIndex + 1"
total-steps="tour.steps.length">
</umb-tour-step-counter>
<div>
<umb-button size="xs" button-style="link" type="button" action="endTour()" label="End tour"></umb-button>
<umb-button size="xs" ng-if="!currentStep.event" button-style="success" type="button" action="nextStep()" label="Next"></umb-button>
</div>
</umb-tour-step-footer>
</umb-tour-step>
<!-- Outro step -->
<div ng-if="currentStepIndex === tour.steps.length && !loadingStep">
<div class="umb-tour__title">WOOOHOOO!</div>
<div class="umb-tour__content">Your completed the tour. That is amazing!</div>
<div class="umb-tour__button-container-center">
<umb-button type="button" button-style="success" size="xs" action="completeTour()" label="Complete"></umb-button>
</div>
</div>
</div>
<div ng-if="currentStepIndex === tour.steps.length && !loadingStep">
<div class="umb-tour__title">WOOOHOOO!</div>
<div class="umb-tour__content">Your completed the tour. That is amazing!</div>
<div class="umb-tour__button-container-center">
<umb-button type="button" button-style="success" size="xs" action="completeTour()" label="Complete"></umb-button>
</div>
</div>
<div ng-if="configuredView" ng-include="configuredView"></div>
<div ng-if="configuredView && !loadingStep" ng-include="configuredView"></div>
</div>

View File

@@ -0,0 +1,4 @@
<div class="umb-tour__content">
<div ng-bind-html="content"></div>
<div ng-transclude></div>
</div>

View File

@@ -0,0 +1 @@
<div class="umb-tour__step-counter">Step {{ currentStep }} of {{ totalSteps }}</div>

View File

@@ -0,0 +1 @@
<div ng-transclude></div>

View File

@@ -0,0 +1 @@
<div class="umb-tour__title">{{title}}</div>

View File

@@ -0,0 +1 @@
<div ng-transclude></div>