diff --git a/src/Umbraco.Core/Logging/WebProfiler.cs b/src/Umbraco.Core/Logging/WebProfiler.cs
index 71f1288fda..7284ea05bd 100644
--- a/src/Umbraco.Core/Logging/WebProfiler.cs
+++ b/src/Umbraco.Core/Logging/WebProfiler.cs
@@ -58,9 +58,9 @@ namespace Umbraco.Core.Logging
if (request.Success == false) return false;
if (request.Result.Url.IsClientSideRequest()) return false;
- if (string.IsNullOrEmpty(request.Result.QueryString["umbDebug"])) return false;
- if (request.Result.Url.IsBackOfficeRequest(HttpRuntime.AppDomainAppVirtualPath)) return true;
- return true;
+ if (bool.TryParse(request.Result.QueryString["umbDebug"], out var umbDebug)) return umbDebug;
+ if (bool.TryParse(request.Result.Headers["X-UMB-DEBUG"], out var xUmbDebug)) return xUmbDebug;
+ return false;
}
///
diff --git a/src/Umbraco.Core/Manifest/ManifestWatcher.cs b/src/Umbraco.Core/Manifest/ManifestWatcher.cs
index 6a8ec0e6f3..014721eb88 100644
--- a/src/Umbraco.Core/Manifest/ManifestWatcher.cs
+++ b/src/Umbraco.Core/Manifest/ManifestWatcher.cs
@@ -17,8 +17,7 @@ namespace Umbraco.Core.Manifest
public ManifestWatcher(ILogger logger)
{
- if (logger == null) throw new ArgumentNullException(nameof(logger));
- _logger = logger;
+ _logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public void Start(params string[] packageFolders)
diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs
index 1a6eadb3c8..e910b5504b 100644
--- a/src/Umbraco.Core/Services/EntityService.cs
+++ b/src/Umbraco.Core/Services/EntityService.cs
@@ -29,7 +29,7 @@ namespace Umbraco.Core.Services
IContentService contentService, IContentTypeService contentTypeService,
IMediaService mediaService, IMediaTypeService mediaTypeService,
IDataTypeService dataTypeService,
- IMemberService memberService, IMemberTypeService memberTypeService, IdkMap idkMap)
+ IMemberService memberService, IMemberTypeService memberTypeService, IdkMap idkMap,
IRuntimeCacheProvider runtimeCache)
: base(provider, logger, eventMessagesFactory)
{
@@ -542,7 +542,7 @@ namespace Umbraco.Core.Services
var entityType = GetEntityType(umbracoObjectType);
var typeFullName = entityType.FullName;
if (_supportedObjectTypes.ContainsKey(typeFullName) == false)
- throw new NotSupportedException("The passed in type is not supported.);
+ throw new NotSupportedException("The passed in type is not supported.");
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
@@ -557,7 +557,7 @@ namespace Umbraco.Core.Services
var entityType = GetEntityType(umbracoObjectType);
var typeFullName = entityType.FullName;
if (_supportedObjectTypes.ContainsKey(typeFullName) == false)
- throw new NotSupportedException("The passed in type is not supported.);
+ throw new NotSupportedException("The passed in type is not supported.");
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.CreateUnitOfWork(readOnly: true))
diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs
index 164abe444c..5451cdf1e5 100644
--- a/src/Umbraco.Core/Services/UserService.cs
+++ b/src/Umbraco.Core/Services/UserService.cs
@@ -77,6 +77,7 @@ namespace Umbraco.Core.Services
IUser IMembershipMemberService.CreateWithIdentity(string username, string email, string passwordValue, string memberTypeAlias)
{
return CreateUserWithIdentity(username, email, passwordValue);
+ }
///
/// Creates and persists a new
diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj
index 7982c105bb..fb8ccee8da 100644
--- a/src/Umbraco.Core/Umbraco.Core.csproj
+++ b/src/Umbraco.Core/Umbraco.Core.csproj
@@ -994,8 +994,6 @@
-
-
@@ -1056,25 +1054,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/src/Umbraco.Tests/DependencyInjection/ActionCollectionTests.cs b/src/Umbraco.Tests/DependencyInjection/ActionCollectionTests.cs
index 6ecc740c06..9ae1ddb6b6 100644
--- a/src/Umbraco.Tests/DependencyInjection/ActionCollectionTests.cs
+++ b/src/Umbraco.Tests/DependencyInjection/ActionCollectionTests.cs
@@ -18,7 +18,7 @@ namespace Umbraco.Tests.DI
public void FindAllActions()
{
var collectionBuilder = new ActionCollectionBuilder();
- collectionBuilder.SetProducer(() => TypeLoader.ResolveActions());
+ collectionBuilder.SetProducer(() => TypeLoader.GetActions());
var actions = collectionBuilder.CreateCollection();
Assert.AreEqual(2, actions.Count());
diff --git a/src/Umbraco.Tests/DependencyInjection/XsltExtensionsResolverTests.cs b/src/Umbraco.Tests/DependencyInjection/XsltExtensionsResolverTests.cs
index e887a787f9..e86d641d12 100644
--- a/src/Umbraco.Tests/DependencyInjection/XsltExtensionsResolverTests.cs
+++ b/src/Umbraco.Tests/DependencyInjection/XsltExtensionsResolverTests.cs
@@ -19,7 +19,7 @@ namespace Umbraco.Tests.DI
{
var container = new ServiceContainer();
var builder = new XsltExtensionCollectionBuilder(container);
- builder.AddExtensionObjectProducer(() => TypeLoader.ResolveXsltExtensions());
+ builder.AddExtensionObjectProducer(() => TypeLoader.GetXsltExtensions());
var extensions = builder.CreateCollection();
Assert.AreEqual(3, extensions.Count());
diff --git a/src/Umbraco.Tests/Plugins/PluginManagerTests.cs b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs
index 21e534e72c..7c1a0a9417 100644
--- a/src/Umbraco.Tests/Plugins/PluginManagerTests.cs
+++ b/src/Umbraco.Tests/Plugins/PluginManagerTests.cs
@@ -278,21 +278,21 @@ AnotherContentFinder
[Test]
public void Resolves_Actions()
{
- var actions = _manager.ResolveActions();
+ var actions = _manager.GetActions();
Assert.AreEqual(36, actions.Count()); // 36 classes in the solution implement IAction
}
[Test]
public void Resolves_Trees()
{
- var trees = _manager.ResolveTrees();
+ var trees = _manager.GetTrees();
Assert.AreEqual(5, trees.Count()); // 5 classes in the solution implement BaseTree
}
[Test]
public void Resolves_XsltExtensions()
{
- var types = _manager.ResolveXsltExtensions();
+ var types = _manager.GetXsltExtensions();
Assert.AreEqual(3, types.Count());
}
diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs
index 2e0ae4e595..7511a816c3 100644
--- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs
+++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs
@@ -64,10 +64,10 @@ namespace Umbraco.Tests.Routing
// set the default RenderMvcController
Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG!
- var surfaceControllerTypes = new SurfaceControllerTypeCollection(Current.TypeLoader.ResolveSurfaceControllers());
+ var surfaceControllerTypes = new SurfaceControllerTypeCollection(Current.TypeLoader.GetSurfaceControllers());
Container.RegisterInstance(surfaceControllerTypes);
- var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Current.TypeLoader.ResolveUmbracoApiControllers());
+ var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(Current.TypeLoader.GetUmbracoApiControllers());
Container.RegisterInstance(umbracoApiControllerTypes);
Container.RegisterSingleton(_ => new DefaultShortStringHelper(SettingsForTests.GetDefault()));
diff --git a/src/Umbraco.Web.UI/Content/bootstrap.css b/src/Umbraco.Web.UI/Content/bootstrap.css
new file mode 100644
index 0000000000..6167622cec
--- /dev/null
+++ b/src/Umbraco.Web.UI/Content/bootstrap.css
@@ -0,0 +1,6757 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
+html {
+ font-family: sans-serif;
+ -webkit-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+}
+body {
+ margin: 0;
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+audio,
+canvas,
+progress,
+video {
+ display: inline-block;
+ vertical-align: baseline;
+}
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+[hidden],
+template {
+ display: none;
+}
+a {
+ background-color: transparent;
+}
+a:active,
+a:hover {
+ outline: 0;
+}
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+b,
+strong {
+ font-weight: bold;
+}
+dfn {
+ font-style: italic;
+}
+h1 {
+ margin: .67em 0;
+ font-size: 2em;
+}
+mark {
+ color: #000;
+ background: #ff0;
+}
+small {
+ font-size: 80%;
+}
+sub,
+sup {
+ position: relative;
+ font-size: 75%;
+ line-height: 0;
+ vertical-align: baseline;
+}
+sup {
+ top: -.5em;
+}
+sub {
+ bottom: -.25em;
+}
+img {
+ border: 0;
+}
+svg:not(:root) {
+ overflow: hidden;
+}
+figure {
+ margin: 1em 40px;
+}
+hr {
+ height: 0;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+pre {
+ overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+ margin: 0;
+ font: inherit;
+ color: inherit;
+}
+button {
+ overflow: visible;
+}
+button,
+select {
+ text-transform: none;
+}
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button;
+ cursor: pointer;
+}
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+}
+input {
+ line-height: normal;
+}
+input[type="checkbox"],
+input[type="radio"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ padding: 0;
+}
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ -webkit-appearance: textfield;
+}
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+fieldset {
+ padding: .35em .625em .75em;
+ margin: 0 2px;
+ border: 1px solid #c0c0c0;
+}
+legend {
+ padding: 0;
+ border: 0;
+}
+textarea {
+ overflow: auto;
+}
+optgroup {
+ font-weight: bold;
+}
+table {
+ border-spacing: 0;
+ border-collapse: collapse;
+}
+td,
+th {
+ padding: 0;
+}
+/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
+@media print {
+ *,
+ *:before,
+ *:after {
+ color: #000 !important;
+ text-shadow: none !important;
+ background: transparent !important;
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+ }
+ a,
+ a:visited {
+ text-decoration: underline;
+ }
+ a[href]:after {
+ content: " (" attr(href) ")";
+ }
+ abbr[title]:after {
+ content: " (" attr(title) ")";
+ }
+ a[href^="#"]:after,
+ a[href^="javascript:"]:after {
+ content: "";
+ }
+ pre,
+ blockquote {
+ border: 1px solid #999;
+
+ page-break-inside: avoid;
+ }
+ thead {
+ display: table-header-group;
+ }
+ tr,
+ img {
+ page-break-inside: avoid;
+ }
+ img {
+ max-width: 100% !important;
+ }
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3;
+ }
+ h2,
+ h3 {
+ page-break-after: avoid;
+ }
+ .navbar {
+ display: none;
+ }
+ .btn > .caret,
+ .dropup > .btn > .caret {
+ border-top-color: #000 !important;
+ }
+ .label {
+ border: 1px solid #000;
+ }
+ .table {
+ border-collapse: collapse !important;
+ }
+ .table td,
+ .table th {
+ background-color: #fff !important;
+ }
+ .table-bordered th,
+ .table-bordered td {
+ border: 1px solid #ddd !important;
+ }
+}
+@font-face {
+ font-family: 'Glyphicons Halflings';
+
+ src: url('../fonts/glyphicons-halflings-regular.eot');
+ src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+}
+.glyphicon {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+.glyphicon-asterisk:before {
+ content: "\002a";
+}
+.glyphicon-plus:before {
+ content: "\002b";
+}
+.glyphicon-euro:before,
+.glyphicon-eur:before {
+ content: "\20ac";
+}
+.glyphicon-minus:before {
+ content: "\2212";
+}
+.glyphicon-cloud:before {
+ content: "\2601";
+}
+.glyphicon-envelope:before {
+ content: "\2709";
+}
+.glyphicon-pencil:before {
+ content: "\270f";
+}
+.glyphicon-glass:before {
+ content: "\e001";
+}
+.glyphicon-music:before {
+ content: "\e002";
+}
+.glyphicon-search:before {
+ content: "\e003";
+}
+.glyphicon-heart:before {
+ content: "\e005";
+}
+.glyphicon-star:before {
+ content: "\e006";
+}
+.glyphicon-star-empty:before {
+ content: "\e007";
+}
+.glyphicon-user:before {
+ content: "\e008";
+}
+.glyphicon-film:before {
+ content: "\e009";
+}
+.glyphicon-th-large:before {
+ content: "\e010";
+}
+.glyphicon-th:before {
+ content: "\e011";
+}
+.glyphicon-th-list:before {
+ content: "\e012";
+}
+.glyphicon-ok:before {
+ content: "\e013";
+}
+.glyphicon-remove:before {
+ content: "\e014";
+}
+.glyphicon-zoom-in:before {
+ content: "\e015";
+}
+.glyphicon-zoom-out:before {
+ content: "\e016";
+}
+.glyphicon-off:before {
+ content: "\e017";
+}
+.glyphicon-signal:before {
+ content: "\e018";
+}
+.glyphicon-cog:before {
+ content: "\e019";
+}
+.glyphicon-trash:before {
+ content: "\e020";
+}
+.glyphicon-home:before {
+ content: "\e021";
+}
+.glyphicon-file:before {
+ content: "\e022";
+}
+.glyphicon-time:before {
+ content: "\e023";
+}
+.glyphicon-road:before {
+ content: "\e024";
+}
+.glyphicon-download-alt:before {
+ content: "\e025";
+}
+.glyphicon-download:before {
+ content: "\e026";
+}
+.glyphicon-upload:before {
+ content: "\e027";
+}
+.glyphicon-inbox:before {
+ content: "\e028";
+}
+.glyphicon-play-circle:before {
+ content: "\e029";
+}
+.glyphicon-repeat:before {
+ content: "\e030";
+}
+.glyphicon-refresh:before {
+ content: "\e031";
+}
+.glyphicon-list-alt:before {
+ content: "\e032";
+}
+.glyphicon-lock:before {
+ content: "\e033";
+}
+.glyphicon-flag:before {
+ content: "\e034";
+}
+.glyphicon-headphones:before {
+ content: "\e035";
+}
+.glyphicon-volume-off:before {
+ content: "\e036";
+}
+.glyphicon-volume-down:before {
+ content: "\e037";
+}
+.glyphicon-volume-up:before {
+ content: "\e038";
+}
+.glyphicon-qrcode:before {
+ content: "\e039";
+}
+.glyphicon-barcode:before {
+ content: "\e040";
+}
+.glyphicon-tag:before {
+ content: "\e041";
+}
+.glyphicon-tags:before {
+ content: "\e042";
+}
+.glyphicon-book:before {
+ content: "\e043";
+}
+.glyphicon-bookmark:before {
+ content: "\e044";
+}
+.glyphicon-print:before {
+ content: "\e045";
+}
+.glyphicon-camera:before {
+ content: "\e046";
+}
+.glyphicon-font:before {
+ content: "\e047";
+}
+.glyphicon-bold:before {
+ content: "\e048";
+}
+.glyphicon-italic:before {
+ content: "\e049";
+}
+.glyphicon-text-height:before {
+ content: "\e050";
+}
+.glyphicon-text-width:before {
+ content: "\e051";
+}
+.glyphicon-align-left:before {
+ content: "\e052";
+}
+.glyphicon-align-center:before {
+ content: "\e053";
+}
+.glyphicon-align-right:before {
+ content: "\e054";
+}
+.glyphicon-align-justify:before {
+ content: "\e055";
+}
+.glyphicon-list:before {
+ content: "\e056";
+}
+.glyphicon-indent-left:before {
+ content: "\e057";
+}
+.glyphicon-indent-right:before {
+ content: "\e058";
+}
+.glyphicon-facetime-video:before {
+ content: "\e059";
+}
+.glyphicon-picture:before {
+ content: "\e060";
+}
+.glyphicon-map-marker:before {
+ content: "\e062";
+}
+.glyphicon-adjust:before {
+ content: "\e063";
+}
+.glyphicon-tint:before {
+ content: "\e064";
+}
+.glyphicon-edit:before {
+ content: "\e065";
+}
+.glyphicon-share:before {
+ content: "\e066";
+}
+.glyphicon-check:before {
+ content: "\e067";
+}
+.glyphicon-move:before {
+ content: "\e068";
+}
+.glyphicon-step-backward:before {
+ content: "\e069";
+}
+.glyphicon-fast-backward:before {
+ content: "\e070";
+}
+.glyphicon-backward:before {
+ content: "\e071";
+}
+.glyphicon-play:before {
+ content: "\e072";
+}
+.glyphicon-pause:before {
+ content: "\e073";
+}
+.glyphicon-stop:before {
+ content: "\e074";
+}
+.glyphicon-forward:before {
+ content: "\e075";
+}
+.glyphicon-fast-forward:before {
+ content: "\e076";
+}
+.glyphicon-step-forward:before {
+ content: "\e077";
+}
+.glyphicon-eject:before {
+ content: "\e078";
+}
+.glyphicon-chevron-left:before {
+ content: "\e079";
+}
+.glyphicon-chevron-right:before {
+ content: "\e080";
+}
+.glyphicon-plus-sign:before {
+ content: "\e081";
+}
+.glyphicon-minus-sign:before {
+ content: "\e082";
+}
+.glyphicon-remove-sign:before {
+ content: "\e083";
+}
+.glyphicon-ok-sign:before {
+ content: "\e084";
+}
+.glyphicon-question-sign:before {
+ content: "\e085";
+}
+.glyphicon-info-sign:before {
+ content: "\e086";
+}
+.glyphicon-screenshot:before {
+ content: "\e087";
+}
+.glyphicon-remove-circle:before {
+ content: "\e088";
+}
+.glyphicon-ok-circle:before {
+ content: "\e089";
+}
+.glyphicon-ban-circle:before {
+ content: "\e090";
+}
+.glyphicon-arrow-left:before {
+ content: "\e091";
+}
+.glyphicon-arrow-right:before {
+ content: "\e092";
+}
+.glyphicon-arrow-up:before {
+ content: "\e093";
+}
+.glyphicon-arrow-down:before {
+ content: "\e094";
+}
+.glyphicon-share-alt:before {
+ content: "\e095";
+}
+.glyphicon-resize-full:before {
+ content: "\e096";
+}
+.glyphicon-resize-small:before {
+ content: "\e097";
+}
+.glyphicon-exclamation-sign:before {
+ content: "\e101";
+}
+.glyphicon-gift:before {
+ content: "\e102";
+}
+.glyphicon-leaf:before {
+ content: "\e103";
+}
+.glyphicon-fire:before {
+ content: "\e104";
+}
+.glyphicon-eye-open:before {
+ content: "\e105";
+}
+.glyphicon-eye-close:before {
+ content: "\e106";
+}
+.glyphicon-warning-sign:before {
+ content: "\e107";
+}
+.glyphicon-plane:before {
+ content: "\e108";
+}
+.glyphicon-calendar:before {
+ content: "\e109";
+}
+.glyphicon-random:before {
+ content: "\e110";
+}
+.glyphicon-comment:before {
+ content: "\e111";
+}
+.glyphicon-magnet:before {
+ content: "\e112";
+}
+.glyphicon-chevron-up:before {
+ content: "\e113";
+}
+.glyphicon-chevron-down:before {
+ content: "\e114";
+}
+.glyphicon-retweet:before {
+ content: "\e115";
+}
+.glyphicon-shopping-cart:before {
+ content: "\e116";
+}
+.glyphicon-folder-close:before {
+ content: "\e117";
+}
+.glyphicon-folder-open:before {
+ content: "\e118";
+}
+.glyphicon-resize-vertical:before {
+ content: "\e119";
+}
+.glyphicon-resize-horizontal:before {
+ content: "\e120";
+}
+.glyphicon-hdd:before {
+ content: "\e121";
+}
+.glyphicon-bullhorn:before {
+ content: "\e122";
+}
+.glyphicon-bell:before {
+ content: "\e123";
+}
+.glyphicon-certificate:before {
+ content: "\e124";
+}
+.glyphicon-thumbs-up:before {
+ content: "\e125";
+}
+.glyphicon-thumbs-down:before {
+ content: "\e126";
+}
+.glyphicon-hand-right:before {
+ content: "\e127";
+}
+.glyphicon-hand-left:before {
+ content: "\e128";
+}
+.glyphicon-hand-up:before {
+ content: "\e129";
+}
+.glyphicon-hand-down:before {
+ content: "\e130";
+}
+.glyphicon-circle-arrow-right:before {
+ content: "\e131";
+}
+.glyphicon-circle-arrow-left:before {
+ content: "\e132";
+}
+.glyphicon-circle-arrow-up:before {
+ content: "\e133";
+}
+.glyphicon-circle-arrow-down:before {
+ content: "\e134";
+}
+.glyphicon-globe:before {
+ content: "\e135";
+}
+.glyphicon-wrench:before {
+ content: "\e136";
+}
+.glyphicon-tasks:before {
+ content: "\e137";
+}
+.glyphicon-filter:before {
+ content: "\e138";
+}
+.glyphicon-briefcase:before {
+ content: "\e139";
+}
+.glyphicon-fullscreen:before {
+ content: "\e140";
+}
+.glyphicon-dashboard:before {
+ content: "\e141";
+}
+.glyphicon-paperclip:before {
+ content: "\e142";
+}
+.glyphicon-heart-empty:before {
+ content: "\e143";
+}
+.glyphicon-link:before {
+ content: "\e144";
+}
+.glyphicon-phone:before {
+ content: "\e145";
+}
+.glyphicon-pushpin:before {
+ content: "\e146";
+}
+.glyphicon-usd:before {
+ content: "\e148";
+}
+.glyphicon-gbp:before {
+ content: "\e149";
+}
+.glyphicon-sort:before {
+ content: "\e150";
+}
+.glyphicon-sort-by-alphabet:before {
+ content: "\e151";
+}
+.glyphicon-sort-by-alphabet-alt:before {
+ content: "\e152";
+}
+.glyphicon-sort-by-order:before {
+ content: "\e153";
+}
+.glyphicon-sort-by-order-alt:before {
+ content: "\e154";
+}
+.glyphicon-sort-by-attributes:before {
+ content: "\e155";
+}
+.glyphicon-sort-by-attributes-alt:before {
+ content: "\e156";
+}
+.glyphicon-unchecked:before {
+ content: "\e157";
+}
+.glyphicon-expand:before {
+ content: "\e158";
+}
+.glyphicon-collapse-down:before {
+ content: "\e159";
+}
+.glyphicon-collapse-up:before {
+ content: "\e160";
+}
+.glyphicon-log-in:before {
+ content: "\e161";
+}
+.glyphicon-flash:before {
+ content: "\e162";
+}
+.glyphicon-log-out:before {
+ content: "\e163";
+}
+.glyphicon-new-window:before {
+ content: "\e164";
+}
+.glyphicon-record:before {
+ content: "\e165";
+}
+.glyphicon-save:before {
+ content: "\e166";
+}
+.glyphicon-open:before {
+ content: "\e167";
+}
+.glyphicon-saved:before {
+ content: "\e168";
+}
+.glyphicon-import:before {
+ content: "\e169";
+}
+.glyphicon-export:before {
+ content: "\e170";
+}
+.glyphicon-send:before {
+ content: "\e171";
+}
+.glyphicon-floppy-disk:before {
+ content: "\e172";
+}
+.glyphicon-floppy-saved:before {
+ content: "\e173";
+}
+.glyphicon-floppy-remove:before {
+ content: "\e174";
+}
+.glyphicon-floppy-save:before {
+ content: "\e175";
+}
+.glyphicon-floppy-open:before {
+ content: "\e176";
+}
+.glyphicon-credit-card:before {
+ content: "\e177";
+}
+.glyphicon-transfer:before {
+ content: "\e178";
+}
+.glyphicon-cutlery:before {
+ content: "\e179";
+}
+.glyphicon-header:before {
+ content: "\e180";
+}
+.glyphicon-compressed:before {
+ content: "\e181";
+}
+.glyphicon-earphone:before {
+ content: "\e182";
+}
+.glyphicon-phone-alt:before {
+ content: "\e183";
+}
+.glyphicon-tower:before {
+ content: "\e184";
+}
+.glyphicon-stats:before {
+ content: "\e185";
+}
+.glyphicon-sd-video:before {
+ content: "\e186";
+}
+.glyphicon-hd-video:before {
+ content: "\e187";
+}
+.glyphicon-subtitles:before {
+ content: "\e188";
+}
+.glyphicon-sound-stereo:before {
+ content: "\e189";
+}
+.glyphicon-sound-dolby:before {
+ content: "\e190";
+}
+.glyphicon-sound-5-1:before {
+ content: "\e191";
+}
+.glyphicon-sound-6-1:before {
+ content: "\e192";
+}
+.glyphicon-sound-7-1:before {
+ content: "\e193";
+}
+.glyphicon-copyright-mark:before {
+ content: "\e194";
+}
+.glyphicon-registration-mark:before {
+ content: "\e195";
+}
+.glyphicon-cloud-download:before {
+ content: "\e197";
+}
+.glyphicon-cloud-upload:before {
+ content: "\e198";
+}
+.glyphicon-tree-conifer:before {
+ content: "\e199";
+}
+.glyphicon-tree-deciduous:before {
+ content: "\e200";
+}
+.glyphicon-cd:before {
+ content: "\e201";
+}
+.glyphicon-save-file:before {
+ content: "\e202";
+}
+.glyphicon-open-file:before {
+ content: "\e203";
+}
+.glyphicon-level-up:before {
+ content: "\e204";
+}
+.glyphicon-copy:before {
+ content: "\e205";
+}
+.glyphicon-paste:before {
+ content: "\e206";
+}
+.glyphicon-alert:before {
+ content: "\e209";
+}
+.glyphicon-equalizer:before {
+ content: "\e210";
+}
+.glyphicon-king:before {
+ content: "\e211";
+}
+.glyphicon-queen:before {
+ content: "\e212";
+}
+.glyphicon-pawn:before {
+ content: "\e213";
+}
+.glyphicon-bishop:before {
+ content: "\e214";
+}
+.glyphicon-knight:before {
+ content: "\e215";
+}
+.glyphicon-baby-formula:before {
+ content: "\e216";
+}
+.glyphicon-tent:before {
+ content: "\26fa";
+}
+.glyphicon-blackboard:before {
+ content: "\e218";
+}
+.glyphicon-bed:before {
+ content: "\e219";
+}
+.glyphicon-apple:before {
+ content: "\f8ff";
+}
+.glyphicon-erase:before {
+ content: "\e221";
+}
+.glyphicon-hourglass:before {
+ content: "\231b";
+}
+.glyphicon-lamp:before {
+ content: "\e223";
+}
+.glyphicon-duplicate:before {
+ content: "\e224";
+}
+.glyphicon-piggy-bank:before {
+ content: "\e225";
+}
+.glyphicon-scissors:before {
+ content: "\e226";
+}
+.glyphicon-bitcoin:before {
+ content: "\e227";
+}
+.glyphicon-btc:before {
+ content: "\e227";
+}
+.glyphicon-xbt:before {
+ content: "\e227";
+}
+.glyphicon-yen:before {
+ content: "\00a5";
+}
+.glyphicon-jpy:before {
+ content: "\00a5";
+}
+.glyphicon-ruble:before {
+ content: "\20bd";
+}
+.glyphicon-rub:before {
+ content: "\20bd";
+}
+.glyphicon-scale:before {
+ content: "\e230";
+}
+.glyphicon-ice-lolly:before {
+ content: "\e231";
+}
+.glyphicon-ice-lolly-tasted:before {
+ content: "\e232";
+}
+.glyphicon-education:before {
+ content: "\e233";
+}
+.glyphicon-option-horizontal:before {
+ content: "\e234";
+}
+.glyphicon-option-vertical:before {
+ content: "\e235";
+}
+.glyphicon-menu-hamburger:before {
+ content: "\e236";
+}
+.glyphicon-modal-window:before {
+ content: "\e237";
+}
+.glyphicon-oil:before {
+ content: "\e238";
+}
+.glyphicon-grain:before {
+ content: "\e239";
+}
+.glyphicon-sunglasses:before {
+ content: "\e240";
+}
+.glyphicon-text-size:before {
+ content: "\e241";
+}
+.glyphicon-text-color:before {
+ content: "\e242";
+}
+.glyphicon-text-background:before {
+ content: "\e243";
+}
+.glyphicon-object-align-top:before {
+ content: "\e244";
+}
+.glyphicon-object-align-bottom:before {
+ content: "\e245";
+}
+.glyphicon-object-align-horizontal:before {
+ content: "\e246";
+}
+.glyphicon-object-align-left:before {
+ content: "\e247";
+}
+.glyphicon-object-align-vertical:before {
+ content: "\e248";
+}
+.glyphicon-object-align-right:before {
+ content: "\e249";
+}
+.glyphicon-triangle-right:before {
+ content: "\e250";
+}
+.glyphicon-triangle-left:before {
+ content: "\e251";
+}
+.glyphicon-triangle-bottom:before {
+ content: "\e252";
+}
+.glyphicon-triangle-top:before {
+ content: "\e253";
+}
+.glyphicon-console:before {
+ content: "\e254";
+}
+.glyphicon-superscript:before {
+ content: "\e255";
+}
+.glyphicon-subscript:before {
+ content: "\e256";
+}
+.glyphicon-menu-left:before {
+ content: "\e257";
+}
+.glyphicon-menu-right:before {
+ content: "\e258";
+}
+.glyphicon-menu-down:before {
+ content: "\e259";
+}
+.glyphicon-menu-up:before {
+ content: "\e260";
+}
+* {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+*:before,
+*:after {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+html {
+ font-size: 10px;
+
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+body {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #333;
+ background-color: #fff;
+}
+input,
+button,
+select,
+textarea {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+a {
+ color: #337ab7;
+ text-decoration: none;
+}
+a:hover,
+a:focus {
+ color: #23527c;
+ text-decoration: underline;
+}
+a:focus {
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+figure {
+ margin: 0;
+}
+img {
+ vertical-align: middle;
+}
+.img-responsive,
+.thumbnail > img,
+.thumbnail a > img,
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ display: block;
+ max-width: 100%;
+ height: auto;
+}
+.img-rounded {
+ border-radius: 6px;
+}
+.img-thumbnail {
+ display: inline-block;
+ max-width: 100%;
+ height: auto;
+ padding: 4px;
+ line-height: 1.42857143;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ -webkit-transition: all .2s ease-in-out;
+ -o-transition: all .2s ease-in-out;
+ transition: all .2s ease-in-out;
+}
+.img-circle {
+ border-radius: 50%;
+}
+hr {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ border: 0;
+ border-top: 1px solid #eee;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ clip: auto;
+}
+[role="button"] {
+ cursor: pointer;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+ font-family: inherit;
+ font-weight: 500;
+ line-height: 1.1;
+ color: inherit;
+}
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small,
+.h1 small,
+.h2 small,
+.h3 small,
+.h4 small,
+.h5 small,
+.h6 small,
+h1 .small,
+h2 .small,
+h3 .small,
+h4 .small,
+h5 .small,
+h6 .small,
+.h1 .small,
+.h2 .small,
+.h3 .small,
+.h4 .small,
+.h5 .small,
+.h6 .small {
+ font-weight: normal;
+ line-height: 1;
+ color: #777;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 20px;
+ margin-bottom: 10px;
+}
+h1 small,
+.h1 small,
+h2 small,
+.h2 small,
+h3 small,
+.h3 small,
+h1 .small,
+.h1 .small,
+h2 .small,
+.h2 .small,
+h3 .small,
+.h3 .small {
+ font-size: 65%;
+}
+h4,
+.h4,
+h5,
+.h5,
+h6,
+.h6 {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+h4 small,
+.h4 small,
+h5 small,
+.h5 small,
+h6 small,
+.h6 small,
+h4 .small,
+.h4 .small,
+h5 .small,
+.h5 .small,
+h6 .small,
+.h6 .small {
+ font-size: 75%;
+}
+h1,
+.h1 {
+ font-size: 36px;
+}
+h2,
+.h2 {
+ font-size: 30px;
+}
+h3,
+.h3 {
+ font-size: 24px;
+}
+h4,
+.h4 {
+ font-size: 18px;
+}
+h5,
+.h5 {
+ font-size: 14px;
+}
+h6,
+.h6 {
+ font-size: 12px;
+}
+p {
+ margin: 0 0 10px;
+}
+.lead {
+ margin-bottom: 20px;
+ font-size: 16px;
+ font-weight: 300;
+ line-height: 1.4;
+}
+@media (min-width: 768px) {
+ .lead {
+ font-size: 21px;
+ }
+}
+small,
+.small {
+ font-size: 85%;
+}
+mark,
+.mark {
+ padding: .2em;
+ background-color: #fcf8e3;
+}
+.text-left {
+ text-align: left;
+}
+.text-right {
+ text-align: right;
+}
+.text-center {
+ text-align: center;
+}
+.text-justify {
+ text-align: justify;
+}
+.text-nowrap {
+ white-space: nowrap;
+}
+.text-lowercase {
+ text-transform: lowercase;
+}
+.text-uppercase {
+ text-transform: uppercase;
+}
+.text-capitalize {
+ text-transform: capitalize;
+}
+.text-muted {
+ color: #777;
+}
+.text-primary {
+ color: #337ab7;
+}
+a.text-primary:hover,
+a.text-primary:focus {
+ color: #286090;
+}
+.text-success {
+ color: #3c763d;
+}
+a.text-success:hover,
+a.text-success:focus {
+ color: #2b542c;
+}
+.text-info {
+ color: #31708f;
+}
+a.text-info:hover,
+a.text-info:focus {
+ color: #245269;
+}
+.text-warning {
+ color: #8a6d3b;
+}
+a.text-warning:hover,
+a.text-warning:focus {
+ color: #66512c;
+}
+.text-danger {
+ color: #a94442;
+}
+a.text-danger:hover,
+a.text-danger:focus {
+ color: #843534;
+}
+.bg-primary {
+ color: #fff;
+ background-color: #337ab7;
+}
+a.bg-primary:hover,
+a.bg-primary:focus {
+ background-color: #286090;
+}
+.bg-success {
+ background-color: #dff0d8;
+}
+a.bg-success:hover,
+a.bg-success:focus {
+ background-color: #c1e2b3;
+}
+.bg-info {
+ background-color: #d9edf7;
+}
+a.bg-info:hover,
+a.bg-info:focus {
+ background-color: #afd9ee;
+}
+.bg-warning {
+ background-color: #fcf8e3;
+}
+a.bg-warning:hover,
+a.bg-warning:focus {
+ background-color: #f7ecb5;
+}
+.bg-danger {
+ background-color: #f2dede;
+}
+a.bg-danger:hover,
+a.bg-danger:focus {
+ background-color: #e4b9b9;
+}
+.page-header {
+ padding-bottom: 9px;
+ margin: 40px 0 20px;
+ border-bottom: 1px solid #eee;
+}
+ul,
+ol {
+ margin-top: 0;
+ margin-bottom: 10px;
+}
+ul ul,
+ol ul,
+ul ol,
+ol ol {
+ margin-bottom: 0;
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+.list-inline {
+ padding-left: 0;
+ margin-left: -5px;
+ list-style: none;
+}
+.list-inline > li {
+ display: inline-block;
+ padding-right: 5px;
+ padding-left: 5px;
+}
+dl {
+ margin-top: 0;
+ margin-bottom: 20px;
+}
+dt,
+dd {
+ line-height: 1.42857143;
+}
+dt {
+ font-weight: bold;
+}
+dd {
+ margin-left: 0;
+}
+@media (min-width: 768px) {
+ .dl-horizontal dt {
+ float: left;
+ width: 160px;
+ overflow: hidden;
+ clear: left;
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ .dl-horizontal dd {
+ margin-left: 180px;
+ }
+}
+abbr[title],
+abbr[data-original-title] {
+ cursor: help;
+ border-bottom: 1px dotted #777;
+}
+.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+blockquote {
+ padding: 10px 20px;
+ margin: 0 0 20px;
+ font-size: 17.5px;
+ border-left: 5px solid #eee;
+}
+blockquote p:last-child,
+blockquote ul:last-child,
+blockquote ol:last-child {
+ margin-bottom: 0;
+}
+blockquote footer,
+blockquote small,
+blockquote .small {
+ display: block;
+ font-size: 80%;
+ line-height: 1.42857143;
+ color: #777;
+}
+blockquote footer:before,
+blockquote small:before,
+blockquote .small:before {
+ content: '\2014 \00A0';
+}
+.blockquote-reverse,
+blockquote.pull-right {
+ padding-right: 15px;
+ padding-left: 0;
+ text-align: right;
+ border-right: 5px solid #eee;
+ border-left: 0;
+}
+.blockquote-reverse footer:before,
+blockquote.pull-right footer:before,
+.blockquote-reverse small:before,
+blockquote.pull-right small:before,
+.blockquote-reverse .small:before,
+blockquote.pull-right .small:before {
+ content: '';
+}
+.blockquote-reverse footer:after,
+blockquote.pull-right footer:after,
+.blockquote-reverse small:after,
+blockquote.pull-right small:after,
+.blockquote-reverse .small:after,
+blockquote.pull-right .small:after {
+ content: '\00A0 \2014';
+}
+address {
+ margin-bottom: 20px;
+ font-style: normal;
+ line-height: 1.42857143;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+code {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #c7254e;
+ background-color: #f9f2f4;
+ border-radius: 4px;
+}
+kbd {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #fff;
+ background-color: #333;
+ border-radius: 3px;
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);
+}
+kbd kbd {
+ padding: 0;
+ font-size: 100%;
+ font-weight: bold;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+pre {
+ display: block;
+ padding: 9.5px;
+ margin: 0 0 10px;
+ font-size: 13px;
+ line-height: 1.42857143;
+ color: #333;
+ word-break: break-all;
+ word-wrap: break-word;
+ background-color: #f5f5f5;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+}
+pre code {
+ padding: 0;
+ font-size: inherit;
+ color: inherit;
+ white-space: pre-wrap;
+ background-color: transparent;
+ border-radius: 0;
+}
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll;
+}
+.container {
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+@media (min-width: 768px) {
+ .container {
+ width: 750px;
+ }
+}
+@media (min-width: 992px) {
+ .container {
+ width: 970px;
+ }
+}
+@media (min-width: 1200px) {
+ .container {
+ width: 1170px;
+ }
+}
+.container-fluid {
+ padding-right: 15px;
+ padding-left: 15px;
+ margin-right: auto;
+ margin-left: auto;
+}
+.row {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
+ position: relative;
+ min-height: 1px;
+ padding-right: 15px;
+ padding-left: 15px;
+}
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
+ float: left;
+}
+.col-xs-12 {
+ width: 100%;
+}
+.col-xs-11 {
+ width: 91.66666667%;
+}
+.col-xs-10 {
+ width: 83.33333333%;
+}
+.col-xs-9 {
+ width: 75%;
+}
+.col-xs-8 {
+ width: 66.66666667%;
+}
+.col-xs-7 {
+ width: 58.33333333%;
+}
+.col-xs-6 {
+ width: 50%;
+}
+.col-xs-5 {
+ width: 41.66666667%;
+}
+.col-xs-4 {
+ width: 33.33333333%;
+}
+.col-xs-3 {
+ width: 25%;
+}
+.col-xs-2 {
+ width: 16.66666667%;
+}
+.col-xs-1 {
+ width: 8.33333333%;
+}
+.col-xs-pull-12 {
+ right: 100%;
+}
+.col-xs-pull-11 {
+ right: 91.66666667%;
+}
+.col-xs-pull-10 {
+ right: 83.33333333%;
+}
+.col-xs-pull-9 {
+ right: 75%;
+}
+.col-xs-pull-8 {
+ right: 66.66666667%;
+}
+.col-xs-pull-7 {
+ right: 58.33333333%;
+}
+.col-xs-pull-6 {
+ right: 50%;
+}
+.col-xs-pull-5 {
+ right: 41.66666667%;
+}
+.col-xs-pull-4 {
+ right: 33.33333333%;
+}
+.col-xs-pull-3 {
+ right: 25%;
+}
+.col-xs-pull-2 {
+ right: 16.66666667%;
+}
+.col-xs-pull-1 {
+ right: 8.33333333%;
+}
+.col-xs-pull-0 {
+ right: auto;
+}
+.col-xs-push-12 {
+ left: 100%;
+}
+.col-xs-push-11 {
+ left: 91.66666667%;
+}
+.col-xs-push-10 {
+ left: 83.33333333%;
+}
+.col-xs-push-9 {
+ left: 75%;
+}
+.col-xs-push-8 {
+ left: 66.66666667%;
+}
+.col-xs-push-7 {
+ left: 58.33333333%;
+}
+.col-xs-push-6 {
+ left: 50%;
+}
+.col-xs-push-5 {
+ left: 41.66666667%;
+}
+.col-xs-push-4 {
+ left: 33.33333333%;
+}
+.col-xs-push-3 {
+ left: 25%;
+}
+.col-xs-push-2 {
+ left: 16.66666667%;
+}
+.col-xs-push-1 {
+ left: 8.33333333%;
+}
+.col-xs-push-0 {
+ left: auto;
+}
+.col-xs-offset-12 {
+ margin-left: 100%;
+}
+.col-xs-offset-11 {
+ margin-left: 91.66666667%;
+}
+.col-xs-offset-10 {
+ margin-left: 83.33333333%;
+}
+.col-xs-offset-9 {
+ margin-left: 75%;
+}
+.col-xs-offset-8 {
+ margin-left: 66.66666667%;
+}
+.col-xs-offset-7 {
+ margin-left: 58.33333333%;
+}
+.col-xs-offset-6 {
+ margin-left: 50%;
+}
+.col-xs-offset-5 {
+ margin-left: 41.66666667%;
+}
+.col-xs-offset-4 {
+ margin-left: 33.33333333%;
+}
+.col-xs-offset-3 {
+ margin-left: 25%;
+}
+.col-xs-offset-2 {
+ margin-left: 16.66666667%;
+}
+.col-xs-offset-1 {
+ margin-left: 8.33333333%;
+}
+.col-xs-offset-0 {
+ margin-left: 0;
+}
+@media (min-width: 768px) {
+ .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
+ float: left;
+ }
+ .col-sm-12 {
+ width: 100%;
+ }
+ .col-sm-11 {
+ width: 91.66666667%;
+ }
+ .col-sm-10 {
+ width: 83.33333333%;
+ }
+ .col-sm-9 {
+ width: 75%;
+ }
+ .col-sm-8 {
+ width: 66.66666667%;
+ }
+ .col-sm-7 {
+ width: 58.33333333%;
+ }
+ .col-sm-6 {
+ width: 50%;
+ }
+ .col-sm-5 {
+ width: 41.66666667%;
+ }
+ .col-sm-4 {
+ width: 33.33333333%;
+ }
+ .col-sm-3 {
+ width: 25%;
+ }
+ .col-sm-2 {
+ width: 16.66666667%;
+ }
+ .col-sm-1 {
+ width: 8.33333333%;
+ }
+ .col-sm-pull-12 {
+ right: 100%;
+ }
+ .col-sm-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-sm-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-sm-pull-9 {
+ right: 75%;
+ }
+ .col-sm-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-sm-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-sm-pull-6 {
+ right: 50%;
+ }
+ .col-sm-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-sm-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-sm-pull-3 {
+ right: 25%;
+ }
+ .col-sm-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-sm-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-sm-pull-0 {
+ right: auto;
+ }
+ .col-sm-push-12 {
+ left: 100%;
+ }
+ .col-sm-push-11 {
+ left: 91.66666667%;
+ }
+ .col-sm-push-10 {
+ left: 83.33333333%;
+ }
+ .col-sm-push-9 {
+ left: 75%;
+ }
+ .col-sm-push-8 {
+ left: 66.66666667%;
+ }
+ .col-sm-push-7 {
+ left: 58.33333333%;
+ }
+ .col-sm-push-6 {
+ left: 50%;
+ }
+ .col-sm-push-5 {
+ left: 41.66666667%;
+ }
+ .col-sm-push-4 {
+ left: 33.33333333%;
+ }
+ .col-sm-push-3 {
+ left: 25%;
+ }
+ .col-sm-push-2 {
+ left: 16.66666667%;
+ }
+ .col-sm-push-1 {
+ left: 8.33333333%;
+ }
+ .col-sm-push-0 {
+ left: auto;
+ }
+ .col-sm-offset-12 {
+ margin-left: 100%;
+ }
+ .col-sm-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-sm-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-sm-offset-9 {
+ margin-left: 75%;
+ }
+ .col-sm-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-sm-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-sm-offset-6 {
+ margin-left: 50%;
+ }
+ .col-sm-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-sm-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-sm-offset-3 {
+ margin-left: 25%;
+ }
+ .col-sm-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-sm-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-sm-offset-0 {
+ margin-left: 0;
+ }
+}
+@media (min-width: 992px) {
+ .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
+ float: left;
+ }
+ .col-md-12 {
+ width: 100%;
+ }
+ .col-md-11 {
+ width: 91.66666667%;
+ }
+ .col-md-10 {
+ width: 83.33333333%;
+ }
+ .col-md-9 {
+ width: 75%;
+ }
+ .col-md-8 {
+ width: 66.66666667%;
+ }
+ .col-md-7 {
+ width: 58.33333333%;
+ }
+ .col-md-6 {
+ width: 50%;
+ }
+ .col-md-5 {
+ width: 41.66666667%;
+ }
+ .col-md-4 {
+ width: 33.33333333%;
+ }
+ .col-md-3 {
+ width: 25%;
+ }
+ .col-md-2 {
+ width: 16.66666667%;
+ }
+ .col-md-1 {
+ width: 8.33333333%;
+ }
+ .col-md-pull-12 {
+ right: 100%;
+ }
+ .col-md-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-md-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-md-pull-9 {
+ right: 75%;
+ }
+ .col-md-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-md-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-md-pull-6 {
+ right: 50%;
+ }
+ .col-md-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-md-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-md-pull-3 {
+ right: 25%;
+ }
+ .col-md-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-md-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-md-pull-0 {
+ right: auto;
+ }
+ .col-md-push-12 {
+ left: 100%;
+ }
+ .col-md-push-11 {
+ left: 91.66666667%;
+ }
+ .col-md-push-10 {
+ left: 83.33333333%;
+ }
+ .col-md-push-9 {
+ left: 75%;
+ }
+ .col-md-push-8 {
+ left: 66.66666667%;
+ }
+ .col-md-push-7 {
+ left: 58.33333333%;
+ }
+ .col-md-push-6 {
+ left: 50%;
+ }
+ .col-md-push-5 {
+ left: 41.66666667%;
+ }
+ .col-md-push-4 {
+ left: 33.33333333%;
+ }
+ .col-md-push-3 {
+ left: 25%;
+ }
+ .col-md-push-2 {
+ left: 16.66666667%;
+ }
+ .col-md-push-1 {
+ left: 8.33333333%;
+ }
+ .col-md-push-0 {
+ left: auto;
+ }
+ .col-md-offset-12 {
+ margin-left: 100%;
+ }
+ .col-md-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-md-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-md-offset-9 {
+ margin-left: 75%;
+ }
+ .col-md-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-md-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-md-offset-6 {
+ margin-left: 50%;
+ }
+ .col-md-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-md-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-md-offset-3 {
+ margin-left: 25%;
+ }
+ .col-md-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-md-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-md-offset-0 {
+ margin-left: 0;
+ }
+}
+@media (min-width: 1200px) {
+ .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
+ float: left;
+ }
+ .col-lg-12 {
+ width: 100%;
+ }
+ .col-lg-11 {
+ width: 91.66666667%;
+ }
+ .col-lg-10 {
+ width: 83.33333333%;
+ }
+ .col-lg-9 {
+ width: 75%;
+ }
+ .col-lg-8 {
+ width: 66.66666667%;
+ }
+ .col-lg-7 {
+ width: 58.33333333%;
+ }
+ .col-lg-6 {
+ width: 50%;
+ }
+ .col-lg-5 {
+ width: 41.66666667%;
+ }
+ .col-lg-4 {
+ width: 33.33333333%;
+ }
+ .col-lg-3 {
+ width: 25%;
+ }
+ .col-lg-2 {
+ width: 16.66666667%;
+ }
+ .col-lg-1 {
+ width: 8.33333333%;
+ }
+ .col-lg-pull-12 {
+ right: 100%;
+ }
+ .col-lg-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-lg-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-lg-pull-9 {
+ right: 75%;
+ }
+ .col-lg-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-lg-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-lg-pull-6 {
+ right: 50%;
+ }
+ .col-lg-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-lg-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-lg-pull-3 {
+ right: 25%;
+ }
+ .col-lg-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-lg-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-lg-pull-0 {
+ right: auto;
+ }
+ .col-lg-push-12 {
+ left: 100%;
+ }
+ .col-lg-push-11 {
+ left: 91.66666667%;
+ }
+ .col-lg-push-10 {
+ left: 83.33333333%;
+ }
+ .col-lg-push-9 {
+ left: 75%;
+ }
+ .col-lg-push-8 {
+ left: 66.66666667%;
+ }
+ .col-lg-push-7 {
+ left: 58.33333333%;
+ }
+ .col-lg-push-6 {
+ left: 50%;
+ }
+ .col-lg-push-5 {
+ left: 41.66666667%;
+ }
+ .col-lg-push-4 {
+ left: 33.33333333%;
+ }
+ .col-lg-push-3 {
+ left: 25%;
+ }
+ .col-lg-push-2 {
+ left: 16.66666667%;
+ }
+ .col-lg-push-1 {
+ left: 8.33333333%;
+ }
+ .col-lg-push-0 {
+ left: auto;
+ }
+ .col-lg-offset-12 {
+ margin-left: 100%;
+ }
+ .col-lg-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-lg-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-lg-offset-9 {
+ margin-left: 75%;
+ }
+ .col-lg-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-lg-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-lg-offset-6 {
+ margin-left: 50%;
+ }
+ .col-lg-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-lg-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-lg-offset-3 {
+ margin-left: 25%;
+ }
+ .col-lg-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-lg-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-lg-offset-0 {
+ margin-left: 0;
+ }
+}
+table {
+ background-color: transparent;
+}
+caption {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ color: #777;
+ text-align: left;
+}
+th {
+ text-align: left;
+}
+.table {
+ width: 100%;
+ max-width: 100%;
+ margin-bottom: 20px;
+}
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+ padding: 8px;
+ line-height: 1.42857143;
+ vertical-align: top;
+ border-top: 1px solid #ddd;
+}
+.table > thead > tr > th {
+ vertical-align: bottom;
+ border-bottom: 2px solid #ddd;
+}
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.table > thead:first-child > tr:first-child > td {
+ border-top: 0;
+}
+.table > tbody + tbody {
+ border-top: 2px solid #ddd;
+}
+.table .table {
+ background-color: #fff;
+}
+.table-condensed > thead > tr > th,
+.table-condensed > tbody > tr > th,
+.table-condensed > tfoot > tr > th,
+.table-condensed > thead > tr > td,
+.table-condensed > tbody > tr > td,
+.table-condensed > tfoot > tr > td {
+ padding: 5px;
+}
+.table-bordered {
+ border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > tbody > tr > th,
+.table-bordered > tfoot > tr > th,
+.table-bordered > thead > tr > td,
+.table-bordered > tbody > tr > td,
+.table-bordered > tfoot > tr > td {
+ border: 1px solid #ddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > thead > tr > td {
+ border-bottom-width: 2px;
+}
+.table-striped > tbody > tr:nth-of-type(odd) {
+ background-color: #f9f9f9;
+}
+.table-hover > tbody > tr:hover {
+ background-color: #f5f5f5;
+}
+table col[class*="col-"] {
+ position: static;
+ display: table-column;
+ float: none;
+}
+table td[class*="col-"],
+table th[class*="col-"] {
+ position: static;
+ display: table-cell;
+ float: none;
+}
+.table > thead > tr > td.active,
+.table > tbody > tr > td.active,
+.table > tfoot > tr > td.active,
+.table > thead > tr > th.active,
+.table > tbody > tr > th.active,
+.table > tfoot > tr > th.active,
+.table > thead > tr.active > td,
+.table > tbody > tr.active > td,
+.table > tfoot > tr.active > td,
+.table > thead > tr.active > th,
+.table > tbody > tr.active > th,
+.table > tfoot > tr.active > th {
+ background-color: #f5f5f5;
+}
+.table-hover > tbody > tr > td.active:hover,
+.table-hover > tbody > tr > th.active:hover,
+.table-hover > tbody > tr.active:hover > td,
+.table-hover > tbody > tr:hover > .active,
+.table-hover > tbody > tr.active:hover > th {
+ background-color: #e8e8e8;
+}
+.table > thead > tr > td.success,
+.table > tbody > tr > td.success,
+.table > tfoot > tr > td.success,
+.table > thead > tr > th.success,
+.table > tbody > tr > th.success,
+.table > tfoot > tr > th.success,
+.table > thead > tr.success > td,
+.table > tbody > tr.success > td,
+.table > tfoot > tr.success > td,
+.table > thead > tr.success > th,
+.table > tbody > tr.success > th,
+.table > tfoot > tr.success > th {
+ background-color: #dff0d8;
+}
+.table-hover > tbody > tr > td.success:hover,
+.table-hover > tbody > tr > th.success:hover,
+.table-hover > tbody > tr.success:hover > td,
+.table-hover > tbody > tr:hover > .success,
+.table-hover > tbody > tr.success:hover > th {
+ background-color: #d0e9c6;
+}
+.table > thead > tr > td.info,
+.table > tbody > tr > td.info,
+.table > tfoot > tr > td.info,
+.table > thead > tr > th.info,
+.table > tbody > tr > th.info,
+.table > tfoot > tr > th.info,
+.table > thead > tr.info > td,
+.table > tbody > tr.info > td,
+.table > tfoot > tr.info > td,
+.table > thead > tr.info > th,
+.table > tbody > tr.info > th,
+.table > tfoot > tr.info > th {
+ background-color: #d9edf7;
+}
+.table-hover > tbody > tr > td.info:hover,
+.table-hover > tbody > tr > th.info:hover,
+.table-hover > tbody > tr.info:hover > td,
+.table-hover > tbody > tr:hover > .info,
+.table-hover > tbody > tr.info:hover > th {
+ background-color: #c4e3f3;
+}
+.table > thead > tr > td.warning,
+.table > tbody > tr > td.warning,
+.table > tfoot > tr > td.warning,
+.table > thead > tr > th.warning,
+.table > tbody > tr > th.warning,
+.table > tfoot > tr > th.warning,
+.table > thead > tr.warning > td,
+.table > tbody > tr.warning > td,
+.table > tfoot > tr.warning > td,
+.table > thead > tr.warning > th,
+.table > tbody > tr.warning > th,
+.table > tfoot > tr.warning > th {
+ background-color: #fcf8e3;
+}
+.table-hover > tbody > tr > td.warning:hover,
+.table-hover > tbody > tr > th.warning:hover,
+.table-hover > tbody > tr.warning:hover > td,
+.table-hover > tbody > tr:hover > .warning,
+.table-hover > tbody > tr.warning:hover > th {
+ background-color: #faf2cc;
+}
+.table > thead > tr > td.danger,
+.table > tbody > tr > td.danger,
+.table > tfoot > tr > td.danger,
+.table > thead > tr > th.danger,
+.table > tbody > tr > th.danger,
+.table > tfoot > tr > th.danger,
+.table > thead > tr.danger > td,
+.table > tbody > tr.danger > td,
+.table > tfoot > tr.danger > td,
+.table > thead > tr.danger > th,
+.table > tbody > tr.danger > th,
+.table > tfoot > tr.danger > th {
+ background-color: #f2dede;
+}
+.table-hover > tbody > tr > td.danger:hover,
+.table-hover > tbody > tr > th.danger:hover,
+.table-hover > tbody > tr.danger:hover > td,
+.table-hover > tbody > tr:hover > .danger,
+.table-hover > tbody > tr.danger:hover > th {
+ background-color: #ebcccc;
+}
+.table-responsive {
+ min-height: .01%;
+ overflow-x: auto;
+}
+@media screen and (max-width: 767px) {
+ .table-responsive {
+ width: 100%;
+ margin-bottom: 15px;
+ overflow-y: hidden;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ border: 1px solid #ddd;
+ }
+ .table-responsive > .table {
+ margin-bottom: 0;
+ }
+ .table-responsive > .table > thead > tr > th,
+ .table-responsive > .table > tbody > tr > th,
+ .table-responsive > .table > tfoot > tr > th,
+ .table-responsive > .table > thead > tr > td,
+ .table-responsive > .table > tbody > tr > td,
+ .table-responsive > .table > tfoot > tr > td {
+ white-space: nowrap;
+ }
+ .table-responsive > .table-bordered {
+ border: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:first-child,
+ .table-responsive > .table-bordered > tbody > tr > th:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+ .table-responsive > .table-bordered > thead > tr > td:first-child,
+ .table-responsive > .table-bordered > tbody > tr > td:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:last-child,
+ .table-responsive > .table-bordered > tbody > tr > th:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+ .table-responsive > .table-bordered > thead > tr > td:last-child,
+ .table-responsive > .table-bordered > tbody > tr > td:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+ }
+ .table-responsive > .table-bordered > tbody > tr:last-child > th,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > th,
+ .table-responsive > .table-bordered > tbody > tr:last-child > td,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+ border-bottom: 0;
+ }
+}
+fieldset {
+ min-width: 0;
+ padding: 0;
+ margin: 0;
+ border: 0;
+}
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: 20px;
+ font-size: 21px;
+ line-height: inherit;
+ color: #333;
+ border: 0;
+ border-bottom: 1px solid #e5e5e5;
+}
+label {
+ display: inline-block;
+ max-width: 100%;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+input[type="search"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+input[type="radio"],
+input[type="checkbox"] {
+ margin: 4px 0 0;
+ margin-top: 1px \9;
+ line-height: normal;
+}
+input[type="file"] {
+ display: block;
+}
+input[type="range"] {
+ display: block;
+ width: 100%;
+}
+select[multiple],
+select[size] {
+ height: auto;
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+output {
+ display: block;
+ padding-top: 7px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555;
+}
+.form-control {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555;
+ background-color: #fff;
+ background-image: none;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+.form-control:focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
+}
+.form-control::-moz-placeholder {
+ color: #999;
+ opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+ color: #999;
+}
+.form-control::-webkit-input-placeholder {
+ color: #999;
+}
+.form-control::-ms-expand {
+ background-color: transparent;
+ border: 0;
+}
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+ background-color: #eee;
+ opacity: 1;
+}
+.form-control[disabled],
+fieldset[disabled] .form-control {
+ cursor: not-allowed;
+}
+textarea.form-control {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-appearance: none;
+}
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ input[type="date"].form-control,
+ input[type="time"].form-control,
+ input[type="datetime-local"].form-control,
+ input[type="month"].form-control {
+ line-height: 34px;
+ }
+ input[type="date"].input-sm,
+ input[type="time"].input-sm,
+ input[type="datetime-local"].input-sm,
+ input[type="month"].input-sm,
+ .input-group-sm input[type="date"],
+ .input-group-sm input[type="time"],
+ .input-group-sm input[type="datetime-local"],
+ .input-group-sm input[type="month"] {
+ line-height: 30px;
+ }
+ input[type="date"].input-lg,
+ input[type="time"].input-lg,
+ input[type="datetime-local"].input-lg,
+ input[type="month"].input-lg,
+ .input-group-lg input[type="date"],
+ .input-group-lg input[type="time"],
+ .input-group-lg input[type="datetime-local"],
+ .input-group-lg input[type="month"] {
+ line-height: 46px;
+ }
+}
+.form-group {
+ margin-bottom: 15px;
+}
+.radio,
+.checkbox {
+ position: relative;
+ display: block;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.radio label,
+.checkbox label {
+ min-height: 20px;
+ padding-left: 20px;
+ margin-bottom: 0;
+ font-weight: normal;
+ cursor: pointer;
+}
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+ position: absolute;
+ margin-top: 4px \9;
+ margin-left: -20px;
+}
+.radio + .radio,
+.checkbox + .checkbox {
+ margin-top: -5px;
+}
+.radio-inline,
+.checkbox-inline {
+ position: relative;
+ display: inline-block;
+ padding-left: 20px;
+ margin-bottom: 0;
+ font-weight: normal;
+ vertical-align: middle;
+ cursor: pointer;
+}
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+ margin-top: 0;
+ margin-left: 10px;
+}
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"].disabled,
+input[type="checkbox"].disabled,
+fieldset[disabled] input[type="radio"],
+fieldset[disabled] input[type="checkbox"] {
+ cursor: not-allowed;
+}
+.radio-inline.disabled,
+.checkbox-inline.disabled,
+fieldset[disabled] .radio-inline,
+fieldset[disabled] .checkbox-inline {
+ cursor: not-allowed;
+}
+.radio.disabled label,
+.checkbox.disabled label,
+fieldset[disabled] .radio label,
+fieldset[disabled] .checkbox label {
+ cursor: not-allowed;
+}
+.form-control-static {
+ min-height: 34px;
+ padding-top: 7px;
+ padding-bottom: 7px;
+ margin-bottom: 0;
+}
+.form-control-static.input-lg,
+.form-control-static.input-sm {
+ padding-right: 0;
+ padding-left: 0;
+}
+.input-sm {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+select.input-sm {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.input-sm,
+select[multiple].input-sm {
+ height: auto;
+}
+.form-group-sm .form-control {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.form-group-sm select.form-control {
+ height: 30px;
+ line-height: 30px;
+}
+.form-group-sm textarea.form-control,
+.form-group-sm select[multiple].form-control {
+ height: auto;
+}
+.form-group-sm .form-control-static {
+ height: 30px;
+ min-height: 32px;
+ padding: 6px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+}
+.input-lg {
+ height: 46px;
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+select.input-lg {
+ height: 46px;
+ line-height: 46px;
+}
+textarea.input-lg,
+select[multiple].input-lg {
+ height: auto;
+}
+.form-group-lg .form-control {
+ height: 46px;
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+.form-group-lg select.form-control {
+ height: 46px;
+ line-height: 46px;
+}
+.form-group-lg textarea.form-control,
+.form-group-lg select[multiple].form-control {
+ height: auto;
+}
+.form-group-lg .form-control-static {
+ height: 46px;
+ min-height: 38px;
+ padding: 11px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+}
+.has-feedback {
+ position: relative;
+}
+.has-feedback .form-control {
+ padding-right: 42.5px;
+}
+.form-control-feedback {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 2;
+ display: block;
+ width: 34px;
+ height: 34px;
+ line-height: 34px;
+ text-align: center;
+ pointer-events: none;
+}
+.input-lg + .form-control-feedback,
+.input-group-lg + .form-control-feedback,
+.form-group-lg .form-control + .form-control-feedback {
+ width: 46px;
+ height: 46px;
+ line-height: 46px;
+}
+.input-sm + .form-control-feedback,
+.input-group-sm + .form-control-feedback,
+.form-group-sm .form-control + .form-control-feedback {
+ width: 30px;
+ height: 30px;
+ line-height: 30px;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline,
+.has-success.radio label,
+.has-success.checkbox label,
+.has-success.radio-inline label,
+.has-success.checkbox-inline label {
+ color: #3c763d;
+}
+.has-success .form-control {
+ border-color: #3c763d;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-success .form-control:focus {
+ border-color: #2b542c;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168;
+}
+.has-success .input-group-addon {
+ color: #3c763d;
+ background-color: #dff0d8;
+ border-color: #3c763d;
+}
+.has-success .form-control-feedback {
+ color: #3c763d;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline,
+.has-warning.radio label,
+.has-warning.checkbox label,
+.has-warning.radio-inline label,
+.has-warning.checkbox-inline label {
+ color: #8a6d3b;
+}
+.has-warning .form-control {
+ border-color: #8a6d3b;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-warning .form-control:focus {
+ border-color: #66512c;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b;
+}
+.has-warning .input-group-addon {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+ border-color: #8a6d3b;
+}
+.has-warning .form-control-feedback {
+ color: #8a6d3b;
+}
+.has-error .help-block,
+.has-error .control-label,
+.has-error .radio,
+.has-error .checkbox,
+.has-error .radio-inline,
+.has-error .checkbox-inline,
+.has-error.radio label,
+.has-error.checkbox label,
+.has-error.radio-inline label,
+.has-error.checkbox-inline label {
+ color: #a94442;
+}
+.has-error .form-control {
+ border-color: #a94442;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+}
+.has-error .form-control:focus {
+ border-color: #843534;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483;
+}
+.has-error .input-group-addon {
+ color: #a94442;
+ background-color: #f2dede;
+ border-color: #a94442;
+}
+.has-error .form-control-feedback {
+ color: #a94442;
+}
+.has-feedback label ~ .form-control-feedback {
+ top: 25px;
+}
+.has-feedback label.sr-only ~ .form-control-feedback {
+ top: 0;
+}
+.help-block {
+ display: block;
+ margin-top: 5px;
+ margin-bottom: 10px;
+ color: #737373;
+}
+@media (min-width: 768px) {
+ .form-inline .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .form-inline .form-control-static {
+ display: inline-block;
+ }
+ .form-inline .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .form-inline .input-group .input-group-addon,
+ .form-inline .input-group .input-group-btn,
+ .form-inline .input-group .form-control {
+ width: auto;
+ }
+ .form-inline .input-group > .form-control {
+ width: 100%;
+ }
+ .form-inline .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio,
+ .form-inline .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio label,
+ .form-inline .checkbox label {
+ padding-left: 0;
+ }
+ .form-inline .radio input[type="radio"],
+ .form-inline .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .form-inline .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+ padding-top: 7px;
+ margin-top: 0;
+ margin-bottom: 0;
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+ min-height: 27px;
+}
+.form-horizontal .form-group {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .control-label {
+ padding-top: 7px;
+ margin-bottom: 0;
+ text-align: right;
+ }
+}
+.form-horizontal .has-feedback .form-control-feedback {
+ right: 15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-lg .control-label {
+ padding-top: 11px;
+ font-size: 18px;
+ }
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-sm .control-label {
+ padding-top: 6px;
+ font-size: 12px;
+ }
+}
+.btn {
+ display: inline-block;
+ padding: 6px 12px;
+ margin-bottom: 0;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 1.42857143;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: middle;
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ cursor: pointer;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ background-image: none;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus,
+.btn.focus,
+.btn:active.focus,
+.btn.active.focus {
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+.btn:hover,
+.btn:focus,
+.btn.focus {
+ color: #333;
+ text-decoration: none;
+}
+.btn:active,
+.btn.active {
+ background-image: none;
+ outline: 0;
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+ cursor: not-allowed;
+ filter: alpha(opacity=65);
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ opacity: .65;
+}
+a.btn.disabled,
+fieldset[disabled] a.btn {
+ pointer-events: none;
+}
+.btn-default {
+ color: #333;
+ background-color: #fff;
+ border-color: #ccc;
+}
+.btn-default:focus,
+.btn-default.focus {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #8c8c8c;
+}
+.btn-default:hover {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #adadad;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ color: #333;
+ background-color: #e6e6e6;
+ border-color: #adadad;
+}
+.btn-default:active:hover,
+.btn-default.active:hover,
+.open > .dropdown-toggle.btn-default:hover,
+.btn-default:active:focus,
+.btn-default.active:focus,
+.open > .dropdown-toggle.btn-default:focus,
+.btn-default:active.focus,
+.btn-default.active.focus,
+.open > .dropdown-toggle.btn-default.focus {
+ color: #333;
+ background-color: #d4d4d4;
+ border-color: #8c8c8c;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ background-image: none;
+}
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus {
+ background-color: #fff;
+ border-color: #ccc;
+}
+.btn-default .badge {
+ color: #fff;
+ background-color: #333;
+}
+.btn-primary {
+ color: #fff;
+ background-color: #337ab7;
+ border-color: #2e6da4;
+}
+.btn-primary:focus,
+.btn-primary.focus {
+ color: #fff;
+ background-color: #286090;
+ border-color: #122b40;
+}
+.btn-primary:hover {
+ color: #fff;
+ background-color: #286090;
+ border-color: #204d74;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ color: #fff;
+ background-color: #286090;
+ border-color: #204d74;
+}
+.btn-primary:active:hover,
+.btn-primary.active:hover,
+.open > .dropdown-toggle.btn-primary:hover,
+.btn-primary:active:focus,
+.btn-primary.active:focus,
+.open > .dropdown-toggle.btn-primary:focus,
+.btn-primary:active.focus,
+.btn-primary.active.focus,
+.open > .dropdown-toggle.btn-primary.focus {
+ color: #fff;
+ background-color: #204d74;
+ border-color: #122b40;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ background-image: none;
+}
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus {
+ background-color: #337ab7;
+ border-color: #2e6da4;
+}
+.btn-primary .badge {
+ color: #337ab7;
+ background-color: #fff;
+}
+.btn-success {
+ color: #fff;
+ background-color: #5cb85c;
+ border-color: #4cae4c;
+}
+.btn-success:focus,
+.btn-success.focus {
+ color: #fff;
+ background-color: #449d44;
+ border-color: #255625;
+}
+.btn-success:hover {
+ color: #fff;
+ background-color: #449d44;
+ border-color: #398439;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ color: #fff;
+ background-color: #449d44;
+ border-color: #398439;
+}
+.btn-success:active:hover,
+.btn-success.active:hover,
+.open > .dropdown-toggle.btn-success:hover,
+.btn-success:active:focus,
+.btn-success.active:focus,
+.open > .dropdown-toggle.btn-success:focus,
+.btn-success:active.focus,
+.btn-success.active.focus,
+.open > .dropdown-toggle.btn-success.focus {
+ color: #fff;
+ background-color: #398439;
+ border-color: #255625;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ background-image: none;
+}
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus {
+ background-color: #5cb85c;
+ border-color: #4cae4c;
+}
+.btn-success .badge {
+ color: #5cb85c;
+ background-color: #fff;
+}
+.btn-info {
+ color: #fff;
+ background-color: #5bc0de;
+ border-color: #46b8da;
+}
+.btn-info:focus,
+.btn-info.focus {
+ color: #fff;
+ background-color: #31b0d5;
+ border-color: #1b6d85;
+}
+.btn-info:hover {
+ color: #fff;
+ background-color: #31b0d5;
+ border-color: #269abc;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ color: #fff;
+ background-color: #31b0d5;
+ border-color: #269abc;
+}
+.btn-info:active:hover,
+.btn-info.active:hover,
+.open > .dropdown-toggle.btn-info:hover,
+.btn-info:active:focus,
+.btn-info.active:focus,
+.open > .dropdown-toggle.btn-info:focus,
+.btn-info:active.focus,
+.btn-info.active.focus,
+.open > .dropdown-toggle.btn-info.focus {
+ color: #fff;
+ background-color: #269abc;
+ border-color: #1b6d85;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ background-image: none;
+}
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus {
+ background-color: #5bc0de;
+ border-color: #46b8da;
+}
+.btn-info .badge {
+ color: #5bc0de;
+ background-color: #fff;
+}
+.btn-warning {
+ color: #fff;
+ background-color: #f0ad4e;
+ border-color: #eea236;
+}
+.btn-warning:focus,
+.btn-warning.focus {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #985f0d;
+}
+.btn-warning:hover {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #d58512;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ color: #fff;
+ background-color: #ec971f;
+ border-color: #d58512;
+}
+.btn-warning:active:hover,
+.btn-warning.active:hover,
+.open > .dropdown-toggle.btn-warning:hover,
+.btn-warning:active:focus,
+.btn-warning.active:focus,
+.open > .dropdown-toggle.btn-warning:focus,
+.btn-warning:active.focus,
+.btn-warning.active.focus,
+.open > .dropdown-toggle.btn-warning.focus {
+ color: #fff;
+ background-color: #d58512;
+ border-color: #985f0d;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ background-image: none;
+}
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus {
+ background-color: #f0ad4e;
+ border-color: #eea236;
+}
+.btn-warning .badge {
+ color: #f0ad4e;
+ background-color: #fff;
+}
+.btn-danger {
+ color: #fff;
+ background-color: #d9534f;
+ border-color: #d43f3a;
+}
+.btn-danger:focus,
+.btn-danger.focus {
+ color: #fff;
+ background-color: #c9302c;
+ border-color: #761c19;
+}
+.btn-danger:hover {
+ color: #fff;
+ background-color: #c9302c;
+ border-color: #ac2925;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ color: #fff;
+ background-color: #c9302c;
+ border-color: #ac2925;
+}
+.btn-danger:active:hover,
+.btn-danger.active:hover,
+.open > .dropdown-toggle.btn-danger:hover,
+.btn-danger:active:focus,
+.btn-danger.active:focus,
+.open > .dropdown-toggle.btn-danger:focus,
+.btn-danger:active.focus,
+.btn-danger.active.focus,
+.open > .dropdown-toggle.btn-danger.focus {
+ color: #fff;
+ background-color: #ac2925;
+ border-color: #761c19;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ background-image: none;
+}
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus {
+ background-color: #d9534f;
+ border-color: #d43f3a;
+}
+.btn-danger .badge {
+ color: #d9534f;
+ background-color: #fff;
+}
+.btn-link {
+ font-weight: normal;
+ color: #337ab7;
+ border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link.active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+ background-color: transparent;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+ border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+ color: #23527c;
+ text-decoration: underline;
+ background-color: transparent;
+}
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+ color: #777;
+ text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+ padding: 1px 5px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.btn-block {
+ display: block;
+ width: 100%;
+}
+.btn-block + .btn-block {
+ margin-top: 5px;
+}
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+ width: 100%;
+}
+.fade {
+ opacity: 0;
+ -webkit-transition: opacity .15s linear;
+ -o-transition: opacity .15s linear;
+ transition: opacity .15s linear;
+}
+.fade.in {
+ opacity: 1;
+}
+.collapse {
+ display: none;
+}
+.collapse.in {
+ display: block;
+}
+tr.collapse.in {
+ display: table-row;
+}
+tbody.collapse.in {
+ display: table-row-group;
+}
+.collapsing {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ -webkit-transition-timing-function: ease;
+ -o-transition-timing-function: ease;
+ transition-timing-function: ease;
+ -webkit-transition-duration: .35s;
+ -o-transition-duration: .35s;
+ transition-duration: .35s;
+ -webkit-transition-property: height, visibility;
+ -o-transition-property: height, visibility;
+ transition-property: height, visibility;
+}
+.caret {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-left: 2px;
+ vertical-align: middle;
+ border-top: 4px dashed;
+ border-top: 4px solid \9;
+ border-right: 4px solid transparent;
+ border-left: 4px solid transparent;
+}
+.dropup,
+.dropdown {
+ position: relative;
+}
+.dropdown-toggle:focus {
+ outline: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 160px;
+ padding: 5px 0;
+ margin: 2px 0 0;
+ font-size: 14px;
+ text-align: left;
+ list-style: none;
+ background-color: #fff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, .15);
+ border-radius: 4px;
+ -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
+}
+.dropdown-menu.pull-right {
+ right: 0;
+ left: auto;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 9px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.dropdown-menu > li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: 1.42857143;
+ color: #333;
+ white-space: nowrap;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+ color: #262626;
+ text-decoration: none;
+ background-color: #f5f5f5;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+ color: #fff;
+ text-decoration: none;
+ background-color: #337ab7;
+ outline: 0;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ color: #777;
+}
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ text-decoration: none;
+ cursor: not-allowed;
+ background-color: transparent;
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+}
+.open > .dropdown-menu {
+ display: block;
+}
+.open > a {
+ outline: 0;
+}
+.dropdown-menu-right {
+ right: 0;
+ left: auto;
+}
+.dropdown-menu-left {
+ right: auto;
+ left: 0;
+}
+.dropdown-header {
+ display: block;
+ padding: 3px 20px;
+ font-size: 12px;
+ line-height: 1.42857143;
+ color: #777;
+ white-space: nowrap;
+}
+.dropdown-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 990;
+}
+.pull-right > .dropdown-menu {
+ right: 0;
+ left: auto;
+}
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+ content: "";
+ border-top: 0;
+ border-bottom: 4px dashed;
+ border-bottom: 4px solid \9;
+}
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 2px;
+}
+@media (min-width: 768px) {
+ .navbar-right .dropdown-menu {
+ right: 0;
+ left: auto;
+ }
+ .navbar-right .dropdown-menu-left {
+ right: auto;
+ left: 0;
+ }
+}
+.btn-group,
+.btn-group-vertical {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+ position: relative;
+ float: left;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus,
+.btn-group > .btn:active,
+.btn-group-vertical > .btn:active,
+.btn-group > .btn.active,
+.btn-group-vertical > .btn.active {
+ z-index: 2;
+}
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+ margin-left: -1px;
+}
+.btn-toolbar {
+ margin-left: -5px;
+}
+.btn-toolbar .btn,
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+ float: left;
+}
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+ margin-left: 5px;
+}
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+ border-radius: 0;
+}
+.btn-group > .btn:first-child {
+ margin-left: 0;
+}
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group > .btn-group {
+ float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+.btn-group > .btn + .dropdown-toggle {
+ padding-right: 8px;
+ padding-left: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+ padding-right: 12px;
+ padding-left: 12px;
+}
+.btn-group.open .dropdown-toggle {
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn .caret {
+ margin-left: 0;
+}
+.btn-lg .caret {
+ border-width: 5px 5px 0;
+ border-bottom-width: 0;
+}
+.dropup .btn-lg .caret {
+ border-width: 0 5px 5px;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+ display: block;
+ float: none;
+ width: 100%;
+ max-width: 100%;
+}
+.btn-group-vertical > .btn-group > .btn {
+ float: none;
+}
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+ margin-top: -1px;
+ margin-left: 0;
+}
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.btn-group-justified {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+ border-collapse: separate;
+}
+.btn-group-justified > .btn,
+.btn-group-justified > .btn-group {
+ display: table-cell;
+ float: none;
+ width: 1%;
+}
+.btn-group-justified > .btn-group .btn {
+ width: 100%;
+}
+.btn-group-justified > .btn-group .dropdown-menu {
+ left: auto;
+}
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+ position: absolute;
+ clip: rect(0, 0, 0, 0);
+ pointer-events: none;
+}
+.input-group {
+ position: relative;
+ display: table;
+ border-collapse: separate;
+}
+.input-group[class*="col-"] {
+ float: none;
+ padding-right: 0;
+ padding-left: 0;
+}
+.input-group .form-control {
+ position: relative;
+ z-index: 2;
+ float: left;
+ width: 100%;
+ margin-bottom: 0;
+}
+.input-group .form-control:focus {
+ z-index: 3;
+}
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+ height: 46px;
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+select.input-group-lg > .form-control,
+select.input-group-lg > .input-group-addon,
+select.input-group-lg > .input-group-btn > .btn {
+ height: 46px;
+ line-height: 46px;
+}
+textarea.input-group-lg > .form-control,
+textarea.input-group-lg > .input-group-addon,
+textarea.input-group-lg > .input-group-btn > .btn,
+select[multiple].input-group-lg > .form-control,
+select[multiple].input-group-lg > .input-group-addon,
+select[multiple].input-group-lg > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+select.input-group-sm > .form-control,
+select.input-group-sm > .input-group-addon,
+select.input-group-sm > .input-group-btn > .btn {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.input-group-sm > .form-control,
+textarea.input-group-sm > .input-group-addon,
+textarea.input-group-sm > .input-group-btn > .btn,
+select[multiple].input-group-sm > .form-control,
+select[multiple].input-group-sm > .input-group-addon,
+select[multiple].input-group-sm > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+ display: table-cell;
+}
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.input-group-addon,
+.input-group-btn {
+ width: 1%;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+.input-group-addon {
+ padding: 6px 12px;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 1;
+ color: #555;
+ text-align: center;
+ background-color: #eee;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+}
+.input-group-addon.input-sm {
+ padding: 5px 10px;
+ font-size: 12px;
+ border-radius: 3px;
+}
+.input-group-addon.input-lg {
+ padding: 10px 16px;
+ font-size: 18px;
+ border-radius: 6px;
+}
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+ margin-top: 0;
+}
+.input-group .form-control:first-child,
+.input-group-addon:first-child,
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
+.input-group-btn:first-child > .dropdown-toggle,
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.input-group-addon:first-child {
+ border-right: 0;
+}
+.input-group .form-control:last-child,
+.input-group-addon:last-child,
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
+.input-group-btn:last-child > .dropdown-toggle,
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.input-group-addon:last-child {
+ border-left: 0;
+}
+.input-group-btn {
+ position: relative;
+ font-size: 0;
+ white-space: nowrap;
+}
+.input-group-btn > .btn {
+ position: relative;
+}
+.input-group-btn > .btn + .btn {
+ margin-left: -1px;
+}
+.input-group-btn > .btn:hover,
+.input-group-btn > .btn:focus,
+.input-group-btn > .btn:active {
+ z-index: 2;
+}
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group {
+ margin-right: -1px;
+}
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group {
+ z-index: 2;
+ margin-left: -1px;
+}
+.nav {
+ padding-left: 0;
+ margin-bottom: 0;
+ list-style: none;
+}
+.nav > li {
+ position: relative;
+ display: block;
+}
+.nav > li > a {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+}
+.nav > li > a:hover,
+.nav > li > a:focus {
+ text-decoration: none;
+ background-color: #eee;
+}
+.nav > li.disabled > a {
+ color: #777;
+}
+.nav > li.disabled > a:hover,
+.nav > li.disabled > a:focus {
+ color: #777;
+ text-decoration: none;
+ cursor: not-allowed;
+ background-color: transparent;
+}
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+ background-color: #eee;
+ border-color: #337ab7;
+}
+.nav .nav-divider {
+ height: 1px;
+ margin: 9px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.nav > li > a > img {
+ max-width: none;
+}
+.nav-tabs {
+ border-bottom: 1px solid #ddd;
+}
+.nav-tabs > li {
+ float: left;
+ margin-bottom: -1px;
+}
+.nav-tabs > li > a {
+ margin-right: 2px;
+ line-height: 1.42857143;
+ border: 1px solid transparent;
+ border-radius: 4px 4px 0 0;
+}
+.nav-tabs > li > a:hover {
+ border-color: #eee #eee #ddd;
+}
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+ color: #555;
+ cursor: default;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-bottom-color: transparent;
+}
+.nav-tabs.nav-justified {
+ width: 100%;
+ border-bottom: 0;
+}
+.nav-tabs.nav-justified > li {
+ float: none;
+}
+.nav-tabs.nav-justified > li > a {
+ margin-bottom: 5px;
+ text-align: center;
+}
+.nav-tabs.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-tabs.nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs.nav-justified > li > a {
+ margin-right: 0;
+ border-radius: 4px;
+}
+.nav-tabs.nav-justified > .active > a,
+.nav-tabs.nav-justified > .active > a:hover,
+.nav-tabs.nav-justified > .active > a:focus {
+ border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li > a {
+ border-bottom: 1px solid #ddd;
+ border-radius: 4px 4px 0 0;
+ }
+ .nav-tabs.nav-justified > .active > a,
+ .nav-tabs.nav-justified > .active > a:hover,
+ .nav-tabs.nav-justified > .active > a:focus {
+ border-bottom-color: #fff;
+ }
+}
+.nav-pills > li {
+ float: left;
+}
+.nav-pills > li > a {
+ border-radius: 4px;
+}
+.nav-pills > li + li {
+ margin-left: 2px;
+}
+.nav-pills > li.active > a,
+.nav-pills > li.active > a:hover,
+.nav-pills > li.active > a:focus {
+ color: #fff;
+ background-color: #337ab7;
+}
+.nav-stacked > li {
+ float: none;
+}
+.nav-stacked > li + li {
+ margin-top: 2px;
+ margin-left: 0;
+}
+.nav-justified {
+ width: 100%;
+}
+.nav-justified > li {
+ float: none;
+}
+.nav-justified > li > a {
+ margin-bottom: 5px;
+ text-align: center;
+}
+.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs-justified {
+ border-bottom: 0;
+}
+.nav-tabs-justified > li > a {
+ margin-right: 0;
+ border-radius: 4px;
+}
+.nav-tabs-justified > .active > a,
+.nav-tabs-justified > .active > a:hover,
+.nav-tabs-justified > .active > a:focus {
+ border: 1px solid #ddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs-justified > li > a {
+ border-bottom: 1px solid #ddd;
+ border-radius: 4px 4px 0 0;
+ }
+ .nav-tabs-justified > .active > a,
+ .nav-tabs-justified > .active > a:hover,
+ .nav-tabs-justified > .active > a:focus {
+ border-bottom-color: #fff;
+ }
+}
+.tab-content > .tab-pane {
+ display: none;
+}
+.tab-content > .active {
+ display: block;
+}
+.nav-tabs .dropdown-menu {
+ margin-top: -1px;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.navbar {
+ position: relative;
+ min-height: 50px;
+ margin-bottom: 20px;
+ border: 1px solid transparent;
+}
+@media (min-width: 768px) {
+ .navbar {
+ border-radius: 4px;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-header {
+ float: left;
+ }
+}
+.navbar-collapse {
+ padding-right: 15px;
+ padding-left: 15px;
+ overflow-x: visible;
+ -webkit-overflow-scrolling: touch;
+ border-top: 1px solid transparent;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1);
+}
+.navbar-collapse.in {
+ overflow-y: auto;
+}
+@media (min-width: 768px) {
+ .navbar-collapse {
+ width: auto;
+ border-top: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+ .navbar-collapse.collapse {
+ display: block !important;
+ height: auto !important;
+ padding-bottom: 0;
+ overflow: visible !important;
+ }
+ .navbar-collapse.in {
+ overflow-y: visible;
+ }
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-static-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+.navbar-fixed-top .navbar-collapse,
+.navbar-fixed-bottom .navbar-collapse {
+ max-height: 340px;
+}
+@media (max-device-width: 480px) and (orientation: landscape) {
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ max-height: 200px;
+ }
+}
+.container > .navbar-header,
+.container-fluid > .navbar-header,
+.container > .navbar-collapse,
+.container-fluid > .navbar-collapse {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+@media (min-width: 768px) {
+ .container > .navbar-header,
+ .container-fluid > .navbar-header,
+ .container > .navbar-collapse,
+ .container-fluid > .navbar-collapse {
+ margin-right: 0;
+ margin-left: 0;
+ }
+}
+.navbar-static-top {
+ z-index: 1000;
+ border-width: 0 0 1px;
+}
+@media (min-width: 768px) {
+ .navbar-static-top {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ position: fixed;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+}
+@media (min-width: 768px) {
+ .navbar-fixed-top,
+ .navbar-fixed-bottom {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top {
+ top: 0;
+ border-width: 0 0 1px;
+}
+.navbar-fixed-bottom {
+ bottom: 0;
+ margin-bottom: 0;
+ border-width: 1px 0 0;
+}
+.navbar-brand {
+ float: left;
+ height: 50px;
+ padding: 15px 15px;
+ font-size: 18px;
+ line-height: 20px;
+}
+.navbar-brand:hover,
+.navbar-brand:focus {
+ text-decoration: none;
+}
+.navbar-brand > img {
+ display: block;
+}
+@media (min-width: 768px) {
+ .navbar > .container .navbar-brand,
+ .navbar > .container-fluid .navbar-brand {
+ margin-left: -15px;
+ }
+}
+.navbar-toggle {
+ position: relative;
+ float: right;
+ padding: 9px 10px;
+ margin-top: 8px;
+ margin-right: 15px;
+ margin-bottom: 8px;
+ background-color: transparent;
+ background-image: none;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.navbar-toggle:focus {
+ outline: 0;
+}
+.navbar-toggle .icon-bar {
+ display: block;
+ width: 22px;
+ height: 2px;
+ border-radius: 1px;
+}
+.navbar-toggle .icon-bar + .icon-bar {
+ margin-top: 4px;
+}
+@media (min-width: 768px) {
+ .navbar-toggle {
+ display: none;
+ }
+}
+.navbar-nav {
+ margin: 7.5px -15px;
+}
+.navbar-nav > li > a {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ line-height: 20px;
+}
+@media (max-width: 767px) {
+ .navbar-nav .open .dropdown-menu {
+ position: static;
+ float: none;
+ width: auto;
+ margin-top: 0;
+ background-color: transparent;
+ border: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+ .navbar-nav .open .dropdown-menu > li > a,
+ .navbar-nav .open .dropdown-menu .dropdown-header {
+ padding: 5px 15px 5px 25px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a {
+ line-height: 20px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-nav .open .dropdown-menu > li > a:focus {
+ background-image: none;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-nav {
+ float: left;
+ margin: 0;
+ }
+ .navbar-nav > li {
+ float: left;
+ }
+ .navbar-nav > li > a {
+ padding-top: 15px;
+ padding-bottom: 15px;
+ }
+}
+.navbar-form {
+ padding: 10px 15px;
+ margin-top: 8px;
+ margin-right: -15px;
+ margin-bottom: 8px;
+ margin-left: -15px;
+ border-top: 1px solid transparent;
+ border-bottom: 1px solid transparent;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1);
+}
+@media (min-width: 768px) {
+ .navbar-form .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control-static {
+ display: inline-block;
+ }
+ .navbar-form .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .navbar-form .input-group .input-group-addon,
+ .navbar-form .input-group .input-group-btn,
+ .navbar-form .input-group .form-control {
+ width: auto;
+ }
+ .navbar-form .input-group > .form-control {
+ width: 100%;
+ }
+ .navbar-form .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio,
+ .navbar-form .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio label,
+ .navbar-form .checkbox label {
+ padding-left: 0;
+ }
+ .navbar-form .radio input[type="radio"],
+ .navbar-form .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .navbar-form .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+@media (max-width: 767px) {
+ .navbar-form .form-group {
+ margin-bottom: 5px;
+ }
+ .navbar-form .form-group:last-child {
+ margin-bottom: 0;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-form {
+ width: auto;
+ padding-top: 0;
+ padding-bottom: 0;
+ margin-right: 0;
+ margin-left: 0;
+ border: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+}
+.navbar-nav > li > .dropdown-menu {
+ margin-top: 0;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
+ margin-bottom: 0;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.navbar-btn {
+ margin-top: 8px;
+ margin-bottom: 8px;
+}
+.navbar-btn.btn-sm {
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.navbar-btn.btn-xs {
+ margin-top: 14px;
+ margin-bottom: 14px;
+}
+.navbar-text {
+ margin-top: 15px;
+ margin-bottom: 15px;
+}
+@media (min-width: 768px) {
+ .navbar-text {
+ float: left;
+ margin-right: 15px;
+ margin-left: 15px;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-left {
+ float: left !important;
+ }
+ .navbar-right {
+ float: right !important;
+ margin-right: -15px;
+ }
+ .navbar-right ~ .navbar-right {
+ margin-right: 0;
+ }
+}
+.navbar-default {
+ background-color: #f8f8f8;
+ border-color: #e7e7e7;
+}
+.navbar-default .navbar-brand {
+ color: #777;
+}
+.navbar-default .navbar-brand:hover,
+.navbar-default .navbar-brand:focus {
+ color: #5e5e5e;
+ background-color: transparent;
+}
+.navbar-default .navbar-text {
+ color: #777;
+}
+.navbar-default .navbar-nav > li > a {
+ color: #777;
+}
+.navbar-default .navbar-nav > li > a:hover,
+.navbar-default .navbar-nav > li > a:focus {
+ color: #333;
+ background-color: transparent;
+}
+.navbar-default .navbar-nav > .active > a,
+.navbar-default .navbar-nav > .active > a:hover,
+.navbar-default .navbar-nav > .active > a:focus {
+ color: #555;
+ background-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .disabled > a,
+.navbar-default .navbar-nav > .disabled > a:hover,
+.navbar-default .navbar-nav > .disabled > a:focus {
+ color: #ccc;
+ background-color: transparent;
+}
+.navbar-default .navbar-toggle {
+ border-color: #ddd;
+}
+.navbar-default .navbar-toggle:hover,
+.navbar-default .navbar-toggle:focus {
+ background-color: #ddd;
+}
+.navbar-default .navbar-toggle .icon-bar {
+ background-color: #888;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+ border-color: #e7e7e7;
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .open > a:hover,
+.navbar-default .navbar-nav > .open > a:focus {
+ color: #555;
+ background-color: #e7e7e7;
+}
+@media (max-width: 767px) {
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+ color: #777;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #333;
+ background-color: transparent;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #555;
+ background-color: #e7e7e7;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #ccc;
+ background-color: transparent;
+ }
+}
+.navbar-default .navbar-link {
+ color: #777;
+}
+.navbar-default .navbar-link:hover {
+ color: #333;
+}
+.navbar-default .btn-link {
+ color: #777;
+}
+.navbar-default .btn-link:hover,
+.navbar-default .btn-link:focus {
+ color: #333;
+}
+.navbar-default .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-default .btn-link:hover,
+.navbar-default .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-default .btn-link:focus {
+ color: #ccc;
+}
+.navbar-inverse {
+ background-color: #222;
+ border-color: #080808;
+}
+.navbar-inverse .navbar-brand {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+ color: #fff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-text {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-nav > li > a {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+ color: #fff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+ color: #fff;
+ background-color: #080808;
+}
+.navbar-inverse .navbar-nav > .disabled > a,
+.navbar-inverse .navbar-nav > .disabled > a:hover,
+.navbar-inverse .navbar-nav > .disabled > a:focus {
+ color: #444;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-toggle {
+ border-color: #333;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+ background-color: #333;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+ background-color: #fff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+ border-color: #101010;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+ color: #fff;
+ background-color: #080808;
+}
+@media (max-width: 767px) {
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
+ border-color: #080808;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
+ background-color: #080808;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+ color: #9d9d9d;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #fff;
+ background-color: transparent;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #fff;
+ background-color: #080808;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #444;
+ background-color: transparent;
+ }
+}
+.navbar-inverse .navbar-link {
+ color: #9d9d9d;
+}
+.navbar-inverse .navbar-link:hover {
+ color: #fff;
+}
+.navbar-inverse .btn-link {
+ color: #9d9d9d;
+}
+.navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link:focus {
+ color: #fff;
+}
+.navbar-inverse .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-inverse .btn-link:focus {
+ color: #444;
+}
+.breadcrumb {
+ padding: 8px 15px;
+ margin-bottom: 20px;
+ list-style: none;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+}
+.breadcrumb > li {
+ display: inline-block;
+}
+.breadcrumb > li + li:before {
+ padding: 0 5px;
+ color: #ccc;
+ content: "/\00a0";
+}
+.breadcrumb > .active {
+ color: #777;
+}
+.pagination {
+ display: inline-block;
+ padding-left: 0;
+ margin: 20px 0;
+ border-radius: 4px;
+}
+.pagination > li {
+ display: inline;
+}
+.pagination > li > a,
+.pagination > li > span {
+ position: relative;
+ float: left;
+ padding: 6px 12px;
+ margin-left: -1px;
+ line-height: 1.42857143;
+ color: #337ab7;
+ text-decoration: none;
+ background-color: #fff;
+ border: 1px solid #ddd;
+}
+.pagination > li:first-child > a,
+.pagination > li:first-child > span {
+ margin-left: 0;
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+.pagination > li:last-child > a,
+.pagination > li:last-child > span {
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+}
+.pagination > li > a:hover,
+.pagination > li > span:hover,
+.pagination > li > a:focus,
+.pagination > li > span:focus {
+ z-index: 2;
+ color: #23527c;
+ background-color: #eee;
+ border-color: #ddd;
+}
+.pagination > .active > a,
+.pagination > .active > span,
+.pagination > .active > a:hover,
+.pagination > .active > span:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span:focus {
+ z-index: 3;
+ color: #fff;
+ cursor: default;
+ background-color: #337ab7;
+ border-color: #337ab7;
+}
+.pagination > .disabled > span,
+.pagination > .disabled > span:hover,
+.pagination > .disabled > span:focus,
+.pagination > .disabled > a,
+.pagination > .disabled > a:hover,
+.pagination > .disabled > a:focus {
+ color: #777;
+ cursor: not-allowed;
+ background-color: #fff;
+ border-color: #ddd;
+}
+.pagination-lg > li > a,
+.pagination-lg > li > span {
+ padding: 10px 16px;
+ font-size: 18px;
+ line-height: 1.3333333;
+}
+.pagination-lg > li:first-child > a,
+.pagination-lg > li:first-child > span {
+ border-top-left-radius: 6px;
+ border-bottom-left-radius: 6px;
+}
+.pagination-lg > li:last-child > a,
+.pagination-lg > li:last-child > span {
+ border-top-right-radius: 6px;
+ border-bottom-right-radius: 6px;
+}
+.pagination-sm > li > a,
+.pagination-sm > li > span {
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+}
+.pagination-sm > li:first-child > a,
+.pagination-sm > li:first-child > span {
+ border-top-left-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.pagination-sm > li:last-child > a,
+.pagination-sm > li:last-child > span {
+ border-top-right-radius: 3px;
+ border-bottom-right-radius: 3px;
+}
+.pager {
+ padding-left: 0;
+ margin: 20px 0;
+ text-align: center;
+ list-style: none;
+}
+.pager li {
+ display: inline;
+}
+.pager li > a,
+.pager li > span {
+ display: inline-block;
+ padding: 5px 14px;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 15px;
+}
+.pager li > a:hover,
+.pager li > a:focus {
+ text-decoration: none;
+ background-color: #eee;
+}
+.pager .next > a,
+.pager .next > span {
+ float: right;
+}
+.pager .previous > a,
+.pager .previous > span {
+ float: left;
+}
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+ color: #777;
+ cursor: not-allowed;
+ background-color: #fff;
+}
+.label {
+ display: inline;
+ padding: .2em .6em .3em;
+ font-size: 75%;
+ font-weight: bold;
+ line-height: 1;
+ color: #fff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: .25em;
+}
+a.label:hover,
+a.label:focus {
+ color: #fff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.label:empty {
+ display: none;
+}
+.btn .label {
+ position: relative;
+ top: -1px;
+}
+.label-default {
+ background-color: #777;
+}
+.label-default[href]:hover,
+.label-default[href]:focus {
+ background-color: #5e5e5e;
+}
+.label-primary {
+ background-color: #337ab7;
+}
+.label-primary[href]:hover,
+.label-primary[href]:focus {
+ background-color: #286090;
+}
+.label-success {
+ background-color: #5cb85c;
+}
+.label-success[href]:hover,
+.label-success[href]:focus {
+ background-color: #449d44;
+}
+.label-info {
+ background-color: #5bc0de;
+}
+.label-info[href]:hover,
+.label-info[href]:focus {
+ background-color: #31b0d5;
+}
+.label-warning {
+ background-color: #f0ad4e;
+}
+.label-warning[href]:hover,
+.label-warning[href]:focus {
+ background-color: #ec971f;
+}
+.label-danger {
+ background-color: #d9534f;
+}
+.label-danger[href]:hover,
+.label-danger[href]:focus {
+ background-color: #c9302c;
+}
+.badge {
+ display: inline-block;
+ min-width: 10px;
+ padding: 3px 7px;
+ font-size: 12px;
+ font-weight: bold;
+ line-height: 1;
+ color: #fff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: middle;
+ background-color: #777;
+ border-radius: 10px;
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.btn-xs .badge,
+.btn-group-xs > .btn .badge {
+ top: 0;
+ padding: 1px 5px;
+}
+a.badge:hover,
+a.badge:focus {
+ color: #fff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+ color: #337ab7;
+ background-color: #fff;
+}
+.list-group-item > .badge {
+ float: right;
+}
+.list-group-item > .badge + .badge {
+ margin-right: 5px;
+}
+.nav-pills > li > a > .badge {
+ margin-left: 3px;
+}
+.jumbotron {
+ padding-top: 30px;
+ padding-bottom: 30px;
+ margin-bottom: 30px;
+ color: inherit;
+ background-color: #eee;
+}
+.jumbotron h1,
+.jumbotron .h1 {
+ color: inherit;
+}
+.jumbotron p {
+ margin-bottom: 15px;
+ font-size: 21px;
+ font-weight: 200;
+}
+.jumbotron > hr {
+ border-top-color: #d5d5d5;
+}
+.container .jumbotron,
+.container-fluid .jumbotron {
+ padding-right: 15px;
+ padding-left: 15px;
+ border-radius: 6px;
+}
+.jumbotron .container {
+ max-width: 100%;
+}
+@media screen and (min-width: 768px) {
+ .jumbotron {
+ padding-top: 48px;
+ padding-bottom: 48px;
+ }
+ .container .jumbotron,
+ .container-fluid .jumbotron {
+ padding-right: 60px;
+ padding-left: 60px;
+ }
+ .jumbotron h1,
+ .jumbotron .h1 {
+ font-size: 63px;
+ }
+}
+.thumbnail {
+ display: block;
+ padding: 4px;
+ margin-bottom: 20px;
+ line-height: 1.42857143;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ -webkit-transition: border .2s ease-in-out;
+ -o-transition: border .2s ease-in-out;
+ transition: border .2s ease-in-out;
+}
+.thumbnail > img,
+.thumbnail a > img {
+ margin-right: auto;
+ margin-left: auto;
+}
+a.thumbnail:hover,
+a.thumbnail:focus,
+a.thumbnail.active {
+ border-color: #337ab7;
+}
+.thumbnail .caption {
+ padding: 9px;
+ color: #333;
+}
+.alert {
+ padding: 15px;
+ margin-bottom: 20px;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.alert h4 {
+ margin-top: 0;
+ color: inherit;
+}
+.alert .alert-link {
+ font-weight: bold;
+}
+.alert > p,
+.alert > ul {
+ margin-bottom: 0;
+}
+.alert > p + p {
+ margin-top: 5px;
+}
+.alert-dismissable,
+.alert-dismissible {
+ padding-right: 35px;
+}
+.alert-dismissable .close,
+.alert-dismissible .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ color: inherit;
+}
+.alert-success {
+ color: #3c763d;
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+}
+.alert-success hr {
+ border-top-color: #c9e2b3;
+}
+.alert-success .alert-link {
+ color: #2b542c;
+}
+.alert-info {
+ color: #31708f;
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+}
+.alert-info hr {
+ border-top-color: #a6e1ec;
+}
+.alert-info .alert-link {
+ color: #245269;
+}
+.alert-warning {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+ border-color: #faebcc;
+}
+.alert-warning hr {
+ border-top-color: #f7e1b5;
+}
+.alert-warning .alert-link {
+ color: #66512c;
+}
+.alert-danger {
+ color: #a94442;
+ background-color: #f2dede;
+ border-color: #ebccd1;
+}
+.alert-danger hr {
+ border-top-color: #e4b9c0;
+}
+.alert-danger .alert-link {
+ color: #843534;
+}
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@-o-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+.progress {
+ height: 20px;
+ margin-bottom: 20px;
+ overflow: hidden;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1);
+}
+.progress-bar {
+ float: left;
+ width: 0;
+ height: 100%;
+ font-size: 12px;
+ line-height: 20px;
+ color: #fff;
+ text-align: center;
+ background-color: #337ab7;
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);
+ -webkit-transition: width .6s ease;
+ -o-transition: width .6s ease;
+ transition: width .6s ease;
+}
+.progress-striped .progress-bar,
+.progress-bar-striped {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ -webkit-background-size: 40px 40px;
+ background-size: 40px 40px;
+}
+.progress.active .progress-bar,
+.progress-bar.active {
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
+ -o-animation: progress-bar-stripes 2s linear infinite;
+ animation: progress-bar-stripes 2s linear infinite;
+}
+.progress-bar-success {
+ background-color: #5cb85c;
+}
+.progress-striped .progress-bar-success {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-info {
+ background-color: #5bc0de;
+}
+.progress-striped .progress-bar-info {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-warning {
+ background-color: #f0ad4e;
+}
+.progress-striped .progress-bar-warning {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.progress-bar-danger {
+ background-color: #d9534f;
+}
+.progress-striped .progress-bar-danger {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+.media {
+ margin-top: 15px;
+}
+.media:first-child {
+ margin-top: 0;
+}
+.media,
+.media-body {
+ overflow: hidden;
+ zoom: 1;
+}
+.media-body {
+ width: 10000px;
+}
+.media-object {
+ display: block;
+}
+.media-object.img-thumbnail {
+ max-width: none;
+}
+.media-right,
+.media > .pull-right {
+ padding-left: 10px;
+}
+.media-left,
+.media > .pull-left {
+ padding-right: 10px;
+}
+.media-left,
+.media-right,
+.media-body {
+ display: table-cell;
+ vertical-align: top;
+}
+.media-middle {
+ vertical-align: middle;
+}
+.media-bottom {
+ vertical-align: bottom;
+}
+.media-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.media-list {
+ padding-left: 0;
+ list-style: none;
+}
+.list-group {
+ padding-left: 0;
+ margin-bottom: 20px;
+}
+.list-group-item {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+ margin-bottom: -1px;
+ background-color: #fff;
+ border: 1px solid #ddd;
+}
+.list-group-item:first-child {
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+.list-group-item:last-child {
+ margin-bottom: 0;
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+a.list-group-item,
+button.list-group-item {
+ color: #555;
+}
+a.list-group-item .list-group-item-heading,
+button.list-group-item .list-group-item-heading {
+ color: #333;
+}
+a.list-group-item:hover,
+button.list-group-item:hover,
+a.list-group-item:focus,
+button.list-group-item:focus {
+ color: #555;
+ text-decoration: none;
+ background-color: #f5f5f5;
+}
+button.list-group-item {
+ width: 100%;
+ text-align: left;
+}
+.list-group-item.disabled,
+.list-group-item.disabled:hover,
+.list-group-item.disabled:focus {
+ color: #777;
+ cursor: not-allowed;
+ background-color: #eee;
+}
+.list-group-item.disabled .list-group-item-heading,
+.list-group-item.disabled:hover .list-group-item-heading,
+.list-group-item.disabled:focus .list-group-item-heading {
+ color: inherit;
+}
+.list-group-item.disabled .list-group-item-text,
+.list-group-item.disabled:hover .list-group-item-text,
+.list-group-item.disabled:focus .list-group-item-text {
+ color: #777;
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+ z-index: 2;
+ color: #fff;
+ background-color: #337ab7;
+ border-color: #337ab7;
+}
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small,
+.list-group-item.active:hover .list-group-item-heading > .small,
+.list-group-item.active:focus .list-group-item-heading > .small {
+ color: inherit;
+}
+.list-group-item.active .list-group-item-text,
+.list-group-item.active:hover .list-group-item-text,
+.list-group-item.active:focus .list-group-item-text {
+ color: #c7ddef;
+}
+.list-group-item-success {
+ color: #3c763d;
+ background-color: #dff0d8;
+}
+a.list-group-item-success,
+button.list-group-item-success {
+ color: #3c763d;
+}
+a.list-group-item-success .list-group-item-heading,
+button.list-group-item-success .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-success:hover,
+button.list-group-item-success:hover,
+a.list-group-item-success:focus,
+button.list-group-item-success:focus {
+ color: #3c763d;
+ background-color: #d0e9c6;
+}
+a.list-group-item-success.active,
+button.list-group-item-success.active,
+a.list-group-item-success.active:hover,
+button.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus,
+button.list-group-item-success.active:focus {
+ color: #fff;
+ background-color: #3c763d;
+ border-color: #3c763d;
+}
+.list-group-item-info {
+ color: #31708f;
+ background-color: #d9edf7;
+}
+a.list-group-item-info,
+button.list-group-item-info {
+ color: #31708f;
+}
+a.list-group-item-info .list-group-item-heading,
+button.list-group-item-info .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-info:hover,
+button.list-group-item-info:hover,
+a.list-group-item-info:focus,
+button.list-group-item-info:focus {
+ color: #31708f;
+ background-color: #c4e3f3;
+}
+a.list-group-item-info.active,
+button.list-group-item-info.active,
+a.list-group-item-info.active:hover,
+button.list-group-item-info.active:hover,
+a.list-group-item-info.active:focus,
+button.list-group-item-info.active:focus {
+ color: #fff;
+ background-color: #31708f;
+ border-color: #31708f;
+}
+.list-group-item-warning {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+}
+a.list-group-item-warning,
+button.list-group-item-warning {
+ color: #8a6d3b;
+}
+a.list-group-item-warning .list-group-item-heading,
+button.list-group-item-warning .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-warning:hover,
+button.list-group-item-warning:hover,
+a.list-group-item-warning:focus,
+button.list-group-item-warning:focus {
+ color: #8a6d3b;
+ background-color: #faf2cc;
+}
+a.list-group-item-warning.active,
+button.list-group-item-warning.active,
+a.list-group-item-warning.active:hover,
+button.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus,
+button.list-group-item-warning.active:focus {
+ color: #fff;
+ background-color: #8a6d3b;
+ border-color: #8a6d3b;
+}
+.list-group-item-danger {
+ color: #a94442;
+ background-color: #f2dede;
+}
+a.list-group-item-danger,
+button.list-group-item-danger {
+ color: #a94442;
+}
+a.list-group-item-danger .list-group-item-heading,
+button.list-group-item-danger .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-danger:hover,
+button.list-group-item-danger:hover,
+a.list-group-item-danger:focus,
+button.list-group-item-danger:focus {
+ color: #a94442;
+ background-color: #ebcccc;
+}
+a.list-group-item-danger.active,
+button.list-group-item-danger.active,
+a.list-group-item-danger.active:hover,
+button.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus,
+button.list-group-item-danger.active:focus {
+ color: #fff;
+ background-color: #a94442;
+ border-color: #a94442;
+}
+.list-group-item-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.list-group-item-text {
+ margin-bottom: 0;
+ line-height: 1.3;
+}
+.panel {
+ margin-bottom: 20px;
+ background-color: #fff;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, .05);
+}
+.panel-body {
+ padding: 15px;
+}
+.panel-heading {
+ padding: 10px 15px;
+ border-bottom: 1px solid transparent;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel-heading > .dropdown .dropdown-toggle {
+ color: inherit;
+}
+.panel-title {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-size: 16px;
+ color: inherit;
+}
+.panel-title > a,
+.panel-title > small,
+.panel-title > .small,
+.panel-title > small > a,
+.panel-title > .small > a {
+ color: inherit;
+}
+.panel-footer {
+ padding: 10px 15px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #ddd;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .list-group,
+.panel > .panel-collapse > .list-group {
+ margin-bottom: 0;
+}
+.panel > .list-group .list-group-item,
+.panel > .panel-collapse > .list-group .list-group-item {
+ border-width: 1px 0;
+ border-radius: 0;
+}
+.panel > .list-group:first-child .list-group-item:first-child,
+.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {
+ border-top: 0;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel > .list-group:last-child .list-group-item:last-child,
+.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {
+ border-bottom: 0;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.panel-heading + .list-group .list-group-item:first-child {
+ border-top-width: 0;
+}
+.list-group + .panel-footer {
+ border-top-width: 0;
+}
+.panel > .table,
+.panel > .table-responsive > .table,
+.panel > .panel-collapse > .table {
+ margin-bottom: 0;
+}
+.panel > .table caption,
+.panel > .table-responsive > .table caption,
+.panel > .panel-collapse > .table caption {
+ padding-right: 15px;
+ padding-left: 15px;
+}
+.panel > .table:first-child,
+.panel > .table-responsive:first-child > .table:first-child {
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
+ border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
+ border-top-right-radius: 3px;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
+ border-bottom-right-radius: 3px;
+}
+.panel > .panel-body + .table,
+.panel > .panel-body + .table-responsive,
+.panel > .table + .panel-body,
+.panel > .table-responsive + .panel-body {
+ border-top: 1px solid #ddd;
+}
+.panel > .table > tbody:first-child > tr:first-child th,
+.panel > .table > tbody:first-child > tr:first-child td {
+ border-top: 0;
+}
+.panel > .table-bordered,
+.panel > .table-responsive > .table-bordered {
+ border: 0;
+}
+.panel > .table-bordered > thead > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
+.panel > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-bordered > thead > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
+.panel > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-bordered > tfoot > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+}
+.panel > .table-bordered > thead > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
+.panel > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-bordered > thead > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
+.panel > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-bordered > tfoot > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+}
+.panel > .table-bordered > thead > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
+.panel > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-bordered > thead > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
+.panel > .table-bordered > tbody > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
+ border-bottom: 0;
+}
+.panel > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-bordered > tfoot > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
+ border-bottom: 0;
+}
+.panel > .table-responsive {
+ margin-bottom: 0;
+ border: 0;
+}
+.panel-group {
+ margin-bottom: 20px;
+}
+.panel-group .panel {
+ margin-bottom: 0;
+ border-radius: 4px;
+}
+.panel-group .panel + .panel {
+ margin-top: 5px;
+}
+.panel-group .panel-heading {
+ border-bottom: 0;
+}
+.panel-group .panel-heading + .panel-collapse > .panel-body,
+.panel-group .panel-heading + .panel-collapse > .list-group {
+ border-top: 1px solid #ddd;
+}
+.panel-group .panel-footer {
+ border-top: 0;
+}
+.panel-group .panel-footer + .panel-collapse .panel-body {
+ border-bottom: 1px solid #ddd;
+}
+.panel-default {
+ border-color: #ddd;
+}
+.panel-default > .panel-heading {
+ color: #333;
+ background-color: #f5f5f5;
+ border-color: #ddd;
+}
+.panel-default > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #ddd;
+}
+.panel-default > .panel-heading .badge {
+ color: #f5f5f5;
+ background-color: #333;
+}
+.panel-default > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #ddd;
+}
+.panel-primary {
+ border-color: #337ab7;
+}
+.panel-primary > .panel-heading {
+ color: #fff;
+ background-color: #337ab7;
+ border-color: #337ab7;
+}
+.panel-primary > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #337ab7;
+}
+.panel-primary > .panel-heading .badge {
+ color: #337ab7;
+ background-color: #fff;
+}
+.panel-primary > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #337ab7;
+}
+.panel-success {
+ border-color: #d6e9c6;
+}
+.panel-success > .panel-heading {
+ color: #3c763d;
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+}
+.panel-success > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #d6e9c6;
+}
+.panel-success > .panel-heading .badge {
+ color: #dff0d8;
+ background-color: #3c763d;
+}
+.panel-success > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #d6e9c6;
+}
+.panel-info {
+ border-color: #bce8f1;
+}
+.panel-info > .panel-heading {
+ color: #31708f;
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+}
+.panel-info > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #bce8f1;
+}
+.panel-info > .panel-heading .badge {
+ color: #d9edf7;
+ background-color: #31708f;
+}
+.panel-info > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #bce8f1;
+}
+.panel-warning {
+ border-color: #faebcc;
+}
+.panel-warning > .panel-heading {
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+ border-color: #faebcc;
+}
+.panel-warning > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #faebcc;
+}
+.panel-warning > .panel-heading .badge {
+ color: #fcf8e3;
+ background-color: #8a6d3b;
+}
+.panel-warning > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #faebcc;
+}
+.panel-danger {
+ border-color: #ebccd1;
+}
+.panel-danger > .panel-heading {
+ color: #a94442;
+ background-color: #f2dede;
+ border-color: #ebccd1;
+}
+.panel-danger > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #ebccd1;
+}
+.panel-danger > .panel-heading .badge {
+ color: #f2dede;
+ background-color: #a94442;
+}
+.panel-danger > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #ebccd1;
+}
+.embed-responsive {
+ position: relative;
+ display: block;
+ height: 0;
+ padding: 0;
+ overflow: hidden;
+}
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ border: 0;
+}
+.embed-responsive-16by9 {
+ padding-bottom: 56.25%;
+}
+.embed-responsive-4by3 {
+ padding-bottom: 75%;
+}
+.well {
+ min-height: 20px;
+ padding: 19px;
+ margin-bottom: 20px;
+ background-color: #f5f5f5;
+ border: 1px solid #e3e3e3;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05);
+}
+.well blockquote {
+ border-color: #ddd;
+ border-color: rgba(0, 0, 0, .15);
+}
+.well-lg {
+ padding: 24px;
+ border-radius: 6px;
+}
+.well-sm {
+ padding: 9px;
+ border-radius: 3px;
+}
+.close {
+ float: right;
+ font-size: 21px;
+ font-weight: bold;
+ line-height: 1;
+ color: #000;
+ text-shadow: 0 1px 0 #fff;
+ filter: alpha(opacity=20);
+ opacity: .2;
+}
+.close:hover,
+.close:focus {
+ color: #000;
+ text-decoration: none;
+ cursor: pointer;
+ filter: alpha(opacity=50);
+ opacity: .5;
+}
+button.close {
+ -webkit-appearance: none;
+ padding: 0;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+}
+.modal-open {
+ overflow: hidden;
+}
+.modal {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1050;
+ display: none;
+ overflow: hidden;
+ -webkit-overflow-scrolling: touch;
+ outline: 0;
+}
+.modal.fade .modal-dialog {
+ -webkit-transition: -webkit-transform .3s ease-out;
+ -o-transition: -o-transform .3s ease-out;
+ transition: transform .3s ease-out;
+ -webkit-transform: translate(0, -25%);
+ -ms-transform: translate(0, -25%);
+ -o-transform: translate(0, -25%);
+ transform: translate(0, -25%);
+}
+.modal.in .modal-dialog {
+ -webkit-transform: translate(0, 0);
+ -ms-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ transform: translate(0, 0);
+}
+.modal-open .modal {
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 10px;
+}
+.modal-content {
+ position: relative;
+ background-color: #fff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #999;
+ border: 1px solid rgba(0, 0, 0, .2);
+ border-radius: 6px;
+ outline: 0;
+ -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+ box-shadow: 0 3px 9px rgba(0, 0, 0, .5);
+}
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1040;
+ background-color: #000;
+}
+.modal-backdrop.fade {
+ filter: alpha(opacity=0);
+ opacity: 0;
+}
+.modal-backdrop.in {
+ filter: alpha(opacity=50);
+ opacity: .5;
+}
+.modal-header {
+ padding: 15px;
+ border-bottom: 1px solid #e5e5e5;
+}
+.modal-header .close {
+ margin-top: -2px;
+}
+.modal-title {
+ margin: 0;
+ line-height: 1.42857143;
+}
+.modal-body {
+ position: relative;
+ padding: 15px;
+}
+.modal-footer {
+ padding: 15px;
+ text-align: right;
+ border-top: 1px solid #e5e5e5;
+}
+.modal-footer .btn + .btn {
+ margin-bottom: 0;
+ margin-left: 5px;
+}
+.modal-footer .btn-group .btn + .btn {
+ margin-left: -1px;
+}
+.modal-footer .btn-block + .btn-block {
+ margin-left: 0;
+}
+.modal-scrollbar-measure {
+ position: absolute;
+ top: -9999px;
+ width: 50px;
+ height: 50px;
+ overflow: scroll;
+}
+@media (min-width: 768px) {
+ .modal-dialog {
+ width: 600px;
+ margin: 30px auto;
+ }
+ .modal-content {
+ -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+ box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
+ }
+ .modal-sm {
+ width: 300px;
+ }
+}
+@media (min-width: 992px) {
+ .modal-lg {
+ width: 900px;
+ }
+}
+.tooltip {
+ position: absolute;
+ z-index: 1070;
+ display: block;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 12px;
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1.42857143;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ letter-spacing: normal;
+ word-break: normal;
+ word-spacing: normal;
+ word-wrap: normal;
+ white-space: normal;
+ filter: alpha(opacity=0);
+ opacity: 0;
+
+ line-break: auto;
+}
+.tooltip.in {
+ filter: alpha(opacity=90);
+ opacity: .9;
+}
+.tooltip.top {
+ padding: 5px 0;
+ margin-top: -3px;
+}
+.tooltip.right {
+ padding: 0 5px;
+ margin-left: 3px;
+}
+.tooltip.bottom {
+ padding: 5px 0;
+ margin-top: 3px;
+}
+.tooltip.left {
+ padding: 0 5px;
+ margin-left: -3px;
+}
+.tooltip-inner {
+ max-width: 200px;
+ padding: 3px 8px;
+ color: #fff;
+ text-align: center;
+ background-color: #000;
+ border-radius: 4px;
+}
+.tooltip-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+.tooltip.top .tooltip-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000;
+}
+.tooltip.top-left .tooltip-arrow {
+ right: 5px;
+ bottom: 0;
+ margin-bottom: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000;
+}
+.tooltip.top-right .tooltip-arrow {
+ bottom: 0;
+ left: 5px;
+ margin-bottom: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000;
+}
+.tooltip.right .tooltip-arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ border-width: 5px 5px 5px 0;
+ border-right-color: #000;
+}
+.tooltip.left .tooltip-arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ border-width: 5px 0 5px 5px;
+ border-left-color: #000;
+}
+.tooltip.bottom .tooltip-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000;
+}
+.tooltip.bottom-left .tooltip-arrow {
+ top: 0;
+ right: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000;
+}
+.tooltip.bottom-right .tooltip-arrow {
+ top: 0;
+ left: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000;
+}
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1060;
+ display: none;
+ max-width: 276px;
+ padding: 1px;
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1.42857143;
+ text-align: left;
+ text-align: start;
+ text-decoration: none;
+ text-shadow: none;
+ text-transform: none;
+ letter-spacing: normal;
+ word-break: normal;
+ word-spacing: normal;
+ word-wrap: normal;
+ white-space: normal;
+ background-color: #fff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, .2);
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, .2);
+
+ line-break: auto;
+}
+.popover.top {
+ margin-top: -10px;
+}
+.popover.right {
+ margin-left: 10px;
+}
+.popover.bottom {
+ margin-top: 10px;
+}
+.popover.left {
+ margin-left: -10px;
+}
+.popover-title {
+ padding: 8px 14px;
+ margin: 0;
+ font-size: 14px;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ border-radius: 5px 5px 0 0;
+}
+.popover-content {
+ padding: 9px 14px;
+}
+.popover > .arrow,
+.popover > .arrow:after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+.popover > .arrow {
+ border-width: 11px;
+}
+.popover > .arrow:after {
+ content: "";
+ border-width: 10px;
+}
+.popover.top > .arrow {
+ bottom: -11px;
+ left: 50%;
+ margin-left: -11px;
+ border-top-color: #999;
+ border-top-color: rgba(0, 0, 0, .25);
+ border-bottom-width: 0;
+}
+.popover.top > .arrow:after {
+ bottom: 1px;
+ margin-left: -10px;
+ content: " ";
+ border-top-color: #fff;
+ border-bottom-width: 0;
+}
+.popover.right > .arrow {
+ top: 50%;
+ left: -11px;
+ margin-top: -11px;
+ border-right-color: #999;
+ border-right-color: rgba(0, 0, 0, .25);
+ border-left-width: 0;
+}
+.popover.right > .arrow:after {
+ bottom: -10px;
+ left: 1px;
+ content: " ";
+ border-right-color: #fff;
+ border-left-width: 0;
+}
+.popover.bottom > .arrow {
+ top: -11px;
+ left: 50%;
+ margin-left: -11px;
+ border-top-width: 0;
+ border-bottom-color: #999;
+ border-bottom-color: rgba(0, 0, 0, .25);
+}
+.popover.bottom > .arrow:after {
+ top: 1px;
+ margin-left: -10px;
+ content: " ";
+ border-top-width: 0;
+ border-bottom-color: #fff;
+}
+.popover.left > .arrow {
+ top: 50%;
+ right: -11px;
+ margin-top: -11px;
+ border-right-width: 0;
+ border-left-color: #999;
+ border-left-color: rgba(0, 0, 0, .25);
+}
+.popover.left > .arrow:after {
+ right: 1px;
+ bottom: -10px;
+ content: " ";
+ border-right-width: 0;
+ border-left-color: #fff;
+}
+.carousel {
+ position: relative;
+}
+.carousel-inner {
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+}
+.carousel-inner > .item {
+ position: relative;
+ display: none;
+ -webkit-transition: .6s ease-in-out left;
+ -o-transition: .6s ease-in-out left;
+ transition: .6s ease-in-out left;
+}
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ line-height: 1;
+}
+@media all and (transform-3d), (-webkit-transform-3d) {
+ .carousel-inner > .item {
+ -webkit-transition: -webkit-transform .6s ease-in-out;
+ -o-transition: -o-transform .6s ease-in-out;
+ transition: transform .6s ease-in-out;
+
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-perspective: 1000px;
+ perspective: 1000px;
+ }
+ .carousel-inner > .item.next,
+ .carousel-inner > .item.active.right {
+ left: 0;
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ }
+ .carousel-inner > .item.prev,
+ .carousel-inner > .item.active.left {
+ left: 0;
+ -webkit-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0);
+ }
+ .carousel-inner > .item.next.left,
+ .carousel-inner > .item.prev.right,
+ .carousel-inner > .item.active {
+ left: 0;
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ }
+}
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ display: block;
+}
+.carousel-inner > .active {
+ left: 0;
+}
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+.carousel-inner > .next {
+ left: 100%;
+}
+.carousel-inner > .prev {
+ left: -100%;
+}
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+ left: 0;
+}
+.carousel-inner > .active.left {
+ left: -100%;
+}
+.carousel-inner > .active.right {
+ left: 100%;
+}
+.carousel-control {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ width: 15%;
+ font-size: 20px;
+ color: #fff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+ background-color: rgba(0, 0, 0, 0);
+ filter: alpha(opacity=50);
+ opacity: .5;
+}
+.carousel-control.left {
+ background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+ background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+ background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001)));
+ background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+ background-repeat: repeat-x;
+}
+.carousel-control.right {
+ right: 0;
+ left: auto;
+ background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+ background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+ background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5)));
+ background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%);
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+ background-repeat: repeat-x;
+}
+.carousel-control:hover,
+.carousel-control:focus {
+ color: #fff;
+ text-decoration: none;
+ filter: alpha(opacity=90);
+ outline: 0;
+ opacity: .9;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-left,
+.carousel-control .glyphicon-chevron-right {
+ position: absolute;
+ top: 50%;
+ z-index: 5;
+ display: inline-block;
+ margin-top: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .glyphicon-chevron-left {
+ left: 50%;
+ margin-left: -10px;
+}
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-right {
+ right: 50%;
+ margin-right: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+ width: 20px;
+ height: 20px;
+ font-family: serif;
+ line-height: 1;
+}
+.carousel-control .icon-prev:before {
+ content: '\2039';
+}
+.carousel-control .icon-next:before {
+ content: '\203a';
+}
+.carousel-indicators {
+ position: absolute;
+ bottom: 10px;
+ left: 50%;
+ z-index: 15;
+ width: 60%;
+ padding-left: 0;
+ margin-left: -30%;
+ text-align: center;
+ list-style: none;
+}
+.carousel-indicators li {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ margin: 1px;
+ text-indent: -999px;
+ cursor: pointer;
+ background-color: #000 \9;
+ background-color: rgba(0, 0, 0, 0);
+ border: 1px solid #fff;
+ border-radius: 10px;
+}
+.carousel-indicators .active {
+ width: 12px;
+ height: 12px;
+ margin: 0;
+ background-color: #fff;
+}
+.carousel-caption {
+ position: absolute;
+ right: 15%;
+ bottom: 20px;
+ left: 15%;
+ z-index: 10;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ color: #fff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
+}
+.carousel-caption .btn {
+ text-shadow: none;
+}
+@media screen and (min-width: 768px) {
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-prev,
+ .carousel-control .icon-next {
+ width: 30px;
+ height: 30px;
+ margin-top: -10px;
+ font-size: 30px;
+ }
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .icon-prev {
+ margin-left: -10px;
+ }
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-next {
+ margin-right: -10px;
+ }
+ .carousel-caption {
+ right: 20%;
+ left: 20%;
+ padding-bottom: 30px;
+ }
+ .carousel-indicators {
+ bottom: 20px;
+ }
+}
+.clearfix:before,
+.clearfix:after,
+.dl-horizontal dd:before,
+.dl-horizontal dd:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after,
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after,
+.btn-toolbar:before,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:before,
+.btn-group-vertical > .btn-group:after,
+.nav:before,
+.nav:after,
+.navbar:before,
+.navbar:after,
+.navbar-header:before,
+.navbar-header:after,
+.navbar-collapse:before,
+.navbar-collapse:after,
+.pager:before,
+.pager:after,
+.panel-body:before,
+.panel-body:after,
+.modal-header:before,
+.modal-header:after,
+.modal-footer:before,
+.modal-footer:after {
+ display: table;
+ content: " ";
+}
+.clearfix:after,
+.dl-horizontal dd:after,
+.container:after,
+.container-fluid:after,
+.row:after,
+.form-horizontal .form-group:after,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:after,
+.nav:after,
+.navbar:after,
+.navbar-header:after,
+.navbar-collapse:after,
+.pager:after,
+.panel-body:after,
+.modal-header:after,
+.modal-footer:after {
+ clear: both;
+}
+.center-block {
+ display: block;
+ margin-right: auto;
+ margin-left: auto;
+}
+.pull-right {
+ float: right !important;
+}
+.pull-left {
+ float: left !important;
+}
+.hide {
+ display: none !important;
+}
+.show {
+ display: block !important;
+}
+.invisible {
+ visibility: hidden;
+}
+.text-hide {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+.hidden {
+ display: none !important;
+}
+.affix {
+ position: fixed;
+}
+@-ms-viewport {
+ width: device-width;
+}
+.visible-xs,
+.visible-sm,
+.visible-md,
+.visible-lg {
+ display: none !important;
+}
+.visible-xs-block,
+.visible-xs-inline,
+.visible-xs-inline-block,
+.visible-sm-block,
+.visible-sm-inline,
+.visible-sm-inline-block,
+.visible-md-block,
+.visible-md-inline,
+.visible-md-inline-block,
+.visible-lg-block,
+.visible-lg-inline,
+.visible-lg-inline-block {
+ display: none !important;
+}
+@media (max-width: 767px) {
+ .visible-xs {
+ display: block !important;
+ }
+ table.visible-xs {
+ display: table !important;
+ }
+ tr.visible-xs {
+ display: table-row !important;
+ }
+ th.visible-xs,
+ td.visible-xs {
+ display: table-cell !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-block {
+ display: block !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline {
+ display: inline !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm {
+ display: block !important;
+ }
+ table.visible-sm {
+ display: table !important;
+ }
+ tr.visible-sm {
+ display: table-row !important;
+ }
+ th.visible-sm,
+ td.visible-sm {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-block {
+ display: block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md {
+ display: block !important;
+ }
+ table.visible-md {
+ display: table !important;
+ }
+ tr.visible-md {
+ display: table-row !important;
+ }
+ th.visible-md,
+ td.visible-md {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-block {
+ display: block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg {
+ display: block !important;
+ }
+ table.visible-lg {
+ display: table !important;
+ }
+ tr.visible-lg {
+ display: table-row !important;
+ }
+ th.visible-lg,
+ td.visible-lg {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-block {
+ display: block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (max-width: 767px) {
+ .hidden-xs {
+ display: none !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .hidden-sm {
+ display: none !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .hidden-md {
+ display: none !important;
+ }
+}
+@media (min-width: 1200px) {
+ .hidden-lg {
+ display: none !important;
+ }
+}
+.visible-print {
+ display: none !important;
+}
+@media print {
+ .visible-print {
+ display: block !important;
+ }
+ table.visible-print {
+ display: table !important;
+ }
+ tr.visible-print {
+ display: table-row !important;
+ }
+ th.visible-print,
+ td.visible-print {
+ display: table-cell !important;
+ }
+}
+.visible-print-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-block {
+ display: block !important;
+ }
+}
+.visible-print-inline {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline {
+ display: inline !important;
+ }
+}
+.visible-print-inline-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline-block {
+ display: inline-block !important;
+ }
+}
+@media print {
+ .hidden-print {
+ display: none !important;
+ }
+}
+/*# sourceMappingURL=bootstrap.css.map */
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index 5b9c7cfff8..0adaa2a9c3 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -465,48 +465,20 @@
True
Settings.settings
-
- passwordChanger.ascx
- ASPXCodeBehind
-
-
- passwordChanger.ascx
-
create.aspx
ASPXCodeBehind
create.aspx
-
-
- PartialView.ascx
- ASPXCodeBehind
-
-
- PartialView.ascx
-
-
- PartialViewMacro.ascx
- ASPXCodeBehind
-
-
- PartialViewMacro.ascx
-
+
xslt.ascx
ASPXCodeBehind
-
- User.ascx
- ASPXCodeBehind
-
xslt.ascx
-
-
- User.ascx
-
+
UserControlProxy.aspx
ASPXCodeBehind
@@ -569,12 +541,6 @@
umbracoPage.Master
-
- ASPXCodeBehind
-
-
- editTemplate.aspx
-
editstylesheet.aspx
ASPXCodeBehind
@@ -620,6 +586,8 @@
+
+
@@ -630,18 +598,9 @@
umbraco.aspx
-
- EditUser.aspx
- ASPXCodeBehind
-
-
- EditUser.aspx
-
-
-
@@ -669,6 +628,13 @@
EmbeddedMedia.config
+
+ Designer
+
+
+ HealthChecks.config
+ Designer
+
umbracoSettings.config
Designer
@@ -721,7 +687,6 @@
-
@@ -746,7 +711,6 @@
-
@@ -758,8 +722,6 @@
-
-
@@ -788,7 +750,6 @@
-
@@ -805,19 +766,13 @@
-
-
-
-
-
-
@@ -829,12 +784,9 @@
-
-
-
@@ -843,7 +795,6 @@
-
@@ -921,16 +872,11 @@
-
-
-
-
-
@@ -941,11 +887,7 @@
UserControl
-
-
-
-
@@ -959,24 +901,19 @@
-
-
-
Form
-
-
@@ -1001,11 +938,6 @@
-
-
-
-
-
diff --git a/src/Umbraco.Web.UI/Umbraco/Images/editor/renderbody.gif b/src/Umbraco.Web.UI/Umbraco/Images/editor/renderbody.gif
deleted file mode 100644
index 1a84493fe9..0000000000
Binary files a/src/Umbraco.Web.UI/Umbraco/Images/editor/renderbody.gif and /dev/null differ
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Breadcrumb.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Breadcrumb.cshtml
old mode 100644
new mode 100755
index ff63081996..5dd44df7f9
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Breadcrumb.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Breadcrumb.cshtml
@@ -1,13 +1,13 @@
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@*
- This snippet makes a breadcrumb of parents using an unordered html list.
+ This snippet makes a breadcrumb of parents using an unordered HTML list.
How it works:
- It uses the Ancestors() method to get all parents and then generates links so the visitor can go back
- Finally it outputs the name of the current page (without a link)
*@
-@{ var selection = CurrentPage.Ancestors(); }
+@{ var selection = Model.Content.Ancestors(); }
@if (selection.Any())
{
@@ -19,6 +19,6 @@
}
@* Display the current page as the last item in the list *@
- @CurrentPage.Name
+ @Model.Content.Name
}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Gallery.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Gallery.cshtml
old mode 100644
new mode 100755
index f7c5954c5a..7ed0e01680
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Gallery.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Gallery.cshtml
@@ -1,50 +1,50 @@
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@*
- Macro to display a gallery of images from media the media section.
+ Macro to display a gallery of images from the Media section.
Works with either a 'Single Media Picker' or a 'Multiple Media Picker' macro parameter (see below).
How it works:
- Confirm the macro parameter has been passed in with a value
- - Loop through all the media Id's passed in (might be a single item, might be many)
+ - Loop through all the media Ids passed in (might be a single item, might be many)
- Display any individual images, as well as any folders of images
Macro Parameters To Create, for this macro to work:
Alias:mediaIds Name:Select folders and/or images Type: Multiple Media Picker
- Type: (note: you can use a Single Media Picker if that's more appropriate to your needs)
+ Type: (note: You can use a Single Media Picker if that's more appropriate to your needs)
*@
-@{ var mediaIds = Model.MacroParameters["mediaIds"]; }
+@{ var mediaIds = Model.MacroParameters["mediaIds"] as string; }
+
@if (mediaIds != null)
{
-
- @foreach (var mediaId in mediaIds.ToString().Split(','))
+
+ @foreach (var mediaId in mediaIds.Split(','))
{
- var media = Umbraco.Media(mediaId);
+ var media = Umbraco.TypedMedia(mediaId);
@* a single image *@
if (media.DocumentTypeAlias == "Image")
{
- @Render(media);
+ @Render(media as Image);
}
@* a folder with images under it *@
- if (media.Children("Image").Any())
+ if (media.Children().Any())
{
- foreach (var image in media.Children("Image"))
+ foreach (var image in media.Children())
{
@Render(image);
}
}
-
}
-
+
}
-@helper Render(dynamic item)
+@helper Render(Image item)
{
-
-
-
+
+
+
-
+
}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListAncestorsFromCurrentPage.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListAncestorsFromCurrentPage.cshtml
old mode 100644
new mode 100755
index b7ca9d06e4..8d4d897b89
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListAncestorsFromCurrentPage.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListAncestorsFromCurrentPage.cshtml
@@ -1,24 +1,24 @@
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@*
- This snippet makes a list of links to the of parents of the current page using an unordered html list.
+ This snippet makes a list of links to the of parents of the current page using an unordered HTML list.
How it works:
- It uses the Ancestors() method to get all parents and then generates links so the visitor can go back
- Finally it outputs the name of the current page (without a link)
*@
-@{ var selection = CurrentPage.Ancestors(); }
+@{ var selection = Model.Content.Ancestors(); }
@if (selection.Any())
{
@* For each page in the ancestors collection which have been ordered by Level (so we start with the highest top node first) *@
- @foreach (var item in selection.OrderBy("Level"))
+ @foreach (var item in selection.OrderBy(x => x.Level))
{
@item.Name »
}
@* Display the current page as the last item in the list *@
- @CurrentPage.Name
+ @Model.Content.Name
}
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesFromChangeableSource.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesFromChangeableSource.cshtml
old mode 100644
new mode 100755
index 2fa2aab07c..3af1291be4
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesFromChangeableSource.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesFromChangeableSource.cshtml
@@ -13,20 +13,19 @@
*@
@{ var startNodeId = Model.MacroParameters["startNodeId"]; }
+
@if (startNodeId != null)
{
@* Get the starting page *@
- var startNode = Umbraco.Content(startNodeId);
- var selection = startNode.Children.Where("Visible");
+ var startNode = Umbraco.TypedContent(startNodeId);
+ var selection = startNode.Children.Where(x => x.IsVisible());
if (selection.Any())
{
}
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesFromCurrentPage.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesFromCurrentPage.cshtml
old mode 100644
new mode 100755
index 9bd13f68a2..09144cff47
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesFromCurrentPage.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesFromCurrentPage.cshtml
@@ -1,6 +1,14 @@
@inherits Umbraco.Web.Macros.PartialViewMacroPage
-@{ var selection = CurrentPage.Children.Where("Visible"); }
+@*
+ This snippet makes a list of links to the of children of the current page using an unordered HTML list.
+
+ How it works:
+ - It uses the Children method to get all child pages
+ - It then generates links so the visitor can go to each page
+*@
+
+@{ var selection = Model.Content.Children.Where(x => x.IsVisible()); }
@if (selection.Any())
{
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByDate.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByDate.cshtml
old mode 100644
new mode 100755
index c8cbdf7d32..5cd74a62f9
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByDate.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByDate.cshtml
@@ -1,11 +1,22 @@
@inherits Umbraco.Web.Macros.PartialViewMacroPage
-@{ var selection = CurrentPage.Children.Where("Visible").OrderBy("CreateDate desc"); }
-@* OrderBy() takes the property to sort by and optionally order desc/asc *@
+@*
+ This snippet makes a list of links to the of children of the current page using an unordered HTML list.
-
- @foreach (var item in selection)
- {
- @item.Name
- }
-
+ How it works:
+ - It uses the Children method to get all child pages
+ - It then uses the OrderByDescending() method, which takes the property to sort. In this case the page's creation date.
+ - It then generates links so the visitor can go to each page
+*@
+
+@{ var selection = Model.Content.Children.Where(x => x.IsVisible()).OrderByDescending(x => x.CreateDate); }
+
+@if (selection.Any())
+{
+
+ @foreach (var item in selection)
+ {
+ @item.Name
+ }
+
+}
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByName.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByName.cshtml
old mode 100644
new mode 100755
index da73ff8164..643855006f
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByName.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByName.cshtml
@@ -1,11 +1,22 @@
@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
-@{ var selection = CurrentPage.Children.Where("Visible").OrderBy("Name"); }
-@* OrderBy() takes the property to sort by *@
+@*
+ This snippet makes a list of links to the of children of the current page using an unordered HTML list.
-
- @foreach (var item in selection)
- {
- @item.Name
- }
-
+ How it works:
+ - It uses the Children method to get all child pages
+ - It then uses the OrderBy() method, which takes the property to sort. In this case, the page's name.
+ - It then generates links so the visitor can go to each page
+*@
+
+@{ var selection = Model.Content.Children.Where(x => x.IsVisible()).OrderBy(x => x.Name); }
+
+@if (selection.Any())
+{
+
+ @foreach (var item in selection)
+ {
+ @item.Name
+ }
+
+}
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByProperty.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByProperty.cshtml
old mode 100644
new mode 100755
index 436faf1ef5..e2eeb08204
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByProperty.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByProperty.cshtml
@@ -15,12 +15,15 @@
@{ var propertyAlias = Model.MacroParameters["propertyAlias"]; }
@if (propertyAlias != null)
{
- var selection = CurrentPage.Children.Where("Visible").OrderBy(propertyAlias);
+ var selection = Model.Content.Children.Where(x => x.IsVisible()).OrderBy(x => x.GetPropertyValue(propertyAlias.ToString()));
-
- @foreach (var item in selection)
- {
- @item.Name
- }
-
+ @if (selection.Any())
+ {
+
+ @foreach (var item in selection)
+ {
+ @item.Name
+ }
+
+ }
}
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesWithDoctype.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesWithDoctype.cshtml
old mode 100644
new mode 100755
index 4ca6f93c71..9ac71a4fd2
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesWithDoctype.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesWithDoctype.cshtml
@@ -1,17 +1,13 @@
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@*
- This snippet shows how simple it is to fetch only children of a certain Document Type using Razor.
- Be sure to change "DocumentTypeAlias" below to match your needs, such as "TextPage" or "NewsItems".
+ This snippet shows how simple it is to fetch only children of a certain Document Type.
+
+ Be sure to change "IPublishedContent" below to match your needs, such as "TextPage" or "NewsItem".
(You can find the alias of your Document Type by editing it in the Settings section)
*@
-@{ var selection = CurrentPage.Children("DocumentTypeAlias").Where("Visible"); }
-@*
- As an example of more querying, if you have a true/false property with the alias of shouldBeFeatured:
- var selection= CurrentPage.Children("DocumentTypeAlias").Where("shouldBeFeatured == true").Where("Visible");
-*@
-
+@{ var selection = Model.Content.Children().Where(x => x.IsVisible()); }
@if (selection.Any())
{
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListDescendantsFromCurrentPage.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListDescendantsFromCurrentPage.cshtml
old mode 100644
new mode 100755
index 1e2274bcc0..e649328cfb
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListDescendantsFromCurrentPage.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListDescendantsFromCurrentPage.cshtml
@@ -2,27 +2,27 @@
@*
This snippet creates links for every single page (no matter how deep) below
- the page currently being viewed by the website visitor, displayed as nested unordered html lists.
+ the page currently being viewed by the website visitor, displayed as nested unordered HTML lists.
*@
-@{ var selection = CurrentPage.Children.Where("Visible"); }
+@{ var selection = Model.Content.Children.Where(x => x.IsVisible()); }
@* Ensure that the Current Page has children *@
@if (selection.Any())
{
@* Get the first page in the children, where the property umbracoNaviHide is not True *@
- var naviLevel = CurrentPage.FirstChild().Where("Visible").Level;
+ var naviLevel = Model.Content.FirstChild(x => x.IsVisible()).Level;
@* Add in level for a CSS hook *@
- @* For each child page where the property umbracoNaviHide is not True *@
+ @* Loop through the selection *@
@foreach (var item in selection)
{
@item.Name
@* if this child page has any children, where the property umbracoNaviHide is not True *@
- @if (item.Children.Where("Visible").Any())
+ @if (item.Children.Where(x => x.IsVisible()).Any())
{
@* Call our helper to display the children *@
@childPages(item.Children)
@@ -33,7 +33,7 @@
}
-@helper childPages(dynamic selection)
+@helper childPages(IEnumerable selection)
{
@* Ensure that we have a collection of pages *@
if (selection.Any())
@@ -43,13 +43,13 @@
@* Add in level for a CSS hook *@
- @foreach (var item in selection.Where("Visible"))
+ @foreach (var item in selection.Where(x => x.IsVisible()))
{
@item.Name
@* if the this page has any children, where the property umbracoNaviHide is not True *@
- @if (item.Children.Where("Visible").Any())
+ @if (item.Children.Where(x => x.IsVisible()).Any())
{
@* Call our helper to display the children *@
@childPages(item.Children)
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListImagesFromMediaFolder.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListImagesFromMediaFolder.cshtml
old mode 100644
new mode 100755
index 1549c1eed2..6e5d68b829
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListImagesFromMediaFolder.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListImagesFromMediaFolder.cshtml
@@ -5,7 +5,7 @@
How it works:
- Confirm the macro parameter has been passed in with a value
- - Loop through all the media Id's passed in (might be a single item, might be many)
+ - Loop through all the media Ids passed in (might be a single item, might be many)
- Display any individual images, as well as any folders of images
Macro Parameters To Create, for this macro to work:
@@ -15,9 +15,9 @@
@{ var mediaId = Model.MacroParameters["mediaId"]; }
@if (mediaId != null)
{
- @* Get all the media item associated with the id passed in *@
- var media = Umbraco.Media(mediaId);
- var selection = media.Children("Image");
+ @* Get the media item associated with the id passed in *@
+ var media = Umbraco.TypedMedia(mediaId);
+ var selection = media.Children();
if (selection.Any())
{
@@ -25,7 +25,7 @@
@foreach (var item in selection)
{
-
+
}
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/MultinodeTree-picker.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/MultinodeTree-picker.cshtml
old mode 100644
new mode 100755
index ae8e427449..379b5b0ea0
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/MultinodeTree-picker.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/MultinodeTree-picker.cshtml
@@ -1,21 +1,23 @@
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@*
- This snippet lists the items from a Multinode tree picker, using the pickers default settings.
- Content Values stored as xml.
+ This snippet lists the items from a Multinode tree picker, using the picker's default settings.
+ Content Values stored as XML.
To get it working with any site's data structure, set the selection equal to the property which has the
multinode treepicker (so: replace "PropertyWithPicker" with the alias of your property).
*@
-@{ var selection = CurrentPage.PropertyWithPicker.Split(','); }
+@{ var selection = Model.Content.GetPropertyValue>("PropertyWithPicker"); }
-
- @foreach (var id in selection)
- {
- var item = Umbraco.Content(id);
-
- @item.Name
-
- }
-
\ No newline at end of file
+@if (selection.Any())
+{
+
+ @foreach (var item in selection)
+ {
+
+ @item.Name
+
+ }
+
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Navigation.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Navigation.cshtml
old mode 100644
new mode 100755
index f2a4920a12..94870a37c4
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Navigation.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Navigation.cshtml
@@ -3,16 +3,19 @@
@*
This snippet displays a list of links of the pages immediately under the top-most page in the content tree.
This is the home page for a standard website.
- It also highlights the current active page/section in the navigation with the css class "current".
+ It also highlights the current active page/section in the navigation with the CSS class "current".
*@
-@{ var selection = CurrentPage.Site().Children.Where("Visible"); }
+@{ var selection = Model.Content.Site().Children.Where(x => x.IsVisible()); }
-
- @foreach (var item in selection)
- {
-
- @item.Name
-
- }
-
+@if (selection.Any())
+{
+
+ @foreach (var item in selection)
+ {
+
+ @item.Name
+
+ }
+
+}
diff --git a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/SiteMap.cshtml b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/SiteMap.cshtml
old mode 100644
new mode 100755
index 0aef1eb3a4..7630b26ed1
--- a/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/SiteMap.cshtml
+++ b/src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/SiteMap.cshtml
@@ -1,13 +1,13 @@
@inherits Umbraco.Web.Macros.PartialViewMacroPage
@*
- This snippet makes a list of links of all visible pages of the site, as nested unordered html lists.
+ This snippet makes a list of links of all visible pages of the site, as nested unordered HTML lists.
How it works:
- It uses a custom Razor helper called Traverse() to select and display the markup and links.
*@
-@{ var selection = CurrentPage.Site(); }
+@{ var selection = Model.Content.Site(); }
@* Render the sitemap by passing the root node to the traverse helper, below *@
@@ -15,14 +15,14 @@
-@* Helper method to travers through all descendants *@
-@helper Traverse(dynamic node)
+@* Helper method to traverse through all descendants *@
+@helper Traverse(IPublishedContent node)
{
@* Update the level to reflect how deep you want the sitemap to go *@
var maxLevelForSitemap = 4;
@* Select visible children *@
- var selection = node.Children.Where("Visible").Where("Level <= " + maxLevelForSitemap);
+ var selection = node.Children.Where(x => x.IsVisible() && x.Level <= maxLevelForSitemap);
@* If any items are returned, render a list *@
if (selection.Any())
diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml
index 4b28bb7e28..f63792e1c7 100644
--- a/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml
+++ b/src/Umbraco.Web.UI/Umbraco/config/lang/cs.xml
@@ -32,10 +32,8 @@
Odeslat k publikování
Odeslat k překladu
Seřadit
- Odeslat k publikování
Přeložit
Aktualizovat
- Výchozí hodnota
Přístup zakázán.
@@ -911,8 +909,6 @@
Vložit za polem
Vložit před polem
Rekurzivní
- Odstranit tagy odstavce
- Odstraní jakékoliv <P> na začátku a na konci textu
Standardní pole
Velká písmena
Kódování URL
@@ -1042,8 +1038,6 @@
Úvodní uzel v obsahu
Uživatelské jméno
Oprávnění uživatele
- Typ uživatele
- Typy uživatelů
Spisovatel
Váš profil
Vaše nedávná historie
diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml
index 29f51c513a..b17c073372 100644
--- a/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml
+++ b/src/Umbraco.Web.UI/Umbraco/config/lang/nb.xml
@@ -33,10 +33,8 @@
Send til publisering
Send til oversetting
Sorter
- Send til publisering
Oversett
Oppdater
- Standard verdi
Ingen tilgang.
@@ -884,8 +882,6 @@ Vennlig hilsen Umbraco roboten
Sett inn etter felt
Sett inn før felt
Rekursivt
- Fjern paragraftagger
- Fjerner eventuelle <P> rundt teksten
Standardfelter
Store bokstaver
URL koding
@@ -1008,8 +1004,6 @@ Vennlig hilsen Umbraco roboten
Startnode
Navn
Brukertillatelser
- Brukertype
- Brukertyper
Forfatter
Oversetter
Endre
diff --git a/src/Umbraco.Web.UI/Umbraco/config/lang/zh_tw.xml b/src/Umbraco.Web.UI/Umbraco/config/lang/zh_tw.xml
new file mode 100644
index 0000000000..83bf8b33a9
--- /dev/null
+++ b/src/Umbraco.Web.UI/Umbraco/config/lang/zh_tw.xml
@@ -0,0 +1,1354 @@
+
+
+
+ The Umbraco community
+ http://our.umbraco.org/documentation/Extending-Umbraco/Language-Files
+
+
+ 管理主機名稱
+ 跟蹤審計
+ 流覽節點
+ 改變文檔類型
+ 複製
+ 創建
+ 創建擴展包
+ 刪除
+ 禁用
+ 清空回收站
+ 匯出文檔類型
+ 導入文檔類型
+ 導入擴展包
+ 即時編輯模式
+ 退出
+ 移動
+ 提醒
+ 公眾存取權限
+ 發佈
+ 取消發佈
+ 重新載入節點
+ 重新發佈整站
+ 回復
+ 許可權
+ 回滾
+ 提交至發佈者
+ 發送給翻譯
+ 排序
+ 提交至發佈者
+ 翻譯
+ 更新
+ 預設值
+
+
+ 禁止訪問
+ 添加功能變數名稱
+ 移除
+ 錯誤的節點
+ 功能變數名稱錯誤
+ 功能變數名稱重複
+ 語言
+ 功能變數名稱
+ 新功能變數名稱 '%0%' 已創建
+ 功能變數名稱 '%0%' 已刪除
+ 功能變數名稱 '%0%' 已使用
+ 功能變數名稱 '%0%' 已更新
+ 編輯當前功能變數名稱
+
+ 繼承
+ 語言
+ 或從父節點繼承文化設定。
+ 也會改變目前節點設定,除非下方網域有其他項目。]]>
+ 功能變數名稱
+
+
+ 查看
+
+
+ 清除選擇
+ 選擇
+ 選擇目前資料夾
+ 做別的事情
+ 粗體
+ 取消段落縮進
+ 插入表單字段
+ 插入圖片標題
+ 編輯Html
+ 段落縮進
+ 斜體
+ 居中
+ 左對齊
+ 右對齊
+ 插入連結
+ 插入本地連結(錨點)
+ 圓點列表
+ 數字清單
+ 插入巨集
+ 插入圖片
+ 編輯關聯
+ 回到清單
+ 保存
+ 保存並發佈
+ 保存並提交審核
+ 保存清單檢視
+ 預覽
+ 因未設置範本無法預覽
+ 選擇樣式
+ 顯示樣式
+ 插入表格
+ 產生模組
+
+
+ 要更改所選節點的文檔類型,先在列表中選擇合適的文檔類型。
+ 然後設置當前文檔類型到新文檔類型的各欄位間的對應映射關係並保存。
+ 內容已被重新發佈
+ 當前屬性
+ 當前類型
+ 不能改變文檔類型,因為沒有可替代的類型。
+ 文檔類型已更改
+ 要映射的欄位
+ 映射欄位
+ 新範本
+ 新類型
+ 無
+ 內容
+ 選擇新的文檔類型
+ 選中文檔的類型已被成功更改為[new type],以下欄位被映射:
+ 至
+ 不能完成欄位映射,因為存在一個欄位映射至多欄位的問題。
+ 僅顯示可作為替代的文檔類型。
+
+
+ 已發表
+ 關於本頁
+ 別名
+ (圖片的替代文本)
+ 替代連結
+ 點擊編輯
+ 創建者
+ 創建者
+ 更新者
+ 創建時間
+ 此文件創建的日期時間
+ 文檔類型
+ 編輯
+ 過期於
+ 該項發佈之後有更改
+ 該項沒有發佈
+ 最近發佈
+ 沒有可供顯示的項目
+ 此列表中沒有可供顯示的項目
+ 媒體類型
+ 媒體連結位址
+ 會員組
+ 角色
+ 會員類型
+ 沒有選擇時間
+ 頁標題
+ 屬性
+ 該文檔不可見,因為其上級 '%0%' 未發佈。
+ 糟糕:該文檔已發佈,但是沒有更新至緩存(內部錯誤)
+ 糟糕:沒辦法連結到此網址(內部錯誤-請參見記錄)
+ 糟糕:此文件已經發表,但是網址和其他內容相衝 %0%
+ 發佈
+ 發佈狀態
+ 發佈於
+ 取消發表於
+ 清空時間
+ 排序完成
+ 拖拽項目或按一下列頭即可排序,可以按住Shift多選。
+ 統計
+ 標題(可選)
+ 其他說明文字(可選)
+ 類型
+ 取消發佈
+ 最近編輯
+ 本文件修改時間
+ 移除文件
+ 連結到文檔
+ 會員組成員
+ 非會員組成員
+ 子項目
+ 目標
+ 預計發表的時間(伺服器端)
+ 這是什麼意思? ]]>
+
+
+ 點選以便上傳
+ 拖曳檔案至此...
+ 媒體連結
+ 或按這裡選擇檔案
+ 只允許檔案類型為
+ 檔案大小上限為
+
+
+ 新增一位會員
+ 所有會員
+
+
+ 您想在哪裡創建 %0%
+ 創建在
+ 選擇類型和標題
+ "文檔類型"處變更。]]>
+ "媒體類型"處變更。]]>
+ 文檔類型沒有相關範本
+ 沒有資料夾
+ 新資料類別
+
+
+ 流覽您的網站
+ - 隱藏
+ 如果Umbraco沒有打開,您可能需要允許彈出式視窗。
+ 已經在新視窗中打開
+ 重啟
+ 訪問
+ 歡迎
+
+
+ 留下
+ 放棄變更
+ 您有未存檔的變更
+ 您確定要離開本頁? - 您有未存檔的變更
+
+
+ 完成
+ 刪除 %0% 個項目
+ 刪除 %0% 個項目
+ 刪除 %1% 個中的 %0% 個項目
+ 刪除 %1% 個中的 %0% 個項目
+ 已發佈 %0% 個項目
+ 已發佈 %0% 個項目
+ 已發佈 %1% 個中的 %0% 個項目
+ 已發佈 %1% 個中的 %0% 個項目
+ 取消發佈 %0% 個項目
+ 取消發佈 %0% 個項目
+ 取消發佈 %1 個中的 %0% 個項目
+ 取消發佈 %1 個中的 %0% 個項目
+ 移動 %0% 個項目
+ 移動 %0% 個項目
+ 移動 %1 個中的 %0% 個項目
+ 移動 %1 個中的 %0% 個項目
+ 複製 %0% 個項目
+ 複製 %0% 個項目
+ 複製 %1 個中的 %0% 個項目
+ 複製 %1 個中的 %0% 個項目
+
+
+ 錨點名稱
+ 管理主機名稱
+ 關閉窗口
+ 您確定要刪除嗎
+ 您確定要禁用嗎
+ 按一下此框確定刪除%0%項
+ 您確定嗎?
+ 您確定嗎?
+ 剪切
+ 編輯字典項
+ 編輯語言
+ 插入本地連結
+ 插入字元
+ 插入圖片標題
+ 插入圖片
+ 插入連結
+ 插入巨集
+ 插入表格
+ 最近編輯
+ 連結
+ 內部連結:
+ 本地連結請用“#”號開頭
+ 在新視窗中打開?
+ 巨集設置
+ 本巨集沒有包含您可以編輯的屬性
+ 粘貼
+ 編輯許可權
+ 正在清空回收站,請不要關閉窗口。
+ 回收站已清空
+ 從回收站刪除的項目將不可恢復
+ regexlib.com的網站服務目前出現些狀況,而我們無能為力。我們對此不便感到十分抱歉。]]>
+ 查找規則運算式來驗證輸入,如: 'email、'zip-code'、'url'。
+ 移除巨集
+ 必填項目
+ 網站已重建索引
+ 網站緩存已刷新,所有已發佈的內容更新生效。
+ 網站緩存將會刷新,所有已發佈的內容將會更新。
+ 表格列數
+ 表格行數
+ 設定預留位置代碼 以便您要在子範本中插入內容到本範本時,填入此代碼到 <asp:content /> 裡面。]]>
+ 選擇預留位置代碼 於此清單中。您只能選擇目前父範本中的代碼。]]>
+ 點擊圖片查看完整大小
+ 拾取項
+ 查看緩存項
+ 新增資料夾...
+ 與原本相關
+ 最友善的社群
+ 頁面連結
+ 打開此連結文檔至新視窗或標籤頁
+ 打開此連結文檔至全新視窗
+ 打開此連結文檔在原本視窗中
+ 媒體連結
+ 選擇媒體
+ 選擇圖示
+ 選擇項目
+ 選擇連結
+ 選擇巨集
+ 選擇內容
+ 選擇會員
+ 選擇會員群組
+ 沒有找到任何圖示
+ 本巨集沒有需要參數
+ 外部登入提供者
+ 例外細節
+ 詳細記錄
+ 內部例外
+ 連結您的
+ 取消連結您的
+ 帳戶
+ 選擇編輯器
+
+
+ %0%' 編輯不同語言版本, 您可以在左方選單「語言」中增添新的語言
+ ]]>
+ 語言名稱
+
+
+ 輸入您的使用者名稱
+ 輸入您的密碼
+ 確認您的密碼
+ 命名此 %0%...
+ 輸入一個名稱
+ 標籤...
+ 輸入一段描述...
+ 搜尋請輸入...
+ 過濾請輸入...
+ 增加標籤(每個標籤後請按輸入鍵)...
+ 輸入您的電子郵件
+
+
+ 允許放置於根節點
+ 只有勾選「允許放置於根節點」的內容種類可以放在內容樹或媒體樹的最頂端
+ 允許子項節點類型
+ 文檔種類集合
+ 創建
+ 刪除選項卡
+ 描述
+ 新建選項卡
+ 選項卡
+ 縮略圖
+ 允許清單檢視
+ 允許內容項目顯示成可以排列及搜尋的清單,子項目不會被顯示
+ 目前清單檢視
+ 作用中的清單檢視資料類別
+ 新增自訂清單檢視
+ 移除自訂清單檢視
+
+
+ 添加預設值
+ 資料庫資料類型
+ 資料類型唯一標識
+ 渲染控制項
+ 按鈕
+ 允許高級設置
+ 允許快顯功能表
+ 插入圖片預設最大
+ 關聯的樣式表
+ 顯示標籤
+ 寬和高
+
+
+ 資料已保存,但是發佈前您需要修正一些錯誤:
+ 當前成員提供程式不支援修改密碼(EnablePasswordRetrieval的值應該為true)
+ %0% 已存在
+ 發現錯誤:
+ 發現錯誤:
+ 密碼最少%0%位元,且至少包含%1%位元非字母數位記號
+ %0% 必須是整數
+ %1% 中的 %0% 欄位是必填項
+ %0% 是必填項
+ %1% 中的 %0% 格式不正確
+ %0% 格式不正確
+
+
+ 收到伺服器傳來的錯誤
+ 該檔案類型已被管理員禁用
+ 注意,儘管配置中允許CodeMirror,但是它在IE上不夠穩定,所以無法在IE運行。
+ 請為新的屬性類型填寫名稱和別名!
+ 許可權有問題,訪問指定文檔或資料夾失敗!
+ 讀取片段視圖腳本錯誤(檔案:%0%)
+ 讀取使用者控制項 %0% 錯誤
+ 讀取使用者控制項 %0% 錯誤(組件:%0%,類別:%1%)
+ 讀取巨集引擎腳本錯誤(檔案:%0%)
+ 分析XSLT檔案錯誤:%0%
+ 讀取XSLT檔案錯誤:%0%
+ 請輸入標題
+ 請選擇類型
+ 圖片尺寸大於原始尺寸不會提高圖片品質,您確定要把圖片尺寸變大嗎?
+ python腳本錯誤
+ python腳本未保存,因為包含錯誤。
+ 預設打開頁面不存在,請聯繫管理員
+ 請先選擇內容,再設置樣式。
+ 沒有可用的樣式
+ 請把游標放在您要合併的兩個儲存格中的左邊儲存格
+ 非合併儲存格不能分離。
+ XSLT源碼出錯
+ XSLT未保存,因為包含錯誤。
+ 這是此屬性所使用的資料類別設定錯誤,請檢查資料類別
+
+
+ 關於
+ 操作
+ 操作
+ 添加
+ 別名
+ 所有
+ 您確定嗎?
+ 回去
+ 邊框
+ 或
+ 取消
+ 儲存格邊距
+ 選擇
+ 關閉
+ 關閉窗口
+ 備註
+ 確認
+ 強制屬性
+ 繼續
+ 複製
+ 創建
+ 資料庫
+ 時間
+ 默認
+ 刪除
+ 已刪除
+ 正在刪除…
+ 設計
+ 規格
+ 下
+ 下載
+ 編輯
+ 已編輯
+ 元素
+ 郵箱
+ 錯誤
+ 查找文檔
+ 高
+ 幫助
+ 圖示
+ 導入
+ 內邊距
+ 插入
+ 安裝
+ 不合格
+ 對齊
+ 語言
+ 佈局
+ 載入中
+ 鎖定
+ 登入
+ 退出
+ 登出
+ 巨集
+ 必要
+ 移動
+ 更多
+ 名稱
+ 新的
+ 下一步
+ 否
+ 屬於
+ 確定
+ 打開
+ 或
+ 密碼
+ 路徑
+ 預留位置代碼
+ 請稍候…
+ 上一步
+ 屬性
+ 接收資料郵箱
+ 回收站
+ 保持狀態中
+ 重命名
+ 更新
+ 必要
+ 重試
+ 許可權
+ 搜索
+ 伺服器
+ 顯示
+ 在發送時預覽
+ 大小
+ 排序
+ 送出
+ 類型
+ 輸入內容開始搜尋…
+ 上
+ 更新
+ 更新
+ 上傳
+ 連結位址
+ 用戶
+ 用戶名
+ 值
+ 查看
+ 歡迎…
+ 寬
+ 是
+ 資料夾
+ 搜尋結果
+ 重新排列
+ 我已經完成排列
+ 預覽
+ 更改密碼
+ 到
+ 清單檢視
+ 存檔中...
+ 目前
+ 內嵌
+ 選取的
+
+
+ 黑
+ 綠
+ 黃
+ 橘
+ 藍
+ 紅
+
+
+ 增加標籤頁
+ 增加屬性
+ 增加編輯器
+ 增加範本
+ 增加子節點
+ 增加子項目
+ 編輯資料類別
+ 瀏覽區塊
+ 捷徑
+ 顯示捷徑
+ 開關清單檢視
+ 開關是否允許為根項目
+
+
+ 背景色
+ 粗體
+ 前景色
+ 字體
+ 文本
+
+
+ 頁面
+
+
+ 無法連接到資料庫。
+ 無法保存web.config檔,請手工修改。
+ 發現資料庫
+ 資料庫配置
+ 安裝 按鈕來安裝Umbraco資料庫 %0%
+ ]]>
+ 下一步繼續。]]>
+ 沒有找到資料庫!請確認檔案"web.config"中的字串"connection string"是否正確。
+ 請編輯檔案"web.config" (例如使用Visual Studio或您喜歡的編輯器),移動到檔案底部,並在名稱為"UmbracoDbDSN"的字串中設定資料庫連結資訊,並存檔。
+
+ 點選重試 按鈕當上述步驟完成。
+
+ 在此查詢更多編輯web.config的資訊。
]]>
+
+ 若需要時,請聯繫您的網路公司。如果您在本地機器或伺服器安裝的話,您也許需要聯絡系統管理者。]]>
+
+ 點選升級 按鈕來升級Umbraco資料庫 %0%
+
+ 請別擔心 - 不會刪除任何資料而且馬上就會繼續運作!
+
+ ]]>
+ 點選下一步 繼續。]]>
+ 下一步繼續設定精靈。]]>
+ 預設使用者的密碼必須更改!]]>
+ 預設使用者已經被暫停或沒有Umbraco的使用權!不需更多的操作步驟。點選下一步 繼續。]]>
+ 安裝後預設使用者的密碼已經成功修改!不需更多的操作步驟。點選下一步 繼續。]]>
+ 密碼已更改
+
+ Umbraco新增一預設使用者,名稱為('admin') ,密碼為('default') 。修改此密碼是十分重要的事情。
+
+ 這個步驟會檢查預設使用者的密碼並在需要時建議修改。
+
+ ]]>
+ 作為入門者,從視頻教程開始吧!
+ 點擊下一步 (或在Web.config中自行修改UmbracoConfigurationStatus),意味著您接受上述授權合約。
+ 安裝失敗。
+ 受影響的檔和資料夾
+ 此處查看更多資訊
+ 您需要對以下檔和資料夾授於ASP.NET用戶修改許可權
+ 您的權限設定幾近完美!
+ 您可以正常執行Umbraco沒有任何問題,只差您將沒有辦法安裝那些建議需要全部許可權的插件。]]>
+ 如何解決
+ 點擊閱讀文字版
+ 影片教學來瞭解如何設定Umbraco的資料夾權限或閱讀文字版本。]]>
+ 您的權限可能有點小問題!
+
+ 您可以正常執行Umbraco沒有任何問題,然而您將無法新增資料夾或安裝那些可以讓Umbraco發揮全力的插件。]]>
+ 您的權限設定尚未未完成!
+
+ 您需要更新權限設定才能執行Umbraco。]]>
+ 您的權限設定完美無瑕!
+ 您已經準備好執行Umbraco和安裝插件!]]>
+ 解決資料夾問題
+ 點此查看ASP.NET和創建資料夾的問題解決方案
+ 設置資料夾許可權
+
+ 我要從頭開始
+ 學習該怎麼做)
+ 您晚點仍可以選擇安裝Runway,請至開發者區域選擇安裝。
+ ]]>
+ 您剛剛安裝了一個乾淨的系統,要繼續嗎?
+ “Runway”已安裝
+
+ 這是我們的模組推薦清單,選取您想要安裝的項目,或者至 查詢完整清單 。
+ ]]>
+ 僅推薦高級用戶使用
+ 給我一個簡單的網站
+
+ "Runway"是一個提供基本檔案類別和範本的簡單網站。安裝程式會自動幫您設定Runway,
+ 但你仍可輕易編輯,擴充或移除它。它並非必要項目而且您可以在沒它的情況下完美執行Umbraco。然而,
+ Runway提供一個輕鬆簡便但基於寶貴經驗的平台讓您可以更快開始。
+ 如果您安裝Runway,您還可以選擇名為「Runway模組」的基本區塊來加強Runway頁面。
+
+
+ 內含於Runway: 首頁,準備開始頁面,模組安裝頁面。
+ 可選模組: 上方瀏覽列,網站地圖,聯絡,藝廊。
+
+ ]]>
+ “Runway”是什麼?
+ 步驟 1/5:接受授權合約
+ 步驟 2/5:資料庫配置
+ 步驟 3/5:文件許可權驗證
+ 步驟 4/5:系統安全性
+ 步驟 5/5:一切就緒,可以開始使用系統。
+ 感謝選擇我們的產品
+ 參觀您的新網站
+您剛安裝好Runway,何不瞧瞧它的模樣。]]>
+ 更多的幫忙與資訊
+從我們獲獎的社群得到幫助,瀏覽文件,或觀看免費影片來瞭解如何輕鬆架設網站,如何使用插件,和瞭解Umbraco項目名稱的快速上手指引。]]>
+ 系統 %0% 安裝完畢
+ /web.config 檔案並且更新AppSetting中的字串UmbracoConfigurationStatus 內容為 '%0%' 。]]>
+ 快速開始指引。 如果您是Umbraco的新成員 ,
+您可以在其中找到相當多的資源。]]>
+ 啟動Umbraco
+想要管理您的網站時,只需開啟Umbraco後台便可增加內容,更新範本和樣式表,或增添新功能。]]>
+ 無法連接到資料庫。
+ 系統版本 3
+ 系統版本 4
+ 觀看
+
+ 點選"下一步" 來啟動精靈。]]>
+
+
+ 語言代碼
+ 語言名稱
+
+
+ 使用者在空閒狀態下將會自動登出
+ 已更新,繼續工作。
+
+
+ 超級星期天快樂
+ 瘋狂星期一快樂
+ 熱鬧星期二快樂
+ 美妙星期三快樂
+ 悅耳星期四快樂
+ 時髦星期五快樂
+ 喵喵星期六快樂
+ 下方登入
+ 登入使用
+ 連線時間過了
+ © 2001 - %0% Umbraco.com ]]>
+ 忘記密碼?
+ 一封內有重設密碼連結的電子郵件已經寄出給您
+ 一封內有重設密碼連結的電子郵件已經寄到此信箱
+ 回到登入畫面
+ 請輸入新密碼
+ 您的密碼已經更新
+ 您點選的連結是無效或過期的
+ Umbraco:重設密碼
+ 您登入到後台的使用者名稱是:%0% 點選這裡 來重設您的密碼或將此連結複製/貼上到您的瀏覽器:
%1%
]]>
+
+
+ 儀錶板
+ 區域
+ 內容
+
+
+ 選擇上面的頁面…
+ %0% 被複製到 %1%
+ 將 %0% 複製到
+ %0% 已被移動到 %1%
+ 將 %0% 移動到
+ 作為內容的根結點,點“確定”。
+ 尚未選擇節點,請選擇一個節點點擊“確定”。
+ 類型不符不允許選擇
+ 該項不能移到其子項
+ 當前節點不能建在根節點下
+ 您在子項的許可權不夠,不允許該操作。
+ 複本和原本建立關聯
+
+
+ 為 %0% 編寫通知
+
+ 哈嘍 %0%
+
+ 這是一封自動產生的信件來通知您 %1% 工作
+ 已經在頁面 %2% 上由使用者 %3% 執行完成
+
+
+
+
更新摘要:
+
+
+
+
+
+ 祝您有美好的一天!
+ Umbraco機器人 謹上
+
]]>
+ 在 %2%,[%0%] 關於 %1% 的通告已執行。
+ 通知
+
+
+
+ 按鈕並點選該檔案。Umbraco擴展包通常有「.zip」的副檔名。
+ ]]>
+ 作者
+ 演示
+ 文檔
+ 中繼資料
+ 名稱
+ 擴展包不含任何項
+
+ 您可以點選下方「移除擴展包」來安全地移除此項目。]]>
+ 無可用更新
+ 選項
+ 說明
+ 程式庫
+ 確認卸載
+ 已卸載
+ 擴展包卸載成功
+ 卸載
+
+ 注意: 任何文檔,媒體或需要這些項目才能運作的物件將會停止運作,並可能使得系統不穩定,
+ 請小心移除。若有疑慮,請聯絡擴展包作者。]]>
+ 從程式庫下載更新
+ 更新擴展包
+ 更新說明
+ 擴展包有可用的更新,您可以從程式庫網站更新。
+ 版本
+ 版本歷史
+ 訪問擴展包網站
+ 擴展包已安裝
+ 這個擴展包無法安裝,它需要Umbraco至少是版本 %0%
+ 移除中...
+ 下載中...
+ 匯入中...
+ 安裝中...
+ 重新啟動中,請稍後...
+ 都好了,您的瀏覽器將重新整理,請稍待...
+
+
+ 帶格式粘貼(不推薦)
+ 您所粘貼的文本含有特殊字元或格式,Umbraco將清除以適應網頁。
+ 無格式粘貼
+ 粘貼並移除格式(推薦)
+
+
+ 基於角色的保護
+ 請使用Umbraco的會員群組。]]>
+ 使用基於角色的授權需要首先建立會員組。
+ 錯誤頁
+ 當用戶登錄後訪問沒有許可權的頁時顯示該頁
+ 選擇限制訪問此頁的方式
+ %0% 現在處於受保護狀態
+ %0% 的保護被取消
+ 登錄頁
+ 選擇公開的登錄入口
+ 取消保護
+ 選擇一個包含登錄表單和提示資訊的頁
+ 選擇訪問該頁的角色類型
+ 為此頁設置帳號和密碼
+ 單用戶保護
+ 如果您只希望提供一個用戶名和密碼就能訪問
+
+
+
+
+
+
+
+ 包含未發佈的子項
+ 正在發佈,請稍候…
+ %0% 中的 %1% 頁面已發佈…
+ %0% 已發佈
+ %0% 及其子項已發佈
+ 發佈 %0% 及其子項
+ 發佈按鈕來將%0% 的內容設定為公開。
+ 您可以同時發佈本頁以及其子項目若您點選下面的包含子頁 。
+ ]]>
+
+
+ 您尚未設定任何許可顏色
+
+
+ 輸入外部連結
+ 選擇內部連結
+ 標題
+ 連結
+ 新視窗
+ 輸入新標題
+ 輸入連結
+
+
+ 重設
+
+
+ 當前版本
+ 紅色 文字將不會顯示於所選版本,而綠色 表示增加部分。]]>
+ 文檔已回滾
+ 這顯示所選版本的HTML格式,如果您想要比較兩版本的差異,請使用比較檢視
+ 回滾至
+ 選擇版本
+ 查看
+
+
+ 編輯腳本
+
+
+ Concierge
+ 內容
+ Courier
+ 開發
+ 設定精靈
+ 媒體
+ 會員
+ 消息
+ 設置
+ 統計
+ 翻譯
+ 用戶
+ 說明
+ 表單
+ 統計
+
+
+ 移至
+ 說明主題為
+ 影片主題為
+ 最好的Umbraco影片教學
+
+
+ 預設範本
+ 字典鍵
+ 要導入文檔類型,請點擊“流覽”按鈕,再點擊“導入”,然後在您電腦上查找 ".udt"檔導入(下一頁中需要您再次確認)
+ 新建選項卡標題
+ 節點類型
+ 類型
+ 樣式表
+ 腳本
+ 樣式表屬性
+ 選項卡
+ 選項卡標題
+ 選項卡
+ 主控文件類型啟動
+ 該文檔類型使用
+ 作為主控文件類型. 主控文件類型的標籤只能在主控文件類型裡修改。
+ 沒有欄位設置在該標籤頁
+ 主文檔類別
+ 新增對應範本
+ 增加圖示
+
+
+ 排列順序
+ 增添時間
+ 排序完成。
+ 上下拖拽項目或按一下列頭進行排序
+ 排序中請不要關閉視窗。]]>
+
+
+ 驗證
+ 驗證錯誤一定要修正才能儲存項目
+ 失敗
+ 使用者權限不足,無法完成操作
+ 已取消
+ 操作被協力廠商外掛程式取消
+ 發佈被協力廠商外掛程式取消
+ 屬性類型已存在
+ 屬性類型已創建
+ 資料類別:%1%]]>
+ 屬性類型已刪除
+ 內容類別型已保存
+ 選項卡已創建
+ 選項卡已刪除
+ id為%0%的選項卡已刪除
+ 樣式表未保存
+ 樣式表已保存
+ 樣式表保存,無錯誤。
+ 資料類型已保存
+ 字典項已保存
+ 因為上級頁面未發佈導致發佈失敗!
+ 內容已發佈
+ 公眾可見
+ 內容已保存
+ 請發佈以使更改生效
+ 提交審核
+ 更改已提交審核
+ 媒體已保存
+ 媒體已保存
+ 會員已保存
+ 樣式表屬性已保存
+ 樣式表已保存
+ 範本已保存
+ 保存使用者出錯(請查看日誌)
+ 用戶已保存
+ 用戶類型已保存
+ 檔未保存
+ 檔無法保存,請檢查許可權。
+ 檔保存
+ 檔保存,無錯誤。
+ 語言已保存
+ 媒體類別已儲存
+ 會員類別已儲存
+ Python腳本未保存
+ Python腳本因為錯誤未能保存
+ Python已保存
+ Python腳本無錯誤
+ 範本未保存
+ 範本別名相同
+ 範本已保存
+ 範本保存,無錯誤。
+ XSLT未保存
+ XSLT有錯誤
+ XSLT無法保存,請檢查許可權。
+ XSLT已保存
+ XSLT無錯誤
+ 內容已取消發佈
+ 片段視圖已保存
+ 片段視圖保存,無錯誤。
+ 片段視圖未保存
+ 片段視圖因為錯誤未能保存
+ 腳本視圖已儲存
+ 腳本視圖已儲存,沒有任何錯誤!
+ 腳本視圖未儲存
+ 儲存檔案時發生錯誤
+ 儲存檔案時發生錯誤
+
+
+ 使用CSS語法,如:h1、.redHeader、.blueTex。
+ 編輯樣式表
+ 編輯樣式屬性
+ 編輯器中的樣式屬性名
+ 預覽
+ 樣式
+
+
+ 編輯範本
+ 插入內容區
+ 插入內容預留位置
+ 插入字典項
+ 插入巨集
+ 插入頁欄位
+ 母版
+ 範本標籤快速指南
+ 範本
+
+
+ 選擇內容類別
+ 選擇排列方式
+ 新增一行
+ 新增內容
+ 放棄內容
+ 設定已儲存
+ 此處不允許有內容
+ 此處允許有內容
+ 點選來內嵌
+ 點選來插入圖片
+ 圖片標題...
+ 在此填寫...
+ 網格排列方式
+ 排列是指網格編輯器的整體工作區域,通常您只需要一種或兩種排列方式
+ 增加網格排列方式
+ 藉由設定列寬以及增加新的區域來調整排列方式
+ 行設定
+ 行是預先水平排列的格子
+ 增加行設定
+ 藉由設定小格寬度和增添小格來調整此行
+ 列
+ 網格排列方式的列總數
+ 設定
+ 調整設定編輯器可以改變的項目
+ 樣式
+ 調整樣式編輯器可以改變的項目
+ 當JSON格式正確時設定才可以儲存
+ 允許所有編輯器
+ 允許所有行設定
+ 定為預設
+ 選擇額外
+ 選擇預設
+ 已增加
+
+
+ 組合
+ 您沒有增加任何選項卡
+ 增加新的選項卡
+ 增加另外的選項卡
+ 繼承的表格
+ 增加屬性
+ 必要標籤
+ 允許清單檢視
+ 允許內容項目顯示成可以排列及搜尋的清單,子項目不會被顯示
+ 允許的範本
+ 選擇哪些範本編輯器可以使用於此類別的內容
+ 允許為根項目
+ 允許編輯器新增此類別的內容為根項目
+ 是的 - 允許此類別內容為根項目
+ 允許子節點種類
+ 允許某些特定種類能夠成為此種類內容的子項目
+ 選擇子節點
+ 從已存在的文檔類別中繼承選項卡以及屬性。新選項卡將被新增至目前文檔種類或合併至已存在同名的選項卡中。
+ 此內容種類已經用於集合中,因此不能重複添加本身。
+ 沒有可用於集合的內容種類。
+ 可用的編輯器
+ 重複使用
+ 編輯器設定
+ 設定
+ 是,刪除
+ 已移至下層
+ 已複製至下層
+ 選擇要移動的資料夾
+ 選擇要複製的資料夾
+ 至下方樹狀結構
+ 所有文檔種類
+ 所有文檔
+ 所有媒體項目
+ 使用此文檔種類的將被永久刪除,請確認您也想要將它們刪除。
+ 使用此媒體種類的將被永久刪除,請確認您也想要將它們刪除。
+ 使用此會員種類的將被永久刪除,請確認您也想要將它們刪除。
+ 以及所有使用此種類的文件項目
+ 以及所有使用此種類的媒體項目
+ 以及所有使用此種類的會員項目
+ 使用此編輯器將會套用新設定
+ 會員可以編輯
+ 顯示於會員資料
+
+
+ 替代欄位
+ 替代文本
+ 大小寫
+ 編碼
+ 選取欄位
+ 轉換分行符號
+ 將換行符號取代成為HTML標籤 <br>
+ 自訂欄位
+ 是,僅日期
+ 格式化時間
+ HTML編碼
+ 將替換HTML中的特殊字元
+ 將在欄位值後插入
+ 將在欄位值前插入
+ 小寫
+ 無
+ 欄位後插入
+ 欄位前插入
+ 遞迴
+ 標準欄位
+ 大寫
+ URL編碼
+ 將格式化URL中的特殊字元
+ 當上面欄位值為空時使用
+ 該欄位僅在主欄位為空時使用
+ 是,含時間,分隔符號為:
+
+
+ 標記為您的任務
+ 指派給您。請按「翻譯詳情」或頁面名稱觀看包含回應的詳細檢視畫面。
+ 您也可以將此頁面下載成為XML格式檔案,請按「下載XML」按鈕。
+ 若想要關閉翻譯任務,請至細節頁面點選「結束」按鈕。
+ ]]>
+ 關閉任務
+ 翻譯詳情
+ 將翻譯任務下載為XML
+ 下載 XML
+ 下載 XML DTD
+ 欄位
+ 包含子頁
+
+ [%0%]翻譯任務:%1%
+ 沒有翻譯員,請創建翻譯員角色的用戶。
+ 您創建的任務
+ 由您創建的頁面。要瀏覽包含回應的詳細檢視畫面,
+ 點選「詳情」或頁面名稱。您可以下載此頁面成為XML格式檔案,請點選「下載XML」連結。
+ 若要關閉翻譯任務,請至詳情檢視並點選「關閉」按鈕。
+ ]]>
+ 頁面'%0%'已經發送給翻譯
+ 請選擇本內容應該被翻譯成的語言
+ 發送頁面'%0%'以便翻譯
+ 分配者
+ 任務開啟
+ 總字數
+ 翻譯到
+ 翻譯完成。
+ 您可以流覽剛翻譯的頁面,如果原始頁存在,您將得到兩者的比較。
+ 翻譯失敗,XML可能損壞了。
+ 翻譯選項
+ 翻譯員
+ 上傳翻譯的xml
+
+
+ 緩存流覽
+ 回收站
+ 創建擴展包
+ 資料類型
+ 字典
+ 已安裝的擴展包
+ 安裝皮膚
+ 安裝新手套件
+ 語言
+ 安裝本地擴展包
+ 巨集
+ 媒體類型
+ 會員
+ 會員組
+ 角色
+ 會員類型
+ 文檔類型
+ 相關類型
+ 擴展包
+ 擴展包
+ Python文件
+ 從線上程式庫安裝
+ 安裝Runway
+ Runway模組
+ Scripting文件
+ 腳本
+ 樣式表
+ 範本
+ XSLT文件
+ 統計
+
+
+ 有可用更新
+ %0%已就緒,點擊這裡下載
+ 無到伺服器的連接
+ 檢查更新失敗
+
+
+ 管理員
+ 分類欄位
+ 更改密碼
+ 更改密碼
+ 確認新密碼
+ 要改變密碼,請在框中輸入新密碼,然後按一下“更改密碼”。
+ 內容頻道
+ 描述欄位
+ 禁用用戶
+ 文檔類型
+ 編輯
+ 排除欄位
+ 語言
+ 登錄
+ 默認打開媒體項
+ 區域
+ 禁用後臺管理介面
+ 舊的密碼
+ 密碼
+ 重設密碼
+ 您的密碼已更改!
+ 重輸密碼
+ 輸入新密碼
+ 新密碼不能為空!
+ 當前密碼
+ 密碼錯誤
+ 新密碼和重輸入的密碼不一致,請重試!
+ 重輸的密碼和原密碼不一致!
+ 替換子項許可權設置
+ 您正在修改存取權限的頁面:
+ 選擇要修改許可權的頁
+ 搜索子物件
+ 預設打開內容項
+ 用戶名
+ 用戶許可權
+ 撰稿人
+ 翻譯者
+ 改變
+ 您的個人檔案
+ 您的歷程記錄
+ 連線到期於
+
+
+ 驗證
+ 以電子郵件驗證
+ 以數字驗證
+ 以網址驗證
+ ...或輸入自訂驗證
+ 必要欄位
+
+
+
+ 數值已設為推薦值:%0%
+ 在設定檔 %3% 中XPath %2% 的數值設為 %1% 。
+ 在設定檔 %3% 中XPath %2% 的預期值設為 %1% ,但卻是 %0%。
+ 在設定檔 %3% 中XPath %2% 的值為非預期值 %0%。
+
+ 自訂錯誤設定為 %0%
+ 自訂錯誤設定為 %0。建議在上線前改為 %1%。
+ 自訂錯誤成功設定為 %0%
+ 巨集錯誤設為 %0%
+ 巨集錯誤設為 %0%,如此一來,當巨集有任何錯誤時會阻止某些或全部頁面正常載入。改正會將此設定 %1%。
+ 巨集錯誤已設為 %0%
+
+ 嘗試略過IIS自訂錯誤目前設為 %0%,而且您使用的IIS版本為 %1%。
+ 嘗試略過IIS自訂錯誤目前設為 %0%,然而在您使用的IIS版本為 %2% 時,建議設定是 %1%。
+ 嘗試略過IIS自訂錯誤已成功設為 %0%。
+
+ 檔案不存在:%0%。
+ '%1%'中無法找到'%0%' 。]]>
+ 有錯誤產生,請參閱下列錯誤的紀錄:%0%。
+ 成員 - 所有XML:%0%,總共:%1%,不合格:%2%
+ 媒體 - 所有XML:%0%,總共發佈:%1%,不合格:%2%
+ 內容 - 所有XML:%0%,總共發佈:%1%,不合格:%2%
+ 憑證驗證錯誤:%0%
+ 網址探查錯誤:%0% - '%1%'
+ 您目前使用HTTPS瀏覽本站:%0%
+ 在您的web.config檔案中,appSetting的umbracoUseSSL是設為false。當您開始使用HTTPS時,應將其改為 true。
+ 在您的web.config檔案中,appSetting的umbracoUseSSL是設為 %0%,您的cookies %0% 標成安全。
+ 無法在您的web.config檔案中,更新appSetting的umbracoUseSSL設定,錯誤訊息:%0%
+
+ 開啟HTTPS
+ 在web.config檔案中,將appSetting的umbracoUseSSL設true。
+ 在您的web.config檔案中,appSetting的umbracoUseSSL已設為 true,您的cookies 將被標成安全。
+ 修正
+ 無法修正比較種類檢查為'ShouldNotEqual'。
+ 用提供的數值無法修正比較種類檢查為'ShouldEqual'。
+ 沒有提供要修正檢查的數值。
+ 偵錯編輯模式關閉。
+ 偵錯編輯模式目前已開啟。上線前建議將其關閉。
+ 偵錯編輯模式已成功關閉。
+ 詳細記錄模式已關閉。
+ 詳細記錄模式目前已開啟。上線前建議將其關閉。
+ 詳細記錄模式已成功關閉。
+ 所有資料夾已有正確權限設定。
+
+ %0%。]]>
+ %0%。如果無須寫入,不需採取行動。]]>
+ 所有檔案已有正確權限設定。
+
+ %0%。]]>
+ %0%。如果無須寫入,不需採取行動。]]>
+ X-Frame-Options 設定能控制網站是否可以被其他人IFRAMEd已找到。]]>
+ X-Frame-Options 設定能控制網站是否可以被其他人IFRAMEd沒有找到。]]>
+ 調整設定的標頭
+ 在 web.config 的 httpProtocol/customHeaders 區域增加設定來防止本站被別的網站IFRAMEd。
+ 在 web.config 的 httpProtocol/customHeaders 區域已經增加設定來防止本站被別的網站IFRAMEd。
+ 無法更新web.config檔案,錯誤:%0%
+
+ %0%。]]>
+ 在標頭中沒有找到揭露網站技術的資訊。
+ 在 Web.config 檔案中,找不到 system.net/mailsettings。
+ 在 Web.config 檔案中的 system.net/mailsettings,沒有設定 host 。
+ SMTP設定正確,而且服務正常運作。
+ SMTP伺服器 %0% : %1% 無法連接。請確認在Web.config 檔案中 system.net/mailsettings 設定正確。
+ %0%。]]>
+ %0%。]]>
+
+
+ 停止網址追蹤器
+ 啟動網址追蹤器
+ 原本網址
+ 轉址成
+ 沒有任何轉址
+ 當發佈後的頁面改名或移動時,會自動轉址至新網頁。
+ 移除
+ 您確定要移除從 %0% 到 %1% 的轉址嗎?
+ 轉址已移除。
+ 移除轉址錯誤。
+
+ 您確定要停止轉址追蹤器?
+ 轉址追蹤器已停止。
+ 停止轉址追蹤器錯誤,更多資訊請參閱您的紀錄檔。
+ 轉址追蹤器已開啟。
+ 啟動轉址追蹤器錯誤,更多資訊請參閱您的紀錄檔。
+
+
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx b/src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx
deleted file mode 100644
index 755b3d772d..0000000000
--- a/src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx
+++ /dev/null
@@ -1,31 +0,0 @@
-<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PartialView.ascx.cs" Inherits="Umbraco.Web.UI.Umbraco.Create.PartialView" %>
-<%@ Import Namespace="umbraco" %>
-<%@ Register TagPrefix="cc1" Namespace="umbraco.uicontrols" Assembly="controls" %>
-
-
-
-
- *
-
- Cannot end with '/' or '.'
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <%=Services.TextService.Localize("cancel")%>
-
-
diff --git a/src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx.cs b/src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx.cs
deleted file mode 100644
index 7991ca1bee..0000000000
--- a/src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-using System.Web.UI.WebControls;
-using Umbraco.Core;
-using Umbraco.Core.Services;
-using umbraco.presentation.create;
-
-namespace Umbraco.Web.UI.Umbraco.Create
-{
- public partial class PartialView : UI.Controls.UmbracoUserControl
- {
- protected override void OnLoad(EventArgs e)
- {
- base.OnLoad(e);
- DataBind();
-
- LoadTemplates(PartialViewTemplate);
-
- // Enable new item in folders to place items in that folder.
- if (Request["nodeType"] == "partialViewsFolder")
- FileName.Text = Request["nodeId"].EnsureEndsWith('/');
- }
-
- private void LoadTemplates(ListControl list)
- {
- var fileService = (FileService)Services.FileService;
- var snippets = fileService.GetPartialViewSnippetNames(
- //ignore these
- "Gallery",
- "ListChildPagesFromChangeableSource",
- "ListChildPagesOrderedByProperty",
- "ListImagesFromMediaFolder");
-
- foreach (var snippet in snippets)
- {
- var liText = snippet.SplitPascalCasing().ToFirstUpperInvariant();
- list.Items.Add(new ListItem(liText, snippet));
- }
- }
-
- protected void SubmitButton_Click(object sender, System.EventArgs e)
- {
- if (Page.IsValid)
- {
- //Seriously, need to overhaul create dialogs, this is rediculous:
- // http://issues.umbraco.org/issue/U4-1373
-
- var createMacroVal = 0;
-
- string returnUrl = dialogHandler_temp.Create(Request.GetItemAsString("nodeType"),
- createMacroVal, //apparently we need to pass this value to 'ParentID'... of course! :P then we'll extract it in PartialViewTasks to create it.
- PartialViewTemplate.SelectedValue + "|||" + FileName.Text);
-
- ClientTools
- .ChangeContentFrameUrl(returnUrl)
- .ChildNodeCreated()
- .CloseModalWindow();
- }
-
- }
- }
-}
diff --git a/src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx.designer.cs b/src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx.designer.cs
deleted file mode 100644
index 08ab84c128..0000000000
--- a/src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx.designer.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-namespace Umbraco.Web.UI.Umbraco.Create {
-
-
- public partial class PartialView {
-
- ///
- /// FileName control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.TextBox FileName;
-
- ///
- /// RequiredFieldValidator1 control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1;
-
- ///
- /// EndsWithValidator control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.RegularExpressionValidator EndsWithValidator;
-
- ///
- /// PartialViewTemplate control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.ListBox PartialViewTemplate;
-
- ///
- /// Textbox1 control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.TextBox Textbox1;
-
- ///
- /// sbmt control.
- ///
- ///
- /// Auto-generated field.
- /// To modify move field declaration from designer file to code-behind file.
- ///
- protected global::System.Web.UI.WebControls.Button sbmt;
- }
-}
diff --git a/src/Umbraco.Web.UI/Umbraco/js/installer.app.js b/src/Umbraco.Web.UI/Umbraco/js/installer.app.js
new file mode 100644
index 0000000000..05315493b7
--- /dev/null
+++ b/src/Umbraco.Web.UI/Umbraco/js/installer.app.js
@@ -0,0 +1,7 @@
+var app = angular.module('umbraco', [
+ 'umbraco.directives',
+ 'umbraco.install',
+ 'ngCookies',
+ 'ngMobile',
+ 'ngSanitize'
+]);
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/config/HealthChecks.Release.config b/src/Umbraco.Web.UI/config/HealthChecks.Release.config
new file mode 100644
index 0000000000..69324bf513
--- /dev/null
+++ b/src/Umbraco.Web.UI/config/HealthChecks.Release.config
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Umbraco.Web.UI/config/HealthChecks.config b/src/Umbraco.Web.UI/config/HealthChecks.config
new file mode 100644
index 0000000000..75cf3713bd
--- /dev/null
+++ b/src/Umbraco.Web.UI/config/HealthChecks.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/config/trees.Release.config b/src/Umbraco.Web.UI/config/trees.Release.config
index 5423905fdf..5842800085 100644
--- a/src/Umbraco.Web.UI/config/trees.Release.config
+++ b/src/Umbraco.Web.UI/config/trees.Release.config
@@ -22,9 +22,8 @@
-
-
-
+
+
diff --git a/src/Umbraco.Web.UI/config/trees.config b/src/Umbraco.Web.UI/config/trees.config
index b3ad5b6310..c97cf5363d 100644
--- a/src/Umbraco.Web.UI/config/trees.config
+++ b/src/Umbraco.Web.UI/config/trees.config
@@ -15,16 +15,15 @@
+
-
-
-
-
+
+
@@ -39,5 +38,5 @@
-
+
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/web.Template.Debug.config b/src/Umbraco.Web.UI/web.Template.Debug.config
index 59da1264a3..ffdeb94e26 100644
--- a/src/Umbraco.Web.UI/web.Template.Debug.config
+++ b/src/Umbraco.Web.UI/web.Template.Debug.config
@@ -27,6 +27,7 @@
+
@@ -43,6 +44,7 @@
+
@@ -109,6 +111,8 @@
+
+
@@ -320,6 +324,10 @@
+
+
+
+
@@ -402,7 +410,7 @@
-
+
diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config
index e301f60a9a..dcad8f245d 100644
--- a/src/Umbraco.Web.UI/web.Template.config
+++ b/src/Umbraco.Web.UI/web.Template.config
@@ -19,7 +19,8 @@
-
+
+
@@ -32,6 +33,7 @@
+
@@ -128,8 +130,6 @@
-
-
@@ -255,7 +255,7 @@
-
+
@@ -297,16 +297,12 @@
-
-
-
-
diff --git a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
index 4a4c6c4c35..c3c9db9ddb 100644
--- a/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/ContentTypeCacheRefresher.cs
@@ -2,6 +2,7 @@
using System.Linq;
using Umbraco.Core.Cache;
using Umbraco.Core.Models;
+using Umbraco.Core.Services;
using Umbraco.Core.Services.Changes;
using Umbraco.Web.PublishedCache;
@@ -10,11 +11,13 @@ namespace Umbraco.Web.Cache
public sealed class ContentTypeCacheRefresher : PayloadCacheRefresherBase
{
private readonly IFacadeService _facadeService;
+ private readonly IdkMap _idkMap;
- public ContentTypeCacheRefresher(CacheHelper cacheHelper, IFacadeService facadeService)
+ public ContentTypeCacheRefresher(CacheHelper cacheHelper, IFacadeService facadeService, IdkMap idkMap)
: base(cacheHelper)
{
_facadeService = facadeService;
+ _idkMap = idkMap;
}
#region Define
@@ -55,11 +58,11 @@ namespace Umbraco.Web.Cache
ClearAllIsolatedCacheByEntityType();
}
- CacheHelper.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
- CacheHelper.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
-
foreach (var id in payloads.Select(x => x.Id))
+ {
+ _idkMap.ClearCache(id);
ClearLegacyCaches(id);
+ }
if (payloads.Any(x => x.ItemType == typeof(IContentType).Name))
// don't try to be clever - refresh all
diff --git a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs
index 8dfb4713b8..a5a2a4eb60 100644
--- a/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/DataTypeCacheRefresher.cs
@@ -2,6 +2,7 @@
using Umbraco.Core.Cache;
using Umbraco.Core.Models;
using Umbraco.Core.PropertyEditors.ValueConverters;
+using Umbraco.Core.Services;
using Umbraco.Web.PropertyEditors.ValueConverters;
using Umbraco.Web.PublishedCache;
@@ -11,11 +12,13 @@ namespace Umbraco.Web.Cache
public sealed class DataTypeCacheRefresher : PayloadCacheRefresherBase
{
private readonly IFacadeService _facadeService;
+ private readonly IdkMap _idkMap;
- public DataTypeCacheRefresher(CacheHelper cacheHelper, IFacadeService facadeService)
+ public DataTypeCacheRefresher(CacheHelper cacheHelper, IFacadeService facadeService, IdkMap idkMap)
: base(cacheHelper)
{
_facadeService = facadeService;
+ _idkMap = idkMap;
}
#region Define
@@ -45,9 +48,6 @@ namespace Umbraco.Web.Cache
ClearAllIsolatedCacheByEntityType();
ClearAllIsolatedCacheByEntityType();
- CacheHelper.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
- CacheHelper.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
-
var dataTypeCache = CacheHelper.IsolatedRuntimeCache.GetCache();
//clears the prevalue cache
@@ -55,6 +55,12 @@ namespace Umbraco.Web.Cache
foreach (var payload in payloads)
dataTypeCache.Result.ClearCacheByKeySearch(CacheKeys.DataTypePreValuesCacheKey + "_" + payload.Id);
+ foreach (var payload in payloads)
+ {
+ _idkMap.ClearCache(payload.Id);
+#error also nested content see 7.7
+ }
+
// fixme - not sure I like these?
TagsValueConverter.ClearCaches();
MultipleMediaPickerPropertyConverter.ClearCaches();
diff --git a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs
index d8ed5d0ad9..8b74b78254 100644
--- a/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs
+++ b/src/Umbraco.Web/Cache/DistributedCacheExtensions.cs
@@ -37,26 +37,7 @@ namespace Umbraco.Web.Cache
#endregion
- #region UserTypeCache
-
- public static void RemoveUserTypeCache(this DistributedCache dc, int userTypeId)
- {
- dc.Remove(UserTypeCacheRefresher.UniqueId, userTypeId);
- }
-
- public static void RefreshUserTypeCache(this DistributedCache dc, int userTypeId)
- {
- dc.Refresh(UserTypeCacheRefresher.UniqueId, userTypeId);
- }
-
- public static void RefreshAllUserTypeCache(this DistributedCache dc)
- {
- dc.RefreshAll(UserTypeCacheRefresher.UniqueId);
- }
-
- #endregion
-
- #region UserCache
+ #region User cache
public static void RemoveUserCache(this DistributedCache dc, int userId)
{
@@ -75,21 +56,41 @@ namespace Umbraco.Web.Cache
#endregion
- #region UserPermissionsCache
+ #region User group cache
- public static void RemoveUserPermissionsCache(this DistributedCache dc, int userId)
+ public static void RemoveUserGroupCache(this DistributedCache dc, int userId)
{
- dc.Remove(UserPermissionsCacheRefresher.UniqueId, userId);
+ dc.Remove(UserGroupCacheRefresher.UniqueId, userId);
}
- public static void RefreshUserPermissionsCache(this DistributedCache dc, int userId)
+ public static void RefreshUserGroupCache(this DistributedCache dc, int userId)
{
- dc.Refresh(UserPermissionsCacheRefresher.UniqueId, userId);
+ dc.Refresh(UserGroupCacheRefresher.UniqueId, userId);
}
- public static void RefreshAllUserPermissionsCache(this DistributedCache dc)
+ public static void RefreshAllUserGroupCache(this DistributedCache dc)
{
- dc.RefreshAll(UserPermissionsCacheRefresher.UniqueId);
+ dc.RefreshAll(UserGroupCacheRefresher.UniqueId);
+ }
+
+ #endregion
+
+ #region User group permissions cache
+
+ public static void RemoveUserGroupPermissionsCache(this DistributedCache dc, int groupId)
+ {
+ dc.Remove(UserGroupPermissionsCacheRefresher.UniqueId, groupId);
+ }
+
+ public static void RefreshUserGroupPermissionsCache(this DistributedCache dc, int groupId)
+ {
+ //TODO: Not sure if we need this yet depends if we start caching permissions
+ //dc.Refresh(UserGroupPermissionsCacheRefresher.UniqueId, groupId);
+ }
+
+ public static void RefreshAllUserGroupPermissionsCache(this DistributedCache dc)
+ {
+ dc.RefreshAll(UserGroupPermissionsCacheRefresher.UniqueId);
}
#endregion
diff --git a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs
index 93a98bf523..1548dea0f2 100644
--- a/src/Umbraco.Web/Cache/MediaCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/MediaCacheRefresher.cs
@@ -15,11 +15,13 @@ namespace Umbraco.Web.Cache
public sealed class MediaCacheRefresher : PayloadCacheRefresherBase
{
private readonly IFacadeService _facadeService;
+ private readonly IdkMap _idkMap;
- public MediaCacheRefresher(CacheHelper cacheHelper, IFacadeService facadeService)
+ public MediaCacheRefresher(CacheHelper cacheHelper, IFacadeService facadeService, IdkMap idkMap)
: base(cacheHelper)
{
_facadeService = facadeService;
+ _idkMap = idkMap;
}
#region Define
@@ -46,11 +48,11 @@ namespace Umbraco.Web.Cache
var mediaCache = CacheHelper.IsolatedRuntimeCache.GetCache();
Current.ApplicationCache.ClearPartialViewCache();
- Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
- Current.ApplicationCache.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
foreach (var payload in payloads)
- {
+ {
+ _idkMap.ClearCache(payload.Id);
+
// note: ClearCacheByKeySearch - does StartsWith(...)
// legacy alert!
diff --git a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs
index c701ecea5d..cb6f11194e 100644
--- a/src/Umbraco.Web/Cache/MemberCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/MemberCacheRefresher.cs
@@ -2,14 +2,19 @@
using Umbraco.Core.Cache;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
+using Umbraco.Core.Services;
namespace Umbraco.Web.Cache
{
public sealed class MemberCacheRefresher : TypedCacheRefresherBase
{
- public MemberCacheRefresher(CacheHelper cacheHelper)
+ private readonly IdkMap _idkMap;
+
+ public MemberCacheRefresher(CacheHelper cacheHelper, IdkMap idkMap)
: base(cacheHelper)
- { }
+ {
+ _idkMap = idkMap;
+ }
#region Define
@@ -50,9 +55,8 @@ namespace Umbraco.Web.Cache
}
private void ClearCache(int id)
- {
- CacheHelper.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
- CacheHelper.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
+ {
+ _idkMap.ClearCache(id);
CacheHelper.ClearPartialViewCache();
CacheHelper.RuntimeCache.ClearCacheByKeySearch($"{CacheKeys.MemberLibraryCacheKey}_{id}");
diff --git a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs
index e4d1e4600a..66289b29fc 100644
--- a/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/TemplateCacheRefresher.cs
@@ -1,14 +1,19 @@
using System;
using Umbraco.Core.Cache;
using Umbraco.Core.Models;
+using Umbraco.Core.Services;
namespace Umbraco.Web.Cache
{
public sealed class TemplateCacheRefresher : CacheRefresherBase
{
- public TemplateCacheRefresher(CacheHelper cacheHelper)
+ private readonly IdkMap _idkMap;
+
+ public TemplateCacheRefresher(CacheHelper cacheHelper, IdkMap idkMap)
: base(cacheHelper)
- { }
+ {
+ _idkMap = idkMap;
+ }
#region Define
@@ -46,8 +51,7 @@ namespace Umbraco.Web.Cache
private void RemoveFromCache(int id)
{
- CacheHelper.RuntimeCache.ClearCacheByKeySearch(CacheKeys.IdToKeyCacheKey);
- CacheHelper.RuntimeCache.ClearCacheByKeySearch(CacheKeys.KeyToIdCacheKey);
+ _idkMap.ClearCache(id);
CacheHelper.RuntimeCache.ClearCacheItem($"{CacheKeys.TemplateFrontEndCacheKey}{id}");
//need to clear the runtime cache for templates
diff --git a/src/Umbraco.Web/Cache/UserCacheRefresher.cs b/src/Umbraco.Web/Cache/UserCacheRefresher.cs
index a6d50231f4..a3d21bd1de 100644
--- a/src/Umbraco.Web/Cache/UserCacheRefresher.cs
+++ b/src/Umbraco.Web/Cache/UserCacheRefresher.cs
@@ -28,9 +28,6 @@ namespace Umbraco.Web.Cache
public override void RefreshAll()
{
ClearAllIsolatedCacheByEntityType();
- var userPermissionsCache = CacheHelper.IsolatedRuntimeCache.GetCache();
- if (userPermissionsCache)
- userPermissionsCache.Result.ClearCacheByKeySearch(CacheKeys.UserPermissionsCacheKey);
base.RefreshAll();
}
@@ -45,14 +42,9 @@ namespace Umbraco.Web.Cache
var userCache = CacheHelper.IsolatedRuntimeCache.GetCache();
if (userCache)
userCache.Result.ClearCacheItem(RepositoryBase.GetCacheIdKey(id));
-
- var userPermissionsCache = CacheHelper.IsolatedRuntimeCache.GetCache();
- if (userPermissionsCache)
- userPermissionsCache.Result.ClearCacheByKeySearch($"{CacheKeys.UserPermissionsCacheKey}{id}");
-
+
base.Remove(id);
}
-
#endregion
}
}
diff --git a/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs b/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs
new file mode 100644
index 0000000000..682ebf41d5
--- /dev/null
+++ b/src/Umbraco.Web/Cache/UserGroupCacheRefresher.cs
@@ -0,0 +1,72 @@
+using System;
+using Umbraco.Core.Cache;
+using Umbraco.Core.Models.Membership;
+using Umbraco.Core.Persistence.Repositories;
+
+namespace Umbraco.Web.Cache
+{
+ ///
+ /// Handles User group cache invalidation/refreshing
+ ///
+ ///
+ /// This also needs to clear the user cache since IReadOnlyUserGroup's are attached to IUser objects
+ ///
+ public sealed class UserGroupCacheRefresher : CacheRefresherBase
+ {
+ public UserGroupCacheRefresher(CacheHelper cacheHelper)
+ : base(cacheHelper)
+ { }
+
+ #region Define
+
+ protected override UserGroupCacheRefresher This => this;
+
+ public static readonly Guid UniqueId = Guid.Parse("45178038-B232-4FE8-AA1A-F2B949C44762");
+
+ public override Guid RefresherUniqueId => UniqueId;
+
+ public override string Name => "User Group Cache Refresher";
+
+ #endregion
+
+ #region Refresher
+
+ public override void RefreshAll()
+ {
+ ClearAllIsolatedCacheByEntityType();
+ var userGroupCache = CacheHelper.IsolatedRuntimeCache.GetCache();
+ if (userGroupCache)
+ {
+ userGroupCache.Result.ClearCacheByKeySearch(UserGroupRepository.GetByAliasCacheKeyPrefix);
+ }
+
+ //We'll need to clear all user cache too
+ ClearAllIsolatedCacheByEntityType();
+
+ base.RefreshAll();
+ }
+
+ public override void Refresh(int id)
+ {
+ Remove(id);
+ base.Refresh(id);
+ }
+
+ public override void Remove(int id)
+ {
+ var userGroupCache = CacheHelper.IsolatedRuntimeCache.GetCache();
+ if (userGroupCache)
+ {
+ userGroupCache.Result.ClearCacheItem(RepositoryBase.GetCacheIdKey(id));
+ userGroupCache.Result.ClearCacheByKeySearch(UserGroupRepository.GetByAliasCacheKeyPrefix);
+ }
+
+ //we don't know what user's belong to this group without doing a look up so we'll need to just clear them all
+ ClearAllIsolatedCacheByEntityType();
+
+ base.Remove(id);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs b/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs
new file mode 100644
index 0000000000..fe511a5be5
--- /dev/null
+++ b/src/Umbraco.Web/Cache/UserGroupPermissionsCacheRefresher.cs
@@ -0,0 +1,31 @@
+using System;
+using System.ComponentModel;
+using Umbraco.Core.Cache;
+
+namespace Umbraco.Web.Cache
+{
+ [Obsolete("This is no longer used and will be removed from the codebase in the future")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public sealed class UserGroupPermissionsCacheRefresher : CacheRefresherBase
+ {
+ public UserGroupPermissionsCacheRefresher(CacheHelper cacheHelper)
+ : base(cacheHelper)
+ { }
+
+ #region Define
+
+ protected override UserGroupPermissionsCacheRefresher This => this;
+
+ public static readonly Guid UniqueId = Guid.Parse("840AB9C5-5C0B-48DB-A77E-29FE4B80CD3A");
+
+ public override Guid RefresherUniqueId => UniqueId;
+
+ public override string Name => "User Group Permissions Cache Refresher";
+
+ #endregion
+
+ #region Refresher
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Cache/UserPermissionsCacheRefresher.cs b/src/Umbraco.Web/Cache/UserPermissionsCacheRefresher.cs
deleted file mode 100644
index b43a7984d1..0000000000
--- a/src/Umbraco.Web/Cache/UserPermissionsCacheRefresher.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using Umbraco.Core.Cache;
-using Umbraco.Core.Models.Membership;
-
-namespace Umbraco.Web.Cache
-{
- public sealed class UserPermissionsCacheRefresher : CacheRefresherBase
- {
- public UserPermissionsCacheRefresher(CacheHelper cacheHelper)
- : base(cacheHelper)
- { }
-
- #region Define
-
- protected override UserPermissionsCacheRefresher This => this;
-
- public static readonly Guid UniqueId = Guid.Parse("840AB9C5-5C0B-48DB-A77E-29FE4B80CD3A");
-
- public override Guid RefresherUniqueId => UniqueId;
-
- public override string Name => "User Permissions Cache Refresher";
-
- #endregion
-
- #region Refresher
-
- public override void RefreshAll()
- {
- var userPermissionCache = CacheHelper.IsolatedRuntimeCache.GetCache();
- if (userPermissionCache)
- userPermissionCache.Result.ClearCacheByKeySearch(CacheKeys.UserPermissionsCacheKey);
- base.RefreshAll();
- }
-
- public override void Refresh(int id)
- {
- Remove(id);
- base.Refresh(id);
- }
-
- public override void Remove(int id)
- {
- var userPermissionCache = CacheHelper.IsolatedRuntimeCache.GetCache();
- if (userPermissionCache)
- userPermissionCache.Result.ClearCacheByKeySearch($"{CacheKeys.UserPermissionsCacheKey}{id}");
- base.Remove(id);
- }
-
- #endregion
- }
-}
diff --git a/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs b/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs
deleted file mode 100644
index 99edfef6bd..0000000000
--- a/src/Umbraco.Web/Cache/UserTypeCacheRefresher.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System;
-using Umbraco.Core.Cache;
-using Umbraco.Core.Models.Membership;
-
-using Umbraco.Core.Persistence.Repositories;
-
-namespace Umbraco.Web.Cache
-{
- public sealed class UserTypeCacheRefresher : CacheRefresherBase
- {
- public UserTypeCacheRefresher(CacheHelper cacheHelper)
- : base(cacheHelper)
- { }
-
- #region Define
-
- protected override UserTypeCacheRefresher This => this;
-
- public static readonly Guid UniqueId = Guid.Parse("7E707E21-0195-4522-9A3C-658CC1761BD4");
-
- public override Guid RefresherUniqueId => UniqueId;
-
- public override string Name => "User Type Cache Refresher";
-
- #endregion
-
- #region Refresher
-
- public override void RefreshAll()
- {
- ClearAllIsolatedCacheByEntityType();
- base.RefreshAll();
- }
-
- public override void Refresh(int id)
- {
- var userTypeCache = CacheHelper.IsolatedRuntimeCache.GetCache();
- if (userTypeCache)
- userTypeCache.Result.ClearCacheItem(RepositoryBase.GetCacheIdKey(id));
- base.Refresh(id);
- }
-
- public override void Remove(int id)
- {
- var userTypeCache = CacheHelper.IsolatedRuntimeCache.GetCache();
- if (userTypeCache)
- userTypeCache.Result.ClearCacheItem(RepositoryBase.GetCacheIdKey(id));
- base.Remove(id);
- }
-
- #endregion
- }
-}
diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs
index 2ee631d149..8f1ff94a16 100644
--- a/src/Umbraco.Web/Editors/BackOfficeController.cs
+++ b/src/Umbraco.Web/Editors/BackOfficeController.cs
@@ -735,7 +735,7 @@ namespace Umbraco.Web.Editors
private IEnumerable> GetTreePluginsMetaData()
{
- var treeTypes = Current.TypeLoader.ResolveAttributedTreeControllers(); // fixme inject
+ var treeTypes = Current.TypeLoader.GetAttributedTreeControllers(); // fixme inject
//get all plugin trees with their attributes
var treesWithAttributes = treeTypes.Select(x => new
{
diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs
index 92ac0c6be5..06308d724c 100644
--- a/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs
+++ b/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs
@@ -7,7 +7,6 @@ using Umbraco.Core.Services;
namespace Umbraco.Web.HealthCheck.Checks.Config
{
-
public abstract class AbstractConfigCheck : HealthCheck
{
private readonly ConfigurationService _configurationService;
@@ -44,10 +43,18 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
///
public abstract ValueComparisonType ValueComparisonType { get; }
+ ///
+ /// Gets the flag indicating if the check is considered successful if the config value is missing (defaults to false - an error - if missing)
+ ///
+ public virtual bool ValidIfConfigMissing
+ {
+ get { return false; }
+ }
+
protected AbstractConfigCheck(ILocalizedTextService textService)
{
TextService = textService;
- _configurationService = new ConfigurationService(AbsoluteFilePath, XPath);
+ _configurationService = new ConfigurationService(AbsoluteFilePath, XPath, _textService);
}
///
@@ -121,11 +128,18 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
public override IEnumerable GetStatus()
{
+ var successMessage = string.Format(CheckSuccessMessage, FileName, XPath, Values, CurrentValue);
+
var configValue = _configurationService.GetConfigurationValue();
if (configValue.Success == false)
{
- var message = configValue.Result;
- return new[] { new HealthCheckStatus(message) { ResultType = StatusResultType.Error } };
+ if (ValidIfConfigMissing)
+ {
+ return new[] { new HealthCheckStatus(successMessage) { ResultType = StatusResultType.Success } };
+ }
+
+ var errorMessage = configValue.Result;
+ return new[] { new HealthCheckStatus(errorMessage) { ResultType = StatusResultType.Error } };
}
CurrentValue = configValue.Result;
@@ -133,8 +147,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
var valueFound = Values.Any(value => string.Equals(CurrentValue, value.Value, StringComparison.InvariantCultureIgnoreCase));
if (ValueComparisonType == ValueComparisonType.ShouldEqual && valueFound || ValueComparisonType == ValueComparisonType.ShouldNotEqual && valueFound == false)
{
- var message = string.Format(CheckSuccessMessage, FileName, XPath, Values, CurrentValue);
- return new[] { new HealthCheckStatus(message) { ResultType = StatusResultType.Success } };
+ return new[] { new HealthCheckStatus(successMessage) { ResultType = StatusResultType.Success } };
}
// Declare the action for rectifying the config value
diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/CompilationDebugCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/CompilationDebugCheck.cs
index 5b33e14491..951609f91f 100644
--- a/src/Umbraco.Web/HealthCheck/Checks/Config/CompilationDebugCheck.cs
+++ b/src/Umbraco.Web/HealthCheck/Checks/Config/CompilationDebugCheck.cs
@@ -18,6 +18,8 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
public override ValueComparisonType ValueComparisonType => ValueComparisonType.ShouldEqual;
+ public override bool ValidIfConfigMissing => true;
+
public override IEnumerable Values => new List
{
new AcceptableConfiguration { IsRecommended = true, Value = bool.FalseString.ToLower() }
diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/ConfigurationService.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/ConfigurationService.cs
index e1f96a2a38..c1d71d4180 100644
--- a/src/Umbraco.Web/HealthCheck/Checks/Config/ConfigurationService.cs
+++ b/src/Umbraco.Web/HealthCheck/Checks/Config/ConfigurationService.cs
@@ -18,11 +18,11 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
/// The absolute file location of the configuration file
/// The XPath to select the value
///
- public ConfigurationService(string configFilePath, string xPath)
+ public ConfigurationService(string configFilePath, string xPath, ILocalizedTextService textService)
{
_configFilePath = configFilePath;
_xPath = xPath;
- _textService = Current.Services.TextService;
+ _textService = textService;
}
///
diff --git a/src/Umbraco.Web/HealthCheck/Checks/Config/CustomErrorsCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Config/CustomErrorsCheck.cs
index 6948326d06..cbf761b581 100644
--- a/src/Umbraco.Web/HealthCheck/Checks/Config/CustomErrorsCheck.cs
+++ b/src/Umbraco.Web/HealthCheck/Checks/Config/CustomErrorsCheck.cs
@@ -31,7 +31,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Config
get
{
return TextService.Localize("healthcheck/customErrorsCheckSuccessMessage",
- new[] { CurrentValue, Values.First(v => v.IsRecommended).Value });
+ new[] { Values.First(v => v.IsRecommended).Value });
}
}
diff --git a/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs
index dc668d75ff..2078dfe951 100644
--- a/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs
+++ b/src/Umbraco.Web/HealthCheck/Checks/Security/ClickJackingCheck.cs
@@ -66,13 +66,10 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
{
var message = string.Empty;
var success = false;
- var url = _runtime.ApplicationUrl;
// Access the site home page and check for the click-jack protection header or meta tag
- var serverVariables = _httpContextAccessor.HttpContext.Request.ServerVariables;
- var useSsl = GlobalSettings.UseSSL || _httpContextAccessor.HttpContext.Request.ServerVariables["SERVER_PORT"] == "443";
- var address = string.Format("http{0}://{1}:{2}", useSsl ? "s" : "", url.Host.ToLower(), url.Port);
- var request = WebRequest.Create(address);
+ var url = _runtime.ApplicationUrl;
+ var request = WebRequest.Create(url);
request.Method = "GET";
try
{
@@ -93,7 +90,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
}
catch (Exception ex)
{
- message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { address, ex.Message });
+ message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url, ex.Message });
}
var actions = new List();
diff --git a/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs
index e794a41426..aec57ab003 100644
--- a/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs
+++ b/src/Umbraco.Web/HealthCheck/Checks/Security/ExcessiveHeadersCheck.cs
@@ -54,10 +54,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
var url = _runtime.ApplicationUrl;
// Access the site home page and check for the headers
- var serverVariables = _httpContextAccessor.HttpContext.Request.ServerVariables;
- var useSsl = GlobalSettings.UseSSL || _httpContextAccessor.HttpContext.Request.ServerVariables["SERVER_PORT"] == "443";
- var address = string.Format("http{0}://{1}:{2}", useSsl ? "s" : "", url.Host.ToLower(), url.Port);
- var request = WebRequest.Create(address);
+ var request = WebRequest.Create(url);
request.Method = "HEAD";
try
{
@@ -74,7 +71,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
}
catch (Exception ex)
{
- message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { address, ex.Message });
+ message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url, ex.Message });
}
var actions = new List();
diff --git a/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs
index 1fb9005036..e9e39f6ebe 100644
--- a/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs
+++ b/src/Umbraco.Web/HealthCheck/Checks/Security/HttpsCheck.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Net;
+using System.Security.Cryptography.X509Certificates;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.IO;
@@ -56,19 +57,48 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
private HealthCheckStatus CheckForValidCertificate()
{
var message = string.Empty;
- var success = false;
- var url = _runtime.ApplicationUrl;
+ StatusResultType result;
// Attempt to access the site over HTTPS to see if it HTTPS is supported
// and a valid certificate has been configured
- var address = string.Format("https://{0}:{1}", url.Host.ToLower(), url.Port);
- var request = (HttpWebRequest)WebRequest.Create(address);
+ var url = _runtime.ApplicationUrl.Replace("http:", "https:");
+ var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "HEAD";
try
{
var response = (HttpWebResponse)request.GetResponse();
- success = response.StatusCode == HttpStatusCode.OK;
+ if (response.StatusCode == HttpStatusCode.OK)
+ {
+ // Got a valid response, check now for if certificate expiring within 14 days
+ // Hat-tip: https://stackoverflow.com/a/15343898/489433
+ const int NumberOfDaysForExpiryWarning = 14;
+ var cert = request.ServicePoint.Certificate;
+ var cert2 = new X509Certificate2(cert);
+ var expirationDate = cert2.NotAfter;
+
+ var daysToExpiry = (int)Math.Floor((cert2.NotAfter - DateTime.Now).TotalDays);
+ if (daysToExpiry <= 0)
+ {
+ result = StatusResultType.Error;
+ message = _textService.Localize("healthcheck/httpsCheckExpiredCertificate");
+ }
+ else if (daysToExpiry < NumberOfDaysForExpiryWarning)
+ {
+ result = StatusResultType.Warning;
+ message = _textService.Localize("healthcheck/httpsCheckExpiringCertificate", new[] { daysToExpiry.ToString() });
+ }
+ else
+ {
+ result = StatusResultType.Success;
+ message = _textService.Localize("healthcheck/httpsCheckValidCertificate");
+ }
+ }
+ else
+ {
+ result = StatusResultType.Error;
+ message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url, response.StatusDescription });
+ }
}
catch (Exception ex)
{
@@ -77,30 +107,29 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
{
message = exception.Status == WebExceptionStatus.TrustFailure
? _textService.Localize("healthcheck/httpsCheckInvalidCertificate", new [] { exception.Message })
- : _textService.Localize("healthcheck/httpsCheckInvalidUrl", new [] { address, exception.Message });
+ : _textService.Localize("healthcheck/httpsCheckInvalidUrl", new [] { url, exception.Message });
}
else
{
- message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { address, ex.Message });
+ message = _textService.Localize("healthcheck/httpsCheckInvalidUrl", new[] { url, ex.Message });
}
+
+ result = StatusResultType.Error;
}
var actions = new List();
- if (success)
- message = _textService.Localize("healthcheck/httpsCheckValidCertificate");
-
return
new HealthCheckStatus(message)
{
- ResultType = success ? StatusResultType.Success : StatusResultType.Error,
+ ResultType = result,
Actions = actions
};
}
private HealthCheckStatus CheckIfCurrentSchemeIsHttps()
{
- var uri = HttpContext.Current.Request.Url;
+ var uri = new Uri(HealthCheckContext.SiteUrl);
var success = uri.Scheme == "https";
var actions = new List();
@@ -116,7 +145,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
private HealthCheckStatus CheckHttpsConfigurationSetting()
{
var httpsSettingEnabled = Core.Configuration.GlobalSettings.UseSSL;
- var uri = HttpContext.Current.Request.Url;
+ var uri = new Uri(HealthCheckContext.SiteUrl);
var actions = new List();
string resultMessage;
@@ -152,7 +181,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Security
{
var configFile = IOHelper.MapPath("~/Web.config");
const string xPath = "/configuration/appSettings/add[@key='umbracoUseSSL']/@value";
- var configurationService = new ConfigurationService(configFile, xPath);
+ var configurationService = new ConfigurationService(configFile, xPath, _textService);
var updateConfigFile = configurationService.UpdateConfigFile("true");
if (updateConfigFile.Success)
diff --git a/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs b/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs
index 8e3447c79f..882b4cf049 100644
--- a/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs
+++ b/src/Umbraco.Web/HealthCheck/Checks/Services/SmtpCheck.cs
@@ -53,7 +53,7 @@ namespace Umbraco.Web.HealthCheck.Checks.Services
// appPath is the virtual application root path on the server
var appPath = "";
- var config = WebConfigurationManager.OpenWebConfiguration(_runtime.ApplicationVirtualPath);
+ var config = WebConfigurationManager.OpenWebConfiguration(_runtime.ApplicationPath);
var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings");
if (settings == null)
{
diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckAction.cs b/src/Umbraco.Web/HealthCheck/HealthCheckAction.cs
index f5549221a1..ce7d842e96 100644
--- a/src/Umbraco.Web/HealthCheck/HealthCheckAction.cs
+++ b/src/Umbraco.Web/HealthCheck/HealthCheckAction.cs
@@ -47,12 +47,11 @@ namespace Umbraco.Web.HealthCheck
[DataMember(Name = "actionParameters")]
public Dictionary ActionParameters { get; set; }
-
///
/// The name of the action - this is used to name the fix button
///
[DataMember(Name = "name")]
- private string _name = Current.Services.TextService.Localize("healthcheck/rectifyButton");
+ private string _name;
public string Name
{
get { return _name; }
diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckController.cs b/src/Umbraco.Web/HealthCheck/HealthCheckController.cs
index ab3a434e36..a0dcfb57d8 100644
--- a/src/Umbraco.Web/HealthCheck/HealthCheckController.cs
+++ b/src/Umbraco.Web/HealthCheck/HealthCheckController.cs
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
+using System.Configuration;
using System.Linq;
using System.Web.Http;
using Umbraco.Core.Logging;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.HealthChecks;
using Umbraco.Web.Editors;
namespace Umbraco.Web.HealthCheck
@@ -13,12 +16,18 @@ namespace Umbraco.Web.HealthCheck
public class HealthCheckController : UmbracoAuthorizedJsonController
{
private readonly HealthCheckCollection _checks;
+ private readonly IList _disabledCheckIds;
private readonly ILogger _logger;
public HealthCheckController(HealthCheckCollection checks, ILogger logger)
{
_checks = checks ?? throw new ArgumentNullException(nameof(checks));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
+
+ var healthCheckConfig = UmbracoConfig.For.HealthCheck();
+ _disabledCheckIds = healthCheckConfig.DisabledChecks
+ .Select(x => x.Id)
+ .ToList();
}
///
@@ -28,6 +37,7 @@ namespace Umbraco.Web.HealthCheck
public object GetAllHealthChecks()
{
var groups = _checks
+ .Where(x => _disabledCheckIds.Contains(x.Id) == false)
.GroupBy(x => x.Group)
.OrderBy(x => x.Key);
var healthCheckGroups = new List();
@@ -49,9 +59,8 @@ namespace Umbraco.Web.HealthCheck
[HttpGet]
public object GetStatus(Guid id)
{
- var check = _checks.FirstOrDefault(x => x.Id == id);
- if (check == null) throw new InvalidOperationException("No health check found with ID " + id);
-
+ var check = GetCheckById(id);
+
try
{
//Core.Logging.LogHelper.Debug("Running health check: " + check.Name);
@@ -67,10 +76,19 @@ namespace Umbraco.Web.HealthCheck
[HttpPost]
public HealthCheckStatus ExecuteAction(HealthCheckAction action)
{
- var check = _checks.FirstOrDefault(x => x.Id == action.HealthCheckId);
- if (check == null) throw new InvalidOperationException("No health check found with id " + action.HealthCheckId);
-
+ var check = GetCheckById(action.HealthCheckId);
return check.ExecuteAction(action);
}
+
+ private HealthCheck GetCheckById(Guid id)
+ {
+ var check = _checks
+ .FirstOrDefault(x => x.Id == action.HealthCheckId)
+ .Where(x => _disabledCheckIds.Contains(x.Id) == false);
+
+ if (check == null) throw new InvalidOperationException(string.Format("No health check found with id {0}", id));
+
+ return check;
+ }
}
}
diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodAttribute.cs b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodAttribute.cs
new file mode 100644
index 0000000000..5aa231f96b
--- /dev/null
+++ b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodAttribute.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Umbraco.Web.HealthCheck
+{
+ ///
+ /// Metadata attribute for health check notification methods
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
+ public sealed class HealthCheckNotificationMethodAttribute : Attribute
+ {
+ public HealthCheckNotificationMethodAttribute(string alias)
+ {
+ Alias = alias;
+ }
+
+ public string Alias { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollection.cs b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollection.cs
new file mode 100644
index 0000000000..6c5f89e4bc
--- /dev/null
+++ b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollection.cs
@@ -0,0 +1,13 @@
+using System.Collections.Generic;
+using Umbraco.Core.Composing;
+using Umbraco.Web.HealthCheck.NotificationMethods;
+
+namespace Umbraco.Web.HealthCheck
+{
+ public class HealthCheckNotificationMethodCollection : BuilderCollectionBase
+ {
+ public HealthCheckNotificationMethodCollection(IEnumerable items)
+ : base(items)
+ { }
+ }
+}
diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs
new file mode 100644
index 0000000000..40b253e4e4
--- /dev/null
+++ b/src/Umbraco.Web/HealthCheck/HealthCheckNotificationMethodCollectionBuilder.cs
@@ -0,0 +1,15 @@
+using LightInject;
+using Umbraco.Core.Composing;
+using Umbraco.Web.HealthCheck.NotificationMethods;
+
+namespace Umbraco.Web.HealthCheck
+{
+ internal class HealthCheckNotificationMethodCollectionBuilder : LazyCollectionBuilderBase
+ {
+ public HealthCheckNotificationMethodCollectionBuilder(IServiceContainer container)
+ : base(container)
+ { }
+
+ protected override HealthCheckNotificationMethodCollectionBuilder This => this;
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/HealthCheck/HealthCheckResults.cs b/src/Umbraco.Web/HealthCheck/HealthCheckResults.cs
new file mode 100644
index 0000000000..139072dcfe
--- /dev/null
+++ b/src/Umbraco.Web/HealthCheck/HealthCheckResults.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using HeyRed.MarkdownSharp;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Configuration.HealthChecks;
+using Umbraco.Core.Logging;
+
+namespace Umbraco.Web.HealthCheck
+{
+ public class HealthCheckResults
+ {
+ private readonly Dictionary> _results;
+ public readonly bool AllChecksSuccessful;
+
+ private ILogger Logger => Current.Logger; // fixme inject
+
+ public HealthCheckResults(IEnumerable checks)
+ {
+ _results = checks.ToDictionary(
+ t => t.Name,
+ t => {
+ try
+ {
+ return t.GetStatus();
+ }
+ catch (Exception ex)
+ {
+ Logger.Error($"Error running scheduled health check: {t.Name}", ex);
+ var message = $"Health check failed with exception: {ex.Message}. See logs for details.";
+ return new List
+ {
+ new HealthCheckStatus(message)
+ {
+ ResultType = StatusResultType.Error
+ }
+ };
+ }
+ });
+
+ // find out if all checks pass or not
+ AllChecksSuccessful = true;
+ foreach (var result in _results)
+ {
+ var checkIsSuccess = result.Value.All(x => x.ResultType == StatusResultType.Success || x.ResultType == StatusResultType.Info || x.ResultType == StatusResultType.Warning);
+ if (checkIsSuccess == false)
+ {
+ AllChecksSuccessful = false;
+ break;
+ }
+ }
+ }
+
+ public void LogResults()
+ {
+ Logger.Info("Scheduled health check results:");
+ foreach (var result in _results)
+ {
+ var checkName = result.Key;
+ var checkResults = result.Value;
+ var checkIsSuccess = result.Value.All(x => x.ResultType == StatusResultType.Success);
+ if (checkIsSuccess)
+ {
+ Logger.Info($" Checks for '{checkName}' all completed succesfully.");
+ }
+ else
+ {
+ Logger.Warn($" Checks for '{checkName}' completed with errors.");
+ }
+
+ foreach (var checkResult in checkResults)
+ {
+ Logger.Info($" Result: {checkResult.ResultType}, Message: '{checkResult.Message}'");
+ }
+ }
+ }
+
+ public string ResultsAsMarkDown(HealthCheckNotificationVerbosity verbosity)
+ {
+ var newItem = "- ";
+
+ var sb = new StringBuilder();
+
+ foreach (var result in _results)
+ {
+ var checkName = result.Key;
+ var checkResults = result.Value;
+ var checkIsSuccess = result.Value.All(x => x.ResultType == StatusResultType.Success);
+
+ // add a new line if not the first check
+ if (result.Equals(_results.First()) == false)
+ {
+ sb.Append(Environment.NewLine);
+ }
+
+ if (checkIsSuccess)
+ {
+ sb.AppendFormat("{0}Checks for '{1}' all completed succesfully.{2}", newItem, checkName, Environment.NewLine);
+ }
+ else
+ {
+ sb.AppendFormat("{0}Checks for '{1}' completed with errors.{2}", newItem, checkName, Environment.NewLine);
+ }
+
+ foreach (var checkResult in checkResults)
+ {
+ sb.AppendFormat("\t{0}Result: '{1}'", newItem, checkResult.ResultType);
+
+ // With summary logging, only record details of warnings or errors
+ if (checkResult.ResultType != StatusResultType.Success || verbosity == HealthCheckNotificationVerbosity.Detailed)
+ {
+ sb.AppendFormat(", Message: '{0}'", SimpleHtmlToMarkDown(checkResult.Message));
+ }
+
+ sb.AppendLine(Environment.NewLine);
+ }
+ }
+
+ return sb.ToString();
+ }
+
+ public string ResultsAsHtml(HealthCheckNotificationVerbosity verbosity)
+ {
+ var mark = new Markdown();
+ var html = mark.Transform(ResultsAsMarkDown(verbosity));
+ html = ApplyHtmlHighlighting(html);
+ return html;
+ }
+
+ private string ApplyHtmlHighlighting(string html)
+ {
+ html = ApplyHtmlHighlightingForStatus(html, StatusResultType.Success, "5cb85c");
+ html = ApplyHtmlHighlightingForStatus(html, StatusResultType.Warning, "f0ad4e");
+ return ApplyHtmlHighlightingForStatus(html, StatusResultType.Error, "d9534f");
+ }
+
+ private string ApplyHtmlHighlightingForStatus(string html, StatusResultType status, string color)
+ {
+ return html
+ .Replace("Result: '" + status + "'", "Result: " + status + " ");
+ }
+
+ private string SimpleHtmlToMarkDown(string html)
+ {
+ return html.Replace("", "**")
+ .Replace(" ", "**")
+ .Replace("", "*")
+ .Replace(" ", "*");
+ }
+
+ public Dictionary> GetResultsForStatus(StatusResultType resultType)
+ {
+ switch (resultType)
+ {
+ case StatusResultType.Success:
+ // a check is considered a success status if all checks are successful or info
+ var successResults = _results.Where(x => x.Value.Any(y => y.ResultType == StatusResultType.Success) && x.Value.All(y => y.ResultType == StatusResultType.Success || y.ResultType == StatusResultType.Info));
+ return successResults.ToDictionary(x => x.Key, x => x.Value);
+ case StatusResultType.Warning:
+ // a check is considered warn status if one check is warn and all others are success or info
+ var warnResults = _results.Where(x => x.Value.Any(y => y.ResultType == StatusResultType.Warning) && x.Value.All(y => y.ResultType == StatusResultType.Warning || y.ResultType == StatusResultType.Success || y.ResultType == StatusResultType.Info));
+ return warnResults.ToDictionary(x => x.Key, x => x.Value);
+ case StatusResultType.Error:
+ // a check is considered error status if any check is error
+ var errorResults = _results.Where(x => x.Value.Any(y => y.ResultType == StatusResultType.Error));
+ return errorResults.ToDictionary(x => x.Key, x => x.Value);
+ case StatusResultType.Info:
+ // a check is considered info status if all checks are info
+ var infoResults = _results.Where(x => x.Value.All(y => y.ResultType == StatusResultType.Info));
+ return infoResults.ToDictionary(x => x.Key, x => x.Value);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/Umbraco.Web/HealthCheck/NotificationMethods/EmailNotificationMethod.cs b/src/Umbraco.Web/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
new file mode 100644
index 0000000000..392d166d68
--- /dev/null
+++ b/src/Umbraco.Web/HealthCheck/NotificationMethods/EmailNotificationMethod.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Net.Mail;
+using System.Threading;
+using System.Threading.Tasks;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Services;
+
+namespace Umbraco.Web.HealthCheck.NotificationMethods
+{
+ [HealthCheckNotificationMethod("email")]
+ public class EmailNotificationMethod : NotificationMethodBase
+ {
+ private readonly ILocalizedTextService _textService;
+
+ internal EmailNotificationMethod(ILocalizedTextService textService)
+ {
+ var recipientEmail = Settings["recipientEmail"]?.Value;
+ if (string.IsNullOrWhiteSpace(recipientEmail))
+ {
+ Enabled = false;
+ return;
+ }
+
+ RecipientEmail = recipientEmail;
+
+ _textService = textService ?? throw new ArgumentNullException(nameof(textService));
+ }
+
+ public string RecipientEmail { get; }
+
+ public override async Task SendAsync(HealthCheckResults results, CancellationToken token)
+ {
+ if (ShouldSend(results) == false)
+ {
+ return;
+ }
+
+ if (string.IsNullOrEmpty(RecipientEmail))
+ {
+ return;
+ }
+
+ var message = _textService.Localize("healthcheck/scheduledHealthCheckEmailBody", new[]
+ {
+ DateTime.Now.ToShortDateString(),
+ DateTime.Now.ToShortTimeString(),
+ results.ResultsAsHtml(Verbosity)
+ });
+
+ var subject = _textService.Localize("healthcheck/scheduledHealthCheckEmailSubject");
+
+ using (var client = new SmtpClient())
+ using (var mailMessage = CreateMailMessage(subject, message))
+ {
+ if (client.DeliveryMethod == SmtpDeliveryMethod.Network)
+ {
+ await client.SendMailAsync(mailMessage);
+ }
+ else
+ {
+ client.Send(mailMessage);
+ }
+ }
+ }
+
+ private MailMessage CreateMailMessage(string subject, string message)
+ {
+ var to = UmbracoConfig.For.UmbracoSettings().Content.NotificationEmailAddress;
+
+ if (string.IsNullOrWhiteSpace(subject))
+ subject = "Umbraco Health Check Status";
+
+ return new MailMessage(to, RecipientEmail, subject, message)
+ {
+ IsBodyHtml = message.IsNullOrWhiteSpace() == false && message.Contains("<") && message.Contains("")
+ };
+ }
+ }
+}
diff --git a/src/Umbraco.Web/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs b/src/Umbraco.Web/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs
new file mode 100644
index 0000000000..17102014bd
--- /dev/null
+++ b/src/Umbraco.Web/HealthCheck/NotificationMethods/IHealthCheckNotificationMethod.cs
@@ -0,0 +1,10 @@
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Umbraco.Web.HealthCheck.NotificationMethods
+{
+ public interface IHealthCheckNotificationMethod
+ {
+ Task SendAsync(HealthCheckResults results, CancellationToken token);
+ }
+}
diff --git a/src/Umbraco.Web/HealthCheck/NotificationMethods/NotificationMethodBase.cs b/src/Umbraco.Web/HealthCheck/NotificationMethods/NotificationMethodBase.cs
new file mode 100644
index 0000000000..af471e63ac
--- /dev/null
+++ b/src/Umbraco.Web/HealthCheck/NotificationMethods/NotificationMethodBase.cs
@@ -0,0 +1,52 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using NuGet;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.HealthChecks;
+
+namespace Umbraco.Web.HealthCheck.NotificationMethods
+{
+ public abstract class NotificationMethodBase : IHealthCheckNotificationMethod
+ {
+ protected NotificationMethodBase()
+ {
+ var type = GetType();
+ var attribute = type.GetCustomAttribute();
+ if (attribute == null)
+ {
+ Enabled = false;
+ return;
+ }
+
+ var healthCheckConfig = UmbracoConfig.For.HealthCheck();
+ var notificationMethods = healthCheckConfig.NotificationSettings.NotificationMethods;
+ var notificationMethod = notificationMethods[attribute.Alias];
+ if (notificationMethod == null)
+ {
+ Enabled = false;
+ return;
+ }
+
+ Enabled = notificationMethod.Enabled;
+ FailureOnly = notificationMethod.FailureOnly;
+ Verbosity = notificationMethod.Verbosity;
+ Settings = notificationMethod.Settings;
+ }
+
+ public bool Enabled { get; protected set; }
+
+ public bool FailureOnly { get; protected set; }
+
+ public HealthCheckNotificationVerbosity Verbosity { get; protected set; }
+
+ public IReadOnlyDictionary Settings { get; }
+
+ protected bool ShouldSend(HealthCheckResults results)
+ {
+ return Enabled && (!FailureOnly || !results.AllChecksSuccessful);
+ }
+
+ public abstract Task SendAsync(HealthCheckResults results, CancellationToken token);
+ }
+}
diff --git a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs
index fe463e36a6..50fe829e1a 100644
--- a/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs
+++ b/src/Umbraco.Web/HtmlHelperBackOfficeExtensions.cs
@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
@@ -20,11 +22,19 @@ namespace Umbraco.Web
///
public static class HtmlHelperBackOfficeExtensions
{
+ [Obsolete("Use the overload with all required parameters instead")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public static IHtmlString BareMinimumServerVariablesScript(this HtmlHelper html, UrlHelper uri, string externalLoginsUrl)
+ {
+ return html.BareMinimumServerVariablesScript(uri, ApplicationContext.Current, externalLoginsUrl);
+ }
+
///
/// Outputs a script tag containing the bare minimum (non secure) server vars for use with the angular app
///
///
///
+ ///
///
/// The post url used to sign in with external logins - this can change depending on for what service the external login is service.
/// Example: normal back office login or authenticating upgrade login
@@ -34,29 +44,15 @@ namespace Umbraco.Web
/// These are the bare minimal server variables that are required for the application to start without being authenticated,
/// we will load the rest of the server vars after the user is authenticated.
///
- public static IHtmlString BareMinimumServerVariablesScript(this HtmlHelper html, UrlHelper uri, string externalLoginsUrl)
+ public static IHtmlString BareMinimumServerVariablesScript(this HtmlHelper html, UrlHelper uri, ApplicationContext appCtx, string externalLoginsUrl)
{
- var version = UmbracoVersion.SemanticVersion.ToSemanticString();
+ var serverVars = new BackOfficeServerVariables(uri, appCtx, UmbracoConfig.For.UmbracoSettings());
+ var minVars = serverVars.BareMinimumServerVariables();
+
var str = @"";
return html.Raw(str);
diff --git a/src/Umbraco.Web/IPublishedContentQuery.cs b/src/Umbraco.Web/IPublishedContentQuery.cs
index 26a332e239..2938fa36d9 100644
--- a/src/Umbraco.Web/IPublishedContentQuery.cs
+++ b/src/Umbraco.Web/IPublishedContentQuery.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Xml.XPath;
+using Umbraco.Core;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Xml;
@@ -15,6 +16,7 @@ namespace Umbraco.Web
{
IPublishedContent Content(int id);
IPublishedContent Content(Guid id);
+ IPublishedContent Content(Udi id);
IPublishedContent ContentSingleAtXPath(string xpath, params XPathVariable[] vars);
IEnumerable Content(IEnumerable ids);
IEnumerable Content(IEnumerable ids);
@@ -24,6 +26,7 @@ namespace Umbraco.Web
IPublishedContent Media(int id);
IPublishedContent Media(Guid id);
+ IPublishedContent Media(Udi id);
IEnumerable Media(IEnumerable ids);
IEnumerable Media(IEnumerable ids);
IEnumerable MediaAtRoot();
diff --git a/src/Umbraco.Web/Install/InstallHelper.cs b/src/Umbraco.Web/Install/InstallHelper.cs
index a94cc96466..379a11c8cd 100644
--- a/src/Umbraco.Web/Install/InstallHelper.cs
+++ b/src/Umbraco.Web/Install/InstallHelper.cs
@@ -48,6 +48,7 @@ namespace Umbraco.Web.Install
new FilePermissionsStep(),
new MajorVersion7UpgradeReport(_databaseBuilder, Current.RuntimeState, Current.DatabaseContext, Current.ScopeProvider),
new Version73FileCleanup(_httpContext, _logger),
+ new ConfigureMachineKey(),
new DatabaseConfigureStep(_databaseBuilder),
new DatabaseInstallStep(_databaseBuilder, Current.RuntimeState, Current.Logger),
new DatabaseUpgradeStep(_databaseBuilder, Current.Services.MigrationEntryService, Current.RuntimeState, Current.MigrationCollectionBuilder, Current.Logger),
diff --git a/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs b/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs
new file mode 100644
index 0000000000..e4038df4ab
--- /dev/null
+++ b/src/Umbraco.Web/Install/InstallSteps/ConfigureMachineKey.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Configuration;
+using System.Linq;
+using System.Web.Configuration;
+using System.Xml.Linq;
+using Umbraco.Core;
+using Umbraco.Core.IO;
+using Umbraco.Core.Security;
+using Umbraco.Web.Install.Models;
+
+namespace Umbraco.Web.Install.InstallSteps
+{
+ [InstallSetupStep(InstallationType.NewInstall,
+ "ConfigureMachineKey", "machinekey", 2,
+ "Updating some security settings...",
+ PerformsAppRestart = true)]
+ internal class ConfigureMachineKey : InstallSetupStep
+ {
+ private readonly ApplicationContext _appContext;
+
+ public ConfigureMachineKey(ApplicationContext appContext)
+ {
+ if (appContext == null) throw new ArgumentNullException("appContext");
+ _appContext = appContext;
+ }
+
+ public override string View
+ {
+ get { return HasMachineKey() == false ? base.View : ""; }
+ }
+
+ ///
+ /// Don't display the view or execute if a machine key already exists
+ ///
+ ///
+ private bool HasMachineKey()
+ {
+ var section = (MachineKeySection)WebConfigurationManager.GetSection("system.web/machineKey");
+ return section.ElementInformation.Source != null;
+ }
+
+ ///
+ /// The step execution method
+ ///
+ ///
+ ///
+ public override InstallSetupResult Execute(bool? model)
+ {
+ if (model.HasValue && model.Value == false) return null;
+
+ //install the machine key
+ var fileName = IOHelper.MapPath(string.Format("{0}/web.config", SystemDirectories.Root));
+ var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
+
+ var systemWeb = xml.Root.DescendantsAndSelf("system.web").Single();
+
+ // Update appSetting if it exists, or else create a new appSetting for the given key and value
+ var machineKey = systemWeb.Descendants("machineKey").FirstOrDefault();
+ if (machineKey != null) return null;
+
+ var generator = new MachineKeyGenerator();
+ var generatedSection = generator.GenerateConfigurationBlock();
+ systemWeb.Add(XElement.Parse(generatedSection));
+
+ xml.Save(fileName, SaveOptions.DisableFormatting);
+
+ return null;
+ }
+
+ public override bool RequiresExecution(bool? model)
+ {
+ return HasMachineKey() == false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
index bc98437143..d1753cdc4c 100644
--- a/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
+++ b/src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
@@ -2,6 +2,7 @@
using System.Configuration;
using Umbraco.Core;
using Umbraco.Core.Configuration;
+using Umbraco.Core.Logging;
using Umbraco.Web.Install.Models;
namespace Umbraco.Web.Install.InstallSteps
@@ -12,6 +13,7 @@ namespace Umbraco.Web.Install.InstallSteps
internal class DatabaseConfigureStep : InstallSetupStep
{
private readonly DatabaseBuilder _databaseBuilder;
+ private readonly ILogger _logger;
public DatabaseConfigureStep(DatabaseBuilder databaseBuilder)
{
@@ -80,8 +82,9 @@ namespace Umbraco.Web.Install.InstallSteps
result.DetermineInstalledVersion();
return false;
}
- catch (Exception)
+ catch (Exception ex)
{
+ _logger.Error("An error occurred, reconfiguring...", ex);
//something went wrong, could not connect so probably need to reconfigure
return true;
}
diff --git a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs
index 0d45a14581..1757311180 100644
--- a/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs
+++ b/src/Umbraco.Web/Install/InstallSteps/NewInstallStep.cs
@@ -35,6 +35,7 @@ namespace Umbraco.Web.Install.InstallSteps
_databaseBuilder = databaseBuilder;
}
+ //TODO: Change all logic in this step to use ASP.NET Identity NOT MembershipProviders
private MembershipProvider CurrentProvider
{
get
diff --git a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs
index 3161dba04a..b8ae254c31 100644
--- a/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs
+++ b/src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs
@@ -12,18 +12,21 @@ using Umbraco.Web.Security;
namespace Umbraco.Web.Install.InstallSteps
{
[InstallSetupStep(InstallationType.NewInstall,
- "StarterKitDownload", "starterKit", 30, "Adding a simple website to Umbraco, will make it easier for you to get started")]
+ "StarterKitDownload", "starterKit", 30, "Adding a simple website to Umbraco, will make it easier for you to get started",
+ PerformsAppRestart = true)]
internal class StarterKitDownloadStep : InstallSetupStep
{
private readonly InstallHelper _installHelper;
private readonly IContentService _contentService;
private readonly WebSecurity _security;
+ private readonly HttpContextBase _httpContext;
public StarterKitDownloadStep(IContentService contentService, InstallHelper installHelper, WebSecurity security)
{
_installHelper = installHelper;
_contentService = contentService;
_security = security;
+ _httpContext = httpContext;
}
private const string RepoGuid = "65194810-1f85-11dd-bd0b-0800200c9a66";
@@ -48,6 +51,8 @@ namespace Umbraco.Web.Install.InstallSteps
var result = DownloadPackageFiles(starterKitId.Value);
+ _applicationContext.RestartApplicationPool(_httpContext);
+
return new InstallSetupResult(new Dictionary
{
{"manifestId", result.Item2},
diff --git a/src/Umbraco.Web/MembershipProviderExtensions.cs b/src/Umbraco.Web/MembershipProviderExtensions.cs
index cb26930b30..614950db59 100644
--- a/src/Umbraco.Web/MembershipProviderExtensions.cs
+++ b/src/Umbraco.Web/MembershipProviderExtensions.cs
@@ -28,7 +28,8 @@ namespace Umbraco.Web
{"enableReset", canReset},
{"enablePasswordRetrieval", membershipProvider.EnablePasswordRetrieval},
{"requiresQuestionAnswer", membershipProvider.RequiresQuestionAndAnswer},
- {"allowManuallyChangingPassword", baseProvider != null && baseProvider.AllowManuallyChangingPassword}
+ {"allowManuallyChangingPassword", baseProvider != null && baseProvider.AllowManuallyChangingPassword},
+ {"minNonAlphaNumericChars", membershipProvider.MinRequiredNonAlphanumericCharacters}
//TODO: Inject the other parameters in here to change the behavior of this control - based on the membership provider settings.
};
}
diff --git a/src/Umbraco.Web/ModelStateExtensions.cs b/src/Umbraco.Web/ModelStateExtensions.cs
index 2db24938ad..3e122199a7 100644
--- a/src/Umbraco.Web/ModelStateExtensions.cs
+++ b/src/Umbraco.Web/ModelStateExtensions.cs
@@ -61,7 +61,7 @@ namespace Umbraco.Web
{
//if there are no member names supplied then we assume that the validation message is for the overall property
// not a sub field on the property editor
- if (!result.MemberNames.Any())
+ if (result.MemberNames.Any() == false)
{
//add a model state error for the entire property
modelState.AddModelError(string.Format("{0}.{1}", "_Properties", propertyAlias), result.ErrorMessage);
diff --git a/src/Umbraco.Web/PluginManagerExtensions.cs b/src/Umbraco.Web/PluginManagerExtensions.cs
deleted file mode 100644
index 77ff98a453..0000000000
--- a/src/Umbraco.Web/PluginManagerExtensions.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using Umbraco.Core;
-using Umbraco.Core.Media;
-using Umbraco.Web.Mvc;
-using Umbraco.Web.Routing;
-using Umbraco.Web.Trees;
-using Umbraco.Web.WebApi;
-using umbraco;
-using umbraco.cms.presentation.Trees;
-using Umbraco.Core.Composing;
-using Umbraco.Web.Models.Trees;
-using Umbraco.Web._Legacy.Actions;
-
-namespace Umbraco.Web
-{
- ///
- /// Extension methods for the PluginTypeResolver
- ///
- public static class PluginManagerExtensions
- {
- ///
- /// Returns all available IAction in application
- ///
- ///
- internal static IEnumerable ResolveActions(this TypeLoader resolver)
- {
- return resolver.GetTypes();
- }
- ///
- /// Returns all available TreeApiController's in application that are attribute with TreeAttribute
- ///
- ///
- ///
- internal static IEnumerable ResolveAttributedTreeControllers(this TypeLoader resolver)
- {
- return resolver.GetTypesWithAttribute();
- }
-
- internal static IEnumerable ResolveSurfaceControllers(this TypeLoader resolver)
- {
- return resolver.GetTypes();
- }
-
- internal static IEnumerable ResolveUmbracoApiControllers(this TypeLoader resolver)
- {
- return resolver.GetTypes();
- }
-
- ///
- /// Returns all available ITrees in application
- ///
- ///
- ///
- internal static IEnumerable ResolveTrees(this TypeLoader resolver)
- {
- return resolver.GetTypes();
- }
-
-
- ///
- /// Returns all classes attributed with XsltExtensionAttribute attribute
- ///
- ///
- ///
- internal static IEnumerable ResolveXsltExtensions(this TypeLoader resolver)
- {
- return resolver.GetAttributedTypes();
- }
-
- ///
- /// Returns all IThumbnailProvider classes
- ///
- ///
- ///
- internal static IEnumerable ResolveThumbnailProviders(this TypeLoader resolver)
- {
- return resolver.GetTypes();
- }
-
- ///
- /// Returns all IImageUrlProvider classes
- ///
- ///
- ///
- internal static IEnumerable ResolveImageUrlProviders(this TypeLoader resolver)
- {
- return resolver.GetTypes();
- }
-
- }
-}
diff --git a/src/Umbraco.Web/PublishedContentExtensions.cs b/src/Umbraco.Web/PublishedContentExtensions.cs
index e3b5fd3ccb..4f637d7dbd 100644
--- a/src/Umbraco.Web/PublishedContentExtensions.cs
+++ b/src/Umbraco.Web/PublishedContentExtensions.cs
@@ -311,20 +311,7 @@ namespace Umbraco.Web
if (content.IsDocumentType(docTypeAlias))
return true;
- return recursive && IsDocumentTypeRecursive(content, docTypeAlias);
- }
-
- private static bool IsDocumentTypeRecursive(IPublishedContent content, string docTypeAlias)
- {
- var contentTypeService = Current.Services.ContentTypeService; // fixme - inject
- var type = contentTypeService.Get(content.DocumentTypeAlias);
- while (type != null && type.ParentId > 0)
- {
- type = contentTypeService.Get(type.ParentId);
- if (type.Alias.InvariantEquals(docTypeAlias))
- return true;
- }
- return false;
+ return recursive && content.IsComposedOf(docTypeAlias);
}
public static bool IsNull(this IPublishedContent content, string alias, bool recurse)
diff --git a/src/Umbraco.Web/PublishedContentQuery.cs b/src/Umbraco.Web/PublishedContentQuery.cs
index 8aea27f675..3200f4ad84 100644
--- a/src/Umbraco.Web/PublishedContentQuery.cs
+++ b/src/Umbraco.Web/PublishedContentQuery.cs
@@ -59,6 +59,14 @@ namespace Umbraco.Web
: _query.Content(id);
}
+ public IPublishedContent Content(Udi id)
+ {
+ if (!(id is GuidUdi udi)) return null;
+ return _query == null
+ ? ItemById(udi.Guid, _contentCache)
+ : _query.Content(udi.Guid);
+ }
+
public IPublishedContent ContentSingleAtXPath(string xpath, params XPathVariable[] vars)
{
return _query == null
@@ -119,6 +127,14 @@ namespace Umbraco.Web
: _query.Media(id);
}
+ public IPublishedContent Media(Udi id)
+ {
+ if (!(id is GuidUdi udi)) return null;
+ return _query == null
+ ? ItemById(udi.Guid, _mediaCache)
+ : _query.Media(udi.Guid);
+ }
+
public IEnumerable Media(IEnumerable ids)
{
return _query == null
diff --git a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs
index 6d186cb314..0e6967daf7 100644
--- a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs
+++ b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs
@@ -74,6 +74,7 @@ namespace Umbraco.Web.Routing
// test for collisions
var uri = new Uri(url.TrimEnd('/'), UriKind.RelativeOrAbsolute);
if (uri.IsAbsoluteUri == false) uri = uri.MakeAbsolute(UmbracoContext.Current.CleanedUmbracoUrl);
+ uri = UriUtility.UriToUmbraco(uri);
var r = Core.Composing.Current.Container.GetInstance(); // fixme inject or ?
var pcr = r.CreateRequest(UmbracoContext.Current, uri);
r.TryRouteRequest(pcr);
diff --git a/src/Umbraco.Web/Scheduling/HealthCheckNotifier.cs b/src/Umbraco.Web/Scheduling/HealthCheckNotifier.cs
new file mode 100644
index 0000000000..61296a37bd
--- /dev/null
+++ b/src/Umbraco.Web/Scheduling/HealthCheckNotifier.cs
@@ -0,0 +1,83 @@
+using System.Configuration;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using Umbraco.Core;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.HealthChecks;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Sync;
+using Umbraco.Web.HealthCheck;
+
+namespace Umbraco.Web.Scheduling
+{
+ internal class HealthCheckNotifier : RecurringTaskBase
+ {
+ private readonly ApplicationContext _appContext;
+ private readonly IHealthCheckResolver _healthCheckResolver;
+
+ public HealthCheckNotifier(IBackgroundTaskRunner runner, int delayMilliseconds, int periodMilliseconds,
+ ApplicationContext appContext)
+ : base(runner, delayMilliseconds, periodMilliseconds)
+ {
+ _appContext = appContext;
+ _healthCheckResolver = HealthCheckResolver.Current;
+ }
+
+ public override async Task PerformRunAsync(CancellationToken token)
+ {
+ if (_appContext == null) return true; // repeat...
+
+ switch (_appContext.GetCurrentServerRole())
+ {
+ case ServerRole.Slave:
+ LogHelper.Debug("Does not run on slave servers.");
+ return true; // DO repeat, server role can change
+ case ServerRole.Unknown:
+ LogHelper.Debug("Does not run on servers with unknown role.");
+ return true; // DO repeat, server role can change
+ }
+
+ // ensure we do not run if not main domain, but do NOT lock it
+ if (_appContext.MainDom.IsMainDom == false)
+ {
+ LogHelper.Debug("Does not run if not MainDom.");
+ return false; // do NOT repeat, going down
+ }
+
+ using (_appContext.ProfilingLogger.DebugDuration("Health checks executing", "Health checks complete"))
+ {
+ var healthCheckConfig = UmbracoConfig.For.HealthCheck();
+
+ // Don't notify for any checks that are disabled, nor for any disabled
+ // just for notifications
+ var disabledCheckIds = healthCheckConfig.NotificationSettings.DisabledChecks
+ .Select(x => x.Id)
+ .Union(healthCheckConfig.DisabledChecks
+ .Select(x => x.Id))
+ .Distinct()
+ .ToArray();
+
+ var checks = _healthCheckResolver.HealthChecks
+ .Where(x => disabledCheckIds.Contains(x.Id) == false);
+
+ var results = new HealthCheckResults(checks);
+ results.LogResults();
+
+ // Send using registered notification methods
+ var registeredNotificationMethods = HealthCheckNotificationMethodResolver.Current.NotificationMethods;
+ foreach (var notificationMethod in registeredNotificationMethods)
+ {
+ await notificationMethod.SendAsync(results);
+ }
+ }
+
+ return true; // repeat
+ }
+
+ public override bool IsAsync
+ {
+ get { return true; }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
index 4f2a54b6f9..8600e947be 100644
--- a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
+++ b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
@@ -1,13 +1,19 @@
using System;
-using System.Net.Http;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using System.Web;
+using System.Web.Hosting;
+using umbraco;
using Umbraco.Core;
+using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Scoping;
+using Umbraco.Core.Publishing;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
-using Umbraco.Web.Mvc;
+using Umbraco.Web.Routing;
+using Umbraco.Web.Security;
namespace Umbraco.Web.Scheduling
{
@@ -49,64 +55,38 @@ namespace Umbraco.Web.Scheduling
return false; // do NOT repeat, going down
}
- string umbracoAppUrl;
+ UmbracoContext tempContext = null;
try
{
- umbracoAppUrl = _runtime.ApplicationUrl.ToString();
- if (umbracoAppUrl.IsNullOrWhiteSpace())
+ // DO not run publishing if content is re-loading
+ if (content.Instance.isInitializing == false)
{
+ //TODO: We should remove this in v8, this is a backwards compat hack
+ // see notes in CacheRefresherEventHandler
+ // because notifications will not be sent if there is no UmbracoContext
+ // see NotificationServiceExtensions
+ var httpContext = new HttpContextWrapper(new HttpContext(new SimpleWorkerRequest("temp.aspx", "", new StringWriter())));
+ tempContext = UmbracoContext.EnsureContext(
+ httpContext,
+ _appContext,
+ new WebSecurity(httpContext, _appContext),
+ _settings,
+ UrlProviderResolver.Current.Providers,
+ true);
+
+ var publisher = new ScheduledPublisher(_appContext.Services.ContentService);
+ var count = publisher.CheckPendingAndProcess();
_logger.Warn("No url for service (yet), skip.");
- return true; // repeat
}
}
catch (Exception e)
{
_logger.Error("Could not acquire application url", e);
- return true; // repeat
}
-
- var url = umbracoAppUrl + "/RestServices/ScheduledPublish/Index";
-
- using (_proflog.DebugDuration($"Scheduled publishing executing at {url}", "Scheduled publishing complete"))
+ finally
{
- try
- {
- using (var wc = new HttpClient())
- {
- var request = new HttpRequestMessage(HttpMethod.Post, url)
- {
- Content = new StringContent(string.Empty)
- };
-
- // running on a background task, requires its own (safe) scope
- // (GetAuthenticationHeaderValue uses UserService to load the current user, hence requires a database)
- // (might not need a scope but we don't know really)
- using (var scope = _scopeProvider.CreateScope())
- {
- //pass custom the authorization header
- request.Headers.Authorization = AdminTokenAuthorizeAttribute.GetAuthenticationHeaderValue(_userService);
- scope.Complete();
- }
-
- var result = await wc.SendAsync(request, token);
- var content = await result.Content.ReadAsStringAsync();
-
- if (result.IsSuccessStatusCode)
- {
- _logger.Debug($"Request successfully sent to url = \"{url}\".");
- }
- else
- {
- var msg = $"Request failed with status code \"{result.StatusCode}\". Request content = \"{content}\".";
- var ex = new HttpRequestException(msg);
- _logger.Error(msg, ex);
- }
- }
- }
- catch (Exception e)
- {
- _logger.Error($"Failed (at \"{umbracoAppUrl}\").", e);
- }
+ if (tempContext != null)
+ tempContext.Dispose(); // nulls the ThreadStatic context
}
return true; // repeat
diff --git a/src/Umbraco.Web/Search/SearchableApplicationTree.cs b/src/Umbraco.Web/Search/SearchableApplicationTree.cs
new file mode 100644
index 0000000000..ec9cbf914f
--- /dev/null
+++ b/src/Umbraco.Web/Search/SearchableApplicationTree.cs
@@ -0,0 +1,18 @@
+using Umbraco.Web.Trees;
+
+namespace Umbraco.Web.Search
+{
+ public class SearchableApplicationTree
+ {
+ public SearchableApplicationTree(string appAlias, string treeAlias, ISearchableTree searchableTree)
+ {
+ AppAlias = appAlias;
+ TreeAlias = treeAlias;
+ SearchableTree = searchableTree;
+ }
+
+ public string AppAlias { get; }
+ public string TreeAlias { get; }
+ public ISearchableTree SearchableTree { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Search/SearchableTreeAttribute.cs b/src/Umbraco.Web/Search/SearchableTreeAttribute.cs
new file mode 100644
index 0000000000..15263165f6
--- /dev/null
+++ b/src/Umbraco.Web/Search/SearchableTreeAttribute.cs
@@ -0,0 +1,36 @@
+using System;
+using Umbraco.Core.Exceptions;
+
+namespace Umbraco.Web.Search
+{
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class SearchableTreeAttribute : Attribute
+ {
+ ///
+ /// This constructor defines both the angular service and method name to use
+ ///
+ ///
+ ///
+ public SearchableTreeAttribute(string serviceName, string methodName)
+ {
+ if (string.IsNullOrWhiteSpace(serviceName)) throw new ArgumentNullOrEmptyException(nameof(serviceName));
+ if (string.IsNullOrWhiteSpace(methodName)) throw new ArgumentNullOrEmptyException(nameof(methodName));
+ MethodName = methodName;
+ ServiceName = serviceName;
+ }
+
+ ///
+ /// This constructor will assume that the method name equals `format(searchResult, appAlias, treeAlias)`
+ ///
+ ///
+ public SearchableTreeAttribute(string serviceName)
+ {
+ if (string.IsNullOrWhiteSpace(serviceName)) throw new ArgumentNullOrEmptyException(nameof(serviceName));
+ MethodName = "";
+ ServiceName = serviceName;
+ }
+
+ public string MethodName { get; }
+ public string ServiceName { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Search/SearchableTreeCollection.cs b/src/Umbraco.Web/Search/SearchableTreeCollection.cs
new file mode 100644
index 0000000000..42a4585f00
--- /dev/null
+++ b/src/Umbraco.Web/Search/SearchableTreeCollection.cs
@@ -0,0 +1,44 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Services;
+using Umbraco.Web.Trees;
+
+namespace Umbraco.Web.Search
+{
+ internal class SearchableTreeCollection : BuilderCollectionBase
+ {
+ private readonly Dictionary _dictionary;
+
+ public SearchableTreeCollection(IEnumerable items, IApplicationTreeService treeService)
+ : base(items)
+ {
+ _dictionary = CreateDictionary(treeService);
+ }
+
+ private Dictionary CreateDictionary(IApplicationTreeService treeService)
+ {
+ var appTrees = treeService.GetAll().ToArray();
+ var dictionary = new Dictionary();
+ var searchableTrees = this.ToArray();
+ foreach (var searchableTree in searchableTrees)
+ {
+ var found = appTrees.FirstOrDefault(x => x.Alias == searchableTree.TreeAlias);
+ if (found != null)
+ {
+ dictionary[searchableTree.TreeAlias] = new SearchableApplicationTree(found.ApplicationAlias, found.Alias, searchableTree);
+ }
+ }
+ return dictionary;
+ }
+
+ // fixme - oh why?!
+ public IReadOnlyDictionary AsReadOnlyDictionary()
+ {
+ return new ReadOnlyDictionary(_dictionary);
+ }
+
+ public SearchableApplicationTree this[string key] => _dictionary[key];
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs b/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs
new file mode 100644
index 0000000000..ae83cc5eab
--- /dev/null
+++ b/src/Umbraco.Web/Search/SearchableTreeCollectionBuilder.cs
@@ -0,0 +1,25 @@
+using LightInject;
+using Umbraco.Core.Composing;
+using Umbraco.Core.Services;
+using Umbraco.Web.Trees;
+
+namespace Umbraco.Web.Search
+{
+ internal class SearchableTreeCollectionBuilder : LazyCollectionBuilderBase
+ {
+ private readonly IApplicationTreeService _treeService;
+
+ public SearchableTreeCollectionBuilder(IServiceContainer container, IApplicationTreeService treeService)
+ : base(container)
+ {
+ _treeService = treeService;
+ }
+
+ protected override SearchableTreeCollectionBuilder This => this;
+
+ public override SearchableTreeCollection CreateCollection()
+ {
+ return new SearchableTreeCollection(CreateItems(), _treeService);
+ }
+ }
+}
diff --git a/src/Umbraco.Web/Search/SearchableTreeResolver.cs b/src/Umbraco.Web/Search/SearchableTreeResolver.cs
new file mode 100644
index 0000000000..4831595072
--- /dev/null
+++ b/src/Umbraco.Web/Search/SearchableTreeResolver.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Linq;
+using Umbraco.Core;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Models;
+using Umbraco.Core.ObjectResolution;
+using Umbraco.Core.Services;
+using Umbraco.Web.Editors;
+using Umbraco.Web.Trees;
+
+namespace Umbraco.Web.Search
+{
+ ///
+ /// A resolver to return the collection of searchable trees
+ ///
+ ///
+ /// This collection has a request scoped lifetime therefore any instance of ISearchableTree needs to support being a request scoped lifetime
+ ///
+ public class SearchableTreeResolver : LazyManyObjectsResolverBase
+ {
+ private readonly IApplicationTreeService _treeService;
+
+ public SearchableTreeResolver(IServiceProvider serviceProvider, ILogger logger, IApplicationTreeService treeService, Func> searchableTrees)
+ : base(serviceProvider, logger, searchableTrees, ObjectLifetimeScope.HttpRequest)
+ {
+ _treeService = treeService;
+ }
+
+ ///
+ /// Returns the a dictionary of tree alias with it's affiliated
+ ///
+ public IReadOnlyDictionary GetSearchableTrees()
+ {
+ var appTrees = _treeService.GetAll().ToArray();
+ var collection = new SearchableTreeCollection();
+ var searchableTrees = Values.ToArray();
+ foreach (var searchableTree in searchableTrees)
+ {
+ var found = appTrees.FirstOrDefault(x => x.Alias == searchableTree.TreeAlias);
+ if (found != null)
+ {
+ collection.Add(new SearchableApplicationTree(found.ApplicationAlias, found.Alias, searchableTree));
+ }
+ }
+ return collection.AsReadOnlyDictionary();
+ }
+ }
+}
diff --git a/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs
new file mode 100644
index 0000000000..0dac79590f
--- /dev/null
+++ b/src/Umbraco.Web/Search/UmbracoTreeSearcher.cs
@@ -0,0 +1,335 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using AutoMapper;
+using Examine;
+using Umbraco.Core;
+using Umbraco.Core.Models;
+using Umbraco.Core.Services;
+using Umbraco.Web.Models.ContentEditing;
+
+namespace Umbraco.Web.Search
+{
+ internal class UmbracoTreeSearcher
+ {
+ ///
+ /// Searches for results based on the entity type
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// A starting point for the search, generally a node id, but for members this is a member type alias
+ ///
+ ///
+ ///
+ ///
+ public IEnumerable ExamineSearch(
+ UmbracoHelper umbracoHelper,
+ string query,
+ UmbracoEntityTypes entityType,
+ int pageSize,
+ long pageIndex, out long totalFound, string searchFrom = null)
+ {
+ var sb = new StringBuilder();
+
+ string type;
+ var searcher = Constants.Examine.InternalSearcher;
+ var fields = new[] { "id", "__NodeId" };
+
+ var umbracoContext = umbracoHelper.UmbracoContext;
+ var appContext = umbracoContext.Application;
+
+ //TODO: WE should really just allow passing in a lucene raw query
+ switch (entityType)
+ {
+ case UmbracoEntityTypes.Member:
+ searcher = Constants.Examine.InternalMemberSearcher;
+ type = "member";
+ fields = new[] { "id", "__NodeId", "email", "loginName" };
+ if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId && searchFrom.Trim() != "-1")
+ {
+ sb.Append("+__NodeTypeAlias:");
+ sb.Append(searchFrom);
+ sb.Append(" ");
+ }
+ break;
+ case UmbracoEntityTypes.Media:
+ type = "media";
+ var allMediaStartNodes = umbracoContext.Security.CurrentUser.CalculateMediaStartNodeIds(appContext.Services.EntityService);
+ AppendPath(sb, UmbracoObjectTypes.Media, allMediaStartNodes, searchFrom, appContext.Services.EntityService);
+ break;
+ case UmbracoEntityTypes.Document:
+ type = "content";
+ var allContentStartNodes = umbracoContext.Security.CurrentUser.CalculateContentStartNodeIds(appContext.Services.EntityService);
+ AppendPath(sb, UmbracoObjectTypes.Document, allContentStartNodes, searchFrom, appContext.Services.EntityService);
+ break;
+ default:
+ throw new NotSupportedException("The " + typeof(UmbracoTreeSearcher) + " currently does not support searching against object type " + entityType);
+ }
+
+ var internalSearcher = ExamineManager.Instance.SearchProviderCollection[searcher];
+
+ //build a lucene query:
+ // the __nodeName will be boosted 10x without wildcards
+ // then __nodeName will be matched normally with wildcards
+ // the rest will be normal without wildcards
+
+
+ //check if text is surrounded by single or double quotes, if so, then exact match
+ var surroundedByQuotes = Regex.IsMatch(query, "^\".*?\"$")
+ || Regex.IsMatch(query, "^\'.*?\'$");
+
+ if (surroundedByQuotes)
+ {
+ //strip quotes, escape string, the replace again
+ query = query.Trim(new[] { '\"', '\'' });
+
+ query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
+
+ //nothing to search
+ if (searchFrom.IsNullOrWhiteSpace() && query.IsNullOrWhiteSpace())
+ {
+ totalFound = 0;
+ return new List();
+ }
+
+ //update the query with the query term
+ if (query.IsNullOrWhiteSpace() == false)
+ {
+ //add back the surrounding quotes
+ query = string.Format("{0}{1}{0}", "\"", query);
+
+ //node name exactly boost x 10
+ sb.Append("+(__nodeName: (");
+ sb.Append(query.ToLower());
+ sb.Append(")^10.0 ");
+
+ foreach (var f in fields)
+ {
+ //additional fields normally
+ sb.Append(f);
+ sb.Append(": (");
+ sb.Append(query);
+ sb.Append(") ");
+ }
+
+ sb.Append(") ");
+ }
+ }
+ else
+ {
+ var trimmed = query.Trim(new[] { '\"', '\'' });
+
+ //nothing to search
+ if (searchFrom.IsNullOrWhiteSpace() && trimmed.IsNullOrWhiteSpace())
+ {
+ totalFound = 0;
+ return new List();
+ }
+
+ //update the query with the query term
+ if (trimmed.IsNullOrWhiteSpace() == false)
+ {
+ query = Lucene.Net.QueryParsers.QueryParser.Escape(query);
+
+ var querywords = query.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+
+ //node name exactly boost x 10
+ sb.Append("+(__nodeName:");
+ sb.Append("\"");
+ sb.Append(query.ToLower());
+ sb.Append("\"");
+ sb.Append("^10.0 ");
+
+ //node name normally with wildcards
+ sb.Append(" __nodeName:");
+ sb.Append("(");
+ foreach (var w in querywords)
+ {
+ sb.Append(w.ToLower());
+ sb.Append("* ");
+ }
+ sb.Append(") ");
+
+
+ foreach (var f in fields)
+ {
+ //additional fields normally
+ sb.Append(f);
+ sb.Append(":");
+ sb.Append("(");
+ foreach (var w in querywords)
+ {
+ sb.Append(w.ToLower());
+ sb.Append("* ");
+ }
+ sb.Append(")");
+ sb.Append(" ");
+ }
+
+ sb.Append(") ");
+ }
+ }
+
+ //must match index type
+ sb.Append("+__IndexType:");
+ sb.Append(type);
+
+ var raw = internalSearcher.CreateSearchCriteria().RawQuery(sb.ToString());
+
+ var result = internalSearcher
+ //only return the number of items specified to read up to the amount of records to fill from 0 -> the number of items on the page requested
+ .Search(raw, Convert.ToInt32(pageSize * (pageIndex + 1)));
+
+ totalFound = result.TotalItemCount;
+
+ var pagedResult = result.Skip(Convert.ToInt32(pageIndex));
+
+ switch (entityType)
+ {
+ case UmbracoEntityTypes.Member:
+ return MemberFromSearchResults(pagedResult.ToArray());
+ case UmbracoEntityTypes.Media:
+ return MediaFromSearchResults(pagedResult);
+ case UmbracoEntityTypes.Document:
+ return ContentFromSearchResults(umbracoHelper, pagedResult);
+ default:
+ throw new NotSupportedException("The " + typeof(UmbracoTreeSearcher) + " currently does not support searching against object type " + entityType);
+ }
+ }
+
+ private void AppendPath(StringBuilder sb, UmbracoObjectTypes objectType, int[] startNodeIds, string searchFrom, IEntityService entityService)
+ {
+ if (sb == null) throw new ArgumentNullException("sb");
+ if (entityService == null) throw new ArgumentNullException("entityService");
+
+ int searchFromId;
+ var entityPath = int.TryParse(searchFrom, out searchFromId) && searchFromId > 0
+ ? entityService.GetAllPaths(objectType, searchFromId).FirstOrDefault()
+ : null;
+ if (entityPath != null)
+ {
+ // find... only what's underneath
+ sb.Append("+__Path:");
+ AppendPath(sb, entityPath.Path, false);
+ sb.Append(" ");
+ }
+ else if (startNodeIds.Length == 0)
+ {
+ // make sure we don't find anything
+ sb.Append("+__Path:none ");
+ }
+ else if (startNodeIds.Contains(-1) == false) // -1 = no restriction
+ {
+ var entityPaths = entityService.GetAllPaths(objectType, startNodeIds);
+
+ // for each start node, find the start node, and what's underneath
+ // +__Path:(-1*,1234 -1*,1234,* -1*,5678 -1*,5678,* ...)
+ sb.Append("+__Path:(");
+ var first = true;
+ foreach (var ep in entityPaths)
+ {
+ if (first)
+ first = false;
+ else
+ sb.Append(" ");
+ AppendPath(sb, ep.Path, true);
+ }
+ sb.Append(") ");
+ }
+ }
+
+ private void AppendPath(StringBuilder sb, string path, bool includeThisNode)
+ {
+ path = path.Replace("-", "\\-").Replace(",", "\\,");
+ if (includeThisNode)
+ {
+ sb.Append(path);
+ sb.Append(" ");
+ }
+ sb.Append(path);
+ sb.Append("\\,*");
+ }
+
+ ///
+ /// Returns a collection of entities for media based on search results
+ ///
+ ///
+ ///
+ private IEnumerable MemberFromSearchResults(SearchResult[] results)
+ {
+ var mapped = Mapper.Map>(results).ToArray();
+ //add additional data
+ foreach (var m in mapped)
+ {
+ //if no icon could be mapped, it will be set to document, so change it to picture
+ if (m.Icon == "icon-document")
+ {
+ m.Icon = "icon-user";
+ }
+
+ var searchResult = results.First(x => x.Id.ToInvariantString() == m.Id.ToString());
+ if (searchResult.Fields.ContainsKey("email") && searchResult.Fields["email"] != null)
+ {
+ m.AdditionalData["Email"] = results.First(x => x.Id.ToInvariantString() == m.Id.ToString()).Fields["email"];
+ }
+ if (searchResult.Fields.ContainsKey("__key") && searchResult.Fields["__key"] != null)
+ {
+ Guid key;
+ if (Guid.TryParse(searchResult.Fields["__key"], out key))
+ {
+ m.Key = key;
+ }
+ }
+ }
+ return mapped;
+ }
+
+ ///
+ /// Returns a collection of entities for media based on search results
+ ///
+ ///
+ ///
+ private IEnumerable MediaFromSearchResults(IEnumerable results)
+ {
+ var mapped = Mapper.Map>(results).ToArray();
+ //add additional data
+ foreach (var m in mapped)
+ {
+ //if no icon could be mapped, it will be set to document, so change it to picture
+ if (m.Icon == "icon-document")
+ {
+ m.Icon = "icon-picture";
+ }
+ }
+ return mapped;
+ }
+
+ ///
+ /// Returns a collection of entities for content based on search results
+ ///
+ ///
+ ///
+ ///
+ private IEnumerable ContentFromSearchResults(UmbracoHelper umbracoHelper, IEnumerable results)
+ {
+ var mapped = Mapper.Map>(results).ToArray();
+ //add additional data
+ foreach (var m in mapped)
+ {
+ var intId = m.Id.TryConvertTo();
+ if (intId.Success)
+ {
+ m.AdditionalData["Url"] = umbracoHelper.NiceUrl(intId.Result);
+ }
+ }
+ return mapped;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Trees/ISearchableTree.cs b/src/Umbraco.Web/Trees/ISearchableTree.cs
index 4851d9bed5..93917c8270 100644
--- a/src/Umbraco.Web/Trees/ISearchableTree.cs
+++ b/src/Umbraco.Web/Trees/ISearchableTree.cs
@@ -5,6 +5,22 @@ namespace Umbraco.Web.Trees
{
public interface ISearchableTree
{
- IEnumerable Search(string searchText);
+ ///
+ /// The alias of the tree that the belongs to
+ ///
+ string TreeAlias { get; }
+
+ ///
+ /// Searches for results based on the entity type
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// A starting point for the search, generally a node id, but for members this is a member type alias
+ ///
+ ///
+ IEnumerable Search(string query, int pageSize, long pageIndex, out long totalFound, string searchFrom = null);
}
}
diff --git a/src/Umbraco.Web/TypeLoaderExtensions.cs b/src/Umbraco.Web/TypeLoaderExtensions.cs
new file mode 100644
index 0000000000..2c7bc430ce
--- /dev/null
+++ b/src/Umbraco.Web/TypeLoaderExtensions.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using Umbraco.Core.Media;
+using Umbraco.Web.Mvc;
+using Umbraco.Web.Trees;
+using Umbraco.Web.WebApi;
+using umbraco.cms.presentation.Trees;
+using Umbraco.Core.Composing;
+using Umbraco.Web._Legacy.Actions;
+
+namespace Umbraco.Web
+{
+ ///
+ /// Extension methods for the PluginTypemgr
+ ///
+ public static class TypeLoaderExtensions
+ {
+ ///
+ /// Returns all available IAction in application
+ ///
+ ///
+ internal static IEnumerable GetActions(this TypeLoader mgr)
+ {
+ return mgr.GetTypes();
+ }
+
+ ///
+ /// Returns all available TreeApiController's in application that are attribute with TreeAttribute
+ ///
+ ///
+ ///
+ internal static IEnumerable GetAttributedTreeControllers(this TypeLoader mgr)
+ {
+ return mgr.GetTypesWithAttribute();
+ }
+
+ internal static IEnumerable GetSurfaceControllers(this TypeLoader mgr)
+ {
+ return mgr.GetTypes();
+ }
+
+ internal static IEnumerable GetUmbracoApiControllers(this TypeLoader mgr)
+ {
+ return mgr.GetTypes();
+ }
+
+ ///
+ /// Returns all available ITrees in application
+ ///
+ ///
+ ///
+ internal static IEnumerable GetTrees(this TypeLoader mgr)
+ {
+ return mgr.GetTypes();
+ }
+
+ ///
+ /// Returns all available ISearchableTrees in application
+ ///
+ ///
+ ///
+ internal static IEnumerable GetSearchableTrees(this TypeLoader mgr)
+ {
+ return mgr.GetTypes();
+ }
+
+ ///
+ /// Returns all classes attributed with XsltExtensionAttribute attribute
+ ///
+ ///
+ ///
+ internal static IEnumerable GetXsltExtensions(this TypeLoader mgr)
+ {
+ return mgr.GetAttributedTypes();
+ }
+
+ ///
+ /// Returns all IThumbnailProvider classes
+ ///
+ ///
+ ///
+ internal static IEnumerable GetThumbnailProviders(this TypeLoader mgr)
+ {
+ return mgr.GetTypes();
+ }
+
+ ///
+ /// Returns all IImageUrlProvider classes
+ ///
+ ///
+ ///
+ internal static IEnumerable GetImageUrlProviders(this TypeLoader mgr)
+ {
+ return mgr.GetTypes();
+ }
+
+ }
+}
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 085d72baa9..23cdb32dd7 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -132,7 +132,14 @@
+
+
+
+
+
+
+
@@ -142,6 +149,7 @@
+
@@ -274,6 +282,13 @@
+
+
+
+
+
+
+
@@ -1144,7 +1159,7 @@
-
+
diff --git a/src/Umbraco.Web/UmbracoContext.cs b/src/Umbraco.Web/UmbracoContext.cs
index f0df622e38..43aed630e9 100644
--- a/src/Umbraco.Web/UmbracoContext.cs
+++ b/src/Umbraco.Web/UmbracoContext.cs
@@ -141,12 +141,12 @@ namespace Umbraco.Web
/// object is instantiated which in the web site is created during the BeginRequest phase.
/// We can then determine complete rendering time from that.
///
- internal DateTime ObjectCreated { get; private set; }
+ internal DateTime ObjectCreated { get; }
///
/// This is used internally for debugging and also used to define anything required to distinguish this request from another.
///
- internal Guid UmbracoRequestId { get; private set; }
+ internal Guid UmbracoRequestId { get; }
///
/// Gets the WebSecurity class
@@ -162,7 +162,7 @@ namespace Umbraco.Web
/// Gets the cleaned up url that is handled by Umbraco.
///
/// That is, lowercase, no trailing slash after path, no .aspx...
- internal Uri CleanedUmbracoUrl { get; private set; }
+ internal Uri CleanedUmbracoUrl { get; }
///
/// Gets the facade.
@@ -253,7 +253,7 @@ namespace Umbraco.Web
if (_previewing.HasValue == false) DetectPreviewMode();
return _previewing.Value;
}
- private set { _previewing = value; }
+ private set => _previewing = value;
}
private string PreviewToken
diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs
index 847b1d707b..a3eaa39abd 100644
--- a/src/Umbraco.Web/UmbracoHelper.cs
+++ b/src/Umbraco.Web/UmbracoHelper.cs
@@ -440,6 +440,17 @@ namespace Umbraco.Web
#region Members
+ public IPublishedContent Member(Udi id)
+ {
+ var guidUdi = id as GuidUdi;
+ return guidUdi == null ? null : Member(guidUdi.Guid);
+ }
+
+ public IPublishedContent Member(Guid id)
+ {
+ return MembershipHelper.GetByProviderKey(id);
+ }
+
public IPublishedContent Member(object id)
{
var asInt = id.TryConvertTo();
@@ -473,12 +484,12 @@ namespace Umbraco.Web
private IPublishedContent ContentForObject(object id)
{
- int intId;
- if (ConvertIdObjectToInt(id, out intId))
+ if (ConvertIdObjectToInt(id, out var intId))
return ContentQuery.Content(intId);
- Guid guidId;
- if (ConvertIdObjectToGuid(id, out guidId))
+ if (ConvertIdObjectToGuid(id, out var guidId))
return ContentQuery.Content(guidId);
+ if (ConvertIdObjectToUdi(id, out var udiId))
+ return ContentQuery.Content(udiId);
return null;
}
@@ -512,6 +523,11 @@ namespace Umbraco.Web
return ContentForObject(id);
}
+ public IPublishedContent Content(Udi id)
+ {
+ return ContentQuery.Content(id);
+ }
+
public IPublishedContent ContentSingleAtXPath(string xpath, params XPathVariable[] vars)
{
return ContentQuery.ContentSingleAtXPath(xpath, vars);
@@ -658,8 +674,7 @@ namespace Umbraco.Web
intIds = null;
foreach (var id in ids)
{
- int intId;
- if (ConvertIdObjectToInt(id, out intId))
+ if (ConvertIdObjectToInt(id, out var intId))
list.Add(intId);
else
return false; // if one of them is not an int, fail
@@ -684,10 +699,39 @@ namespace Umbraco.Web
return true;
}
+ private static bool ConvertIdObjectToUdi(object id, out Udi guidId)
+ {
+ if (id is string s)
+ return Udi.TryParse(s, out guidId);
+ if (id is Udi)
+ {
+ guidId = (Udi) id;
+ return true;
+ }
+ guidId = null;
+ return false;
+ }
+
#endregion
#region Media
+ public IPublishedContent TypedMedia(Udi id)
+ {
+ var guidUdi = id as GuidUdi;
+ return guidUdi == null ? null : Media(guidUdi.Guid);
+ }
+
+ public IPublishedContent Media(Guid id)
+ {
+ //TODO: This is horrible but until the media cache properly supports GUIDs we have no choice here and
+ // currently there won't be any way to add this method correctly to `ITypedPublishedContentQuery` without breaking an interface and adding GUID support for media
+
+ var entityService = Current.Services.EntityService; // fixme inject
+ var mediaAttempt = entityService.GetIdForKey(id, UmbracoObjectTypes.Media);
+ return mediaAttempt.Success ? ContentQuery.Media(mediaAttempt.Result) : null;
+ }
+
///
/// Overloaded method accepting an 'object' type
///
@@ -705,12 +749,12 @@ namespace Umbraco.Web
private IPublishedContent MediaForObject(object id)
{
- int intId;
- if (ConvertIdObjectToInt(id, out intId))
+ if (ConvertIdObjectToInt(id, out var intId))
return ContentQuery.Media(intId);
- //Guid guidId;
- //if (ConvertIdObjectToGuid(id, out guidId))
- // return ContentQuery.Media(guidId);
+ if (ConvertIdObjectToGuid(id, out var guidId))
+ return ContentQuery.Media(guidId);
+ if (ConvertIdObjectToUdi(id, out var udiId))
+ return ContentQuery.Media(udiId);
return null;
}
@@ -853,11 +897,24 @@ namespace Umbraco.Web
///
/// The text to create a hash from
/// Md5 has of the string
+ [Obsolete("Please use the CreateHash method instead. This may be removed in future versions")]
+ [EditorBrowsable(EditorBrowsableState.Never)]
public string CreateMd5Hash(string text)
{
return text.ToMd5();
}
+ ///
+ /// Generates a hash based on the text string passed in. This method will detect the
+ /// security requirements (is FIPS enabled) and return an appropriate hash.
+ ///
+ /// The text to create a hash from
+ /// Hash of the text string
+ public string CreateHash(string text)
+ {
+ return text.GenerateHash();
+ }
+
///
/// Strips all html tags from a given string, all contents of the tags will remain.
///
diff --git a/src/Umbraco.Web/UrlHelperExtensions.cs b/src/Umbraco.Web/UrlHelperExtensions.cs
index 20961a3897..14e25f0819 100644
--- a/src/Umbraco.Web/UrlHelperExtensions.cs
+++ b/src/Umbraco.Web/UrlHelperExtensions.cs
@@ -178,22 +178,14 @@ namespace Umbraco.Web
//make a hash of umbraco and client dependency version
//in case the user bypasses the installer and just bumps the web.config or clientdep config
- var versionHash = new HashCodeCombiner();
-
//if in debug mode, always burst the cache
if (GlobalSettings.DebugMode)
{
- versionHash.AddCaseInsensitiveString(DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture));
- }
- else
- {
- //create a unique hash code of the current umb version and the current cdf version
-
- versionHash.AddCaseInsensitiveString(UmbracoVersion.Current.ToString());
- versionHash.AddCaseInsensitiveString(ClientDependencySettings.Instance.Version.ToString(CultureInfo.InvariantCulture));
+ return DateTime.Now.Ticks.ToString(CultureInfo.InvariantCulture).GenerateHash();
}
- return versionHash.GetCombinedHashCode();
+ var version = UmbracoVersion.GetSemanticVersion().ToSemanticString();
+ return string.Format("{0}.{1}", version, ClientDependencySettings.Instance.Version).GenerateHash();
}
}
}
diff --git a/src/Umbraco.Web/UrlHelperRenderExtensions.cs b/src/Umbraco.Web/UrlHelperRenderExtensions.cs
index 802ef51422..b3c601b90f 100644
--- a/src/Umbraco.Web/UrlHelperRenderExtensions.cs
+++ b/src/Umbraco.Web/UrlHelperRenderExtensions.cs
@@ -345,5 +345,24 @@ namespace Umbraco.Web
{
return url.SurfaceAction(action, typeof (T), additionalRouteVals);
}
+
+ ///
+ /// Generates a Absolute Media Item URL based on the current context
+ ///
+ ///
+ ///
+ ///
+ public static string GetAbsoluteMediaUrl(this UrlHelper urlHelper, IPublishedContent mediaItem)
+ {
+ if (urlHelper == null) throw new ArgumentNullException("urlHelper");
+ if (mediaItem == null) throw new ArgumentNullException("mediaItem");
+
+ if (urlHelper.RequestContext.HttpContext.Request.Url != null)
+ {
+ var requestUrl = urlHelper.RequestContext.HttpContext.Request.Url.GetLeftPart(UriPartial.Authority);
+ return string.Format("{0}{1}", requestUrl, mediaItem.Url);
+ }
+ return null;
+ }
}
-}
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/WebRuntimeComponent.cs b/src/Umbraco.Web/WebRuntimeComponent.cs
index cee9ef0a04..8d8ebccb41 100644
--- a/src/Umbraco.Web/WebRuntimeComponent.cs
+++ b/src/Umbraco.Web/WebRuntimeComponent.cs
@@ -42,6 +42,8 @@ using Umbraco.Web.UI.JavaScript;
using Umbraco.Web.WebApi;
using Umbraco.Web._Legacy.Actions;
using Umbraco.Examine;
+using Umbraco.Web.Search;
+using Umbraco.Web.Trees;
using Current = Umbraco.Web.Composing.Current;
namespace Umbraco.Web
@@ -55,7 +57,7 @@ namespace Umbraco.Web
composition.Container.RegisterFrom();
- var pluginManager = composition.Container.GetInstance();
+ var typeLoader = composition.Container.GetInstance();
var logger = composition.Container.GetInstance();
var proflog = composition.Container.GetInstance();
@@ -101,26 +103,29 @@ namespace Umbraco.Web
composition.Container.EnableMvc(); // does container.EnablePerWebRequestScope()
composition.Container.ScopeManagerProvider = smp; // reverts - we will do it last (in WebRuntime)
- composition.Container.RegisterMvcControllers(pluginManager, GetType().Assembly);
+ composition.Container.RegisterMvcControllers(typeLoader, GetType().Assembly);
composition.Container.EnableWebApi(GlobalConfiguration.Configuration);
- composition.Container.RegisterApiControllers(pluginManager, GetType().Assembly);
+ composition.Container.RegisterApiControllers(typeLoader, GetType().Assembly);
XsltExtensionCollectionBuilder.Register(composition.Container)
- .AddExtensionObjectProducer(() => pluginManager.ResolveXsltExtensions());
+ .AddExtensionObjectProducer(() => typeLoader.GetXsltExtensions());
+
+ composition.Container.RegisterCollectionBuilder()
+ .Add(() => typeLoader.GetTypes()); // fixme which searchable trees?!
composition.Container.RegisterCollectionBuilder()
- .Add(() => pluginManager.GetTypes());
+ .Add(() => typeLoader.GetTypes());
// set the default RenderMvcController
Current.DefaultRenderMvcControllerType = typeof(RenderMvcController); // fixme WRONG!
ActionCollectionBuilder.Register(composition.Container)
- .SetProducer(() => pluginManager.ResolveActions());
+ .SetProducer(() => typeLoader.GetActions());
- var surfaceControllerTypes = new SurfaceControllerTypeCollection(pluginManager.ResolveSurfaceControllers());
+ var surfaceControllerTypes = new SurfaceControllerTypeCollection(typeLoader.GetSurfaceControllers());
composition.Container.RegisterInstance(surfaceControllerTypes);
- var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(pluginManager.ResolveUmbracoApiControllers());
+ var umbracoApiControllerTypes = new UmbracoApiControllerTypeCollection(typeLoader.GetUmbracoApiControllers());
composition.Container.RegisterInstance(umbracoApiControllerTypes);
// both TinyMceValueConverter (in Core) and RteMacroRenderingValueConverter (in Web) will be
@@ -160,16 +165,19 @@ namespace Umbraco.Web
composition.Container.RegisterSingleton();
composition.Container.RegisterCollectionBuilder()
- .Add(pluginManager.ResolveThumbnailProviders());
+ .Add(typeLoader.GetThumbnailProviders());
composition.Container.RegisterCollectionBuilder()
- .Append(pluginManager.ResolveImageUrlProviders());
+ .Append(typeLoader.GetImageUrlProviders());
composition.Container.RegisterSingleton();
// register *all* checks, except those marked [HideFromTypeFinder] of course
composition.Container.RegisterCollectionBuilder()
- .Add(() => pluginManager.GetTypes());
+ .Add(() => typeLoader.GetTypes());
+
+ composition.Container.RegisterCollectionBuilder()
+ .Add(() => typeLoader.GetTypes());
// auto-register views
composition.Container.RegisterAuto(typeof(UmbracoViewPage<>));
diff --git a/src/Umbraco.Web/WebServices/ScheduledPublishController.cs b/src/Umbraco.Web/WebServices/ScheduledPublishController.cs
deleted file mode 100644
index 01e044dd4f..0000000000
--- a/src/Umbraco.Web/WebServices/ScheduledPublishController.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-using System;
-using System.Web.Mvc;
-using Umbraco.Core;
-using Umbraco.Core.Logging;
-using Umbraco.Core.Services;
-using Umbraco.Web.Mvc;
-
-namespace Umbraco.Web.WebServices
-{
- ///
- /// Represents a REST controller used for running the scheduled publishing.
- ///
- [AdminTokenAuthorize]
- public class ScheduledPublishController : UmbracoController
- {
- private static bool _isPublishingRunning;
- private static readonly object Locker = new object();
- private readonly IRuntimeState _runtime;
-
- public ScheduledPublishController(IRuntimeState runtime)
- {
- _runtime = runtime;
- }
-
- [HttpPost]
- public JsonResult Index()
- {
- lock (Locker)
- {
- if (_isPublishingRunning)
- {
- Logger.Debug(() => "Already executing, skipping.");
- return null;
- }
-
- _isPublishingRunning = true;
- }
-
- try
- {
- // ensure we have everything we need
- if (_runtime.Level != RuntimeLevel.Run) return null;
- Services.ContentService.WithResult().PerformScheduledPublish();
- return Json(new { success = true });
- }
- catch (Exception ee)
- {
- var errorMessage = "Error executing scheduled task";
- if (HttpContext != null && HttpContext.Request != null)
- {
- if (HttpContext.Request.Url != null)
- errorMessage = string.Format("{0} | Request to {1}", errorMessage, HttpContext.Request.Url);
- if (HttpContext.Request.UserHostAddress != null)
- errorMessage = string.Format("{0} | Coming from {1}", errorMessage, HttpContext.Request.UserHostAddress);
- if (HttpContext.Request.UrlReferrer != null)
- errorMessage = string.Format("{0} | Referrer {1}", errorMessage, HttpContext.Request.UrlReferrer);
- }
- Logger.Error(errorMessage, ee);
-
- Response.StatusCode = 400;
-
- return Json(new
- {
- success = false,
- message = ee.Message
- });
- }
- finally
- {
- lock (Locker)
- {
- _isPublishingRunning = false;
- }
- }
- }
- }
-}
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/TreeDefinitionCollection.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/TreeDefinitionCollection.cs
index 33e2503aac..0397d603f2 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/TreeDefinitionCollection.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/Trees/TreeDefinitionCollection.cs
@@ -138,7 +138,7 @@ namespace umbraco.cms.presentation.Trees
if (_ensureTrees == false)
{
- var foundITrees = Current.TypeLoader.ResolveTrees();
+ var foundITrees = Current.TypeLoader.GetTrees();
var appTrees = Current.Services.ApplicationTreeService.GetAll().ToList();
var apps = Current.Services.SectionService.GetSections().ToList();