Compare commits
196 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e7f9902f6 | |||
| dcd2630d6b | |||
| b70f543790 | |||
| 24c1c15b66 | |||
| 4a0cd7228b | |||
| edfe212227 | |||
| e3bc98a155 | |||
| f85532f15e | |||
| b04d71ca5f | |||
| ab4de382f3 | |||
| a293c633fc | |||
| 507e3ece98 | |||
| b77826fd3d | |||
| 4c7358d63b | |||
| 4814612102 | |||
| 6dae4396bb | |||
| dd5560f00b | |||
| b56575fc50 | |||
| b06d30c0f9 | |||
| 9c50e1c48d | |||
| 0688835ac0 | |||
| 353b8f21cd | |||
| 30a0d553d5 | |||
| d0fbc362b2 | |||
| 39c534ef54 | |||
| 7f86166abf | |||
| 838e86469a | |||
| 24b147e2a6 | |||
| 11342ff1df | |||
| bf20af9345 | |||
| c69774e3f2 | |||
| 7de8f5a59a | |||
| 6795afd5c2 | |||
| 9411a22a0d | |||
| 461ce64feb | |||
| 53c251feb5 | |||
| c5a55b17e6 | |||
| fd577afe2c | |||
| f46ef0b006 | |||
| 909e3788ea | |||
| 09a92ef6ce | |||
| 7d9c2bcce9 | |||
| 529ae961ff | |||
| 04f64cd804 | |||
| dc937ec942 | |||
| cefd9e7323 | |||
| 315690e758 | |||
| fb8c519f71 | |||
| 80f172e3fb | |||
| 5eced19816 | |||
| 5df4d3509d | |||
| 4bd263e7bc | |||
| b094bfad29 | |||
| e333f6c628 | |||
| 916bc6badb | |||
| 76ee23b933 | |||
| 2a0cc71d06 | |||
| a2e6da2491 | |||
| ba7d8b0955 | |||
| 7288bcf679 | |||
| ca57b9c5e6 | |||
| 62ce7f6132 | |||
| b1f2c5d93a | |||
| 1ec07aa205 | |||
| 13055ad1f2 | |||
| d5447106a6 | |||
| c5d874464a | |||
| 1cc3b39601 | |||
| c5f4793d11 | |||
| 4175c0530f | |||
| cf97926f26 | |||
| 4b08c3a5c3 | |||
| fbda4fc8d1 | |||
| 312b994537 | |||
| dd1bfe9cbf | |||
| de17b69564 | |||
| 7f44f4a030 | |||
| 422219ab21 | |||
| 9986a3c2c2 | |||
| ce81416368 | |||
| 04e04ae47a | |||
| 0f6e7d26c9 | |||
| 51ceba6fea | |||
| 5dde2efe0d | |||
| fe2b86b681 | |||
| 368fec4ac1 | |||
| 9016147118 | |||
| bee75803f7 | |||
| 7b3f7f4ad4 | |||
| f6c25f29c0 | |||
| 6de3b920eb | |||
| 76dc311586 | |||
| 581f15b172 | |||
| daf01fb0fa | |||
| 588640037c | |||
| 7b106caf95 | |||
| 828a94bc4f | |||
| efd1ea5b86 | |||
| 376d93de61 | |||
| 33d7598d3c | |||
| 6a74967a49 | |||
| 79351efd36 | |||
| 70c9da93e9 | |||
| 521acc0618 | |||
| 95c3a7386d | |||
| 448a99d5a4 | |||
| 83f705e19f | |||
| 880ae5cb95 | |||
| 476773fce5 | |||
| 953355cddd | |||
| e0801cd05a | |||
| b363a1711a | |||
| 45fca02dd1 | |||
| b426f92e4f | |||
| 3e3372752a | |||
| 4104ffc699 | |||
| f63aa2e2ed | |||
| 57553a5956 | |||
| d2d43255aa | |||
| 9ad767a285 | |||
| b39e218d51 | |||
| 22ff362521 | |||
| 3bbeb6670b | |||
| 581b1b6fbf | |||
| 4053c52dfb | |||
| 6a80cc5708 | |||
| 01ba781e75 | |||
| b477ed726d | |||
| 147d6aa638 | |||
| efca0a904d | |||
| 7e25501ac5 | |||
| 4b581a2182 | |||
| 581eac5369 | |||
| c941ff093c | |||
| 60f9490892 | |||
| 7c864fe2e9 | |||
| 8a52865d22 | |||
| 78e5d6d3ad | |||
| 33cf983cae | |||
| 3ce6eb09aa | |||
| 963015cf4a | |||
| cc35af4eab | |||
| 7c4eb71f07 | |||
| 9282312305 | |||
| fc46569cd9 | |||
| 30f42f4ea8 | |||
| fa777c46b1 | |||
| a01f69807c | |||
| e12498ccae | |||
| 4fc51e4a8b | |||
| 4c3e66e58d | |||
| 17abd53b1b | |||
| 202a3e10b5 | |||
| 925f64c79d | |||
| c28e5f4d55 | |||
| 439c460220 | |||
| ae1702c62a | |||
| 1ed29fb8bb | |||
| c9ea1a5504 | |||
| 10da318989 | |||
| 74e3308017 | |||
| 349d89e4d7 | |||
| 201ac076c3 | |||
| bc2e9936d8 | |||
| e8e9f5ca49 | |||
| b938685db0 | |||
| 39498ad362 | |||
| 92b6e276bf | |||
| a239e92bc0 | |||
| e0025db56d | |||
| 1238c10b3d | |||
| 35177eea9f | |||
| 7cd632302b | |||
| 7142222234 | |||
| fd35d89949 | |||
| 1b3fc9fb21 | |||
| 2e98651d62 | |||
| 704e981284 | |||
| 0f17a27d86 | |||
| 9c24dc71a4 | |||
| 606abd8ac7 | |||
| 65db5396cf | |||
| 32d5a0a57c | |||
| 7367c8ef67 | |||
| bfb5dd91cc | |||
| be1172d604 | |||
| 7cf8cd3518 | |||
| 4cab1c89b4 | |||
| 88fd5a9623 | |||
| 361ef2a475 | |||
| d382fcc919 | |||
| aac8451627 | |||
| c96c09f42f | |||
| 50f8f18503 | |||
| 9001cd8a6f | |||
| 1279fd234f |
@@ -1,4 +1,4 @@
|
||||
[](https://ci.appveyor.com/project/Umbraco/umbraco-cms-hs8dx/branch/dev-v7)
|
||||
[](https://ci.appveyor.com/project/Umbraco/umbraco-cms-b2cri/branch/dev-v7)
|
||||
|
||||
Umbraco CMS
|
||||
===========
|
||||
|
||||
@@ -7,45 +7,39 @@ function Build-UmbracoDocs
|
||||
$src = "$($uenv.SolutionRoot)\src"
|
||||
$out = "$($uenv.SolutionRoot)\build.out"
|
||||
$tmp = "$($uenv.SolutionRoot)\build.tmp"
|
||||
|
||||
|
||||
$buildTemp = "$PSScriptRoot\temp"
|
||||
$cache = 2
|
||||
|
||||
|
||||
Prepare-Build -keep $uenv
|
||||
|
||||
################ Do the UI docs
|
||||
# get a temp clean node env (will restore)
|
||||
Sandbox-Node $uenv
|
||||
|
||||
Write-Host "Executing gulp docs"
|
||||
|
||||
push-location "$($uenv.SolutionRoot)\src\Umbraco.Web.UI.Client"
|
||||
write "node version is:" > $tmp\belle-docs.log
|
||||
&node -v >> $tmp\belle-docs.log 2>&1
|
||||
write "npm version is:" >> $tmp\belle-docs.log 2>&1
|
||||
&npm -v >> $tmp\belle-docs.log 2>&1
|
||||
write "executing npm install" >> $tmp\belle-docs.log 2>&1
|
||||
&npm install >> $tmp\belle-docs.log 2>&1
|
||||
write "executing bower install" >> $tmp\belle-docs.log 2>&1
|
||||
&npm install -g bower >> $tmp\belle-docs.log 2>&1
|
||||
write "installing gulp" >> $tmp\belle-docs.log 2>&1
|
||||
&npm install -g gulp >> $tmp\belle-docs.log 2>&1
|
||||
write "installing gulp-cli" >> $tmp\belle-docs.log 2>&1
|
||||
&npm install -g gulp-cli --quiet >> $tmp\belle-docs.log 2>&1
|
||||
write "building docs using gulp" >> $tmp\belle-docs.log 2>&1
|
||||
&gulp docs >> $tmp\belle-docs.log 2>&1
|
||||
pop-location
|
||||
|
||||
# No need to build belle again if it exists
|
||||
$belleAppJs = "$src\Umbraco.Web.UI\Umbraco\js\app.js"
|
||||
if(-not (Test-Path $belleAppJs))
|
||||
{
|
||||
# get a temp clean node env (will restore)
|
||||
Sandbox-Node $uenv
|
||||
|
||||
push-location "$($uenv.SolutionRoot)\src\Umbraco.Web.UI.Client"
|
||||
write "node version is:" > $tmp\belle.log
|
||||
&node -v >> $tmp\belle.log 2>&1
|
||||
write "npm version is:" >> $tmp\belle.log 2>&1
|
||||
&npm -v >> $tmp\belle.log 2>&1
|
||||
write "cleaning npm cache" >> $tmp\belle.log 2>&1
|
||||
&npm cache clean >> $tmp\belle.log 2>&1
|
||||
write "installing bower" >> $tmp\belle.log 2>&1
|
||||
&npm install -g bower >> $tmp\belle.log 2>&1
|
||||
write "installing gulp" >> $tmp\belle.log 2>&1
|
||||
&npm install -g gulp >> $tmp\belle.log 2>&1
|
||||
write "installing gulp-cli" >> $tmp\belle.log 2>&1
|
||||
&npm install -g gulp-cli --quiet >> $tmp\belle.log 2>&1
|
||||
write "executing npm install" >> $tmp\belle.log 2>&1
|
||||
&npm install >> $tmp\belle.log 2>&1
|
||||
write "building docs using gulp" >> $tmp\belle.log 2>&1
|
||||
&gulp docs >> $tmp\belle.log 2>&1
|
||||
pop-location
|
||||
|
||||
# fixme - should we filter the log to find errors?
|
||||
#get-content .\build.tmp\belle-docs.log | %{ if ($_ -match "build") { write $_}}
|
||||
} else {
|
||||
Write-Host "Skipping belle build, $belleAppJs already exists"
|
||||
}
|
||||
Write-Host "Completed gulp docs build"
|
||||
|
||||
# fixme - should we filter the log to find errors?
|
||||
#get-content .\build.tmp\belle-docs.log | %{ if ($_ -match "build") { write $_}}
|
||||
|
||||
# change baseUrl
|
||||
$baseUrl = "https://our.umbraco.org/apidocs/ui/"
|
||||
|
||||
@@ -40,6 +40,7 @@ function Get-UmbracoBuildEnv
|
||||
&$nuget install 7-Zip.CommandLine -OutputDirectory $path -Verbosity quiet
|
||||
$dir = ls "$path\7-Zip.CommandLine.*" | sort -property Name -descending | select -first 1
|
||||
$file = ls -path "$dir" -name 7za.exe -recurse
|
||||
$file = ls -path "$dir" -name 7za.exe -recurse | select -first 1 #A select is because there is tools\7za.exe & tools\x64\7za.exe
|
||||
mv "$dir\$file" $sevenZip
|
||||
Remove-Directory $dir
|
||||
}
|
||||
|
||||
@@ -51,13 +51,19 @@ function Prepare-Build
|
||||
|
||||
if (-not $keep)
|
||||
{
|
||||
Remove-Directory "$tmp"
|
||||
mkdir "$tmp" > $null
|
||||
|
||||
Remove-Directory "$out"
|
||||
mkdir "$out" > $null
|
||||
Remove-Directory "$tmp"
|
||||
Remove-Directory "$out"
|
||||
}
|
||||
|
||||
if (-not (Test-Path "$tmp"))
|
||||
{
|
||||
mkdir "$tmp" > $null
|
||||
}
|
||||
if (-not (Test-Path "$out"))
|
||||
{
|
||||
mkdir "$out" > $null
|
||||
}
|
||||
|
||||
# ensure proper web.config
|
||||
$webUi = "$src\Umbraco.Web.UI"
|
||||
Store-WebConfig $webUi
|
||||
@@ -371,14 +377,6 @@ function Prepare-Packages
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\lib" "*" "$tmp\WebApp\umbraco\lib"
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\views" "*" "$tmp\WebApp\umbraco\views"
|
||||
Copy-Files "$src\Umbraco.Web.UI\umbraco\preview" "*" "$tmp\WebApp\umbraco\preview"
|
||||
|
||||
# prepare WebPI
|
||||
Write-Host "Prepare WebPI"
|
||||
Remove-Directory "$tmp\WebPi"
|
||||
mkdir "$tmp\WebPi" > $null
|
||||
mkdir "$tmp\WebPi\umbraco" > $null
|
||||
Copy-Files "$tmp\WebApp" "*" "$tmp\WebPi\umbraco"
|
||||
Copy-Files "$src\WebPi" "*" "$tmp\WebPi"
|
||||
}
|
||||
|
||||
#
|
||||
@@ -407,17 +405,6 @@ function Package-Zip
|
||||
"$tmp\WebApp\*" `
|
||||
"-x!dotless.Core.*" "-x!Content_Types.xml" "-x!*.pdb"`
|
||||
> $null
|
||||
|
||||
Write-Host "Zip WebPI"
|
||||
&$uenv.Zip a -r "$out\UmbracoCms.WebPI.$($version.Semver).zip" "-x!*.pdb"`
|
||||
"$tmp\WebPi\*" `
|
||||
"-x!dotless.Core.*" `
|
||||
> $null
|
||||
|
||||
# hash the webpi file
|
||||
Write-Host "Hash WebPI"
|
||||
$hash = Get-FileHash "$out\UmbracoCms.WebPI.$($version.Semver).zip"
|
||||
Write $hash | out-file "$out\webpihash.txt" -encoding ascii
|
||||
}
|
||||
|
||||
#
|
||||
@@ -461,6 +448,24 @@ function Restore-NuGet
|
||||
&$uenv.NuGet restore "$src\Umbraco.sln" > "$tmp\nuget.restore.log"
|
||||
}
|
||||
|
||||
#
|
||||
# Copies the Azure Gallery script to output
|
||||
#
|
||||
function Prepare-AzureGallery
|
||||
{
|
||||
param (
|
||||
$uenv # an Umbraco build environment (see Get-UmbracoBuildEnv)
|
||||
)
|
||||
|
||||
$src = "$($uenv.SolutionRoot)\src"
|
||||
$tmp = "$($uenv.SolutionRoot)\build.tmp"
|
||||
$out = "$($uenv.SolutionRoot)\build.out"
|
||||
$psScript = "$($uenv.SolutionRoot)\build\azuregalleryrelease.ps1"
|
||||
|
||||
Write-Host ">> Copy azuregalleryrelease.ps1 to output folder"
|
||||
Copy-Item $psScript $out
|
||||
}
|
||||
|
||||
#
|
||||
# Creates the NuGet packages
|
||||
#
|
||||
@@ -570,6 +575,10 @@ function Build-Umbraco
|
||||
{
|
||||
Compile-Belle $uenv $version
|
||||
}
|
||||
elseif ($target -eq "prepare-azuregallery")
|
||||
{
|
||||
Prepare-AzureGallery $uenv
|
||||
}
|
||||
elseif ($target -eq "all")
|
||||
{
|
||||
Prepare-Build $uenv
|
||||
@@ -584,6 +593,7 @@ function Build-Umbraco
|
||||
Verify-NuGet $uenv
|
||||
Prepare-NuGet $uenv
|
||||
Package-NuGet $uenv $version
|
||||
Prepare-AzureGallery $uenv
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,28 +1,3 @@
|
||||
# returns a string containing the hash of $file
|
||||
function Get-FileHash($file)
|
||||
{
|
||||
try
|
||||
{
|
||||
$crypto = new-object System.Security.Cryptography.SHA1CryptoServiceProvider
|
||||
$stream = [System.IO.File]::OpenRead($file)
|
||||
$hash = $crypto.ComputeHash($stream)
|
||||
$text = ""
|
||||
$hash | foreach `
|
||||
{
|
||||
$text = $text + $_.ToString("x2")
|
||||
}
|
||||
return $text
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ($stream)
|
||||
{
|
||||
$stream.Dispose()
|
||||
}
|
||||
$crypto.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
# returns the full path if $file is relative to $pwd
|
||||
function Get-FullPath($file)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.9.2, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="InsertIfMissing" />
|
||||
|
||||
<add application="settings" alias="scripts" title="Scripts" type="umbraco.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
||||
<add application="settings" alias="scripts" title="Scripts" type="Umbraco.Web.Trees.ScriptTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="dictionary" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6"
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
Param(
|
||||
[string]$GitHubPersonalAccessToken,
|
||||
[string]$Directory
|
||||
)
|
||||
$workingDirectory = $Directory
|
||||
CD $workingDirectory
|
||||
|
||||
# Clone repo
|
||||
$fullGitUrl = "https://$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
|
||||
git clone $fullGitUrl 2>&1 | % { $_.ToString() }
|
||||
|
||||
# Remove everything so that unzipping the release later will update everything
|
||||
# Don't remove the readme file nor the git directory
|
||||
Write-Host "Cleaning up git directory before adding new version"
|
||||
Remove-Item -Recurse $workingDirectory\$env:GIT_REPOSITORYNAME\* -Exclude README.md,.git
|
||||
|
||||
# Find release zip
|
||||
$zipsDir = "$workingDirectory\$env:BUILD_DEFINITIONNAME\zips"
|
||||
$pattern = "UmbracoCms.([0-9]{1,2}.[0-9]{1,3}.[0-9]{1,3}).zip"
|
||||
Write-Host "Searching for Umbraco release files in $workingDirectory\$zipsDir for a file with pattern $pattern"
|
||||
$file = (Get-ChildItem $zipsDir | Where-Object { $_.Name -match "$pattern" })
|
||||
|
||||
if($file)
|
||||
{
|
||||
# Get release name
|
||||
$version = [regex]::Match($file.Name, $pattern).captures.groups[1].value
|
||||
$releaseName = "Umbraco $version"
|
||||
Write-Host "Found $releaseName"
|
||||
|
||||
# Unzip into repository to update release
|
||||
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
||||
Write-Host "Unzipping $($file.FullName) to $workingDirectory\$env:GIT_REPOSITORYNAME"
|
||||
[System.IO.Compression.ZipFile]::ExtractToDirectory("$($file.FullName)", "$workingDirectory\$env:GIT_REPOSITORYNAME")
|
||||
|
||||
# Telling git who we are
|
||||
git config --global user.email "coffee@umbraco.com" 2>&1 | % { $_.ToString() }
|
||||
git config --global user.name "Umbraco HQ" 2>&1 | % { $_.ToString() }
|
||||
|
||||
# Commit
|
||||
CD $env:GIT_REPOSITORYNAME
|
||||
Write-Host "Committing Umbraco $version Release from Build Output"
|
||||
|
||||
git add . 2>&1 | % { $_.ToString() }
|
||||
git commit -m " Release $releaseName from Build Output" 2>&1 | % { $_.ToString() }
|
||||
|
||||
# Tag the release
|
||||
git tag -a "v$version" -m "v$version"
|
||||
|
||||
# Push release to master
|
||||
$fullGitAuthUrl = "https://$($env:GIT_USERNAME):$GitHubPersonalAccessToken@$env:GIT_URL/$env:GIT_REPOSITORYNAME.git"
|
||||
git push $fullGitAuthUrl 2>&1 | % { $_.ToString() }
|
||||
|
||||
#Push tag to master
|
||||
git push $fullGitAuthUrl --tags 2>&1 | % { $_.ToString() }
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Error "Umbraco release file not found, searched in $workingDirectory\$zipsDir for a file with pattern $pattern - cancelling"
|
||||
}
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.7.1")]
|
||||
[assembly: AssemblyInformationalVersion("7.7.1")]
|
||||
[assembly: AssemblyFileVersion("7.7.4")]
|
||||
[assembly: AssemblyInformationalVersion("7.7.4")]
|
||||
@@ -538,24 +538,41 @@ namespace Umbraco.Core.Configuration
|
||||
|
||||
internal static bool ContentCacheXmlStoredInCodeGen
|
||||
{
|
||||
get { return ContentCacheXmlStorageLocation == ContentXmlStorage.AspNetTemp; }
|
||||
get { return LocalTempStorageLocation == LocalTempStorage.AspNetTemp; }
|
||||
}
|
||||
|
||||
internal static ContentXmlStorage ContentCacheXmlStorageLocation
|
||||
|
||||
/// <summary>
|
||||
/// This is the location type to store temporary files such as cache files or other localized files for a given machine
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Currently used for the xml cache file and the plugin cache files
|
||||
/// </remarks>
|
||||
internal static LocalTempStorage LocalTempStorageLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
{
|
||||
//there's a bunch of backwards compat config checks here....
|
||||
|
||||
//This is the current one
|
||||
if (ConfigurationManager.AppSettings.ContainsKey("umbracoLocalTempStorage"))
|
||||
{
|
||||
return Enum<LocalTempStorage>.Parse(ConfigurationManager.AppSettings["umbracoLocalTempStorage"]);
|
||||
}
|
||||
|
||||
//This one is old
|
||||
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLStorage"))
|
||||
{
|
||||
return Enum<ContentXmlStorage>.Parse(ConfigurationManager.AppSettings["umbracoContentXMLStorage"]);
|
||||
}
|
||||
return Enum<LocalTempStorage>.Parse(ConfigurationManager.AppSettings["umbracoContentXMLStorage"]);
|
||||
}
|
||||
|
||||
//This one is older
|
||||
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp"))
|
||||
{
|
||||
return bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"])
|
||||
? ContentXmlStorage.AspNetTemp
|
||||
: ContentXmlStorage.Default;
|
||||
? LocalTempStorage.AspNetTemp
|
||||
: LocalTempStorage.Default;
|
||||
}
|
||||
return ContentXmlStorage.Default;
|
||||
return LocalTempStorage.Default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
internal enum ContentXmlStorage
|
||||
internal enum LocalTempStorage
|
||||
{
|
||||
Default,
|
||||
AspNetTemp,
|
||||
@@ -357,6 +357,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
string IContentSection.LoginBackgroundImage
|
||||
{
|
||||
get { return LoginBackgroundImage; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
bool EnablePropertyValueConverters { get; }
|
||||
|
||||
string LoginBackgroundImage { get; }
|
||||
string LoginBackgroundImage { get; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.7.1");
|
||||
private static readonly Version Version = new Version("7.7.4");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -13,11 +13,28 @@ using Umbraco.Core.Configuration;
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
public static class IOHelper
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value forcing Umbraco to consider it is non-hosted.
|
||||
/// </summary>
|
||||
/// <remarks>This should always be false, unless unit testing.</remarks>
|
||||
public static bool ForceNotHosted { get; set; }
|
||||
|
||||
private static string _rootDir = "";
|
||||
|
||||
// static compiled regex for faster performance
|
||||
private readonly static Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether Umbraco is hosted.
|
||||
/// </summary>
|
||||
public static bool IsHosted
|
||||
{
|
||||
get
|
||||
{
|
||||
return ForceNotHosted == false && (HttpContext.Current != null || HostingEnvironment.IsHosted);
|
||||
}
|
||||
}
|
||||
|
||||
public static char DirSepChar
|
||||
{
|
||||
@@ -72,14 +89,14 @@ namespace Umbraco.Core.IO
|
||||
internal static string ResolveUrlsFromTextString(string text)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.ResolveUrlsFromTextString)
|
||||
{
|
||||
{
|
||||
using (DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete"))
|
||||
{
|
||||
// find all relative urls (ie. urls that contain ~)
|
||||
var tags = ResolveUrlPattern.Matches(text);
|
||||
|
||||
|
||||
foreach (Match tag in tags)
|
||||
{
|
||||
{
|
||||
string url = "";
|
||||
if (tag.Groups[1].Success)
|
||||
url = tag.Groups[1].Value;
|
||||
@@ -97,7 +114,8 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public static string MapPath(string path, bool useHttpContext)
|
||||
{
|
||||
if (path == null) throw new ArgumentNullException("path");
|
||||
if (path == null) throw new ArgumentNullException("path");
|
||||
useHttpContext = useHttpContext && IsHosted;
|
||||
|
||||
// Check if the path is already mapped
|
||||
if ((path.Length >= 2 && path[1] == Path.VolumeSeparatorChar)
|
||||
@@ -303,7 +321,7 @@ namespace Umbraco.Core.IO
|
||||
var debugFolder = Path.Combine(binFolder, "debug");
|
||||
if (Directory.Exists(debugFolder))
|
||||
return debugFolder;
|
||||
#endif
|
||||
#endif
|
||||
var releaseFolder = Path.Combine(binFolder, "release");
|
||||
if (Directory.Exists(releaseFolder))
|
||||
return releaseFolder;
|
||||
|
||||
@@ -73,19 +73,19 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (GlobalSettings.ContentCacheXmlStorageLocation)
|
||||
switch (GlobalSettings.LocalTempStorageLocation)
|
||||
{
|
||||
case ContentXmlStorage.AspNetTemp:
|
||||
case LocalTempStorage.AspNetTemp:
|
||||
return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config");
|
||||
case ContentXmlStorage.EnvironmentTemp:
|
||||
case LocalTempStorage.EnvironmentTemp:
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoXml",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path
|
||||
appDomainHash);
|
||||
return Path.Combine(cachePath, "umbraco.config");
|
||||
case ContentXmlStorage.Default:
|
||||
case LocalTempStorage.Default:
|
||||
return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config");
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
|
||||
@@ -42,6 +42,14 @@ namespace Umbraco.Core.Models.Identity
|
||||
|
||||
private BackOfficeIdentityUser()
|
||||
{
|
||||
_startMediaIds = new int[] { };
|
||||
_startContentIds = new int[] { };
|
||||
_groups = new IReadOnlyUserGroup[] { };
|
||||
_allowedSections = new string[] { };
|
||||
_culture = Configuration.GlobalSettings.DefaultUILanguage;
|
||||
_groups = new IReadOnlyUserGroup[0];
|
||||
_roles = new ObservableCollection<IdentityUserRole<string>>();
|
||||
_roles.CollectionChanged += _roles_CollectionChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,7 +17,30 @@ namespace Umbraco.Core.Models.Membership
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the aggregate permissions in the permission set
|
||||
/// Returns the aggregate permissions in the permission set for a single node
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This value is only calculated once per node
|
||||
/// </remarks>
|
||||
public IEnumerable<string> GetAllPermissions(int entityId)
|
||||
{
|
||||
if (_aggregateNodePermissions == null)
|
||||
_aggregateNodePermissions = new Dictionary<int, string[]>();
|
||||
|
||||
string[] entityPermissions;
|
||||
if (_aggregateNodePermissions.TryGetValue(entityId, out entityPermissions) == false)
|
||||
{
|
||||
entityPermissions = this.Where(x => x.EntityId == entityId).SelectMany(x => x.AssignedPermissions).Distinct().ToArray();
|
||||
_aggregateNodePermissions[entityId] = entityPermissions;
|
||||
}
|
||||
return entityPermissions;
|
||||
}
|
||||
|
||||
private Dictionary<int, string[]> _aggregateNodePermissions;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the aggregate permissions in the permission set for all nodes
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
internal class UserGroup : Entity, IUserGroup, IReadOnlyUserGroup
|
||||
public class UserGroup : Entity, IUserGroup, IReadOnlyUserGroup
|
||||
{
|
||||
private int? _startContentId;
|
||||
private int? _startMediaId;
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace Umbraco.Core.Persistence
|
||||
{
|
||||
private int _version;
|
||||
private bool _hasVersion;
|
||||
private string _exe;
|
||||
|
||||
#region Availability & Version
|
||||
|
||||
@@ -84,16 +85,31 @@ namespace Umbraco.Core.Persistence
|
||||
{
|
||||
_hasVersion = true;
|
||||
_version = -1;
|
||||
_exe = null;
|
||||
|
||||
var programFiles = Environment.GetEnvironmentVariable("ProgramFiles");
|
||||
if (programFiles == null) return;
|
||||
|
||||
// MS SQL Server installs in e.g. "C:\Program Files\Microsoft SQL Server", so
|
||||
// we want to detect it in "%ProgramFiles%\Microsoft SQL Server" - however, if
|
||||
// Umbraco runs as a 32bits process (e.g. IISExpress configured as 32bits)
|
||||
// on a 64bits system, %ProgramFiles% will point to "C:\Program Files (x86)"
|
||||
// and SQL Server cannot be found. But then, %ProgramW6432% will point to
|
||||
// the original "C:\Program Files". Using it to fix the path.
|
||||
// see also: MSDN doc for WOW64 implementation
|
||||
//
|
||||
var programW6432 = Environment.GetEnvironmentVariable("ProgramW6432");
|
||||
if (string.IsNullOrWhiteSpace(programW6432) == false && programW6432 != programFiles)
|
||||
programFiles = programW6432;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(programFiles)) return;
|
||||
|
||||
// detect 14, 13, 12, 11
|
||||
for (var i = 14; i > 10; i--)
|
||||
{
|
||||
var path = Path.Combine(programFiles, string.Format(@"Microsoft SQL Server\{0}0\Tools\Binn\SqlLocalDB.exe", i));
|
||||
if (File.Exists(path) == false) continue;
|
||||
var exe = Path.Combine(programFiles, string.Format(@"Microsoft SQL Server\{0}0\Tools\Binn\SqlLocalDB.exe", i));
|
||||
if (File.Exists(exe) == false) continue;
|
||||
_version = i;
|
||||
_exe = exe;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -897,16 +913,13 @@ namespace Umbraco.Core.Persistence
|
||||
/// </remarks>
|
||||
private int ExecuteSqlLocalDb(string args, out string output, out string error)
|
||||
{
|
||||
var programFiles = Environment.GetEnvironmentVariable("ProgramFiles");
|
||||
if (programFiles == null)
|
||||
if (_exe == null) // should never happen - we should not execute if not available
|
||||
{
|
||||
output = string.Empty;
|
||||
error = "SqlLocalDB.exe not found";
|
||||
return -1;
|
||||
}
|
||||
|
||||
var path = Path.Combine(programFiles, string.Format(@"Microsoft SQL Server\{0}0\Tools\Binn\SqlLocalDB.exe", _version));
|
||||
|
||||
var p = new Process
|
||||
{
|
||||
StartInfo =
|
||||
@@ -914,7 +927,7 @@ namespace Umbraco.Core.Persistence
|
||||
UseShellExecute = false,
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
FileName = path,
|
||||
FileName = _exe,
|
||||
Arguments = args,
|
||||
CreateNoWindow = true,
|
||||
WindowStyle = ProcessWindowStyle.Hidden
|
||||
@@ -929,7 +942,7 @@ namespace Umbraco.Core.Persistence
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Unicode string with the delimiters added to make the input string a valid SQL Server delimited identifier.
|
||||
/// Returns a Unicode string with the delimiters added to make the input string a valid SQL Server delimited identifier.
|
||||
/// </summary>
|
||||
/// <param name="name">The name to quote.</param>
|
||||
/// <param name="quote">A quote character.</param>
|
||||
|
||||
@@ -687,8 +687,8 @@ ORDER BY contentNodeId, versionId, propertytypeid
|
||||
case "NAME":
|
||||
return "umbracoNode.text";
|
||||
case "PUBLISHED":
|
||||
case "OWNER":
|
||||
return "cmsDocument.published";
|
||||
case "OWNER":
|
||||
//TODO: This isn't going to work very nicely because it's going to order by ID, not by letter
|
||||
return "umbracoNode.nodeUser";
|
||||
// Members only
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using System.Web.Compilation;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.IO;
|
||||
@@ -15,6 +16,7 @@ using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core.Configuration;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Umbraco.Core
|
||||
@@ -39,7 +41,8 @@ namespace Umbraco.Core
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IRuntimeCacheProvider _runtimeCache;
|
||||
private readonly ProfilingLogger _logger;
|
||||
private readonly string _tempFolder;
|
||||
private readonly Lazy<string> _pluginListFilePath = new Lazy<string>(GetPluginListFilePath);
|
||||
private readonly Lazy<string> _pluginHashFilePath = new Lazy<string>(GetPluginHashFilePath);
|
||||
|
||||
private readonly object _typesLock = new object();
|
||||
private readonly Dictionary<TypeListKey, TypeList> _types = new Dictionary<TypeListKey, TypeList>();
|
||||
@@ -65,14 +68,7 @@ namespace Umbraco.Core
|
||||
_serviceProvider = serviceProvider;
|
||||
_runtimeCache = runtimeCache;
|
||||
_logger = logger;
|
||||
|
||||
// the temp folder where the cache file lives
|
||||
_tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
|
||||
if (Directory.Exists(_tempFolder) == false)
|
||||
Directory.CreateDirectory(_tempFolder);
|
||||
|
||||
var pluginListFile = GetPluginListFilePath();
|
||||
|
||||
|
||||
if (detectChanges)
|
||||
{
|
||||
//first check if the cached hash is string.Empty, if it is then we need
|
||||
@@ -84,7 +80,8 @@ namespace Umbraco.Core
|
||||
// if the hash has changed, clear out the persisted list no matter what, this will force
|
||||
// rescanning of all plugin types including lazy ones.
|
||||
// http://issues.umbraco.org/issue/U4-4789
|
||||
File.Delete(pluginListFile);
|
||||
if(File.Exists(_pluginListFilePath.Value))
|
||||
File.Delete(_pluginListFilePath.Value);
|
||||
|
||||
WriteCachePluginsHash();
|
||||
}
|
||||
@@ -94,7 +91,8 @@ namespace Umbraco.Core
|
||||
// if the hash has changed, clear out the persisted list no matter what, this will force
|
||||
// rescanning of all plugin types including lazy ones.
|
||||
// http://issues.umbraco.org/issue/U4-4789
|
||||
File.Delete(pluginListFile);
|
||||
if (File.Exists(_pluginListFilePath.Value))
|
||||
File.Delete(_pluginListFilePath.Value);
|
||||
|
||||
// always set to true if we're not detecting (generally only for testing)
|
||||
RequiresRescanning = true;
|
||||
@@ -187,11 +185,10 @@ namespace Umbraco.Core
|
||||
{
|
||||
if (_cachedAssembliesHash != null)
|
||||
return _cachedAssembliesHash;
|
||||
|
||||
if (File.Exists(_pluginHashFilePath.Value) == false) return string.Empty;
|
||||
|
||||
var filePath = GetPluginHashFilePath();
|
||||
if (File.Exists(filePath) == false) return string.Empty;
|
||||
|
||||
var hash = File.ReadAllText(filePath, Encoding.UTF8);
|
||||
var hash = File.ReadAllText(_pluginHashFilePath.Value, Encoding.UTF8);
|
||||
|
||||
_cachedAssembliesHash = hash;
|
||||
return _cachedAssembliesHash;
|
||||
@@ -229,9 +226,8 @@ namespace Umbraco.Core
|
||||
/// Writes the assembly hash file.
|
||||
/// </summary>
|
||||
private void WriteCachePluginsHash()
|
||||
{
|
||||
var filePath = GetPluginHashFilePath();
|
||||
File.WriteAllText(filePath, CurrentAssembliesHash.ToString(), Encoding.UTF8);
|
||||
{
|
||||
File.WriteAllText(_pluginHashFilePath.Value, CurrentAssembliesHash, Encoding.UTF8);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -274,7 +270,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
}
|
||||
return generator.GenerateHash();
|
||||
return generator.GenerateHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -314,7 +310,7 @@ namespace Umbraco.Core
|
||||
uniqInfos.Add(fileOrFolder.FullName);
|
||||
generator.AddFileSystemItem(fileOrFolder);
|
||||
}
|
||||
return generator.GenerateHash();
|
||||
return generator.GenerateHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,12 +343,11 @@ namespace Umbraco.Core
|
||||
{
|
||||
return ReadCache();
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filePath = GetPluginListFilePath();
|
||||
File.Delete(filePath);
|
||||
File.Delete(_pluginListFilePath.Value);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -366,12 +361,11 @@ namespace Umbraco.Core
|
||||
internal Dictionary<Tuple<string, string>, IEnumerable<string>> ReadCache()
|
||||
{
|
||||
var cache = new Dictionary<Tuple<string, string>, IEnumerable<string>>();
|
||||
|
||||
var filePath = GetPluginListFilePath();
|
||||
if (File.Exists(filePath) == false)
|
||||
|
||||
if (File.Exists(_pluginListFilePath.Value) == false)
|
||||
return cache;
|
||||
|
||||
using (var stream = GetFileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, ListFileOpenReadTimeout))
|
||||
using (var stream = GetFileStream(_pluginListFilePath.Value, FileMode.Open, FileAccess.Read, FileShare.Read, ListFileOpenReadTimeout))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
while (true)
|
||||
@@ -414,38 +408,86 @@ namespace Umbraco.Core
|
||||
/// <remarks>Generally only used for resetting cache, for example during the install process.</remarks>
|
||||
public void ClearPluginCache()
|
||||
{
|
||||
var path = GetPluginListFilePath();
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
|
||||
path = GetPluginHashFilePath();
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
if (File.Exists(_pluginListFilePath.Value))
|
||||
File.Delete(_pluginListFilePath.Value);
|
||||
|
||||
if (File.Exists(_pluginHashFilePath.Value))
|
||||
File.Delete(_pluginHashFilePath.Value);
|
||||
|
||||
_runtimeCache.ClearCacheItem(CacheKey);
|
||||
}
|
||||
|
||||
private string GetPluginListFilePath()
|
||||
private static string GetPluginListFilePath()
|
||||
{
|
||||
var filename = "umbraco-plugins." + NetworkHelper.FileSafeMachineName + ".list";
|
||||
return Path.Combine(_tempFolder, filename);
|
||||
string pluginListFilePath;
|
||||
switch (GlobalSettings.LocalTempStorageLocation)
|
||||
{
|
||||
case LocalTempStorage.AspNetTemp:
|
||||
pluginListFilePath = Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco-plugins.list");
|
||||
break;
|
||||
case LocalTempStorage.EnvironmentTemp:
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path
|
||||
appDomainHash);
|
||||
pluginListFilePath = Path.Combine(cachePath, "umbraco-plugins.list");
|
||||
break;
|
||||
case LocalTempStorage.Default:
|
||||
default:
|
||||
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
|
||||
pluginListFilePath = Path.Combine(tempFolder, "umbraco-plugins." + NetworkHelper.FileSafeMachineName + ".list");
|
||||
break;
|
||||
}
|
||||
|
||||
//ensure the folder exists
|
||||
var folder = Path.GetDirectoryName(pluginListFilePath);
|
||||
if (folder == null)
|
||||
throw new InvalidOperationException("The folder could not be determined for the file " + pluginListFilePath);
|
||||
if (Directory.Exists(folder) == false)
|
||||
Directory.CreateDirectory(folder);
|
||||
|
||||
return pluginListFilePath;
|
||||
}
|
||||
|
||||
private string GetPluginHashFilePath()
|
||||
private static string GetPluginHashFilePath()
|
||||
{
|
||||
var filename = "umbraco-plugins." + NetworkHelper.FileSafeMachineName + ".hash";
|
||||
return Path.Combine(_tempFolder, filename);
|
||||
string pluginHashFilePath;
|
||||
switch (GlobalSettings.LocalTempStorageLocation)
|
||||
{
|
||||
case LocalTempStorage.AspNetTemp:
|
||||
pluginHashFilePath = Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco-plugins.hash");
|
||||
break;
|
||||
case LocalTempStorage.EnvironmentTemp:
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path
|
||||
appDomainHash);
|
||||
pluginHashFilePath = Path.Combine(cachePath, "umbraco-plugins.hash");
|
||||
break;
|
||||
case LocalTempStorage.Default:
|
||||
default:
|
||||
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/PluginCache");
|
||||
pluginHashFilePath = Path.Combine(tempFolder, "umbraco-plugins." + NetworkHelper.FileSafeMachineName + ".hash");
|
||||
break;
|
||||
}
|
||||
|
||||
//ensure the folder exists
|
||||
var folder = Path.GetDirectoryName(pluginHashFilePath);
|
||||
if (folder == null)
|
||||
throw new InvalidOperationException("The folder could not be determined for the file " + pluginHashFilePath);
|
||||
if (Directory.Exists(folder) == false)
|
||||
Directory.CreateDirectory(folder);
|
||||
|
||||
return pluginHashFilePath;
|
||||
}
|
||||
|
||||
internal void WriteCache()
|
||||
{
|
||||
// be absolutely sure
|
||||
if (Directory.Exists(_tempFolder) == false)
|
||||
Directory.CreateDirectory(_tempFolder);
|
||||
|
||||
var filePath = GetPluginListFilePath();
|
||||
|
||||
using (var stream = GetFileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, ListFileOpenWriteTimeout))
|
||||
using (var stream = GetFileStream(_pluginListFilePath.Value, FileMode.Create, FileAccess.Write, FileShare.None, ListFileOpenWriteTimeout))
|
||||
using (var writer = new StreamWriter(stream))
|
||||
{
|
||||
foreach (var typeList in _types.Values)
|
||||
@@ -461,8 +503,7 @@ namespace Umbraco.Core
|
||||
|
||||
internal void UpdateCache()
|
||||
{
|
||||
// note
|
||||
// at the moment we write the cache to disk every time we update it. ideally we defer the writing
|
||||
// TODO: at the moment we write the cache to disk every time we update it. ideally we defer the writing
|
||||
// since all the updates are going to happen in a row when Umbraco starts. that being said, the
|
||||
// file is small enough, so it is not a priority.
|
||||
WriteCache();
|
||||
@@ -475,13 +516,13 @@ namespace Umbraco.Core
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
return new FileStream(path, fileMode, fileAccess, fileShare);
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (--attempts == 0)
|
||||
throw;
|
||||
throw;
|
||||
|
||||
LogHelper.Debug<PluginManager>(string.Format("Attempted to get filestream for file {0} failed, {1} attempts left, pausing for {2} milliseconds", path, attempts, pauseMilliseconds));
|
||||
Thread.Sleep(pauseMilliseconds);
|
||||
@@ -691,7 +732,7 @@ namespace Umbraco.Core
|
||||
// else proceed,
|
||||
typeList = new TypeList(baseType, attributeType);
|
||||
|
||||
var scan = RequiresRescanning || File.Exists(GetPluginListFilePath()) == false;
|
||||
var scan = RequiresRescanning || File.Exists(_pluginListFilePath.Value) == false;
|
||||
|
||||
if (scan)
|
||||
{
|
||||
|
||||
@@ -178,29 +178,25 @@ namespace Umbraco.Core.PropertyEditors
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ConvertItemsToJsonIfDetected(IDictionary<string, object> result)
|
||||
protected void ConvertItemsToJsonIfDetected(IDictionary<string, object> result)
|
||||
{
|
||||
//now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects
|
||||
// so they can be consumed as real json in angular!
|
||||
// convert values that are Json to true Json objects that can be consumed by Angular
|
||||
|
||||
var keys = result.Keys.ToArray();
|
||||
for (var i = 0; i < keys.Length; i++)
|
||||
{
|
||||
if (result[keys[i]] is string)
|
||||
if ((result[keys[i]] is string) == false) continue;
|
||||
|
||||
var asString = result[keys[i]].ToString();
|
||||
if (asString.DetectIsJson() == false) continue;
|
||||
|
||||
try
|
||||
{
|
||||
var asString = result[keys[i]].ToString();
|
||||
if (asString.DetectIsJson())
|
||||
{
|
||||
try
|
||||
{
|
||||
var json = JsonConvert.DeserializeObject(asString);
|
||||
result[keys[i]] = json;
|
||||
}
|
||||
catch
|
||||
{
|
||||
//swallow this exception, we thought it was json but it really isn't so continue returning a string
|
||||
}
|
||||
}
|
||||
result[keys[i]] = JsonConvert.DeserializeObject(asString);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// swallow this exception, we thought it was Json but it really isn't so continue returning a string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.PublishedContent;
|
||||
|
||||
namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
{
|
||||
[DefaultPropertyValueConverter]
|
||||
[PropertyValueType(typeof(string))]
|
||||
[PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
|
||||
public class ColorPickerValueConverter : PropertyValueConverterBase
|
||||
public class ColorPickerValueConverter : PropertyValueConverterBase, IPropertyValueConverterMeta
|
||||
{
|
||||
public override bool IsConverter(PublishedPropertyType propertyType)
|
||||
{
|
||||
@@ -18,11 +19,60 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
return false;
|
||||
}
|
||||
|
||||
public Type GetPropertyValueType(PublishedPropertyType propertyType)
|
||||
{
|
||||
return UseLabel(propertyType) ? typeof(PickedColor) : typeof(string);
|
||||
}
|
||||
|
||||
public PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType, PropertyCacheValue cacheValue)
|
||||
{
|
||||
return PropertyCacheLevel.Content;
|
||||
}
|
||||
|
||||
private bool UseLabel(PublishedPropertyType propertyType)
|
||||
{
|
||||
var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(propertyType.DataTypeId);
|
||||
PreValue preValue;
|
||||
return preValues.PreValuesAsDictionary.TryGetValue("useLabel", out preValue) && preValue.Value == "1";
|
||||
}
|
||||
|
||||
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
|
||||
{
|
||||
// make sure it's a string
|
||||
return source == null ? string.Empty : source.ToString();
|
||||
var useLabel = UseLabel(propertyType);
|
||||
|
||||
if (source == null) return useLabel ? null : string.Empty;
|
||||
|
||||
var ssource = source.ToString();
|
||||
if (ssource.DetectIsJson())
|
||||
{
|
||||
try
|
||||
{
|
||||
var jo = JsonConvert.DeserializeObject<JObject>(ssource);
|
||||
if (useLabel) return new PickedColor(jo["value"].ToString(), jo["label"].ToString());
|
||||
return jo["value"].ToString();
|
||||
}
|
||||
catch { /* not json finally */ }
|
||||
}
|
||||
|
||||
if (useLabel) return new PickedColor(ssource, ssource);
|
||||
return ssource;
|
||||
}
|
||||
|
||||
public class PickedColor
|
||||
{
|
||||
public PickedColor(string color, string label)
|
||||
{
|
||||
Color = color;
|
||||
Label = label;
|
||||
}
|
||||
|
||||
public string Color { get; private set; }
|
||||
public string Label { get; private set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Color;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
|
||||
var gridConfig = UmbracoConfig.For.GridConfig(
|
||||
ApplicationContext.Current.ProfilingLogger.Logger,
|
||||
ApplicationContext.Current.ApplicationCache.RuntimeCache,
|
||||
new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.AppPlugins)),
|
||||
new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.Config)),
|
||||
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.AppPlugins)),
|
||||
new DirectoryInfo(IOHelper.MapPath(SystemDirectories.Config)),
|
||||
HttpContext.Current.IsDebuggingEnabled);
|
||||
|
||||
var sections = GetArray(obj, "sections");
|
||||
|
||||
@@ -124,12 +124,15 @@ namespace Umbraco.Core.Security
|
||||
var found = _userService.GetUserById(asInt.Result);
|
||||
if (found != null)
|
||||
{
|
||||
// we have to remember whether Logins property is dirty, since the UpdateMemberProperties will reset it.
|
||||
var isLoginsPropertyDirty = user.IsPropertyDirty("Logins");
|
||||
|
||||
if (UpdateMemberProperties(found, user))
|
||||
{
|
||||
_userService.Save(found);
|
||||
}
|
||||
|
||||
if (user.IsPropertyDirty("Logins"))
|
||||
if (isLoginsPropertyDirty)
|
||||
{
|
||||
var logins = await GetLoginsAsync(user);
|
||||
_externalLoginService.SaveUserLogins(found.Id, logins);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Configuration.Provider;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
@@ -8,6 +9,7 @@ using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Web.Hosting;
|
||||
using System.Web.Security;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
@@ -677,11 +679,7 @@ namespace Umbraco.Core.Security
|
||||
|
||||
internal static bool IsEmailValid(string email)
|
||||
{
|
||||
const string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
|
||||
+ @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
|
||||
+ @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";
|
||||
|
||||
return Regex.IsMatch(email, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
return new EmailAddressAttribute().IsValid(email);
|
||||
}
|
||||
|
||||
protected internal string EncryptOrHashPassword(string pass, string salt)
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
|
||||
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim();
|
||||
|
||||
|
||||
private readonly Dictionary<int, TypedId<Guid>> _id2Key = new Dictionary<int, TypedId<Guid>>();
|
||||
private readonly Dictionary<Guid, TypedId<int>> _key2Id = new Dictionary<Guid, TypedId<int>>();
|
||||
|
||||
@@ -39,8 +39,8 @@ namespace Umbraco.Core.Services
|
||||
int? val;
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
val = uow.Database.ExecuteScalar<int?>("SELECT id FROM umbracoNode WHERE uniqueId=@id AND nodeObjectType=@nodeObjectType",
|
||||
new { id = key, nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType) });
|
||||
val = uow.Database.ExecuteScalar<int?>("SELECT id FROM umbracoNode WHERE uniqueId=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)",
|
||||
new { id = key, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Constants.ObjectTypes.IdReservationGuid });
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
@@ -92,8 +92,8 @@ namespace Umbraco.Core.Services
|
||||
Guid? val;
|
||||
using (var uow = _uowProvider.GetUnitOfWork())
|
||||
{
|
||||
val = uow.Database.ExecuteScalar<Guid?>("SELECT uniqueId FROM umbracoNode WHERE id=@id AND nodeObjectType=@nodeObjectType",
|
||||
new { id, nodeObjectType = GetNodeObjectTypeGuid(umbracoObjectType) });
|
||||
val = uow.Database.ExecuteScalar<Guid?>("SELECT uniqueId FROM umbracoNode WHERE id=@id AND (nodeObjectType=@type OR nodeObjectType=@reservation)",
|
||||
new { id, type = GetNodeObjectTypeGuid(umbracoObjectType), reservation = Constants.ObjectTypes.IdReservationGuid });
|
||||
uow.Commit();
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Umbraco.Core.Services
|
||||
{
|
||||
private readonly T _id;
|
||||
private readonly UmbracoObjectTypes _umbracoObjectType;
|
||||
|
||||
|
||||
public T Id
|
||||
{
|
||||
get { return _id; }
|
||||
|
||||
@@ -14,6 +14,7 @@ using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Sync
|
||||
@@ -39,6 +40,7 @@ namespace Umbraco.Core.Sync
|
||||
private bool _syncing;
|
||||
private bool _released;
|
||||
private readonly ProfilingLogger _profilingLogger;
|
||||
private readonly Lazy<string> _distCacheFilePath = new Lazy<string>(GetDistCacheFilePath);
|
||||
|
||||
protected DatabaseServerMessengerOptions Options { get; private set; }
|
||||
protected ApplicationContext ApplicationContext { get { return _appContext; } }
|
||||
@@ -460,10 +462,9 @@ namespace Umbraco.Core.Sync
|
||||
/// </remarks>
|
||||
private void ReadLastSynced()
|
||||
{
|
||||
var path = SyncFilePath;
|
||||
if (File.Exists(path) == false) return;
|
||||
if (File.Exists(_distCacheFilePath.Value) == false) return;
|
||||
|
||||
var content = File.ReadAllText(path);
|
||||
var content = File.ReadAllText(_distCacheFilePath.Value);
|
||||
int last;
|
||||
if (int.TryParse(content, out last))
|
||||
_lastId = last;
|
||||
@@ -478,7 +479,7 @@ namespace Umbraco.Core.Sync
|
||||
/// </remarks>
|
||||
private void SaveLastSynced(int id)
|
||||
{
|
||||
File.WriteAllText(SyncFilePath, id.ToString(CultureInfo.InvariantCulture));
|
||||
File.WriteAllText(_distCacheFilePath.Value, id.ToString(CultureInfo.InvariantCulture));
|
||||
_lastId = id;
|
||||
}
|
||||
|
||||
@@ -498,20 +499,40 @@ namespace Umbraco.Core.Sync
|
||||
+ "/D" + AppDomain.CurrentDomain.Id // eg 22
|
||||
+ "] " + Guid.NewGuid().ToString("N").ToUpper(); // make it truly unique
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sync file path for the local server.
|
||||
/// </summary>
|
||||
/// <returns>The sync file path for the local server.</returns>
|
||||
private static string SyncFilePath
|
||||
private static string GetDistCacheFilePath()
|
||||
{
|
||||
get
|
||||
{
|
||||
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/DistCache/" + NetworkHelper.FileSafeMachineName);
|
||||
if (Directory.Exists(tempFolder) == false)
|
||||
Directory.CreateDirectory(tempFolder);
|
||||
var fileName = HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty) + "-lastsynced.txt";
|
||||
|
||||
return Path.Combine(tempFolder, HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty) + "-lastsynced.txt");
|
||||
string distCacheFilePath;
|
||||
switch (GlobalSettings.LocalTempStorageLocation)
|
||||
{
|
||||
case LocalTempStorage.AspNetTemp:
|
||||
distCacheFilePath = Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData", fileName);
|
||||
break;
|
||||
case LocalTempStorage.EnvironmentTemp:
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoData",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path
|
||||
appDomainHash);
|
||||
distCacheFilePath = Path.Combine(cachePath, fileName);
|
||||
break;
|
||||
case LocalTempStorage.Default:
|
||||
default:
|
||||
var tempFolder = IOHelper.MapPath("~/App_Data/TEMP/DistCache");
|
||||
distCacheFilePath = Path.Combine(tempFolder, fileName);
|
||||
break;
|
||||
}
|
||||
|
||||
//ensure the folder exists
|
||||
var folder = Path.GetDirectoryName(distCacheFilePath);
|
||||
if (folder == null)
|
||||
throw new InvalidOperationException("The folder could not be determined for the file " + distCacheFilePath);
|
||||
if (Directory.Exists(folder) == false)
|
||||
Directory.CreateDirectory(folder);
|
||||
|
||||
return distCacheFilePath;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Web.Compilation;
|
||||
using System.Web.Hosting;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -21,6 +20,38 @@ namespace Umbraco.Core
|
||||
{
|
||||
private static volatile HashSet<Assembly> _localFilteredAssemblyCache;
|
||||
private static readonly object LocalFilteredAssemblyCacheLocker = new object();
|
||||
private static readonly List<string> NotifiedLoadExceptionAssemblies = new List<string>();
|
||||
private static string[] _assembliesAcceptingLoadExceptions;
|
||||
|
||||
private static string[] AssembliesAcceptingLoadExceptions
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_assembliesAcceptingLoadExceptions != null)
|
||||
return _assembliesAcceptingLoadExceptions;
|
||||
|
||||
var s = ConfigurationManager.AppSettings["Umbraco.AssembliesAcceptingLoadExceptions"];
|
||||
return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s)
|
||||
? new string[0]
|
||||
: s.Split(',').Select(x => x.Trim()).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static bool AcceptsLoadExceptions(Assembly a)
|
||||
{
|
||||
if (AssembliesAcceptingLoadExceptions.Length == 0)
|
||||
return false;
|
||||
if (AssembliesAcceptingLoadExceptions.Length == 1 && AssembliesAcceptingLoadExceptions[0] == "*")
|
||||
return true;
|
||||
var name = a.GetName().Name; // simple name of the assembly
|
||||
return AssembliesAcceptingLoadExceptions.Any(pattern =>
|
||||
{
|
||||
if (pattern.Length > name.Length) return false; // pattern longer than name
|
||||
if (pattern.Length == name.Length) return pattern.InvariantEquals(name); // same length, must be identical
|
||||
if (pattern[pattern.Length] != '.') return false; // pattern is shorter than name, must end with dot
|
||||
return name.StartsWith(pattern); // and name must start with pattern
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// lazily load a reference to all assemblies and only local assemblies.
|
||||
@@ -45,7 +76,7 @@ namespace Umbraco.Core
|
||||
HashSet<Assembly> assemblies = null;
|
||||
try
|
||||
{
|
||||
var isHosted = HttpContext.Current != null || HostingEnvironment.IsHosted;
|
||||
var isHosted = IOHelper.IsHosted;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -528,9 +559,22 @@ namespace Umbraco.Core
|
||||
AppendCouldNotLoad(sb, a, getAll);
|
||||
foreach (var loaderException in rex.LoaderExceptions.WhereNotNull())
|
||||
AppendLoaderException(sb, loaderException);
|
||||
|
||||
var ex = new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
|
||||
|
||||
// rethrow with new message
|
||||
throw new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
|
||||
// rethrow with new message, unless accepted
|
||||
if (AcceptsLoadExceptions(a) == false) throw ex;
|
||||
|
||||
// log a warning, and return what we can
|
||||
lock (NotifiedLoadExceptionAssemblies)
|
||||
{
|
||||
if (NotifiedLoadExceptionAssemblies.Contains(a.FullName) == false)
|
||||
{
|
||||
NotifiedLoadExceptionAssemblies.Add(a.FullName);
|
||||
LogHelper.WarnWithException(typeof(TypeFinder), "Could not load all types from " + a.GetName().Name + ".", ex);
|
||||
}
|
||||
}
|
||||
return rex.Types.WhereNotNull().ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
<Compile Include="Configuration\BaseRest\ExtensionElement.cs" />
|
||||
<Compile Include="Configuration\BaseRest\ExtensionElementCollection.cs" />
|
||||
<Compile Include="Configuration\BaseRest\MethodElement.cs" />
|
||||
<Compile Include="Configuration\ContentXmlStorage.cs" />
|
||||
<Compile Include="Configuration\LocalTempStorage.cs" />
|
||||
<Compile Include="Configuration\CoreDebug.cs" />
|
||||
<Compile Include="Configuration\Dashboard\AccessElement.cs" />
|
||||
<Compile Include="Configuration\Dashboard\AccessItem.cs" />
|
||||
|
||||
@@ -20,7 +20,7 @@ using Umbraco.Tests.TestHelpers.Entities;
|
||||
namespace Umbraco.Tests.Models
|
||||
{
|
||||
[TestFixture]
|
||||
public class ContentTests : BaseUmbracoConfigurationTest
|
||||
public class ContentTests : BaseUmbracoApplicationTest
|
||||
{
|
||||
[SetUp]
|
||||
public void Init()
|
||||
|
||||
@@ -26,15 +26,15 @@ namespace Umbraco.Tests.Services
|
||||
public override void TearDown()
|
||||
{
|
||||
base.TearDown();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Content_Children()
|
||||
{
|
||||
|
||||
|
||||
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
|
||||
|
||||
var root = MockedContent.CreateSimpleContent(contentType);
|
||||
|
||||
var root = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(root);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
@@ -45,7 +45,7 @@ namespace Umbraco.Tests.Services
|
||||
var service = ServiceContext.EntityService;
|
||||
|
||||
long total;
|
||||
var entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Document, 0, 6, out total).ToArray();
|
||||
var entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Document, 0, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(6));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Document, 1, 6, out total).ToArray();
|
||||
@@ -72,7 +72,7 @@ namespace Umbraco.Tests.Services
|
||||
var c2 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), c1);
|
||||
ServiceContext.ContentService.Save(c2);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var service = ServiceContext.EntityService;
|
||||
@@ -181,7 +181,7 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
var root = MockedContent.CreateSimpleContent(contentType);
|
||||
ServiceContext.ContentService.Save(root);
|
||||
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedContent.CreateSimpleContent(contentType, "ssss" + Guid.NewGuid(), root);
|
||||
@@ -204,7 +204,7 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(entities.Length, Is.EqualTo(50));
|
||||
Assert.That(total, Is.EqualTo(50));
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void EntityService_Can_Get_Paged_Media_Children()
|
||||
{
|
||||
@@ -227,7 +227,7 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
entities = service.GetPagedChildren(root.Id, UmbracoObjectTypes.Media, 1, 6, out total).ToArray();
|
||||
Assert.That(entities.Length, Is.EqualTo(4));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
Assert.That(total, Is.EqualTo(10));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -362,7 +362,7 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
var root = MockedMedia.CreateMediaFolder(folderType, -1);
|
||||
ServiceContext.MediaService.Save(root);
|
||||
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var c1 = MockedMedia.CreateMediaImage(imageMediaType, root.Id);
|
||||
@@ -519,7 +519,7 @@ namespace Umbraco.Tests.Services
|
||||
Assert.That(
|
||||
entities.Any(
|
||||
x =>
|
||||
x.AdditionalData.Any(y => y.Value is UmbracoEntity.EntityProperty
|
||||
x.AdditionalData.Any(y => y.Value is UmbracoEntity.EntityProperty
|
||||
&& ((UmbracoEntity.EntityProperty)y.Value).PropertyEditorAlias == Constants.PropertyEditors.UploadFieldAlias)), Is.True);
|
||||
}
|
||||
|
||||
@@ -575,6 +575,30 @@ namespace Umbraco.Tests.Services
|
||||
Assert.IsFalse(result2.Success);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ReserveId()
|
||||
{
|
||||
var service = ServiceContext.EntityService;
|
||||
var guid = Guid.NewGuid();
|
||||
|
||||
// can reserve
|
||||
var reservedId = service.ReserveId(guid);
|
||||
Assert.IsTrue(reservedId > 0);
|
||||
|
||||
// can get it back
|
||||
var id = service.GetIdForKey(guid, UmbracoObjectTypes.DocumentType);
|
||||
Assert.IsTrue(id.Success);
|
||||
Assert.AreEqual(reservedId, id.Result);
|
||||
|
||||
// anything goes
|
||||
id = service.GetIdForKey(guid, UmbracoObjectTypes.Media);
|
||||
Assert.IsTrue(id.Success);
|
||||
Assert.AreEqual(reservedId, id.Result);
|
||||
|
||||
// a random guid won't work
|
||||
Assert.IsFalse(service.GetIdForKey(Guid.NewGuid(), UmbracoObjectTypes.DocumentType).Success);
|
||||
}
|
||||
|
||||
private static bool _isSetup = false;
|
||||
|
||||
private int folderId;
|
||||
@@ -589,7 +613,7 @@ namespace Umbraco.Tests.Services
|
||||
|
||||
//Create and Save folder-Media -> 1050
|
||||
var folderMediaType = ServiceContext.ContentTypeService.GetMediaType(1031);
|
||||
var folder = MockedMedia.CreateMediaFolder(folderMediaType, -1);
|
||||
var folder = MockedMedia.CreateMediaFolder(folderMediaType, -1);
|
||||
ServiceContext.MediaService.Save(folder, 0);
|
||||
folderId = folder.Id;
|
||||
|
||||
@@ -607,9 +631,9 @@ namespace Umbraco.Tests.Services
|
||||
ServiceContext.MediaService.Save(subfolder, 0);
|
||||
var subfolder2 = MockedMedia.CreateMediaFolder(folderMediaType, subfolder.Id);
|
||||
ServiceContext.MediaService.Save(subfolder2, 0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@ namespace Umbraco.Tests.Strings
|
||||
Assert.IsTrue(foo.IsValid("futureTLD@somewhere.fooo"));
|
||||
|
||||
Assert.IsTrue(foo.IsValid("abc@xyz.financial"));
|
||||
Assert.IsTrue(foo.IsValid("admin+gmail-syntax@c.pizza"));
|
||||
Assert.IsTrue(foo.IsValid("admin@c.pizza"));
|
||||
|
||||
Assert.IsFalse(foo.IsValid("fdsa"));
|
||||
Assert.IsFalse(foo.IsValid("fdsa@"));
|
||||
|
||||
@@ -388,13 +388,12 @@ namespace Umbraco.Tests.TestHelpers
|
||||
return ctx;
|
||||
}
|
||||
|
||||
protected FakeHttpContextFactory GetHttpContextFactory(string url, RouteData routeData = null)
|
||||
protected virtual FakeHttpContextFactory GetHttpContextFactory(string url, RouteData routeData = null)
|
||||
{
|
||||
var factory = routeData != null
|
||||
? new FakeHttpContextFactory(url, routeData)
|
||||
: new FakeHttpContextFactory(url);
|
||||
|
||||
|
||||
//set the state helper
|
||||
StateHelper.HttpContext = factory.HttpContext;
|
||||
|
||||
|
||||
@@ -118,25 +118,12 @@ namespace Umbraco.Tests.TestHelpers
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// By default this returns false which means the plugin manager will not be reset so it doesn't need to re-scan
|
||||
/// all of the assemblies. Inheritors can override this if plugin manager resetting is required, generally needs
|
||||
/// to be set to true if the SetupPluginManager has been overridden.
|
||||
/// </summary>
|
||||
protected virtual bool PluginManagerResetRequired
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inheritors can resset the plugin manager if they choose to on teardown
|
||||
/// </summary>
|
||||
protected virtual void ResetPluginManager()
|
||||
{
|
||||
if (PluginManagerResetRequired)
|
||||
{
|
||||
PluginManager.Current = null;
|
||||
}
|
||||
PluginManager.Current = null;
|
||||
}
|
||||
|
||||
protected virtual CacheHelper CreateCacheHelper()
|
||||
@@ -185,26 +172,23 @@ namespace Umbraco.Tests.TestHelpers
|
||||
/// </summary>
|
||||
protected virtual void SetupPluginManager()
|
||||
{
|
||||
if (PluginManager.Current == null || PluginManagerResetRequired)
|
||||
PluginManager.Current = new PluginManager(
|
||||
new ActivatorServiceProvider(),
|
||||
CacheHelper.RuntimeCache, ProfilingLogger, false)
|
||||
{
|
||||
PluginManager.Current = new PluginManager(
|
||||
new ActivatorServiceProvider(),
|
||||
CacheHelper.RuntimeCache, ProfilingLogger, false)
|
||||
AssembliesToScan = new[]
|
||||
{
|
||||
AssembliesToScan = new[]
|
||||
{
|
||||
Assembly.Load("Umbraco.Core"),
|
||||
Assembly.Load("umbraco"),
|
||||
Assembly.Load("Umbraco.Tests"),
|
||||
Assembly.Load("businesslogic"),
|
||||
Assembly.Load("cms"),
|
||||
Assembly.Load("controls"),
|
||||
Assembly.Load("umbraco.editorControls"),
|
||||
Assembly.Load("umbraco.MacroEngines"),
|
||||
Assembly.Load("umbraco.providers"),
|
||||
}
|
||||
};
|
||||
}
|
||||
Assembly.Load("Umbraco.Core"),
|
||||
Assembly.Load("umbraco"),
|
||||
Assembly.Load("Umbraco.Tests"),
|
||||
Assembly.Load("businesslogic"),
|
||||
Assembly.Load("cms"),
|
||||
Assembly.Load("controls"),
|
||||
Assembly.Load("umbraco.editorControls"),
|
||||
Assembly.Load("umbraco.MacroEngines"),
|
||||
Assembly.Load("umbraco.providers"),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -7,11 +7,12 @@ using NUnit.Framework;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Deploy;
|
||||
using Umbraco.Core.Serialization;
|
||||
using Umbraco.Tests.TestHelpers;
|
||||
|
||||
namespace Umbraco.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class UdiTests
|
||||
public class UdiTests : BaseUmbracoApplicationTest
|
||||
{
|
||||
[Test]
|
||||
public void StringUdiCtorTest()
|
||||
|
||||
@@ -22,5 +22,40 @@ namespace Umbraco.Tests.Web.Mvc
|
||||
var expected = "<div><h1>hello world</h1><p>hello world<br />hello world<br />hello world<br />hello world</p></div>";
|
||||
Assert.AreEqual(expected, output);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TruncateWithElipsis()
|
||||
{
|
||||
var output = _htmlStringUtilities.Truncate("hello world", 5, true, false).ToString();
|
||||
var expected = "hello…";
|
||||
Assert.AreEqual(expected, output);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TruncateWithoutElipsis()
|
||||
{
|
||||
var output = _htmlStringUtilities.Truncate("hello world", 5, false, false).ToString();
|
||||
var expected = "hello";
|
||||
Assert.AreEqual(expected, output);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TruncateShorterWordThanHellip()
|
||||
{
|
||||
//http://issues.umbraco.org/issue/U4-10478
|
||||
var output = _htmlStringUtilities.Truncate("hi", 5, true, false).ToString();
|
||||
var expected = "hi";
|
||||
Assert.AreEqual(expected, output);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TruncateAndRemoveSpaceBetweenHellipAndWord()
|
||||
{
|
||||
var output = _htmlStringUtilities.Truncate("hello world", 6 /* hello plus space */, true, false).ToString();
|
||||
var expected = "hello…";
|
||||
Assert.AreEqual(expected, output);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -361,11 +361,29 @@ Umbraco.Sys.registerNamespace("Umbraco.Application");
|
||||
rootScope : function(){
|
||||
return getRootScope();
|
||||
},
|
||||
|
||||
reloadLocation: function() {
|
||||
var injector = getRootInjector();
|
||||
var $route = injector.get("$route");
|
||||
$route.reload();
|
||||
|
||||
/**
|
||||
This will reload the content frame based on it's current route, if pathToMatch is specified it will only reload it if the current
|
||||
location matches the path
|
||||
*/
|
||||
reloadLocation: function(pathToMatch) {
|
||||
|
||||
var injector = getRootInjector();
|
||||
var doChange = true;
|
||||
if (pathToMatch) {
|
||||
var $location = injector.get("$location");
|
||||
var path = $location.path();
|
||||
if (path != pathToMatch) {
|
||||
doChange = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (doChange) {
|
||||
var $route = injector.get("$route");
|
||||
$route.reload();
|
||||
var $rootScope = injector.get("$rootScope");
|
||||
$rootScope.$apply();
|
||||
}
|
||||
},
|
||||
|
||||
closeModalWindow: function(rVal) {
|
||||
|
||||
@@ -7,12 +7,22 @@ var app = angular.module("Umbraco.canvasdesigner", ['colorpicker', 'ui.slider',
|
||||
|
||||
.controller("Umbraco.canvasdesignerController", function ($scope, $http, $window, $timeout, $location, dialogService) {
|
||||
|
||||
var isInit = $location.search().init;
|
||||
if (isInit === "true") {
|
||||
//do not continue, this is the first load of this new window, if this is passed in it means it's been
|
||||
//initialized by the content editor and then the content editor will actually re-load this window without
|
||||
//this flag. This is a required trick to get around chrome popup mgr. We don't want to double load preview.aspx
|
||||
//since that will double prepare the preview documents
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.isOpen = false;
|
||||
$scope.frameLoaded = false;
|
||||
$scope.enableCanvasdesigner = 0;
|
||||
$scope.googleFontFamilies = {};
|
||||
$scope.pageId = $location.search().id;
|
||||
$scope.pageUrl = "../dialogs/Preview.aspx?id=" + $location.search().id;
|
||||
var pageId = $location.search().id;
|
||||
$scope.pageId = pageId;
|
||||
$scope.pageUrl = "../dialogs/Preview.aspx?id=" + pageId;
|
||||
$scope.valueAreLoaded = false;
|
||||
$scope.devices = [
|
||||
{ name: "desktop", css: "desktop", icon: "icon-display", title: "Desktop" },
|
||||
|
||||
+2
-2
@@ -208,9 +208,9 @@
|
||||
if (!$scope.busy) {
|
||||
|
||||
// Chromes popup blocker will kick in if a window is opened
|
||||
// outwith the initial scoped request. This trick will fix that.
|
||||
// without the initial scoped request. This trick will fix that.
|
||||
//
|
||||
var previewWindow = $window.open('preview/?id=' + content.id, 'umbpreview');
|
||||
var previewWindow = $window.open('preview/?init=true&id=' + content.id, 'umbpreview');
|
||||
|
||||
// Build the correct path so both /#/ and #/ work.
|
||||
var redirect = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/?id=' + content.id;
|
||||
|
||||
@@ -66,9 +66,13 @@ Use this directive to render an avatar.
|
||||
|
||||
function getNameInitials(name) {
|
||||
if(name) {
|
||||
var initials = name.match(/\b\w/g) || [];
|
||||
initials = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase();
|
||||
return initials;
|
||||
var names = name.split(' '),
|
||||
initials = names[0].substring(0, 1);
|
||||
|
||||
if (names.length > 1) {
|
||||
initials += names[names.length - 1].substring(0, 1);
|
||||
}
|
||||
return initials.toUpperCase();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// comes from https://codepen.io/jakob-e/pen/eNBQaP
|
||||
// works fine with Angular 1.6.5 - alas not with 1.1.5 - binding issue
|
||||
|
||||
function PasswordToggleDirective($compile) {
|
||||
|
||||
var directive = {
|
||||
restrict: 'A',
|
||||
scope: {},
|
||||
link: function(scope, elem, attrs) {
|
||||
scope.tgl = function () { elem.attr("type", (elem.attr("type") === "text" ? "password" : "text")); }
|
||||
var lnk = angular.element("<a data-ng-click=\"tgl()\">Toggle</a>");
|
||||
$compile(lnk)(scope);
|
||||
elem.wrap("<div class=\"password-toggle\"/>").after(lnk);
|
||||
}
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive('umbPasswordToggle', PasswordToggleDirective);
|
||||
|
||||
})();
|
||||
@@ -47,8 +47,8 @@ function valEmail(valEmailExpression) {
|
||||
angular.module('umbraco.directives.validation')
|
||||
.directive("valEmail", valEmail)
|
||||
.factory('valEmailExpression', function () {
|
||||
//NOTE: This is the fixed regex which is part of the newer angular
|
||||
var emailRegex = /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
|
||||
return {
|
||||
EMAIL_REGEXP: /^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i
|
||||
EMAIL_REGEXP: emailRegex
|
||||
};
|
||||
});
|
||||
@@ -2,12 +2,12 @@
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.assetsService
|
||||
*
|
||||
* @requires $q
|
||||
* @requires $q
|
||||
* @requires angularHelper
|
||||
*
|
||||
*
|
||||
* @description
|
||||
* Promise-based utillity service to lazy-load client-side dependencies inside angular controllers.
|
||||
*
|
||||
*
|
||||
* ##usage
|
||||
* To use, simply inject the assetsService into any controller that needs it, and make
|
||||
* sure the umbraco.services module is accesible - which it should be by default.
|
||||
@@ -18,7 +18,7 @@
|
||||
* //this code executes when the dependencies are done loading
|
||||
* });
|
||||
* });
|
||||
* </pre>
|
||||
* </pre>
|
||||
*
|
||||
* You can also load individual files, which gives you greater control over what attibutes are passed to the file, as well as timeout
|
||||
*
|
||||
@@ -38,13 +38,14 @@
|
||||
* //loadcss cannot determine when the css is done loading, so this will trigger instantly
|
||||
* });
|
||||
* });
|
||||
* </pre>
|
||||
* </pre>
|
||||
*/
|
||||
angular.module('umbraco.services')
|
||||
.factory('assetsService', function ($q, $log, angularHelper, umbRequestHelper, $rootScope, $http) {
|
||||
|
||||
var initAssetsLoaded = false;
|
||||
var appendRnd = function (url) {
|
||||
|
||||
function appendRnd (url) {
|
||||
//if we don't have a global umbraco obj yet, the app is bootstrapping
|
||||
if (!Umbraco.Sys.ServerVariables.application) {
|
||||
return url;
|
||||
@@ -77,7 +78,8 @@ angular.module('umbraco.services')
|
||||
return this.loadedAssets[path];
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
||||
/**
|
||||
Internal method. This is called when the application is loading and the user is already authenticated, or once the user is authenticated.
|
||||
There's a few assets the need to be loaded for the application to function but these assets require authentication to load.
|
||||
*/
|
||||
@@ -108,10 +110,10 @@ angular.module('umbraco.services')
|
||||
*
|
||||
* @description
|
||||
* Injects a file as a stylesheet into the document head
|
||||
*
|
||||
*
|
||||
* @param {String} path path to the css file to load
|
||||
* @param {Scope} scope optional scope to pass into the loader
|
||||
* @param {Object} keyvalue collection of attributes to pass to the stylesheet element
|
||||
* @param {Object} keyvalue collection of attributes to pass to the stylesheet element
|
||||
* @param {Number} timeout in milliseconds
|
||||
* @returns {Promise} Promise object which resolves when the file has loaded
|
||||
*/
|
||||
@@ -149,10 +151,10 @@ angular.module('umbraco.services')
|
||||
*
|
||||
* @description
|
||||
* Injects a file as a javascript into the document
|
||||
*
|
||||
*
|
||||
* @param {String} path path to the js file to load
|
||||
* @param {Scope} scope optional scope to pass into the loader
|
||||
* @param {Object} keyvalue collection of attributes to pass to the script element
|
||||
* @param {Object} keyvalue collection of attributes to pass to the script element
|
||||
* @param {Number} timeout in milliseconds
|
||||
* @returns {Promise} Promise object which resolves when the file has loaded
|
||||
*/
|
||||
@@ -192,8 +194,8 @@ angular.module('umbraco.services')
|
||||
* @methodOf umbraco.services.assetsService
|
||||
*
|
||||
* @description
|
||||
* Injects a collection of files, this can be ONLY js files
|
||||
*
|
||||
* Injects a collection of css and js files
|
||||
*
|
||||
*
|
||||
* @param {Array} pathArray string array of paths to the files to load
|
||||
* @param {Scope} scope optional scope to pass into the loader
|
||||
@@ -206,61 +208,72 @@ angular.module('umbraco.services')
|
||||
throw "pathArray must be an array";
|
||||
}
|
||||
|
||||
// Check to see if there's anything to load, resolve promise if not
|
||||
var nonEmpty = _.reject(pathArray, function (item) {
|
||||
return item === undefined || item === "";
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//don't load anything if there's nothing to load
|
||||
if (nonEmpty.length > 0) {
|
||||
var promises = [];
|
||||
var assets = [];
|
||||
|
||||
//compile a list of promises
|
||||
//blocking
|
||||
_.each(nonEmpty, function (path) {
|
||||
|
||||
path = convertVirtualPath(path);
|
||||
|
||||
var asset = service._getAssetPromise(path);
|
||||
//if not previously loaded, add to list of promises
|
||||
if (asset.state !== "loaded") {
|
||||
if (asset.state === "new") {
|
||||
asset.state = "loading";
|
||||
assets.push(asset);
|
||||
}
|
||||
|
||||
//we need to always push to the promises collection to monitor correct
|
||||
//execution
|
||||
promises.push(asset.deferred.promise);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//gives a central monitoring of all assets to load
|
||||
promise = $q.all(promises);
|
||||
|
||||
_.each(assets, function (asset) {
|
||||
LazyLoad.js(appendRnd(asset.path), function () {
|
||||
asset.state = "loaded";
|
||||
if (!scope) {
|
||||
asset.deferred.resolve(true);
|
||||
}
|
||||
else {
|
||||
angularHelper.safeApply(scope, function () {
|
||||
asset.deferred.resolve(true);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
//return and resolve
|
||||
if (nonEmpty.length === 0) {
|
||||
var deferred = $q.defer();
|
||||
promise = deferred.promise;
|
||||
deferred.resolve(true);
|
||||
return promise;
|
||||
}
|
||||
|
||||
//compile a list of promises
|
||||
//blocking
|
||||
var promises = [];
|
||||
var assets = [];
|
||||
_.each(nonEmpty, function (path) {
|
||||
path = convertVirtualPath(path);
|
||||
var asset = service._getAssetPromise(path);
|
||||
//if not previously loaded, add to list of promises
|
||||
if (asset.state !== "loaded") {
|
||||
if (asset.state === "new") {
|
||||
asset.state = "loading";
|
||||
assets.push(asset);
|
||||
}
|
||||
|
||||
//we need to always push to the promises collection to monitor correct
|
||||
//execution
|
||||
promises.push(asset.deferred.promise);
|
||||
}
|
||||
});
|
||||
|
||||
//gives a central monitoring of all assets to load
|
||||
promise = $q.all(promises);
|
||||
|
||||
// Split into css and js asset arrays, and use LazyLoad on each array
|
||||
var cssAssets = _.filter(assets,
|
||||
function (asset) {
|
||||
return asset.path.match(/(\.css$|\.css\?)/ig);
|
||||
});
|
||||
var jsAssets = _.filter(assets,
|
||||
function (asset) {
|
||||
return asset.path.match(/(\.js$|\.js\?)/ig);
|
||||
});
|
||||
|
||||
function assetLoaded(asset) {
|
||||
asset.state = "loaded";
|
||||
if (!scope) {
|
||||
asset.deferred.resolve(true);
|
||||
return;
|
||||
}
|
||||
angularHelper.safeApply(scope,
|
||||
function () {
|
||||
asset.deferred.resolve(true);
|
||||
});
|
||||
}
|
||||
|
||||
if (cssAssets.length > 0) {
|
||||
var cssPaths = _.map(cssAssets, function (asset) { return appendRnd(asset.path) });
|
||||
LazyLoad.css(cssPaths, function() { _.each(cssAssets, assetLoaded); });
|
||||
}
|
||||
|
||||
if (jsAssets.length > 0) {
|
||||
var jsPaths = _.map(jsAssets, function (asset) { return appendRnd(asset.path) });
|
||||
LazyLoad.js(jsPaths, function () { _.each(jsAssets, assetLoaded); });
|
||||
}
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
@@ -269,7 +269,8 @@
|
||||
var isSelected = false;
|
||||
for (var i = 0; selection.length > i; i++) {
|
||||
var selectedItem = selection[i];
|
||||
if (item.id === selectedItem.id || item.key === selectedItem.key) {
|
||||
// if item.id is 2147483647 (int.MaxValue) use item.key
|
||||
if ((item.id !== 2147483647 && item.id === selectedItem.id) || item.key === selectedItem.key) {
|
||||
isSelected = true;
|
||||
}
|
||||
}
|
||||
@@ -294,7 +295,8 @@
|
||||
function deselectItem(item, selection) {
|
||||
for (var i = 0; selection.length > i; i++) {
|
||||
var selectedItem = selection[i];
|
||||
if (item.id === selectedItem.id) {
|
||||
// if item.id is 2147483647 (int.MaxValue) use item.key
|
||||
if ((item.id !== 2147483647 && item.id === selectedItem.id) || item.key === selectedItem.key) {
|
||||
selection.splice(i, 1);
|
||||
item.selected = false;
|
||||
}
|
||||
@@ -366,7 +368,7 @@
|
||||
var item = items[i];
|
||||
|
||||
if (checkbox.checked) {
|
||||
selection.push({ id: item.id });
|
||||
selection.push({ id: item.id, key: item.key });
|
||||
} else {
|
||||
clearSelection = true;
|
||||
}
|
||||
@@ -405,7 +407,8 @@
|
||||
for (var selectedIndex = 0; selection.length > selectedIndex; selectedIndex++) {
|
||||
var selectedItem = selection[selectedIndex];
|
||||
|
||||
if (item.id === selectedItem.id) {
|
||||
// if item.id is 2147483647 (int.MaxValue) use item.key
|
||||
if ((item.id !== 2147483647 && item.id === selectedItem.id) || item.key === selectedItem.key) {
|
||||
numberOfSelectedItem++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,18 @@
|
||||
{ "value": 3, "name": "Invited", "key": "Invited", "color": "warning" }
|
||||
];
|
||||
|
||||
angular.forEach(userStates, function (userState) {
|
||||
var key = "user_state" + userState.key;
|
||||
localizationService.localize(key).then(function (value) {
|
||||
var reg = /^\[[\S\s]*]$/g;
|
||||
var result = reg.test(value);
|
||||
if (result === false) {
|
||||
// Only translate if key exists
|
||||
userState.name = value;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function getUserStateFromValue(value) {
|
||||
var foundUserState;
|
||||
angular.forEach(userStates, function (userState) {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="email">Email</label>
|
||||
<div class="controls">
|
||||
<input type="text" id="email" name="email" placeholder="you@example.com" required ng-model="installer.current.model.email" val-email />
|
||||
<input type="email" id="email" name="email" placeholder="you@example.com" required ng-model="installer.current.model.email" val-email />
|
||||
<small class="inline-help">Your email will be used as your login</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -261,6 +261,9 @@ input[type="submit"].btn {
|
||||
*padding-top: 1px;
|
||||
*padding-bottom: 1px;
|
||||
}
|
||||
|
||||
// Safari defaults to 1px for input. Ref U4-7721.
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
background: @white;
|
||||
z-index: 7500;
|
||||
z-index: @zindexUmbOverlay;
|
||||
animation: fadeIn 0.2s;
|
||||
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(255, 255, 255, 0.50);
|
||||
z-index: 2000;
|
||||
z-index: @zindexOverlayBackdrop;
|
||||
top: 0;
|
||||
left: 0;
|
||||
animation: fadeIn 0.2s;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
color: @black;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
|
||||
@@ -35,3 +35,10 @@
|
||||
margin-right: 5px;
|
||||
color: @gray-7;
|
||||
}
|
||||
|
||||
input.umb-breadcrumbs__add-ancestor {
|
||||
height: 25px;
|
||||
margin-top: -2px;
|
||||
margin-left: 3px;
|
||||
width: 100px;
|
||||
}
|
||||
@@ -636,9 +636,19 @@
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.umb-grid .mce-btn button {
|
||||
padding: 8px 6px;
|
||||
line-height: inherit;
|
||||
.umb-grid .mce-btn {
|
||||
button {
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
padding-left: 6px;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
&:not(.mce-menubtn) {
|
||||
button {
|
||||
padding-right: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.umb-grid .mce-toolbar {
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
flex: 0 0 100%;
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.umb-user-card:hover,
|
||||
|
||||
@@ -5,21 +5,20 @@
|
||||
top: -30px;
|
||||
padding-top: 30px;
|
||||
box-shadow: inset 0px -40px 30px 25px rgba(255,255,255,1);
|
||||
border-radius: 0px 0px 200px 200px;
|
||||
-moz-border-radius: 0px 0px 200px 200px;
|
||||
-moz-border-radius: 0px 0px 200px 200px;
|
||||
-webkit-border-radius: 0px 0px 200px 200px;
|
||||
border-radius: 0px 0px 200px 200px;
|
||||
|
||||
small {
|
||||
font-size: 14px;
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.umb-loader{
|
||||
.umb-loader {
|
||||
width: 640px;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
|
||||
.video_player{
|
||||
video {
|
||||
width: 100%;
|
||||
@@ -27,8 +26,8 @@
|
||||
border: 1px solid @gray-9;
|
||||
border-left: none;
|
||||
border-bottom: none;
|
||||
-moz-box-sizing:border-box;
|
||||
box-sizing:border-box;
|
||||
-moz-box-sizing:border-box;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
@@ -67,8 +66,8 @@
|
||||
|
||||
.progress-bar {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
-moz-box-sizing:border-box;
|
||||
-moz-box-sizing:border-box;
|
||||
box-sizing: border-box;
|
||||
max-width: 100%;
|
||||
width: 200px;
|
||||
height: 100%;
|
||||
@@ -112,26 +111,25 @@
|
||||
line-height: 80px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
i, h3 {
|
||||
.icon, h3 {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
i {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
margin-top: -40px;
|
||||
.icon {
|
||||
font-size: 80px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
margin: 0 0 0 20px;
|
||||
line-height: 80px;
|
||||
font-weight: 700;
|
||||
margin-left: 100px;
|
||||
font-size: 36px;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -249,6 +249,11 @@
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
// fix dropdown with checkbox + long text in label
|
||||
.dropdown-menu > li > .flex > label {
|
||||
flex: 1 1 0;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a {
|
||||
padding: 8px 20px;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.login-overlay .form input[type="text"],
|
||||
.login-overlay .form input[type="text"],
|
||||
.login-overlay .form input[type="password"],
|
||||
.login-overlay .form input[type="email"] {
|
||||
height: 36px;
|
||||
@@ -114,8 +114,44 @@
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.login-overlay .text-error,
|
||||
.login-overlay .text-info
|
||||
.login-overlay .text-error,
|
||||
.login-overlay .text-info
|
||||
{
|
||||
font-weight:bold;
|
||||
}
|
||||
}
|
||||
|
||||
.password-toggle {
|
||||
position: relative;
|
||||
display: block;
|
||||
user-select: none;
|
||||
|
||||
input::-ms-clear, input::-ms-reveal {
|
||||
display: none;
|
||||
}
|
||||
|
||||
a {
|
||||
opacity: .5;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
height: 1px;
|
||||
width: 45px;
|
||||
height: 75%;
|
||||
font-size: 0;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 50%;
|
||||
background-position: center;
|
||||
top: 0;
|
||||
margin-left: -45px;
|
||||
z-index: 1;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
[type="text"] + a {
|
||||
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M29.6.4C29 0 28 0 27.4.4L21 6.8c-1.4-.5-3-.8-5-.8C9 6 3 10 0 16c1.3 2.6 3 4.8 5.4 6.5l-5 5c-.5.5-.5 1.5 0 2 .3.4.7.5 1 .5s1 0 1.2-.4l27-27C30 2 30 1 29.6.4zM13 10c1.3 0 2.4 1 2.8 2L12 15.8c-1-.4-2-1.5-2-2.8 0-1.7 1.3-3 3-3zm-9.6 6c1.2-2 2.8-3.5 4.7-4.7l.7-.2c-.4 1-.6 2-.6 3 0 1.8.6 3.4 1.6 4.7l-2 2c-1.6-1.2-3-2.7-4-4.4zM24 13.8c0-.8 0-1.7-.4-2.4l-10 10c.7.3 1.6.4 2.4.4 4.4 0 8-3.6 8-8z'/%3E%3Cpath fill='%23444' d='M26 9l-2.2 2.2c2 1.3 3.6 3 4.8 4.8-1.2 2-2.8 3.5-4.7 4.7-2.7 1.5-5.4 2.3-8 2.3-1.4 0-2.6 0-3.8-.4L10 25c2 .6 4 1 6 1 7 0 13-4 16-10-1.4-2.8-3.5-5.2-6-7z'/%3E%3C/svg%3E");
|
||||
}
|
||||
|
||||
[type="password"] + a {
|
||||
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M16 6C9 6 3 10 0 16c3 6 9 10 16 10s13-4 16-10c-3-6-9-10-16-10zm8 5.3c1.8 1.2 3.4 2.8 4.6 4.7-1.2 2-2.8 3.5-4.7 4.7-3 1.5-6 2.3-8 2.3s-6-.8-8-2.3C6 19.5 4 18 3 16c1.5-2 3-3.5 5-4.7l.6-.2C8 12 8 13 8 14c0 4.5 3.5 8 8 8s8-3.5 8-8c0-1-.3-2-.6-2.6l.4.3zM16 13c0 1.7-1.3 3-3 3s-3-1.3-3-3 1.3-3 3-3 3 1.3 3 3z'/%3E%3C/svg%3E");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,16 +109,48 @@ ul.color-picker li a {
|
||||
}
|
||||
|
||||
/* pre-value editor */
|
||||
|
||||
/*.control-group.color-picker-preval:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 100%;
|
||||
}*/
|
||||
|
||||
/*.control-group.color-picker-preval div.thumbnail {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}*/
|
||||
.control-group.color-picker-preval div.color-picker-prediv {
|
||||
display: inline-block;
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval pre {
|
||||
display: inline;
|
||||
margin-right: 20px;
|
||||
margin-left: 10px;
|
||||
width: 50%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
margin-bottom: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval btn {
|
||||
//vertical-align: middle;
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval input[type="text"] {
|
||||
min-width: 40%;
|
||||
width: 40%;
|
||||
display: inline-block;
|
||||
margin-right: 20px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.control-group.color-picker-preval label {
|
||||
border:solid @white 1px;
|
||||
padding:6px;
|
||||
border: solid @white 1px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,21 +158,21 @@ ul.color-picker li a {
|
||||
// Media picker
|
||||
// --------------------------------------------------
|
||||
.umb-mediapicker .add-link {
|
||||
display: inline-block;
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
text-align: center;
|
||||
color: @gray-8;
|
||||
border: 2px @gray-8 dashed;
|
||||
line-height: 120px;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
justify-content:center;
|
||||
align-items:center;
|
||||
width: 120px;
|
||||
text-align: center;
|
||||
color: @gray-8;
|
||||
border: 2px @gray-8 dashed;
|
||||
text-decoration: none;
|
||||
|
||||
transition: all 150ms ease-in-out;
|
||||
transition: all 150ms ease-in-out;
|
||||
|
||||
&:hover {
|
||||
color: @turquoise-d1;
|
||||
border-color: @turquoise;
|
||||
}
|
||||
&:hover {
|
||||
color: @turquoise-d1;
|
||||
border-color: @turquoise;
|
||||
}
|
||||
}
|
||||
|
||||
.umb-mediapicker .picked-image {
|
||||
@@ -165,6 +197,10 @@ ul.color-picker li a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-mediapicker .add-link-square {
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.umb-thumbnails{
|
||||
@@ -207,11 +243,10 @@ ul.color-picker li a {
|
||||
|
||||
.umb-mediapicker .umb-sortable-thumbnails li {
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
margin: 0 5px 0 0;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
|
||||
.umb-sortable-thumbnails li:hover a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@@ -219,16 +254,20 @@ ul.color-picker li a {
|
||||
}
|
||||
|
||||
.umb-sortable-thumbnails li img {
|
||||
max-width:100%;
|
||||
max-height:100%;
|
||||
margin:auto;
|
||||
display:block;
|
||||
background-image: url(../img/checkered-background.png);
|
||||
max-width:100%;
|
||||
max-height:100%;
|
||||
margin:auto;
|
||||
display:block;
|
||||
background-image: url(../img/checkered-background.png);
|
||||
}
|
||||
|
||||
.umb-sortable-thumbnails li img.noScale{
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
.umb-sortable-thumbnails li img.trashed {
|
||||
opacity:0.3;
|
||||
}
|
||||
|
||||
.umb-sortable-thumbnails li img.noScale {
|
||||
max-width: none !important;
|
||||
max-height: none !important;
|
||||
}
|
||||
|
||||
.umb-sortable-thumbnails .umb-icon-holder {
|
||||
@@ -254,8 +293,8 @@ ul.color-picker li a {
|
||||
}
|
||||
|
||||
.umb-sortable-thumbnails li:hover .umb-sortable-thumbnails__actions {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.umb-sortable-thumbnails .umb-sortable-thumbnails__action {
|
||||
@@ -285,27 +324,27 @@ ul.color-picker li a {
|
||||
// -------------------------------------------------
|
||||
|
||||
.umb-cropper{
|
||||
position: relative;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.umb-cropper img, .umb-cropper-gravity img{
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: relative;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.umb-cropper img {
|
||||
max-width: none;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.umb-cropper .overlay, .umb-cropper-gravity .overlay {
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: move;
|
||||
z-index: 6001;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
cursor: move;
|
||||
z-index: @zindexCropperOverlay;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.umb-cropper .viewport{
|
||||
@@ -317,43 +356,43 @@ ul.color-picker li a {
|
||||
}
|
||||
|
||||
.umb-cropper-gravity .viewport{
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.umb-cropper .viewport:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 5999;
|
||||
-moz-opacity: .75;
|
||||
opacity: .75;
|
||||
filter: alpha(opacity=7);
|
||||
-webkit-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
|
||||
box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: @zindexCropperOverlay - 1;
|
||||
-moz-opacity: .75;
|
||||
opacity: .75;
|
||||
filter: alpha(opacity=7);
|
||||
-webkit-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
|
||||
box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.umb-cropper-gravity .overlay{
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
text-align: center;
|
||||
border-radius: 20px;
|
||||
background: @turquoise;
|
||||
border: 3px solid @white;
|
||||
opacity: 0.8;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
text-align: center;
|
||||
border-radius: 20px;
|
||||
background: @turquoise;
|
||||
border: 3px solid @white;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.umb-cropper-gravity .overlay i {
|
||||
font-size: 26px;
|
||||
line-height: 26px;
|
||||
opacity: 0.8 !important;
|
||||
font-size: 26px;
|
||||
line-height: 26px;
|
||||
opacity: 0.8 !important;
|
||||
}
|
||||
|
||||
.umb-cropper .crop-container {
|
||||
@@ -361,16 +400,16 @@ ul.color-picker li a {
|
||||
}
|
||||
|
||||
.umb-cropper .crop-slider {
|
||||
padding: 10px;
|
||||
border-top: 1px solid @gray-10;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
@media (min-width: 769px) {
|
||||
padding: 10px;
|
||||
border-top: 1px solid @gray-10;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
@media (min-width: 769px) {
|
||||
padding: 10px 50px 10px 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.umb-cropper .crop-slider i {
|
||||
@@ -438,6 +477,7 @@ ul.color-picker li a {
|
||||
top: 3px;
|
||||
right: 3px;
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.umb-close-cropper:hover {
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
|
||||
.umb-tree div > a.umb-options {
|
||||
visibility: hidden;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
.umb-tree div:hover > a.umb-options {
|
||||
visibility: visible;
|
||||
@@ -156,8 +157,8 @@
|
||||
|
||||
.umb-tree li > div a:not(.umb-options) {
|
||||
padding: 6px 0;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex: 1 1 100%;
|
||||
}
|
||||
|
||||
.umb-tree li > div:hover a:not(.umb-options) {
|
||||
|
||||
@@ -230,6 +230,12 @@
|
||||
@zindexModalBackdrop: 1040;
|
||||
@zindexModal: 1050;
|
||||
|
||||
@zindexUmbOverlay: 7500;
|
||||
@zindexOverlayBackdrop: 2000;
|
||||
|
||||
// Sticky bar has a z-index of "500", which is set from javascript in directive
|
||||
// so set z-index of cropper should be lower to be behind sticky bar.
|
||||
@zindexCropperOverlay: 499;
|
||||
|
||||
// Sprite icons path
|
||||
// -------------------------
|
||||
|
||||
@@ -31,6 +31,12 @@ app.config(function ($routeProvider) {
|
||||
userService.getCurrentUser({ broadcastEvent: broadcast }).then(function (user) {
|
||||
//is auth, check if we allow or reject
|
||||
if (isRequired) {
|
||||
|
||||
//This checks the current section and will force a redirect to 'content' as the default
|
||||
if ($route.current.params.section.toLowerCase() === "default" || $route.current.params.section.toLowerCase() === "umbraco" || $route.current.params.section === "") {
|
||||
$route.current.params.section = "content";
|
||||
}
|
||||
|
||||
// U4-5430, Benjamin Howarth
|
||||
// We need to change the current route params if the user only has access to a single section
|
||||
// To do this we need to grab the current user's allowed sections, then reject the promise with the correct path.
|
||||
@@ -98,26 +104,24 @@ app.config(function ($routeProvider) {
|
||||
resolve: doLogout()
|
||||
})
|
||||
.when('/:section', {
|
||||
|
||||
//This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method.
|
||||
template: "<div ng-include='templateUrl'></div>",
|
||||
//This controller will execute for this route, then we can execute some code in order to set the template Url
|
||||
controller: function ($scope, $route, $routeParams, $location, sectionService) {
|
||||
if ($routeParams.section.toLowerCase() === "default" || $routeParams.section.toLowerCase() === "umbraco" || $routeParams.section === "") {
|
||||
$routeParams.section = "content";
|
||||
}
|
||||
|
||||
//We are going to check the currently loaded sections for the user and if the section we are navigating
|
||||
|
||||
//We are going to check the currently loaded sections for the user and if the section we are navigating
|
||||
//to has a custom route path we'll use that
|
||||
sectionService.getSectionsForUser().then(function(sections) {
|
||||
//find the one we're requesting
|
||||
//find the one we're requesting
|
||||
var found = _.find(sections, function(s) {
|
||||
return s.alias === $routeParams.section;
|
||||
})
|
||||
})
|
||||
if (found && found.routePath) {
|
||||
//there's a custom route path so redirect
|
||||
$location.path(found.routePath);
|
||||
}
|
||||
else {
|
||||
else {
|
||||
//there's no custom route path so continue as normal
|
||||
$routeParams.url = "dashboard.aspx?app=" + $routeParams.section;
|
||||
$scope.templateUrl = 'views/common/dashboard.html';
|
||||
@@ -138,8 +142,8 @@ app.config(function ($routeProvider) {
|
||||
})
|
||||
.when('/:section/:tree/:method', {
|
||||
templateUrl: function (rp) {
|
||||
|
||||
//if there is no method registered for this then show the dashboard
|
||||
|
||||
//if there is no method registered for this then show the dashboard
|
||||
if (!rp.method)
|
||||
return "views/common/dashboard.html";
|
||||
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
maxFileSize: Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB",
|
||||
acceptedFileTypes: mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes),
|
||||
uploaded: false
|
||||
}
|
||||
}
|
||||
$scope.togglePassword = function () {
|
||||
var elem = $("form[name='loginForm'] input[name='password']");
|
||||
elem.attr("type", (elem.attr("type") === "text" ? "password" : "text"));
|
||||
}
|
||||
|
||||
function init() {
|
||||
// Check if it is a new user
|
||||
@@ -48,7 +52,7 @@
|
||||
]).then(function () {
|
||||
|
||||
$scope.inviteStep = Number(inviteVal);
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -82,7 +86,7 @@
|
||||
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10);
|
||||
|
||||
// set percentage property on file
|
||||
$scope.avatarFile.uploadProgress = progressPercentage;
|
||||
$scope.avatarFile.uploadProgress = progressPercentage;
|
||||
}
|
||||
|
||||
}).success(function (data, status, headers, config) {
|
||||
@@ -149,11 +153,11 @@
|
||||
|
||||
//error
|
||||
formHelper.handleError(err);
|
||||
|
||||
|
||||
$scope.invitedUserPasswordModel.buttonState = "error";
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var setFieldFocus = function (form, field) {
|
||||
@@ -180,7 +184,7 @@
|
||||
}
|
||||
|
||||
function resetInputValidation() {
|
||||
$scope.confirmPassword = "";
|
||||
$scope.confirmPassword = "";
|
||||
$scope.password = "";
|
||||
$scope.login = "";
|
||||
if ($scope.loginForm) {
|
||||
@@ -255,7 +259,7 @@
|
||||
|
||||
//TODO: Do validation properly like in the invite password update
|
||||
|
||||
//if the login and password are not empty we need to automatically
|
||||
//if the login and password are not empty we need to automatically
|
||||
// validate them - this is because if there are validation errors on the server
|
||||
// then the user has to change both username & password to resubmit which isn't ideal,
|
||||
// so if they're not empty, we'll just make sure to set them to valid.
|
||||
@@ -289,7 +293,7 @@
|
||||
});
|
||||
|
||||
//setup a watch for both of the model values changing, if they change
|
||||
// while the form is invalid, then revalidate them so that the form can
|
||||
// while the form is invalid, then revalidate them so that the form can
|
||||
// be submitted again.
|
||||
$scope.loginForm.username.$viewChangeListeners.push(function () {
|
||||
if ($scope.loginForm.username.$invalid) {
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
</label>
|
||||
<input type="password" ng-model="invitedUserPasswordModel.password" name="password" class="-full-width-input" umb-auto-focus required val-server-field="value" autocomplete="off" ng-minlength="{{invitedUserPasswordModel.passwordPolicies.minPasswordLength}}" />
|
||||
<span class="help-inline" val-msg-for="password" val-toggle-msg="required"><localize key="user_passwordIsBlank">Your new password cannot be blank!</localize></span>
|
||||
<span class="help-inline" val-msg-for="password" val-toggle-msg="minlength">Minimum {{invitedUserPasswordModel.passwordPolicies.minPasswordLength}} characters</span>
|
||||
<span class="help-inline" val-msg-for="password" val-toggle-msg="valServerField"></span>
|
||||
<span class="help-inline" val-msg-for="password" val-toggle-msg="minlength">Minimum {{invitedUserPasswordModel.passwordPolicies.minPasswordLength}} characters</span>
|
||||
<span class="help-inline" val-msg-for="password" val-toggle-msg="valServerField"></span>
|
||||
</div>
|
||||
|
||||
<div class="control-group" ng-class="{error: setPasswordForm.confirmPassword.$invalid}">
|
||||
@@ -49,15 +49,15 @@
|
||||
<div class="form" ng-if="inviteStep === 2">
|
||||
|
||||
<div class="flex justify-center items-center">
|
||||
|
||||
|
||||
<ng-form name="avatarForm">
|
||||
|
||||
|
||||
<umb-progress-bar style="max-width: 100px; margin-bottom: 5px;"
|
||||
ng-show="avatarFile.uploadStatus === 'uploading'"
|
||||
progress="{{ avatarFile.uploadProgress }}"
|
||||
size="s">
|
||||
</umb-progress-bar>
|
||||
|
||||
|
||||
<div class="umb-info-local-item text-error mt3" ng-if="avatarFile.uploadStatus === 'error'">
|
||||
{{ avatarFile.serverErrorMessage }}
|
||||
</div>
|
||||
@@ -69,7 +69,7 @@
|
||||
ngf-multiple="false"
|
||||
ngf-pattern="{{avatarFile.acceptedFileTypes}}"
|
||||
ngf-max-size="{{ avatarFile.maxFileSize }}">
|
||||
|
||||
|
||||
<umb-avatar color="gray"
|
||||
size="xl"
|
||||
unknown-char="+"
|
||||
@@ -77,7 +77,7 @@
|
||||
img-srcset="{{invitedUser.avatars[4]}} 2x, {{invitedUser.avatars[4]}} 3x">
|
||||
</umb-avatar>
|
||||
</a>
|
||||
|
||||
|
||||
</ng-form>
|
||||
</div>
|
||||
|
||||
@@ -149,8 +149,9 @@
|
||||
|
||||
<div class="control-group" ng-class="{error: loginForm.password.$invalid}">
|
||||
<label><localize key="general_password">Password</localize></label>
|
||||
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" autocomplete="off" />
|
||||
</div>
|
||||
<div class="password-toggle">
|
||||
<input type="password" ng-model="password" name="password" class="-full-width-input" localize="placeholder" placeholder="@placeholders_password" autocomplete="off" /><a ng-click="togglePassword()">Toggle</a>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center">
|
||||
<button type="submit" class="btn btn-success" val-trigger-change="#login .form input"><localize key="general_login">Login</localize></button>
|
||||
|
||||
+44
-27
@@ -56,6 +56,46 @@ angular.module("umbraco")
|
||||
$scope.target = dialogOptions.currentTarget;
|
||||
}
|
||||
|
||||
function onInit() {
|
||||
if ($scope.startNodeId !== -1) {
|
||||
entityResource.getById($scope.startNodeId, "media")
|
||||
.then(function (ent) {
|
||||
$scope.startNodeId = ent.id;
|
||||
run();
|
||||
});
|
||||
} else {
|
||||
run();
|
||||
}
|
||||
}
|
||||
|
||||
function run() {
|
||||
//default root item
|
||||
if (!$scope.target) {
|
||||
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
|
||||
entityResource.getById($scope.lastOpenedNode, "media")
|
||||
.then(ensureWithinStartNode, gotoStartNode);
|
||||
} else {
|
||||
gotoStartNode();
|
||||
}
|
||||
} else {
|
||||
//if a target is specified, go look it up - generally this target will just contain ids not the actual full
|
||||
//media object so we need to look it up
|
||||
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
|
||||
var altText = $scope.target.altText;
|
||||
mediaResource.getById(id)
|
||||
.then(function (node) {
|
||||
$scope.target = node;
|
||||
if (ensureWithinStartNode(node)) {
|
||||
selectImage(node);
|
||||
$scope.target.url = mediaHelper.resolveFile(node);
|
||||
$scope.target.altText = altText;
|
||||
$scope.openDetailsDialog();
|
||||
}
|
||||
},
|
||||
gotoStartNode);
|
||||
}
|
||||
}
|
||||
|
||||
$scope.upload = function(v) {
|
||||
angular.element(".umb-file-dropzone-directive .file-select").click();
|
||||
};
|
||||
@@ -107,7 +147,7 @@ angular.module("umbraco")
|
||||
|
||||
if (folder.id > 0) {
|
||||
entityResource.getAncestors(folder.id, "media")
|
||||
.then(function(anc) {
|
||||
.then(function(anc) {
|
||||
$scope.path = _.filter(anc,
|
||||
function(f) {
|
||||
return f.path.indexOf($scope.startNodeId) !== -1;
|
||||
@@ -218,32 +258,6 @@ angular.module("umbraco")
|
||||
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
|
||||
}
|
||||
|
||||
//default root item
|
||||
if (!$scope.target) {
|
||||
if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
|
||||
entityResource.getById($scope.lastOpenedNode, "media")
|
||||
.then(ensureWithinStartNode, gotoStartNode);
|
||||
} else {
|
||||
gotoStartNode();
|
||||
}
|
||||
} else {
|
||||
//if a target is specified, go look it up - generally this target will just contain ids not the actual full
|
||||
//media object so we need to look it up
|
||||
var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
|
||||
var altText = $scope.target.altText;
|
||||
mediaResource.getById(id)
|
||||
.then(function(node) {
|
||||
$scope.target = node;
|
||||
if (ensureWithinStartNode(node)) {
|
||||
selectImage(node);
|
||||
$scope.target.url = mediaHelper.resolveFile(node);
|
||||
$scope.target.altText = altText;
|
||||
$scope.openDetailsDialog();
|
||||
}
|
||||
},
|
||||
gotoStartNode);
|
||||
}
|
||||
|
||||
$scope.openDetailsDialog = function() {
|
||||
|
||||
$scope.mediaPickerDetailsOverlay = {};
|
||||
@@ -368,4 +382,7 @@ angular.module("umbraco")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onInit();
|
||||
|
||||
});
|
||||
@@ -48,14 +48,14 @@
|
||||
<span class="umb-breadcrumbs__seperator">/</span>
|
||||
</li>
|
||||
|
||||
<li class="umb-breadcrumbs__ancestor" ng-if="!lockedFolder">
|
||||
<li class="umb-breadcrumbs__ancestor" ng-show="!lockedFolder">
|
||||
<a href ng-hide="showFolderInput" ng-click="showFolderInput = true">
|
||||
<i class="icon icon-add small"></i>
|
||||
</a>
|
||||
|
||||
<input
|
||||
type="text"
|
||||
class="input-foldername input-mini inline"
|
||||
class="umb-breadcrumbs__add-ancestor"
|
||||
ng-show="showFolderInput"
|
||||
ng-model="newFolderName"
|
||||
ng-keydown="enterSubmitFolder($event)"
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
<a class="umb-node-preview__action" title="Open" href="" ng-if="allowEdit" ng-click="onEdit()"><localize key="general_edit">Edit</localize></a>
|
||||
<a class="umb-node-preview__action" title="Open" href="" ng-if="allowOpen" ng-click="onOpen()"><localize key="general_open">Open</localize></a>
|
||||
<a class="umb-node-preview__action umb-node-preview__action--red" title="Remove" href="" ng-if="allowRemove" ng-click="onRemove()"><localize key="general_remove">Remove</localize></i></a>
|
||||
<div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div style="max-width: 800px; text-align: center; margin: auto; padding: 20px; min-height: 800px;">
|
||||
|
||||
<div class="installer-top"> <!-- ADDED -->
|
||||
<i style="font-size: 80px" class="icon icon-umb-contour"></i>
|
||||
<i class="icon icon-umb-contour"></i>
|
||||
<h3>Umbraco Forms</h3>
|
||||
</div> <!-- ADDED -->
|
||||
|
||||
|
||||
+122
-16
@@ -1,25 +1,131 @@
|
||||
function ColorPickerController($scope) {
|
||||
$scope.toggleItem = function (color) {
|
||||
if ($scope.model.value == color) {
|
||||
$scope.model.value = "";
|
||||
//this is required to re-validate
|
||||
$scope.propertyForm.modelValue.$setViewValue($scope.model.value);
|
||||
}
|
||||
else {
|
||||
$scope.model.value = color;
|
||||
//this is required to re-validate
|
||||
$scope.propertyForm.modelValue.$setViewValue($scope.model.value);
|
||||
}
|
||||
};
|
||||
function ColorPickerController($scope) {
|
||||
|
||||
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
|
||||
|
||||
if ($scope.isConfigured) {
|
||||
|
||||
for (var key in $scope.model.config.items) {
|
||||
if (!$scope.model.config.items[key].hasOwnProperty("value"))
|
||||
$scope.model.config.items[key] = { value: $scope.model.config.items[key], label: $scope.model.config.items[key] };
|
||||
}
|
||||
|
||||
$scope.model.useLabel = isTrue($scope.model.config.useLabel);
|
||||
initActiveColor();
|
||||
}
|
||||
|
||||
$scope.toggleItem = function (color) {
|
||||
|
||||
var currentColor = $scope.model.value.hasOwnProperty("value")
|
||||
? $scope.model.value.value
|
||||
: $scope.model.value;
|
||||
|
||||
var newColor;
|
||||
if (currentColor === color.value) {
|
||||
// deselect
|
||||
$scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
|
||||
newColor = "";
|
||||
}
|
||||
else {
|
||||
// select
|
||||
$scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
|
||||
newColor = color.value;
|
||||
}
|
||||
|
||||
// this is required to re-validate
|
||||
$scope.propertyForm.modelValue.$setViewValue(newColor);
|
||||
};
|
||||
|
||||
// Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected)
|
||||
$scope.validateMandatory = function () {
|
||||
$scope.validateMandatory = function () {
|
||||
var isValid = !$scope.model.validation.mandatory || (
|
||||
$scope.model.value != null
|
||||
&& $scope.model.value != ""
|
||||
&& (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "")
|
||||
);
|
||||
return {
|
||||
isValid: !$scope.model.validation.mandatory || ($scope.model.value != null && $scope.model.value != ""),
|
||||
isValid: isValid,
|
||||
errorMsg: "Value cannot be empty",
|
||||
errorKey: "required"
|
||||
};
|
||||
}
|
||||
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
|
||||
$scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
|
||||
|
||||
// A color is active if it matches the value and label of the model.
|
||||
// If the model doesn't store the label, ignore the label during the comparison.
|
||||
$scope.isActiveColor = function (color) {
|
||||
|
||||
// no value
|
||||
if (!$scope.model.value)
|
||||
return false;
|
||||
|
||||
// Complex color (value and label)?
|
||||
if (!$scope.model.value.hasOwnProperty("value"))
|
||||
return $scope.model.value === color.value;
|
||||
|
||||
return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
|
||||
};
|
||||
|
||||
// Finds the color best matching the model's color,
|
||||
// and sets the model color to that one. This is useful when
|
||||
// either the value or label was changed on the data type.
|
||||
function initActiveColor() {
|
||||
|
||||
// no value
|
||||
if (!$scope.model.value)
|
||||
return;
|
||||
|
||||
// Complex color (value and label)?
|
||||
if (!$scope.model.value.hasOwnProperty("value"))
|
||||
return;
|
||||
|
||||
var modelColor = $scope.model.value.value;
|
||||
var modelLabel = $scope.model.value.label;
|
||||
|
||||
// Check for a full match or partial match.
|
||||
var foundItem = null;
|
||||
|
||||
// Look for a fully matching color.
|
||||
for (var key in $scope.model.config.items) {
|
||||
var item = $scope.model.config.items[key];
|
||||
if (item.value == modelColor && item.label == modelLabel) {
|
||||
foundItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for a color with a matching value.
|
||||
if (!foundItem) {
|
||||
for (var key in $scope.model.config.items) {
|
||||
var item = $scope.model.config.items[key];
|
||||
if (item.value == modelColor) {
|
||||
foundItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Look for a color with a matching label.
|
||||
if (!foundItem) {
|
||||
for (var key in $scope.model.config.items) {
|
||||
var item = $scope.model.config.items[key];
|
||||
if (item.label == modelLabel) {
|
||||
foundItem = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If a match was found, set it as the active color.
|
||||
if (foundItem) {
|
||||
$scope.model.value.value = foundItem.value;
|
||||
$scope.model.value.label = foundItem.label;
|
||||
}
|
||||
}
|
||||
|
||||
// figures out if a value is trueish enough
|
||||
function isTrue(bool) {
|
||||
return !!bool && bool !== "0" && angular.lowercase(bool) !== "false";
|
||||
}
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.PropertyEditors.ColorPickerController", ColorPickerController);
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
</div>
|
||||
|
||||
<ul class="thumbnails color-picker">
|
||||
<li ng-repeat="(key, val) in model.config.items" ng-class="{active: model.value === val}">
|
||||
<a ng-click="toggleItem(val)" class="thumbnail" hex-bg-color="{{val}}">
|
||||
|
||||
</a>
|
||||
<li ng-repeat="(key, val) in model.config.items" ng-class="{active: isActiveColor(val)}">
|
||||
<a ng-click="toggleItem(val)" class="thumbnail" hex-bg-color="{{val.value}}">
|
||||
</a>
|
||||
<span class="color-label" ng-if="model.useLabel" ng-bind="val.label"></span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
+3
-2
@@ -1,12 +1,13 @@
|
||||
<div ng-controller="Umbraco.PrevalueEditors.MultiColorPickerController">
|
||||
<div class="control-group color-picker-preval">
|
||||
<input name="newColor" type="hidden" />
|
||||
<label for="newColor" val-highlight="hasError">#{{newColor}}</label>
|
||||
<input name="newLabel" type="text" ng-model="newLabel" class="umb-editor color-label" placeholder="Label" />
|
||||
<button class="btn add" ng-click="add($event)"><localize key="general_add">Add</localize></button>
|
||||
<label for="newColor" val-highlight="hasError">{{newColor}}</label>
|
||||
</div>
|
||||
<div class="control-group color-picker-preval" ng-repeat="item in model.value">
|
||||
<div class="thumbnail span1" hex-bg-color="{{item.value}}" bg-orig="transparent"></div>
|
||||
<pre>{{item.value}}</pre>
|
||||
<div class="color-picker-prediv"><pre>#{{item.value}} - {{item.label}}</pre></div>
|
||||
<button class="btn btn-danger" ng-click="remove(item, $event)"><localize key="general_remove">Remove</localize></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+37
-15
@@ -2,15 +2,17 @@
|
||||
function ($scope, $timeout, assetsService, angularHelper, $element) {
|
||||
//NOTE: We need to make each color an object, not just a string because you cannot 2-way bind to a primitive.
|
||||
var defaultColor = "000000";
|
||||
|
||||
var defaultLabel = null;
|
||||
|
||||
$scope.newColor = defaultColor;
|
||||
$scope.newLavel = defaultLabel;
|
||||
$scope.hasError = false;
|
||||
|
||||
assetsService.load([
|
||||
//"lib/spectrum/tinycolor.js",
|
||||
"lib/spectrum/spectrum.js"
|
||||
"lib/spectrum/spectrum.js"
|
||||
], $scope).then(function () {
|
||||
var elem = $element.find("input");
|
||||
var elem = $element.find("input[name='newColor']");
|
||||
elem.spectrum({
|
||||
color: null,
|
||||
showInitial: false,
|
||||
@@ -21,7 +23,7 @@
|
||||
clickoutFiresChange: true,
|
||||
hide: function (color) {
|
||||
//show the add butotn
|
||||
$element.find(".btn.add").show();
|
||||
$element.find(".btn.add").show();
|
||||
},
|
||||
change: function (color) {
|
||||
angularHelper.safeApply($scope, function () {
|
||||
@@ -39,21 +41,41 @@
|
||||
//make an array from the dictionary
|
||||
var items = [];
|
||||
for (var i in $scope.model.value) {
|
||||
items.push({
|
||||
value: $scope.model.value[i],
|
||||
id: i
|
||||
});
|
||||
var oldValue = $scope.model.value[i];
|
||||
if (oldValue.hasOwnProperty("value")) {
|
||||
items.push({
|
||||
value: oldValue.value,
|
||||
label: oldValue.label,
|
||||
id: i
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
value: oldValue,
|
||||
label: oldValue,
|
||||
id: i
|
||||
});
|
||||
}
|
||||
}
|
||||
//now make the editor model the array
|
||||
$scope.model.value = items;
|
||||
}
|
||||
|
||||
// ensure labels
|
||||
for (var i = 0; i < $scope.model.value.length; i++) {
|
||||
var item = $scope.model.value[i];
|
||||
item.label = item.hasOwnProperty("label") ? item.label : item.value;
|
||||
}
|
||||
|
||||
function validLabel(label) {
|
||||
return label !== null && typeof label !== "undefined" && label !== "" && label.length && label.length > 0;
|
||||
}
|
||||
|
||||
$scope.remove = function (item, evt) {
|
||||
|
||||
evt.preventDefault();
|
||||
|
||||
$scope.model.value = _.reject($scope.model.value, function (x) {
|
||||
return x.value === item.value;
|
||||
return x.value === item.value && x.label === item.label;
|
||||
});
|
||||
|
||||
};
|
||||
@@ -63,15 +85,15 @@
|
||||
evt.preventDefault();
|
||||
|
||||
if ($scope.newColor) {
|
||||
var newLabel = validLabel($scope.newLabel) ? $scope.newLabel : $scope.newColor;
|
||||
var exists = _.find($scope.model.value, function(item) {
|
||||
return item.value.toUpperCase() == $scope.newColor.toUpperCase();
|
||||
return item.value.toUpperCase() === $scope.newColor.toUpperCase() || item.label.toUpperCase() === newLabel.toUpperCase();
|
||||
});
|
||||
if (!exists) {
|
||||
$scope.model.value.push({ value: $scope.newColor });
|
||||
//$scope.newColor = defaultColor;
|
||||
// set colorpicker to default color
|
||||
//var elem = $element.find("input");
|
||||
//elem.spectrum("set", $scope.newColor);
|
||||
$scope.model.value.push({
|
||||
value: $scope.newColor,
|
||||
label: newLabel
|
||||
});
|
||||
$scope.hasError = false;
|
||||
return;
|
||||
}
|
||||
|
||||
+8
-4
@@ -1,7 +1,7 @@
|
||||
//this controller simply tells the dialogs service to open a mediaPicker window
|
||||
//with a specified callback, this callback will receive an object with a selection on it
|
||||
|
||||
function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper) {
|
||||
function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper, localizationService) {
|
||||
|
||||
var unsubscribe;
|
||||
|
||||
@@ -154,7 +154,6 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($routeParams.section === "settings" && $routeParams.tree === "documentTypes") {
|
||||
//if the content-picker is being rendered inside the document-type editor, we don't need to process the startnode query
|
||||
dialogOptions.startNodeId = -1;
|
||||
@@ -287,8 +286,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
entityResource.getUrl(entity.id, entityType).then(function(data){
|
||||
// update url
|
||||
angular.forEach($scope.renderModel, function(item){
|
||||
if(item.id === entity.id) {
|
||||
item.url = data;
|
||||
if (item.id === entity.id) {
|
||||
if (entity.trashed) {
|
||||
item.url = localizationService.dictionary.general_recycleBin;
|
||||
} else {
|
||||
item.url = data;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -330,6 +333,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
|
||||
"icon": item.icon,
|
||||
"path": item.path,
|
||||
"url": item.url,
|
||||
"trashed": item.trashed,
|
||||
"published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true
|
||||
// only content supports published/unpublished content so we set everything else to published so the UI looks correct
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<div ng-controller="Umbraco.PropertyEditors.ContentPickerController" class="umb-editor umb-contentpicker">
|
||||
|
||||
<p ng-if="(renderModel|filter:{trashed:true}).length == 1"><localize key="contentPicker_pickedTrashedItem"></localize></p>
|
||||
<p ng-if="(renderModel|filter:{trashed:true}).length > 1"><localize key="contentPicker_pickedTrashedItems"></localize></p>
|
||||
|
||||
<ng-form name="contentPickerForm">
|
||||
|
||||
<div ui-sortable="sortableOptions" ng-model="renderModel">
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
val-server="value" />
|
||||
|
||||
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="required"><localize key="general_required">Required</localize></span>
|
||||
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valEmail"><localize key="valiation_invalidEmail">Invalid email</localize></span>
|
||||
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valEmail"><localize key="validation_invalidEmail">Invalid email</localize></span>
|
||||
<span class="help-inline" val-msg-for="textbox" val-toggle-msg="valServer"></span>
|
||||
</div>
|
||||
|
||||
@@ -48,14 +48,18 @@
|
||||
<a href ng-click="scaleDown(currentCell)">
|
||||
<i class="icon icon-remove"></i>
|
||||
</a>
|
||||
{{currentCell.grid}}
|
||||
{{currentCell.grid}}
|
||||
<a href ng-click="scaleUp(currentCell, availableRowSpace, true)">
|
||||
<i class="icon icon-add"></i>
|
||||
</a>
|
||||
</div>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@grid_maxItems" description="@grid_maxItemsDescription">
|
||||
<input type="number" ng-model="currentCell.maxItems" class="umb-editor-tiny" placeholder="Max" min="0" />
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group hide-label="true">
|
||||
<umb-control-group hide-label="true">
|
||||
<i class="icon-delete red"></i>
|
||||
<a class="btn btn-small btn-link" href="" ng-click="deleteArea(currentCell, currentRow)">
|
||||
<localize key="general_delete" class="ng-isolate-scope ng-scope">Delete</localize>
|
||||
|
||||
@@ -81,6 +81,7 @@ angular.module("umbraco")
|
||||
|
||||
var notIncludedRte = [];
|
||||
var cancelMove = false;
|
||||
var startingArea;
|
||||
|
||||
$scope.sortableOptionsCell = {
|
||||
distance: 10,
|
||||
@@ -112,9 +113,11 @@ angular.module("umbraco")
|
||||
},
|
||||
|
||||
over: function (event, ui) {
|
||||
var allowedEditors = $(event.target).scope().area.allowed;
|
||||
var area = $(event.target).scope().area;
|
||||
var allowedEditors = area.allowed;
|
||||
|
||||
if ($.inArray(ui.item.scope().control.editor.alias, allowedEditors) < 0 && allowedEditors) {
|
||||
if (($.inArray(ui.item.scope().control.editor.alias, allowedEditors) < 0 && allowedEditors) ||
|
||||
(startingArea != area && area.maxItems != '' && area.maxItems > 0 && area.maxItems < area.controls.length + 1)) {
|
||||
|
||||
$scope.$apply(function () {
|
||||
$(event.target).scope().area.dropNotAllowed = true;
|
||||
@@ -168,6 +171,10 @@ angular.module("umbraco")
|
||||
|
||||
start: function (e, ui) {
|
||||
|
||||
//Get the starting area for reference
|
||||
var area = $(e.target).scope().area;
|
||||
startingArea = area;
|
||||
|
||||
// fade out control when sorting
|
||||
ui.item.context.style.display = "block";
|
||||
ui.item.context.style.opacity = "0.5";
|
||||
|
||||
@@ -224,7 +224,7 @@
|
||||
<!-- Controls repeat end -->
|
||||
|
||||
<!-- if area is empty tools -->
|
||||
<div class="umb-grid-add-more-content" ng-if="area.controls.length > 0 && !sortMode">
|
||||
<div class="umb-grid-add-more-content" ng-if="area.controls.length > 0 && !sortMode && (area.maxItems == undefined || area.maxItems == '' || area.maxItems == 0 || area.maxItems > area.controls.length)">
|
||||
<div class="cell-tools-add -bar newbtn" ng-click="openEditorOverlay($event, area, 0, area.$uniqueId);"><localize key="grid_addElement" /></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -65,7 +65,9 @@
|
||||
ng-repeat="area in layout.areas | filter:zeroWidthFilter"
|
||||
ng-style="{width: percentage(area.grid) + '%', 'max-width': '100%'}">
|
||||
|
||||
<div class="preview-cell"></div>
|
||||
<div class="preview-cell">
|
||||
<p style="font-size: 6px; line-height: 8px; text-align: center" ng-show="area.maxItems > 0">{{area.maxItems}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+42
-17
@@ -1,7 +1,7 @@
|
||||
//this controller simply tells the dialogs service to open a mediaPicker window
|
||||
//with a specified callback, this callback will receive an object with a selection on it
|
||||
angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController",
|
||||
function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location) {
|
||||
function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location, localizationService) {
|
||||
|
||||
//check the pre-values for multi-picker
|
||||
var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false;
|
||||
@@ -26,17 +26,47 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
|
||||
// the mediaResource has server side auth configured for which the user must have
|
||||
// access to the media section, if they don't they'll get auth errors. The entityResource
|
||||
// acts differently in that it allows access if the user has access to any of the apps that
|
||||
// might require it's use. Therefore we need to use the metatData property to get at the thumbnail
|
||||
// might require it's use. Therefore we need to use the metaData property to get at the thumbnail
|
||||
// value.
|
||||
|
||||
entityResource.getByIds(ids, "Media").then(function (medias) {
|
||||
entityResource.getByIds(ids, "Media").then(function(medias) {
|
||||
|
||||
_.each(medias, function (media, i) {
|
||||
// The service only returns item results for ids that exist (deleted items are silently ignored).
|
||||
// This results in the picked items value to be set to contain only ids of picked items that could actually be found.
|
||||
// Since a referenced item could potentially be restored later on, instead of changing the selected values here based
|
||||
// on whether the items exist during a save event - we should keep "placeholder" items for picked items that currently
|
||||
// could not be fetched. This will preserve references and ensure that the state of an item does not differ depending
|
||||
// on whether it is simply resaved or not.
|
||||
// This is done by remapping the int/guid ids into a new array of items, where we create "Deleted item" placeholders
|
||||
// when there is no match for a selected id. This will ensure that the values being set on save, are the same as before.
|
||||
|
||||
medias = _.map(ids,
|
||||
function(id) {
|
||||
var found = _.find(medias,
|
||||
function(m) {
|
||||
// We could use coercion (two ='s) here .. but not sure if this works equally well in all browsers and
|
||||
// it's prone to someone "fixing" it at some point without knowing the effects. Rather use toString()
|
||||
// compares and be completely sure it works.
|
||||
return m.udi.toString() === id.toString() || m.id.toString() === id.toString();
|
||||
});
|
||||
if (found) {
|
||||
return found;
|
||||
} else {
|
||||
return {
|
||||
name: localizationService.dictionary.mediaPicker_deletedItem,
|
||||
id: $scope.model.config.idType !== "udi" ? id : null,
|
||||
udi: $scope.model.config.idType === "udi" ? id : null,
|
||||
icon: "icon-picture",
|
||||
thumbnail: null,
|
||||
trashed: true
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
//only show non-trashed items
|
||||
if (media.parentId >= -1) {
|
||||
|
||||
if (!media.thumbnail) {
|
||||
_.each(medias,
|
||||
function(media, i) {
|
||||
// if there is no thumbnail, try getting one if the media is not a placeholder item
|
||||
if (!media.thumbnail && media.id && media.metaData) {
|
||||
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
|
||||
}
|
||||
|
||||
@@ -44,12 +74,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
|
||||
|
||||
if ($scope.model.config.idType === "udi") {
|
||||
$scope.ids.push(media.udi);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$scope.ids.push(media.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$scope.sync();
|
||||
});
|
||||
@@ -82,8 +110,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
|
||||
submit: function(model) {
|
||||
|
||||
_.each(model.selectedImages, function(media, i) {
|
||||
|
||||
if (!media.thumbnail) {
|
||||
// if there is no thumbnail, try getting one if the media is not a placeholder item
|
||||
if (!media.thumbnail && media.id && media.metaData) {
|
||||
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
|
||||
}
|
||||
|
||||
@@ -101,10 +129,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
|
||||
|
||||
$scope.mediaPickerOverlay.show = false;
|
||||
$scope.mediaPickerOverlay = null;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
$scope.sortableOptions = {
|
||||
@@ -142,5 +168,4 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
|
||||
//update the display val again if it has changed from the server
|
||||
setupViewModel();
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
<div class="umb-editor umb-mediapicker" ng-controller="Umbraco.PropertyEditors.MediaPickerController">
|
||||
|
||||
<ul ui-sortable="sortableOptions" ng-model="images" class="umb-sortable-thumbnails">
|
||||
<li style="width: 120px; height: 100px; overflow: hidden;" ng-repeat="image in images">
|
||||
<p ng-if="(images|filter:{trashed:true}).length == 1"><localize key="mediaPicker_pickedTrashedItem"></localize></p>
|
||||
<p ng-if="(images|filter:{trashed:true}).length > 1"><localize key="mediaPicker_pickedTrashedItems"></localize></p>
|
||||
|
||||
<!-- IMAGE -->
|
||||
<img ng-src="{{image.thumbnail}}" alt="" ng-show="image.thumbnail" title="{{image.name}}" />
|
||||
<div class="flex error">
|
||||
<ul ui-sortable="sortableOptions" ng-model="images" class="umb-sortable-thumbnails">
|
||||
<li style="width: 120px; height: 100px; overflow: hidden;" ng-repeat="image in images">
|
||||
|
||||
<!-- SVG -->
|
||||
<img ng-if="image.metaData.umbracoExtension.Value === 'svg'" ng-src="{{image.metaData.umbracoFile.Value}}" alt="" title="{{image.name}}" />
|
||||
<img ng-if="image.extension === 'svg'" ng-src="{{image.file}}" alt="" />
|
||||
<!-- IMAGE -->
|
||||
<img ng-class="{'trashed': image.trashed}" ng-src="{{image.thumbnail}}" alt="" ng-show="image.thumbnail" title="{{image.trashed ? 'Trashed: ' + image.name : image.name}}" />
|
||||
|
||||
<!-- FILE -->
|
||||
<span class="umb-icon-holder" ng-hide="image.thumbnail || image.metaData.umbracoExtension.Value === 'svg' || image.extension === 'svg'">
|
||||
<i class="icon {{image.icon}} large"></i>
|
||||
<small>{{image.name}}</small>
|
||||
</span>
|
||||
<!-- SVG -->
|
||||
<img ng-class="{'trashed': image.trashed}" ng-if="image.metaData.umbracoExtension.Value === 'svg'" ng-src="{{image.metaData.umbracoFile.Value}}" alt="" title="{{image.trashed ? 'Trashed: ' + image.name : image.name}}" />
|
||||
<img ng-class="{'trashed': image.trashed}" ng-if="image.extension === 'svg'" ng-src="{{image.file}}" alt="" />
|
||||
|
||||
<div class="umb-sortable-thumbnails__actions">
|
||||
<a class="umb-sortable-thumbnails__action" href="" ng-click="goToItem(image)">
|
||||
<i class="icon icon-edit"></i>
|
||||
</a>
|
||||
<a class="umb-sortable-thumbnails__action -red" href="" ng-click="remove($index)">
|
||||
<i class="icon icon-delete"></i>
|
||||
</a>
|
||||
</div>
|
||||
<!-- FILE -->
|
||||
<span class="umb-icon-holder" ng-hide="image.thumbnail || image.metaData.umbracoExtension.Value === 'svg' || image.extension === 'svg'">
|
||||
<i class="icon {{image.icon}} large"></i>
|
||||
<small>{{image.name}}</small>
|
||||
</span>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
<div class="umb-sortable-thumbnails__actions">
|
||||
<a class="umb-sortable-thumbnails__action" href="" ng-click="goToItem(image)">
|
||||
<i class="icon icon-edit"></i>
|
||||
</a>
|
||||
<a class="umb-sortable-thumbnails__action -red" href="" ng-click="remove($index)">
|
||||
<i class="icon icon-delete"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
<ul class="umb-sortable-thumbnails" ng-if="showAdd()">
|
||||
<li style="border: none">
|
||||
<a href="#" class="add-link" ng-click="add()" prevent-default>
|
||||
<i class="icon icon-add large"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
<a href="#" class="add-link" ng-click="add()" ng-class="{'add-link-square': images.length === 0}" ng-if="showAdd()" prevent-default>
|
||||
<i class="icon icon-add large"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<umb-overlay
|
||||
ng-if="mediaPickerOverlay.show"
|
||||
model="mediaPickerOverlay"
|
||||
position="right"
|
||||
view="mediaPickerOverlay.view">
|
||||
</umb-overlay>
|
||||
<umb-overlay
|
||||
ng-if="mediaPickerOverlay.show"
|
||||
model="mediaPickerOverlay"
|
||||
position="right"
|
||||
view="mediaPickerOverlay.view">
|
||||
</umb-overlay>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -76,6 +76,7 @@ angular.module("umbraco").controller("Umbraco.PrevalueEditors.RteController",
|
||||
icon.isCustom = false;
|
||||
break;
|
||||
case "styleselect":
|
||||
case "fontsizeselect":
|
||||
icon.name = "icon-list";
|
||||
icon.isCustom = true;
|
||||
break;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
//note on the below, we dont assign a view unless it's the right route since if we did that it will load in that controller
|
||||
//for the view which is unecessary and will cause extra overhead/requests to occur
|
||||
vm.page = {};
|
||||
vm.page.name = "User Management";
|
||||
vm.page.name = localizationService.localize("user_userManagement");
|
||||
vm.page.navigation = [
|
||||
{
|
||||
"name": localizationService.localize("sections_users"),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function UserEditController($scope, $timeout, $location, $routeParams, formHelper, usersResource, contentEditingHelper, localizationService, notificationsService, mediaHelper, Upload, umbRequestHelper, usersHelper, authResource, dateHelper) {
|
||||
function UserEditController($scope, $timeout, $location, $routeParams, formHelper, usersResource, userService, contentEditingHelper, localizationService, notificationsService, mediaHelper, Upload, umbRequestHelper, usersHelper, authResource, dateHelper) {
|
||||
|
||||
var vm = this;
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
function getLocalDate(date, format) {
|
||||
function getLocalDate(date, culture, format) {
|
||||
if(date) {
|
||||
var dateVal;
|
||||
var serverOffset = Umbraco.Sys.ServerVariables.application.serverTimeOffset;
|
||||
@@ -105,7 +105,7 @@
|
||||
dateVal = moment(date, "YYYY-MM-DD HH:mm:ss");
|
||||
}
|
||||
|
||||
return dateVal.format(format);
|
||||
return dateVal.locale(culture).format(format);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,11 +393,14 @@
|
||||
}
|
||||
|
||||
function formatDatesToLocal(user) {
|
||||
user.formattedLastLogin = getLocalDate(user.lastLoginDate, "MMMM Do YYYY, HH:mm");
|
||||
user.formattedLastLockoutDate = getLocalDate(user.lastLockoutDate, "MMMM Do YYYY, HH:mm");
|
||||
user.formattedCreateDate = getLocalDate(user.createDate, "MMMM Do YYYY, HH:mm");
|
||||
user.formattedUpdateDate = getLocalDate(user.updateDate, "MMMM Do YYYY, HH:mm");
|
||||
user.formattedLastPasswordChangeDate = getLocalDate(user.lastPasswordChangeDate, "MMMM Do YYYY, HH:mm");
|
||||
// get current backoffice user and format dates
|
||||
userService.getCurrentUser().then(function (currentUser) {
|
||||
user.formattedLastLogin = getLocalDate(user.lastLoginDate, currentUser.locale, "LLL");
|
||||
user.formattedLastLockoutDate = getLocalDate(user.lastLockoutDate, currentUser.locale, "LLL");
|
||||
user.formattedCreateDate = getLocalDate(user.createDate, currentUser.locale, "LLL");
|
||||
user.formattedUpdateDate = getLocalDate(user.updateDate, currentUser.locale, "LLL");
|
||||
user.formattedLastPasswordChangeDate = getLocalDate(user.lastPasswordChangeDate, currentUser.locale, "LLL");
|
||||
});
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
</umb-load-indicator>
|
||||
|
||||
<div ng-if="!vm.loading" class="umb-packages-view-wrapper" style="padding: 0;">
|
||||
|
||||
|
||||
<div class="umb-package-details">
|
||||
|
||||
<div class="umb-package-details__main-content">
|
||||
@@ -30,17 +30,19 @@
|
||||
<umb-box-content class="block-form">
|
||||
|
||||
<umb-control-group label="@general_email" required="true">
|
||||
<input
|
||||
type="email"
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_enteremail"
|
||||
class="input-block-level"
|
||||
|
||||
<input
|
||||
type="email"
|
||||
localize="placeholder"
|
||||
placeholder="@placeholders_enteremail"
|
||||
class="input-block-level"
|
||||
ng-model="vm.user.email"
|
||||
umb-auto-focus name="email"
|
||||
required
|
||||
val-email
|
||||
required
|
||||
val-server-field="Email" />
|
||||
<span class="help-inline" val-msg-for="email" val-toggle-msg="required"><localize key="general_required">Required</localize></span>
|
||||
<span class="help-inline" val-msg-for="email" val-toggle-msg="valServerField"></span>
|
||||
<span class="help-inline" val-msg-for="email" val-toggle-msg="valServerField"></span>
|
||||
</umb-control-group>
|
||||
|
||||
<umb-control-group label="@general_username" ng-if="!vm.usernameIsEmail" required="true">
|
||||
@@ -51,7 +53,7 @@
|
||||
class="input-block-level"
|
||||
ng-model="vm.user.username"
|
||||
umb-auto-focus name="username"
|
||||
required
|
||||
required
|
||||
val-server-field="Username" />
|
||||
<span class="help-inline" val-msg-for="username" val-toggle-msg="required"><localize key="general_required">Required</localize></span>
|
||||
<span class="help-inline" val-msg-for="username" val-toggle-msg="valServerField"></span>
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
<umb-button
|
||||
type="button"
|
||||
label="Delete"
|
||||
label-key="general_delete"
|
||||
icon="icon-trash"
|
||||
action="vm.deleteUserGroups()"
|
||||
size="xs">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function UsersController($scope, $timeout, $location, usersResource, userGroupsResource, localizationService, contentEditingHelper, usersHelper, formHelper, notificationsService, dateHelper) {
|
||||
function UsersController($scope, $timeout, $location, usersResource, userGroupsResource, userService, localizationService, contentEditingHelper, usersHelper, formHelper, notificationsService, dateHelper) {
|
||||
|
||||
var vm = this;
|
||||
var localizeSaving = localizationService.localize("general_saving");
|
||||
@@ -20,6 +20,19 @@
|
||||
{ label: "Oldest", key: "CreateDate", direction: "Ascending" },
|
||||
{ label: "Last login", key: "LastLoginDate", direction: "Descending" }
|
||||
];
|
||||
|
||||
angular.forEach(vm.userSortData, function (userSortData) {
|
||||
var key = "user_sort" + userSortData.key + userSortData.direction;
|
||||
localizationService.localize(key).then(function (value) {
|
||||
var reg = /^\[[\S\s]*]$/g;
|
||||
var result = reg.test(value);
|
||||
if (result === false) {
|
||||
// Only translate if key exists
|
||||
userSortData.label = value;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
vm.userStatesFilter = [];
|
||||
vm.newUser.userGroups = [];
|
||||
vm.usersViewState = 'overview';
|
||||
@@ -284,10 +297,10 @@
|
||||
vm.selectedBulkUserGroups = _.clone(firstSelectedUser.userGroups);
|
||||
|
||||
vm.userGroupPicker = {
|
||||
title: "Select user groups",
|
||||
title: localizationService.localize("user_selectUserGroups"),
|
||||
view: "usergrouppicker",
|
||||
selection: vm.selectedBulkUserGroups,
|
||||
closeButtonLabel: "Cancel",
|
||||
closeButtonLabel: localizationService.localize("general_cancel"),
|
||||
show: true,
|
||||
submit: function (model) {
|
||||
usersResource.setUserGroupsOnUsers(model.selection, vm.selection).then(function (data) {
|
||||
@@ -320,10 +333,10 @@
|
||||
|
||||
function openUserGroupPicker(event) {
|
||||
vm.userGroupPicker = {
|
||||
title: "Select user groups",
|
||||
title: localizationService.localize("user_selectUserGroups"),
|
||||
view: "usergrouppicker",
|
||||
selection: vm.newUser.userGroups,
|
||||
closeButtonLabel: "Cancel",
|
||||
closeButtonLabel: localizationService.localize("general_cancel"),
|
||||
show: true,
|
||||
submit: function (model) {
|
||||
// apply changes
|
||||
@@ -583,7 +596,10 @@
|
||||
dateVal = moment(user.lastLoginDate, "YYYY-MM-DD HH:mm:ss");
|
||||
}
|
||||
|
||||
user.formattedLastLogin = dateVal.format("MMMM Do YYYY, HH:mm");
|
||||
// get current backoffice user and format date
|
||||
userService.getCurrentUser().then(function (currentUser) {
|
||||
user.formattedLastLogin = dateVal.locale(currentUser.locale).format("LLL");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
expect(valEmailExpression.EMAIL_REGEXP.test('a@3b.c')).toBe(true);
|
||||
expect(valEmailExpression.EMAIL_REGEXP.test('a@b')).toBe(true);
|
||||
expect(valEmailExpression.EMAIL_REGEXP.test('abc@xyz.financial')).toBe(true);
|
||||
|
||||
expect(valEmailExpression.EMAIL_REGEXP.test('admin@c.pizza')).toBe(true);
|
||||
expect(valEmailExpression.EMAIL_REGEXP.test('admin+gmail-syntax@c.pizza')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1027,9 +1027,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
|
||||
<WebProjectProperties>
|
||||
<UseIIS>True</UseIIS>
|
||||
<AutoAssignPort>True</AutoAssignPort>
|
||||
<DevelopmentServerPort>7710</DevelopmentServerPort>
|
||||
<DevelopmentServerPort>7740</DevelopmentServerPort>
|
||||
<DevelopmentServerVPath>/</DevelopmentServerVPath>
|
||||
<IISUrl>http://localhost:7710</IISUrl>
|
||||
<IISUrl>http://localhost:7740</IISUrl>
|
||||
<NTLMAuthentication>False</NTLMAuthentication>
|
||||
<UseCustomServer>False</UseCustomServer>
|
||||
<CustomServerUrl>
|
||||
|
||||
@@ -60,21 +60,29 @@
|
||||
JObject cfg = contentItem.config;
|
||||
|
||||
if(cfg != null)
|
||||
foreach (JProperty property in cfg.Properties()) {
|
||||
attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
|
||||
foreach (JProperty property in cfg.Properties())
|
||||
{
|
||||
var propertyValue = HttpUtility.HtmlAttributeEncode(property.Value.ToString());
|
||||
attrs.Add(property.Name + "=\"" + propertyValue + "\"");
|
||||
}
|
||||
|
||||
|
||||
JObject style = contentItem.styles;
|
||||
|
||||
if (style != null) {
|
||||
var cssVals = new List<string>();
|
||||
foreach (JProperty property in style.Properties())
|
||||
cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
|
||||
if (style != null) {
|
||||
var cssVals = new List<string>();
|
||||
foreach (JProperty property in style.Properties())
|
||||
{
|
||||
var propertyValue = property.Value.ToString();
|
||||
if (string.IsNullOrWhiteSpace(propertyValue) == false)
|
||||
{
|
||||
cssVals.Add(property.Name + ":" + propertyValue + ";");
|
||||
}
|
||||
}
|
||||
|
||||
if (cssVals.Any())
|
||||
attrs.Add("style='" + string.Join(" ", cssVals) + "'");
|
||||
if (cssVals.Any())
|
||||
attrs.Add("style=\"" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "\"");
|
||||
}
|
||||
|
||||
|
||||
return new MvcHtmlString(string.Join(" ", attrs));
|
||||
}
|
||||
}
|
||||
@@ -60,21 +60,29 @@
|
||||
JObject cfg = contentItem.config;
|
||||
|
||||
if(cfg != null)
|
||||
foreach (JProperty property in cfg.Properties()) {
|
||||
attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
|
||||
foreach (JProperty property in cfg.Properties())
|
||||
{
|
||||
var propertyValue = HttpUtility.HtmlAttributeEncode(property.Value.ToString());
|
||||
attrs.Add(property.Name + "=\"" + propertyValue + "\"");
|
||||
}
|
||||
|
||||
|
||||
JObject style = contentItem.styles;
|
||||
|
||||
if (style != null) {
|
||||
var cssVals = new List<string>();
|
||||
foreach (JProperty property in style.Properties())
|
||||
cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
|
||||
if (style != null) {
|
||||
var cssVals = new List<string>();
|
||||
foreach (JProperty property in style.Properties())
|
||||
{
|
||||
var propertyValue = property.Value.ToString();
|
||||
if (string.IsNullOrWhiteSpace(propertyValue) == false)
|
||||
{
|
||||
cssVals.Add(property.Name + ":" + propertyValue + ";");
|
||||
}
|
||||
}
|
||||
|
||||
if (cssVals.Any())
|
||||
attrs.Add("style='" + string.Join(" ", cssVals) + "'");
|
||||
if (cssVals.Any())
|
||||
attrs.Add("style=\"" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "\"");
|
||||
}
|
||||
|
||||
|
||||
return new MvcHtmlString(string.Join(" ", attrs));
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,13 @@
|
||||
@if (Model.editor.config.markup != null)
|
||||
{
|
||||
string markup = Model.editor.config.markup.ToString();
|
||||
|
||||
markup = markup.Replace("#value#", Model.value.ToString());
|
||||
markup = markup.Replace("#style#", Model.editor.config.style.ToString());
|
||||
var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
|
||||
markup = markup.Replace("#value#", umbracoHelper.ReplaceLineBreaksForHtml(HttpUtility.HtmlEncode(Model.value.ToString())));
|
||||
|
||||
if (Model.editor.config.style != null)
|
||||
{
|
||||
markup = markup.Replace("#style#", Model.editor.config.style.ToString());
|
||||
}
|
||||
|
||||
<text>
|
||||
@Html.Raw(markup)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@using Umbraco.Web
|
||||
@using Umbraco.Core.Configuration
|
||||
@using Umbraco.Web
|
||||
@using Umbraco.Web.Install.Controllers
|
||||
@{
|
||||
Layout = null;
|
||||
|
||||
@@ -12,13 +12,12 @@
|
||||
<key alias="copy">Kopier</key>
|
||||
<key alias="create">Opret</key>
|
||||
<key alias="createPackage">Opret pakke</key>
|
||||
<key alias="createGroup">Opret gruppe</key>
|
||||
<key alias="delete">Slet</key>
|
||||
<key alias="disable">Deaktivér</key>
|
||||
<key alias="emptyTrashcan">Tøm papirkurv</key>
|
||||
<key alias="enable">Aktivér</key>
|
||||
<key alias="exportDocumentType">Eksportér dokumenttype</key>
|
||||
<key alias="exportDocumentTypeAsCode">Eksportér til .NET</key>
|
||||
<key alias="exportDocumentTypeAsCode-Full">Eksportér til .NET</key>
|
||||
<key alias="importDocumentType">Importér dokumenttype</key>
|
||||
<key alias="importPackage">Importér pakke</key>
|
||||
<key alias="liveEdit">Redigér i Canvas</key>
|
||||
@@ -30,15 +29,48 @@
|
||||
<key alias="unpublish">Fortryd udgivelse</key>
|
||||
<key alias="refreshNode">Genindlæs elementer</key>
|
||||
<key alias="republish">Genudgiv hele sitet</key>
|
||||
<key alias="rename" version="7.3.0">Omdøb</key>
|
||||
<key alias="restore" version="7.3.0">Gendan</key>
|
||||
<key alias="SetPermissionsForThePage">Sæt rettigheder for siden %0%</key>
|
||||
<key alias="chooseWhereToMove">Vælg hvortil du vil flytte</key>
|
||||
<key alias="toInTheTreeStructureBelow">I træstrukturen nedenfor</key>
|
||||
<key alias="rights">Rettigheder</key>
|
||||
<key alias="rollback">Fortryd ændringer</key>
|
||||
<key alias="sendtopublish">Send til udgivelse</key>
|
||||
<key alias="sendToTranslate">Send til oversættelse</key>
|
||||
<key alias="setGroup">Sæt gruppe</key>
|
||||
<key alias="sort">Sortér</key>
|
||||
<key alias="translate">Oversæt</key>
|
||||
<key alias="update">Opdatér</key>
|
||||
<key alias="setPermissions">Sæt rettigheder</key>
|
||||
<key alias="unlock">Lås op</key>
|
||||
<key alias="createblueprint">Opret indholdsskabelon</key>
|
||||
</area>
|
||||
<area alias="actionCategories">
|
||||
<key alias="content">Indhold</key>
|
||||
<key alias="administration">Administration</key>
|
||||
<key alias="structure">Struktur</key>
|
||||
<key alias="other">Andet</key>
|
||||
</area>
|
||||
<area alias="actionDescriptions">
|
||||
<key alias="assignDomain">Tillad adgang til at tildele sprog og domæner</key>
|
||||
<key alias="auditTrail">Tillad adgang for at få vist en nodes historik</key>
|
||||
<key alias="browse">Tillad adgang for at få vist en node</key>
|
||||
<key alias="changeDocType">Tillad adgang til at ændre dokumenttype for en node</key>
|
||||
<key alias="copy">Tillad adgang til at kopiere en node</key>
|
||||
<key alias="create">Tillad adgang til at oprette noder</key>
|
||||
<key alias="delete">Tillad adgang til at slette noder</key>
|
||||
<key alias="move">Tillad adgang til at flytte en node</key>
|
||||
<key alias="protect">Tillad adgang til at indstille og ændre offentlig adgang til en node</key>
|
||||
<key alias="publish">Tillad adgang til at udgive en node</key>
|
||||
<key alias="rights">Tillad adgang til at ændre rettigheder for en node</key>
|
||||
<key alias="rollback">Tillad adgang til at returnere en node til en tidligere tilstand</key>
|
||||
<key alias="sendtopublish">Tillad adgang til at sende en node til godkendelse før den udgives</key>
|
||||
<key alias="sendToTranslate">Tillad adgang til at sende en node til oversættelse</key>
|
||||
<key alias="sort">Tillad adgang til at ændre sorteringsrækkefølge for noder</key>
|
||||
<key alias="translate">Tillad adgang til at oversætte en node</key>
|
||||
<key alias="update">Tillad adgang til at gemme en node</key>
|
||||
<key alias="createblueprint">Tillad adgang til at oprette en indholdsskabelon</key>
|
||||
</area>
|
||||
<area alias="assignDomain">
|
||||
<key alias="permissionDenied">Tilladelse nægtet.</key>
|
||||
@@ -55,6 +87,13 @@
|
||||
<key alias="domainUpdated">Domænet '%0%' er nu opdateret</key>
|
||||
<key alias="orEdit">eller rediger nuværende domæner</key>
|
||||
<key alias="domainHelp">f.eks. ditdomaene.com, www.ditdomaene.com</key>
|
||||
<key alias="inherit">Nedarv</key>
|
||||
<key alias="setLanguage">Sprog</key>
|
||||
<key alias="setLanguageHelp">
|
||||
<![CDATA[Indstil sproget for noder under den aktuelle node,<br /> eller nedarv sprog fra forældre noder. Gælder også<br />
|
||||
for den aktuelle node, medmindre et domæne nedenfor også indstiller et sprog.]]>
|
||||
</key>
|
||||
<key alias="setDomains">Domæner</key>
|
||||
</area>
|
||||
<area alias="auditTrails">
|
||||
<key alias="atViewingFor">For</key>
|
||||
@@ -92,6 +131,9 @@
|
||||
<key alias="styleShow">Vis koder</key>
|
||||
<key alias="tableInsert">Indsæt tabel</key>
|
||||
<key alias="generateModels">Generer modeller</key>
|
||||
<key alias="saveAndGenerateModels">Gem og generer modeller</key>
|
||||
<key alias="undo">Fortryd</key>
|
||||
<key alias="redo">Genskab</key>
|
||||
</area>
|
||||
<area alias="changeDocType">
|
||||
<key alias="changeDocTypeInstruction">For at skifte det valgte indholds dokumenttype, skal du først vælge en ny dokumenttype, som er gyldig på denne placering.</key>
|
||||
@@ -131,7 +173,10 @@
|
||||
<key alias="itemChanged">Dette punkt er ændret siden udgivelsen</key>
|
||||
<key alias="itemNotPublished">Dette punkt er endnu ikke udgivet</key>
|
||||
<key alias="lastPublished">Sidst udgivet</key>
|
||||
<key alias="noItemsToShow">Der er ingen elementer at vise</key>
|
||||
<key alias="listViewNoItems" version="7.1.5">Der er ingen elementer at vise på listen.</key>
|
||||
<key alias="listViewNoContent">Intet indhold er blevet tilføjet</key>
|
||||
<key alias="listViewNoMembers">Ingen medlemmer er blevet tilføjet</key>
|
||||
<key alias="mediatype">Medietype</key>
|
||||
<key alias="mediaLinks">Link til medie(r)</key>
|
||||
<key alias="membergroup">Medlemsgruppe</key>
|
||||
@@ -142,6 +187,8 @@
|
||||
<key alias="otherElements">Egenskaber</key>
|
||||
<key alias="parentNotPublished">Dette dokument er udgivet, men ikke synligt da den overliggende side '%0%' ikke er udgivet!</key>
|
||||
<key alias="parentNotPublishedAnomaly">Upd: dette dokument er udgiver, men er ikke i cachen (intern fejl)</key>
|
||||
<key alias="getUrlException">Kunne ikke hente url'en</key>
|
||||
<key alias="routeError">Dette dokument er udgivet, men dets url ville kollidere med indholdet %0%</key>
|
||||
<key alias="publish">Udgivet</key>
|
||||
<key alias="publishStatus">Udgivelsesstatus</key>
|
||||
<key alias="releaseDate">Udgivelsesdato</key>
|
||||
@@ -162,6 +209,22 @@
|
||||
<key alias="notmemberof">Ikke medlem af grupper(ne)</key>
|
||||
<key alias="childItems" version="7.0">Undersider</key>
|
||||
<key alias="target" version="7.0">Åben i vindue</key>
|
||||
<key alias="scheduledPublishServerTime">Dette oversætter til den følgende tid på serveren:</key>
|
||||
<key alias="scheduledPublishDocumentation"><![CDATA[<a href="https://our.umbraco.org/documentation/Getting-Started/Data/Scheduled-Publishing/#timezones" target="_blank">Hvad betyder det?</a>]]></key>
|
||||
<key alias="nestedContentDeleteItem">Er du sikker på, at du vil slette dette element?</key>
|
||||
<key alias="nestedContentEditorNotSupported">Egenskaben %0% anvender editoren %1% som ikke er understøttet af Nested Content.</key>
|
||||
<key alias="addTextBox">Tilføj en ny tekstboks</key>
|
||||
<key alias="removeTextBox">Fjern denne tekstboks</key>
|
||||
<key alias="contentRoot">Indholdsrod</key>
|
||||
</area>
|
||||
<area alias="blueprints">
|
||||
<key alias="createBlueprintFrom">Opret en ny indholdsskabelon fra '%0%'</key>
|
||||
<key alias="blankBlueprint">Blank</key>
|
||||
<key alias="selectBlueprint">Vælg en indholdsskabelon</key>
|
||||
<key alias="createdBlueprintHeading">Indholdsskabelon oprettet</key>
|
||||
<key alias="createdBlueprintMessage">En indholdsskabelon blev oprettet fra '%0%'</key>
|
||||
<key alias="duplicateBlueprintMessage">En anden indholdsskabelon med samme navn eksisterer allerede</key>
|
||||
<key alias="blueprintDescription">En indholdskabelon er foruddefineret indhold, som en redaktør kan vælge at bruge som grundlag for at oprette nyt indhold</key>
|
||||
</area>
|
||||
<area alias="media">
|
||||
<key alias="clickToUpload">Klik for at uploade</key>
|
||||
@@ -169,7 +232,9 @@
|
||||
<key alias="urls">Link til medie</key>
|
||||
<key alias="orClickHereToUpload">eller klik her for at vælge filer</key>
|
||||
<key alias="onlyAllowedFiles">Tilladte filtyper er kun</key>
|
||||
<key alias="disallowedFileType">Kan ikke uploade denne fil, den har ikke en godkendt filtype</key>
|
||||
<key alias="maxFileSize">Maks filstørrelse er</key>
|
||||
<key alias="mediaRoot">Medie rod</key>
|
||||
</area>
|
||||
<area alias="member">
|
||||
<key alias="createNewMember">Opret et nyt medlem</key>
|
||||
@@ -178,14 +243,21 @@
|
||||
<area alias="create">
|
||||
<key alias="chooseNode">Hvor ønsker du at oprette den nye %0%</key>
|
||||
<key alias="createUnder">Opret under</key>
|
||||
<key alias="createContentBlueprint">Vælg den dokumenttype, du vil oprette en indholdsskabelon til</key>
|
||||
<key alias="updateData">Vælg en type og skriv en titel</key>
|
||||
<key alias="noDocumentTypes" version="7.0"><![CDATA[Der kunne ikke findes nogen tilladte dokument typer. Du skal tillade disse i indstillinger under <strong>"dokument typer"</strong>.]]></key>
|
||||
<key alias="noMediaTypes" version="7.0"><![CDATA[Der kunne ikke findes nogen tilladte media typer. Du skal tillade disse i indstillinger under <strong>"media typer"</strong>.]]></key>
|
||||
<key alias="documentTypeWithoutTemplate">Dokumenttype uden skabelon</key>
|
||||
<key alias="newEmptyPartialView">Ny tom partial view</key>
|
||||
<key alias="newFolder">Ny mappe</key>
|
||||
<key alias="newDataType">Ny datatype</key>
|
||||
<key alias="newJavascriptFile">Ny javascript fil</key>
|
||||
<key alias="newEmptyPartialView">Ny tom partial view</key>
|
||||
<key alias="newFolder">Ny mappe</key>
|
||||
<key alias="newPartialViewMacro">Ny partial view makro</key>
|
||||
<key alias="newPartialViewFromSnippet">Ny partial view fra snippet</key>
|
||||
<key alias="newEmptyPartialViewMacro">Ny tom partial view makro</key>
|
||||
<key alias="newPartialViewMacroFromSnippet">Ny partial view makro fra snippet</key>
|
||||
<key alias="newPartialViewMacroNoMacro">Ny partial view makro (uden makro)</key>
|
||||
</area>
|
||||
<area alias="dashboard">
|
||||
<key alias="browser">Til dit website</key>
|
||||
@@ -231,6 +303,8 @@
|
||||
<key alias="copiedItemOfItems">Kopierede %0% ud af %1% elementer</key>
|
||||
</area>
|
||||
<area alias="defaultdialogs">
|
||||
<key alias="nodeNameLinkPicker">Link titel</key>
|
||||
<key alias="urlLinkPicker">Link</key>
|
||||
<key alias="anchorInsert">Navn på lokalt link</key>
|
||||
<key alias="assignDomain">Rediger domæner</key>
|
||||
<key alias="closeThisWindow">Luk denne dialog</key>
|
||||
@@ -258,6 +332,9 @@
|
||||
<key alias="macroDoesNotHaveProperties">Denne makro har ingen egenskaber du kan redigere</key>
|
||||
<key alias="paste">Indsæt tekst</key>
|
||||
<key alias="permissionsEdit">Rediger rettigheder for</key>
|
||||
<key alias="permissionsSet">Sæt rettigheder for</key>
|
||||
<key alias="permissionsSetForGroup">Sæt rettigheder for %0% for brugergruppe %1%</key>
|
||||
<key alias="permissionsHelp">Vælg de brugergrupper, du vil angive tilladelser til</key>
|
||||
<key alias="recycleBinDeleting">Elementerne i papirkurven slettes. Luk venligst ikke dette vindue mens sletningen foregår</key>
|
||||
<key alias="recycleBinIsEmpty">Papirkurven er nu tom</key>
|
||||
<key alias="recycleBinWarning">Når elementer slettes fra papirkurven, slettes de for altid</key>
|
||||
@@ -281,20 +358,28 @@
|
||||
<key alias="linkToPage">Link til side</key>
|
||||
<key alias="openInNewWindow">Åben linket i et nyt vindue eller fane</key>
|
||||
<key alias="linkToMedia">Link til medie</key>
|
||||
<key alias="linkToFile">Link til fil</key>
|
||||
<key alias="selectContentStartNode">Vælg indhold startnode</key>
|
||||
<key alias="selectMedia">Vælg medie</key>
|
||||
<key alias="selectIcon">Vælg ikon</key>
|
||||
<key alias="selectItem">Vælg item</key>
|
||||
<key alias="selectLink">Vælg link</key>
|
||||
<key alias="selectMacro">Vælg makro</key>
|
||||
<key alias="selectContent">Vælg indhold</key>
|
||||
<key alias="selectMediaStartNode">Vælg medie startnode</key>
|
||||
<key alias="selectMember">Vælg medlem</key>
|
||||
<key alias="selectMemberGroup">Vælg medlemsgruppe</key>
|
||||
<key alias="selectNode">Vælg node</key>
|
||||
<key alias="selectSections">Vælg sektioner</key>
|
||||
<key alias="selectUsers">Vælg brugere</key>
|
||||
<key alias="noIconsFound">Ingen ikoner blev fundet</key>
|
||||
<key alias="noMacroParams">Der er ingen parametre for denne makro</key>
|
||||
<key alias="noMacros">Der er ikke tilføjet nogen makroer</key>
|
||||
<key alias="linkYour">Link dit</key>
|
||||
<key alias="unLinkYour">Fjern link fra dit</key>
|
||||
<key alias="account">konto</key>
|
||||
<key alias="selectEditor">Vælg editor</key>
|
||||
<key alias="selectSnippet">Vælg snippet</key>
|
||||
</area>
|
||||
<area alias="dictionaryItem">
|
||||
<key alias="description">
|
||||
@@ -313,14 +398,18 @@
|
||||
<area alias="placeholders">
|
||||
<key alias="username">Indtast dit brugernavn</key>
|
||||
<key alias="password">Indtast dit kodeord</key>
|
||||
<key alias="confirmPassword">Bekræft dit kodeord</key>
|
||||
<key alias="nameentity">Navngiv %0%...</key>
|
||||
<key alias="entername">Indtast navn...</key>
|
||||
<key alias="enteremail">Indtast en e-mail...</key>
|
||||
<key alias="enterusername">Indtast et brugernavn...</key>
|
||||
<key alias="label">Label...</key>
|
||||
<key alias="enterDescription">Indtast beskrivelse</key>
|
||||
<key alias="search">Søg...</key>
|
||||
<key alias="filter">Filtrer...</key>
|
||||
<key alias="enterTags">Indtast nøgleord (tryk på Enter efter hvert nøgleord)...</key>
|
||||
<key alias="email">Indtast din e-mail</key>
|
||||
<key alias="enterMessage">Indtast en besked...</key>
|
||||
<key alias="usernameHint">Dit brugernavn er typisk din e-mailadresse</key>
|
||||
</area>
|
||||
<area alias="editcontenttype">
|
||||
@@ -341,6 +430,11 @@
|
||||
<key alias="createListView" version="7.2">Opret brugerdefineret listevisning</key>
|
||||
<key alias="removeListView" version="7.2">Fjern brugerdefineret listevisning</key>
|
||||
</area>
|
||||
<area alias="renamecontainer">
|
||||
<key alias="renamed">Omdøbt</key>
|
||||
<key alias="enterNewFolderName">Indtast et ny mappenavn her</key>
|
||||
<key alias="folderWasRenamed">%0% was renamed to %1%</key>
|
||||
</area>
|
||||
<area alias="editdatatype">
|
||||
<key alias="addPrevalue">Tilføj førværdi</key>
|
||||
<key alias="dataBaseDatatype">Database-datatype</key>
|
||||
@@ -353,6 +447,13 @@
|
||||
<key alias="rteRelatedStylesheets">Relaterede stylesheets</key>
|
||||
<key alias="rteShowLabel">Vis label</key>
|
||||
<key alias="rteWidthAndHeight">Bredde og højde</key>
|
||||
<key alias="allPropTypes">All property types & property data</key>
|
||||
<key alias="willBeDeleted">using this data type will be deleted permanently, please confirm you want to delete these as well</key>
|
||||
<key alias="yesDelete">Ja, slet</key>
|
||||
<key alias="andAllRelated">and all property types & property data using this data type</key>
|
||||
<key alias="selectFolder">Vælg den mappe, der skal flyttes</key>
|
||||
<key alias="inTheTree">til i træstrukturen nedenfor</key>
|
||||
<key alias="wasMoved">blev flyttet under</key>
|
||||
</area>
|
||||
<area alias="errorHandling">
|
||||
<key alias="errorButDataWasSaved">Dine data er blevet gemt, men før du kan udgive denne side er der nogle fejl der skal rettes:</key>
|
||||
@@ -424,15 +525,20 @@
|
||||
<key alias="email">E-mail</key>
|
||||
<key alias="error">Fejl</key>
|
||||
<key alias="findDocument">Find</key>
|
||||
<key alias="first">Første</key>
|
||||
<key alias="groups">Grupper</key>
|
||||
<key alias="height">Højde</key>
|
||||
<key alias="help">Hjælp</key>
|
||||
<key alias="hide">Skjul</key>
|
||||
<key alias="icon">Ikon</key>
|
||||
<key alias="import">Importer</key>
|
||||
<key alias="innerMargin">Indre margen</key>
|
||||
<key alias="insert">Indsæt</key>
|
||||
<key alias="install">Installér</key>
|
||||
<key alias="invalid">Ugyldig</key>
|
||||
<key alias="justify">Justering</key>
|
||||
<key alias="language">Sprog</key>
|
||||
<key alias="last">Sidste</key>
|
||||
<key alias="layout">Layout</key>
|
||||
<key alias="loading">Henter</key>
|
||||
<key alias="locked">Låst</key>
|
||||
@@ -440,6 +546,8 @@
|
||||
<key alias="logoff">Log af</key>
|
||||
<key alias="logout">Log ud</key>
|
||||
<key alias="macro">Makro</key>
|
||||
<key alias="mandatory">Påkrævet</key>
|
||||
<key alias="message">Besked</key>
|
||||
<key alias="move">Flyt</key>
|
||||
<key alias="more">Mere</key>
|
||||
<key alias="name">Navn</key>
|
||||
@@ -450,6 +558,7 @@
|
||||
<key alias="ok">OK</key>
|
||||
<key alias="open">Åben</key>
|
||||
<key alias="or">eller</key>
|
||||
<key alias="orderBy">Sortér efter</key>
|
||||
<key alias="password">Kodeord</key>
|
||||
<key alias="path">Sti</key>
|
||||
<key alias="placeHolderID">Placeholder ID</key>
|
||||
@@ -464,15 +573,18 @@
|
||||
<key alias="rename">Omdøb</key>
|
||||
<key alias="renew">Forny</key>
|
||||
<key alias="required" version="7.0">Påkrævet</key>
|
||||
<key alias="retrieve">Hent</key>
|
||||
<key alias="retry">Prøv igen</key>
|
||||
<key alias="rights">Rettigheder</key>
|
||||
<key alias="search">Søg</key>
|
||||
<key alias="searchNoResult">Beklager, vi kan ikke finde det, du leder efter.</key>
|
||||
<key alias="noItemsInList">Ingen elementer er blevet tilføjet</key>
|
||||
<key alias="server">Server</key>
|
||||
<key alias="show">Vis</key>
|
||||
<key alias="showPageOnSend">Hvilken side skal vises efter at formularen er sendt</key>
|
||||
<key alias="size">Størrelse</key>
|
||||
<key alias="sort">Sortér</key>
|
||||
<key alias="status">Status</key>
|
||||
<key alias="submit">Indsend</key>
|
||||
<!-- TODO: Translate this -->
|
||||
<key alias="type">Type</key>
|
||||
@@ -703,7 +815,40 @@ Mange hilsner fra Umbraco robotten
|
||||
</area>
|
||||
<area alias="packager">
|
||||
<key alias="chooseLocalPackageText">Vælg pakken fra din computer. Umbraco pakker er oftest en ".zip" fil</key>
|
||||
<key alias="packageAuthor">Udvikler</key>
|
||||
<key alias="dropHere">Slip her for at uploade</key>
|
||||
<key alias="orClickHereToUpload">eller klik her for at vælge pakkefil</key>
|
||||
<key alias="uploadPackage">Upload pakke</key>
|
||||
<key alias="localPackageDescription">Installer en lokal pakke ved at vælge den fra din computer. Installer kun pakker fra kilder, du kender og stoler på</key>
|
||||
<key alias="uploadAnother">Upload en anden pakke</key>
|
||||
<key alias="cancelAndUploadAnother">Annuller og upload en anden pakke</key>
|
||||
<key alias="packageLicense">Licens</key>
|
||||
<key alias="accept">Jeg accepterer</key>
|
||||
<key alias="termsOfUse">betingelser for anvendelse</key>
|
||||
<key alias="packageInstall">Installér pakke</key>
|
||||
<key alias="installFinish">Afslut</key>
|
||||
<key alias="installedPackages">Installeret pakker</key>
|
||||
<key alias="noPackages">Du har ingen pakker installeret</key>
|
||||
<key alias="noPackagesDescription"><![CDATA[Du har ikke nogen pakker installeret. Du kan enten installere en lokal pakke ved at vælge den fra din computer eller gennemse de tilgængelige pakker ved hjælp af ikonet <strong>'Pakker'</strong> øverst til højre på din skærm]]></key>
|
||||
<key alias="packageSearch">Søg efter pakker</key>
|
||||
<key alias="packageSearchResults">Resultater for</key>
|
||||
<key alias="packageNoResults">Vi kunne ikke finde resultater for</key>
|
||||
<key alias="packageNoResultsDescription">Prøv venligst at søge efter en anden pakke eller gennemse kategorierne</key>
|
||||
<key alias="packagesPopular">Populære</key>
|
||||
<key alias="packagesNew">Nye udgivelser</key>
|
||||
<key alias="packageHas">har</key>
|
||||
<key alias="packageKarmaPoints">karma points</key>
|
||||
<key alias="packageInfo">Information</key>
|
||||
<key alias="packageOwner">Ejer</key>
|
||||
<key alias="packageContrib">Bidragsydere</key>
|
||||
<key alias="packageCreated">Oprettet</key>
|
||||
<key alias="packageCurrentVersion">Nuværende version</key>
|
||||
<key alias="packageNetVersion">.NET version</key>
|
||||
<key alias="packageDownloads">Downloads</key>
|
||||
<key alias="packageLikes">Likes</key>
|
||||
<key alias="packageCompatibility">Kompatibilitet</key>
|
||||
<key alias="packageCompatibilityDescription">Denne pakke er kompatibel med de følgende versioner af Umbraco, som rapporteret af community-medlemmer. Fuld kompatibilitet kan ikke garanteres for versioner rapporteret nedenfor 100%</key>
|
||||
<key alias="packageExternalSources">Eksterne kilder</key>
|
||||
<key alias="packageAuthor">Forfatter</key>
|
||||
<key alias="packageDemonstration">Demonstration</key>
|
||||
<key alias="packageDocumentation">Dokumentation</key>
|
||||
<key alias="packageMetaData">Pakke meta data</key>
|
||||
@@ -727,7 +872,18 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="packageUpgradeInstructions">Opdateringsinstrukser</key>
|
||||
<key alias="packageUpgradeText">Der er en tilgængelig opdatering til denne pakke. Du kan downloade den direkte fra Umbracos pakke opbevaringsbase.</key>
|
||||
<key alias="packageVersion">Pakke version</key>
|
||||
<key alias="packageVersionHistory">Pakke versionshistorik</key>
|
||||
<key alias="viewPackageWebsite">Se pakkeudviklerens website</key>
|
||||
<key alias="packageAlreadyInstalled">Pakke allerede installeret</key>
|
||||
<key alias="targetVersionMismatch">Denne pakke kan ikke installeres, den kræver en minimum Umbraco version af</key>
|
||||
<key alias="installStateUninstalling">Afinstallerer...</key>
|
||||
<key alias="installStateDownloading">Downloader...</key>
|
||||
<key alias="installStateImporting">Importeret...</key>
|
||||
<key alias="installStateInstalling">Installerer...</key>
|
||||
<key alias="installStateRestarting">Genstarter, vent venligst...</key>
|
||||
<key alias="installStateComplete">Færdig, din browser opdateres nu, vent venligst...</key>
|
||||
<key alias="installStateCompleted">Klik venligst på 'Afslut' for at gennemføre installation og opdatere siden.</key>
|
||||
<key alias="installStateUploading">Uploader pakke...</key>
|
||||
</area>
|
||||
<area alias="paste">
|
||||
<key alias="doNothing">Indsæt med fuld formattering (Anbefales ikke)</key>
|
||||
@@ -779,6 +935,15 @@ Mange hilsner fra Umbraco robotten
|
||||
<area alias="colorpicker">
|
||||
<key alias="noColors">Du har ikke konfigureret nogen godkendte farver</key>
|
||||
</area>
|
||||
<area alias="contentPicker">
|
||||
<key alias="pickedTrashedItem">Du har valgt et dokument som er slettet eller lagt i papirkurven</key>
|
||||
<key alias="pickedTrashedItems">Du har valgt dokumenter som er slettede eller lagt i papirkurven</key>
|
||||
</area>
|
||||
<area alias="mediaPicker">
|
||||
<key alias="pickedTrashedItem">Du har valgt et medie som er slettet eller lagt i papirkurven</key>
|
||||
<key alias="pickedTrashedItems">Du har valgt medier som er slettede eller lagt i papirkurven</key>
|
||||
<key alias="deletedItem">Slettet medie</key>
|
||||
</area>
|
||||
<area alias="relatedlinks">
|
||||
<key alias="enterExternal">indtast eksternt link</key>
|
||||
<key alias="chooseInternal">vælg en intern side</key>
|
||||
@@ -791,108 +956,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<area alias="imagecropper">
|
||||
<key alias="reset">Nulstil</key>
|
||||
</area>
|
||||
<area alias="grid">
|
||||
<key alias="insertControl">Vælg indholdstype</key>
|
||||
<key alias="chooseLayout">Vælg layout</key>
|
||||
<key alias="addRows">Tilføj række</key>
|
||||
<key alias="addElement">Tilføj indhold</key>
|
||||
<key alias="dropElement">Slip indhold</key>
|
||||
<key alias="settingsApplied">Indstillinger tilføjet</key>
|
||||
|
||||
<key alias="contentNotAllowed">Indholdet er ikke tilladt her</key>
|
||||
<key alias="contentAllowed">Indholdet er tilladt her</key>
|
||||
|
||||
<key alias="clickToEmbed">Klik for at indlejre</key>
|
||||
<key alias="clickToInsertImage">Klik for at indsætte et billede</key>
|
||||
<key alias="placeholderImageCaption">Billedtekst...</key>
|
||||
<key alias="placeholderWriteHere">Skriv her...</key>
|
||||
|
||||
<key alias="gridLayouts">Gridlayout</key>
|
||||
<key alias="gridLayoutsDetail">Et layout er det overordnede arbejdsområde til dit gitter - du vil typisk kun behøve ét eller to</key>
|
||||
<key alias="addGridLayout">Tilføj gitterlayout</key>
|
||||
<key alias="addGridLayoutDetail">Juster dit layout ved at justere kolonnebredder og tilføj yderligere sektioner</key>
|
||||
|
||||
<key alias="rowConfigurations">Rækkekonfigurationer</key>
|
||||
<key alias="rowConfigurationsDetail">Rækker er foruddefinerede celler, der arrangeres vandret</key>
|
||||
<key alias="addRowConfiguration">Tilføj rækkekonfiguration</key>
|
||||
<key alias="addRowConfigurationDetail">Juster rækken ved at indstille cellebredder og tilføje yderligere celler</key>
|
||||
|
||||
<key alias="columns">Kolonner</key>
|
||||
<key alias="columnsDetails">Det totale antaller kolonner i gitteret</key>
|
||||
|
||||
<key alias="settings">Indstillinger</key>
|
||||
<key alias="settingsDetails">Konfigurer, hvilket indstillinger, brugeren kan ændre</key>
|
||||
|
||||
|
||||
<key alias="styles">Typografi</key>
|
||||
<key alias="stylesDetails">Vælg, hvilke typografiværdier, en redaktør kan ændre</key>
|
||||
|
||||
<key alias="settingDialogDetails">Indstillinger gemmes kun, hvis den indtaste json-konfiguration er gyldig</key>
|
||||
|
||||
<key alias="allowAllEditors">Tillad alle editorer</key>
|
||||
<key alias="allowAllRowConfigurations">Tillad alle rækkekonfigurationer</key>
|
||||
|
||||
<key alias="setAsDefault">Sæt som standard</key>
|
||||
<key alias="chooseExtra">Vælg ekstra</key>
|
||||
<key alias="chooseDefault">Vælg standard</key>
|
||||
<key alias="areAdded">er tilføjet</key>
|
||||
</area>
|
||||
|
||||
<area alias="contentTypeEditor">
|
||||
|
||||
<key alias="compositions">Kompositioner</key>
|
||||
<key alias="noTabs">Du har ikke tilføjet nogle faner</key>
|
||||
<key alias="addNewTab">Tilføj ny fane</key>
|
||||
<key alias="addAnotherTab">Tilføj endnu en fane</key>
|
||||
<key alias="inheritedFrom">Nedarvet fra</key>
|
||||
<key alias="addProperty">Tilføj property</key>
|
||||
<key alias="requiredLabel">Påkrævet label</key>
|
||||
|
||||
<key alias="enableListViewHeading">Aktiver listevisning</key>
|
||||
<key alias="enableListViewDescription">Konfigurer indholdet til at blive vist i en sorterbar og søgbar liste, dens børn vil ikke blive vist i træet</key>
|
||||
|
||||
<key alias="allowedTemplatesHeading">Tilladte skabeloner</key>
|
||||
<key alias="allowedTemplatesDescription">Vælg hvilke skabeloner der er tilladt at bruge på dette indhold</key>
|
||||
|
||||
<key alias="allowAsRootHeading">Tillad på rodniveau</key>
|
||||
<key alias="allowAsRootDescription">Kun dokumenttyper med denne indstilling aktiveret oprettes i rodniveau under inhold og mediearkiv</key>
|
||||
<key alias="allowAsRootCheckbox">Ja – indhold af denne type er tilladt i roden</key>
|
||||
|
||||
<key alias="childNodesHeading">Tilladte typer</key>
|
||||
<key alias="childNodesDescription">Tillad at oprette indhold af en specifik type under denne</key>
|
||||
|
||||
<key alias="chooseChildNode">Vælg child node</key>
|
||||
|
||||
<key alias="compositionsDescription">Nedarv faner og egenskaber fra en anden dokumenttype. Nye faner vil blive tilføjet den nuværende dokumenttype eller sammenflettet hvis fanenavnene er ens.</key>
|
||||
<key alias="compositionInUse">Indholdstypen bliver brugt i en komposition og kan derfor ikke blive anvendt som komposition</key>
|
||||
<key alias="noAvailableCompositions">Der er ingen indholdstyper tilgængelige at bruge som komposition</key>
|
||||
|
||||
<key alias="availableEditors">Tilgængelige editors</key>
|
||||
<key alias="reuse">Genbrug</key>
|
||||
<key alias="editorSettings">Editor indstillinger</key>
|
||||
|
||||
<key alias="configuration">Konfiguration</key>
|
||||
|
||||
<key alias="yesDelete">Ja, slet</key>
|
||||
|
||||
<key alias="movedUnderneath">blev flyttet til</key>
|
||||
<key alias="folderToMove">Vælg hvor</key>
|
||||
<key alias="structureBelow">skal flyttes til</key>
|
||||
|
||||
<key alias="allDocumentTypes">Alle dokumenttyper</key>
|
||||
<key alias="allDocuments">Alle dokumenter</key>
|
||||
<key alias="allMediaItems">Alle medier</key>
|
||||
|
||||
<key alias="usingThisDocument">som benytter denne dokumenttype vil blive slettet permanent. Bekræft at du også vil slette dem.</key>
|
||||
<key alias="usingThisMedia">som benytter denne medietype vil blive slettet permanent. Bekræft at du også vil slette dem.</key>
|
||||
<key alias="usingThisMember">som benytter denne medlemstype vil blive slettet permanent. Bekræft at du også vil slette dem.</key>
|
||||
|
||||
<key alias="andAllDocuments">og alle dokumenter, som benytter denne type</key>
|
||||
<key alias="andAllMediaItems">og alle medier, som benytter denne type</key>
|
||||
<key alias="andAllMembers">og alle medlemmer, som benytter denne type</key>
|
||||
|
||||
<key alias="thisEditorUpdateSettings">der bruger denne editor vil blive opdateret med de nye indstillinger</key>
|
||||
</area>
|
||||
|
||||
|
||||
<area alias="rollback">
|
||||
<key alias="currentVersion">Nuværende version</key>
|
||||
@@ -1008,13 +1072,36 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="partialViewSavedText">Partial view gemt uden fejl!</key>
|
||||
<key alias="partialViewErrorHeader">Partial view ikke gemt</key>
|
||||
<key alias="partialViewErrorText">Der opstod en fejl ved at gemme filen.</key>
|
||||
<key alias="permissionsSavedFor">Rettigheder gemt for</key>
|
||||
<key alias="scriptSavedHeader">Script view gemt</key>
|
||||
<key alias="scriptSavedText">Script view gemt uden fejl!</key>
|
||||
<key alias="scriptErrorHeader">Script view ikke gemt</key>
|
||||
<key alias="scriptErrorText">An error occurred saving the file.</key>
|
||||
<key alias="cssErrorText">An error occurred saving the file.</key>
|
||||
<key alias="deleteUserGroupsSuccess">Slettede %0% brugergrupper</key>
|
||||
<key alias="deleteUserGroupSuccess">%0% blev slettet</key>
|
||||
<key alias="enableUsersSuccess">Aktiverede %0% brugere</key>
|
||||
<key alias="enableUsersError">Der opstod en fejl under aktivering af brugerne</key>
|
||||
<key alias="disableUsersSuccess">Deaktiverede %0% brugere</key>
|
||||
<key alias="disableUsersError">Der opstod en fejl under deaktivering af brugerne</key>
|
||||
<key alias="enableUserSuccess">%0% er nu aktiveret</key>
|
||||
<key alias="enableUserError">Der opstod en fejl under aktivering af brugeren</key>
|
||||
<key alias="disableUserSuccess">%0% er nu deaktiveret</key>
|
||||
<key alias="disableUserError">Der opstod en fejl under deaktivering af brugeren</key>
|
||||
<key alias="setUserGroupOnUsersSuccess">Brugergrupper er blevet indstillet</key>
|
||||
<key alias="deleteUserGroupsSuccess">Slettede %0% brugergrupper</key>
|
||||
<key alias="deleteUserGroupSuccess">%0% blev slettet</key>
|
||||
<key alias="unlockUsersSuccess">Låste %0% brugere op</key>
|
||||
<key alias="unlockUsersError">Der opstod en fejl under oplåsning af brugerne</key>
|
||||
<key alias="unlockUserSuccess">%0% er nu låst op</key>
|
||||
<key alias="unlockUserError">Der opstod en fejl under oplåsning af brugeren</key>
|
||||
</area>
|
||||
<area alias="stylesheet">
|
||||
<key alias="aliasHelp">Bruger CSS-syntax f.eks. h1, .redheader, .blueTex</key>
|
||||
<key alias="aliasHelp">Bruger CSS-syntaks f.eks. h1, .redheader, .blueTex</key>
|
||||
<key alias="editstylesheet">Rediger stylesheet</key>
|
||||
<key alias="editstylesheetproperty">Rediger CSS-egenskab</key>
|
||||
<key alias="nameHelp">Navn der identificerer CSS-egenskaben i tekstredigeringsværktøjet</key>
|
||||
<key alias="preview">Vis prøve</key>
|
||||
<key alias="preview">Forhåndsvisning</key>
|
||||
<key alias="styles">Styles</key>
|
||||
</area>
|
||||
|
||||
@@ -1127,7 +1214,114 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="template">Skabelon</key>
|
||||
</area>
|
||||
|
||||
|
||||
<area alias="grid">
|
||||
<key alias="insertControl">Vælg indholdstype</key>
|
||||
<key alias="chooseLayout">Vælg layout</key>
|
||||
<key alias="addRows">Tilføj række</key>
|
||||
<key alias="addElement">Tilføj indhold</key>
|
||||
<key alias="dropElement">Slip indhold</key>
|
||||
<key alias="settingsApplied">Indstillinger tilføjet</key>
|
||||
|
||||
<key alias="contentNotAllowed">Indholdet er ikke tilladt her</key>
|
||||
<key alias="contentAllowed">Indholdet er tilladt her</key>
|
||||
|
||||
<key alias="clickToEmbed">Klik for at indlejre</key>
|
||||
<key alias="clickToInsertImage">Klik for at indsætte et billede</key>
|
||||
<key alias="placeholderImageCaption">Billedtekst...</key>
|
||||
<key alias="placeholderWriteHere">Skriv her...</key>
|
||||
|
||||
<key alias="gridLayouts">Gitterlayout</key>
|
||||
<key alias="gridLayoutsDetail">Et layout er det overordnede arbejdsområde til dit gitter - du vil typisk kun behøve ét eller to</key>
|
||||
<key alias="addGridLayout">Tilføj gitterlayout</key>
|
||||
<key alias="addGridLayoutDetail">Juster dit layout ved at justere kolonnebredder og tilføj yderligere sektioner</key>
|
||||
|
||||
<key alias="rowConfigurations">Rækkekonfigurationer</key>
|
||||
<key alias="rowConfigurationsDetail">Rækker er foruddefinerede celler, der arrangeres vandret</key>
|
||||
<key alias="addRowConfiguration">Tilføj rækkekonfiguration</key>
|
||||
<key alias="addRowConfigurationDetail">Juster rækken ved at indstille cellebredder og tilføje yderligere celler</key>
|
||||
|
||||
<key alias="columns">Kolonner</key>
|
||||
<key alias="columnsDetails">Det totale antaller kolonner i gitteret</key>
|
||||
|
||||
<key alias="settings">Indstillinger</key>
|
||||
<key alias="settingsDetails">Konfigurer, hvilket indstillinger, brugeren kan ændre</key>
|
||||
|
||||
|
||||
<key alias="styles">Typografi</key>
|
||||
<key alias="stylesDetails">Vælg, hvilke typografiværdier, en redaktør kan ændre</key>
|
||||
|
||||
<key alias="settingDialogDetails">Indstillinger gemmes kun, hvis den indtaste json-konfiguration er gyldig</key>
|
||||
|
||||
<key alias="allowAllEditors">Tillad alle editorer</key>
|
||||
<key alias="allowAllRowConfigurations">Tillad alle rækkekonfigurationer</key>
|
||||
|
||||
<key alias="setAsDefault">Sæt som standard</key>
|
||||
<key alias="chooseExtra">Vælg ekstra</key>
|
||||
<key alias="chooseDefault">Vælg standard</key>
|
||||
<key alias="areAdded">er tilføjet</key>
|
||||
|
||||
<key alias="maxItems">Maksimalt emner</key>
|
||||
<key alias="maxItemsDescription">Efterlad blank eller sat til 0 ubegrænset for</key>
|
||||
|
||||
</area>
|
||||
<area alias="contentTypeEditor">
|
||||
|
||||
<key alias="compositions">Kompositioner</key>
|
||||
<key alias="noTabs">Du har ikke tilføjet nogle faner</key>
|
||||
<key alias="addNewTab">Tilføj ny fane</key>
|
||||
<key alias="addAnotherTab">Tilføj endnu en fane</key>
|
||||
<key alias="inheritedFrom">Nedarvet fra</key>
|
||||
<key alias="addProperty">Tilføj property</key>
|
||||
<key alias="requiredLabel">Påkrævet label</key>
|
||||
|
||||
<key alias="enableListViewHeading">Aktiver listevisning</key>
|
||||
<key alias="enableListViewDescription">Konfigurer indholdet til at blive vist i en sorterbar og søgbar liste, dens børn vil ikke blive vist i træet</key>
|
||||
|
||||
<key alias="allowedTemplatesHeading">Tilladte skabeloner</key>
|
||||
<key alias="allowedTemplatesDescription">Vælg hvilke skabeloner der er tilladt at bruge på dette indhold</key>
|
||||
|
||||
<key alias="allowAsRootHeading">Tillad på rodniveau</key>
|
||||
<key alias="allowAsRootDescription">Kun dokumenttyper med denne indstilling aktiveret oprettes i rodniveau under inhold og mediearkiv</key>
|
||||
<key alias="allowAsRootCheckbox">Ja – indhold af denne type er tilladt i roden</key>
|
||||
|
||||
<key alias="childNodesHeading">Tilladte typer</key>
|
||||
<key alias="childNodesDescription">Tillad at oprette indhold af en specifik type under denne</key>
|
||||
|
||||
<key alias="chooseChildNode">Vælg child node</key>
|
||||
|
||||
<key alias="compositionsDescription">Nedarv faner og egenskaber fra en anden dokumenttype. Nye faner vil blive tilføjet den nuværende dokumenttype eller sammenflettet hvis fanenavnene er ens.</key>
|
||||
<key alias="compositionInUse">Indholdstypen bliver brugt i en komposition og kan derfor ikke blive anvendt som komposition</key>
|
||||
<key alias="noAvailableCompositions">Der er ingen indholdstyper tilgængelige at bruge som komposition</key>
|
||||
|
||||
<key alias="availableEditors">Tilgængelige editors</key>
|
||||
<key alias="reuse">Genbrug</key>
|
||||
<key alias="editorSettings">Editor indstillinger</key>
|
||||
|
||||
<key alias="configuration">Konfiguration</key>
|
||||
|
||||
<key alias="yesDelete">Ja, slet</key>
|
||||
|
||||
<key alias="movedUnderneath">blev flyttet til</key>
|
||||
<key alias="folderToMove">Vælg hvor</key>
|
||||
<key alias="structureBelow">skal flyttes til</key>
|
||||
|
||||
<key alias="allDocumentTypes">Alle dokumenttyper</key>
|
||||
<key alias="allDocuments">Alle dokumenter</key>
|
||||
<key alias="allMediaItems">Alle medier</key>
|
||||
|
||||
<key alias="usingThisDocument">som benytter denne dokumenttype vil blive slettet permanent. Bekræft at du også vil slette dem.</key>
|
||||
<key alias="usingThisMedia">som benytter denne medietype vil blive slettet permanent. Bekræft at du også vil slette dem.</key>
|
||||
<key alias="usingThisMember">som benytter denne medlemstype vil blive slettet permanent. Bekræft at du også vil slette dem.</key>
|
||||
|
||||
<key alias="andAllDocuments">og alle dokumenter, som benytter denne type</key>
|
||||
<key alias="andAllMediaItems">og alle medier, som benytter denne type</key>
|
||||
<key alias="andAllMembers">og alle medlemmer, som benytter denne type</key>
|
||||
|
||||
<key alias="thisEditorUpdateSettings">der bruger denne editor vil blive opdateret med de nye indstillinger</key>
|
||||
<key alias="memberCanEdit">Medlem kan redigere</key>
|
||||
<key alias="showOnMemberProfile">Vis på medlemsprofil</key>
|
||||
<key alias="tabHasNoSortOrder">fane har ingen sorteringsrækkefølge</key>
|
||||
</area>
|
||||
<area alias="templateEditor">
|
||||
<key alias="alternativeField">Alternativt felt</key>
|
||||
<key alias="alternativeText">Alternativ tekst</key>
|
||||
@@ -1183,6 +1377,9 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="uploadTranslationXml">Upload oversættelse (xml)</key>
|
||||
</area>
|
||||
<area alias="treeHeaders">
|
||||
<key alias="content">Indhold</key>
|
||||
<key alias="contentBlueprints">Indholdsskabeloner</key>
|
||||
<key alias="media">Mediearkiv</key>
|
||||
<key alias="cacheBrowser">Cacheviser</key>
|
||||
<key alias="contentRecycleBin">Papirkurv</key>
|
||||
<key alias="createdPackages">Oprettede pakker</key>
|
||||
@@ -1215,6 +1412,7 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="templates">Skabeloner</key>
|
||||
<key alias="xslt">XSLT-filer</key>
|
||||
<key alias="analytics">Analytics</key>
|
||||
<key alias="users">Brugere</key>
|
||||
</area>
|
||||
<area alias="update">
|
||||
<key alias="updateAvailable">Ny opdatering er klar</key>
|
||||
@@ -1224,23 +1422,41 @@ Mange hilsner fra Umbraco robotten
|
||||
</area>
|
||||
<area alias="user">
|
||||
<key alias="access">Adgang</key>
|
||||
<key alias="accessHelp">Baseret på de tildelte grupper og startnoder har brugeren adgang til følgende noder</key>
|
||||
<key alias="assignAccess">Tildel adgang</key>
|
||||
<key alias="administrators">Administrator</key>
|
||||
<key alias="categoryField">Kategorifelt</key>
|
||||
<key alias="createDate">Bruger oprettet</key>
|
||||
<key alias="changePassword">Skift dit kodeord</key>
|
||||
<key alias="changePhoto">Skift billede</key>
|
||||
<key alias="newPassword">Nyt kodeord</key>
|
||||
<key alias="noLockouts">er ikke blevet låst ude</key>
|
||||
<key alias="noPasswordChange">Kodeordet er ikke blevet ændret</key>
|
||||
<key alias="confirmNewPassword">Gentag dit nye kodeord</key>
|
||||
<key alias="changePasswordDescription">Du kan ændre dit kodeord, som giver dig adgang til Umbraco Back Office ved at udfylde formularen og klikke på knappen 'Skift dit kodeord'</key>
|
||||
<key alias="contentChannel">Indholdskanal</key>
|
||||
<key alias="changePhoto">Skift billede</key>
|
||||
<key alias="createUserHelp">Opret nye brugere for at give dem adgang til Umbraco. Når en ny bruger oprettes, genereres der en adgangskode, som du kan dele med brugeren.</key>
|
||||
<key alias="descriptionField">Beskrivelsesfelt</key>
|
||||
<key alias="disabled">Deaktivér bruger</key>
|
||||
<key alias="documentType">Dokumenttype</key>
|
||||
<key alias="editors">Redaktør</key>
|
||||
<key alias="excerptField">Uddragsfelt</key>
|
||||
<key alias="failedPasswordAttempts">Fejlet loginforsøg</key>
|
||||
<key alias="goToProfile">Gå til brugerprofil</key>
|
||||
<key alias="groupsHelp">Tilføj grupper for at tildele adgang og tilladelser</key>
|
||||
<key alias="inviteAnotherUser">Invitér anden bruger</key>
|
||||
<key alias="inviteUserHelp">Invitér nye brugere til at give dem adgang til Umbraco. En invitation vil blive sendt via e-mail til brugeren med oplysninger om, hvordan man logger ind i Umbraco.</key>
|
||||
<key alias="language">Sprog</key>
|
||||
<key alias="lastLogin">Sidste login</key>
|
||||
<key alias="languageHelp">Indstil det sprog, du vil se i menuer og dialoger</key>
|
||||
<key alias="lastLockoutDate">Seneste låst ude dato</key>
|
||||
<key alias="lastLogin">Senest login</key>
|
||||
<key alias="lastPasswordChangeDate">Kodeord sidst ændret</key>
|
||||
<key alias="loginname">Brugernavn</key>
|
||||
<key alias="mediastartnode">Startnode i mediearkivet</key>
|
||||
<key alias="mediastartnodehelp">Begræns mediebiblioteket til en bestemt startnode</key>
|
||||
<key alias="mediastartnodes">Medie startnoder</key>
|
||||
<key alias="mediastartnodeshelp">Begræns mediebiblioteket til bestemte startnoder</key>
|
||||
<key alias="modules">Moduler</key>
|
||||
<key alias="noConsole">Deaktivér adgang til Umbraco</key>
|
||||
<key alias="noLogin">har endnu ikke logget ind</key>
|
||||
@@ -1259,17 +1475,58 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="permissionReplaceChildren">Erstat underelement-rettigheder</key>
|
||||
<key alias="permissionSelectedPages">Du ændrer i øjeblikket rettigheder for siderne:</key>
|
||||
<key alias="permissionSelectPages">Vælg sider for at ændre deres rettigheder</key>
|
||||
<key alias="removePhoto">Fjern billede</key>
|
||||
<key alias="permissionsDefault">Standard rettigheder</key>
|
||||
<key alias="permissionsGranular">Granulære rettigheder</key>
|
||||
<key alias="permissionsGranularHelp">Sæt rettigheder for specifikke noder</key>
|
||||
<key alias="profile">Profil</key>
|
||||
<key alias="searchAllChildren">Søg alle 'børn'</key>
|
||||
<key alias="startnode">Start node</key>
|
||||
<key alias="stateActive">Aktiv</key>
|
||||
<key alias="stateAll">Alle</key>
|
||||
<key alias="stateDisabled">Deaktiveret</key>
|
||||
<key alias="stateLockedOut">Låst ude</key>
|
||||
<key alias="stateInvited">Inviteret</key>
|
||||
<key alias="sortNameAscending">Navn (A-Å)</key>
|
||||
<key alias="sortNameDescending">Navn (Å-A)</key>
|
||||
<key alias="sortCreateDateDescending">Nyeste</key>
|
||||
<key alias="sortCreateDateAscending">Ældste</key>
|
||||
<key alias="sortLastLoginDateDescending">Senest login</key>
|
||||
<key alias="sectionsHelp">Tilføj sektioner for at give brugerne adgang</key>
|
||||
<key alias="selectUserGroups">Vælg brugergrupper</key>
|
||||
<key alias="noStartNode">Ingen startnode valgt</key>
|
||||
<key alias="noStartNodes">Ingen startnoder valgt</key>
|
||||
<key alias="startnode">Startnode</key>
|
||||
<key alias="startnodehelp">Begræns indholdstræet til en bestemt startnode</key>
|
||||
<key alias="startnodes">Indhold startnoder</key>
|
||||
<key alias="startnodeshelp">Begræns indholdstræet til bestemte startnoder</key>
|
||||
<key alias="updateDate">Bruger sidst opdateret</key>
|
||||
<key alias="userCreated">er blevet oprettet</key>
|
||||
<key alias="userCreatedSuccessHelp">Den nye bruger er blevet oprettet. For at logge ind i Umbraco skal du bruge adgangskoden nedenfor.</key>
|
||||
<key alias="userManagement">Brugeradministration</key>
|
||||
<key alias="username">Navn</key>
|
||||
<key alias="userPermissions">Brugertilladelser</key>
|
||||
<key alias="userGroupPermissions">Brugergruppe tilladelser</key>
|
||||
<key alias="usergroup">Brugergruppe</key>
|
||||
<key alias="userGroups">Brugergrupper</key>
|
||||
<key alias="userInvited">er blevet inviteret</key>
|
||||
<key alias="userInvitedSuccessHelp">En invitation er blevet sendt til den nye bruger med oplysninger om, hvordan man logger ind i Umbraco.</key>
|
||||
<key alias="userinviteWelcomeMessage">Hej og velkommen til Umbraco! På bare 1 minut vil du være klar til at komme i gang, vi skal bare have dig til at oprette en adgangskode og tilføje et billede til din avatar.</key>
|
||||
<key alias="userinviteAvatarMessage">Upload et billede for at gøre det nemt for andre brugere at genkende dig.</key>
|
||||
<key alias="writer">Forfatter</key>
|
||||
<key alias="translator">Oversætter</key>
|
||||
<key alias="change">Skift</key>
|
||||
<key alias="yourProfile">Din profil</key>
|
||||
<key alias="yourHistory">Din historik</key>
|
||||
<key alias="sessionExpires">Session udløber</key>
|
||||
<key alias="inviteUser">Invitér bruger</key>
|
||||
<key alias="createUser">Opret bruger</key>
|
||||
<key alias="sendInvite">Send invitation</key>
|
||||
<key alias="backToUsers">Tilbage til brugere</key>
|
||||
<key alias="inviteEmailCopySubject">Umbraco: Invitation</key>
|
||||
<key alias="inviteEmailCopyFormat">
|
||||
<![CDATA[<html><body><p>Hej %0%, du er blevet inviteret af %1% til Umbraco backoffice.</p><p>Besked fra %1%: <em>%2%</em></p><p>Klik på dette <a href="%3%" target="_blank">link</a> for acceptere invitationen</p><p><small>Hvis du ikke kan klikke på linket, så kopier og indsæt denne URL i dit browservindue<br/><br/>%3%</small></p></body></html>]]>
|
||||
</key>
|
||||
</area>
|
||||
<area alias="validation">
|
||||
<key alias="validation">Validation</key>
|
||||
@@ -1278,6 +1535,14 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="validateAsUrl">Valider som Url</key>
|
||||
<key alias="enterCustomValidation">...eller indtast din egen validering</key>
|
||||
<key alias="fieldIsMandatory">Feltet er påkrævet</key>
|
||||
<key alias="validationRegExp">Indtast et regulært udtryk</key>
|
||||
<key alias="minCount">Du skal tilføje mindst</key>
|
||||
<key alias="maxCount">Du kan kun have</key>
|
||||
<key alias="items">elementer</key>
|
||||
<key alias="itemsSelected">elementer valgt</key>
|
||||
<key alias="invalidDate">Ugyldig dato</key>
|
||||
<key alias="invalidNumber">Ikke et tal</key>
|
||||
<key alias="invalidEmail">Ugyldig e-mail</key>
|
||||
</area>
|
||||
<area alias="redirectUrls">
|
||||
<key alias="disableUrlTracker">Slå URL tracker fra</key>
|
||||
@@ -1296,6 +1561,9 @@ Mange hilsner fra Umbraco robotten
|
||||
<key alias="enabledConfirm">URL tracker er nu slået fra.</key>
|
||||
<key alias="enableError">Der opstod en fejl under forsøget på at slå URL trackeren til, der findes mere information i logfilen.</key>
|
||||
</area>
|
||||
<area alias="emptyStates">
|
||||
<key alias="emptyDictionaryTree">Ingen ordbog elementer at vælge imellem</key>
|
||||
</area>
|
||||
<area alias="textbox">
|
||||
<key alias="characters_left">Karakterer tilbage</key>
|
||||
</area>
|
||||
|
||||
@@ -87,14 +87,14 @@
|
||||
<key alias="domainUpdated">Domain '%0%' has been updated</key>
|
||||
<key alias="orEdit">Edit Current Domains</key>
|
||||
<key alias="domainHelp">
|
||||
<![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
|
||||
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
|
||||
<![CDATA[Valid domain names are: "example.com", "www.example.com", "example.com:8080" or
|
||||
"https://www.example.com/". One-level paths in domains are supported, eg. "example.com/en". However, they
|
||||
should be avoided. Better use the culture setting above.]]>
|
||||
</key>
|
||||
<key alias="inherit">Inherit</key>
|
||||
<key alias="setLanguage">Culture</key>
|
||||
<key alias="setLanguageHelp">
|
||||
<![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
|
||||
<![CDATA[Set the culture for nodes below the current node,<br /> or inherit culture from parent nodes. Will also apply<br />
|
||||
to the current node, unless a domain below applies too.]]>
|
||||
</key>
|
||||
<key alias="setDomains">Domains</key>
|
||||
@@ -351,11 +351,11 @@
|
||||
<key alias="tableColumns">Number of columns</key>
|
||||
<key alias="tableRows">Number of rows</key>
|
||||
<key alias="templateContentAreaHelp">
|
||||
<![CDATA[<strong>Set a placeholder id</strong> by setting an ID on your placeholder you can inject content into this template from child templates,
|
||||
<![CDATA[<strong>Set a placeholder id</strong> by setting an ID on your placeholder you can inject content into this template from child templates,
|
||||
by referring this ID using a <code><asp:content /></code> element.]]>
|
||||
</key>
|
||||
<key alias="templateContentPlaceHolderHelp">
|
||||
<![CDATA[<strong>Select a placeholder id</strong> from the list below. You can only
|
||||
<![CDATA[<strong>Select a placeholder id</strong> from the list below. You can only
|
||||
choose Id's from the current template's master.]]>
|
||||
</key>
|
||||
<key alias="thumbnailimageclickfororiginal">Click on the image to see full size</key>
|
||||
@@ -397,15 +397,15 @@
|
||||
</area>
|
||||
<area alias="dictionaryItem">
|
||||
<key alias="description">
|
||||
<![CDATA[
|
||||
Edit the different language versions for the dictionary item '<em>%0%</em>' below<br/>You can add additional languages under the 'languages' in the menu on the left
|
||||
<![CDATA[
|
||||
Edit the different language versions for the dictionary item '<em>%0%</em>' below<br/>You can add additional languages under the 'languages' in the menu on the left
|
||||
]]>
|
||||
</key>
|
||||
<key alias="displayName">Culture Name</key>
|
||||
<key alias="changeKey">Edit the key of the dictionary item.</key>
|
||||
<key alias="changeKeyError">
|
||||
<![CDATA[
|
||||
The key '%0%' already exists.
|
||||
<![CDATA[
|
||||
The key '%0%' already exists.
|
||||
]]>
|
||||
</key>
|
||||
</area>
|
||||
@@ -1081,6 +1081,15 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<area alias="colorpicker">
|
||||
<key alias="noColors">You have not configured any approved colours</key>
|
||||
</area>
|
||||
<area alias="contentPicker">
|
||||
<key alias="pickedTrashedItem">You have picked a content item currently deleted or in the recycle bin</key>
|
||||
<key alias="pickedTrashedItems">You have picked content items currently deleted or in the recycle bin</key>
|
||||
</area>
|
||||
<area alias="mediaPicker">
|
||||
<key alias="pickedTrashedItem">You have picked a media item currently deleted or in the recycle bin</key>
|
||||
<key alias="pickedTrashedItems">You have picked media items currently deleted or in the recycle bin</key>
|
||||
<key alias="deletedItem">Deleted item</key>
|
||||
</area>
|
||||
<area alias="relatedlinks">
|
||||
<key alias="enterExternal">enter external link</key>
|
||||
<key alias="chooseInternal">choose internal page</key>
|
||||
@@ -1401,6 +1410,8 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
|
||||
<key alias="allowAllEditors">Allow all editors</key>
|
||||
<key alias="allowAllRowConfigurations">Allow all row configurations</key>
|
||||
<key alias="maxItemsDescription">Leave blank or set to 0 for unlimited</key>
|
||||
<key alias="maxItems">Maximum items</key>
|
||||
<key alias="setAsDefault">Set as default</key>
|
||||
<key alias="chooseExtra">Choose extra</key>
|
||||
<key alias="chooseDefault">Choose default</key>
|
||||
@@ -1676,15 +1687,27 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="profile">Profile</key>
|
||||
<key alias="searchAllChildren">Search all children</key>
|
||||
<key alias="sectionsHelp">Add sections to give users access</key>
|
||||
<key alias="selectUserGroups">Select user groups</key>
|
||||
<key alias="noStartNode">No start node selected</key>
|
||||
<key alias="noStartNodes">No start nodes selected</key>
|
||||
<key alias="stateActive">Active</key>
|
||||
<key alias="stateAll">All</key>
|
||||
<key alias="stateDisabled">Disabled</key>
|
||||
<key alias="stateLockedOut">Locked out</key>
|
||||
<key alias="stateInvited">Invited</key>
|
||||
<key alias="startnode">Content start node</key>
|
||||
<key alias="startnodehelp">Limit the content tree to a specific start node</key>
|
||||
<key alias="startnodes">Content start nodes</key>
|
||||
<key alias="startnodeshelp">Limit the content tree to specific start nodes</key>
|
||||
<key alias="sortNameAscending">Name (A-Z)</key>
|
||||
<key alias="sortNameDescending">Name (Z-A)</key>
|
||||
<key alias="sortCreateDateDescending">Newest</key>
|
||||
<key alias="sortCreateDateAscending">Oldest</key>
|
||||
<key alias="sortLastLoginDateDescending">Last login</key>
|
||||
<key alias="updateDate">User last updated</key>
|
||||
<key alias="userCreated">has been created</key>
|
||||
<key alias="userCreatedSuccessHelp">The new user has successfully been created. To log in to Umbraco use the password below.</key>
|
||||
<key alias="userManagement">User management</key>
|
||||
<key alias="username">Name</key>
|
||||
<key alias="userPermissions">User permissions</key>
|
||||
<key alias="userGroupPermissions">User group permissions</key>
|
||||
@@ -1857,4 +1880,4 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<area alias="textbox">
|
||||
<key alias="characters_left">characters left</key>
|
||||
</area>
|
||||
</language>
|
||||
</language>
|
||||
|
||||
@@ -1079,6 +1079,15 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<area alias="colorpicker">
|
||||
<key alias="noColors">You have not configured any approved colors</key>
|
||||
</area>
|
||||
<area alias="contentPicker">
|
||||
<key alias="pickedTrashedItem">You have picked a content item currently deleted or in the recycle bin</key>
|
||||
<key alias="pickedTrashedItems">You have picked content items currently deleted or in the recycle bin</key>
|
||||
</area>
|
||||
<area alias="mediaPicker">
|
||||
<key alias="pickedTrashedItem">You have picked a media item currently deleted or in the recycle bin</key>
|
||||
<key alias="pickedTrashedItems">You have picked media items currently deleted or in the recycle bin</key>
|
||||
<key alias="deletedItem">Deleted item</key>
|
||||
</area>
|
||||
<area alias="relatedlinks">
|
||||
<key alias="enterExternal">enter external link</key>
|
||||
<key alias="chooseInternal">choose internal page</key>
|
||||
@@ -1397,6 +1406,8 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
|
||||
<key alias="allowAllEditors">Allow all editors</key>
|
||||
<key alias="allowAllRowConfigurations">Allow all row configurations</key>
|
||||
<key alias="maxItems">Maximum items</key>
|
||||
<key alias="maxItemsDescription">Leave blank or set to 0 for unlimited</key>
|
||||
<key alias="setAsDefault">Set as default</key>
|
||||
<key alias="chooseExtra">Choose extra</key>
|
||||
<key alias="chooseDefault">Choose default</key>
|
||||
@@ -1669,15 +1680,27 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="profile">Profile</key>
|
||||
<key alias="searchAllChildren">Search all children</key>
|
||||
<key alias="sectionsHelp">Add sections to give users access</key>
|
||||
<key alias="selectUserGroups">Select user groups</key>
|
||||
<key alias="noStartNode">No start node selected</key>
|
||||
<key alias="noStartNodes">No start nodes selected</key>
|
||||
<key alias="stateActive">Active</key>
|
||||
<key alias="stateAll">All</key>
|
||||
<key alias="stateDisabled">Disabled</key>
|
||||
<key alias="stateLockedOut">Locked out</key>
|
||||
<key alias="stateInvited">Invited</key>
|
||||
<key alias="startnode">Content start node</key>
|
||||
<key alias="startnodehelp">Limit the content tree to a specific start node</key>
|
||||
<key alias="startnodes">Content start nodes</key>
|
||||
<key alias="startnodeshelp">Limit the content tree to specific start nodes</key>
|
||||
<key alias="sortNameAscending">Name (A-Z)</key>
|
||||
<key alias="sortNameDescending">Name (Z-A)</key>
|
||||
<key alias="sortCreateDateDescending">Newest</key>
|
||||
<key alias="sortCreateDateAscending">Oldest</key>
|
||||
<key alias="sortLastLoginDateDescending">Last login</key>
|
||||
<key alias="updateDate">User last updated</key>
|
||||
<key alias="userCreated">has been created</key>
|
||||
<key alias="userCreatedSuccessHelp">The new user has successfully been created. To log in to Umbraco use the password below.</key>
|
||||
<key alias="userManagement">User management</key>
|
||||
<key alias="username">Name</key>
|
||||
<key alias="userPermissions">User permissions</key>
|
||||
<key alias="userGroupPermissions">User group permissions</key>
|
||||
|
||||
@@ -789,6 +789,9 @@
|
||||
|
||||
<key alias="allowAllEditors">Permitir todos los controles de edición</key>
|
||||
<key alias="allowAllRowConfigurations">Permitir todas las configuraciones de fila</key>
|
||||
<key alias="maxItems">Artículos máximos</key>
|
||||
<key alias="maxItemsDescription">Laat dit leeg of is ingesteld op -1 voor onbeperkt</key>
|
||||
<key alias="maxItemsDescription">Dejar en blanco o se establece en 0 para ilimitada</key>
|
||||
</area>
|
||||
<area alias="templateEditor">
|
||||
<key alias="alternativeField">Campo opcional</key>
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
<key alias="disable">נטרל</key>
|
||||
<key alias="emptyTrashcan">רוקן סל מיחזור</key>
|
||||
<key alias="exportDocumentType">ייצא סוג קובץ</key>
|
||||
<key alias="exportDocumentTypeAsCode">ייצא אל.NET</key>
|
||||
<key alias="exportDocumentTypeAsCode-Full">ייצא אל .NET</key>
|
||||
<key alias="importDocumentType">ייבא סוג מסמך</key>
|
||||
<key alias="importPackage">ייבא חבילה</key>
|
||||
<key alias="liveEdit">ערוך במצב "קנבס"</key>
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
<key alias="disable">비활성</key>
|
||||
<key alias="emptyTrashcan">휴지통 비우기</key>
|
||||
<key alias="exportDocumentType">추출 문서 유형</key>
|
||||
<key alias="exportDocumentTypeAsCode">.NET으로 추출</key>
|
||||
<key alias="exportDocumentTypeAsCode-Full">.NET으로 추출</key>
|
||||
<key alias="importDocumentType">등록 문서 유형</key>
|
||||
<key alias="importPackage">패키지 등록</key>
|
||||
<key alias="liveEdit">캔버스 내용 편집</key>
|
||||
|
||||
@@ -1077,7 +1077,9 @@ Echter, Runway biedt een gemakkelijke basis om je snel op weg te helpen. Als je
|
||||
|
||||
<key alias="allowAllEditors">Alle editors toelaten</key>
|
||||
<key alias="allowAllRowConfigurations">Alle rijconfiguraties toelaten</key>
|
||||
<key alias="setAsDefault">Instellen als standaard</key>
|
||||
<key alias="maxItems">Maximale artikelen</key>
|
||||
<key alias="maxItemsDescription">Laat dit leeg of is ingesteld op -1 voor onbeperkt</key>
|
||||
<key alias="setAsDefault">Instellen als standaard</key>
|
||||
<key alias="chooseExtra">Kies extra</key>
|
||||
<key alias="chooseDefault">Kies standaard</key>
|
||||
<key alias="areAdded">zijn toegevoegd</key>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user