diff --git a/src/Umbraco.Core/Models/Membership/IUser.cs b/src/Umbraco.Core/Models/Membership/IUser.cs
index b9d9447343..cb177539be 100644
--- a/src/Umbraco.Core/Models/Membership/IUser.cs
+++ b/src/Umbraco.Core/Models/Membership/IUser.cs
@@ -69,6 +69,11 @@ namespace Umbraco.Core.Models.Membership
/// Thank you for choosing Umbraco - we think this could be the beginning of something beautiful. While it may feel overwhelming at first, we've done a lot to make the learning curve as smooth and fast as possible. In this quick tour we will introduce you to the main areas of Umbraco and show you how to best get started. This is where you can see details about your user, change your password and log out of Umbraco. In the User section you will be able to do more advaned user management. In the help drawer you will find articles and videos related to the section you are using. This is also where you will find the next tour on how to get started with Umbraco. Step 1 of any site is to create a Document Type. A Document Type is a data container where you can add data fields. The editor can then input data and Umbraco can use it to output it in the relevant parts of a template. In this tour you will learn how to set up a basic Document Type with a data field to enter a short text. Hover the document types tree and click the three small dots to open the context menu. Click Document Type to create a new document type with a template. We will use the template in a later tour when we need to render our content. Our document type needs a name. Enter A description helps to pick the right document type when creating content. Write a description to our Home page. It could be: Home in the field and click Next.",
- view: "doctypename"
- },
- {
- element: "[data-element='editor-description']",
- title: "Enter a description",
- content: "The home to our website
Content in the tab name.",
- view: "tabName"
- },
- {
- element: "[data-element='property-add']",
- title: "Add a property",
- content: "Properties are the different types of data on our content page.
On our Home page we wan't to add a welcome text.
Click Add property to open the property dialog.
", - event: "click" - }, - { - element: "[data-element~='overlay-property-settings'] [data-element='property-name']", - title: "Enter a name", - content: "EnterWelcome Text as name for the property.",
- view: "propertyname"
- },
- {
- element: "[data-element~='overlay-property-settings'] [data-element='property-description']",
- title: "Enter a description",
- content: "A description will help to fill in the right content.
Enter a description for the property editor. It could be:
Write a nice introduction text so the visitors feel welcome" - }, - { - element: "[data-element~='overlay-property-settings'] [data-element='editor-add']", - title: "Add editor", - content: "The editor defines what data type the property is. Click Add editor to open the editor picker dialog.", - event: "click" - }, - { - element: "[data-element~='overlay-editor-picker']", - elementPreventClick: true, - title: "Editor picker", - content: "
In the editor picker dialog we can pick one of the many build in editor.
" - }, - { - element: "[data-element~='overlay-editor-picker'] [data-element='editor-Textarea']", - title: "Select editor", - content: "Select the Textarea editor which allows us to enter long texts.", - event: "click" - }, - { - element: "[data-element~='overlay-editor-settings']", - elementPreventClick: true, - title: "Editor settings", - content: "Each property editor can have individual settings. We don't want to change any of these now." - }, - { - element: "[data-element~='overlay-editor-settings'] [data-element='button-overlaySubmit']", - title: "Save editor", - content: "Click Submit to save the editor.", - event: "click" - }, - { - element: "[data-element~='overlay-property-settings'] [data-element='button-overlaySubmit']", - title: "Add property to document type", - content: "Click Submit to add the property to the document type.", - event: "click" - }, - { - element: "[data-element='button-save']", - title: "Save the document type", - content: "All we need now is to save the document type. Click Save to create and save your new document type.", - event: "click" - } - ] - }, - { - "name": "Create Content", - "alias": "umbIntroCreateContent", - "group": "Getting Started", - "steps": [ - { - title: "Creating your first content node", - content: "The Content section contains the content of the website. Content is displayed as nodes in the content tree.
In this tour we will learn how to create our Home page for our website.
", - type: "intro" - }, - { - element: "#applications [data-element='section-content']", - title: "Navigate to the content sections", - content: "In the Content section we will find the content of our website.", - event: "click", - backdropOpacity: 0.6 - }, - { - element: "[data-element='tree-root']", - title: "Open context menu", - content: "Open the context menu by hovering the root of the content section.
Now click the three small dots to the right.
", - event: "click", - eventElement: "[data-element='tree-root'] [data-element='tree-item-options']" - }, - { - element: "[data-element='action-create-home']", - title: "Create Home page", - content: "Click on Home to create a new page of type Home.
", - event: "click" - }, - { - element: "[data-element='editor-content'] [data-element='editor-name-field']", - title: "Give your new page a name", - content: "Our new page needs a name. Enter Home in the field and click Next.
Add content to the Welcome Text field
If you don't have any ideas here is a start:
I am learning Umbraco. High Five I Rock #H5IR." - }, - { - element: "[data-element='editor-content'] [data-element='button-saveAndPublish']", - title: "Save and publish", - content: "
Now click the Save and publish button to save and publish your changes.
", - event: "click" - } - ] - }, - { - "name": "Render in template", - "alias": "umbIntroRenderInTemplate", - "group": "Getting Started", - "steps": [ - { - title: "Render your content in a template", - content: "Templating in Umbraco builds on the concept of Razor Views from asp.net MVC. - This tour is a sneak peak on how to write templates in Umbraco.
In this tour we will learn how to render content from our Home document type so we can see the content added to our Home page.
", - type: "intro" - }, - { - element: "#applications [data-element='section-settings']", - title: "Navigate to the Settings section", - content: "In the Settings section you will find all the templates
It is of course also possible to edit all your code files in your favorite code editor.
", - event: "click", - backdropOpacity: 0.6 - }, - { - element: "#tree [data-element='tree-item-templates']", - title: "Expand the Templates node", - content: "To see all our templates click the small triangle to the left of the templates node.
", - event: "click", - 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']", - title: "Open Home template", - content: "Click the Home template to open and edit it.
", - eventElement: "#tree [data-element='tree-item-templates'] [data-element='tree-item-Home'] a.umb-tree-item__label", - event: "click" - }, - { - element: "[data-element='editor-templates'] [data-element='code-editor']", - title: "Edit template", - content: 'The template can be edited here or in your favorite code editor.
To render the field from the document type add the following to the template:
@Model.Content.GetPropertyValue("welcomeText")'
- },
- {
- element: "[data-element='editor-templates'] [data-element='button-save']",
- title: "Save the template",
- content: "Click the Save button and your template will be saved.",
- event: "click"
- }
- ]
- },
- {
- "name": "View Home page",
- "alias": "umbIntroViewHomePage",
- "group": "Getting Started",
- "steps": [
- {
- title: "View your Umbraco site",
- content: "Our three main components to a page is done: Document type, Template, and Content - it is now time to see the result.
In this tour we will learn how to see our published website.
", - type: "intro" - }, - { - element: "#applications [data-element='section-content']", - title: "Navigate to the content sections", - content: "In the Content section 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", - content: "Click the Home page to open it
", - event: "click", - eventElement: "#tree [data-element='tree-item-Home'] a.umb-tree-item__label" - }, - { - element: "[data-element='editor-content'] [data-element='tab-Generic properties']", - title: "Properties", - content: "Under the properties tab you will find the default information about a content item.
", - event: "click" - }, - { - element: "[data-element='editor-content'] [data-element='property-_umb_urls']", - title: "Open page", - content: "Click the Link to document to view your page.
Tip: Click the preview button in the bottom right corner to preview changes without publishing them.
", - event: "click", - eventElement: "[data-element='editor-content'] [data-element='property-_umb_urls'] a[target='_blank']" - } - ] - }, - { - "name": "The media library", - "alias": "umbIntroMediaSection", - "group": "Getting Started", - "steps": [ - { - title: "How to use the media library", - content: "A website would be boring without media content. In Umbraco you can manage all your images, documents, videos etc. in the Media section. Here you can upload and organise your media items and see details about each item.
In this tour we will learn how to upload and orginise your Media library in Umbraco. It will also show you how to view details about a specific media item.
", - type: "intro" - }, - { - element: "#applications [data-element='section-media']", - title: "Navigate to the media section", - content: "The media section is where you will manage all your media items.", - event: "click", - backdropOpacity: 0.6 - }, - { - element: "#tree [data-element='tree-root']", - title: "Create a new folder", - content: "Let's first create a folder for our images. Hover the media root and click the three small dots on the right side of the item.
", - event: "click", - eventElement: "#tree [data-element='tree-root'] [data-element='tree-item-options']" - }, - { - element: "#dialog [data-element='action-Folder']", - title: "Create a new folder", - content: "Select the Folder options to select the type folder.
", - event: "click" - }, - { - element: "[data-element='editor-media'] [data-element='editor-name-field']", - title: "Enter a name", - content: "Enter My folder in the field.
Click the Save button to create the new folder
", - event: "click" - }, - { - element: "[data-element='editor-media'] [data-element='dropzone']", - title: "Upload images", - content: "In the upload area you can upload your media items.
Click the Upload button and select a couple of images on your computer and upload them.
", - view: "uploadimages" - }, - { - element: "[data-element='editor-media'] [data-element='media-grid-item-0']", - title: "View media item details", - content: "Hover the media item and Click the purple bar to view details about the media item", - event: "click", - 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']", - title: "The uploaded image", - content: "Here you can see the image you have uploaded.
You can use the dot in the center of the image to set a focal point on the image.
" - }, - { - element: "[data-element='editor-media'] [data-element='property-umbracoBytes']", - title: "Image size", - content: "You will also find other details about the image, like the size.
You can add extra properties to an image by creating or editing the Media types
" - }, - { - element: "[data-element='editor-media'] [data-element='tab-Generic properties']", - title: "Properties", - content: "Like the content section you can also find default properties about the media item. You will find these under the properties tab.", - event: "click" - }, - { - element: "[data-element='editor-media'] [data-element='property-_umb_urls']", - title: "Link to media", - content: "The path to the media item..." - }, - { - element: "[data-element='editor-media'] [data-element='property-_umb_updatedate']", - title: "Last edited", - content: "...and information about when the media item has been created and edited." - } - ] - } - ]; + /** + * Method to return all of the tours as a new instance + */ + function getTours() { + var tours = [ + { + "name": "Introduction", + "alias": "umbIntroIntroduction", + "group": "Getting Started", + "allowDisable": true, + "steps": [ + { + title: "Welcome to Umbraco - The Friendly CMS", + content: "Thank you for choosing Umbraco - we think this could be the beginning of something beautiful. While it may feel overwhelming at first, we've done a lot to make the learning curve as smooth and fast as possible.
In this quick tour we will introduce you to the main areas of Umbraco and show you how to best get started.
", + type: "intro" + }, + { + element: "#applications", + elementPreventClick: true, + title: "Sections", + content: "These are the Sections and allows you to navigate the different areas of Umbraco.", + backdropOpacity: 0.6 + }, + + { + element: "#tree", + elementPreventClick: true, + title: "The Tree", + content: "This is the Tree 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", + content: "The search allows you to quickly find content across sections within Umbraco." + }, + { + element: "#applications [data-element='section-user']", + title: "User profile", + content: "Click on the user photo to open the user profile dialog.", + event: "click", + backdropOpacity: 0.6 + }, + { + element: "[data-element~='overlay-user']", + elementPreventClick: true, + title: "User profile", + content: "This is where you can see details about your user, change your password and log out of Umbraco.
In the User section you will be able to do more advaned user management.
" + }, + { + element: "[data-element~='overlay-user'] [data-element='button-overlayClose']", + title: "User profile", + content: "Let's close the user profile again", + event: "click" + }, + { + element: "#applications [data-element='section-help']", + title: "Help", + content: "If you ever find yourself in trouble click here to open the help drawer.", + event: "click", + backdropOpacity: 0.6 + }, + { + element: "[data-element='drawer']", + elementPreventClick: true, + title: "Help", + content: "In the help drawer you will find articles and videos related to the section you are using.
This is also where you will find the next tour on how to get started with Umbraco.
", + 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." + } + ] + }, + { + "name": "Create document type", + "alias": "umbIntroCreateDocType", + "group": "Getting Started", + "steps": [ + { + title: "Create your first Document Type", + content: "Step 1 of any site is to create a Document Type. A Document Type is a data container where you can add data fields. The editor can then input data and Umbraco can use it to output it in the relevant parts of a template.
In this tour you will learn how to set up a basic Document Type with a data field to enter a short text.
", + type: "intro" + }, + { + element: "#applications [data-element='section-settings']", + title: "Navigate to the settings sections", + content: "In the Settings section we will find the document types.", + event: "click", + backdropOpacity: 0.6 + }, + { + element: "#tree [data-element='tree-item-documentTypes']", + title: "Create document type", + content: "Hover the document types tree and click the three small dots to open the context menu.
", + event: "click", + eventElement: "#tree [data-element='tree-item-documentTypes'] [data-element='tree-item-options']" + }, + { + element: "#dialog [data-element='action-documentType']", + title: "Create document type", + content: "Click Document Type to create a new document type with a template.
We will use the template in a later tour when we need to render our content.
", + event: "click" + }, + { + element: "[data-element='editor-name-field']", + title: "Enter a name", + content: "Our document type needs a name. Enter Home in the field and click Next.",
+ view: "doctypename"
+ },
+ {
+ element: "[data-element='editor-description']",
+ title: "Enter a description",
+ content: "
A description helps to pick the right document type when creating content.
Write a description to our Home page. It could be:
The home to our website" + }, + { + element: "[data-element='group-add']", + title: "Add tab", + content: "Tabs help us organize the content on a content page. Click Add new tab to add a tab.", + event: "click" + }, + { + element: "[data-element='group-name-field']", + title: "Enter a name", + content: "Enter
Content in the tab name.",
+ view: "tabName"
+ },
+ {
+ element: "[data-element='property-add']",
+ title: "Add a property",
+ content: "Properties are the different types of data on our content page.
On our Home page we wan't to add a welcome text.
Click Add property to open the property dialog.
", + event: "click" + }, + { + element: "[data-element~='overlay-property-settings'] [data-element='property-name']", + title: "Enter a name", + content: "EnterWelcome Text as name for the property.",
+ view: "propertyname"
+ },
+ {
+ element: "[data-element~='overlay-property-settings'] [data-element='property-description']",
+ title: "Enter a description",
+ content: "A description will help to fill in the right content.
Enter a description for the property editor. It could be:
Write a nice introduction text so the visitors feel welcome" + }, + { + element: "[data-element~='overlay-property-settings'] [data-element='editor-add']", + title: "Add editor", + content: "The editor defines what data type the property is. Click Add editor to open the editor picker dialog.", + event: "click" + }, + { + element: "[data-element~='overlay-editor-picker']", + elementPreventClick: true, + title: "Editor picker", + content: "
In the editor picker dialog we can pick one of the many build in editor.
" + }, + { + element: "[data-element~='overlay-editor-picker'] [data-element='editor-Textarea']", + title: "Select editor", + content: "Select the Textarea editor which allows us to enter long texts.", + event: "click" + }, + { + element: "[data-element~='overlay-editor-settings']", + elementPreventClick: true, + title: "Editor settings", + content: "Each property editor can have individual settings. We don't want to change any of these now." + }, + { + element: "[data-element~='overlay-editor-settings'] [data-element='button-overlaySubmit']", + title: "Save editor", + content: "Click Submit to save the editor.", + event: "click" + }, + { + element: "[data-element~='overlay-property-settings'] [data-element='button-overlaySubmit']", + title: "Add property to document type", + content: "Click Submit to add the property to the document type.", + event: "click" + }, + { + element: "[data-element='button-save']", + title: "Save the document type", + content: "All we need now is to save the document type. Click Save to create and save your new document type.", + event: "click" + } + ] + }, + { + "name": "Create Content", + "alias": "umbIntroCreateContent", + "group": "Getting Started", + "steps": [ + { + title: "Creating your first content node", + content: "The Content section contains the content of the website. Content is displayed as nodes in the content tree.
In this tour we will learn how to create our Home page for our website.
", + type: "intro" + }, + { + element: "#applications [data-element='section-content']", + title: "Navigate to the content sections", + content: "In the Content section we will find the content of our website.", + event: "click", + backdropOpacity: 0.6 + }, + { + element: "[data-element='tree-root']", + title: "Open context menu", + content: "Open the context menu by hovering the root of the content section.
Now click the three small dots to the right.
", + event: "click", + eventElement: "[data-element='tree-root'] [data-element='tree-item-options']" + }, + { + element: "[data-element='action-create-home']", + title: "Create Home page", + content: "Click on Home to create a new page of type Home.
", + event: "click" + }, + { + element: "[data-element='editor-content'] [data-element='editor-name-field']", + title: "Give your new page a name", + content: "Our new page needs a name. Enter Home in the field and click Next.
Add content to the Welcome Text field
If you don't have any ideas here is a start:
I am learning Umbraco. High Five I Rock #H5IR." + }, + { + element: "[data-element='editor-content'] [data-element='button-saveAndPublish']", + title: "Save and publish", + content: "
Now click the Save and publish button to save and publish your changes.
", + event: "click" + } + ] + }, + { + "name": "Render in template", + "alias": "umbIntroRenderInTemplate", + "group": "Getting Started", + "steps": [ + { + title: "Render your content in a template", + content: "Templating in Umbraco builds on the concept of Razor Views from asp.net MVC. - This tour is a sneak peak on how to write templates in Umbraco.
In this tour we will learn how to render content from our Home document type so we can see the content added to our Home page.
", + type: "intro" + }, + { + element: "#applications [data-element='section-settings']", + title: "Navigate to the Settings section", + content: "In the Settings section you will find all the templates
It is of course also possible to edit all your code files in your favorite code editor.
", + event: "click", + backdropOpacity: 0.6 + }, + { + element: "#tree [data-element='tree-item-templates']", + title: "Expand the Templates node", + content: "To see all our templates click the small triangle to the left of the templates node.
", + event: "click", + 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']", + title: "Open Home template", + content: "Click the Home template to open and edit it.
", + eventElement: "#tree [data-element='tree-item-templates'] [data-element='tree-item-Home'] a.umb-tree-item__label", + event: "click" + }, + { + element: "[data-element='editor-templates'] [data-element='code-editor']", + title: "Edit template", + content: 'The template can be edited here or in your favorite code editor.
To render the field from the document type add the following to the template:
@Model.Content.GetPropertyValue("welcomeText")'
+ },
+ {
+ element: "[data-element='editor-templates'] [data-element='button-save']",
+ title: "Save the template",
+ content: "Click the Save button and your template will be saved.",
+ event: "click"
+ }
+ ]
+ },
+ {
+ "name": "View Home page",
+ "alias": "umbIntroViewHomePage",
+ "group": "Getting Started",
+ "steps": [
+ {
+ title: "View your Umbraco site",
+ content: "Our three main components to a page is done: Document type, Template, and Content - it is now time to see the result.
In this tour we will learn how to see our published website.
", + type: "intro" + }, + { + element: "#applications [data-element='section-content']", + title: "Navigate to the content sections", + content: "In the Content section 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", + content: "Click the Home page to open it
", + event: "click", + eventElement: "#tree [data-element='tree-item-Home'] a.umb-tree-item__label" + }, + { + element: "[data-element='editor-content'] [data-element='tab-Generic properties']", + title: "Properties", + content: "Under the properties tab you will find the default information about a content item.
", + event: "click" + }, + { + element: "[data-element='editor-content'] [data-element='property-_umb_urls']", + title: "Open page", + content: "Click the Link to document to view your page.
Tip: Click the preview button in the bottom right corner to preview changes without publishing them.
", + event: "click", + eventElement: "[data-element='editor-content'] [data-element='property-_umb_urls'] a[target='_blank']" + } + ] + }, + { + "name": "The media library", + "alias": "umbIntroMediaSection", + "group": "Getting Started", + "steps": [ + { + title: "How to use the media library", + content: "A website would be boring without media content. In Umbraco you can manage all your images, documents, videos etc. in the Media section. Here you can upload and organise your media items and see details about each item.
In this tour we will learn how to upload and orginise your Media library in Umbraco. It will also show you how to view details about a specific media item.
", + type: "intro" + }, + { + element: "#applications [data-element='section-media']", + title: "Navigate to the media section", + content: "The media section is where you will manage all your media items.", + event: "click", + backdropOpacity: 0.6 + }, + { + element: "#tree [data-element='tree-root']", + title: "Create a new folder", + content: "Let's first create a folder for our images. Hover the media root and click the three small dots on the right side of the item.
", + event: "click", + eventElement: "#tree [data-element='tree-root'] [data-element='tree-item-options']" + }, + { + element: "#dialog [data-element='action-Folder']", + title: "Create a new folder", + content: "Select the Folder options to select the type folder.
", + event: "click" + }, + { + element: "[data-element='editor-media'] [data-element='editor-name-field']", + title: "Enter a name", + content: "Enter My folder in the field.
Click the Save button to create the new folder
", + event: "click" + }, + { + element: "[data-element='editor-media'] [data-element='dropzone']", + title: "Upload images", + content: "In the upload area you can upload your media items.
Click the Upload button and select a couple of images on your computer and upload them.
", + view: "uploadimages" + }, + { + element: "[data-element='editor-media'] [data-element='media-grid-item-0']", + title: "View media item details", + content: "Hover the media item and Click the purple bar to view details about the media item", + event: "click", + 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']", + title: "The uploaded image", + content: "Here you can see the image you have uploaded.
You can use the dot in the center of the image to set a focal point on the image.
" + }, + { + element: "[data-element='editor-media'] [data-element='property-umbracoBytes']", + title: "Image size", + content: "You will also find other details about the image, like the size.
You can add extra properties to an image by creating or editing the Media types
" + }, + { + element: "[data-element='editor-media'] [data-element='tab-Generic properties']", + title: "Properties", + content: "Like the content section you can also find default properties about the media item. You will find these under the properties tab.", + event: "click" + }, + { + element: "[data-element='editor-media'] [data-element='property-_umb_urls']", + title: "Link to media", + content: "The path to the media item..." + }, + { + element: "[data-element='editor-media'] [data-element='property-_umb_updatedate']", + title: "Last edited", + content: "...and information about when the media item has been created and edited." + } + ] + } + ]; + return tours; + } function startTour(tour) { eventsService.emit("appState.tour.start", tour); @@ -425,74 +430,140 @@ currentTour = null; } + /** + * Disables a tour for the user, raises an event and returns a promise + * @param {any} tour + */ function disableTour(tour) { + var deferred = $q.defer(); tour.disabled = true; - saveInLocalStorage(tour); - eventsService.emit("appState.tour.end", tour); - currentTour = null; + currentUserResource + .saveTourStatus({ alias: tour.alias, disabled: tour.disabled, completed: tour.completed }).then( + function() { + eventsService.emit("appState.tour.end", tour); + currentTour = null; + deferred.resolve(tour); + }); + return deferred.promise; } + /** + * Completes a tour for the user, raises an event and returns a promise + * @param {any} tour + */ function completeTour(tour) { + var deferred = $q.defer(); tour.completed = true; - saveInLocalStorage(tour); - eventsService.emit("appState.tour.complete", tour); - currentTour = null; + currentUserResource + .saveTourStatus({ alias: tour.alias, disabled: tour.disabled, completed: tour.completed }).then( + function() { + eventsService.emit("appState.tour.complete", tour); + currentTour = null; + deferred.resolve(tour); + }); + return deferred.promise; } + /** + * Returns the current tour + */ function getCurrentTour() { + //TODO: This should be reset if a new user logs in return currentTour; } - + + /** + * Returns a promise of all tours with the current user statuses + */ function getAllTours() { - setCompletedTours(); - return tours; + var tours = getTours(); + return setTourStatuses(tours); } + /** + * Returns a promise of grouped tours with the current user statuses + */ function getGroupedTours() { - setCompletedTours(); - var groupedTours = _.groupBy(tours, "group"); - return groupedTours; + var deferred = $q.defer(); + var tours = getTours(); + setTourStatuses(tours).then(function() { + var groupedTours = _.groupBy(tours, "group"); + deferred.resolve(groupedTours); + }); + return deferred.promise; } + /** + * Returns a promise of the tour found by alias with the current user statuses + * @param {any} tourAlias + */ function getTourByAlias(tourAlias) { - var tour = _.findWhere(tours, {alias: tourAlias}); - return tour; + var deferred = $q.defer(); + var tours = getTours(); + setTourStatuses(tours).then(function () { + var tour = _.findWhere(tours, { alias: tourAlias }); + deferred.resolve(tour); + }); + return deferred.promise; } + /** + * Returns a promise of completed tours for the user + */ function getCompletedTours() { - var storedTours = localStorageService.get(localStorageKey); - var completedTours = _.where(storedTours, {completed: true}); - var aliases = _.pluck(completedTours, "alias"); - return aliases; + var deferred = $q.defer(); + currentUserResource.getTours().then(function (storedTours) { + var completedTours = _.where(storedTours, { completed: true }); + var aliases = _.pluck(completedTours, "alias"); + deferred.resolve(aliases); + }); + return deferred.promise; } + /** + * Returns a promise of disabled tours for the user + */ function getDisabledTours() { - var storedTours = localStorageService.get(localStorageKey); - var disabledTours = _.where(storedTours, {disabled: true}); - var aliases = _.pluck(disabledTours, "alias"); - return aliases; + var deferred = $q.defer(); + currentUserResource.getTours().then(function (storedTours) { + var disabledTours = _.where(storedTours, { disabled: true }); + var aliases = _.pluck(disabledTours, "alias"); + deferred.resolve(aliases); + }); + return deferred.promise; } /////////// - function setCompletedTours() { + /** + * Based on the tours given, this will set each of the tour statuses (disabled/completed) based on what is stored against the current user + * @param {any} tours + */ + function setTourStatuses(tours) { - var storedTours = []; + var deferred = $q.defer(); + currentUserResource.getTours().then(function (storedTours) { - if (localStorageService.get(localStorageKey)) { - storedTours = localStorageService.get(localStorageKey); - } + angular.forEach(storedTours, function (storedTour) { + if (storedTour.completed === true) { + angular.forEach(tours, function (tour) { + if (storedTour.alias === tour.alias) { + tour.completed = true; + } + }); + } + if (storedTour.disabled === true) { + angular.forEach(tours, function (tour) { + if (storedTour.alias === tour.alias) { + tour.disabled = true; + } + }); + } + }); - angular.forEach(storedTours, function (storedTour) { - if (storedTour.completed === true) { - angular.forEach(tours, function (tour) { - if (storedTour.alias === tour.alias) { - tour.completed = true; - } - }); - } + deferred.resolve(tours); }); - + return deferred.promise; } function saveInLocalStorage(tour) { @@ -535,10 +606,13 @@ disableTour: disableTour, completeTour: completeTour, getCurrentTour: getCurrentTour, + //TODO: Not used getAllTours: getAllTours, getGroupedTours: getGroupedTours, getTourByAlias: getTourByAlias, + //TODO: Not used getCompletedTours: getCompletedTours, + //TODO: Not used getDisabledTours: getDisabledTours, }; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js index b4773cdaad..286100f830 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js @@ -26,7 +26,9 @@ function oninit() { - vm.tours = tourService.getGroupedTours(); + tourService.getGroupedTours().then(function(groupedTours) { + vm.tours = groupedTours; + }); // load custom help dashboard dashboardResource.getDashboard("user-help").then(function (dashboard) { @@ -156,9 +158,11 @@ } evts.push(eventsService.on("appState.tour.complete", function (event, tour) { - vm.tours = tourService.getGroupedTours(); - openTourGroup(tour.alias); - getTourGroupCompletedPercentage(); + tourService.getGroupedTours().then(function(groupedTours) { + vm.tours = groupedTours; + openTourGroup(tour.alias); + getTourGroupCompletedPercentage(); + }); })); $scope.$on('$destroy', function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js index 67a69fef2c..f187ec15cf 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js @@ -30,20 +30,17 @@ function startUpDynamicContentController($timeout, dashboardResource, assetsServ function onInit() { // load tours - vm.tours = tourService.getGroupedTours(); + tourService.getGroupedTours().then(function(groupedTours) { + vm.tours = groupedTours; + }); - // get list of completed tours and disabled tours - var completedTours = tourService.getCompletedTours(); - var disabledTours = tourService.getDisabledTours(); - // get intro tour - var introTour = tourService.getTourByAlias("umbIntroIntroduction"); - - // start intro tour if it hasn't been completed or disabled - if(completedTours.indexOf(introTour.alias) === -1 && disabledTours.indexOf(introTour.alias) === -1) { - tourService.startTour(introTour); - } - + tourService.getTourByAlias("umbIntroIntroduction").then(function (introTour) { + // start intro tour if it hasn't been completed or disabled + if (introTour.disabled !== true && introTour.completed !== true) { + tourService.startTour(introTour); + } + }); } function startTour(tour) { diff --git a/src/Umbraco.Web/Editors/CurrentUserController.cs b/src/Umbraco.Web/Editors/CurrentUserController.cs index 3d8ec01937..8a348fd23e 100644 --- a/src/Umbraco.Web/Editors/CurrentUserController.cs +++ b/src/Umbraco.Web/Editors/CurrentUserController.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections; +using System.Collections.Generic; using System.Net; using System.Text; using System.Threading.Tasks; @@ -17,6 +19,9 @@ using umbraco; using legacyUser = umbraco.BusinessLogic.User; using System.Net.Http; using System.Collections.Specialized; +using System.Linq; +using Newtonsoft.Json; +using Umbraco.Core; using Umbraco.Core.Security; using Umbraco.Web.WebApi.Filters; using Constants = Umbraco.Core.Constants; @@ -30,6 +35,48 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class CurrentUserController : UmbracoAuthorizedJsonController { + ///