Merge branch 'temp8' into temp8-upgrade-angular

This commit is contained in:
Mads Rasmussen
2018-06-11 14:17:00 +02:00
59 changed files with 839 additions and 295 deletions

View File

@@ -7,6 +7,7 @@ var sort = require('gulp-sort');
var connect = require('gulp-connect');
var open = require('gulp-open');
var runSequence = require('run-sequence');
const imagemin = require('gulp-imagemin');
var _ = require('lodash');
var MergeStream = require('merge-stream');
@@ -206,6 +207,17 @@ gulp.task('dependencies', function () {
//css, fonts and image files
stream.add(
gulp.src(sources.globs.assets)
.pipe(imagemin([
imagemin.gifsicle({interlaced: true}),
imagemin.jpegtran({progressive: true}),
imagemin.optipng({optimizationLevel: 5}),
imagemin.svgo({
plugins: [
{removeViewBox: true},
{cleanupIDs: false}
]
})
]))
.pipe(gulp.dest(root + targets.assets))
);

View File

@@ -27,6 +27,7 @@
"gulp": "^3.9.1",
"gulp-concat": "^2.6.0",
"gulp-connect": "5.0.0",
"gulp-imagemin": "^4.1.0",
"gulp-less": "^3.5.0",
"gulp-ngdocs": "^0.3.0",
"gulp-open": "^2.1.0",

View File

@@ -75,15 +75,12 @@ Use this directive to render an umbraco button. The directive can be used to gen
function link(scope, el, attr, ctrl) {
scope.style = null;
scope.innerState = "init";
function activate() {
scope.blockElement = false;
if (!scope.state) {
scope.state = "init";
}
if (scope.buttonStyle) {
// make it possible to pass in multiple styles
@@ -116,10 +113,13 @@ Use this directive to render an umbraco button. The directive can be used to gen
activate();
var unbindStateWatcher = scope.$watch('state', function(newValue, oldValue) {
if (newValue) {
scope.innerState = newValue;
}
if (newValue === 'success' || newValue === 'error') {
$timeout(function() {
scope.state = 'init';
scope.innerState = 'init';
}, 2000);
}

View File

@@ -1,12 +1,51 @@
/**
* @ngdoc directive
* @name umbraco.directives.directive:umbConfirm
* @function
* @description
* A confirmation dialog
*
* @restrict E
*/
@ngdoc directive
@name umbraco.directives.directive:umbConfirm
@restrict E
@scope
@description
A confirmation dialog
<h3>Markup example</h3>
<pre>
<div ng-controller="My.Controller as vm">
<umb-confirm caption="Title" on-confirm="vm.onConfirm()" on-cancel="vm.onCancel()"></umb-confirm>
</div>
</pre>
<h3>Controller example</h3>
<pre>
(function () {
"use strict";
function Controller() {
var vm = this;
vm.onConfirm = function() {
alert('Confirm clicked');
};
vm.onCancel = function() {
alert('Cancel clicked');
}
}
angular.module("umbraco").controller("My.Controller", Controller);
})();
</pre>
@param {string} caption (<code>attribute</code>): The caption shown above the buttons
@param {callback} on-confirm (<code>attribute</code>): The call back when the "OK" button is clicked. If not set the button will not be shown
@param {callback} on-cancel (<code>atribute</code>): The call back when the "Cancel" button is clicked. If not set the button will not be shown
**/
function confirmDirective() {
return {
restrict: "E", // restrict to an element
@@ -18,7 +57,16 @@ function confirmDirective() {
caption: '@'
},
link: function (scope, element, attr, ctrl) {
scope.showCancel = false;
scope.showConfirm = false;
if (scope.onConfirm) {
scope.showConfirm = true;
}
if (scope.onCancel) {
scope.showCancel = true;
}
}
};
}

View File

@@ -348,9 +348,10 @@
}
};
//select which resource methods to use, eg document Type or Media Type versions
var availableContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getAvailableCompositeContentTypes : mediaTypeResource.getAvailableCompositeContentTypes;
var countContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getCount : mediaTypeResource.getCount;
var whereUsedContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getWhereCompositionIsUsedInContentTypes : mediaTypeResource.getWhereCompositionIsUsedInContentTypes;
var countContentTypeResource = scope.contentType === "documentType" ? contentTypeResource.getCount : mediaTypeResource.getCount;
//get the currently assigned property type aliases - ensure we pass these to the server side filer
var propAliasesExisting = _.filter(_.flatten(_.map(scope.model.groups, function(g) {
@@ -363,7 +364,14 @@
$q.all([
//get available composite types
availableContentTypeResource(scope.model.id, [], propAliasesExisting).then(function (result) {
setupAvailableContentTypesModel(result);
setupAvailableContentTypesModel(result);
}),
//get where used document types
whereUsedContentTypeResource(scope.model.id).then(function (whereUsed) {
//pass to the dialog model the content type eg documentType or mediaType
scope.compositionsDialogModel.section = scope.contentType;
//pass the list of 'where used' document types
scope.compositionsDialogModel.whereCompositionUsed = whereUsed;
}),
//get content type count
countContentTypeResource().then(function(result) {

View File

@@ -38,7 +38,37 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
query),
'Failed to retrieve data for content type id ' + contentTypeId);
},
/**
* @ngdoc method
* @name umbraco.resources.contentTypeResource#getWhereCompositionIsUsedInContentTypes
* @methodOf umbraco.resources.contentTypeResource
*
* @description
* Returns a list of content types which use a specific composition with a given id
*
* ##usage
* <pre>
* contentTypeResource.getWhereCompositionIsUsedInContentTypes(1234)
* .then(function(contentTypeList) {
* console.log(contentTypeList);
* });
* </pre>
* @param {Int} contentTypeId id of the composition content type to retrieve the list of the content types where it has been used
* @returns {Promise} resourcePromise object.
*
*/
getWhereCompositionIsUsedInContentTypes: function (contentTypeId) {
var query = {
contentTypeId: contentTypeId
};
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentTypeApiBaseUrl",
"GetWhereCompositionIsUsedInContentTypes"),
query),
'Failed to retrieve data for content type id ' + contentTypeId);
},
/**
* @ngdoc method

View File

@@ -38,7 +38,38 @@ function mediaTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
query),
'Failed to retrieve data for content type id ' + contentTypeId);
},
/**
* @ngdoc method
* @name umbraco.resources.mediaTypeResource#getWhereCompositionIsUsedInContentTypes
* @methodOf umbraco.resources.mediaTypeResource
*
* @description
* Returns a list of media types which use a specific composition with a given id
*
* ##usage
* <pre>
* mediaTypeResource.getWhereCompositionIsUsedInContentTypes(1234)
* .then(function(mediaTypeList) {
* console.log(mediaTypeList);
* });
* </pre>
* @param {Int} contentTypeId id of the composition content type to retrieve the list of the media types where it has been used
* @returns {Promise} resourcePromise object.
*
*/
getWhereCompositionIsUsedInContentTypes: function (contentTypeId) {
var query = {
contentTypeId: contentTypeId
};
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"mediaTypeApiBaseUrl",
"GetWhereCompositionIsUsedInContentTypes"),
query),
'Failed to retrieve data for content type id ' + contentTypeId);
},
/**
* @ngdoc method
* @name umbraco.resources.mediaTypeResource#getAllowedTypes

View File

@@ -166,7 +166,13 @@ function iconHelper($q, $timeout) {
var c = ".icon-";
for (var i = document.styleSheets.length - 1; i >= 0; i--) {
var classes = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
var classes = null;
try {
classes = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
} catch (e) {
console.warn("Can't read the css rules of: " + document.styleSheets[i].href, e);
continue;
}
if (classes !== null) {
for(var x=0;x<classes.length;x++) {
@@ -224,4 +230,4 @@ function iconHelper($q, $timeout) {
}
};
}
angular.module('umbraco.services').factory('iconHelper', iconHelper);
angular.module('umbraco.services').factory('iconHelper', iconHelper);

View File

@@ -29,9 +29,9 @@ angular.module("umbraco.install").factory('installerService', function($rootScop
"There's a pretty big chance, you've visited a website powered by Umbraco today",
"'Umbraco-spotting' is the game of spotting big brands running Umbraco",
"At least 4 people have the Umbraco logo tattooed on them",
"'Umbraco' is the danish name for an allen key",
"'Umbraco' is the Danish name for an allen key",
"Umbraco has been around since 2005, that's a looong time in IT",
"More than 600 people from all over the world meet each year in Denmark in June for our annual conference <a target='_blank' href='https://umbra.co/codegarden'>CodeGarden</a>",
"More than 600 people from all over the world meet each year in Denmark in May for our annual conference <a target='_blank' href='https://umbra.co/codegarden'>CodeGarden</a>",
"While you are installing Umbraco someone else on the other side of the planet is probably doing it too",
"You can extend Umbraco without modifying the source code using either JavaScript or C#",
"Umbraco has been installed in more than 198 countries"

View File

@@ -183,6 +183,7 @@
@import "hacks.less";
@import "healthcheck.less";
@import "getstarted.less";
// cleanup properties.less when it is done
@import "properties.less";

View File

@@ -14,6 +14,7 @@
padding: 10px 10px 5px 10px;
box-sizing: border-box;
background-color: @white;
position:relative;
}
.umb-group-builder__group.-active {

View File

@@ -0,0 +1,88 @@
.umb-getstarted {
display: flex;
flex-wrap: wrap;
margin-left: -10px;
margin-right: -10px;
}
.umb-getstartedcards {
display: flex;
flex-wrap: wrap;
margin: 0 auto;
max-width: 100%;
@media (min-width: 500px) {
margin: 0 -10px;
}
}
.umb-getstartedcard {
width: 100%;
padding: 0.5em;
text-align: center;
display: flex;
align-items: center;
border: 1px solid #d8d7d9;
background-color: #fff;
margin: 0 0 0.5em;
@media (min-width: 500px) {
display: block;
align-items: unset;
padding: 1em 1em 0 1em;
margin: 0 10px 20px;
width: auto;
flex-basis: 35%;
max-width: 35%;
}
@media (min-width: 768px) {
width: auto;
flex-basis: 14%;
max-width: 14%;
}
@media (min-width: 1930px) {
width: auto;
flex-basis: 7%;
max-width: 7%;
}
}
.umb-getstartedcard img {
height: 3em;
max-width: 100%;
@media (min-width: 500px) {
height: auto;
}
}
.umb-getstartedcards {
margin: 0 auto;
max-width: 100%;
}
.umb-getstartedbody {
font-weight: bold;
margin: 0.5em;
@media (min-width: 500px) {
padding: 10px;
margin: auto;
}
}
.umb-getstartedbody p {
margin: 0;
@media (min-width: 500px) {
margin: inherit;
}
}
.umb-getstartedcard:hover {
border: 1px solid @turquoise;
cursor: pointer;
}

View File

@@ -1,17 +1,23 @@
(function() {
"use strict";
function CompositionsOverlay($scope) {
function CompositionsOverlay($scope,$location) {
var vm = this;
vm.isSelected = isSelected;
vm.openContentType = openContentType;
function isSelected(alias) {
if($scope.model.contentType.compositeContentTypes.indexOf(alias) !== -1) {
return true;
}
}
function openContentType(contentType, section) {
var url = (section === "documentType" ? "/settings/documenttypes/edit/" : "/settings/mediaTypes/edit/") + contentType.id;
$location.path(url);
}
}
angular.module("umbraco").controller("Umbraco.Overlays.CompositionsOverlay", CompositionsOverlay);

View File

@@ -22,11 +22,16 @@
position="center">
<localize key="contentTypeEditor_noAvailableCompositions"></localize>
</umb-empty-state>
<umb-empty-state ng-if="model.availableCompositeContentTypes.length === 0 && model.totalContentTypes > 1"
position="center">
<umb-empty-state ng-if="model.availableCompositeContentTypes.length === 0 && model.totalContentTypes > 1">
<localize key="contentTypeEditor_compositionInUse"></localize>
</umb-empty-state>
<div ng-if="model.availableCompositeContentTypes.length === 0 && model.totalContentTypes > 1 && model.whereCompositionUsed.length > 0">
<h5><localize key="contentTypeEditor_compositionUsageHeading"></localize></h5>
<p><localize key="contentTypeEditor_compositionUsageSpecification"></localize></p>
<ul class="umb-checkbox-list">
<li class="umb-checkbox-list__item" ng-repeat="contentTypeEntity in model.whereCompositionUsed"><a ng-click="vm.openContentType(contentTypeEntity.contentType, model.section)"><i class="{{contentTypeEntity.contentType.icon}}"></i>&nbsp;{{contentTypeEntity.contentType.name}}</a></li>
</ul>
</div>
<ul class="umb-checkbox-list">
<li class="umb-checkbox-list__item"
ng-repeat="compositeContentType in model.availableCompositeContentTypes | filter:searchTerm"
@@ -50,4 +55,4 @@
</li>
</ul>
</div>
</div>

View File

@@ -156,14 +156,15 @@ angular.module("umbraco")
});
});
mediaTypeHelper.getAllowedImagetypes(folder.id)
.then(function(types) {
$scope.acceptedMediatypes = types;
});
} else {
$scope.path = [];
}
mediaTypeHelper.getAllowedImagetypes(folder.id)
.then(function (types) {
$scope.acceptedMediatypes = types;
});
$scope.lockedFolder = folder.id === -1 && $scope.model.startNodeIsVirtual;
$scope.currentFolder = folder;
@@ -387,4 +388,4 @@ angular.module("umbraco")
onInit();
});
});

View File

@@ -27,7 +27,8 @@
<umb-button type="button"
label-key="general_upload"
action="upload()"
disabled="lockedFolder">
disabled="lockedFolder"
ng-if="acceptedMediatypes.length > 0">
</umb-button>
</div>

View File

@@ -1,15 +1,15 @@
<div class="umb-button" ng-class="{'umb-button--block': blockElement}" data-element="{{ alias ? 'button-' + alias : '' }}">
<div class="icon-check umb-button__success" ng-class="{'-hidden': state !== 'success', '-white': style}"></div>
<div class="icon-check umb-button__success" ng-class="{'-hidden': innerState !== 'success', '-white': style}"></div>
<div class="icon-delete umb-button__error" ng-class="{'-hidden': state !== 'error', '-white': style}"></div>
<div class="icon-delete umb-button__error" ng-class="{'-hidden': innerState !== 'error', '-white': style}"></div>
<div class="umb-button__progress" ng-class="{'-hidden': state !== 'busy', '-white': style}"></div>
<div class="umb-button__progress" ng-class="{'-hidden': innerState !== 'busy', '-white': style}"></div>
<div ng-if="state !== 'init'" class="umb-button__overlay"></div>
<div ng-if="innerState !== 'init'" class="umb-button__overlay"></div>
<a ng-if="type === 'link'" href="{{href}}" class="btn umb-button__button {{style}} umb-button--{{size}}" ng-click="clickButton($event)" hotkey="{{shortcut}}" hotkey-when-hidden="{{shortcutWhenHidden}}">
<span class="umb-button__content" ng-class="{'-hidden': state !== 'init'}">
<span class="umb-button__content" ng-class="{'-hidden': innerState !== 'init'}">
<i ng-if="icon" class="{{icon}} umb-button__icon"></i>
<localize ng-if="labelKey" key="{{labelKey}}">{{label}}</localize>
<span ng-if="!labelKey">{{label}}</span>
@@ -17,7 +17,7 @@
</a>
<button ng-if="type === 'button'" type="button" class="btn umb-button__button {{style}} umb-button--{{size}}" ng-click="clickButton($event)" hotkey="{{shortcut}}" hotkey-when-hidden="{{shortcutWhenHidden}}" ng-disabled="disabled">
<span class="umb-button__content" ng-class="{'-hidden': state !== 'init'}">
<span class="umb-button__content" ng-class="{'-hidden': innerState !== 'init'}">
<i ng-if="icon" class="{{icon}} umb-button__icon"></i>
<localize ng-if="labelKey" key="{{labelKey}}">{{label}}</localize>
<span ng-if="!labelKey">{{label}}</span>
@@ -25,7 +25,7 @@
</button>
<button ng-if="type === 'submit'" type="submit" class="btn umb-button__button {{style}} umb-button--{{size}}" hotkey="{{shortcut}}" hotkey-when-hidden="{{shortcutWhenHidden}}" ng-disabled="disabled">
<span class="umb-button__content" ng-class="{'-hidden': state !== 'init'}">
<span class="umb-button__content" ng-class="{'-hidden': innerState !== 'init'}">
<i ng-if="icon" class="{{icon}} umb-button__icon"></i>
<localize ng-if="labelKey" key="{{labelKey}}">{{label}}</localize>
<span ng-if="!labelKey">{{label}}</span>

View File

@@ -3,8 +3,8 @@
<div class="umb-pane btn-toolbar umb-btn-toolbar">
<div class="control-group umb-control-group">
<a href class="btn btn-link" ng-click="onCancel()"><localize key="general_cancel">Cancel</localize></a>
<a href class="btn btn-primary" ng-click="onConfirm()"><localize key="general_ok">Ok</localize></a>
<a ng-if="showCancel" href class="btn btn-link" ng-click="onCancel()"><localize key="general_cancel">Cancel</localize></a>
<a ng-if="showConfirm" href class="btn btn-primary" ng-click="onConfirm()"><localize key="general_ok">Ok</localize></a>
</div>
</div>
</div>
</div>

View File

@@ -1,14 +1,15 @@
<h3 class="bold">Hours of Umbraco training videos are only a click away</h3>
<p style="margin-bottom: 20px;">Want to master Umbraco? Spend a couple of minutes learning some best practices by watching one of these videos about using Umbraco, then visit <a class="btn-link -underline" href="http://umbraco.tv" target="_blank">umbraco.tv</a> for even more Umbraco videos.</p>
<div
ng-init="init('http://umbraco.tv/videos/developer/chapterrss?sort=no')"
<div ng-init="init('http://umbraco.tv/videos/developer/chapterrss?sort=no')"
ng-controller="Umbraco.Dashboard.StartupVideosController">
<div class="umb-training-videos">
<a class="umb-training-video" ng-repeat="video in videos" target="_blank" href="{{video.link}}" title="{{video.title}}">
<div class="umb-getstartedcards">
<a class="umb-getstartedcard" ng-repeat="video in videos" href="{{video.link}}" title="{{video.title}}" target="_blank" rel="noopener">
<img ng-src="{{video.thumbnail}}" alt="{{video.title}}">
<span class="umb-training-video__label">{{video.title}}</span>
<div class="umb-getstartedbody">
<p>{{video.title}}</p>
</div>
</a>
</div>

View File

@@ -1,7 +1,30 @@
angular.module("umbraco").controller("Umbraco.PrevalueEditors.BooleanController",
function ($scope) {
if ($scope.model.value === 1 || $scope.model.value === "1" || $scope.model.value === true) {
$scope.model.value = "1";
function updateToggleValue() {
$scope.toggleValue = false;
if ($scope.model && $scope.model.value && ($scope.model.value.toString() === "1" || angular.lowercase($scope.model.value) === "true")) {
$scope.toggleValue = true;
}
}
if($scope.model.value === null){
$scope.model.value = "0";
}
updateToggleValue();
$scope.toggle = function(){
if($scope.model.value === 1 || $scope.model.value === "1"){
$scope.model.value = "0";
updateToggleValue();
return;
}
$scope.model.value = "1";
updateToggleValue();
}
$scope.htmlId = "bool-" + String.CreateGuid();
});

View File

@@ -1,4 +1,6 @@
<label ng-controller="Umbraco.PrevalueEditors.BooleanController" for="{{htmlId}}" class="checkbox">
<input name="boolean" type="checkbox" ng-model="model.value" ng-true-value="1" ng-false-value="0" id="{{htmlId}}" />
<localize key="general_yes">Yes</localize>
</label>
<div ng-controller="Umbraco.PrevalueEditors.BooleanController">
<umb-toggle
checked="toggleValue"
on-click="toggle()">
</umb-toggle>
</div>

View File

@@ -4,7 +4,7 @@ function booleanEditorController($scope, $rootScope, assetsService) {
$scope.renderModel = {
value: false
};
if ($scope.model.config && $scope.model.config.default && $scope.model.config.default.toString() === "1" && $scope.model && !$scope.model.value) {
$scope.renderModel.value = true;
}
@@ -16,10 +16,6 @@ function booleanEditorController($scope, $rootScope, assetsService) {
setupViewModel();
$scope.$watch("renderModel.value", function (newVal) {
$scope.model.value = newVal === true ? "1" : "0";
});
//here we declare a special method which will be called whenever the value has changed from the server
//this is instead of doing a watch on the model.value = faster
$scope.model.onValueChanged = function (newVal, oldVal) {
@@ -27,5 +23,17 @@ function booleanEditorController($scope, $rootScope, assetsService) {
setupViewModel();
};
// Update the value when the toggle is clicked
$scope.toggle = function(){
if($scope.renderModel.value){
$scope.model.value = "0";
setupViewModel();
return;
}
$scope.model.value = "1";
setupViewModel();
};
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.BooleanController", booleanEditorController);

View File

@@ -1,3 +1,6 @@
<div class="umb-property-editor umb-boolean" ng-controller="Umbraco.PropertyEditors.BooleanController">
<input type="checkbox" ng-model="renderModel.value" id="{{model.alias}}" />
<umb-toggle
checked="renderModel.value"
on-click="toggle()">
</umb-toggle>
</div>

View File

@@ -1,6 +1,21 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.GridController",
function ($scope, $http, assetsService, localizationService, $rootScope, dialogService, gridService, mediaResource, imageHelper, $timeout, umbRequestHelper, angularHelper) {
function (
$scope,
$http,
assetsService,
localizationService,
$rootScope,
dialogService,
gridService,
mediaResource,
imageHelper,
$timeout,
umbRequestHelper,
angularHelper,
$element,
eventsService
) {
// Grid status variables
var placeHolder = "";
@@ -335,6 +350,8 @@ angular.module("umbraco")
$scope.showRowConfigurations = false;
eventsService.emit("grid.rowAdded", { scope: $scope, element: $element, row: row });
};
$scope.removeRow = function (section, $index) {
@@ -584,6 +601,8 @@ angular.module("umbraco")
cell.controls.push(newControl);
eventsService.emit("grid.itemAdded", { scope: $scope, element: $element, cell: cell, item: newControl });
};
$scope.addTinyMce = function (cell) {
@@ -873,8 +892,13 @@ angular.module("umbraco")
// *********************************************
// Init grid
// *********************************************
eventsService.emit("grid.initializing", { scope: $scope, element: $element });
$scope.initContent();
eventsService.emit("grid.initialized", { scope: $scope, element: $element });
});
//Clean the grid value before submitting to the server, we don't need

View File

@@ -75,7 +75,8 @@
'-active': row.active,
'-active-child': row.hasActiveChild}"
on-outside-click="clickOutsideRow($index, section.rows)"
bind-click-on="{{row.active}}">
bind-click-on="{{row.active}}"
data-rowid="{{row.$uniqueId}}">
<div class="umb-row-title-bar">
@@ -175,7 +176,8 @@
ng-class="{'-active': control.active}"
on-outside-click="clickOutsideControl($index, area.controls, area)"
bind-click-on="{{control.active}}"
umb-set-dirty-on-change="{{control.value}}">
umb-set-dirty-on-change="{{control.value}}"
data-itemid="{{control.$uniqueId}}">
<div class="umb-control-click-overlay" ng-show="!control.active && !sortMode"></div>