Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 927b8ac6d4 | |||
| 2a60dad15e |
+1
-2
@@ -13,5 +13,4 @@ indent_size = 4
|
||||
|
||||
# Trim trailing whitespace, limited support.
|
||||
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
|
||||
trim_trailing_whitespace = true
|
||||
csharp_prefer_braces = false : none
|
||||
trim_trailing_whitespace = true
|
||||
@@ -17,7 +17,7 @@ Assume positive intent and try to understand before being understood.
|
||||
|
||||
Treat others as you would like to be treated.
|
||||
|
||||
This also goes for treating the HQ with respect. For example: don’t promote products on [our.umbraco.com](https://our.umbraco.com) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco.
|
||||
This also goes for treating the HQ with respect. For example: don’t promote products on [our.umbraco.org](https://our.umbraco.org) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco.
|
||||
|
||||
## Open
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
_Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-CMS/blob/temp8/.github/V8_GETTING_STARTED.md) to go to the v8 branch_
|
||||
_Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-CMS/blob/temp8/docs/CONTRIBUTING.md) to go to the v8 branch_
|
||||
# Contributing to Umbraco CMS
|
||||
|
||||
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
|
||||
@@ -16,9 +16,9 @@ This document gives you a quick overview on how to get started, we will link to
|
||||
|
||||
## Guidelines for contributions we welcome
|
||||
|
||||
Not all changes are wanted, so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valueable time.
|
||||
Not all changes are wanted so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valueable time.
|
||||
|
||||
We have [documented what we consider small and large changes](CONTRIBUTION_GUIDELINES.md). Make sure to talk to us before making large changes.
|
||||
We have [documented what we consider small and large changes](CONTRIBUTION_GUIDELINES.md), make sure to talk to us before making large changes.
|
||||
|
||||
Remember, if an issue is in the `Up for grabs` list or you've asked for some feedback before you sent us a PR, your PR will not be closed as unwanted.
|
||||
|
||||
@@ -36,7 +36,7 @@ Great question! The short version goes like this:
|
||||
|
||||
* **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](BUILD.md)
|
||||
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will [happily give feedback](#questions)
|
||||
* **Commit** - done? Yay! 🎉 It is recommended to create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `12345`
|
||||
* **Commit** - done? Yay! 🎉 It is recommended to create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-U4-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `U4-12345`
|
||||
* **Push** - great, now you can push the changes up to your fork on GitHub
|
||||
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
|
||||
|
||||
@@ -72,6 +72,7 @@ The pull request team consists of a member of Umbraco HQ, [Sebastiaan](https://g
|
||||
- [Anders Bjerner](https://github.com/abjerner)
|
||||
- [Dave Woestenborghs](https://github.com/dawoe)
|
||||
- [Emma Burstow](https://github.com/emmaburstow)
|
||||
- [Kyle Weems](https://github.com/cssquirrel)
|
||||
- [Poornima Nayar](https://github.com/poornimanayar)
|
||||
|
||||
These wonderful volunteers will provide you with a first reply to your PR, review and test out your changes and might ask more questions. After that they'll let Umbraco HQ know if everything seems okay.
|
||||
@@ -81,7 +82,8 @@ These wonderful volunteers will provide you with a first reply to your PR, revie
|
||||
You can get in touch with [the PR team](#the-pr-team) in multiple ways, we love open conversations and we are a friendly bunch. No question you have is stupid. Any questions you have usually helps out multiple people with the same question. Ask away:
|
||||
|
||||
- If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward
|
||||
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.com/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
|
||||
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
|
||||
- We're also [active in the Gitter chatroom](https://gitter.im/umbraco/Umbraco-CMS)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
|
||||
@@ -19,19 +19,19 @@ When contributing code to Umbraco there's plenty of things you'll want to know,
|
||||
* [What branch should I target for my contributions?](#what-branch-should-i-target-for-my-contributions)
|
||||
* [Building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
|
||||
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
### Reporting Bugs
|
||||
This section guides you through submitting a bug report for Umbraco CMS. Following these guidelines helps maintainers and the community understand your report 📝, reproduce the behavior 💻 💻, and find related reports 🔎.
|
||||
|
||||
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](https://github.com/umbraco/Umbraco-CMS/issues/new/choose), the information it asks for helps us resolve issues faster.
|
||||
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](http://issues.umbraco.org/issues#newissue=61-30118), the information it asks for helps us resolve issues faster.
|
||||
|
||||
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
|
||||
|
||||
##### Before Submitting A Bug Report
|
||||
|
||||
* Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.com/download/). We might have already fixed your particular problem.
|
||||
* Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.org/download/). We might have already fixed your particular problem.
|
||||
* It also helps tremendously to check if the issue you're experiencing is present in **a clean install** of the Umbraco version you're currently using. Custom code can have side-effects that don't occur in a clean install.
|
||||
* **Use the Google**. Whatever you're experiencing, Google it plus "Umbraco" - usually you can get some pretty good hints from the search results, including open issues and further troubleshooting hints.
|
||||
* If you do find and existing issue has **and the issue is still open**, add a comment to the existing issue if you have additional information. If you have the same problem and no new info to add, just "star" the issue.
|
||||
@@ -52,7 +52,7 @@ Provide more context by answering these questions:
|
||||
|
||||
Include details about your configuration and environment:
|
||||
|
||||
* **Which version of Umbraco are you using?**
|
||||
* **Which version of Umbraco are you using?**
|
||||
* **What is the environment you're using Umbraco in?** Is this a problem on your local machine or on a server. Tell us about your configuration: Windows version, IIS/IISExpress, database type, etc.
|
||||
* **Which packages do you have installed?**
|
||||
|
||||
@@ -65,11 +65,13 @@ Most of the suggestions in the [reporting bugs](#reporting-bugs) section also co
|
||||
Some additional hints that may be helpful:
|
||||
|
||||
* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Umbraco which the suggestion is related to.
|
||||
* **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.com/projects/).
|
||||
* **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.org/projects/).
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` and issues](https://issues.umbraco.org/issues?q=&project=U4&tagValue=upforgrabs&release=&issueType=&search=search) or on the [new issue tracker](https://github.com/umbraco/Umbraco-CMS/issues?q=is%3Aopen+is%3Aissue+label%3Acommunity%2Fup-for-grabs).
|
||||
Unsure where to begin contributing to Umbraco? You can start by looking through [these `Up for grabs` and issues](http://issues.umbraco.org/issues/U4?q=%28project%3A+%7BU4%7D+Difficulty%3A+%7BVery+Easy%7D+%23Easy+%23Unresolved+Priority%3A+Normal+%23Major+%23Show-stopper+State%3A+-%7BIn+Progress%7D+sort+by%3A+votes+Affected+versions%3A+-6.*+Affected+versions%3A+-4.*%29+OR+%28tag%3A+%7BUp+For+Grabs%7D+%23Unresolved+%29).
|
||||
|
||||
The issue list is sorted by total number of upvotes. While not perfect, number of upvotes is a reasonable proxy for impact a given change will have.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
@@ -78,9 +80,9 @@ The most successful pull requests usually look a like this:
|
||||
* Fill in the required template
|
||||
* Include screenshots and animated GIFs in your pull request whenever possible.
|
||||
* Unit tests, while optional are awesome, thank you!
|
||||
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.com/documentation/Reference/) is generated
|
||||
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.org/documentation/Reference/) is generated
|
||||
|
||||
Again, these are guidelines, not strict requirements.
|
||||
Again, these are guidelines, not strict requirements.
|
||||
|
||||
## Making changes after the PR was opened
|
||||
|
||||
@@ -90,7 +92,7 @@ If you make the corrections we ask for in the same branch and push them to your
|
||||
|
||||
To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
|
||||
|
||||
That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
|
||||
That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
|
||||
|
||||
## What should I know before I get started?
|
||||
|
||||
@@ -114,8 +116,8 @@ There's two big areas that you should know about:
|
||||
|
||||
To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation.
|
||||
|
||||
* [The AngularJS based backoffice files](https://our.umbraco.com/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`)
|
||||
* [The rest](https://our.umbraco.com/apidocs/csharp/)
|
||||
* [The AngularJS based backoffice files](https://our.umbraco.org/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`)
|
||||
* [The rest](https://our.umbraco.org/apidocs/csharp/)
|
||||
|
||||
### What branch should I target for my contributions?
|
||||
|
||||
@@ -125,12 +127,6 @@ We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-fl
|
||||
|
||||
### Building Umbraco from source code
|
||||
|
||||
In order to build the Umbraco source code locally, first make sure you have the following installed.
|
||||
|
||||
* Visual Studio 2017 v15.3+
|
||||
* Node v10+ (Installed via `build.bat` script. If you already have it installed, make sure you're running at least v10)
|
||||
* npm v6.4.1+ (Installed via `build.bat` script. If you already have it installed, make sure you're running at least v6.4.1)
|
||||
|
||||
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
|
||||
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 (version 15.3 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
### Prerequisites
|
||||
|
||||
- [ ] I have [created an issue](https://github.com/umbraco/Umbraco-CMS/issues) for the proposed changes in this PR, the link is:
|
||||
- [ ] I have added steps to test this contribution in the description below
|
||||
|
||||
If there's an existing issue for this PR then this fixes: <!-- link to the issue here! -->
|
||||
|
||||
### Description
|
||||
<!-- A description of the changes proposed in the pull-request and how to test these changes -->
|
||||
|
||||
<!-- A description of the changes proposed in the pull-request -->
|
||||
<!-- Make sure to link to the related issue number so we can easily find it in the issue tracker -->
|
||||
|
||||
|
||||
<!-- Thanks for contributing to Umbraco CMS! -->
|
||||
|
||||
+11
-11
@@ -4,7 +4,7 @@ _Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-
|
||||
|
||||
Umbraco CMS
|
||||
===========
|
||||
The friendliest, most flexible and fastest growing ASP.NET CMS, and used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
|
||||
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
|
||||
|
||||
[](https://vimeo.com/172382998/)
|
||||
|
||||
@@ -17,34 +17,34 @@ Umbraco is a free open source Content Management System built on the ASP.NET pla
|
||||
|
||||
## Umbraco - The Friendly CMS
|
||||
|
||||
For the first time on the Microsoft platform, there is a free user- and developer-friendly CMS that makes it quick and easy to create websites - and a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, right out of the box.
|
||||
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box.
|
||||
|
||||
Umbraco is not only loved by developers, but is a content editor's dream. Enjoy intuitive editing tools, media management, responsive views, and approval workflows to send your content live.
|
||||
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
|
||||
|
||||
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scalable. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
|
||||
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
|
||||
|
||||
To view more examples, please visit [https://umbraco.com/case-studies-testimonials/](https://umbraco.com/case-studies-testimonials/)
|
||||
|
||||
## Why Open Source?
|
||||
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible, and community contributions and packages are available for all to use.
|
||||
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible and community contributions and packages are available for all to use.
|
||||
|
||||
## Trying out Umbraco CMS
|
||||
|
||||
[Umbraco Cloud](https://umbraco.com/cloud) is the easiest and fastest way to use Umbraco yet, with full support for all your custom .NET code and integrations. You're up and running in less than a minute, and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14-day trial, no credit card needed.
|
||||
[Umbraco Cloud](https://umbraco.com/cloud) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
|
||||
|
||||
If you want to DIY, you can [download Umbraco](https://our.umbraco.com/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host it yourself, and handling deployments and upgrades will be all up to you.
|
||||
If you want to DIY you can [download Umbraco](https://our.umbraco.com/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
|
||||
|
||||
## Community
|
||||
|
||||
Our friendly community is available 24/7 at the community hub we call ["Our Umbraco"](https://our.umbraco.com). Our Umbraco features forums for questions and answers, documentation, downloadable plugins for Umbraco, and a rich collection of community resources.
|
||||
Our friendly community is available 24/7 at the community hub we call ["Our Umbraco"](https://our.umbraco.com). Our Umbraco feature forums for questions and answers, documentation, downloadable plugins for Umbraco and a rich collection of community resources.
|
||||
|
||||
## Contribute to Umbraco
|
||||
|
||||
Umbraco is contribution-focused and community-driven. If you want to contribute back to Umbraco, please check out our [guide to contributing](CONTRIBUTING.md).
|
||||
Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](CONTRIBUTING.md).
|
||||
|
||||
## Found a bug?
|
||||
|
||||
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report, refer to our [online guide for reporting issues](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md).
|
||||
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md).
|
||||
|
||||
You can comment and report issues on the [github issue tracker](https://github.com/umbraco/Umbraco-CMS/issues).
|
||||
Since [September 2018](https://umbraco.com/blog/a-second-take-on-umbraco-issue-tracker-hello-github-issues/), the old issue tracker is in read-only mode, but can still be found at [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
Since [September 2018](https://umbraco.com/blog/a-second-take-on-umbraco-issue-tracker-hello-github-issues/) the old issue tracker is in read only mode, but can still be found at [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
|
||||
@@ -90,7 +90,6 @@ src/Umbraco.Web.UI.Client/[Bb]uild/*
|
||||
src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
|
||||
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
|
||||
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
|
||||
src/Umbraco.Web.UI.Client/vwd.webinfo
|
||||
tools/NDepend/
|
||||
|
||||
src/Umbraco.Web.UI/App_Plugins/*
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# The MIT License (MIT) #
|
||||
|
||||
Copyright (c) 2013-present Umbraco
|
||||
Copyright (c) 2013 Umbraco
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<span class="pull-right">
|
||||
<a href="#top">Back to top</a>
|
||||
</span>
|
||||
<span>Copyright © 2016-present Umbraco<br>Generated by <strong>DocFX</strong></span>
|
||||
<span>Copyright © 2016 Umbraco<br>Generated by <strong>DocFX</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<meta name="title" content="{{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}">
|
||||
<meta name="generator" content="docfx {{_docfxVersion}}">
|
||||
{{#_description}}<meta name="description" content="{{_description}}">{{/_description}}
|
||||
<link rel="icon" type="image/png" href="https://our.umbraco.com/assets/images/app-icons/favicon.png">
|
||||
<link rel="icon" type="image/png" href="https://our.umbraco.org/assets/images/app-icons/favicon.png">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/docfx.vendor.css">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/docfx.css">
|
||||
<link rel="stylesheet" href="{{_rel}}styles/main.css">
|
||||
|
||||
@@ -63,7 +63,7 @@ a:focus {
|
||||
}
|
||||
|
||||
.navbar-header .navbar-brand {
|
||||
background: url(https://our.umbraco.com/assets/images/logo.svg) left center no-repeat;
|
||||
background: url(https://our.umbraco.org/assets/images/logo.svg) left center no-repeat;
|
||||
background-size: 40px auto;
|
||||
width:50px;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ IF ERRORLEVEL 1 (
|
||||
|
||||
:error
|
||||
ECHO.
|
||||
ECHO Cannot run build\build.ps1.
|
||||
ECHO Can not run build\build.ps1.
|
||||
ECHO If this is due to a SecurityError then please refer to BUILD.md for help!
|
||||
ECHO.
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyCompany("Umbraco")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2018")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.13.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.13.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.13.0")]
|
||||
@@ -70,8 +70,7 @@ namespace Umbraco.Core.Configuration
|
||||
|
||||
var config = WebConfigurationManager.OpenWebConfiguration(appPath);
|
||||
var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings");
|
||||
// note: "noreply@example.com" is/was the sample SMTP from email - we'll regard that as "not configured"
|
||||
if (settings == null || settings.Smtp == null || "noreply@example.com".Equals(settings.Smtp.From, StringComparison.OrdinalIgnoreCase)) return false;
|
||||
if (settings == null || settings.Smtp == null) return false;
|
||||
if (settings.Smtp.SpecifiedPickupDirectory != null && string.IsNullOrEmpty(settings.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation) == false)
|
||||
return true;
|
||||
if (settings.Smtp.Network != null && string.IsNullOrEmpty(settings.Smtp.Network.Host) == false)
|
||||
|
||||
@@ -202,4 +202,4 @@ namespace Umbraco.Core.Configuration
|
||||
|
||||
//TODO: Add other configurations here !
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,8 +139,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
internal CommaDelimitedConfigurationElement DisallowedUploadFiles
|
||||
{
|
||||
get { return GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"}); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[ConfigurationProperty("allowedUploadFiles")]
|
||||
internal CommaDelimitedConfigurationElement AllowedUploadFiles
|
||||
{
|
||||
@@ -195,6 +195,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return GetOptionalTextElement("loginBackgroundImage", string.Empty); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("StripUdiAttributes")]
|
||||
internal InnerTextConfigurationElement<bool> StripUdiAttributes
|
||||
{
|
||||
get { return GetOptionalTextElement("StripUdiAttributes", true); }
|
||||
}
|
||||
|
||||
string IContentSection.NotificationEmailAddress
|
||||
{
|
||||
get { return Notifications.NotificationEmailAddress; }
|
||||
@@ -313,8 +319,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
IEnumerable<string> IContentSection.DisallowedUploadFiles
|
||||
{
|
||||
get { return DisallowedUploadFiles; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
IEnumerable<string> IContentSection.AllowedUploadFiles
|
||||
{
|
||||
get { return AllowedUploadFiles; }
|
||||
@@ -357,7 +363,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
string IContentSection.LoginBackgroundImage
|
||||
{
|
||||
get { return LoginBackgroundImage; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool IContentSection.StripUdiAttributes
|
||||
{
|
||||
get { return StripUdiAttributes; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
bool EnablePropertyValueConverters { get; }
|
||||
|
||||
string LoginBackgroundImage { get; }
|
||||
|
||||
bool StripUdiAttributes { get; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,12 +21,7 @@ namespace Umbraco.Core.Models
|
||||
string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the icon for the content type. The value is a CSS class name representing
|
||||
/// the icon (eg. <c>icon-home</c>) along with an optional CSS class name representing the
|
||||
/// color (eg. <c>icon-blue</c>). Put together, the value for this scenario would be
|
||||
/// <c>icon-home color-blue</c>.
|
||||
///
|
||||
/// If a class name for the color isn't specified, the icon color will default to black.
|
||||
/// Gets or Sets the Icon for the ContentType
|
||||
/// </summary>
|
||||
string Icon { get; set; }
|
||||
|
||||
@@ -124,4 +119,4 @@ namespace Umbraco.Core.Models
|
||||
/// <returns></returns>
|
||||
bool MovePropertyType(string propertyTypeAlias, string propertyGroupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -36,12 +35,9 @@ namespace Umbraco.Core.Models
|
||||
/// A list of 5 different sized avatar URLs
|
||||
/// </returns>
|
||||
internal static string[] GetUserAvatarUrls(this IUser user, ICacheProvider staticCache)
|
||||
{
|
||||
// If FIPS is required, never check the Gravatar service as it only supports MD5 hashing.
|
||||
// Unfortunately, if the FIPS setting is enabled on Windows, using MD5 will throw an exception
|
||||
// and the website will not run.
|
||||
// Also, check if the user has explicitly removed all avatars including a gravatar, this will be possible and the value will be "none"
|
||||
if (user.Avatar == "none" || CryptoConfig.AllowOnlyFipsAlgorithms)
|
||||
{
|
||||
//check if the user has explicitly removed all avatars including a gravatar, this will be possible and the value will be "none"
|
||||
if (user.Avatar == "none")
|
||||
{
|
||||
return new string[0];
|
||||
}
|
||||
|
||||
@@ -158,7 +158,9 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
|
||||
Name = indexName,
|
||||
IndexType = attribute.IndexType,
|
||||
ColumnName = columnName,
|
||||
TableName = tableName,
|
||||
TableName = tableName,
|
||||
IsClustered = attribute.IndexType == IndexTypes.Clustered,
|
||||
IsUnique = attribute.IndexType == IndexTypes.UniqueNonClustered
|
||||
};
|
||||
|
||||
if (string.IsNullOrEmpty(attribute.ForColumns) == false)
|
||||
@@ -172,4 +174,4 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
|
||||
return definition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
|
||||
@@ -15,13 +14,9 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
|
||||
public virtual string SchemaName { get; set; }
|
||||
public virtual string TableName { get; set; }
|
||||
public virtual string ColumnName { get; set; }
|
||||
|
||||
[Obsolete("Use the IndexType property instead and set it to IndexTypes.UniqueNonClustered")]
|
||||
public virtual bool IsUnique { get; set; }
|
||||
|
||||
[Obsolete("Use the IndexType property instead and set it to IndexTypes.Clustered")]
|
||||
public bool IsClustered { get; set; }
|
||||
public virtual ICollection<IndexColumnDefinition> Columns { get; set; }
|
||||
public IndexTypes IndexType { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
@@ -10,9 +11,6 @@ using Umbraco.Core.Services;
|
||||
namespace Umbraco.Core.Persistence
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Helper class for working with databases and schemas.
|
||||
/// </summary>
|
||||
public class DatabaseSchemaHelper
|
||||
{
|
||||
private readonly Database _db;
|
||||
@@ -20,22 +18,6 @@ namespace Umbraco.Core.Persistence
|
||||
private readonly ISqlSyntaxProvider _syntaxProvider;
|
||||
private readonly BaseDataCreation _baseDataCreation;
|
||||
|
||||
/// <summary>
|
||||
/// Intializes a new helper instance.
|
||||
/// </summary>
|
||||
/// <param name="db">The database to be used.</param>
|
||||
/// <param name="logger">The logger.</param>
|
||||
/// <param name="syntaxProvider">The syntax provider.</param>
|
||||
/// <example>
|
||||
/// A new instance could be initialized like:
|
||||
/// <code>
|
||||
/// var schemaHelper = new DatabaseSchemaHelper(
|
||||
/// ApplicationContext.Current.DatabaseContext.Database,
|
||||
/// ApplicationContext.Current.ProfilingLogger.Logger,
|
||||
/// ApplicationContext.Current.DatabaseContext.SqlSyntax
|
||||
/// );
|
||||
/// </code>
|
||||
/// </example>
|
||||
public DatabaseSchemaHelper(Database db, ILogger logger, ISqlSyntaxProvider syntaxProvider)
|
||||
{
|
||||
_db = db;
|
||||
@@ -44,41 +26,11 @@ namespace Umbraco.Core.Persistence
|
||||
_baseDataCreation = new BaseDataCreation(db, logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a table with the specified <paramref name="tableName"/> exists in the database.
|
||||
/// </summary>
|
||||
/// <param name="tableName">The name of the table.</param>
|
||||
/// <returns><c>true</c> if the table exists; otherwise <c>false</c>.</returns>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// if (schemaHelper.TableExist("MyTable"))
|
||||
/// {
|
||||
/// // do something when the table exists
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public bool TableExist(string tableName)
|
||||
{
|
||||
return _syntaxProvider.DoesTableExist(_db, tableName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the table for the specified <typeparamref name="T"/> exists in the database.
|
||||
///
|
||||
/// If <typeparamref name="T"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from that
|
||||
/// attribute will be used for the table name. If the attribute is not present, the name
|
||||
/// <typeparamref name="T"/> will be used instead.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type representing the DTO/table.</typeparam>
|
||||
/// <returns><c>true</c> if the table exists; otherwise <c>false</c>.</returns>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// if (schemaHelper.TableExist<MyDto>)
|
||||
/// {
|
||||
/// // do something when the table exists
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public bool TableExist<T>()
|
||||
{
|
||||
var poco = Database.PocoData.ForType(typeof(T));
|
||||
@@ -138,17 +90,6 @@ namespace Umbraco.Core.Persistence
|
||||
_logger.Info<Database>("Finalized database schema creation");
|
||||
}
|
||||
|
||||
/// Creates a new table in the database based on the type of <typeparamref name="T"/>.
|
||||
///
|
||||
/// If <typeparamref name="T"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from that
|
||||
/// attribute will be used for the table name. If the attribute is not present, the name
|
||||
/// <typeparamref name="T"/> will be used instead.
|
||||
///
|
||||
/// If a table with the same name already exists, the <paramref name="overwrite"/> parameter will determine
|
||||
/// whether the table is overwritten. If <c>true</c>, the table will be overwritten, whereas this method will
|
||||
/// not do anything if the parameter is <c>false</c>.
|
||||
/// <typeparam name="T">The type representing the DTO/table.</typeparam>
|
||||
/// <param name="overwrite">Whether the table should be overwritten if it already exists.</param>
|
||||
public void CreateTable<T>(bool overwrite)
|
||||
where T : new()
|
||||
{
|
||||
@@ -156,16 +97,6 @@ namespace Umbraco.Core.Persistence
|
||||
CreateTable(overwrite, tableType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new table in the database based on the type of <typeparamref name="T"/>.
|
||||
///
|
||||
/// If <typeparamref name="T"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from that
|
||||
/// attribute will be used for the table name. If the attribute is not present, the name
|
||||
/// <typeparamref name="T"/> will be used instead.
|
||||
///
|
||||
/// If a table with the same name already exists, this method will not do anything.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type representing the DTO/table.</typeparam>
|
||||
public void CreateTable<T>()
|
||||
where T : new()
|
||||
{
|
||||
@@ -173,19 +104,6 @@ namespace Umbraco.Core.Persistence
|
||||
CreateTable(false, tableType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new table in the database for the specified <paramref name="modelType"/>.
|
||||
///
|
||||
/// If <paramref name="modelType"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from
|
||||
/// that attribute will be used for the table name. If the attribute is not present, the name
|
||||
/// <paramref name="modelType"/> will be used instead.
|
||||
///
|
||||
/// If a table with the same name already exists, the <paramref name="overwrite"/> parameter will determine
|
||||
/// whether the table is overwritten. If <c>true</c>, the table will be overwritten, whereas this method will
|
||||
/// not do anything if the parameter is <c>false</c>.
|
||||
/// </summary>
|
||||
/// <param name="overwrite">Whether the table should be overwritten if it already exists.</param>
|
||||
/// <param name="modelType">The the representing the table.</param>
|
||||
public void CreateTable(bool overwrite, Type modelType)
|
||||
{
|
||||
var tableDefinition = DefinitionFactory.GetTableDefinition(_syntaxProvider, modelType);
|
||||
@@ -199,8 +117,6 @@ namespace Umbraco.Core.Persistence
|
||||
var tableExist = TableExist(tableName);
|
||||
if (overwrite && tableExist)
|
||||
{
|
||||
_logger.Info<Database>(string.Format("Table '{0}' already exists, but will be recreated", tableName));
|
||||
|
||||
DropTable(tableName);
|
||||
tableExist = false;
|
||||
}
|
||||
@@ -253,37 +169,15 @@ namespace Umbraco.Core.Persistence
|
||||
_logger.Info<Database>(string.Format("Create Foreign Key sql {0}:\n {1}", createdFk, sql));
|
||||
}
|
||||
|
||||
|
||||
|
||||
transaction.Complete();
|
||||
if (overwrite)
|
||||
{
|
||||
_logger.Info<Database>(string.Format("Table '{0}' was recreated", tableName));
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Info<Database>(string.Format("New table '{0}' was created", tableName));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The table exists and was not recreated/overwritten.
|
||||
_logger.Info<Database>(string.Format("Table '{0}' already exists - no changes were made", tableName));
|
||||
}
|
||||
|
||||
_logger.Info<Database>(string.Format("New table '{0}' was created", tableName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drops the table for the specified <typeparamref name="T"/>.
|
||||
///
|
||||
/// If <typeparamref name="T"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from that
|
||||
/// attribute will be used for the table name. If the attribute is not present, the name
|
||||
/// <typeparamref name="T"/> will be used instead.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type representing the DTO/table.</typeparam>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// schemaHelper.DropTable<MyDto>);
|
||||
/// </code>
|
||||
/// </example>
|
||||
public void DropTable<T>()
|
||||
where T : new()
|
||||
{
|
||||
@@ -299,15 +193,6 @@ namespace Umbraco.Core.Persistence
|
||||
DropTable(tableName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drops the table with the specified <paramref name="tableName"/>.
|
||||
/// </summary>
|
||||
/// <param name="tableName">The name of the table.</param>
|
||||
/// <example>
|
||||
/// <code>
|
||||
/// schemaHelper.DropTable("MyTable");
|
||||
/// </code>
|
||||
/// </example>
|
||||
public void DropTable(string tableName)
|
||||
{
|
||||
var sql = new Sql(string.Format(
|
||||
|
||||
@@ -140,9 +140,6 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
/// <returns></returns>
|
||||
internal static bool TryMatch(string text, out string mediaPath)
|
||||
{
|
||||
//TODO: In v8 we should allow exposing this via the property editor in a much nicer way so that the property editor
|
||||
// can tell us directly what any URL is for a given property if it contains an asset
|
||||
|
||||
mediaPath = null;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
@@ -158,4 +155,4 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
|
||||
if(tableName.Equals("umbracoNode"))
|
||||
{
|
||||
CreateUmbracoNodeData();
|
||||
CreateUmbracNodeData();
|
||||
}
|
||||
|
||||
if (tableName.Equals("umbracoLock"))
|
||||
@@ -111,7 +111,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_logger.Info<BaseDataCreation>(string.Format("Done creating data in table {0}", tableName));
|
||||
}
|
||||
|
||||
private void CreateUmbracoNodeData()
|
||||
private void CreateUmbracNodeData()
|
||||
{
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -1, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1", SortOrder = 0, UniqueId = new Guid("916724a5-173d-4619-b97e-b9de133dd6f5"), Text = "SYSTEM DATA: umbraco master root", NodeObjectType = new Guid(Constants.ObjectTypes.SystemRoot), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -20, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1,-20", SortOrder = 0, UniqueId = new Guid("0F582A79-1E41-4CF0-BFA0-76340651891A"), Text = "Recycle Bin", NodeObjectType = new Guid(Constants.ObjectTypes.ContentRecycleBin), CreateDate = DateTime.Now });
|
||||
@@ -256,10 +256,10 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 7, DataTypeId = -92, PropertyEditorAlias = Constants.PropertyEditors.NoEditAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 8, DataTypeId = -36, PropertyEditorAlias = Constants.PropertyEditors.DateTimeAlias, DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 9, DataTypeId = -37, PropertyEditorAlias = Constants.PropertyEditors.ColorPickerAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 11, DataTypeId = -39, PropertyEditorAlias = Constants.PropertyEditors.DropDownListFlexibleAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 11, DataTypeId = -39, PropertyEditorAlias = Constants.PropertyEditors.DropDownListMultipleAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, PropertyEditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, PropertyEditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListFlexibleAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, PropertyEditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = 1043, PropertyEditorAlias = Constants.PropertyEditors.ImageCropperAlias, DbType = "Ntext" });
|
||||
@@ -300,12 +300,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
|
||||
//default's for MultipleMediaPickerAlias picker
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 6, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1049, Value = "1" });
|
||||
|
||||
// Defaults for single item dropdown
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 7, Alias = "multiple", SortOrder = 0, DataTypeNodeId = -42, Value = "0" });
|
||||
|
||||
// Defaults for multiple item dropdown
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 8, Alias = "multiple", SortOrder = 0, DataTypeNodeId = -39, Value = "1" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoRelationTypeData()
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Data;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
|
||||
@@ -140,12 +139,10 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
|
||||
{
|
||||
Name = indexName,
|
||||
SchemaName = Expression.SchemaName,
|
||||
TableName = Expression.TableName,
|
||||
IndexType = IndexTypes.UniqueNonClustered
|
||||
TableName = Expression.TableName,
|
||||
IsUnique = true
|
||||
});
|
||||
|
||||
|
||||
|
||||
index.Index.Columns.Add(new IndexColumnDefinition
|
||||
{
|
||||
Name = Expression.Column.Name
|
||||
@@ -245,4 +242,4 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Column
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Data;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Alter.Expressions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
|
||||
@@ -125,8 +124,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
|
||||
{
|
||||
Name = indexName,
|
||||
SchemaName = Expression.SchemaName,
|
||||
TableName = Expression.TableName,
|
||||
IndexType = IndexTypes.UniqueNonClustered
|
||||
TableName = Expression.TableName,
|
||||
IsUnique = true
|
||||
});
|
||||
|
||||
index.Index.Columns.Add(new IndexColumnDefinition
|
||||
@@ -260,4 +259,4 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter.Table
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Data;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
@@ -115,8 +114,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Column
|
||||
{
|
||||
Name = indexName,
|
||||
SchemaName = Expression.SchemaName,
|
||||
TableName = Expression.TableName,
|
||||
IndexType = IndexTypes.UniqueNonClustered
|
||||
TableName = Expression.TableName,
|
||||
IsUnique = true
|
||||
});
|
||||
|
||||
index.Index.Columns.Add(new IndexColumnDefinition
|
||||
@@ -218,4 +217,4 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Column
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,27 +47,39 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Index
|
||||
}
|
||||
|
||||
ICreateIndexOnColumnSyntax ICreateIndexColumnOptionsSyntax.Unique()
|
||||
{
|
||||
Expression.Index.IndexType = IndexTypes.UniqueNonClustered;
|
||||
{
|
||||
Expression.Index.IsUnique = true;
|
||||
//if it is Unique then it must be unique nonclustered and set the other flags
|
||||
Expression.Index.IndexType = IndexTypes.UniqueNonClustered;
|
||||
Expression.Index.IsClustered = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICreateIndexOnColumnSyntax NonClustered()
|
||||
{
|
||||
Expression.Index.IndexType = IndexTypes.NonClustered;
|
||||
Expression.Index.IndexType = IndexTypes.NonClustered;
|
||||
Expression.Index.IsClustered = false;
|
||||
Expression.Index.IndexType = IndexTypes.NonClustered;
|
||||
Expression.Index.IsUnique = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ICreateIndexOnColumnSyntax Clustered()
|
||||
{
|
||||
Expression.Index.IndexType = IndexTypes.Clustered;
|
||||
return this;
|
||||
{
|
||||
Expression.Index.IndexType = IndexTypes.Clustered;
|
||||
Expression.Index.IsClustered = true;
|
||||
//if it is clustered then we have to change the index type set the other flags
|
||||
Expression.Index.IndexType = IndexTypes.Clustered;
|
||||
Expression.Index.IsClustered = true;
|
||||
Expression.Index.IsUnique = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
ICreateIndexOnColumnSyntax ICreateIndexOptionsSyntax.Unique()
|
||||
{
|
||||
Expression.Index.IndexType = IndexTypes.UniqueNonClustered;
|
||||
Expression.Index.IndexType = IndexTypes.UniqueNonClustered;
|
||||
Expression.Index.IsUnique = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Data;
|
||||
using Umbraco.Core.Persistence.DatabaseAnnotations;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Create.Expressions;
|
||||
using Umbraco.Core.Persistence.Migrations.Syntax.Expressions;
|
||||
@@ -165,8 +164,8 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
|
||||
{
|
||||
Name = indexName,
|
||||
SchemaName = Expression.SchemaName,
|
||||
TableName = Expression.TableName,
|
||||
IndexType = IndexTypes.UniqueNonClustered
|
||||
TableName = Expression.TableName,
|
||||
IsUnique = true
|
||||
});
|
||||
|
||||
index.Index.Columns.Add(new IndexColumnDefinition
|
||||
@@ -268,4 +267,4 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Create.Table
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = GetBaseQuery(false);
|
||||
|
||||
if (query == null) query = new Query<IAuditItem>();
|
||||
|
||||
|
||||
var queryHasWhereClause = query.GetWhereClauses().Any();
|
||||
var translatorIds = new SqlTranslator<IAuditItem>(sql, query);
|
||||
var translatedQuery = translatorIds.Translate();
|
||||
@@ -59,7 +59,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var filterSql = new Sql();
|
||||
foreach (var filterClause in customFilterWheres)
|
||||
{
|
||||
{
|
||||
filterSql.Append($"AND ({filterClause.Item1})", filterClause.Item2);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
var filterSql = new Sql();
|
||||
foreach (var filterClause in auditTypeFilter)
|
||||
{
|
||||
{
|
||||
filterSql.Append("AND (logHeader = @logHeader)", new { logHeader = filterClause.ToString() });
|
||||
}
|
||||
|
||||
@@ -80,14 +80,14 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (orderDirection == Direction.Descending)
|
||||
translatedQuery.OrderByDescending("Datestamp");
|
||||
else
|
||||
translatedQuery.OrderBy("Datestamp");
|
||||
translatedQuery.OrderBy("Datestamp");
|
||||
|
||||
// Get page of results and total count
|
||||
var pagedResult = Database.Page<LogDto>(pageIndex + 1, pageSize, translatedQuery);
|
||||
totalRecords = pagedResult.TotalItems;
|
||||
|
||||
var pages = pagedResult.Items.Select(
|
||||
dto => new AuditItem(dto.NodeId, dto.Comment, Enum<AuditType>.ParseOrNull(dto.Header) ?? AuditType.Custom, dto.UserId)).ToArray();
|
||||
dto => new AuditItem(dto.Id, dto.Comment, Enum<AuditType>.ParseOrNull(dto.Header) ?? AuditType.Custom, dto.UserId)).ToArray();
|
||||
|
||||
//Mapping the DateStamp
|
||||
for (var i = 0; i < pages.Length; i++)
|
||||
@@ -142,7 +142,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
protected override IEnumerable<IAuditItem> PerformGetByQuery(IQuery<IAuditItem> query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
protected override string GetBaseWhereClause()
|
||||
{
|
||||
@@ -167,7 +167,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
// Apply filter
|
||||
if (filterSql != null)
|
||||
{
|
||||
//ensure we don't append a WHERE if there is already one
|
||||
//ensure we don't append a WHERE if there is already one
|
||||
var sqlFilter = hasWhereClause
|
||||
? filterSql.SQL
|
||||
: " WHERE " + filterSql.SQL.TrimStart("AND ");
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.InnerJoin<ContentDto>(SqlSyntax)
|
||||
.On<ContentVersionDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<ContentTypeDto>()
|
||||
.On<ContentTypeDto, ContentDto>(left => left.NodeId, right => right.ContentTypeId);
|
||||
//TODO: IF we want to enable querying on content type information this will need to be joined
|
||||
@@ -836,19 +836,19 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
}
|
||||
|
||||
public int CountPublished(string contentTypeAlias = null)
|
||||
{
|
||||
if (contentTypeAlias.IsNullOrWhiteSpace())
|
||||
{
|
||||
{
|
||||
if (contentTypeAlias.IsNullOrWhiteSpace())
|
||||
{
|
||||
var sql = GetBaseQuery(true).Where<NodeDto>(x => x.Trashed == false)
|
||||
.Where<DocumentDto>(x => x.Published == true);
|
||||
return Database.ExecuteScalar<int>(sql);
|
||||
.Where<DocumentDto>(x => x.Published == true);
|
||||
return Database.ExecuteScalar<int>(sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
else
|
||||
{
|
||||
var sql = GetBaseQuery(true).Where<NodeDto>(x => x.Trashed == false)
|
||||
.Where<DocumentDto>(x => x.Published == true)
|
||||
.Where<ContentTypeDto>(x => x.Alias == contentTypeAlias);
|
||||
return Database.ExecuteScalar<int>(sql);
|
||||
.Where<DocumentDto>(x => x.Published == true)
|
||||
.Where<ContentTypeDto>(x => x.Alias == contentTypeAlias);
|
||||
return Database.ExecuteScalar<int>(sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1220,14 +1220,7 @@ ORDER BY cmsContentVersion.id DESC
|
||||
if (def.DocumentDto.TemplateId.HasValue)
|
||||
templates.TryGetValue(def.DocumentDto.TemplateId.Value, out template); // else null
|
||||
cc.Template = template;
|
||||
if (propertyData.ContainsKey(cc.Version))
|
||||
{
|
||||
cc.Properties = propertyData[cc.Version];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"No property data found for version: '{cc.Version}'.");
|
||||
}
|
||||
cc.Properties = propertyData[cc.Version];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
@@ -1314,4 +1307,4 @@ ORDER BY cmsContentVersion.id DESC
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
@@ -64,8 +64,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}, objectTypeId);
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var entitySql = translator.Translate();
|
||||
var pagedSql = entitySql.Append(GetGroupBy(isContent, isMedia, false));
|
||||
pagedSql = (orderDirection == Direction.Descending) ? pagedSql.OrderByDescending("umbracoNode.id") : pagedSql.OrderBy("umbracoNode.id");
|
||||
var pagedSql = entitySql.Append(GetGroupBy(isContent, isMedia, false)).OrderBy("umbracoNode.id");
|
||||
|
||||
IEnumerable<IUmbracoEntity> result;
|
||||
|
||||
@@ -81,8 +80,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
foreach (var idGroup in ids)
|
||||
{
|
||||
var propSql = GetPropertySql(Constants.ObjectTypes.Media)
|
||||
.Where("contentNodeId IN (@ids)", new { ids = idGroup });
|
||||
propSql = (orderDirection == Direction.Descending) ? propSql.OrderByDescending("contentNodeId") : propSql.OrderBy("contentNodeId");
|
||||
.Where("contentNodeId IN (@ids)", new {ids = idGroup})
|
||||
.OrderBy("contentNodeId");
|
||||
|
||||
//This does NOT fetch all data into memory in a list, this will read
|
||||
// over the records as a data reader, this is much better for performance and memory,
|
||||
@@ -332,23 +331,14 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets entities by query.
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="objectTypeId"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Note that this will also fetch all property data for media items, which can cause performance problems
|
||||
/// when used without paging, in sites with large amounts of data in cmsPropertyData.
|
||||
/// </remarks>
|
||||
public virtual IEnumerable<IUmbracoEntity> GetByQuery(IQuery<IUmbracoEntity> query, Guid objectTypeId)
|
||||
{
|
||||
var isContent = objectTypeId == Constants.ObjectTypes.DocumentGuid || objectTypeId == Constants.ObjectTypes.DocumentBlueprintGuid;
|
||||
var isMedia = objectTypeId == Constants.ObjectTypes.MediaGuid;
|
||||
|
||||
bool isContent = objectTypeId == Constants.ObjectTypes.DocumentGuid || objectTypeId == Constants.ObjectTypes.DocumentBlueprintGuid;
|
||||
bool isMedia = objectTypeId == Constants.ObjectTypes.MediaGuid;
|
||||
|
||||
var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, null, objectTypeId);
|
||||
|
||||
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var entitySql = translator.Translate();
|
||||
|
||||
@@ -374,49 +364,22 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetByQueryInternal(entitySql, isContent, isMedia);
|
||||
//use dynamic so that we can get ALL properties from the SQL so we can chuck that data into our AdditionalData
|
||||
var finalSql = entitySql.Append(GetGroupBy(isContent, false));
|
||||
|
||||
//query = read forward data reader, do not load everything into mem
|
||||
var dtos = _work.Database.Query<dynamic>(finalSql);
|
||||
var collection = new EntityDefinitionCollection();
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
collection.AddOrUpdate(new EntityDefinition(factory, dto, isContent, false));
|
||||
}
|
||||
return collection.Select(x => x.BuildFromDynamic()).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets entities by query without fetching property data.
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="objectTypeId"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is supposed to be internal and can be used when getting all entities without paging, without causing
|
||||
/// performance issues.
|
||||
/// </remarks>
|
||||
internal IEnumerable<IUmbracoEntity> GetMediaByQueryWithoutPropertyData(IQuery<IUmbracoEntity> query)
|
||||
{
|
||||
var sqlClause = GetBaseWhere(GetBase, false, true, null, UmbracoObjectTypes.Media.GetGuid());
|
||||
|
||||
var translator = new SqlTranslator<IUmbracoEntity>(sqlClause, query);
|
||||
var entitySql = translator.Translate();
|
||||
|
||||
return GetByQueryInternal(entitySql, false, true);
|
||||
}
|
||||
|
||||
internal IEnumerable<IUmbracoEntity> GetByQueryInternal(Sql entitySql, bool isContent, bool isMedia)
|
||||
{
|
||||
var factory = new UmbracoEntityFactory();
|
||||
|
||||
//use dynamic so that we can get ALL properties from the SQL so we can chuck that data into our AdditionalData
|
||||
var finalSql = entitySql.Append(GetGroupBy(isContent, isMedia));
|
||||
|
||||
//query = read forward data reader, do not load everything into mem
|
||||
var dtos = _work.Database.Query<dynamic>(finalSql);
|
||||
var collection = new EntityDefinitionCollection();
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
collection.AddOrUpdate(new EntityDefinition(factory, dto, isContent, isMedia));
|
||||
}
|
||||
return collection.Select(x => x.BuildFromDynamic()).ToList();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
#region Sql Statements
|
||||
|
||||
@@ -888,4 +851,4 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,7 +284,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var nonAssignedRoles = roleNames.Except(assignedRoles, StringComparer.CurrentCultureIgnoreCase);
|
||||
foreach (var toAssign in nonAssignedRoles)
|
||||
{
|
||||
var groupId = rolesForNames.First(x => x.Text.InvariantEquals(toAssign)).NodeId;
|
||||
var groupId = rolesForNames.First(x => x.Text == toAssign).NodeId;
|
||||
Database.Insert(new Member2MemberGroupDto { Member = mId, MemberGroup = groupId });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,20 +258,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//.Where(x => Equals(x, default(TId)) == false)
|
||||
.ToArray();
|
||||
|
||||
// can't query more than 2000 ids at a time... but if someone is really querying 2000+ entities,
|
||||
// the additional overhead of fetching them in groups is minimal compared to the lookup time of each group
|
||||
const int maxParams = 2000;
|
||||
if (ids.Length <= maxParams)
|
||||
if (ids.Length > 2000)
|
||||
{
|
||||
return CachePolicy.GetAll(ids, PerformGetAll);
|
||||
throw new InvalidOperationException("Cannot perform a query with more than 2000 parameters");
|
||||
}
|
||||
var entities = new List<TEntity>();
|
||||
foreach (var groupOfIds in ids.InGroupsOf(maxParams))
|
||||
{
|
||||
entities.AddRange(CachePolicy.GetAll(groupOfIds.ToArray(), PerformGetAll));
|
||||
}
|
||||
return entities;
|
||||
|
||||
return CachePolicy.GetAll(ids, PerformGetAll);
|
||||
}
|
||||
|
||||
protected abstract IEnumerable<TEntity> PerformGetByQuery(IQuery<TEntity> query);
|
||||
|
||||
@@ -152,7 +152,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public IProfile GetProfile(string username)
|
||||
{
|
||||
var sql = GetBaseQuery(false).Where<UserDto>(userDto => userDto.Login == username, SqlSyntax);
|
||||
var sql = GetBaseQuery(false).Where<UserDto>(userDto => userDto.UserName == username, SqlSyntax);
|
||||
|
||||
var dto = Database.Fetch<UserDto>(sql)
|
||||
.FirstOrDefault();
|
||||
@@ -382,7 +382,6 @@ ORDER BY colName";
|
||||
"DELETE FROM cmsTask WHERE parentUserId = @Id",
|
||||
"DELETE FROM umbracoUser2UserGroup WHERE userId = @Id",
|
||||
"DELETE FROM umbracoUser2NodeNotify WHERE userId = @Id",
|
||||
"DELETE FROM umbracoUserStartNode WHERE userId = @Id",
|
||||
"DELETE FROM umbracoUser WHERE id = @Id",
|
||||
"DELETE FROM umbracoExternalLogin WHERE id = @Id"
|
||||
};
|
||||
|
||||
@@ -385,16 +385,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (orderDirection == Direction.Descending)
|
||||
{
|
||||
sortedSql.OrderByDescending("CustomPropData.CustomPropVal");
|
||||
// need to ensure ordering unique by using id as CustomPropVal may not be unique
|
||||
// see: https://github.com/umbraco/Umbraco-CMS/issues/3296
|
||||
sortedSql.OrderByDescending("umbracoNode.id");
|
||||
}
|
||||
else
|
||||
{
|
||||
sortedSql.OrderBy("CustomPropData.CustomPropVal");
|
||||
// need to ensure ordering unique by using id as CustomPropVal may not be unique
|
||||
// see: https://github.com/umbraco/Umbraco-CMS/issues/3296
|
||||
sortedSql.OrderBy("umbracoNode.id");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -333,9 +333,14 @@ ORDER BY TABLE_NAME, INDEX_NAME",
|
||||
switch (systemMethod)
|
||||
{
|
||||
case SystemMethods.NewGuid:
|
||||
return null; // NOT SUPPORTED!
|
||||
return null; // NOT SUPPORTED!
|
||||
//return "NEWID()";
|
||||
case SystemMethods.CurrentDateTime:
|
||||
return "CURRENT_TIMESTAMP";
|
||||
//case SystemMethods.NewSequentialId:
|
||||
// return "NEWSEQUENTIALID()";
|
||||
//case SystemMethods.CurrentUTCDateTime:
|
||||
// return "GETUTCDATE()";
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -236,10 +236,7 @@ namespace Umbraco.Core.Security
|
||||
|
||||
if (dataProtectionProvider != null)
|
||||
{
|
||||
manager.UserTokenProvider = new DataProtectorTokenProvider<T, int>(dataProtectionProvider.Create("ASP.NET Identity"))
|
||||
{
|
||||
TokenLifespan = TimeSpan.FromDays(3)
|
||||
};
|
||||
manager.UserTokenProvider = new DataProtectorTokenProvider<T, int>(dataProtectionProvider.Create("ASP.NET Identity"));
|
||||
}
|
||||
|
||||
manager.UserLockoutEnabledByDefault = true;
|
||||
@@ -751,7 +748,6 @@ namespace Umbraco.Core.Security
|
||||
var httpContext = HttpContext.Current == null ? (HttpContextBase)null : new HttpContextWrapper(HttpContext.Current);
|
||||
return httpContext.GetCurrentRequestIpAddress();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -630,9 +630,7 @@ namespace Umbraco.Core.Security
|
||||
|| identityUser.LastLoginDateUtc.HasValue && user.LastLoginDate.ToUniversalTime() != identityUser.LastLoginDateUtc.Value)
|
||||
{
|
||||
anythingChanged = true;
|
||||
//if the LastLoginDate is being set to MinValue, don't convert it ToLocalTime
|
||||
var dt = identityUser.LastLoginDateUtc == DateTime.MinValue ? DateTime.MinValue : identityUser.LastLoginDateUtc.Value.ToLocalTime();
|
||||
user.LastLoginDate = dt;
|
||||
user.LastLoginDate = identityUser.LastLoginDateUtc.Value.ToLocalTime();
|
||||
}
|
||||
if (identityUser.IsPropertyDirty("LastPasswordChangeDateUtc")
|
||||
|| (user.LastPasswordChangeDate != default(DateTime) && identityUser.LastPasswordChangeDateUtc.HasValue == false)
|
||||
|
||||
@@ -2060,15 +2060,12 @@ namespace Umbraco.Core.Services
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
var allContent = GetByIds(ids).ToDictionary(x => x.Id, x => x);
|
||||
if (allContent.Any() == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var items = ids.Select(x => allContent[x]).ToArray();
|
||||
var items = ids.Select(x => allContent[x]);
|
||||
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
{
|
||||
var saveEventArgs = new SaveEventArgs<IContent>(items);
|
||||
var asArray = items.ToArray();
|
||||
var saveEventArgs = new SaveEventArgs<IContent>(asArray);
|
||||
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving"))
|
||||
{
|
||||
uow.Commit();
|
||||
@@ -2078,7 +2075,7 @@ namespace Umbraco.Core.Services
|
||||
var repository = RepositoryFactory.CreateContentRepository(uow);
|
||||
|
||||
var i = 0;
|
||||
foreach (var content in items)
|
||||
foreach (var content in asArray)
|
||||
{
|
||||
//If the current sort order equals that of the content
|
||||
//we don't need to update it, so just increment the sort order
|
||||
@@ -2125,7 +2122,7 @@ namespace Umbraco.Core.Services
|
||||
_publishingStrategy.PublishingFinalized(uow, shouldBePublished, false);
|
||||
}
|
||||
|
||||
Audit(uow, AuditType.Sort, "Sort child items performed by user", userId, items.First().ParentId);
|
||||
Audit(uow, AuditType.Sort, "Sorting content performed by user", userId, 0);
|
||||
uow.Commit();
|
||||
}
|
||||
}
|
||||
@@ -2575,18 +2572,8 @@ namespace Umbraco.Core.Services
|
||||
_publishingStrategy.PublishingFinalized(uow, descendants, false);
|
||||
}
|
||||
|
||||
Audit(uow, AuditType.Publish, "Save and Publish performed by user", userId, content.Id);
|
||||
uow.Commit();
|
||||
|
||||
if (publishStatus.StatusType == PublishStatusType.Success)
|
||||
{
|
||||
Audit(uow, AuditType.Publish, "Save and Publish performed by user", userId, content.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
Audit(uow, AuditType.Save, "Save performed by user", userId, content.Id);
|
||||
}
|
||||
uow.Commit();
|
||||
|
||||
return Attempt.If(publishStatus.StatusType == PublishStatusType.Success, publishStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -11,7 +13,6 @@ using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -286,35 +287,16 @@ namespace Umbraco.Core.Services
|
||||
public virtual IEnumerable<IUmbracoEntity> GetChildren(int parentId, UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
var objectTypeId = umbracoObjectType.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
|
||||
return repository.GetByQuery(query, objectTypeId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of children by the parent's Id and UmbracoObjectType without adding property data
|
||||
/// </summary>
|
||||
/// <param name="parentId">Id of the parent to retrieve children for</param>
|
||||
/// <returns>An enumerable list of <see cref="IUmbracoEntity"/> objects</returns>
|
||||
internal IEnumerable<IUmbracoEntity> GetMediaChildrenWithoutPropertyData(int parentId)
|
||||
{
|
||||
var objectTypeId = UmbracoObjectTypes.Media.GetGuid();
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateEntityRepository(uow);
|
||||
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
|
||||
|
||||
// Not pretty having to cast the repository, but it is the only way to get to use an internal method that we
|
||||
// do not want to make public on the interface. Unfortunately also prevents this from being unit tested.
|
||||
// See this issue for details on why we need this:
|
||||
// https://github.com/umbraco/Umbraco-CMS/issues/3457
|
||||
return ((EntityRepository)repository).GetMediaByQueryWithoutPropertyData(query);
|
||||
var contents = repository.GetByQuery(query, objectTypeId);
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns a paged collection of children
|
||||
/// </summary>
|
||||
@@ -799,4 +781,4 @@ namespace Umbraco.Core.Services
|
||||
return node.NodeId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,15 +26,6 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="userId">Id of the User deleting the Media</param>
|
||||
Attempt<OperationStatus> MoveToRecycleBin(IMedia media, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Moves an <see cref="IMedia"/> object to a new location
|
||||
/// </summary>
|
||||
/// <param name="media">The <see cref="IMedia"/> to move</param>
|
||||
/// <param name="parentId">Id of the Media's new Parent</param>
|
||||
/// <param name="userId">Id of the User moving the Media</param>
|
||||
/// <returns>True if moving succeeded, otherwise False</returns>
|
||||
Attempt<OperationStatus> Move(IMedia media, int parentId, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Permanently deletes an <see cref="IMedia"/> object
|
||||
/// </summary>
|
||||
@@ -278,7 +269,6 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="userId">Id of the User moving the Media</param>
|
||||
void Move(IMedia media, int parentId, int userId = 0);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an <see cref="IMedia"/> object by moving it to the Recycle Bin
|
||||
/// </summary>
|
||||
|
||||
@@ -465,7 +465,7 @@ namespace Umbraco.Core.Services
|
||||
return repository.GetByQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Obsolete("Use the overload with 'long' parameter types instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public IEnumerable<IMedia> GetPagedChildren(int id, int pageIndex, int pageSize, out int totalChildren,
|
||||
@@ -758,20 +758,19 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="media">The <see cref="IMedia"/> to move</param>
|
||||
/// <param name="parentId">Id of the Media's new Parent</param>
|
||||
/// <param name="userId">Id of the User moving the Media</param>
|
||||
/// <returns>True if moving succeeded, otherwise False</returns>
|
||||
public Attempt<OperationStatus> Move(IMedia media, int parentId, int userId = 0)
|
||||
public void Move(IMedia media, int parentId, int userId = 0)
|
||||
{
|
||||
//TODO: This all needs to be on the repo layer in one transaction!
|
||||
|
||||
if (media == null) throw new ArgumentNullException("media");
|
||||
var evtMsgs = EventMessagesFactory.Get();
|
||||
|
||||
using (new WriteLock(Locker))
|
||||
{
|
||||
//This ensures that the correct method is called if this method is used to Move to recycle bin.
|
||||
if (parentId == Constants.System.RecycleBinMedia)
|
||||
{
|
||||
MoveToRecycleBin(media, userId);
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
return;
|
||||
}
|
||||
|
||||
using (var uow = UowProvider.GetUnitOfWork())
|
||||
@@ -779,11 +778,11 @@ namespace Umbraco.Core.Services
|
||||
var originalPath = media.Path;
|
||||
|
||||
var moveEventInfo = new MoveEventInfo<IMedia>(media, originalPath, parentId);
|
||||
var moveEventArgs = new MoveEventArgs<IMedia>(true, evtMsgs, moveEventInfo);
|
||||
var moveEventArgs = new MoveEventArgs<IMedia>(moveEventInfo);
|
||||
if (uow.Events.DispatchCancelable(Moving, this, moveEventArgs, "Moving"))
|
||||
{
|
||||
uow.Commit();
|
||||
return OperationStatus.Cancelled(evtMsgs); ;
|
||||
return;
|
||||
}
|
||||
|
||||
media.ParentId = parentId;
|
||||
@@ -817,8 +816,6 @@ namespace Umbraco.Core.Services
|
||||
Audit(uow, AuditType.Move, "Move Media performed by user", userId, media.Id);
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
return OperationStatus.Success(evtMsgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1104,7 +1101,7 @@ namespace Umbraco.Core.Services
|
||||
media.EnsureValidPath(Logger, entity => GetById(entity.ParentId), QuickUpdate);
|
||||
var originalPath = media.Path;
|
||||
var moveEventInfo = new MoveEventInfo<IMedia>(media, originalPath, Constants.System.RecycleBinMedia);
|
||||
var moveEventArgs = new MoveEventArgs<IMedia>(true, evtMsgs, moveEventInfo);
|
||||
var moveEventArgs = new MoveEventArgs<IMedia>(moveEventInfo);
|
||||
if (uow.Events.DispatchCancelable(Trashing, this, moveEventArgs, "Trashing"))
|
||||
{
|
||||
uow.Commit();
|
||||
@@ -1471,11 +1468,6 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
void IMediaService.Move(IMedia media, int parentId, int userId)
|
||||
{
|
||||
Move(media, parentId, userId);
|
||||
}
|
||||
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
|
||||
@@ -58,7 +58,54 @@ namespace Umbraco.Core.Services
|
||||
if (entity is IContent == false)
|
||||
throw new NotSupportedException();
|
||||
|
||||
SendNotifications(operatingUser, new[] { (IContent)entity }, action, actionName, http, createSubject, createBody);
|
||||
var content = (IContent) entity;
|
||||
|
||||
// lazily get previous version
|
||||
IContentBase prevVersion = null;
|
||||
|
||||
// do not load *all* users in memory at once
|
||||
// do not load notifications *per user* (N+1 select)
|
||||
// cannot load users & notifications in 1 query (combination btw User2AppDto and User2NodeNotifyDto)
|
||||
// => get batches of users, get all their notifications in 1 query
|
||||
// re. users:
|
||||
// users being (dis)approved = not an issue, filtered in memory not in SQL
|
||||
// users being modified or created = not an issue, ordering by ID, as long as we don't *insert* low IDs
|
||||
// users being deleted = not an issue for GetNextUsers
|
||||
var id = 0;
|
||||
var nodeIds = content.Path.Split(',').Select(int.Parse).ToArray();
|
||||
const int pagesz = 400; // load batches of 400 users
|
||||
do
|
||||
{
|
||||
// users are returned ordered by id, notifications are returned ordered by user id
|
||||
var users = ((UserService) _userService).GetNextUsers(id, pagesz).Where(x => x.IsApproved).ToList();
|
||||
var notifications = GetUsersNotifications(users.Select(x => x.Id), action, nodeIds, Constants.ObjectTypes.DocumentGuid).ToList();
|
||||
if (notifications.Count == 0) break;
|
||||
|
||||
var i = 0;
|
||||
foreach (var user in users)
|
||||
{
|
||||
// continue if there's no notification for this user
|
||||
if (notifications[i].UserId != user.Id) continue; // next user
|
||||
|
||||
// lazy load prev version
|
||||
if (prevVersion == null)
|
||||
{
|
||||
prevVersion = GetPreviousVersion(entity.Id);
|
||||
}
|
||||
|
||||
// queue notification
|
||||
var req = CreateNotificationRequest(operatingUser, user, content, prevVersion, actionName, http, createSubject, createBody);
|
||||
Enqueue(req);
|
||||
|
||||
// skip other notifications for this user
|
||||
while (i < notifications.Count && notifications[i++].UserId == user.Id) ;
|
||||
if (i >= notifications.Count) break; // break if no more notifications
|
||||
}
|
||||
|
||||
// load more users if any
|
||||
id = users.Count == pagesz ? users.Last().Id + 1 : -1;
|
||||
|
||||
} while (id > 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -107,14 +154,7 @@ namespace Umbraco.Core.Services
|
||||
// lazily get versions
|
||||
var prevVersionDictionary = new Dictionary<int, IContentBase>();
|
||||
|
||||
// do not load *all* users in memory at once
|
||||
// do not load notifications *per user* (N+1 select)
|
||||
// cannot load users & notifications in 1 query (combination btw User2AppDto and User2NodeNotifyDto)
|
||||
// => get batches of users, get all their notifications in 1 query
|
||||
// re. users:
|
||||
// users being (dis)approved = not an issue, filtered in memory not in SQL
|
||||
// users being modified or created = not an issue, ordering by ID, as long as we don't *insert* low IDs
|
||||
// users being deleted = not an issue for GetNextUsers
|
||||
// see notes above
|
||||
var id = 0;
|
||||
const int pagesz = 400; // load batches of 400 users
|
||||
do
|
||||
@@ -616,4 +656,4 @@ namespace Umbraco.Core.Services
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ namespace Umbraco.Core
|
||||
.Reverse()
|
||||
.ToArray();
|
||||
return nodeIds;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes new lines and tabs
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Umbraco.Tests.Migrations.Upgrades
|
||||
catch (Exception)
|
||||
{
|
||||
//if this doesn't work we have to make sure everything is reset! otherwise
|
||||
// we'll run into issues because we've already set some things up
|
||||
// well run into issues because we've already set some things up
|
||||
TearDown();
|
||||
throw;
|
||||
}
|
||||
@@ -83,4 +83,4 @@ namespace Umbraco.Tests.Migrations.Upgrades
|
||||
return SqlScripts.SqlResources.SqlCeTotal_480;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine,
|
||||
var sqlSyntax = new SqlServerSyntaxProvider();
|
||||
|
||||
var indexDefinition = CreateIndexDefinition();
|
||||
indexDefinition.IndexType = IndexTypes.Clustered;
|
||||
indexDefinition.IsClustered = false;
|
||||
|
||||
var actual = sqlSyntax.Format(indexDefinition);
|
||||
Assert.AreEqual("CREATE CLUSTERED INDEX [IX_A] ON [TheTable] ([A])", actual);
|
||||
@@ -159,4 +159,4 @@ WHERE (([umbracoNode].[nodeObjectType] = @0))) x)".Replace(Environment.NewLine,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -288,29 +288,6 @@ namespace Umbraco.Tests.Services
|
||||
Assert.AreEqual(2, membersInRole.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Associate_Members_To_Roles_With_Member_Id_Casing()
|
||||
{
|
||||
ServiceContext.MemberService.AddRole("MyTestRole1");
|
||||
|
||||
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
|
||||
ServiceContext.MemberTypeService.Save(memberType);
|
||||
var member1 = MockedMember.CreateSimpleMember(memberType, "test1", "test1@test.com", "pass", "test1");
|
||||
ServiceContext.MemberService.Save(member1);
|
||||
var member2 = MockedMember.CreateSimpleMember(memberType, "test2", "test2@test.com", "pass", "test2");
|
||||
ServiceContext.MemberService.Save(member2);
|
||||
|
||||
// temp make sure they exist
|
||||
Assert.IsNotNull(ServiceContext.MemberService.GetById(member1.Id));
|
||||
Assert.IsNotNull(ServiceContext.MemberService.GetById(member2.Id));
|
||||
|
||||
ServiceContext.MemberService.AssignRoles(new[] { member1.Id, member2.Id }, new[] { "mytestrole1" });
|
||||
|
||||
var membersInRole = ServiceContext.MemberService.GetMembersInRole("MyTestRole1");
|
||||
|
||||
Assert.AreEqual(2, membersInRole.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Associate_Members_To_Roles_With_Member_Username()
|
||||
{
|
||||
@@ -1202,4 +1179,4 @@ namespace Umbraco.Tests.Services
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,8 +183,8 @@ namespace Umbraco.Tests.TestHelpers
|
||||
{
|
||||
RemoveDatabaseFile(ex =>
|
||||
{
|
||||
//If this doesn't work we have to make sure everything is reset! otherwise
|
||||
// we'll run into issues because we've already set some things up
|
||||
//if this doesn't work we have to make sure everything is reset! otherwise
|
||||
// well run into issues because we've already set some things up
|
||||
TearDown();
|
||||
throw ex;
|
||||
});
|
||||
@@ -435,4 +435,4 @@ namespace Umbraco.Tests.TestHelpers
|
||||
</root>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,9 @@
|
||||
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Examine.0.1.89\lib\net45\Examine.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using HtmlAgilityPack;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
@@ -10,7 +10,6 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Core.Scoping;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
using Umbraco.Web;
|
||||
using Umbraco.Web.Routing;
|
||||
@@ -34,6 +33,14 @@ namespace Umbraco.Tests.Web
|
||||
[TestCase("hello href=\"{localLink:umb://document-type/9931BDE0AAC34BABB838909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")]
|
||||
//this one has an invalid char so won't match
|
||||
[TestCase("hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ")]
|
||||
// with a-tag with data-udi attribute, that needs to be stripped
|
||||
[TestCase("hello <a data-udi=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\"> world</a> ", "hello <a href=\"/my-test-url\"> world</a> ")]
|
||||
// with a-tag with data-udi attribute spelled wrong, so don't need stripping
|
||||
[TestCase("hello <a data-uid=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\"> world</a> ", "hello <a data-uid=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" href=\"/my-test-url\"> world</a> ")]
|
||||
// with a img-tag with data-udi id, that needs to be strippde
|
||||
[TestCase("hello <img data-udi=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" src=\"imageofcats.jpg\"> world ", "hello <img src=\"imageofcats.jpg\"> world ")]
|
||||
// with a img-tag with data-udi id spelled wrong, so don't need stripping
|
||||
[TestCase("hello <img data-uid=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" src=\"imageofcats.jpg\"> world ", "hello <img data-uid=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" src=\"imageofcats.jpg\"> world ")]
|
||||
public void ParseLocalLinks(string input, string result)
|
||||
{
|
||||
var serviceCtxMock = MockHelper.GetMockedServiceContext();
|
||||
@@ -63,7 +70,7 @@ namespace Umbraco.Tests.Web
|
||||
//setup a quick mock of the WebRouting section
|
||||
Mock.Of<IUmbracoSettingsSection>(section => section.WebRouting == Mock.Of<IWebRoutingSection>(routingSection => routingSection.UrlProviderMode == "AutoLegacy")),
|
||||
//pass in the custom url provider
|
||||
new[]{ testUrlProvider.Object },
|
||||
new[] { testUrlProvider.Object },
|
||||
true))
|
||||
{
|
||||
var output = TemplateUtilities.ParseInternalLinks(input, umbCtx.UrlProvider);
|
||||
@@ -71,5 +78,27 @@ namespace Umbraco.Tests.Web
|
||||
Assert.AreEqual(result, output);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StripDataUdiAttributesUsingSrtringOnLinks()
|
||||
{
|
||||
var input = "hello <a data-udi=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" href=\"/my-test-url\"> world</a> ";
|
||||
var expected = "hello <a href=\"/my-test-url\"> world</a> ";
|
||||
|
||||
var result = TemplateUtilities.StripUdiDataAttributes(input);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void StripDataUdiAttributesUsingStringOnImages()
|
||||
{
|
||||
var input = "hello <img data-udi=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" src=\"imageofcats.jpg\"> world ";
|
||||
var expected = "hello <img src=\"imageofcats.jpg\"> world ";
|
||||
|
||||
var result = TemplateUtilities.StripUdiDataAttributes(input);
|
||||
|
||||
Assert.AreEqual(expected, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
|
||||
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
|
||||
<package id="Examine" version="0.1.89" targetFramework="net45" />
|
||||
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net45" />
|
||||
<package id="Log4Net.Async" version="2.0.4" targetFramework="net45" />
|
||||
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
|
||||
|
||||
@@ -31,10 +31,7 @@
|
||||
"moment": "~2.10.3",
|
||||
"ace-builds": "^1.2.3",
|
||||
"clipboard": "1.7.1",
|
||||
"font-awesome": "~4.7"
|
||||
},
|
||||
"resolutions": {
|
||||
"font-awesome": "~4.7"
|
||||
"font-awesome": "~4.2"
|
||||
},
|
||||
"install": {
|
||||
"path": "lib-bower",
|
||||
@@ -46,11 +43,11 @@
|
||||
],
|
||||
"sources": {
|
||||
"moment": [
|
||||
"bower_components/moment/min/moment.min.js",
|
||||
"bower_components/moment/min/moment-with-locales.js",
|
||||
"bower_components/moment/min/moment-with-locales.min.js",
|
||||
"bower_components/moment/locale/*.js"
|
||||
],
|
||||
"bower_components/moment/min/moment.min.js",
|
||||
"bower_components/moment/min/moment-with-locales.js",
|
||||
"bower_components/moment/min/moment-with-locales.min.js",
|
||||
"bower_components/moment/locale/*.js"
|
||||
],
|
||||
"underscore": [
|
||||
"bower_components/underscore/underscore-min.js",
|
||||
"bower_components/underscore/underscore-min.map"
|
||||
|
||||
@@ -150,8 +150,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Application");
|
||||
sourceUrl: currentMenuNode.childNodesUrl,
|
||||
updateDefinition: function() {
|
||||
throw "'updateDefinition' method is not supported in Umbraco 7, consider upgrading to the new v7 APIs";
|
||||
},
|
||||
expanded: currentMenuNode.expanded === true
|
||||
}
|
||||
};
|
||||
//defined getters that will throw a not implemented/supported exception
|
||||
Object.defineProperty(legacyNode, "menu", {
|
||||
|
||||
+4552
-5610
File diff suppressed because it is too large
Load Diff
@@ -11,10 +11,10 @@
|
||||
"cssnano": "^3.7.6",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-concat": "^2.6.0",
|
||||
"gulp-connect": "5.6.1",
|
||||
"gulp-connect": "5.0.0",
|
||||
"gulp-eslint": "^5.0.0",
|
||||
"gulp-imagemin": "^4.1.0",
|
||||
"gulp-less": "^4.0.1",
|
||||
"gulp-less": "^3.5.0",
|
||||
"gulp-ngdocs": "^0.3.0",
|
||||
"gulp-open": "^2.1.0",
|
||||
"gulp-postcss": "^6.2.0",
|
||||
@@ -24,14 +24,12 @@
|
||||
"gulp-wrap": "^0.13.0",
|
||||
"gulp-wrap-js": "^0.4.1",
|
||||
"jasmine-core": "2.5.2",
|
||||
"karma": "^3.1.3",
|
||||
"karma": "^1.7.0",
|
||||
"karma-jasmine": "^1.1.1",
|
||||
"karma-phantomjs-launcher": "^1.0.4",
|
||||
"less": "^3.9.0",
|
||||
"less": "^2.7.3",
|
||||
"lodash": "^4.17.5",
|
||||
"merge-stream": "^1.0.1",
|
||||
"run-sequence": "^2.2.1",
|
||||
"marked": "^0.5.2",
|
||||
"event-stream": "3.3.4"
|
||||
"run-sequence": "^2.2.1"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-14
@@ -1,17 +1,4 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbTourStep
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
<b>Added in Umbraco 7.8</b>. The tour step component is a component that can be used in custom views for tour steps.
|
||||
|
||||
@param {callback} onClose The callback which should be performened when the close button of the tour step is clicked
|
||||
@param {boolean=} hideClose A boolean indicating if the close button needs to be shown
|
||||
|
||||
**/
|
||||
(function () {
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function TourStepDirective() {
|
||||
|
||||
+1
-14
@@ -1,17 +1,4 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbTourStepContent
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
<b>Added in Umbraco 7.8</b>. The tour step content component is a component that can be used in custom views for tour steps.
|
||||
It's meant to be used in the umb-tour-step directive.
|
||||
All markup in the body of the directive will be shown after the content attribute
|
||||
|
||||
@param {string} content The content that needs to be shown
|
||||
**/
|
||||
(function () {
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function TourStepContentDirective() {
|
||||
|
||||
+1
-15
@@ -1,18 +1,4 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbTourStepCounter
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
<b>Added in Umbraco 7.8</b>. The tour step counter component is a component that can be used in custom views for tour steps.
|
||||
It's meant to be used in the umb-tour-step-footer directive. It will show the progress you have made in a tour eg. step 2/12
|
||||
|
||||
|
||||
@param {int} currentStep The current step the tour is on
|
||||
@param {int} totalSteps The current step the tour is on
|
||||
**/
|
||||
(function () {
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function TourStepCounterDirective() {
|
||||
|
||||
+1
-13
@@ -1,16 +1,4 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbTourStepFooter
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
<b>Added in Umbraco 7.8</b>. The tour step footer component is a component that can be used in custom views for tour steps. It's meant to be used in the umb-tour-step directive.
|
||||
All markup in the body of the directive will be shown as the footer of the tour step
|
||||
|
||||
|
||||
**/
|
||||
(function () {
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function TourStepFooterDirective() {
|
||||
|
||||
+1
-13
@@ -1,16 +1,4 @@
|
||||
/**
|
||||
@ngdoc directive
|
||||
@name umbraco.directives.directive:umbTourStepHeader
|
||||
@restrict E
|
||||
@scope
|
||||
|
||||
@description
|
||||
<b>Added in Umbraco 7.8</b>. The tour step header component is a component that can be used in custom views for tour steps. It's meant to be used in the umb-tour-step directive.
|
||||
|
||||
|
||||
@param {string} title The title that needs to be shown
|
||||
**/
|
||||
(function () {
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function TourStepHeaderDirective() {
|
||||
|
||||
+1
-1
@@ -252,7 +252,7 @@ Use this directive to construct a header inside the main editor window.
|
||||
icon: "=",
|
||||
hideIcon: "@",
|
||||
alias: "=",
|
||||
hideAlias: "=",
|
||||
hideAlias: "@",
|
||||
description: "=",
|
||||
hideDescription: "@",
|
||||
descriptionLocked: "@",
|
||||
|
||||
+3
-19
@@ -1,5 +1,5 @@
|
||||
angular.module("umbraco.directives")
|
||||
.directive('gridRte', function (tinyMceService, stylesheetResource, angularHelper, assetsService, $q, $timeout, eventsService) {
|
||||
.directive('gridRte', function (tinyMceService, stylesheetResource, angularHelper, assetsService, $q, $timeout) {
|
||||
return {
|
||||
scope: {
|
||||
uniqueId: '=',
|
||||
@@ -362,23 +362,8 @@ angular.module("umbraco.directives")
|
||||
// tinyMceEditor.fire('LoadContent', null);
|
||||
//};
|
||||
|
||||
|
||||
var tabShownListener = eventsService.on("app.tabChange", function (e, args) {
|
||||
|
||||
var tabId = args.id;
|
||||
var myTabId = element.closest(".umb-tab-pane").attr("rel");
|
||||
|
||||
if (String(tabId) === myTabId) {
|
||||
//the tab has been shown, trigger the mceAutoResize (as it could have timed out before the tab was shown)
|
||||
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
|
||||
tinyMceEditor.execCommand('mceAutoResize', false, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//listen for formSubmitting event (the result is callback used to remove the event subscription)
|
||||
var formSubmittingListener = scope.$on("formSubmitting", function () {
|
||||
var unsubscribe = scope.$on("formSubmitting", function () {
|
||||
//TODO: Here we should parse out the macro rendered content so we can save on a lot of bytes in data xfer
|
||||
// we do parse it out on the server side but would be nice to do that on the client side before as well.
|
||||
scope.value = tinyMceEditor ? tinyMceEditor.getContent() : null;
|
||||
@@ -388,8 +373,7 @@ angular.module("umbraco.directives")
|
||||
// NOTE: this is very important otherwise if this is part of a modal, the listener still exists because the dom
|
||||
// element might still be there even after the modal has been hidden.
|
||||
scope.$on('$destroy', function () {
|
||||
formSubmittingListener();
|
||||
eventsService.unsubscribe(tabShownListener);
|
||||
unsubscribe();
|
||||
if (tinyMceEditor !== undefined && tinyMceEditor != null) {
|
||||
tinyMceEditor.destroy()
|
||||
}
|
||||
|
||||
+18
-34
@@ -14,7 +14,7 @@ angular.module("umbraco.directives")
|
||||
scope: {
|
||||
src: '=',
|
||||
center: "=",
|
||||
onImageLoaded: "&"
|
||||
onImageLoaded: "="
|
||||
},
|
||||
link: function(scope, element, attrs) {
|
||||
|
||||
@@ -56,17 +56,23 @@ angular.module("umbraco.directives")
|
||||
};
|
||||
|
||||
var setDimensions = function () {
|
||||
if (scope.isCroppable) {
|
||||
scope.dimensions.width = $image.width();
|
||||
scope.dimensions.height = $image.height();
|
||||
|
||||
if(scope.center){
|
||||
scope.dimensions.left = scope.center.left * scope.dimensions.width -10;
|
||||
scope.dimensions.top = scope.center.top * scope.dimensions.height -10;
|
||||
}else{
|
||||
scope.center = { left: 0.5, top: 0.5 };
|
||||
}
|
||||
if (scope.src.endsWith(".svg")) {
|
||||
// svg files don't automatically get a size by
|
||||
// loading them set a default size for now
|
||||
$image.attr("width", "200");
|
||||
$image.attr("height", "200");
|
||||
// can't crop an svg file, don't show the focal point
|
||||
$overlay.remove();
|
||||
}
|
||||
scope.dimensions.width = $image.width();
|
||||
scope.dimensions.height = $image.height();
|
||||
|
||||
if(scope.center){
|
||||
scope.dimensions.left = scope.center.left * scope.dimensions.width -10;
|
||||
scope.dimensions.top = scope.center.top * scope.dimensions.height -10;
|
||||
}else{
|
||||
scope.center = { left: 0.5, top: 0.5 };
|
||||
}
|
||||
};
|
||||
|
||||
var calculateGravity = function(offsetX, offsetY){
|
||||
@@ -107,32 +113,10 @@ angular.module("umbraco.directives")
|
||||
//// INIT /////
|
||||
$image.load(function() {
|
||||
$timeout(function() {
|
||||
scope.isCroppable = true;
|
||||
scope.hasDimensions = true;
|
||||
|
||||
if (scope.src) {
|
||||
if (scope.src.endsWith(".svg")) {
|
||||
scope.isCroppable = false;
|
||||
scope.hasDimensions = false;
|
||||
} else {
|
||||
// From: https://stackoverflow.com/a/51789597/5018
|
||||
var type = scope.src.substring(scope.src.indexOf("/") + 1, scope.src.indexOf(";base64"));
|
||||
if (type.startsWith("svg")) {
|
||||
scope.isCroppable = false;
|
||||
scope.hasDimensions = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDimensions();
|
||||
scope.loaded = true;
|
||||
if (angular.isFunction(scope.onImageLoaded)) {
|
||||
scope.onImageLoaded(
|
||||
{
|
||||
"isCroppable": scope.isCroppable,
|
||||
"hasDimensions": scope.hasDimensions
|
||||
}
|
||||
);
|
||||
scope.onImageLoaded();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+3
-11
@@ -135,19 +135,11 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
|
||||
//is this the current action node (this is not the same as the current selected node!)
|
||||
var actionNode = appState.getMenuState("currentNode");
|
||||
var actionNode = appState.getMenuState("currentNode");
|
||||
if(actionNode) {
|
||||
|
||||
if(actionNode.id === node.id && actionNode.id !== "-1") {
|
||||
if(actionNode.id === node.id) {
|
||||
css.push("active");
|
||||
}
|
||||
|
||||
// special handling of root nodes with id -1
|
||||
// as there can be many nodes with id -1 in a tree we need to check the treeAlias instead
|
||||
if(actionNode.id === "-1" && actionNode.metaData.treeAlias === node.metaData.treeAlias) {
|
||||
css.push("active");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return css.join(" ");
|
||||
|
||||
+4
-18
@@ -48,7 +48,7 @@ the directive will use {@link umbraco.directives.directive:umbLockedField umbLoc
|
||||
**/
|
||||
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbGenerateAlias', function ($timeout, entityResource, localizationService) {
|
||||
.directive('umbGenerateAlias', function ($timeout, entityResource) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: 'views/components/umb-generate-alias.html',
|
||||
@@ -67,21 +67,7 @@ angular.module("umbraco.directives")
|
||||
var updateAlias = false;
|
||||
|
||||
scope.locked = true;
|
||||
|
||||
scope.labels = {
|
||||
idle: "Enter alias...",
|
||||
busy: "Generating alias..."
|
||||
};
|
||||
|
||||
scope.placeholderText = scope.labels.idle;
|
||||
|
||||
localizationService.localize('placeholders_enterAlias').then(function (value) {
|
||||
scope.labels.idle = scope.placeholderText = value;
|
||||
});
|
||||
|
||||
localizationService.localize('placeholders_generatingAlias').then(function (value) {
|
||||
scope.labels.busy = value;
|
||||
});
|
||||
scope.placeholderText = "Enter alias...";
|
||||
|
||||
function generateAlias(value) {
|
||||
|
||||
@@ -92,7 +78,7 @@ angular.module("umbraco.directives")
|
||||
if( value !== undefined && value !== "" && value !== null) {
|
||||
|
||||
scope.alias = "";
|
||||
scope.placeholderText = scope.labels.busy;
|
||||
scope.placeholderText = "Generating Alias...";
|
||||
|
||||
generateAliasTimeout = $timeout(function () {
|
||||
updateAlias = true;
|
||||
@@ -106,7 +92,7 @@ angular.module("umbraco.directives")
|
||||
} else {
|
||||
updateAlias = true;
|
||||
scope.alias = "";
|
||||
scope.placeholderText = scope.labels.idle;
|
||||
scope.placeholderText = "Enter alias...";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-19
@@ -125,20 +125,6 @@ Use this directive to generate a thumbnail grid of media items.
|
||||
i--;
|
||||
}
|
||||
|
||||
|
||||
// If subfolder search is not enabled remove the media items that's not needed
|
||||
// Make sure that includeSubFolder is not undefined since the directive is used
|
||||
// in contexts where it should not be used. Currently only used when we trigger
|
||||
// a media picker
|
||||
if(scope.includeSubFolders !== undefined){
|
||||
if (scope.includeSubFolders !== 'true') {
|
||||
if (item.parentId !== parseInt(scope.currentFolderId)) {
|
||||
scope.items.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (scope.items.length > 0) {
|
||||
@@ -158,7 +144,7 @@ Use this directive to generate a thumbnail grid of media items.
|
||||
}
|
||||
|
||||
if (!item.isFolder) {
|
||||
|
||||
|
||||
// handle entity
|
||||
if(item.image) {
|
||||
item.thumbnail = mediaHelper.resolveFileFromEntity(item, true);
|
||||
@@ -167,7 +153,7 @@ Use this directive to generate a thumbnail grid of media items.
|
||||
} else {
|
||||
item.thumbnail = mediaHelper.resolveFile(item, true);
|
||||
item.image = mediaHelper.resolveFile(item, false);
|
||||
|
||||
|
||||
var fileProp = _.find(item.properties, function (v) {
|
||||
return (v.alias === "umbracoFile");
|
||||
});
|
||||
@@ -321,9 +307,7 @@ Use this directive to generate a thumbnail grid of media items.
|
||||
itemMaxHeight: "@",
|
||||
itemMinWidth: "@",
|
||||
itemMinHeight: "@",
|
||||
onlyImages: "@",
|
||||
includeSubFolders: "@",
|
||||
currentFolderId: "@"
|
||||
onlyImages: "@"
|
||||
},
|
||||
link: link
|
||||
};
|
||||
|
||||
@@ -13,8 +13,8 @@ function valTab() {
|
||||
link: function (scope, element, attr, ctrs) {
|
||||
|
||||
var valFormManager = ctrs[1];
|
||||
var tabId = "tab" + scope.tab.id;
|
||||
scope.tabHasError = false;
|
||||
var tabId = "tab" + scope.tab.id;
|
||||
scope.tabHasError = false;
|
||||
|
||||
//listen for form validation changes
|
||||
valFormManager.onValidationStatusChanged(function (evt, args) {
|
||||
@@ -31,7 +31,8 @@ function valTab() {
|
||||
scope.tabHasError = false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.directives.validation').directive("valTab", valTab);
|
||||
angular.module('umbraco.directives.validation').directive("valTab", valTab);
|
||||
@@ -46,7 +46,7 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* .then(function() {
|
||||
* $scope.complete = true;
|
||||
* });
|
||||
* </pre>
|
||||
* </pre>
|
||||
* @param {Object} args arguments object
|
||||
* @param {Int} args.parentId the ID of the parent node
|
||||
* @param {Array} options.sortedIds array of node IDs as they should be sorted
|
||||
@@ -87,9 +87,9 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* .then(function() {
|
||||
* alert("node was moved");
|
||||
* }, function(err){
|
||||
* alert("node didnt move:" + err.data.Message);
|
||||
* alert("node didnt move:" + err.data.Message);
|
||||
* });
|
||||
* </pre>
|
||||
* </pre>
|
||||
* @param {Object} args arguments object
|
||||
* @param {Int} args.idd the ID of the node to move
|
||||
* @param {Int} args.parentId the ID of the parent node to move to
|
||||
@@ -109,34 +109,11 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaApiBaseUrl", "PostMove"),
|
||||
{
|
||||
parentId: args.parentId,
|
||||
id: args.id
|
||||
}),
|
||||
{
|
||||
error: function(data){
|
||||
var errorMsg = 'Failed to move media';
|
||||
if (data.id !== undefined && data.parentId !== undefined) {
|
||||
if (data.id === data.parentId) {
|
||||
errorMsg = 'Media can\'t be moved into itself';
|
||||
}
|
||||
}
|
||||
else if (data.notifications !== undefined) {
|
||||
if (data.notifications.length > 0) {
|
||||
if (data.notifications[0].header.length > 0) {
|
||||
errorMsg = data.notifications[0].header;
|
||||
}
|
||||
if (data.notifications[0].message.length > 0) {
|
||||
errorMsg = errorMsg + ": " + data.notifications[0].message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
errorMsg: errorMsg
|
||||
};
|
||||
}
|
||||
});
|
||||
{
|
||||
parentId: args.parentId,
|
||||
id: args.id
|
||||
}),
|
||||
'Failed to move media');
|
||||
},
|
||||
|
||||
|
||||
@@ -152,12 +129,12 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* <pre>
|
||||
* mediaResource.getById(1234)
|
||||
* .then(function(media) {
|
||||
* var myMedia = media;
|
||||
* var myMedia = media;
|
||||
* alert('its here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id id of media item to return
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id id of media item to return
|
||||
* @returns {Promise} resourcePromise object containing the media item.
|
||||
*
|
||||
*/
|
||||
@@ -186,9 +163,9 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* .then(function() {
|
||||
* alert('its gone!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id id of media item to delete
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} id id of media item to delete
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
@@ -214,12 +191,12 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* <pre>
|
||||
* mediaResource.getByIds( [1234,2526,28262])
|
||||
* .then(function(mediaArray) {
|
||||
* var myDoc = contentArray;
|
||||
* var myDoc = contentArray;
|
||||
* alert('they are here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} ids ids of media items to return as an array
|
||||
* </pre>
|
||||
*
|
||||
* @param {Array} ids ids of media items to return as an array
|
||||
* @returns {Promise} resourcePromise object containing the media items array.
|
||||
*
|
||||
*/
|
||||
@@ -246,28 +223,28 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*
|
||||
* @description
|
||||
* Returns a scaffold of an empty media item, given the id of the media item to place it underneath and the media type alias.
|
||||
*
|
||||
*
|
||||
* - Parent Id must be provided so umbraco knows where to store the media
|
||||
* - Media Type alias must be provided so umbraco knows which properties to put on the media scaffold
|
||||
*
|
||||
* - Media Type alias must be provided so umbraco knows which properties to put on the media scaffold
|
||||
*
|
||||
* The scaffold is used to build editors for media that has not yet been populated with data.
|
||||
*
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaResource.getScaffold(1234, 'folder')
|
||||
* .then(function(scaffold) {
|
||||
* var myDoc = scaffold;
|
||||
* myDoc.name = "My new media item";
|
||||
* myDoc.name = "My new media item";
|
||||
*
|
||||
* mediaResource.save(myDoc, true)
|
||||
* .then(function(media){
|
||||
* alert("Retrieved, updated and saved again");
|
||||
* });
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} parentId id of media item to return
|
||||
* @param {String} alias mediatype alias to base the scaffold on
|
||||
* @param {String} alias mediatype alias to base the scaffold on
|
||||
* @returns {Promise} resourcePromise object containing the media scaffold.
|
||||
*
|
||||
*/
|
||||
@@ -306,11 +283,11 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* <pre>
|
||||
* mediaResource.getChildren(1234, {pageSize: 10, pageNumber: 2})
|
||||
* .then(function(contentArray) {
|
||||
* var children = contentArray;
|
||||
* var children = contentArray;
|
||||
* alert('they are here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @param {Int} parentid id of content item to return children of
|
||||
* @param {Object} options optional options object
|
||||
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 0
|
||||
@@ -384,9 +361,9 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*
|
||||
* @description
|
||||
* Saves changes made to a media item, if the media item is new, the isNew paramater must be passed to force creation
|
||||
* if the media item needs to have files attached, they must be provided as the files param and passed separately
|
||||
*
|
||||
*
|
||||
* if the media item needs to have files attached, they must be provided as the files param and passed separately
|
||||
*
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaResource.getById(1234)
|
||||
@@ -397,11 +374,11 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* alert("Retrieved, updated and saved again");
|
||||
* });
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @param {Object} media The media item object with changes applied
|
||||
* @param {Bool} isNew set to true to create a new item or to update an existing
|
||||
* @param {Array} files collection of files for the media item
|
||||
* @param {Bool} isNew set to true to create a new item or to update an existing
|
||||
* @param {Array} files collection of files for the media item
|
||||
* @returns {Promise} resourcePromise object containing the saved media item.
|
||||
*
|
||||
*/
|
||||
@@ -423,10 +400,10 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* .then(function(folder) {
|
||||
* alert('New folder');
|
||||
* });
|
||||
* </pre>
|
||||
* </pre>
|
||||
*
|
||||
* @param {string} name Name of the folder to create
|
||||
* @param {int} parentId Id of the media item to create the folder underneath
|
||||
* @param {int} parentId Id of the media item to create the folder underneath
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
@@ -450,18 +427,18 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* Retrieves all media children with types used as folders.
|
||||
* Uses the convention of looking for media items with mediaTypes ending in
|
||||
* *Folder so will match "Folder", "bannerFolder", "secureFolder" etc,
|
||||
*
|
||||
*
|
||||
* NOTE: This will return a max of 500 folders, if more is required it needs to be paged
|
||||
*
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaResource.getChildFolders(1234)
|
||||
* .then(function(data) {
|
||||
* alert('folders');
|
||||
* });
|
||||
* </pre>
|
||||
* </pre>
|
||||
*
|
||||
* @param {int} parentId Id of the media item to query for child folders
|
||||
* @param {int} parentId Id of the media item to query for child folders
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
@@ -496,8 +473,8 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* .then(function() {
|
||||
* alert('its empty!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
@@ -524,8 +501,8 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
* .then(function(searchResult) {
|
||||
* alert('it's here!');
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @param {string} query The search query
|
||||
* @param {int} pageNumber The page number
|
||||
* @param {int} pageSize The number of media items on a page
|
||||
@@ -536,7 +513,7 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
search: function (query, pageNumber, pageSize, searchFrom) {
|
||||
|
||||
var args = [
|
||||
{ "query": query },
|
||||
{ "query": query },
|
||||
{ "pageNumber": pageNumber },
|
||||
{ "pageSize": pageSize },
|
||||
{ "searchFrom": searchFrom }
|
||||
|
||||
@@ -1,272 +1,264 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.mediaTypeResource
|
||||
* @description Loads in data for media types
|
||||
**/
|
||||
function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter, localizationService) {
|
||||
|
||||
return {
|
||||
|
||||
getCount: function () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetCount")),
|
||||
'Failed to retrieve count');
|
||||
},
|
||||
|
||||
getAvailableCompositeContentTypes: function (contentTypeId, filterContentTypes, filterPropertyTypes) {
|
||||
if (!filterContentTypes) {
|
||||
filterContentTypes = [];
|
||||
}
|
||||
if (!filterPropertyTypes) {
|
||||
filterPropertyTypes = [];
|
||||
}
|
||||
|
||||
var query = {
|
||||
contentTypeId: contentTypeId,
|
||||
filterContentTypes: filterContentTypes,
|
||||
filterPropertyTypes: filterPropertyTypes
|
||||
};
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetAvailableCompositeMediaTypes"),
|
||||
query),
|
||||
'Failed to retrieve data for content type id ' + contentTypeId);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaTypeResource#getWhereCompositionIsUsedInContentTypes
|
||||
* @methodOf umbraco.resources.mediaTypeResource
|
||||
*
|
||||
* @description
|
||||
* Returns a list of media types which use a specific composition with a given id
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaTypeResource.getWhereCompositionIsUsedInContentTypes(1234)
|
||||
* .then(function(mediaTypeList) {
|
||||
* console.log(mediaTypeList);
|
||||
* });
|
||||
* </pre>
|
||||
* @param {Int} contentTypeId id of the composition content type to retrieve the list of the media types where it has been used
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getWhereCompositionIsUsedInContentTypes: function (contentTypeId) {
|
||||
var query = {
|
||||
contentTypeId: contentTypeId
|
||||
};
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetWhereCompositionIsUsedInContentTypes"),
|
||||
query),
|
||||
'Failed to retrieve data for content type id ' + contentTypeId);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaTypeResource#getAllowedTypes
|
||||
* @methodOf umbraco.resources.mediaTypeResource
|
||||
*
|
||||
* @description
|
||||
* Returns a list of allowed media types underneath a media item with a given ID
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaTypeResource.getAllowedTypes(1234)
|
||||
* .then(function(array) {
|
||||
* $scope.type = type;
|
||||
* });
|
||||
* </pre>
|
||||
* @param {Int} mediaId id of the media item to retrive allowed child types for
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getAllowedTypes: function (mediaId) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetAllowedChildren",
|
||||
[{ contentId: mediaId }])),
|
||||
'Failed to retrieve allowed types for media id ' + mediaId);
|
||||
},
|
||||
|
||||
getById: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetById",
|
||||
[{ id: id }])),
|
||||
'Failed to retrieve content type');
|
||||
},
|
||||
|
||||
getAll: function () {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetAll")),
|
||||
'Failed to retrieve all content types');
|
||||
},
|
||||
|
||||
getScaffold: function (parentId) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetEmpty", { parentId: parentId })),
|
||||
'Failed to retrieve content type scaffold');
|
||||
},
|
||||
|
||||
deleteById: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"DeleteById",
|
||||
[{ id: id }])),
|
||||
'Failed to retrieve content type');
|
||||
},
|
||||
|
||||
deleteContainerById: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"DeleteContainer",
|
||||
[{ id: id }])),
|
||||
'Failed to delete content type contaier');
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaTypeResource#save
|
||||
* @methodOf umbraco.resources.mediaTypeResource
|
||||
*
|
||||
* @description
|
||||
* Saves or update a media type
|
||||
*
|
||||
* @param {Object} content data type object to create/update
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
save: function (contentType) {
|
||||
|
||||
var saveModel = umbDataFormatter.formatContentTypePostData(contentType);
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostSave"), saveModel),
|
||||
'Failed to save data for content type id ' + contentType.id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaTypeResource#move
|
||||
* @methodOf umbraco.resources.mediaTypeResource
|
||||
*
|
||||
* @description
|
||||
* Moves a node underneath a new parentId
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaTypeResource.move({ parentId: 1244, id: 123 })
|
||||
* .then(function() {
|
||||
* alert("node was moved");
|
||||
* }, function(err){
|
||||
* alert("node didnt move:" + err.data.Message);
|
||||
* });
|
||||
* </pre>
|
||||
* @param {Object} args arguments object
|
||||
* @param {Int} args.idd the ID of the node to move
|
||||
* @param {Int} args.parentId the ID of the parent node to move to
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
move: function (args) {
|
||||
if (!args) {
|
||||
throw "args cannot be null";
|
||||
}
|
||||
if (!args.parentId) {
|
||||
throw "args.parentId cannot be null";
|
||||
}
|
||||
if (!args.id) {
|
||||
throw "args.id cannot be null";
|
||||
}
|
||||
|
||||
var promise = localizationService.localize("media_moveFailed");
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostMove"),
|
||||
{
|
||||
parentId: args.parentId,
|
||||
id: args.id
|
||||
}),
|
||||
promise);
|
||||
},
|
||||
|
||||
copy: function (args) {
|
||||
if (!args) {
|
||||
throw "args cannot be null";
|
||||
}
|
||||
if (!args.parentId) {
|
||||
throw "args.parentId cannot be null";
|
||||
}
|
||||
if (!args.id) {
|
||||
throw "args.id cannot be null";
|
||||
}
|
||||
|
||||
var promise = localizationService.localize("media_copyFailed");
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostCopy"),
|
||||
{
|
||||
parentId: args.parentId,
|
||||
id: args.id
|
||||
}),
|
||||
promise);
|
||||
},
|
||||
|
||||
createContainer: function(parentId, name) {
|
||||
|
||||
var promise = localizationService.localize("media_createFolderFailed", [parentId]);
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"PostCreateContainer",
|
||||
{ parentId: parentId, name: encodeURIComponent(name) })),
|
||||
promise);
|
||||
},
|
||||
|
||||
renameContainer: function (id, name) {
|
||||
|
||||
var promise = localizationService.localize("media_renameFolderFailed", [id]);
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl",
|
||||
"PostRenameContainer",
|
||||
{ id: id, name: name })),
|
||||
promise
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.resources').factory('mediaTypeResource', mediaTypeResource);
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.resources.mediaTypeResource
|
||||
* @description Loads in data for media types
|
||||
**/
|
||||
function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
|
||||
|
||||
return {
|
||||
|
||||
getCount: function () {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetCount")),
|
||||
'Failed to retrieve count');
|
||||
},
|
||||
|
||||
getAvailableCompositeContentTypes: function (contentTypeId, filterContentTypes, filterPropertyTypes) {
|
||||
if (!filterContentTypes) {
|
||||
filterContentTypes = [];
|
||||
}
|
||||
if (!filterPropertyTypes) {
|
||||
filterPropertyTypes = [];
|
||||
}
|
||||
|
||||
var query = {
|
||||
contentTypeId: contentTypeId,
|
||||
filterContentTypes: filterContentTypes,
|
||||
filterPropertyTypes: filterPropertyTypes
|
||||
};
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetAvailableCompositeMediaTypes"),
|
||||
query),
|
||||
'Failed to retrieve data for content type id ' + contentTypeId);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaTypeResource#getWhereCompositionIsUsedInContentTypes
|
||||
* @methodOf umbraco.resources.mediaTypeResource
|
||||
*
|
||||
* @description
|
||||
* Returns a list of media types which use a specific composition with a given id
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaTypeResource.getWhereCompositionIsUsedInContentTypes(1234)
|
||||
* .then(function(mediaTypeList) {
|
||||
* console.log(mediaTypeList);
|
||||
* });
|
||||
* </pre>
|
||||
* @param {Int} contentTypeId id of the composition content type to retrieve the list of the media types where it has been used
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getWhereCompositionIsUsedInContentTypes: function (contentTypeId) {
|
||||
var query = {
|
||||
contentTypeId: contentTypeId
|
||||
};
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetWhereCompositionIsUsedInContentTypes"),
|
||||
query),
|
||||
'Failed to retrieve data for content type id ' + contentTypeId);
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaTypeResource#getAllowedTypes
|
||||
* @methodOf umbraco.resources.mediaTypeResource
|
||||
*
|
||||
* @description
|
||||
* Returns a list of allowed media types underneath a media item with a given ID
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaTypeResource.getAllowedTypes(1234)
|
||||
* .then(function(array) {
|
||||
* $scope.type = type;
|
||||
* });
|
||||
* </pre>
|
||||
* @param {Int} mediaId id of the media item to retrive allowed child types for
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
getAllowedTypes: function (mediaId) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetAllowedChildren",
|
||||
[{ contentId: mediaId }])),
|
||||
'Failed to retrieve allowed types for media id ' + mediaId);
|
||||
},
|
||||
|
||||
getById: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetById",
|
||||
[{ id: id }])),
|
||||
'Failed to retrieve content type');
|
||||
},
|
||||
|
||||
getAll: function () {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetAll")),
|
||||
'Failed to retrieve all content types');
|
||||
},
|
||||
|
||||
getScaffold: function (parentId) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"GetEmpty", { parentId: parentId })),
|
||||
'Failed to retrieve content type scaffold');
|
||||
},
|
||||
|
||||
deleteById: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"DeleteById",
|
||||
[{ id: id }])),
|
||||
'Failed to retrieve content type');
|
||||
},
|
||||
|
||||
deleteContainerById: function (id) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"DeleteContainer",
|
||||
[{ id: id }])),
|
||||
'Failed to delete content type contaier');
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaTypeResource#save
|
||||
* @methodOf umbraco.resources.mediaTypeResource
|
||||
*
|
||||
* @description
|
||||
* Saves or update a media type
|
||||
*
|
||||
* @param {Object} content data type object to create/update
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
save: function (contentType) {
|
||||
|
||||
var saveModel = umbDataFormatter.formatContentTypePostData(contentType);
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostSave"), saveModel),
|
||||
'Failed to save data for content type id ' + contentType.id);
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.resources.mediaTypeResource#move
|
||||
* @methodOf umbraco.resources.mediaTypeResource
|
||||
*
|
||||
* @description
|
||||
* Moves a node underneath a new parentId
|
||||
*
|
||||
* ##usage
|
||||
* <pre>
|
||||
* mediaTypeResource.move({ parentId: 1244, id: 123 })
|
||||
* .then(function() {
|
||||
* alert("node was moved");
|
||||
* }, function(err){
|
||||
* alert("node didnt move:" + err.data.Message);
|
||||
* });
|
||||
* </pre>
|
||||
* @param {Object} args arguments object
|
||||
* @param {Int} args.idd the ID of the node to move
|
||||
* @param {Int} args.parentId the ID of the parent node to move to
|
||||
* @returns {Promise} resourcePromise object.
|
||||
*
|
||||
*/
|
||||
move: function (args) {
|
||||
if (!args) {
|
||||
throw "args cannot be null";
|
||||
}
|
||||
if (!args.parentId) {
|
||||
throw "args.parentId cannot be null";
|
||||
}
|
||||
if (!args.id) {
|
||||
throw "args.id cannot be null";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostMove"),
|
||||
{
|
||||
parentId: args.parentId,
|
||||
id: args.id
|
||||
}),
|
||||
'Failed to move content');
|
||||
},
|
||||
|
||||
copy: function (args) {
|
||||
if (!args) {
|
||||
throw "args cannot be null";
|
||||
}
|
||||
if (!args.parentId) {
|
||||
throw "args.parentId cannot be null";
|
||||
}
|
||||
if (!args.id) {
|
||||
throw "args.id cannot be null";
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl", "PostCopy"),
|
||||
{
|
||||
parentId: args.parentId,
|
||||
id: args.id
|
||||
}),
|
||||
'Failed to copy content');
|
||||
},
|
||||
|
||||
createContainer: function(parentId, name) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"mediaTypeApiBaseUrl",
|
||||
"PostCreateContainer",
|
||||
{ parentId: parentId, name: encodeURIComponent(name) })),
|
||||
'Failed to create a folder under parent id ' + parentId);
|
||||
},
|
||||
|
||||
renameContainer: function (id, name) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(umbRequestHelper.getApiUrl("mediaTypeApiBaseUrl",
|
||||
"PostRenameContainer",
|
||||
{ id: id, name: name })),
|
||||
"Failed to rename the folder with id " + id
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.resources').factory('mediaTypeResource', mediaTypeResource);
|
||||
|
||||
@@ -253,9 +253,9 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a scheduled publish date change the default button to
|
||||
// If we have a scheduled publish or unpublish date change the default button to
|
||||
// "save" and update the label to "save and schedule
|
||||
if(args.content.releaseDate) {
|
||||
if(args.content.releaseDate || args.content.removeDate) {
|
||||
|
||||
// if save button is alread the default don't change it just update the label
|
||||
if (buttons.defaultButton && buttons.defaultButton.letter === "A") {
|
||||
|
||||
@@ -25,7 +25,6 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
var mainTreeEventHandler = null;
|
||||
//tracks the user profile dialog
|
||||
var userDialog = null;
|
||||
var syncTreePromise;
|
||||
|
||||
function setMode(mode) {
|
||||
switch (mode) {
|
||||
@@ -177,11 +176,6 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
//when a tree is loaded into a section, we need to put it into appState
|
||||
mainTreeEventHandler.bind("treeLoaded", function(ev, args) {
|
||||
appState.setTreeState("currentRootNode", args.tree);
|
||||
if (syncTreePromise) {
|
||||
mainTreeEventHandler.syncTree(syncTreePromise.args).then(function(syncArgs) {
|
||||
syncTreePromise.resolve(syncArgs);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//when a tree node is synced this event will fire, this allows us to set the currentNode
|
||||
@@ -303,10 +297,8 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
}
|
||||
}
|
||||
|
||||
//create a promise and resolve it later
|
||||
syncTreePromise = $q.defer();
|
||||
syncTreePromise.args = args;
|
||||
return syncTreePromise.promise;
|
||||
//couldn't sync
|
||||
return angularHelper.rejectedPromise();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -471,7 +463,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
|
||||
//if it is not two parts long then this most likely means that it's a legacy action
|
||||
var js = action.metaData["jsAction"].replace("javascript:", "");
|
||||
//there's not really a different way to achieve this except for eval
|
||||
//there's not really a different way to acheive this except for eval
|
||||
eval(js);
|
||||
}
|
||||
else {
|
||||
@@ -669,10 +661,10 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
*/
|
||||
hideDialog: function (showMenu) {
|
||||
|
||||
if (showMenu) {
|
||||
setMode("default");
|
||||
|
||||
if(showMenu){
|
||||
this.showMenu(undefined, { skipDefault: true, node: appState.getMenuState("currentNode") });
|
||||
} else {
|
||||
setMode("default");
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
||||
@@ -1,464 +1,455 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.umbRequestHelper
|
||||
* @description A helper object used for sending requests to the server
|
||||
**/
|
||||
function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogService, notificationsService, eventsService) {
|
||||
return {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.umbRequestHelper#convertVirtualToAbsolutePath
|
||||
* @methodOf umbraco.services.umbRequestHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This will convert a virtual path (i.e. ~/App_Plugins/Blah/Test.html ) to an absolute path
|
||||
*
|
||||
* @param {string} a virtual path, if this is already an absolute path it will just be returned, if this is a relative path an exception will be thrown
|
||||
*/
|
||||
convertVirtualToAbsolutePath: function(virtualPath) {
|
||||
if (virtualPath.startsWith("/")) {
|
||||
return virtualPath;
|
||||
}
|
||||
if (!virtualPath.startsWith("~/")) {
|
||||
throw "The path " + virtualPath + " is not a virtual path";
|
||||
}
|
||||
if (!Umbraco.Sys.ServerVariables.application.applicationPath) {
|
||||
throw "No applicationPath defined in Umbraco.ServerVariables.application.applicationPath";
|
||||
}
|
||||
return Umbraco.Sys.ServerVariables.application.applicationPath + virtualPath.trimStart("~/");
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.umbRequestHelper#dictionaryToQueryString
|
||||
* @methodOf umbraco.services.umbRequestHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This will turn an array of key/value pairs or a standard dictionary into a query string
|
||||
*
|
||||
* @param {Array} queryStrings An array of key/value pairs
|
||||
*/
|
||||
dictionaryToQueryString: function (queryStrings) {
|
||||
|
||||
if (angular.isArray(queryStrings)) {
|
||||
return _.map(queryStrings, function (item) {
|
||||
var key = null;
|
||||
var val = null;
|
||||
for (var k in item) {
|
||||
key = k;
|
||||
val = item[k];
|
||||
break;
|
||||
}
|
||||
if (key === null || val === null) {
|
||||
throw "The object in the array was not formatted as a key/value pair";
|
||||
}
|
||||
return encodeURIComponent(key) + "=" + encodeURIComponent(val);
|
||||
}).join("&");
|
||||
}
|
||||
else if (angular.isObject(queryStrings)) {
|
||||
|
||||
//this allows for a normal object to be passed in (ie. a dictionary)
|
||||
return decodeURIComponent($.param(queryStrings));
|
||||
}
|
||||
|
||||
throw "The queryString parameter is not an array or object of key value pairs";
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.umbRequestHelper#getApiUrl
|
||||
* @methodOf umbraco.services.umbRequestHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This will return the webapi Url for the requested key based on the servervariables collection
|
||||
*
|
||||
* @param {string} apiName The webapi name that is found in the servervariables["umbracoUrls"] dictionary
|
||||
* @param {string} actionName The webapi action name
|
||||
* @param {object} queryStrings Can be either a string or an array containing key/value pairs
|
||||
*/
|
||||
getApiUrl: function (apiName, actionName, queryStrings) {
|
||||
if (!Umbraco || !Umbraco.Sys || !Umbraco.Sys.ServerVariables || !Umbraco.Sys.ServerVariables["umbracoUrls"]) {
|
||||
throw "No server variables defined!";
|
||||
}
|
||||
|
||||
if (!Umbraco.Sys.ServerVariables["umbracoUrls"][apiName]) {
|
||||
throw "No url found for api name " + apiName;
|
||||
}
|
||||
|
||||
return Umbraco.Sys.ServerVariables["umbracoUrls"][apiName] + actionName +
|
||||
(!queryStrings ? "" : "?" + (angular.isString(queryStrings) ? queryStrings : this.dictionaryToQueryString(queryStrings)));
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.umbRequestHelper#resourcePromise
|
||||
* @methodOf umbraco.services.umbRequestHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This returns a promise with an underlying http call, it is a helper method to reduce
|
||||
* the amount of duplicate code needed to query http resources and automatically handle any
|
||||
* Http errors. See /docs/source/using-promises-resources.md
|
||||
*
|
||||
* @param {object} opts A mixed object which can either be a string representing the error message to be
|
||||
* returned OR an object containing either:
|
||||
* { success: successCallback, errorMsg: errorMessage }
|
||||
* OR
|
||||
* { success: successCallback, error: errorCallback }
|
||||
* In both of the above, the successCallback must accept these parameters: data, status, headers, config
|
||||
* If using the errorCallback it must accept these parameters: data, status, headers, config
|
||||
* The success callback must return the data which will be resolved by the deferred object.
|
||||
* The error callback must return an object containing: {errorMsg: errorMessage, data: originalData, status: status }
|
||||
*/
|
||||
resourcePromise: function (httpPromise, opts) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
/** The default success callback used if one is not supplied in the opts */
|
||||
function defaultSuccess(data, status, headers, config) {
|
||||
//when it's successful, just return the data
|
||||
return data;
|
||||
}
|
||||
|
||||
/** The default error callback used if one is not supplied in the opts */
|
||||
function defaultError(data, status, headers, config) {
|
||||
|
||||
var err = {
|
||||
//NOTE: the default error message here should never be used based on the above docs!
|
||||
errorMsg: (angular.isString(opts) ? opts : 'An error occurred!'),
|
||||
data: data,
|
||||
status: status
|
||||
};
|
||||
|
||||
// if "opts" is a promise, we set "err.errorMsg" to be that promise
|
||||
if (typeof(opts) == "object" && typeof(opts.then) == "function") {
|
||||
err.errorMsg = opts;
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
}
|
||||
|
||||
//create the callbacs based on whats been passed in.
|
||||
var callbacks = {
|
||||
success: ((!opts || !opts.success) ? defaultSuccess : opts.success),
|
||||
error: ((!opts || !opts.error) ? defaultError : opts.error)
|
||||
};
|
||||
|
||||
httpPromise.success(function (data, status, headers, config) {
|
||||
|
||||
//invoke the callback
|
||||
var result = callbacks.success.apply(this, [data, status, headers, config]);
|
||||
|
||||
//when it's successful, just return the data
|
||||
deferred.resolve(result);
|
||||
|
||||
}).error(function (data, status, headers, config) {
|
||||
|
||||
//invoke the callback
|
||||
var result = callbacks.error.apply(this, [data, status, headers, config]);
|
||||
|
||||
//when there's a 500 (unhandled) error show a YSOD overlay if debugging is enabled.
|
||||
if (status >= 500 && status < 600) {
|
||||
|
||||
//show a ysod dialog
|
||||
if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) {
|
||||
eventsService.emit('app.ysod',
|
||||
{
|
||||
errorMsg: 'An error occured',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
else {
|
||||
//show a simple error notification
|
||||
notificationsService.error("Server error", "Contact administrator, see log for full details.<br/><i>" + result.errorMsg + "</i>");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//return an error object including the error message for UI
|
||||
deferred.reject({
|
||||
errorMsg: result.errorMsg,
|
||||
data: result.data,
|
||||
status: result.status
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
|
||||
},
|
||||
|
||||
/** Used for saving media/content specifically */
|
||||
postSaveContent: function (args) {
|
||||
|
||||
if (!args.restApiUrl) {
|
||||
throw "args.restApiUrl is a required argument";
|
||||
}
|
||||
if (!args.content) {
|
||||
throw "args.content is a required argument";
|
||||
}
|
||||
if (!args.action) {
|
||||
throw "args.action is a required argument";
|
||||
}
|
||||
if (!args.files) {
|
||||
throw "args.files is a required argument";
|
||||
}
|
||||
if (!args.dataFormatter) {
|
||||
throw "args.dataFormatter is a required argument";
|
||||
}
|
||||
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
//save the active tab id so we can set it when the data is returned.
|
||||
var activeTab = _.find(args.content.tabs, function (item) {
|
||||
return item.active;
|
||||
});
|
||||
var activeTabIndex = (activeTab === undefined ? 0 : _.indexOf(args.content.tabs, activeTab));
|
||||
|
||||
//save the data
|
||||
this.postMultiPartRequest(
|
||||
args.restApiUrl,
|
||||
{ key: "contentItem", value: args.dataFormatter(args.content, args.action) },
|
||||
function (data, formData) {
|
||||
//now add all of the assigned files
|
||||
for (var f in args.files) {
|
||||
//each item has a property alias and the file object, we'll ensure that the alias is suffixed to the key
|
||||
// so we know which property it belongs to on the server side
|
||||
formData.append("file_" + args.files[f].alias, args.files[f].file);
|
||||
}
|
||||
|
||||
},
|
||||
function (data, status, headers, config) {
|
||||
//success callback
|
||||
|
||||
//reset the tabs and set the active one
|
||||
if(data.tabs && data.tabs.length > 0) {
|
||||
_.each(data.tabs, function (item) {
|
||||
item.active = false;
|
||||
});
|
||||
data.tabs[activeTabIndex].active = true;
|
||||
}
|
||||
|
||||
//the data returned is the up-to-date data so the UI will refresh
|
||||
deferred.resolve(data);
|
||||
},
|
||||
function (data, status, headers, config) {
|
||||
//failure callback
|
||||
|
||||
//when there's a 500 (unhandled) error show a YSOD overlay if debugging is enabled.
|
||||
if (status >= 500 && status < 600) {
|
||||
|
||||
//This is a bit of a hack to check if the error is due to a file being uploaded that is too large,
|
||||
// we have to just check for the existence of a string value but currently that is the best way to
|
||||
// do this since it's very hacky/difficult to catch this on the server
|
||||
if (typeof data !== "undefined" && typeof data.indexOf === "function" && data.indexOf("Maximum request length exceeded") >= 0) {
|
||||
notificationsService.error("Server error", "The uploaded file was too large, check with your site administrator to adjust the maximum size allowed");
|
||||
}
|
||||
else if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) {
|
||||
//show a ysod dialog
|
||||
eventsService.emit('app.ysod',
|
||||
{
|
||||
errorMsg: 'An error occured',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
else {
|
||||
//show a simple error notification
|
||||
notificationsService.error("Server error", "Contact administrator, see log for full details.<br/><i>" + data.ExceptionMessage + "</i>");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//return an error object including the error message for UI
|
||||
deferred.reject({
|
||||
errorMsg: 'An error occurred',
|
||||
data: data,
|
||||
status: status
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/** Posts a multi-part mime request to the server */
|
||||
postMultiPartRequest: function (url, jsonData, transformCallback, successCallback, failureCallback) {
|
||||
|
||||
//validate input, jsonData can be an array of key/value pairs or just one key/value pair.
|
||||
if (!jsonData) { throw "jsonData cannot be null"; }
|
||||
|
||||
if (angular.isArray(jsonData)) {
|
||||
_.each(jsonData, function (item) {
|
||||
if (!item.key || !item.value) { throw "jsonData array item must have both a key and a value property"; }
|
||||
});
|
||||
}
|
||||
else if (!jsonData.key || !jsonData.value) { throw "jsonData object must have both a key and a value property"; }
|
||||
|
||||
|
||||
$http({
|
||||
method: 'POST',
|
||||
url: url,
|
||||
//IMPORTANT!!! You might think this should be set to 'multipart/form-data' but this is not true because when we are sending up files
|
||||
// the request needs to include a 'boundary' parameter which identifies the boundary name between parts in this multi-part request
|
||||
// and setting the Content-type manually will not set this boundary parameter. For whatever reason, setting the Content-type to 'false'
|
||||
// will force the request to automatically populate the headers properly including the boundary parameter.
|
||||
headers: { 'Content-Type': false },
|
||||
transformRequest: function (data) {
|
||||
var formData = new FormData();
|
||||
//add the json data
|
||||
if (angular.isArray(data)) {
|
||||
_.each(data, function (item) {
|
||||
formData.append(item.key, !angular.isString(item.value) ? angular.toJson(item.value) : item.value);
|
||||
});
|
||||
}
|
||||
else {
|
||||
formData.append(data.key, !angular.isString(data.value) ? angular.toJson(data.value) : data.value);
|
||||
}
|
||||
|
||||
//call the callback
|
||||
if (transformCallback) {
|
||||
transformCallback.apply(this, [data, formData]);
|
||||
}
|
||||
|
||||
return formData;
|
||||
},
|
||||
data: jsonData
|
||||
}).
|
||||
success(function (data, status, headers, config) {
|
||||
if (successCallback) {
|
||||
successCallback.apply(this, [data, status, headers, config]);
|
||||
}
|
||||
}).
|
||||
error(function (data, status, headers, config) {
|
||||
if (failureCallback) {
|
||||
failureCallback.apply(this, [data, status, headers, config]);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Downloads a file to the client using AJAX/XHR
|
||||
* Based on an implementation here: web.student.tuwien.ac.at/~e0427417/jsdownload.html
|
||||
* See https://stackoverflow.com/a/24129082/694494
|
||||
*/
|
||||
downloadFile : function (httpPath) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
// Use an arraybuffer
|
||||
$http.get(httpPath, { responseType: 'arraybuffer' })
|
||||
.success(function (data, status, headers) {
|
||||
|
||||
var octetStreamMime = 'application/octet-stream';
|
||||
var success = false;
|
||||
|
||||
// Get the headers
|
||||
headers = headers();
|
||||
|
||||
// Get the filename from the x-filename header or default to "download.bin"
|
||||
var filename = headers['x-filename'] || 'download.bin';
|
||||
|
||||
// Determine the content type from the header or default to "application/octet-stream"
|
||||
var contentType = headers['content-type'] || octetStreamMime;
|
||||
|
||||
try {
|
||||
// Try using msSaveBlob if supported
|
||||
console.log("Trying saveBlob method ...");
|
||||
var blob = new Blob([data], { type: contentType });
|
||||
if (navigator.msSaveBlob)
|
||||
navigator.msSaveBlob(blob, filename);
|
||||
else {
|
||||
// Try using other saveBlob implementations, if available
|
||||
var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
|
||||
if (saveBlob === undefined) throw "Not supported";
|
||||
saveBlob(blob, filename);
|
||||
}
|
||||
console.log("saveBlob succeeded");
|
||||
success = true;
|
||||
} catch (ex) {
|
||||
console.log("saveBlob method failed with the following exception:");
|
||||
console.log(ex);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// Get the blob url creator
|
||||
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
||||
if (urlCreator) {
|
||||
// Try to use a download link
|
||||
var link = document.createElement('a');
|
||||
if ('download' in link) {
|
||||
// Try to simulate a click
|
||||
try {
|
||||
// Prepare a blob URL
|
||||
console.log("Trying download link method with simulated click ...");
|
||||
var blob = new Blob([data], { type: contentType });
|
||||
var url = urlCreator.createObjectURL(blob);
|
||||
link.setAttribute('href', url);
|
||||
|
||||
// Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
|
||||
link.setAttribute("download", filename);
|
||||
|
||||
// Simulate clicking the download link
|
||||
var event = document.createEvent('MouseEvents');
|
||||
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
link.dispatchEvent(event);
|
||||
console.log("Download link method with simulated click succeeded");
|
||||
success = true;
|
||||
|
||||
} catch (ex) {
|
||||
console.log("Download link method with simulated click failed with the following exception:");
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// Fallback to window.location method
|
||||
try {
|
||||
// Prepare a blob URL
|
||||
// Use application/octet-stream when using window.location to force download
|
||||
console.log("Trying download link method with window.location ...");
|
||||
var blob = new Blob([data], { type: octetStreamMime });
|
||||
var url = urlCreator.createObjectURL(blob);
|
||||
window.location = url;
|
||||
console.log("Download link method with window.location succeeded");
|
||||
success = true;
|
||||
} catch (ex) {
|
||||
console.log("Download link method with window.location failed with the following exception:");
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// Fallback to window.open method
|
||||
console.log("No methods worked for saving the arraybuffer, using last resort window.open");
|
||||
window.open(httpPath, '_blank', '');
|
||||
}
|
||||
|
||||
deferred.resolve();
|
||||
})
|
||||
.error(function (data, status) {
|
||||
console.log("Request failed with status: " + status);
|
||||
|
||||
deferred.reject({
|
||||
errorMsg: "An error occurred downloading the file",
|
||||
data: data,
|
||||
status: status
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('umbRequestHelper', umbRequestHelper);
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.umbRequestHelper
|
||||
* @description A helper object used for sending requests to the server
|
||||
**/
|
||||
function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogService, notificationsService, eventsService) {
|
||||
return {
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.umbRequestHelper#convertVirtualToAbsolutePath
|
||||
* @methodOf umbraco.services.umbRequestHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This will convert a virtual path (i.e. ~/App_Plugins/Blah/Test.html ) to an absolute path
|
||||
*
|
||||
* @param {string} a virtual path, if this is already an absolute path it will just be returned, if this is a relative path an exception will be thrown
|
||||
*/
|
||||
convertVirtualToAbsolutePath: function(virtualPath) {
|
||||
if (virtualPath.startsWith("/")) {
|
||||
return virtualPath;
|
||||
}
|
||||
if (!virtualPath.startsWith("~/")) {
|
||||
throw "The path " + virtualPath + " is not a virtual path";
|
||||
}
|
||||
if (!Umbraco.Sys.ServerVariables.application.applicationPath) {
|
||||
throw "No applicationPath defined in Umbraco.ServerVariables.application.applicationPath";
|
||||
}
|
||||
return Umbraco.Sys.ServerVariables.application.applicationPath + virtualPath.trimStart("~/");
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.umbRequestHelper#dictionaryToQueryString
|
||||
* @methodOf umbraco.services.umbRequestHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This will turn an array of key/value pairs or a standard dictionary into a query string
|
||||
*
|
||||
* @param {Array} queryStrings An array of key/value pairs
|
||||
*/
|
||||
dictionaryToQueryString: function (queryStrings) {
|
||||
|
||||
if (angular.isArray(queryStrings)) {
|
||||
return _.map(queryStrings, function (item) {
|
||||
var key = null;
|
||||
var val = null;
|
||||
for (var k in item) {
|
||||
key = k;
|
||||
val = item[k];
|
||||
break;
|
||||
}
|
||||
if (key === null || val === null) {
|
||||
throw "The object in the array was not formatted as a key/value pair";
|
||||
}
|
||||
return encodeURIComponent(key) + "=" + encodeURIComponent(val);
|
||||
}).join("&");
|
||||
}
|
||||
else if (angular.isObject(queryStrings)) {
|
||||
|
||||
//this allows for a normal object to be passed in (ie. a dictionary)
|
||||
return decodeURIComponent($.param(queryStrings));
|
||||
}
|
||||
|
||||
throw "The queryString parameter is not an array or object of key value pairs";
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name umbraco.services.umbRequestHelper#getApiUrl
|
||||
* @methodOf umbraco.services.umbRequestHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This will return the webapi Url for the requested key based on the servervariables collection
|
||||
*
|
||||
* @param {string} apiName The webapi name that is found in the servervariables["umbracoUrls"] dictionary
|
||||
* @param {string} actionName The webapi action name
|
||||
* @param {object} queryStrings Can be either a string or an array containing key/value pairs
|
||||
*/
|
||||
getApiUrl: function (apiName, actionName, queryStrings) {
|
||||
if (!Umbraco || !Umbraco.Sys || !Umbraco.Sys.ServerVariables || !Umbraco.Sys.ServerVariables["umbracoUrls"]) {
|
||||
throw "No server variables defined!";
|
||||
}
|
||||
|
||||
if (!Umbraco.Sys.ServerVariables["umbracoUrls"][apiName]) {
|
||||
throw "No url found for api name " + apiName;
|
||||
}
|
||||
|
||||
return Umbraco.Sys.ServerVariables["umbracoUrls"][apiName] + actionName +
|
||||
(!queryStrings ? "" : "?" + (angular.isString(queryStrings) ? queryStrings : this.dictionaryToQueryString(queryStrings)));
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.umbRequestHelper#resourcePromise
|
||||
* @methodOf umbraco.services.umbRequestHelper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* This returns a promise with an underlying http call, it is a helper method to reduce
|
||||
* the amount of duplicate code needed to query http resources and automatically handle any
|
||||
* Http errors. See /docs/source/using-promises-resources.md
|
||||
*
|
||||
* @param {object} opts A mixed object which can either be a string representing the error message to be
|
||||
* returned OR an object containing either:
|
||||
* { success: successCallback, errorMsg: errorMessage }
|
||||
* OR
|
||||
* { success: successCallback, error: errorCallback }
|
||||
* In both of the above, the successCallback must accept these parameters: data, status, headers, config
|
||||
* If using the errorCallback it must accept these parameters: data, status, headers, config
|
||||
* The success callback must return the data which will be resolved by the deferred object.
|
||||
* The error callback must return an object containing: {errorMsg: errorMessage, data: originalData, status: status }
|
||||
*/
|
||||
resourcePromise: function (httpPromise, opts) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
/** The default success callback used if one is not supplied in the opts */
|
||||
function defaultSuccess(data, status, headers, config) {
|
||||
//when it's successful, just return the data
|
||||
return data;
|
||||
}
|
||||
|
||||
/** The default error callback used if one is not supplied in the opts */
|
||||
function defaultError(data, status, headers, config) {
|
||||
return {
|
||||
//NOTE: the default error message here should never be used based on the above docs!
|
||||
errorMsg: (angular.isString(opts) ? opts : 'An error occurred!'),
|
||||
data: data,
|
||||
status: status
|
||||
};
|
||||
}
|
||||
|
||||
//create the callbacs based on whats been passed in.
|
||||
var callbacks = {
|
||||
success: ((!opts || !opts.success) ? defaultSuccess : opts.success),
|
||||
error: ((!opts || !opts.error) ? defaultError : opts.error)
|
||||
};
|
||||
|
||||
httpPromise.success(function (data, status, headers, config) {
|
||||
|
||||
//invoke the callback
|
||||
var result = callbacks.success.apply(this, [data, status, headers, config]);
|
||||
|
||||
//when it's successful, just return the data
|
||||
deferred.resolve(result);
|
||||
|
||||
}).error(function (data, status, headers, config) {
|
||||
|
||||
//invoke the callback
|
||||
var result = callbacks.error.apply(this, [data, status, headers, config]);
|
||||
|
||||
//when there's a 500 (unhandled) error show a YSOD overlay if debugging is enabled.
|
||||
if (status >= 500 && status < 600) {
|
||||
|
||||
//show a ysod dialog
|
||||
if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) {
|
||||
eventsService.emit('app.ysod',
|
||||
{
|
||||
errorMsg: 'An error occured',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
else {
|
||||
//show a simple error notification
|
||||
notificationsService.error("Server error", "Contact administrator, see log for full details.<br/><i>" + result.errorMsg + "</i>");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//return an error object including the error message for UI
|
||||
deferred.reject({
|
||||
errorMsg: result.errorMsg,
|
||||
data: result.data,
|
||||
status: result.status
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
|
||||
},
|
||||
|
||||
/** Used for saving media/content specifically */
|
||||
postSaveContent: function (args) {
|
||||
|
||||
if (!args.restApiUrl) {
|
||||
throw "args.restApiUrl is a required argument";
|
||||
}
|
||||
if (!args.content) {
|
||||
throw "args.content is a required argument";
|
||||
}
|
||||
if (!args.action) {
|
||||
throw "args.action is a required argument";
|
||||
}
|
||||
if (!args.files) {
|
||||
throw "args.files is a required argument";
|
||||
}
|
||||
if (!args.dataFormatter) {
|
||||
throw "args.dataFormatter is a required argument";
|
||||
}
|
||||
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
//save the active tab id so we can set it when the data is returned.
|
||||
var activeTab = _.find(args.content.tabs, function (item) {
|
||||
return item.active;
|
||||
});
|
||||
var activeTabIndex = (activeTab === undefined ? 0 : _.indexOf(args.content.tabs, activeTab));
|
||||
|
||||
//save the data
|
||||
this.postMultiPartRequest(
|
||||
args.restApiUrl,
|
||||
{ key: "contentItem", value: args.dataFormatter(args.content, args.action) },
|
||||
function (data, formData) {
|
||||
//now add all of the assigned files
|
||||
for (var f in args.files) {
|
||||
//each item has a property alias and the file object, we'll ensure that the alias is suffixed to the key
|
||||
// so we know which property it belongs to on the server side
|
||||
formData.append("file_" + args.files[f].alias, args.files[f].file);
|
||||
}
|
||||
|
||||
},
|
||||
function (data, status, headers, config) {
|
||||
//success callback
|
||||
|
||||
//reset the tabs and set the active one
|
||||
if(data.tabs && data.tabs.length > 0) {
|
||||
_.each(data.tabs, function (item) {
|
||||
item.active = false;
|
||||
});
|
||||
data.tabs[activeTabIndex].active = true;
|
||||
}
|
||||
|
||||
//the data returned is the up-to-date data so the UI will refresh
|
||||
deferred.resolve(data);
|
||||
},
|
||||
function (data, status, headers, config) {
|
||||
//failure callback
|
||||
|
||||
//when there's a 500 (unhandled) error show a YSOD overlay if debugging is enabled.
|
||||
if (status >= 500 && status < 600) {
|
||||
|
||||
//This is a bit of a hack to check if the error is due to a file being uploaded that is too large,
|
||||
// we have to just check for the existence of a string value but currently that is the best way to
|
||||
// do this since it's very hacky/difficult to catch this on the server
|
||||
if (typeof data !== "undefined" && typeof data.indexOf === "function" && data.indexOf("Maximum request length exceeded") >= 0) {
|
||||
notificationsService.error("Server error", "The uploaded file was too large, check with your site administrator to adjust the maximum size allowed");
|
||||
}
|
||||
else if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) {
|
||||
//show a ysod dialog
|
||||
eventsService.emit('app.ysod',
|
||||
{
|
||||
errorMsg: 'An error occured',
|
||||
data: data
|
||||
});
|
||||
}
|
||||
else {
|
||||
//show a simple error notification
|
||||
notificationsService.error("Server error", "Contact administrator, see log for full details.<br/><i>" + data.ExceptionMessage + "</i>");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//return an error object including the error message for UI
|
||||
deferred.reject({
|
||||
errorMsg: 'An error occurred',
|
||||
data: data,
|
||||
status: status
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/** Posts a multi-part mime request to the server */
|
||||
postMultiPartRequest: function (url, jsonData, transformCallback, successCallback, failureCallback) {
|
||||
|
||||
//validate input, jsonData can be an array of key/value pairs or just one key/value pair.
|
||||
if (!jsonData) { throw "jsonData cannot be null"; }
|
||||
|
||||
if (angular.isArray(jsonData)) {
|
||||
_.each(jsonData, function (item) {
|
||||
if (!item.key || !item.value) { throw "jsonData array item must have both a key and a value property"; }
|
||||
});
|
||||
}
|
||||
else if (!jsonData.key || !jsonData.value) { throw "jsonData object must have both a key and a value property"; }
|
||||
|
||||
|
||||
$http({
|
||||
method: 'POST',
|
||||
url: url,
|
||||
//IMPORTANT!!! You might think this should be set to 'multipart/form-data' but this is not true because when we are sending up files
|
||||
// the request needs to include a 'boundary' parameter which identifies the boundary name between parts in this multi-part request
|
||||
// and setting the Content-type manually will not set this boundary parameter. For whatever reason, setting the Content-type to 'false'
|
||||
// will force the request to automatically populate the headers properly including the boundary parameter.
|
||||
headers: { 'Content-Type': false },
|
||||
transformRequest: function (data) {
|
||||
var formData = new FormData();
|
||||
//add the json data
|
||||
if (angular.isArray(data)) {
|
||||
_.each(data, function (item) {
|
||||
formData.append(item.key, !angular.isString(item.value) ? angular.toJson(item.value) : item.value);
|
||||
});
|
||||
}
|
||||
else {
|
||||
formData.append(data.key, !angular.isString(data.value) ? angular.toJson(data.value) : data.value);
|
||||
}
|
||||
|
||||
//call the callback
|
||||
if (transformCallback) {
|
||||
transformCallback.apply(this, [data, formData]);
|
||||
}
|
||||
|
||||
return formData;
|
||||
},
|
||||
data: jsonData
|
||||
}).
|
||||
success(function (data, status, headers, config) {
|
||||
if (successCallback) {
|
||||
successCallback.apply(this, [data, status, headers, config]);
|
||||
}
|
||||
}).
|
||||
error(function (data, status, headers, config) {
|
||||
if (failureCallback) {
|
||||
failureCallback.apply(this, [data, status, headers, config]);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Downloads a file to the client using AJAX/XHR
|
||||
* Based on an implementation here: web.student.tuwien.ac.at/~e0427417/jsdownload.html
|
||||
* See https://stackoverflow.com/a/24129082/694494
|
||||
*/
|
||||
downloadFile : function (httpPath) {
|
||||
|
||||
var deferred = $q.defer();
|
||||
|
||||
// Use an arraybuffer
|
||||
$http.get(httpPath, { responseType: 'arraybuffer' })
|
||||
.success(function (data, status, headers) {
|
||||
|
||||
var octetStreamMime = 'application/octet-stream';
|
||||
var success = false;
|
||||
|
||||
// Get the headers
|
||||
headers = headers();
|
||||
|
||||
// Get the filename from the x-filename header or default to "download.bin"
|
||||
var filename = headers['x-filename'] || 'download.bin';
|
||||
|
||||
// Determine the content type from the header or default to "application/octet-stream"
|
||||
var contentType = headers['content-type'] || octetStreamMime;
|
||||
|
||||
try {
|
||||
// Try using msSaveBlob if supported
|
||||
console.log("Trying saveBlob method ...");
|
||||
var blob = new Blob([data], { type: contentType });
|
||||
if (navigator.msSaveBlob)
|
||||
navigator.msSaveBlob(blob, filename);
|
||||
else {
|
||||
// Try using other saveBlob implementations, if available
|
||||
var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
|
||||
if (saveBlob === undefined) throw "Not supported";
|
||||
saveBlob(blob, filename);
|
||||
}
|
||||
console.log("saveBlob succeeded");
|
||||
success = true;
|
||||
} catch (ex) {
|
||||
console.log("saveBlob method failed with the following exception:");
|
||||
console.log(ex);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// Get the blob url creator
|
||||
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
||||
if (urlCreator) {
|
||||
// Try to use a download link
|
||||
var link = document.createElement('a');
|
||||
if ('download' in link) {
|
||||
// Try to simulate a click
|
||||
try {
|
||||
// Prepare a blob URL
|
||||
console.log("Trying download link method with simulated click ...");
|
||||
var blob = new Blob([data], { type: contentType });
|
||||
var url = urlCreator.createObjectURL(blob);
|
||||
link.setAttribute('href', url);
|
||||
|
||||
// Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
|
||||
link.setAttribute("download", filename);
|
||||
|
||||
// Simulate clicking the download link
|
||||
var event = document.createEvent('MouseEvents');
|
||||
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
link.dispatchEvent(event);
|
||||
console.log("Download link method with simulated click succeeded");
|
||||
success = true;
|
||||
|
||||
} catch (ex) {
|
||||
console.log("Download link method with simulated click failed with the following exception:");
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// Fallback to window.location method
|
||||
try {
|
||||
// Prepare a blob URL
|
||||
// Use application/octet-stream when using window.location to force download
|
||||
console.log("Trying download link method with window.location ...");
|
||||
var blob = new Blob([data], { type: octetStreamMime });
|
||||
var url = urlCreator.createObjectURL(blob);
|
||||
window.location = url;
|
||||
console.log("Download link method with window.location succeeded");
|
||||
success = true;
|
||||
} catch (ex) {
|
||||
console.log("Download link method with window.location failed with the following exception:");
|
||||
console.log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
// Fallback to window.open method
|
||||
console.log("No methods worked for saving the arraybuffer, using last resort window.open");
|
||||
window.open(httpPath, '_blank', '');
|
||||
}
|
||||
|
||||
deferred.resolve();
|
||||
})
|
||||
.error(function (data, status) {
|
||||
console.log("Request failed with status: " + status);
|
||||
|
||||
deferred.reject({
|
||||
errorMsg: "An error occurred downloading the file",
|
||||
data: data,
|
||||
status: status
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('umbRequestHelper', umbRequestHelper);
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
function NavigationController($scope, $rootScope, $location, $log, $routeParams, $timeout, appState, navigationService, keyboardService, dialogService, historyService, eventsService, sectionResource, angularHelper) {
|
||||
|
||||
//TODO: Need to think about this and an nicer way to achieve what this is doing.
|
||||
//TODO: Need to think about this and an nicer way to acheive what this is doing.
|
||||
//the tree event handler i used to subscribe to the main tree click events
|
||||
$scope.treeEventHandler = $({});
|
||||
navigationService.setupTreeEvents($scope.treeEventHandler);
|
||||
@@ -40,7 +40,7 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
|
||||
navigationService.showSearch();
|
||||
});
|
||||
|
||||
//trigger dialogs with a hotkey:
|
||||
//trigger dialods with a hotkey:
|
||||
keyboardService.bind("esc", function () {
|
||||
eventsService.emit("app.closeDialogs");
|
||||
});
|
||||
@@ -112,7 +112,7 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
|
||||
$scope.authenticated = false;
|
||||
}));
|
||||
|
||||
//when the application is ready and the user is authorized, setup the data
|
||||
//when the application is ready and the user is authorized setup the data
|
||||
evts.push(eventsService.on("app.ready", function(evt, data) {
|
||||
$scope.authenticated = true;
|
||||
}));
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
ng-pattern="passwordPattern"
|
||||
autocorrect="off"
|
||||
autocapitalize="off"
|
||||
autocomplete="off"
|
||||
required
|
||||
ng-model="installer.current.model.password" id="password" />
|
||||
<small class="inline-help">At least {{installer.current.model.minCharLength}} characters long</small>
|
||||
|
||||
@@ -1,187 +1,185 @@
|
||||
|
||||
// Core variables and mixins
|
||||
@import "fonts.less"; // Loading fonts
|
||||
@import "variables.less"; // Modify this for custom colors, font-sizes, etc
|
||||
@import "mixins.less";
|
||||
|
||||
// CSS Reset
|
||||
@import "../../lib/bootstrap/less/reset.less";
|
||||
|
||||
// Grid system and page structure
|
||||
@import "../../lib/bootstrap/less/scaffolding.less";
|
||||
@import "../../lib/bootstrap/less/grid.less";
|
||||
@import "../../lib/bootstrap/less/layouts.less";
|
||||
|
||||
// Base CSS
|
||||
@import "../../lib/bootstrap/less/type.less";
|
||||
@import "../../lib/bootstrap/less/code.less";
|
||||
@import "tables.less";
|
||||
|
||||
|
||||
// Components: common
|
||||
@import "../../lib/bootstrap/less/dropdowns.less";
|
||||
@import "../../lib/bootstrap/less/wells.less";
|
||||
@import "../../lib/bootstrap/less/component-animations.less";
|
||||
@import "../../lib/bootstrap/less/close.less";
|
||||
|
||||
// Components: Buttons & Alerts
|
||||
@import "../../lib/bootstrap/less/button-groups.less";
|
||||
@import "alerts.less"; // Note: alerts share common CSS with buttons and thus have styles in buttons.less
|
||||
|
||||
// Components: Nav
|
||||
@import "navs.less";
|
||||
@import "../../lib/bootstrap/less/navbar.less";
|
||||
@import "../../lib/bootstrap/less/breadcrumbs.less";
|
||||
@import "../../lib/bootstrap/less/pagination.less";
|
||||
@import "../../lib/bootstrap/less/pager.less";
|
||||
|
||||
// Components: Popovers
|
||||
@import "../../lib/bootstrap/less/modals.less";
|
||||
@import "../../lib/bootstrap/less/tooltip.less";
|
||||
@import "../../lib/bootstrap/less/popovers.less";
|
||||
@import "tipmenu.less";
|
||||
|
||||
// Components: Misc
|
||||
@import "../../lib/bootstrap/less/thumbnails.less";
|
||||
@import "../../lib/bootstrap/less/media.less";
|
||||
@import "../../lib/bootstrap/less/labels-badges.less";
|
||||
@import "../../lib/bootstrap/less/progress-bars.less";
|
||||
@import "../../lib/bootstrap/less/accordion.less";
|
||||
@import "../../lib/bootstrap/less/carousel.less";
|
||||
@import "../../lib/bootstrap/less/hero-unit.less";
|
||||
|
||||
|
||||
// Utility classes
|
||||
@import "../../lib/bootstrap/less/utilities.less"; // Has to be last to override when necessary
|
||||
|
||||
|
||||
// Application wide styles (refactor is WIP)
|
||||
@import "application/grid.less";
|
||||
@import "application/shadows.less";
|
||||
@import "application/animations.less";
|
||||
|
||||
// Utilities
|
||||
@import "utilities/_font-weight.less";
|
||||
|
||||
// Belle styles
|
||||
@import "buttons.less";
|
||||
@import "forms.less";
|
||||
@import "legacydialog.less";
|
||||
@import "modals.less";
|
||||
@import "panel.less";
|
||||
@import "sections.less";
|
||||
@import "helveticons.less";
|
||||
@import "main.less";
|
||||
@import "tree.less";
|
||||
@import "listview.less";
|
||||
@import "gridview.less";
|
||||
@import "footer.less";
|
||||
@import "dragdrop.less";
|
||||
@import "dashboards.less";
|
||||
|
||||
@import "forms/umb-validation-label.less";
|
||||
|
||||
// Umbraco Components
|
||||
@import "components/application/umb-tour.less";
|
||||
@import "components/application/umb-backdrop.less";
|
||||
@import "components/application/umb-drawer.less";
|
||||
|
||||
@import "components/editor.less";
|
||||
@import "components/overlays.less";
|
||||
@import "components/card.less";
|
||||
@import "components/umb-sub-views.less";
|
||||
@import "components/umb-editor-navigation.less";
|
||||
@import "components/umb-editor-sub-views.less";
|
||||
@import "components/editor/subheader/umb-editor-sub-header.less";
|
||||
@import "components/umb-grid-selector.less";
|
||||
@import "components/umb-child-selector.less";
|
||||
@import "components/umb-group-builder.less";
|
||||
@import "components/umb-list-view-settings.less";
|
||||
@import "components/umb-table.less";
|
||||
@import "components/umb-confirm-action.less";
|
||||
@import "components/umb-keyboard-shortcuts-overview.less";
|
||||
@import "components/umb-checkbox-list.less";
|
||||
@import "components/umb-locked-field.less";
|
||||
@import "components/umb-tabs.less";
|
||||
@import "components/umb-load-indicator.less";
|
||||
@import "components/umb-breadcrumbs.less";
|
||||
@import "components/umb-media-grid.less";
|
||||
@import "components/umb-folder-grid.less";
|
||||
@import "components/umb-content-grid.less";
|
||||
@import "components/umb-layout-selector.less";
|
||||
@import "components/tooltip/umb-tooltip.less";
|
||||
@import "components/tooltip/umb-tooltip-list.less";
|
||||
@import "components/overlays/umb-overlay-backdrop.less";
|
||||
@import "components/umb-grid.less";
|
||||
@import "components/umb-empty-state.less";
|
||||
@import "components/umb-property-editor.less";
|
||||
@import "components/umb-color-swatches.less";
|
||||
@import "components/check-circle.less";
|
||||
@import "components/umb-iconpicker.less";
|
||||
@import "components/umb-insert-code-box.less";
|
||||
@import "components/umb-packages.less";
|
||||
@import "components/umb-package-local-install.less";
|
||||
@import "components/umb-lightbox.less";
|
||||
@import "components/umb-avatar.less";
|
||||
@import "components/umb-progress-bar.less";
|
||||
@import "components/umb-querybuilder.less";
|
||||
@import "components/umb-pagination.less";
|
||||
@import "components/umb-mini-list-view.less";
|
||||
@import "components/umb-multiple-textbox.less";
|
||||
@import "components/umb-badge.less";
|
||||
@import "components/umb-nested-content.less";
|
||||
@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";
|
||||
@import "components/buttons/umb-era-button.less";
|
||||
@import "components/buttons/umb-toggle.less";
|
||||
|
||||
@import "components/notifications/umb-notifications.less";
|
||||
@import "components/umb-file-dropzone.less";
|
||||
@import "components/umb-node-preview.less";
|
||||
@import "components/umb-mini-editor.less";
|
||||
|
||||
@import "components/users/umb-user-cards.less";
|
||||
@import "components/users/umb-user-details.less";
|
||||
@import "components/users/umb-user-group-picker-list.less";
|
||||
@import "components/users/umb-user-group-preview.less";
|
||||
@import "components/users/umb-user-preview.less";
|
||||
@import "components/users/umb-user-picker-list.less";
|
||||
@import "components/users/umb-permission.less";
|
||||
|
||||
|
||||
// Utilities
|
||||
@import "utilities/layout/_display.less";
|
||||
@import "utilities/typography/_text-decoration.less";
|
||||
@import "utilities/typography/_white-space.less";
|
||||
@import "utilities/_flexbox.less";
|
||||
@import "utilities/_spacing.less";
|
||||
@import "utilities/_text-align.less";
|
||||
@import "utilities/_width.less";
|
||||
|
||||
//page specific styles
|
||||
@import "pages/document-type-editor.less";
|
||||
@import "pages/login.less";
|
||||
@import "pages/welcome-dashboard.less";
|
||||
|
||||
|
||||
//used for property editors
|
||||
@import "property-editors.less";
|
||||
|
||||
//used for prevalue editors
|
||||
@import "components/prevalues/multivalues.less";
|
||||
|
||||
|
||||
@import "typeahead.less";
|
||||
@import "hacks.less";
|
||||
|
||||
@import "healthcheck.less";
|
||||
@import "getstarted.less";
|
||||
|
||||
// cleanup properties.less when it is done
|
||||
@import "properties.less";
|
||||
|
||||
// Core variables and mixins
|
||||
@import "fonts.less"; // Loading fonts
|
||||
@import "variables.less"; // Modify this for custom colors, font-sizes, etc
|
||||
@import "mixins.less";
|
||||
|
||||
// CSS Reset
|
||||
@import "../../lib/bootstrap/less/reset.less";
|
||||
|
||||
// Grid system and page structure
|
||||
@import "../../lib/bootstrap/less/scaffolding.less";
|
||||
@import "../../lib/bootstrap/less/grid.less";
|
||||
@import "../../lib/bootstrap/less/layouts.less";
|
||||
|
||||
// Base CSS
|
||||
@import "../../lib/bootstrap/less/type.less";
|
||||
@import "../../lib/bootstrap/less/code.less";
|
||||
@import "tables.less";
|
||||
|
||||
|
||||
// Components: common
|
||||
@import "../../lib/bootstrap/less/dropdowns.less";
|
||||
@import "../../lib/bootstrap/less/wells.less";
|
||||
@import "../../lib/bootstrap/less/component-animations.less";
|
||||
@import "../../lib/bootstrap/less/close.less";
|
||||
|
||||
// Components: Buttons & Alerts
|
||||
@import "../../lib/bootstrap/less/button-groups.less";
|
||||
@import "alerts.less"; // Note: alerts share common CSS with buttons and thus have styles in buttons.less
|
||||
|
||||
// Components: Nav
|
||||
@import "navs.less";
|
||||
@import "../../lib/bootstrap/less/navbar.less";
|
||||
@import "../../lib/bootstrap/less/breadcrumbs.less";
|
||||
@import "../../lib/bootstrap/less/pagination.less";
|
||||
@import "../../lib/bootstrap/less/pager.less";
|
||||
|
||||
// Components: Popovers
|
||||
@import "../../lib/bootstrap/less/modals.less";
|
||||
@import "../../lib/bootstrap/less/tooltip.less";
|
||||
@import "../../lib/bootstrap/less/popovers.less";
|
||||
@import "tipmenu.less";
|
||||
|
||||
// Components: Misc
|
||||
@import "../../lib/bootstrap/less/thumbnails.less";
|
||||
@import "../../lib/bootstrap/less/media.less";
|
||||
@import "../../lib/bootstrap/less/labels-badges.less";
|
||||
@import "../../lib/bootstrap/less/progress-bars.less";
|
||||
@import "../../lib/bootstrap/less/accordion.less";
|
||||
@import "../../lib/bootstrap/less/carousel.less";
|
||||
@import "../../lib/bootstrap/less/hero-unit.less";
|
||||
|
||||
|
||||
// Utility classes
|
||||
@import "../../lib/bootstrap/less/utilities.less"; // Has to be last to override when necessary
|
||||
|
||||
|
||||
// Application wide styles (refactor is WIP)
|
||||
@import "application/grid.less";
|
||||
@import "application/shadows.less";
|
||||
@import "application/animations.less";
|
||||
|
||||
// Utilities
|
||||
@import "utilities/_font-weight.less";
|
||||
|
||||
// Belle styles
|
||||
@import "buttons.less";
|
||||
@import "forms.less";
|
||||
@import "modals.less";
|
||||
@import "panel.less";
|
||||
@import "sections.less";
|
||||
@import "helveticons.less";
|
||||
@import "main.less";
|
||||
@import "tree.less";
|
||||
@import "listview.less";
|
||||
@import "gridview.less";
|
||||
@import "footer.less";
|
||||
@import "dragdrop.less";
|
||||
@import "dashboards.less";
|
||||
|
||||
@import "forms/umb-validation-label.less";
|
||||
|
||||
// Umbraco Components
|
||||
@import "components/application/umb-tour.less";
|
||||
@import "components/application/umb-backdrop.less";
|
||||
@import "components/application/umb-drawer.less";
|
||||
|
||||
@import "components/editor.less";
|
||||
@import "components/overlays.less";
|
||||
@import "components/card.less";
|
||||
@import "components/umb-sub-views.less";
|
||||
@import "components/umb-editor-navigation.less";
|
||||
@import "components/umb-editor-sub-views.less";
|
||||
@import "components/editor/subheader/umb-editor-sub-header.less";
|
||||
@import "components/umb-grid-selector.less";
|
||||
@import "components/umb-child-selector.less";
|
||||
@import "components/umb-group-builder.less";
|
||||
@import "components/umb-list-view-settings.less";
|
||||
@import "components/umb-table.less";
|
||||
@import "components/umb-confirm-action.less";
|
||||
@import "components/umb-keyboard-shortcuts-overview.less";
|
||||
@import "components/umb-checkbox-list.less";
|
||||
@import "components/umb-locked-field.less";
|
||||
@import "components/umb-tabs.less";
|
||||
@import "components/umb-load-indicator.less";
|
||||
@import "components/umb-breadcrumbs.less";
|
||||
@import "components/umb-media-grid.less";
|
||||
@import "components/umb-folder-grid.less";
|
||||
@import "components/umb-content-grid.less";
|
||||
@import "components/umb-layout-selector.less";
|
||||
@import "components/tooltip/umb-tooltip.less";
|
||||
@import "components/tooltip/umb-tooltip-list.less";
|
||||
@import "components/overlays/umb-overlay-backdrop.less";
|
||||
@import "components/umb-grid.less";
|
||||
@import "components/umb-empty-state.less";
|
||||
@import "components/umb-property-editor.less";
|
||||
@import "components/umb-color-swatches.less";
|
||||
@import "components/check-circle.less";
|
||||
@import "components/umb-iconpicker.less";
|
||||
@import "components/umb-insert-code-box.less";
|
||||
@import "components/umb-packages.less";
|
||||
@import "components/umb-package-local-install.less";
|
||||
@import "components/umb-lightbox.less";
|
||||
@import "components/umb-avatar.less";
|
||||
@import "components/umb-progress-bar.less";
|
||||
@import "components/umb-querybuilder.less";
|
||||
@import "components/umb-pagination.less";
|
||||
@import "components/umb-mini-list-view.less";
|
||||
@import "components/umb-multiple-textbox.less";
|
||||
@import "components/umb-badge.less";
|
||||
@import "components/umb-nested-content.less";
|
||||
@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";
|
||||
@import "components/buttons/umb-era-button.less";
|
||||
@import "components/buttons/umb-toggle.less";
|
||||
|
||||
@import "components/notifications/umb-notifications.less";
|
||||
@import "components/umb-file-dropzone.less";
|
||||
@import "components/umb-node-preview.less";
|
||||
@import "components/umb-mini-editor.less";
|
||||
|
||||
@import "components/users/umb-user-cards.less";
|
||||
@import "components/users/umb-user-group-picker-list.less";
|
||||
@import "components/users/umb-user-group-preview.less";
|
||||
@import "components/users/umb-user-preview.less";
|
||||
@import "components/users/umb-user-picker-list.less";
|
||||
@import "components/users/umb-permission.less";
|
||||
|
||||
|
||||
// Utilities
|
||||
@import "utilities/layout/_display.less";
|
||||
@import "utilities/typography/_text-decoration.less";
|
||||
@import "utilities/typography/_white-space.less";
|
||||
@import "utilities/_flexbox.less";
|
||||
@import "utilities/_spacing.less";
|
||||
@import "utilities/_text-align.less";
|
||||
@import "utilities/_width.less";
|
||||
|
||||
//page specific styles
|
||||
@import "pages/document-type-editor.less";
|
||||
@import "pages/login.less";
|
||||
@import "pages/welcome-dashboard.less";
|
||||
|
||||
|
||||
//used for property editors
|
||||
@import "property-editors.less";
|
||||
|
||||
//used for prevalue editors
|
||||
@import "components/prevalues/multivalues.less";
|
||||
|
||||
|
||||
@import "typeahead.less";
|
||||
@import "hacks.less";
|
||||
|
||||
@import "healthcheck.less";
|
||||
@import "getstarted.less";
|
||||
|
||||
// cleanup properties.less when it is done
|
||||
@import "properties.less";
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
.btn-group>.btn+.dropdown-toggle {
|
||||
box-shadow: none;
|
||||
-webkit-box-shadow:none;
|
||||
}
|
||||
|
||||
.btn-group .btn.dropdown-toggle {
|
||||
border-left-width: 1px;
|
||||
border-left-style: solid;
|
||||
}
|
||||
|
||||
@@ -81,9 +81,9 @@ a, a:hover{
|
||||
|
||||
.wait {
|
||||
display: block;
|
||||
height: 100%;
|
||||
height: 280px;
|
||||
width: 100%;
|
||||
background:#fff center center url(../img/loader.gif) no-repeat;
|
||||
background: center center url(../img/loader.gif) no-repeat;
|
||||
}
|
||||
|
||||
/****************************/
|
||||
|
||||
@@ -156,7 +156,6 @@
|
||||
margin-bottom: 1px;
|
||||
border-radius: 0;
|
||||
border-bottom: 1px solid @gray-9;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.umb-help-list-item__group-title i {
|
||||
@@ -187,7 +186,6 @@
|
||||
.umb-help-list-item__title {
|
||||
font-size: 14px;
|
||||
display: block;
|
||||
margin-left: 26px;
|
||||
}
|
||||
|
||||
.umb-help-list-item__description {
|
||||
@@ -200,7 +198,6 @@
|
||||
margin-right: 8px;
|
||||
color: @gray-4;
|
||||
font-size: 18px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.umb-help-list-item__open-icon {
|
||||
@@ -215,4 +212,4 @@
|
||||
|
||||
[data-element*="tour-"].umb-help-list-item:hover .umb-help-list-item__title {
|
||||
text-decoration:none;
|
||||
}
|
||||
}
|
||||
@@ -110,4 +110,4 @@
|
||||
|
||||
.umb-era-button i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.umb-toggle:focus .umb-toggle__toggle{
|
||||
box-shadow: 0 1px 3px fade(@black, 12%), 0 1px 2px fade(@black, 24%);
|
||||
}
|
||||
|
||||
.umb-toggle__handler {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -34,7 +30,6 @@
|
||||
background: @gray-8;
|
||||
border-radius: 90px;
|
||||
position: relative;
|
||||
transition: box-shadow .3s;
|
||||
}
|
||||
|
||||
.umb-toggle--checked .umb-toggle__toggle {
|
||||
@@ -48,6 +43,7 @@
|
||||
/* Labels */
|
||||
|
||||
.umb-toggle__label {
|
||||
font-size: 12px;
|
||||
color: @gray-2;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,13 +102,11 @@
|
||||
}
|
||||
|
||||
.umb-card-grid li.-four-in-row {
|
||||
flex: 0 0 25%;
|
||||
max-width: 25%;
|
||||
flex: 0 0 25%;
|
||||
}
|
||||
|
||||
.umb-card-grid li.-three-in-row {
|
||||
flex: 0 0 33.33%;
|
||||
max-width:33.33%;
|
||||
}
|
||||
|
||||
.umb-card-grid .umb-card-grid-item {
|
||||
|
||||
@@ -174,7 +174,6 @@
|
||||
box-sizing: border-box;
|
||||
background: @gray-10;
|
||||
border-bottom: 1px solid @purple-l3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.umb-overlay__item-details-title-wrapper {
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
.umb-overlay & {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
p{
|
||||
margin: 7px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-prevalues-multivalues__left {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
flex-flow: row wrap;
|
||||
|
||||
.umb-color-box {
|
||||
border: 1px solid rgba(0,0,0,0.15);
|
||||
color: @white;
|
||||
border: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
padding: 1px;
|
||||
text-align: center;
|
||||
@@ -19,7 +19,7 @@
|
||||
justify-content: center;
|
||||
|
||||
&:hover, &:focus {
|
||||
box-shadow: 0 1px 3px fade(@black, 12%), 0 1px 2px fade(@black, 24%);
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
|
||||
}
|
||||
|
||||
&.active {
|
||||
@@ -42,11 +42,10 @@
|
||||
&.with-labels {
|
||||
|
||||
.umb-color-box {
|
||||
width: 130px;
|
||||
height: auto;
|
||||
width: 120px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
border: 1px solid @gray-8;
|
||||
|
||||
.umb-color-box-inner {
|
||||
display: flex;
|
||||
@@ -54,21 +53,15 @@
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
min-height: 80px;
|
||||
padding: 0;
|
||||
|
||||
.check_circle {
|
||||
margin: 15px auto;
|
||||
}
|
||||
padding-top: 10px;
|
||||
|
||||
.umb-color-box__label {
|
||||
background: @white;
|
||||
background: #fff;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
flex-flow: column wrap;
|
||||
flex: 1 0 100%;
|
||||
justify-content: flex-end;
|
||||
flex: 0 0 100%;
|
||||
padding: 1px 5px;
|
||||
min-height: 45px;
|
||||
max-width: 100%;
|
||||
margin-top: auto;
|
||||
margin-bottom: -3px;
|
||||
@@ -76,8 +69,7 @@
|
||||
margin-right: -1px;
|
||||
text-indent: 0;
|
||||
text-align: left;
|
||||
border-top: 1px solid @gray-8;
|
||||
border-bottom: 1px solid @gray-8;
|
||||
border: 1px solid @gray-8;
|
||||
border-bottom-left-radius: 3px;
|
||||
border-bottom-right-radius: 3px;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -1,17 +1,4 @@
|
||||
.umb-multiple-textbox{
|
||||
&__confirm{
|
||||
position: relative;
|
||||
|
||||
&-action{
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
background: transparent;
|
||||
border: 0 none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.umb-multiple-textbox .textbox-wrapper {
|
||||
.umb-multiple-textbox .textbox-wrapper {
|
||||
align-items: center;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
@@ -20,7 +7,7 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.umb-multiple-textbox .textbox-wrapper i:not(.icon-delete, .icon-check) {
|
||||
.umb-multiple-textbox .textbox-wrapper i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
.umb-nested-content {
|
||||
text-align: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.umb-nested-content--not-supported {
|
||||
@@ -209,6 +208,12 @@
|
||||
width: 99%;
|
||||
}
|
||||
|
||||
.usky-grid.umb-nested-content__node-type-picker .cell-tools-menu {
|
||||
position: relative;
|
||||
transform: translate(-50%, -25%);
|
||||
}
|
||||
|
||||
|
||||
// this resolves the layout issue introduced in nested content in 7.12 with the addition of the input for link anchors
|
||||
// the attribute selector ensures the change only applies to the linkpicker overlay
|
||||
.form-horizontal .umb-nested-content--narrow [ng-controller*="Umbraco.Overlays.LinkPickerController"] .controls-row {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
.umb-nav-tabs {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.umb-nav-tabs.-padding-left {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.umb-tab-content {
|
||||
padding-top: 20px;
|
||||
position: relative;
|
||||
top: 31px;
|
||||
border-top: 1px solid @purple-l3;
|
||||
}
|
||||
.umb-nav-tabs {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.umb-nav-tabs.-padding-left {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.umb-tab-content {
|
||||
padding-top: 20px;
|
||||
position: relative;
|
||||
top: 22px;
|
||||
border-top: 1px solid @purple-l3;
|
||||
}
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
.umb-user-details-avtar {
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #d8d7d9;
|
||||
}
|
||||
|
||||
div.umb-user-details-actions > div {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.umb-user-details-actions .umb-button {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.umb-user-details-view-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: @black;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.umb-user-details-view-wrapper {
|
||||
padding: 20px 60px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
.umb-user-details-view-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-user-details-section {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.umb-user-details-details {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
a.umb-user-details-details__back-link {
|
||||
font-weight: bold;
|
||||
color: @black;
|
||||
}
|
||||
|
||||
.umb-user-details-details__back-link:hover {
|
||||
color: @gray-4;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
@sidebarwidth: 350px; // Width of sidebar. Ugly hack because of old version of Less
|
||||
|
||||
.umb-user-details-details__main-content {
|
||||
flex: 1 1 auto;
|
||||
margin-right: 30px;
|
||||
width: calc(~'100%' - ~'@{sidebarwidth}' - ~'30px'); // Make sure that the main content area doesn't gets affected by inline styling
|
||||
}
|
||||
|
||||
.umb-user-details-details__main-content .umb-node-preview-add {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.umb-user-details-details__sidebar {
|
||||
flex: 0 0 @sidebarwidth;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
||||
.umb-user-details-details {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.umb-user-details-details__main-content {
|
||||
flex: 1 1 auto;
|
||||
width: 100%;
|
||||
margin-bottom: 30px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.umb-user-details-details__sidebar {
|
||||
flex: 1 1 auto;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-user-details-details__section {
|
||||
background: @gray-10;
|
||||
padding: 20px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid @gray-8;
|
||||
}
|
||||
|
||||
.umb-user-details-details__section-title {
|
||||
font-size: 17px;
|
||||
font-weight: bold;
|
||||
color: @black;
|
||||
margin-top: 0;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.umb-user-details-details__section-description {
|
||||
font-size: 12px;
|
||||
line-height: 1.6em;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.umb-user-details-details__information-item {
|
||||
margin-bottom: 10px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.umb-user-details-details__information-item-label {
|
||||
color: @black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.umb-user-details-details__information-item-content {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
@@ -594,7 +594,7 @@ div.help {
|
||||
text-align: center;
|
||||
text-shadow: 0 1px 0 @white;
|
||||
background-color: @gray-10;
|
||||
border: 1px solid @purple-l3;
|
||||
border: 1px solid @gray-8;
|
||||
}
|
||||
.add-on,
|
||||
.btn,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
.umb-validation-label {
|
||||
position: absolute;
|
||||
top: 27px;
|
||||
width: 200px;
|
||||
position: relative;
|
||||
padding: 1px 5px;
|
||||
background: @red;
|
||||
color: @white;
|
||||
|
||||
@@ -202,7 +202,7 @@ pre {
|
||||
//font-size: @baseFontSize - 1; // 14px to 13px
|
||||
color: @gray-2;
|
||||
line-height: @baseLineHeight;
|
||||
white-space: pre-wrap; // 1
|
||||
white-space: pre-line; // 1
|
||||
overflow-x: auto; // 1
|
||||
background-color: @gray-10;
|
||||
border: 1px solid @gray-8;
|
||||
@@ -222,4 +222,4 @@ pre {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,5 +236,4 @@
|
||||
.umb-healthcheck-group__details-status-action-description {
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
padding-left: 165px;
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
|
||||
.umb-dialog .propertyItemheader {
|
||||
width: 140px !Important;
|
||||
}
|
||||
|
||||
.umb-dialog .diffDropdown {
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.umb-dialog .diffPanel {
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
|
||||
.umb-dialog .diff {
|
||||
margin-top: 10px;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
border-top: 1px solid #ccc;
|
||||
border-top: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.umb-dialog .diff table {
|
||||
width: 95%;
|
||||
max-width: 95%;
|
||||
margin: 0 3px;
|
||||
}
|
||||
|
||||
.umb-dialog .diff table th {
|
||||
padding: 5px;
|
||||
width: 25%;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.umb-dialog .diff table td {
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.umb-dialog .diff del {
|
||||
background: rgb(255, 230, 230) none repeat scroll 0%;
|
||||
-moz-background-clip: -moz-initial;
|
||||
-moz-background-origin: -moz-initial;
|
||||
-moz-background-inline-policy: -moz-initial;
|
||||
}
|
||||
|
||||
.umb-dialog .diff ins {
|
||||
background: rgb(230, 255, 230) none repeat scroll 0%;
|
||||
-moz-background-clip: -moz-initial;
|
||||
-moz-background-origin: -moz-initial;
|
||||
-moz-background-inline-policy: -moz-initial;
|
||||
}
|
||||
|
||||
.umb-dialog .diff .diffnotice {
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
margin-top: 0px;
|
||||
margin-bottom: 15px;
|
||||
font-size: 14px;
|
||||
color: @gray-7;
|
||||
color: @gray-7;
|
||||
}
|
||||
|
||||
h5{
|
||||
@@ -134,7 +134,7 @@ h5.-black {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.block-form .umb-control-group label .help-block,
|
||||
.block-form .umb-control-group label .help-block,
|
||||
.block-form .umb-control-group label small {
|
||||
font-size: 13px;
|
||||
padding-top: 2px;
|
||||
@@ -243,9 +243,9 @@ label:not([for]) {
|
||||
}
|
||||
|
||||
.umb-version {
|
||||
color: @gray-7;
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
color: @gray-7;
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
@@ -653,14 +653,3 @@ input[type=checkbox]:checked + .input-label--small {
|
||||
.bootstrap-datetimepicker-widget td span {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.visuallyhidden{
|
||||
position: absolute !important;
|
||||
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
padding:0 !important;
|
||||
border:0 !important;
|
||||
height: 1px !important;
|
||||
width: 1px !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -1,197 +1,197 @@
|
||||
/* Modals
|
||||
// -------------------------*/
|
||||
|
||||
/* Modalcolumn is used for menu panels */
|
||||
.umb-modalcolumn {
|
||||
background: @white;
|
||||
}
|
||||
|
||||
.umb-modalcolumn-header {
|
||||
background: @gray-10;
|
||||
border-bottom: 1px solid @purple-l3;
|
||||
height: 94px;
|
||||
padding: 5px 20px 0px 20px;
|
||||
white-space: nowrap
|
||||
}
|
||||
|
||||
.umb-modalcolumn-header h1{
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
font-size: @fontSizeLarge;
|
||||
font-weight: 400;
|
||||
padding-top: 10px !important;
|
||||
}
|
||||
|
||||
.umb-modalcolumn-body {
|
||||
padding: 0px;
|
||||
background: @white;
|
||||
top: 100px;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.no-padding .umb-modalcolumn-body {
|
||||
padding: 0px
|
||||
}
|
||||
|
||||
.umb-modalcolumn .umb-modalcolumn-header .btn {
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
right: 15px
|
||||
}
|
||||
|
||||
.umb-modalcolumn iframe.auto-expand, .umb-modal iframe.auto-expand {
|
||||
border: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
position: absolute;;
|
||||
}
|
||||
|
||||
/* re-align loader */
|
||||
.umb-modal .umb-loader-wrapper, .umb-modalcolumn .umb-loader-wrapper, .umb-dialog .umb-loader-wrapper{
|
||||
position:relative;
|
||||
margin: 20px -20px;
|
||||
}
|
||||
|
||||
.umb-modal-left .umb-panel-header .umb-headline, .umb-modal-left .umb-panel-header h1 {
|
||||
width: auto;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/* umb.dialog is used for the dialogs on the conent tree*/
|
||||
.umb-dialog {
|
||||
outline: none;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
position: absolute;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.umb-dialog .umb-btn-toolbar .umb-control-group{
|
||||
border: none;
|
||||
padding: none;
|
||||
}
|
||||
|
||||
.umb-dialog-body{
|
||||
position: absolute;
|
||||
overflow:auto;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 52px;
|
||||
}
|
||||
.umb-dialog-body .umb-pane{margin-top: 15px;}
|
||||
|
||||
.umb-dialog-footer{
|
||||
position: absolute;
|
||||
overflow:auto;
|
||||
text-align: right;
|
||||
height: 32px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
padding: 10px 20px;
|
||||
margin: 0;
|
||||
background: @gray-10;
|
||||
border-top: 1px solid @purple-l3;
|
||||
}
|
||||
|
||||
/*we will always make sure to wrap iframe dialogs in proper padding*/
|
||||
.umbracoDialog{
|
||||
width: auto !Important;
|
||||
height: auto !Important;
|
||||
padding: 20px;
|
||||
}
|
||||
.umbracoDialog .umb-pane{margin-left: 0px; margin-right: 0px; margin-top: 0px;}
|
||||
.umbracoDialog .umb-dialog-body .umb-pane{margin-left: 20px; margin-right: 20px; margin-top: 20px;}
|
||||
.umbracoDialog form{height: 100%;}
|
||||
|
||||
/*ensures dialogs doesnt have side-by-side labels*/
|
||||
.umbracoDialog .controls-row,
|
||||
.umb-modal .controls-row{margin-left: 0px !important;}
|
||||
|
||||
/* modal and umb-modal are used for right.hand dialogs */
|
||||
.modal {
|
||||
border-radius: 0 !important;
|
||||
|
||||
&.fade.in{border: none !important;}
|
||||
}
|
||||
.umb-modal.fade {
|
||||
outline: none;
|
||||
top: 0 !important;
|
||||
left: -100% !important;
|
||||
width: 0px !important;
|
||||
-webkit-transition: left 0.3s linear, left 0.3s ease-out;
|
||||
-moz-transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
-o-transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.umb-modal.fade.in {
|
||||
top: 0 !important;
|
||||
left: 100% !important;
|
||||
margin-left: -440px;
|
||||
width: 440px !important;
|
||||
height: 100% !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.umb-modal-left.fade {
|
||||
top: 0 !important;
|
||||
left: -100% !important;
|
||||
width: 0px !important;
|
||||
-webkit-transition: left 0.3s linear, left 0.3s ease-out;
|
||||
-moz-transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
-o-transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
height: 100% !important;
|
||||
}
|
||||
.umb-modal-left.fade.in {
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
margin-left: 80px;
|
||||
width: 440px !important;
|
||||
height: 100% !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*Modal default panel styles*/
|
||||
.umb-modal .umb-panel-header {
|
||||
padding: 20px;
|
||||
background: @white;
|
||||
border: none;
|
||||
height: auto;
|
||||
}
|
||||
.umb-modal .umb-panel-body{
|
||||
padding: 0px 20px 0px 20px;
|
||||
}
|
||||
|
||||
.umb-modal.fade.in.wide {
|
||||
margin-left: -640px;
|
||||
width: 640px !important;
|
||||
}
|
||||
.umb-modal i {
|
||||
font-size: 20px;
|
||||
}
|
||||
.umb-modal .breadcrumb {
|
||||
background: none;
|
||||
padding: 0
|
||||
}
|
||||
|
||||
.umb-modal .breadcrumb input {
|
||||
height: 12px
|
||||
}
|
||||
|
||||
.umb-modal.ysod {
|
||||
z-index: 10000;
|
||||
}
|
||||
/* Modals
|
||||
// -------------------------*/
|
||||
|
||||
/* Modalcolumn is used for menu panels */
|
||||
.umb-modalcolumn {
|
||||
background: @white;
|
||||
}
|
||||
|
||||
.umb-modalcolumn-header {
|
||||
background: @gray-10;
|
||||
border-bottom: 1px solid @purple-l3;
|
||||
height: 94px;
|
||||
padding: 5px 20px 0px 20px;
|
||||
white-space: nowrap
|
||||
}
|
||||
|
||||
.umb-modalcolumn-header h1{
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
font-size: @fontSizeLarge;
|
||||
font-weight: 400;
|
||||
padding-top: 10px !important;
|
||||
}
|
||||
|
||||
.umb-modalcolumn-body {
|
||||
padding: 0px;
|
||||
background: @white;
|
||||
top: 100px;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.no-padding .umb-modalcolumn-body {
|
||||
padding: 0px
|
||||
}
|
||||
|
||||
.umb-modalcolumn .umb-modalcolumn-header .btn {
|
||||
position: absolute;
|
||||
top: 13px;
|
||||
right: 15px
|
||||
}
|
||||
|
||||
.umb-modalcolumn iframe.auto-expand, .umb-modal iframe.auto-expand {
|
||||
border: none;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
position: absolute;;
|
||||
}
|
||||
|
||||
/* re-align loader */
|
||||
.umb-modal .umb-loader-wrapper, .umb-modalcolumn .umb-loader-wrapper, .umb-dialog .umb-loader-wrapper{
|
||||
position:relative;
|
||||
margin: 20px -20px;
|
||||
}
|
||||
|
||||
.umb-modal-left .umb-panel-header .umb-headline, .umb-modal-left .umb-panel-header h1 {
|
||||
width: auto;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
/* umb.dialog is used for the dialogs on the conent tree*/
|
||||
.umb-dialog {
|
||||
outline: none;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
position: absolute;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.umb-dialog .umb-btn-toolbar .umb-control-group{
|
||||
border: none;
|
||||
padding: none;
|
||||
}
|
||||
|
||||
.umb-dialog-body{
|
||||
position: absolute;
|
||||
overflow:auto;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 52px;
|
||||
}
|
||||
.umb-dialog-body .umb-pane{margin-top: 15px;}
|
||||
|
||||
.umb-dialog-footer{
|
||||
position: absolute;
|
||||
overflow:auto;
|
||||
text-align: right;
|
||||
height: 32px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
padding: 10px 20px;
|
||||
margin: 0;
|
||||
background: @gray-10;
|
||||
border-top: 1px solid @purple-l3;
|
||||
}
|
||||
|
||||
/*we will always make sure to wrap iframe dialogs in proper padding*/
|
||||
.umbracoDialog{
|
||||
width: auto !Important;
|
||||
height: auto !Important;
|
||||
padding: 20px;
|
||||
}
|
||||
.umbracoDialog .umb-pane{margin-left: 0px; margin-right: 0px; margin-top: 0px;}
|
||||
.umbracoDialog .umb-dialog-body .umb-pane{margin-left: 20px; margin-right: 20px; margin-top: 20px;}
|
||||
.umbracoDialog form{height: 100%;}
|
||||
|
||||
/*ensures dialogs doesnt have side-by-side labels*/
|
||||
.umbracoDialog .controls-row,
|
||||
.umb-modal .controls-row{margin-left: 0px !important;}
|
||||
|
||||
/* modal and umb-modal are used for right.hand dialogs */
|
||||
.modal {
|
||||
border-radius: 0 !important;
|
||||
|
||||
&.fade.in{border: none !important;}
|
||||
}
|
||||
.umb-modal.fade {
|
||||
outline: none;
|
||||
top: 0 !important;
|
||||
left: -100% !important;
|
||||
width: 0px !important;
|
||||
-webkit-transition: left 0.3s linear, left 0.3s ease-out;
|
||||
-moz-transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
-o-transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.umb-modal.fade.in {
|
||||
top: 0 !important;
|
||||
left: 100% !important;
|
||||
margin-left: -440px;
|
||||
width: 440px !important;
|
||||
height: 100% !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.umb-modal-left.fade {
|
||||
top: 0 !important;
|
||||
left: -100% !important;
|
||||
width: 0px !important;
|
||||
-webkit-transition: left 0.3s linear, left 0.3s ease-out;
|
||||
-moz-transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
-o-transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
transition: opacity 0.3s linear, top 0.3s ease-out;
|
||||
height: 100% !important;
|
||||
}
|
||||
.umb-modal-left.fade.in {
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
margin-left: 80px;
|
||||
width: 440px !important;
|
||||
height: 100% !important;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*Modal default panel styles*/
|
||||
.umb-modal .umb-panel-header {
|
||||
padding: 20px;
|
||||
background: @white;
|
||||
border: none;
|
||||
height: auto;
|
||||
}
|
||||
.umb-modal .umb-panel-body{
|
||||
padding: 0px 20px 0px 20px;
|
||||
}
|
||||
|
||||
.umb-modal.fade.in.wide {
|
||||
margin-left: -640px;
|
||||
width: 640px !important;
|
||||
}
|
||||
.umb-modal i {
|
||||
font-size: 20px;
|
||||
}
|
||||
.umb-modal .breadcrumb {
|
||||
background: none;
|
||||
padding: 0
|
||||
}
|
||||
|
||||
.umb-modal .breadcrumb input {
|
||||
height: 12px
|
||||
}
|
||||
|
||||
.umb-modal.ysod {
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
.umb-panel-header {
|
||||
background: @gray-10;
|
||||
border-bottom: 1px solid @purple-l3;
|
||||
border-bottom: 1px solid @gray-8;
|
||||
position: absolute;
|
||||
height: 99px;
|
||||
top: 0px;
|
||||
@@ -43,25 +43,15 @@
|
||||
}
|
||||
|
||||
.umb-mediapicker-upload {
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
|
||||
.form-search {
|
||||
-webkit-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
|
||||
&__toggle{
|
||||
margin: 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-left: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-button {
|
||||
@@ -368,6 +358,7 @@
|
||||
flex-direction: column;
|
||||
height: 99px;
|
||||
padding: 0 20px;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.umb-panel-header-content {
|
||||
|
||||
@@ -102,11 +102,11 @@ div.umb-codeeditor {
|
||||
border: 1px solid @gray-8;
|
||||
}
|
||||
div.umb-codeeditor .umb-el-wrap {
|
||||
padding: 0;
|
||||
padding: 0px;
|
||||
}
|
||||
div.umb-codeeditor .umb-btn-toolbar {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
border-bottom: @gray-8 1px solid;
|
||||
background: @gray-10;
|
||||
}
|
||||
@@ -115,14 +115,7 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
//
|
||||
// RTE
|
||||
// --------------------------------------------------
|
||||
.umb-rte {
|
||||
position: relative;
|
||||
|
||||
.-loading {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
.mce-tinymce{border: 1px solid @gray-8 !important; border-radius: 0 !important;}
|
||||
.mce-tinymce{border: 1px solid @gray-8 !important; border-radius: 0px !important;}
|
||||
.mce-panel{background: @gray-10 !important; border-color: @gray-8 !important;}
|
||||
.mce-btn-group, .mce-btn{border: none !important; background: none !important;}
|
||||
.mce-ico{font-size: 12px !important; color: @gray-1 !important;}
|
||||
@@ -144,15 +137,11 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
/* pre-value editor */
|
||||
.control-group.color-picker-preval {
|
||||
.thumbnail {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
width: 36px;
|
||||
min-width: auto;
|
||||
border: none;
|
||||
cursor: move;
|
||||
border-radius: 3px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.handle {
|
||||
@@ -164,19 +153,19 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
div.color-picker-prediv {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
max-width: 100%;
|
||||
flex: 1;
|
||||
max-width: 85%;
|
||||
|
||||
pre {
|
||||
display: inline-flex;
|
||||
font-family: monospace;
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
margin-bottom: 0;
|
||||
vertical-align: middle;
|
||||
padding: 6px 10px;
|
||||
padding-top: 7px;
|
||||
padding-bottom: 7px;
|
||||
background: #f7f7f7;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
@@ -204,59 +193,16 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
}
|
||||
|
||||
label {
|
||||
border: 1px solid @white;
|
||||
padding: 6px 10px;
|
||||
border: 1px solid #fff;
|
||||
padding: 7px 10px;
|
||||
font-family: monospace;
|
||||
border: 1px solid #dfdfe1;
|
||||
background: #f7f7f7;
|
||||
margin: 0 15px 0 3px;
|
||||
margin: 0 15px 0 0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Image Cropper
|
||||
// --------------------------------------------------
|
||||
|
||||
.umb-prevalues-multivalues.umb-cropsizes{
|
||||
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
min-width: 66.6%;
|
||||
|
||||
@media (min-width: 1101px) and (max-width: 1300px), (max-width: 930px) {
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.umb-overlay__form & {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-cropsizes {
|
||||
|
||||
&__add {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&__controls {
|
||||
margin: 24px 0 0;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
&__input {
|
||||
width: 100%;
|
||||
&-wrap{
|
||||
flex: 1 1 auto;
|
||||
margin-right: 10px;
|
||||
&--narrow {
|
||||
flex: 0 1 100px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Media picker
|
||||
@@ -279,18 +225,6 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
}
|
||||
}
|
||||
|
||||
.umb-mediapicker .label{
|
||||
&__trashed{
|
||||
background-color: @red;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: 1;
|
||||
transform: translate3d(-50%,-50%,0);
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-mediapicker .picked-image {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
@@ -371,7 +305,7 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
|
||||
.umb-mediapicker .umb-sortable-thumbnails li {
|
||||
flex-direction: column;
|
||||
margin: 0 0 5px 5px;
|
||||
margin: 0 5px 5px 0;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
@@ -389,7 +323,7 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
background-image: url(../img/checkered-background.png);
|
||||
}
|
||||
|
||||
.umb-sortable-thumbnails li .trashed {
|
||||
.umb-sortable-thumbnails li img.trashed {
|
||||
opacity:0.3;
|
||||
}
|
||||
|
||||
@@ -630,16 +564,6 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
}
|
||||
}
|
||||
|
||||
.imagecropper .umb-cropper__container .button-drawer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 10px;
|
||||
|
||||
button {
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-close-cropper {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
@@ -763,8 +687,8 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
|
||||
|
||||
.umb-photo-folder .picrow div, .umb-photo-preview{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
border: none;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
@@ -801,9 +725,9 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
//this is a temp hack, to provide selectors in the dialog:
|
||||
.umb-photo-folder .pic:hover .selector-overlay {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
padding: 5px;
|
||||
background: @black;
|
||||
z-index: 100;
|
||||
@@ -883,7 +807,7 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
.umb-fileupload ul {
|
||||
list-style: none;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 0;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.umb-fileupload label {
|
||||
@@ -1041,20 +965,7 @@ div.umb-codeeditor .umb-btn-toolbar {
|
||||
|
||||
//
|
||||
// Nested boolean (e.g. list view bulk action permissions)
|
||||
// -------------------------------------------------------
|
||||
// ---------------------=====-----------------------------
|
||||
.umb-nested-boolean label {margin-bottom: 8px; float: left; width: 320px;}
|
||||
.umb-nested-boolean label span {float: left; width: 80%;}
|
||||
.umb-nested-boolean label input[type='checkbox'] {margin-right: 10px; float: left;}
|
||||
|
||||
//
|
||||
// Custom styles of property editors in property preview in document type editor
|
||||
// -----------------------------------------------------------------------------
|
||||
.umb-group-builder__property-preview {
|
||||
.umb-property-editor {
|
||||
.slider {
|
||||
.tooltip {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ angular.module("umbraco")
|
||||
$scope.classes.splice(0, 0, "noclass");
|
||||
})
|
||||
|
||||
assetsService.loadCss("/App_Plugins/Lecoati.uSky.Grid/lib/uSky.Grid.ApprovedColorPicker.css", $scope);
|
||||
assetsService.loadCss(cssPath, $scope);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
function init() {
|
||||
// Check if it is a new user
|
||||
var inviteVal = $location.search().invite;
|
||||
//1 = enter password, 2 = password set, 3 = invalid token
|
||||
if (inviteVal && (inviteVal === "1" || inviteVal === "2")) {
|
||||
|
||||
$q.all([
|
||||
@@ -59,8 +58,6 @@
|
||||
$scope.inviteStep = Number(inviteVal);
|
||||
|
||||
});
|
||||
} else if (inviteVal && inviteVal === "3") {
|
||||
$scope.inviteStep = Number(inviteVal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +204,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
$scope.allowPasswordReset = Umbraco.Sys.ServerVariables.umbracoSettings.canSendRequiredEmail && Umbraco.Sys.ServerVariables.umbracoSettings.allowPasswordReset;
|
||||
$scope.allowPasswordReset = Umbraco.Sys.ServerVariables.umbracoSettings.allowPasswordReset;
|
||||
|
||||
$scope.showLogin = function () {
|
||||
$scope.errorMsg = "";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user