Merge pull request #2267 from umbraco/temp-U4-10550

U4-10550 Finalise tour layout in the drawer
This commit is contained in:
Mads Rasmussen
2017-10-26 21:28:01 +02:00
committed by GitHub
15 changed files with 420 additions and 45 deletions

View File

@@ -0,0 +1,88 @@
/**
@ngdoc directive
@name umbraco.directives.directive:umbProgressCircle
@restrict E
@scope
@description
Use this directive to render a circular progressbar.
<h3>Markup example</h3>
<pre>
<div>
<umb-progress-circle
percentage="80"
size="60"
color="secondary">
</umb-progress-circle>
</div>
</pre>
@param {string} size (<code>attribute</code>): This parameter defines the width and the height of the circle in pixels.
@param {string} percentage (<code>attribute</code>): Takes a number between 0 and 100 and applies it to the circle's highlight length.
@param {string} color (<code>attribute</code>): the color of the highlight (primary, secondary, success, warning, danger). Success by default.
**/
(function (){
'use strict';
function ProgressCircleDirective($http, $timeout) {
function link(scope, element, $filter) {
function onInit() {
// making sure we get the right numbers
var percent = scope.percentage;
if (percent > 100) {
percent = 100;
}
else if (percent < 0) {
percent = 0;
}
// calculating the circle's highlight
var circle = element.find(".umb-progress-circle__highlight");
var r = circle.attr('r');
var strokeDashArray = (r*Math.PI)*2;
// Full circle length
scope.strokeDashArray = strokeDashArray;
var strokeDashOffsetDifference = (percent/100)*strokeDashArray;
var strokeDashOffset = strokeDashArray - strokeDashOffsetDifference;
// Distance for the highlight dash's offset
scope.strokeDashOffset = strokeDashOffset;
// set font size
scope.percentageSize = (scope.size * 0.3) + "px";
}
onInit();
}
var directive = {
restrict: 'E',
replace: true,
templateUrl: 'views/components/umb-progress-circle.html',
scope: {
size: "@?",
percentage: "@",
color: "@"
},
link: link
};
return directive;
}
angular.module('umbraco.directives').directive('umbProgressCircle', ProgressCircleDirective);
})();

View File

