From ab8fc33691a5693d0119e99008138484453698ee Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 14 Aug 2017 18:21:48 +0200 Subject: [PATCH] Port 7.7 - WIP --- .editorconfig | 10 + build/NuSpecs/tools/Web.config.install.xdt | 10 +- build/NuSpecs/tools/trees.config.install.xdt | 15 +- src/Umbraco.Core/Cache/CacheKeys.cs | 8 +- .../ActionMetadataAttribute.cs | 35 + .../Configuration/GlobalSettings.cs | 22 +- .../DisabledHealthCheckElement.cs | 42 + .../DisabledHealthChecksElementCollection.cs | 40 + .../HealthCheckNotificationSettingsElement.cs | 85 ++ .../HealthCheckNotificationVerbosity.cs | 8 + .../HealthChecks/HealthChecksSection.cs | 34 + .../HealthChecks/IDisabledHealthCheck.cs | 11 + .../IHealthCheckNotificationSettings.cs | 13 + .../HealthChecks/IHealthChecks.cs | 10 + .../HealthChecks/INotificationMethod.cs | 13 + .../INotificationMethodSettings.cs | 8 + .../HealthChecks/NotificationMethodElement.cs | 85 ++ .../NotificationMethodSettingsElement.cs | 28 + ...ficationMethodSettingsElementCollection.cs | 80 ++ .../NotificationMethodsElementCollection.cs | 80 ++ .../Configuration/UmbracoConfig.cs | 38 +- .../UmbracoSettings/ContentElement.cs | 4 +- .../Configuration/UmbracoSettings/ILink.cs | 7 +- .../UmbracoSettings/IRequestHandlerSection.cs | 2 + .../IUmbracoSettingsSection.cs | 5 +- .../UmbracoSettings/RequestHandlerElement.cs | 7 +- .../UmbracoSettings/UmbracoSettingsSection.cs | 1 + .../UmbracoSettings/UrlReplacingElement.cs | 6 +- .../Events/ImportPackageEventArgs.cs | 2 +- .../Events/UninstallPackageEventArgs.cs | 2 +- src/Umbraco.Core/IO/IOHelper.cs | 2 + src/Umbraco.Core/Models/EntityBase/Entity.cs | 6 +- .../Models/EntityBase/EntityPath.cs | 8 + .../Models/Identity/BackOfficeIdentityUser.cs | 367 +++++- .../Models/Identity/IdentityProfile.cs | 30 +- .../Models/Membership/ContentPermissionSet.cs | 54 + .../Models/Membership/EntityPermission.cs | 52 +- .../Membership/EntityPermissionCollection.cs | 34 + .../Models/Membership/EntityPermissionSet.cs | 70 +- .../Models/Membership/IProfile.cs | 10 +- .../Models/Membership/IReadOnlyUserGroup.cs | 31 + src/Umbraco.Core/Models/Membership/IUser.cs | 42 +- .../Models/Membership/IUserGroup.cs | 44 + .../Models/Membership/IUserType.cs | 23 +- .../Models/Membership/ReadOnlyUserGroup.cs | 70 + src/Umbraco.Core/Models/Membership/User.cs | 479 +++++-- .../Models/Membership/UserGroupExtensions.cs | 26 + .../Models/Membership/UserProfile.cs | 46 + .../Models/Membership/UserState.cs | 14 + .../Models/Membership/UserType.cs | 10 +- .../Syntax/Alter/IAlterSyntaxBuilder.cs | 2 +- .../MicrosoftSqlSyntaxProviderBase.cs | 32 +- .../MultipleTextStringValueConverter.cs | 4 +- src/Umbraco.Core/Umbraco.Core.csproj | 15 + .../AzureLocalStorageDirectory.cs | 2 +- .../UmbracoSettings/ContentElementTests.cs | 2 +- .../UmbracoSettings/UmbracoSettingsTests.cs | 2 +- src/Umbraco.Web.UI.Client/bower.json | 5 +- src/Umbraco.Web.UI.Client/gruntFile.js | 9 +- .../lib/tinymce/langs/da.js | 219 ++++ .../lib/tinymce/langs/de.js | 219 ++++ .../lib/tinymce/langs/en.js | 1 + .../lib/tinymce/langs/en_us.js | 1 + .../lib/tinymce/langs/fi.js | 219 ++++ .../lib/tinymce/langs/fr.js | 1 + .../lib/tinymce/langs/he.js | 1 + .../lib/tinymce/langs/it.js | 219 ++++ .../lib/tinymce/langs/ja.js | 219 ++++ .../lib/tinymce/langs/nl.js | 219 ++++ .../lib/tinymce/langs/no.js | 1 + .../lib/tinymce/langs/pl.js | 219 ++++ .../lib/tinymce/langs/pt.js | 1 + .../lib/tinymce/langs/ru.js | 219 ++++ .../lib/tinymce/langs/sv.js | 1 + .../lib/tinymce/langs/zh.js | 1 + .../tinymce/plugins/codemirror/langs/da.js | 8 + .../tinymce/plugins/codemirror/langs/de.js | 8 + .../tinymce/plugins/codemirror/langs/en_us.js | 8 + .../tinymce/plugins/codemirror/langs/fi.js | 8 + .../tinymce/plugins/codemirror/langs/fr.js | 8 + .../tinymce/plugins/codemirror/langs/he.js | 8 + .../tinymce/plugins/codemirror/langs/it.js | 8 + .../tinymce/plugins/codemirror/langs/ja.js | 8 + .../tinymce/plugins/codemirror/langs/nl.js | 8 + .../tinymce/plugins/codemirror/langs/no.js | 8 + .../tinymce/plugins/codemirror/langs/pl.js | 8 + .../tinymce/plugins/codemirror/langs/pt.js | 8 + .../tinymce/plugins/codemirror/langs/ru.js | 8 + .../tinymce/plugins/codemirror/langs/sv.js | 8 + .../tinymce/plugins/codemirror/langs/zh.js | 8 + .../umbracocontextmenu/editor_plugin_src.js | 69 - .../plugins/umbracocontextmenu/plugin.min.js | 69 - .../plugins/umbracocss/img/example.gif | Bin 87 -> 0 bytes .../tinymce/plugins/umbracocss/js/dialog.js | 19 - .../tinymce/plugins/umbracocss/langs/en.js | 3 - .../plugins/umbracocss/langs/en_dlg.js | 3 - .../tinymce/plugins/umbracocss/langs/en_us.js | 3 - .../plugins/umbracocss/langs/en_us_dlg.js | 3 - .../tinymce/plugins/umbracocss/langs/it.js | 3 - .../plugins/umbracocss/langs/it_dlg.js | 3 - .../tinymce/plugins/umbracocss/langs/ja.js | 3 - .../plugins/umbracocss/langs/ja_dlg.js | 3 - .../tinymce/plugins/umbracocss/langs/ru.js | 3 - .../plugins/umbracocss/langs/ru_dlg.js | 3 - .../tinymce/plugins/umbracocss/langs/sv.js | 3 - .../plugins/umbracocss/langs/sv_dlg.js | 3 - .../tinymce/plugins/umbracocss/langs/zh.js | 3 - .../plugins/umbracocss/langs/zh_dlg.js | 3 - .../tinymce/plugins/umbracocss/plugin.min.js | 182 --- .../tinymce/plugins/umbracoembed/dialog.htm | 92 -- .../plugins/umbracoembed/editor_plugin.js | 1 - .../plugins/umbracoembed/editor_plugin_src.js | 84 -- .../plugins/umbracoembed/img/ajax-loader.gif | Bin 1928 -> 0 bytes .../plugins/umbracoembed/img/embed.gif | Bin 260 -> 0 bytes .../plugins/umbracoembed/img/embed.png | Bin 537 -> 0 bytes .../tinymce/plugins/umbracoembed/js/dialog.js | 90 -- .../tinymce/plugins/umbracoembed/langs/da.js | 3 - .../plugins/umbracoembed/langs/da_dlg.js | 9 - .../tinymce/plugins/umbracoembed/langs/de.js | 10 - .../plugins/umbracoembed/langs/de_dlg.js | 10 - .../tinymce/plugins/umbracoembed/langs/en.js | 3 - .../plugins/umbracoembed/langs/en_dlg.js | 10 - .../plugins/umbracoembed/langs/en_us.js | 3 - .../plugins/umbracoembed/langs/en_us_dlg.js | 10 - .../tinymce/plugins/umbracoembed/langs/it.js | 9 - .../plugins/umbracoembed/langs/it_dlg.js | 9 - .../tinymce/plugins/umbracoembed/langs/ja.js | 10 - .../plugins/umbracoembed/langs/ja_dlg.js | 10 - .../tinymce/plugins/umbracoembed/langs/ru.js | 10 - .../plugins/umbracoembed/langs/ru_dlg.js | 10 - .../tinymce/plugins/umbracoembed/langs/sv.js | 10 - .../plugins/umbracoembed/langs/sv_dlg.js | 10 - .../tinymce/plugins/umbracoembed/langs/zh.js | 10 - .../plugins/umbracoembed/langs/zh_dlg.js | 9 - .../plugins/umbracoimg/editor_plugin_src.js | 52 - .../tinymce/plugins/umbracoimg/js/image.js | 332 ----- .../plugins/umbracoimg/langs/en_dlg.js | 43 - .../plugins/umbracoimg/langs/en_us_dlg.js | 43 - .../plugins/umbracoimg/langs/he_dlg.js | 43 - .../plugins/umbracoimg/langs/it_dlg.js | 43 - .../plugins/umbracoimg/langs/ja_dlg.js | 43 - .../plugins/umbracoimg/langs/ru_dlg.js | 43 - .../plugins/umbracoimg/langs/sv_dlg.js | 43 - .../plugins/umbracoimg/langs/zh_dlg.js | 43 - .../tinymce/plugins/umbracolink/plugin.min.js | 285 ---- .../tinymce/plugins/umbracomacro/dialog.htm | 27 - .../plugins/umbracomacro/editor_plugin_src.js | 145 -- .../plugins/umbracomacro/img/insMacro.gif | Bin 603 -> 0 bytes .../tinymce/plugins/umbracomacro/js/dialog.js | 19 - .../tinymce/plugins/umbracomacro/langs/en.js | 3 - .../plugins/umbracomacro/langs/en_dlg.js | 3 - .../plugins/umbracomacro/langs/en_us.js | 3 - .../plugins/umbracomacro/langs/en_us_dlg.js | 3 - .../tinymce/plugins/umbracomacro/langs/he.js | 3 - .../plugins/umbracomacro/langs/he_dlg.js | 3 - .../tinymce/plugins/umbracomacro/langs/ja.js | 3 - .../plugins/umbracomacro/langs/ja_dlg.js | 3 - .../tinymce/plugins/umbracomacro/langs/ru.js | 3 - .../plugins/umbracomacro/langs/ru_dlg.js | 3 - .../tinymce/plugins/umbracomacro/langs/sv.js | 3 - .../plugins/umbracomacro/langs/sv_dlg.js | 3 - .../tinymce/plugins/umbracomacro/langs/zh.js | 3 - .../plugins/umbracomacro/langs/zh_dlg.js | 3 - .../plugins/umbracopaste/editor_plugin_src.js | 53 - .../umbracoshortcut/editor_plugin_src.js | 43 - src/Umbraco.Web.UI.Client/src/app.js | 2 +- .../src/assets/img/installer.jpg | Bin 279297 -> 317197 bytes .../components/buttons/umbbutton.directive.js | 35 +- .../components/buttons/umbtoggle.directive.js | 135 ++ .../components/content/edit.controller.js | 252 ++++ .../editor/umbeditorheader.directive.js | 8 +- .../components/events/events.directive.js | 1 - .../components/grid/grid.rte.directive.js | 2 +- .../html/umbcontrolgroup.directive.js | 78 +- .../components/tree/umbtree.directive.js | 51 +- .../components/umbavatar.directive.js | 39 +- .../components/umbbadge.directive.js | 23 + .../components/umbcheckmark.directive.js | 23 + .../components/umbclipboard.directive.js | 166 +++ .../components/umbdropdown.directive.js | 133 ++ .../components/umbdropdownitem.directive.js | 29 + .../components/umbmediagrid.directive.js | 45 +- .../components/umbnestedcontent.directive.js | 97 ++ .../components/umbnodepreview.directive.js | 11 +- .../components/umbpagination.directive.js | 6 +- .../components/umbprogressbar.directive.js | 5 +- .../upload/umbfiledropzone.directive.js | 15 +- .../users/changepassword.directive.js | 171 +++ .../users/umbpermission.directive.js | 36 + .../users/umbusergrouppreview.directive.js | 36 + .../users/umbuserpreview.directive.js | 29 + .../util/umbkeyboardlist.directive.js | 115 ++ .../validation/valcompare.directive.js | 12 +- .../validation/valsubview.directive.js | 7 +- .../common/filters/nestedcontent.filter.js | 47 + .../filters/preserveNewLineInHtml.filter.js | 15 + .../src/common/filters/umbwordlimit.filter.js | 38 + .../src/common/resources/auth.resource.js | 782 +++++------ .../src/common/resources/content.resource.js | 97 +- .../common/resources/currentuser.resource.js | 81 +- .../src/common/resources/log.resource.js | 8 +- .../resources/nestedcontent.resource.js | 12 + .../src/common/resources/package.resource.js | 10 + .../src/common/resources/section.resource.js | 12 +- .../src/common/resources/user.resource.js | 25 - .../common/resources/usergroups.resource.js | 87 ++ .../src/common/resources/users.resource.js | 203 +++ .../common/security/securityinterceptor.js | 24 +- .../src/common/services/assets.service.js | 2 +- .../services/contenteditinghelper.service.js | 3 +- .../src/common/services/events.service.js | 5 +- .../src/common/services/formhelper.service.js | 21 +- .../common/services/listviewhelper.service.js | 4 +- .../common/services/mediahelper.service.js | 22 + .../services/mediatypehelper.service.js | 4 + .../src/common/services/search.service.js | 256 ++-- .../services/searchresultformatter.service.js | 37 + .../services/umbdataformatter.service.js | 326 +++++ .../services/umbrequesthelper.service.js | 12 +- .../src/common/services/user.service.js | 511 ++++---- .../common/services/usershelper.service.js | 67 + .../src/common/services/util.service.js | 1164 +++++++---------- .../src/controllers/main.controller.js | 63 +- .../src/controllers/search.controller.js | 78 +- src/Umbraco.Web.UI.Client/src/init.js | 9 +- .../src/install.loader.js | 34 +- .../src/installer.app.js | 7 + .../src/installer/_module.js | 1 + .../src/installer/installer.service.js | 8 +- .../installer/steps/database.controller.js | 33 +- .../installer/steps/machinekey.controller.js | 14 + .../src/installer/steps/machinekey.html | 23 + src/Umbraco.Web.UI.Client/src/less/belle.less | 17 + .../less/components/buttons/umb-button.less | 50 +- .../less/components/buttons/umb-toggle.less | 65 + .../src/less/components/umb-avatar.less | 96 +- .../src/less/components/umb-badge.less | 65 + .../src/less/components/umb-box.less | 20 + .../src/less/components/umb-breadcrumbs.less | 2 +- .../src/less/components/umb-checkmark.less | 46 + .../src/less/components/umb-list.less | 25 + .../less/components/umb-nested-content.less | 208 +++ .../src/less/components/umb-node-preview.less | 18 +- .../src/less/components/umb-packages.less | 5 +- .../src/less/components/umb-progress-bar.less | 10 + .../less/components/users/umb-permission.less | 26 + .../less/components/users/umb-user-cards.less | 126 ++ .../users/umb-user-group-picker-list.less | 38 + .../users/umb-user-group-preview.less | 64 + .../users/umb-user-picker-list.less | 42 + .../components/users/umb-user-preview.less | 50 + src/Umbraco.Web.UI.Client/src/less/forms.less | 50 +- src/Umbraco.Web.UI.Client/src/less/main.less | 34 +- src/Umbraco.Web.UI.Client/src/less/panel.less | 6 +- .../src/less/sections.less | 16 +- .../src/less/tables.less | 8 +- src/Umbraco.Web.UI.Client/src/less/tree.less | 51 +- .../src/less/utilities/layout/_display.less | 41 + .../typography/_text-decoration.less | 9 + .../utilities/typography/_white-space.less | 15 + .../src/less/variables.less | 4 +- .../views/common/dialogs/help.controller.js | 1 - .../src/views/common/dialogs/iconpicker.html | 15 +- .../views/common/dialogs/legacydelete.html | 2 +- .../common/dialogs/linkpicker.controller.js | 18 +- .../src/views/common/dialogs/linkpicker.html | 6 +- .../views/common/dialogs/login.controller.js | 614 +++++---- .../src/views/common/dialogs/login.html | 374 ++++-- .../src/views/common/dialogs/mediapicker.html | 3 +- .../src/views/common/dialogs/rteembed.html | 10 +- .../common/dialogs/template/querybuilder.html | 6 +- .../common/dialogs/template/snippet.html | 2 +- .../views/common/dialogs/user.controller.js | 2 +- .../src/views/common/dialogs/user.html | 8 +- .../propertysettings/propertysettings.html | 5 +- .../views/common/overlays/embed/embed.html | 10 +- .../common/overlays/help/help.controller.js | 1 - .../overlays/iconpicker/iconpicker.html | 12 +- .../insertfield/insertfield.controller.js | 2 - .../overlays/insertfield/insertfield.html | 72 +- .../linkpicker/linkpicker.controller.js | 31 +- .../mediaPicker/mediapicker.controller.js | 161 +-- .../overlays/mediaPicker/mediapicker.html | 9 +- .../nodepermissions.controller.js | 25 + .../nodepermissions/nodepermissions.html | 12 + .../sectionpicker/sectionpicker.controller.js | 87 ++ .../overlays/sectionpicker/sectionpicker.html | 24 + .../treepicker/treepicker.controller.js | 29 +- .../common/overlays/user/user.controller.js | 6 +- .../src/views/common/overlays/user/user.html | 6 +- .../usergrouppicker.controller.js | 82 ++ .../usergrouppicker/usergrouppicker.html | 66 + .../userpicker/userpicker.controller.js | 109 ++ .../overlays/userpicker/userpicker.html | 58 + .../application/umb-navigation.html | 186 +-- .../components/application/umb-sections.html | 2 + .../views/components/buttons/umb-button.html | 14 +- .../views/components/buttons/umb-toggle.html | 19 + .../src/views/components/content/edit.html | 86 ++ .../components/editor/umb-editor-header.html | 37 +- .../components/html/umb-control-group.html | 8 +- .../components/property/umb-property.html | 2 +- .../src/views/components/umb-avatar.html | 8 +- .../src/views/components/umb-badge.html | 1 + .../src/views/components/umb-checkmark.html | 1 + .../views/components/umb-dropdown-item.html | 1 + .../src/views/components/umb-dropdown.html | 1 + .../src/views/components/umb-media-grid.html | 2 +- .../views/components/umb-mini-list-view.html | 4 +- .../views/components/umb-node-preview.html | 17 +- .../views/components/umb-progress-bar.html | 2 +- .../components/users/change-password.html | 68 + .../components/users/umb-permission.html | 11 + .../users/umb-user-group-preview.html | 46 + .../components/users/umb-user-preview.html | 21 + .../content/content.create.controller.js | 66 +- .../content.createblueprint.controller.js | 56 + .../views/content/content.edit.controller.js | 232 +--- .../content/content.rights.controller.js | 152 +++ .../src/views/content/create.html | 84 +- .../src/views/content/createblueprint.html | 44 + .../src/views/content/edit.html | 93 +- .../src/views/content/rights.html | 117 ++ .../contentblueprints/delete.controller.js | 32 + .../src/views/contentblueprints/delete.html | 12 + .../contentblueprints/edit.controller.js | 34 + .../src/views/contentblueprints/edit.html | 9 + .../src/views/contentblueprints/intro.html | 32 + .../dashboard/dashboard.tabs.controller.js | 8 +- .../developer/developerdashboardintro.html | 2 +- .../settings/settingsdashboardintro.html | 2 +- .../src/views/datatypes/delete.html | 6 +- .../src/views/datatypes/edit.html | 2 +- .../src/views/datatypes/move.html | 4 +- .../src/views/documenttypes/edit.html | 1 + .../src/views/media/move.html | 4 +- .../src/views/mediatypes/edit.html | 1 + .../src/views/member/create.html | 2 +- .../views/install-local.controller.js | 34 +- .../views/packager/views/install-local.html | 30 +- .../src/views/packager/views/installed.html | 22 +- .../views/packager/views/repo.controller.js | 32 +- .../src/views/packager/views/repo.html | 58 +- .../partialviewmacros/create.controller.js | 6 +- .../src/views/partialviewmacros/create.html | 2 +- .../partialviewmacros/edit.controller.js | 7 +- .../src/views/partialviewmacros/edit.html | 12 +- .../views/partialviews/create.controller.js | 7 +- .../src/views/partialviews/edit.html | 10 +- .../src/views/prevalueeditors/textstring.html | 2 +- .../src/views/prevalueeditors/treepicker.html | 2 +- .../changepassword.controller.js | 195 +-- .../changepassword/changepassword.html | 66 +- .../colorpicker/colorpicker.prevalues.html | 6 +- .../contentpicker/contentpicker.controller.js | 7 +- .../contentpicker/contentpicker.html | 5 +- .../datepicker/datepicker.html | 4 +- .../propertyeditors/decimal/decimal.html | 6 +- .../views/propertyeditors/email/email.html | 8 +- .../grid/editors/media.controller.js | 4 +- .../grid/editors/rte.controller.js | 2 +- .../propertyeditors/grid/grid.prevalues.html | 31 +- .../imagecropper/imagecropper.prevalues.html | 18 +- .../propertyeditors/integer/integer.html | 6 +- .../listview/listview.controller.js | 3 +- .../mediapicker/mediapicker.controller.js | 8 +- .../membergroups/membergroups.html | 8 +- .../multipletextbox/multipletextbox.html | 8 +- .../nestedcontent/nestedcontent.controller.js | 447 +++++++ .../nestedcontent.doctypepicker.html | 62 + .../nestedcontent/nestedcontent.editor.html | 13 + .../nestedcontent/nestedcontent.html | 62 + .../propertyeditors/rte/rte.controller.js | 54 +- .../src/views/propertyeditors/rte/rte.html | 4 +- .../slider/slider.controller.js | 2 +- .../textarea/textarea.controller.js | 26 + .../propertyeditors/textarea/textarea.html | 12 +- .../textbox/textbox.controller.js | 26 + .../propertyeditors/textbox/textbox.html | 13 +- .../src/views/scripts/create.controller.js | 11 +- .../src/views/templates/edit.html | 1 + .../src/views/users/group.controller.js | 327 +++++ .../src/views/users/group.html | 257 ++++ .../src/views/users/overview.controller.js | 49 + .../src/views/users/overview.html | 24 + .../src/views/users/user.controller.js | 353 +++++ .../src/views/users/user.html | 366 ++++++ .../users/views/groups/groups.controller.js | 102 ++ .../src/views/users/views/groups/groups.html | 86 ++ .../users/views/users/users.controller.js | 614 +++++++++ .../src/views/users/views/users/users.html | 519 ++++++++ .../test/config/karma.conf.js | 2 +- .../content/create-content-controller.spec.js | 124 ++ .../content/edit-content-controller.spec.js | 37 +- .../umbraco/images/actions/sprites.png | Bin 12301 -> 0 bytes .../umbraco_client/Application/Extensions.js | 31 +- .../Application/UmbracoApplicationActions.js | 62 +- .../umbraco_client/Editors/EditScript.js | 116 -- .../umbraco_client/Editors/EditXslt.js | 2 +- .../scrollingmenu/images/arrawBack.gif | Bin 834 -> 0 bytes .../scrollingmenu/images/arrowForward.gif | Bin 834 -> 0 bytes .../scrollingmenu/images/background.gif | Bin 183 -> 0 bytes .../scrollingmenu/images/button/buttonbg.gif | Bin 273 -> 0 bytes .../images/button/buttonbgdown.gif | Bin 273 -> 0 bytes .../Editors/AuthenticationController.cs | 2 +- src/Umbraco.Web/Editors/MediaController.cs | 2 +- .../ContentTypeCompositionDisplay.cs | 10 +- .../Models/ContentEditing/DataTypeBasic.cs | 4 +- .../Providers/UsersMembershipProvider.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 4 + src/Umbraco.Web/_Legacy/Actions/Action.cs | 3 +- .../_Legacy/Actions/ActionAssignDomain.cs | 102 +- .../_Legacy/Actions/ActionAudit.cs | 3 + .../_Legacy/Actions/ActionBrowse.cs | 6 +- .../_Legacy/Actions/ActionChangeDocType.cs | 3 + .../_Legacy/Actions/ActionCollection.cs | 19 + .../Actions/ActionCollectionBuilder.cs | 75 ++ src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs | 3 + .../ActionCreateBlueprintFromContent.cs | 32 + .../_Legacy/Actions/ActionDelete.cs | 3 + src/Umbraco.Web/_Legacy/Actions/ActionMove.cs | 3 + src/Umbraco.Web/_Legacy/Actions/ActionNew.cs | 3 + .../_Legacy/Actions/ActionProtect.cs | 3 + .../_Legacy/Actions/ActionPublish.cs | 3 + .../_Legacy/Actions/ActionRights.cs | 3 + .../_Legacy/Actions/ActionRollback.cs | 3 + .../_Legacy/Actions/ActionSendToTranslate.cs | 3 + src/Umbraco.Web/_Legacy/Actions/ActionSort.cs | 3 + .../_Legacy/Actions/ActionToPublish.cs | 3 + .../_Legacy/Actions/ActionTranslate.cs | 3 + .../_Legacy/Actions/ActionUpdate.cs | 3 + src/Umbraco.Web/_Legacy/Actions/IAction.cs | 18 + .../umbraco/templateControls/Image.cs | 4 +- src/umbraco.presentation.targets | 4 + src/umbraco.sln | 5 - 435 files changed, 15298 insertions(+), 5993 deletions(-) create mode 100644 .editorconfig create mode 100644 src/Umbraco.Core/CodeAnnotations/ActionMetadataAttribute.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthCheckElement.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthChecksElementCollection.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationSettingsElement.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/HealthChecksSection.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/IDisabledHealthCheck.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/IHealthCheckNotificationSettings.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/INotificationMethod.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/INotificationMethodSettings.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodElement.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElement.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElementCollection.cs create mode 100644 src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodsElementCollection.cs create mode 100644 src/Umbraco.Core/Models/EntityBase/EntityPath.cs create mode 100644 src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs create mode 100644 src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs create mode 100644 src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs create mode 100644 src/Umbraco.Core/Models/Membership/IUserGroup.cs create mode 100644 src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs create mode 100644 src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs create mode 100644 src/Umbraco.Core/Models/Membership/UserProfile.cs create mode 100644 src/Umbraco.Core/Models/Membership/UserState.cs create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/da.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/de.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/en.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/en_us.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/fi.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/fr.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/he.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/it.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/ja.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/nl.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/no.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/pl.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/pt.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/ru.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/sv.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/langs/zh.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/da.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/de.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/en_us.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/fi.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/fr.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/he.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/it.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/ja.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/nl.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/no.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/pl.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/pt.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/ru.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/sv.js create mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/zh.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocontextmenu/editor_plugin_src.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocontextmenu/plugin.min.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/img/example.gif delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/js/dialog.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/en.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/en_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/en_us.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/en_us_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/it.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/it_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/ja.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/ja_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/ru.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/ru_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/sv.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/sv_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/zh.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/langs/zh_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/plugin.min.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/dialog.htm delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/editor_plugin.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/editor_plugin_src.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/img/ajax-loader.gif delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/img/embed.gif delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/img/embed.png delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/js/dialog.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/da.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/da_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/de.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/de_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_us.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_us_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/it.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/it_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ja.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ja_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ru.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ru_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/sv.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/sv_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/zh.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/zh_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/editor_plugin_src.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/js/image.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/en_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/en_us_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/he_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/it_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/ja_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/ru_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/sv_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/zh_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracolink/plugin.min.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/dialog.htm delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/editor_plugin_src.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/img/insMacro.gif delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/js/dialog.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_us.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_us_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/he.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/he_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ja.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ja_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ru.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ru_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/sv.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/sv_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/zh.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/zh_dlg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracopaste/editor_plugin_src.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoshortcut/editor_plugin_src.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbbadge.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbcheckmark.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbclipboard.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbdropdown.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbdropdownitem.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/umbnestedcontent.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbpermission.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbusergrouppreview.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbuserpreview.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/directives/util/umbkeyboardlist.directive.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/filters/nestedcontent.filter.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/filters/preserveNewLineInHtml.filter.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/filters/umbwordlimit.filter.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/resources/nestedcontent.resource.js delete mode 100644 src/Umbraco.Web.UI.Client/src/common/resources/user.resource.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/resources/usergroups.resource.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/services/searchresultformatter.service.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js create mode 100644 src/Umbraco.Web.UI.Client/src/installer.app.js create mode 100644 src/Umbraco.Web.UI.Client/src/installer/_module.js create mode 100644 src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.html create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-box.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-checkmark.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-list.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/users/umb-permission.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-cards.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-group-picker-list.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-group-preview.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-picker-list.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/utilities/layout/_display.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/utilities/typography/_text-decoration.less create mode 100644 src/Umbraco.Web.UI.Client/src/less/utilities/typography/_white-space.less create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/overlays/nodepermissions/nodepermissions.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/overlays/nodepermissions/nodepermissions.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/overlays/sectionpicker/sectionpicker.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/overlays/sectionpicker/sectionpicker.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/overlays/userpicker/userpicker.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/common/overlays/userpicker/userpicker.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/buttons/umb-toggle.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/content/edit.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/umb-badge.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/umb-checkmark.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/umb-dropdown-item.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/umb-dropdown.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/users/change-password.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/users/umb-permission.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/users/umb-user-group-preview.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/users/umb-user-preview.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/content/content.createblueprint.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/content/content.rights.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/content/createblueprint.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/content/rights.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/contentblueprints/delete.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/contentblueprints/delete.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/contentblueprints/edit.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/contentblueprints/edit.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/contentblueprints/intro.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.doctypepicker.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.editor.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/nestedcontent/nestedcontent.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/group.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/group.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/overview.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/user.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/user.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js create mode 100644 src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html create mode 100644 src/Umbraco.Web.UI.Client/test/unit/app/content/create-content-controller.spec.js delete mode 100644 src/Umbraco.Web.UI/umbraco/images/actions/sprites.png delete mode 100644 src/Umbraco.Web.UI/umbraco_client/Editors/EditScript.js delete mode 100644 src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/arrawBack.gif delete mode 100644 src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/arrowForward.gif delete mode 100644 src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/background.gif delete mode 100644 src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/button/buttonbg.gif delete mode 100644 src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/button/buttonbgdown.gif create mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs create mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs create mode 100644 src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs create mode 100644 src/Umbraco.Web/_Legacy/Actions/IAction.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..208052cbb7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root=true + +[*] +end_of_line = lf +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.{cs,cshtml,csx,vb,vbx,vbhtml,fs,fsx,txt,ps1,sql}] +indent_size = 4 \ No newline at end of file diff --git a/build/NuSpecs/tools/Web.config.install.xdt b/build/NuSpecs/tools/Web.config.install.xdt index 1a68fe492a..4851cd75b3 100644 --- a/build/NuSpecs/tools/Web.config.install.xdt +++ b/build/NuSpecs/tools/Web.config.install.xdt @@ -15,6 +15,7 @@
+
@@ -30,6 +31,7 @@ + @@ -366,19 +368,19 @@ - + - + - + - + diff --git a/build/NuSpecs/tools/trees.config.install.xdt b/build/NuSpecs/tools/trees.config.install.xdt index e6c9e074ab..4067318be7 100644 --- a/build/NuSpecs/tools/trees.config.install.xdt +++ b/build/NuSpecs/tools/trees.config.install.xdt @@ -92,15 +92,16 @@ xdt:Transform="Remove" /> - + + - + - + xdt:Transform="Remove" /> + /// Constructor used to assign a Category, since no name is assigned it will try to be translated from the language files based on the action's alias + /// + /// + public ActionMetadataAttribute(string category) + { + if (string.IsNullOrWhiteSpace(category)) throw new ArgumentNullOrEmptyException(nameof(category)); + Category = category; + } + + /// + /// Constructor used to assign an explicit name and category + /// + /// + /// + public ActionMetadataAttribute(string category, string name) + { + if (string.IsNullOrWhiteSpace(category)) throw new ArgumentNullOrEmptyException(nameof(category)); + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullOrEmptyException(nameof(name)); + Category = category; + Name = name; + } + } +} diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs index f85dbdb4d4..1ef1b1645b 100644 --- a/src/Umbraco.Core/Configuration/GlobalSettings.cs +++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Configuration; using System.Linq; +using System.Net.Configuration; using System.Web; using System.Web.Configuration; using System.Web.Hosting; @@ -44,7 +45,6 @@ namespace Umbraco.Core.Configuration //ensure the built on (non-changeable) reserved paths are there at all times private const string StaticReservedPaths = "~/app_plugins/,~/install/,"; private const string StaticReservedUrls = "~/config/splashes/booting.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd,"; - #endregion /// @@ -55,6 +55,7 @@ namespace Umbraco.Core.Configuration _reservedUrlsCache = null; _reservedPaths = null; _reservedUrls = null; + HasSmtpServer = null; } /// @@ -66,6 +67,25 @@ namespace Umbraco.Core.Configuration ResetInternal(); } + public static bool HasSmtpServerConfigured(string appPath) + { + if (HasSmtpServer.HasValue) return HasSmtpServer.Value; + + var config = WebConfigurationManager.OpenWebConfiguration(appPath); + var settings = (MailSettingsSectionGroup)config.GetSectionGroup("system.net/mailSettings"); + if (settings == null || settings.Smtp == null) return false; + if (settings.Smtp.SpecifiedPickupDirectory != null && string.IsNullOrEmpty(settings.Smtp.SpecifiedPickupDirectory.PickupDirectoryLocation) == false) + return true; + if (settings.Smtp.Network != null && string.IsNullOrEmpty(settings.Smtp.Network.Host) == false) + return true; + return false; + } + + /// + /// For testing only + /// + internal static bool? HasSmtpServer { get; set; } + /// /// Gets the reserved urls from web.config. /// diff --git a/src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthCheckElement.cs b/src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthCheckElement.cs new file mode 100644 index 0000000000..01392da614 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthCheckElement.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; +using System.Text; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + public class DisabledHealthCheckElement : ConfigurationElement, IDisabledHealthCheck + { + private const string IdKey = "id"; + private const string DisabledOnKey = "disabledOn"; + private const string DisabledByKey = "disabledBy"; + + [ConfigurationProperty(IdKey, IsKey = true, IsRequired = true)] + public Guid Id + { + get + { + return ((Guid)(base[IdKey])); + } + } + + [ConfigurationProperty(DisabledOnKey, IsKey = false, IsRequired = false)] + public DateTime DisabledOn + { + get + { + return ((DateTime)(base[DisabledOnKey])); + } + } + + [ConfigurationProperty(DisabledByKey, IsKey = false, IsRequired = false)] + public int DisabledBy + { + get + { + return ((int)(base[DisabledByKey])); + } + } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthChecksElementCollection.cs b/src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthChecksElementCollection.cs new file mode 100644 index 0000000000..87600b8ae3 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/DisabledHealthChecksElementCollection.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Configuration; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + [ConfigurationCollection(typeof(DisabledHealthCheckElement), AddItemName = "check")] + public class DisabledHealthChecksElementCollection : ConfigurationElementCollection, IEnumerable + { + protected override ConfigurationElement CreateNewElement() + { + return new DisabledHealthCheckElement(); + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((DisabledHealthCheckElement)(element)).Id; + } + + public new DisabledHealthCheckElement this[string key] + { + get + { + return (DisabledHealthCheckElement)BaseGet(key); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + for (var i = 0; i < Count; i++) + { + yield return BaseGet(i) as DisabledHealthCheckElement; + } + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationSettingsElement.cs b/src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationSettingsElement.cs new file mode 100644 index 0000000000..1ccf3e357b --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationSettingsElement.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + public class HealthCheckNotificationSettingsElement : ConfigurationElement, IHealthCheckNotificationSettings + { + private const string EnabledKey = "enabled"; + private const string FirstRunTimeKey = "firstRunTime"; + private const string PeriodKey = "periodInHours"; + private const string NotificationMethodsKey = "notificationMethods"; + private const string DisabledChecksKey = "disabledChecks"; + + [ConfigurationProperty(EnabledKey, IsRequired = true)] + public bool Enabled + { + get + { + return (bool)base[EnabledKey]; + } + } + + [ConfigurationProperty(FirstRunTimeKey, IsRequired = false)] + public string FirstRunTime + { + get + { + return (string)base[FirstRunTimeKey]; + } + } + + [ConfigurationProperty(PeriodKey, IsRequired = true)] + public int PeriodInHours + { + get + { + return (int)base[PeriodKey]; + } + } + + [ConfigurationProperty(NotificationMethodsKey, IsDefaultCollection = true, IsRequired = false)] + public NotificationMethodsElementCollection NotificationMethods + { + get + { + return (NotificationMethodsElementCollection)base[NotificationMethodsKey]; + } + } + + [ConfigurationProperty(DisabledChecksKey, IsDefaultCollection = false, IsRequired = false)] + public DisabledHealthChecksElementCollection DisabledChecks + { + get + { + return (DisabledHealthChecksElementCollection)base[DisabledChecksKey]; + } + } + + bool IHealthCheckNotificationSettings.Enabled + { + get { return Enabled; } + } + + string IHealthCheckNotificationSettings.FirstRunTime + { + get { return FirstRunTime; } + } + + int IHealthCheckNotificationSettings.PeriodInHours + { + get { return PeriodInHours; } + } + + IReadOnlyDictionary IHealthCheckNotificationSettings.NotificationMethods + { + get { return NotificationMethods; } + } + + IEnumerable IHealthCheckNotificationSettings.DisabledChecks + { + get { return DisabledChecks; } + } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs b/src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs new file mode 100644 index 0000000000..6556c19c32 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/HealthCheckNotificationVerbosity.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Core.Configuration.HealthChecks +{ + public enum HealthCheckNotificationVerbosity + { + Summary, + Detailed + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/HealthChecksSection.cs b/src/Umbraco.Core/Configuration/HealthChecks/HealthChecksSection.cs new file mode 100644 index 0000000000..90a7d8c567 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/HealthChecksSection.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + public class HealthChecksSection : ConfigurationSection, IHealthChecks + { + private const string DisabledChecksKey = "disabledChecks"; + private const string NotificationSettingsKey = "notificationSettings"; + + [ConfigurationProperty(DisabledChecksKey)] + public DisabledHealthChecksElementCollection DisabledChecks + { + get { return ((DisabledHealthChecksElementCollection)(base[DisabledChecksKey])); } + } + + [ConfigurationProperty(NotificationSettingsKey, IsRequired = true)] + public HealthCheckNotificationSettingsElement NotificationSettings + { + get { return ((HealthCheckNotificationSettingsElement)(base[NotificationSettingsKey])); } + } + + IEnumerable IHealthChecks.DisabledChecks + { + get { return DisabledChecks; } + } + + IHealthCheckNotificationSettings IHealthChecks.NotificationSettings + { + get { return NotificationSettings; } + } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/IDisabledHealthCheck.cs b/src/Umbraco.Core/Configuration/HealthChecks/IDisabledHealthCheck.cs new file mode 100644 index 0000000000..4ea63048f8 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/IDisabledHealthCheck.cs @@ -0,0 +1,11 @@ +using System; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + public interface IDisabledHealthCheck + { + Guid Id { get; } + DateTime DisabledOn { get; } + int DisabledBy { get; } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/IHealthCheckNotificationSettings.cs b/src/Umbraco.Core/Configuration/HealthChecks/IHealthCheckNotificationSettings.cs new file mode 100644 index 0000000000..4564e87ed6 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/IHealthCheckNotificationSettings.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + public interface IHealthCheckNotificationSettings + { + bool Enabled { get; } + string FirstRunTime { get; } + int PeriodInHours { get; } + IReadOnlyDictionary NotificationMethods { get; } + IEnumerable DisabledChecks { get; } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs b/src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs new file mode 100644 index 0000000000..fa98e3b054 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/IHealthChecks.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + public interface IHealthChecks + { + IEnumerable DisabledChecks { get; } + IHealthCheckNotificationSettings NotificationSettings { get; } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/INotificationMethod.cs b/src/Umbraco.Core/Configuration/HealthChecks/INotificationMethod.cs new file mode 100644 index 0000000000..84bf55e160 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/INotificationMethod.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + public interface INotificationMethod + { + string Alias { get; } + bool Enabled { get; } + HealthCheckNotificationVerbosity Verbosity { get; } + bool FailureOnly { get; } + IReadOnlyDictionary Settings { get; } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/INotificationMethodSettings.cs b/src/Umbraco.Core/Configuration/HealthChecks/INotificationMethodSettings.cs new file mode 100644 index 0000000000..e41c82b393 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/INotificationMethodSettings.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Core.Configuration.HealthChecks +{ + public interface INotificationMethodSettings + { + string Key { get; } + string Value { get; } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodElement.cs b/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodElement.cs new file mode 100644 index 0000000000..cbbe5e8b02 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodElement.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Configuration; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + public class NotificationMethodElement : ConfigurationElement, INotificationMethod + { + private const string AliasKey = "alias"; + private const string EnabledKey = "enabled"; + private const string VerbosityKey = "verbosity"; + private const string FailureonlyKey = "failureOnly"; + private const string SettingsKey = "settings"; + + [ConfigurationProperty(AliasKey, IsKey = true, IsRequired = true)] + public string Alias + { + get + { + return (string)base[AliasKey]; + } + } + + [ConfigurationProperty(EnabledKey, IsKey = true, IsRequired = true)] + public bool Enabled + { + get + { + return (bool)base[EnabledKey]; + } + } + + [ConfigurationProperty(VerbosityKey, IsRequired = true)] + public HealthCheckNotificationVerbosity Verbosity + { + get + { + return (HealthCheckNotificationVerbosity)base[VerbosityKey]; + } + } + + [ConfigurationProperty(FailureonlyKey, IsRequired = false)] + public bool FailureOnly + { + get + { + return (bool)base[FailureonlyKey]; + } + } + + [ConfigurationProperty(SettingsKey, IsDefaultCollection = true, IsRequired = false)] + public NotificationMethodSettingsElementCollection Settings + { + get + { + return (NotificationMethodSettingsElementCollection)base[SettingsKey]; + } + } + + string INotificationMethod.Alias + { + get { return Alias; } + } + + bool INotificationMethod.Enabled + { + get { return Enabled; } + } + + HealthCheckNotificationVerbosity INotificationMethod.Verbosity + { + get { return Verbosity; } + } + + bool INotificationMethod.FailureOnly + { + get { return FailureOnly; } + } + + IReadOnlyDictionary INotificationMethod.Settings + { + get { return Settings; } + } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElement.cs b/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElement.cs new file mode 100644 index 0000000000..ed42eb7221 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElement.cs @@ -0,0 +1,28 @@ +using System.Configuration; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + public class NotificationMethodSettingsElement : ConfigurationElement, INotificationMethodSettings + { + private const string KeyKey = "key"; + private const string ValueKey = "value"; + + [ConfigurationProperty(KeyKey, IsKey = true, IsRequired = true)] + public string Key + { + get + { + return (string)base[KeyKey]; + } + } + + [ConfigurationProperty(ValueKey, IsRequired = true)] + public string Value + { + get + { + return (string)base[ValueKey]; + } + } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElementCollection.cs b/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElementCollection.cs new file mode 100644 index 0000000000..226278ab61 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodSettingsElementCollection.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + [ConfigurationCollection(typeof(NotificationMethodSettingsElement), AddItemName = "add")] + public class NotificationMethodSettingsElementCollection : ConfigurationElementCollection, IEnumerable, IReadOnlyDictionary + { + protected override ConfigurationElement CreateNewElement() + { + return new NotificationMethodSettingsElement(); + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((NotificationMethodSettingsElement)(element)).Key; + } + + IEnumerator> IEnumerable>.GetEnumerator() + { + for (var i = 0; i < Count; i++) + { + var val = (NotificationMethodSettingsElement)BaseGet(i); + var key = (string)BaseGetKey(i); + yield return new KeyValuePair(key, val); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + for (var i = 0; i < Count; i++) + { + yield return (NotificationMethodSettingsElement)BaseGet(i); + } + } + + bool IReadOnlyDictionary.ContainsKey(string key) + { + return ((IReadOnlyDictionary)this).Keys.Any(x => x == key); + } + + bool IReadOnlyDictionary.TryGetValue(string key, out INotificationMethodSettings value) + { + try + { + var val = (NotificationMethodSettingsElement)BaseGet(key); + value = val; + return true; + } + catch (Exception) + { + value = null; + return false; + } + } + + INotificationMethodSettings IReadOnlyDictionary.this[string key] + { + get { return (NotificationMethodSettingsElement)BaseGet(key); } + } + + IEnumerable IReadOnlyDictionary.Keys + { + get { return BaseGetAllKeys().Cast(); } + } + + IEnumerable IReadOnlyDictionary.Values + { + get + { + for (var i = 0; i < Count; i++) + { + yield return (NotificationMethodSettingsElement)BaseGet(i); + } + } + } + } +} diff --git a/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodsElementCollection.cs b/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodsElementCollection.cs new file mode 100644 index 0000000000..ee7e135961 --- /dev/null +++ b/src/Umbraco.Core/Configuration/HealthChecks/NotificationMethodsElementCollection.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Linq; + +namespace Umbraco.Core.Configuration.HealthChecks +{ + [ConfigurationCollection(typeof(NotificationMethodElement), AddItemName = "notificationMethod")] + public class NotificationMethodsElementCollection : ConfigurationElementCollection, IEnumerable, IReadOnlyDictionary + { + protected override ConfigurationElement CreateNewElement() + { + return new NotificationMethodElement(); + } + + protected override object GetElementKey(ConfigurationElement element) + { + return ((NotificationMethodElement)(element)).Alias; + } + + IEnumerator> IEnumerable>.GetEnumerator() + { + for (var i = 0; i < Count; i++) + { + var val = (NotificationMethodElement)BaseGet(i); + var key = (string)BaseGetKey(i); + yield return new KeyValuePair(key, val); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + for (var i = 0; i < Count; i++) + { + yield return (NotificationMethodElement)BaseGet(i); + } + } + + bool IReadOnlyDictionary.ContainsKey(string key) + { + return ((IReadOnlyDictionary) this).Keys.Any(x => x == key); + } + + bool IReadOnlyDictionary.TryGetValue(string key, out INotificationMethod value) + { + try + { + var val = (NotificationMethodElement)BaseGet(key); + value = val; + return true; + } + catch (Exception) + { + value = null; + return false; + } + } + + INotificationMethod IReadOnlyDictionary.this[string key] + { + get { return (NotificationMethodElement)BaseGet(key); } + } + + IEnumerable IReadOnlyDictionary.Keys + { + get { return BaseGetAllKeys().Cast(); } + } + + IEnumerable IReadOnlyDictionary.Values + { + get + { + for (var i = 0; i < Count; i++) + { + yield return (NotificationMethodElement)BaseGet(i); + } + } + } + } +} diff --git a/src/Umbraco.Core/Configuration/UmbracoConfig.cs b/src/Umbraco.Core/Configuration/UmbracoConfig.cs index 9a0dc12485..0776af1784 100644 --- a/src/Umbraco.Core/Configuration/UmbracoConfig.cs +++ b/src/Umbraco.Core/Configuration/UmbracoConfig.cs @@ -4,6 +4,7 @@ using System.IO; using Umbraco.Core.Cache; using Umbraco.Core.Configuration.Dashboard; using Umbraco.Core.Configuration.Grid; +using Umbraco.Core.Configuration.HealthChecks; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Composing; using Umbraco.Core.Logging; @@ -53,6 +54,12 @@ namespace Umbraco.Core.Configuration } SetDashboardSettings(dashboardConfig); } + + if (_healthChecks == null) + { + var healthCheckConfig = ConfigurationManager.GetSection("umbracoConfiguration/HealthChecks") as IHealthChecks; + SetHealthCheckSettings(healthCheckConfig); + } } /// @@ -60,16 +67,34 @@ namespace Umbraco.Core.Configuration /// /// /// - public UmbracoConfig(IUmbracoSettingsSection umbracoSettings, IDashboardSection dashboardSettings) + /// + public UmbracoConfig(IUmbracoSettingsSection umbracoSettings, IDashboardSection dashboardSettings, IHealthChecks healthChecks) { + SetHealthCheckSettings(healthChecks); SetUmbracoSettings(umbracoSettings); SetDashboardSettings(dashboardSettings); } + private IHealthChecks _healthChecks; private IDashboardSection _dashboardSection; private IUmbracoSettingsSection _umbracoSettings; private IGridConfig _gridConfig; + /// + /// Gets the IHealthCheck config + /// + public IHealthChecks HealthCheck() + { + if (_healthChecks == null) + { + var ex = new ConfigurationErrorsException("Could not load the " + typeof(IHealthChecks) + " from config file, ensure the web.config and healthchecks.config files are formatted correctly"); + LogHelper.Error("Config error", ex); + throw ex; + } + + return _healthChecks; + } + /// /// Gets the IDashboardSection /// @@ -89,11 +114,20 @@ namespace Umbraco.Core.Configuration /// Only for testing /// /// - internal void SetDashboardSettings(IDashboardSection value) + public void SetDashboardSettings(IDashboardSection value) { _dashboardSection = value; } + /// + /// Only for testing + /// + /// + public void SetHealthCheckSettings(IHealthChecks value) + { + _healthChecks = value; + } + /// /// Only for testing /// diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs index 87d4c4a7f5..79283242e2 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs @@ -117,7 +117,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings { get { return GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"}); } } - + [ConfigurationProperty("allowedUploadFiles")] internal CommaDelimitedConfigurationElement AllowedUploadFiles { @@ -270,7 +270,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings { get { return DisallowedUploadFiles; } } - + IEnumerable IContentSection.AllowedUploadFiles { get { return AllowedUploadFiles; } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ILink.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ILink.cs index 8de74c0f7c..c4b5781ca3 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ILink.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ILink.cs @@ -1,5 +1,10 @@ -namespace Umbraco.Core.Configuration.UmbracoSettings +using System; +using System.ComponentModel; + +namespace Umbraco.Core.Configuration.UmbracoSettings { + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("This is no longer used and will be removed in future versions")] public interface ILink { string Application { get; } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs index 5d03466402..c1151b24d2 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IRequestHandlerSection.cs @@ -12,6 +12,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings bool ConvertUrlsToAscii { get; } + bool TryConvertUrlsToAscii { get; } + IEnumerable CharCollection { get; } } } diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs index 11504cf2a4..0801c9933f 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IUmbracoSettingsSection.cs @@ -1,4 +1,7 @@ -namespace Umbraco.Core.Configuration.UmbracoSettings +using System; +using System.ComponentModel; + +namespace Umbraco.Core.Configuration.UmbracoSettings { public interface IUmbracoSettingsSection : IUmbracoConfigurationSection { diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs index 76d23b1757..cf16a31889 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/RequestHandlerElement.cs @@ -111,7 +111,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings bool IRequestHandlerSection.ConvertUrlsToAscii { - get { return UrlReplacing.ConvertUrlsToAscii; } + get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("true"); } + } + + bool IRequestHandlerSection.TryConvertUrlsToAscii + { + get { return UrlReplacing.ConvertUrlsToAscii.InvariantEquals("try"); } } IEnumerable IRequestHandlerSection.CharCollection diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs index 2c9875522d..49a791144b 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/UmbracoSettingsSection.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Configuration; using System.Linq; diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs index f95a999f8a..6d76f45a8c 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/UrlReplacingElement.cs @@ -11,10 +11,10 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return (bool) base["removeDoubleDashes"]; } } - [ConfigurationProperty("toAscii", DefaultValue = false)] - internal bool ConvertUrlsToAscii + [ConfigurationProperty("toAscii", DefaultValue = "false")] + internal string ConvertUrlsToAscii { - get { return (bool)base["toAscii"]; } + get { return (string) base["toAscii"]; } } [ConfigurationCollection(typeof(CharCollection), AddItemName = "char")] diff --git a/src/Umbraco.Core/Events/ImportPackageEventArgs.cs b/src/Umbraco.Core/Events/ImportPackageEventArgs.cs index 589f758531..6ad7b52806 100644 --- a/src/Umbraco.Core/Events/ImportPackageEventArgs.cs +++ b/src/Umbraco.Core/Events/ImportPackageEventArgs.cs @@ -4,7 +4,7 @@ using Umbraco.Core.Models.Packaging; namespace Umbraco.Core.Events { - internal class ImportPackageEventArgs : CancellableEnumerableObjectEventArgs, IEquatable> + public class ImportPackageEventArgs : CancellableEnumerableObjectEventArgs, IEquatable> { private readonly MetaData _packageMetaData; diff --git a/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs b/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs index feeb92fc03..13c260bf3e 100644 --- a/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs +++ b/src/Umbraco.Core/Events/UninstallPackageEventArgs.cs @@ -3,7 +3,7 @@ using Umbraco.Core.Models.Packaging; namespace Umbraco.Core.Events { - internal class UninstallPackageEventArgs : CancellableObjectEventArgs> + public class UninstallPackageEventArgs : CancellableObjectEventArgs> { public UninstallPackageEventArgs(TEntity eventObject, bool canCancel) : base(new[] { eventObject }, canCancel) diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs index cb6fb5ccee..57abeaeb12 100644 --- a/src/Umbraco.Core/IO/IOHelper.cs +++ b/src/Umbraco.Core/IO/IOHelper.cs @@ -109,6 +109,8 @@ namespace Umbraco.Core.IO public static string MapPath(string path, bool useHttpContext) { + if (path == null) throw new ArgumentNullException("path"); + // Check if the path is already mapped if ((path.Length >= 2 && path[1] == Path.VolumeSeparatorChar) || path.StartsWith(@"\\")) //UNC Paths start with "\\". If the site is running off a network drive mapped paths will look like "\\Whatever\Boo\Bar" diff --git a/src/Umbraco.Core/Models/EntityBase/Entity.cs b/src/Umbraco.Core/Models/EntityBase/Entity.cs index c583a13ee5..d764314907 100644 --- a/src/Umbraco.Core/Models/EntityBase/Entity.cs +++ b/src/Umbraco.Core/Models/EntityBase/Entity.cs @@ -117,7 +117,7 @@ namespace Umbraco.Core.Models.EntityBase if (IsPropertyDirty("CreateDate") == false || _createDate == default(DateTime)) CreateDate = DateTime.Now; if (IsPropertyDirty("UpdateDate") == false || _updateDate == default(DateTime)) - UpdateDate = CreateDate; + UpdateDate = DateTime.Now; } /// @@ -127,6 +127,10 @@ namespace Umbraco.Core.Models.EntityBase { if (IsPropertyDirty("UpdateDate") == false || _updateDate == default(DateTime)) UpdateDate = DateTime.Now; + + //this is just in case + if (_createDate == default(DateTime)) + CreateDate = DateTime.Now; } /// diff --git a/src/Umbraco.Core/Models/EntityBase/EntityPath.cs b/src/Umbraco.Core/Models/EntityBase/EntityPath.cs new file mode 100644 index 0000000000..368d6bd87b --- /dev/null +++ b/src/Umbraco.Core/Models/EntityBase/EntityPath.cs @@ -0,0 +1,8 @@ +namespace Umbraco.Core.Models.EntityBase +{ + public class EntityPath + { + public int Id { get; set; } + public string Path { get; set; } + } +} diff --git a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs index cecfe7da9a..37e7b3f8f4 100644 --- a/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs +++ b/src/Umbraco.Core/Models/Identity/BackOfficeIdentityUser.cs @@ -2,21 +2,67 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.Linq; +using System.Reflection; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNet.Identity; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Models.Membership; using Umbraco.Core.Security; namespace Umbraco.Core.Models.Identity { - public class BackOfficeIdentityUser : IdentityUser, IdentityUserClaim> + public class BackOfficeIdentityUser : IdentityUser, IdentityUserClaim>, IRememberBeingDirty { - - public BackOfficeIdentityUser() + /// + /// Used to construct a new instance without an identity + /// + /// + /// This is allowed to be null (but would need to be filled in if trying to persist this instance) + /// + /// + public static BackOfficeIdentityUser CreateNew(string username, string email, string culture) { - StartMediaId = -1; - StartContentId = -1; - Culture = Configuration.GlobalSettings.DefaultUILanguage; + if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", "username"); + if (string.IsNullOrWhiteSpace(culture)) throw new ArgumentException("Value cannot be null or whitespace.", "culture"); + + var user = new BackOfficeIdentityUser(); + user.DisableChangeTracking(); + user._userName = username; + user._email = email; + //we are setting minvalue here because the default is "0" which is the id of the admin user + //which we cannot allow because the admin user will always exist + user._id = int.MinValue; + user._hasIdentity = false; + user._culture = culture; + user.EnableChangeTracking(); + return user; + } + + private BackOfficeIdentityUser() + { + } + + /// + /// Creates an existing user with the specified groups + /// + /// + /// + public BackOfficeIdentityUser(int userId, IEnumerable groups) + { + _startMediaIds = new int[] { }; + _startContentIds = new int[] { }; + _groups = new IReadOnlyUserGroup[] { }; + _allowedSections = new string[] { }; + _culture = Configuration.GlobalSettings.DefaultUILanguage; + _groups = groups.ToArray(); + _roles = new ObservableCollection>(_groups.Select(x => new IdentityUserRole + { + RoleId = x.Alias, + UserId = userId.ToString() + })); + _roles.CollectionChanged += _roles_CollectionChanged; } public virtual async Task GenerateUserIdentityAsync(BackOfficeUserManager manager) @@ -27,16 +73,155 @@ namespace Umbraco.Core.Models.Identity return userIdentity; } + /// + /// Returns true if an Id has been set on this object this will be false if the object is new and not peristed to the database + /// + public bool HasIdentity + { + get { return _hasIdentity; } + } + + public int[] CalculatedMediaStartNodeIds { get; internal set; } + public int[] CalculatedContentStartNodeIds { get; internal set; } + + public override int Id + { + get { return _id; } + set + { + _id = value; + _hasIdentity = true; + } + } + + /// + /// Override Email so we can track changes to it + /// + public override string Email + { + get { return _email; } + set { _tracker.SetPropertyValueAndDetectChanges(value, ref _email, Ps.Value.EmailSelector); } + } + + /// + /// Override UserName so we can track changes to it + /// + public override string UserName + { + get { return _userName; } + set { _tracker.SetPropertyValueAndDetectChanges(value, ref _userName, Ps.Value.UserNameSelector); } + } + + /// + /// Override LastLoginDateUtc so we can track changes to it + /// + public override DateTime? LastLoginDateUtc + { + get { return _lastLoginDateUtc; } + set { _tracker.SetPropertyValueAndDetectChanges(value, ref _lastLoginDateUtc, Ps.Value.LastLoginDateUtcSelector); } + } + + /// + /// Override EmailConfirmed so we can track changes to it + /// + public override bool EmailConfirmed + { + get { return _emailConfirmed; } + set { _tracker.SetPropertyValueAndDetectChanges(value, ref _emailConfirmed, Ps.Value.EmailConfirmedSelector); } + } + /// /// Gets/sets the user's real name /// - public string Name { get; set; } - public int StartContentId { get; set; } - public int StartMediaId { get; set; } - public string[] AllowedSections { get; set; } - public string Culture { get; set; } + public string Name + { + get { return _name; } + set { _tracker.SetPropertyValueAndDetectChanges(value, ref _name, Ps.Value.NameSelector); } + } - public string UserTypeAlias { get; set; } + /// + /// Override AccessFailedCount so we can track changes to it + /// + public override int AccessFailedCount + { + get { return _accessFailedCount; } + set { _tracker.SetPropertyValueAndDetectChanges(value, ref _accessFailedCount, Ps.Value.AccessFailedCountSelector); } + } + + /// + /// Override PasswordHash so we can track changes to it + /// + public override string PasswordHash + { + get { return _passwordHash; } + set { _tracker.SetPropertyValueAndDetectChanges(value, ref _passwordHash, Ps.Value.PasswordHashSelector); } + } + + + /// + /// Content start nodes assigned to the User (not ones assigned to the user's groups) + /// + public int[] StartContentIds + { + get { return _startContentIds; } + set + { + if (value == null) value = new int[0]; + _tracker.SetPropertyValueAndDetectChanges(value, ref _startContentIds, Ps.Value.StartContentIdsSelector, Ps.Value.StartIdsComparer); + } + } + + /// + /// Media start nodes assigned to the User (not ones assigned to the user's groups) + /// + public int[] StartMediaIds + { + get { return _startMediaIds; } + set + { + if (value == null) value = new int[0]; + _tracker.SetPropertyValueAndDetectChanges(value, ref _startMediaIds, Ps.Value.StartMediaIdsSelector, Ps.Value.StartIdsComparer); + } + } + + /// + /// This is a readonly list of the user's allowed sections which are based on it's user groups + /// + public string[] AllowedSections + { + get { return _allowedSections ?? (_allowedSections = _groups.SelectMany(x => x.AllowedSections).Distinct().ToArray()); } + } + + public string Culture + { + get { return _culture; } + set { _tracker.SetPropertyValueAndDetectChanges(value, ref _culture, Ps.Value.CultureSelector); } + } + + public IReadOnlyUserGroup[] Groups + { + get { return _groups; } + set + { + //so they recalculate + _allowedSections = null; + + //now clear all roles and re-add them + _roles.CollectionChanged -= _roles_CollectionChanged; + _roles.Clear(); + foreach (var identityUserRole in _groups.Select(x => new IdentityUserRole + { + RoleId = x.Alias, + UserId = Id.ToString() + })) + { + _roles.Add(identityUserRole); + } + _roles.CollectionChanged += _roles_CollectionChanged; + + _tracker.SetPropertyValueAndDetectChanges(value, ref _groups, Ps.Value.GroupsSelector, Ps.Value.GroupsComparer); + } + } /// /// Lockout is always enabled @@ -83,15 +268,41 @@ namespace Umbraco.Core.Models.Identity } } - public bool LoginsChanged { get; private set; } - void Logins_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - LoginsChanged = true; + _tracker.OnPropertyChanged(Ps.Value.LoginsSelector); } - private ObservableCollection _logins; - private Lazy> _getLogins; + private void _roles_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) + { + _tracker.OnPropertyChanged(Ps.Value.RolesSelector); + } + + private readonly ObservableCollection> _roles; + + /// + /// helper method to easily add a role without having to deal with IdentityUserRole{T} + /// + /// + /// + /// Adding a role this way will not reflect on the user's group's collection or it's allowed sections until the user is persisted + /// + public void AddRole(string role) + { + Roles.Add(new IdentityUserRole + { + UserId = this.Id.ToString(), + RoleId = role + }); + } + + /// + /// Override Roles because the value of these are the user's group aliases + /// + public override ICollection> Roles + { + get { return _roles; } + } /// /// Used to set a lazy call back to populate the user's Login list @@ -102,5 +313,127 @@ namespace Umbraco.Core.Models.Identity if (callback == null) throw new ArgumentNullException("callback"); _getLogins = callback; } + + #region Change tracking + + public void DisableChangeTracking() + { + _tracker.DisableChangeTracking(); + } + + public void EnableChangeTracking() + { + _tracker.EnableChangeTracking(); + } + + /// + /// Since this class only has change tracking turned on for Email/Username this will return true if either of those have changed + /// + /// + public bool IsDirty() + { + return _tracker.IsDirty(); + } + + /// + /// Returns true if the specified property is dirty + /// + /// + /// + public bool IsPropertyDirty(string propName) + { + return _tracker.IsPropertyDirty(propName); + } + + /// + /// Resets dirty properties + /// + void ICanBeDirty.ResetDirtyProperties() + { + _tracker.ResetDirtyProperties(); + } + + bool IRememberBeingDirty.WasDirty() + { + return _tracker.WasDirty(); + } + + bool IRememberBeingDirty.WasPropertyDirty(string propertyName) + { + return _tracker.WasPropertyDirty(propertyName); + } + + void IRememberBeingDirty.ForgetPreviouslyDirtyProperties() + { + _tracker.ForgetPreviouslyDirtyProperties(); + } + + public void ResetDirtyProperties(bool rememberPreviouslyChangedProperties) + { + _tracker.ResetDirtyProperties(rememberPreviouslyChangedProperties); + } + + private static readonly Lazy Ps = new Lazy(); + private class PropertySelectors + { + public readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo(x => x.Email); + public readonly PropertyInfo UserNameSelector = ExpressionHelper.GetPropertyInfo(x => x.UserName); + public readonly PropertyInfo LastLoginDateUtcSelector = ExpressionHelper.GetPropertyInfo(x => x.LastLoginDateUtc); + public readonly PropertyInfo EmailConfirmedSelector = ExpressionHelper.GetPropertyInfo(x => x.EmailConfirmed); + public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); + public readonly PropertyInfo AccessFailedCountSelector = ExpressionHelper.GetPropertyInfo(x => x.AccessFailedCount); + public readonly PropertyInfo PasswordHashSelector = ExpressionHelper.GetPropertyInfo(x => x.PasswordHash); + public readonly PropertyInfo CultureSelector = ExpressionHelper.GetPropertyInfo(x => x.Culture); + public readonly PropertyInfo StartMediaIdsSelector = ExpressionHelper.GetPropertyInfo(x => x.StartMediaIds); + public readonly PropertyInfo StartContentIdsSelector = ExpressionHelper.GetPropertyInfo(x => x.StartContentIds); + public readonly PropertyInfo GroupsSelector = ExpressionHelper.GetPropertyInfo(x => x.Groups); + public readonly PropertyInfo LoginsSelector = ExpressionHelper.GetPropertyInfo>(x => x.Logins); + public readonly PropertyInfo RolesSelector = ExpressionHelper.GetPropertyInfo>>(x => x.Roles); + + //Custom comparer for enumerables + public readonly DelegateEqualityComparer GroupsComparer = new DelegateEqualityComparer( + (groups, enumerable) => groups.Select(x => x.Alias).UnsortedSequenceEqual(enumerable.Select(x => x.Alias)), + groups => groups.GetHashCode()); + public readonly DelegateEqualityComparer StartIdsComparer = new DelegateEqualityComparer( + (groups, enumerable) => groups.UnsortedSequenceEqual(enumerable), + groups => groups.GetHashCode()); + + } + + private readonly ChangeTracker _tracker = new ChangeTracker(); + private string _email; + private string _userName; + private int _id; + private bool _hasIdentity = false; + private DateTime? _lastLoginDateUtc; + private bool _emailConfirmed; + private string _name; + private int _accessFailedCount; + private string _passwordHash; + private string _culture; + private ObservableCollection _logins; + private Lazy> _getLogins; + private IReadOnlyUserGroup[] _groups; + private string[] _allowedSections; + private int[] _startMediaIds; + private int[] _startContentIds; + + /// + /// internal class used to track changes for properties that have it enabled + /// + private class ChangeTracker : TracksChangesEntityBase + { + /// + /// Make this public so that it's usable + /// + /// + public new void OnPropertyChanged(PropertyInfo propertyInfo) + { + base.OnPropertyChanged(propertyInfo); + } + } + #endregion + + } } diff --git a/src/Umbraco.Core/Models/Identity/IdentityProfile.cs b/src/Umbraco.Core/Models/Identity/IdentityProfile.cs index 931d023c65..b6a39227d3 100644 --- a/src/Umbraco.Core/Models/Identity/IdentityProfile.cs +++ b/src/Umbraco.Core/Models/Identity/IdentityProfile.cs @@ -1,29 +1,38 @@ using System; using System.Linq; using AutoMapper; +using Umbraco.Core.Composing; using Umbraco.Core.Models.Membership; using Umbraco.Core.Security; using Umbraco.Core.Services; +using Umbraco.Core.Models.EntityBase; namespace Umbraco.Core.Models.Identity { public class IdentityProfile : Profile { - public IdentityProfile(ILocalizedTextService textService) + public IdentityProfile(ILocalizedTextService textService, IEntityService entityService) { CreateMap() + .BeforeMap((src, dest) => + { + dest.DisableChangeTracking(); + }) + .ConstructUsing(src => new BackOfficeIdentityUser(src.Id, src.Groups)) .ForMember(dest => dest.LastLoginDateUtc, opt => opt.MapFrom(src => src.LastLoginDate.ToUniversalTime())) .ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email)) + .ForMember(dest => dest.EmailConfirmed, opt => opt.MapFrom(src => src.EmailConfirmedDate.HasValue)) .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id)) .ForMember(dest => dest.LockoutEndDateUtc, opt => opt.MapFrom(src => src.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?) null)) .ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Username)) .ForMember(dest => dest.PasswordHash, opt => opt.MapFrom(user => GetPasswordHash(user.RawPasswordValue))) .ForMember(dest => dest.Culture, opt => opt.MapFrom(src => src.GetUserCulture(textService))) .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name)) - .ForMember(dest => dest.StartMediaId, opt => opt.MapFrom(src => src.StartMediaId)) - .ForMember(dest => dest.StartContentId, opt => opt.MapFrom(src => src.StartContentId)) - .ForMember(dest => dest.UserTypeAlias, opt => opt.MapFrom(src => src.UserType.Alias)) + .ForMember(dest => dest.StartMediaIds, opt => opt.MapFrom(src => src.StartMediaIds)) + .ForMember(dest => dest.StartContentIds, opt => opt.MapFrom(src => src.StartContentIds)) .ForMember(dest => dest.AccessFailedCount, opt => opt.MapFrom(src => src.FailedPasswordAttempts)) + .ForMember(dest => dest.CalculatedContentStartNodeIds, opt => opt.MapFrom(src => src.CalculateContentStartNodeIds(entityService))) + .ForMember(dest => dest.CalculatedMediaStartNodeIds, opt => opt.MapFrom(src => src.CalculateMediaStartNodeIds(entityService))) .ForMember(dest => dest.AllowedSections, opt => opt.MapFrom(src => src.AllowedSections.ToArray())) .ForMember(dest => dest.LockoutEnabled, opt => opt.Ignore()) .ForMember(dest => dest.Logins, opt => opt.Ignore()) @@ -33,12 +42,21 @@ namespace Umbraco.Core.Models.Identity .ForMember(dest => dest.PhoneNumberConfirmed, opt => opt.Ignore()) .ForMember(dest => dest.TwoFactorEnabled, opt => opt.Ignore()) .ForMember(dest => dest.Roles, opt => opt.Ignore()) - .ForMember(dest => dest.Claims, opt => opt.Ignore()); + .ForMember(dest => dest.Claims, opt => opt.Ignore()) + .AfterMap((src, dest) => + { + dest.ResetDirtyProperties(true); + dest.EnableChangeTracking(); + }); CreateMap() .ConstructUsing(source => new UserData(Guid.NewGuid().ToString("N"))) //this is the 'session id' .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Id)) .ForMember(dest => dest.AllowedApplications, opt => opt.MapFrom(src => src.AllowedSections)) + //When mapping to UserData which is used in the authcookie we want ALL start nodes including ones defined on the groups + .ForMember(dest => dest.StartContentNodes, opt => opt.MapFrom(src => src.CalculatedContentStartNodeIds)) + //When mapping to UserData which is used in the authcookie we want ALL start nodes including ones defined on the groups + .ForMember(dest => dest.StartMediaNodes, opt => opt.MapFrom(src => src.CalculatedMediaStartNodeIds)) .ForMember(dest => dest.RealName, opt => opt.MapFrom(src => src.Name)) .ForMember(dest => dest.Roles, opt => opt.MapFrom(user => new[] { user.UserTypeAlias })) .ForMember(dest => dest.StartContentNode, opt => opt.MapFrom(src => src.StartContentId)) @@ -50,7 +68,7 @@ namespace Umbraco.Core.Models.Identity private static string GetPasswordHash(string storedPass) { - return storedPass.StartsWith("___UIDEMPTYPWORD__") ? null : storedPass; + return storedPass.StartsWith(Constants.Security.EmptyPasswordPrefix) ? null : storedPass; } } } diff --git a/src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs b/src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs new file mode 100644 index 0000000000..f55093402b --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/ContentPermissionSet.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models.EntityBase; + +namespace Umbraco.Core.Models.Membership +{ + /// + /// Represents an -> user group & permission key value pair collection + /// + /// + /// This implements purely so it can be used with the repository layer which is why it's explicitly implemented. + /// + public class ContentPermissionSet : EntityPermissionSet, IAggregateRoot + { + private readonly IContent _content; + + public ContentPermissionSet(IContent content, EntityPermissionCollection permissionsSet) + : base(content.Id, permissionsSet) + { + _content = content; + } + + public override int EntityId + { + get { return _content.Id; } + } + + #region Explicit implementation of IAggregateRoot + int IEntity.Id + { + get { return EntityId; } + set { throw new NotImplementedException(); } + } + + bool IEntity.HasIdentity + { + get { return EntityId > 0; } + } + + Guid IEntity.Key { get; set; } + + DateTime IEntity.CreateDate { get; set; } + + DateTime IEntity.UpdateDate { get; set; } + + DateTime? IDeletableEntity.DeletedDate { get; set; } + + object IDeepCloneable.DeepClone() + { + throw new NotImplementedException(); + } + #endregion + } +} diff --git a/src/Umbraco.Core/Models/Membership/EntityPermission.cs b/src/Umbraco.Core/Models/Membership/EntityPermission.cs index 205da81d5d..11f86a1cf2 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermission.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermission.cs @@ -1,26 +1,66 @@ -using System.Collections; +using System; namespace Umbraco.Core.Models.Membership { /// - /// Represents a user -> entity permission + /// Represents an entity permission (defined on the user group and derived to retrieve permissions for a given user) /// - public class EntityPermission + public class EntityPermission : IEquatable { - public EntityPermission(int userId, int entityId, string[] assignedPermissions) + public EntityPermission(int groupId, int entityId, string[] assignedPermissions) { - UserId = userId; + UserGroupId = groupId; EntityId = entityId; AssignedPermissions = assignedPermissions; + IsDefaultPermissions = false; + } + + public EntityPermission(int groupId, int entityId, string[] assignedPermissions, bool isDefaultPermissions) + { + UserGroupId = groupId; + EntityId = entityId; + AssignedPermissions = assignedPermissions; + IsDefaultPermissions = isDefaultPermissions; } - public int UserId { get; private set; } public int EntityId { get; private set; } + public int UserGroupId { get; private set; } /// /// The assigned permissions for the user/entity combo /// public string[] AssignedPermissions { get; private set; } + + /// + /// True if the permissions assigned to this object are the group's default permissions and not explicitly defined permissions + /// + /// + /// This will be the case when looking up entity permissions and falling back to the default permissions + /// + public bool IsDefaultPermissions { get; private set; } + + public bool Equals(EntityPermission other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return EntityId == other.EntityId && UserGroupId == other.UserGroupId; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((EntityPermission) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (EntityId * 397) ^ UserGroupId; + } + } } } diff --git a/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs b/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs new file mode 100644 index 0000000000..a2f70ef5ef --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/EntityPermissionCollection.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Umbraco.Core.Models.Membership +{ + /// + /// A of + /// + public class EntityPermissionCollection : HashSet + { + public EntityPermissionCollection() + { + } + + public EntityPermissionCollection(IEnumerable collection) : base(collection) + { + } + + /// + /// Returns the aggregate permissions in the permission set + /// + /// + /// + /// This value is only calculated once + /// + public IEnumerable GetAllPermissions() + { + return _aggregatePermissions ?? (_aggregatePermissions = + this.SelectMany(x => x.AssignedPermissions).Distinct().ToArray()); + } + + private string[] _aggregatePermissions; + } +} diff --git a/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs b/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs index 7bb3408412..e85ab06f33 100644 --- a/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs +++ b/src/Umbraco.Core/Models/Membership/EntityPermissionSet.cs @@ -1,59 +1,55 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; namespace Umbraco.Core.Models.Membership { /// - /// Represents an entity -> user & permission key value pair collection + /// Represents an entity -> user group & permission key value pair collection /// public class EntityPermissionSet { + private static readonly Lazy EmptyInstance = new Lazy(() => new EntityPermissionSet(-1, new EntityPermissionCollection())); + /// + /// Returns an empty permission set + /// + /// + public static EntityPermissionSet Empty() + { + return EmptyInstance.Value; + } + + public EntityPermissionSet(int entityId, EntityPermissionCollection permissionsSet) + { + EntityId = entityId; + PermissionsSet = permissionsSet; + } + /// /// The entity id with permissions assigned /// - public int EntityId { get; private set; } + public virtual int EntityId { get; private set; } /// - /// The key/value pairs of user id & single permission + /// The key/value pairs of user group id & single permission /// - public IEnumerable UserPermissionsSet { get; private set; } + public EntityPermissionCollection PermissionsSet { get; private set; } - public EntityPermissionSet(int entityId, IEnumerable userPermissionsSet) + + /// + /// Returns the aggregate permissions in the permission set + /// + /// + /// + /// This value is only calculated once + /// + public IEnumerable GetAllPermissions() { - EntityId = entityId; - UserPermissionsSet = userPermissionsSet; + return PermissionsSet.GetAllPermissions(); } - public class UserPermission - { - public UserPermission(int userId, string permission) - { - UserId = userId; - Permission = permission; - } - public int UserId { get; private set; } - public string Permission { get; private set; } - protected bool Equals(UserPermission other) - { - return UserId == other.UserId && string.Equals(Permission, other.Permission); - } - public override bool Equals(object obj) - { - if (ReferenceEquals(null, obj)) return false; - if (ReferenceEquals(this, obj)) return true; - if (obj.GetType() != this.GetType()) return false; - return Equals((UserPermission) obj); - } - - public override int GetHashCode() - { - unchecked - { - return (UserId*397) ^ Permission.GetHashCode(); - } - } - } } } diff --git a/src/Umbraco.Core/Models/Membership/IProfile.cs b/src/Umbraco.Core/Models/Membership/IProfile.cs index 820089c6d9..e711c43cbe 100644 --- a/src/Umbraco.Core/Models/Membership/IProfile.cs +++ b/src/Umbraco.Core/Models/Membership/IProfile.cs @@ -1,15 +1,11 @@ namespace Umbraco.Core.Models.Membership { /// - /// Defines the the Profile interface + /// Defines the the User Profile interface /// - /// - /// This interface is pretty useless but has been exposed publicly from 6.x so we're stuck with it. It would make more sense - /// if the Id was an int but since it's not people have to cast it to int all of the time! - /// public interface IProfile { - object Id { get; set; } - string Name { get; set; } + int Id { get; } + string Name { get; } } } diff --git a/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs b/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs new file mode 100644 index 0000000000..571c13cf70 --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/IReadOnlyUserGroup.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; + +namespace Umbraco.Core.Models.Membership +{ + /// + /// A readonly user group providing basic information + /// + public interface IReadOnlyUserGroup + { + string Name { get; } + string Icon { get; } + int Id { get; } + int? StartContentId { get; } + int? StartMediaId { get; } + + /// + /// The alias + /// + string Alias { get; } + + /// + /// The set of default permissions + /// + /// + /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future. + /// + IEnumerable Permissions { get; set; } + + IEnumerable AllowedSections { get; } + } +} diff --git a/src/Umbraco.Core/Models/Membership/IUser.cs b/src/Umbraco.Core/Models/Membership/IUser.cs index 4f2224a072..af0f0b8da7 100644 --- a/src/Umbraco.Core/Models/Membership/IUser.cs +++ b/src/Umbraco.Core/Models/Membership/IUser.cs @@ -1,6 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.ComponentModel; using Umbraco.Core.Models.EntityBase; -using Umbraco.Core.Persistence.Mappers; namespace Umbraco.Core.Models.Membership { @@ -10,28 +11,38 @@ namespace Umbraco.Core.Models.Membership /// Will be left internal until a proper Membership implementation is part of the roadmap public interface IUser : IMembershipUser, IRememberBeingDirty, ICanBeDirty { + UserState UserState { get; } + string Name { get; set; } int SessionTimeout { get; set; } - int StartContentId { get; set; } - int StartMediaId { get; set; } + int[] StartContentIds { get; set; } + int[] StartMediaIds { get; set; } string Language { get; set; } - /// - /// Gets/sets the user type for the user - /// + [Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] IUserType UserType { get; set; } - //TODO: This should be a private set + DateTime? EmailConfirmedDate { get; set; } + DateTime? InvitedDate { get; set; } + /// - /// The default permission set for the user + /// Gets the groups that user is part of /// - /// - /// Currently in umbraco each permission is a single char but with an Enumerable{string} collection this allows for flexible changes to this in the future - /// - IEnumerable DefaultPermissions { get; set; } + IEnumerable Groups { get; } + + void RemoveGroup(string group); + void ClearGroups(); + void AddGroup(IReadOnlyUserGroup group); IEnumerable AllowedSections { get; } + + [Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] void RemoveAllowedSection(string sectionAlias); + + [Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] void AddAllowedSection(string sectionAlias); /// @@ -43,5 +54,10 @@ namespace Umbraco.Core.Models.Membership /// The security stamp used by ASP.Net identity /// string SecurityStamp { get; set; } + + /// + /// Will hold the media file system relative path of the users custom avatar if they uploaded one + /// + string Avatar { get; set; } } } diff --git a/src/Umbraco.Core/Models/Membership/IUserGroup.cs b/src/Umbraco.Core/Models/Membership/IUserGroup.cs new file mode 100644 index 0000000000..0551fcc8a8 --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/IUserGroup.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using Umbraco.Core.Models.EntityBase; + +namespace Umbraco.Core.Models.Membership +{ + public interface IUserGroup : IAggregateRoot + { + string Alias { get; set; } + + int? StartContentId { get; set; } + int? StartMediaId { get; set; } + + /// + /// The icon + /// + string Icon { get; set; } + + /// + /// The name + /// + string Name { get; set; } + + /// + /// The set of default permissions + /// + /// + /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future. + /// + IEnumerable Permissions { get; set; } + + IEnumerable AllowedSections { get; } + + void RemoveAllowedSection(string sectionAlias); + + void AddAllowedSection(string sectionAlias); + + void ClearAllowedSections(); + + /// + /// Specifies the number of users assigned to this group + /// + int UserCount { get; } + } +} diff --git a/src/Umbraco.Core/Models/Membership/IUserType.cs b/src/Umbraco.Core/Models/Membership/IUserType.cs index 92cce3ecd4..6d97a0b206 100644 --- a/src/Umbraco.Core/Models/Membership/IUserType.cs +++ b/src/Umbraco.Core/Models/Membership/IUserType.cs @@ -1,28 +1,17 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.ComponentModel; using Umbraco.Core.Models.EntityBase; -using Umbraco.Core.Persistence.Mappers; namespace Umbraco.Core.Models.Membership { - + [Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] public interface IUserType : IAggregateRoot { - /// - /// The user type alias - /// string Alias { get; set; } - - /// - /// The user type name - /// string Name { get; set; } - - /// - /// The set of default permissions for the user type - /// - /// - /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future. - /// IEnumerable Permissions { get; set; } + } } diff --git a/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs b/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs new file mode 100644 index 0000000000..2c93664ec6 --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/ReadOnlyUserGroup.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Umbraco.Core.Models.Membership +{ + public class ReadOnlyUserGroup : IReadOnlyUserGroup, IEquatable + { + public ReadOnlyUserGroup(int id, string name, string icon, int? startContentId, int? startMediaId, string @alias, + IEnumerable allowedSections, IEnumerable permissions) + { + Name = name; + Icon = icon; + Id = id; + Alias = alias; + AllowedSections = allowedSections.ToArray(); + Permissions = permissions.ToArray(); + + //Zero is invalid and will be treated as Null + StartContentId = startContentId == 0 ? null : startContentId; + StartMediaId = startMediaId == 0 ? null : startMediaId; + } + + public int Id { get; private set; } + public string Name { get; private set; } + public string Icon { get; private set; } + public int? StartContentId { get; private set; } + public int? StartMediaId { get; private set; } + public string Alias { get; private set; } + + /// + /// The set of default permissions + /// + /// + /// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future. + /// + public IEnumerable Permissions { get; set; } + public IEnumerable AllowedSections { get; private set; } + + public bool Equals(ReadOnlyUserGroup other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return string.Equals(Alias, other.Alias); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((ReadOnlyUserGroup) obj); + } + + public override int GetHashCode() + { + return Alias.GetHashCode(); + } + + public static bool operator ==(ReadOnlyUserGroup left, ReadOnlyUserGroup right) + { + return Equals(left, right); + } + + public static bool operator !=(ReadOnlyUserGroup left, ReadOnlyUserGroup right) + { + return !Equals(left, right); + } + } +} diff --git a/src/Umbraco.Core/Models/Membership/User.cs b/src/Umbraco.Core/Models/Membership/User.cs index 55ba3d6ddb..688b600041 100644 --- a/src/Umbraco.Core/Models/Membership/User.cs +++ b/src/Umbraco.Core/Models/Membership/User.cs @@ -2,13 +2,14 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; +using System.ComponentModel; using System.Linq; using System.Reflection; using System.Runtime.Serialization; using Umbraco.Core.Configuration; +using Umbraco.Core.Logging; using Umbraco.Core.Models.EntityBase; - namespace Umbraco.Core.Models.Membership { /// @@ -18,64 +19,107 @@ namespace Umbraco.Core.Models.Membership [DataContract(IsReference = true)] public class User : Entity, IUser { - public User(IUserType userType) + /// + /// Constructor for creating a new/empty user + /// + public User() { - if (userType == null) throw new ArgumentNullException("userType"); - - _userType = userType; - _defaultPermissions = _userType.Permissions == null ? Enumerable.Empty() : new List(_userType.Permissions); - //Groups = new List { userType }; SessionTimeout = 60; - _sectionCollection = new ObservableCollection(); - _addedSections = new List(); - _removedSections = new List(); + _userGroups = new HashSet(); _language = GlobalSettings.DefaultUILanguage; - _sectionCollection.CollectionChanged += SectionCollectionChanged; _isApproved = true; _isLockedOut = false; - _startContentId = -1; - _startMediaId = -1; + _startContentIds = new int[] { }; + _startMediaIds = new int[] { }; //cannot be null _rawPasswordValue = ""; } - public User(string name, string email, string username, string rawPasswordValue, IUserType userType) - : this(userType) + /// + /// Constructor for creating a new/empty user + /// + /// + /// + /// + /// + public User(string name, string email, string username, string rawPasswordValue) + : this() { + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name"); + if (string.IsNullOrWhiteSpace(email)) throw new ArgumentException("Value cannot be null or whitespace.", "email"); + if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", "username"); + if (string.IsNullOrEmpty(rawPasswordValue)) throw new ArgumentException("Value cannot be null or empty.", "rawPasswordValue"); + _name = name; _email = email; _username = username; _rawPasswordValue = rawPasswordValue; + _userGroups = new HashSet(); _isApproved = true; _isLockedOut = false; - _startContentId = -1; - _startMediaId = -1; + _startContentIds = new int[] { }; + _startMediaIds = new int[] { }; + + } + + /// + /// Constructor for creating a new User instance for an existing user + /// + /// + /// + /// + /// + /// + /// + /// + /// + public User(int id, string name, string email, string username, string rawPasswordValue, IEnumerable userGroups, int[] startContentIds, int[] startMediaIds) + : this() + { + //we allow whitespace for this value so just check null + if (rawPasswordValue == null) throw new ArgumentNullException("rawPasswordValue"); + if (userGroups == null) throw new ArgumentNullException("userGroups"); + if (startContentIds == null) throw new ArgumentNullException("startContentIds"); + if (startMediaIds == null) throw new ArgumentNullException("startMediaIds"); + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Value cannot be null or whitespace.", "name"); + if (string.IsNullOrWhiteSpace(username)) throw new ArgumentException("Value cannot be null or whitespace.", "username"); + + Id = id; + _name = name; + _email = email; + _username = username; + _rawPasswordValue = rawPasswordValue; + _userGroups = new HashSet(userGroups); + _isApproved = true; + _isLockedOut = false; + _startContentIds = startContentIds; + _startMediaIds = startMediaIds; } - private IUserType _userType; private string _name; private string _securityStamp; - private List _addedSections; - private List _removedSections; - private ObservableCollection _sectionCollection; + private string _avatar; private int _sessionTimeout; - private int _startContentId; - private int _startMediaId; + private int[] _startContentIds; + private int[] _startMediaIds; private int _failedLoginAttempts; private string _username; + private DateTime? _emailConfirmedDate; + private DateTime? _invitedDate; private string _email; private string _rawPasswordValue; + private IEnumerable _allowedSections; + private HashSet _userGroups; private bool _isApproved; private bool _isLockedOut; private string _language; private DateTime _lastPasswordChangedDate; private DateTime _lastLoginDate; private DateTime _lastLockoutDate; - - private IEnumerable _defaultPermissions; - private bool _defaultToLiveEditing; + private IDictionary _additionalData; + private object _additionalDataLock = new object(); private static readonly Lazy Ps = new Lazy(); @@ -87,10 +131,10 @@ namespace Umbraco.Core.Models.Membership public readonly PropertyInfo LastPasswordChangeDateSelector = ExpressionHelper.GetPropertyInfo(x => x.LastPasswordChangeDate); public readonly PropertyInfo SecurityStampSelector = ExpressionHelper.GetPropertyInfo(x => x.SecurityStamp); + public readonly PropertyInfo AvatarSelector = ExpressionHelper.GetPropertyInfo(x => x.Avatar); public readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo(x => x.SessionTimeout); - public readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.StartContentId); - public readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo(x => x.StartMediaId); - public readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo>(x => x.AllowedSections); + public readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo(x => x.StartContentIds); + public readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo(x => x.StartMediaIds); public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); public readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo(x => x.Username); @@ -99,9 +143,18 @@ namespace Umbraco.Core.Models.Membership public readonly PropertyInfo IsLockedOutSelector = ExpressionHelper.GetPropertyInfo(x => x.IsLockedOut); public readonly PropertyInfo IsApprovedSelector = ExpressionHelper.GetPropertyInfo(x => x.IsApproved); public readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo(x => x.Language); + public readonly PropertyInfo EmailConfirmedDateSelector = ExpressionHelper.GetPropertyInfo(x => x.EmailConfirmedDate); + public readonly PropertyInfo InvitedDateSelector = ExpressionHelper.GetPropertyInfo(x => x.InvitedDate); public readonly PropertyInfo DefaultToLiveEditingSelector = ExpressionHelper.GetPropertyInfo(x => x.DefaultToLiveEditing); - public readonly PropertyInfo UserTypeSelector = ExpressionHelper.GetPropertyInfo(x => x.UserType); + + public readonly PropertyInfo UserGroupsSelector = ExpressionHelper.GetPropertyInfo>(x => x.Groups); + + //Custom comparer for enumerable + public readonly DelegateEqualityComparer> IntegerEnumerableComparer = + new DelegateEqualityComparer>( + (enum1, enum2) => enum1.UnsortedSequenceEqual(enum2), + enum1 => enum1.GetHashCode()); } #region Implementation of IMembershipUser @@ -113,7 +166,18 @@ namespace Umbraco.Core.Models.Membership set { throw new NotSupportedException("Cannot set the provider user key for a user"); } } - + [DataMember] + public DateTime? EmailConfirmedDate + { + get { return _emailConfirmedDate; } + set { SetPropertyValueAndDetectChanges(value, ref _emailConfirmedDate, Ps.Value.EmailConfirmedDateSelector); } + } + [DataMember] + public DateTime? InvitedDate + { + get { return _invitedDate; } + set { SetPropertyValueAndDetectChanges(value, ref _invitedDate, Ps.Value.InvitedDateSelector); } + } [DataMember] public string Username { @@ -189,6 +253,22 @@ namespace Umbraco.Core.Models.Membership #region Implementation of IUser + public UserState UserState + { + get + { + if (LastLoginDate == default(DateTime) && IsApproved == false && InvitedDate != null) + return UserState.Invited; + + if (IsLockedOut) + return UserState.LockedOut; + if (IsApproved == false) + return UserState.Disabled; + + return UserState.Active; + } + } + [DataMember] public string Name { @@ -198,28 +278,171 @@ namespace Umbraco.Core.Models.Membership public IEnumerable AllowedSections { - get { return _sectionCollection; } + get { return _allowedSections ?? (_allowedSections = new List(_userGroups.SelectMany(x => x.AllowedSections).Distinct())); } } - public void RemoveAllowedSection(string sectionAlias) + [Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] + IUserType IUser.UserType { - if (_sectionCollection.Contains(sectionAlias)) + get { - _sectionCollection.Remove(sectionAlias); + //the best we can do here is to return the user's first user group as a IUserType object + //but we should attempt to return any group that is the built in ones first + var groups = Groups.ToArray(); + if (groups.Length == 0) + { + //In backwards compatibility land, a user type cannot be null! so we need to return a fake one. + return new UserType + { + Alias = "temp", + Id = int.MinValue, + Key = Guid.Empty, + CreateDate = default(DateTime), + DeletedDate = null, + Name = "Temp", + Permissions = new List(), + UpdateDate = default(DateTime) + }; + } + var builtIns = new[] { Constants.Security.AdminGroupAlias, "writer", "editor", "translator" }; + var foundBuiltIn = groups.FirstOrDefault(x => builtIns.Contains(x.Alias)); + IUserGroup realGroup; + if (foundBuiltIn != null) + { + //if the group isn't IUserGroup we'll need to look it up + realGroup = foundBuiltIn as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(foundBuiltIn.Id); + + //return a mapped version of the group + return new UserType + { + Alias = realGroup.Alias, + Id = realGroup.Id, + Key = realGroup.Key, + CreateDate = realGroup.CreateDate, + DeletedDate = realGroup.DeletedDate, + Name = realGroup.Name, + Permissions = realGroup.Permissions, + UpdateDate = realGroup.UpdateDate + }; + } + + //otherwise return the first + //if the group isn't IUserGroup we'll need to look it up + realGroup = groups[0] as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(groups[0].Id); + //return a mapped version of the group + return new UserType + { + Alias = realGroup.Alias, + Id = realGroup.Id, + Key = realGroup.Key, + CreateDate = realGroup.CreateDate, + DeletedDate = realGroup.DeletedDate, + Name = realGroup.Name, + Permissions = realGroup.Permissions, + UpdateDate = realGroup.UpdateDate + }; + } + set + { + //if old APIs are still using this lets first check if the user is part of the user group with the alias specified + if (Groups.Any(x => x.Alias == value.Alias)) + return; + + //the only other option we have here is to lookup the group (and we'll need to use singletons here :( ) + var found = ApplicationContext.Current.Services.UserService.GetUserGroupByAlias(value.Alias); + if (found == null) + throw new InvalidOperationException("No user group was found with the alias " + value.Alias + ", this API (IUser.UserType) is obsolete, use user groups instead"); + + //if it's found, all we can do is add it, we can't really replace them + AddGroup(found.ToReadOnlyGroup()); } } - public void AddAllowedSection(string sectionAlias) + [Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] + void IUser.RemoveAllowedSection(string sectionAlias) { - if (_sectionCollection.Contains(sectionAlias) == false) + //don't do anything if they aren't allowed it already + if (AllowedSections.Contains(sectionAlias) == false) + return; + + var groups = Groups.ToArray(); + //our only option here is to check if a custom group is created for this user, if so we can remove it from that group, otherwise we'll throw + //now we'll check if the user has a special 1:1 user group created for itself. This will occur if this method is used and also during an upgrade. + //this comes in the alias form of userName + 'Group' + var customUserGroup = groups.FirstOrDefault(x => x.Alias == (Username + "Group")); + if (customUserGroup != null) { - _sectionCollection.Add(sectionAlias); + //if the group isn't IUserGroup we'll need to look it up + var realGroup = customUserGroup as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(customUserGroup.Id); + realGroup.RemoveAllowedSection(sectionAlias); + //now we need to flag this for saving (hack!) + GroupsToSave.Add(realGroup); } + else + { + throw new InvalidOperationException("Cannot remove the allowed section using this obsolete API. Modify the user's groups instead"); + } + } + [Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] + void IUser.AddAllowedSection(string sectionAlias) + { + //don't do anything if they are allowed it already + if (AllowedSections.Contains(sectionAlias)) + return; + + //This is here for backwards compat only. + //First we'll check if the user is part of the 'admin' group. If so then we can ensure that the admin group has this section available to it. + //otherwise, the only thing we can do is create a custom user group for this user and add this section. + //We are checking for admin here because if the user is an admin and an allowed section is being added, then it's assumed it's to be added + //for the whole admin group (i.e. Forms installer does this for admins) + var groups = Groups.ToArray(); + var admin = groups.FirstOrDefault(x => x.Alias == Constants.Security.AdminGroupAlias); + if (admin != null) + { + //if the group isn't IUserGroup we'll need to look it up + var realGroup = admin as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(admin.Id); + realGroup.AddAllowedSection(sectionAlias); + //now we need to flag this for saving (hack!) + GroupsToSave.Add(realGroup); + } + + //now we'll check if the user has a special 1:1 user group created for itself. This will occur if this method is used and also during an upgrade. + //this comes in the alias form of userName + 'Group' + var customUserGroup = groups.FirstOrDefault(x => x.Alias == (Username + "Group")); + if (customUserGroup != null) + { + //if the group isn't IUserGroup we'll need to look it up + var realGroup = customUserGroup as IUserGroup ?? ApplicationContext.Current.Services.UserService.GetUserGroupById(customUserGroup.Id); + realGroup.AddAllowedSection(sectionAlias); + //now we need to flag this for saving (hack!) + GroupsToSave.Add(realGroup); + } + + //ok, so the user doesn't have a 1:1 group, we'll need to flag it for creation + var newUserGroup = new UserGroup + { + Alias = Username + "Group", + Name = "Group for " + Username + }; + newUserGroup.AddAllowedSection(sectionAlias); + GroupsToSave.Add(newUserGroup); + } + + /// + /// This used purely for hacking backwards compatibility into this class for < 7.7 compat + /// + [DoNotClone] + [IgnoreDataMember] + internal List GroupsToSave = new List(); + public IProfile ProfileData { - get { return new UserProfile(this); } + get { return new WrappedUserProfile(this); } } /// @@ -232,20 +455,11 @@ namespace Umbraco.Core.Models.Membership set { SetPropertyValueAndDetectChanges(value, ref _securityStamp, Ps.Value.SecurityStampSelector); } } - /// - /// Used internally to check if we need to add a section in the repository to the db - /// - internal IEnumerable AddedSections + [DataMember] + public string Avatar { - get { return _addedSections; } - } - - /// - /// Used internally to check if we need to remove a section in the repository to the db - /// - internal IEnumerable RemovedSections - { - get { return _removedSections; } + get { return _avatar; } + set { SetPropertyValueAndDetectChanges(value, ref _avatar, Ps.Value.AvatarSelector); } } /// @@ -268,10 +482,11 @@ namespace Umbraco.Core.Models.Membership /// The start content id. /// [DataMember] - public int StartContentId + [DoNotClone] + public int[] StartContentIds { - get { return _startContentId; } - set { SetPropertyValueAndDetectChanges(value, ref _startContentId, Ps.Value.StartContentIdSelector); } + get { return _startContentIds; } + set { SetPropertyValueAndDetectChanges(value, ref _startContentIds, Ps.Value.StartContentIdSelector, Ps.Value.IntegerEnumerableComparer); } } /// @@ -281,10 +496,11 @@ namespace Umbraco.Core.Models.Membership /// The start media id. /// [DataMember] - public int StartMediaId + [DoNotClone] + public int[] StartMediaIds { - get { return _startMediaId; } - set { SetPropertyValueAndDetectChanges(value, ref _startMediaId, Ps.Value.StartMediaIdSelector); } + get { return _startMediaIds; } + set { SetPropertyValueAndDetectChanges(value, ref _startMediaIds, Ps.Value.StartMediaIdSelector, Ps.Value.IntegerEnumerableComparer); } } [DataMember] @@ -294,14 +510,6 @@ namespace Umbraco.Core.Models.Membership set { SetPropertyValueAndDetectChanges(value, ref _language, Ps.Value.LanguageSelector); } } - //TODO: This should be a private set - [DataMember] - public IEnumerable DefaultPermissions - { - get { return _defaultPermissions;} - set { _defaultPermissions = value; } - } - [IgnoreDataMember] internal bool DefaultToLiveEditing { @@ -309,78 +517,107 @@ namespace Umbraco.Core.Models.Membership set { SetPropertyValueAndDetectChanges(value, ref _defaultToLiveEditing, Ps.Value.DefaultToLiveEditingSelector); } } - [IgnoreDataMember] - public IUserType UserType + /// + /// Gets the groups that user is part of + /// + [DataMember] + public IEnumerable Groups { - get { return _userType; } - set - { - if (value.HasIdentity == false) - { - throw new InvalidOperationException("Cannot assign a User Type that has not been persisted"); - } + get { return _userGroups; } + } - SetPropertyValueAndDetectChanges(value, ref _userType, Ps.Value.UserTypeSelector); + public void RemoveGroup(string group) + { + foreach (var userGroup in _userGroups.ToArray()) + { + if (userGroup.Alias == group) + { + _userGroups.Remove(userGroup); + //reset this flag so it's rebuilt with the assigned groups + _allowedSections = null; + OnPropertyChanged(Ps.Value.UserGroupsSelector); + } + } + } + + public void ClearGroups() + { + if (_userGroups.Count > 0) + { + _userGroups.Clear(); + //reset this flag so it's rebuilt with the assigned groups + _allowedSections = null; + OnPropertyChanged(Ps.Value.UserGroupsSelector); + } + } + + public void AddGroup(IReadOnlyUserGroup group) + { + if (_userGroups.Add(group)) + { + //reset this flag so it's rebuilt with the assigned groups + _allowedSections = null; + OnPropertyChanged(Ps.Value.UserGroupsSelector); } } #endregion /// - /// Whenever resetting occurs, clear the remembered add/removed collections, even if - /// rememberPreviouslyChangedProperties is true, the AllowedSections property will still - /// be flagged as dirty. + /// This is used as an internal cache for this entity - specifically for calculating start nodes so we don't re-calculated all of the time /// - /// - public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties) + [IgnoreDataMember] + [DoNotClone] + internal IDictionary AdditionalData { - _addedSections.Clear(); - _removedSections.Clear(); - base.ResetDirtyProperties(rememberPreviouslyChangedProperties); - } - - /// - /// Handles the collection changed event in order for us to flag the AllowedSections property as changed - /// - /// - /// - void SectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) - { - OnPropertyChanged(Ps.Value.AllowedSectionsSelector); - - if (e.Action == NotifyCollectionChangedAction.Add) + get { - var item = e.NewItems.Cast().First(); - - if (_addedSections.Contains(item) == false) + lock (_additionalDataLock) { - _addedSections.Add(item); + return _additionalData ?? (_additionalData = new Dictionary()); } } - else if (e.Action == NotifyCollectionChangedAction.Remove) - { - var item = e.OldItems.Cast().First(); - - if (_removedSections.Contains(item) == false) - { - _removedSections.Add(item); - } - - } } + [IgnoreDataMember] + [DoNotClone] + internal object AdditionalDataLock { get { return _additionalDataLock; } } + public override object DeepClone() { var clone = (User)base.DeepClone(); //turn off change tracking clone.DisableChangeTracking(); + //manually clone the start node props + clone._startContentIds = _startContentIds.ToArray(); + clone._startMediaIds = _startMediaIds.ToArray(); + + // this value has been cloned and points to the same object + // which obviously is bad - needs to point to a new object + clone._additionalDataLock = new object(); + + if (_additionalData != null) + { + // clone._additionalData points to the same dictionary, which is bad, because + // changing one clone impacts all of them - so we need to reset it with a fresh + // dictionary that will contain the same values - and, if some values are deep + // cloneable, they should be deep-cloned too + var cloneAdditionalData = clone._additionalData = new Dictionary(); + + lock (_additionalDataLock) + { + foreach (var kvp in _additionalData) + { + var deepCloneable = kvp.Value as IDeepCloneable; + cloneAdditionalData[kvp.Key] = deepCloneable == null ? kvp.Value : deepCloneable.DeepClone(); + } + } + } + //need to create new collections otherwise they'll get copied by ref - clone._addedSections = new List(); - clone._removedSections = new List(); - clone._sectionCollection = new ObservableCollection(_sectionCollection.ToList()); - clone._defaultPermissions = new List(_defaultPermissions.ToList()); + clone._userGroups = new HashSet(_userGroups); + clone._allowedSections = _allowedSections != null ? new List(_allowedSections) : null; //re-create the event handler - clone._sectionCollection.CollectionChanged += clone.SectionCollectionChanged; //this shouldn't really be needed since we're not tracking clone.ResetDirtyProperties(false); //re-enable tracking @@ -392,28 +629,26 @@ namespace Umbraco.Core.Models.Membership /// /// Internal class used to wrap the user in a profile /// - private class UserProfile : IProfile + private class WrappedUserProfile : IProfile { private readonly IUser _user; - public UserProfile(IUser user) + public WrappedUserProfile(IUser user) { _user = user; } - public object Id + public int Id { get { return _user.Id; } - set { _user.Id = (int)value; } } public string Name { get { return _user.Name; } - set { _user.Name = value; } } - protected bool Equals(UserProfile other) + private bool Equals(WrappedUserProfile other) { return _user.Equals(other._user); } @@ -423,7 +658,7 @@ namespace Umbraco.Core.Models.Membership if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != this.GetType()) return false; - return Equals((UserProfile) obj); + return Equals((WrappedUserProfile) obj); } public override int GetHashCode() diff --git a/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs b/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs new file mode 100644 index 0000000000..9df2e3c7df --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/UserGroupExtensions.cs @@ -0,0 +1,26 @@ +using Umbraco.Core.Models.Rdbms; +using System.Linq; + +namespace Umbraco.Core.Models.Membership +{ + internal static class UserGroupExtensions + { + public static IReadOnlyUserGroup ToReadOnlyGroup(this IUserGroup group) + { + //this will generally always be the case + var readonlyGroup = group as IReadOnlyUserGroup; + if (readonlyGroup != null) return readonlyGroup; + + //otherwise create one + return new ReadOnlyUserGroup(group.Id, group.Name, group.Icon, group.StartContentId, group.StartMediaId, group.Alias, group.AllowedSections, group.Permissions); + } + + public static IReadOnlyUserGroup ToReadOnlyGroup(this UserGroupDto group) + { + return new ReadOnlyUserGroup(group.Id, group.Name, group.Icon, + group.StartContentId, group.StartMediaId, group.Alias, + group.UserGroup2AppDtos.Select(x => x.AppAlias).ToArray(), + group.DefaultPermissions == null ? Enumerable.Empty() : group.DefaultPermissions.ToCharArray().Select(x => x.ToString())); + } + } +} diff --git a/src/Umbraco.Core/Models/Membership/UserProfile.cs b/src/Umbraco.Core/Models/Membership/UserProfile.cs new file mode 100644 index 0000000000..8d7ae5437b --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/UserProfile.cs @@ -0,0 +1,46 @@ +using System; + +namespace Umbraco.Core.Models.Membership +{ + internal class UserProfile : IProfile, IEquatable + { + public UserProfile(int id, string name) + { + Id = id; + Name = name; + } + + public int Id { get; private set; } + public string Name { get; private set; } + + public bool Equals(UserProfile other) + { + if (ReferenceEquals(null, other)) return false; + if (ReferenceEquals(this, other)) return true; + return Id == other.Id; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((UserProfile) obj); + } + + public override int GetHashCode() + { + return Id; + } + + public static bool operator ==(UserProfile left, UserProfile right) + { + return Equals(left, right); + } + + public static bool operator !=(UserProfile left, UserProfile right) + { + return Equals(left, right) == false; + } + } +} diff --git a/src/Umbraco.Core/Models/Membership/UserState.cs b/src/Umbraco.Core/Models/Membership/UserState.cs new file mode 100644 index 0000000000..0f8d0ec030 --- /dev/null +++ b/src/Umbraco.Core/Models/Membership/UserState.cs @@ -0,0 +1,14 @@ +namespace Umbraco.Core.Models.Membership +{ + /// + /// The state of a user + /// + public enum UserState + { + All = -1, + Active = 0, + Disabled = 1, + LockedOut = 2, + Invited = 3 + } +} diff --git a/src/Umbraco.Core/Models/Membership/UserType.cs b/src/Umbraco.Core/Models/Membership/UserType.cs index 29d6f3c8cc..1b8d71f4c0 100644 --- a/src/Umbraco.Core/Models/Membership/UserType.cs +++ b/src/Umbraco.Core/Models/Membership/UserType.cs @@ -1,17 +1,15 @@ using System; using System.Collections.Generic; -using System.Linq; +using System.ComponentModel; using System.Reflection; using System.Runtime.Serialization; using Umbraco.Core.Models.EntityBase; -using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Strings; namespace Umbraco.Core.Models.Membership { - /// - /// Represents the Type for a Backoffice User - /// + [Obsolete("This should not be used it exists for legacy reasons only, use user groups instead, it will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] [Serializable] [DataContract(IsReference = true)] internal class UserType : Entity, IUserType @@ -19,9 +17,7 @@ namespace Umbraco.Core.Models.Membership private string _alias; private string _name; private IEnumerable _permissions; - private static readonly Lazy Ps = new Lazy(); - private class PropertySelectors { public readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo(x => x.Name); diff --git a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs index 34b1c4ab05..6d6b10ae9f 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Syntax/Alter/IAlterSyntaxBuilder.cs @@ -7,7 +7,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Alter public interface IAlterSyntaxBuilder : IFluentSyntax { IAlterTableSyntax Table(string tableName); - + /// /// The problem with this is that only under particular circumstances is the expression added to the context /// so you wouldn't actually know if you are using it correctly or not and chances are you are not and therefore diff --git a/src/Umbraco.Core/Persistence/SqlSyntax/MicrosoftSqlSyntaxProviderBase.cs b/src/Umbraco.Core/Persistence/SqlSyntax/MicrosoftSqlSyntaxProviderBase.cs index c115cd4286..82cb999c37 100644 --- a/src/Umbraco.Core/Persistence/SqlSyntax/MicrosoftSqlSyntaxProviderBase.cs +++ b/src/Umbraco.Core/Persistence/SqlSyntax/MicrosoftSqlSyntaxProviderBase.cs @@ -2,7 +2,7 @@ using System.Data; using System.Linq; using Umbraco.Core.Persistence.Querying; - + namespace Umbraco.Core.Persistence.SqlSyntax { /// @@ -21,27 +21,27 @@ namespace Umbraco.Core.Persistence.SqlSyntax DecimalColumnDefinition = "DECIMAL(38,6)"; TimeColumnDefinition = "TIME"; //SQLSERVER 2008+ BlobColumnDefinition = "VARBINARY(MAX)"; - + InitColumnTypeMap(); } - + public override string RenameTable => "sp_rename '{0}', '{1}'"; - + public override string AddColumn => "ALTER TABLE {0} ADD {1}"; - + public override string GetQuotedTableName(string tableName) { if (tableName.Contains(".") == false) return $"[{tableName}]"; - + var tableNameParts = tableName.Split(new[] { '.' }, 2); return $"[{tableNameParts[0]}].[{tableNameParts[1]}]"; } - + public override string GetQuotedColumnName(string columnName) => $"[{columnName}]"; - + public override string GetQuotedName(string name) => $"[{name}]"; - + public override string GetStringColumnEqualComparison(string column, int paramIndex, TextColumnType columnType) { switch (columnType) @@ -55,7 +55,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax throw new ArgumentOutOfRangeException(nameof(columnType)); } } - + public override string GetStringColumnWildcardComparison(string column, int paramIndex, TextColumnType columnType) { switch (columnType) @@ -69,7 +69,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax throw new ArgumentOutOfRangeException(nameof(columnType)); } } - + [Obsolete("Use the overload with the parameter index instead")] public override string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType) { @@ -84,7 +84,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax throw new ArgumentOutOfRangeException(nameof(columnType)); } } - + [Obsolete("Use the overload with the parameter index instead")] public override string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType) { @@ -99,7 +99,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax throw new ArgumentOutOfRangeException(nameof(columnType)); } } - + [Obsolete("Use the overload with the parameter index instead")] public override string GetStringColumnContainsComparison(string column, string value, TextColumnType columnType) { @@ -114,7 +114,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax throw new ArgumentOutOfRangeException(nameof(columnType)); } } - + [Obsolete("Use the overload with the parameter index instead")] public override string GetStringColumnWildcardComparison(string column, string value, TextColumnType columnType) { @@ -129,7 +129,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax throw new ArgumentOutOfRangeException(nameof(columnType)); } } - + /// /// This uses a the DbTypeMap created and custom mapping to resolve the SqlDbType /// @@ -140,7 +140,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax var dbType = DbTypeMap.ColumnDbTypeMap.First(x => x.Key == clrType).Value; return GetSqlDbType(dbType); } - + /// /// Returns the mapped SqlDbType for the DbType specified /// diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs index 9a50493519..899a145862 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs @@ -51,8 +51,8 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters } // fall back on normal behaviour - return values.Any() == false - ? sourceString.Split(Environment.NewLine.ToCharArray()) + return values.Any() == false + ? sourceString.Split(Environment.NewLine.ToCharArray()) : values.ToArray(); } diff --git a/src/Umbraco.Core/Umbraco.Core.csproj b/src/Umbraco.Core/Umbraco.Core.csproj index b7b8318def..c9ea4a11b5 100644 --- a/src/Umbraco.Core/Umbraco.Core.csproj +++ b/src/Umbraco.Core/Umbraco.Core.csproj @@ -125,6 +125,7 @@ + @@ -204,6 +205,20 @@ + + + + + + + + + + + + + + diff --git a/src/Umbraco.Examine/LocalStorage/AzureLocalStorageDirectory.cs b/src/Umbraco.Examine/LocalStorage/AzureLocalStorageDirectory.cs index 1d750424b1..1cdc64f879 100644 --- a/src/Umbraco.Examine/LocalStorage/AzureLocalStorageDirectory.cs +++ b/src/Umbraco.Examine/LocalStorage/AzureLocalStorageDirectory.cs @@ -16,7 +16,7 @@ namespace Umbraco.Examine.LocalStorage { public DirectoryInfo GetLocalStorageDirectory(NameValueCollection config, string configuredPath) { - var appDomainHash = HttpRuntime.AppDomainAppId.ToMd5(); + var appDomainHash = HttpRuntime.AppDomainAppId.GenerateHash(); var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "LuceneDir", //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 diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs b/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs index 4e7889d319..fa2e5b1fbd 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs @@ -167,7 +167,7 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings { Assert.IsTrue(SettingsSection.Content.DisallowedUploadFiles.All(x => "ashx,aspx,ascx,config,cshtml,vbhtml,asmx,air,axd".Split(',').Contains(x))); } - + [Test] public void AllowedUploadFiles() { diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/UmbracoSettingsTests.cs b/src/Umbraco.Tests/Configurations/UmbracoSettings/UmbracoSettingsTests.cs index 4facaac2b3..426f9cc1a6 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/UmbracoSettingsTests.cs +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/UmbracoSettingsTests.cs @@ -18,7 +18,7 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = config.FullName }; var configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); - + Debug.WriteLine("Testing defaults? {0}", TestingDefaults); if (TestingDefaults) { diff --git a/src/Umbraco.Web.UI.Client/bower.json b/src/Umbraco.Web.UI.Client/bower.json index da9408026a..7c808a1f6d 100644 --- a/src/Umbraco.Web.UI.Client/bower.json +++ b/src/Umbraco.Web.UI.Client/bower.json @@ -1,5 +1,5 @@ { - "name": "Umbraco", + "name": "umbraco", "version": "7", "homepage": "https://github.com/umbraco/Umbraco-CMS", "authors": [ @@ -30,6 +30,7 @@ "codemirror": "~5.3.0", "angular-local-storage": "~0.2.3", "moment": "~2.10.3", - "ace-builds": "^1.2.3" + "ace-builds": "^1.2.3", + "clipboard": "1.7.1" } } diff --git a/src/Umbraco.Web.UI.Client/gruntFile.js b/src/Umbraco.Web.UI.Client/gruntFile.js index 6c785489c4..5170fddcba 100644 --- a/src/Umbraco.Web.UI.Client/gruntFile.js +++ b/src/Umbraco.Web.UI.Client/gruntFile.js @@ -197,7 +197,7 @@ module.exports = function (grunt) { src: ['src/installer/**/*.js'], dest: '<%= distdir %>/js/umbraco.installer.js', options: { - banner: "<%= banner %>\n(function() { \n\n angular.module('umbraco.install', []); \n", + banner: "<%= banner %>\n(function() { \n\n", footer: "\n\n})();" } }, @@ -382,6 +382,9 @@ module.exports = function (grunt) { html: { files: ['src/views/**/*.html', 'src/*.html'], tasks: ['watch-html', 'timestamp'] + }, + options: { + interval: 500 } }, @@ -553,6 +556,10 @@ module.exports = function (grunt) { 'src-min-noconflict/worker-javascript.js', ] + }, + 'clipboard': { + keepExpandedHierarchy: false, + files: ['dist/clipboard.min.js'] } } } diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/da.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/da.js new file mode 100644 index 0000000000..d295bf5750 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/da.js @@ -0,0 +1,219 @@ +tinymce.addI18n('da',{ +"Cut": "Klip", +"Heading 5": "Overskrift 5", +"Header 2": "Overskrift 2", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Din browser underst\u00f8tter ikke direkte adgang til clipboard. Benyt Ctrl+X\/C\/ keybord shortcuts i stedet for.", +"Heading 4": "Overskrift 4", +"Div": "Div", +"Heading 2": "Overskrift 2", +"Paste": "Inds\u00e6t", +"Close": "Luk", +"Font Family": "Skrifttype", +"Pre": "Pre", +"Align right": "H\u00f8jrejusteret", +"New document": "Nyt dokument", +"Blockquote": "Indrykning", +"Numbered list": "Nummerering", +"Heading 1": "Overskrift 1", +"Headings": "Overskrifter", +"Increase indent": "For\u00f8g indrykning", +"Formats": "Formater", +"Headers": "Overskrifter", +"Select all": "V\u00e6lg alle", +"Header 3": "Overskrift 3", +"Blocks": "Blokke", +"Undo": "Fortryd", +"Strikethrough": "Gennemstreg", +"Bullet list": "Punkt tegn", +"Header 1": "Overskrift 1", +"Superscript": "H\u00e6vet", +"Clear formatting": "Nulstil formattering", +"Font Sizes": "Skriftst\u00f8rrelse", +"Subscript": "S\u00e6nket", +"Header 6": "Overskrift 6", +"Redo": "Genopret", +"Paragraph": "S\u00e6tning", +"Ok": "Ok", +"Bold": "Fed", +"Code": "Code", +"Italic": "Kursiv", +"Align center": "Centreret", +"Header 5": "Overskrift 5", +"Heading 6": "Overskrift 6", +"Heading 3": "Overskrift 3", +"Decrease indent": "Formindsk indrykning", +"Header 4": "Overskrift 4", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "S\u00e6t ind er indstillet til at inds\u00e6tte som ren tekst. Indhold bliver nu indsat uden formatering indtil du \u00e6ndrer indstillingen.", +"Underline": "Understreg", +"Cancel": "Fortryd", +"Justify": "Justering", +"Inline": "Inline", +"Copy": "Kopier", +"Align left": "Venstrejusteret", +"Visual aids": "Visuel hj\u00e6lp", +"Lower Greek": "Lower Gr\u00e6sk", +"Square": "Kvadrat", +"Default": "Standard", +"Lower Alpha": "Lower Alpha", +"Circle": "Cirkel", +"Disc": "Disk", +"Upper Alpha": "Upper Alpha", +"Upper Roman": "Upper Roman", +"Lower Roman": "Lower Roman", +"Name": "Navn", +"Anchor": "Anchor", +"You have unsaved changes are you sure you want to navigate away?": "Du har ikke gemte \u00e6ndringer. Er du sikker p\u00e5 at du vil forts\u00e6tte?", +"Restore last draft": "Genopret sidste kladde", +"Special character": "Specielle tegn", +"Source code": "Kildekode", +"B": "B", +"R": "R", +"G": "G", +"Color": "Farve", +"Right to left": "H\u00f8jre til venstre", +"Left to right": "Venstre til h\u00f8jre", +"Emoticons": "Emot-ikoner", +"Robots": "Robotter", +"Document properties": "Dokument egenskaber", +"Title": "Titel", +"Keywords": "S\u00f8geord", +"Encoding": "Kodning", +"Description": "Beskrivelse", +"Author": "Forfatter", +"Fullscreen": "Fuldsk\u00e6rm", +"Horizontal line": "Vandret linie", +"Horizontal space": "Vandret afstand", +"Insert\/edit image": "Inds\u00e6t\/ret billede", +"General": "Generet", +"Advanced": "Avanceret", +"Source": "Kilde", +"Border": "Kant", +"Constrain proportions": "Behold propertioner", +"Vertical space": "Lodret afstand", +"Image description": "Billede beskrivelse", +"Style": "Stil", +"Dimensions": "Dimensioner", +"Insert image": "Inds\u00e6t billede", +"Zoom in": "Zoom ind", +"Contrast": "Kontrast", +"Back": "Tilbage", +"Gamma": "Gamma", +"Flip horizontally": "Flip horisontalt", +"Resize": "Skaler", +"Sharpen": "G\u00f8r skarpere", +"Zoom out": "Zoom ud", +"Image options": "Billede indstillinger", +"Apply": "Anvend", +"Brightness": "Lysstyrke", +"Rotate clockwise": "Drej med urets retning", +"Rotate counterclockwise": "Drej modsat urets retning", +"Edit image": "Rediger billede", +"Color levels": "Farve niveauer", +"Crop": "Besk\u00e6r", +"Orientation": "Retning", +"Flip vertically": "Flip vertikalt", +"Invert": "Inverter", +"Insert date\/time": "Inds\u00e6t dato\/klokkeslet", +"Remove link": "Fjern link", +"Url": "Url", +"Text to display": "Vis tekst", +"Anchors": "Ankre", +"Insert link": "Inds\u00e6t link", +"New window": "Nyt vindue", +"None": "Ingen", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "URLen som du angav ser ud til at v\u00e6re et eksternt link. \u00d8nsker du at tilf\u00f8je det kr\u00e6vede prefiks http:\/\/ ?", +"Target": "Target", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "URLen som du angav ser ud til at v\u00e6re en email adresse. \u00d8nsker du at tilf\u00f8je det kr\u00e6vede prefiks mailto: ?", +"Insert\/edit link": "Inds\u00e6t\/ret link", +"Insert\/edit video": "Inds\u00e6t\/ret video", +"Poster": "Poster", +"Alternative source": "Alternativ kilde", +"Paste your embed code below:": "Inds\u00e6t din embed kode herunder:", +"Insert video": "Inds\u00e6t video", +"Embed": "Integrer", +"Nonbreaking space": "H\u00e5rdt mellemrum", +"Page break": "Sideskift", +"Paste as text": "Inds\u00e6t som ren tekst", +"Preview": "Forh\u00e5ndsvisning", +"Print": "Udskriv", +"Save": "Gem", +"Could not find the specified string.": "Kunne ikke finde s\u00f8getekst", +"Replace": "Erstat", +"Next": "N\u00e6ste", +"Whole words": "Hele ord", +"Find and replace": "Find og erstat", +"Replace with": "Erstat med", +"Find": "Find", +"Replace all": "Erstat alt", +"Match case": "STORE og sm\u00e5 bogstaver", +"Prev": "Forrige", +"Spellcheck": "Stavekontrol", +"Finish": "F\u00e6rdig", +"Ignore all": "Ignorer alt", +"Ignore": "Ignorer", +"Add to Dictionary": "Tilf\u00f8j til ordbog", +"Insert row before": "Inds\u00e6t r\u00e6kke f\u00f8r", +"Rows": "R\u00e6kker", +"Height": "H\u00f8jde", +"Paste row after": "Inds\u00e6t r\u00e6kke efter", +"Alignment": "Tilpasning", +"Border color": "Kant farve", +"Column group": "Kolonne gruppe", +"Row": "R\u00e6kke", +"Insert column before": "Inds\u00e6t kolonne f\u00f8r", +"Split cell": "Split celle", +"Cell padding": "Celle padding", +"Cell spacing": "Celle afstand", +"Row type": "R\u00e6kke type", +"Insert table": "Inds\u00e6t tabel", +"Body": "Krop", +"Caption": "Tekst", +"Footer": "Sidefod", +"Delete row": "Slet r\u00e6kke", +"Paste row before": "Inds\u00e6t r\u00e6kke f\u00f8r", +"Scope": "Anvendelsesomr\u00e5de", +"Delete table": "Slet tabel", +"H Align": "H juster", +"Top": "Top", +"Header cell": "Sidehoved celle", +"Column": "Kolonne", +"Row group": "R\u00e6kke gruppe", +"Cell": "Celle", +"Middle": "Midt", +"Cell type": "Celle type", +"Copy row": "Kopier r\u00e6kke", +"Row properties": "R\u00e6kke egenskaber", +"Table properties": "Tabel egenskaber", +"Bottom": "Bund", +"V Align": "V juster", +"Header": "Sidehoved", +"Right": "H\u00f8jre", +"Insert column after": "Inds\u00e6t kolonne efter", +"Cols": "Kolonne", +"Insert row after": "Inds\u00e6t r\u00e6kke efter", +"Width": "Bredde", +"Cell properties": "Celle egenskaber", +"Left": "Venstre", +"Cut row": "Klip r\u00e6kke", +"Delete column": "Slet kolonne", +"Center": "Centrering", +"Merge cells": "Flet celler", +"Insert template": "Inds\u00e6t skabelon", +"Templates": "Skabeloner", +"Background color": "Baggrunds farve", +"Custom...": "Brugerdefineret...", +"Custom color": "Brugerdefineret farve", +"No color": "Ingen farve", +"Text color": "Tekst farve", +"Show blocks": "Vis klokke", +"Show invisible characters": "Vis usynlige tegn", +"Words: {0}": "Ord: {0}", +"Insert": "Inds\u00e6t", +"File": "Fil", +"Edit": "Rediger", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich Text omr\u00e5de. Tryk ALT-F9 for menu. Tryk ALT-F10 for toolbar. Tryk ALT-0 for hj\u00e6lp", +"Tools": "V\u00e6rkt\u00f8j", +"View": "Vis", +"Table": "Tabel", +"Format": "Format" +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/de.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/de.js new file mode 100644 index 0000000000..9a31056850 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/de.js @@ -0,0 +1,219 @@ +tinymce.addI18n('de',{ +"Cut": "Ausschneiden", +"Heading 5": "\u00dcberschrift 5", +"Header 2": "\u00dcberschrift 2", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Ihr Browser unterst\u00fctzt leider keinen direkten Zugriff auf die Zwischenablage. Bitte benutzen Sie die Strg + X \/ C \/ V Tastenkombinationen.", +"Heading 4": "\u00dcberschrift 4", +"Div": "Textblock", +"Heading 2": "\u00dcberschrift 2", +"Paste": "Einf\u00fcgen", +"Close": "Schlie\u00dfen", +"Font Family": "Schriftart", +"Pre": "Vorformatierter Text", +"Align right": "Rechtsb\u00fcndig ausrichten", +"New document": "Neues Dokument", +"Blockquote": "Zitat", +"Numbered list": "Nummerierte Liste", +"Heading 1": "\u00dcberschrift 1", +"Headings": "\u00dcberschriften", +"Increase indent": "Einzug vergr\u00f6\u00dfern", +"Formats": "Formate", +"Headers": "\u00dcberschriften", +"Select all": "Alles ausw\u00e4hlen", +"Header 3": "\u00dcberschrift 3", +"Blocks": "Absatzformate", +"Undo": "R\u00fcckg\u00e4ngig", +"Strikethrough": "Durchgestrichen", +"Bullet list": "Aufz\u00e4hlung", +"Header 1": "\u00dcberschrift 1", +"Superscript": "Hochgestellt", +"Clear formatting": "Formatierung entfernen", +"Font Sizes": "Schriftgr\u00f6\u00dfe", +"Subscript": "Tiefgestellt", +"Header 6": "\u00dcberschrift 6", +"Redo": "Wiederholen", +"Paragraph": "Absatz", +"Ok": "Ok", +"Bold": "Fett", +"Code": "Quelltext", +"Italic": "Kursiv", +"Align center": "Zentriert ausrichten", +"Header 5": "\u00dcberschrift 5", +"Heading 6": "\u00dcberschrift 6", +"Heading 3": "\u00dcberschrift 3", +"Decrease indent": "Einzug verkleinern", +"Header 4": "\u00dcberschrift 4", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Einf\u00fcgen ist nun im einfachen Textmodus. Inhalte werden ab jetzt als unformatierter Text eingef\u00fcgt, bis Sie diese Einstellung wieder ausschalten!", +"Underline": "Unterstrichen", +"Cancel": "Abbrechen", +"Justify": "Blocksatz", +"Inline": "Zeichenformate", +"Copy": "Kopieren", +"Align left": "Linksb\u00fcndig ausrichten", +"Visual aids": "Visuelle Hilfen", +"Lower Greek": "Griechische Kleinbuchstaben", +"Square": "Quadrat", +"Default": "Standard", +"Lower Alpha": "Kleinbuchstaben", +"Circle": "Kreis", +"Disc": "Punkt", +"Upper Alpha": "Gro\u00dfbuchstaben", +"Upper Roman": "R\u00f6mische Zahlen (Gro\u00dfbuchstaben)", +"Lower Roman": "R\u00f6mische Zahlen (Kleinbuchstaben)", +"Name": "Name", +"Anchor": "Textmarke", +"You have unsaved changes are you sure you want to navigate away?": "Die \u00c4nderungen wurden noch nicht gespeichert, sind Sie sicher, dass Sie diese Seite verlassen wollen?", +"Restore last draft": "Letzten Entwurf wiederherstellen", +"Special character": "Sonderzeichen", +"Source code": "Quelltext", +"B": "B", +"R": "R", +"G": "G", +"Color": "Farbe", +"Right to left": "Von rechts nach links", +"Left to right": "Von links nach rechts", +"Emoticons": "Emoticons", +"Robots": "Robots", +"Document properties": "Dokumenteigenschaften", +"Title": "Titel", +"Keywords": "Sch\u00fcsselw\u00f6rter", +"Encoding": "Zeichenkodierung", +"Description": "Beschreibung", +"Author": "Verfasser", +"Fullscreen": "Vollbild", +"Horizontal line": "Horizontale Linie", +"Horizontal space": "Horizontaler Abstand", +"Insert\/edit image": "Bild einf\u00fcgen\/bearbeiten", +"General": "Allgemein", +"Advanced": "Erweitert", +"Source": "Quelle", +"Border": "Rahmen", +"Constrain proportions": "Seitenverh\u00e4ltnis beibehalten", +"Vertical space": "Vertikaler Abstand", +"Image description": "Bildbeschreibung", +"Style": "Stil", +"Dimensions": "Abmessungen", +"Insert image": "Bild einf\u00fcgen", +"Zoom in": "Ansicht vergr\u00f6\u00dfern", +"Contrast": "Kontrast", +"Back": "Zur\u00fcck", +"Gamma": "Gamma", +"Flip horizontally": "Horizontal spiegeln", +"Resize": "Skalieren", +"Sharpen": "Sch\u00e4rfen", +"Zoom out": "Ansicht verkleinern", +"Image options": "Bildeigenschaften", +"Apply": "Anwenden", +"Brightness": "Helligkeit", +"Rotate clockwise": "Im Uhrzeigersinn drehen", +"Rotate counterclockwise": "Gegen den Uhrzeigersinn drehen", +"Edit image": "Bild bearbeiten", +"Color levels": "Farbwerte", +"Crop": "Bescheiden", +"Orientation": "Ausrichtung", +"Flip vertically": "Vertikal spiegeln", +"Invert": "Invertieren", +"Insert date\/time": "Datum\/Uhrzeit einf\u00fcgen ", +"Remove link": "Link entfernen", +"Url": "URL", +"Text to display": "Anzuzeigender Text", +"Anchors": "Textmarken", +"Insert link": "Link einf\u00fcgen", +"New window": "Neues Fenster", +"None": "Keine", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "Diese Adresse scheint ein externer Link zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"http:\/\/\" voranstellen?", +"Target": "Ziel", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "Diese Adresse scheint eine E-Mail-Adresse zu sein. M\u00f6chten Sie das dazu ben\u00f6tigte \"mailto:\" voranstellen?", +"Insert\/edit link": "Link einf\u00fcgen\/bearbeiten", +"Insert\/edit video": "Video einf\u00fcgen\/bearbeiten", +"Poster": "Poster", +"Alternative source": "Alternative Quelle", +"Paste your embed code below:": "F\u00fcgen Sie Ihren Einbettungscode hier ein:", +"Insert video": "Video einf\u00fcgen", +"Embed": "Einbetten", +"Nonbreaking space": "Gesch\u00fctztes Leerzeichen", +"Page break": "Seitenumbruch", +"Paste as text": "Als Text einf\u00fcgen", +"Preview": "Vorschau", +"Print": "Drucken", +"Save": "Speichern", +"Could not find the specified string.": "Die Zeichenfolge wurde nicht gefunden.", +"Replace": "Ersetzen", +"Next": "Weiter", +"Whole words": "Nur ganze W\u00f6rter", +"Find and replace": "Suchen und ersetzen", +"Replace with": "Ersetzen durch", +"Find": "Suchen", +"Replace all": "Alles ersetzen", +"Match case": "Gro\u00df-\/Kleinschreibung beachten", +"Prev": "Zur\u00fcck", +"Spellcheck": "Rechtschreibpr\u00fcfung", +"Finish": "Ende", +"Ignore all": "Alles Ignorieren", +"Ignore": "Ignorieren", +"Add to Dictionary": "Zum W\u00f6rterbuch hinzuf\u00fcgen", +"Insert row before": "Neue Zeile davor einf\u00fcgen ", +"Rows": "Zeilen", +"Height": "H\u00f6he", +"Paste row after": "Zeile danach einf\u00fcgen", +"Alignment": "Ausrichtung", +"Border color": "Rahmenfarbe", +"Column group": "Spaltengruppe", +"Row": "Zeile", +"Insert column before": "Neue Spalte davor einf\u00fcgen", +"Split cell": "Zelle aufteilen", +"Cell padding": "Zelleninnenabstand", +"Cell spacing": "Zellenabstand", +"Row type": "Zeilentyp", +"Insert table": "Tabelle einf\u00fcgen", +"Body": "Inhalt", +"Caption": "Beschriftung", +"Footer": "Fu\u00dfzeile", +"Delete row": "Zeile l\u00f6schen", +"Paste row before": "Zeile davor einf\u00fcgen", +"Scope": "G\u00fcltigkeitsbereich", +"Delete table": "Tabelle l\u00f6schen", +"H Align": "Horizontale Ausrichtung", +"Top": "Oben", +"Header cell": "Kopfzelle", +"Column": "Spalte", +"Row group": "Zeilengruppe", +"Cell": "Zelle", +"Middle": "Mitte", +"Cell type": "Zellentyp", +"Copy row": "Zeile kopieren", +"Row properties": "Zeileneigenschaften", +"Table properties": "Tabelleneigenschaften", +"Bottom": "Unten", +"V Align": "Vertikale Ausrichtung", +"Header": "Kopfzeile", +"Right": "Rechtsb\u00fcndig", +"Insert column after": "Neue Spalte danach einf\u00fcgen", +"Cols": "Spalten", +"Insert row after": "Neue Zeile danach einf\u00fcgen", +"Width": "Breite", +"Cell properties": "Zelleneigenschaften", +"Left": "Linksb\u00fcndig", +"Cut row": "Zeile ausschneiden", +"Delete column": "Spalte l\u00f6schen", +"Center": "Zentriert", +"Merge cells": "Zellen verbinden", +"Insert template": "Vorlage einf\u00fcgen ", +"Templates": "Vorlagen", +"Background color": "Hintergrundfarbe", +"Custom...": "Benutzerdefiniert...", +"Custom color": "Benutzerdefinierte Farbe", +"No color": "Keine Farbe", +"Text color": "Textfarbe", +"Show blocks": " Bl\u00f6cke anzeigen", +"Show invisible characters": "Unsichtbare Zeichen anzeigen", +"Words: {0}": "W\u00f6rter: {0}", +"Insert": "Einf\u00fcgen", +"File": "Datei", +"Edit": "Bearbeiten", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich-Text- Area. Dr\u00fccken Sie ALT-F9 f\u00fcr das Men\u00fc. Dr\u00fccken Sie ALT-F10 f\u00fcr Symbolleiste. Dr\u00fccken Sie ALT-0 f\u00fcr Hilfe", +"Tools": "Werkzeuge", +"View": "Ansicht", +"Table": "Tabelle", +"Format": "Format" +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/en.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/en.js new file mode 100644 index 0000000000..19324f74cd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/en.js @@ -0,0 +1 @@ +tinyMCE.addI18n({en:{common:{"more_colors":"More Colors...","invalid_data":"Error: Invalid values entered, these are marked in red.","popup_blocked":"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.","clipboard_no_support":"Currently not supported by your browser, use keyboard shortcuts instead.","clipboard_msg":"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?","not_set":"-- Not Set --","class_name":"Class",browse:"Browse",close:"Close",cancel:"Cancel",update:"Update",insert:"Insert",apply:"Apply","edit_confirm":"Do you want to use the WYSIWYG mode for this textarea?","invalid_data_number":"{#field} must be a number","invalid_data_min":"{#field} must be a number greater than {#min}","invalid_data_size":"{#field} must be a number or percentage",value:"(value)"},contextmenu:{full:"Full",right:"Right",center:"Center",left:"Left",align:"Alignment"},insertdatetime:{"day_short":"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun","day_long":"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday","months_short":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","months_long":"January,February,March,April,May,June,July,August,September,October,November,December","inserttime_desc":"Insert Time","insertdate_desc":"Insert Date","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d"},print:{"print_desc":"Print"},preview:{"preview_desc":"Preview"},directionality:{"rtl_desc":"Direction Right to Left","ltr_desc":"Direction Left to Right"},layer:{content:"New layer...","absolute_desc":"Toggle Absolute Positioning","backward_desc":"Move Backward","forward_desc":"Move Forward","insertlayer_desc":"Insert New Layer"},save:{"save_desc":"Save","cancel_desc":"Cancel All Changes"},nonbreaking:{"nonbreaking_desc":"Insert Non-Breaking Space Character"},iespell:{download:"ieSpell not detected. Do you want to install it now?","iespell_desc":"Check Spelling"},advhr:{"delta_height":"","delta_width":"","advhr_desc":"Insert Horizontal Line"},emotions:{"delta_height":"","delta_width":"","emotions_desc":"Emotions"},searchreplace:{"replace_desc":"Find/Replace","delta_width":"","delta_height":"","search_desc":"Find"},advimage:{"delta_width":"","image_desc":"Insert/Edit Image","delta_height":""},advlink:{"delta_height":"","delta_width":"","link_desc":"Insert/Edit Link"},xhtmlxtras:{"attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":"","attribs_desc":"Insert/Edit Attributes","ins_desc":"Insertion","del_desc":"Deletion","acronym_desc":"Acronym","abbr_desc":"Abbreviation","cite_desc":"Citation"},style:{"delta_height":"","delta_width":"",desc:"Edit CSS Style"},paste:{"plaintext_mode_stick":"Paste is now in plain text mode. Click again to toggle back to regular paste mode.","plaintext_mode":"Paste is now in plain text mode. Click again to toggle back to regular paste mode. After you paste something you will be returned to regular paste mode.","selectall_desc":"Select All","paste_word_desc":"Paste from Word","paste_text_desc":"Paste as Plain Text"},"paste_dlg":{"word_title":"Use Ctrl+V on your keyboard to paste the text into the window.","text_linebreaks":"Keep Linebreaks","text_title":"Use Ctrl+V on your keyboard to paste the text into the window."},table:{"merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":"",cell:"Cell",col:"Column",row:"Row",del:"Delete Table","copy_row_desc":"Copy Table Row","cut_row_desc":"Cut Table Row","paste_row_after_desc":"Paste Table Row After","paste_row_before_desc":"Paste Table Row Before","props_desc":"Table Properties","cell_desc":"Table Cell Properties","row_desc":"Table Row Properties","merge_cells_desc":"Merge Table Cells","split_cells_desc":"Split Merged Table Cells","delete_col_desc":"Delete Column","col_after_desc":"Insert Column After","col_before_desc":"Insert Column Before","delete_row_desc":"Delete Row","row_after_desc":"Insert Row After","row_before_desc":"Insert Row Before",desc:"Insert/Edit Table"},autosave:{"warning_message":"If you restore the saved content, you will lose all the content that is currently in the editor.\n\nAre you sure you want to restore the saved content?","restore_content":"Restore auto-saved content.","unload_msg":"The changes you made will be lost if you navigate away from this page."},fullscreen:{desc:"Toggle Full Screen Mode"},media:{"delta_height":"","delta_width":"",edit:"Edit Embedded Media",desc:"Insert/Edit Embedded Media"},fullpage:{desc:"Document Properties","delta_width":"","delta_height":""},template:{desc:"Insert Predefined Template Content"},visualchars:{desc:"Show/Hide Visual Control Characters"},spellchecker:{desc:"Toggle Spell Checker",menu:"Spell Checker Settings","ignore_word":"Ignore Word","ignore_words":"Ignore All",langs:"Languages",wait:"Please wait...",sug:"Suggestions","no_sug":"No Suggestions","no_mpell":"No misspellings found.","learn_word":"Learn word"},pagebreak:{desc:"Insert Page Break for Printing"},advlist:{types:"Types",def:"Default","lower_alpha":"Lower Alpha","lower_greek":"Lower Greek","lower_roman":"Lower Roman","upper_alpha":"Upper Alpha","upper_roman":"Upper Roman",circle:"Circle",disc:"Disc",square:"Square"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Rich Text Area"},wordcount:{words:"Words:"},visualblocks:{desc:'Show/hide block elements'}}}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/en_us.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/en_us.js new file mode 100644 index 0000000000..4e94198e5a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/en_us.js @@ -0,0 +1 @@ +tinyMCE.addI18n({en_us:{common:{"more_colors":"More Colors...","invalid_data":"Error: Invalid values entered, these are marked in red.","popup_blocked":"Sorry, but we have noticed that your popup-blocker has disabled a window that provides application functionality. You will need to disable popup blocking on this site in order to fully utilize this tool.","clipboard_no_support":"Currently not supported by your browser, use keyboard shortcuts instead.","clipboard_msg":"Copy/Cut/Paste is not available in Mozilla and Firefox.\nDo you want more information about this issue?","not_set":"-- Not Set --","class_name":"Class",browse:"Browse",close:"Close",cancel:"Cancel",update:"Update",insert:"Insert",apply:"Apply","edit_confirm":"Do you want to use the WYSIWYG mode for this textarea?","invalid_data_number":"{#field} must be a number","invalid_data_min":"{#field} must be a number greater than {#min}","invalid_data_size":"{#field} must be a number or percentage",value:"(value)"},contextmenu:{full:"Full",right:"Right",center:"Center",left:"Left",align:"Alignment"},insertdatetime:{"day_short":"Sun,Mon,Tue,Wed,Thu,Fri,Sat,Sun","day_long":"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday","months_short":"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec","months_long":"January,February,March,April,May,June,July,August,September,October,November,December","inserttime_desc":"Insert Time","insertdate_desc":"Insert Date","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d"},print:{"print_desc":"Print"},preview:{"preview_desc":"Preview"},directionality:{"rtl_desc":"Direction Right to Left","ltr_desc":"Direction Left to Right"},layer:{content:"New layer...","absolute_desc":"Toggle Absolute Positioning","backward_desc":"Move Backward","forward_desc":"Move Forward","insertlayer_desc":"Insert New Layer"},save:{"save_desc":"Save","cancel_desc":"Cancel All Changes"},nonbreaking:{"nonbreaking_desc":"Insert Non-Breaking Space Character"},iespell:{download:"ieSpell not detected. Do you want to install it now?","iespell_desc":"Check Spelling"},advhr:{"delta_height":"","delta_width":"","advhr_desc":"Insert Horizontal Line"},emotions:{"delta_height":"","delta_width":"","emotions_desc":"Emotions"},searchreplace:{"replace_desc":"Find/Replace","delta_width":"","delta_height":"","search_desc":"Find"},advimage:{"delta_width":"","image_desc":"Insert/Edit Image","delta_height":""},advlink:{"delta_height":"","delta_width":"","link_desc":"Insert/Edit Link"},xhtmlxtras:{"attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":"","attribs_desc":"Insert/Edit Attributes","ins_desc":"Insertion","del_desc":"Deletion","acronym_desc":"Acronym","abbr_desc":"Abbreviation","cite_desc":"Citation"},style:{"delta_height":"","delta_width":"",desc:"Edit CSS Style"},paste:{"plaintext_mode_stick":"Paste is now in plain text mode. Click again to toggle back to regular paste mode.","plaintext_mode":"Paste is now in plain text mode. Click again to toggle back to regular paste mode. After you paste something you will be returned to regular paste mode.","selectall_desc":"Select All","paste_word_desc":"Paste from Word","paste_text_desc":"Paste as Plain Text"},"paste_dlg":{"word_title":"Use Ctrl+V on your keyboard to paste the text into the window.","text_linebreaks":"Keep Linebreaks","text_title":"Use Ctrl+V on your keyboard to paste the text into the window."},table:{"merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":"",cell:"Cell",col:"Column",row:"Row",del:"Delete Table","copy_row_desc":"Copy Table Row","cut_row_desc":"Cut Table Row","paste_row_after_desc":"Paste Table Row After","paste_row_before_desc":"Paste Table Row Before","props_desc":"Table Properties","cell_desc":"Table Cell Properties","row_desc":"Table Row Properties","merge_cells_desc":"Merge Table Cells","split_cells_desc":"Split Merged Table Cells","delete_col_desc":"Delete Column","col_after_desc":"Insert Column After","col_before_desc":"Insert Column Before","delete_row_desc":"Delete Row","row_after_desc":"Insert Row After","row_before_desc":"Insert Row Before",desc:"Insert/Edit Table"},autosave:{"warning_message":"If you restore the saved content, you will lose all the content that is currently in the editor.\n\nAre you sure you want to restore the saved content?","restore_content":"Restore auto-saved content.","unload_msg":"The changes you made will be lost if you navigate away from this page."},fullscreen:{desc:"Toggle Full Screen Mode"},media:{"delta_height":"","delta_width":"",edit:"Edit Embedded Media",desc:"Insert/Edit Embedded Media"},fullpage:{desc:"Document Properties","delta_width":"","delta_height":""},template:{desc:"Insert Predefined Template Content"},visualchars:{desc:"Show/Hide Visual Control Characters"},spellchecker:{desc:"Toggle Spell Checker",menu:"Spell Checker Settings","ignore_word":"Ignore Word","ignore_words":"Ignore All",langs:"Languages",wait:"Please wait...",sug:"Suggestions","no_sug":"No Suggestions","no_mpell":"No misspellings found.","learn_word":"Learn word"},pagebreak:{desc:"Insert Page Break for Printing"},advlist:{types:"Types",def:"Default","lower_alpha":"Lower Alpha","lower_greek":"Lower Greek","lower_roman":"Lower Roman","upper_alpha":"Upper Alpha","upper_roman":"Upper Roman",circle:"Circle",disc:"Disc",square:"Square"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"Rich Text Area"},wordcount:{words:"Words:"},visualblocks:{desc:'Show/hide block elements'}}}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/fi.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/fi.js new file mode 100644 index 0000000000..87677bd3ff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/fi.js @@ -0,0 +1,219 @@ +tinymce.addI18n('fi',{ +"Cut": "Leikkaa", +"Heading 5": "Otsikko 5", +"Header 2": "Otsikko 2", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Selaimesi ei tue leikep\u00f6yd\u00e4n suoraa k\u00e4ytt\u00e4mist\u00e4. Ole hyv\u00e4 ja k\u00e4yt\u00e4 n\u00e4pp\u00e4imist\u00f6n Ctrl+X\/C\/V n\u00e4pp\u00e4inyhdistelmi\u00e4.", +"Heading 4": "Otsikko 4", +"Div": "Div", +"Heading 2": "Otsikko 2", +"Paste": "Liit\u00e4", +"Close": "Sulje", +"Font Family": "Fontti", +"Pre": "Esimuotoiltu", +"Align right": "Tasaa oikealle", +"New document": "Uusi dokumentti", +"Blockquote": "Lainauslohko", +"Numbered list": "J\u00e4rjestetty lista", +"Heading 1": "Otsikko 1", +"Headings": "Otsikot", +"Increase indent": "Loitonna", +"Formats": "Muotoilut", +"Headers": "Otsikot", +"Select all": "Valitse kaikki", +"Header 3": "Otsikko 3", +"Blocks": "Lohkot", +"Undo": "Peru", +"Strikethrough": "Yliviivaus", +"Bullet list": "J\u00e4rjest\u00e4m\u00e4t\u00f6n lista", +"Header 1": "Otsikko 1", +"Superscript": "Yl\u00e4indeksi", +"Clear formatting": "Poista muotoilu", +"Font Sizes": "Fonttikoko", +"Subscript": "Alaindeksi", +"Header 6": "Otsikko 6", +"Redo": "Tee uudelleen", +"Paragraph": "Kappale", +"Ok": "Ok", +"Bold": "Lihavointi", +"Code": "Koodi", +"Italic": "Kursivointi", +"Align center": "Keskit\u00e4", +"Header 5": "Otsikko 5", +"Heading 6": "Otsikko 6", +"Heading 3": "Otsikko 3", +"Decrease indent": "Sisenn\u00e4", +"Header 4": "Otsikko 4", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Liitt\u00e4minen on nyt pelk\u00e4n tekstin -tilassa. Sis\u00e4ll\u00f6t liitet\u00e4\u00e4n nyt pelkk\u00e4n\u00e4 tekstin\u00e4, kunnes otat vaihtoehdon pois k\u00e4yt\u00f6st\u00e4.", +"Underline": "Alleviivaus", +"Cancel": "Peruuta", +"Justify": "Tasaa", +"Inline": "Samalla rivill\u00e4", +"Copy": "Kopioi", +"Align left": "Tasaa vasemmalle", +"Visual aids": "Visuaaliset neuvot", +"Lower Greek": "pienet kirjaimet: \u03b1, \u03b2, \u03b3", +"Square": "Neli\u00f6", +"Default": "Oletus", +"Lower Alpha": "pienet kirjaimet: a, b, c", +"Circle": "Pallo", +"Disc": "Ympyr\u00e4", +"Upper Alpha": "isot kirjaimet: A, B, C", +"Upper Roman": "isot kirjaimet: I, II, III", +"Lower Roman": "pienet kirjaimet: i, ii, iii", +"Name": "Nimi", +"Anchor": "Ankkuri", +"You have unsaved changes are you sure you want to navigate away?": "Sinulla on tallentamattomia muutoksia, haluatko varmasti siirty\u00e4 toiselle sivulle?", +"Restore last draft": "Palauta aiempi luonnos", +"Special character": "Erikoismerkki", +"Source code": "L\u00e4hdekoodi", +"B": "B", +"R": "R", +"G": "G", +"Color": "V\u00e4ri", +"Right to left": "Oikealta vasemmalle", +"Left to right": "Vasemmalta oikealle", +"Emoticons": "Hymi\u00f6t", +"Robots": "Robotit", +"Document properties": "Dokumentin ominaisuudet", +"Title": "Otsikko", +"Keywords": "Avainsanat", +"Encoding": "Merkist\u00f6", +"Description": "Kuvaus", +"Author": "Tekij\u00e4", +"Fullscreen": "Koko ruutu", +"Horizontal line": "Vaakasuora viiva", +"Horizontal space": "Horisontaalinen tila", +"Insert\/edit image": "Lis\u00e4\u00e4\/muokkaa kuva", +"General": "Yleiset", +"Advanced": "Lis\u00e4asetukset", +"Source": "L\u00e4hde", +"Border": "Reunus", +"Constrain proportions": "S\u00e4ilyt\u00e4 mittasuhteet", +"Vertical space": "Vertikaalinen tila", +"Image description": "Kuvaus", +"Style": "Tyyli", +"Dimensions": "Mittasuhteet", +"Insert image": "Lis\u00e4\u00e4 kuva", +"Zoom in": "L\u00e4henn\u00e4", +"Contrast": "Kontrasti", +"Back": "Takaisin", +"Gamma": "Gamma", +"Flip horizontally": "K\u00e4\u00e4nn\u00e4 vaakasuunnassa", +"Resize": "Kuvan koon muutos", +"Sharpen": "Ter\u00e4vyys", +"Zoom out": "Loitonna", +"Image options": "Kuvan asetukset", +"Apply": "Aseta", +"Brightness": "Kirkkaus", +"Rotate clockwise": "Kierr\u00e4 my\u00f6t\u00e4p\u00e4iv\u00e4\u00e4n", +"Rotate counterclockwise": "Kierr\u00e4 vastap\u00e4iv\u00e4\u00e4n", +"Edit image": "Muokkaa kuvaa", +"Color levels": "V\u00e4ritasot", +"Crop": "Rajaa valintaan", +"Orientation": "Suunta", +"Flip vertically": "K\u00e4\u00e4nn\u00e4 pystysuunnassa", +"Invert": "K\u00e4\u00e4nteinen", +"Insert date\/time": "Lis\u00e4\u00e4 p\u00e4iv\u00e4m\u00e4\u00e4r\u00e4 tai aika", +"Remove link": "Poista linkki", +"Url": "Osoite", +"Text to display": "N\u00e4ytett\u00e4v\u00e4 teksti", +"Anchors": "Ankkurit", +"Insert link": "Lis\u00e4\u00e4 linkki", +"New window": "Uusi ikkuna", +"None": "Ei mit\u00e4\u00e4n", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "Antamasi osoite n\u00e4ytt\u00e4\u00e4 olevan ulkoinen linkki. Haluatko lis\u00e4t\u00e4 osoitteeseen vaaditun http:\/\/ -etuliitteen?", +"Target": "Kohde", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "Antamasi osoite n\u00e4ytt\u00e4\u00e4 olevan s\u00e4hk\u00f6postiosoite. Haluatko lis\u00e4t\u00e4 osoitteeseen vaaditun mailto: -etuliitteen?", +"Insert\/edit link": "Lis\u00e4\u00e4\/muokkaa linkki", +"Insert\/edit video": "Lis\u00e4\u00e4\/muokkaa video", +"Poster": "L\u00e4hett\u00e4j\u00e4", +"Alternative source": "Vaihtoehtoinen l\u00e4hde", +"Paste your embed code below:": "Liit\u00e4 upotuskoodisi alapuolelle:", +"Insert video": "Lis\u00e4\u00e4 video", +"Embed": "Upota", +"Nonbreaking space": "Sitova v\u00e4lily\u00f6nti", +"Page break": "Sivunvaihto", +"Paste as text": "Liit\u00e4 tekstin\u00e4", +"Preview": "Esikatselu", +"Print": "Tulosta", +"Save": "Tallenna", +"Could not find the specified string.": "Haettua merkkijonoa ei l\u00f6ytynyt.", +"Replace": "Korvaa", +"Next": "Seur.", +"Whole words": "Koko sanat", +"Find and replace": "Etsi ja korvaa", +"Replace with": "Korvaa", +"Find": "Etsi", +"Replace all": "Korvaa kaikki", +"Match case": "Erota isot ja pienet kirjaimet", +"Prev": "Edel.", +"Spellcheck": "Oikolue", +"Finish": "Lopeta", +"Ignore all": "\u00c4l\u00e4 huomioi mit\u00e4\u00e4n", +"Ignore": "\u00c4l\u00e4 huomioi", +"Add to Dictionary": "Lis\u00e4\u00e4 sanakirjaan", +"Insert row before": "Lis\u00e4\u00e4 rivi ennen", +"Rows": "Rivit", +"Height": "Korkeus", +"Paste row after": "Liit\u00e4 rivi j\u00e4lkeen", +"Alignment": "Tasaus", +"Border color": "Reunuksen v\u00e4ri", +"Column group": "Sarakeryhm\u00e4", +"Row": "Rivi", +"Insert column before": "Lis\u00e4\u00e4 rivi ennen", +"Split cell": "Jaa solu", +"Cell padding": "Solun tyhj\u00e4 tila", +"Cell spacing": "Solun v\u00e4li", +"Row type": "Rivityyppi", +"Insert table": "Lis\u00e4\u00e4 taulukko", +"Body": "Runko", +"Caption": "Seloste", +"Footer": "Alaosa", +"Delete row": "Poista rivi", +"Paste row before": "Liit\u00e4 rivi ennen", +"Scope": "Laajuus", +"Delete table": "Poista taulukko", +"H Align": "H tasaus", +"Top": "Yl\u00e4reuna", +"Header cell": "Otsikkosolu", +"Column": "Sarake", +"Row group": "Riviryhm\u00e4", +"Cell": "Solu", +"Middle": "Keskikohta", +"Cell type": "Solun tyyppi", +"Copy row": "Kopioi rivi", +"Row properties": "Rivin ominaisuudet", +"Table properties": "Taulukon ominaisuudet", +"Bottom": "Alareuna", +"V Align": "V tasaus", +"Header": "Otsikko", +"Right": "Oikea", +"Insert column after": "Lis\u00e4\u00e4 rivi j\u00e4lkeen", +"Cols": "Sarakkeet", +"Insert row after": "Lis\u00e4\u00e4 rivi j\u00e4lkeen", +"Width": "Leveys", +"Cell properties": "Solun ominaisuudet", +"Left": "Vasen", +"Cut row": "Leikkaa rivi", +"Delete column": "Poista sarake", +"Center": "Keskell\u00e4", +"Merge cells": "Yhdist\u00e4 solut", +"Insert template": "Lis\u00e4\u00e4 pohja", +"Templates": "Pohjat", +"Background color": "Taustan v\u00e4ri", +"Custom...": "Mukauta...", +"Custom color": "Mukautettu v\u00e4ri", +"No color": "Ei v\u00e4ri\u00e4", +"Text color": "Tekstin v\u00e4ri", +"Show blocks": "N\u00e4yt\u00e4 lohkot", +"Show invisible characters": "N\u00e4yt\u00e4 n\u00e4kym\u00e4tt\u00f6m\u00e4t merkit", +"Words: {0}": "Sanat: {0}", +"Insert": "Lis\u00e4\u00e4", +"File": "Tiedosto", +"Edit": "Muokkaa", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rikastetun tekstin alue. Paina ALT-F9 valikkoon. Paina ALT-F10 ty\u00f6kaluriviin. Paina ALT-0 ohjeeseen.", +"Tools": "Ty\u00f6kalut", +"View": "N\u00e4yt\u00e4", +"Table": "Taulukko", +"Format": "Muotoilu" +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/fr.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/fr.js new file mode 100644 index 0000000000..b9cfd8b515 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/fr.js @@ -0,0 +1 @@ +tinyMCE.addI18n({fr:{common:{"more_colors":"Plus de couleurs","invalid_data":"Erreur : saisie de valeurs incorrectes. Elles sont mises en \u00e9vidence en rouge.","popup_blocked":"D\u00e9sol\u00e9, nous avons d\u00e9tect\u00e9 que votre bloqueur de popup a bloqu\u00e9 une fen\u00eatre dont l\'application a besoin. Vous devez d\u00e9sactiver votre bloqueur de popup pour pouvoir utiliser cet outil.","clipboard_no_support":"Actuellement non support\u00e9 par votre navigateur.\n Veuillez utiliser les raccourcis clavier \u00e0 la place.","clipboard_msg":"Les fonctions Copier/Couper/Coller ne sont pas valables sur Mozilla et Firefox.\nSouhaitez-vous avoir plus d\'informations sur ce sujet ?","not_set":"-- non d\u00e9fini --","class_name":"Classe",browse:"parcourir",close:"Fermer",cancel:"Annuler",update:"Mettre \u00e0 jour",insert:"Ins\u00e9rer",apply:"Appliquer","edit_confirm":"Souhaitez-vous utiliser le mode WYSIWYG pour cette zone de texte ?","invalid_data_number":"{#field} doit \u00eatre un nombre","invalid_data_min":"{#field} doit \u00eatre un nombre plus grand que {#min}","invalid_data_size":"{#field} doit \u00eatre un nombre ou un pourcentage",value:"(valeur)"},contextmenu:{full:"Justifi\u00e9",right:"Droite",center:"Centr\u00e9",left:"Gauche",align:"Alignement"},insertdatetime:{"day_short":"Dim,Lun,Mar,Mer,Jeu,Ven,Sam,Dim","day_long":"Dimanche,Lundi,Mardi,Mercredi,Jeudi,Vendredi,Samedi,Dimanche","months_short":"Jan,F\u00e9v,Mar,Avr,Mai,Juin,Juil,Ao\u00fbt,Sep,Oct,Nov,D\u00e9c","months_long":"Janvier,F\u00e9vrier,Mars,Avril,Mai,Juin,Juillet,Ao\u00fbt,Septembre,Octobre,Novembre,D\u00e9cembre","inserttime_desc":"Ins\u00e9rer l\'heure","insertdate_desc":"Ins\u00e9rer la date","time_fmt":"%H:%M:%S","date_fmt":"%d-%m-%Y"},print:{"print_desc":"Imprimer"},preview:{"preview_desc":"Pr\u00e9visualiser"},directionality:{"rtl_desc":"\u00c9criture de droite \u00e0 gauche","ltr_desc":"\u00c9criture de gauche \u00e0 droite"},layer:{content:"Nouvelle couche\u2026","absolute_desc":"Activer le positionnement absolu","backward_desc":"D\u00e9placer vers l\'arri\u00e8re","forward_desc":"D\u00e9placer vers l\'avant","insertlayer_desc":"Ins\u00e9rer une nouvelle couche"},save:{"save_desc":"Enregistrer","cancel_desc":"Annuler toutes les modifications"},nonbreaking:{"nonbreaking_desc":"Ins\u00e9rer une espace ins\u00e9cable"},iespell:{download:"ieSpell n\'est pas install\u00e9. Souhaitez-vous l\'installer maintenant ?","iespell_desc":"Lancer le v\u00e9rificateur d\'orthographe"},advhr:{"delta_height":"Ecart de hauteur","delta_width":"Ecart de largeur","advhr_desc":"Ins\u00e9rer un trait horizontal"},emotions:{"delta_height":"delta_height","delta_width":"delta_width","emotions_desc":"\u00c9motic\u00f4nes"},searchreplace:{"replace_desc":"Rechercher / remplacer","search_desc":"Rechercher","delta_width":"","delta_height":""},advimage:{"image_desc":"Ins\u00e9rer / \u00e9diter une image","delta_width":"","delta_height":""},advlink:{"link_desc":"Ins\u00e9rer / \u00e9diter un lien","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"Ins\u00e9rer / \u00e9diter les attributs","ins_desc":"Ins\u00e9r\u00e9","del_desc":"Barr\u00e9","acronym_desc":"Acronyme","abbr_desc":"Abr\u00e9viation","cite_desc":"Citation","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"\u00c9diter la feuille de style (CSS)","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Le collage est actuellement en mode texte non format\u00e9. Cliquez \u00e0 nouveau pour revenir en mode de collage ordinaire.","plaintext_mode_sticky":"Le collage est actuellement en mode texte non format\u00e9. Cliquez \u00e0 nouveau pour revenir en mode de collage ordinaire. Apr\u00e8s avoir coll\u00e9 quelque chose, vous retournerez en mode de collage ordinaire.","selectall_desc":"Tout s\u00e9lectionner","paste_word_desc":"Coller un texte cr\u00e9\u00e9 sous Word","paste_text_desc":"Coller comme texte brut"},"paste_dlg":{"word_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre.","text_linebreaks":"Conserver les retours \u00e0 la ligne","text_title":"Utilisez CTRL+V sur votre clavier pour coller le texte dans la fen\u00eatre."},table:{cell:"Cellule",col:"Colonne",row:"Ligne",del:"Effacer le tableau","copy_row_desc":"Copier la ligne","cut_row_desc":"Couper la ligne","paste_row_after_desc":"Coller la ligne apr\u00e8s","paste_row_before_desc":"Coller la ligne avant","props_desc":"Propri\u00e9t\u00e9s du tableau","cell_desc":"Propri\u00e9t\u00e9s de la cellule","row_desc":"Propri\u00e9t\u00e9s de la ligne","merge_cells_desc":"Fusionner les cellules","split_cells_desc":"Scinder les cellules fusionn\u00e9es","delete_col_desc":"Effacer la colonne","col_after_desc":"Ins\u00e9rer une colonne apr\u00e8s","col_before_desc":"Ins\u00e9rer une colonne avant","delete_row_desc":"Effacer la ligne","row_after_desc":"Ins\u00e9rer une ligne apr\u00e8s","row_before_desc":"Ins\u00e9rer une ligne avant",desc:"Ins\u00e9rer un nouveau tableau","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Si vous restaurez le contenu sauv\u00e9, vous perdrez le contenu qui est actuellement dans l\'\u00e9diteur.\n\n\u00cates-vous s\u00fbr de vouloir restaurer le contenu sauv\u00e9 ?","restore_content":"Restaurer le contenu auto-sauvegard\u00e9.","unload_msg":"Les modifications apport\u00e9es seront perdues si vous quittez cette page."},fullscreen:{desc:"Passer en mode plein \u00e9cran"},media:{edit:"\u00c9diter un m\u00e9dia incorpor\u00e9",desc:"Ins\u00e9rer / \u00e9diter un m\u00e9dia incorpor\u00e9","delta_height":"","delta_width":""},fullpage:{desc:"Propri\u00e9t\u00e9s du document","delta_width":"","delta_height":""},template:{desc:"Ins\u00e9rer un mod\u00e8le pr\u00e9d\u00e9fini."},visualchars:{desc:"Activer les caract\u00e8res de mise en page."},spellchecker:{desc:"Activer le v\u00e9rificateur d\'orthographe",menu:"Param\u00e8tres du v\u00e9rificateur d\'orthographe","ignore_word":"Ignorer le mot","ignore_words":"Tout ignorer",langs:"Langues",wait:"Veuillez patienter\u2026",sug:"Suggestions","no_sug":"Aucune suggestion","no_mpell":"Aucune erreur trouv\u00e9e.","learn_word":"Apprendre le mot"},pagebreak:{desc:"Ins\u00e9rer un saut de page."},advlist:{types:"Types",def:"D\u00e9faut","lower_alpha":"Alpha minuscule","lower_greek":"Grec minuscule","lower_roman":"Romain minuscule","upper_alpha":"Alpha majuscule","upper_roman":"Romain majuscule",circle:"Cercle",disc:"Disque",square:"Carr\u00e9"},colors:{"333300":"Olive fonc\u00e9","993300":"Orange br\u00fbl\u00e9","000000":"Noir","003300":"Vert fonc\u00e9","003366":"Azur fonc\u00e9","000080":"Bleu marine","333399":"Indigo","333333":"Gris tr\u00e8s fonc\u00e9","800000":"Bordeaux",FF6600:"Orange","808000":"Olive","008000":"Vert","008080":"Sarcelle","0000FF":"Bleu","666699":"Bleu gris\u00e2tre","808080":"Gris",FF0000:"Rouge",FF9900:"Ambre","99CC00":"Jaune vert","339966":"Mer verte","33CCCC":"Turquoise","3366FF":"Bleu royal","800080":"Violet","999999":"Gris moyen",FF00FF:"Magenta",FFCC00:"Or",FFFF00:"Jaune","00FF00":"Lime","00FFFF":"Bleu vert","00CCFF":"Bleu ciel","993366":"Brun",C0C0C0:"Argent",FF99CC:"Rose",FFCC99:"P\u00eache",FFFF99:"Jaune clair",CCFFCC:"Vert p\u00e2le",CCFFFF:"Cyan p\u00e2le","99CCFF":"Bleu ciel clair",CC99FF:"Prune",FFFFFF:"Blanc"},aria:{"rich_text_area":"Texte riche"},wordcount:{words:"Mots:"}}}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/he.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/he.js new file mode 100644 index 0000000000..0f4e12d7b5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/he.js @@ -0,0 +1 @@ +tinyMCE.addI18n({he:{common:{"more_colors":"\u05e2\u05d5\u05d3 \u05e6\u05d1\u05e2\u05d9\u05dd","invalid_data":"\u05e9\u05d2\u05d9\u05d0\u05d4: \u05d4\u05d5\u05e7\u05dc\u05d3 \u05de\u05d9\u05d3\u05e2 \u05dc\u05d0 \u05ea\u05e7\u05e0\u05d9. \u05d4\u05de\u05d9\u05d3\u05e2 \u05e1\u05d5\u05de\u05df \u05d1\u05d0\u05d3\u05d5\u05dd.","popup_blocked":"\u05d7\u05d5\u05e1\u05dd \u05e4\u05e8\u05d9\u05d8\u05d9\u05dd \u05de\u05d5\u05e7\u05e4\u05e6\u05d9\u05dd \u05de\u05e0\u05e2 \u05de\u05d7\u05dc\u05d5\u05df \u05d7\u05e9\u05d5\u05d1 \u05de\u05dc\u05d4\u05e4\u05ea\u05d7,\u05d0\u05dd \u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05db\u05dc\u05d9 \u05d6\u05d4 \u05e2\u05dc\u05d9\u05da \u05dc\u05d1\u05d8\u05dc \u05d0\u05ea \u05d7\u05d5\u05e1\u05dd \u05d4\u05e4\u05e8\u05d9\u05d8\u05d9\u05dd","clipboard_no_support":"\u05db\u05e8\u05d2\u05e2 \u05dc\u05d0 \u05e0\u05ea\u05de\u05da \u05e2\u05dc \u05d9\u05d3\u05d9 \u05d4\u05d3\u05e4\u05d3\u05e4\u05df \u05e9\u05dc\u05da. \u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05e7\u05d9\u05e6\u05d5\u05e8\u05d9 \u05d4\u05de\u05e7\u05dc\u05d3\u05ea.","clipboard_msg":"\n \u05d4\u05e2\u05ea\u05e7\u05d4/\u05d2\u05d6\u05d9\u05e8\u05d4 \u05d5\u05d4\u05d3\u05d1\u05e7\u05d4 \u05d0\u05d9\u05e0\u05dd \u05d6\u05de\u05d9\u05e0\u05d9\u05dd \u05d1 Mozilla \u05d5\u05d1-Firefox.\n \u05d4\u05d0\u05dd \u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05e7\u05d1\u05dc \u05de\u05d9\u05d3\u05e2 \u05e0\u05d5\u05e1\u05e3 \u05e2\u05dc \u05d4\u05e0\u05d5\u05e9\u05d0?\n ","not_set":"-- \u05dc\u05d0 \u05d4\u05d5\u05d2\u05d3\u05e8 --","class_name":"\u05de\u05d7\u05dc\u05e7\u05d4",browse:"\u05e2\u05d9\u05d5\u05df",close:"\u05e1\u05d2\u05d9\u05e8\u05d4",cancel:"\u05d1\u05d9\u05d8\u05d5\u05dc",update:"\u05e2\u05d3\u05db\u05d5\u05df",insert:"\u05d4\u05d5\u05e1\u05e4\u05d4",apply:"\u05d0\u05d9\u05e9\u05d5\u05e8","edit_confirm":"\u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05d4\u05e9\u05ea\u05de\u05e9 \u05d1\u05e2\u05d5\u05e8\u05da \u05d4\u05de\u05ea\u05e7\u05d3\u05dd?","invalid_data_number":"{#field} \u05d7\u05d9\u05d9\u05d1 \u05dc\u05d4\u05d9\u05d5\u05ea \u05de\u05e1\u05e4\u05e8","invalid_data_min":"{#field} \u05d4\u05de\u05e1\u05e4\u05e8 \u05d7\u05d9\u05d9\u05d1 \u05dc\u05d4\u05d9\u05d5\u05ea \u05d2\u05d3\u05d5\u05dc \u05de-{#min}","invalid_data_size":"{#field} \u05d4\u05e2\u05e8\u05da \u05d7\u05d9\u05d9\u05d1 \u05dc\u05d4\u05d9\u05d5\u05ea \u05de\u05e1\u05e4\u05e8 \u05d0\u05d5 \u05d0\u05d7\u05d5\u05d6",value:"(\u05e2\u05e8\u05da)"},contextmenu:{full:"\u05e9\u05e0\u05d9 \u05d4\u05e6\u05d3\u05d3\u05d9\u05dd",right:"\u05d9\u05de\u05d9\u05df",center:"\u05d0\u05de\u05e6\u05e2",left:"\u05e9\u05de\u05d0\u05dc",align:"\u05d9\u05d9\u05e9\u05d5\u05e8"},insertdatetime:{"day_short":"\u05d9\u05d5\u05dd \u05d0\',\u05d9\u05d5\u05dd \u05d1\',\u05d9\u05d5\u05dd \u05d2\',\u05d9\u05d5\u05dd \u05d3\',\u05d9\u05d5\u05dd \u05d4\',\u05d9\u05d5\u05dd \u05d5\',\u05e9\u05d1\u05ea,\u05d9\u05d5\u05dd \u05d0\'","day_long":"\u05d9\u05d5\u05dd \u05e8\u05d0\u05e9\u05d5\u05df,\u05d9\u05d5\u05dd \u05e9\u05e0\u05d9,\u05d9\u05d5\u05dd \u05e9\u05dc\u05d9\u05e9\u05d9,\u05d9\u05d5\u05dd \u05e8\u05d1\u05d9\u05e2\u05d9,\u05d9\u05d5\u05dd \u05d7\u05de\u05d9\u05e9\u05d9,\u05d9\u05d5\u05dd \u05e9\u05d9\u05e9,\u05d9\u05d5\u05dd \u05e9\u05d1\u05ea,\u05d9\u05d5\u05dd \u05e8\u05d0\u05e9\u05d5\u05df","months_short":"\u05d9\u05e0\u05d5\u05d0\u05e8,\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8,\u05de\u05e8\u05e5,\u05d0\u05e4\u05e8\u05d9\u05dc,\u05de\u05d0\u05d9,\u05d9\u05d5\u05e0\u05e2,\u05d9\u05d5\u05dc\u05d9,\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8,\u05e1\u05e4\u05d8\u05de\u05d1\u05e8,\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8,\u05e0\u05d5\u05d1\u05de\u05d1\u05e8,\u05d3\u05e6\u05de\u05d1\u05e8","months_long":"\u05d9\u05e0\u05d5\u05d0\u05e8,\u05e4\u05d1\u05e8\u05d5\u05d0\u05e8,\u05de\u05e8\u05e5,\u05d0\u05e4\u05e8\u05d9\u05dc,\u05de\u05d0\u05d9,\u05d9\u05d5\u05e0\u05e2,\u05d9\u05d5\u05dc\u05d9,\u05d0\u05d5\u05d2\u05d5\u05e1\u05d8,\u05e1\u05e4\u05d8\u05de\u05d1\u05e8,\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8,\u05e0\u05d5\u05d1\u05de\u05d1\u05e8,\u05d3\u05e6\u05de\u05d1\u05e8","inserttime_desc":"\u05d4\u05d5\u05e1\u05e4\u05ea \u05d6\u05de\u05df","insertdate_desc":"\u05d4\u05d5\u05e1\u05e4\u05ea \u05ea\u05d0\u05e8\u05d9\u05da","time_fmt":"%H:%M:%S","date_fmt":"%d-%m-%Y"},print:{"print_desc":"\u05d4\u05d3\u05e4\u05e1\u05d4"},preview:{"preview_desc":"\u05ea\u05e6\u05d5\u05d2\u05d4 \u05de\u05e7\u05d3\u05d9\u05de\u05d4"},directionality:{"rtl_desc":"\u05db\u05d9\u05d5\u05d5\u05df \u05d8\u05e7\u05e1\u05d8 \u05de\u05d9\u05de\u05d9\u05df \u05dc\u05e9\u05de\u05d0\u05dc","ltr_desc":"\u05db\u05d9\u05d5\u05d5\u05df \u05d8\u05e7\u05e1\u05d8 \u05de\u05e9\u05de\u05d0\u05dc \u05dc\u05d9\u05de\u05d9\u05df"},layer:{content:"\u05e9\u05db\u05d1\u05d4 \u05d7\u05d3\u05e9\u05d4...","absolute_desc":"\u05d1\u05d7\u05d9\u05e8\u05ea \u05de\u05d9\u05e7\u05d5\u05dd \u05de\u05d5\u05d7\u05dc\u05d8","backward_desc":"\u05d4\u05e2\u05d1\u05e8\u05d4 \u05d0\u05d7\u05d5\u05e8\u05d4","forward_desc":"\u05d4\u05e2\u05d1\u05e8\u05d4 \u05e7\u05d3\u05d9\u05de\u05d4","insertlayer_desc":"\u05d4\u05d5\u05e1\u05e4\u05ea \u05e9\u05db\u05d1\u05d4 \u05d7\u05d3\u05e9\u05d4"},save:{"save_desc":"\u05e9\u05de\u05d9\u05e8\u05d4","cancel_desc":"\u05d1\u05d9\u05d8\u05d5\u05dc \u05db\u05dc \u05d4\u05e9\u05d9\u05e0\u05d5\u05d9\u05dd"},nonbreaking:{"nonbreaking_desc":"\u05d4\u05d5\u05e1\u05e4\u05ea \u05e8\u05d5\u05d5\u05d7"},iespell:{download:" \u05dc\u05d0 \u05e0\u05de\u05e6\u05d0 ieSpell. \u05d4\u05d0\u05dd \u05d1\u05e8\u05e6\u05d5\u05e0\u05da \u05dc\u05d4\u05ea\u05e7\u05d9\u05df?","iespell_desc":"\u05d1\u05d3\u05d9\u05e7\u05ea \u05d0\u05d9\u05d5\u05ea \u05d1\u05d0\u05e0\u05d2\u05dc\u05d9\u05ea"},advhr:{"advhr_desc":"\u05e7\u05d5 \u05d0\u05d5\u05e4\u05e7\u05d9","delta_height":"","delta_width":""},emotions:{"emotions_desc":"\u05e1\u05de\u05d9\u05d9\u05dc\u05d9\u05dd","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"\u05d4\u05d7\u05dc\u05e4\u05d4","search_desc":"\u05d7\u05d9\u05e4\u05d5\u05e9","delta_width":"","delta_height":""},advimage:{"image_desc":"\u05d4\u05d5\u05e1\u05e4\u05d4/\u05e2\u05e8\u05d9\u05db\u05ea \u05ea\u05de\u05d5\u05e0\u05d4","delta_width":"","delta_height":""},advlink:{"link_desc":"\u05d4\u05d5\u05e1\u05e4\u05ea/\u05e2\u05e8\u05d9\u05db\u05ea \u05e7\u05d9\u05e9\u05d5\u05e8","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"\u05d4\u05db\u05e0\u05e1/\u05e2\u05e8\u05d5\u05da \u05ea\u05db\u05d5\u05e0\u05d5\u05ea","ins_desc":"\u05d4\u05db\u05e0\u05e1\u05d4","del_desc":"\u05de\u05d7\u05d9\u05e7\u05d4","acronym_desc":"\u05e8\u05d0\u05e9\u05d9 \u05ea\u05d9\u05d1\u05d5\u05ea","abbr_desc":"\u05e7\u05d9\u05e6\u05d5\u05e8","cite_desc":"\u05e6\u05d9\u05d8\u05d5\u05d8","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"\u05e2\u05d3\u05db\u05d5\u05df \u05d4\u05d2\u05d3\u05e8\u05d5\u05ea CSS","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Paste is now in plain text mode. Click again to toggle back to regular paste mode.","plaintext_mode_sticky":"Paste is now in plain text mode. Click again to toggle back to regular paste mode. After you paste something you will be returned to regular paste mode.","selectall_desc":"\u05d1\u05d7\u05e8 \u05d4\u05db\u05dc","paste_word_desc":"\u05d4\u05d3\u05d1\u05e7\u05d4 \u05de-WORD","paste_text_desc":"\u05d4\u05d3\u05d1\u05e7\u05d4 \u05db\u05d8\u05e7\u05e1\u05d8 \u05d1\u05dc\u05d1\u05d3"},"paste_dlg":{"word_title":"\u05d4\u05d3\u05d1\u05d9\u05e7\u05d5 \u05d1\u05d7\u05dc\u05d5\u05df \u05d6\u05d4 \u05d0\u05ea \u05d4\u05d8\u05e7\u05e1\u05d8 \u05d1\u05d0\u05de\u05e6\u05e2\u05d5\u05ea \u05d4\u05de\u05e7\u05e9\u05d9\u05dd CTRL+V.","text_linebreaks":"\u05d4\u05e9\u05d0\u05e8 \u05d0\u05ea \u05e9\u05d5\u05e8\u05d5\u05ea \u05d4\u05e8\u05d5\u05d5\u05d7","text_title":"\u05d4\u05d3\u05d1\u05d9\u05e7\u05d5 \u05d1\u05d7\u05dc\u05d5\u05df \u05d6\u05d4 \u05d0\u05ea \u05d4\u05d8\u05e7\u05e1\u05d8 \u05d1\u05d0\u05de\u05e6\u05e2\u05d5\u05ea \u05d4\u05de\u05e7\u05e9\u05d9\u05dd CTRL+V."},table:{cell:"\u05ea\u05d0",col:"\u05e2\u05de\u05d5\u05d3\u05d4",row:"\u05e9\u05d5\u05e8\u05d4",del:"\u05de\u05d7\u05d9\u05e7\u05ea \u05d8\u05d1\u05dc\u05d4","copy_row_desc":"\u05d4\u05e2\u05ea\u05e7\u05ea \u05e9\u05d5\u05e8\u05d4 \u05d1\u05d8\u05d1\u05dc\u05d4","cut_row_desc":"\u05d2\u05d6\u05d9\u05e8\u05ea \u05e9\u05d5\u05e8\u05d4 \u05d1\u05d8\u05d1\u05dc\u05d4","paste_row_after_desc":"\u05d4\u05d3\u05d1\u05e7\u05ea \u05e9\u05d5\u05e8\u05d4 \u05d1\u05d8\u05d1\u05dc\u05d4 \u05d0\u05d7\u05e8\u05d9","paste_row_before_desc":"\u05d4\u05d3\u05d1\u05e7\u05ea \u05e9\u05d5\u05e8\u05d4 \u05d1\u05d8\u05d1\u05dc\u05d4 \u05dc\u05e4\u05e0\u05d9","props_desc":"\u05ea\u05db\u05d5\u05e0\u05d5\u05ea \u05d4\u05d8\u05d1\u05dc\u05d4","cell_desc":"\u05ea\u05db\u05d5\u05e0\u05d5\u05ea \u05ea\u05d0 \u05d1\u05d8\u05d1\u05dc\u05d4","row_desc":"\u05ea\u05db\u05d5\u05e0\u05d5\u05ea \u05e9\u05d5\u05e8\u05d4 \u05d1\u05d8\u05d1\u05dc\u05d4","merge_cells_desc":"\u05d0\u05d9\u05d7\u05d5\u05d3 \u05ea\u05d0\u05d9\u05dd \u05d1\u05d8\u05d1\u05dc\u05d4","split_cells_desc":"\u05e4\u05d9\u05e6\u05d5\u05dc \u05ea\u05d0\u05d9\u05dd \u05d1\u05d8\u05d1\u05dc\u05d4","delete_col_desc":"\u05d4\u05e1\u05e8\u05ea \u05e2\u05de\u05d5\u05d3\u05d4","col_after_desc":"\u05d4\u05db\u05e0\u05e1\u05ea \u05e2\u05de\u05d5\u05d3\u05d4 \u05de\u05e9\u05de\u05d0\u05dc","col_before_desc":"\u05d4\u05db\u05e0\u05e1\u05ea \u05e2\u05de\u05d5\u05d3\u05d4 \u05de\u05d9\u05de\u05d9\u05df","delete_row_desc":"\u05de\u05d7\u05d9\u05e7\u05ea \u05e9\u05d5\u05e8\u05d4","row_after_desc":"\u05d4\u05db\u05e0\u05e1\u05ea \u05e9\u05d5\u05e8\u05d4 \u05de\u05ea\u05d7\u05ea","row_before_desc":"\u05d4\u05db\u05e0\u05e1\u05ea \u05e9\u05d5\u05e8\u05d4 \u05de\u05e2\u05dc",desc:"\u05d4\u05db\u05e0\u05e1\u05ea \u05d0\u05d5 \u05e2\u05e8\u05d9\u05db\u05ea \u05d8\u05d1\u05dc\u05d4","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"\u05d0\u05dd \u05ea\u05e9\u05d7\u05d6\u05e8 \u05d0\u05ea \u05d4\u05ea\u05d5\u05db\u05df \u05dc\u05d2\u05e8\u05d9\u05e1\u05d0 \u05d4\u05e9\u05de\u05d5\u05e8\u05d4, \u05ea\u05d0\u05d1\u05d3 \u05d0\u05ea \u05db\u05dc \u05d4\u05ea\u05d5\u05db\u05df \u05e9\u05e0\u05de\u05e6\u05d0 \u05db\u05e2\u05ea \u05d1\u05e2\u05d5\u05e8\u05da. \u05d4\u05d0\u05dd \u05d0\u05ea\u05d4 \u05d1\u05d8\u05d5\u05d7 \u05e9\u05d0\u05ea\u05d4 \u05e8\u05d5\u05e6\u05d4 \u05dc\u05e9\u05d7\u05d6\u05e8 \u05d0\u05ea \u05d4\u05ea\u05d5\u05db\u05df \u05dc\u05d2\u05d9\u05e8\u05e1\u05d0 \u05d4\u05e9\u05de\u05d5\u05e8\u05d4?.","restore_content":"\u05e9\u05d7\u05d6\u05d5\u05e8 \u05dc\u05d2\u05d9\u05e8\u05e1\u05d0 \u05e9\u05de\u05d5\u05e8\u05d4 \u05d0\u05d5\u05d8\u05d5\u05de\u05d8\u05d9\u05ea","unload_msg":"\u05d4\u05e9\u05d9\u05e0\u05d5\u05d9\u05d9\u05dd \u05e9\u05d1\u05d9\u05e6\u05e2\u05ea \u05dc\u05d0 \u05d9\u05e9\u05de\u05e8\u05d5 \u05d0\u05dd \u05ea\u05e2\u05d1\u05d5\u05e8 \u05de\u05d3\u05e3 \u05d6\u05d4"},fullscreen:{desc:"\u05de\u05e2\u05d1\u05e8 \u05dc\u05de\u05e1\u05da \u05de\u05dc\u05d0/\u05d7\u05dc\u05e7\u05d9"},media:{edit:"\u05e2\u05e8\u05d9\u05db\u05ea \u05e1\u05e8\u05d8\u05d5\u05df",desc:"\u05d4\u05d5\u05e1\u05e4\u05ea/\u05e2\u05e8\u05d9\u05db\u05ea \u05e1\u05e8\u05d8\u05d5\u05df","delta_height":"","delta_width":""},fullpage:{desc:"\u05de\u05d0\u05e4\u05d9\u05d9\u05e0\u05d9 \u05e2\u05de\u05d5\u05d3","delta_width":"","delta_height":""},template:{desc:"Insert predefined template content"},visualchars:{desc:"\u05d4\u05e6\u05d2/\u05d4\u05e1\u05ea\u05e8 \u05ea\u05d5\u05d5\u05d9 \u05d1\u05e7\u05e8\u05d4"},spellchecker:{desc:"\u05d4\u05e4\u05e2\u05dc\u05ea \u05d1\u05d5\u05d3\u05e7 \u05d0\u05d9\u05d5\u05ea",menu:"\u05d4\u05d2\u05d3\u05e8\u05d5\u05ea \u05d1\u05d5\u05d3\u05e7 \u05d0\u05d9\u05d5\u05ea","ignore_word":"\u05dc\u05d4\u05ea\u05e2\u05dc\u05dd \u05de\u05d4\u05de\u05d9\u05dc\u05d4","ignore_words":"\u05dc\u05d4\u05ea\u05e2\u05dc\u05dd \u05de\u05d4\u05db\u05dc",langs:"\u05e9\u05e4\u05d5\u05ea",wait:"\u05e0\u05d0 \u05dc\u05d4\u05de\u05ea\u05d9\u05df..",sug:"\u05d4\u05e6\u05e2\u05d5\u05ea","no_sug":"\u05d0\u05d9\u05df \u05d4\u05e6\u05e2\u05d5\u05ea","no_mpell":"\u05dc\u05d0 \u05e0\u05de\u05e6\u05d0\u05d5 \u05e9\u05d2\u05d9\u05d0\u05d5\u05ea \u05d0\u05d9\u05d5\u05ea","learn_word":"\u05dc\u05de\u05d3 \u05de\u05d9\u05dc\u05d9\u05dd"},pagebreak:{desc:"\u05d4\u05d5\u05e1\u05e4\u05ea \u05de\u05e2\u05d1\u05e8 \u05d3\u05e3"},advlist:{types:"\u05e1\u05d5\u05d2\u05d9\u05dd",def:"\u05d1\u05e8\u05d9\u05e8\u05ea \u05de\u05d7\u05d3\u05dc","lower_alpha":"Lower alpha","lower_greek":"Lower greek","lower_roman":"Lower roman","upper_alpha":"Upper alpha","upper_roman":"Upper roman",circle:"\u05e2\u05d2\u05d5\u05dc",disc:"\u05d3\u05d9\u05e1\u05e7",square:"\u05de\u05e8\u05d5\u05d1\u05e2"},colors:{"333300":"\u05d6\u05d9\u05ea \u05db\u05d4\u05d4","993300":"\u05db\u05ea\u05d5\u05dd \u05db\u05d4\u05d4","000000":"\u05e9\u05d7\u05d5\u05e8","003300":"\u05d9\u05e8\u05d5\u05e7 \u05db\u05d4\u05d4","003366":"\u05d8\u05d5\u05e8\u05e7\u05d9\u05d6 \u05db\u05d4\u05d4","000080":"\u05db\u05d7\u05d5\u05dc \u05e6\u05d9","333399":"\u05d0\u05d9\u05e0\u05d3\u05d9\u05d2\u05d5","333333":"\u05d0\u05e4\u05d5\u05e8 \u05db\u05d4\u05d4 \u05de\u05d0\u05d5\u05d3","800000":"\u05e2\u05e8\u05de\u05d5\u05e0\u05d9",FF6600:"\u05db\u05ea\u05d5\u05dd","808000":"\u05d6\u05d9\u05ea","008000":"\u05d9\u05e8\u05d5\u05e7","008080":"\u05d9\u05e8\u05d5\u05e7-\u05db\u05d7\u05d5\u05dc \u05e2\u05de\u05d5\u05e7","0000FF":"\u05db\u05d7\u05d5\u05dc","666699":"\u05db\u05d7\u05d5\u05dc \u05d0\u05e4\u05e8\u05e4\u05e8","808080":"\u05d0\u05e4\u05d5\u05e8",FF0000:"\u05d0\u05d3\u05d5\u05dd",FF9900:"\u05e2\u05e0\u05d1\u05e8","99CC00":"\u05d9\u05e8\u05d5\u05e7 \u05e6\u05d4\u05d1\u05d4\u05d1","339966":"\u05d9\u05e8\u05d5\u05e7 \u05d9\u05dd","33CCCC":"\u05d8\u05d5\u05e8\u05e7\u05d9\u05d6","3366FF":"\u05db\u05d7\u05d5\u05dc \u05e8\u05d5\u05d9\u05d0\u05dc","800080":"\u05e1\u05d2\u05d5\u05dc","999999":"\u05d0\u05e4\u05d5\u05e8 \u05d1\u05d9\u05e0\u05d9\u05d9\u05dd",FF00FF:"\u05e1\u05d2\u05d5\u05dc-\u05d5\u05e8\u05d5\u05d3 (\u05de\u05d2\u05f3\u05e0\u05d8\u05d4)",FFCC00:"\u05d6\u05d4\u05d1",FFFF00:"\u05e6\u05d4\u05d5\u05d1","00FF00":"\u05dc\u05d9\u05d9\u05dd","00FFFF":"\u05d8\u05d5\u05e8\u05e7\u05d9\u05d6 \u05de\u05d9\u05dd","00CCFF":"\u05ea\u05db\u05dc\u05ea","993366":"\u05d7\u05d5\u05dd",C0C0C0:"\u05db\u05e1\u05e3",FF99CC:"\u05d5\u05e8\u05d5\u05d3",FFCC99:"\u05d0\u05e4\u05e8\u05e1\u05e7",FFFF99:"\u05e6\u05d4\u05d5\u05d1 \u05d1\u05d4\u05d9\u05e8",CCFFCC:"\u05d9\u05e8\u05d5\u05e7 \u05d7\u05d9\u05d5\u05d5\u05e8",CCFFFF:"\u05d8\u05d5\u05e8\u05e7\u05d9\u05d6 \u05d1\u05d4\u05d9\u05e8","99CCFF":"\u05ea\u05db\u05dc\u05ea \u05d1\u05d4\u05d9\u05e8",CC99FF:"\u05d5\u05e8\u05d5\u05d3 \u05e2\u05de\u05d5\u05e7",FFFFFF:"\u05dc\u05d1\u05df"},aria:{"rich_text_area":"\u05d0\u05d6\u05d5\u05e8 \u05e2\u05d5\u05e8\u05da \u05d8\u05e7\u05e1\u05d8 \u05e2\u05e9\u05d9\u05e8"},wordcount:{words:"\u05de\u05d9\u05dc\u05d9\u05dd:"}}}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/it.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/it.js new file mode 100644 index 0000000000..d97803d2b3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/it.js @@ -0,0 +1,219 @@ +tinymce.addI18n('it',{ +"Cut": "Taglia", +"Heading 5": "Intestazione 5", +"Header 2": "Header 2", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Il tuo browser non supporta l'accesso diretto negli Appunti. Per favore usa i tasti di scelta rapida Ctrl+X\/C\/V.", +"Heading 4": "Intestazione 4", +"Div": "Div", +"Heading 2": "Intestazione 2", +"Paste": "Incolla", +"Close": "Chiudi", +"Font Family": "Famiglia font", +"Pre": "Pre", +"Align right": "Allinea a Destra", +"New document": "Nuovo Documento", +"Blockquote": "Blockquote", +"Numbered list": "Elenchi Numerati", +"Heading 1": "Intestazione 1", +"Headings": "Intestazioni", +"Increase indent": "Aumenta Rientro", +"Formats": "Formattazioni", +"Headers": "Intestazioni", +"Select all": "Seleziona Tutto", +"Header 3": "Intestazione 3", +"Blocks": "Blocchi", +"Undo": "Indietro", +"Strikethrough": "Barrato", +"Bullet list": "Elenchi Puntati", +"Header 1": "Intestazione 1", +"Superscript": "Apice", +"Clear formatting": "Cancella Formattazione", +"Font Sizes": "Dimensioni font", +"Subscript": "Pedice", +"Header 6": "Intestazione 6", +"Redo": "Ripeti", +"Paragraph": "Paragrafo", +"Ok": "Ok", +"Bold": "Grassetto", +"Code": "Codice", +"Italic": "Corsivo", +"Align center": "Allinea al Cento", +"Header 5": "Intestazione 5", +"Heading 6": "Intestazione 6", +"Heading 3": "Intestazione 3", +"Decrease indent": "Riduci Rientro", +"Header 4": "Intestazione 4", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Incolla \u00e8 in modalit\u00e0 testo normale. I contenuti sono incollati come testo normale se non disattivi l'opzione.", +"Underline": "Sottolineato", +"Cancel": "Annulla", +"Justify": "Giustifica", +"Inline": "Inlinea", +"Copy": "Copia", +"Align left": "Allinea a Sinistra", +"Visual aids": "Elementi Visivi", +"Lower Greek": "Greek Minore", +"Square": "Quadrato", +"Default": "Default", +"Lower Alpha": "Alpha Minore", +"Circle": "Cerchio", +"Disc": "Disco", +"Upper Alpha": "Alpha Superiore", +"Upper Roman": "Roman Superiore", +"Lower Roman": "Roman Minore", +"Name": "Nome", +"Anchor": "Fissa", +"You have unsaved changes are you sure you want to navigate away?": "Non hai salvato delle modifiche, sei sicuro di andartene?", +"Restore last draft": "Ripristina l'ultima bozza.", +"Special character": "Carattere Speciale", +"Source code": "Codice Sorgente", +"B": "B", +"R": "R", +"G": "G", +"Color": "Colore", +"Right to left": "Da Destra a Sinistra", +"Left to right": "Da Sinistra a Destra", +"Emoticons": "Emoction", +"Robots": "Robot", +"Document properties": "Propriet\u00e0 Documento", +"Title": "Titolo", +"Keywords": "Parola Chiave", +"Encoding": "Codifica", +"Description": "Descrizione", +"Author": "Autore", +"Fullscreen": "Schermo Intero", +"Horizontal line": "Linea Orizzontale", +"Horizontal space": "Spazio Orizzontale", +"Insert\/edit image": "Aggiungi\/Modifica Immagine", +"General": "Generale", +"Advanced": "Avanzato", +"Source": "Fonte", +"Border": "Bordo", +"Constrain proportions": "Mantieni Proporzioni", +"Vertical space": "Spazio Verticale", +"Image description": "Descrizione Immagine", +"Style": "Stile", +"Dimensions": "Dimenzioni", +"Insert image": "Inserisci immagine", +"Zoom in": "Ingrandisci", +"Contrast": "Contrasto", +"Back": "Indietro", +"Gamma": "Gamma", +"Flip horizontally": "Rifletti orizzontalmente", +"Resize": "Ridimensiona", +"Sharpen": "Contrasta", +"Zoom out": "Rimpicciolisci", +"Image options": "Opzioni immagine", +"Apply": "Applica", +"Brightness": "Luminosit\u00e0", +"Rotate clockwise": "Ruota in senso orario", +"Rotate counterclockwise": "Ruota in senso antiorario", +"Edit image": "Modifica immagine", +"Color levels": "Livelli colore", +"Crop": "Taglia", +"Orientation": "Orientamento", +"Flip vertically": "Rifletti verticalmente", +"Invert": "Inverti", +"Insert date\/time": "Inserisci Data\/Ora", +"Remove link": "Rimuovi link", +"Url": "Url", +"Text to display": "Testo da Visualizzare", +"Anchors": "Anchors", +"Insert link": "Inserisci il Link", +"New window": "Nuova Finestra", +"None": "No", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "L'URL inserito sembra essere un collegamento esterno. Vuoi aggiungere il prefisso necessario http:\/\/?", +"Target": "Target", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "L'URL inserito sembra essere un indirizzo email. Vuoi aggiungere il prefisso necessario mailto:?", +"Insert\/edit link": "Inserisci\/Modifica Link", +"Insert\/edit video": "Inserisci\/Modifica Video", +"Poster": "Anteprima", +"Alternative source": "Alternativo", +"Paste your embed code below:": "Incolla il codice d'incorporamento qui:", +"Insert video": "Inserisci Video", +"Embed": "Incorporare", +"Nonbreaking space": "Spazio unificatore", +"Page break": "Interruzione di pagina", +"Paste as text": "incolla come testo", +"Preview": "Anteprima", +"Print": "Stampa", +"Save": "Salva", +"Could not find the specified string.": "Impossibile trovare la parola specifica.", +"Replace": "Sostituisci", +"Next": "Successivo", +"Whole words": "Parole Sbagliate", +"Find and replace": "Trova e Sostituisci", +"Replace with": "Sostituisci Con", +"Find": "Trova", +"Replace all": "Sostituisci Tutto", +"Match case": "Maiuscole\/Minuscole ", +"Prev": "Precedente", +"Spellcheck": "Controllo ortografico", +"Finish": "Termina", +"Ignore all": "Ignora Tutto", +"Ignore": "Ignora", +"Add to Dictionary": "Aggiungi al Dizionario", +"Insert row before": "Inserisci una Riga Prima", +"Rows": "Righe", +"Height": "Altezza", +"Paste row after": "Incolla una Riga Dopo", +"Alignment": "Allineamento", +"Border color": "Colore bordo", +"Column group": "Gruppo di Colonne", +"Row": "Riga", +"Insert column before": "Inserisci una Colonna Prima", +"Split cell": "Dividi Cella", +"Cell padding": "Padding della Cella", +"Cell spacing": "Spaziatura della Cella", +"Row type": "Tipo di Riga", +"Insert table": "Inserisci Tabella", +"Body": "Body", +"Caption": "Didascalia", +"Footer": "Footer", +"Delete row": "Cancella Riga", +"Paste row before": "Incolla una Riga Prima", +"Scope": "Campo", +"Delete table": "Cancella Tabella", +"H Align": "Allineamento H", +"Top": "In alto", +"Header cell": "cella d'intestazione", +"Column": "Colonna", +"Row group": "Gruppo di Righe", +"Cell": "Cella", +"Middle": "In mezzo", +"Cell type": "Tipo di Cella", +"Copy row": "Copia Riga", +"Row properties": "Propriet\u00e0 della Riga", +"Table properties": "Propiet\u00e0 della Tabella", +"Bottom": "In fondo", +"V Align": "Allineamento V", +"Header": "Header", +"Right": "Destra", +"Insert column after": "Inserisci una Colonna Dopo", +"Cols": "Colonne", +"Insert row after": "Inserisci una Riga Dopo", +"Width": "Larghezza", +"Cell properties": "Propiet\u00e0 della Cella", +"Left": "Sinistra", +"Cut row": "Taglia Riga", +"Delete column": "Cancella Colonna", +"Center": "Centro", +"Merge cells": "Unisci Cella", +"Insert template": "Inserisci Template", +"Templates": "Template", +"Background color": "Colore Background", +"Custom...": "Personalizzato...", +"Custom color": "Colore personalizzato", +"No color": "Nessun colore", +"Text color": "Colore Testo", +"Show blocks": "Mostra Blocchi", +"Show invisible characters": "Mostra Caratteri Invisibili", +"Words: {0}": "Parole: {0}", +"Insert": "Inserisci", +"File": "File", +"Edit": "Modifica", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich Text Area. Premi ALT-F9 per il men\u00f9. Premi ALT-F10 per la barra degli strumenti. Premi ALT-0 per l'aiuto.", +"Tools": "Strumenti", +"View": "Visualiza", +"Table": "Tabella", +"Format": "Formato" +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/ja.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/ja.js new file mode 100644 index 0000000000..848cbd36b9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/ja.js @@ -0,0 +1,219 @@ +tinymce.addI18n('ja',{ +"Cut": "\u5207\u308a\u53d6\u308a", +"Heading 5": "\u898b\u51fa\u3057 5", +"Header 2": "\u30d8\u30c3\u30c0\u30fc 2", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u304a\u4f7f\u3044\u306e\u30d6\u30e9\u30a6\u30b6\u3067\u306f\u30af\u30ea\u30c3\u30d7\u30dc\u30fc\u30c9\u6a5f\u80fd\u3092\u5229\u7528\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3002\u30ad\u30fc\u30dc\u30fc\u30c9\u306e\u30b7\u30e7\u30fc\u30c8\u30ab\u30c3\u30c8\uff08Ctrl+X, Ctrl+C, Ctrl+V\uff09\u3092\u304a\u4f7f\u3044\u4e0b\u3055\u3044\u3002", +"Heading 4": "\u898b\u51fa\u3057 4", +"Div": "Div", +"Heading 2": "\u898b\u51fa\u3057 2", +"Paste": "\u8cbc\u308a\u4ed8\u3051", +"Close": "\u9589\u3058\u308b", +"Font Family": "\u30d5\u30a9\u30f3\u30c8\u30d5\u30a1\u30df\u30ea\u30fc", +"Pre": "Pre", +"Align right": "\u53f3\u5bc4\u305b", +"New document": "\u65b0\u898f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8", +"Blockquote": "\u5f15\u7528", +"Numbered list": "\u756a\u53f7\u4ed8\u304d\u7b87\u6761\u66f8\u304d", +"Heading 1": "\u898b\u51fa\u3057 1", +"Headings": "\u898b\u51fa\u3057", +"Increase indent": "\u30a4\u30f3\u30c7\u30f3\u30c8\u3092\u5897\u3084\u3059", +"Formats": "\u66f8\u5f0f", +"Headers": "\u30d8\u30c3\u30c0\u30fc", +"Select all": "\u5168\u3066\u3092\u9078\u629e", +"Header 3": "\u30d8\u30c3\u30c0\u30fc 3", +"Blocks": "\u30d6\u30ed\u30c3\u30af", +"Undo": "\u5143\u306b\u623b\u3059", +"Strikethrough": "\u53d6\u308a\u6d88\u3057\u7dda", +"Bullet list": "\u7b87\u6761\u66f8\u304d", +"Header 1": "\u30d8\u30c3\u30c0\u30fc 1", +"Superscript": "\u4e0a\u4ed8\u304d\u6587\u5b57", +"Clear formatting": "\u66f8\u5f0f\u3092\u30af\u30ea\u30a2", +"Font Sizes": "\u30d5\u30a9\u30f3\u30c8\u30b5\u30a4\u30ba", +"Subscript": "\u4e0b\u4ed8\u304d\u6587\u5b57", +"Header 6": "\u30d8\u30c3\u30c0\u30fc 6", +"Redo": "\u3084\u308a\u76f4\u3059", +"Paragraph": "\u6bb5\u843d", +"Ok": "OK", +"Bold": "\u592a\u5b57", +"Code": "\u30b3\u30fc\u30c9", +"Italic": "\u659c\u4f53", +"Align center": "\u4e2d\u592e\u63c3\u3048", +"Header 5": "\u30d8\u30c3\u30c0\u30fc 5", +"Heading 6": "\u898b\u51fa\u3057 6", +"Heading 3": "\u898b\u51fa\u3057 3", +"Decrease indent": "\u30a4\u30f3\u30c7\u30f3\u30c8\u3092\u6e1b\u3089\u3059", +"Header 4": "\u30d8\u30c3\u30c0\u30fc 4", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u8cbc\u308a\u4ed8\u3051\u306f\u73fe\u5728\u30d7\u30ec\u30fc\u30f3\u30c6\u30ad\u30b9\u30c8\u30e2\u30fc\u30c9\u3067\u3059\u3002\u3053\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3092\u30aa\u30d5\u306b\u3057\u306a\u3044\u9650\u308a\u5185\u5bb9\u306f\u30d7\u30ec\u30fc\u30f3\u30c6\u30ad\u30b9\u30c8\u3068\u3057\u3066\u8cbc\u308a\u4ed8\u3051\u3089\u308c\u307e\u3059\u3002", +"Underline": "\u4e0b\u7dda", +"Cancel": "\u30ad\u30e3\u30f3\u30bb\u30eb", +"Justify": "\u4e21\u7aef\u63c3\u3048", +"Inline": "\u30a4\u30f3\u30e9\u30a4\u30f3", +"Copy": "\u30b3\u30d4\u30fc", +"Align left": "\u5de6\u5bc4\u305b", +"Visual aids": "\u8868\u306e\u67a0\u7dda\u3092\u70b9\u7dda\u3067\u8868\u793a", +"Lower Greek": "\u5c0f\u6587\u5b57\u306e\u30ae\u30ea\u30b7\u30e3\u6587\u5b57", +"Square": "\u56db\u89d2", +"Default": "\u30c7\u30d5\u30a9\u30eb\u30c8", +"Lower Alpha": "\u5c0f\u6587\u5b57\u306e\u30a2\u30eb\u30d5\u30a1\u30d9\u30c3\u30c8", +"Circle": "\u5186", +"Disc": "\u70b9", +"Upper Alpha": "\u5927\u6587\u5b57\u306e\u30a2\u30eb\u30d5\u30a1\u30d9\u30c3\u30c8", +"Upper Roman": "\u5927\u6587\u5b57\u306e\u30ed\u30fc\u30de\u6570\u5b57", +"Lower Roman": "\u5c0f\u6587\u5b57\u306e\u30ed\u30fc\u30de\u6570\u5b57", +"Name": "\u30a2\u30f3\u30ab\u30fc\u540d", +"Anchor": "\u30a2\u30f3\u30ab\u30fc\uff08\u30ea\u30f3\u30af\u306e\u5230\u9054\u70b9\uff09", +"You have unsaved changes are you sure you want to navigate away?": "\u307e\u3060\u4fdd\u5b58\u3057\u3066\u3044\u306a\u3044\u5909\u66f4\u304c\u3042\u308a\u307e\u3059\u304c\u3001\u672c\u5f53\u306b\u3053\u306e\u30da\u30fc\u30b8\u3092\u96e2\u308c\u307e\u3059\u304b\uff1f", +"Restore last draft": "\u524d\u56de\u306e\u4e0b\u66f8\u304d\u3092\u5fa9\u6d3b\u3055\u305b\u308b", +"Special character": "\u7279\u6b8a\u6587\u5b57", +"Source code": "\u30bd\u30fc\u30b9\u30b3\u30fc\u30c9", +"B": "B", +"R": "R", +"G": "G", +"Color": "\u30ab\u30e9\u30fc", +"Right to left": "\u53f3\u304b\u3089\u5de6", +"Left to right": "\u5de6\u304b\u3089\u53f3", +"Emoticons": "\u7d75\u6587\u5b57", +"Robots": "\u30ed\u30dc\u30c3\u30c4", +"Document properties": "\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306e\u30d7\u30ed\u30d1\u30c6\u30a3", +"Title": "\u30bf\u30a4\u30c8\u30eb", +"Keywords": "\u30ad\u30fc\u30ef\u30fc\u30c9", +"Encoding": "\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0", +"Description": "\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u5185\u5bb9", +"Author": "\u8457\u8005", +"Fullscreen": "\u5168\u753b\u9762\u8868\u793a", +"Horizontal line": "\u6c34\u5e73\u7f6b\u7dda", +"Horizontal space": "\u6a2a\u65b9\u5411\u306e\u4f59\u767d", +"Insert\/edit image": "\u753b\u50cf\u306e\u633f\u5165\u30fb\u7de8\u96c6", +"General": "\u4e00\u822c", +"Advanced": "\u8a73\u7d30\u8a2d\u5b9a", +"Source": "\u753b\u50cf\u306e\u30bd\u30fc\u30b9", +"Border": "\u67a0\u7dda", +"Constrain proportions": "\u7e26\u6a2a\u6bd4\u3092\u4fdd\u6301\u3059\u308b", +"Vertical space": "\u7e26\u65b9\u5411\u306e\u4f59\u767d", +"Image description": "\u753b\u50cf\u306e\u8aac\u660e\u6587", +"Style": "\u30b9\u30bf\u30a4\u30eb", +"Dimensions": "\u753b\u50cf\u30b5\u30a4\u30ba\uff08\u6a2a\u30fb\u7e26\uff09", +"Insert image": "\u753b\u50cf\u306e\u633f\u5165", +"Zoom in": "\u30ba\u30fc\u30e0\u30a4\u30f3", +"Contrast": "\u30b3\u30f3\u30c8\u30e9\u30b9\u30c8", +"Back": "\u623b\u308b", +"Gamma": "\u30ac\u30f3\u30de", +"Flip horizontally": "\u6c34\u5e73\u306b\u53cd\u8ee2", +"Resize": "\u30ea\u30b5\u30a4\u30ba", +"Sharpen": "\u30b7\u30e3\u30fc\u30d7\u5316", +"Zoom out": "\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8", +"Image options": "\u753b\u50cf\u30aa\u30d7\u30b7\u30e7\u30f3", +"Apply": "\u9069\u7528", +"Brightness": "\u660e\u308b\u3055", +"Rotate clockwise": "\u6642\u8a08\u56de\u308a\u306b\u56de\u8ee2", +"Rotate counterclockwise": "\u53cd\u6642\u8a08\u56de\u308a\u306b\u56de\u8ee2", +"Edit image": "\u753b\u50cf\u306e\u7de8\u96c6", +"Color levels": "\u30ab\u30e9\u30fc\u30ec\u30d9\u30eb", +"Crop": "\u30af\u30ed\u30c3\u30d7", +"Orientation": "\u5411\u304d", +"Flip vertically": "\u4e0a\u4e0b\u306b\u53cd\u8ee2", +"Invert": "\u53cd\u8ee2", +"Insert date\/time": "\u65e5\u4ed8\u30fb\u6642\u523b", +"Remove link": "\u30ea\u30f3\u30af\u306e\u524a\u9664", +"Url": "\u30ea\u30f3\u30af\u5148URL", +"Text to display": "\u30ea\u30f3\u30af\u5143\u30c6\u30ad\u30b9\u30c8", +"Anchors": "\u30a2\u30f3\u30ab\u30fc\uff08\u30ea\u30f3\u30af\u306e\u5230\u9054\u70b9\uff09", +"Insert link": "\u30ea\u30f3\u30af", +"New window": "\u65b0\u898f\u30a6\u30a3\u30f3\u30c9\u30a6", +"None": "\u306a\u3057", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u5165\u529b\u3055\u308c\u305fURL\u306f\u5916\u90e8\u30ea\u30f3\u30af\u306e\u3088\u3046\u3067\u3059\u3002\u300chttp:\/\/\u300d\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u8ffd\u52a0\u3057\u307e\u3059\u304b\uff1f", +"Target": "\u30bf\u30fc\u30b2\u30c3\u30c8\u5c5e\u6027", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u5165\u529b\u3055\u308c\u305fURL\u306f\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u306e\u3088\u3046\u3067\u3059\u3002\u300cmailto:\u300d\u30d7\u30ec\u30d5\u30a3\u30c3\u30af\u30b9\u3092\u8ffd\u52a0\u3057\u307e\u3059\u304b\uff1f", +"Insert\/edit link": "\u30ea\u30f3\u30af\u306e\u633f\u5165\u30fb\u7de8\u96c6", +"Insert\/edit video": "\u52d5\u753b\u306e\u633f\u5165\u30fb\u7de8\u96c6", +"Poster": "\u4ee3\u66ff\u753b\u50cf\u306e\u5834\u6240", +"Alternative source": "\u4ee3\u66ff\u52d5\u753b\u306e\u5834\u6240", +"Paste your embed code below:": "\u57cb\u3081\u8fbc\u307f\u7528\u30b3\u30fc\u30c9\u3092\u4e0b\u8a18\u306b\u8cbc\u308a\u4ed8\u3051\u3066\u304f\u3060\u3055\u3044\u3002", +"Insert video": "\u52d5\u753b", +"Embed": "\u57cb\u3081\u8fbc\u307f", +"Nonbreaking space": "\u56fa\u5b9a\u30b9\u30da\u30fc\u30b9\uff08 \uff09", +"Page break": "\u30da\u30fc\u30b8\u533a\u5207\u308a", +"Paste as text": "\u30c6\u30ad\u30b9\u30c8\u3068\u3057\u3066\u8cbc\u308a\u4ed8\u3051", +"Preview": "\u30d7\u30ec\u30d3\u30e5\u30fc", +"Print": "\u5370\u5237", +"Save": "\u4fdd\u5b58", +"Could not find the specified string.": "\u304a\u63a2\u3057\u306e\u6587\u5b57\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002", +"Replace": "\u7f6e\u304d\u63db\u3048", +"Next": "\u6b21", +"Whole words": "\u5358\u8a9e\u5358\u4f4d\u3067\u691c\u7d22\u3059\u308b", +"Find and replace": "\u691c\u7d22\u3068\u7f6e\u304d\u63db\u3048", +"Replace with": "\u7f6e\u304d\u63db\u3048\u308b\u6587\u5b57", +"Find": "\u691c\u7d22", +"Replace all": "\u5168\u3066\u3092\u7f6e\u304d\u63db\u3048\u308b", +"Match case": "\u5927\u6587\u5b57\u30fb\u5c0f\u6587\u5b57\u3092\u533a\u5225\u3059\u308b", +"Prev": "\u524d", +"Spellcheck": "\u30b9\u30da\u30eb\u30c1\u30a7\u30c3\u30af", +"Finish": "\u7d42\u4e86", +"Ignore all": "\u5168\u3066\u3092\u7121\u8996", +"Ignore": "\u7121\u8996", +"Add to Dictionary": "\u8f9e\u66f8\u306b\u8ffd\u52a0", +"Insert row before": "\u4e0a\u5074\u306b\u884c\u3092\u633f\u5165", +"Rows": "\u884c\u6570", +"Height": "\u9ad8\u3055", +"Paste row after": "\u4e0b\u5074\u306b\u884c\u3092\u8cbc\u308a\u4ed8\u3051", +"Alignment": "\u914d\u7f6e", +"Border color": "\u67a0\u7dda\u306e\u8272", +"Column group": "\u5217\u30b0\u30eb\u30fc\u30d7", +"Row": "\u884c", +"Insert column before": "\u5de6\u5074\u306b\u5217\u3092\u633f\u5165", +"Split cell": "\u30bb\u30eb\u306e\u5206\u5272", +"Cell padding": "\u30bb\u30eb\u5185\u4f59\u767d\uff08\u30d1\u30c7\u30a3\u30f3\u30b0\uff09", +"Cell spacing": "\u30bb\u30eb\u306e\u9593\u9694", +"Row type": "\u884c\u30bf\u30a4\u30d7", +"Insert table": "\u8868\u306e\u633f\u5165", +"Body": "\u30dc\u30c7\u30a3\u30fc", +"Caption": "\u8868\u984c", +"Footer": "\u30d5\u30c3\u30bf\u30fc", +"Delete row": "\u884c\u306e\u524a\u9664", +"Paste row before": "\u4e0a\u5074\u306b\u884c\u3092\u8cbc\u308a\u4ed8\u3051", +"Scope": "\u30b9\u30b3\u30fc\u30d7", +"Delete table": "\u8868\u306e\u524a\u9664", +"H Align": "\u6c34\u5e73\u65b9\u5411\u306e\u914d\u7f6e", +"Top": "\u4e0a", +"Header cell": "\u30d8\u30c3\u30c0\u30fc\u30bb\u30eb", +"Column": "\u5217", +"Row group": "\u884c\u30b0\u30eb\u30fc\u30d7", +"Cell": "\u30bb\u30eb", +"Middle": "\u4e2d\u592e", +"Cell type": "\u30bb\u30eb\u30bf\u30a4\u30d7", +"Copy row": "\u884c\u306e\u30b3\u30d4\u30fc", +"Row properties": "\u884c\u306e\u8a73\u7d30\u8a2d\u5b9a", +"Table properties": "\u8868\u306e\u8a73\u7d30\u8a2d\u5b9a", +"Bottom": "\u4e0b", +"V Align": "\u5782\u76f4\u65b9\u5411\u306e\u914d\u7f6e", +"Header": "\u30d8\u30c3\u30c0\u30fc", +"Right": "\u53f3\u5bc4\u305b", +"Insert column after": "\u53f3\u5074\u306b\u5217\u3092\u633f\u5165", +"Cols": "\u5217\u6570", +"Insert row after": "\u4e0b\u5074\u306b\u884c\u3092\u633f\u5165", +"Width": "\u5e45", +"Cell properties": "\u30bb\u30eb\u306e\u8a73\u7d30\u8a2d\u5b9a", +"Left": "\u5de6\u5bc4\u305b", +"Cut row": "\u884c\u306e\u5207\u308a\u53d6\u308a", +"Delete column": "\u5217\u306e\u524a\u9664", +"Center": "\u4e2d\u592e\u63c3\u3048", +"Merge cells": "\u30bb\u30eb\u306e\u7d50\u5408", +"Insert template": "\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u306e\u633f\u5165", +"Templates": "\u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u540d", +"Background color": "\u80cc\u666f\u8272", +"Custom...": "\u30ab\u30b9\u30bf\u30e0...", +"Custom color": "\u30ab\u30b9\u30bf\u30e0\u30ab\u30e9\u30fc", +"No color": "\u30ab\u30e9\u30fc\u306a\u3057", +"Text color": "\u30c6\u30ad\u30b9\u30c8\u306e\u8272", +"Show blocks": "\u6587\u7ae0\u306e\u533a\u5207\u308a\u3092\u70b9\u7dda\u3067\u8868\u793a", +"Show invisible characters": "\u4e0d\u53ef\u8996\u6587\u5b57\u3092\u8868\u793a", +"Words: {0}": "\u5358\u8a9e\u6570: {0}", +"Insert": "\u633f\u5165", +"File": "\u30d5\u30a1\u30a4\u30eb", +"Edit": "\u7de8\u96c6", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u66f8\u5f0f\u4ed8\u304d\u30c6\u30ad\u30b9\u30c8\u306e\u7de8\u96c6\u753b\u9762\u3002ALT-F9\u3067\u30e1\u30cb\u30e5\u30fc\u3001ALT-F10\u3067\u30c4\u30fc\u30eb\u30d0\u30fc\u3001ALT-0\u3067\u30d8\u30eb\u30d7\u304c\u8868\u793a\u3055\u308c\u307e\u3059\u3002", +"Tools": "\u30c4\u30fc\u30eb", +"View": "\u8868\u793a", +"Table": "\u8868", +"Format": "\u66f8\u5f0f" +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/nl.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/nl.js new file mode 100644 index 0000000000..ee1f335624 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/nl.js @@ -0,0 +1,219 @@ +tinymce.addI18n('nl',{ +"Cut": "Knippen", +"Heading 5": "Kop 5", +"Header 2": "Kop 2", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Uw browser ondersteunt geen toegang tot het clipboard. Gelieve ctrl+X\/C\/V sneltoetsen te gebruiken.", +"Heading 4": "Kop 4", +"Div": "Div", +"Heading 2": "Kop 2", +"Paste": "Plakken", +"Close": "Sluiten", +"Font Family": "Lettertype", +"Pre": "Pre", +"Align right": "Rechts uitlijnen", +"New document": "Nieuw document", +"Blockquote": "Quote", +"Numbered list": "Nummering", +"Heading 1": "Kop 1", +"Headings": "Koppen", +"Increase indent": "Inspringen vergroten", +"Formats": "Opmaak", +"Headers": "Kopteksten", +"Select all": "Alles selecteren", +"Header 3": "Kop 3", +"Blocks": "Blok", +"Undo": "Ongedaan maken", +"Strikethrough": "Doorhalen", +"Bullet list": "Opsommingsteken", +"Header 1": "Kop 1", +"Superscript": "Superscript", +"Clear formatting": "Opmaak verwijderen", +"Font Sizes": "Tekengrootte", +"Subscript": "Subscript", +"Header 6": "Kop 6", +"Redo": "Opnieuw", +"Paragraph": "Paragraaf", +"Ok": "Ok\u00e9", +"Bold": "Vet", +"Code": "Code", +"Italic": "Cursief", +"Align center": "Centreren", +"Header 5": "Kop 5", +"Heading 6": "Kop 6", +"Heading 3": "Kop 3", +"Decrease indent": "Inspringen verkleinen", +"Header 4": "Kop 4", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Plakken gebeurt nu als platte tekst. Tekst wordt nu ingevoegd zonder opmaak tot deze optie uitgeschakeld wordt.", +"Underline": "Onderstreept", +"Cancel": "Annuleren", +"Justify": "Uitlijnen", +"Inline": "Inlijn", +"Copy": "Kopi\u00ebren", +"Align left": "Links uitlijnen", +"Visual aids": "Hulpmiddelen", +"Lower Greek": "Griekse letters", +"Square": "Vierkant", +"Default": "Standaard", +"Lower Alpha": "Kleine letters", +"Circle": "Cirkel", +"Disc": "Bolletje", +"Upper Alpha": "Hoofdletters", +"Upper Roman": "Romeinse cijfers groot", +"Lower Roman": "Romeinse cijfers klein", +"Name": "Naam", +"Anchor": "Anker", +"You have unsaved changes are you sure you want to navigate away?": "U hebt niet alles opgeslagen bent u zeker dat u de pagina wenst te verlaten?", +"Restore last draft": "Herstel het laatste concept", +"Special character": "Speciale karakters", +"Source code": "Broncode", +"B": "Blauw", +"R": "Rood", +"G": "Groen", +"Color": "Kleur", +"Right to left": "Rechts naar links", +"Left to right": "Links naar rechts", +"Emoticons": "Emoticons", +"Robots": "Robots", +"Document properties": "Document eigenschappen", +"Title": "Titel", +"Keywords": "Sleutelwoorden", +"Encoding": "Codering", +"Description": "Omschrijving", +"Author": "Auteur", +"Fullscreen": "Volledig scherm", +"Horizontal line": "Horizontale lijn", +"Horizontal space": "Horizontale ruimte", +"Insert\/edit image": "Afbeelding invoegen\/bewerken", +"General": "Algemeen", +"Advanced": "Geavanceerd", +"Source": "Bron", +"Border": "Rand", +"Constrain proportions": "Verhoudingen behouden", +"Vertical space": "Verticale ruimte", +"Image description": "Afbeelding omschrijving", +"Style": "Stijl", +"Dimensions": "Afmetingen", +"Insert image": "Afbeelding invoegen", +"Zoom in": "Inzoomen", +"Contrast": "Contrast", +"Back": "Terug", +"Gamma": "Gamma", +"Flip horizontally": "Horizontaal spiegelen", +"Resize": "Formaat aanpassen", +"Sharpen": "Scherpte", +"Zoom out": "Uitzoomen", +"Image options": "Afbeelding opties", +"Apply": "Toepassen", +"Brightness": "Helderheid", +"Rotate clockwise": "Rechtsom draaien", +"Rotate counterclockwise": "Linksom draaien", +"Edit image": "Bewerk afbeelding", +"Color levels": "Kleurniveau's", +"Crop": "Uitsnijden", +"Orientation": "Orientatie", +"Flip vertically": "Verticaal spiegelen", +"Invert": "Omkeren", +"Insert date\/time": "Voeg datum\/tijd in", +"Remove link": "Link verwijderen", +"Url": "Url", +"Text to display": "Linktekst", +"Anchors": "Anker", +"Insert link": "Hyperlink invoegen", +"New window": "Nieuw venster", +"None": "Geen", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "De ingegeven URL verwijst naar een extern adres. Wil je er \"http:\/\/\" aan toevoegen?", +"Target": "Doel", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "De ingegeven URL lijkt op een e-mailadres. Wil je er \"mailto:\" aan toevoegen?", +"Insert\/edit link": "Hyperlink invoegen\/bewerken", +"Insert\/edit video": "Video invoegen\/bewerken", +"Poster": "Poster", +"Alternative source": "Alternatieve bron", +"Paste your embed code below:": "Plak u in te sluiten code hieronder:", +"Insert video": "Video invoegen", +"Embed": "Insluiten", +"Nonbreaking space": "Vaste spatie invoegen", +"Page break": "Pagina einde", +"Paste as text": "Plakken als tekst", +"Preview": "Voorbeeld", +"Print": "Print", +"Save": "Opslaan", +"Could not find the specified string.": "Geen resultaten gevonden", +"Replace": "Vervangen", +"Next": "Volgende", +"Whole words": "Alleen hele woorden", +"Find and replace": "Zoek en vervang", +"Replace with": "Vervangen door", +"Find": "Zoeken", +"Replace all": "Alles vervangen", +"Match case": "Identieke hoofd\/kleine letters", +"Prev": "Vorige", +"Spellcheck": "Spellingscontrole", +"Finish": "Einde", +"Ignore all": "Alles negeren", +"Ignore": "Negeren", +"Add to Dictionary": "Toevoegen aan woordenlijst", +"Insert row before": "Voeg rij boven toe", +"Rows": "Rijen", +"Height": "Hoogte", +"Paste row after": "Plak rij onder", +"Alignment": "Uitlijning", +"Border color": "Randkleur", +"Column group": "Kolomgroep", +"Row": "Rij", +"Insert column before": "Voeg kolom in voor", +"Split cell": "Cel splitsen", +"Cell padding": "Ruimte binnen cel", +"Cell spacing": "Celruimte", +"Row type": "Rijtype", +"Insert table": "Tabel invoegen", +"Body": "Body", +"Caption": "Onderschrift", +"Footer": "Voettekst", +"Delete row": "Verwijder rij", +"Paste row before": "Plak rij boven", +"Scope": "Bereik", +"Delete table": "Verwijder tabel", +"H Align": "Links uitlijnen", +"Top": "Bovenaan", +"Header cell": "Kopcel", +"Column": "Kolom", +"Row group": "Rijgroep", +"Cell": "Cel", +"Middle": "Centreren", +"Cell type": "Celtype", +"Copy row": "Kopieer rij", +"Row properties": "Rij eigenschappen", +"Table properties": "Tabel eigenschappen", +"Bottom": "Onderaan", +"V Align": "Boven uitlijnen", +"Header": "Koptekst", +"Right": "Rechts", +"Insert column after": "Voeg kolom in na", +"Cols": "Kolommen", +"Insert row after": "Voeg rij onder toe", +"Width": "Breedte", +"Cell properties": "Cel eigenschappen", +"Left": "Links", +"Cut row": "Knip rij", +"Delete column": "Verwijder kolom", +"Center": "Midden", +"Merge cells": "Cellen samenvoegen", +"Insert template": "Sjabloon invoegen", +"Templates": "Sjablonen", +"Background color": "Achtergrondkleur", +"Custom...": "Eigen...", +"Custom color": "Eigen kleur", +"No color": "Geen kleur", +"Text color": "Tekstkleur", +"Show blocks": "Blokken tonen", +"Show invisible characters": "Onzichtbare karakters tonen", +"Words: {0}": "Woorden: {0}", +"Insert": "Invoegen", +"File": "Bestand", +"Edit": "Bewerken", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Rich Text Area. Druk ALT-F9 voor het menu. Druk ALT-F10 voor de toolbar. Druk ALT-0 voor help.", +"Tools": "Gereedschap", +"View": "Beeld", +"Table": "Tabel", +"Format": "Opmaak" +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/no.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/no.js new file mode 100644 index 0000000000..69ded56dab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/no.js @@ -0,0 +1 @@ +tinyMCE.addI18n({no:{common:{"more_colors":"Flere farger","invalid_data":"Feil: Ugyldig verdi er skrevet inn, disse er merket med r\u00f8dt","popup_blocked":"Beklager, men vi har registrert at din popup-sperrer har blokkert et vindu i nettleseren. Du m\u00e5 oppheve popup-sperren for at nettstedet skal f\u00e5 tilgang til dette verkt\u00f8yet","clipboard_no_support":"For tiden ikke st\u00f8ttet av din nettleser, bruk tastatursnarveier i stedet.","clipboard_msg":"Klipp ut / Kopier /Lim inn fungerer ikke i Mozilla og Firefox. Vil du vite mer om dette?","not_set":"--Ikke satt--","class_name":"Klasse",browse:"Bla gjennom",close:"Lukk",cancel:"Avbryt",update:"Oppdater",insert:"Sett inn",apply:"Bruk","edit_confirm":"Vil du bruke WYSIWYG-editoren for dette tekstfeltet?","invalid_data_number":"{#field} m\u00e5 v\u00e6re et nummer","invalid_data_min":"{#field} m\u00e5 v\u00e6re et nummber st\u00f8rre en {#min}","invalid_data_size":"{#field} m\u00e5 v\u00e6re et nummer eller prosent av",value:"(verdi)"},contextmenu:{full:"Full",right:"H\u00f8yre",center:"Midtstilt",left:"Venstre",align:"Justering"},insertdatetime:{"day_short":"S\u00f8n,Man,Tir,Ons,Tor,Fre,L\u00f8r,S\u00f8n","day_long":"s\u00f8ndag,mandag,tirsdag,onsdag,torsdag,fredag,l\u00f8rdag,s\u00f8ndag","months_short":"jan,feb,mar,apr,mai,jun,jul,aug,sep,okt,nov,des","months_long":"januar,februar,mars,april,mai,juni,juli,august,september,oktober,november,desember","inserttime_desc":"Sett inn tid","insertdate_desc":"Sett inn dato","time_fmt":"%H:%M:%S","date_fmt":"%d-%m-%Y"},print:{"print_desc":"Skriv ut"},preview:{"preview_desc":"Forh\u00e5ndsvisning"},directionality:{"rtl_desc":"Retning h\u00f8yre mot venstre","ltr_desc":"Retning venstre mot h\u00f8yre"},layer:{content:"Nytt lag ...","absolute_desc":"Sl\u00e5 p\u00e5/av absolutt plassering","backward_desc":"Flytt bakover","forward_desc":"Flytt fremover","insertlayer_desc":"Sett inn nytt lag"},save:{"save_desc":"Lagre","cancel_desc":"Kanseller alle endringer"},nonbreaking:{"nonbreaking_desc":"Sett inn tegn for hardt mellomrom"},iespell:{download:"ieSpell ikke funnet. \u00d8nsker du \u00e5 installere ieSpell?","iespell_desc":"Stavekontroll"},advhr:{"advhr_desc":"Horisontal linje","delta_height":"","delta_width":""},emotions:{"emotions_desc":"Hum\u00f8rfjes","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"S\u00f8k/Erstatt","search_desc":"S\u00f8k","delta_width":"","delta_height":""},advimage:{"image_desc":"Sett inn / rediger bilde","delta_width":"","delta_height":""},advlink:{"link_desc":"Sett inn / rediger lenke","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"Sett inn / rediger attributter","ins_desc":"Innsetting","del_desc":"Sletting","acronym_desc":"Akronym","abbr_desc":"Forkortelse","cite_desc":"Sitat","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"Rediger CSS-stil","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Lim inn er n\u00e5 i vanlig tekst modus. Klikk igjen for \u00e5 bytte til vanlig innlimings modus.","plaintext_mode_sticky":"Lim inn er n\u00e5 i vanlig tekst modus. Klikk igjen for \u00e5 bytte til vanlig innlimings modus. Etter at du limer inn noe vil du g\u00e5 tilbake til ordin\u00e6r innliming.","selectall_desc":"Merk alt","paste_word_desc":"Lim inn fra Word","paste_text_desc":"Lim inn som ren tekst"},"paste_dlg":{"word_title":"Bruk CTRL+V p\u00e5 tastaturet for \u00e5 lime inn teksten i dette vinduet.","text_linebreaks":"Behold tekstbryting","text_title":"Bruk CTRL+V p\u00e5 tastaturet for \u00e5 lime inn teksten i dette vinduet."},table:{cell:"Celle",col:"Kolonne",row:"Rad",del:"Slett tabell","copy_row_desc":"Kopier rad","cut_row_desc":"Slett rad","paste_row_after_desc":"Lim inn rad etter","paste_row_before_desc":"Lim inn rad foran","props_desc":"Tabellegenskaper","cell_desc":"Celleegenskaper","row_desc":"Radegenskaper","merge_cells_desc":"Sl\u00e5 sammen celler","split_cells_desc":"Splitt sammensl\u00e5tte celler","delete_col_desc":"Slett kolonne","col_after_desc":"Sett inn kolonne etter","col_before_desc":"Sett inn kolonne foran","delete_row_desc":"Slett rad","row_after_desc":"Sett inn rad etter","row_before_desc":"Sett inn rad foran",desc:"Sett inn ny tabell","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Hvis du gjenoppretter tidligere lagret innhold s\u00e5 vil du miste alt n\u00e5v\u00e6rende innhold i editoren.\n\nEr du sikker p\u00e5 at du vil gjenopprette tidligere lagret innhold?.","restore_content":"Gjenopprett autolagret innhold.","unload_msg":"Utf\u00f8rte endringer g\u00e5r tapt hvis du navigerer vekk fra denne siden!"},fullscreen:{desc:"Sl\u00e5 fullskjermsmodus av/p\u00e5"},media:{edit:"Rediger innebygd objekt",desc:"Sett inn / rediger innebygd objekt","delta_height":"","delta_width":""},fullpage:{desc:"Dokumentegenskaper","delta_width":"","delta_height":""},template:{desc:"Sett inn forh\u00e5ndsdefinert malinnhold"},visualchars:{desc:"Visuelle konktrolltegn p\u00e5/av"},spellchecker:{desc:"Stavekontroll p\u00e5/av",menu:"Oppsett stavekontroll","ignore_word":"Ignorer ord","ignore_words":"Ignorer alt",langs:"Spr\u00e5k",wait:"Vennligst vent ...",sug:"Forslag","no_sug":"Ingen forslag","no_mpell":"Ingen stavefeil funnet.","learn_word":"L\u00e6r ordet"},pagebreak:{desc:"Sett inn sideskift"},advlist:{types:"Types",def:"Standard","lower_alpha":"Sm\u00e5 alfanumerisk","lower_greek":"Sm\u00e5 gresk","lower_roman":"Sm\u00e5 roman","upper_alpha":"Store alfanumerisk","upper_roman":"Store roman",circle:"Sirkel",disc:"Plate",square:"Firkant"},colors:{"333300":"M\u00f8rk olivengr\u00f8nn","993300":"Brent oransje","000000":"Svart","003300":"M\u00f8rkegr\u00f8nn","003366":"M\u00f8rk asurbl\u00e5","000080":"Marinebl\u00e5","333399":"Indigobl\u00e5","333333":"M\u00f8rk m\u00f8rkegr\u00e5","800000":"R\u00f8dbrun",FF6600:"Oransje","808000":"Olivengr\u00f8nn","008000":"Gr\u00f8nn","008080":"M\u00f8rk gr\u00f8nnbl\u00e5","0000FF":"Bl\u00e5","666699":"Gr\u00e5bl\u00e5","808080":"Gr\u00e5",FF0000:"R\u00f8d",FF9900:"Amber","99CC00":"Gulgr\u00f8nn","339966":"Havgr\u00f8nn","33CCCC":"Turkis","3366FF":"Kongebl\u00e5","800080":"Purpur","999999":"Medium gr\u00e5",FF00FF:"Magentar\u00f8d",FFCC00:"Gull",FFFF00:"Gul","00FF00":"Limegr\u00f8nn","00FFFF":"Cyanbl\u00e5","00CCFF":"Himmelbl\u00e5","993366":"Brun",C0C0C0:"S\u00f8lv",FF99CC:"Rosa",FFCC99:"Fersken",FFFF99:"Lysgul",CCFFCC:"Lysegr\u00f8nn",CCFFFF:"Lys cyanbl\u00e5","99CCFF":"Lys himmelbl\u00e5",CC99FF:"Plomme",FFFFFF:"Hvit"},aria:{"rich_text_area":"Rikt tekstfelt"},wordcount:{words:"Ord:"}}}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/pl.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/pl.js new file mode 100644 index 0000000000..b80cb7bc95 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/pl.js @@ -0,0 +1,219 @@ +tinymce.addI18n('pl',{ +"Cut": "Wytnij", +"Heading 5": "Nag\u0142\u00f3wek 5", +"Header 2": "Nag\u0142\u00f3wek 2", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "Twoja przegl\u0105darka nie obs\u0142uguje bezpo\u015bredniego dost\u0119pu do schowka. U\u017cyj zamiast tego kombinacji klawiszy Ctrl+X\/C\/V.", +"Heading 4": "Nag\u0142\u00f3wek 4", +"Div": "Div", +"Heading 2": "Nag\u0142\u00f3wek 2", +"Paste": "Wklej", +"Close": "Zamknij", +"Font Family": "Kr\u00f3j fontu", +"Pre": "Sformatowany tekst", +"Align right": "Wyr\u00f3wnaj do prawej", +"New document": "Nowy dokument", +"Blockquote": "Blok cytatu", +"Numbered list": "Lista numerowana", +"Heading 1": "Nag\u0142\u00f3wek 1", +"Headings": "Nag\u0142\u00f3wki", +"Increase indent": "Zwi\u0119ksz wci\u0119cie", +"Formats": "Formaty", +"Headers": "Nag\u0142\u00f3wki", +"Select all": "Zaznacz wszystko", +"Header 3": "Nag\u0142\u00f3wek 3", +"Blocks": "Bloki", +"Undo": "Cofnij", +"Strikethrough": "Przekre\u015blenie", +"Bullet list": "Lista wypunktowana", +"Header 1": "Nag\u0142\u00f3wek 1", +"Superscript": "Indeks g\u00f3rny", +"Clear formatting": "Wyczy\u015b\u0107 formatowanie", +"Font Sizes": "Rozmiar fontu", +"Subscript": "Indeks dolny", +"Header 6": "Nag\u0142\u00f3wek 6", +"Redo": "Pon\u00f3w", +"Paragraph": "Akapit", +"Ok": "Ok", +"Bold": "Pogrubienie", +"Code": "Kod \u017ar\u00f3d\u0142owy", +"Italic": "Kursywa", +"Align center": "Wyr\u00f3wnaj do \u015brodka", +"Header 5": "Nag\u0142\u00f3wek 5", +"Heading 6": "Nag\u0142\u00f3wek 6", +"Heading 3": "Nag\u0142\u00f3wek 3", +"Decrease indent": "Zmniejsz wci\u0119cie", +"Header 4": "Nag\u0142\u00f3wek 4", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "Wklejanie jest w trybie tekstowym. Zawarto\u015b\u0107 zostanie wklejona jako zwyk\u0142y tekst dop\u00f3ki nie wy\u0142\u0105czysz tej opcji.", +"Underline": "Podkre\u015blenie", +"Cancel": "Anuluj", +"Justify": "Do lewej i prawej", +"Inline": "W tek\u015bcie", +"Copy": "Kopiuj", +"Align left": "Wyr\u00f3wnaj do lewej", +"Visual aids": "Pomoce wizualne", +"Lower Greek": "Ma\u0142e greckie", +"Square": "Kwadrat", +"Default": "Domy\u015blne", +"Lower Alpha": "Ma\u0142e litery", +"Circle": "K\u00f3\u0142ko", +"Disc": "Dysk", +"Upper Alpha": "Wielkie litery", +"Upper Roman": "Wielkie rzymskie", +"Lower Roman": "Ma\u0142e rzymskie", +"Name": "Nazwa", +"Anchor": "Kotwica", +"You have unsaved changes are you sure you want to navigate away?": "Masz niezapisane zmiany. Czy na pewno chcesz opu\u015bci\u0107 stron\u0119?", +"Restore last draft": "Przywr\u00f3\u0107 ostatni szkic", +"Special character": "Znak specjalny", +"Source code": "Kod \u017ar\u00f3d\u0142owy", +"B": "B", +"R": "R", +"G": "G", +"Color": "Kolor", +"Right to left": "Od prawej do lewej", +"Left to right": "Od lewej do prawej", +"Emoticons": "Ikony emocji", +"Robots": "Roboty", +"Document properties": "W\u0142a\u015bciwo\u015bci dokumentu", +"Title": "Tytu\u0142", +"Keywords": "S\u0142owa kluczowe", +"Encoding": "Kodowanie", +"Description": "Opis", +"Author": "Autor", +"Fullscreen": "Pe\u0142ny ekran", +"Horizontal line": "Pozioma linia", +"Horizontal space": "Odst\u0119p poziomy", +"Insert\/edit image": "Wstaw\/edytuj obrazek", +"General": "Og\u00f3lne", +"Advanced": "Zaawansowane", +"Source": "\u0179r\u00f3d\u0142o", +"Border": "Ramka", +"Constrain proportions": "Zachowaj proporcje", +"Vertical space": "Odst\u0119p pionowy", +"Image description": "Opis obrazka", +"Style": "Styl", +"Dimensions": "Wymiary", +"Insert image": "Wstaw obrazek", +"Zoom in": "Powi\u0119ksz", +"Contrast": "Kontrast", +"Back": "Cofnij", +"Gamma": "Gamma", +"Flip horizontally": "Przerzu\u0107 w poziomie", +"Resize": "Zmiana rozmiaru", +"Sharpen": "Wyostrz", +"Zoom out": "Pomniejsz", +"Image options": "Opcje obrazu", +"Apply": "Zaakceptuj", +"Brightness": "Jasno\u015b\u0107", +"Rotate clockwise": "Obr\u00f3\u0107 w prawo", +"Rotate counterclockwise": "Obr\u00f3\u0107 w lewo", +"Edit image": "Edytuj obrazek", +"Color levels": "Poziom koloru", +"Crop": "Przytnij", +"Orientation": "Orientacja", +"Flip vertically": "Przerzu\u0107 w pionie", +"Invert": "Odwr\u00f3\u0107", +"Insert date\/time": "Wstaw dat\u0119\/czas", +"Remove link": "Usu\u0144 \u0142\u0105cze", +"Url": "URL", +"Text to display": "Tekst do wy\u015bwietlenia", +"Anchors": "Kotwice", +"Insert link": "Wstaw \u0142\u0105cze", +"New window": "Nowe okno", +"None": "\u017baden", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "URL, kt\u00f3ry wprowadzi\u0142e\u015b wygl\u0105da na link zewn\u0119trzny. Czy chcesz doda\u0107 http:\/\/ jako prefiks?", +"Target": "Cel", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "URL, kt\u00f3ry wprowadzi\u0142e\u015b wygl\u0105da na adres e-mail. Czy chcesz doda\u0107 mailto: jako prefiks?", +"Insert\/edit link": "Wstaw\/edytuj \u0142\u0105cze", +"Insert\/edit video": "Wstaw\/edytuj wideo", +"Poster": "Plakat", +"Alternative source": "Alternatywne \u017ar\u00f3d\u0142o", +"Paste your embed code below:": "Wklej tutaj kod do osadzenia:", +"Insert video": "Wstaw wideo", +"Embed": "Osad\u017a", +"Nonbreaking space": "Nie\u0142amliwa spacja", +"Page break": "Podzia\u0142 strony", +"Paste as text": "Wklej jako zwyk\u0142y tekst", +"Preview": "Podgl\u0105d", +"Print": "Drukuj", +"Save": "Zapisz", +"Could not find the specified string.": "Nie znaleziono szukanego tekstu.", +"Replace": "Zamie\u0144", +"Next": "Nast.", +"Whole words": "Ca\u0142e s\u0142owa", +"Find and replace": "Znajd\u017a i zamie\u0144", +"Replace with": "Zamie\u0144 na", +"Find": "Znajd\u017a", +"Replace all": "Zamie\u0144 wszystko", +"Match case": "Dopasuj wielko\u015b\u0107 liter", +"Prev": "Poprz.", +"Spellcheck": "Sprawdzanie pisowni", +"Finish": "Zako\u0144cz", +"Ignore all": "Ignoruj wszystko", +"Ignore": "Ignoruj", +"Add to Dictionary": "Dodaj do s\u0142ownika", +"Insert row before": "Wstaw wiersz przed", +"Rows": "Wiersz.", +"Height": "Wysoko\u015b\u0107", +"Paste row after": "Wklej wiersz po", +"Alignment": "Wyr\u00f3wnanie", +"Border color": "Kolor ramki", +"Column group": "Grupa kolumn", +"Row": "Wiersz", +"Insert column before": "Wstaw kolumn\u0119 przed", +"Split cell": "Podziel kom\u00f3rk\u0119", +"Cell padding": "Dope\u0142nienie kom\u00f3rki", +"Cell spacing": "Odst\u0119py kom\u00f3rek", +"Row type": "Typ wiersza", +"Insert table": "Wstaw tabel\u0119", +"Body": "Tre\u015b\u0107", +"Caption": "Tytu\u0142", +"Footer": "Stopka", +"Delete row": "Usu\u0144 wiersz", +"Paste row before": "Wklej wiersz przed", +"Scope": "Kontekst", +"Delete table": "Usu\u0144 tabel\u0119", +"H Align": "Wyr\u00f3wnanie w pionie", +"Top": "G\u00f3ra", +"Header cell": "Kom\u00f3rka nag\u0142\u00f3wka", +"Column": "Kolumna", +"Row group": "Grupa wierszy", +"Cell": "Kom\u00f3rka", +"Middle": "\u015arodek", +"Cell type": "Typ kom\u00f3rki", +"Copy row": "Kopiuj wiersz", +"Row properties": "W\u0142a\u015bciwo\u015bci wiersza", +"Table properties": "W\u0142a\u015bciwo\u015bci tabeli", +"Bottom": "D\u00f3\u0142", +"V Align": "Wyr\u00f3wnanie w poziomie", +"Header": "Nag\u0142\u00f3wek", +"Right": "Prawo", +"Insert column after": "Wstaw kolumn\u0119 po", +"Cols": "Kol.", +"Insert row after": "Wstaw wiersz po", +"Width": "Szeroko\u015b\u0107", +"Cell properties": "W\u0142a\u015bciwo\u015bci kom\u00f3rki", +"Left": "Lewo", +"Cut row": "Wytnij wiersz", +"Delete column": "Usu\u0144 kolumn\u0119", +"Center": "\u015arodek", +"Merge cells": "\u0141\u0105cz kom\u00f3rki", +"Insert template": "Wstaw szablon", +"Templates": "Szablony", +"Background color": "Kolor t\u0142a", +"Custom...": "Niestandardowy...", +"Custom color": "Kolor niestandardowy", +"No color": "Bez koloru", +"Text color": "Kolor tekstu", +"Show blocks": "Poka\u017c bloki", +"Show invisible characters": "Poka\u017c niewidoczne znaki", +"Words: {0}": "S\u0142\u00f3w: {0}", +"Insert": "Wstaw", +"File": "Plik", +"Edit": "Edycja", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "Obszar Edycji. ALT-F9 - menu. ALT-F10 - pasek narz\u0119dzi. ALT-0 - pomoc", +"Tools": "Narz\u0119dzia", +"View": "Widok", +"Table": "Tabela", +"Format": "Format" +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/pt.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/pt.js new file mode 100644 index 0000000000..809f1c2d9b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/pt.js @@ -0,0 +1 @@ +tinyMCE.addI18n({pt:{common:{"more_colors":"Mais Cores","invalid_data":"Erro: Valores inv\u00e1lidos marcados em vermelho.","popup_blocked":"Detectamos que o seu bloqueador de popups bloqueou uma janela que \u00e9 essencial para a aplica\u00e7\u00e3o. Voc\u00ea precisa desativar o bloqueador de janelas de popups para utilizar esta ferramenta.","clipboard_no_support":"O seu browser n\u00e3o suporta esta fun\u00e7\u00e3o, use os atalhos do teclado.","clipboard_msg":"Copiar/recortar/colar n\u00e3o est\u00e1 dispon\u00edvel no Mozilla e Firefox. Deseja mais informa\u00e7\u00f5es sobre este problema?","not_set":"-- N/A --","class_name":"Classe",browse:"Procurar",close:"Fechar",cancel:"Cancelar",update:"Atualizar",insert:"Inserir",apply:"Aplicar","edit_confirm":"Deseja usar o modo de edi\u00e7\u00e3o avan\u00e7ado neste campo de texto?","invalid_data_number":"{#field} deve ser um n\u00famero","invalid_data_min":"{#field} deve ser um n\u00famero maior que {#min}","invalid_data_size":"{#field} deve ser um n\u00famero ou uma percentagem",value:"(valor)"},contextmenu:{full:"Justificado",right:"Direita",center:"Centro",left:"Esquerda",align:"Alinhamento"},insertdatetime:{"day_short":"Dom,Seg,Ter,Qua,Qui,Sex,Sab,Dom","day_long":"Domingo,Segunda-feira,Ter\u00e7a-feira,Quarta-feira,Quinta-feira,Sexta-feira,S\u00e1bado,Domingo","months_short":"Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez","months_long":"Janeiro,Fevereiro,Mar\u00e7o,Abril,Maio,Junho,Julho,Agosto,Setembro,Outubro,Novembro,Dezembro","inserttime_desc":"Inserir hora","insertdate_desc":"Inserir data","time_fmt":"%H:%M:%S","date_fmt":"%d-%m-%Y"},print:{"print_desc":"Imprimir"},preview:{"preview_desc":"Pr\u00e9-visualizar"},directionality:{"rtl_desc":"Da direita para esquerda","ltr_desc":"Da esquerda para direita"},layer:{content:"Nova camada...","absolute_desc":"Alternar o posicionamento absoluto","backward_desc":"Mover para tr\u00e1s","forward_desc":"Mover para frente","insertlayer_desc":"Inserir nova camada"},save:{"save_desc":"Salvar","cancel_desc":"Cancelar todas as altera\u00e7\u00f5es"},nonbreaking:{"nonbreaking_desc":"Inserir um espa\u00e7o \"sem quebra\""},iespell:{download:"Plugin de ortografia n\u00e3o-detectado. Deseja instalar agora?","iespell_desc":"Verificar ortografia"},advhr:{"advhr_desc":"Separador horizontal","delta_height":"","delta_width":""},emotions:{"emotions_desc":"Emoticons","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"Localizar/substituir","search_desc":"Localizar","delta_width":"","delta_height":""},advimage:{"image_desc":"Inserir/editar imagem","delta_width":"","delta_height":""},advlink:{"delta_width":"50","link_desc":"Inserir/editar hyperlink","delta_height":""},xhtmlxtras:{"attribs_desc":"Inserir/Editar atributos","ins_desc":"Inserir","del_desc":"Apagar","acronym_desc":"Acr\u00f4nimo","abbr_desc":"Abrevia\u00e7\u00e3o","cite_desc":"Cita\u00e7\u00e3o","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"Editar CSS","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Comando colar est\u00e1 em modo texto simples. Clique novamente para voltar para o modo normal.","plaintext_mode_sticky":"Comando colar est\u00e1 em modo texto simples. Clique novamente para voltar para o modo normal. Depois de colar alguma coisa retornar\u00e1 para o modo normal.","selectall_desc":"Selecionar tudo","paste_word_desc":"Colar (copiado do WORD)","paste_text_desc":"Colar como texto simples"},"paste_dlg":{"word_title":"Use CTRL+V para colar o texto na janela.","text_linebreaks":"Manter quebras de linha","text_title":"Use CTRL+V para colar o texto na janela."},table:{cell:"C\u00e9lula",col:"Coluna",row:"Linha",del:"Apagar tabela","copy_row_desc":"Copiar linha","cut_row_desc":"Recortar linha","paste_row_after_desc":"Colar linha depois","paste_row_before_desc":"Colar linha antes","props_desc":"Propriedades da tabela","cell_desc":"Propriedades das c\u00e9lulas","row_desc":"Propriedades das linhas","merge_cells_desc":"Unir c\u00e9lulas","split_cells_desc":"Dividir c\u00e9lulas","delete_col_desc":"Remover coluna","col_after_desc":"Inserir coluna depois","col_before_desc":"Inserir coluna antes","delete_row_desc":"Apagar linha","row_after_desc":"Inserir linha depois","row_before_desc":"Inserir linha antes",desc:"Inserir nova tabela","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Se restaurar o conte\u00fado, voc\u00ea ir\u00e1 perder tudo que est\u00e1 atualmente no editor.\n\nTem certeza que quer restaurar o conte\u00fado salvo?","restore_content":"Restaura conte\u00fado salvo automaticamente.","unload_msg":"As mudan\u00e7as efetuadas ser\u00e3o perdidas se sair desta p\u00e1gina."},fullscreen:{desc:"Tela Inteira"},media:{edit:"Editar m\u00eddia embutida",desc:"Inserir/Editar m\u00eddia embutida","delta_height":"","delta_width":""},fullpage:{desc:"Propriedades do Documento","delta_width":"","delta_height":""},template:{desc:"Inserir template"},visualchars:{desc:"Caracteres de controle visual ligado/desligado"},spellchecker:{desc:"Alternar verifica\u00e7\u00e3o ortogr\u00e1fica",menu:"Configura\u00e7\u00f5es de ortografia","ignore_word":"Ignorar palavra","ignore_words":"Ignorar tudo",langs:"Linguagens",wait:"Aguarde...",sug:"Sugest\u00f5es","no_sug":"Sem sugest\u00f5es","no_mpell":"N\u00e3o foram detectados erros de ortografia.","learn_word":"Aprender palavra"},pagebreak:{desc:"Inserir quebra de p\u00e1gina."},advlist:{types:"Tipos",def:"Padr\u00e3o","lower_alpha":"Alfabeto min\u00fasculo","lower_greek":"Alfabeto grego","lower_roman":"Num. romanos min\u00fasculos","upper_alpha":"Alfabeto mai\u00fasculos","upper_roman":"Num. romanos mai\u00fasculos",circle:"C\u00edrculo",disc:"Disco",square:"Quadrado"},colors:{"333300":"Oliva escuro","993300":"Laranja queimado","000000":"Preto","003300":"Verde escuro","003366":"Azul escuro","000080":"Azul marinho","333399":"\u00cdndigo","333333":"Cinza muito escuro","800000":"Marrom 1",FF6600:"Laranja","808000":"Oliva","008000":"Verde","008080":"Verde azulado","0000FF":"Azul","666699":"Azul acinzentado","808080":"Cinza",FF0000:"Vermelho",FF9900:"\u00c2mbar","99CC00":"Amarelo esverdeado","339966":"Verde mar","33CCCC":"Turquesa","3366FF":"Azul real","800080":"Roxo","999999":"Cinza m\u00e9dio",FF00FF:"Magenta",FFCC00:"Ouro",FFFF00:"Amarelo","00FF00":"Lima","00FFFF":"\u00c1gua","00CCFF":"Azul celeste","993366":"Marrom 2",C0C0C0:"Prata",FF99CC:"Rosa",FFCC99:"P\u00eassego",FFFF99:"Amarelo claro",CCFFCC:"Verde p\u00e1lido",CCFFFF:"Ciano p\u00e1lido","99CCFF":"Azul celeste claro",CC99FF:"Ameixa",FFFFFF:"Branco"},aria:{"rich_text_area":"\u00c1rea de texto rico"},wordcount:{words:"Palavras:"}}}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/ru.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/ru.js new file mode 100644 index 0000000000..110a978002 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/ru.js @@ -0,0 +1,219 @@ +tinymce.addI18n('ru',{ +"Cut": "\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c", +"Heading 5": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 5", +"Header 2": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 2", +"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "\u0412\u0430\u0448 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u044f\u043c\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0431\u0443\u0444\u0435\u0440\u0443 \u043e\u0431\u043c\u0435\u043d\u0430. \u041f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u043e\u0447\u0435\u0442\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0432\u0438\u0448: Ctrl+X\/C\/V.", +"Heading 4": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 4", +"Div": "\u0411\u043b\u043e\u043a", +"Heading 2": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 2", +"Paste": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c", +"Close": "\u0417\u0430\u043a\u0440\u044b\u0442\u044c", +"Font Family": "\u0428\u0440\u0438\u0444\u0442", +"Pre": "\u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435", +"Align right": "\u041f\u043e \u043f\u0440\u0430\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e", +"New document": "\u041d\u043e\u0432\u044b\u0439 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442", +"Blockquote": "\u0426\u0438\u0442\u0430\u0442\u0430", +"Numbered list": "\u041d\u0443\u043c\u0435\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a", +"Heading 1": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 1", +"Headings": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438", +"Increase indent": "\u0423\u0432\u0435\u043b\u0438\u0447\u0438\u0442\u044c \u043e\u0442\u0441\u0442\u0443\u043f", +"Formats": "\u0424\u043e\u0440\u043c\u0430\u0442", +"Headers": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438", +"Select all": "\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u0441\u0435", +"Header 3": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 3", +"Blocks": "\u0411\u043b\u043e\u043a\u0438", +"Undo": "\u0412\u0435\u0440\u043d\u0443\u0442\u044c", +"Strikethrough": "\u0417\u0430\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044b\u0439", +"Bullet list": "\u041c\u0430\u0440\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0438\u0441\u043e\u043a", +"Header 1": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 1", +"Superscript": "\u0412\u0435\u0440\u0445\u043d\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441", +"Clear formatting": "\u041e\u0447\u0438\u0441\u0442\u0438\u0442\u044c \u0444\u043e\u0440\u043c\u0430\u0442", +"Font Sizes": "\u0420\u0430\u0437\u043c\u0435\u0440 \u0448\u0440\u0438\u0444\u0442\u0430", +"Subscript": "\u041d\u0438\u0436\u043d\u0438\u0439 \u0438\u043d\u0434\u0435\u043a\u0441", +"Header 6": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 6", +"Redo": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c", +"Paragraph": "\u041f\u0430\u0440\u0430\u0433\u0440\u0430\u0444", +"Ok": "\u041e\u043a", +"Bold": "\u041f\u043e\u043b\u0443\u0436\u0438\u0440\u043d\u044b\u0439", +"Code": "\u041a\u043e\u0434", +"Italic": "\u041a\u0443\u0440\u0441\u0438\u0432", +"Align center": "\u041f\u043e \u0446\u0435\u043d\u0442\u0440\u0443", +"Header 5": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 5", +"Heading 6": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 6", +"Heading 3": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 3", +"Decrease indent": "\u0423\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u043e\u0442\u0441\u0442\u0443\u043f", +"Header 4": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a 4", +"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\u0412\u0441\u0442\u0430\u0432\u043a\u0430 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0442\u0435\u043a\u0441\u0442\u0430, \u043f\u043e\u043a\u0430 \u043d\u0435 \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u043e\u043f\u0446\u0438\u044e.", +"Underline": "\u041f\u043e\u0434\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044b\u0439", +"Cancel": "\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c", +"Justify": "\u041f\u043e \u0448\u0438\u0440\u0438\u043d\u0435", +"Inline": "\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435", +"Copy": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c", +"Align left": "\u041f\u043e \u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e", +"Visual aids": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u0442\u0443\u0440\u044b", +"Lower Greek": "\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435 \u0433\u0440\u0435\u0447\u0435\u0441\u043a\u0438\u0435 \u0431\u0443\u043a\u0432\u044b", +"Square": "\u041a\u0432\u0430\u0434\u0440\u0430\u0442\u044b", +"Default": "\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439", +"Lower Alpha": "\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435 \u043b\u0430\u0442\u0438\u043d\u0441\u043a\u0438\u0435 \u0431\u0443\u043a\u0432\u044b", +"Circle": "\u041e\u043a\u0440\u0443\u0436\u043d\u043e\u0441\u0442\u0438", +"Disc": "\u041a\u0440\u0443\u0433\u0438", +"Upper Alpha": "\u0417\u0430\u0433\u043b\u0430\u0432\u043d\u044b\u0435 \u043b\u0430\u0442\u0438\u043d\u0441\u043a\u0438\u0435 \u0431\u0443\u043a\u0432\u044b", +"Upper Roman": "\u0417\u0430\u0433\u043b\u0430\u0432\u043d\u044b\u0435 \u0440\u0438\u043c\u0441\u043a\u0438\u0435 \u0446\u0438\u0444\u0440\u044b", +"Lower Roman": "\u0421\u0442\u0440\u043e\u0447\u043d\u044b\u0435 \u0440\u0438\u043c\u0441\u043a\u0438\u0435 \u0446\u0438\u0444\u0440\u044b", +"Name": "\u0418\u043c\u044f", +"Anchor": "\u042f\u043a\u043e\u0440\u044c", +"You have unsaved changes are you sure you want to navigate away?": "\u0423 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f. \u0412\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435 \u0443\u0439\u0442\u0438?", +"Restore last draft": "\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430", +"Special character": "\u0421\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b", +"Source code": "\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434", +"B": "B", +"R": "R", +"G": "G", +"Color": "\u0426\u0432\u0435\u0442", +"Right to left": "\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0430\u043b\u0435\u0432\u043e", +"Left to right": "\u041d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e", +"Emoticons": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043c\u0430\u0439\u043b", +"Robots": "\u0420\u043e\u0431\u043e\u0442\u044b", +"Document properties": "\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430", +"Title": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a", +"Keywords": "\u041a\u043b\u044e\u0447\u0438\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430", +"Encoding": "\u041a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430", +"Description": "\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435", +"Author": "\u0410\u0432\u0442\u043e\u0440", +"Fullscreen": "\u041f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c", +"Horizontal line": "\u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u043b\u0438\u043d\u0438\u044f", +"Horizontal space": "\u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b", +"Insert\/edit image": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c\/\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435", +"General": "\u041e\u0431\u0449\u0435\u0435", +"Advanced": "\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u0435", +"Source": "\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a", +"Border": "\u0420\u0430\u043c\u043a\u0430", +"Constrain proportions": "\u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u0438", +"Vertical space": "\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b", +"Image description": "\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f", +"Style": "\u0421\u0442\u0438\u043b\u044c", +"Dimensions": "\u0420\u0430\u0437\u043c\u0435\u0440", +"Insert image": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435", +"Zoom in": "\u041f\u0440\u0438\u0431\u043b\u0438\u0437\u0438\u0442\u044c", +"Contrast": "\u041a\u043e\u043d\u0442\u0440\u0430\u0441\u0442", +"Back": "\u041d\u0430\u0437\u0430\u0434", +"Gamma": "\u0413\u0430\u043c\u043c\u0430", +"Flip horizontally": "\u041e\u0442\u0440\u0430\u0437\u0438\u0442\u044c \u043f\u043e \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438", +"Resize": "\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440", +"Sharpen": "\u0427\u0435\u0442\u043a\u043e\u0441\u0442\u044c", +"Zoom out": "\u041e\u0442\u0434\u0430\u043b\u0438\u0442\u044c", +"Image options": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f", +"Apply": "\u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c", +"Brightness": "\u042f\u0440\u043a\u043e\u0441\u0442\u044c", +"Rotate clockwise": "\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u043e \u0447\u0430\u0441\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0435\u043b\u043a\u0435", +"Rotate counterclockwise": "\u041f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u043e\u0442\u0438\u0432 \u0447\u0430\u0441\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0435\u043b\u043a\u0438", +"Edit image": "\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435", +"Color levels": "\u0426\u0432\u0435\u0442\u043e\u0432\u044b\u0435 \u0443\u0440\u043e\u0432\u043d\u0438", +"Crop": "\u041e\u0431\u0440\u0435\u0437\u0430\u0442\u044c", +"Orientation": "\u041e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u044f", +"Flip vertically": "\u041e\u0442\u0440\u0430\u0437\u0438\u0442\u044c \u043f\u043e \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438", +"Invert": "\u0418\u043d\u0432\u0435\u0440\u0441\u0438\u044f", +"Insert date\/time": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u0430\u0442\u0443\/\u0432\u0440\u0435\u043c\u044f", +"Remove link": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443", +"Url": "\u0410\u0434\u0440\u0435\u0441 \u0441\u0441\u044b\u043b\u043a\u0438", +"Text to display": "\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0439 \u0442\u0435\u043a\u0441\u0442", +"Anchors": "\u042f\u043a\u043e\u0440\u044f", +"Insert link": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443", +"New window": "\u0412 \u043d\u043e\u0432\u043e\u043c \u043e\u043a\u043d\u0435", +"None": "\u041d\u0435\u0442", +"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\u0412\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0439 URL \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u043d\u0435\u0448\u043d\u0435\u0439 \u0441\u0441\u044b\u043b\u043a\u043e\u0439. \u0412\u044b \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u00abhttp:\/\/\u00bb?", +"Target": "\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443", +"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\u0412\u0432\u0435\u0434\u0451\u043d\u043d\u044b\u0439 URL \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b. \u0412\u044b \u0436\u0435\u043b\u0430\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u00abmailto:\u00bb?", +"Insert\/edit link": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c\/\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443", +"Insert\/edit video": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c\/\u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0438\u0434\u0435\u043e", +"Poster": "\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435", +"Alternative source": "\u0410\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a", +"Paste your embed code below:": "\u0412\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u0432\u0430\u0448 \u043a\u043e\u0434 \u043d\u0438\u0436\u0435:", +"Insert video": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u0438\u0434\u0435\u043e", +"Embed": "\u041a\u043e\u0434 \u0434\u043b\u044f \u0432\u0441\u0442\u0430\u0432\u043a\u0438", +"Nonbreaking space": "\u041d\u0435\u0440\u0430\u0437\u0440\u044b\u0432\u043d\u044b\u0439 \u043f\u0440\u043e\u0431\u0435\u043b", +"Page break": "\u0420\u0430\u0437\u0440\u044b\u0432 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b", +"Paste as text": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u043a \u0442\u0435\u043a\u0441\u0442", +"Preview": "\u041f\u0440\u0435\u0434\u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440", +"Print": "\u041f\u0435\u0447\u0430\u0442\u044c", +"Save": "\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c", +"Could not find the specified string.": "\u0417\u0430\u0434\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430", +"Replace": "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c", +"Next": "\u0412\u043d\u0438\u0437", +"Whole words": "\u0421\u043b\u043e\u0432\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c", +"Find and replace": "\u041f\u043e\u0438\u0441\u043a \u0438 \u0437\u0430\u043c\u0435\u043d\u0430", +"Replace with": "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u043d\u0430", +"Find": "\u041d\u0430\u0439\u0442\u0438", +"Replace all": "\u0417\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u0441\u0435", +"Match case": "\u0423\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440", +"Prev": "\u0412\u0432\u0435\u0440\u0445", +"Spellcheck": "\u041f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u043f\u0440\u0430\u0432\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435", +"Finish": "\u0417\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c", +"Ignore all": "\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435", +"Ignore": "\u0418\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c", +"Add to Dictionary": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u044c", +"Insert row before": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u0432\u0435\u0440\u0445\u0443", +"Rows": "\u0421\u0442\u0440\u043e\u043a\u0438", +"Height": "\u0412\u044b\u0441\u043e\u0442\u0430", +"Paste row after": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u043d\u0438\u0437\u0443", +"Alignment": "\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435", +"Border color": "\u0426\u0432\u0435\u0442 \u0440\u0430\u043c\u043a\u0438", +"Column group": "\u0413\u0440\u0443\u043f\u043f\u0430 \u043a\u043e\u043b\u043e\u043d\u043e\u043a", +"Row": "\u0421\u0442\u0440\u043e\u043a\u0430", +"Insert column before": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0441\u043b\u0435\u0432\u0430", +"Split cell": "\u0420\u0430\u0437\u0431\u0438\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0443", +"Cell padding": "\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u043e\u0442\u0441\u0442\u0443\u043f", +"Cell spacing": "\u0412\u043d\u0435\u0448\u043d\u0438\u0439 \u043e\u0442\u0441\u0442\u0443\u043f", +"Row type": "\u0422\u0438\u043f \u0441\u0442\u0440\u043e\u043a\u0438", +"Insert table": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443", +"Body": "\u0422\u0435\u043b\u043e", +"Caption": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a", +"Footer": "\u041d\u0438\u0437", +"Delete row": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443", +"Paste row before": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u0432\u0435\u0440\u0445\u0443", +"Scope": "Scope", +"Delete table": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443", +"H Align": "\u0413\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435", +"Top": "\u041f\u043e \u0432\u0435\u0440\u0445\u0443", +"Header cell": "\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a", +"Column": "\u0421\u0442\u043e\u043b\u0431\u0435\u0446", +"Row group": "\u0413\u0440\u0443\u043f\u043f\u0430 \u0441\u0442\u0440\u043e\u043a", +"Cell": "\u042f\u0447\u0435\u0439\u043a\u0430", +"Middle": "\u041f\u043e \u0441\u0435\u0440\u0435\u0434\u0438\u043d\u0435", +"Cell type": "\u0422\u0438\u043f \u044f\u0447\u0435\u0439\u043a\u0438", +"Copy row": "\u041a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443", +"Row properties": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0442\u0440\u043e\u043a\u0438", +"Table properties": "\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u044b", +"Bottom": "\u041f\u043e \u043d\u0438\u0437\u0443", +"V Align": "\u0412\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435", +"Header": "\u0428\u0430\u043f\u043a\u0430", +"Right": "\u041f\u043e \u043f\u0440\u0430\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e", +"Insert column after": "\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0435\u0446 \u0441\u043f\u0440\u0430\u0432\u0430", +"Cols": "\u0421\u0442\u043e\u043b\u0431\u0446\u044b", +"Insert row after": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443 \u0441\u043d\u0438\u0437\u0443", +"Width": "\u0428\u0438\u0440\u0438\u043d\u0430", +"Cell properties": "\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u044f\u0447\u0435\u0439\u043a\u0438", +"Left": "\u041f\u043e \u043b\u0435\u0432\u043e\u043c\u0443 \u043a\u0440\u0430\u044e", +"Cut row": "\u0412\u044b\u0440\u0435\u0437\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443", +"Delete column": "\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0442\u043e\u043b\u0431\u0435\u0446", +"Center": "\u041f\u043e \u0446\u0435\u043d\u0442\u0440\u0443", +"Merge cells": "\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0438", +"Insert template": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d", +"Templates": "\u0428\u0430\u0431\u043b\u043e\u043d\u044b", +"Background color": "\u0426\u0432\u0435\u0442 \u0444\u043e\u043d\u0430", +"Custom...": "\u0412\u044b\u0431\u0440\u0430\u0442\u044c\u2026", +"Custom color": "\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0446\u0432\u0435\u0442", +"No color": "\u0411\u0435\u0437 \u0446\u0432\u0435\u0442\u0430", +"Text color": "\u0426\u0432\u0435\u0442 \u0442\u0435\u043a\u0441\u0442\u0430", +"Show blocks": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0431\u043b\u043e\u043a\u0438", +"Show invisible characters": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0435\u0432\u0438\u0434\u0438\u043c\u044b\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b", +"Words: {0}": "\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043b\u043e\u0432: {0}", +"Insert": "\u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c", +"File": "\u0424\u0430\u0439\u043b", +"Edit": "\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c", +"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\u0422\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435. \u041d\u0430\u0436\u043c\u0438\u0442\u0435 ALT-F9 \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u043d\u044e, ALT-F10 \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, ALT-0 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u043f\u043e\u043c\u043e\u0449\u0438.", +"Tools": "\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b", +"View": "\u0412\u0438\u0434", +"Table": "\u0422\u0430\u0431\u043b\u0438\u0446\u0430", +"Format": "\u0424\u043e\u0440\u043c\u0430\u0442" +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/sv.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/sv.js new file mode 100644 index 0000000000..a2a3d77ffd --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/sv.js @@ -0,0 +1 @@ +tinyMCE.addI18n({sv:{common:{"more_colors":"Fler f\u00e4rger","invalid_data":"Fel: Inkorrekta v\u00e4rden har matats in, dessa \u00e4r markerade i r\u00f6tt.","popup_blocked":"Popup blockerare detekterad. St\u00e4ng av den s\u00e5 att dialogerna kan \u00f6ppnas.","clipboard_no_support":"Funktionen \u00e4r inte tillg\u00e4nglig i din webbl\u00e4sare, anv\u00e4nd tangentbordsgenv\u00e4garna i st\u00e4llet.","clipboard_msg":"Kopiera/klipp ut/klistra in \u00e4r inte tillg\u00e4ngligt i din webbl\u00e4sare.\nVill du veta mer?","not_set":"-- Inte satt --","class_name":"Klass",browse:"Bl\u00e4ddra",close:"St\u00e4ng",cancel:"Avbryt",update:"Uppdatera",insert:"Infoga",apply:"Applicera","edit_confirm":"Vill du anv\u00e4nda WYSIWYG f\u00f6r denna textarea?","invalid_data_number":"{#field} m\u00e5ste vara ett nummer","invalid_data_min":"{#field} m\u00e5ste vara ett nummer st\u00f6rren \u00e4n {#min}","invalid_data_size":"{#field} m\u00e5ste vara ett nummer eller i procent",value:"(V\u00e4rde)"},contextmenu:{full:"Utfyllnad",right:"H\u00f6ger",center:"Centrerad",left:"V\u00e4nster",align:"Justering"},insertdatetime:{"day_short":"S\u00f6n,M\u00e5n,Tis,Ons,Tors,Fre,L\u00f6r,S\u00f6n","day_long":"S\u00f6ndag,M\u00e5ndag,Tisdag,Onsdag,Torsdag,Fredag,L\u00f6rdag,S\u00f6ndag","months_short":"Jan,Feb,Mar,Apr,Maj,Jun,Jul,Aug,Sep,Okt,Nov,Dec","months_long":"Januari,Februari,Mars,April,Maj,Juni,Juli,Augusti,September,Oktober,November,December","inserttime_desc":"Infoga tid","insertdate_desc":"Infoga datum","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d "},print:{"print_desc":"Skriv ut"},preview:{"preview_desc":"F\u00f6rhandsgranska"},directionality:{"rtl_desc":"Skriftl\u00e4ge - h\u00f6ger till v\u00e4nster","ltr_desc":"Skriftl\u00e4ge - v\u00e4nster till h\u00f6ger"},layer:{content:"Nytt lager...","absolute_desc":"Sl\u00e5 av/p\u00e5 absolut positionering","backward_desc":"Flytta bak\u00e5t","forward_desc":"Flytta fram\u00e5t","insertlayer_desc":"Infoga nytt lager"},save:{"save_desc":"Spara","cancel_desc":"Hoppa \u00f6ver alla f\u00f6r\u00e4ndringar"},nonbreaking:{"nonbreaking_desc":"Infoga icke radbrytande mellanslag"},iespell:{download:"ieSpell kunde inte hittas, vill du installera denna nu?","iespell_desc":"R\u00e4ttstava"},advhr:{"advhr_desc":"Horisontell skiljelinje","delta_height":"","delta_width":""},emotions:{"emotions_desc":"Smileys","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"S\u00f6k/ers\u00e4tt","search_desc":"S\u00f6k","delta_width":"","delta_height":""},advimage:{"image_desc":"Infoga/redigera bild","delta_width":"","delta_height":""},advlink:{"link_desc":"Infoga/redigera l\u00e4nk","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"Redigera attribut","ins_desc":"Markera som tillagt","del_desc":"Markera som struket","acronym_desc":"Akronym","abbr_desc":"F\u00f6rkortning","cite_desc":"citat","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"Redigera inline CSS","delta_height":"","delta_width":""},paste:{"plaintext_mode":"Inklistring \u00e4r nu i textl\u00e4ge.","plaintext_mode_sticky":"Inklistring \u00e4r nu i textl\u00e4ge. Efter att du klistrat in kommer den att \u00e5terg\u00e5 till normall\u00e4ge.","selectall_desc":"Markera allt","paste_word_desc":"Klistra in fr\u00e5n Word","paste_text_desc":"Klistra in som text"},"paste_dlg":{"word_title":"Anv\u00e4nd ctrl-v p\u00e5 ditt tangentbord f\u00f6r att klistra in i detta f\u00f6nster.","text_linebreaks":"Spara radbrytningar","text_title":"Anv\u00e4nd ctrl-v p\u00e5 ditt tangentbord f\u00f6r att klistra in i detta f\u00f6nster."},table:{cell:"Cell",col:"Kolumn",row:"Rad",del:"Radera tabell","copy_row_desc":"Klistra in rad","cut_row_desc":"Klipp ut rad","paste_row_after_desc":"Klistra in rad efter","paste_row_before_desc":"Klistra in rad ovanf\u00f6r","props_desc":"Tabellinst\u00e4llningar","cell_desc":"Tabellcellsinst\u00e4llningar","row_desc":"Tabellradsinst\u00e4llningar","merge_cells_desc":"Sammanfoga celler","split_cells_desc":"Separera sammansatta celler","delete_col_desc":"Radera kolumn","col_after_desc":"Infoga kolumn efter","col_before_desc":"Infoga kolumn f\u00f6re","delete_row_desc":"Radera rad","row_after_desc":"Infoga ny rad efter","row_before_desc":"Infoga ny rad f\u00f6re",desc:"Infoga/redigera ny tabell","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"Om du \u00e5terskapar inneh\u00e5ll s\u00e5 kommer det nuvarande inneh\u00e5llet i f\u00e4ltet att raderas.\n\n\u00c4r du s\u00e4ker p\u00e5 att du vill g\u00f6ra detta?","restore_content":"\u00c5terskapa automatiskt sparat inneh\u00e5ll.","unload_msg":"De f\u00f6r\u00e4ndringar som du gjort kommer att g\u00e5 f\u00f6rlorade om du l\u00e4mnar sidan."},fullscreen:{desc:"Sl\u00e5 av/p\u00e5 fullsk\u00e4rmsl\u00e4ge"},media:{edit:"Redigera inb\u00e4ddad media",desc:"Infoga/redigera inb\u00e4ddad media","delta_height":"","delta_width":""},fullpage:{desc:"Dokumentinst\u00e4llningar","delta_width":"","delta_height":""},template:{desc:"Infoga en f\u00e4rdig mall"},visualchars:{desc:"Visa osynliga tecken"},spellchecker:{desc:"Sl\u00e5 av/p\u00e5 r\u00e4ttstavningskontroll",menu:"R\u00e4ttstavningsinst\u00e4llningar","ignore_word":"Ignorera ord","ignore_words":"Ignorera alla",langs:"Spr\u00e5k",wait:"Var god v\u00e4nta...",sug:"F\u00f6rslag","no_sug":"Inga f\u00f6rslag","no_mpell":"Inga felstavningar funna.","learn_word":"L\u00e4r ord"},pagebreak:{desc:"Infoga sidbrytning"},advlist:{types:"Typer",def:"Standard","lower_alpha":"Lower alpha","lower_greek":"Lower greek","lower_roman":"Lower roman","upper_alpha":"Upper alpha","upper_roman":"Upper roman",circle:"Cirkel",disc:"Disc",square:"Fyrkant"},colors:{"333300":"M\u00f6rkoliv","993300":"Br\u00e4ndorange","000000":"Svart","003300":"M\u00f6rkgr\u00f6n","003366":"M\u00f6rkazur","000080":"Marinbl\u00e5","333399":"Indigo","333333":"Mycket m\u00f6rkgr\u00e5","800000":"R\u00f6dbrun",FF6600:"Orange","808000":"Oliv","008000":"Gr\u00f6n","008080":"Kricka","0000FF":"Bl\u00e5","666699":"Gr\u00e5bl\u00e5","808080":"Gr\u00e5",FF0000:"R\u00f6d",FF9900:"B\u00e4rnsten","99CC00":"Gulgr\u00f6n","339966":"Havsbl\u00e5","33CCCC":"Turkos","3366FF":"Kungligtbl\u00e5tt","800080":"Lila","999999":"Medelgr\u00e5",FF00FF:"Magenta",FFCC00:"Guld",FFFF00:"Gul","00FF00":"Lime","00FFFF":"Vatten","00CCFF":"Himmelsbl\u00e5","993366":"Brun",C0C0C0:"Silver",FF99CC:"Rosa",FFCC99:"Periska",FFFF99:"Ljusgul",CCFFCC:"Blekgr\u00f6n",CCFFFF:"Blekcyan","99CCFF":"Ljus himmel",CC99FF:"Plommon",FFFFFF:"Vitt"},aria:{"rich_text_area":"Redigeringsarea"},wordcount:{words:"Ord:"}}}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/langs/zh.js b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/zh.js new file mode 100644 index 0000000000..42f7abbc96 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/langs/zh.js @@ -0,0 +1 @@ +tinyMCE.addI18n({"zh-cn":{common:{"more_colors":"\u66f4\u591a\u989c\u8272","invalid_data":"\u9519\u8bef\uff1a\u6807\u8bb0\u4e3a\u7ea2\u8272\u7684\u90e8\u5206\u6709\u8bef\u3002","popup_blocked":"\u62b1\u6b49\uff0c\u60a8\u7981\u7528\u4e86\u5f39\u51fa\u7a97\u53e3\u529f\u80fd\u3002\u4e3a\u4e86\u4f7f\u7528\u8be5\u5de5\u5177\u7684\u5168\u90e8\u529f\u80fd\uff0c\u60a8\u9700\u8981\u5141\u8bb8\u5f39\u51fa\u7a97\u53e3\u3002","clipboard_no_support":"\u60a8\u7684\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\uff0c\u4f7f\u7528\u5feb\u6377\u952e\u4ee3\u66ff\u3002","clipboard_msg":"\u5728Mozilla\u548cFirefox\u4e2d\u4e0d\u80fd\u4f7f\u7528\u590d\u5236/\u7c98\u8d34/\u526a\u5207\u3002\u60a8\u8981\u67e5\u770b\u8be5\u95ee\u9898\u66f4\u591a\u7684\u4fe1\u606f\u5417\uff1f","not_set":"-- \u672a\u8bbe\u7f6e --","class_name":"\u7c7b\u522b",browse:"\u6d4f\u89c8",close:"\u5173\u95ed",cancel:"\u53d6\u6d88",update:"\u66f4\u65b0",insert:"\u63d2\u5165",apply:"\u5e94\u7528","edit_confirm":"\u8be5\u6587\u672c\u57df\u662f\u5426\u9700\u8981\u4f7f\u7528\u6240\u89c1\u5373\u6240\u5f97\u6a21\u5f0f\uff1f","invalid_data_number":"{#field} \u5fc5\u987b\u4e3a\u6570\u5b57","invalid_data_min":"{#field} \u5fc5\u987b\u4e3a\u5927\u4e8e {#min} \u7684\u6570\u5b57","invalid_data_size":"{#field} \u5fc5\u987b\u4e3a\u6570\u5b57\u6216\u767e\u5206\u6570",value:"(value)"},contextmenu:{full:"\u4e24\u7aef\u5bf9\u9f50",right:"\u53f3\u5bf9\u9f50",center:"\u5c45\u4e2d",left:"\u5de6\u5bf9\u9f50",align:"\u5bf9\u9f50"},insertdatetime:{"day_short":"\u5468\u65e5,\u5468\u4e00,\u5468\u4e8c,\u5468\u4e09,\u5468\u56db,\u5468\u4e94,\u5468\u516d,\u5468\u65e5","day_long":"\u661f\u671f\u65e5,\u661f\u671f\u4e00,\u661f\u671f\u4e8c,\u661f\u671f\u4e09,\u661f\u671f\u56db,\u661f\u671f\u4e94,\u661f\u671f\u516d,\u661f\u671f\u65e5","months_short":"1\u6708,2\u6708,3\u6708,4\u6708,5\u6708,6\u6708,7\u6708,8\u6708,9\u6708,10\u6708,11\u6708,12\u6708","months_long":"\u4e00\u6708,\u4e8c\u6708,\u4e09\u6708,\u56db\u6708,\u4e94\u6708,\u516d\u6708,\u4e03\u6708,\u516b\u6708,\u4e5d\u6708,\u5341\u6708,\u5341\u4e00\u6708,\u5341\u4e8c\u6708","inserttime_desc":"\u63d2\u5165\u65f6\u95f4","insertdate_desc":"\u63d2\u5165\u65e5\u671f","time_fmt":"%H:%M:%S","date_fmt":"%Y-%m-%d"},print:{"print_desc":"\u6253\u5370"},preview:{"preview_desc":"\u9884\u89c8"},directionality:{"rtl_desc":"\u6587\u5b57\u65b9\u5411\u4e3a\u4ece\u53f3\u5230\u5de6","ltr_desc":"\u6587\u5b57\u65b9\u5411\u4e3a\u4ece\u5de6\u5230\u53f3"},layer:{content:"\u65b0\u5efa\u5c42...","absolute_desc":"\u5207\u6362\u5230\u7edd\u5bf9\u4f4d\u7f6e","backward_desc":"\u7f6e\u540e","forward_desc":"\u7f6e\u524d","insertlayer_desc":"\u63d2\u5165\u65b0\u5c42"},save:{"save_desc":"\u4fdd\u5b58","cancel_desc":"\u53d6\u6d88\u66f4\u6539"},nonbreaking:{"nonbreaking_desc":"\u63d2\u5165\u4e0d\u95f4\u65ad\u7a7a\u683c\u7b26"},iespell:{download:"\u62fc\u5199\u68c0\u67e5\u672a\u5b89\u88c5\uff0c\u662f\u5426\u9a6c\u4e0a\u5b89\u88c5\uff1f","iespell_desc":"\u62fc\u5199\u68c0\u67e5"},advhr:{"delta_height":"\u9ad8\u5ea6","delta_width":"\u5bbd\u5ea6","advhr_desc":"\u6c34\u5e73\u7ebf"},emotions:{"emotions_desc":"\u8868\u60c5","delta_height":"","delta_width":""},searchreplace:{"replace_desc":"\u67e5\u627e/\u66ff\u6362","search_desc":"\u67e5\u627e","delta_width":"","delta_height":""},advimage:{"image_desc":"\u63d2\u5165/\u7f16\u8f91 \u56fe\u7247","delta_width":"","delta_height":""},advlink:{"link_desc":"\u63d2\u5165/\u7f16\u8f91 \u8d85\u94fe\u63a5","delta_height":"","delta_width":""},xhtmlxtras:{"attribs_desc":"\u63d2\u5165/\u7f16\u8f91\u5c5e\u6027","ins_desc":"\u63d2\u5165","del_desc":"\u5220\u9664","acronym_desc":"\u9996\u5b57\u6bcd\u7f29\u5199","abbr_desc":"\u7f29\u5199","cite_desc":"\u5f15\u7528","attribs_delta_height":"","attribs_delta_width":"","ins_delta_height":"","ins_delta_width":"","del_delta_height":"","del_delta_width":"","acronym_delta_height":"","acronym_delta_width":"","abbr_delta_height":"","abbr_delta_width":"","cite_delta_height":"","cite_delta_width":""},style:{desc:"\u7f16\u8f91CSS\u6837\u5f0f","delta_height":"","delta_width":""},paste:{"plaintext_mode":"\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u6a21\u5f0f\u7c98\u8d34\uff0c\u518d\u6b21\u70b9\u51fb\u8fd4\u56de\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002","plaintext_mode_sticky":"\u5f53\u524d\u4e3a\u7eaf\u6587\u672c\u6a21\u5f0f\u7c98\u8d34\u3002\u518d\u6b21\u70b9\u51fb\u8fd4\u56de\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\uff0c\u5728\u60a8\u7c98\u8d34\u5185\u5bb9\u540e\u5c06\u8fd4\u56de\u666e\u901a\u7c98\u8d34\u6a21\u5f0f\u3002","selectall_desc":"\u5168\u9009","paste_word_desc":"\u4eceWord\u7c98\u8d34","paste_text_desc":"\u4ee5\u7eaf\u6587\u672c\u7c98\u8d34"},"paste_dlg":{"word_title":"\u4f7f\u7528CTRL V\u7c98\u8d34\u6587\u672c\u5230\u7a97\u53e3\u4e2d\u3002","text_linebreaks":"\u4fdd\u7559\u65ad\u884c","text_title":"\u4f7f\u7528CTRL V\u7c98\u8d34\u6587\u672c\u5230\u7a97\u53e3\u4e2d\u3002"},table:{cell:"\u5355\u5143\u683c",col:"\u5217",row:"\u884c",del:"\u5220\u9664\u8868\u683c","copy_row_desc":"\u590d\u5236\u884c","cut_row_desc":"\u526a\u5207\u884c","paste_row_after_desc":"\u5728\u4e0b\u65b9\u7c98\u8d34\u884c","paste_row_before_desc":"\u5728\u4e0a\u65b9\u7c98\u8d34\u884c","props_desc":"\u8868\u683c\u5c5e\u6027","cell_desc":"\u5355\u5143\u683c\u5c5e\u6027","row_desc":"\u884c\u5c5e\u6027","merge_cells_desc":"\u5408\u5e76\u5355\u5143\u683c","split_cells_desc":"\u5206\u5272\u5355\u5143\u683c","delete_col_desc":"\u5220\u9664\u5217","col_after_desc":"\u5728\u53f3\u4fa7\u63d2\u5165\u5217","col_before_desc":"\u5728\u5de6\u4fa7\u63d2\u5165\u5217","delete_row_desc":"\u5220\u9664\u884c","row_after_desc":"\u5728\u4e0b\u65b9\u63d2\u5165\u884c","row_before_desc":"\u5728\u4e0a\u65b9\u63d2\u5165\u884c",desc:"\u63d2\u5165\u65b0\u8868\u683c","merge_cells_delta_height":"","merge_cells_delta_width":"","table_delta_height":"","table_delta_width":"","cellprops_delta_height":"","cellprops_delta_width":"","rowprops_delta_height":"","rowprops_delta_width":""},autosave:{"warning_message":"\u5982\u679c\u6062\u590d\u4fdd\u5b58\u7684\u5185\u5bb9\uff0c\u60a8\u5f53\u524d\u7f16\u8f91\u7684\u6240\u6709\u7684\u5185\u5bb9\u5c06\u4e22\u5931\u3002nn\u60a8\u786e\u5b9a\u8981\u6062\u590d\u4fdd\u5b58\u7684\u5185\u5bb9\u5417\uff1f","restore_content":"\u6062\u590d\u81ea\u52a8\u4fdd\u5b58\u7684\u5185\u5bb9\u3002","unload_msg":"\u5982\u679c\u9000\u51fa\u8be5\u9875\uff0c\u60a8\u6240\u505a\u7684\u66f4\u6539\u5c06\u4e22\u5931\u3002"},fullscreen:{desc:"\u5207\u6362\u5168\u5c4f\u6a21\u5f0f"},media:{edit:"\u7f16\u8f91\u5d4c\u5165\u5f0f\u5a92\u4f53",desc:"\u63d2\u5165/\u7f16\u8f91 \u5d4c\u5165\u5f0f\u5a92\u4f53","delta_height":"","delta_width":""},fullpage:{desc:"\u6587\u4ef6\u5c5e\u6027","delta_width":"\u5bbd\u5ea6","delta_height":"\u9ad8\u5ea6"},template:{desc:"\u63d2\u5165\u9884\u8bbe\u7684\u6a21\u677f\u5185\u5bb9"},visualchars:{desc:"\u663e\u793a/\u9690\u85cf \u975e\u53ef\u89c1\u5b57\u7b26"},spellchecker:{desc:"\u62fc\u5199\u68c0\u67e5",menu:"\u62fc\u5199\u68c0\u67e5\u8bbe\u7f6e","ignore_word":"\u5ffd\u7565","ignore_words":"\u5168\u90e8\u5ffd\u7565",langs:"\u8bed\u8a00",wait:"\u8bf7\u7a0d\u5019...",sug:"\u5efa\u8bae","no_sug":"\u65e0\u5efa\u8bae","no_mpell":"\u65e0\u62fc\u5199\u9519\u8bef","learn_word":"\u5b66\u4e60\u8bcd\u7ec4"},pagebreak:{desc:"\u63d2\u5165\u5206\u9875\u7b26"},advlist:{types:"\u6837\u5f0f",def:"\u9ed8\u8ba4","lower_alpha":"\u5c0f\u5199\u5b57\u6bcd","lower_greek":"\u5c0f\u5199\u5e0c\u814a\u5b57\u6bcd","lower_roman":"\u5c0f\u5199\u7f57\u9a6c\u6570\u5b57","upper_alpha":"\u5927\u5199\u5b57\u6bcd","upper_roman":"\u5927\u5199\u7f57\u9a6c\u6570\u5b57",circle:"\u5706\u5708",disc:"\u5706\u70b9",square:"\u65b9\u5757"},colors:{"333300":"Dark olive","993300":"Burnt orange","000000":"Black","003300":"Dark green","003366":"Dark azure","000080":"Navy Blue","333399":"Indigo","333333":"Very dark gray","800000":"Maroon",FF6600:"Orange","808000":"Olive","008000":"Green","008080":"Teal","0000FF":"Blue","666699":"Grayish blue","808080":"Gray",FF0000:"Red",FF9900:"Amber","99CC00":"Yellow green","339966":"Sea green","33CCCC":"Turquoise","3366FF":"Royal blue","800080":"Purple","999999":"Medium gray",FF00FF:"Magenta",FFCC00:"Gold",FFFF00:"Yellow","00FF00":"Lime","00FFFF":"Aqua","00CCFF":"Sky blue","993366":"Brown",C0C0C0:"Silver",FF99CC:"Pink",FFCC99:"Peach",FFFF99:"Light yellow",CCFFCC:"Pale green",CCFFFF:"Pale cyan","99CCFF":"Light sky blue",CC99FF:"Plum",FFFFFF:"White"},aria:{"rich_text_area":"\u5bcc\u6587\u672c\u57df"},wordcount:{words:"\u5b57\u6570:"}}}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/da.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/da.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/da.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/de.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/de.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/de.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/en_us.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/en_us.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/en_us.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/fi.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/fi.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/fi.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/fr.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/fr.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/fr.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/he.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/he.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/he.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/it.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/it.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/it.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/ja.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/ja.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/ja.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/nl.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/nl.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/nl.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/no.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/no.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/no.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/pl.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/pl.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/pl.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/pt.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/pt.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/pt.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/ru.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/ru.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/ru.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/sv.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/sv.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/sv.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/zh.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/zh.js new file mode 100644 index 0000000000..d5e0bbde43 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/codemirror/langs/zh.js @@ -0,0 +1,8 @@ +tinymce.addI18n('en',{ + 'HTML source code': 'HTML source code', + 'Start search': 'Start search', + 'Find next': 'Find next', + 'Find previous': 'Find previous', + 'Replace': 'Replace', + 'Replace all': 'Replace all' +}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocontextmenu/editor_plugin_src.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocontextmenu/editor_plugin_src.js deleted file mode 100644 index f3074ef21f..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocontextmenu/editor_plugin_src.js +++ /dev/null @@ -1,69 +0,0 @@ -/** -* editor_plugin_src.js -* -* Copyright 2012, Umbraco -* Released under MIT License. -* -* License: http://opensource.org/licenses/mit-license.html -*/ - -(function () { - var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM; - - /** - * This plugin modifies the standard TinyMCE context menu, with umbraco specific changes. - * - * @class tinymce.plugins.umbContextMenu - */ - tinymce.create('tinymce.plugins.UmbracoContextMenu', { - /** - * Initializes the plugin, this will be executed after the plugin has been created. - * This call is done before the editor instance has finished it's initialization so use the onInit event - * of the editor instance to intercept that event. - * - * @method init - * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. - * @param {string} url Absolute URL to where the plugin is located. - */ - init: function (ed) { - if (ed.plugins.contextmenu) { - - ed.plugins.contextmenu.onContextMenu.add(function (th, menu, event) { - - var keys = UmbClientMgr.uiKeys(); - - $.each(menu.items, function (idx, el) { - - switch (el.settings.cmd) { - case "Cut": - el.settings.title = keys['defaultdialogs_cut']; - break; - case "Copy": - el.settings.title = keys['general_copy']; - break; - case "Paste": - el.settings.title = keys['defaultdialogs_paste']; - break; - case "mceAdvLink": - case "mceLink": - el.settings.title = keys['defaultdialogs_insertlink']; - break; - case "UnLink": - el.settings.title = keys['relatedlinks_removeLink']; - break; - case "mceImage": - el.settings.title = keys['defaultdialogs_insertimage']; - el.settings.cmd = "mceUmbimage"; - break; - } - - }); - - }); - } - } - }); - - // Register plugin - tinymce.PluginManager.add('umbracocontextmenu', tinymce.plugins.UmbracoContextMenu); -})(); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocontextmenu/plugin.min.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocontextmenu/plugin.min.js deleted file mode 100644 index f3074ef21f..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocontextmenu/plugin.min.js +++ /dev/null @@ -1,69 +0,0 @@ -/** -* editor_plugin_src.js -* -* Copyright 2012, Umbraco -* Released under MIT License. -* -* License: http://opensource.org/licenses/mit-license.html -*/ - -(function () { - var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM; - - /** - * This plugin modifies the standard TinyMCE context menu, with umbraco specific changes. - * - * @class tinymce.plugins.umbContextMenu - */ - tinymce.create('tinymce.plugins.UmbracoContextMenu', { - /** - * Initializes the plugin, this will be executed after the plugin has been created. - * This call is done before the editor instance has finished it's initialization so use the onInit event - * of the editor instance to intercept that event. - * - * @method init - * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. - * @param {string} url Absolute URL to where the plugin is located. - */ - init: function (ed) { - if (ed.plugins.contextmenu) { - - ed.plugins.contextmenu.onContextMenu.add(function (th, menu, event) { - - var keys = UmbClientMgr.uiKeys(); - - $.each(menu.items, function (idx, el) { - - switch (el.settings.cmd) { - case "Cut": - el.settings.title = keys['defaultdialogs_cut']; - break; - case "Copy": - el.settings.title = keys['general_copy']; - break; - case "Paste": - el.settings.title = keys['defaultdialogs_paste']; - break; - case "mceAdvLink": - case "mceLink": - el.settings.title = keys['defaultdialogs_insertlink']; - break; - case "UnLink": - el.settings.title = keys['relatedlinks_removeLink']; - break; - case "mceImage": - el.settings.title = keys['defaultdialogs_insertimage']; - el.settings.cmd = "mceUmbimage"; - break; - } - - }); - - }); - } - } - }); - - // Register plugin - tinymce.PluginManager.add('umbracocontextmenu', tinymce.plugins.UmbracoContextMenu); -})(); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/img/example.gif b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracocss/img/example.gif deleted file mode 100644 index 1ab5da4461113d2af579898528246fdbe52ecd00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 87 zcmZ?wbhEHb6k!lyn83&Y1dNP~ia%L^OhyJB5FaGNz@*pGzw+SQ`#f{}FJ-?!v#V)e mtsGNfpJeCKSAiOz**>0`XR2{OVa>-G_df0vaY 1) { - // register with new formatter engine (can't access from here so a hack in the set style above!) - // tinyMCE.activeEditor.formatter.register('umb' + alias.substring(1, alias.length), { - // classes: alias.substring(1, alias.length) - // }); - } - styles.add(name, alias); - } - } - - - return styles; - } - - return null; - }, - - - /** - * Returns information about the plugin as a name/value array. - * The current keys are longname, author, authorurl, infourl and version. - * - * @return {Object} Name/value array containing information about the plugin. - */ - getInfo: function () { - return { - longname: 'Umbraco CSS/Styling Plugin', - author: 'Umbraco', - authorurl: 'http://umbraco.org', - infourl: 'http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example', - version: "1.0" - }; - } - }); - - // Register plugin - tinymce.PluginManager.add('umbracocss', tinymce.plugins.umbracocss); -})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/dialog.htm b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/dialog.htm deleted file mode 100644 index a89fcc1283..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/dialog.htm +++ /dev/null @@ -1,92 +0,0 @@ - - - - {#embed_dlg.title} - - - - - - - - -
- -
-
-
- {#embed_dlg.general} - - - - - - - - - -
- -
- - - - - - -
x   
-
- -
-
- {#embed_dlg.preview} -
-
- -
-
-
-
-
-
- {#embed_dlg.source} - -
-
-
- - -
- - -
-
- - - diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/editor_plugin.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/editor_plugin.js deleted file mode 100644 index ec1f81ea40..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/editor_plugin.js +++ /dev/null @@ -1 +0,0 @@ -(function(){tinymce.PluginManager.requireLangPack("example");tinymce.create("tinymce.plugins.ExamplePlugin",{init:function(a,b){a.addCommand("mceExample",function(){a.windowManager.open({file:b+"/dialog.htm",width:320+parseInt(a.getLang("example.delta_width",0)),height:120+parseInt(a.getLang("example.delta_height",0)),inline:1},{plugin_url:b,some_custom_arg:"custom arg"})});a.addButton("example",{title:"example.desc",cmd:"mceExample",image:b+"/img/example.gif"});a.onNodeChange.add(function(d,c,e){c.setActive("example",e.nodeName=="IMG")})},createControl:function(b,a){return null},getInfo:function(){return{longname:"Example plugin",author:"Some author",authorurl:"http://tinymce.moxiecode.com",infourl:"http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/example",version:"1.0"}}});tinymce.PluginManager.add("example",tinymce.plugins.ExamplePlugin)})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/editor_plugin_src.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/editor_plugin_src.js deleted file mode 100644 index 4649f37ecf..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/editor_plugin_src.js +++ /dev/null @@ -1,84 +0,0 @@ -/** - * editor_plugin_src.js - * - * Copyright 2009, Moxiecode Systems AB - * Released under LGPL License. - * - * License: http://tinymce.moxiecode.com/license - * Contributing: http://tinymce.moxiecode.com/contributing - */ - -(function() { - // Load plugin specific language pack - tinymce.PluginManager.requireLangPack('umbracoembed'); - - tinymce.create('tinymce.plugins.umbracoembed', { - /** - * Initializes the plugin, this will be executed after the plugin has been created. - * This call is done before the editor instance has finished it's initialization so use the onInit event - * of the editor instance to intercept that event. - * - * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. - * @param {string} url Absolute URL to where the plugin is located. - */ - init : function(ed, url) { - // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample'); - ed.addCommand('mceUmbracoEmbed', function() { - ed.windowManager.open({ - file : url + '/dialog.htm', - width : 600 + parseInt(ed.getLang('example.delta_width', 0)), - height : 400 + parseInt(ed.getLang('example.delta_height', 0)), - inline : 1 - }, { - plugin_url : url, // Plugin absolute URL - some_custom_arg : 'custom arg' // Custom argument - }); - }); - - // Register example button - ed.addButton('umbracoembed', { - title : 'umbracoembed.desc', - cmd : 'mceUmbracoEmbed', - image : url + '/img/embed.gif' - }); - - // Add a node change handler, selects the button in the UI when a image is selected - /*ed.onNodeChange.add(function(ed, cm, n) { - cm.setActive('example', n.nodeName == 'IMG'); - });*/ - }, - - /** - * Creates control instances based in the incomming name. This method is normally not - * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons - * but you sometimes need to create more complex controls like listboxes, split buttons etc then this - * method can be used to create those. - * - * @param {String} n Name of the control to create. - * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control. - * @return {tinymce.ui.Control} New control instance or null if no control was created. - */ - createControl : function(n, cm) { - return null; - }, - - /** - * Returns information about the plugin as a name/value array. - * The current keys are longname, author, authorurl, infourl and version. - * - * @return {Object} Name/value array containing information about the plugin. - */ - getInfo : function() { - return { - longname : 'Umbraco Embed', - author : 'Tim Geyssens', - authorurl : 'http://http://umbraco.com/', - infourl : 'http://http://umbraco.com/', - version : "1.0" - }; - } - }); - - // Register plugin - tinymce.PluginManager.add('umbracoembed', tinymce.plugins.umbracoembed); -})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/img/ajax-loader.gif b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/img/ajax-loader.gif deleted file mode 100644 index 521a291d748c84b37cf75fe7003ca0ff04f33fb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1928 zcmdVa?@tz=)H2#yZ97W^J8C-PQkOKwEW@eMrL&ze+4jWP zV^YDJfAZl`ssWC@PoBeLmm#__$Cg ztgWrx+1V*BF3!x%EGsMP>+3@hq_eZr@At2)tZ=#9hK2?l$A^c9o12?kTU#qDD+7Um zLZMh%S{fJ_u-R<&_4OK!rm(P3B9Rmn6u8}PtybIA)Kp$xUQ<)!bUFnB!TS1oV`HPs zn98)6rvP@y%!q zMV&DtHhafuf;rg1LChe_Wrd{#ZNmBv0YI}NH$b0A>2g~JlT#OgmBF-MmtE=N#f6EC zMaC>U(GB_rCE4z$vt9z>Zh8omx7kndovud@Kj?PWx3Lm`e)!R7vsnFz2j$#+a(%E= z6fTI0>CN*;VWpM@HMKcTD-1@J!7Uj5&7lc{BL?6w^HVimm8!a$mFaTn3c) zx+3)(5qm9L6Du8m`Qp|3Fe_0}b-Vl7eKQSo)@kC9uo{e1+m5T*`NxO+ubTf>9rHaN zRNF5G(L-nTAZwHoillnlWXJRj4$ZOWP4vlSv&He8SaopH2+TWq=`!J2ymHROSR|or z1NhrkK`K77MKVL^OGcEp#am$AXf-@gtJJa5(U+8M9{(JZRZO>vZ$V(9Otof~#)R3l zNOu4K*umZSZ`iOr%uYJaPU_MJ-OQkS%pr@%Xj4O37&OLz2PF zCIFu!{i@1qdOjz-!YnlY|di&S4|F-Jwp z$El=B_lG1t=g!ymdr@lRO}h4WjK7~6QH2Yj$bxT=7YMmfLj2LXz|6PXO>&~cgGWQ_ zV&@?EQ2`4K6(j@;91uqL*m;=6+ap-bgjtr{_Fz+j0%(Kk>nFObU3o$w|e4FHR$QNaKJ diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/img/embed.png b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/img/embed.png deleted file mode 100644 index a8d147d76cd81bb242538ee22760db471a28998b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 537 zcmV+!0_OdRP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXP; z6%!Cz#+@<%00EgvL_t(I%k7jsOCwPfhM!2XsH8|BYNa?@3^qX#gM}~_u?RMzh+sDs zasR+p+oT+~@()PZW{WArM#a)jP%upj323kp#bQK_;wbMni5rtyMX^xu>Fzm)d(VB( z2Lxbv(}N-yxsIN3*HcVJRZK=D*AZawI{aVX1)!Cm|6bGVumG+m2gLg#*O6~qIRM|b zBo$Yt?nm|`=v$QE>1M(v)6}!IKV~^%Wn|jV^A-LZ(F%)MIUJa@TLb9 z9vkEO;sSt3e*5=*xlDa<3qWf}2M_1x#8wNTs{QC>eI0gpY1G!ZnjEM#5XEFvnjKa# z84WDHQ56{=UKRg~z+TU$rEEGEV9zO={;zPMMnh$ORBcmJkLR1UHQN8|gkJJBU3i)? z)oI&ME_3I3c>DWwZ65RiM~!7Z&6tO=p&`D-V$j>mSw2tK=0Q_(Mk$q0Wo|@T7?)f} zrBtHnYo$~|avf=5T$Q4;abzN)gNB2_q}%FjoP|sApU7r b2LOKoGp)W|>}K$200000NkvXXu0mjf'); - $('#source').val(''); - - $.ajax({ - type: 'POST', - async: true, - url: '../../../../base/EmbedMediaService/Embed/', - data: { url: url, width: width, height: height }, - dataType: 'json', - success: function (result) { - switch (result.Status) { - case 0: - //not supported - $('#preview').html('Not Supported'); - break; - case 1: - //error - $('#preview').html('Error'); - break; - case 2: - $('#preview').html(result.Markup); - $('#source').val(result.Markup); - if (result.SupportsDimensions) { - $('#dimensions').show(); - } else { - $('#dimensions').hide(); - } - $('#insert').removeAttr('disabled'); - break; - } - }, - error: function (xhr, ajaxOptions, thrownError) { - $('#preview').html("Error"); - } - }); - }, - beforeResize: function () { - this.width = parseInt($('#width').val(), 10); - this.height = parseInt($('#height').val(), 10); - }, - changeSize: function (type) { - var width, height, scale, size; - - if ($('#constrain').is(':checked')) { - width = parseInt($('#width').val(), 10); - height = parseInt($('#height').val(), 10); - if (type == 'width') { - this.height = Math.round((width / this.width) * height); - $('#height').val(this.height); - } else { - this.width = Math.round((height / this.height) * width); - $('#width').val(this.width); - } - } - if ($('#url').val() != '') { - UmbracoEmbedDialog.showPreview(); - } - }, - changeSource: function (type) { - if ($('#source').val() != '') { - $('#insert').removeAttr('disabled'); - } - else { - $('#insert').attr('disabled', 'disabled'); - } - }, - updatePreviewFromSource: function (type) { - var sourceVal = $('#source').val(); - - if (sourceVal != '') { - $('#preview').html(sourceVal); - } - } -}; - diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/da.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/da.js deleted file mode 100644 index a93d2e36f2..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/da.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('da.umbracoembed', { - desc: 'Inds\u00E6t ekstern mediefil' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/da_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/da_dlg.js deleted file mode 100644 index 3082589539..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/da_dlg.js +++ /dev/null @@ -1,9 +0,0 @@ -tinyMCE.addI18n('da.embed_dlg', { - title: 'Inds\u00E6t ekstern mediefil', - general: 'Generelt', - url: 'Url:', - size: 'Dimensioner:', - constrain_proportions: 'Bevar proportioner', - preview: 'Vis', - source: 'Vis kilde' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/de.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/de.js deleted file mode 100644 index ad0b940580..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/de.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('de.embed_dlg', { - title: 'Medien von Drittanbietern einbetten', - general: 'Allgemein', - url: 'Url:', - size: 'Abmessungen:', - constrain_proportions: 'Proportionen beibehalten', - preview: 'Vorschau', - source: 'Quellcode' - -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/de_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/de_dlg.js deleted file mode 100644 index ad0b940580..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/de_dlg.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('de.embed_dlg', { - title: 'Medien von Drittanbietern einbetten', - general: 'Allgemein', - url: 'Url:', - size: 'Abmessungen:', - constrain_proportions: 'Proportionen beibehalten', - preview: 'Vorschau', - source: 'Quellcode' - -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en.js deleted file mode 100644 index 2b086df34e..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('en.umbracoembed', { - desc: 'Embed third party media' -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_dlg.js deleted file mode 100644 index e131d87533..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_dlg.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('en.embed_dlg', { - title: 'Embed third party media', - general: 'General', - url: 'Url:', - size: 'Size:', - constrain_proportions: 'Constrain', - preview: 'Preview', - source: 'Source' - -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_us.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_us.js deleted file mode 100644 index 4698979aab..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_us.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('en_us.umbracoembed', { - desc: 'Embed third party media' -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_us_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_us_dlg.js deleted file mode 100644 index 8c6a070226..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/en_us_dlg.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('en_us.embed_dlg', { - title: 'Embed third party media', - general: 'General', - url: 'Url:', - size: 'Size:', - constrain_proportions: 'Constrain', - preview: 'Preview', - source: 'Source' - -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/it.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/it.js deleted file mode 100644 index a8ff6693ab..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/it.js +++ /dev/null @@ -1,9 +0,0 @@ -tinyMCE.addI18n('en.embed_dlg', { -title: 'Integra media di terze parti', -general: 'Generale', -url: 'Url:', -size: 'Dimensione:', -constrain_proportions: 'Vincolo', -preview: 'Anteprima', -source: 'Sorgente' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/it_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/it_dlg.js deleted file mode 100644 index 87766ce2da..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/it_dlg.js +++ /dev/null @@ -1,9 +0,0 @@ -tinyMCE.addI18n('it.embed_dlg', { -title: 'Integra media di terze parti', -general: 'Generale', -url: 'Url:', -size: 'Dimensione:', -constrain_proportions: 'Vincolo', -preview: 'Anteprima', -source: 'Sorgente' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ja.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ja.js deleted file mode 100644 index c525d3a37e..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ja.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('ja.embed_dlg', { - title: 'サードパーティメディアの埋め込み', - general: '一般', - url: 'Url:', - size: 'サイズ:', - constrain_proportions: '制約', - preview: 'プレビュー', - source: 'ソース' - -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ja_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ja_dlg.js deleted file mode 100644 index db01d093c9..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ja_dlg.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('ja.embed_dlg', { - title: サードパーティメディアの埋め込み', - general: '一般', - url: 'Url:', - size: 'サイズ:', - constrain_proportions: '制約', - preview: 'プレビュー', - source: 'ソース' - -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ru.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ru.js deleted file mode 100644 index a1b566597b..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ru.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('ru.embed_dlg', { - title: 'Вставить внеший элемент медиа', - general: 'Общее', - url: 'Ссылка:', - size: 'Размер:', - constrain_proportions: 'Сохранять пропорции', - preview: 'Просмотр', - source: 'Источник' - -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ru_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ru_dlg.js deleted file mode 100644 index a1b566597b..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/ru_dlg.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('ru.embed_dlg', { - title: 'Вставить внеший элемент медиа', - general: 'Общее', - url: 'Ссылка:', - size: 'Размер:', - constrain_proportions: 'Сохранять пропорции', - preview: 'Просмотр', - source: 'Источник' - -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/sv.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/sv.js deleted file mode 100644 index 36bcaf8758..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/sv.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('sv.embed_dlg', { - title: 'Bädda in tredjeparts media', - general: 'Generell', - url: 'Url:', - size: 'Storlek:', - constrain_proportions: 'Bibehåll proportioner', - preview: 'Förhandsgranska', - source: 'Källa' - -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/sv_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/sv_dlg.js deleted file mode 100644 index 36bcaf8758..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/sv_dlg.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('sv.embed_dlg', { - title: 'Bädda in tredjeparts media', - general: 'Generell', - url: 'Url:', - size: 'Storlek:', - constrain_proportions: 'Bibehåll proportioner', - preview: 'Förhandsgranska', - source: 'Källa' - -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/zh.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/zh.js deleted file mode 100644 index ee41077410..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/zh.js +++ /dev/null @@ -1,10 +0,0 @@ -tinyMCE.addI18n('zh.embed_dlg', { - title: '嵌入第三方媒体', - general: '普通', - url: '链接:', - size: '尺寸:', - constrain_proportions: '约束比例', - preview: '预览', - source: '源' - -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/zh_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/zh_dlg.js deleted file mode 100644 index 2e59f0be58..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoembed/langs/zh_dlg.js +++ /dev/null @@ -1,9 +0,0 @@ -tinyMCE.addI18n('zh.embed_dlg', { - title: '嵌入第三方媒体', - general: '普通', - url: '链接:', - size: '尺寸:', - constrain_proportions: '约束比例', - preview: '预览', - source: '源' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/editor_plugin_src.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/editor_plugin_src.js deleted file mode 100644 index accb078909..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/editor_plugin_src.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * $Id: editor_plugin_src.js 677 2008-03-07 13:52:41Z spocke $ - * - * @author Moxiecode - * @copyright Copyright 2004-2008, Moxiecode Systems AB, All rights reserved. - */ - -(function() { -// tinymce.PluginManager.requireLangPack('umbraco'); - - tinymce.create('tinymce.plugins.UmbracoImagePlugin', { - init: function(ed, url) { - // Register commands - ed.addCommand('mceUmbimage', function() { - // Internal image object like a flash placeholder - if (ed.dom.getAttrib(ed.selection.getNode(), 'class').indexOf('mceItem') != -1) - return; - - ed.windowManager.open({ - /* UMBRACO SPECIFIC: Load Umbraco modal window */ - file: tinyMCE.activeEditor.getParam('umbraco_path') + '/plugins/tinymce3/insertImage.aspx', - width: 575 + ed.getLang('umbracoimg.delta_width', 0), - height: 505 + ed.getLang('umbracoimg.delta_height', 0), - inline: 1 - }, { - plugin_url: url - }); - }); - - // Register buttons - ed.addButton('image', { - title: 'advimage.image_desc', - cmd: 'mceUmbimage' - }); - - }, - - getInfo: function() { - return { - longname: 'Umbraco image dialog', - author: 'Umbraco', - authorurl: 'http://umbraco.org', - infourl: 'http://umbraco.org', - version: "1.0" - }; - } - }); - - // Register plugin - tinymce.PluginManager.add('umbracoimg', tinymce.plugins.UmbracoImagePlugin); - -})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/js/image.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/js/image.js deleted file mode 100644 index 25d0028fe8..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/js/image.js +++ /dev/null @@ -1,332 +0,0 @@ -var ImageDialog = { - preInit: function() { - var url; - - tinyMCEPopup.requireLangPack(); - - if (url = tinyMCEPopup.getParam("external_image_list_url")) - document.write(''); - }, - - init: function(ed) { - var f = document.forms[0], nl = f.elements, ed = tinyMCEPopup.editor, dom = ed.dom, n = ed.selection.getNode(); - - tinyMCEPopup.resizeToInnerSize(); - - if (n.nodeName == 'IMG') { - nl.src.value = dom.getAttrib(n, 'src'); - nl.width.value = dom.getAttrib(n, 'width'); - nl.height.value = dom.getAttrib(n, 'height'); - nl.alt.value = dom.getAttrib(n, 'alt'); - nl.orgHeight.value = dom.getAttrib(n, 'rel').split(",")[1]; - nl.orgWidth.value = dom.getAttrib(n, 'rel').split(",")[0]; - - } - - // If option enabled default contrain proportions to checked - if ((ed.getParam("advimage_constrain_proportions", true)) && f.constrain) - f.constrain.checked = true; - - this.changeAppearance(); - this.showPreviewImage(nl.src.value, 1); - }, - - insert: function(file, title) { - var ed = tinyMCEPopup.editor, t = this, f = document.forms[0]; - - if (f.src.value === '') { - if (ed.selection.getNode().nodeName == 'IMG') { - ed.dom.remove(ed.selection.getNode()); - ed.execCommand('mceRepaint'); - } - - tinyMCEPopup.close(); - return; - } - - if (tinyMCEPopup.getParam("accessibility_warnings", 1)) { - if (!f.alt.value) { - tinyMCEPopup.confirm(tinyMCEPopup.getLang('advimage_dlg.missing_alt'), function(s) { - if (s) - t.insertAndClose(); - }); - - return; - } - } - - t.insertAndClose(); - }, - - insertAndClose: function() { - var ed = tinyMCEPopup.editor, f = document.forms[0], nl = f.elements, v, args = {}, el; - - tinyMCEPopup.restoreSelection(); - - // Fixes crash in Safari - if (tinymce.isWebKit) - ed.getWin().focus(); - - if (!ed.settings.inline_styles) { - args = { - vspace: nl.vspace.value, - hspace: nl.hspace.value, - border: nl.border.value, - align: getSelectValue(f, 'align') - }; - } else { - // Remove deprecated values - args = { - vspace: '', - hspace: '', - border: '', - align: '' - }; - } - - tinymce.extend(args, { - src: nl.src.value, - width: nl.width.value, - height: nl.height.value, - alt: nl.alt.value, - title: nl.alt.value, - rel: nl.orgWidth.value + ',' + nl.orgHeight.value - }); - - args.onmouseover = args.onmouseout = ''; - - el = ed.selection.getNode(); - - if (el && el.nodeName == 'IMG') { - ed.dom.setAttribs(el, args); - } else { - ed.execCommand('mceInsertContent', false, '', { skip_undo: 1 }); - ed.dom.setAttribs('__mce_tmp', args); - ed.dom.setAttrib('__mce_tmp', 'id', ''); - ed.undoManager.add(); - } - - tinyMCEPopup.close(); - }, - - getAttrib: function(e, at) { - var ed = tinyMCEPopup.editor, dom = ed.dom, v, v2; - - if (ed.settings.inline_styles) { - switch (at) { - case 'align': - if (v = dom.getStyle(e, 'float')) - return v; - - if (v = dom.getStyle(e, 'vertical-align')) - return v; - - break; - - case 'hspace': - v = dom.getStyle(e, 'margin-left') - v2 = dom.getStyle(e, 'margin-right'); - - if (v && v == v2) - return parseInt(v.replace(/[^0-9]/g, '')); - - break; - - case 'vspace': - v = dom.getStyle(e, 'margin-top') - v2 = dom.getStyle(e, 'margin-bottom'); - if (v && v == v2) - return parseInt(v.replace(/[^0-9]/g, '')); - - break; - - case 'border': - v = 0; - - tinymce.each(['top', 'right', 'bottom', 'left'], function(sv) { - sv = dom.getStyle(e, 'border-' + sv + '-width'); - - // False or not the same as prev - if (!sv || (sv != v && v !== 0)) { - v = 0; - return false; - } - - if (sv) - v = sv; - }); - - if (v) - return parseInt(v.replace(/[^0-9]/g, '')); - - break; - } - } - - if (v = dom.getAttrib(e, at)) - return v; - - return ''; - }, - - setSwapImage: function(st) { - var f = document.forms[0]; - - f.onmousemovecheck.checked = st; - setBrowserDisabled('overbrowser', !st); - setBrowserDisabled('outbrowser', !st); - - if (f.over_list) - f.over_list.disabled = !st; - - if (f.out_list) - f.out_list.disabled = !st; - - f.onmouseoversrc.disabled = !st; - f.onmouseoutsrc.disabled = !st; - }, - - resetImageData: function() { - var f = document.forms[0]; - - f.elements.width.value = f.elements.height.value = ''; - }, - - updateImageData: function(img, st) { - var f = document.forms[0]; - - if (!st) { - f.elements.width.value = img.width; - f.elements.height.value = img.height; - } - - this.preloadImg = img; - }, - - changeAppearance: function() { - var ed = tinyMCEPopup.editor, f = document.forms[0], img = document.getElementById('alignSampleImg'); - - if (img) { - if (ed.getParam('inline_styles')) { - ed.dom.setAttrib(img, 'style', f.style.value); - } else { - img.align = f.align.value; - img.border = f.border.value; - img.hspace = f.hspace.value; - img.vspace = f.vspace.value; - } - } - }, - - changeHeight: function() { - var f = document.forms[0], tp, t = this; - alert(t.preloadImg); - - if (!f.constrain.checked || !t.preloadImg) { - return; - } - - if (f.width.value == '' || f.height.value == '') - return; - - tp = (parseInt(f.width.value) / parseInt(t.preloadImg.width)) * t.preloadImg.height; - f.height.value = tp.toFixed(0); - }, - - changeWidth: function() { - var f = document.forms[0], tp, t = this; - - if (!f.constrain.checked || !t.preloadImg) { - return; - } - - if (f.width.value == '' || f.height.value == '') - return; - - tp = (parseInt(f.height.value) / parseInt(t.preloadImg.height)) * t.preloadImg.width; - f.width.value = tp.toFixed(0); - }, - - updateStyle: function(ty) { - var dom = tinyMCEPopup.dom, st, v, f = document.forms[0], img = dom.create('img', { style: dom.get('style').value }); - - if (tinyMCEPopup.editor.settings.inline_styles) { - // Handle align - if (ty == 'align') { - dom.setStyle(img, 'float', ''); - dom.setStyle(img, 'vertical-align', ''); - - v = getSelectValue(f, 'align'); - if (v) { - if (v == 'left' || v == 'right') - dom.setStyle(img, 'float', v); - else - img.style.verticalAlign = v; - } - } - - // Handle border - if (ty == 'border') { - dom.setStyle(img, 'border', ''); - - v = f.border.value; - if (v || v == '0') { - if (v == '0') - img.style.border = '0'; - else - img.style.border = v + 'px solid black'; - } - } - - // Handle hspace - if (ty == 'hspace') { - dom.setStyle(img, 'marginLeft', ''); - dom.setStyle(img, 'marginRight', ''); - - v = f.hspace.value; - if (v) { - img.style.marginLeft = v + 'px'; - img.style.marginRight = v + 'px'; - } - } - - // Handle vspace - if (ty == 'vspace') { - dom.setStyle(img, 'marginTop', ''); - dom.setStyle(img, 'marginBottom', ''); - - v = f.vspace.value; - if (v) { - img.style.marginTop = v + 'px'; - img.style.marginBottom = v + 'px'; - } - } - - // Merge - dom.get('style').value = dom.serializeStyle(dom.parseStyle(img.style.cssText)); - } - }, - - changeMouseMove: function() { - }, - - showPreviewImage: function(u, st) { - if (!u) { - tinyMCEPopup.dom.setHTML('prev', ''); - return; - } - - if (!st && tinyMCEPopup.getParam("advimage_update_dimensions_onchange", true)) - this.resetImageData(); - - u = tinyMCEPopup.editor.documentBaseURI.toAbsolute(u); - - if (!st) - tinyMCEPopup.dom.setHTML('prev', ''); - else - tinyMCEPopup.dom.setHTML('prev', ''); - } -}; - -ImageDialog.preInit(); -tinyMCEPopup.onInit.add(ImageDialog.init, ImageDialog); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/en_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/en_dlg.js deleted file mode 100644 index 36c09935a4..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/en_dlg.js +++ /dev/null @@ -1,43 +0,0 @@ -tinyMCE.addI18n('en.umbimage_dlg', { - tab_general: 'General', - tab_appearance: 'Appearance', - tab_advanced: 'Advanced', - general: 'General', - title: 'Title', - preview: 'Preview', - constrain_proportions: 'Constrain proportions', - langdir: 'Language direction', - langcode: 'Language code', - long_desc: 'Long description link', - style: 'Style', - classes: 'Classes', - ltr: 'Left to right', - rtl: 'Right to left', - id: 'Id', - map: 'Image map', - swap_image: 'Swap image', - alt_image: 'Alternative image', - mouseover: 'for mouse over', - mouseout: 'for mouse out', - misc: 'Miscellaneous', - example_img: 'Appearance preview image', - missing_alt: 'Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.', - dialog_title: 'Insert/edit image', - src: 'Image URL', - alt: 'Image description', - list: 'Image list', - border: 'Border', - dimensions: 'Dimensions', - vspace: 'Vertical space', - hspace: 'Horizontal space', - align: 'Alignment', - align_baseline: 'Baseline', - align_top: 'Top', - align_middle: 'Middle', - align_bottom: 'Bottom', - align_texttop: 'Text top', - align_textbottom: 'Text bottom', - align_left: 'Left', - align_right: 'Right', - image_list: 'Image list' -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/en_us_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/en_us_dlg.js deleted file mode 100644 index db5be8ae0b..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/en_us_dlg.js +++ /dev/null @@ -1,43 +0,0 @@ -tinyMCE.addI18n('en_us.umbimage_dlg', { - tab_general: 'General', - tab_appearance: 'Appearance', - tab_advanced: 'Advanced', - general: 'General', - title: 'Title', - preview: 'Preview', - constrain_proportions: 'Constrain proportions', - langdir: 'Language direction', - langcode: 'Language code', - long_desc: 'Long description link', - style: 'Style', - classes: 'Classes', - ltr: 'Left to right', - rtl: 'Right to left', - id: 'Id', - map: 'Image map', - swap_image: 'Swap image', - alt_image: 'Alternative image', - mouseover: 'for mouse over', - mouseout: 'for mouse out', - misc: 'Miscellaneous', - example_img: 'Appearance preview image', - missing_alt: 'Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.', - dialog_title: 'Insert/edit image', - src: 'Image URL', - alt: 'Image description', - list: 'Image list', - border: 'Border', - dimensions: 'Dimensions', - vspace: 'Vertical space', - hspace: 'Horizontal space', - align: 'Alignment', - align_baseline: 'Baseline', - align_top: 'Top', - align_middle: 'Middle', - align_bottom: 'Bottom', - align_texttop: 'Text top', - align_textbottom: 'Text bottom', - align_left: 'Left', - align_right: 'Right', - image_list: 'Image list' -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/he_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/he_dlg.js deleted file mode 100644 index 98091a1b41..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/he_dlg.js +++ /dev/null @@ -1,43 +0,0 @@ -tinyMCE.addI18n('he.umbimage_dlg', { - tab_general: 'General', - tab_appearance: 'Appearance', - tab_advanced: 'Advanced', - general: 'General', - title: 'Title', - preview: 'Preview', - constrain_proportions: 'Constrain proportions', - langdir: 'Language direction', - langcode: 'Language code', - long_desc: 'Long description link', - style: 'Style', - classes: 'Classes', - ltr: 'Left to right', - rtl: 'Right to left', - id: 'Id', - map: 'Image map', - swap_image: 'Swap image', - alt_image: 'Alternative image', - mouseover: 'for mouse over', - mouseout: 'for mouse out', - misc: 'Miscellaneous', - example_img: 'Appearance preview image', - missing_alt: 'Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.', - dialog_title: 'Insert/edit image', - src: 'Image URL', - alt: 'Image description', - list: 'Image list', - border: 'Border', - dimensions: 'Dimensions', - vspace: 'Vertical space', - hspace: 'Horizontal space', - align: 'Alignment', - align_baseline: 'Baseline', - align_top: 'Top', - align_middle: 'Middle', - align_bottom: 'Bottom', - align_texttop: 'Text top', - align_textbottom: 'Text bottom', - align_left: 'Left', - align_right: 'Right', - image_list: 'Image list' -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/it_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/it_dlg.js deleted file mode 100644 index d1b32b26c2..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/it_dlg.js +++ /dev/null @@ -1,43 +0,0 @@ -tinyMCE.addI18n('it.umbimage_dlg', { - tab_general: 'Generale', - tab_appearance: 'Aspetto', - tab_advanced: 'Avanzate', - general: 'Generale', - title: 'Titolo', - preview: 'Anteprima', - constrain_proportions: 'Vincola proporzioni', - langdir: 'Direzione lingua', - langcode: 'Codice lingua', - long_desc: 'Descrizione lunga del collegamento', - style: 'Stile', - classes: 'Classi', - ltr: 'Da sinistra a destra', - rtl: 'Da destra a sinistra', - id: 'Id', - map: 'Image map', - swap_image: 'Swap immagine', - alt_image: 'Testo alternativo', - mouseover: 'Mouse over', - mouseout: 'Mouse out', - misc: 'Varie', - example_img: 'Aspetto anteprima immagine', - missing_alt: 'Sei sicuro di voler continuare senza includere una Descrizione dell'immagine? Se non lo fai l'immagine potrebbe risultare non accessibile per gli utenti con disabilit\u00E0, o per chi utilizza un browser di testo, o per chi naviga senza immagini.', - dialog_title: 'Inserisci/Modifica immagine', - src: 'URL immagine', - alt: 'Descrizione immagine', - list: 'Immagine lista', - border: 'Bordo', - dimensions: 'Dimensioni', - vspace: 'Spaziatura verticale', - hspace: 'Spaziatura orizzontale', - align: 'Allineamento', - align_baseline: 'Baseline', - align_top: 'Top', - align_middle: 'Middle', - align_bottom: 'Bottom', - align_texttop: 'Testo superiore', - align_textbottom: 'Testo inferiore', - align_left: 'Sinistra', - align_right: 'Destra', - image_list: 'Immagine lista' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/ja_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/ja_dlg.js deleted file mode 100644 index 1140ea22c9..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/ja_dlg.js +++ /dev/null @@ -1,43 +0,0 @@ -tinyMCE.addI18n('ja.umbimage_dlg', { - tab_general: '一般', - tab_appearance: '表示', - tab_advanced: '高度な設定', - general: '一般', - title: 'タイトル', - preview: 'プレビュー', - constrain_proportions: '縦横比の維持', - langdir: '文章の方向', - langcode: '言語コード', - long_desc: '詳細な説明のリンク', - style: 'スタイル', - classes: 'クラス', - ltr: '左から右', - rtl: '右から左', - id: 'Id', - map: 'イメージマップ', - swap_image: '画像の入れ替え', - alt_image: '別の画像', - mouseover: 'マウスカーソルがかかる時', - mouseout: 'マウスカーソルが外れる時', - misc: 'その他', - example_img: '画像のプレビューの様子', - missing_alt: '画像の説明を含めずに続けますか?画像の説明がないと目の不自由な方、テキスト表示だけのブラウザを使用している方、画像の表示を止めてる方がアクセスできないかもしれません。', - dialog_title: '画像の挿入/編集', - src: '画像のURL', - alt: '画像の説明', - list: '画像の一覧', - border: '枠線', - dimensions: '寸法', - vspace: '上下の余白', - hspace: '左右の余白', - align: '配置', - align_baseline: 'ベースライン揃え', - align_top: '上揃え', - align_middle: '中央揃え', - align_bottom: '下揃え', - align_texttop: 'テキストの上端揃え', - align_textbottom: 'テキストの下端揃え', - align_left: '左寄せ', - align_right: '右寄せ', - image_list: '画像の一覧' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/ru_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/ru_dlg.js deleted file mode 100644 index 4cb8e5558a..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/ru_dlg.js +++ /dev/null @@ -1,43 +0,0 @@ -tinyMCE.addI18n('ru.umbimage_dlg', { - tab_general: 'Общее', - tab_appearance: 'Вид', - tab_advanced: 'Дополнительно', - general: 'Общие свойства', - title: 'Заголовок', - preview: 'Предпросмотр', - constrain_proportions: 'Сохранять пропорции', - langdir: 'Направление языка', - langcode: 'Код языка', - long_desc: 'Ссылка на длинное описание', - style: 'Стиль', - classes: 'Классы CSS', - ltr: 'Слева напрапво', - rtl: 'Справа налево', - id: 'Id', - map: 'Карта', - swap_image: 'Замена', - alt_image: 'Альтернатива', - mouseover: 'при заходе мыши', - mouseout: 'при выходе мыши', - misc: 'Разное', - example_img: 'Пример внешнего вида', - missing_alt: 'Вы уверены, что хотите продолжить без указания описания изображения? Без описания изображение может оказаться недоступным некоторым категориям пользователей с ограниченными возможностями, или использующим текстовый браузер, а также пользователям, отключившим показ изображений.', - dialog_title: 'Вставить/изменить изображение', - src: 'URL изображения', - alt: 'Описание изображения', - list: 'Список', - border: 'Рамка', - dimensions: 'Размеры', - vspace: 'Отступ по вертикали', - hspace: 'Отступ по горизонтали', - align: 'Выравнивание', - align_baseline: 'По базовой линии', - align_top: 'По верху', - align_middle: 'По центру', - align_bottom: 'По низу', - align_texttop: 'По верху текста', - align_textbottom: 'По низу текста', - align_left: 'По левому краю', - align_right: 'По правому краю', - image_list: 'Список изображений' -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/sv_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/sv_dlg.js deleted file mode 100644 index 2c18b280c5..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/sv_dlg.js +++ /dev/null @@ -1,43 +0,0 @@ -tinyMCE.addI18n('sv.umbimage_dlg', { - tab_general: 'Generellt', - tab_appearance: 'Utseende', - tab_advanced: 'Avancerat', - general: 'Generellt', - title: 'Titel', - preview: 'Förhandsgranska', - constrain_proportions: 'Bibehåll proportioner', - langdir: 'Språkdirektion', - langcode: 'Språkkod', - long_desc: 'Lång länkbeskrivning', - style: 'Stil', - classes: 'Klasser', - ltr: 'Vänster till höger', - rtl: 'höger till vänster', - id: 'Id', - map: 'Bildkarta', - swap_image: 'Byt bild', - alt_image: 'Alternativ bild', - mouseover: 'För musen över', - mouseout: 'för musen utanför', - misc: 'Blandat', - example_img: 'Visning av bildförhandsgranskning', - missing_alt: 'Are you sure you want to continue without including an Image Description? Without it the image may not be accessible to some users with disabilities, or to those using a text browser, or browsing the Web with images turned off.', - dialog_title: 'Infoga/redigera bild', - src: 'Bild URL', - alt: 'Bildbeskrivning', - list: 'Bildlista', - border: 'Ram', - dimensions: 'Dimensioner', - vspace: 'Vertikalt avstånd', - hspace: 'Horisontellt avstånd', - align: 'Position', - align_baseline: 'Baslinje', - align_top: 'Toppen', - align_middle: 'Mitten', - align_bottom: 'Botten', - align_texttop: 'Text topp', - align_textbottom: 'Text botten', - align_left: 'Vänster', - align_right: 'Höger', - image_list: 'Bildlista' -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/zh_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/zh_dlg.js deleted file mode 100644 index 449c6df44d..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoimg/langs/zh_dlg.js +++ /dev/null @@ -1,43 +0,0 @@ -tinyMCE.addI18n('zh.umbimage_dlg', { - tab_general: '普通', - tab_appearance: '外观', - tab_advanced: '高级', - general: '普通', - title: '标题', - preview: '预览', - constrain_proportions: '约束比例', - langdir: '语言书写方向', - langcode: '语言代码', - long_desc: '长原文链接', - style: '样式', - classes: '类', - ltr: '从左到右', - rtl: '从右到左', - id: 'Id', - map: '图片热区', - swap_image: '交换图片', - alt_image: '替代图片', - mouseover: '鼠标移入', - mouseout: '鼠标移出', - misc: '其它', - example_img: '样图外观', - missing_alt: '你确定不要图片替代文字吗?替代文字可以在图片无法显示时显示。', - dialog_title: '插入/编辑图片', - src: '图片URL', - alt: '图片描述', - list: '图片列表', - border: '边框', - dimensions: '尺寸', - vspace: '垂直间距', - hspace: '水平间距', - align: '对齐', - align_baseline: '对齐底线', - align_top: '顶部对齐', - align_middle: '中间对齐', - align_bottom: '底部对齐', - align_texttop: '对齐文字顶部', - align_textbottom: '对齐文字底部', - align_left: '左对齐', - align_right: '右对齐', - image_list: '图片列表' -}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracolink/plugin.min.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracolink/plugin.min.js deleted file mode 100644 index d1757de319..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracolink/plugin.min.js +++ /dev/null @@ -1,285 +0,0 @@ -/** - * Umbraco Link Plugin, based on the original link plugin by MoxieCode - * swapped out the dialog implementation with our own dialog service - * and support for passing in localLinks - */ - -/*global tinymce:true */ - -tinymce.PluginManager.add('umbracolink', function(editor) { - function createLinkList(callback) { - return function() { - var linkList = editor.settings.link_list; - - if (typeof(linkList) == "string") { - tinymce.util.XHR.send({ - url: linkList, - success: function(text) { - callback(tinymce.util.JSON.parse(text)); - } - }); - } else { - callback(linkList); - } - }; - } - - function showDialog(linkList) { - var data = {}, selection = editor.selection, dom = editor.dom, selectedElm, anchorElm, initialText; - var win, linkListCtrl, relListCtrl, targetListCtrl; - - function linkListChangeHandler(e) { - var textCtrl = win.find('#text'); - - if (!textCtrl.value() || (e.lastControl && textCtrl.value() == e.lastControl.text())) { - textCtrl.value(e.control.text()); - } - - win.find('#href').value(e.control.value()); - } - - function buildLinkList() { - var linkListItems = [{text: 'None', value: ''}]; - - tinymce.each(linkList, function(link) { - linkListItems.push({ - text: link.text || link.title, - value: link.value || link.url, - menu: link.menu - }); - }); - - return linkListItems; - } - - function buildRelList(relValue) { - var relListItems = [{text: 'None', value: ''}]; - - tinymce.each(editor.settings.rel_list, function(rel) { - relListItems.push({ - text: rel.text || rel.title, - value: rel.value, - selected: relValue === rel.value - }); - }); - - return relListItems; - } - - function buildTargetList(targetValue) { - var targetListItems = [{text: 'None', value: ''}]; - - if (!editor.settings.target_list) { - targetListItems.push({text: 'New window', value: '_blank'}); - } - - tinymce.each(editor.settings.target_list, function(target) { - targetListItems.push({ - text: target.text || target.title, - value: target.value, - selected: targetValue === target.value - }); - }); - - return targetListItems; - } - - function buildAnchorListControl(url) { - var anchorList = []; - - tinymce.each(editor.dom.select('a:not([href])'), function(anchor) { - var id = anchor.name || anchor.id; - - if (id) { - anchorList.push({ - text: id, - value: '#' + id, - selected: url.indexOf('#' + id) != -1 - }); - } - }); - - if (anchorList.length) { - anchorList.unshift({text: 'None', value: ''}); - - return { - name: 'anchor', - type: 'listbox', - label: 'Anchors', - values: anchorList, - onselect: linkListChangeHandler - }; - } - } - - function updateText() { - if (!initialText && data.text.length === 0) { - this.parent().parent().find('#text')[0].value(this.value()); - } - } - - selectedElm = selection.getNode(); - anchorElm = dom.getParent(selectedElm, 'a[href]'); - - data.text = initialText = anchorElm ? (anchorElm.innerText || anchorElm.textContent) : selection.getContent({format: 'text'}); - data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : ''; - data.target = anchorElm ? dom.getAttrib(anchorElm, 'target') : ''; - data.rel = anchorElm ? dom.getAttrib(anchorElm, 'rel') : ''; - - if (selectedElm.nodeName == "IMG") { - data.text = initialText = " "; - } - - if (linkList) { - linkListCtrl = { - type: 'listbox', - label: 'Link list', - values: buildLinkList(), - onselect: linkListChangeHandler - }; - } - - if (editor.settings.target_list !== false) { - targetListCtrl = { - name: 'target', - type: 'listbox', - label: 'Target', - values: buildTargetList(data.target) - }; - } - - if (editor.settings.rel_list) { - relListCtrl = { - name: 'rel', - type: 'listbox', - label: 'Rel', - values: buildRelList(data.rel) - }; - } - - var injector = angular.element(document.getElementById("umbracoMainPageBody")).injector(); - var dialogService = injector.get("dialogService"); - var currentTarget = undefined; - - //if we already have a link selected, we want to pass that data over to the dialog - if(anchorElm){ - var anchor = $(anchorElm); - currentTarget = { - name: anchor.attr("title"), - url: anchor.attr("href"), - target: anchor.attr("target") - }; - - //locallink detection, we do this here, to avoid poluting the dialogservice - //so the dialog service can just expect to get a node-like structure - if (currentTarget.url.indexOf("localLink:") > 0) { - var linkId = currentTarget.url.substring(currentTarget.url.indexOf(":") + 1, currentTarget.url.length - 1); - //we need to check if this is an INT or a UDI - var parsedIntId = parseInt(linkId, 10); - if (isNaN(parsedIntId)) { - //it's a UDI - currentTarget.udi = linkId; - } - else { - currentTarget.id = linkId; - } - } - } - - dialogService.linkPicker({ - currentTarget: currentTarget, - callback: function (data) { - if (data) { - var href = data.url; - // We want to use the Udi. If it is set, we use it, else fallback to id, and finally to null - var hasUdi = data.udi ? true : false; - var id = hasUdi ? data.udi : (data.id ? data.id : null); - - //Create a json obj used to create the attributes for the tag - function createElemAttributes() { - var a = { - href: href, - title: data.name, - target: data.target ? data.target : null, - rel: data.rel ? data.rel : null - }; - if (hasUdi) { - a["data-udi"] = data.udi; - } - else if (data.id) { - a["data-id"] = data.id; - } - } - - function insertLink() { - if (anchorElm) { - dom.setAttribs(anchorElm, createElemAttributes()); - - selection.select(anchorElm); - editor.execCommand('mceEndTyping'); - } else { - editor.execCommand('mceInsertLink', false, createElemAttributes()); - } - } - - if (!href) { - editor.execCommand('unlink'); - return; - } - - //if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set - if (id && (angular.isUndefined(data.isMedia) || !data.isMedia)){ - - href = "/{localLink:" + id + "}"; - - insertLink(); - return; - } - - // Is email and not //user@domain.com - if (href.indexOf('@') > 0 && href.indexOf('//') == -1 && href.indexOf('mailto:') == -1) { - href = 'mailto:' + href; - insertLink(); - return; - } - - // Is www. prefixed - if (/^\s*www\./i.test(href)) { - href = 'http://' + href; - insertLink(); - return; - } - insertLink(); - } - } - }); - } - - editor.addButton('link', { - icon: 'link', - tooltip: 'Insert/edit link', - shortcut: 'Ctrl+K', - onclick: createLinkList(showDialog), - stateSelector: 'a[href]' - }); - - editor.addButton('unlink', { - icon: 'unlink', - tooltip: 'Remove link', - cmd: 'unlink', - stateSelector: 'a[href]' - }); - - editor.addShortcut('Ctrl+K', '', createLinkList(showDialog)); - this.showDialog = showDialog; - - editor.addMenuItem('link', { - icon: 'link', - text: 'Insert link', - shortcut: 'Ctrl+K', - onclick: createLinkList(showDialog), - stateSelector: 'a[href]', - context: 'insert', - prependToContext: true - }); -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/dialog.htm b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/dialog.htm deleted file mode 100644 index b4c62840ea..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/dialog.htm +++ /dev/null @@ -1,27 +0,0 @@ - - - - {#example_dlg.title} - - - - - -
-

Here is a example dialog.

-

Selected text:

-

Custom arg:

- -
-
- -
- -
- -
-
-
- - - diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/editor_plugin_src.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/editor_plugin_src.js deleted file mode 100644 index 35fc20fc14..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/editor_plugin_src.js +++ /dev/null @@ -1,145 +0,0 @@ -/** -* $Id: editor_plugin_src.js 201 2007-02-12 15:56:56Z spocke $ -* -* @author Moxiecode -* @copyright Copyright 2004-2008, Moxiecode Systems AB, All rights reserved. -*/ - -(function() { - // Load plugin specific language pack -// tinymce.PluginManager.requireLangPack('umbraco'); - - tinymce.create('tinymce.plugins.umbracomacro', { - /** - * Initializes the plugin, this will be executed after the plugin has been created. - * This call is done before the editor instance has finished it's initialization so use the onInit event - * of the editor instance to intercept that event. - * - * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. - * @param {string} url Absolute URL to where the plugin is located. - */ - init: function(ed, url) { - var t = this; - - // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample'); - ed.addCommand('mceumbracomacro', function() { - var se = ed.selection; - - var urlParams = ""; - var el = se.getNode(); - - // ie selector bug - if (!ed.dom.hasClass(el, 'umbMacroHolder')) { - el = ed.dom.getParent(el, 'div.umbMacroHolder'); - } - - var attrString = ""; - if (ed.dom.hasClass(el, 'umbMacroHolder')) { - for (var i = 0; i < el.attributes.length; i++) { - attrName = el.attributes[i].nodeName.toLowerCase(); - if (attrName != "mce_serialized") { - if (el.attributes[i].nodeValue && (attrName != 'ismacro' && attrName != 'style' && attrName != 'contenteditable')) { - attrString += el.attributes[i].nodeName + '=' + escape(t._utf8_encode(el.attributes[i].nodeValue)) + '&'; //.replace(/#/g, "%23").replace(/\/g, "%3E").replace(/\"/g, "%22") + '&'; - - } - } - } - - // vi trunkerer strengen ved at fjerne et evt. overskydende amp; - if (attrString.length > 0) - attrString = attrString.substr(0, attrString.length - 1); - - urlParams = "&" + attrString; - } else { - urlParams = '&umbPageId=' + tinyMCE.activeEditor.getParam('theme_umbraco_pageId') + '&umbVersionId=' + tinyMCE.activeEditor.getParam('theme_umbraco_versionId'); - } - - ed.windowManager.open({ - file: tinyMCE.activeEditor.getParam('umbraco_path') + '/plugins/tinymce3/insertMacro.aspx?editor=trueurl' + urlParams, - width: 480 + parseInt(ed.getLang('umbracomacro.delta_width', 0)), - height: 470 + parseInt(ed.getLang('umbracomacro.delta_height', 0)), - inline: 1 - }, { - plugin_url: url // Plugin absolute URL - }); - }); - - // Register example button - ed.addButton('umbracomacro', { - title: 'umbracomacro.desc', - cmd: 'mceumbracomacro', - image: url + '/img/insMacro.gif' - }); - - // Add a node change handler, test if we're editing a macro - ed.onNodeChange.addToTop(function(ed, cm, n) { - - var macroElement = ed.dom.getParent(ed.selection.getStart(), 'div.umbMacroHolder'); - - // mark button if it's a macro - cm.setActive('umbracomacro', macroElement && ed.dom.hasClass(macroElement, 'umbMacroHolder')); - - }); - }, - - _utf8_encode: function(string) { - string = string.replace(/\r\n/g, "\n"); - var utftext = ""; - - for (var n = 0; n < string.length; n++) { - - var c = string.charCodeAt(n); - - if (c < 128) { - utftext += String.fromCharCode(c); - } - else if ((c > 127) && (c < 2048)) { - utftext += String.fromCharCode((c >> 6) | 192); - utftext += String.fromCharCode((c & 63) | 128); - } - else { - utftext += String.fromCharCode((c >> 12) | 224); - utftext += String.fromCharCode(((c >> 6) & 63) | 128); - utftext += String.fromCharCode((c & 63) | 128); - } - - } - - return utftext; - }, - - /** - * Creates control instances based in the incomming name. This method is normally not - * needed since the addButton method of the tinymce.Editor class is a more easy way of adding buttons - * but you sometimes need to create more complex controls like listboxes, split buttons etc then this - * method can be used to create those. - * - * @param {String} n Name of the control to create. - * @param {tinymce.ControlManager} cm Control manager to use inorder to create new control. - * @return {tinymce.ui.Control} New control instance or null if no control was created. - */ - createControl: function(n, cm) { - return null; - }, - - - /** - * Returns information about the plugin as a name/value array. - * The current keys are longname, author, authorurl, infourl and version. - * - * @return {Object} Name/value array containing information about the plugin. - */ - getInfo: function() { - return { - longname: 'Umbraco Macro Insertion Plugin', - author: 'Umbraco', - authorurl: 'http://umbraco.org', - infourl: 'http://umbraco.org/redir/tinymcePlugins', - version: "1.0" - }; - } - }); - - // Register plugin - tinymce.PluginManager.add('umbracomacro', tinymce.plugins.umbracomacro); -})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/img/insMacro.gif b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/img/insMacro.gif deleted file mode 100644 index 43c58f4f03cc8702deda7ba83d6756d7a15211e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 603 zcmZ?wbhEHb6k!lyc*el+{Q1kbpZbFz3zh8d% zbLG|(Z$AAwaP{lrO($lp*t>k&nYpX?FIabI;krXhHyvHE^~B{zKiBR&y>aikL#J;( zdHehA=Rcpn|26eYp1f%L^kuuJE!{PB$n^m$|Gmo3p>wk3YqnelaR!MB6u-wsuOJ5u-USj+blZQoCJeLvOn{dE8Lvy*?E zpZ??GoS#>h{Jg&M=dJa>?rs0|V9)Qzhkidj_WSAafB*jd|Noz1pn>8~7Dfh!5C$EP zLqKujz`mm)q^Y^3wXKOSxU0KMjY(QWwoOiU>a^+8+BDqfxVbnv*xT9KSX)gF*40yI z=3z6}F%eUl)V^(d$ZU64XU9cLtqy9mDF>_TX_*BZXc{rF2yShW>tbePlw#rJ&7uhu%5f1&s_0)&Mvp3Vr|p diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/js/dialog.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/js/dialog.js deleted file mode 100644 index fa8341132f..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/js/dialog.js +++ /dev/null @@ -1,19 +0,0 @@ -tinyMCEPopup.requireLangPack(); - -var ExampleDialog = { - init : function() { - var f = document.forms[0]; - - // Get the selected contents as text and place it in the input - f.someval.value = tinyMCEPopup.editor.selection.getContent({format : 'text'}); - f.somearg.value = tinyMCEPopup.getWindowArg('some_custom_arg'); - }, - - insert : function() { - // Insert the contents from the input into the document - tinyMCEPopup.editor.execCommand('mceInsertContent', false, document.forms[0].someval.value); - tinyMCEPopup.close(); - } -}; - -tinyMCEPopup.onInit.add(ExampleDialog.init, ExampleDialog); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en.js deleted file mode 100644 index 60b03b55c7..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('en.umbracomacro',{ - desc : 'Insert macro' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_dlg.js deleted file mode 100644 index ebcf948dac..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_dlg.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('en.example_dlg',{ - title : 'This is just a example title' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_us.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_us.js deleted file mode 100644 index 61fee28c63..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_us.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('en_us.umbracomacro',{ - desc : 'Insert macro' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_us_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_us_dlg.js deleted file mode 100644 index 0468c4553c..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/en_us_dlg.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('en_us.example_dlg',{ - title : 'This is just a example title' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/he.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/he.js deleted file mode 100644 index 09319cceaa..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/he.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('he.umbracomacro',{ - desc : 'הוסף מאקרו' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/he_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/he_dlg.js deleted file mode 100644 index 390eabc168..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/he_dlg.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('he.example_dlg',{ - title : 'This is just a example title' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ja.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ja.js deleted file mode 100644 index 32e79f18c6..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ja.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('ja.umbracomacro',{ - desc : 'マクロの挿入' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ja_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ja_dlg.js deleted file mode 100644 index 67f4140f92..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ja_dlg.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('ja.example_dlg',{ - title : 'これはタイトルの例です' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ru.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ru.js deleted file mode 100644 index f9a98c4fb0..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ru.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('ru.umbracomacro',{ - desc : 'Вставить макрос' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ru_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ru_dlg.js deleted file mode 100644 index 3fa610a3ee..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/ru_dlg.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('ru.example_dlg',{ - title : ' ' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/sv.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/sv.js deleted file mode 100644 index fc134d5698..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/sv.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('sv.umbracomacro',{ - desc : 'Infoga makro' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/sv_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/sv_dlg.js deleted file mode 100644 index 3bf4ed0880..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/sv_dlg.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('sv.example_dlg',{ - title : 'Detta är bar ett exempel på en titel' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/zh.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/zh.js deleted file mode 100644 index f2edf9598f..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/zh.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('zh.umbracomacro',{ - desc : '插入宏' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/zh_dlg.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/zh_dlg.js deleted file mode 100644 index db7ad925a0..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracomacro/langs/zh_dlg.js +++ /dev/null @@ -1,3 +0,0 @@ -tinyMCE.addI18n('zh.example_dlg',{ - title : '这是示例标题' -}); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracopaste/editor_plugin_src.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracopaste/editor_plugin_src.js deleted file mode 100644 index aaf58e7c2d..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracopaste/editor_plugin_src.js +++ /dev/null @@ -1,53 +0,0 @@ -/** -* editor_plugin_src.js -* -* Copyright 2012, Umbraco -* Released under MIT License. -* -* License: http://opensource.org/licenses/mit-license.html -*/ - -(function () { - var Event = tinymce.dom.Event, each = tinymce.each, DOM = tinymce.DOM; - - /** - * This plugin modifies the standard TinyMCE paste, with umbraco specific changes. - * - * @class tinymce.plugins.umbContextMenu - */ - tinymce.create('tinymce.plugins.UmbracoPaste', { - /** - * Initializes the plugin, this will be executed after the plugin has been created. - * This call is done before the editor instance has finished it's initialization so use the onInit event - * of the editor instance to intercept that event. - * - * @method init - * @param {tinymce.Editor} ed Editor instance that the plugin is initialized in. - * @param {string} url Absolute URL to where the plugin is located. - */ - init: function (ed) { - var t = this; - - ed.plugins.paste.onPreProcess.add(function (pl, o) { - - var ed = this.editor, h = o.content; - - var umbracoAllowedStyles = ed.getParam('theme_umbraco_styles'); - for (var i = 1; i < 7; i++) { - if (umbracoAllowedStyles.indexOf("h" + i) == -1) { - h = h.replace(new RegExp(']*', 'gi'), '

', 'gi'), '

'); - } - } - - o.content = h; - - }); - - } - - }); - - // Register plugin - tinymce.PluginManager.add('umbracopaste', tinymce.plugins.UmbracoPaste); -})(); diff --git a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoshortcut/editor_plugin_src.js b/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoshortcut/editor_plugin_src.js deleted file mode 100644 index 15d669b4e1..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/tinymce/plugins/umbracoshortcut/editor_plugin_src.js +++ /dev/null @@ -1,43 +0,0 @@ - -(function () { - tinymce.create('tinymce.plugins.Umbracoshortcut', { - init: function (ed, url) { - var t = this; - var ctrlPressed = false; - - t.editor = ed; - - ed.onKeyDown.add(function (ed, e) { - if (e.keyCode == 17) - ctrlPressed = true; - - if (ctrlPressed && e.keyCode == 83) { - jQuery(document).trigger("UMBRACO_TINYMCE_SAVE", e); - ctrlPressed = false; - tinymce.dom.Event.cancel(e); - return false; - } - }); - - ed.onKeyUp.add(function (ed, e) { - if (e.keyCode == 17) - ctrlPressed = false; - }); - }, - - getInfo: function () { - return { - longname: 'Umbraco Save short cut key', - author: 'Umbraco HQ', - authorurl: 'http://umbraco.com', - infourl: 'http://our.umbraco.org', - version: "1.0" - }; - } - - // Private methods - }); - - // Register plugin - tinymce.PluginManager.add('umbracoshortcut', tinymce.plugins.Umbracoshortcut); -})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/app.js b/src/Umbraco.Web.UI.Client/src/app.js index 64f468712a..e7b7288f43 100644 --- a/src/Umbraco.Web.UI.Client/src/app.js +++ b/src/Umbraco.Web.UI.Client/src/app.js @@ -39,7 +39,7 @@ angular.module("umbraco.viewcache", []) $delegate.get = function (url, config) { if (Umbraco.Sys.ServerVariables.application && url.startsWith("views/") && url.endsWith(".html")) { - var rnd = Umbraco.Sys.ServerVariables.application.version + "." + Umbraco.Sys.ServerVariables.application.cdf; + var rnd = Umbraco.Sys.ServerVariables.application.cacheBuster; var _op = (url.indexOf("?") > 0) ? "&" : "?"; url += _op + "umb__rnd=" + rnd; } diff --git a/src/Umbraco.Web.UI.Client/src/assets/img/installer.jpg b/src/Umbraco.Web.UI.Client/src/assets/img/installer.jpg index b380efc4956ca90fb05399310e04275427e21160..def9226482278c2fab3bce88124c086af5590563 100644 GIT binary patch literal 317197 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 z za<+TThkF|)<3_o$GQ`XWrPMGfBKU_=7-3T)y;YZT9E?vLw!WyVXu03D@#2i<@U(!K)#9ie;%04M#sRsR4!Y;+X=0DXst z_pz&o{`Gz1N3CE=l9_{#drF9Z1S*L|8b|HL^{QP2DbgB)o+A?40IHBe`R9bdlX7() zd~tyyK}(Q88RAI*A*k7&bpsNB7hXSR2pDh){{UVb0B)IKn8VsJwai6S;x3{v&(&xn zwl+X{-^>31Q;rYTR93$K0OTVD*)P`0{Y2mPYnnwkJOY!Gd{pO-XVdw9j#WP`w72#9 z3i4NSEdKyZk-3P9XeCWJk}>J6NN{5tZ<_>nw({R2l(@BsvZh5{Q#v05O4A(gsPI-w zyQdba`{1`8NYJXl`dksf@%UrS<9eEdO>-=*QfN5=!v(TFz$J>n>>xV;9e@tN2Velv zF1b|)GBDDX1F5McLjb{e>hti$urVp;xG;zwS9rk`LhQ&X;H1+LvIfL4SdPO3uz>6U zb{HMc03Cn}Ut?6+U4xJ^sQ&=S!$j&>Y;2a!CRj<*^gKEIKc@*O8KQe7*pc^-buRI{ zul>i{Qb%!c2&lNauDD>&DpYHKAO}2V^;19zU?MCZlX%G;0j`801sXurLlFH@9xVMaHcbZd|Oi4

3V@;(UNY8L~&gZ?nup4lSEtbqp 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%0Dr}OELZ?b=FDySmPEu&5b#!wvb20 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 QfH8lHzusTpgvNjW*@k81;s5{u literal 279297 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�_ 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

{n!T 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%0AG>(4EB`{yw2&m^Zkp%h6w_f7 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

Markup example

+
+    
+ + + + + + + +
+
+ +

Controller example

+
+    (function () {
+        "use strict";
+
+        function Controller() {
+
+            var vm = this;
+            vm.checked = false;
+
+            vm.toggle = toggle;
+
+            function toggle() {
+                vm.checked = !vm.checked;
+            }
+        }
+
+        angular.module("umbraco").controller("My.Controller", Controller);
+
+    })();
+
+ +@param {boolean} checked Set to true or false to toggle the switch. +@param {callback} onClick The function which should be called when the toggle is clicked. +@param {string=} showLabels Set to true or false to show a "On" or "Off" label next to the switch. +@param {string=} labelOn Set a custom label for when the switched is turned on. It will default to "On". +@param {string=} labelOff Set a custom label for when the switched is turned off. It will default to "Off". +@param {string=} labelPosition Sets the label position to the left or right of the switch. It will default to "left" ("left", "right"). +@param {string=} hideIcons Set to true or false to hide the icons on the switch. + +**/ + +(function () { + 'use strict'; + + function ToggleDirective(localizationService) { + + function link(scope, el, attr, ctrl) { + + scope.displayLabelOn = ""; + scope.displayLabelOff = ""; + + function onInit() { + setLabelText(); + } + + function setLabelText() { + + // set default label for "on" + if (scope.labelOn) { + scope.displayLabelOn = scope.labelOn; + } else { + localizationService.localize("general_on").then(function (value) { + scope.displayLabelOn = value; + }); + } + + // set default label for "Off" + if (scope.labelOff) { + scope.displayLabelOff = scope.labelOff; + } else { + localizationService.localize("general_off").then(function (value) { + scope.displayLabelOff = value; + }); + } + + } + + scope.click = function() { + if(scope.onClick) { + scope.onClick(); + } + }; + + onInit(); + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/buttons/umb-toggle.html', + scope: { + checked: "=", + onClick: "&", + labelOn: "@?", + labelOff: "@?", + labelPosition: "@?", + showLabels: "@?", + hideIcons: "@?" + }, + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('umbToggle', ToggleDirective); + +})(); + + + diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js new file mode 100644 index 0000000000..db5def83d8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -0,0 +1,252 @@ +(function () { + 'use strict'; + + function ContentEditController($rootScope, $scope, $routeParams, $q, $timeout, $window, appState, contentResource, entityResource, navigationService, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, treeService, fileManager, formHelper, umbRequestHelper, keyboardService, umbModelMapper, editorState, $http) { + + //setup scope vars + $scope.defaultButton = null; + $scope.subButtons = []; + + $scope.page = {}; + $scope.page.loading = false; + $scope.page.menu = {}; + $scope.page.menu.currentNode = null; + $scope.page.menu.currentSection = appState.getSectionState("currentSection"); + $scope.page.listViewPath = null; + $scope.page.isNew = $scope.isNew ? true : false; + $scope.page.buttonGroupState = "init"; + + function init(content) { + + var buttons = contentEditingHelper.configureContentEditorButtons({ + create: $scope.page.isNew, + content: content, + methods: { + saveAndPublish: $scope.saveAndPublish, + sendToPublish: $scope.sendToPublish, + save: $scope.save, + unPublish: $scope.unPublish + } + }); + $scope.defaultButton = buttons.defaultButton; + $scope.subButtons = buttons.subButtons; + + editorState.set($scope.content); + + //We fetch all ancestors of the node to generate the footer breadcrumb navigation + if (!$scope.page.isNew) { + if (content.parentId && content.parentId !== -1) { + entityResource.getAncestors(content.id, "document") + .then(function (anc) { + $scope.ancestors = anc; + }); + } + } + } + + /** Syncs the content item to it's tree node - this occurs on first load and after saving */ + function syncTreeNode(content, path, initialLoad) { + + if (!$scope.content.isChildOfListView) { + navigationService.syncTree({ tree: $scope.treeAlias, path: path.split(","), forceReload: initialLoad !== true }).then(function (syncArgs) { + $scope.page.menu.currentNode = syncArgs.node; + }); + } + else if (initialLoad === true) { + + //it's a child item, just sync the ui node to the parent + navigationService.syncTree({ tree: $scope.treeAlias, path: path.substring(0, path.lastIndexOf(",")).split(","), forceReload: initialLoad !== true }); + + //if this is a child of a list view and it's the initial load of the editor, we need to get the tree node + // from the server so that we can load in the actions menu. + umbRequestHelper.resourcePromise( + $http.get(content.treeNodeUrl), + 'Failed to retrieve data for child node ' + content.id).then(function (node) { + $scope.page.menu.currentNode = node; + }); + } + } + + // This is a helper method to reduce the amount of code repitition for actions: Save, Publish, SendToPublish + function performSave(args) { + var deferred = $q.defer(); + + $scope.page.buttonGroupState = "busy"; + + contentEditingHelper.contentEditorPerformSave({ + statusMessage: args.statusMessage, + saveMethod: args.saveMethod, + scope: $scope, + content: $scope.content, + action: args.action + }).then(function (data) { + //success + init($scope.content); + syncTreeNode($scope.content, data.path); + + $scope.page.buttonGroupState = "success"; + + deferred.resolve(data); + }, function (err) { + //error + if (err) { + editorState.set($scope.content); + } + + $scope.page.buttonGroupState = "error"; + + deferred.reject(err); + }); + + return deferred.promise; + } + + function resetLastListPageNumber(content) { + // We're using rootScope to store the page number for list views, so if returning to the list + // we can restore the page. If we've moved on to edit a piece of content that's not the list or it's children + // we should remove this so as not to confuse if navigating to a different list + if (!content.isChildOfListView && !content.isContainer) { + $rootScope.lastListViewPageViewed = null; + } + } + + if ($scope.page.isNew) { + + $scope.page.loading = true; + + //we are creating so get an empty content item + $scope.getScaffoldMethod()() + .then(function (data) { + + $scope.content = data; + + init($scope.content); + + resetLastListPageNumber($scope.content); + + $scope.page.loading = false; + + }); + } + else { + + $scope.page.loading = true; + + //we are editing so get the content item from the server + $scope.getMethod()($scope.contentId) + .then(function (data) { + + $scope.content = data; + + if (data.isChildOfListView && data.trashed === false) { + $scope.page.listViewPath = ($routeParams.page) ? + "/content/content/edit/" + data.parentId + "?page=" + $routeParams.page : + "/content/content/edit/" + data.parentId; + } + + init($scope.content); + + //in one particular special case, after we've created a new item we redirect back to the edit + // route but there might be server validation errors in the collection which we need to display + // after the redirect, so we will bind all subscriptions which will show the server validation errors + // if there are any and then clear them so the collection no longer persists them. + serverValidationManager.executeAndClearAllSubscriptions(); + + syncTreeNode($scope.content, data.path, true); + + resetLastListPageNumber($scope.content); + + $scope.page.loading = false; + + }); + } + + + $scope.unPublish = function () { + + if (formHelper.submitForm({ scope: $scope, statusMessage: "Unpublishing...", skipValidation: true })) { + + $scope.page.buttonGroupState = "busy"; + + contentResource.unPublish($scope.content.id) + .then(function (data) { + + formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + + contentEditingHelper.handleSuccessfulSave({ + scope: $scope, + savedContent: data, + rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data) + }); + + init($scope.content); + + syncTreeNode($scope.content, data.path); + + $scope.page.buttonGroupState = "success"; + + }); + } + + }; + + $scope.sendToPublish = function () { + return performSave({ saveMethod: contentResource.sendToPublish, statusMessage: "Sending...", action: "sendToPublish" }); + }; + + $scope.saveAndPublish = function () { + return performSave({ saveMethod: contentResource.publish, statusMessage: "Publishing...", action: "publish" }); + }; + + $scope.save = function () { + return performSave({ saveMethod: $scope.saveMethod(), statusMessage: "Saving...", action: "save" }); + }; + + $scope.preview = function (content) { + + + if (!$scope.busy) { + + // Chromes popup blocker will kick in if a window is opened + // outwith the initial scoped request. This trick will fix that. + // + var previewWindow = $window.open('preview/?id=' + content.id, 'umbpreview'); + $scope.save().then(function (data) { + // Build the correct path so both /#/ and #/ work. + var redirect = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/?id=' + data.id; + previewWindow.location.href = redirect; + }); + + + } + + }; + + } + + function createDirective() { + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/content/edit.html', + controller: 'Umbraco.Editors.Content.EditorDirectiveController', + scope: { + contentId: "=", + isNew: "=?", + treeAlias: "@", + page: "=?", + saveMethod: "&", + getMethod: "&", + getScaffoldMethod: "&?" + } + }; + + return directive; + + } + + angular.module('umbraco.directives').controller('Umbraco.Editors.Content.EditorDirectiveController', ContentEditController); + angular.module('umbraco.directives').directive('contentEditor', createDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js index 4d9222fa45..255897e3f8 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorheader.directive.js @@ -225,8 +225,8 @@ Use this directive to construct a header inside the main editor window. scope.icon = model.icon; } - // set form to dirty - ctrl.$setDirty(); + // set the icon form to dirty + scope.iconForm.$setDirty(); } scope.dialogModel.show = false; @@ -237,7 +237,6 @@ Use this directive to construct a header inside the main editor window. } var directive = { - require: '^form', transclude: true, restrict: 'E', replace: true, @@ -255,7 +254,8 @@ Use this directive to construct a header inside the main editor window. description: "=", hideDescription: "@", descriptionLocked: "@", - navigation: "=" + navigation: "=", + key: "=" }, link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js index 6cf5f68461..de497ccffe 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/events/events.directive.js @@ -155,7 +155,6 @@ angular.module('umbraco.directives') var els = ["INPUT","A","BUTTON"]; if(els.indexOf(el) >= 0){return;} - // ignore children of links and buttons // ignore clicks on new overlay var parents = $(event.target).parents("a,button,.umb-overlay"); if(parents.length > 0){ diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/grid/grid.rte.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/grid/grid.rte.directive.js index 60bb4957ae..e3a50b482c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/grid/grid.rte.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/grid/grid.rte.directive.js @@ -358,7 +358,7 @@ angular.module("umbraco.directives") var unsubscribe = scope.$on("formSubmitting", function () { //TODO: Here we should parse out the macro rendered content so we can save on a lot of bytes in data xfer // we do parse it out on the server side but would be nice to do that on the client side before as well. - scope.value = tinyMceEditor.getContent(); + scope.value = tinyMceEditor ? tinyMceEditor.getContent() : null; }); //when the element is disposed we need to unsubscribe! diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js index 70baa6718b..94ab5537dc 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js @@ -4,43 +4,45 @@ * @restrict E **/ angular.module("umbraco.directives.html") - .directive('umbControlGroup', function (localizationService) { - return { - scope: { - label: "@label", - description: "@", - hideLabel: "@", - alias: "@" - }, - require: '?^form', - transclude: true, - restrict: 'E', - replace: true, - templateUrl: 'views/components/html/umb-control-group.html', - link: function (scope, element, attr, formCtrl) { + .directive('umbControlGroup', function (localizationService) { + return { + scope: { + label: "@label", + description: "@", + hideLabel: "@", + alias: "@", + labelFor: "@" + }, + require: '?^form', + transclude: true, + restrict: 'E', + replace: true, + templateUrl: 'views/components/html/umb-control-group.html', + link: function (scope, element, attr, formCtrl) { - scope.formValid = function() { - if (formCtrl) { - return formCtrl.$valid; - } - //there is no form. - return true; - }; - - if (scope.label && scope.label[0] === "@") { - scope.labelstring = localizationService.localize(scope.label.substring(1)); - } - else { - scope.labelstring = scope.label; - } - - if (scope.description && scope.description[0] === "@") { - scope.descriptionstring = localizationService.localize(scope.description.substring(1)); - } - else { - scope.descriptionstring = scope.description; - } - - } + scope.formValid = function () { + if (formCtrl && scope.labelFor) { + //if a label-for has been set, use that for the validation + return formCtrl[scope.labelFor].$valid; + } + //there is no form. + return true; }; - }); + + if (scope.label && scope.label[0] === "@") { + scope.labelstring = localizationService.localize(scope.label.substring(1)); + } + else { + scope.labelstring = scope.label; + } + + if (scope.description && scope.description[0] === "@") { + scope.descriptionstring = localizationService.localize(scope.description.substring(1)); + } + else { + scope.descriptionstring = scope.description; + } + + } + }; + }); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js index c95e1a7b7f..1a652a787c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js @@ -26,7 +26,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat enablelistviewexpand: '@' }, - compile: function(element, attrs) { + compile: function (element, attrs) { //config //var showheader = (attrs.showheader !== 'false'); var hideoptions = (attrs.hideoptions === 'true') ? "hide-options" : ""; @@ -44,7 +44,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat element.replaceWith(template); - return function(scope, elem, attr, controller) { + return function (scope, elem, attr, controller) { //flag to track the last loaded section when the tree 'un-loads'. We use this to determine if we should // re-load the tree again. For example, if we hover over 'content' the content tree is shown. Then we hover @@ -84,16 +84,16 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat function setupExternalEvents() { if (scope.eventhandler) { - scope.eventhandler.clearCache = function(section) { + scope.eventhandler.clearCache = function (section) { treeService.clearCache({ section: section }); }; - scope.eventhandler.load = function(section) { + scope.eventhandler.load = function (section) { scope.section = section; loadTree(); }; - scope.eventhandler.reloadNode = function(node) { + scope.eventhandler.reloadNode = function (node) { if (!node) { node = scope.currentNode; @@ -108,7 +108,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat Used to do the tree syncing. If the args.tree is not specified we are assuming it has been specified previously using the _setActiveTreeType */ - scope.eventhandler.syncTree = function(args) { + scope.eventhandler.syncTree = function (args) { if (!args) { throw "args cannot be null"; } @@ -146,9 +146,16 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat // and previous so that the tree syncs properly. The tree syncs from the top down and if there are parts // of the tree's path in there that don't actually exist in the dom/model then syncing will not work. - userService.getCurrentUser().then(function(userData) { + userService.getCurrentUser().then(function (userData) { + + var startNodes = []; + for (var i = 0; i < userData.startContentIds; i++) { + startNodes.push(userData.startContentIds[i]); + } + for (var j = 0; j < userData.startMediaIds; j++) { + startNodes.push(userData.startMediaIds[j]); + } - var startNodes = [userData.startContentId, userData.startMediaId]; _.each(startNodes, function (i) { var found = _.find(args.path, function (p) { return String(p) === String(i); @@ -175,7 +182,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat node's children - this is synonymous with the legacy refreshTree method - again should not be used and should only be used for the legacy code to work. */ - scope.eventhandler._setActiveTreeType = function(treeAlias, loadChildren) { + scope.eventhandler._setActiveTreeType = function (treeAlias, loadChildren) { loadActiveTree(treeAlias, loadChildren); }; } @@ -210,7 +217,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat function doLoad(tree) { var childrenAndSelf = [tree].concat(tree.children); scope.activeTree = _.find(childrenAndSelf, function (node) { - if(node && node.metaData && node.metaData.treeAlias) { + if (node && node.metaData && node.metaData.treeAlias) { return node.metaData.treeAlias.toUpperCase() === treeAlias.toUpperCase(); } return false; @@ -223,7 +230,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat //This is only used for the legacy tree method refreshTree! if (loadChildren) { scope.activeTree.expanded = true; - scope.loadChildren(scope.activeTree, false).then(function() { + scope.loadChildren(scope.activeTree, false).then(function () { emitEvent("activeTreeLoaded", { tree: scope.activeTree }); }); } @@ -236,7 +243,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat doLoad(scope.tree.root); } else { - scope.eventhandler.one("treeLoaded", function(e, args) { + scope.eventhandler.one("treeLoaded", function (e, args) { doLoad(args.tree.root); }); } @@ -261,7 +268,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat } treeService.getTree(args) - .then(function(data) { + .then(function (data) { //set the data once we have it scope.tree = data; @@ -274,7 +281,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat emitEvent("treeLoaded", { tree: scope.tree }); emitEvent("treeNodeExpanded", { tree: scope.tree, node: scope.tree.root, children: scope.tree.root.children }); - }, function(reason) { + }, function (reason) { scope.loading = false; notificationsService.error("Tree Error", reason); }); @@ -306,8 +313,8 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat scope.selectEnabledNodeClass = function (node) { return node ? node.selected ? - 'icon umb-tree-icon sprTree icon-check green temporary' : - '' : + 'icon umb-tree-icon sprTree icon-check green temporary' : + '' : ''; }; @@ -315,7 +322,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat * This changes dynamically based on if we are changing sections or just loading normal tree data. * When changing sections we don't want all of the tree-ndoes to do their 'leave' animations. */ - scope.animation = function() { + scope.animation = function () { if (deleteAnimations && scope.tree && scope.tree.root && scope.tree.root.expanded) { return { leave: 'tree-node-delete-leave' }; } @@ -325,7 +332,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat }; /* helper to force reloading children of a tree node */ - scope.loadChildren = function(node, forceReload) { + scope.loadChildren = function (node, forceReload) { var deferred = $q.defer(); //emit treeNodeExpanding event, if a callback object is set on the tree @@ -339,7 +346,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat if (forceReload || (node.hasChildren && node.children.length === 0)) { //get the children from the tree service treeService.loadNodeChildren({ node: node, section: scope.section }) - .then(function(data) { + .then(function (data) { //emit expanded event emitEvent("treeNodeExpanded", { tree: scope.tree, node: node, children: data }); @@ -365,7 +372,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat The tree doesnt know about this, so it raises an event to tell the parent controller about it. */ - scope.options = function(n, ev) { + scope.options = function (n, ev) { emitEvent("treeOptionsClick", { element: elem, node: n, event: ev }); }; @@ -384,12 +391,12 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat emitEvent("treeNodeSelect", { element: elem, node: n, event: ev }); }; - scope.altSelect = function(n, ev) { + scope.altSelect = function (n, ev) { emitEvent("treeNodeAltSelect", { element: elem, tree: scope.tree, node: n, event: ev }); }; //watch for section changes - scope.$watch("section", function(newVal, oldVal) { + scope.$watch("section", function (newVal, oldVal) { if (!scope.tree) { loadTree(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbavatar.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbavatar.directive.js index ba34a752ed..7fad3e8a74 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbavatar.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbavatar.directive.js @@ -52,15 +52,50 @@ Use this directive to render an avatar. function AvatarDirective() { + function link(scope, element, attrs, ctrl) { + + var eventBindings = []; + scope.initials = ""; + + function onInit() { + if (!scope.unknownChar) { + scope.unknownChar = "?"; + } + scope.initials = getNameInitials(scope.name); + } + + function getNameInitials(name) { + if(name) { + var initials = name.match(/\b\w/g) || []; + initials = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase(); + return initials; + } + return null; + } + + eventBindings.push(scope.$watch('name', function (newValue, oldValue) { + if (newValue === oldValue) { return; } + if (oldValue === undefined || newValue === undefined) { return; } + scope.initials = getNameInitials(newValue); + })); + + onInit(); + + } + var directive = { restrict: 'E', replace: true, templateUrl: 'views/components/umb-avatar.html', scope: { size: "@", + name: "@", + color: "@", imgSrc: "@", - imgSrcset: "@" - } + imgSrcset: "@", + unknownChar: "@" + }, + link: link }; return directive; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbbadge.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbbadge.directive.js new file mode 100644 index 0000000000..ee2c53eba0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbbadge.directive.js @@ -0,0 +1,23 @@ +(function() { + 'use strict'; + + function BadgeDirective() { + + var directive = { + restrict: 'E', + replace: true, + transclude: true, + templateUrl: 'views/components/umb-badge.html', + scope: { + size: "@?", + color: "@?" + } + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('umbBadge', BadgeDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbcheckmark.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbcheckmark.directive.js new file mode 100644 index 0000000000..b0899f0f8b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbcheckmark.directive.js @@ -0,0 +1,23 @@ +(function() { + 'use strict'; + + function CheckmarkDirective() { + + var directive = { + restrict: 'E', + replace: true, + transclude: true, + templateUrl: 'views/components/umb-checkmark.html', + scope: { + size: "@?", + checked: "=" + } + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('umbCheckmark', CheckmarkDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbclipboard.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbclipboard.directive.js new file mode 100644 index 0000000000..bb49a60eca --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbclipboard.directive.js @@ -0,0 +1,166 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbClipboard +@restrict E +@scope + +@description +Added in Umbraco v. 7.7: Use this directive to copy content to the clipboard + +

Markup example

+
+    
+ + +
Copy me!
+ + + + + + + + + + + + + + +
+
+ +

Controller example

+
+    (function () {
+        "use strict";
+
+        function Controller() {
+
+            var vm = this;
+
+            vm.copyText = "Copy text without element";
+            vm.cutText = "Text to cut";
+
+            vm.copySuccess = copySuccess;
+            vm.copyError = copyError;
+
+            function copySuccess() {
+                vm.clipboardButtonState = "success";
+            }
+            
+            function copyError() {
+                vm.clipboardButtonState = "error";
+            }
+
+        }
+
+        angular.module("umbraco").controller("My.ClipBoardController", Controller);
+
+    })();
+
+ +@param {callback} umbClipboardSuccess (expression): Callback function when the content is copied. +@param {callback} umbClipboardError (expression): Callback function if the copy fails. +@param {string} umbClipboardTarget (attribute): The target element to copy. +@param {string} umbClipboardAction (attribute): Specify if you want to copy or cut content ("copy", "cut"). Cut only works on input and textarea elements. +@param {string} umbClipboardText (attribute): Use this attribute if you don't have an element to copy from. + +**/ + +(function () { + 'use strict'; + + function umbClipboardDirective($timeout, assetsService) { + + function link(scope, element, attrs, ctrl) { + + var clipboard; + var target = element[0]; + + assetsService.loadJs("lib/clipboard/clipboard.min.js") + .then(function () { + + if(scope.umbClipboardTarget) { + target.setAttribute("data-clipboard-target", scope.umbClipboardTarget); + } + + if(scope.umbClipboardAction) { + target.setAttribute("data-clipboard-action", scope.umbClipboardAction); + } + + if(scope.umbClipboardText) { + target.setAttribute("data-clipboard-text", scope.umbClipboardText); + } + + clipboard = new Clipboard(target); + + clipboard.on('success', function (e) { + e.clearSelection(); + if (scope.umbClipboardSuccess) { + scope.$apply(function () { + scope.umbClipboardSuccess({ e: e }); + }); + } + }); + + clipboard.on('error', function (e) { + if (scope.umbClipboardError) { + scope.$apply(function () { + scope.umbClipboardError({ e: e }); + }); + } + }); + + }); + + // clean up + scope.$on('$destroy', function(){ + clipboard.destroy(); + }); + + } + + //////////// + + var directive = { + restrict: 'A', + scope: { + umbClipboardSuccess: '&?', + umbClipboardError: '&?', + umbClipboardTarget: "@?", + umbClipboardAction: "@?", + umbClipboardText: "=?" + }, + link: link + }; + + return directive; + } + + angular.module('umbraco.directives').directive('umbClipboard', umbClipboardDirective); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdropdown.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdropdown.directive.js new file mode 100644 index 0000000000..d6006114a6 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdropdown.directive.js @@ -0,0 +1,133 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbDropdown +@restrict E +@scope + +@description +Added in versions 7.7.0: Use this component to render a dropdown menu. + +

Markup example

+
+    
+
+ +

Controller example

+
+    (function () {
+        "use strict";
+
+        function Controller() {
+
+            var vm = this;
+
+            vm.dropdownOpen = false;
+            vm.items = [
+                { "name": "Item 1" },
+                { "name": "Item 2" },
+                { "name": "Item 3" }
+            ];
+
+            vm.toggle = toggle;
+            vm.close = close;
+            vm.select = select;
+
+            function toggle() {
+                vm.dropdownOpen = true;
+            }
+
+            function close() {
+                vm.dropdownOpen = false;
+            }
+
+            function select(item) {
+                // Do your magic here
+            }
+
+        }
+
+        angular.module("umbraco").controller("MyDropdown.Controller", Controller);
+    })();
+
+ +

Use in combination with

+
    +
  • {@link umbraco.directives.directive:umbDropdownItem umbDropdownItem}
  • +
  • {@link umbraco.directives.directive:umbKeyboardList umbKeyboardList}
  • +
+ +@param {callback} onClose Callback when the dropdown menu closes. When you click outside or press esc. + +**/ + +(function() { + 'use strict'; + + function umbDropdown($document) { + + function link(scope, element, attr, ctrl) { + + scope.close = function() { + if (scope.onClose) { + scope.onClose(); + } + }; + + // Handle keydown events + function keydown(event) { + // press escape + if(event.keyCode === 27) { + scope.onClose(); + } + } + + // Stop to listen typing. + function stopListening() { + $document.off('keydown', keydown); + } + + // Start listening to key typing. + $document.on('keydown', keydown); + + // Stop listening when scope is destroyed. + scope.$on('$destroy', stopListening); + + } + + var directive = { + restrict: 'E', + replace: true, + transclude: true, + templateUrl: 'views/components/umb-dropdown.html', + scope: { + onClose: "&" + }, + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('umbDropdown', umbDropdown); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdropdownitem.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdropdownitem.directive.js new file mode 100644 index 0000000000..59b2b827eb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbdropdownitem.directive.js @@ -0,0 +1,29 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbDropdownItem +@restrict E + +@description +Added in versions 7.7.0: Use this directive to construct a dropdown item. See documentation for {@link umbraco.directives.directive:umbDropdown umbDropdown}. + +**/ + +(function() { + 'use strict'; + + function umbDropdownItem() { + + var directive = { + restrict: 'E', + replace: true, + transclude: true, + templateUrl: 'views/components/umb-dropdown-item.html', + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('umbDropdownItem', umbDropdownItem); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js index 4960a11f19..c0bd7a4eff 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js @@ -134,25 +134,42 @@ Use this directive to generate a thumbnail grid of media items. } function setItemData(item) { - item.isFolder = !mediaHelper.hasFilePropertyType(item); + + // check if item is a folder + if(item.image) { + // if is has an image path, it is not a folder + item.isFolder = false; + } else { + item.isFolder = !mediaHelper.hasFilePropertyType(item); + } + if (!item.isFolder) { - item.thumbnail = mediaHelper.resolveFile(item, true); - item.image = mediaHelper.resolveFile(item, false); + + // handle entity + if(item.image) { + item.thumbnail = mediaHelper.resolveFileFromEntity(item, true); + item.extension = mediaHelper.getFileExtension(item.image); + // handle full media object + } else { + item.thumbnail = mediaHelper.resolveFile(item, true); + item.image = mediaHelper.resolveFile(item, false); + + var fileProp = _.find(item.properties, function (v) { + return (v.alias === "umbracoFile"); + }); - var fileProp = _.find(item.properties, function (v) { - return (v.alias === "umbracoFile"); - }); + if (fileProp && fileProp.value) { + item.file = fileProp.value; + } - if (fileProp && fileProp.value) { - item.file = fileProp.value; - } + var extensionProp = _.find(item.properties, function (v) { + return (v.alias === "umbracoExtension"); + }); - var extensionProp = _.find(item.properties, function (v) { - return (v.alias === "umbracoExtension"); - }); + if (extensionProp && extensionProp.value) { + item.extension = extensionProp.value; + } - if (extensionProp && extensionProp.value) { - item.extension = extensionProp.value; } } } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnestedcontent.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnestedcontent.directive.js new file mode 100644 index 0000000000..366294630b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnestedcontent.directive.js @@ -0,0 +1,97 @@ +angular.module("umbraco.directives").directive('umbNestedContentEditor', [ + + function () { + + var link = function ($scope) { + + // Clone the model because some property editors + // do weird things like updating and config values + // so we want to ensure we start from a fresh every + // time, we'll just sync the value back when we need to + $scope.model = angular.copy($scope.ngModel); + $scope.nodeContext = $scope.model; + + // Find the selected tab + var selectedTab = $scope.model.tabs[0]; + + if ($scope.tabAlias) { + angular.forEach($scope.model.tabs, function (tab) { + if (tab.alias.toLowerCase() === $scope.tabAlias.toLowerCase()) { + selectedTab = tab; + return; + } + }); + } + + $scope.tab = selectedTab; + + // Listen for sync request + var unsubscribe = $scope.$on("ncSyncVal", function (ev, args) { + if (args.key === $scope.model.key) { + + // Tell inner controls we are submitting + $scope.$broadcast("formSubmitting", { scope: $scope }); + + // Sync the values back + angular.forEach($scope.ngModel.tabs, function (tab) { + if (tab.alias.toLowerCase() === selectedTab.alias.toLowerCase()) { + + var localPropsMap = selectedTab.properties.reduce(function (map, obj) { + map[obj.alias] = obj; + return map; + }, {}); + + angular.forEach(tab.properties, function (prop) { + if (localPropsMap.hasOwnProperty(prop.alias)) { + prop.value = localPropsMap[prop.alias].value; + } + }); + + } + }); + } + }); + + $scope.$on('$destroy', function () { + unsubscribe(); + }); + }; + + return { + restrict: "E", + replace: true, + templateUrl: Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + "/views/propertyeditors/nestedcontent/nestedcontent.editor.html", + scope: { + ngModel: '=', + tabAlias: '=' + }, + link: link + }; + + } +]); + +//angular.module("umbraco.directives").directive('nestedContentSubmitWatcher', function () { +// var link = function (scope) { +// // call the load callback on scope to obtain the ID of this submit watcher +// var id = scope.loadCallback(); +// scope.$on("formSubmitting", function (ev, args) { +// // on the "formSubmitting" event, call the submit callback on scope to notify the nestedContent controller to do it's magic +// if (id === scope.activeSubmitWatcher) { +// scope.submitCallback(); +// } +// }); +// } + +// return { +// restrict: "E", +// replace: true, +// template: "", +// scope: { +// loadCallback: '=', +// submitCallback: '=', +// activeSubmitWatcher: '=' +// }, +// link: link +// } +//}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnodepreview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnodepreview.directive.js index 77f6f06a30..d98246ac42 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnodepreview.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbnodepreview.directive.js @@ -82,8 +82,10 @@ @param {boolean} sortable (binding): Will add a move cursor on the node preview. Can used in combination with ui-sortable. @param {boolean} allowRemove (binding): Show/Hide the remove button. @param {boolean} allowOpen (binding): Show/Hide the open button. +@param {boolean} allowEdit (binding): Show/Hide the edit button (Added in version 7.7.0). @param {function} onRemove (expression): Callback function when the remove button is clicked. @param {function} onOpen (expression): Callback function when the open button is clicked. +@param {function} onEdit (expression): Callback function when the edit button is clicked (Added in version 7.7.0). **/ (function () { @@ -92,7 +94,9 @@ function NodePreviewDirective() { function link(scope, el, attr, ctrl) { - + if (!scope.editLabelKey) { + scope.editLabelKey = "general_edit"; + } } var directive = { @@ -103,12 +107,15 @@ icon: "=?", name: "=", description: "=?", + permissions: "=?", published: "=?", sortable: "=?", allowOpen: "=?", allowRemove: "=?", + allowEdit: "=?", onOpen: "&?", - onRemove: "&?" + onRemove: "&?", + onEdit: "&?" }, link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpagination.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpagination.directive.js index 610f8546a3..84b3adb471 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpagination.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpagination.directive.js @@ -86,7 +86,7 @@ Use this directive to generate a pagination. (function() { 'use strict'; - function PaginationDirective() { + function PaginationDirective(localizationService) { function link(scope, el, attr, ctrl) { @@ -123,12 +123,12 @@ Use this directive to generate a pagination. //now, if the start is greater than 0 then '1' will not be displayed, so do the elipses thing if (start > 0) { - scope.pagination.unshift({ name: "First", val: 1, isActive: false }, {val: "...",isActive: false}); + scope.pagination.unshift({ name: localizationService.localize("general_first"), val: 1, isActive: false }, {val: "...",isActive: false}); } //same for the end if (start < maxIndex) { - scope.pagination.push({ val: "...", isActive: false }, { name: "Last", val: scope.totalPages, isActive: false }); + scope.pagination.push({ val: "...", isActive: false }, { name: localizationService.localize("general_last"), val: scope.totalPages, isActive: false }); } } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbprogressbar.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbprogressbar.directive.js index 77bab9f023..59f51fca3f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbprogressbar.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbprogressbar.directive.js @@ -16,6 +16,8 @@ Use this directive to generate a progress bar. @param {number} percentage (attribute): The progress in percentage. +@param {string} size (attribute): The size (s, m). + **/ (function() { @@ -28,7 +30,8 @@ Use this directive to generate a progress bar. replace: true, templateUrl: 'views/components/umb-progress-bar.html', scope: { - percentage: "@" + percentage: "@", + size: "@?" } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfiledropzone.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfiledropzone.directive.js index 6cafa05bc8..6619af3cc0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfiledropzone.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/upload/umbfiledropzone.directive.js @@ -142,12 +142,14 @@ angular.module("umbraco.directives") file: file }) .progress(function(evt) { - // calculate progress in percentage - var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10); - // set percentage property on file - file.uploadProgress = progressPercentage; - // set uploading status on file - file.uploadStatus = "uploading"; + if (file.uploadStat !== "done" && file.uploadStat !== "error") { + // calculate progress in percentage + var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10); + // set percentage property on file + file.uploadProgress = progressPercentage; + // set uploading status on file + file.uploadStatus = "uploading"; + } }) .success(function(data, status, headers, config) { if (data.notifications && data.notifications.length > 0) { @@ -160,6 +162,7 @@ angular.module("umbraco.directives") } else { // set done status on file file.uploadStatus = "done"; + file.uploadProgress = 100; // set date/time for when done - used for sorting file.doneDate = new Date(); // Put the file in the done pool diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js new file mode 100644 index 0000000000..f2834e4a36 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/changepassword.directive.js @@ -0,0 +1,171 @@ +(function () { + 'use strict'; + + function ChangePasswordController($scope) { + + function resetModel(isNew) { + //the model config will contain an object, if it does not we'll create defaults + //NOTE: We will not support doing the password regex on the client side because the regex on the server side + //based on the membership provider cannot always be ported to js from .net directly. + /* + { + hasPassword: true/false, + requiresQuestionAnswer: true/false, + enableReset: true/false, + enablePasswordRetrieval: true/false, + minPasswordLength: 10 + } + */ + + //set defaults if they are not available + if ($scope.config.disableToggle === undefined) { + $scope.config.disableToggle = false; + } + if ($scope.config.hasPassword === undefined) { + $scope.config.hasPassword = false; + } + if ($scope.config.enablePasswordRetrieval === undefined) { + $scope.config.enablePasswordRetrieval = true; + } + if ($scope.config.requiresQuestionAnswer === undefined) { + $scope.config.requiresQuestionAnswer = false; + } + if ($scope.config.enableReset === undefined) { + $scope.config.enableReset = true; + } + if ($scope.config.minPasswordLength === undefined) { + $scope.config.minPasswordLength = 0; + } + + //set the model defaults + if (!angular.isObject($scope.passwordValues)) { + //if it's not an object then just create a new one + $scope.passwordValues = { + newPassword: null, + oldPassword: null, + reset: null, + answer: null + }; + } + else { + //just reset the values + + if (!isNew) { + //if it is new, then leave the generated pass displayed + $scope.passwordValues.newPassword = null; + $scope.passwordValues.oldPassword = null; + } + $scope.passwordValues.reset = null; + $scope.passwordValues.answer = null; + } + + //the value to compare to match passwords + if (!isNew) { + $scope.confirm = ""; + } + else if ($scope.passwordValues.newPassword && $scope.passwordValues.newPassword.length > 0) { + //if it is new and a new password has been set, then set the confirm password too + $scope.confirm = $scope.passwordValues.newPassword; + } + + } + + resetModel($scope.isNew); + + //if there is no password saved for this entity , it must be new so we do not allow toggling of the change password, it is always there + //with validators turned on. + $scope.changing = $scope.config.disableToggle === true || !$scope.config.hasPassword; + + //we're not currently changing so set the model to null + if (!$scope.changing) { + $scope.passwordValues = null; + } + + $scope.doChange = function () { + resetModel(); + $scope.changing = true; + //if there was a previously generated password displaying, clear it + $scope.passwordValues.generatedPassword = null; + }; + + $scope.cancelChange = function () { + $scope.changing = false; + //set model to null + $scope.passwordValues = null; + }; + + var unsubscribe = []; + + //listen for the saved event, when that occurs we'll + //change to changing = false; + unsubscribe.push($scope.$on("formSubmitted", function () { + if ($scope.config.disableToggle === false) { + $scope.changing = false; + } + })); + unsubscribe.push($scope.$on("formSubmitting", function () { + //if there was a previously generated password displaying, clear it + if ($scope.changing && $scope.passwordValues) { + $scope.passwordValues.generatedPassword = null; + } + else if (!$scope.changing) { + //we are not changing, so the model needs to be null + $scope.passwordValues = null; + } + })); + + //when the scope is destroyed we need to unsubscribe + $scope.$on('$destroy', function () { + for (var u in unsubscribe) { + unsubscribe[u](); + } + }); + + $scope.showReset = function () { + return $scope.config.enableReset; + }; + + $scope.showOldPass = function () { + return $scope.config.hasPassword && + !$scope.config.allowManuallyChangingPassword && + !$scope.config.enablePasswordRetrieval && !$scope.passwordValues.reset; + }; + + $scope.showNewPass = function () { + return !$scope.passwordValues.reset; + }; + + $scope.showConfirmPass = function () { + return !$scope.passwordValues.reset; + }; + + //TODO: I don't think we need this or the cancel button, this can be up to the editor rendering this directive + $scope.showCancelBtn = function () { + return $scope.config.disableToggle !== true && $scope.config.hasPassword; + }; + + } + + function ChangePasswordDirective() { + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/users/change-password.html', + controller: 'Umbraco.Editors.Users.ChangePasswordDirectiveController', + scope: { + isNew: "=?", + passwordValues: "=", + config: "=" + } + }; + + return directive; + + } + + angular.module('umbraco.directives').controller('Umbraco.Editors.Users.ChangePasswordDirectiveController', ChangePasswordController); + angular.module('umbraco.directives').directive('changePassword', ChangePasswordDirective); + + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbpermission.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbpermission.directive.js new file mode 100644 index 0000000000..bae87789ca --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbpermission.directive.js @@ -0,0 +1,36 @@ +(function () { + 'use strict'; + + function PermissionDirective() { + + function link(scope, el, attr, ctrl) { + + scope.change = function() { + scope.selected = !scope.selected; + if(scope.onChange) { + scope.onChange({'selected': scope.selected}); + } + }; + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/users/umb-permission.html', + scope: { + name: "=", + description: "=?", + selected: "=", + onChange: "&" + }, + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('umbPermission', PermissionDirective); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbusergrouppreview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbusergrouppreview.directive.js new file mode 100644 index 0000000000..7a777b76c5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbusergrouppreview.directive.js @@ -0,0 +1,36 @@ +(function () { + 'use strict'; + + function UserGroupPreviewDirective() { + + function link(scope, el, attr, ctrl) { + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/users/umb-user-group-preview.html', + scope: { + icon: "=?", + name: "=", + description: "=?", + sections: "=?", + contentStartNode: "=?", + mediaStartNode: "=?", + permissions: "=?", + allowRemove: "=?", + allowEdit: "=?", + onRemove: "&?", + onEdit: "&?" + }, + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('umbUserGroupPreview', UserGroupPreviewDirective); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbuserpreview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbuserpreview.directive.js new file mode 100644 index 0000000000..634decfa3d --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/users/umbuserpreview.directive.js @@ -0,0 +1,29 @@ +(function () { + 'use strict'; + + function UserPreviewDirective() { + + function link(scope, el, attr, ctrl) { + + } + + var directive = { + restrict: 'E', + replace: true, + templateUrl: 'views/components/users/umb-user-preview.html', + scope: { + avatars: "=?", + name: "=", + allowRemove: "=?", + onRemove: "&?" + }, + link: link + }; + + return directive; + + } + + angular.module('umbraco.directives').directive('umbUserPreview', UserPreviewDirective); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/util/umbkeyboardlist.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/util/umbkeyboardlist.directive.js new file mode 100644 index 0000000000..187228f0c4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/util/umbkeyboardlist.directive.js @@ -0,0 +1,115 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbKeyboardList +@restrict E + +@description +Added in versions 7.7.0: Use this directive to add arrow up and down keyboard shortcuts to a list. Use this together with the {@link umbraco.directives.directive:umbDropdown umbDropdown} component to make easy accessible dropdown menus. + +

Markup example

+
+    
+ +
+
+ +

Use in combination with

+
    +
  • {@link umbraco.directives.directive:umbDropdown umbDropdown}
  • +
+ +**/ + +angular.module('umbraco.directives') + .directive('umbKeyboardList', ['$document', '$timeout', function ($document, $timeout) { + + return { + restrict: 'A', + link: function (scope, element, attr) { + + var listItems = []; + var currentIndex = 0; + var focusSet = false; + + $timeout(function(){ + // get list of all links in the list + listItems = element.find("li a"); + }); + + // Handle keydown events + function keydown(event) { + $timeout(function(){ + checkFocus(); + // arrow down + if (event.keyCode === 40) { + arrowDown(); + } + // arrow up + if (event.keyCode === 38) { + arrowUp(); + } + }); + } + + function checkFocus() { + var found = false; + + // check if any element has focus + angular.forEach(listItems, function (item, index) { + if ($(item).is(":focus")) { + // if an element already has focus set the + // currentIndex so we navigate from that element + currentIndex = index; + focusSet = true; + found = true; + } + }); + + // If we don't find an element with focus we reset the currentIndex and the focusSet flag + // we do this because you can have navigated away from the list with tab and we want to reset it if you navigate back + if (!found) { + currentIndex = 0; + focusSet = false; + } + } + + function arrowDown() { + if (currentIndex < listItems.length - 1) { + // only bump the current index if the focus is already + // set else we just want to focus the first element + if (focusSet) { + currentIndex++; + } + listItems[currentIndex].focus(); + focusSet = true; + } + } + + function arrowUp() { + if (currentIndex > 0) { + currentIndex--; + listItems[currentIndex].focus(); + } + } + + // Stop to listen typing. + function stopListening() { + $document.off('keydown', keydown); + } + + // Start listening to key typing. + $document.on('keydown', keydown); + + // Stop listening when scope is destroyed. + scope.$on('$destroy', stopListening); + + } + }; + }]); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js index 1a36dcc24f..195c70ce0f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js @@ -1,11 +1,13 @@ angular.module('umbraco.directives.validation') .directive('valCompare',function () { return { - require: "ngModel", - link: function (scope, elem, attrs, ctrl) { - - //TODO: Pretty sure this should be done using a requires ^form in the directive declaration - var otherInput = elem.inheritedData("$formController")[attrs.valCompare]; + require: ["ngModel", "^form"], + link: function (scope, elem, attrs, ctrls) { + + var ctrl = ctrls[0]; + var formCtrl = ctrls[1]; + + var otherInput = formCtrl[attrs.valCompare]; ctrl.$parsers.push(function(value) { if(value === otherInput.$viewValue) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js index 916b933063..98c4c6768f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js @@ -12,6 +12,11 @@ function link(scope, el, attr, ctrl) { + //if there are no containing form or valFormManager controllers, then we do nothing + if (!ctrl || !angular.isArray(ctrl) || ctrl.length !== 2 || !ctrl[0] || !ctrl[1]) { + return; + } + var valFormManager = ctrl[1]; scope.subView.hasError = false; @@ -36,7 +41,7 @@ } var directive = { - require: ['^form', '^valFormManager'], + require: ['?^form', '?^valFormManager'], restrict: "A", link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/filters/nestedcontent.filter.js b/src/Umbraco.Web.UI.Client/src/common/filters/nestedcontent.filter.js new file mode 100644 index 0000000000..76e4e4a822 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/filters/nestedcontent.filter.js @@ -0,0 +1,47 @@ +// Filter to take a node id and grab it's name instead +// Usage: {{ pickerAlias | ncNodeName }} + +// Cache for node names so we don't make a ton of requests +var ncNodeNameCache = { + id: "", + keys: {} +}; + +angular.module("umbraco.filters").filter("ncNodeName", function (editorState, entityResource) { + + return function (input) { + + // Check we have a value at all + if (input === "" || input.toString() === "0") { + return ""; + } + + var currentNode = editorState.getCurrent(); + + // Ensure a unique cache per editor instance + var key = "ncNodeName_" + currentNode.key; + if (ncNodeNameCache.id !== key) { + ncNodeNameCache.id = key; + ncNodeNameCache.keys = {}; + } + + // See if there is a value in the cache and use that + if (ncNodeNameCache.keys[input]) { + return ncNodeNameCache.keys[input]; + } + + // No value, so go fetch one + // We'll put a temp value in the cache though so we don't + // make a load of requests while we wait for a response + ncNodeNameCache.keys[input] = "Loading..."; + + entityResource.getById(input, "Document") + .then(function (ent) { + ncNodeNameCache.keys[input] = ent.name; + }); + + // Return the current value for now + return ncNodeNameCache.keys[input]; + }; + +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/filters/preserveNewLineInHtml.filter.js b/src/Umbraco.Web.UI.Client/src/common/filters/preserveNewLineInHtml.filter.js new file mode 100644 index 0000000000..8105282020 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/filters/preserveNewLineInHtml.filter.js @@ -0,0 +1,15 @@ +/** +* @ngdoc filter +* @name umbraco.filters.preserveNewLineInHtml +* @description +* Used when rendering a string as HTML (i.e. with ng-bind-html) to convert line-breaks to
tags +**/ +angular.module("umbraco.filters").filter('preserveNewLineInHtml', function () { + return function (text) { + if (!text) { + return ''; + } + return text.replace(/\n/g, '
'); + }; +}); + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/filters/umbwordlimit.filter.js b/src/Umbraco.Web.UI.Client/src/common/filters/umbwordlimit.filter.js new file mode 100644 index 0000000000..c02624409f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/filters/umbwordlimit.filter.js @@ -0,0 +1,38 @@ +/** + * @ngdoc filter + * @name umbraco.filters.filter:umbWordLimit + * @namespace umbWordLimitFilter + * + * @description + * Limits the number of words in a string to the passed in value + */ + +(function () { + 'use strict'; + + function umbWordLimitFilter() { + return function (collection, property) { + + if (!angular.isString(collection)) { + return collection; + } + + if (angular.isUndefined(property)) { + return collection; + } + + var newString = ""; + var array = []; + + array = collection.split(" ", property); + array.length = property; + newString = array.join(" "); + + return newString; + + }; + } + + angular.module('umbraco.filters').filter('umbWordLimit', umbWordLimitFilter); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js index 40f1dbb807..3680b32245 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/auth.resource.js @@ -11,391 +11,423 @@ */ function authResource($q, $http, umbRequestHelper, angularHelper) { - return { + return { - get2FAProviders: function () { - - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "Get2FAProviders")), - 'Could not retrive two factor provider info'); - }, + get2FAProviders: function () { - send2FACode: function (provider) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "Get2FAProviders")), + 'Could not retrive two factor provider info'); + }, - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "PostSend2FACode"), - angular.toJson(provider)), - 'Could not send code'); - }, + send2FACode: function (provider) { - verify2FACode: function (provider, code) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostSend2FACode"), + angular.toJson(provider)), + 'Could not send code'); + }, - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "PostVerify2FACode"), - { - code: code, - provider: provider - }), - 'Could not verify code'); - }, + verify2FACode: function (provider, code) { - /** - * @ngdoc method - * @name umbraco.resources.authResource#performLogin - * @methodOf umbraco.resources.authResource - * - * @description - * Logs the Umbraco backoffice user in if the credentials are good - * - * ##usage - *
-         * authResource.performLogin(login, password)
-         *    .then(function(data) {
-         *        //Do stuff for login...
-         *    });
-         * 
- * @param {string} login Username of backoffice user - * @param {string} password Password of backoffice user - * @returns {Promise} resourcePromise object - * - */ - performLogin: function (username, password) { - - if (!username || !password) { - return angularHelper.rejectedPromise({ - errorMsg: 'Username or password cannot be empty' - }); + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostVerify2FACode"), + { + code: code, + provider: provider + }), + 'Could not verify code'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.authResource#performLogin + * @methodOf umbraco.resources.authResource + * + * @description + * Logs the Umbraco backoffice user in if the credentials are good + * + * ##usage + *
+     * authResource.performLogin(login, password)
+     *    .then(function(data) {
+     *        //Do stuff for login...
+     *    });
+     * 
+ * @param {string} login Username of backoffice user + * @param {string} password Password of backoffice user + * @returns {Promise} resourcePromise object + * + */ + performLogin: function (username, password) { + + if (!username || !password) { + return angularHelper.rejectedPromise({ + errorMsg: 'Username or password cannot be empty' + }); + } + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostLogin"), { + username: username, + password: password + }), + 'Login failed for user ' + username); + }, + + /** + * There are not parameters for this since when the user has clicked on their invite email they will be partially + * logged in (but they will not be approved) so we need to use this method to verify the non approved logged in user's details. + * Using the getCurrentUser will not work since that only works for approved users + * @returns {} + */ + getCurrentInvitedUser: function () { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "GetCurrentInvitedUser")), + 'Failed to verify invite'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.authResource#performRequestPasswordReset + * @methodOf umbraco.resources.authResource + * + * @description + * Checks to see if the provided email address is a valid user account and sends a link + * to allow them to reset their password + * + * ##usage + *
+     * authResource.performRequestPasswordReset(email)
+     *    .then(function(data) {
+     *        //Do stuff for password reset request...
+     *    });
+     * 
+ * @param {string} email Email address of backoffice user + * @returns {Promise} resourcePromise object + * + */ + performRequestPasswordReset: function (email) { + + if (!email) { + return angularHelper.rejectedPromise({ + errorMsg: 'Email address cannot be empty' + }); + } + + //TODO: This validation shouldn't really be done here, the validation on the login dialog + // is pretty hacky which is why this is here, ideally validation on the login dialog would + // be done properly. + var emailRegex = /\S+@\S+\.\S+/; + if (!emailRegex.test(email)) { + return angularHelper.rejectedPromise({ + errorMsg: 'Email address is not valid' + }); + } + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostRequestPasswordReset"), { + email: email + }), + 'Request password reset failed for email ' + email); + }, + + /** + * @ngdoc method + * @name umbraco.resources.authResource#performValidatePasswordResetCode + * @methodOf umbraco.resources.authResource + * + * @description + * Checks to see if the provided password reset code is valid + * + * ##usage + *
+     * authResource.performValidatePasswordResetCode(resetCode)
+     *    .then(function(data) {
+     *        //Allow reset of password
+     *    });
+     * 
+ * @param {integer} userId User Id + * @param {string} resetCode Password reset code + * @returns {Promise} resourcePromise object + * + */ + performValidatePasswordResetCode: function (userId, resetCode) { + + if (!userId) { + return angularHelper.rejectedPromise({ + errorMsg: 'User Id cannot be empty' + }); + } + + if (!resetCode) { + return angularHelper.rejectedPromise({ + errorMsg: 'Reset code cannot be empty' + }); + } + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostValidatePasswordResetCode"), + { + userId: userId, + resetCode: resetCode + }), + 'Password reset code validation failed for userId ' + userId + ', code' + resetCode); + }, + + /** + * @ngdoc method + * @name umbraco.resources.currentUserResource#getMembershipProviderConfig + * @methodOf umbraco.resources.currentUserResource + * + * @description + * Gets the configuration of the user membership provider which is used to configure the change password form + */ + getMembershipProviderConfig: function () { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "GetMembershipProviderConfig")), + 'Failed to retrieve membership provider config'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.authResource#performSetPassword + * @methodOf umbraco.resources.authResource + * + * @description + * Checks to see if the provided password reset code is valid and sets the user's password + * + * ##usage + *
+     * authResource.performSetPassword(userId, password, confirmPassword, resetCode)
+     *    .then(function(data) {
+     *        //Password set
+     *    });
+     * 
+ * @param {integer} userId User Id + * @param {string} password New password + * @param {string} confirmPassword Confirmation of new password + * @param {string} resetCode Password reset code + * @returns {Promise} resourcePromise object + * + */ + performSetPassword: function (userId, password, confirmPassword, resetCode) { + + if (userId === undefined || userId === null) { + return angularHelper.rejectedPromise({ + errorMsg: 'User Id cannot be empty' + }); + } + + if (!password) { + return angularHelper.rejectedPromise({ + errorMsg: 'Password cannot be empty' + }); + } + + if (password !== confirmPassword) { + return angularHelper.rejectedPromise({ + errorMsg: 'Password and confirmation do not match' + }); + } + + if (!resetCode) { + return angularHelper.rejectedPromise({ + errorMsg: 'Reset code cannot be empty' + }); + } + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostSetPassword"), + { + userId: userId, + password: password, + resetCode: resetCode + }), + 'Password reset code validation failed for userId ' + userId); + }, + + unlinkLogin: function (loginProvider, providerKey) { + if (!loginProvider || !providerKey) { + return angularHelper.rejectedPromise({ + errorMsg: 'loginProvider or providerKey cannot be empty' + }); + } + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostUnLinkLogin"), { + loginProvider: loginProvider, + providerKey: providerKey + }), + 'Unlinking login provider failed'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.authResource#performLogout + * @methodOf umbraco.resources.authResource + * + * @description + * Logs out the Umbraco backoffice user + * + * ##usage + *
+     * authResource.performLogout()
+     *    .then(function(data) {
+     *        //Do stuff for logging out...
+     *    });
+     * 
+ * @returns {Promise} resourcePromise object + * + */ + performLogout: function () { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "PostLogout"))); + }, + + /** + * @ngdoc method + * @name umbraco.resources.authResource#getCurrentUser + * @methodOf umbraco.resources.authResource + * + * @description + * Sends a request to the server to get the current user details, will return a 401 if the user is not logged in + * + * ##usage + *
+     * authResource.getCurrentUser()
+     *    .then(function(data) {
+     *        //Do stuff for fetching the current logged in Umbraco backoffice user
+     *    });
+     * 
+ * @returns {Promise} resourcePromise object + * + */ + getCurrentUser: function () { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "GetCurrentUser")), + 'Server call failed for getting current user'); + }, + + getCurrentUserLinkedLogins: function () { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "GetCurrentUserLinkedLogins")), + 'Server call failed for getting current users linked logins'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.authResource#isAuthenticated + * @methodOf umbraco.resources.authResource + * + * @description + * Checks if the user is logged in or not - does not return 401 or 403 + * + * ##usage + *
+     * authResource.isAuthenticated()
+     *    .then(function(data) {
+     *        //Do stuff to check if user is authenticated
+     *    });
+     * 
+ * @returns {Promise} resourcePromise object + * + */ + isAuthenticated: function () { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "IsAuthenticated")), + { + success: function (data, status, headers, config) { + //if the response is false, they are not logged in so return a rejection + if (data === false || data === "false") { + return $q.reject('User is not logged in'); } + return data; + }, + error: function (data, status, headers, config) { + return { + errorMsg: 'Server call failed for checking authentication', + data: data, + status: status + }; + } + }); + }, - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "PostLogin"), { - username: username, - password: password - }), - 'Login failed for user ' + username); - }, + /** + * @ngdoc method + * @name umbraco.resources.authResource#getRemainingTimeoutSeconds + * @methodOf umbraco.resources.authResource + * + * @description + * Gets the user's remaining seconds before their login times out + * + * ##usage + *
+     * authResource.getRemainingTimeoutSeconds()
+     *    .then(function(data) {
+     *        //Number of seconds is returned
+     *    });
+     * 
+ * @returns {Promise} resourcePromise object + * + */ + getRemainingTimeoutSeconds: function () { - /** - * @ngdoc method - * @name umbraco.resources.authResource#performRequestPasswordReset - * @methodOf umbraco.resources.authResource - * - * @description - * Checks to see if the provided email address is a valid user account and sends a link - * to allow them to reset their password - * - * ##usage - *
-         * authResource.performRequestPasswordReset(email)
-         *    .then(function(data) {
-         *        //Do stuff for password reset request...
-         *    });
-         * 
- * @param {string} email Email address of backoffice user - * @returns {Promise} resourcePromise object - * - */ - performRequestPasswordReset: function (email) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "authenticationApiBaseUrl", + "GetRemainingTimeoutSeconds")), + 'Server call failed for checking remaining seconds'); + } - if (!email) { - return angularHelper.rejectedPromise({ - errorMsg: 'Email address cannot be empty' - }); - } - - //TODO: This validation shouldn't really be done here, the validation on the login dialog - // is pretty hacky which is why this is here, ideally validation on the login dialog would - // be done properly. - var emailRegex = /\S+@\S+\.\S+/; - if (!emailRegex.test(email)) { - return angularHelper.rejectedPromise({ - errorMsg: 'Email address is not valid' - }); - } - - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "PostRequestPasswordReset"), { - email: email - }), - 'Request password reset failed for email ' + email); - }, - - /** - * @ngdoc method - * @name umbraco.resources.authResource#performValidatePasswordResetCode - * @methodOf umbraco.resources.authResource - * - * @description - * Checks to see if the provided password reset code is valid - * - * ##usage - *
-         * authResource.performValidatePasswordResetCode(resetCode)
-         *    .then(function(data) {
-         *        //Allow reset of password
-         *    });
-         * 
- * @param {integer} userId User Id - * @param {string} resetCode Password reset code - * @returns {Promise} resourcePromise object - * - */ - performValidatePasswordResetCode: function (userId, resetCode) { - - if (!userId) { - return angularHelper.rejectedPromise({ - errorMsg: 'User Id cannot be empty' - }); - } - - if (!resetCode) { - return angularHelper.rejectedPromise({ - errorMsg: 'Reset code cannot be empty' - }); - } - - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "PostValidatePasswordResetCode"), - { - userId: userId, - resetCode: resetCode - }), - 'Password reset code validation failed for userId ' + userId + ', code' + resetCode); - }, - - /** - * @ngdoc method - * @name umbraco.resources.authResource#performSetPassword - * @methodOf umbraco.resources.authResource - * - * @description - * Checks to see if the provided password reset code is valid and sets the user's password - * - * ##usage - *
-         * authResource.performSetPassword(userId, password, confirmPassword, resetCode)
-         *    .then(function(data) {
-         *        //Password set
-         *    });
-         * 
- * @param {integer} userId User Id - * @param {string} password New password - * @param {string} confirmPassword Confirmation of new password - * @param {string} resetCode Password reset code - * @returns {Promise} resourcePromise object - * - */ - performSetPassword: function (userId, password, confirmPassword, resetCode) { - - if (userId === undefined || userId === null) { - return angularHelper.rejectedPromise({ - errorMsg: 'User Id cannot be empty' - }); - } - - if (!password) { - return angularHelper.rejectedPromise({ - errorMsg: 'Password cannot be empty' - }); - } - - if (password !== confirmPassword) { - return angularHelper.rejectedPromise({ - errorMsg: 'Password and confirmation do not match' - }); - } - - if (!resetCode) { - return angularHelper.rejectedPromise({ - errorMsg: 'Reset code cannot be empty' - }); - } - - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "PostSetPassword"), - { - userId: userId, - password: password, - resetCode: resetCode - }), - 'Password reset code validation failed for userId ' + userId); - }, - - unlinkLogin: function (loginProvider, providerKey) { - if (!loginProvider || !providerKey) { - return angularHelper.rejectedPromise({ - errorMsg: 'loginProvider or providerKey cannot be empty' - }); - } - - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "PostUnLinkLogin"), { - loginProvider: loginProvider, - providerKey: providerKey - }), - 'Unlinking login provider failed'); - }, - - /** - * @ngdoc method - * @name umbraco.resources.authResource#performLogout - * @methodOf umbraco.resources.authResource - * - * @description - * Logs out the Umbraco backoffice user - * - * ##usage - *
-         * authResource.performLogout()
-         *    .then(function(data) {
-         *        //Do stuff for logging out...
-         *    });
-         * 
- * @returns {Promise} resourcePromise object - * - */ - performLogout: function() { - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "PostLogout"))); - }, - - /** - * @ngdoc method - * @name umbraco.resources.authResource#getCurrentUser - * @methodOf umbraco.resources.authResource - * - * @description - * Sends a request to the server to get the current user details, will return a 401 if the user is not logged in - * - * ##usage - *
-         * authResource.getCurrentUser()
-         *    .then(function(data) {
-         *        //Do stuff for fetching the current logged in Umbraco backoffice user
-         *    });
-         * 
- * @returns {Promise} resourcePromise object - * - */ - getCurrentUser: function () { - - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "GetCurrentUser")), - 'Server call failed for getting current user'); - }, - - getCurrentUserLinkedLogins: function () { - - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "GetCurrentUserLinkedLogins")), - 'Server call failed for getting current users linked logins'); - }, - - /** - * @ngdoc method - * @name umbraco.resources.authResource#isAuthenticated - * @methodOf umbraco.resources.authResource - * - * @description - * Checks if the user is logged in or not - does not return 401 or 403 - * - * ##usage - *
-         * authResource.isAuthenticated()
-         *    .then(function(data) {
-         *        //Do stuff to check if user is authenticated
-         *    });
-         * 
- * @returns {Promise} resourcePromise object - * - */ - isAuthenticated: function () { - - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "IsAuthenticated")), - { - success: function (data, status, headers, config) { - //if the response is false, they are not logged in so return a rejection - if (data === false || data === "false") { - return $q.reject('User is not logged in'); - } - return data; - }, - error: function (data, status, headers, config) { - return { - errorMsg: 'Server call failed for checking authentication', - data: data, - status: status - }; - } - }); - }, - - /** - * @ngdoc method - * @name umbraco.resources.authResource#getRemainingTimeoutSeconds - * @methodOf umbraco.resources.authResource - * - * @description - * Gets the user's remaining seconds before their login times out - * - * ##usage - *
-         * authResource.getRemainingTimeoutSeconds()
-         *    .then(function(data) {
-         *        //Number of seconds is returned
-         *    });
-         * 
- * @returns {Promise} resourcePromise object - * - */ - getRemainingTimeoutSeconds: function () { - - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "authenticationApiBaseUrl", - "GetRemainingTimeoutSeconds")), - 'Server call failed for checking remaining seconds'); - } - - }; + }; } angular.module('umbraco.resources').factory('authResource', authResource); diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js index f44401f5c5..d24a29dc61 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js @@ -26,11 +26,9 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { /** internal method process the saving of data and post processing the result */ - function saveContentItem(content, action, files) { + function saveContentItem(content, action, files, restApiUrl) { return umbRequestHelper.postSaveContent({ - restApiUrl: umbRequestHelper.getApiUrl( - "contentApiBaseUrl", - "PostSave"), + restApiUrl: restApiUrl, content: content, action: action, files: files, @@ -42,6 +40,25 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { return { + + savePermissions: function (saveModel) { + if (!saveModel) { + throw "saveModel cannot be null"; + } + if (!saveModel.contentId) { + throw "saveModel.contentId cannot be null"; + } + if (!saveModel.permissions) { + throw "saveModel.permissions cannot be null"; + } + + return umbRequestHelper.resourcePromise( + $http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostSaveUserGroupPermissions"), + saveModel), + 'Failed to save permissions'); + }, + + getRecycleBin: function () { return umbRequestHelper.resourcePromise( $http.get( @@ -269,6 +286,16 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to delete item ' + id); }, + deleteBlueprint: function (id) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "DeleteBlueprint", + [{ id: id }])), + 'Failed to delete blueprint ' + id); + }, + /** * @ngdoc method * @name umbraco.resources.contentResource#getById @@ -300,6 +327,16 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to retrieve data for content id ' + id); }, + getBlueprintById: function (id) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetBlueprintById", + [{ id: id }])), + 'Failed to retrieve data for content id ' + id); + }, + /** * @ngdoc method * @name umbraco.resources.contentResource#getByIds @@ -381,6 +418,17 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to retrieve data for empty content item type ' + alias); }, + getBlueprintScaffold: function (blueprintId) { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetEmpty", + [{ blueprintId: blueprintId }])), + 'Failed to retrieve blueprint for id ' + blueprintId); + }, + /** * @ngdoc method * @name umbraco.resources.contentResource#getNiceUrl @@ -525,6 +573,15 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to check permission for item ' + id); }, + getDetailedPermissions: function (contentId) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "GetDetailedPermissions", { contentId: contentId })), + 'Failed to retrieve permissions for content item ' + contentId); + }, + getPermissions: function (nodeIds) { return umbRequestHelper.resourcePromise( $http.post( @@ -564,9 +621,18 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { * */ save: function (content, isNew, files) { - return saveContentItem(content, "save" + (isNew ? "New" : ""), files); + var endpoint = umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "PostSave"); + return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint); }, + saveBlueprint: function (content, isNew, files) { + var endpoint = umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "PostSaveBlueprint"); + return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint); + }, /** * @ngdoc method @@ -597,7 +663,10 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { * */ publish: function (content, isNew, files) { - return saveContentItem(content, "publish" + (isNew ? "New" : ""), files); + var endpoint = umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "PostSave"); + return saveContentItem(content, "publish" + (isNew ? "New" : ""), files, endpoint); }, @@ -628,7 +697,10 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { * */ sendToPublish: function (content, isNew, files) { - return saveContentItem(content, "sendPublish" + (isNew ? "New" : ""), files); + var endpoint = umbRequestHelper.getApiUrl( + "contentApiBaseUrl", + "PostSave"); + return saveContentItem(content, "sendPublish" + (isNew ? "New" : ""), files, endpoint); }, /** @@ -665,6 +737,17 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) { [{ id: id }])), 'Failed to publish content with id ' + id); + }, + + createBlueprintFromContent: function (contentId, name) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl("contentApiBaseUrl", "CreateBlueprintFromContent", { + contentId: contentId, name: name + }) + ), + "Failed to create blueprint from content with id " + contentId + ); } diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js index 5375c9507b..fadbb88bb7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/currentuser.resource.js @@ -7,47 +7,46 @@ **/ function currentUserResource($q, $http, umbRequestHelper) { - //the factory object returned - return { - - /** - * @ngdoc method - * @name umbraco.resources.currentUserResource#changePassword - * @methodOf umbraco.resources.currentUserResource - * - * @description - * Changes the current users password - * - * @returns {Promise} resourcePromise object containing the user array. - * - */ - changePassword: function (changePasswordArgs) { - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "currentUserApiBaseUrl", - "PostChangePassword"), - changePasswordArgs), - 'Failed to change password'); - }, - - /** - * @ngdoc method - * @name umbraco.resources.currentUserResource#getMembershipProviderConfig - * @methodOf umbraco.resources.currentUserResource - * - * @description - * Gets the configuration of the user membership provider which is used to configure the change password form - */ - getMembershipProviderConfig: function () { - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "currentUserApiBaseUrl", - "GetMembershipProviderConfig")), - 'Failed to retrieve membership provider config'); - }, - }; + //the factory object returned + return { + + performSetInvitedUserPassword: function (newPassword) { + + if (!newPassword) { + return angularHelper.rejectedPromise({ errorMsg: 'newPassword cannot be empty' }); + } + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "currentUserApiBaseUrl", + "PostSetInvitedUserPassword"), + angular.toJson(newPassword)), + 'Failed to change password'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.currentUserResource#changePassword + * @methodOf umbraco.resources.currentUserResource + * + * @description + * Changes the current users password + * + * @returns {Promise} resourcePromise object containing the user array. + * + */ + changePassword: function (changePasswordArgs) { + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "currentUserApiBaseUrl", + "PostChangePassword"), + changePasswordArgs), + 'Failed to change password'); + } + + }; } angular.module('umbraco.resources').factory('currentUserResource', currentUserResource); diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/log.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/log.resource.js index 8059975fc1..a5e8149952 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/log.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/log.resource.js @@ -67,8 +67,8 @@ function logResource($q, $http, umbRequestHelper) { umbRequestHelper.getApiUrl( "logApiBaseUrl", "GetCurrentUserLog", - [{ logtype: type, sinceDate: since }])), - 'Failed to retrieve user data for id ' + id); + [{ logtype: type}, {sinceDate: since }])), + 'Failed to retrieve log data for current user of type ' + type + ' since ' + since); }, /** @@ -98,8 +98,8 @@ function logResource($q, $http, umbRequestHelper) { umbRequestHelper.getApiUrl( "logApiBaseUrl", "GetLog", - [{ logtype: type, sinceDate: since }])), - 'Failed to retrieve user data for id ' + id); + [{ logtype: type}, {sinceDate: since }])), + 'Failed to retrieve log data of type ' + type + ' since ' + since); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/nestedcontent.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/nestedcontent.resource.js new file mode 100644 index 0000000000..b3488fdff4 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/resources/nestedcontent.resource.js @@ -0,0 +1,12 @@ +angular.module('umbraco.resources').factory('Umbraco.PropertyEditors.NestedContent.Resources', + function ($q, $http, umbRequestHelper) { + return { + getContentTypes: function () { + var url = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + "/backoffice/UmbracoApi/NestedContent/GetContentTypes"; + return umbRequestHelper.resourcePromise( + $http.get(url), + 'Failed to retrieve content types' + ); + }, + }; + }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js index c9a501ba24..cb810c6edb 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/package.resource.js @@ -123,6 +123,16 @@ function packageResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to install package. Error during the step "InstallFiles" '); }, + checkRestart: function (package) { + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "packageInstallApiBaseUrl", + "CheckRestart"), package), + 'Failed to install package. Error during the step "CheckRestart" '); + }, + installData: function (package) { return umbRequestHelper.resourcePromise( diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/section.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/section.resource.js index a2a911ff50..23fab36897 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/section.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/section.resource.js @@ -14,14 +14,22 @@ function sectionResource($q, $http, umbRequestHelper) { return { /** Loads in the data to display the section list */ getSections: function () { - return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( "sectionApiBaseUrl", "GetSections")), 'Failed to retrieve data for sections'); - + }, + + /** Loads in all available sections */ + getAllSections: function () { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "sectionApiBaseUrl", + "GetAllSections")), + 'Failed to retrieve data for sections'); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/user.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/user.resource.js deleted file mode 100644 index 0c6f851eb0..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/resources/user.resource.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @ngdoc service - * @name umbraco.resources.userResource - **/ -function userResource($q, $http, umbDataFormatter, umbRequestHelper) { - - return { - - disableUser: function (userId) { - - if (!userId) { - throw "userId not specified"; - } - - return umbRequestHelper.resourcePromise( - $http.post( - umbRequestHelper.getApiUrl( - "userApiBaseUrl", - "PostDisableUser", [{ userId: userId }])), - 'Failed to disable the user ' + userId); - } - }; -} - -angular.module('umbraco.resources').factory('userResource', userResource); diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/usergroups.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/usergroups.resource.js new file mode 100644 index 0000000000..90d9e58736 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/resources/usergroups.resource.js @@ -0,0 +1,87 @@ +/** + * @ngdoc service + * @name umbraco.resources.usersResource + * @function + * + * @description + * Used by the users section to get users and send requests to create, invite, delete, etc. users. + */ +(function () { + 'use strict'; + + function userGroupsResource($http, umbRequestHelper, $q, umbDataFormatter) { + + function getUserGroupScaffold() { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "userGroupsApiBaseUrl", + "GetEmptyUserGroup")), + 'Failed to get the user group scaffold'); + } + + function saveUserGroup(userGroup, isNew) { + if (!userGroup) { + throw "userGroup not specified"; + } + + //need to convert the user data into the correctly formatted save data - it is *not* the same and we don't want to over-post + var formattedSaveData = umbDataFormatter.formatUserGroupPostData(userGroup, "save" + (isNew ? "New" : "")); + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "userGroupsApiBaseUrl", + "PostSaveUserGroup"), + formattedSaveData), + "Failed to save user group"); + } + + function getUserGroup(id) { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "userGroupsApiBaseUrl", + "GetUserGroup", + { id: id })), + "Failed to retrieve data for user group " + id); + + } + + function getUserGroups() { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "userGroupsApiBaseUrl", + "GetUserGroups")), + "Failed to retrieve user groups"); + } + + function deleteUserGroups(userGroupIds) { + var query = "userGroupIds=" + userGroupIds.join("&userGroupIds="); + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "userGroupsApiBaseUrl", + "PostDeleteUserGroups", + query)), + 'Failed to delete user groups'); + } + + var resource = { + saveUserGroup: saveUserGroup, + getUserGroup: getUserGroup, + getUserGroups: getUserGroups, + getUserGroupScaffold: getUserGroupScaffold, + deleteUserGroups: deleteUserGroups + }; + + return resource; + + } + + angular.module('umbraco.resources').factory('userGroupsResource', userGroupsResource); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js new file mode 100644 index 0000000000..0acd30afe0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/resources/users.resource.js @@ -0,0 +1,203 @@ +/** + * @ngdoc service + * @name umbraco.resources.usersResource + * @function + * + * @description + * Used by the users section to get users and send requests to create, invite, delete, etc. users. + */ +(function () { + 'use strict'; + + function usersResource($http, umbRequestHelper, $q, umbDataFormatter) { + + function clearAvatar(userId) { + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "PostClearAvatar", + { id: userId })), + 'Failed to clear the user avatar ' + userId); + } + + function disableUsers(userIds) { + if (!userIds) { + throw "userIds not specified"; + } + + //we need to create a custom query string for the usergroup array, so create it now and we can append the user groups if needed + var qry = "userIds=" + userIds.join("&userIds="); + + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "PostDisableUsers", qry)), + 'Failed to disable the users ' + userIds.join(",")); + } + + function enableUsers(userIds) { + if (!userIds) { + throw "userIds not specified"; + } + + //we need to create a custom query string for the usergroup array, so create it now and we can append the user groups if needed + var qry = "userIds=" + userIds.join("&userIds="); + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "PostEnableUsers", qry)), + 'Failed to enable the users ' + userIds.join(",")); + } + + function setUserGroupsOnUsers(userGroups, userIds) { + var userGroupAliases = userGroups.map(function(o) { return o.alias; }); + var query = "userGroupAliases=" + userGroupAliases.join("&userGroupAliases=") + "&userIds=" + userIds.join("&userIds="); + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "PostSetUserGroupsOnUsers", + query)), + 'Failed to set user groups ' + userGroupAliases.join(",") + ' on the users ' + userIds.join(",")); + } + + function getPagedResults(options) { + var defaults = { + pageSize: 25, + pageNumber: 1, + filter: '', + orderDirection: "Ascending", + orderBy: "Username", + userGroups: [], + userStates: [] + }; + if (options === undefined) { + options = {}; + } + //overwrite the defaults if there are any specified + angular.extend(defaults, options); + //now copy back to the options we will use + options = defaults; + //change asc/desct + if (options.orderDirection === "asc") { + options.orderDirection = "Ascending"; + } + else if (options.orderDirection === "desc") { + options.orderDirection = "Descending"; + } + + var params = { + pageNumber: options.pageNumber, + pageSize: options.pageSize, + orderBy: options.orderBy, + orderDirection: options.orderDirection, + filter: options.filter + }; + //we need to create a custom query string for the usergroup array, so create it now and we can append the user groups if needed + var qry = umbRequestHelper.dictionaryToQueryString(params); + if (options.userGroups.length > 0) { + //we need to create a custom query string for an array + qry += "&userGroups=" + options.userGroups.join("&userGroups="); + } + if (options.userStates.length > 0) { + //we need to create a custom query string for an array + qry += "&userStates=" + options.userStates.join("&userStates="); + } + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "GetPagedUsers", + qry)), + 'Failed to retrieve users paged result'); + } + + function getUser(userId) { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "GetById", + { id: userId })), + "Failed to retrieve data for user " + userId); + } + + function createUser(user) { + if (!user) { + throw "user not specified"; + } + + //need to convert the user data into the correctly formatted save data - it is *not* the same and we don't want to over-post + var formattedSaveData = umbDataFormatter.formatUserPostData(user); + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "PostCreateUser"), + formattedSaveData), + "Failed to save user"); + } + + function inviteUser(user) { + if (!user) { + throw "user not specified"; + } + + //need to convert the user data into the correctly formatted save data - it is *not* the same and we don't want to over-post + var formattedSaveData = umbDataFormatter.formatUserPostData(user); + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "PostInviteUser"), + formattedSaveData), + "Failed to invite user"); + } + + function saveUser(user) { + if (!user) { + throw "user not specified"; + } + + //need to convert the user data into the correctly formatted save data - it is *not* the same and we don't want to over-post + var formattedSaveData = umbDataFormatter.formatUserPostData(user); + + return umbRequestHelper.resourcePromise( + $http.post( + umbRequestHelper.getApiUrl( + "userApiBaseUrl", + "PostSaveUser"), + formattedSaveData), + "Failed to save user"); + } + + + var resource = { + disableUsers: disableUsers, + enableUsers: enableUsers, + setUserGroupsOnUsers: setUserGroupsOnUsers, + getPagedResults: getPagedResults, + getUser: getUser, + createUser: createUser, + inviteUser: inviteUser, + saveUser: saveUser, + clearAvatar: clearAvatar + }; + + return resource; + + } + + angular.module('umbraco.resources').factory('usersResource', usersResource); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js index 024e8d5a43..6f5712a78d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js @@ -1,6 +1,6 @@ angular.module('umbraco.security.interceptor') // This http interceptor listens for authentication successes and failures - .factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', 'requestInterceptorFilter', function ($injector, queue, notifications, requestInterceptorFilter) { + .factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', 'eventsService', 'requestInterceptorFilter', function ($injector, queue, notifications, eventsService, requestInterceptorFilter) { return function(promise) { return promise.then( @@ -16,6 +16,12 @@ angular.module('umbraco.security.interceptor') userService.setUserTimeout(headers["x-umb-user-seconds"]); } + //this checks if the user's values have changed, in which case we need to update the user details throughout + //the back office similar to how we do when a user logs in + if (headers["x-umb-user-modified"]) { + eventsService.emit("app.userRefresh"); + } + return promise; }, function(originalResponse) { // Intercept failed requests @@ -39,7 +45,7 @@ angular.module('umbraco.security.interceptor') } //A 401 means that the user is not logged in - if (originalResponse.status === 401) { + if (originalResponse.status === 401 && !originalResponse.config.url.endsWith("umbraco/backoffice/UmbracoApi/Authentication/GetCurrentUser")) { var userService = $injector.get('userService'); // see above @@ -96,7 +102,18 @@ angular.module('umbraco.security.interceptor') }); }; }]) - + //used to set headers on all requests where necessary + .factory('umbracoRequestInterceptor', function ($q, queryStrings) { + return { + //dealing with requests: + 'request': function(config) { + if (queryStrings.getParams().umbDebug === "true" || queryStrings.getParams().umbdebug === "true") { + config.headers["X-UMB-DEBUG"] = "true"; + } + return config; + } + }; + }) .value('requestInterceptorFilter', function() { return ["www.gravatar.com"]; }) @@ -104,4 +121,5 @@ angular.module('umbraco.security.interceptor') // We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block. .config(['$httpProvider', function ($httpProvider) { $httpProvider.responseInterceptors.push('securityInterceptor'); + $httpProvider.interceptors.push('umbracoRequestInterceptor'); }]); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js index ff54c5c222..a84be208ba 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js @@ -50,7 +50,7 @@ angular.module('umbraco.services') return url; } - var rnd = Umbraco.Sys.ServerVariables.application.version + "." + Umbraco.Sys.ServerVariables.application.cdf; + var rnd = Umbraco.Sys.ServerVariables.application.cacheBuster; var _op = (url.indexOf("?") > 0) ? "&" : "?"; url = url + _op + "umb__rnd=" + rnd; return url; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js index 020ac9c710..d1014adc69 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js @@ -28,7 +28,8 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica return { - /** Used by the content editor and mini content editor to perform saving operations */ + /** Used by the content editor and mini content editor to perform saving operations */ + //TODO: Make this a more helpful/reusable method for other form operations! we can simplify this form most forms contentEditorPerformSave: function (args) { if (!angular.isObject(args)) { throw "args must be an object"; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/events.service.js b/src/Umbraco.Web.UI.Client/src/common/services/events.service.js index 5c1f606614..174cc8abe2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/events.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/events.service.js @@ -6,7 +6,10 @@ app.ready app.authenticated app.notAuthenticated - app.closeDialogs + app.closeDialogs + app.ysod + app.reInitialize + app.userRefresh */ function eventsService($q, $rootScope) { diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js index 9dfa440a0e..5d5b509315 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js @@ -102,15 +102,24 @@ function formHelper(angularHelper, serverValidationManager, $timeout, notificati //clear the status args.scope[args.statusPropertyName] = null; - if (angular.isArray(args.notifications)) { - for (var i = 0; i < args.notifications.length; i++) { - notificationsService.showNotification(args.notifications[i]); - } - } + this.showNotifications(args); args.scope.$broadcast("formSubmitted", { scope: args.scope }); }, - + + showNotifications: function (args) { + if (!args || !args.notifications) { + return false; + } + if (angular.isArray(args.notifications)) { + for (var i = 0; i < args.notifications.length; i++) { + notificationsService.showNotification(args.notifications[i]); + } + return true; + } + return false; + }, + /** * @ngdoc function * @name umbraco.services.formHelper#handleError diff --git a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js index 0bdc3bb524..84bb4333a2 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/listviewhelper.service.js @@ -269,12 +269,12 @@ var isSelected = false; for (var i = 0; selection.length > i; i++) { var selectedItem = selection[i]; - if (item.id === selectedItem.id) { + if (item.id === selectedItem.id || item.key === selectedItem.key) { isSelected = true; } } if (!isSelected) { - selection.push({ id: item.id }); + selection.push({ id: item.id, key: item.key }); item.selected = true; } } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js index 114e1a0962..636437e387 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js @@ -365,6 +365,28 @@ function mediaHelper(umbRequestHelper) { return newFileTypesArray.join(","); + }, + + /** + * @ngdoc function + * @name umbraco.services.mediaHelper#getFileExtension + * @methodOf umbraco.services.mediaHelper + * @function + * + * @description + * Returns file extension + * + * @param {string} filePath File path, ex /media/1234/my-image.jpg + */ + getFileExtension: function(filePath) { + + if (!filePath) { + return false; + } + + var lowered = filePath.toLowerCase(); + var ext = lowered.substr(lowered.lastIndexOf(".") + 1); + return ext; } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/mediatypehelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/mediatypehelper.service.js index 87804c8473..7e0e1db24f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/mediatypehelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/mediatypehelper.service.js @@ -23,6 +23,10 @@ function mediaTypeHelper(mediaTypeResource, $q) { getAllowedImagetypes: function (mediaId){ //TODO: This is horribly inneficient - why make one request per type!? + //This should make a call to c# to get exactly what it's looking for instead of returning every single media type and doing + //some filtering on the client side. + //This is also called multiple times when it's not needed! Example, when launching the media picker, this will be called twice + //which means we'll be making at least 6 REST calls to fetch each media type // Get All allowedTypes return mediaTypeResource.getAllowedTypes(mediaId) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/search.service.js b/src/Umbraco.Web.UI.Client/src/common/services/search.service.js index f945070a2a..c692fda7ba 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/search.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/search.service.js @@ -21,154 +21,140 @@ * */ angular.module('umbraco.services') -.factory('searchService', function ($q, $log, entityResource, contentResource, umbRequestHelper) { + .factory('searchService', function ($q, $log, entityResource, contentResource, umbRequestHelper, $injector, searchResultFormatter) { - function configureMemberResult(member) { - member.menuUrl = umbRequestHelper.getApiUrl("memberTreeBaseUrl", "GetMenu", [{ id: member.id }, { application: 'member' }]); - member.editorPath = "member/member/edit/" + (member.key ? member.key : member.id); - angular.extend(member.metaData, { treeAlias: "member" }); - member.subTitle = member.metaData.Email; - } - - function configureMediaResult(media) - { - media.menuUrl = umbRequestHelper.getApiUrl("mediaTreeBaseUrl", "GetMenu", [{ id: media.id }, { application: 'media' }]); - media.editorPath = "media/media/edit/" + media.id; - angular.extend(media.metaData, { treeAlias: "media" }); - } - - function configureContentResult(content) { - content.menuUrl = umbRequestHelper.getApiUrl("contentTreeBaseUrl", "GetMenu", [{ id: content.id }, { application: 'content' }]); - content.editorPath = "content/content/edit/" + content.id; - angular.extend(content.metaData, { treeAlias: "content" }); - content.subTitle = content.metaData.Url; - } + return { - return { + /** + * @ngdoc method + * @name umbraco.services.searchService#searchMembers + * @methodOf umbraco.services.searchService + * + * @description + * Searches the default member search index + * @param {Object} args argument object + * @param {String} args.term seach term + * @returns {Promise} returns promise containing all matching members + */ + searchMembers: function (args) { - /** - * @ngdoc method - * @name umbraco.services.searchService#searchMembers - * @methodOf umbraco.services.searchService - * - * @description - * Searches the default member search index - * @param {Object} args argument object - * @param {String} args.term seach term - * @returns {Promise} returns promise containing all matching members - */ - searchMembers: function(args) { + if (!args.term) { + throw "args.term is required"; + } - if (!args.term) { - throw "args.term is required"; - } - - return entityResource.search(args.term, "Member", args.searchFrom).then(function (data) { - _.each(data, function(item) { - configureMemberResult(item); - }); - return data; - }); - }, - - /** - * @ngdoc method - * @name umbraco.services.searchService#searchContent - * @methodOf umbraco.services.searchService - * - * @description - * Searches the default internal content search index - * @param {Object} args argument object - * @param {String} args.term seach term - * @returns {Promise} returns promise containing all matching content items - */ - searchContent: function(args) { - - if (!args.term) { - throw "args.term is required"; - } - - return entityResource.search(args.term, "Document", args.searchFrom, args.canceler).then(function (data) { - _.each(data, function (item) { - configureContentResult(item); + return entityResource.search(args.term, "Member", args.searchFrom).then(function (data) { + _.each(data, function (item) { + configureMemberResult(item); + }); + return data; }); - return data; - }); - }, + }, - /** - * @ngdoc method - * @name umbraco.services.searchService#searchMedia - * @methodOf umbraco.services.searchService - * - * @description - * Searches the default media search index - * @param {Object} args argument object - * @param {String} args.term seach term - * @returns {Promise} returns promise containing all matching media items - */ - searchMedia: function(args) { + /** + * @ngdoc method + * @name umbraco.services.searchService#searchContent + * @methodOf umbraco.services.searchService + * + * @description + * Searches the default internal content search index + * @param {Object} args argument object + * @param {String} args.term seach term + * @returns {Promise} returns promise containing all matching content items + */ + searchContent: function (args) { - if (!args.term) { - throw "args.term is required"; - } + if (!args.term) { + throw "args.term is required"; + } - return entityResource.search(args.term, "Media", args.searchFrom).then(function (data) { - _.each(data, function (item) { - configureMediaResult(item); + return entityResource.search(args.term, "Document", args.searchFrom, args.canceler).then(function (data) { + _.each(data, function (item) { + configureContentResult(item); + }); + return data; }); - return data; - }); - }, + }, - /** - * @ngdoc method - * @name umbraco.services.searchService#searchAll - * @methodOf umbraco.services.searchService - * - * @description - * Searches all available indexes and returns all results in one collection - * @param {Object} args argument object - * @param {String} args.term seach term - * @returns {Promise} returns promise containing all matching items - */ - searchAll: function (args) { - - if (!args.term) { - throw "args.term is required"; - } + /** + * @ngdoc method + * @name umbraco.services.searchService#searchMedia + * @methodOf umbraco.services.searchService + * + * @description + * Searches the default media search index + * @param {Object} args argument object + * @param {String} args.term seach term + * @returns {Promise} returns promise containing all matching media items + */ + searchMedia: function (args) { - return entityResource.searchAll(args.term, args.canceler).then(function (data) { + if (!args.term) { + throw "args.term is required"; + } - _.each(data, function(resultByType) { - switch(resultByType.type) { - case "Document": - _.each(resultByType.results, function (item) { - configureContentResult(item); - }); - break; - case "Media": - _.each(resultByType.results, function (item) { - configureMediaResult(item); - }); - break; - case "Member": - _.each(resultByType.results, function (item) { - configureMemberResult(item); - }); - break; - } + return entityResource.search(args.term, "Media", args.searchFrom).then(function (data) { + _.each(data, function (item) { + configureMediaResult(item); + }); + return data; + }); + }, + + /** + * @ngdoc method + * @name umbraco.services.searchService#searchAll + * @methodOf umbraco.services.searchService + * + * @description + * Searches all available indexes and returns all results in one collection + * @param {Object} args argument object + * @param {String} args.term seach term + * @returns {Promise} returns promise containing all matching items + */ + searchAll: function (args) { + + if (!args.term) { + throw "args.term is required"; + } + + return entityResource.searchAll(args.term, args.canceler).then(function (data) { + + _.each(data, function (resultByType) { + + //we need to format the search result data to include things like the subtitle, urls, etc... + // this is done with registered angular services as part of the SearchableTreeAttribute, if that + // is not found, than we format with the default formatter + var formatterMethod = searchResultFormatter.configureDefaultResult; + //check if a custom formatter is specified... + if (resultByType.jsSvc) { + var searchFormatterService = $injector.get(resultByType.jsSvc); + if (searchFormatterService) { + if (!resultByType.jsMethod) { + resultByType.jsMethod = "format"; + } + formatterMethod = searchFormatterService[resultByType.jsMethod]; + + if (!formatterMethod) { + throw "The method " + resultByType.jsMethod + " on the angular service " + resultByType.jsSvc + " could not be found"; + } + } + } + //now apply the formatter for each result + _.each(resultByType.results, function (item) { + formatterMethod.apply(this, [item, resultByType.treeAlias, resultByType.appAlias]); + }); + + }); + + return data; }); - return data; - }); - - }, + }, - //TODO: This doesn't do anything! - setCurrent: function(sectionAlias) { + //TODO: This doesn't do anything! + setCurrent: function (sectionAlias) { - var currentSection = sectionAlias; - } - }; -}); \ No newline at end of file + var currentSection = sectionAlias; + } + }; + }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/services/searchresultformatter.service.js b/src/Umbraco.Web.UI.Client/src/common/services/searchresultformatter.service.js new file mode 100644 index 0000000000..9bf9f3762c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/searchresultformatter.service.js @@ -0,0 +1,37 @@ + +function searchResultFormatter(umbRequestHelper) { + + function configureDefaultResult(content, treeAlias, appAlias) { + content.editorPath = appAlias + "/" + treeAlias + "/edit/" + content.id; + angular.extend(content.metaData, { treeAlias: treeAlias }); + } + + function configureContentResult(content, treeAlias, appAlias) { + content.menuUrl = umbRequestHelper.getApiUrl("contentTreeBaseUrl", "GetMenu", [{ id: content.id }, { application: appAlias }]); + content.editorPath = appAlias + "/" + treeAlias + "/edit/" + content.id; + angular.extend(content.metaData, { treeAlias: treeAlias }); + content.subTitle = content.metaData.Url; + } + + function configureMemberResult(member, treeAlias, appAlias) { + member.menuUrl = umbRequestHelper.getApiUrl("memberTreeBaseUrl", "GetMenu", [{ id: member.id }, { application: appAlias }]); + member.editorPath = appAlias + "/" + treeAlias + "/edit/" + (member.key ? member.key : member.id); + angular.extend(member.metaData, { treeAlias: treeAlias }); + member.subTitle = member.metaData.Email; + } + + function configureMediaResult(media, treeAlias, appAlias) { + media.menuUrl = umbRequestHelper.getApiUrl("mediaTreeBaseUrl", "GetMenu", [{ id: media.id }, { application: appAlias }]); + media.editorPath = appAlias + "/" + treeAlias + "/edit/" + media.id; + angular.extend(media.metaData, { treeAlias: treeAlias }); + } + + return { + configureContentResult: configureContentResult, + configureMemberResult: configureMemberResult, + configureMediaResult: configureMediaResult, + configureDefaultResult: configureDefaultResult + }; +} + +angular.module('umbraco.services').factory('searchResultFormatter', searchResultFormatter); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js new file mode 100644 index 0000000000..75c7b02d55 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbdataformatter.service.js @@ -0,0 +1,326 @@ +(function () { + 'use strict'; + + /** + * @ngdoc service + * @name umbraco.services.umbDataFormatter + * @description A helper object used to format/transform JSON Umbraco data, mostly used for persisting data to the server + **/ + function umbDataFormatter() { + return { + + formatContentTypePostData: function (displayModel, action) { + + //create the save model from the display model + var saveModel = _.pick(displayModel, + 'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes', + 'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed', + 'key', 'parentId', 'alias', 'path'); + + //TODO: Map these + saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; }); + saveModel.defaultTemplate = displayModel.defaultTemplate ? displayModel.defaultTemplate.alias : null; + var realGroups = _.reject(displayModel.groups, function (g) { + //do not include these tabs + return g.tabState === "init"; + }); + saveModel.groups = _.map(realGroups, function (g) { + + var saveGroup = _.pick(g, 'inherited', 'id', 'sortOrder', 'name'); + + var realProperties = _.reject(g.properties, function (p) { + //do not include these properties + return p.propertyState === "init" || p.inherited === true; + }); + + var saveProperties = _.map(realProperties, function (p) { + var saveProperty = _.pick(p, 'id', 'alias', 'description', 'validation', 'label', 'sortOrder', 'dataTypeId', 'groupId', 'memberCanEdit', 'showOnMemberProfile'); + return saveProperty; + }); + + saveGroup.properties = saveProperties; + + //if this is an inherited group and there are not non-inherited properties on it, then don't send up the data + if (saveGroup.inherited === true && saveProperties.length === 0) { + return null; + } + + return saveGroup; + }); + + //we don't want any null groups + saveModel.groups = _.reject(saveModel.groups, function (g) { + return !g; + }); + + return saveModel; + }, + + /** formats the display model used to display the data type to the model used to save the data type */ + formatDataTypePostData: function (displayModel, preValues, action) { + var saveModel = { + parentId: displayModel.parentId, + id: displayModel.id, + name: displayModel.name, + selectedEditor: displayModel.selectedEditor, + //set the action on the save model + action: action, + preValues: [] + }; + for (var i = 0; i < preValues.length; i++) { + + saveModel.preValues.push({ + key: preValues[i].alias, + value: preValues[i].value + }); + } + return saveModel; + }, + + /** formats the display model used to display the user to the model used to save the user */ + formatUserPostData: function (displayModel) { + + //create the save model from the display model + var saveModel = _.pick(displayModel, 'id', 'parentId', 'name', 'username', 'culture', 'email', 'startContentIds', 'startMediaIds', 'userGroups', 'message', 'changePassword'); + + //make sure the userGroups are just a string array + var currGroups = saveModel.userGroups; + var formattedGroups = []; + for (var i = 0; i < currGroups.length; i++) { + if (!angular.isString(currGroups[i])) { + formattedGroups.push(currGroups[i].alias); + } + else { + formattedGroups.push(currGroups[i]); + } + } + saveModel.userGroups = formattedGroups; + + //make sure the startnodes are just a string array + var props = ["startContentIds", "startMediaIds"]; + for (var m = 0; m < props.length; m++) { + var startIds = saveModel[props[m]]; + if (!startIds) { + continue; + } + var formattedIds = []; + for (var j = 0; j < startIds.length; j++) { + formattedIds.push(Number(startIds[j].id)); + } + saveModel[props[m]] = formattedIds; + } + + return saveModel; + }, + + /** formats the display model used to display the user group to the model used to save the user group*/ + formatUserGroupPostData: function (displayModel, action) { + //create the save model from the display model + var saveModel = _.pick(displayModel, 'id', 'alias', 'name', 'icon', 'sections', 'users', 'defaultPermissions', 'assignedPermissions'); + + // the start nodes cannot be picked as the property name needs to change - assign manually + saveModel.startContentId = displayModel['contentStartNode']; + saveModel.startMediaId = displayModel['mediaStartNode']; + + //set the action on the save model + saveModel.action = action; + if (!saveModel.id) { + saveModel.id = 0; + } + + //the permissions need to just be the array of permission letters, currently it will be a dictionary of an array + var currDefaultPermissions = saveModel.defaultPermissions; + var saveDefaultPermissions = []; + _.each(currDefaultPermissions, function (value, key, list) { + _.each(value, function (element, index, list) { + if (element.checked) { + saveDefaultPermissions.push(element.permissionCode); + } + }); + }); + saveModel.defaultPermissions = saveDefaultPermissions; + + //now format that assigned/content permissions + var currAssignedPermissions = saveModel.assignedPermissions; + var saveAssignedPermissions = {}; + _.each(currAssignedPermissions, function (nodePermissions, index) { + saveAssignedPermissions[nodePermissions.id] = []; + _.each(nodePermissions.allowedPermissions, function (permission, index) { + if (permission.checked) { + saveAssignedPermissions[nodePermissions.id].push(permission.permissionCode); + } + }); + }); + saveModel.assignedPermissions = saveAssignedPermissions; + + + //make sure the sections are just a string array + var currSections = saveModel.sections; + var formattedSections = []; + for (var i = 0; i < currSections.length; i++) { + if (!angular.isString(currSections[i])) { + formattedSections.push(currSections[i].alias); + } + else { + formattedSections.push(currSections[i]); + } + } + saveModel.sections = formattedSections; + + //make sure the user are just an int array + var currUsers = saveModel.users; + var formattedUsers = []; + for (var j = 0; j < currUsers.length; j++) { + if (!angular.isNumber(currUsers[j])) { + formattedUsers.push(currUsers[j].id); + } + else { + formattedUsers.push(currUsers[j]); + } + } + saveModel.users = formattedUsers; + + //make sure the startnodes are just an int if one is set + var props = ["startContentId", "startMediaId"]; + for (var m = 0; m < props.length; m++) { + var startId = saveModel[props[m]]; + if (!startId) { + continue; + } + saveModel[props[m]] = startId.id; + } + + saveModel.parentId = -1; + return saveModel; + }, + + /** formats the display model used to display the member to the model used to save the member */ + formatMemberPostData: function (displayModel, action) { + //this is basically the same as for media but we need to explicitly add the username,email, password to the save model + + var saveModel = this.formatMediaPostData(displayModel, action); + + saveModel.key = displayModel.key; + + var genericTab = _.find(displayModel.tabs, function (item) { + return item.id === 0; + }); + + //map the member login, email, password and groups + var propLogin = _.find(genericTab.properties, function (item) { + return item.alias === "_umb_login"; + }); + var propEmail = _.find(genericTab.properties, function (item) { + return item.alias === "_umb_email"; + }); + var propPass = _.find(genericTab.properties, function (item) { + return item.alias === "_umb_password"; + }); + var propGroups = _.find(genericTab.properties, function (item) { + return item.alias === "_umb_membergroup"; + }); + saveModel.email = propEmail.value; + saveModel.username = propLogin.value; + saveModel.password = propPass.value; + + var selectedGroups = []; + for (var n in propGroups.value) { + if (propGroups.value[n] === true) { + selectedGroups.push(n); + } + } + saveModel.memberGroups = selectedGroups; + + //turn the dictionary into an array of pairs + var memberProviderPropAliases = _.pairs(displayModel.fieldConfig); + _.each(displayModel.tabs, function (tab) { + _.each(tab.properties, function (prop) { + var foundAlias = _.find(memberProviderPropAliases, function (item) { + return prop.alias === item[1]; + }); + if (foundAlias) { + //we know the current property matches an alias, now we need to determine which membership provider property it was for + // by looking at the key + switch (foundAlias[0]) { + case "umbracoMemberLockedOut": + saveModel.isLockedOut = prop.value.toString() === "1" ? true : false; + break; + case "umbracoMemberApproved": + saveModel.isApproved = prop.value.toString() === "1" ? true : false; + break; + case "umbracoMemberComments": + saveModel.comments = prop.value; + break; + } + } + }); + }); + + + + return saveModel; + }, + + /** formats the display model used to display the media to the model used to save the media */ + formatMediaPostData: function (displayModel, action) { + //NOTE: the display model inherits from the save model so we can in theory just post up the display model but + // we don't want to post all of the data as it is unecessary. + var saveModel = { + id: displayModel.id, + properties: [], + name: displayModel.name, + contentTypeAlias: displayModel.contentTypeAlias, + parentId: displayModel.parentId, + //set the action on the save model + action: action + }; + + _.each(displayModel.tabs, function (tab) { + + _.each(tab.properties, function (prop) { + + //don't include the custom generic tab properties + if (!prop.alias.startsWith("_umb_")) { + saveModel.properties.push({ + id: prop.id, + alias: prop.alias, + value: prop.value + }); + } + + }); + }); + + return saveModel; + }, + + /** formats the display model used to display the content to the model used to save the content */ + formatContentPostData: function (displayModel, action) { + + //this is basically the same as for media but we need to explicitly add some extra properties + var saveModel = this.formatMediaPostData(displayModel, action); + + var genericTab = _.find(displayModel.tabs, function (item) { + return item.id === 0; + }); + + var propExpireDate = _.find(genericTab.properties, function (item) { + return item.alias === "_umb_expiredate"; + }); + var propReleaseDate = _.find(genericTab.properties, function (item) { + return item.alias === "_umb_releasedate"; + }); + var propTemplate = _.find(genericTab.properties, function (item) { + return item.alias === "_umb_template"; + }); + saveModel.expireDate = propExpireDate ? propExpireDate.value : null; + saveModel.releaseDate = propReleaseDate ? propReleaseDate.value : null; + saveModel.templateAlias = propTemplate ? propTemplate.value : null; + + return saveModel; + } + }; + } + angular.module('umbraco.services').factory('umbDataFormatter', umbDataFormatter); + +})(); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index 67df26d50a..3732e25403 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -37,7 +37,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ * @function * * @description - * This will turn an array of key/value pairs into a query string + * This will turn an array of key/value pairs or a standard dictionary into a query string * * @param {Array} queryStrings An array of key/value pairs */ @@ -103,15 +103,15 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ * @description * This returns a promise with an underlying http call, it is a helper method to reduce * the amount of duplicate code needed to query http resources and automatically handle any - * 500 Http server errors. + * Http errors. See /docs/source/using-promises-resources.md * - * @param {object} opts A mixed object which can either be a `string` representing the error message to be - * returned OR an `object` containing either: + * @param {object} opts A mixed object which can either be a string representing the error message to be + * returned OR an object containing either: * { success: successCallback, errorMsg: errorMessage } * OR * { success: successCallback, error: errorCallback } - * In both of the above, the successCallback must accept these parameters: `data`, `status`, `headers`, `config` - * If using the errorCallback it must accept these parameters: `data`, `status`, `headers`, `config` + * In both of the above, the successCallback must accept these parameters: data, status, headers, config + * If using the errorCallback it must accept these parameters: data, status, headers, config * The success callback must return the data which will be resolved by the deferred object. * The error callback must return an object containing: {errorMsg: errorMessage, data: originalData, status: status } */ diff --git a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js index 262b06dd50..f20c3df44f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js @@ -1,272 +1,285 @@ angular.module('umbraco.services') - .factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, dialogService, $timeout, angularHelper, $http) { + .factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, dialogService, $timeout, angularHelper, $http) { - var currentUser = null; - var lastUserId = null; - var loginDialog = null; - - //this tracks the last date/time that the user's remainingAuthSeconds was updated from the server - // this is used so that we know when to go and get the user's remaining seconds directly. - var lastServerTimeoutSet = null; + var currentUser = null; + var lastUserId = null; + var loginDialog = null; - function openLoginDialog(isTimedOut) { - if (!loginDialog) { - loginDialog = dialogService.open({ + //this tracks the last date/time that the user's remainingAuthSeconds was updated from the server + // this is used so that we know when to go and get the user's remaining seconds directly. + var lastServerTimeoutSet = null; - //very special flag which means that global events cannot close this dialog - manualClose: true, + function openLoginDialog(isTimedOut) { + if (!loginDialog) { + loginDialog = dialogService.open({ - template: 'views/common/dialogs/login.html', - modalClass: "login-overlay", - animation: "slide", - show: true, - callback: onLoginDialogClose, - dialogData: { - isTimedOut: isTimedOut - } + //very special flag which means that global events cannot close this dialog + manualClose: true, + + template: 'views/common/dialogs/login.html', + modalClass: "login-overlay", + animation: "slide", + show: true, + callback: onLoginDialogClose, + dialogData: { + isTimedOut: isTimedOut + } + }); + } + } + + function onLoginDialogClose(success) { + loginDialog = null; + + if (success) { + securityRetryQueue.retryAll(currentUser.name); + } + else { + securityRetryQueue.cancelAll(); + $location.path('/'); + } + } + + /** + This methods will set the current user when it is resolved and + will then start the counter to count in-memory how many seconds they have + remaining on the auth session + */ + function setCurrentUser(usr) { + if (!usr.remainingAuthSeconds) { + throw "The user object is invalid, the remainingAuthSeconds is required."; + } + currentUser = usr; + lastServerTimeoutSet = new Date(); + //start the timer + countdownUserTimeout(); + } + + /** + Method to count down the current user's timeout seconds, + this will continually count down their current remaining seconds every 5 seconds until + there are no more seconds remaining. + */ + function countdownUserTimeout() { + + $timeout(function () { + + if (currentUser) { + //countdown by 5 seconds since that is how long our timer is for. + currentUser.remainingAuthSeconds -= 5; + + //if there are more than 30 remaining seconds, recurse! + if (currentUser.remainingAuthSeconds > 30) { + + //we need to check when the last time the timeout was set from the server, if + // it has been more than 30 seconds then we'll manually go and retrieve it from the + // server - this helps to keep our local countdown in check with the true timeout. + if (lastServerTimeoutSet != null) { + var now = new Date(); + var seconds = (now.getTime() - lastServerTimeoutSet.getTime()) / 1000; + + if (seconds > 30) { + + //first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we + // wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait. + lastServerTimeoutSet = null; + + //now go get it from the server + //NOTE: the safeApply because our timeout is set to not run digests (performance reasons) + angularHelper.safeApply($rootScope, function () { + authResource.getRemainingTimeoutSeconds().then(function (result) { + setUserTimeoutInternal(result); + }); }); + } } - } - function onLoginDialogClose(success) { - loginDialog = null; + //recurse the countdown! + countdownUserTimeout(); + } + else { - if (success) { - securityRetryQueue.retryAll(currentUser.name); + //we are either timed out or very close to timing out so we need to show the login dialog. + if (Umbraco.Sys.ServerVariables.umbracoSettings.keepUserLoggedIn !== true) { + //NOTE: the safeApply because our timeout is set to not run digests (performance reasons) + angularHelper.safeApply($rootScope, function () { + try { + //NOTE: We are calling this again so that the server can create a log that the timeout has expired, we + // don't actually care about this result. + authResource.getRemainingTimeoutSeconds(); + } + finally { + userAuthExpired(); + } + }); } else { - securityRetryQueue.cancelAll(); - $location.path('/'); + //we've got less than 30 seconds remaining so let's check the server + + if (lastServerTimeoutSet != null) { + //first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we + // wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait. + lastServerTimeoutSet = null; + + //now go get it from the server + //NOTE: the safeApply because our timeout is set to not run digests (performance reasons) + angularHelper.safeApply($rootScope, function () { + authResource.getRemainingTimeoutSeconds().then(function (result) { + setUserTimeoutInternal(result); + }); + }); + } + + //recurse the countdown! + countdownUserTimeout(); + } + } } + }, 5000, //every 5 seconds + false); //false = do NOT execute a digest for every iteration + } - /** - This methods will set the current user when it is resolved and - will then start the counter to count in-memory how many seconds they have - remaining on the auth session - */ - function setCurrentUser(usr) { - if (!usr.remainingAuthSeconds) { - throw "The user object is invalid, the remainingAuthSeconds is required."; - } - currentUser = usr; - lastServerTimeoutSet = new Date(); - //start the timer - countdownUserTimeout(); - } - - /** - Method to count down the current user's timeout seconds, - this will continually count down their current remaining seconds every 5 seconds until - there are no more seconds remaining. - */ - function countdownUserTimeout() { - - $timeout(function () { - - if (currentUser) { - //countdown by 5 seconds since that is how long our timer is for. - currentUser.remainingAuthSeconds -= 5; - - //if there are more than 30 remaining seconds, recurse! - if (currentUser.remainingAuthSeconds > 30) { - - //we need to check when the last time the timeout was set from the server, if - // it has been more than 30 seconds then we'll manually go and retrieve it from the - // server - this helps to keep our local countdown in check with the true timeout. - if (lastServerTimeoutSet != null) { - var now = new Date(); - var seconds = (now.getTime() - lastServerTimeoutSet.getTime()) / 1000; - - if (seconds > 30) { - - //first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we - // wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait. - lastServerTimeoutSet = null; - - //now go get it from the server - //NOTE: the safeApply because our timeout is set to not run digests (performance reasons) - angularHelper.safeApply($rootScope, function () { - authResource.getRemainingTimeoutSeconds().then(function (result) { - setUserTimeoutInternal(result); - }); - }); - } - } - - //recurse the countdown! - countdownUserTimeout(); - } - else { - - //we are either timed out or very close to timing out so we need to show the login dialog. - if (Umbraco.Sys.ServerVariables.umbracoSettings.keepUserLoggedIn !== true) { - //NOTE: the safeApply because our timeout is set to not run digests (performance reasons) - angularHelper.safeApply($rootScope, function () { - try { - //NOTE: We are calling this again so that the server can create a log that the timeout has expired, we - // don't actually care about this result. - authResource.getRemainingTimeoutSeconds(); - } - finally { - userAuthExpired(); - } - }); - } - else { - //we've got less than 30 seconds remaining so let's check the server - - if (lastServerTimeoutSet != null) { - //first we'll set the lastServerTimeoutSet to null - this is so we don't get back in to this loop while we - // wait for a response from the server otherwise we'll be making double/triple/etc... calls while we wait. - lastServerTimeoutSet = null; - - //now go get it from the server - //NOTE: the safeApply because our timeout is set to not run digests (performance reasons) - angularHelper.safeApply($rootScope, function () { - authResource.getRemainingTimeoutSeconds().then(function (result) { - setUserTimeoutInternal(result); - }); - }); - } - - //recurse the countdown! - countdownUserTimeout(); - - } - } - } - }, 5000, //every 5 seconds - false); //false = do NOT execute a digest for every iteration - } - - /** Called to update the current user's timeout */ - function setUserTimeoutInternal(newTimeout) { + /** Called to update the current user's timeout */ + function setUserTimeoutInternal(newTimeout) { - var asNumber = parseFloat(newTimeout); - if (!isNaN(asNumber) && currentUser && angular.isNumber(asNumber)) { - currentUser.remainingAuthSeconds = newTimeout; - lastServerTimeoutSet = new Date(); - } - } + var asNumber = parseFloat(newTimeout); + if (!isNaN(asNumber) && currentUser && angular.isNumber(asNumber)) { + currentUser.remainingAuthSeconds = newTimeout; + lastServerTimeoutSet = new Date(); + } + } - /** resets all user data, broadcasts the notAuthenticated event and shows the login dialog */ - function userAuthExpired(isLogout) { - //store the last user id and clear the user - if (currentUser && currentUser.id !== undefined) { - lastUserId = currentUser.id; - } + /** resets all user data, broadcasts the notAuthenticated event and shows the login dialog */ + function userAuthExpired(isLogout) { + //store the last user id and clear the user + if (currentUser && currentUser.id !== undefined) { + lastUserId = currentUser.id; + } - if (currentUser) { - currentUser.remainingAuthSeconds = 0; - } + if (currentUser) { + currentUser.remainingAuthSeconds = 0; + } - lastServerTimeoutSet = null; - currentUser = null; + lastServerTimeoutSet = null; + currentUser = null; - //broadcast a global event that the user is no longer logged in - eventsService.emit("app.notAuthenticated"); + //broadcast a global event that the user is no longer logged in + eventsService.emit("app.notAuthenticated"); - openLoginDialog(isLogout === undefined ? true : !isLogout); - } - - // Register a handler for when an item is added to the retry queue - securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) { - if (securityRetryQueue.hasMore()) { - userAuthExpired(); - } - }); - - return { - - /** Internal method to display the login dialog */ - _showLoginDialog: function () { - openLoginDialog(); - }, - /** Returns a promise, sends a request to the server to check if the current cookie is authorized */ - isAuthenticated: function () { - //if we've got a current user then just return true - if (currentUser) { - var deferred = $q.defer(); - deferred.resolve(true); - return deferred.promise; - } - return authResource.isAuthenticated(); - }, - - /** Returns a promise, sends a request to the server to validate the credentials */ - authenticate: function (login, password) { - - return authResource.performLogin(login, password) - .then(this.setAuthenticationSuccessful); - }, - setAuthenticationSuccessful:function (data) { - - //when it's successful, return the user data - setCurrentUser(data); - - var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "credentials" }; - - //broadcast a global event - eventsService.emit("app.authenticated", result); - return result; - }, - - /** Logs the user out - */ - logout: function () { - - return authResource.performLogout() - .then(function(data) { - userAuthExpired(); - //done! - return null; - }); - }, - - /** Returns the current user object in a promise */ - getCurrentUser: function (args) { - var deferred = $q.defer(); - - if (!currentUser) { - authResource.getCurrentUser() - .then(function (data) { - - var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" }; - - //TODO: This is a mega backwards compatibility hack... These variables SHOULD NOT exist in the server variables - // since they are not supposed to be dynamic but I accidentally added them there in 7.1.5 IIRC so some people might - // now be relying on this :( - if (Umbraco && Umbraco.Sys && Umbraco.Sys.ServerVariables) { - Umbraco.Sys.ServerVariables["security"] = { - startContentId: data.startContentId, - startMediaId: data.startMediaId - }; - } - - if (args && args.broadcastEvent) { - //broadcast a global event, will inform listening controllers to load in the user specific data - eventsService.emit("app.authenticated", result); - } - - setCurrentUser(data); - - deferred.resolve(currentUser); - }); - - } - else { - deferred.resolve(currentUser); - } - - return deferred.promise; - }, - - /** Called whenever a server request is made that contains a x-umb-user-seconds response header for which we can update the user's remaining timeout seconds */ - setUserTimeout: function (newTimeout) { - setUserTimeoutInternal(newTimeout); - } - }; + openLoginDialog(isLogout === undefined ? true : !isLogout); + } + // Register a handler for when an item is added to the retry queue + securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) { + if (securityRetryQueue.hasMore()) { + userAuthExpired(); + } }); + + return { + + /** Internal method to display the login dialog */ + _showLoginDialog: function () { + openLoginDialog(); + }, + /** Returns a promise, sends a request to the server to check if the current cookie is authorized */ + isAuthenticated: function () { + //if we've got a current user then just return true + if (currentUser) { + var deferred = $q.defer(); + deferred.resolve(true); + return deferred.promise; + } + return authResource.isAuthenticated(); + }, + + /** Returns a promise, sends a request to the server to validate the credentials */ + authenticate: function (login, password) { + + return authResource.performLogin(login, password) + .then(this.setAuthenticationSuccessful); + }, + setAuthenticationSuccessful: function (data) { + + //when it's successful, return the user data + setCurrentUser(data); + + var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "credentials" }; + + //broadcast a global event + eventsService.emit("app.authenticated", result); + return result; + }, + + /** Logs the user out + */ + logout: function () { + + return authResource.performLogout() + .then(function (data) { + userAuthExpired(); + //done! + return null; + }); + }, + + /** Refreshes the current user data with the data stored for the user on the server and returns it */ + refreshCurrentUser: function() { + var deferred = $q.defer(); + + authResource.getCurrentUser() + .then(function (data) { + + var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" }; + + setCurrentUser(data); + + deferred.resolve(currentUser); + }, function () { + //it failed, so they are not logged in + deferred.reject(); + }); + + return deferred.promise; + }, + + /** Returns the current user object in a promise */ + getCurrentUser: function (args) { + var deferred = $q.defer(); + + if (!currentUser) { + authResource.getCurrentUser() + .then(function (data) { + + var result = { user: data, authenticated: true, lastUserId: lastUserId, loginType: "implicit" }; + + if (args && args.broadcastEvent) { + //broadcast a global event, will inform listening controllers to load in the user specific data + eventsService.emit("app.authenticated", result); + } + + setCurrentUser(data); + + deferred.resolve(currentUser); + }, function () { + //it failed, so they are not logged in + deferred.reject(); + }); + + } + else { + deferred.resolve(currentUser); + } + + return deferred.promise; + }, + + /** Called whenever a server request is made that contains a x-umb-user-seconds response header for which we can update the user's remaining timeout seconds */ + setUserTimeout: function (newTimeout) { + setUserTimeoutInternal(newTimeout); + } + }; + + }); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js new file mode 100644 index 0000000000..7d96e17d1f --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/usershelper.service.js @@ -0,0 +1,67 @@ +(function () { + 'use strict'; + + function usersHelperService(localizationService) { + + var userStates = [ + { "name": "All", "key": "All"} , + { "value": 0, "name": "Active", "key": "Active", "color": "success" }, + { "value": 1, "name": "Disabled", "key": "Disabled", "color": "danger" }, + { "value": 2, "name": "Locked out", "key": "LockedOut", "color": "danger" }, + { "value": 3, "name": "Invited", "key": "Invited", "color": "warning" } + ]; + + function getUserStateFromValue(value) { + var foundUserState; + angular.forEach(userStates, function (userState) { + if(userState.value === value) { + foundUserState = userState; + } + }); + return foundUserState; + } + + function getUserStateByKey(key) { + var foundUserState; + angular.forEach(userStates, function (userState) { + if(userState.key === key) { + foundUserState = userState; + } + }); + return foundUserState; + } + + function getUserStatesFilter(userStatesObject) { + + var userStatesFilter = []; + + for (var key in userStatesObject) { + if (userStatesObject.hasOwnProperty(key)) { + var userState = getUserStateByKey(key); + if(userState) { + userState.count = userStatesObject[key]; + userStatesFilter.push(userState); + } + } + } + + return userStatesFilter; + + } + + //////////// + + var service = { + getUserStateFromValue: getUserStateFromValue, + getUserStateByKey: getUserStateByKey, + getUserStatesFilter: getUserStatesFilter + }; + + return service; + + } + + angular.module('umbraco.services').factory('usersHelper', usersHelperService); + + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js index ba395becfc..067ef60492 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/util.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/util.service.js @@ -1,420 +1,420 @@ /*Contains multiple services for various helper tasks */ function versionHelper() { - return { + return { - //see: https://gist.github.com/TheDistantSea/8021359 - versionCompare: function(v1, v2, options) { - var lexicographical = options && options.lexicographical, - zeroExtend = options && options.zeroExtend, - v1parts = v1.split('.'), - v2parts = v2.split('.'); + //see: https://gist.github.com/TheDistantSea/8021359 + versionCompare: function (v1, v2, options) { + var lexicographical = options && options.lexicographical, + zeroExtend = options && options.zeroExtend, + v1parts = v1.split('.'), + v2parts = v2.split('.'); - function isValidPart(x) { - return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x); - } + function isValidPart(x) { + return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x); + } - if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) { - return NaN; - } + if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) { + return NaN; + } - if (zeroExtend) { - while (v1parts.length < v2parts.length) { - v1parts.push("0"); - } - while (v2parts.length < v1parts.length) { - v2parts.push("0"); - } - } - - if (!lexicographical) { - v1parts = v1parts.map(Number); - v2parts = v2parts.map(Number); - } - - for (var i = 0; i < v1parts.length; ++i) { - if (v2parts.length === i) { - return 1; - } - - if (v1parts[i] === v2parts[i]) { - continue; - } - else if (v1parts[i] > v2parts[i]) { - return 1; - } - else { - return -1; - } - } - - if (v1parts.length !== v2parts.length) { - return -1; - } - - return 0; + if (zeroExtend) { + while (v1parts.length < v2parts.length) { + v1parts.push("0"); } - }; + while (v2parts.length < v1parts.length) { + v2parts.push("0"); + } + } + + if (!lexicographical) { + v1parts = v1parts.map(Number); + v2parts = v2parts.map(Number); + } + + for (var i = 0; i < v1parts.length; ++i) { + if (v2parts.length === i) { + return 1; + } + + if (v1parts[i] === v2parts[i]) { + continue; + } + else if (v1parts[i] > v2parts[i]) { + return 1; + } + else { + return -1; + } + } + + if (v1parts.length !== v2parts.length) { + return -1; + } + + return 0; + } + }; } angular.module('umbraco.services').factory('versionHelper', versionHelper); function dateHelper() { - return { - - convertToServerStringTime: function(momentLocal, serverOffsetMinutes, format) { + return { - //get the formatted offset time in HH:mm (server time offset is in minutes) - var formattedOffset = (serverOffsetMinutes > 0 ? "+" : "-") + - moment() - .startOf('day') - .minutes(Math.abs(serverOffsetMinutes)) - .format('HH:mm'); + convertToServerStringTime: function (momentLocal, serverOffsetMinutes, format) { - var server = moment.utc(momentLocal).utcOffset(formattedOffset); - return server.format(format ? format : "YYYY-MM-DD HH:mm:ss"); - }, + //get the formatted offset time in HH:mm (server time offset is in minutes) + var formattedOffset = (serverOffsetMinutes > 0 ? "+" : "-") + + moment() + .startOf('day') + .minutes(Math.abs(serverOffsetMinutes)) + .format('HH:mm'); - convertToLocalMomentTime: function (strVal, serverOffsetMinutes) { + var server = moment.utc(momentLocal).utcOffset(formattedOffset); + return server.format(format ? format : "YYYY-MM-DD HH:mm:ss"); + }, - //get the formatted offset time in HH:mm (server time offset is in minutes) - var formattedOffset = (serverOffsetMinutes > 0 ? "+" : "-") + - moment() - .startOf('day') - .minutes(Math.abs(serverOffsetMinutes)) - .format('HH:mm'); + convertToLocalMomentTime: function (strVal, serverOffsetMinutes) { - //convert to the iso string format - var isoFormat = moment(strVal).format("YYYY-MM-DDTHH:mm:ss") + formattedOffset; + //get the formatted offset time in HH:mm (server time offset is in minutes) + var formattedOffset = (serverOffsetMinutes > 0 ? "+" : "-") + + moment() + .startOf('day') + .minutes(Math.abs(serverOffsetMinutes)) + .format('HH:mm'); - //create a moment with the iso format which will include the offset with the correct time - // then convert it to local time - return moment.parseZone(isoFormat).local(); - } + //convert to the iso string format + var isoFormat = moment(strVal).format("YYYY-MM-DDTHH:mm:ss") + formattedOffset; - }; + //create a moment with the iso format which will include the offset with the correct time + // then convert it to local time + return moment.parseZone(isoFormat).local(); + } + + }; } angular.module('umbraco.services').factory('dateHelper', dateHelper); function packageHelper(assetsService, treeService, eventsService, $templateCache) { - return { + return { - /** Called when a package is installed, this resets a bunch of data and ensures the new package assets are loaded in */ - packageInstalled: function () { + /** Called when a package is installed, this resets a bunch of data and ensures the new package assets are loaded in */ + packageInstalled: function () { - //clears the tree - treeService.clearCache(); + //clears the tree + treeService.clearCache(); - //clears the template cache - $templateCache.removeAll(); + //clears the template cache + $templateCache.removeAll(); - //emit event to notify anything else - eventsService.emit("app.reInitialize"); - } + //emit event to notify anything else + eventsService.emit("app.reInitialize"); + } - }; + }; } angular.module('umbraco.services').factory('packageHelper', packageHelper); //TODO: I believe this is obsolete function umbPhotoFolderHelper($compile, $log, $timeout, $filter, imageHelper, mediaHelper, umbRequestHelper) { - return { - /** sets the image's url, thumbnail and if its a folder */ - setImageData: function(img) { - - img.isFolder = !mediaHelper.hasFilePropertyType(img); + return { + /** sets the image's url, thumbnail and if its a folder */ + setImageData: function (img) { - if(!img.isFolder){ - img.thumbnail = mediaHelper.resolveFile(img, true); - img.image = mediaHelper.resolveFile(img, false); - } - }, + img.isFolder = !mediaHelper.hasFilePropertyType(img); - /** sets the images original size properties - will check if it is a folder and if so will just make it square */ - setOriginalSize: function(img, maxHeight) { - //set to a square by default - img.originalWidth = maxHeight; - img.originalHeight = maxHeight; + if (!img.isFolder) { + img.thumbnail = mediaHelper.resolveFile(img, true); + img.image = mediaHelper.resolveFile(img, false); + } + }, - var widthProp = _.find(img.properties, function(v) { return (v.alias === "umbracoWidth"); }); - if (widthProp && widthProp.value) { - img.originalWidth = parseInt(widthProp.value, 10); - if (isNaN(img.originalWidth)) { - img.originalWidth = maxHeight; - } - } - var heightProp = _.find(img.properties, function(v) { return (v.alias === "umbracoHeight"); }); - if (heightProp && heightProp.value) { - img.originalHeight = parseInt(heightProp.value, 10); - if (isNaN(img.originalHeight)) { - img.originalHeight = maxHeight; - } - } - }, + /** sets the images original size properties - will check if it is a folder and if so will just make it square */ + setOriginalSize: function (img, maxHeight) { + //set to a square by default + img.originalWidth = maxHeight; + img.originalHeight = maxHeight; - /** sets the image style which get's used in the angular markup */ - setImageStyle: function(img, width, height, rightMargin, bottomMargin) { - img.style = { width: width + "px", height: height + "px", "margin-right": rightMargin + "px", "margin-bottom": bottomMargin + "px" }; - img.thumbStyle = { - "background-image": "url('" + img.thumbnail + "')", - "background-repeat": "no-repeat", - "background-position": "center", - "background-size": Math.min(width, img.originalWidth) + "px " + Math.min(height, img.originalHeight) + "px" - }; - }, - - /** gets the image's scaled wdith based on the max row height */ - getScaledWidth: function(img, maxHeight) { - var scaled = img.originalWidth * maxHeight / img.originalHeight; - return scaled; - //round down, we don't want it too big even by half a pixel otherwise it'll drop to the next row - //return Math.floor(scaled); - }, - - /** returns the target row width taking into account how many images will be in the row and removing what the margin is */ - getTargetWidth: function(imgsPerRow, maxRowWidth, margin) { - //take into account the margin, we will have 1 less margin item than we have total images - return (maxRowWidth - ((imgsPerRow - 1) * margin)); - }, - - /** - This will determine the row/image height for the next collection of images which takes into account the - ideal image count per row. It will check if a row can be filled with this ideal count and if not - if there - are additional images available to fill the row it will keep calculating until they fit. - - It will return the calculated height and the number of images for the row. - - targetHeight = optional; - */ - getRowHeightForImages: function(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, targetHeight) { - - var idealImages = imgs.slice(0, idealImgPerRow); - //get the target row width without margin - var targetRowWidth = this.getTargetWidth(idealImages.length, maxRowWidth, margin); - //this gets the image with the smallest height which equals the maximum we can scale up for this image block - var maxScaleableHeight = this.getMaxScaleableHeight(idealImages, maxRowHeight); - //if the max scale height is smaller than the min display height, we'll use the min display height - targetHeight = targetHeight !== undefined ? targetHeight : Math.max(maxScaleableHeight, minDisplayHeight); - - var attemptedRowHeight = this.performGetRowHeight(idealImages, targetRowWidth, minDisplayHeight, targetHeight); - - if (attemptedRowHeight != null) { - - //if this is smaller than the min display then we need to use the min display, - // which means we'll need to remove one from the row so we can scale up to fill the row - if (attemptedRowHeight < minDisplayHeight) { - - if (idealImages.length > 1) { - - //we'll generate a new targetHeight that is halfway between the max and the current and recurse, passing in a new targetHeight - targetHeight += Math.floor((maxRowHeight - targetHeight) / 2); - return this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow - 1, margin, targetHeight); - } - else { - //this will occur when we only have one image remaining in the row but it's still going to be too wide even when - // using the minimum display height specified. In this case we're going to have to just crop the image in it's center - // using the minimum display height and the full row width - return { height: minDisplayHeight, imgCount: 1 }; - } - } - else { - //success! - return { height: attemptedRowHeight, imgCount: idealImages.length }; - } - } - - //we know the width will fit in a row, but we now need to figure out if we can fill - // the entire row in the case that we have more images remaining than the idealImgPerRow. - - if (idealImages.length === imgs.length) { - //we have no more remaining images to fill the space, so we'll just use the calc height - return { height: targetHeight, imgCount: idealImages.length }; - } - else if (idealImages.length === 1) { - //this will occur when we only have one image remaining in the row to process but it's not really going to fit ideally - // in the row. - return { height: minDisplayHeight, imgCount: 1 }; - } - else if (idealImages.length === idealImgPerRow && targetHeight < maxRowHeight) { - - //if we're already dealing with the ideal images per row and it's not quite wide enough, we can scale up a little bit so - // long as the targetHeight is currently less than the maxRowHeight. The scale up will be half-way between our current - // target height and the maxRowHeight (we won't loop forever though - if there's a difference of 5 px we'll just quit) - - while (targetHeight < maxRowHeight && (maxRowHeight - targetHeight) > 5) { - targetHeight += Math.floor((maxRowHeight - targetHeight) / 2); - attemptedRowHeight = this.performGetRowHeight(idealImages, targetRowWidth, minDisplayHeight, targetHeight); - if (attemptedRowHeight != null) { - //success! - return { height: attemptedRowHeight, imgCount: idealImages.length }; - } - } - - //Ok, we couldn't actually scale it up with the ideal row count we'll just recurse with a lesser image count. - return this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow - 1, margin); - } - else if (targetHeight === maxRowHeight) { - - //This is going to happen when: - // * We can fit a list of images in a row, but they come up too short (based on minDisplayHeight) - // * Then we'll try to remove an image, but when we try to scale to fit, the width comes up too narrow but the images are already at their - // maximum height (maxRowHeight) - // * So we're stuck, we cannot precicely fit the current list of images, so we'll render a row that will be max height but won't be wide enough - // which is better than rendering a row that is shorter than the minimum since that could be quite small. - - return { height: targetHeight, imgCount: idealImages.length }; - } - else { - - //we have additional images so we'll recurse and add 1 to the idealImgPerRow until it fits - return this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow + 1, margin); - } - - }, - - performGetRowHeight: function(idealImages, targetRowWidth, minDisplayHeight, targetHeight) { - - var currRowWidth = 0; - - for (var i = 0; i < idealImages.length; i++) { - var scaledW = this.getScaledWidth(idealImages[i], targetHeight); - currRowWidth += scaledW; - } - - if (currRowWidth > targetRowWidth) { - //get the new scaled height to fit - var newHeight = targetRowWidth * targetHeight / currRowWidth; - - return newHeight; - } - else if (idealImages.length === 1 && (currRowWidth <= targetRowWidth) && !idealImages[0].isFolder) { - //if there is only one image, then return the target height - return targetHeight; - } - else if (currRowWidth / targetRowWidth > 0.90) { - //it's close enough, it's at least 90% of the width so we'll accept it with the target height - return targetHeight; - } - else { - //if it's not successful, return null - return null; - } - }, - - /** builds an image grid row */ - buildRow: function(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, totalRemaining) { - var currRowWidth = 0; - var row = { images: [] }; - - var imageRowHeight = this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin); - var targetWidth = this.getTargetWidth(imageRowHeight.imgCount, maxRowWidth, margin); - - var sizes = []; - //loop through the images we know fit into the height - for (var i = 0; i < imageRowHeight.imgCount; i++) { - //get the lower width to ensure it always fits - var scaledWidth = Math.floor(this.getScaledWidth(imgs[i], imageRowHeight.height)); - - if (currRowWidth + scaledWidth <= targetWidth) { - currRowWidth += scaledWidth; - sizes.push({ - width:scaledWidth, - //ensure that the height is rounded - height: Math.round(imageRowHeight.height) - }); - row.images.push(imgs[i]); - } - else if (imageRowHeight.imgCount === 1 && row.images.length === 0) { - //the image is simply too wide, we'll crop/center it - sizes.push({ - width: maxRowWidth, - //ensure that the height is rounded - height: Math.round(imageRowHeight.height) - }); - row.images.push(imgs[i]); - } - else { - //the max width has been reached - break; - } - } - - //loop through the images for the row and apply the styles - for (var j = 0; j < row.images.length; j++) { - var bottomMargin = margin; - //make the margin 0 for the last one - if (j === (row.images.length - 1)) { - margin = 0; - } - this.setImageStyle(row.images[j], sizes[j].width, sizes[j].height, margin, bottomMargin); - } - - if (row.images.length === 1 && totalRemaining > 1) { - //if there's only one image on the row and there are more images remaining, set the container to max width - row.images[0].style.width = maxRowWidth + "px"; - } - - - return row; - }, - - /** Returns the maximum image scaling height for the current image collection */ - getMaxScaleableHeight: function(imgs, maxRowHeight) { - - var smallestHeight = _.min(imgs, function(item) { return item.originalHeight; }).originalHeight; - - //adjust the smallestHeight if it is larger than the static max row height - if (smallestHeight > maxRowHeight) { - smallestHeight = maxRowHeight; - } - return smallestHeight; - }, - - /** Creates the image grid with calculated widths/heights for images to fill the grid nicely */ - buildGrid: function(images, maxRowWidth, maxRowHeight, startingIndex, minDisplayHeight, idealImgPerRow, margin,imagesOnly) { - - var rows = []; - var imagesProcessed = 0; - - //first fill in all of the original image sizes and URLs - for (var i = startingIndex; i < images.length; i++) { - var item = images[i]; - - this.setImageData(item); - this.setOriginalSize(item, maxRowHeight); - - if(imagesOnly && !item.isFolder && !item.thumbnail){ - images.splice(i, 1); - i--; - } - } - - while ((imagesProcessed + startingIndex) < images.length) { - //get the maxHeight for the current un-processed images - var currImgs = images.slice(imagesProcessed); - - //build the row - var remaining = images.length - imagesProcessed; - var row = this.buildRow(currImgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, remaining); - if (row.images.length > 0) { - rows.push(row); - imagesProcessed += row.images.length; - } - else { - - if (currImgs.length > 0) { - throw "Could not fill grid with all images, images remaining: " + currImgs.length; - } - - //if there was nothing processed, exit - break; - } - } - - return rows; + var widthProp = _.find(img.properties, function (v) { return (v.alias === "umbracoWidth"); }); + if (widthProp && widthProp.value) { + img.originalWidth = parseInt(widthProp.value, 10); + if (isNaN(img.originalWidth)) { + img.originalWidth = maxHeight; } - }; + } + var heightProp = _.find(img.properties, function (v) { return (v.alias === "umbracoHeight"); }); + if (heightProp && heightProp.value) { + img.originalHeight = parseInt(heightProp.value, 10); + if (isNaN(img.originalHeight)) { + img.originalHeight = maxHeight; + } + } + }, + + /** sets the image style which get's used in the angular markup */ + setImageStyle: function (img, width, height, rightMargin, bottomMargin) { + img.style = { width: width + "px", height: height + "px", "margin-right": rightMargin + "px", "margin-bottom": bottomMargin + "px" }; + img.thumbStyle = { + "background-image": "url('" + img.thumbnail + "')", + "background-repeat": "no-repeat", + "background-position": "center", + "background-size": Math.min(width, img.originalWidth) + "px " + Math.min(height, img.originalHeight) + "px" + }; + }, + + /** gets the image's scaled wdith based on the max row height */ + getScaledWidth: function (img, maxHeight) { + var scaled = img.originalWidth * maxHeight / img.originalHeight; + return scaled; + //round down, we don't want it too big even by half a pixel otherwise it'll drop to the next row + //return Math.floor(scaled); + }, + + /** returns the target row width taking into account how many images will be in the row and removing what the margin is */ + getTargetWidth: function (imgsPerRow, maxRowWidth, margin) { + //take into account the margin, we will have 1 less margin item than we have total images + return (maxRowWidth - ((imgsPerRow - 1) * margin)); + }, + + /** + This will determine the row/image height for the next collection of images which takes into account the + ideal image count per row. It will check if a row can be filled with this ideal count and if not - if there + are additional images available to fill the row it will keep calculating until they fit. + + It will return the calculated height and the number of images for the row. + + targetHeight = optional; + */ + getRowHeightForImages: function (imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, targetHeight) { + + var idealImages = imgs.slice(0, idealImgPerRow); + //get the target row width without margin + var targetRowWidth = this.getTargetWidth(idealImages.length, maxRowWidth, margin); + //this gets the image with the smallest height which equals the maximum we can scale up for this image block + var maxScaleableHeight = this.getMaxScaleableHeight(idealImages, maxRowHeight); + //if the max scale height is smaller than the min display height, we'll use the min display height + targetHeight = targetHeight !== undefined ? targetHeight : Math.max(maxScaleableHeight, minDisplayHeight); + + var attemptedRowHeight = this.performGetRowHeight(idealImages, targetRowWidth, minDisplayHeight, targetHeight); + + if (attemptedRowHeight != null) { + + //if this is smaller than the min display then we need to use the min display, + // which means we'll need to remove one from the row so we can scale up to fill the row + if (attemptedRowHeight < minDisplayHeight) { + + if (idealImages.length > 1) { + + //we'll generate a new targetHeight that is halfway between the max and the current and recurse, passing in a new targetHeight + targetHeight += Math.floor((maxRowHeight - targetHeight) / 2); + return this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow - 1, margin, targetHeight); + } + else { + //this will occur when we only have one image remaining in the row but it's still going to be too wide even when + // using the minimum display height specified. In this case we're going to have to just crop the image in it's center + // using the minimum display height and the full row width + return { height: minDisplayHeight, imgCount: 1 }; + } + } + else { + //success! + return { height: attemptedRowHeight, imgCount: idealImages.length }; + } + } + + //we know the width will fit in a row, but we now need to figure out if we can fill + // the entire row in the case that we have more images remaining than the idealImgPerRow. + + if (idealImages.length === imgs.length) { + //we have no more remaining images to fill the space, so we'll just use the calc height + return { height: targetHeight, imgCount: idealImages.length }; + } + else if (idealImages.length === 1) { + //this will occur when we only have one image remaining in the row to process but it's not really going to fit ideally + // in the row. + return { height: minDisplayHeight, imgCount: 1 }; + } + else if (idealImages.length === idealImgPerRow && targetHeight < maxRowHeight) { + + //if we're already dealing with the ideal images per row and it's not quite wide enough, we can scale up a little bit so + // long as the targetHeight is currently less than the maxRowHeight. The scale up will be half-way between our current + // target height and the maxRowHeight (we won't loop forever though - if there's a difference of 5 px we'll just quit) + + while (targetHeight < maxRowHeight && (maxRowHeight - targetHeight) > 5) { + targetHeight += Math.floor((maxRowHeight - targetHeight) / 2); + attemptedRowHeight = this.performGetRowHeight(idealImages, targetRowWidth, minDisplayHeight, targetHeight); + if (attemptedRowHeight != null) { + //success! + return { height: attemptedRowHeight, imgCount: idealImages.length }; + } + } + + //Ok, we couldn't actually scale it up with the ideal row count we'll just recurse with a lesser image count. + return this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow - 1, margin); + } + else if (targetHeight === maxRowHeight) { + + //This is going to happen when: + // * We can fit a list of images in a row, but they come up too short (based on minDisplayHeight) + // * Then we'll try to remove an image, but when we try to scale to fit, the width comes up too narrow but the images are already at their + // maximum height (maxRowHeight) + // * So we're stuck, we cannot precicely fit the current list of images, so we'll render a row that will be max height but won't be wide enough + // which is better than rendering a row that is shorter than the minimum since that could be quite small. + + return { height: targetHeight, imgCount: idealImages.length }; + } + else { + + //we have additional images so we'll recurse and add 1 to the idealImgPerRow until it fits + return this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow + 1, margin); + } + + }, + + performGetRowHeight: function (idealImages, targetRowWidth, minDisplayHeight, targetHeight) { + + var currRowWidth = 0; + + for (var i = 0; i < idealImages.length; i++) { + var scaledW = this.getScaledWidth(idealImages[i], targetHeight); + currRowWidth += scaledW; + } + + if (currRowWidth > targetRowWidth) { + //get the new scaled height to fit + var newHeight = targetRowWidth * targetHeight / currRowWidth; + + return newHeight; + } + else if (idealImages.length === 1 && (currRowWidth <= targetRowWidth) && !idealImages[0].isFolder) { + //if there is only one image, then return the target height + return targetHeight; + } + else if (currRowWidth / targetRowWidth > 0.90) { + //it's close enough, it's at least 90% of the width so we'll accept it with the target height + return targetHeight; + } + else { + //if it's not successful, return null + return null; + } + }, + + /** builds an image grid row */ + buildRow: function (imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, totalRemaining) { + var currRowWidth = 0; + var row = { images: [] }; + + var imageRowHeight = this.getRowHeightForImages(imgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin); + var targetWidth = this.getTargetWidth(imageRowHeight.imgCount, maxRowWidth, margin); + + var sizes = []; + //loop through the images we know fit into the height + for (var i = 0; i < imageRowHeight.imgCount; i++) { + //get the lower width to ensure it always fits + var scaledWidth = Math.floor(this.getScaledWidth(imgs[i], imageRowHeight.height)); + + if (currRowWidth + scaledWidth <= targetWidth) { + currRowWidth += scaledWidth; + sizes.push({ + width: scaledWidth, + //ensure that the height is rounded + height: Math.round(imageRowHeight.height) + }); + row.images.push(imgs[i]); + } + else if (imageRowHeight.imgCount === 1 && row.images.length === 0) { + //the image is simply too wide, we'll crop/center it + sizes.push({ + width: maxRowWidth, + //ensure that the height is rounded + height: Math.round(imageRowHeight.height) + }); + row.images.push(imgs[i]); + } + else { + //the max width has been reached + break; + } + } + + //loop through the images for the row and apply the styles + for (var j = 0; j < row.images.length; j++) { + var bottomMargin = margin; + //make the margin 0 for the last one + if (j === (row.images.length - 1)) { + margin = 0; + } + this.setImageStyle(row.images[j], sizes[j].width, sizes[j].height, margin, bottomMargin); + } + + if (row.images.length === 1 && totalRemaining > 1) { + //if there's only one image on the row and there are more images remaining, set the container to max width + row.images[0].style.width = maxRowWidth + "px"; + } + + + return row; + }, + + /** Returns the maximum image scaling height for the current image collection */ + getMaxScaleableHeight: function (imgs, maxRowHeight) { + + var smallestHeight = _.min(imgs, function (item) { return item.originalHeight; }).originalHeight; + + //adjust the smallestHeight if it is larger than the static max row height + if (smallestHeight > maxRowHeight) { + smallestHeight = maxRowHeight; + } + return smallestHeight; + }, + + /** Creates the image grid with calculated widths/heights for images to fill the grid nicely */ + buildGrid: function (images, maxRowWidth, maxRowHeight, startingIndex, minDisplayHeight, idealImgPerRow, margin, imagesOnly) { + + var rows = []; + var imagesProcessed = 0; + + //first fill in all of the original image sizes and URLs + for (var i = startingIndex; i < images.length; i++) { + var item = images[i]; + + this.setImageData(item); + this.setOriginalSize(item, maxRowHeight); + + if (imagesOnly && !item.isFolder && !item.thumbnail) { + images.splice(i, 1); + i--; + } + } + + while ((imagesProcessed + startingIndex) < images.length) { + //get the maxHeight for the current un-processed images + var currImgs = images.slice(imagesProcessed); + + //build the row + var remaining = images.length - imagesProcessed; + var row = this.buildRow(currImgs, maxRowHeight, minDisplayHeight, maxRowWidth, idealImgPerRow, margin, remaining); + if (row.images.length > 0) { + rows.push(row); + imagesProcessed += row.images.length; + } + else { + + if (currImgs.length > 0) { + throw "Could not fill grid with all images, images remaining: " + currImgs.length; + } + + //if there was nothing processed, exit + break; + } + } + + return rows; + } + }; } angular.module("umbraco.services").factory("umbPhotoFolderHelper", umbPhotoFolderHelper); @@ -428,40 +428,40 @@ angular.module("umbraco.services").factory("umbPhotoFolderHelper", umbPhotoFolde */ function umbModelMapper() { - return { + return { - /** - * @ngdoc function - * @name umbraco.services.umbModelMapper#convertToEntityBasic - * @methodOf umbraco.services.umbModelMapper - * @function - * - * @description - * Converts the source model to a basic entity model, it will throw an exception if there isn't enough data to create the model. - * @param {Object} source The source model - * @param {Number} source.id The node id of the model - * @param {String} source.name The node name - * @param {String} source.icon The models icon as a css class (.icon-doc) - * @param {Number} source.parentId The parentID, if no parent, set to -1 - * @param {path} source.path comma-separated string of ancestor IDs (-1,1234,1782,1234) - */ + /** + * @ngdoc function + * @name umbraco.services.umbModelMapper#convertToEntityBasic + * @methodOf umbraco.services.umbModelMapper + * @function + * + * @description + * Converts the source model to a basic entity model, it will throw an exception if there isn't enough data to create the model. + * @param {Object} source The source model + * @param {Number} source.id The node id of the model + * @param {String} source.name The node name + * @param {String} source.icon The models icon as a css class (.icon-doc) + * @param {Number} source.parentId The parentID, if no parent, set to -1 + * @param {path} source.path comma-separated string of ancestor IDs (-1,1234,1782,1234) + */ - /** This converts the source model to a basic entity model, it will throw an exception if there isn't enough data to create the model */ - convertToEntityBasic: function (source) { - var required = ["id", "name", "icon", "parentId", "path"]; - _.each(required, function (k) { - if (!_.has(source, k)) { - throw "The source object does not contain the property " + k; - } - }); - var optional = ["metaData", "key", "alias"]; - //now get the basic object - var result = _.pick(source, required.concat(optional)); - return result; + /** This converts the source model to a basic entity model, it will throw an exception if there isn't enough data to create the model */ + convertToEntityBasic: function (source) { + var required = ["id", "name", "icon", "parentId", "path"]; + _.each(required, function (k) { + if (!_.has(source, k)) { + throw "The source object does not contain the property " + k; } + }); + var optional = ["metaData", "key", "alias"]; + //now get the basic object + var result = _.pick(source, required.concat(optional)); + return result; + } - }; + }; } angular.module('umbraco.services').factory('umbModelMapper', umbModelMapper); @@ -476,21 +476,21 @@ angular.module('umbraco.services').factory('umbModelMapper', umbModelMapper); */ function umbSessionStorage($window) { - //gets the sessionStorage object if available, otherwise just uses a normal object - // - required for unit tests. - var storage = $window['sessionStorage'] ? $window['sessionStorage'] : {}; + //gets the sessionStorage object if available, otherwise just uses a normal object + // - required for unit tests. + var storage = $window['sessionStorage'] ? $window['sessionStorage'] : {}; - return { + return { - get: function (key) { - return angular.fromJson(storage["umb_" + key]); - }, - - set : function(key, value) { - storage["umb_" + key] = angular.toJson(value); - } - - }; + get: function (key) { + return angular.fromJson(storage["umb_" + key]); + }, + + set: function (key, value) { + storage["umb_" + key] = angular.toJson(value); + } + + }; } angular.module('umbraco.services').factory('umbSessionStorage', umbSessionStorage); @@ -503,28 +503,28 @@ angular.module('umbraco.services').factory('umbSessionStorage', umbSessionStorag * used to check for updates and display a notifcation */ function updateChecker($http, umbRequestHelper) { - return { - - /** - * @ngdoc function - * @name umbraco.services.updateChecker#check - * @methodOf umbraco.services.updateChecker - * @function - * - * @description - * Called to load in the legacy tree js which is required on startup if a user is logged in or - * after login, but cannot be called until they are authenticated which is why it needs to be lazy loaded. - */ - check: function() { - - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "updateCheckApiBaseUrl", - "GetCheck")), - 'Failed to retrieve update status'); - } - }; + return { + + /** + * @ngdoc function + * @name umbraco.services.updateChecker#check + * @methodOf umbraco.services.updateChecker + * @function + * + * @description + * Called to load in the legacy tree js which is required on startup if a user is logged in or + * after login, but cannot be called until they are authenticated which is why it needs to be lazy loaded. + */ + check: function () { + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "updateCheckApiBaseUrl", + "GetCheck")), + 'Failed to retrieve update status'); + } + }; } angular.module('umbraco.services').factory('updateChecker', updateChecker); @@ -534,250 +534,72 @@ angular.module('umbraco.services').factory('updateChecker', updateChecker); * @description A helper object used for property editors **/ function umbPropEditorHelper() { - return { - /** - * @ngdoc function - * @name getImagePropertyValue - * @methodOf umbraco.services.umbPropertyEditorHelper - * @function - * - * @description - * Returns the correct view path for a property editor, it will detect if it is a full virtual path but if not then default to the internal umbraco one - * - * @param {string} input the view path currently stored for the property editor - */ - getViewPath: function(input, isPreValue) { - var path = String(input); + return { + /** + * @ngdoc function + * @name getImagePropertyValue + * @methodOf umbraco.services.umbPropertyEditorHelper + * @function + * + * @description + * Returns the correct view path for a property editor, it will detect if it is a full virtual path but if not then default to the internal umbraco one + * + * @param {string} input the view path currently stored for the property editor + */ + getViewPath: function (input, isPreValue) { + var path = String(input); - if (path.startsWith('/')) { + if (path.startsWith('/')) { - //This is an absolute path, so just leave it - return path; - } else { + //This is an absolute path, so just leave it + return path; + } else { - if (path.indexOf("/") >= 0) { - //This is a relative path, so just leave it - return path; - } else { - if (!isPreValue) { - //i.e. views/propertyeditors/fileupload/fileupload.html - return "views/propertyeditors/" + path + "/" + path + ".html"; - } else { - //i.e. views/prevalueeditors/requiredfield.html - return "views/prevalueeditors/" + path + ".html"; - } - } - - } + if (path.indexOf("/") >= 0) { + //This is a relative path, so just leave it + return path; + } else { + if (!isPreValue) { + //i.e. views/propertyeditors/fileupload/fileupload.html + return "views/propertyeditors/" + path + "/" + path + ".html"; + } else { + //i.e. views/prevalueeditors/requiredfield.html + return "views/prevalueeditors/" + path + ".html"; + } } - }; + + } + } + }; } angular.module('umbraco.services').factory('umbPropEditorHelper', umbPropEditorHelper); - /** * @ngdoc service -* @name umbraco.services.umbDataFormatter -* @description A helper object used to format/transform JSON Umbraco data, mostly used for persisting data to the server +* @name umbraco.services.queryStrings +* @description A helper used to get query strings in the real URL (not the hash URL) **/ -function umbDataFormatter() { - return { - - formatContentTypePostData: function (displayModel, action) { +function queryStrings($window) { - //create the save model from the display model - var saveModel = _.pick(displayModel, - 'compositeContentTypes', 'isContainer', 'allowAsRoot', 'allowedTemplates', 'allowedContentTypes', - 'alias', 'description', 'thumbnail', 'name', 'id', 'icon', 'trashed', - 'key', 'parentId', 'alias', 'path'); + var pl = /\+/g; // Regex for replacing addition symbol with a space + var search = /([^&=]+)=?([^&]*)/g; + var decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); }; - //TODO: Map these - saveModel.allowedTemplates = _.map(displayModel.allowedTemplates, function (t) { return t.alias; }); - saveModel.defaultTemplate = displayModel.defaultTemplate ? displayModel.defaultTemplate.alias : null; - var realGroups = _.reject(displayModel.groups, function(g) { - //do not include these tabs - return g.tabState === "init"; - }); - saveModel.groups = _.map(realGroups, function (g) { + return { + + getParams: function () { + var match; + var query = $window.location.search.substring(1); - var saveGroup = _.pick(g, 'inherited', 'id', 'sortOrder', 'name'); + var urlParams = {}; + while (match = search.exec(query)) { + urlParams[decode(match[1])] = decode(match[2]); + } - var realProperties = _.reject(g.properties, function (p) { - //do not include these properties - return p.propertyState === "init" || p.inherited === true; - }); - - var saveProperties = _.map(realProperties, function (p) { - var saveProperty = _.pick(p, 'id', 'alias', 'description', 'validation', 'label', 'sortOrder', 'dataTypeId', 'groupId', 'memberCanEdit', 'showOnMemberProfile'); - return saveProperty; - }); - - saveGroup.properties = saveProperties; - - //if this is an inherited group and there are not non-inherited properties on it, then don't send up the data - if (saveGroup.inherited === true && saveProperties.length === 0) { - return null; - } - - return saveGroup; - }); - - //we don't want any null groups - saveModel.groups = _.reject(saveModel.groups, function(g) { - return !g; - }); - - return saveModel; - }, - - /** formats the display model used to display the data type to the model used to save the data type */ - formatDataTypePostData: function(displayModel, preValues, action) { - var saveModel = { - parentId: displayModel.parentId, - id: displayModel.id, - name: displayModel.name, - selectedEditor: displayModel.selectedEditor, - //set the action on the save model - action: action, - preValues: [] - }; - for (var i = 0; i < preValues.length; i++) { - - saveModel.preValues.push({ - key: preValues[i].alias, - value: preValues[i].value - }); - } - return saveModel; - }, - - /** formats the display model used to display the member to the model used to save the member */ - formatMemberPostData: function(displayModel, action) { - //this is basically the same as for media but we need to explicitly add the username,email, password to the save model - - var saveModel = this.formatMediaPostData(displayModel, action); - - saveModel.key = displayModel.key; - - var genericTab = _.find(displayModel.tabs, function (item) { - return item.id === 0; - }); - - //map the member login, email, password and groups - var propLogin = _.find(genericTab.properties, function (item) { - return item.alias === "_umb_login"; - }); - var propEmail = _.find(genericTab.properties, function (item) { - return item.alias === "_umb_email"; - }); - var propPass = _.find(genericTab.properties, function (item) { - return item.alias === "_umb_password"; - }); - var propGroups = _.find(genericTab.properties, function (item) { - return item.alias === "_umb_membergroup"; - }); - saveModel.email = propEmail.value; - saveModel.username = propLogin.value; - saveModel.password = propPass.value; - - var selectedGroups = []; - for (var n in propGroups.value) { - if (propGroups.value[n] === true) { - selectedGroups.push(n); - } - } - saveModel.memberGroups = selectedGroups; - - //turn the dictionary into an array of pairs - var memberProviderPropAliases = _.pairs(displayModel.fieldConfig); - _.each(displayModel.tabs, function (tab) { - _.each(tab.properties, function (prop) { - var foundAlias = _.find(memberProviderPropAliases, function(item) { - return prop.alias === item[1]; - }); - if (foundAlias) { - //we know the current property matches an alias, now we need to determine which membership provider property it was for - // by looking at the key - switch (foundAlias[0]) { - case "umbracoMemberLockedOut": - saveModel.isLockedOut = prop.value.toString() === "1" ? true : false; - break; - case "umbracoMemberApproved": - saveModel.isApproved = prop.value.toString() === "1" ? true : false; - break; - case "umbracoMemberComments": - saveModel.comments = prop.value; - break; - } - } - }); - }); - - - - return saveModel; - }, - - /** formats the display model used to display the media to the model used to save the media */ - formatMediaPostData: function(displayModel, action) { - //NOTE: the display model inherits from the save model so we can in theory just post up the display model but - // we don't want to post all of the data as it is unecessary. - var saveModel = { - id: displayModel.id, - properties: [], - name: displayModel.name, - contentTypeAlias: displayModel.contentTypeAlias, - parentId: displayModel.parentId, - //set the action on the save model - action: action - }; - - _.each(displayModel.tabs, function (tab) { - - _.each(tab.properties, function (prop) { - - //don't include the custom generic tab properties - if (!prop.alias.startsWith("_umb_")) { - saveModel.properties.push({ - id: prop.id, - alias: prop.alias, - value: prop.value - }); - } - - }); - }); - - return saveModel; - }, - - /** formats the display model used to display the content to the model used to save the content */ - formatContentPostData: function (displayModel, action) { - - //this is basically the same as for media but we need to explicitly add some extra properties - var saveModel = this.formatMediaPostData(displayModel, action); - - var genericTab = _.find(displayModel.tabs, function (item) { - return item.id === 0; - }); - - var propExpireDate = _.find(genericTab.properties, function(item) { - return item.alias === "_umb_expiredate"; - }); - var propReleaseDate = _.find(genericTab.properties, function (item) { - return item.alias === "_umb_releasedate"; - }); - var propTemplate = _.find(genericTab.properties, function (item) { - return item.alias === "_umb_template"; - }); - saveModel.expireDate = propExpireDate.value; - saveModel.releaseDate = propReleaseDate.value; - saveModel.templateAlias = propTemplate.value; - - return saveModel; - } - }; + return urlParams; + } + }; } -angular.module('umbraco.services').factory('umbDataFormatter', umbDataFormatter); +angular.module('umbraco.services').factory('queryStrings', queryStrings); diff --git a/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js index 1504abf7c1..dc39678a2f 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/main.controller.js @@ -54,13 +54,33 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $ $scope.user = null; })); - //when the app is read/user is logged in, setup the data + evts.push(eventsService.on("app.userRefresh", function(evt) { + userService.refreshCurrentUser().then(function(data) { + $scope.user = data; + + //Load locale file + if ($scope.user.locale) { + tmhDynamicLocale.set($scope.user.locale); + } + + if ($scope.user.avatars) { + $scope.avatar = []; + if (angular.isArray($scope.user.avatars)) { + for (var i = 0; i < $scope.user.avatars.length; i++) { + $scope.avatar.push({ value: $scope.user.avatars[i] }); + } + } + } + }); + })); + + //when the app is ready/user is logged in, setup the data evts.push(eventsService.on("app.ready", function (evt, data) { $scope.authenticated = data.authenticated; $scope.user = data.user; - updateChecker.check().then(function(update) { + updateChecker.check().then(function (update) { if (update && update !== "null") { if (update.type !== "None") { var notification = { @@ -87,7 +107,7 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $ } //if this is a new login (i.e. the user entered credentials), then clear out local storage - could contain sensitive data - if (data.loginType === "credentials") { + if (data.loginType === "credentials") { localStorageService.clearAll(); } @@ -96,30 +116,15 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $ tmhDynamicLocale.set($scope.user.locale); } - if ($scope.user.emailHash) { + if ($scope.user.avatars) { - //let's attempt to load the avatar, it might not exist or we might not have - // internet access, well get an empty string back - $http.get(umbRequestHelper.getApiUrl("gravatarApiBaseUrl", "GetCurrentUserGravatarUrl")) - .then( - function successCallback(response) { - // if we can't download the gravatar for some reason, an null gets returned, we cannot do anything - if (response.data !== "null") { - if ($scope.user && $scope.user.emailHash) { - var avatarBaseUrl = "https://www.gravatar.com/avatar/"; - var hash = $scope.user.emailHash; + $scope.avatar = []; + if (angular.isArray($scope.user.avatars)) { + for (var i = 0; i < $scope.user.avatars.length; i++) { + $scope.avatar.push({ value: $scope.user.avatars[i] }); + } + } - $scope.avatar = [ - { value: avatarBaseUrl + hash + ".jpg?s=30&d=mm" }, - { value: avatarBaseUrl + hash + ".jpg?s=60&d=mm" }, - { value: avatarBaseUrl + hash + ".jpg?s=90&d=mm" } - ]; - } - } - - }, function errorCallback(response) { - //cannot load it from the server so we cannot do anything - }); } })); @@ -143,7 +148,7 @@ function MainController($scope, $rootScope, $location, $routeParams, $timeout, $ //register it angular.module('umbraco').controller("Umbraco.MainController", MainController). - config(function (tmhDynamicLocaleProvider) { - //Set url for locale files - tmhDynamicLocaleProvider.localeLocationPattern('lib/angular/1.1.5/i18n/angular-locale_{{locale}}.js'); - }); + config(function (tmhDynamicLocaleProvider) { + //Set url for locale files + tmhDynamicLocaleProvider.localeLocationPattern('lib/angular/1.1.5/i18n/angular-locale_{{locale}}.js'); + }); diff --git a/src/Umbraco.Web.UI.Client/src/controllers/search.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/search.controller.js index 54519f353b..57ddb6babd 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/search.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/search.controller.js @@ -15,21 +15,21 @@ function SearchController($scope, searchService, $log, $location, navigationServ $scope.selectedResult = -1; - $scope.navigateResults = function(ev){ + $scope.navigateResults = function (ev) { //38: up 40: down, 13: enter - switch(ev.keyCode){ + switch (ev.keyCode) { case 38: - iterateResults(true); + iterateResults(true); break; case 40: - iterateResults(false); + iterateResults(false); break; case 13: if ($scope.selectedItem) { $location.path($scope.selectedItem.editorPath); navigationService.hideSearch(); - } + } break; } }; @@ -39,50 +39,50 @@ function SearchController($scope, searchService, $log, $location, navigationServ var groupIndex = -1; var itemIndex = -1; $scope.selectedItem = undefined; - - function iterateResults(up){ + + function iterateResults(up) { //default group - if(!group){ + if (!group) { group = $scope.groups[0]; groupIndex = 0; } - if(up){ - if(itemIndex === 0){ - if(groupIndex === 0){ - gotoGroup($scope.groups.length-1, true); - }else{ - gotoGroup(groupIndex-1, true); + if (up) { + if (itemIndex === 0) { + if (groupIndex === 0) { + gotoGroup($scope.groups.length - 1, true); + } else { + gotoGroup(groupIndex - 1, true); } - }else{ - gotoItem(itemIndex-1); + } else { + gotoItem(itemIndex - 1); } - }else{ - if(itemIndex < group.results.length-1){ - gotoItem(itemIndex+1); - }else{ - if(groupIndex === $scope.groups.length-1){ + } else { + if (itemIndex < group.results.length - 1) { + gotoItem(itemIndex + 1); + } else { + if (groupIndex === $scope.groups.length - 1) { gotoGroup(0); - }else{ - gotoGroup(groupIndex+1); + } else { + gotoGroup(groupIndex + 1); } } } } - function gotoGroup(index, up){ + function gotoGroup(index, up) { groupIndex = index; group = $scope.groups[groupIndex]; - - if(up){ - gotoItem(group.results.length-1); - }else{ - gotoItem(0); + + if (up) { + gotoItem(group.results.length - 1); + } else { + gotoItem(0); } } - function gotoItem(index){ + function gotoItem(index) { itemIndex = index; $scope.selectedItem = group.results[itemIndex]; } @@ -91,7 +91,8 @@ function SearchController($scope, searchService, $log, $location, navigationServ var canceler = null; $scope.$watch("searchTerm", _.debounce(function (newVal, oldVal) { - $scope.$apply(function() { + $scope.$apply(function () { + $scope.hasResults = false; if ($scope.searchTerm) { if (newVal !== null && newVal !== undefined && newVal !== oldVal) { $scope.isSearching = true; @@ -107,10 +108,21 @@ function SearchController($scope, searchService, $log, $location, navigationServ canceler = $q.defer(); } - searchService.searchAll({ term: $scope.searchTerm, canceler: canceler }).then(function(result) { - $scope.groups = _.filter(result, function (group) { return group.results.length > 0; }); + searchService.searchAll({ term: $scope.searchTerm, canceler: canceler }).then(function (result) { + + //result is a dictionary of group Title and it's results + var filtered = {}; + _.each(result, function (value, key) { + if (value.results.length > 0) { + filtered[key] = value; + } + }); + $scope.groups = filtered; + // check if search has results + $scope.hasResults = Object.keys($scope.groups).length > 0; //set back to null so it can be re-created canceler = null; + $scope.isSearching = false; }); } } diff --git a/src/Umbraco.Web.UI.Client/src/init.js b/src/Umbraco.Web.UI.Client/src/init.js index 016c33015d..5c70ca6a90 100644 --- a/src/Umbraco.Web.UI.Client/src/init.js +++ b/src/Umbraco.Web.UI.Client/src/init.js @@ -1,13 +1,16 @@ /** Executed when the application starts, binds to events and set global state */ -app.run(['userService', '$log', '$rootScope', '$location', 'navigationService', 'appState', 'editorState', 'fileManager', 'assetsService', 'eventsService', '$cookies', '$templateCache', 'localStorageService', - function (userService, $log, $rootScope, $location, navigationService, appState, editorState, fileManager, assetsService, eventsService, $cookies, $templateCache, localStorageService) { +app.run(['userService', '$log', '$rootScope', '$location', 'queryStrings', 'navigationService', 'appState', 'editorState', 'fileManager', 'assetsService', 'eventsService', '$cookies', '$templateCache', 'localStorageService', + function (userService, $log, $rootScope, $location, queryStrings, navigationService, appState, editorState, fileManager, assetsService, eventsService, $cookies, $templateCache, localStorageService) { //This sets the default jquery ajax headers to include our csrf token, we // need to user the beforeSend method because our token changes per user/login so // it cannot be static $.ajaxSetup({ beforeSend: function (xhr) { - xhr.setRequestHeader("X-XSRF-TOKEN", $cookies["XSRF-TOKEN"]); + xhr.setRequestHeader("X-XSRF-TOKEN", $cookies["XSRF-TOKEN"]); + if (queryStrings.getParams().umbDebug === "true" || queryStrings.getParams().umbdebug === "true") { + xhr.setRequestHeader("X-UMB-DEBUG", "true"); + } } }); diff --git a/src/Umbraco.Web.UI.Client/src/install.loader.js b/src/Umbraco.Web.UI.Client/src/install.loader.js index 869521ec7d..ead413ed3e 100644 --- a/src/Umbraco.Web.UI.Client/src/install.loader.js +++ b/src/Umbraco.Web.UI.Client/src/install.loader.js @@ -1,17 +1,19 @@ -LazyLoad.js( [ - 'lib/jquery/jquery.min.js', - /* 1.1.5 */ - 'lib/angular/1.1.5/angular.min.js', - 'lib/angular/1.1.5/angular-cookies.min.js', - 'lib/angular/1.1.5/angular-mobile.min.js', - 'lib/angular/1.1.5/angular-mocks.js', - 'lib/angular/1.1.5/angular-sanitize.min.js', - 'lib/underscore/underscore-min.js', - 'js/umbraco.installer.js', - 'js/umbraco.directives.js' - ], function () { - jQuery(document).ready(function () { - angular.bootstrap(document, ['ngSanitize', 'umbraco.install', 'umbraco.directives.validation']); - }); - } +LazyLoad.js([ + 'lib/jquery/jquery.min.js', + /* 1.1.5 */ + 'lib/angular/1.1.5/angular.min.js', + 'lib/angular/1.1.5/angular-cookies.min.js', + 'lib/angular/1.1.5/angular-mobile.min.js', + 'lib/angular/1.1.5/angular-mocks.js', + 'lib/angular/1.1.5/angular-sanitize.min.js', + 'lib/underscore/underscore-min.js', + 'lib/angular/angular-ui-sortable.js', + 'js/installer.app.js', + 'js/umbraco.directives.js', + 'js/umbraco.installer.js' +], function () { + jQuery(document).ready(function () { + angular.bootstrap(document, ['umbraco']); + }); +} ); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/installer.app.js b/src/Umbraco.Web.UI.Client/src/installer.app.js new file mode 100644 index 0000000000..05315493b7 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/installer.app.js @@ -0,0 +1,7 @@ +var app = angular.module('umbraco', [ + 'umbraco.directives', + 'umbraco.install', + 'ngCookies', + 'ngMobile', + 'ngSanitize' +]); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/installer/_module.js b/src/Umbraco.Web.UI.Client/src/installer/_module.js new file mode 100644 index 0000000000..03ba93c846 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/installer/_module.js @@ -0,0 +1 @@ +angular.module("umbraco.install", ["umbraco.directives"]); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js index 5cb8e6230f..54b4733529 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/installer.service.js +++ b/src/Umbraco.Web.UI.Client/src/installer/installer.service.js @@ -17,11 +17,11 @@ angular.module("umbraco.install").factory('installerService', function($rootScop //add to umbraco installer facts here var facts = ['Umbraco helped millions of people watch a man jump from the edge of space', - 'Over 370 000 websites are currently powered by Umbraco', + 'Over 420 000 websites are currently powered by Umbraco', "At least 2 people have named their cat 'Umbraco'", 'On an average day, more than 1000 people download Umbraco', - 'umbraco.tv is the premier source of Umbraco video tutorials to get you started', - 'You can find the world\'s friendliest CMS community at our.umbraco.org', + 'umbraco.tv is the premier source of Umbraco video tutorials to get you started', + 'You can find the world\'s friendliest CMS community at our.umbraco.org', 'You can become a certified Umbraco developer by attending one of the official courses', 'Umbraco works really well on tablets', 'You have 100% control over your markup and design when crafting a website in Umbraco', @@ -31,7 +31,7 @@ angular.module("umbraco.install").factory('installerService', function($rootScop "At least 4 people have the Umbraco logo tattooed on them", "'Umbraco' is the danish name for an allen key", "Umbraco has been around since 2005, that's a looong time in IT", - "More than 400 people from all over the world meet each year in Denmark in June for our annual conference CodeGarden", + "More than 550 people from all over the world meet each year in Denmark in June for our annual conference CodeGarden", "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 was installed in more than 165 countries in 2015" diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/database.controller.js b/src/Umbraco.Web.UI.Client/src/installer/steps/database.controller.js index 5b3e174930..c4ac65bff1 100644 --- a/src/Umbraco.Web.UI.Client/src/installer/steps/database.controller.js +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/database.controller.js @@ -1,28 +1,35 @@ angular.module("umbraco.install").controller("Umbraco.Installer.DataBaseController", function($scope, $http, installerService){ $scope.checking = false; + $scope.invalidDbDns = false; + $scope.dbs = [ - {name: 'Microsoft SQL Server Compact (SQL CE)', id: 0}, - {name: 'Microsoft SQL Server', id: 1}, - { name: 'Microsoft SQL Azure', id: 3 }, - { name: 'MySQL', id: 2 }, - {name: 'Custom connection string', id: -1}]; + { name: 'Microsoft SQL Server Compact (SQL CE)', id: 0}, + { name: 'Microsoft SQL Server', id: 1}, + { name: 'Microsoft SQL Azure', id: 3 }, + { name: 'MySQL', id: 2 }, + { name: 'Custom connection string', id: -1} + ]; - if(installerService.status.current.model.dbType === undefined){ + if ( installerService.status.current.model.dbType === undefined ) { installerService.status.current.model.dbType = 0; } - $scope.validateAndForward = function(){ - if(!$scope.checking && this.myForm.$valid){ + $scope.validateAndForward = function(){ + if ( !$scope.checking && this.myForm.$valid ) { $scope.checking = true; + $scope.invalidDbDns = false; + var model = installerService.status.current.model; - $http.post(Umbraco.Sys.ServerVariables.installApiBaseUrl + "PostValidateDatabaseConnection", - model).then(function(response){ + $http.post( + Umbraco.Sys.ServerVariables.installApiBaseUrl + "PostValidateDatabaseConnection", + model ).then( function( response ) { - if(response.data === "true"){ + if ( response.data === "true" ) { installerService.forward(); - }else{ + } + else { $scope.invalidDbDns = true; } @@ -33,4 +40,4 @@ angular.module("umbraco.install").controller("Umbraco.Installer.DataBaseControll }); } }; -}); \ No newline at end of file +}); diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.controller.js b/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.controller.js new file mode 100644 index 0000000000..bdcef63d95 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.controller.js @@ -0,0 +1,14 @@ +angular.module("umbraco.install").controller("Umbraco.Installer.MachineKeyController", function ($scope, installerService) { + + + $scope.continue = function () { + installerService.status.current.model = true; + installerService.forward(); + }; + + $scope.ignoreKey = function () { + installerService.status.current.model = false; + installerService.forward(); + }; + +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.html b/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.html new file mode 100644 index 0000000000..732c7c1d56 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/installer/steps/machinekey.html @@ -0,0 +1,23 @@ +
+

Configure an ASP.Net Machine Key

+

+ By default the installer will generate a custom ASP.Net Machine Key for your site and install it into your web.config file. + A Machine Key is used for hashing and encryption and it is recommended that you install a custom one into your site. + This ensures that your site is fully portable between environments that might have different Machine Key settings and that + your site by default will work with load balancing when installed between various server environments. +

+ +
+ +
+
+
+ + + +
+
+
+ +
+
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index cfe82ff3ea..44365b95e7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -120,17 +120,34 @@ @import "components/umb-querybuilder.less"; @import "components/umb-pagination.less"; @import "components/umb-mini-list-view.less"; +@import "components/umb-badge.less"; +@import "components/umb-nested-content.less"; +@import "components/umb-checkmark.less"; +@import "components/umb-list.less"; +@import "components/umb-box.less"; @import "components/buttons/umb-button.less"; @import "components/buttons/umb-button-group.less"; @import "components/buttons/umb-era-button.less"; +@import "components/buttons/umb-toggle.less"; @import "components/notifications/umb-notifications.less"; @import "components/umb-file-dropzone.less"; @import "components/umb-node-preview.less"; @import "components/umb-mini-editor.less"; +@import "components/users/umb-user-cards.less"; +@import "components/users/umb-user-group-picker-list.less"; +@import "components/users/umb-user-group-preview.less"; +@import "components/users/umb-user-preview.less"; +@import "components/users/umb-user-picker-list.less"; +@import "components/users/umb-permission.less"; + + // Utilities +@import "utilities/layout/_display.less"; +@import "utilities/typography/_text-decoration.less"; +@import "utilities/typography/_white-space.less"; @import "utilities/_flexbox.less"; @import "utilities/_spacing.less"; @import "utilities/_text-align.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less index afe050e211..82e3afbb83 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-button.less @@ -18,10 +18,13 @@ transition: opacity 0.25s ease; display: flex; flex-wrap: wrap; + align-items: center; + justify-content: center; } .umb-button__icon { margin-right: 5px; + line-height: 1em; } .umb-button__content.-hidden { @@ -52,7 +55,7 @@ .umb-button__progress.-white { border-color: rgba(255, 255, 255, 0.4); - border-left-color: #ffffff; + border-left-color: @white; } .umb-button__success, @@ -64,18 +67,9 @@ transform: translate(-50%, -50%); opacity: 1; font-size: 20px; - color: @green; transition: opacity 0.25s ease; } -.umb-button__success { - color: @green; -} - -.umb-button__error { - color: @red; -} - .umb-button__success.-hidden, .umb-button__error.-hidden { opacity: 0; @@ -84,7 +78,7 @@ .umb-button__success.-white, .umb-button__error.-white { - color: #ffffff; + color: @white; } .umb-button__overlay { @@ -92,7 +86,7 @@ width: 100%; height: 100%; z-index: 10; - background: #ffffff; + background: @white; opacity: 0; } @@ -104,3 +98,35 @@ transform: rotate(360deg); } } + +/* Sizes */ +.umb-button--xs { + padding: 5px 16px; + font-size: 14px; +} + +.umb-button--s { + padding: 6px 16px; + font-size: 15px; +} + +.umb-button--m { + padding: 10px 24px; + font-size: 15px; +} + +.umb-button--l { + padding: 14px 40px; + font-size: 16px; +} + +.umb-button--xl { + padding: 18px 52px; + font-size: 16px; +} + +/* types */ +.umb-button--block { + display: block; + width: 100%; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less new file mode 100644 index 0000000000..2156f75d00 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/buttons/umb-toggle.less @@ -0,0 +1,65 @@ +.umb-toggle { + display: flex; + align-items: center; +} + +.umb-toggle__handler { + display: inline-block; + width: 24px; + height: 24px; + background-color: @white; + border-radius: 50px; + transform: rotate(-45deg); +} + +.umb-toggle__toggle { + cursor: pointer; + display: inline-block; + width: 48px; + height: 24px; + background: @gray-8; + border-radius: 90px; + position: relative; +} + +.umb-toggle--checked .umb-toggle__toggle { + background-color: @green; +} + +.umb-toggle--checked .umb-toggle__handler { + transform: translate3d(24px, 0, 0) rotate(0); +} + +/* Labels */ + +.umb-toggle__label { + font-size: 12px; + color: @gray-2; +} + +.umb-toggle__label--left { + margin-right: 8px; +} + +.umb-toggle__label--right { + margin-left: 8px; +} + +/* Icons */ + +.umb-toggle__icon { + position: absolute; + top: 3px; + text-decoration: none; + transition: all 0.2s ease; +} + +.umb-toggle__icon--left { + left: 7px; + color: @white; +} + +.umb-toggle__icon--right { + right: 7px; + color: @gray-5; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-avatar.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-avatar.less index c4414c2880..2807c2d427 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-avatar.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-avatar.less @@ -2,29 +2,115 @@ border-radius: 50%; width: 50px; height: 50px; + background-color: transparent; + display: flex; + align-items: center; + justify-content: center; + color: @black; + font-weight: bold; + font-size: 16px; + box-sizing: border-box; } -.umb-avatar.-xs { +/* Sizes */ + +.umb-avatar--xxs { + width: 26px; + height: 26px; + font-size: 12px; +} + +.umb-avatar--xs { width: 30px; height: 30px; + font-size: 12px; } -.umb-avatar.-s { +.umb-avatar--s { width: 40px; height: 40px; + font-size: 14px; } -.umb-avatar.-m { +.umb-avatar--m { width: 50px; height: 50px; + font-size: 16px; } -.umb-avatar.-l { +.umb-avatar--l { width: 70px; height: 70px; + font-size: 18px; } -.umb-avatar.-xl { +.umb-avatar--xl { width: 100px; height: 100px; + font-size: 20px; } + +.umb-avatar--xxl { + width: 150px; + height: 150px; + font-size: 36px; +} + +/* Colors */ + +.umb-avatar--white { + background-color: @white; + color: @black; +} + +.umb-avatar--gray { + background-color: @gray-10; + color: @black; +} + +.umb-avatar--primary { + background-color: @turquoise-l1; + color: @white; +} + +.umb-avatar--secondary { + background-color: @purple-l3; + color: @white; +} + +.umb-avatar--success { + background-color: @green-l1; + color: @white; +} + +.umb-avatar--warning { + background-color: @yellow-l1; + color: @white; +} + +.umb-avatar--danger { + background-color: @red-l1; + color: @white; +} + +/*with button*/ + +a.umb-avatar-btn { + cursor: pointer; +} +a.umb-avatar-btn:hover { + text-decoration: none; +} +a.umb-avatar-btn .umb-avatar { + border: 2px dashed #A2A1A6; +} +a.umb-avatar-btn .umb-avatar span { + font-size: 50px; + color: @gray-6; +} +a.umb-avatar-btn .umb-avatar span { + color: @gray-6; + font-size: 50px; +} + +/*border-radius: 50%; width: 100px; height: 100px; font-size: 50px; text-align: center; display: flex; align-items: center; justify-content: center; background-color: #F3F3F5; border: 2px dashed #A2A1A6; color: #A2A1A6;*/ \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less new file mode 100644 index 0000000000..6998afa556 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-badge.less @@ -0,0 +1,65 @@ +.umb-badge { + padding: 6px 8px; + margin: 0 5px 0 0; + color: @black; + background-color: @turquoise-washed; + border-width: 1px; + border-style: solid; + border-color: @turquoise; + display: inline-flex; + align-items: center; + justify-content: center; + text-transform: capitalize; +} + +// Colors +.umb-badge--primary { + background-color: @turquoise-washed; + border-color: @turquoise; +} + +.umb-badge--seconday { + background-color: @purple-washed; + border-color: @purple; +} + +.umb-badge--danger { + background-color: @red-washed; + border-color: @red; +} + +.umb-badge--warning { + background-color: @yellow-washed; + border-color: @yellow; +} + +.umb-badge--success { + background-color: @green-washed; + border-color: @green; +} + +// Size +.umb-badge--xs { + font-size: 13px; + padding: 1px 6px; +} + +.umb-badge--s { + font-size: 14px; + padding: 3px 6px; +} + +.umb-badge--m { + font-size: 16px; + padding: 6px 8px; +} + +.umb-badge--l { + font-size: 18px; + padding: 6px 8px; +} + +.umb-badge--xl { + font-size: 20px; + padding: 6px 8px; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-box.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-box.less new file mode 100644 index 0000000000..cfbd929a3a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-box.less @@ -0,0 +1,20 @@ +.umb-box { + border: 1px solid @gray-8; + border-radius: 3px; + margin-bottom: 30px; +} + +.umb-box-header { + padding: 10px 20px; + background-color: @gray-10; +} + +.umb-box-header-title { + font-size: 16px; + color: @black; + font-weight: bold; +} + +.umb-box-content { + padding: 20px; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less index 2cad03a2ab..d25744a108 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less @@ -12,7 +12,7 @@ .umb-breadcrumbs__ancestor-link, .umb-breadcrumbs__ancestor-text { - font-size: 12px; + font-size: 13px; color: @gray-3; max-width: 150px; white-space: nowrap; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-checkmark.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-checkmark.less new file mode 100644 index 0000000000..75ac13bdd0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-checkmark.less @@ -0,0 +1,46 @@ +.umb-checkmark { + border: 2px solid @white; + width: 25px; + height: 25px; + background: @gray-7; + border-radius: 50%; + box-sizing: border-box; + display: flex; + justify-content: center; + align-items: center; + color: @white; + cursor: pointer; + font-size: 15px; +} + +.umb-checkmark--checked { + background: @green; +} + +.umb-checkmark--xs { + width: 20px; + height: 20px; + font-size: 13px; +} + +.umb-checkmark--s { + width: 25px; + height: 25px; +} + +.umb-checkmark--m { + width: 30px; + height: 30px; +} + +.umb-checkmark--l { + width: 40px; + height: 40px; + font-size: 18px; +} + +.umb-checkmark--xl { + width: 50px; + height: 50px; + font-size: 20px; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less new file mode 100644 index 0000000000..be63bb3a9c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-list.less @@ -0,0 +1,25 @@ +.umb-list-item { + border-bottom: 1px solid @gray-9; + padding-top: 15px; + padding-bottom: 15px; + display: flex; +} + +a.umb-list-item:hover, +a.umb-list-item:focus { + text-decoration: none; +} + +.umb-list-item:hover .umb-list-checkbox, +.umb-list-item--selected .umb-list-checkbox { + opacity: 1; +} + +.umb-list-checkbox { + position: absolute; + opacity: 0; +} + +.umb-list-checkbox--visible { + opacity: 1; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less new file mode 100644 index 0000000000..4f24fcf504 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-nested-content.less @@ -0,0 +1,208 @@ +.nested-content +{ + text-align: center; +} + +.nested-content--not-supported +{ + opacity: 0.3; + pointer-events: none; +} + +.nested-content-overlay +{ + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; +} + +.nested-content__item +{ + position: relative; + text-align: left; + border-top: solid 1px transparent; + background: white; + + +} + +.nested-content__item--active:not(.nested-content__item--single) +{ + background: #f8f8f8; +} + +.nested-content__item.ui-sortable-placeholder +{ + background: #f8f8f8; + border: 1px dashed #d9d9d9; + visibility: visible !important; + height: 55px; + margin-top: -1px; +} + +.nested-content__item--single > .nested-content__content +{ + border: 0; +} + +.nested-content__item--single > .nested-content__content > .umb-pane +{ + margin: 0; +} + +.nested-content__header-bar +{ + padding: 15px 20px; + border-bottom: 1px dashed #e0e0e0; + text-align: right; + cursor: pointer; + background-color: white; + + -moz-user-select: none; + -khtml-user-select: none; + -webkit-user-select: none; + -o-user-select: none; +} + +.nested-content__heading +{ + float: left; + line-height: 20px; +} + +.nested-content__heading i +{ + vertical-align: text-top; + color: #999; /* same icon color as the icons in the item type picker */ + margin-right: 10px; +} + +.nested-content__icons +{ + margin: -6px 0; + opacity: 0; + + transition: opacity .15s ease-in-out; + -moz-transition: opacity .15s ease-in-out; + -webkit-transition: opacity .15s ease-in-out; +} + +.nested-content__header-bar:hover .nested-content__icons, +.nested-content__item--active > .nested-content__header-bar .nested-content__icons +{ + opacity: 1; +} + +.nested-content__icon, +.nested-content__icon.nested-content__icon--disabled:hover +{ + display: inline-block; + padding: 4px 6px; + margin: 2px; + cursor: pointer; + background: #fff; + border: 1px solid #b6b6b6; + border-radius: 200px; + text-decoration: none !important; +} + +.nested-content__icon:hover, +.nested-content__icon--active +{ + color: white; + background: #2e8aea; + border-color: #2e8aea; + text-decoration: none; +} + +.nested-content__icon .icon, +.nested-content__icon.nested-content__icon--disabled:hover .icon +{ + display: block; + font-size: 16px !important; + color: #5f5f5f; +} + +.nested-content__icon:hover .icon, +.nested-content__icon--active .icon +{ + color: white; +} + +.nested-content__icon--disabled +{ + opacity: 0.3; +} + + +.nested-content__footer-bar +{ + text-align: center; + padding-top: 20px; +} + +.nested-content__content +{ + border-bottom: 1px dashed #e0e0e0; +} + +.nested-content__content .umb-control-group { + padding-bottom: 0; +} + +.nested-content__item.ui-sortable-helper .nested-content__content +{ + display: none !important; +} + +.nested-content__help-text +{ + display: inline-block; + padding: 10px 20px 10px 20px; + clear: both; + font-size: 14px; + color: #555; + background: #f8f8f8; + border-radius: 15px; +} + +.nested-content__doctypepicker table input, .nested-content__doctypepicker table select { + width: 100%; + padding-right: 0; +} + +.nested-content__doctypepicker table td.icon-navigation, .nested-content__doctypepicker i.nested-content__help-icon { + vertical-align: middle; + color: #CCC; +} + +.nested-content__doctypepicker table td.icon-navigation:hover, .nested-content__doctypepicker i.nested-content__help-icon:hover { + color: #343434; +} + +.nested-content__doctypepicker i.nested-content__help-icon { + margin-left: 10px; +} + +.form-horizontal .nested-content--narrow .controls-row +{ + margin-left: 40% !important; +} + +.form-horizontal .nested-content--narrow .controls-row .umb-textstring, +.form-horizontal .nested-content--narrow .controls-row .umb-textarea +{ + width: 95%; +} + +.form-horizontal .nested-content--narrow .controls-row .umb-dropdown { + width: 99%; +} + +.usky-grid.nested-content__node-type-picker .cell-tools-menu { + position: relative; + transform: translate(-50%, -25%); +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less index f0c5ed143f..65d34ba693 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-node-preview.less @@ -1,12 +1,14 @@ .umb-node-preview { - padding: 5px 15px; - margin-bottom: 5px; - background: @gray-10; - border-radius: 3px; + padding: 7px 0; display: flex; - align-items: center; max-width: 66.6%; box-sizing: border-box; + border-bottom: 1px solid @gray-9; +} + +.umb-node-preview:last-of-type { + border-bottom: none; + margin-bottom: 7px; } .umb-node-preview--sortable { @@ -34,12 +36,12 @@ .umb-node-preview__content { flex: 1 1 auto; + margin-right: 25px; } .umb-node-preview__name { - font-size: 13px; - font-weight: bold; color: @black; + margin-top: 3px; } .umb-node-preview__description { @@ -76,7 +78,7 @@ display: flex; align-items: center; justify-content: center; - border: 1px dashed @gray-8; + border: 1px dashed @gray-7; color: @turquoise-d1; font-weight: bold; padding: 5px 15px; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less index e053d58a7f..9f9d288f09 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-packages.less @@ -328,8 +328,8 @@ a.umb-package-details__back-link { .umb-package-details__main-content { flex: 1 1 auto; - margin-right: 40px; - width: ~"(calc(~'100%' - ~'@{sidebarwidth}' - ~'40px'))"; // Make sure that the main content area doesn't gets affected by inline styling + margin-right: 30px; + width: ~"(calc(~'100%' - ~'@{sidebarwidth}' - ~'30px'))"; // Make sure that the main content area doesn't gets affected by inline styling } .umb-package-details__sidebar { @@ -360,6 +360,7 @@ a.umb-package-details__back-link { padding: 20px; margin-bottom: 20px; border-radius: 3px; + border: 1px solid @gray-8; } .umb-package-details__section-title { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-progress-bar.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-progress-bar.less index e4889446e8..8c15084d55 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-progress-bar.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-progress-bar.less @@ -18,3 +18,13 @@ width: 100%; border-radius: 10px; } + +.umb-progress-bar--s { + height: 5px; + border-radius: 5px; +} + +.umb-progress-bar--m { + height: 10px; + border-radius: 10px; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-permission.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-permission.less new file mode 100644 index 0000000000..faed098fc8 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-permission.less @@ -0,0 +1,26 @@ +.umb-permission { + display: flex; + border-bottom: 1px solid @gray-9; + padding: 7px 0; +} + +.umb-permission:last-of-type { + border-bottom: none; +} + +.umb-permission__toggle { + padding-right: 20px; + cursor: pointer; +} + +.umb-permission__content { + display: flex; + flex-direction: column; + flex: 1 1 auto; + cursor: pointer; +} + +.umb-permission__description { + font-size: 13px; + color: @gray-5; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-cards.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-cards.less new file mode 100644 index 0000000000..40a85bec71 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-cards.less @@ -0,0 +1,126 @@ +.umb-user-cards { + display: flex; + flex-direction: row; + flex-wrap: wrap; + margin: -10px; +} + +.umb-user-card { + padding: 10px; + box-sizing: border-box; + flex: 0 0 100%; + max-width: 100%; + display: flex; +} + +.umb-user-card:hover, +.umb-user-card:focus { + outline: none; + text-decoration: none !important; +} + +@media (min-width: 768px) { + .umb-user-card { + flex: 0 0 50%; + max-width: 50%; + } +} + +@media (min-width: 1200px) { + .umb-user-card { + flex: 0 0 33.33%; + max-width: 33.33%; + } +} + +@media (min-width: 1400px) { + .umb-user-card { + flex: 0 0 25%; + max-width: 25%; + } +} + +@media (min-width: 1700px) { + .umb-user-card { + flex: 0 0 20%; + max-width: 20%; + } +} + + +@media (min-width: 1900px) { + .umb-user-card { + flex: 0 0 16.66%; + max-width: 16.66%; + } +} + +@media (min-width: 2200px) { + .umb-user-card { + flex: 0 0 14.28%; + max-width: 14.28%; + } +} + +.umb-user-card__content { + position: relative; + padding: 15px; + flex: 1 1 auto; + background-color: @gray-10; + border: 1px solid @gray-9; + border-radius: 3px; + box-sizing: border-box; + display: flex; + flex-direction: column; + cursor: pointer; + max-width: 100%; +} + +.umb-user-card__content:hover, +.umb-user-card:focus .umb-user-card__content { + border-color: @turquoise; +} + +.umb-user-card__avatar { + margin-bottom: 10px; + margin-left: auto; + margin-right: auto; +} + +.umb-user-card__badge { + position: absolute; + top: 10px; + left: 10px; +} + +.umb-user-card__name { + font-size: 15px; + font-weight: bold; + text-align: center; + margin-bottom: 2px; + word-wrap: break-word; +} + +.umb-user-card__checkmark { + position: absolute; + top: 10px; + right: 10px; + display: none; +} + +.umb-user-card:hover .umb-user-card__checkmark, +.umb-user-card__checkmark--visible { + display: block; +} + +.umb-user-card__group { + font-size: 14px; + text-align: center; + margin-bottom: 15px; +} + +.umb-user-card__last-login { + font-size: 13px; + text-align: center; + margin-top: auto; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-group-picker-list.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-group-picker-list.less new file mode 100644 index 0000000000..dff78ce627 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-group-picker-list.less @@ -0,0 +1,38 @@ +.umb-user-group-picker-list { + display: flex; + flex-direction: column; +} + +.umb-user-group-picker-list-item { + display: flex; + margin-bottom: 5px; + padding: 10px; +} + +.umb-user-group-picker-list-item:active, +.umb-user-group-picker-list-item:focus { + text-decoration: none; +} + +.umb-user-group-picker-list-item:hover { + background-color: @gray-10; + text-decoration: none; +} + +.umb-user-group-picker-list-item__icon { + font-size: 20px; + line-height: 20px; + min-width: 20px; + margin-right: 15px; +} + +.umb-user-group-picker-list-item__name { + font-size: 15px; + margin-bottom: 3px; + font-weight: bold; +} + +.umb-user-group-picker-list-item__permission { + font-size: 13px; + color: @gray-4; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-group-preview.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-group-preview.less new file mode 100644 index 0000000000..f39096b565 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-group-preview.less @@ -0,0 +1,64 @@ +.umb-user-group-preview { + padding-top: 10px; + padding-bottom: 10px; + display: flex; + box-sizing: border-box; + border-bottom: 1px solid @gray-9; +} + +.umb-user-group-preview:last-of-type { + border-bottom: none; + margin-bottom: 10px; +} + +.umb-user-group-preview__icon { + display: flex; + width: 25px; + height: 25px; + justify-content: center; + align-items: center; + font-size: 20px; + margin-right: 10px; + flex: 0 0 auto; +} + +.umb-user-group-preview__content { + flex: 1 1 auto; + margin-right: 25px; +} + +.umb-user-group-preview__name { + font-size: 15px; + color: @black; + margin-bottom: 3px; + margin-top: 2px; +} + +.umb-user-group-preview__permission { + font-size: 13px; + color: @gray-3; +} + +.umb-user-group-preview__actions { + flex: 0 0 auto; + display: flex; + align-items: center; +} + +.umb-user-group-preview__action { + margin-left: 5px; + margin-right: 5px; + font-size: 13px; + font-weight: bold; + color: @gray-5; +} + +.umb-user-group-preview__action:hover { + color: @turquoise; + text-decoration: none; + opacity: 1; +} + +.umb-user-group-preview__action--red:hover { + color: @red; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-picker-list.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-picker-list.less new file mode 100644 index 0000000000..2e0d79e803 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-picker-list.less @@ -0,0 +1,42 @@ +.umb-user-picker-list { + display: flex; + flex-direction: column; +} + +.umb-user-picker-list-item { + display: flex; + margin-bottom: 5px; + padding: 10px; + align-items: center; +} + +.umb-user-picker-list-item:active, +.umb-user-picker-list-item:focus { + text-decoration: none; +} + +.umb-user-picker-list-item:hover { + background-color: @gray-10; + text-decoration: none; +} + +.umb-user-picker-list-item__avatar { + margin-right: 15px; + position: relative; +} + +.umb-user-picker-list-item__checkmark { + position: absolute; + bottom: -3px; + right: -3px; +} + +.umb-user-picker-list-item__group { + font-size: 14px; + color: @gray-5; +} + +.umb-user-picker-list-item__name { + font-size: 15px; + font-weight: bold; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less new file mode 100644 index 0000000000..f62f3afd37 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/users/umb-user-preview.less @@ -0,0 +1,50 @@ +.umb-user-preview { + padding-top: 7px; + padding-bottom: 7px; + display: flex; + box-sizing: border-box; + border-bottom: 1px solid @gray-9; +} + +.umb-user-preview:last-of-type { + border-bottom: none; + margin-bottom: 7px; +} + +.umb-user-preview__avatar { + margin-right: 10px; +} + +.umb-user-preview__content { + flex: 1 1 auto; +} + +.umb-user-preview__name { + color: @black; + margin-bottom: 3px; + margin-top: 2px; +} + +.umb-user-preview__actions { + flex: 0 0 auto; + display: flex; + align-items: center; +} + +.umb-user-preview__action { + margin-left: 5px; + margin-right: 5px; + font-size: 13px; + font-weight: bold; + color: @gray-5; +} + +.umb-user-preview__action:hover { + color: @turquoise; + text-decoration: none; + opacity: 1; +} + +.umb-user-preview__action--red:hover { + color: @red; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/forms.less b/src/Umbraco.Web.UI.Client/src/less/forms.less index 869d0b7740..b0557954e6 100644 --- a/src/Umbraco.Web.UI.Client/src/less/forms.less +++ b/src/Umbraco.Web.UI.Client/src/less/forms.less @@ -66,8 +66,9 @@ label.control-label, .control-label { } .form-search .icon, .form-search .icon-search { position: absolute; + z-index: 1; top: 6px; - left: 4px; + left: 6px; color: @gray-8; } @@ -86,6 +87,9 @@ label.control-label, .control-label { background: @white } +.form-search .icon-search + .search-input { + padding-left: 25px !important; +} .form-search .search-input { font-weight: bold; @@ -191,7 +195,7 @@ input[type="tel"], input[type="color"], .uneditable-input { display: inline-block; - height: 30px; + height: @inputHeight; padding: 4px 6px; margin-bottom: @baseLineHeight / 2; font-size: @baseFontSize; @@ -206,7 +210,6 @@ input.-full-width-input { width: 100%; box-sizing: border-box; padding: 4px 6px; - height: 30px; } // Reset appearance properties for textual inputs and textarea @@ -579,9 +582,9 @@ input[type="checkbox"][readonly] { .add-on { display: inline-block; width: auto; - height: @baseLineHeight; - min-width: 16px; - padding: 4px 5px; + height: 22px; + min-width: 18px; + padding: 4px 6px; font-size: @baseFontSize; font-weight: normal; line-height: @baseLineHeight; @@ -653,29 +656,21 @@ input.search-query { padding-left: 14px; padding-left: 4px \9; /* IE7-8 doesn't have border-radius, so don't indent the padding */ margin: 0; // Remove the default margin on all inputs - .border-radius(0px); } /* Allow for input prepend/append in search forms */ -.form-search .input-append .search-query, -.form-search .input-prepend .search-query { - .border-radius(0); // Override due to specificity +.form-search { + .input-prepend { + .btn { + .border-radius(0 @borderRadiusSmall @borderRadiusSmall 0); + } + } + .input-append { + .btn { + .border-radius(0 @borderRadiusSmall @borderRadiusSmall 0); + } + } } -.form-search .input-append .search-query { - .border-radius(14px 0 0 14px); -} -.form-search .input-append .btn { - .border-radius(0 14px 14px 0); -} -.form-search .input-prepend .search-query { - .border-radius(0 14px 14px 0); -} -.form-search .input-prepend .btn { - .border-radius(14px 0 0 14px); -} - - - // HORIZONTAL & VERTICAL FORMS // --------------------------- @@ -819,3 +814,8 @@ legend + .control-group { } } + +/* User/group selector */ +.group-selector .group-selector-list { float: left; } +.group-selector .group-selector-list div { height: 24px; } +.group-selector .group-selector-buttons { float: left; margin: 24px 16px; } diff --git a/src/Umbraco.Web.UI.Client/src/less/main.less b/src/Umbraco.Web.UI.Client/src/less/main.less index 1b573bbe0b..699deb9b18 100644 --- a/src/Umbraco.Web.UI.Client/src/less/main.less +++ b/src/Umbraco.Web.UI.Client/src/less/main.less @@ -47,10 +47,25 @@ h5.-black { background: none; border: none } -.datepicker td.active, -.datepicker td span.active { - background: @turquoise !important; +.bootstrap-datetimepicker-widget { + td { + &.active, span.active { + background: @turquoise !important; + } + &.today:not(.active):before { + border-bottom-color: @purple-l1 !important; + } + a[data-action] { + padding: 0 !important; + } + .timepicker-hour, + .timepicker-minute, + .timepicker-second { + margin: 8px 0; + } + } } + .umb-datetime-picker div.info { vertical-align: middle } @@ -113,6 +128,19 @@ h5.-black { border: none; } +/* BLOCK MODE */ +.block-form .umb-control-group { + border-bottom: none; + margin-bottom: 10px !important; + padding-bottom: 0; +} + +.block-form .umb-control-group label .help-block, +.block-form .umb-control-group label small { + font-size: 13px; + padding-top: 2px; + margin-bottom: 5px; +} /*COMPACT MODE */ .compact .umb-pane{margin: 0px 0px 15px 0px;} diff --git a/src/Umbraco.Web.UI.Client/src/less/panel.less b/src/Umbraco.Web.UI.Client/src/less/panel.less index 6bc2a2b2de..378f6228a6 100644 --- a/src/Umbraco.Web.UI.Client/src/less/panel.less +++ b/src/Umbraco.Web.UI.Client/src/less/panel.less @@ -387,8 +387,8 @@ background: @white; border: 1px solid @gray-8; animation: fadeIn 0.5s; - flex: 0 0 55px; border-radius: 3px; + width: 55px; } .umb-panel-header-title-wrapper { @@ -446,8 +446,8 @@ input.umb-panel-header-name-input { margin-bottom: 0; font-weight: bold; box-sizing: border-box; - height: 30px; - line-height: 30px; + height: 32px; + line-height: 32px; width: 100%; &:hover { background: @white; diff --git a/src/Umbraco.Web.UI.Client/src/less/sections.less b/src/Umbraco.Web.UI.Client/src/less/sections.less index 51ec5c7436..e90a053a3d 100644 --- a/src/Umbraco.Web.UI.Client/src/less/sections.less +++ b/src/Umbraco.Web.UI.Client/src/less/sections.less @@ -7,7 +7,7 @@ ul.sections { background: @purple; height: 100%; width: 80px; - border-right: 1px solid @purple; + border-right: 1px solid @purple-d1; } ul.sections li { @@ -22,13 +22,16 @@ ul.sections li [class^="icon-"], ul.sections li [class*=" icon-"], ul.sections li img.icon-section { font-size: 30px; - line-height: 20px; /* set line-height to ensure all icons use same line-height */ display: inline-block; margin: 1px 0 0 0; color: @purple-l2; -webkit-transition: all .3s linear; -moz-transition: all .3s linear; transition: all .3s linear; + + &, &:before { + line-height: 20px !important; /* set line-height to ensure all icons use same line-height */ + } } ul.sections:hover li [class^="icon-"], @@ -84,9 +87,14 @@ ul.sections li.avatar a { border: none } -ul.sections li.avatar a img { +ul.sections li.avatar a div { border-radius: 50%; width: 30px; + margin:0 auto; +} + +ul.sections li.avatar a span { + opacity: 1; } .faded ul.sections li { @@ -168,7 +176,7 @@ ul.sections-tray { width: 80px; & > li:first-child > a { - border-top: 1px solid @purple; + border-top: 1px solid @purple-d1; } & > li { diff --git a/src/Umbraco.Web.UI.Client/src/less/tables.less b/src/Umbraco.Web.UI.Client/src/less/tables.less index f16447928f..3c63785957 100644 --- a/src/Umbraco.Web.UI.Client/src/less/tables.less +++ b/src/Umbraco.Web.UI.Client/src/less/tables.less @@ -13,6 +13,10 @@ table { border-spacing: 0; } +table thead { + background-color: @gray-10; +} + // BASELINE STYLES // --------------- @@ -20,13 +24,13 @@ table { .table { width: 100%; margin-bottom: @baseLineHeight; + border: 1px solid @gray-8; // Cells th, td { - padding: 8px; + padding: 10px 8px; line-height: @baseLineHeight; text-align: left; - vertical-align: top; border-top: 1px solid @tableBorder; } th { diff --git a/src/Umbraco.Web.UI.Client/src/less/tree.less b/src/Umbraco.Web.UI.Client/src/less/tree.less index df1bc4114a..5de27de9f3 100644 --- a/src/Umbraco.Web.UI.Client/src/less/tree.less +++ b/src/Umbraco.Web.UI.Client/src/less/tree.less @@ -53,22 +53,21 @@ border-color: @turquoise-d1; } -.umb-tree li.root > div { - padding: 0; +.umb-tree li.root > div:first-child { + padding: 0; } -.umb-tree li.root > div h5 { - margin: 0; - width: 100%; - - display: flex; - align-items: center; +.umb-tree li.root > div h5, .umb-tree li.root > div h6 { + margin: 0; + width: 100%; + display: flex; + align-items: center; } -.umb-tree li.root > div h5 > a, .umb-tree-header { - display: flex; - padding: 20px 0 20px 20px; - box-sizing: border-box; +.umb-tree li.root > div:first-child h5 > a, .umb-tree-header { + display: flex; + padding: 20px 0 20px 20px; + box-sizing: border-box; } .umb-tree * { @@ -96,14 +95,22 @@ text-decoration: none } -.umb-tree div { +/*.umb-tree div.tree-node { padding: 5px 0 5px 0; position: relative; overflow: hidden; display: flex; flex-wrap: nowrap; align-items: center; +}*/ +.umb-tree div { + padding: 5px 0 5px 0; + position: relative; + overflow: hidden; + display: flex; + flex-wrap: nowrap; + align-items: center; } .umb-tree a.noSpr { @@ -192,6 +199,23 @@ /*color:@turquoise;*/ } +.umb-tree div.umb-search-group { + position: inherit; + display: inherit; +} + +.umb-tree div.umb-search-group:hover { + background: inherit; +} +.umb-tree div.umb-search-group h6 { + /*color: @gray-5;*/ + padding: 10px 0 10px 20px; + font-weight: inherit; + background: @gray-10; + font-size: 14px; + font-weight: bold; +} + .umb-tree .umb-search-group-item { padding-left: 20px; } @@ -200,6 +224,7 @@ display: flex; flex-wrap: wrap; flex-direction: column; + font-weight: normal !important; } .icon-check:before { diff --git a/src/Umbraco.Web.UI.Client/src/less/utilities/layout/_display.less b/src/Umbraco.Web.UI.Client/src/less/utilities/layout/_display.less new file mode 100644 index 0000000000..b156b4135b --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/utilities/layout/_display.less @@ -0,0 +1,41 @@ +/* + DISPLAY + Base: + d = display + Modifiers: + n = none + b = block + ib = inline-block + it = inline-table + t = table + tc = table-cell + tr = table-row + tcol = table-column + tcolg = table-column-group + Media Query Extensions: + -ns = not-small + -m = medium + -l = large +*/ + +.dn { display: none; } +.di { display: inline; } +.db { display: block; } +.dib { display: inline-block; } +.dit { display: inline-table; } +.dt { display: table; } +.dtc { display: table-cell; } +.dt-row { display: table-row; } +.dt-row-group { display: table-row-group; } +.dt-column { display: table-column; } +.dt-column-group { display: table-column-group; } + +/* + This will set table to full width and then + all cells will be equal width +*/ + +.dt--fixed { + table-layout: fixed; + width: 100%; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/utilities/typography/_text-decoration.less b/src/Umbraco.Web.UI.Client/src/less/utilities/typography/_text-decoration.less new file mode 100644 index 0000000000..39ba646aac --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/utilities/typography/_text-decoration.less @@ -0,0 +1,9 @@ +/* + + TEXT DECORATION + +*/ + +.strike { text-decoration: line-through; } +.underline { text-decoration: underline; } +.no-underline { text-decoration: none; } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/utilities/typography/_white-space.less b/src/Umbraco.Web.UI.Client/src/less/utilities/typography/_white-space.less new file mode 100644 index 0000000000..b8fb5ca5db --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/utilities/typography/_white-space.less @@ -0,0 +1,15 @@ +/* + + WHITE SPACE + +*/ + +.ws-normal { white-space: normal; } +.nowrap { white-space: nowrap; } +.pre { white-space: pre; } + +.truncate { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index c173f122cb..635d75d895 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -152,7 +152,7 @@ // ------------------------- @tableBackground: transparent; // overall background-color @tableBackgroundAccent: @gray-10; // for striping -@tableBackgroundHover: @gray-9; // for hover +@tableBackgroundHover: @gray-10; // for hover @tableBorder: @gray-8; // table and cell border // Buttons @@ -190,7 +190,7 @@ @inputBorderRadius: 0; @inputDisabledBackground: @gray-10; @formActionsBackground: @gray-9; -@inputHeight: @baseLineHeight + 10px; // base line-height + 8px vertical padding + 2px top/bottom border +@inputHeight: @baseLineHeight + 12px; // base line-height + 8px vertical padding + 2px top/bottom border @controlRequiredColor: @red; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/help.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/help.controller.js index d898ec48f8..e33c37ab05 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/help.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/help.controller.js @@ -19,7 +19,6 @@ angular.module("umbraco") userService.getCurrentUser().then(function(user){ - rq.usertype = user.userType; rq.lang = user.locale; if($routeParams.url){ diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.html index 96ab990447..c159aafd6e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/iconpicker.html @@ -7,7 +7,8 @@ style="width: 100%" ng-model="searchTerm" class="umb-search-field search-query input-block-level" - placeholder="Filter..." + localize="plceholder" + placeholder="@placeholders_filter" no-dirty-check> @@ -17,12 +18,12 @@
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.html index 287e16049e..e6c757ef1e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/legacydelete.html @@ -3,7 +3,7 @@

- Are you sure you want to delete {{currentNode.name}} ? + Are you sure you want to delete {{currentNode.name}} ?

diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js index 5ee103a32b..e76db90f47 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.controller.js @@ -108,15 +108,15 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LinkPickerController", $scope.switchToMediaPicker = function () { userService.getCurrentUser().then(function (userData) { - dialogService.mediaPicker({ - startNodeId: userData.startMediaId, - callback: function (media) { - $scope.target.id = media.id; - $scope.target.isMedia = true; - $scope.target.name = media.name; - $scope.target.url = mediaHelper.resolveFile(media); - } - }); + dialogService.mediaPicker({ + startNodeId: userData.startMediaIds.length == 0 ? -1 : userData.startMediaIds[0], + callback: function(media) { + $scope.target.id = media.id; + $scope.target.isMedia = true; + $scope.target.name = media.name; + $scope.target.url = mediaHelper.resolveFile(media); + } + }); }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.html index be9024045e..badcc14487 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/linkpicker.html @@ -22,7 +22,7 @@ @@ -63,7 +63,7 @@ Cancel - Link to file + Link to file
- \ No newline at end of file + diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js index 49db7dc191..18158a5ff2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js @@ -1,237 +1,399 @@ angular.module("umbraco").controller("Umbraco.Dialogs.LoginController", - function ($scope, $cookies, localizationService, userService, externalLoginInfo, resetPasswordCodeInfo, $timeout, authResource, dialogService) { + function ($scope, $cookies, $location, currentUserResource, formHelper, mediaHelper, umbRequestHelper, Upload, localizationService, userService, externalLoginInfo, resetPasswordCodeInfo, $timeout, authResource, dialogService, $q) { - var setFieldFocus = function(form, field) { - $timeout(function() { - $("form[name='" + form + "'] input[name='" + field + "']").focus(); + $scope.invitedUser = null; + $scope.invitedUserPasswordModel = { + password: "", + confirmPassword: "", + buttonState: "", + passwordPolicies: null, + passwordPolicyText: "" + } + $scope.avatarFile = { + filesHolder: null, + uploadStatus: null, + uploadProgress: 0, + maxFileSize: Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB", + acceptedFileTypes: mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes), + uploaded: false + } + + function init() { + // Check if it is a new user + var inviteVal = $location.search().invite; + if (inviteVal && (inviteVal === "1" || inviteVal === "2")) { + + $q.all([ + //get the current invite user + authResource.getCurrentInvitedUser().then(function (data) { + $scope.invitedUser = data; + }, + function() { + //it failed so we should remove the search + $location.search('invite', null); + }), + //get the membership provider config for password policies + authResource.getMembershipProviderConfig().then(function (data) { + $scope.invitedUserPasswordModel.passwordPolicies = data; + + //localize the text + localizationService.localize("errorHandling_errorInPasswordFormat", + [ + $scope.invitedUserPasswordModel.passwordPolicies.minPasswordLength, + $scope.invitedUserPasswordModel.passwordPolicies.minNonAlphaNumericChars + ]).then(function(data) { + $scope.invitedUserPasswordModel.passwordPolicyText = data; }); + }) + ]).then(function () { + + $scope.inviteStep = Number(inviteVal); + + }); + } + } + + $scope.changeAvatar = function (files, event) { + if (files && files.length > 0) { + upload(files[0]); + } + }; + + $scope.getStarted = function() { + $location.search('invite', null); + $scope.submit(true); + } + + function upload(file) { + + $scope.avatarFile.uploadProgress = 0; + + Upload.upload({ + url: umbRequestHelper.getApiUrl("currentUserApiBaseUrl", "PostSetAvatar"), + fields: {}, + file: file + }).progress(function (evt) { + + if ($scope.avatarFile.uploadStatus !== "done" && $scope.avatarFile.uploadStatus !== "error") { + // set uploading status on file + $scope.avatarFile.uploadStatus = "uploading"; + + // calculate progress in percentage + var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10); + + // set percentage property on file + $scope.avatarFile.uploadProgress = progressPercentage; } - var twoFactorloginDialog = null; - function show2FALoginDialog(view, callback) { - if (!twoFactorloginDialog) { - twoFactorloginDialog = dialogService.open({ + }).success(function (data, status, headers, config) { - //very special flag which means that global events cannot close this dialog - manualClose: true, - template: view, - modalClass: "login-overlay", - animation: "slide", - show: true, - callback: callback, + $scope.avatarFile.uploadProgress = 100; - }); - } + // set done status on file + $scope.avatarFile.uploadStatus = "done"; + + $scope.invitedUser.avatars = data; + + $scope.avatarFile.uploaded = true; + + }).error(function (evt, status, headers, config) { + + // set status done + $scope.avatarFile.uploadStatus = "error"; + + // If file not found, server will return a 404 and display this message + if (status === 404) { + $scope.avatarFile.serverErrorMessage = "File not found"; } - - function resetInputValidation() { - $scope.confirmPassword = ""; - $scope.password = ""; - $scope.login = ""; - if ($scope.loginForm) { - $scope.loginForm.username.$setValidity('auth', true); - $scope.loginForm.password.$setValidity('auth', true); - } - if ($scope.requestPasswordResetForm) { - $scope.requestPasswordResetForm.email.$setValidity("auth", true); - } - if ($scope.setPasswordForm) { - $scope.setPasswordForm.password.$setValidity('auth', true); - $scope.setPasswordForm.confirmPassword.$setValidity('auth', true); - } - } - - $scope.allowPasswordReset = Umbraco.Sys.ServerVariables.umbracoSettings.allowPasswordReset; - - $scope.showLogin = function () { - $scope.errorMsg = ""; - resetInputValidation(); - $scope.view = "login"; - setFieldFocus("loginForm", "username"); - } - - $scope.showRequestPasswordReset = function () { - $scope.errorMsg = ""; - resetInputValidation(); - $scope.view = "request-password-reset"; - $scope.showEmailResetConfirmation = false; - setFieldFocus("requestPasswordResetForm", "email"); - } - - $scope.showSetPassword = function () { - $scope.errorMsg = ""; - resetInputValidation(); - $scope.view = "set-password"; - setFieldFocus("setPasswordForm", "password"); - } - - var d = new Date(); - var konamiGreetings = new Array("Suze Sunday", "Malibu Monday", "Tequila Tuesday", "Whiskey Wednesday", "Negroni Day", "Fernet Friday", "Sancerre Saturday"); - var konamiMode = $cookies.konamiLogin; - if (konamiMode == "1") { - $scope.greeting = "Happy " + konamiGreetings[d.getDay()]; - } else { - localizationService.localize("login_greeting" + d.getDay()).then(function (label) { - $scope.greeting = label; - }); // weekday[d.getDay()]; - } - $scope.errorMsg = ""; - - $scope.externalLoginFormAction = Umbraco.Sys.ServerVariables.umbracoUrls.externalLoginsUrl; - $scope.externalLoginProviders = externalLoginInfo.providers; - $scope.externalLoginInfo = externalLoginInfo; - $scope.resetPasswordCodeInfo = resetPasswordCodeInfo; - $scope.backgroundImage = Umbraco.Sys.ServerVariables.umbracoSettings.loginBackgroundImage; - - $scope.activateKonamiMode = function () { - if ($cookies.konamiLogin == "1") { - // somehow I can't update the cookie value using $cookies, so going native - document.cookie = "konamiLogin=; expires=Thu, 01 Jan 1970 00:00:01 GMT;"; - document.location.reload(); - } else { - document.cookie = "konamiLogin=1; expires=Tue, 01 Jan 2030 00:00:01 GMT;"; - $scope.$apply(function () { - $scope.greeting = "Happy " + konamiGreetings[d.getDay()]; - }); - } - } - - $scope.loginSubmit = function (login, password) { - - //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. - if (login && password && login.length > 0 && password.length > 0) { - $scope.loginForm.username.$setValidity('auth', true); - $scope.loginForm.password.$setValidity('auth', true); - } - - if ($scope.loginForm.$invalid) { - return; - } - - userService.authenticate(login, password) - .then(function(data) { - $scope.submit(true); - }, - function(reason) { - - //is Two Factor required? - if (reason.status === 402) { - $scope.errorMsg = "Additional authentication required"; - show2FALoginDialog(reason.data.twoFactorView, $scope.submit); - } - else { - $scope.errorMsg = reason.errorMsg; - - //set the form inputs to invalid - $scope.loginForm.username.$setValidity("auth", false); - $scope.loginForm.password.$setValidity("auth", false); - } - }); - - //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 - // be submitted again. - $scope.loginForm.username.$viewChangeListeners.push(function () { - if ($scope.loginForm.username.$invalid) { - $scope.loginForm.username.$setValidity('auth', true); - } - }); - $scope.loginForm.password.$viewChangeListeners.push(function () { - if ($scope.loginForm.password.$invalid) { - $scope.loginForm.password.$setValidity('auth', true); - } - }); - }; - - $scope.requestPasswordResetSubmit = function (email) { - - if (email && email.length > 0) { - $scope.requestPasswordResetForm.email.$setValidity('auth', true); - } - - $scope.showEmailResetConfirmation = false; - - if ($scope.requestPasswordResetForm.$invalid) { - return; - } - - $scope.errorMsg = ""; - - authResource.performRequestPasswordReset(email) - .then(function () { - //remove the email entered - $scope.email = ""; - $scope.showEmailResetConfirmation = true; - }, function (reason) { - $scope.errorMsg = reason.errorMsg; - $scope.requestPasswordResetForm.email.$setValidity("auth", false); - }); - - $scope.requestPasswordResetForm.email.$viewChangeListeners.push(function () { - if ($scope.requestPasswordResetForm.email.$invalid) { - $scope.requestPasswordResetForm.email.$setValidity('auth', true); - } - }); - }; - - $scope.setPasswordSubmit = function (password, confirmPassword) { - - $scope.showSetPasswordConfirmation = false; - - if (password && confirmPassword && password.length > 0 && confirmPassword.length > 0) { - $scope.setPasswordForm.password.$setValidity('auth', true); - $scope.setPasswordForm.confirmPassword.$setValidity('auth', true); - } - - if ($scope.setPasswordForm.$invalid) { - return; - } - - authResource.performSetPassword($scope.resetPasswordCodeInfo.resetCodeModel.userId, password, confirmPassword, $scope.resetPasswordCodeInfo.resetCodeModel.resetCode) - .then(function () { - $scope.showSetPasswordConfirmation = true; - $scope.resetComplete = true; - - //reset the values in the resetPasswordCodeInfo angular so if someone logs out the change password isn't shown again - resetPasswordCodeInfo.resetCodeModel = null; - - }, function (reason) { - if (reason.data && reason.data.Message) { - $scope.errorMsg = reason.data.Message; - } - else { - $scope.errorMsg = reason.errorMsg; - } - $scope.setPasswordForm.password.$setValidity("auth", false); - $scope.setPasswordForm.confirmPassword.$setValidity("auth", false); - }); - - $scope.setPasswordForm.password.$viewChangeListeners.push(function () { - if ($scope.setPasswordForm.password.$invalid) { - $scope.setPasswordForm.password.$setValidity('auth', true); - } - }); - $scope.setPasswordForm.confirmPassword.$viewChangeListeners.push(function () { - if ($scope.setPasswordForm.confirmPassword.$invalid) { - $scope.setPasswordForm.confirmPassword.$setValidity('auth', true); - } - }); - } - - - //Now, show the correct panel: - - if ($scope.resetPasswordCodeInfo.resetCodeModel) { - $scope.showSetPassword(); - } - else if ($scope.resetPasswordCodeInfo.errors.length > 0) { - $scope.view = "password-reset-code-expired"; + else if (status == 400) { + //it's a validation error + $scope.avatarFile.serverErrorMessage = evt.message; } else { - $scope.showLogin(); - } + //it's an unhandled error + //if the service returns a detailed error + if (evt.InnerException) { + $scope.avatarFile.serverErrorMessage = evt.InnerException.ExceptionMessage; - }); + //Check if its the common "too large file" exception + if (evt.InnerException.StackTrace && evt.InnerException.StackTrace.indexOf("ValidateRequestEntityLength") > 0) { + $scope.avatarFile.serverErrorMessage = "File too large to upload"; + } + + } else if (evt.Message) { + $scope.avatarFile.serverErrorMessage = evt.Message; + } + } + }); + } + + $scope.inviteSavePassword = function () { + + if (formHelper.submitForm({ scope: $scope, statusMessage: "Saving..." })) { + + $scope.invitedUserPasswordModel.buttonState = "busy"; + + currentUserResource.performSetInvitedUserPassword($scope.invitedUserPasswordModel.password) + .then(function (data) { + + //success + formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + $scope.invitedUserPasswordModel.buttonState = "success"; + //set the user and set them as logged in + $scope.invitedUser = data; + userService.setAuthenticationSuccessful(data); + + $scope.inviteStep = 2; + + }, function(err) { + + //error + formHelper.handleError(err); + + $scope.invitedUserPasswordModel.buttonState = "error"; + + }); + } + }; + + var setFieldFocus = function (form, field) { + $timeout(function () { + $("form[name='" + form + "'] input[name='" + field + "']").focus(); + }); + } + + var twoFactorloginDialog = null; + function show2FALoginDialog(view, callback) { + if (!twoFactorloginDialog) { + twoFactorloginDialog = dialogService.open({ + + //very special flag which means that global events cannot close this dialog + manualClose: true, + template: view, + modalClass: "login-overlay", + animation: "slide", + show: true, + callback: callback, + + }); + } + } + + function resetInputValidation() { + $scope.confirmPassword = ""; + $scope.password = ""; + $scope.login = ""; + if ($scope.loginForm) { + $scope.loginForm.username.$setValidity('auth', true); + $scope.loginForm.password.$setValidity('auth', true); + } + if ($scope.requestPasswordResetForm) { + $scope.requestPasswordResetForm.email.$setValidity("auth", true); + } + if ($scope.setPasswordForm) { + $scope.setPasswordForm.password.$setValidity('auth', true); + $scope.setPasswordForm.confirmPassword.$setValidity('auth', true); + } + } + + $scope.allowPasswordReset = Umbraco.Sys.ServerVariables.umbracoSettings.allowPasswordReset; + + $scope.showLogin = function () { + $scope.errorMsg = ""; + resetInputValidation(); + $scope.view = "login"; + setFieldFocus("loginForm", "username"); + } + + $scope.showRequestPasswordReset = function () { + $scope.errorMsg = ""; + resetInputValidation(); + $scope.view = "request-password-reset"; + $scope.showEmailResetConfirmation = false; + setFieldFocus("requestPasswordResetForm", "email"); + } + + $scope.showSetPassword = function () { + $scope.errorMsg = ""; + resetInputValidation(); + $scope.view = "set-password"; + setFieldFocus("setPasswordForm", "password"); + } + + var d = new Date(); + var konamiGreetings = new Array("Suze Sunday", "Malibu Monday", "Tequila Tuesday", "Whiskey Wednesday", "Negroni Day", "Fernet Friday", "Sancerre Saturday"); + var konamiMode = $cookies.konamiLogin; + if (konamiMode == "1") { + $scope.greeting = "Happy " + konamiGreetings[d.getDay()]; + } else { + localizationService.localize("login_greeting" + d.getDay()).then(function (label) { + $scope.greeting = label; + }); // weekday[d.getDay()]; + } + $scope.errorMsg = ""; + + $scope.externalLoginFormAction = Umbraco.Sys.ServerVariables.umbracoUrls.externalLoginsUrl; + $scope.externalLoginProviders = externalLoginInfo.providers; + $scope.externalLoginInfo = externalLoginInfo; + $scope.resetPasswordCodeInfo = resetPasswordCodeInfo; + $scope.backgroundImage = Umbraco.Sys.ServerVariables.umbracoSettings.loginBackgroundImage; + + $scope.activateKonamiMode = function () { + if ($cookies.konamiLogin == "1") { + // somehow I can't update the cookie value using $cookies, so going native + document.cookie = "konamiLogin=; expires=Thu, 01 Jan 1970 00:00:01 GMT;"; + document.location.reload(); + } else { + document.cookie = "konamiLogin=1; expires=Tue, 01 Jan 2030 00:00:01 GMT;"; + $scope.$apply(function () { + $scope.greeting = "Happy " + konamiGreetings[d.getDay()]; + }); + } + } + + $scope.loginSubmit = function (login, password) { + + //TODO: Do validation properly like in the invite password update + + //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. + if (login && password && login.length > 0 && password.length > 0) { + $scope.loginForm.username.$setValidity('auth', true); + $scope.loginForm.password.$setValidity('auth', true); + } + + if ($scope.loginForm.$invalid) { + return; + } + + userService.authenticate(login, password) + .then(function (data) { + $scope.submit(true); + }, + function (reason) { + + //is Two Factor required? + if (reason.status === 402) { + $scope.errorMsg = "Additional authentication required"; + show2FALoginDialog(reason.data.twoFactorView, $scope.submit); + } + else { + $scope.errorMsg = reason.errorMsg; + + //set the form inputs to invalid + $scope.loginForm.username.$setValidity("auth", false); + $scope.loginForm.password.$setValidity("auth", false); + } + }); + + //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 + // be submitted again. + $scope.loginForm.username.$viewChangeListeners.push(function () { + if ($scope.loginForm.username.$invalid) { + $scope.loginForm.username.$setValidity('auth', true); + } + }); + $scope.loginForm.password.$viewChangeListeners.push(function () { + if ($scope.loginForm.password.$invalid) { + $scope.loginForm.password.$setValidity('auth', true); + } + }); + }; + + $scope.requestPasswordResetSubmit = function (email) { + + //TODO: Do validation properly like in the invite password update + + if (email && email.length > 0) { + $scope.requestPasswordResetForm.email.$setValidity('auth', true); + } + + $scope.showEmailResetConfirmation = false; + + if ($scope.requestPasswordResetForm.$invalid) { + return; + } + + $scope.errorMsg = ""; + + authResource.performRequestPasswordReset(email) + .then(function () { + //remove the email entered + $scope.email = ""; + $scope.showEmailResetConfirmation = true; + }, function (reason) { + $scope.errorMsg = reason.errorMsg; + $scope.requestPasswordResetForm.email.$setValidity("auth", false); + }); + + $scope.requestPasswordResetForm.email.$viewChangeListeners.push(function () { + if ($scope.requestPasswordResetForm.email.$invalid) { + $scope.requestPasswordResetForm.email.$setValidity('auth', true); + } + }); + }; + + $scope.setPasswordSubmit = function (password, confirmPassword) { + + $scope.showSetPasswordConfirmation = false; + + if (password && confirmPassword && password.length > 0 && confirmPassword.length > 0) { + $scope.setPasswordForm.password.$setValidity('auth', true); + $scope.setPasswordForm.confirmPassword.$setValidity('auth', true); + } + + if ($scope.setPasswordForm.$invalid) { + return; + } + + //TODO: All of this logic can/should be shared! We should do validation the nice way instead of all of this manual stuff, see: inviteSavePassword + authResource.performSetPassword($scope.resetPasswordCodeInfo.resetCodeModel.userId, password, confirmPassword, $scope.resetPasswordCodeInfo.resetCodeModel.resetCode) + .then(function () { + $scope.showSetPasswordConfirmation = true; + $scope.resetComplete = true; + + //reset the values in the resetPasswordCodeInfo angular so if someone logs out the change password isn't shown again + resetPasswordCodeInfo.resetCodeModel = null; + + }, function (reason) { + if (reason.data && reason.data.Message) { + $scope.errorMsg = reason.data.Message; + } + else { + $scope.errorMsg = reason.errorMsg; + } + $scope.setPasswordForm.password.$setValidity("auth", false); + $scope.setPasswordForm.confirmPassword.$setValidity("auth", false); + }); + + $scope.setPasswordForm.password.$viewChangeListeners.push(function () { + if ($scope.setPasswordForm.password.$invalid) { + $scope.setPasswordForm.password.$setValidity('auth', true); + } + }); + $scope.setPasswordForm.confirmPassword.$viewChangeListeners.push(function () { + if ($scope.setPasswordForm.confirmPassword.$invalid) { + $scope.setPasswordForm.confirmPassword.$setValidity('auth', true); + } + }); + } + + + //Now, show the correct panel: + + if ($scope.resetPasswordCodeInfo.resetCodeModel) { + $scope.showSetPassword(); + } + else if ($scope.resetPasswordCodeInfo.errors.length > 0) { + $scope.view = "password-reset-code-expired"; + } + else { + $scope.showLogin(); + } + + init(); + + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html index 65ce1c3ecb..3af0c30a08 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html @@ -1,148 +1,238 @@ 
- -
- - - +
- + + + + + +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.html index 194752f2bc..99102fed19 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/mediapicker.html @@ -75,7 +75,8 @@ + localize="placeholder" + placeholder="@placeholders_filter">
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/rteembed.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/rteembed.html index 62b0340769..7bf24c086f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/rteembed.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/rteembed.html @@ -1,17 +1,17 @@ -
+
- \ No newline at end of file + diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/snippet.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/snippet.html index 7b5187303e..0d6c05091c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/snippet.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/template/snippet.html @@ -29,7 +29,7 @@ Close - Insert + Insert diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js index bac8fcded7..cc7f1d158f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.controller.js @@ -115,7 +115,7 @@ angular.module("umbraco") }; //go get the config for the membership provider and add it to the model - currentUserResource.getMembershipProviderConfig().then(function(data) { + authResource.getMembershipProviderConfig().then(function(data) { $scope.changePasswordModel.config = data; //ensure the hasPassword config option is set to true (the user of course has a password already assigned) //this will ensure the oldPassword is shown so they can change it diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.html index 2b2d3bd1cf..4ad5226eb1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/user.html @@ -24,7 +24,7 @@
- @@ -42,7 +42,7 @@
-
External login providers
+
External login providers
@@ -55,7 +55,7 @@ onclick="document.forms.oauthloginform.submit();"> - Link your {{login.caption}} account + Link your {{login.caption}} account @@ -67,7 +67,7 @@ name="provider" value="{{login.authType}}"> - Un-link your {{login.caption}} account + Un-link your {{login.caption}} account
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/propertysettings/propertysettings.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/propertysettings/propertysettings.html index 7c457ac4c9..03ae935f47 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/propertysettings/propertysettings.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/contenttypeeditor/propertysettings/propertysettings.html @@ -69,12 +69,13 @@ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js index 76d1599508..404c311d8b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js @@ -127,7 +127,7 @@ var i2 = parseFloat($scope.model.config.initVal2); sliderVal = [ isNaN(i1) ? $scope.model.config.minVal : (i1 >= $scope.model.config.minVal ? i1 : $scope.model.config.minVal), - isNaN(i2) ? $scope.model.config.maxVal : (i2 > i1 ? (i2 <= $scope.model.config.maxVal ? i2 : $scope.model.config.maxVal) : $scope.model.config.maxVal) + isNaN(i2) ? $scope.model.config.maxVal : (i2 >= i1 ? (i2 <= $scope.model.config.maxVal ? i2 : $scope.model.config.maxVal) : $scope.model.config.maxVal) ]; } else { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.controller.js new file mode 100644 index 0000000000..05d1e5fbfa --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.controller.js @@ -0,0 +1,26 @@ +function textAreaController($rootScope, $scope, $log) { + $scope.model.maxlength = false; + if ($scope.model.config && $scope.model.config.maxChars) { + $scope.model.maxlength = true; + if($scope.model.value == undefined) { + $scope.model.count = ($scope.model.config.maxChars * 1); + } else { + $scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length; + } + } + + $scope.model.change = function() { + if ($scope.model.config && $scope.model.config.maxChars) { + if($scope.model.value == undefined) { + $scope.model.count = ($scope.model.config.maxChars * 1); + } else { + $scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length; + } + if($scope.model.count < 0) { + $scope.model.value = $scope.model.value.substring(0, ($scope.model.config.maxChars * 1)); + $scope.model.count = 0; + } + } + } +} +angular.module('umbraco').controller("Umbraco.PropertyEditors.textAreaController", textAreaController); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html index 0d1fae3f6f..ffb692ced0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textarea/textarea.html @@ -1,3 +1,9 @@ - -Required - \ No newline at end of file +
+ + Required + +
+ {{model.count}} + characters left +
+
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.controller.js new file mode 100644 index 0000000000..c0f084f0c3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.controller.js @@ -0,0 +1,26 @@ +function textboxController($rootScope, $scope, $log) { + $scope.model.maxlength = false; + if ($scope.model.config && $scope.model.config.maxChars) { + $scope.model.maxlength = true; + if($scope.model.value == undefined) { + $scope.model.count = ($scope.model.config.maxChars * 1); + } else { + $scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length; + } + } + + $scope.model.change = function() { + if ($scope.model.config && $scope.model.config.maxChars) { + if($scope.model.value == undefined) { + $scope.model.count = ($scope.model.config.maxChars * 1); + } else { + $scope.model.count = ($scope.model.config.maxChars * 1) - $scope.model.value.length; + } + if($scope.model.count < 0) { + $scope.model.value = $scope.model.value.substring(0, ($scope.model.config.maxChars * 1)); + $scope.model.count = 0; + } + } + } +} +angular.module('umbraco').controller("Umbraco.PropertyEditors.textboxController", textboxController); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html index c55fc350fa..d8c51ce9e0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/textbox/textbox.html @@ -1,9 +1,14 @@ -
+
+ ng-trim="false" + ng-keyup="model.change()" /> - Required -
+ Required +
+ {{model.count}} + characters left +
+
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js index bb3aedeb4a..9b5754912a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js @@ -48,14 +48,9 @@ }, function(err) { - vm.createFolderError = err; - - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } + vm.createFolderError = err; + formHelper.showNotifications(err.data); + }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html index ec8ca3e9b4..2d59b644d0 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.html @@ -13,6 +13,7 @@ 0) { + selection.splice(index, 1); + } + } + + function clearStartNode(type) { + if (type === "content") { + vm.userGroup.contentStartNode = null; + } else if (type === "media") { + vm.userGroup.mediaStartNode = null; + } + } + + function makeBreadcrumbs() { + vm.breadcrumbs = [ + { + "name": vm.labels.groups, + "path": "/users/users/overview", + "subView": "groups" + }, + { + "name": vm.userGroup.name + } + ]; + } + + function setSectionIcon(sections) { + angular.forEach(sections, function (section) { + section.icon = "icon-section " + section.cssclass; + }); + } + + init(); + + } + + angular.module("umbraco").controller("Umbraco.Editors.Users.GroupController", UserGroupEditController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/users/group.html b/src/Umbraco.Web.UI.Client/src/views/users/group.html new file mode 100644 index 0000000000..a9df8afcd3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/users/group.html @@ -0,0 +1,257 @@ +
+ + + +
+ + + + + + + + +
+ +
+ +
+ + + +
+
+
Default permissions
+
+
+ + + + +
+
+ +
+
+
Granular permissions
+
+
+ + + + + + + Add + + + +
+
+ +
+ +
+ +
+ +
Users
+ + + + + + Add + + +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js new file mode 100644 index 0000000000..e84ebc81cb --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js @@ -0,0 +1,49 @@ +(function () { + "use strict"; + + function UsersOverviewController($scope, $location, $timeout, navigationService, localizationService) { + + var vm = this; + var usersUri = $location.search().subview; + if (!usersUri) { + $location.search("subview", "users") + } + + vm.page = {}; + vm.page.name = "User Management"; + vm.page.navigation = [ + { + "name": localizationService.localize("sections_users"), + "icon": "icon-user", + "action": function() { + $location.search("subview", "users") + }, + "view": "views/users/views/users/users.html", + "active": !usersUri || usersUri === "users" + }, + { + "name": localizationService.localize("general_groups"), + "icon": "icon-users", + "action": function () { + $location.search("subview", "groups") + }, + "view": "views/users/views/groups/groups.html", + "active": usersUri === "groups" + } + ]; + + function init() { + + $timeout(function () { + navigationService.syncTree({ tree: "users", path: "-1" }); + }); + + } + + init(); + + } + + angular.module("umbraco").controller("Umbraco.Editors.Users.OverviewController", UsersOverviewController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/users/overview.html b/src/Umbraco.Web.UI.Client/src/views/users/overview.html new file mode 100644 index 0000000000..2816e80e09 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/users/overview.html @@ -0,0 +1,24 @@ +
+ + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js new file mode 100644 index 0000000000..237c44255c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js @@ -0,0 +1,353 @@ +(function () { + "use strict"; + + function UserEditController($scope, $timeout, $location, $routeParams, formHelper, usersResource, contentEditingHelper, localizationService, notificationsService, mediaHelper, Upload, umbRequestHelper, usersHelper, authResource) { + + var vm = this; + + vm.page = {}; + vm.page.rootIcon = "icon-folder"; + vm.user = { + changePassword: null + }; + vm.breadcrumbs = []; + vm.avatarFile = {}; + vm.labels = {}; + vm.maxFileSize = Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB"; + vm.acceptedFileTypes = mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes); + vm.emailIsUsername = true; + + //create the initial model for change password + vm.changePasswordModel = { + config: {}, + isChanging: false + }; + + vm.goToPage = goToPage; + vm.openUserGroupPicker = openUserGroupPicker; + vm.openContentPicker = openContentPicker; + vm.openMediaPicker = openMediaPicker; + vm.removeSelectedItem = removeSelectedItem; + vm.disableUser = disableUser; + vm.enableUser = enableUser; + vm.clearAvatar = clearAvatar; + vm.save = save; + vm.toggleChangePassword = toggleChangePassword; + + function init() { + + vm.loading = true; + + var labelKeys = [ + "general_saving", + "general_cancel", + "defaultdialogs_selectContentStartNode", + "defaultdialogs_selectMediaStartNode", + "sections_users", + "content_contentRoot", + "media_mediaRoot", + "user_noStartNodes" + ]; + + localizationService.localizeMany(labelKeys).then(function (values) { + vm.labels.saving = values[0]; + vm.labels.cancel = values[1]; + vm.labels.selectContentStartNode = values[2]; + vm.labels.selectMediaStartNode = values[3]; + vm.labels.users = values[4]; + vm.labels.contentRoot = values[5]; + vm.labels.mediaRoot = values[6]; + vm.labels.noStartNodes = values[7]; + }); + + // get user + usersResource.getUser($routeParams.id).then(function (user) { + vm.user = user; + makeBreadcrumbs(vm.user); + setUserDisplayState(); + + vm.emailIsUsername = user.email === user.username; + + //go get the config for the membership provider and add it to the model + authResource.getMembershipProviderConfig().then(function (data) { + vm.changePasswordModel.config = data; + + //the user has a password if they are not states: Invited, NoCredentials + vm.changePasswordModel.config.hasPassword = vm.user.userState !== 3 && vm.user.userState !== 4; + + vm.changePasswordModel.config.disableToggle = true; + + vm.loading = false; + }); + }); + } + + function toggleChangePassword() { + vm.changePasswordModel.isChanging = !vm.changePasswordModel.isChanging; + //reset it + vm.user.changePassword = null; + } + + function save() { + + vm.page.saveButtonState = "busy"; + vm.user.resetPasswordValue = null; + + contentEditingHelper.contentEditorPerformSave({ + statusMessage: vm.labels.saving, + saveMethod: usersResource.saveUser, + scope: $scope, + content: vm.user, + // We do not redirect on failure for users - this is because it is not possible to actually save a user + // when server side validation fails - as opposed to content where we are capable of saving the content + // item if server side validation fails + redirectOnFailure: false, + rebindCallback: function (orignal, saved) { } + }).then(function (saved) { + + vm.user = saved; + setUserDisplayState(); + + vm.changePasswordModel.isChanging = false; + vm.page.saveButtonState = "success"; + + //the user has a password if they are not states: Invited, NoCredentials + vm.changePasswordModel.config.hasPassword = vm.user.userState !== 3 && vm.user.userState !== 4; + }, function (err) { + vm.page.saveButtonState = "error"; + }); + } + + function goToPage(ancestor) { + $location.path(ancestor.path).search("subview", ancestor.subView); + } + + function openUserGroupPicker() { + vm.userGroupPicker = { + view: "usergrouppicker", + selection: vm.user.userGroups, + closeButtonLabel: vm.labels.cancel, + show: true, + submit: function (model) { + // apply changes + if (model.selection) { + vm.user.userGroups = model.selection; + } + vm.userGroupPicker.show = false; + vm.userGroupPicker = null; + }, + close: function (oldModel) { + // rollback on close + if (oldModel.selection) { + vm.user.userGroups = oldModel.selection; + } + vm.userGroupPicker.show = false; + vm.userGroupPicker = null; + } + }; + } + + function openContentPicker() { + vm.contentPicker = { + title: vm.labels.selectContentStartNode, + view: "contentpicker", + multiPicker: true, + selection: vm.user.startContentIds, + hideHeader: false, + show: true, + submit: function (model) { + // select items + if (model.selection) { + angular.forEach(model.selection, function (item) { + if (item.id === "-1") { + item.name = vm.labels.contentRoot; + item.icon = "icon-folder"; + } + multiSelectItem(item, vm.user.startContentIds); + }); + } + // close overlay + vm.contentPicker.show = false; + vm.contentPicker = null; + }, + close: function (oldModel) { + // close overlay + vm.contentPicker.show = false; + vm.contentPicker = null; + } + }; + } + + function openMediaPicker() { + vm.mediaPicker = { + title: vm.labels.selectMediaStartNode, + view: "treepicker", + section: "media", + treeAlias: "media", + entityType: "media", + multiPicker: true, + hideHeader: false, + show: true, + submit: function (model) { + // select items + if (model.selection) { + angular.forEach(model.selection, function (item) { + if (item.id === "-1") { + item.name = vm.labels.mediaRoot; + item.icon = "icon-folder"; + } + multiSelectItem(item, vm.user.startMediaIds); + }); + } + // close overlay + vm.mediaPicker.show = false; + vm.mediaPicker = null; + }, + close: function (oldModel) { + // close overlay + vm.mediaPicker.show = false; + vm.mediaPicker = null; + } + }; + } + + function multiSelectItem(item, selection) { + var found = false; + // check if item is already in the selected list + if (selection.length > 0) { + angular.forEach(selection, function (selectedItem) { + if (selectedItem.udi === item.udi) { + found = true; + } + }); + } + // only add the selected item if it is not already selected + if (!found) { + selection.push(item); + } + } + + function removeSelectedItem(index, selection) { + selection.splice(index, 1); + } + + function disableUser() { + vm.disableUserButtonState = "busy"; + usersResource.disableUsers([vm.user.id]).then(function (data) { + vm.user.userState = 1; + setUserDisplayState(); + vm.disableUserButtonState = "success"; + formHelper.showNotifications(data); + }, function(error){ + vm.disableUserButtonState = "error"; + formHelper.showNotifications(error.data); + }); + } + + function enableUser() { + vm.enableUserButtonState = "busy"; + usersResource.enableUsers([vm.user.id]).then(function (data) { + vm.user.userState = 0; + setUserDisplayState(); + vm.enableUserButtonState = "success"; + formHelper.showNotifications(data); + }, function(error){ + vm.disableUserButtonState = "error"; + formHelper.showNotifications(error.data); + }); + } + + + function clearAvatar() { + // get user + usersResource.clearAvatar(vm.user.id).then(function (data) { + vm.user.avatars = data; + }); + } + + $scope.changeAvatar = function (files, event) { + if (files && files.length > 0) { + upload(files[0]); + } + }; + + function upload(file) { + + vm.avatarFile.uploadProgress = 0; + + Upload.upload({ + url: umbRequestHelper.getApiUrl("userApiBaseUrl", "PostSetAvatar", { id: vm.user.id }), + fields: {}, + file: file + }).progress(function (evt) { + + if (vm.avatarFile.uploadStatus !== "done" && vm.avatarFile.uploadStatus !== "error") { + // set uploading status on file + vm.avatarFile.uploadStatus = "uploading"; + + // calculate progress in percentage + var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10); + + // set percentage property on file + vm.avatarFile.uploadProgress = progressPercentage; + } + + }).success(function (data, status, headers, config) { + + // set done status on file + vm.avatarFile.uploadStatus = "done"; + vm.avatarFile.uploadProgress = 100; + vm.user.avatars = data; + + }).error(function (evt, status, headers, config) { + + // set status done + vm.avatarFile.uploadStatus = "error"; + + // If file not found, server will return a 404 and display this message + if (status === 404) { + vm.avatarFile.serverErrorMessage = "File not found"; + } + else if (status == 400) { + //it's a validation error + vm.avatarFile.serverErrorMessage = evt.message; + } + else { + //it's an unhandled error + //if the service returns a detailed error + if (evt.InnerException) { + vm.avatarFile.serverErrorMessage = evt.InnerException.ExceptionMessage; + + //Check if its the common "too large file" exception + if (evt.InnerException.StackTrace && evt.InnerException.StackTrace.indexOf("ValidateRequestEntityLength") > 0) { + vm.avatarFile.serverErrorMessage = "File too large to upload"; + } + + } else if (evt.Message) { + vm.avatarFile.serverErrorMessage = evt.Message; + } + } + }); + } + + function makeBreadcrumbs() { + vm.breadcrumbs = [ + { + "name": vm.labels.users, + "path": "/users/users/overview", + "subView": "users" + }, + { + "name": vm.user.name + } + ]; + } + + function setUserDisplayState() { + vm.user.userDisplayState = usersHelper.getUserStateFromValue(vm.user.userState); + } + + init(); + } + angular.module("umbraco").controller("Umbraco.Editors.Users.UserController", UserEditController); +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/users/user.html b/src/Umbraco.Web.UI.Client/src/views/users/user.html new file mode 100644 index 0000000000..84e50a3360 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/users/user.html @@ -0,0 +1,366 @@ +
+ + + +
+ + + + + + + + +
+ +
+ +
+ +
+
+
+ Profile +
+
+
+ + + + Required + + + + + + Required + + + + + + Required + + +
+
+ +
+
+
+ Access +
+
+
+ + + + + + + + Add + + + + + + + + + + + + + + Add + + + + + + + + + + + + + + Add + + + + +
+
+
+ +
+ +
+ +
+ + + + + + + + + + + + +
+ +
+
+ Status:
+
+ + {{vm.user.userDisplayState.name}} + +
+
+ +
+
+ Last login:
+
+ {{ vm.user.lastLoginDate }} + {{ vm.user.name }} has not logged in yet +
+
+ +
+
+ + +
+ +
+ + +
+ + + + + + + + + + + + + + +
+


Password reset to value: {{vm.user.resetPasswordValue}}

+
+ +
+ +
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js new file mode 100644 index 0000000000..e7331de240 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js @@ -0,0 +1,102 @@ +(function () { + "use strict"; + + function UserGroupsController($scope, $timeout, $location, userGroupsResource, formHelper, localizationService) { + + var vm = this; + + vm.userGroups = []; + vm.selection = []; + + vm.createUserGroup = createUserGroup; + vm.clickUserGroup = clickUserGroup; + vm.clearSelection = clearSelection; + vm.selectUserGroup = selectUserGroup; + vm.deleteUserGroups = deleteUserGroups; + + function onInit() { + + vm.loading = true; + + // Get usergroups + userGroupsResource.getUserGroups().then(function (userGroups) { + vm.userGroups = userGroups; + vm.loading = false; + }); + + } + + function createUserGroup() { + // clear all query params + $location.search({}); + // go to create user group + $location.path('users/users/group/-1').search("create", "true");; + } + + function clickUserGroup(userGroup) { + if (vm.selection.length > 0) { + selectUserGroup(userGroup, vm.selection); + } else { + goToUserGroup(userGroup.id); + } + } + + function selectUserGroup(userGroup, selection, event) { + + if (userGroup.selected) { + var index = selection.indexOf(userGroup.id); + selection.splice(index, 1); + userGroup.selected = false; + } else { + userGroup.selected = true; + vm.selection.push(userGroup.id); + } + + if(event){ + event.preventDefault(); + event.stopPropagation(); + } + } + + function deleteUserGroups() { + + if(vm.selection.length > 0) { + + localizationService.localize("defaultdialogs_confirmdelete") + .then(function(value) { + + var confirmResponse = confirm(value); + + if (confirmResponse === true) { + userGroupsResource.deleteUserGroups(vm.selection).then(function (data) { + clearSelection(); + onInit(); + formHelper.showNotifications(data); + }, function(error) { + formHelper.showNotifications(error.data); + }); + } + + }); + + } + } + + function clearSelection() { + angular.forEach(vm.userGroups, function (userGroup) { + userGroup.selected = false; + }); + vm.selection = []; + } + + function goToUserGroup(userGroupId) { + $location.path('users/users/group/' + userGroupId).search("create", null); + } + + onInit(); + + } + + angular.module("umbraco").controller("Umbraco.Editors.Users.GroupsController", UserGroupsController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html new file mode 100644 index 0000000000..ed4d92b099 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.html @@ -0,0 +1,86 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + {{ vm.selection.length }} of {{ vm.userGroups.length }} selected + + + + + + + + + + +
+
+ Groups ({{vm.userGroups.length}}) +
+
+ + + +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js new file mode 100644 index 0000000000..96db5e07b1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js @@ -0,0 +1,614 @@ +(function () { + "use strict"; + + function UsersController($scope, $timeout, $location, usersResource, userGroupsResource, localizationService, contentEditingHelper, usersHelper, formHelper, notificationsService) { + + var vm = this; + var localizeSaving = localizationService.localize("general_saving"); + + vm.page = {}; + vm.users = []; + vm.userGroups = []; + vm.userStates = []; + vm.selection = []; + vm.newUser = {}; + vm.usersOptions = {}; + vm.userSortData = [ + { label: "Name (A-Z)", key: "Name", direction: "Ascending" }, + { label: "Name (Z-A)", key: "Name", direction: "Descending" }, + { label: "Newest", key: "CreateDate", direction: "Descending" }, + { label: "Oldest", key: "CreateDate", direction: "Ascending" }, + { label: "Last login", key: "LastLoginDate", direction: "Descending" } + ]; + vm.userStatesFilter = []; + vm.newUser.userGroups = []; + vm.usersViewState = 'overview'; + + vm.selectedBulkUserGroups = []; + + vm.allowDisableUser = true; + vm.allowEnableUser = true; + vm.allowSetUserGroup = true; + + vm.layouts = [ + { + "icon": "icon-thumbnails-small", + "path": "1", + "selected": true + }, + { + "icon": "icon-list", + "path": "2", + "selected": true + } + ]; + + vm.activeLayout = { + "icon": "icon-thumbnails-small", + "path": "1", + "selected": true + }; + + //don't set this if no email is configured + if (Umbraco.Sys.ServerVariables.umbracoSettings.emailServerConfigured) { + vm.defaultButton = { + labelKey: "user_inviteUser", + handler: function () { + vm.setUsersViewState('inviteUser'); + } + }; + } + + vm.subButtons = [ + { + labelKey: "user_createUser", + handler: function () { + vm.setUsersViewState('createUser'); + } + } + ]; + + vm.toggleFilter = toggleFilter; + vm.setUsersViewState = setUsersViewState; + vm.selectLayout = selectLayout; + vm.selectUser = selectUser; + vm.clearSelection = clearSelection; + vm.clickUser = clickUser; + vm.disableUsers = disableUsers; + vm.enableUsers = enableUsers; + vm.openBulkUserGroupPicker = openBulkUserGroupPicker; + vm.openUserGroupPicker = openUserGroupPicker; + vm.removeSelectedUserGroup = removeSelectedUserGroup; + vm.selectAll = selectAll; + vm.areAllSelected = areAllSelected; + vm.searchUsers = searchUsers; + vm.getFilterName = getFilterName; + vm.setUserStatesFilter = setUserStatesFilter; + vm.setUserGroupFilter = setUserGroupFilter; + vm.setOrderByFilter = setOrderByFilter; + vm.changePageNumber = changePageNumber; + vm.createUser = createUser; + vm.inviteUser = inviteUser; + vm.getSortLabel = getSortLabel; + vm.toggleNewUserPassword = toggleNewUserPassword; + vm.copySuccess = copySuccess; + vm.copyError = copyError; + vm.goToUser = goToUser; + + function init() { + + vm.usersOptions.orderBy = "Name"; + vm.usersOptions.orderDirection = "Ascending"; + + // Get users + getUsers(); + + // Get user groups + userGroupsResource.getUserGroups().then(function (userGroups) { + vm.userGroups = userGroups; + }); + + } + + function getSortLabel(sortKey, sortDirection) { + var found = _.find(vm.userSortData, + function (i) { + return i.key === sortKey && i.direction === sortDirection; + }); + return found ? found.label : sortKey; + } + + function toggleFilter(type) { + // hack: on-outside-click prevents us from closing the dropdown when clicking on another link + // so I had to do this manually + switch (type) { + case "state": + vm.page.showStatusFilter = !vm.page.showStatusFilter; + vm.page.showGroupFilter = false; + vm.page.showOrderByFilter = false; + break; + case "group": + vm.page.showGroupFilter = !vm.page.showGroupFilter; + vm.page.showStatusFilter = false; + vm.page.showOrderByFilter = false; + break; + case "orderBy": + vm.page.showOrderByFilter = !vm.page.showOrderByFilter; + vm.page.showStatusFilter = false; + vm.page.showGroupFilter = false; + break; + } + } + + function setUsersViewState(state) { + + if (state === "createUser") { + clearAddUserForm(); + } + + vm.usersViewState = state; + } + + function selectLayout(selectedLayout) { + angular.forEach(vm.layouts, function (layout) { + layout.active = false; + }); + selectedLayout.active = true; + vm.activeLayout = selectedLayout; + } + + function selectUser(user, selection, event) { + + // prevent the current user to be selected + if (!user.isCurrentUser) { + + if (user.selected) { + var index = selection.indexOf(user.id); + selection.splice(index, 1); + user.selected = false; + } else { + user.selected = true; + vm.selection.push(user.id); + } + + setBulkActions(vm.users); + + if (event) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + + function clearSelection() { + angular.forEach(vm.users, function (user) { + user.selected = false; + }); + vm.selection = []; + } + + function clickUser(user) { + if (vm.selection.length > 0) { + selectUser(user, vm.selection); + } else { + goToUser(user.id); + } + } + + function disableUsers() { + vm.disableUserButtonState = "busy"; + usersResource.disableUsers(vm.selection).then(function (data) { + // update userState + angular.forEach(vm.selection, function (userId) { + var user = getUserFromArrayById(userId, vm.users); + if (user) { + user.userState = 1; + } + }); + // show the correct badges + setUserDisplayState(vm.users); + + formHelper.showNotifications(data); + + vm.disableUserButtonState = "init"; + clearSelection(); + + }, function (error) { + vm.disableUserButtonState = "error"; + formHelper.showNotifications(error.data); + }); + } + + function enableUsers() { + vm.enableUserButtonState = "busy"; + usersResource.enableUsers(vm.selection).then(function (data) { + // update userState + angular.forEach(vm.selection, function (userId) { + var user = getUserFromArrayById(userId, vm.users); + if (user) { + user.userState = 0; + } + }); + // show the correct badges + setUserDisplayState(vm.users); + // show notification + formHelper.showNotifications(data); + vm.enableUserButtonState = "init"; + clearSelection(); + }, function (error) { + vm.enableUserButtonState = "error"; + formHelper.showNotifications(error.data); + }); + } + + function getUserFromArrayById(userId, users) { + return _.find(users, function (u) { return u.id === userId }); + } + + function openBulkUserGroupPicker(event) { + var firstSelectedUser = getUserFromArrayById(vm.selection[0], vm.users); + + vm.selectedBulkUserGroups = _.clone(firstSelectedUser.userGroups); + + vm.userGroupPicker = { + title: "Select user groups", + view: "usergrouppicker", + selection: vm.selectedBulkUserGroups, + closeButtonLabel: "Cancel", + show: true, + submit: function (model) { + usersResource.setUserGroupsOnUsers(model.selection, vm.selection).then(function (data) { + // sorting to ensure they show up in right order when updating the UI + vm.selectedBulkUserGroups.sort(function (a, b) { + return a.alias > b.alias ? 1 : a.alias < b.alias ? -1 : 0; + }); + // apply changes to UI + _.each(vm.selection, + function (userId) { + var user = getUserFromArrayById(userId, vm.users); + user.userGroups = vm.selectedBulkUserGroups; + }); + vm.selectedBulkUserGroups = []; + vm.userGroupPicker.show = false; + vm.userGroupPicker = null; + formHelper.showNotifications(data); + clearSelection(); + }, function (error) { + formHelper.showNotifications(error.data); + }); + }, + close: function (oldModel) { + vm.selectedBulkUserGroups = []; + vm.userGroupPicker.show = false; + vm.userGroupPicker = null; + } + }; + } + + function openUserGroupPicker(event) { + vm.userGroupPicker = { + title: "Select user groups", + view: "usergrouppicker", + selection: vm.newUser.userGroups, + closeButtonLabel: "Cancel", + show: true, + submit: function (model) { + // apply changes + if (model.selection) { + vm.newUser.userGroups = model.selection; + } + vm.userGroupPicker.show = false; + vm.userGroupPicker = null; + }, + close: function (oldModel) { + // rollback on close + if (oldModel.selection) { + vm.newUser.userGroups = oldModel.selection; + } + vm.userGroupPicker.show = false; + vm.userGroupPicker = null; + } + }; + } + + function removeSelectedUserGroup(index, selection) { + selection.splice(index, 1); + } + + function selectAll() { + if (areAllSelected()) { + vm.selection = []; + angular.forEach(vm.users, function (user) { + user.selected = false; + }); + } else { + // clear selection so we don't add the same user twice + vm.selection = []; + // select all users + angular.forEach(vm.users, function (user) { + // prevent the current user to be selected + if (!user.isCurrentUser) { + user.selected = true; + vm.selection.push(user.id); + } + }); + } + } + + function areAllSelected() { + // we need to check if the current user is part of the selection and + // subtract the user from the total selection to find out if all users are selected + var includesCurrentUser = vm.users.some(function (user) { return user.isCurrentUser === true; }); + + if (includesCurrentUser) { + if (vm.selection.length === vm.users.length - 1) { return true; } + } else { + if (vm.selection.length === vm.users.length) { return true; } + } + } + + var search = _.debounce(function () { + $scope.$apply(function () { + getUsers(); + }); + }, 500); + + function searchUsers() { + search(); + } + + function getFilterName(array) { + var name = "All"; + var found = false; + angular.forEach(array, function (item) { + if (item.selected) { + if (!found) { + name = item.name + found = true; + } else { + name = name + ", " + item.name; + } + } + }); + return name; + } + + function setUserStatesFilter(userState) { + + if (!vm.usersOptions.userStates) { + vm.usersOptions.userStates = []; + } + + //If the selection is "ALL" then we need to unselect everything else since this is an 'odd' filter + if (userState.key === "All") { + angular.forEach(vm.userStatesFilter, function (i) { + i.selected = false; + }); + //we can't unselect All + userState.selected = true; + //reset the selection passed to the server + vm.usersOptions.userStates = []; + } + else { + angular.forEach(vm.userStatesFilter, function (i) { + if (i.key === "All") { + i.selected = false; + } + }); + var indexOfAll = vm.usersOptions.userStates.indexOf("All"); + if (indexOfAll >= 0) { + vm.usersOptions.userStates.splice(indexOfAll, 1); + } + } + + if (userState.selected) { + vm.usersOptions.userStates.push(userState.key); + } + else { + var index = vm.usersOptions.userStates.indexOf(userState.key); + vm.usersOptions.userStates.splice(index, 1); + } + + getUsers(); + } + + function setUserGroupFilter(userGroup) { + + if (!vm.usersOptions.userGroups) { + vm.usersOptions.userGroups = []; + } + + if (userGroup.selected) { + vm.usersOptions.userGroups.push(userGroup.alias); + } else { + var index = vm.usersOptions.userGroups.indexOf(userGroup.alias); + vm.usersOptions.userGroups.splice(index, 1); + } + + getUsers(); + } + + function setOrderByFilter(value, direction) { + vm.usersOptions.orderBy = value; + vm.usersOptions.orderDirection = direction; + getUsers(); + } + + function changePageNumber(pageNumber) { + vm.usersOptions.pageNumber = pageNumber; + getUsers(); + } + + function createUser(addUserForm) { + + if (formHelper.submitForm({ formCtrl: addUserForm, scope: $scope, statusMessage: "Saving..." })) { + + vm.newUser.id = -1; + vm.newUser.parentId = -1; + vm.page.createButtonState = "busy"; + + usersResource.createUser(vm.newUser) + .then(function (saved) { + vm.page.createButtonState = "success"; + vm.newUser = saved; + setUsersViewState('createUserSuccess'); + getUsers(); + }, function (err) { + formHelper.handleError(err); + vm.page.createButtonState = "error"; + }); + } + + } + + function inviteUser(addUserForm) { + + if (formHelper.submitForm({ formCtrl: addUserForm, scope: $scope, statusMessage: "Saving..." })) { + vm.newUser.id = -1; + vm.newUser.parentId = -1; + vm.page.createButtonState = "busy"; + + usersResource.inviteUser(vm.newUser) + .then(function (saved) { + //success + vm.page.createButtonState = "success"; + vm.newUser = saved; + setUsersViewState('inviteUserSuccess'); + getUsers(); + }, function (err) { + //error + formHelper.handleError(err); + vm.page.createButtonState = "error"; + }); + } + + } + + function toggleNewUserPassword() { + vm.newUser.showPassword = !vm.newUser.showPassword; + } + + // copy to clip board success + function copySuccess() { + vm.page.copyPasswordButtonState = "success"; + } + + // copy to clip board error + function copyError() { + vm.page.copyPasswordButtonState = "error"; + } + + function goToUser(userId) { + $location.path('users/users/user/' + userId); + } + + // helpers + function getUsers() { + + vm.loading = true; + + // Get users + usersResource.getPagedResults(vm.usersOptions).then(function (data) { + + vm.users = data.items; + + vm.usersOptions.pageNumber = data.pageNumber; + vm.usersOptions.pageSize = data.pageSize; + vm.usersOptions.totalItems = data.totalItems; + vm.usersOptions.totalPages = data.totalPages; + + formatDates(vm.users); + setUserDisplayState(vm.users); + vm.userStatesFilter = usersHelper.getUserStatesFilter(data.userStates); + + vm.loading = false; + + }, function (error) { + + vm.loading = false; + + }); + } + + function setUserDisplayState(users) { + angular.forEach(users, function (user) { + user.userDisplayState = usersHelper.getUserStateFromValue(user.userState); + }); + } + + function formatDates(users) { + angular.forEach(users, function (user) { + if (user.lastLoginDate) { + user.formattedLastLogin = moment(user.lastLoginDate).format("MMMM Do YYYY, HH:mm"); + } + }); + } + + function setBulkActions(users) { + + // reset all states + vm.allowDisableUser = true; + vm.allowEnableUser = true; + vm.allowSetUserGroup = true; + + var firstSelectedUserGroups; + + angular.forEach(users, function (user) { + + if (!user.selected) { + return; + } + + // if the current user is selected prevent any bulk actions with the user included + if (user.isCurrentUser) { + vm.allowDisableUser = false; + vm.allowEnableUser = false; + vm.allowSetUserGroup = false; + return; + } + + if (user.userDisplayState && user.userDisplayState.key === "Disabled") { + vm.allowDisableUser = false; + } + + if (user.userDisplayState && user.userDisplayState.key === "Active") { + vm.allowEnableUser = false; + } + + if (user.userDisplayState && user.userDisplayState.key === "Invited") { + vm.allowEnableUser = false; + } + + // store the user group aliases of the first selected user + if (!firstSelectedUserGroups) { + firstSelectedUserGroups = user.userGroups.map(function (ug) { return ug.alias; }); + vm.allowSetUserGroup = true; + } else if (vm.allowSetUserGroup === true) { + // for 2nd+ selected user, compare the user group aliases to determine if we should allow bulk editing. + // we don't allow bulk editing of users not currently having the same assigned user groups, as we can't + // really support that in the user group picker. + var userGroups = user.userGroups.map(function (ug) { return ug.alias; }); + if (_.difference(firstSelectedUserGroups, userGroups).length > 0) { + vm.allowSetUserGroup = false; + } + } + }); + } + + function clearAddUserForm() { + // clear form data + vm.newUser.name = ""; + vm.newUser.email = ""; + vm.newUser.userGroups = []; + vm.newUser.message = ""; + // clear button state + vm.page.createButtonState = "init"; + } + + init(); + + } + + angular.module("umbraco").controller("Umbraco.Editors.Users.UsersController", UsersController); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html new file mode 100644 index 0000000000..c938329926 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.html @@ -0,0 +1,519 @@ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ vm.selection.length }} of {{ vm.users.length }} selected + + + + + +
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+ Users ({{vm.usersOptions.totalItems}}) +
+ + + +
+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + + + NameUser groupLast loginStatus
+
+ + +
+
+ + + {{user.name}}{{ userGroup.name }}, {{ user.formattedLastLogin }} + + {{ user.userDisplayState.name }} + +
+ +
+ + +
+ + +
+ +
+ + +
+ + + + Back to users + + + +
+
+
+
+

+ Invite User +

+

+ +

+
+
+

+ Create user +

+

+ +

+
+
+ + + + Required + + + + + + Required + + + + + + + + + + Add + + + + + + + Required + + + + + + + + + +
+ +
+
+ + +
+ + + + Back to users + + + +
+
+ + +
+ + +

+ {{vm.newUser.name | umbWordLimit:1}} + has been created +

+
+ +

+ + +
+ +
+
{{vm.newUser.resetPasswordValue}}
+
••••••••
+
+ + + + + + +
+
+
+ + +
+ + + + +
+ +
+
+
+ + +
+ + + Back to users + + + +
+
+ + +
+ + +

+ {{vm.newUser.name | umbWordLimit:1}} + has been created +

+
+ +

+ + +
+ + + + +
+ +
+
+ +
+ + + + +
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/test/config/karma.conf.js b/src/Umbraco.Web.UI.Client/test/config/karma.conf.js index ede7c20538..0e06085ff4 100644 --- a/src/Umbraco.Web.UI.Client/test/config/karma.conf.js +++ b/src/Umbraco.Web.UI.Client/test/config/karma.conf.js @@ -32,7 +32,7 @@ module.exports = function(karma) { 'test/config/app.unit.js', 'src/common/mocks/umbraco.servervariables.js', - 'src/common/directives/*.js', + 'src/common/directives/**/*.js', 'src/common/filters/*.js', 'src/common/services/*.js', 'src/common/security/*.js', diff --git a/src/Umbraco.Web.UI.Client/test/unit/app/content/create-content-controller.spec.js b/src/Umbraco.Web.UI.Client/test/unit/app/content/create-content-controller.spec.js new file mode 100644 index 0000000000..46f5a7bbc9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/test/unit/app/content/create-content-controller.spec.js @@ -0,0 +1,124 @@ +(function() { + + describe("create content dialog", + function() { + + var scope, + allowedTypes = [ + { id: 1, alias: "x" }, + { id: 2, alias: "y", blueprints: { "1": "a", "2": "b" } } + ], + location, + searcher, + controller, + rootScope, + contentTypeResource; + + beforeEach(module("umbraco")); + + function initialize(blueprintConfig) { + scope = rootScope.$new(); + scope.currentNode = { id: 1234 }; + var dependencies = { + $scope: scope, + contentTypeResource: contentTypeResource + }; + if (blueprintConfig) { + dependencies.blueprintConfig = blueprintConfig; + } + controller("Umbraco.Editors.Content.CreateController", + dependencies); + + scope.$digest(); + + } + + beforeEach(inject(function($controller, $rootScope, $q, $location) { + contentTypeResource = { + getAllowedTypes: function() { + var def = $q.defer(); + def.resolve(allowedTypes); + return def.promise; + } + }; + location = $location; + controller = $controller; + rootScope = $rootScope; + + searcher = { search: function() {} }; + spyOn(location, "path").andReturn(searcher); + spyOn(searcher, "search"); + + initialize(); + })); + + it("shows available child document types for the given node", + function() { + expect(scope.selectContentType).toBe(true); + expect(scope.allowedTypes).toBe(allowedTypes); + }); + + it("creates content directly when there are no blueprints", + function() { + scope.createOrSelectBlueprintIfAny(allowedTypes[0]); + + expect(location.path).toHaveBeenCalledWith("/content/content/edit/1234"); + expect(searcher.search).toHaveBeenCalledWith("doctype=x&create=true"); + }); + + it("shows list of blueprints when there are some", + function() { + scope.createOrSelectBlueprintIfAny(allowedTypes[1]); + expect(scope.selectContentType).toBe(false); + expect(scope.selectBlueprint).toBe(true); + expect(scope.docType).toBe(allowedTypes[1]); + }); + + it("creates blueprint when selected", + function() { + scope.createOrSelectBlueprintIfAny(allowedTypes[1]); + scope.createFromBlueprint("1"); + + expect(location.path).toHaveBeenCalledWith("/content/content/edit/1234"); + expect(searcher.search).toHaveBeenCalledWith("doctype=y&create=true&blueprintId=1"); + }); + + it("skips selection and creates first blueprint when configured to", + function() { + initialize({ + allowBlank: true, + skipSelect: true + }); + + scope.createOrSelectBlueprintIfAny(allowedTypes[1]); + + expect(location.path).toHaveBeenCalledWith("/content/content/edit/1234"); + expect(searcher.search).toHaveBeenCalledWith("doctype=y&create=true&blueprintId=1"); + }); + + it("allows blank to be selected", + function() { + expect(scope.allowBlank).toBe(true); + }); + + it("creates blank when selected", + function() { + scope.createBlank(allowedTypes[1]); + + expect(location.path).toHaveBeenCalledWith("/content/content/edit/1234"); + expect(searcher.search).toHaveBeenCalledWith("doctype=y&create=true"); + }); + + it("hides blank when configured to", + function() { + initialize({ + allowBlank: false, + skipSelect: false + }); + + expect(scope.allowBlank).toBe(false); + }); + + }); + +}()); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/test/unit/app/content/edit-content-controller.spec.js b/src/Umbraco.Web.UI.Client/test/unit/app/content/edit-content-controller.spec.js index 0d9b8a29e2..ae3c33a19a 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/app/content/edit-content-controller.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/app/content/edit-content-controller.spec.js @@ -1,12 +1,16 @@ +// The content editor has been wrapped in a directive +// The current setup will have problems with loading the HTML etc. +// These tests are therefore ignored for now. + describe('edit content controller tests', function () { - var scope, controller, routeParams, httpBackend; + var scope, controller, routeParams, httpBackend, wasSaved, q; routeParams = {id: 1234, create: false}; beforeEach(module('umbraco')); //inject the contentMocks service - beforeEach(inject(function ($rootScope, $controller, angularHelper, $httpBackend, contentMocks, entityMocks, mocksUtils, localizationMocks) { - + beforeEach(inject(function ($rootScope, $q, $controller, $compile, angularHelper, $httpBackend, contentMocks, entityMocks, mocksUtils, localizationMocks) { + q = $q; //for these tests we don't want any authorization to occur mocksUtils.disableAuth(); @@ -20,27 +24,32 @@ describe('edit content controller tests', function () { localizationMocks.register(); //this controller requires an angular form controller applied to it - scope.contentForm = angularHelper.getNullForm("contentForm"); - - controller = $controller('Umbraco.Editors.Content.EditController', { + scope.contentForm = angularHelper.getNullForm("contentForm"); + + var deferred = $q.defer(); + wasSaved = false; + scope.saveMethod = function() { wasSaved = true; }; + scope.getMethod = function() { return function() { return deferred.promise; } }; + scope.treeAlias = "content"; + + controller = $controller('Umbraco.Editors.Content.EditorDirectiveController', { $scope: scope, $routeParams: routeParams }); //For controller tests its easiest to have the digest and flush happen here //since its intially always the same $http calls made - - //scope.$digest resolves the promise against the httpbackend - scope.$digest(); - //httpbackend.flush() resolves all request against the httpbackend - //to fake a async response, (which is what happens on a real setup) - httpBackend.flush(); + + // Resolve the get method + deferred.resolve(mocksUtils.getMockContent(1234)); + + //scope.$digest resolves the promise + scope.$digest(); })); describe('content edit controller save and publish', function () { - it('it should have an content object', function() { - + it('it should have an content object', function() { //controller should have a content object expect(scope.content).toNotBe(undefined); diff --git a/src/Umbraco.Web.UI/umbraco/images/actions/sprites.png b/src/Umbraco.Web.UI/umbraco/images/actions/sprites.png deleted file mode 100644 index 8a3ed9b934e88ab3a1ac7c6b75629a865f32c233..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12301 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 diff --git a/src/Umbraco.Web.UI/umbraco_client/Application/Extensions.js b/src/Umbraco.Web.UI/umbraco_client/Application/Extensions.js index 63870fad08..9884df1c80 100644 --- a/src/Umbraco.Web.UI/umbraco_client/Application/Extensions.js +++ b/src/Umbraco.Web.UI/umbraco_client/Application/Extensions.js @@ -26,7 +26,24 @@ } }; } + + if (!window.location.getParams) { + var pl = /\+/g; // Regex for replacing addition symbol with a space + var search = /([^&=]+)=?([^&]*)/g; + var decode = function(s) { return decodeURIComponent(s.replace(pl, " ")); }; + + window.location.getParams = function() { + var match; + var query = window.location.search.substring(1); + var urlParams = {}; + while (match = search.exec(query)) + urlParams[decode(match[1])] = decode(match[2]); + + return urlParams; + } + } + if (!String.prototype.startsWith) { String.prototype.startsWith = function (str) { ///startsWith extension method for string @@ -366,10 +383,20 @@ function getCookie(name) { var value = "; " + document.cookie; var parts = value.split("; " + name + "="); - if (parts.length === 2) return parts.pop().split(";").shift(); + if (parts.length === 2) + return parts.pop().split(";").shift(); + return null; } - xhr.setRequestHeader("X-XSRF-TOKEN", getCookie("XSRF-TOKEN")); + var cookieVal = getCookie("XSRF-TOKEN"); + if (cookieVal) { + xhr.setRequestHeader("X-XSRF-TOKEN", cookieVal); + } + + var queryString = window.location.getParams(); + if (queryString.umbDebug === "true") { + xhr.setRequestHeader("X-UMB-DEBUG", cookieVal); + } } }); diff --git a/src/Umbraco.Web.UI/umbraco_client/Application/UmbracoApplicationActions.js b/src/Umbraco.Web.UI/umbraco_client/Application/UmbracoApplicationActions.js index f8d1061cbe..0fc433a98e 100644 --- a/src/Umbraco.Web.UI/umbraco_client/Application/UmbracoApplicationActions.js +++ b/src/Umbraco.Web.UI/umbraco_client/Application/UmbracoApplicationActions.js @@ -1,7 +1,6 @@ /// /// /// -/// /// Umbraco.Sys.registerNamespace("Umbraco.Application"); @@ -38,27 +37,7 @@ Umbraco.Application.Actions = function() { } else alert(msg); }, - - launchHelp: function(lang, userType) { - /// Launches the contextual help window - var rightUrl = UmbClientMgr.contentFrame().document.location.href.split("\/"); - if (rightUrl.length > 0) { - rightUrl = rightUrl[rightUrl.length - 1]; - } - if (rightUrl.indexOf("?") > 0) { - rightUrl = rightUrl.substring(0, rightUrl.indexOf("?")); - } - var url = "/umbraco/helpRedirect.aspx?Application=" + this._currApp + '&ApplicationURL=' + rightUrl + '&Language=' + lang + "&UserType=" + userType; - window.open(url); - return false; - }, - - launchAbout: function() { - /// Launches the about Umbraco window - UmbClientMgr.openModalWindow("dialogs/about.aspx", UmbClientMgr.uiKeys()['general_about'], true, 450, 390); - return false; - }, - + launchCreateWizard: function() { /// Launches the create content wizard @@ -208,15 +187,7 @@ Umbraco.Application.Actions = function() { } }, - - actionRights: function() { - /// - - if (UmbClientMgr.mainTree().getActionNode().nodeId != '-1' && UmbClientMgr.mainTree().getActionNode().nodeType != '') { - UmbClientMgr.openModalWindow("dialogs/cruds.aspx?id=" + UmbClientMgr.mainTree().getActionNode().nodeId + '&rnd=' + this._utils.generateRandom(), uiKeys['actions_rights'], true, 800, 300); - } - }, - + actionProtect: function() { /// @@ -304,10 +275,7 @@ Umbraco.Application.Actions = function() { } else if (actionNode.nodeType == "users") { UmbClientMgr.openModalWindow("create.aspx?nodeId=" + actionNode.nodeId + "&nodeType=" + actionNode.nodeType + "&nodeName=" + actionNode.nodeName + '&rnd=' + this._utils.generateRandom(), uiKeys['actions_create'], true, 480, 380); - } - else if (actionNode.nodeType == "initpython" || actionNode.nodeType == "initdlrscripting") { - UmbClientMgr.openModalWindow("create.aspx?nodeId=" + actionNode.nodeId + "&nodeType=" + actionNode.nodeType + "&nodeName=" + actionNode.nodeName + '&rnd=' + this._utils.generateRandom(), uiKeys['actions_create'], true, 420, 380); - } + } else { UmbClientMgr.openModalWindow("create.aspx?nodeId=" + actionNode.nodeId + "&nodeType=" + actionNode.nodeType + "&nodeName=" + actionNode.nodeName + '&rnd=' + this._utils.generateRandom(), uiKeys['actions_create'], true, 420, 270); } @@ -329,14 +297,7 @@ Umbraco.Application.Actions = function() { UmbClientMgr.openModalWindow("dialogs/sendToTranslation.aspx?id=" + UmbClientMgr.mainTree().getActionNode().nodeId + '&rnd=' + this._utils.generateRandom(), uiKeys['actions_sendToTranslate'], true, 500, 470); } }, - - actionEmptyTranscan: function() { - /// - - if (UmbClientMgr.mainTree().getActionNode().nodeId != '-1' && UmbClientMgr.mainTree().getActionNode().nodeType != '') { - UmbClientMgr.openModalWindow("dialogs/emptyTrashcan.aspx?type=" + this._currApp, uiKeys['actions_emptyTrashcan'], true, 500, 220); - } - }, + actionImport: function() { /// @@ -415,21 +376,6 @@ Umbraco.Application.Actions = function() { }, - actionMove: function() { - /// - - if (UmbClientMgr.mainTree().getActionNode().nodeId != '-1' && UmbClientMgr.mainTree().getActionNode().nodeType != '') { - UmbClientMgr.openModalWindow("dialogs/moveOrCopy.aspx?app=" + this._currApp + "&mode=cut&id=" + UmbClientMgr.mainTree().getActionNode().nodeId + '&rnd=' + this._utils.generateRandom(), uiKeys['actions_move'], true, 500, 460); - } - }, - - actionCopy: function() { - /// - - if (UmbClientMgr.mainTree().getActionNode().nodeId != '-1' && UmbClientMgr.mainTree().getActionNode().nodeType != '') { - UmbClientMgr.openModalWindow("dialogs/moveOrCopy.aspx?app=" + this._currApp + "&mode=copy&id=" + UmbClientMgr.mainTree().getActionNode().nodeId + '&rnd=' + this._utils.generateRandom(), uiKeys['actions_copy'], true, 500, 470); - } - }, _debug: function(strMsg) { if (this._isDebug) { Sys.Debug.trace("AppActions: " + strMsg); diff --git a/src/Umbraco.Web.UI/umbraco_client/Editors/EditScript.js b/src/Umbraco.Web.UI/umbraco_client/Editors/EditScript.js deleted file mode 100644 index c1506b9ffd..0000000000 --- a/src/Umbraco.Web.UI/umbraco_client/Editors/EditScript.js +++ /dev/null @@ -1,116 +0,0 @@ -Umbraco.Sys.registerNamespace("Umbraco.Editors"); - -(function ($) { - - Umbraco.Editors.EditScript = base2.Base.extend({ - //private methods/variables - _opts: null, - - // Constructor - constructor: function(opts) { - // Merge options with default - this._opts = $.extend({ - - - // Default options go here - }, opts); - }, - - init: function () { - //setup UI elements - var self = this; - - //bind to the save event - this._opts.saveButton.click(function (event) { - event.preventDefault(); - self.doSubmit(); - }); - }, - - doSubmit: function () { - var self = this; - - var filename = this._opts.nameTxtBox.val(); - var codeval = this._opts.editorSourceElement.val(); - //if CodeMirror is not defined, then the code editor is disabled. - if (typeof (CodeMirror) != "undefined") { - codeval = UmbEditor.GetCode(); - } - - this.save( - filename, - self._opts.originalFileName, - codeval); - }, - - save: function (filename, oldName, contents) { - var self = this; - - $.post(self._opts.restServiceLocation + "SaveScript", - JSON.stringify({ - filename: filename, - oldName: oldName, - contents: contents - }), - function (e) { - if (e.success) { - self.submitSuccess(e); - } else { - self.submitFailure(e.message, e.header); - } - }); - }, - - submitSuccess: function (args) { - var msg = args.message; - var header = args.header; - var path = this._opts.treeSyncPath; - var pathChanged = false; - if (args.path) { - if (path != args.path) { - pathChanged = true; - } - path = args.path; - } - if (args.contents) { - UmbEditor.SetCode(args.contents); - } - - UmbClientMgr.mainTree().setActiveTreeType("scripts"); - if (pathChanged) { - // no! file is used in url so we need to redirect - //UmbClientMgr.mainTree().moveNode(this._opts.originalFileName, path); - //this._opts.treeSyncPath = args.path; - //this._opts.lttPathElement.prop("href", args.url).html(args.url); - - var qs = window.location.search; - if (qs.startsWith("?")) qs = qs.substring("?".length); - var qp1 = qs.split("&"); - var qp2 = []; - for (var i = 0; i < qp1.length; i++) - if (!qp1[i].startsWith("file=")) - qp2.push(qp1[i]); - - var location = window.location.pathname + "?" + qp2.join("&") + "&file=" + args.name; - UmbClientMgr.contentFrame(location); - - // need to do it after we navigate otherwise the navigation waits until the message timeout is done - top.UmbSpeechBubble.ShowMessage("save", header, msg); - } - else { - top.UmbSpeechBubble.ShowMessage("save", header, msg); - this._opts.lttPathElement.prop("href", args.url).html(args.url); - this._opts.originalFileName = args.name; - this._opts.treeSyncPath = args.path; - UmbClientMgr.mainTree().syncTree(path, true); - } - - //this._opts.lttPathElement.prop("href", args.url).html(args.url); - //this._opts.originalFileName = args.name; - }, - - submitFailure: function(err, header) { - top.UmbSpeechBubble.ShowMessage('error', header, err); - } - }); -})(jQuery); \ No newline at end of file diff --git a/src/Umbraco.Web.UI/umbraco_client/Editors/EditXslt.js b/src/Umbraco.Web.UI/umbraco_client/Editors/EditXslt.js index d17296a958..67f0259afb 100644 --- a/src/Umbraco.Web.UI/umbraco_client/Editors/EditXslt.js +++ b/src/Umbraco.Web.UI/umbraco_client/Editors/EditXslt.js @@ -37,7 +37,7 @@ codeVal = UmbEditor.GetCode(); } umbraco.presentation.webservices.codeEditorSave.SaveXslt( - fileName, self._opts.originalFileName, codeVal, self._opts.skipTestingCheckBox.is(':checked'), + fileName, self._opts.originalFileName, codeVal, true, function (t) { self.submitSucces(t); }, function (t) { self.submitFailure(t); }); diff --git a/src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/arrawBack.gif b/src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/arrawBack.gif deleted file mode 100644 index 9d3f0ca6869d1af01a28961dd171ec57bc826569..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 834 zcmZ?wbhEHbWM>dz_|C)t1poj4hm#=wC>RZa5fcK6KUo+V7?>DzKt2ZL2?h>%238Ik ij|~eBHggCo{R#gdf4GrP-f0R);KHNb68dZ`4AubXbQK2x diff --git a/src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/arrowForward.gif b/src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/arrowForward.gif deleted file mode 100644 index bf3f49e02463fa56ac1e3bf90a7fa8cb14e575de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 834 zcmZ?wbhEHbWM>dz_|C)t1poj4hm#=wC>RZa5fcK6KUo+V7?>DzKt2ZL2?h>%238Ik ij|~eBHggC|{nU;fa}+&IBQ df``db!9XI#sGq%6X<~@hWY2{S2U{2ztO2IrWT*fD diff --git a/src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/button/buttonbg.gif b/src/Umbraco.Web.UI/umbraco_client/scrollingmenu/images/button/buttonbg.gif deleted file mode 100644 index 6268a1bc0d8b6ae8fc753bf2b5f46e5e9106ef81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 273 zcmZ?wbhEHb6k`x)IKsg2|K9Tdm#6)IvHkz+egAJQ`v3OO|My4#KV19&!o>eqXa4_k z=Ku9M|L-jM|LMg4him@7-2MN?{Qu9k{J%K)|C0^>AFTHF&S$_26o0aS<#j+L$W8{< zz6902l*}%#RqJ%L%?fnRZ_c<=vF>%!!~X{o0!%cd`aPDsIGAHK-+y9)*V?GHi#p0q zzb$i}yrIHJt()(~ma4sCmiIpFh|ybg#j0_B73_2hs zAUhdY`xF%VQZl=OSFO|04l2+&zd7P=#k$u?PyQcB2vE_K>i1Z3;$V)|eE*BdUTdS) zDs_~dep}|+wV}dCty}EHma4sChW9?~h|$Zs@%~3m+>{r;|2H%!vA49gwYMvAbocc3 z^(nDUnmlFdR3(;~vu4kkqr|#k;iAQhm6(^WSh;GI64Sc%8#ZoKV%)lI`;HyzyLT%x GSOWm&o_o*$ diff --git a/src/Umbraco.Web/Editors/AuthenticationController.cs b/src/Umbraco.Web/Editors/AuthenticationController.cs index 702d1ee3d3..057c77cf04 100644 --- a/src/Umbraco.Web/Editors/AuthenticationController.cs +++ b/src/Umbraco.Web/Editors/AuthenticationController.cs @@ -315,7 +315,7 @@ namespace Umbraco.Web.Editors Logger.Warn("Could not unlock for user {0} - error {1}", () => model.UserId, () => unlockResult.Errors.First()); } - + var resetAccessFailedCountResult = await UserManager.ResetAccessFailedCountAsync(model.UserId); if (resetAccessFailedCountResult.Succeeded == false) { diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 7394a2d34b..608480ee70 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -35,7 +35,7 @@ using Umbraco.Web.UI; using Notification = Umbraco.Web.Models.ContentEditing.Notification; using Umbraco.Core.Persistence; using Umbraco.Core.Configuration.UmbracoSettings; - + namespace Umbraco.Web.Editors { /// diff --git a/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs b/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs index f80cd12516..f37fb833ec 100644 --- a/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs +++ b/src/Umbraco.Web/Models/ContentEditing/ContentTypeCompositionDisplay.cs @@ -7,7 +7,7 @@ using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; using Umbraco.Core.Models.Validation; - + namespace Umbraco.Web.Models.ContentEditing { public abstract class ContentTypeCompositionDisplay : ContentTypeBasic, INotificationModel @@ -29,7 +29,7 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "listViewEditorName")] [ReadOnly(true)] public string ListViewEditorName { get; set; } - + //Allowed child types [DataMember(Name = "allowedContentTypes")] public IEnumerable AllowedContentTypes { get; set; } @@ -44,14 +44,14 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "allowAsRoot")] public bool AllowAsRoot { get; set; } - + /// /// This is used to add custom localized messages/strings to the response for the app to use for localized UI purposes. /// [DataMember(Name = "notifications")] [ReadOnly(true)] public List Notifications { get; private set; } - + /// /// This is used for validation of a content item. /// @@ -66,7 +66,7 @@ namespace Umbraco.Web.Models.ContentEditing [ReadOnly(true)] public IDictionary Errors { get; set; } } - + [DataContract(Name = "contentType", Namespace = "")] public abstract class ContentTypeCompositionDisplay : ContentTypeCompositionDisplay where TPropertyTypeDisplay : PropertyTypeDisplay diff --git a/src/Umbraco.Web/Models/ContentEditing/DataTypeBasic.cs b/src/Umbraco.Web/Models/ContentEditing/DataTypeBasic.cs index 3834129ed0..31c4dcc6e8 100644 --- a/src/Umbraco.Web/Models/ContentEditing/DataTypeBasic.cs +++ b/src/Umbraco.Web/Models/ContentEditing/DataTypeBasic.cs @@ -1,6 +1,6 @@ using System.ComponentModel; using System.Runtime.Serialization; - + namespace Umbraco.Web.Models.ContentEditing { /// @@ -15,7 +15,7 @@ namespace Umbraco.Web.Models.ContentEditing [DataMember(Name = "isSystem")] [ReadOnly(true)] public bool IsSystemDataType { get; set; } - + [DataMember(Name = "group")] [ReadOnly(true)] public string Group { get; set; } diff --git a/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs b/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs index b7677a7225..46370cebea 100644 --- a/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs +++ b/src/Umbraco.Web/Security/Providers/UsersMembershipProvider.cs @@ -55,7 +55,7 @@ namespace Umbraco.Web.Security.Providers _defaultMemberTypeAlias = config["defaultUserTypeAlias"]; if (_defaultMemberTypeAlias.IsNullOrWhiteSpace()) { - throw new ProviderException("No default user type alias is specified in the web.config string. Please add a 'defaultUserTypeAlias' to the add element in the provider declaration in web.config"); + throw new ProviderException("No default MemberType alias is specified in the web.config string. Please add a 'defaultUserTypeAlias' to the add element in the provider declaration in web.config"); } _hasDefaultMember = true; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 9c8ac148cf..085d72baa9 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -308,7 +308,10 @@ + + + @@ -335,6 +338,7 @@ + diff --git a/src/Umbraco.Web/_Legacy/Actions/Action.cs b/src/Umbraco.Web/_Legacy/Actions/Action.cs index 2df788bef8..9ca5a52d86 100644 --- a/src/Umbraco.Web/_Legacy/Actions/Action.cs +++ b/src/Umbraco.Web/_Legacy/Actions/Action.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using Umbraco.Core.Logging; @@ -143,7 +144,7 @@ namespace Umbraco.Web._Legacy.Actions /// public static string ToString(List actions) { - string[] strMenu = Array.ConvertAll(actions.ToArray(), delegate(IAction a) { return (a.Letter.ToString()); }); + string[] strMenu = Array.ConvertAll(actions.ToArray(), delegate(IAction a) { return (a.Letter.ToString(CultureInfo.InvariantCulture)); }); return string.Join("", strMenu); } diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs b/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs index 1936cf3f61..51abac9998 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs @@ -1,110 +1,14 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using LightInject; -using Umbraco.Core.Composing; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { - internal class ActionCollectionBuilder : ICollectionBuilder - { - private static Func> _producer; - - public static ActionCollectionBuilder Register(IServiceContainer container) - { - // register the builder - per container - var builderLifetime = new PerContainerLifetime(); - container.Register(builderLifetime); - - // get the builder, get the collection lifetime - var builder = container.GetInstance(); - var collectionLifetime = builder.CollectionLifetime; - - // register the collection - special lifetime - // the lifetime here is custom ResettablePerContainerLifetime which will manage one - // single instance of the collection (much alike PerContainerLifetime) but can be resetted - // to force a new collection to be created. - // this is needed because of the weird things we do during install, where we'd use the - // infamous DirtyBackdoorToConfiguration to reset the ActionResolver way after Resolution - // had frozen. This has been replaced by the possibility here to set the producer at any - // time - but the builder is internal - and all this will be gone eventually. - container.Register(factory => factory.GetInstance().CreateCollection(), collectionLifetime); - - return builder; - } - - public ActionCollection CreateCollection() - { - var actions = new List(); - foreach (var type in _producer()) - { - var getter = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); - var instance = getter == null - ? Activator.CreateInstance(type) as IAction - : getter.GetValue(null, null) as IAction; - if (instance == null) continue; - actions.Add(instance); - } - return new ActionCollection(actions); - } - - public void SetProducer(Func> producer) - { - _producer = producer; - CollectionLifetime.Reset(); - } - - private ResettablePerContainerLifetime CollectionLifetime { get; } = new ResettablePerContainerLifetime(); - - private class ResettablePerContainerLifetime : ILifetime - { - private object _instance; - - public object GetInstance(Func createInstance, Scope scope) - { - // not dealing with disposable instances, actions are not disposable - return _instance ?? (_instance = createInstance()); - } - - public void Reset() - { - _instance = null; - } - } - } - - public class ActionCollection : BuilderCollectionBase - { - public ActionCollection(IEnumerable items) - : base(items) - { } - - internal T GetAction() - where T : IAction - { - return this.OfType().SingleOrDefault(); - } - } - - public interface IAction : IDiscoverable - { - char Letter { get; } - bool ShowInNotifier { get; } - bool CanBePermissionAssigned { get; } - string Icon { get; } - string Alias { get; } - string JsFunctionName { get; } - /// - /// A path to a supporting JavaScript file for the IAction. A script tag will be rendered out with the reference to the JavaScript file. - /// - string JsSource { get; } - } - /// /// This action is invoked when a domain is being assigned to a document /// + [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] public class ActionAssignDomain : IAction { /// diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionAudit.cs b/src/Umbraco.Web/_Legacy/Actions/ActionAudit.cs index 5b1508c0db..db780f4051 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionAudit.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionAudit.cs @@ -1,4 +1,6 @@ using System; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; using Umbraco.Web.UI.Pages; namespace Umbraco.Web._Legacy.Actions @@ -6,6 +8,7 @@ namespace Umbraco.Web._Legacy.Actions /// /// This action is invoked upon viewing audittrailing on a document /// + [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] public class ActionAudit : IAction { /// diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs b/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs index e8e8046092..1425b27917 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs @@ -1,4 +1,7 @@ -namespace Umbraco.Web._Legacy.Actions +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; + +namespace Umbraco.Web._Legacy.Actions { /// /// This action is used as a security constraint that grants a user the ability to view nodes in a tree @@ -9,6 +12,7 @@ /// granting a user this permission, the user is able to see the node in the tree but not edit the document. This may be used by other trees /// that support permissions in the future. /// + [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] public class ActionBrowse : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs b/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs index 7690c52431..eeb627a4ad 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when the document type of a piece of content is changed /// + [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] public class ActionChangeDocType : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs new file mode 100644 index 0000000000..1899d52f97 --- /dev/null +++ b/src/Umbraco.Web/_Legacy/Actions/ActionCollection.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Linq; +using Umbraco.Core.Composing; + +namespace Umbraco.Web._Legacy.Actions +{ + public class ActionCollection : BuilderCollectionBase + { + public ActionCollection(IEnumerable items) + : base(items) + { } + + internal T GetAction() + where T : IAction + { + return this.OfType().SingleOrDefault(); + } + } +} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs new file mode 100644 index 0000000000..ff767a03f3 --- /dev/null +++ b/src/Umbraco.Web/_Legacy/Actions/ActionCollectionBuilder.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using LightInject; +using Umbraco.Core.Composing; + +namespace Umbraco.Web._Legacy.Actions +{ + internal class ActionCollectionBuilder : ICollectionBuilder + { + private static Func> _producer; + + public static ActionCollectionBuilder Register(IServiceContainer container) + { + // register the builder - per container + var builderLifetime = new PerContainerLifetime(); + container.Register(builderLifetime); + + // get the builder, get the collection lifetime + var builder = container.GetInstance(); + var collectionLifetime = builder.CollectionLifetime; + + // register the collection - special lifetime + // the lifetime here is custom ResettablePerContainerLifetime which will manage one + // single instance of the collection (much alike PerContainerLifetime) but can be resetted + // to force a new collection to be created. + // this is needed because of the weird things we do during install, where we'd use the + // infamous DirtyBackdoorToConfiguration to reset the ActionResolver way after Resolution + // had frozen. This has been replaced by the possibility here to set the producer at any + // time - but the builder is internal - and all this will be gone eventually. + container.Register(factory => factory.GetInstance().CreateCollection(), collectionLifetime); + + return builder; + } + + public ActionCollection CreateCollection() + { + var actions = new List(); + foreach (var type in _producer()) + { + var getter = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); + var instance = getter == null + ? Activator.CreateInstance(type) as IAction + : getter.GetValue(null, null) as IAction; + if (instance == null) continue; + actions.Add(instance); + } + return new ActionCollection(actions); + } + + public void SetProducer(Func> producer) + { + _producer = producer; + CollectionLifetime.Reset(); + } + + private ResettablePerContainerLifetime CollectionLifetime { get; } = new ResettablePerContainerLifetime(); + + private class ResettablePerContainerLifetime : ILifetime + { + private object _instance; + + public object GetInstance(Func createInstance, Scope scope) + { + // not dealing with disposable instances, actions are not disposable + return _instance ?? (_instance = createInstance()); + } + + public void Reset() + { + _instance = null; + } + } + } +} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs index 7b167b9d52..a86b872d5f 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when copying a document, media, member /// + [ActionMetadata(Constants.Conventions.PermissionCategories.StructureCategory)] public class ActionCopy : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs b/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs new file mode 100644 index 0000000000..e00de39aea --- /dev/null +++ b/src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs @@ -0,0 +1,32 @@ +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; + +namespace Umbraco.Web._Legacy.Actions +{ + [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] + public class ActionCreateBlueprintFromContent : IAction + { + private static readonly ActionCreateBlueprintFromContent instance = new ActionCreateBlueprintFromContent(); + + public static ActionCreateBlueprintFromContent Instance + { + get { return instance; } + } + + public char Letter { get; private set; } + public bool ShowInNotifier { get; private set; } + public bool CanBePermissionAssigned { get; private set; } + public string Icon { get; private set; } + public string Alias { get; private set; } + public string JsFunctionName { get; private set; } + public string JsSource { get; private set; } + + public ActionCreateBlueprintFromContent() + { + Letter = 'ï'; + CanBePermissionAssigned = true; + Icon = "blueprint"; + Alias = "createblueprint"; + } + } +} diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs b/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs index c073090cf0..8b7f115c5a 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when a document, media, member is deleted /// + [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] public class ActionDelete : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs b/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs index 780048106d..cd37199506 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionMove.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked upon creation of a document, media, member /// + [ActionMetadata(Constants.Conventions.PermissionCategories.StructureCategory)] public class ActionMove : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs b/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs index 25089217d8..b6c1738bd9 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionNew.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked upon creation of a document /// + [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] public class ActionNew : IAction { /// diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs b/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs index 9a0ddc7299..8e2f765eeb 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when a document is protected or unprotected /// + [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] public class ActionProtect : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs index f029bb72bb..d48e91a504 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when a document is being published /// + [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] public class ActionPublish : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs index 8614df0650..31db2b02ba 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionRights.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when rights are changed on a document /// + [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] public class ActionRights : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs b/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs index fa6159fa31..587b1f1bbb 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when copying a document is being rolled back /// + [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] public class ActionRollback : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionSendToTranslate.cs b/src/Umbraco.Web/_Legacy/Actions/ActionSendToTranslate.cs index faa224ba58..021394b691 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionSendToTranslate.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionSendToTranslate.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when a send to translate request occurs /// + [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] public class ActionSendToTranslate : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs b/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs index f3ac8da000..5512c3222d 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionSort.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when children to a document, media, member is being sorted /// + [ActionMetadata(Constants.Conventions.PermissionCategories.StructureCategory)] public class ActionSort : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs b/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs index 1a0a14dd03..8a8536554f 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when children to a document is being sent to published (by an editor without publishrights) /// + [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] public class ActionToPublish : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs b/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs index a29cf1124f..e82137d475 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs @@ -1,10 +1,13 @@ using System; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when a translation occurs /// + [ActionMetadata(Constants.Conventions.PermissionCategories.AdministrationCategory)] public class ActionTranslate : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs b/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs index 87962bfe53..6661df8997 100644 --- a/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs +++ b/src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs @@ -1,11 +1,14 @@ using System; using Umbraco.Web.UI.Pages; +using Umbraco.Core; +using Umbraco.Core.CodeAnnotations; namespace Umbraco.Web._Legacy.Actions { /// /// This action is invoked when copying a document or media /// + [ActionMetadata(Constants.Conventions.PermissionCategories.ContentCategory)] public class ActionUpdate : IAction { //create singleton diff --git a/src/Umbraco.Web/_Legacy/Actions/IAction.cs b/src/Umbraco.Web/_Legacy/Actions/IAction.cs new file mode 100644 index 0000000000..410a407517 --- /dev/null +++ b/src/Umbraco.Web/_Legacy/Actions/IAction.cs @@ -0,0 +1,18 @@ +using Umbraco.Core.Composing; + +namespace Umbraco.Web._Legacy.Actions +{ + public interface IAction : IDiscoverable + { + char Letter { get; } + bool ShowInNotifier { get; } + bool CanBePermissionAssigned { get; } + string Icon { get; } + string Alias { get; } + string JsFunctionName { get; } + /// + /// A path to a supporting JavaScript file for the IAction. A script tag will be rendered out with the reference to the JavaScript file. + /// + string JsSource { get; } + } +} diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/Image.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/Image.cs index 801f689848..020a555fbc 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/Image.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/templateControls/Image.cs @@ -3,7 +3,7 @@ using System.Web.UI; using System.Web.UI.HtmlControls; using Umbraco.Core.Media; using Umbraco.Web.Media; - + namespace umbraco.presentation.templateControls { [Obsolete("This is no longer used and will be removed in future versions")] @@ -13,7 +13,7 @@ namespace umbraco.presentation.templateControls public string Field { get; set; } public string Provider { get; set; } public string Parameters { get; set; } - + protected override void Render(HtmlTextWriter writer) { int id; diff --git a/src/umbraco.presentation.targets b/src/umbraco.presentation.targets index 2a33705d6f..6eb87ad9fa 100644 --- a/src/umbraco.presentation.targets +++ b/src/umbraco.presentation.targets @@ -58,6 +58,10 @@ $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll + + + + $(VSWherePath)\Microsoft\VisualStudio\v15.0\Web\Microsoft.Web.Publishing.Tasks.dll

Eiv!E!Eo#U-X!l^TR*Jtj~VH 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∈)Tfzzb%Nq3zNPu0ss8}XdRdoI-)ygfC(W$A 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 X+p-rY%%{hdwRA)vYIrgAnrHvn#Z-AT diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js index 47901a533c..b503648317 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js @@ -57,12 +57,13 @@ Use this directive to render an umbraco button. The directive can be used to gen @param {callback} action The button action which should be performed when the button is clicked. @param {string=} href Url/Path to navigato to. @param {string=} type Set the button type ("button" or "submit"). -@param {string=} buttonStyle Set the style of the button. The directive uses the default bootstrap styles ("primary", "info", "success", "warning", "danger", "inverse", "link"). +@param {string=} buttonStyle Set the style of the button. The directive uses the default bootstrap styles ("primary", "info", "success", "warning", "danger", "inverse", "link", "block"). Pass in array to add multple styles [success,block]. @param {string=} state Set a progress state on the button ("init", "busy", "success", "error"). @param {string=} shortcut Set a keyboard shortcut for the button ("ctrl+c"). @param {string=} label Set the button label. @param {string=} labelKey Set a localization key to make a multi lingual button ("general_buttonText"). -@param {string=} icon Set a button icon. Can only be used when buttonStyle is "link". +@param {string=} icon Set a button icon. +@param {string=} size Set a button icon ("xs", "m", "l", "xl"). @param {boolean=} disabled Set to true to disable the button. **/ @@ -77,12 +78,37 @@ Use this directive to render an umbraco button. The directive can be used to gen function activate() { + scope.blockElement = false; + if (!scope.state) { scope.state = "init"; } if (scope.buttonStyle) { - scope.style = "btn-" + scope.buttonStyle; + + // make it possible to pass in multiple styles + if(scope.buttonStyle.startsWith("[") && scope.buttonStyle.endsWith("]")) { + + // when using an attr it will always be a string so we need to remove square brackets + // and turn it into and array + var withoutBrackets = scope.buttonStyle.replace(/[\[\]']+/g,''); + // split array by , + make sure to catch whitespaces + var array = withoutBrackets.split(/\s?,\s?/g); + + angular.forEach(array, function(item){ + scope.style = scope.style + " " + "btn-" + item; + if(item === "block") { + scope.blockElement = true; + } + }); + + } else { + scope.style = "btn-" + scope.buttonStyle; + if(scope.buttonStyle === "block") { + scope.blockElement = true; + } + } + } } @@ -122,7 +148,8 @@ Use this directive to render an umbraco button. The directive can be used to gen label: "@?", labelKey: "@?", icon: "@?", - disabled: "=" + disabled: "=", + size: "@?" } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js new file mode 100644 index 0000000000..a7bdd4b741 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbtoggle.directive.js @@ -0,0 +1,135 @@ +/** +@ngdoc directive +@name umbraco.directives.directive:umbToggle +@restrict E +@scope + +@description +Added in Umbraco version 7.7.0 Use this directive to render an umbraco toggle. + +