@@ -4,6 +4,7 @@
function tourService(eventsService, localStorageService) {
var localStorageKey = "umbTours";
var currentTour = null;
var tours = [
{
@@ -23,12 +24,19 @@
content: "These are the <b>Sections</b> and allows you to navigate the different areas of Umbraco.",
backdropOpacity: 0.6
},
{
element: "#tree",
elementPreventClick: true,
title: "The Tree",
content: "This is the <b>Tree</b> and will contain all the content of your website."
},
{
element: "[data-element='editor-content']",
elementPreventClick: true,
title: "Dashboards",
content: "A dashboard is the main view you are presented with when entering a section within the backoffice, and can be used to show valuable information to the users of the system."
},
{
element: "[data-element='global-search-field']",
title: "Search",
@@ -66,6 +74,11 @@
title: "Help",
content: "<p>In the help drawer you will find articles and videos related to the section you are using.</p><p>This is also where you will find the next tour on how to get started with Umbraco.</p>",
backdropOpacity: 0.6
},
{
element: "[data-element='drawer'] [data-element='help-tours']",
title: "Tours",
content: "To continue your journey on getting started with Umbraco, you can find more tours right here."
}
]
},
@@ -117,9 +130,10 @@
event: "click"
},
{
element: "[data-element='group-name']",
element: "[data-element='group-name-field']",
title: "Enter a name",
content: "Enter <code>Content</code> in the tab name."
content: "Enter <code>Content</code> in the tab name.",
view: "tabName"
},
{
element: "[data-element='property-add']",
@@ -192,6 +206,13 @@
content: "<p>The <b>Content section</b> contains the content of the website. Content is displayed as <b>nodes</b> in the content tree.</p><p>In this tour we will learn how to create our <b>Home</b> page for our website.</p>",
type: "intro"
},
{
element: "#applications [data-element='section-content']",
title: "Navigate to the content sections",
content: "In the <b>Content section</b> we will find the content of our website.",
event: "click",
backdropOpacity: 0.6
},
{
element: "[data-element='tree-root']",
title: "Open context menu",
@@ -279,6 +300,13 @@
content: "<p>Our three main components to a page is done: <b>Document type, Template, and Content</b> - it is now time to see the result.</p><p>In this tour we will learn how to see our published website.</p>",
type: "intro"
},
{
element: "#applications [data-element='section-content']",
title: "Navigate to the content sections",
content: "In the <b>Content section</b> we will find the content of our website.",
event: "click",
backdropOpacity: 0.6
},
{
element: "#tree [data-element='tree-item-Home']",
title: "Open the Home page",
@@ -387,15 +415,23 @@
function startTour(tour) {
eventsService.emit("appState.tour.start", tour);
currentTour = tour;
}
function endTour() {
currentTour = null;
eventsService.emit("appState.tour.end");
currentTour = null;
}
function completeTour(tour) {
saveInLocalStorage(tour);
eventsService.emit("appState.tour.complete", tour);
currentTour = null;
}
function getCurrentTour() {
return currentTour;
}
function getAllTours() {
@@ -475,6 +511,7 @@
startTour: startTour,
endTour: endTour,
completeTour: completeTour,
getCurrentTour: getCurrentTour,
getAllTours: getAllTours,
getGroupedTours: getGroupedTours,
getTourByAlias: getTourByAlias,

View File

@@ -129,6 +129,8 @@
@import "components/umb-checkmark.less";
@import "components/umb-list.less";
@import "components/umb-box.less";
@import "components/umb-number-badge.less";
@import "components/umb-progress-circle.less";
@import "components/buttons/umb-button.less";
@import "components/buttons/umb-button-group.less";
@@ -170,4 +172,4 @@
@import "typeahead.less";
@import "hacks.less";
@import "healthcheck.less";
@import "healthcheck.less";

View File

@@ -149,7 +149,8 @@
border-bottom: 1px solid @gray-9;
}
.umb-help-list-item > a {
.umb-help-list-item > a,
.umb-help-list-item__content {
display: flex;
align-items: center;
padding: 10px 20px;
@@ -186,4 +187,8 @@
font-size: 14px;
color: @gray-6;
margin-left: auto;
}
.umb-help-list-item:hover .umb-help-list-item__group-title {
text-decoration: underline;
}

View File

@@ -99,6 +99,11 @@
}
/* Sizes */
.umb-button--xxs {
padding: 2px 10px;
font-size: 13px;
}
.umb-button--xs {
padding: 5px 16px;
font-size: 14px;

View File

@@ -0,0 +1,40 @@
.umb-number-badge {
border: 1px solid @gray-6;
width: 25px;
height: 25px;
border-radius: 50%;
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
color: @black;
font-size: 15px;
}
.umb-number-badge--xs {
width: 20px;
height: 20px;
font-size: 13px;
}
.umb-number-badge--s {
width: 25px;
height: 25px;
}
.umb-number-badge--m {
width: 30px;
height: 30px;
}
.umb-number-badge--l {
width: 40px;
height: 40px;
font-size: 18px;
}
.umb-number-badge--xl {
width: 50px;
height: 50px;
font-size: 20px;
}

View File

@@ -0,0 +1,49 @@
.umb-progress-circle {
position: relative;
}
.umb-progress-circle__view-box {
position: absolute;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
transform: rotate(-90deg);
}
// circle highlight on progressbar
.umb-progress-circle__highlight {
stroke: @green;
}
.umb-progress-circle__highlight--primary {
stroke: @turquoise;
}
.umb-progress-circle__highlight--secondary {
stroke: @purple;
}
.umb-progress-circle__highlight--success {
stroke: @green;
}
.umb-progress-circle__highlight--warning {
stroke: @yellow;
}
.umb-progress-circle__highlight--danger {
stroke: @red;
}
// circle progressbar bg
.umb-progress-circle__bg {
stroke: @gray-8;
}
// the text in the center
.umb-progress-circle__percentage {
font-size: 16px;
font-weight: bold;
text-align: center;
}

View File

@@ -1,7 +1,7 @@
(function () {
"use strict";
function HelpDrawerController($scope, $routeParams, $timeout, dashboardResource, localizationService, userService, eventsService, helpService, appState) {
function HelpDrawerController($scope, $routeParams, $timeout, dashboardResource, localizationService, userService, eventsService, helpService, appState, tourService, $filter) {
var vm = this;
var evts = [];
@@ -12,11 +12,22 @@
vm.tree = $routeParams.tree;
vm.sectionName = "";
vm.customDashboard = null;
vm.tours = [];
vm.closeDrawer = closeDrawer;
vm.startTour = startTour;
vm.getTourGroupCompletedPercentage = getTourGroupCompletedPercentage;
vm.showTourButton = showTourButton;
function startTour(tour) {
tourService.startTour(tour);
closeDrawer();
}
function oninit() {
vm.tours = tourService.getGroupedTours();
// load custom help dashboard
dashboardResource.getDashboard("user-help").then(function (dashboard) {
vm.customDashboard = dashboard;
@@ -41,6 +52,15 @@
});
getTourGroupCompletedPercentage();
// check if a tour is running - if it is open the matching group
var currentTour = tourService.getCurrentTour();
if (currentTour) {
openTourGroup(currentTour.alias);
}
}
function closeDrawer() {
@@ -101,7 +121,45 @@
});
}
oninit();
function showTourButton(index, tourGroup) {
if(index !== 0) {
var prevTour = tourGroup[index - 1];
if(prevTour.completed) {
return true;
}
} else {
return true;
}
}
function openTourGroup(tourAlias) {
angular.forEach(vm.tours, function (group) {
angular.forEach(group, function (tour) {
if (tour.alias === tourAlias) {
group.open = true;
}
});
});
}
function getTourGroupCompletedPercentage() {
// Finding out, how many tours are completed for the progress circle
angular.forEach(vm.tours, function(group){
var completedTours = 0;
angular.forEach(group, function(tour){
if(tour.completed) {
completedTours++;
}
});
group.completedPercentage = Math.round((completedTours/group.length)*100);
});
}
evts.push(eventsService.on("appState.tour.complete", function (event, tour) {
vm.tours = tourService.getGroupedTours();
openTourGroup(tour.alias);
getTourGroupCompletedPercentage();
}));
$scope.$on('$destroy', function () {
for (var e in evts) {
@@ -109,6 +167,8 @@
}
});
oninit();
}
angular.module("umbraco").controller("Umbraco.Drawers.Help", HelpDrawerController);

View File

@@ -4,11 +4,49 @@
title="{{ vm.title }}"
description="{{ vm.subtitle }}">
</umb-drawer-header>
<umb-drawer-content>
<!-- Tours -->
<div data-element="help-tours" style="margin-bottom: 20px;">
<h5 style="margin-bottom: 10px; margin-top: 0;">Tours</h5>
<div ng-repeat="(key,value) in vm.tours" style="margin-bottom: 5px;">
<div class="umb-help-list">
<a href="" class="umb-help-list-item umb-help-list-item__content flex items-center justify-between" style="text-decoration: none;" ng-click="value.open = !value.open">
<h5 class="umb-help-list-item__group-title"><i style="margin-right: 2px;text-decoration: none;" ng-class="{'icon-navigation-right': !value.open, 'icon-navigation-down': value.open}"></i>{{key}}</h5>
<umb-progress-circle
percentage="{{value.completedPercentage}}"
size="40">
</umb-progress-circle>
</a>
<div ng-if="value.open">
<div data-element="tour-{{tour.alias}}" class="umb-help-list-item" ng-repeat="tour in value">
<div class="umb-help-list-item__content justify-between">
<div class="flex items-center">
<div ng-if="!tour.completed" class="umb-number-badge umb-number-badge--xs umb-help-list-item__icon">{{ $index + 1 }}</div>
<umb-checkmark ng-if="tour.completed" size="xs" checked="tour.completed" class="umb-help-list-item__icon"></umb-checkmark>
<span ng-class="{'strike': tour.completed}" class="umb-help-list-item__title">{{ tour.name }}</span>
</div>
<div>
<umb-button ng-if="!tour.completed && vm.showTourButton($index, value)" button-style="primary" size="xxs" type="button" label="Start" action="vm.startTour(tour)"></umb-button>
<umb-button ng-if="tour.completed" size="xxs" type="button" label="Rerun" action="vm.startTour(tour)"></umb-button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Show in custom help dashboard -->
<div style="margin-bottom: 20px;" ng-if="vm.customDashboard.length > 0">
<div data-element="help-custom-dashboard" style="margin-bottom: 20px;" ng-if="vm.customDashboard.length > 0">
<div ng-repeat="tab in vm.customDashboard">
<div ng-repeat="property in tab.properties">
<div>
@@ -20,11 +58,11 @@
</div>
<!-- Help Content -->
<div style="margin-bottom: 20px;" ng-if="vm.topics.length > 0">
<div data-element="help-articles" style="margin-bottom: 20px;" ng-if="vm.topics.length > 0">
<h5 style="margin-bottom: 10px; margin-top: 0;">Articles</h5>
<ul class="umb-help-list">
<li class="umb-help-list-item" ng-repeat="topic in vm.topics track by $index">
<a target="_blank" ng-href="{{topic.url}}?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=tv">
<a data-element="help-article-{{topic.name}}" target="_blank" ng-href="{{topic.url}}?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=tv">
<span>
<span class="umb-help-list-item__title">
<span class="bold">{{topic.name}}</span>
@@ -38,11 +76,11 @@
</div>
<!-- Umbraco tv content -->
<div>
<div data-element="help-videos" style="margin-bottom: 20px;">
<h5 style="margin-bottom: 10px; margin-top: 0;" ng-if="vm.videos.length > 0">Videos</h5>
<ul class="umb-help-list">
<li class="umb-help-list-item" ng-repeat="video in vm.videos track by $index">
<a target="_blank" ng-href="{{video.link}}?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=tv">
<a data-element="help-article-{{video.title}}" target="_blank" ng-href="{{video.link}}?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=tv">
<i class="umb-help-list-item__icon icon-tv-old"></i>
<span class="umb-help-list-item__title">{{video.title}}</span>
<i class="umb-help-list-item__open-icon icon-out"></i>
@@ -51,28 +89,32 @@
</ul>
</div>
<!-- Links -->
<div data-element="help-links">
<a data-element="help-link-umbraco-tv" class="umb-help-badge" style="margin-bottom: 5px;" target="_blank" href="http://umbraco.tv?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=tv">
<i class="umb-help-badge__icon icon-tv-old"></i>
<div class="umb-help-badge__title">Visit umbraco.tv</div>
<small>
<localize key="help_theBestUmbracoVideoTutorials">The best Umbraco video tutorials</localize>
</small>
</a>
<a data-element="help-link-our-umbraco" class="umb-help-badge" style="margin-bottom: 5px;" target="_blank" href="http://our.umbraco.org?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=our">
<i class="umb-help-badge__icon icon-favorite"></i>
<div class="umb-help-badge__title">Visit our.umbraco.org</div>
<small>
<localize key="defaultdialogs_theFriendliestCommunity">The friendliest community</localize>
</small>
</a>
</div>
</umb-drawer-content>
<umb-drawer-footer>
<a class="umb-help-badge" style="margin-bottom: 5px;" target="_blank" href="http://umbraco.tv?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=tv">
<i class="umb-help-badge__icon icon-tv-old"></i>
<div class="umb-help-badge__title">Visit umbraco.tv</div>
<small>
<localize key="help_theBestUmbracoVideoTutorials">The best Umbraco video tutorials</localize>
</small>
</a>
<a class="umb-help-badge" style="margin-bottom: 5px;" target="_blank" href="http://our.umbraco.org?utm_source=core&utm_medium=help&utm_content=link&utm_campaign=our">
<i class="umb-help-badge__icon icon-favorite"></i>
<div class="umb-help-badge__title">Visit our.umbraco.org</div>
<small>
<localize key="defaultdialogs_theFriendliestCommunity">The friendliest community</localize>
</small>
</a>
<div class="flex justify-end">
<umb-button
alias="close"
type="button"
button-style="link"
label="Close"

View File

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

View File

@@ -0,0 +1,30 @@
<div ng-controller="Umbraco.Tours.UmbIntroCreateDocType.TabNameController as vm">
<umb-tour-step>
<umb-tour-step-header
title="model.currentStep.title">
</umb-tour-step-header>
<umb-tour-step-content
content="model.currentStep.content">
<div ng-if="vm.error" class="color-red" style="margin-top: 5px;">Please enter <b>Content</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="model.currentStepIndex + 1"
total-steps="model.steps.length">
</umb-tour-step-counter>
<div>
<umb-button size="xs" button-style="link" type="button" action="model.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>
</div>

View File

@@ -1,4 +1,4 @@
<div class="umb-editor-container umb-panel-body umb-scrollable row-fluid" ng-class="{'-stop-scrolling': numberOfOverlays > 0}">
<div data-element="editor-content" class="umb-editor-container umb-panel-body umb-scrollable row-fluid" ng-class="{'-stop-scrolling': numberOfOverlays > 0}">
<umb-overlay-backdrop></umb-overlay-backdrop>
<div class="umb-pane">
<div ng-transclude></div>

View File

@@ -66,7 +66,8 @@
<ng-form name="groupNameForm" data-element="group-name">
<div class="umb-group-builder__group-title control-group -no-margin" ng-class="{'-active':tab.tabState=='active', '-inherited': tab.inherited}">
<i class="umb-group-builder__group-title-icon icon-navigation" ng-if="sortingMode && !tab.inherited"></i>
<input class="umb-group-builder__group-title-input"
<input data-element="group-name-field"
class="umb-group-builder__group-title-input"
type="text"
localize="placeholder"
placeholder="@placeholders_entername"

View File

@@ -0,0 +1,7 @@
<div class="umb-progress-circle" ng-style="{'width': size, 'height': size, 'line-height': size + 'px' }">
<svg class="umb-progress-circle__view-box" viewBox="0 0 100 100">
<circle class="umb-progress-circle__bg" cx="50" cy="50" r="47" fill="none" stroke-width="6"/>
<circle class="umb-progress-circle__highlight umb-progress-circle__highlight--{{ color }}" cx="50" cy="50" r="47" fill="none" stroke-width="6" stroke-dasharray="{{ strokeDashArray }}" stroke-dashoffset="{{ strokeDashOffset }}" />
</svg>
<div ng-style="{'font-size': percentageSize}" class="umb-progress-circle__percentage">{{ percentage }}%</div>
</div>

View File

@@ -1,21 +1,6 @@
<div class="umb-dashboard-grid" ng-controller="Umbraco.Dashboard.StartUpDynamicContentController as vm">
<umb-load-indicator ng-if="vm.loading"></umb-load-indicator>
<!-- Tours -->
<div>
<div ng-repeat="(key,value) in vm.tours">
<h5>
<span ng-if="key !== 'undefined'">{{key}}</span>
<span ng-if="key === 'undefined'">Other</span>
</h5>
<div ng-repeat="tour in value">
{{ tour.name }}
<div ng-if="tour.completed">Completed</div>
<button ng-click="vm.startTour(tour)">Start</button>
</div>
</div>
</div>
<div class="row clearfix" ng-if="vm.dashboard">
<!-- Sections -->