diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.Localization/Controllers/AdminController.cs index ed006cda0..c17ca4537 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Controllers/AdminController.cs +++ b/src/Orchard.Web/Modules/Orchard.Localization/Controllers/AdminController.cs @@ -6,6 +6,7 @@ using Orchard.Localization.Services; using Orchard.UI.Notify; using System; using System.Web.Mvc; +using System.Linq; namespace Orchard.Localization.Controllers { @@ -72,6 +73,14 @@ namespace Orchard.Localization.Controllers Services.Notifier.Success(T("Successfully cloned. The translated content was saved as a draft.")); var editorRouteValues = _contentManager.GetItemMetadata(contentItemTranslation).EditorRouteValues; + // adds request variables of current controller to the new redirect route + // for example the returnUrl parameter + foreach (var key in Request.Form.AllKeys.Where(x=> !x.StartsWith("__") && !editorRouteValues.Keys.Contains(x))) { + editorRouteValues.Add(key, Request.Form[key]); + } + foreach (var key in Request.QueryString.AllKeys.Where(x => !x.StartsWith("__") && !editorRouteValues.Keys.Contains(x))) { + editorRouteValues.Add(key, Request.QueryString[key]); + } return RedirectToRoute(editorRouteValues); } } diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Services/LocalizationService.cs b/src/Orchard.Web/Modules/Orchard.Localization/Services/LocalizationService.cs index bdf97f533..0e5fd5fe4 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Services/LocalizationService.cs +++ b/src/Orchard.Web/Modules/Orchard.Localization/Services/LocalizationService.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Orchard.ContentManagement; using Orchard.Localization.Models; @@ -29,11 +30,12 @@ namespace Orchard.Localization.Services { if (localized == null) return null; + var masterContent = content.ContentItem.As().MasterContentItem != null ? content.ContentItem.As().MasterContentItem : content; // Warning: Returns only the first of same culture localizations. return _contentManager .Query(versionOptions, content.ContentItem.ContentType) .Where(l => - (l.Id == content.ContentItem.Id || l.MasterContentItemId == content.ContentItem.Id) + (l.Id == masterContent.Id || l.MasterContentItemId == masterContent.Id) && l.CultureId == cultureRecord.Id) .Slice(1) .FirstOrDefault(); @@ -92,5 +94,6 @@ namespace Orchard.Localization.Services { // Warning: May contain more than one localization of the same culture. return query.List().ToList(); } + } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Localization/Views/EditorTemplates/Parts/Localization.ContentTranslations.Edit.cshtml b/src/Orchard.Web/Modules/Orchard.Localization/Views/EditorTemplates/Parts/Localization.ContentTranslations.Edit.cshtml index a086a9c0f..c20783654 100644 --- a/src/Orchard.Web/Modules/Orchard.Localization/Views/EditorTemplates/Parts/Localization.ContentTranslations.Edit.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Localization/Views/EditorTemplates/Parts/Localization.ContentTranslations.Edit.cshtml @@ -2,37 +2,44 @@ @using System.Globalization @{ Style.Require("LocalizationAdmin"); + string returnUrl = Request.QueryString["ReturnUrl"] ?? ""; }
- @if (!string.IsNullOrEmpty(Model.SelectedCulture)) - { + @if (!string.IsNullOrEmpty(Model.SelectedCulture)) { @T("This is the {0} variation of the content", Html.Encode(Model.SelectedCulture)) - if (Model.ContentLocalizations.Localizations.Any()) - { + if (Model.ContentLocalizations.Localizations.Any()) {
@T("Other translations:")
- @Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) => - Html.ItemEditLink(c.Culture.Culture, c), "localizations") + @if (returnUrl != "") { + @Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) => + Html.ItemEditLink(c.Culture.Culture, c, new { ReturnUrl = returnUrl }), "localizations") + } + else { + @Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) => + Html.ItemEditLink(c.Culture.Culture, c), "localizations") + }
} - if (Model.MissingCultures.Any()) - { + if (Model.MissingCultures.Any()) { var contentItemId = Model.MasterContentItem != null ? Model.MasterContentItem.Id : Model.ContentItem.Id; - -
@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = contentItemId }, new { itemprop = "UnsafeUrl" })
+ if (returnUrl != "") { +
@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = contentItemId, ReturnUrl = returnUrl }, new { itemprop = "UnsafeUrl" })
+ } + else { +
@Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = contentItemId }, new { itemprop = "UnsafeUrl" })
+ } } @Html.Hidden(Html.FieldNameFor(m => m.SelectedCulture), Model.SelectedCulture) } - else if (Model.MasterContentItem != null) - { + else if (Model.MasterContentItem != null) { @T("This is the {0} variation of {1}", BuildSelectedCultureList( Html.FieldIdFor(m => m.SelectedCulture), @@ -41,19 +48,23 @@ Model.SelectedCulture), Html.ItemEditLink(Model.MasterContentItem)) - if (Model.ContentLocalizations.Localizations.Any()) - { + if (Model.ContentLocalizations.Localizations.Any()) {
@T("Other translations:")
+ @if (returnUrl != "") { + @Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) => + Html.ItemEditLink(c.Culture.Culture, c, new { ReturnUrl = returnUrl }), "localizations"); + } + else { @Html.UnorderedList(Model.ContentLocalizations.Localizations, (c, i) => - Html.ItemEditLink(c.Culture.Culture, c), "localizations") + Html.ItemEditLink(c.Culture.Culture, c), "localizations"); + }
} } - else - { + else { @T("This is the {0} variation of the content", BuildSelectedCultureList( Html.FieldIdFor(m => m.SelectedCulture), @@ -76,7 +87,7 @@ TagBuilder optionTag = new TagBuilder("option"); optionTag.Attributes["data-content-dir"] = CultureInfo.GetCultureInfo(siteCulture).TextInfo.IsRightToLeft ? "rtl" : "ltr"; - if(string.IsNullOrEmpty(culture)) { + if (string.IsNullOrEmpty(culture)) { if (siteCulture == WorkContext.CurrentSite.SiteCulture) { optionTag.Attributes["selected"] = "selected"; } @@ -95,32 +106,32 @@ } @using (Script.Foot()) { } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs index 946d7659f..6086a4ac2 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/ClientStorageController.cs @@ -183,8 +183,18 @@ namespace Orchard.MediaLibrary.Controllers { // Raise update and publish events which will update relevant Media properties _handlers.Invoke(x => x.Updating(new UpdateContentContext(replaceMedia.ContentItem)), Logger); - _mediaLibraryService.DeleteFile(replaceMedia.FolderPath, replaceMedia.FileName); - _mediaLibraryService.UploadMediaFile(replaceMedia.FolderPath, replaceMedia.FileName, file.InputStream); + var mediaItemsUsingTheFile = Services.ContentManager.Query() + .ForVersion(VersionOptions.Latest) + .Where(x => x.FolderPath == replaceMedia.FolderPath && x.FileName == replaceMedia.FileName) + .Count(); + if (mediaItemsUsingTheFile == 1) { // if the file is referenced only by the deleted media content, the file too can be removed. + _mediaLibraryService.DeleteFile(replaceMedia.FolderPath, replaceMedia.FileName); + } + else { + // it changes the media file name + replaceMedia.FileName = filename; + } + _mediaLibraryService.UploadMediaFile(replaceMedia.FolderPath, filename, file.InputStream); replaceMedia.MimeType = mimeType; _handlers.Invoke(x => x.Updated(new UpdateContentContext(replaceMedia.ContentItem)), Logger); diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/LocalizedMediaController.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/LocalizedMediaController.cs new file mode 100644 index 000000000..9077d46eb --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Controllers/LocalizedMediaController.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Mvc; +using Orchard.ContentManagement; +using Orchard.Core.Common.Models; +using Orchard.Core.Title.Models; +using Orchard.Environment.Extensions; +using Orchard.Indexing; +using Orchard.Localization; +using Orchard.Localization.Models; +using Orchard.Localization.Services; +using Orchard.Logging; +using Orchard.MediaLibrary.Models; +using Orchard.MediaLibrary.Services; +using Orchard.MediaLibrary.ViewModels; +using Orchard.Themes; +using Orchard.UI.Admin; + +namespace Orchard.MediaLibrary.Controllers { + [Admin] + [Themed(false)] + [OrchardFeature("Orchard.MediaLibrary.LocalizationExtensions")] + public class LocalizedMediaController : Controller { + private readonly IContentManager _contentManager; + private readonly IMediaLibraryService _mediaLibraryService; + private readonly ICultureManager _cultureManager; + + public LocalizedMediaController(IOrchardServices services, + IContentManager contentManager, + ICultureManager cultureManager, + IMediaLibraryService mediaLibraryService) { + _contentManager = contentManager; + _mediaLibraryService = mediaLibraryService; + _cultureManager = cultureManager; + Services = services; + + T = NullLocalizer.Instance; + Logger = NullLogger.Instance; + + } + public IOrchardServices Services { get; set; } + public Localizer T { get; set; } + public ILogger Logger { get; set; } + public ActionResult MediaItems(string folderPath, int skip = 0, int count = 0, string order = "created", string mediaType = "", string culture = "") { + if (String.IsNullOrWhiteSpace(folderPath)) { + folderPath = null; + } + if (!_mediaLibraryService.CheckMediaFolderPermission(Permissions.SelectMediaContent, folderPath)) { + Services.Notifier.Add(UI.Notify.NotifyType.Error, T("Cannot select media")); + var model = new MediaManagerMediaItemsViewModel { + MediaItems = new List(), + MediaItemsCount = 0, + FolderPath = folderPath + }; + + return View(model); + } + + // Check permission + if (!_mediaLibraryService.CheckMediaFolderPermission(Permissions.SelectMediaContent, folderPath) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) { + var model = new MediaManagerMediaItemsViewModel { + MediaItems = new List(), + MediaItemsCount = 0, + FolderPath = folderPath + }; + + return View(model); + } + + IEnumerable mediaParts; + var mediaPartsCount = 0; + if (culture == "") { + mediaParts = _mediaLibraryService.GetMediaContentItems(folderPath, skip, count, order, mediaType, VersionOptions.Latest); + mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(folderPath, mediaType, VersionOptions.Latest); + } + else { + var cultureId = _cultureManager.GetCultureByName(culture).Id; + var query = BuildGetMediaContentItemsQuery(Services.ContentManager, folderPath, order: order, mediaType: mediaType, versionOptions: VersionOptions.Latest) + .Join() + .Where(x => x.CultureId == cultureId) + .Join(); + mediaParts = query + .Slice(skip, count); + mediaPartsCount = query.Count(); + } + + var mediaItems = mediaParts.Select(x => new MediaManagerMediaItemViewModel { + MediaPart = x, + Shape = Services.ContentManager.BuildDisplay(x.ContentItem, "Thumbnail") + }).ToList(); + + var viewModel = new MediaManagerMediaItemsViewModel { + MediaItems = mediaItems, + MediaItemsCount = mediaPartsCount, + FolderPath = folderPath + }; + return View(viewModel); + } + + //TODO: extract the logic from MediaLibraryService and insert a method definition into IMediaLibraryService in order to give a point of extension + private static IContentQuery BuildGetMediaContentItemsQuery( + IContentManager contentManager, string folderPath = null, bool recursive = false, string order = null, string mediaType = null, VersionOptions versionOptions = null) { + + var query = contentManager.Query(versionOptions); + + query = query.Join(); + + if (!String.IsNullOrEmpty(mediaType)) { + query = query.ForType(new[] { mediaType }); + } + + if (!String.IsNullOrEmpty(folderPath)) { + if (recursive) { + query = query.Join().Where(m => m.FolderPath.StartsWith(folderPath)); + } + else { + query = query.Join().Where(m => m.FolderPath == folderPath); + } + } + + switch (order) { + case "title": + query = query.Join() + .OrderBy(x => x.Title) + .Join(); + break; + + case "modified": + query = query.Join() + .OrderByDescending(x => x.ModifiedUtc) + .Join(); + break; + + case "published": + query = query.Join() + .OrderByDescending(x => x.PublishedUtc) + .Join(); + break; + + default: + query = query.Join() + .OrderByDescending(x => x.CreatedUtc) + .Join(); + break; + } + + query = query.Join(); + + return query; + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs index 0f56323e8..859db198b 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/AudioPartDriver.cs @@ -1,4 +1,5 @@ using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Handlers; using Orchard.MediaLibrary.Models; namespace Orchard.MediaLibrary.Drivers { @@ -26,5 +27,8 @@ namespace Orchard.MediaLibrary.Drivers { part.Length = int.Parse(length) ); } + protected override void Cloning(AudioPart originalPart, AudioPart clonePart, CloneContentContext context) { + clonePart.Length = originalPart.Length; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs index b70023a67..0ef734942 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/DocumentPartDriver.cs @@ -1,4 +1,5 @@ using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Handlers; using Orchard.MediaLibrary.Models; namespace Orchard.MediaLibrary.Drivers { @@ -26,5 +27,8 @@ namespace Orchard.MediaLibrary.Drivers { part.Length = int.Parse(length) ); } + protected override void Cloning(DocumentPart originalPart, DocumentPart clonePart, CloneContentContext context) { + clonePart.Length = originalPart.Length; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs index 57e8a400f..7fe045a73 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/ImagePartDriver.cs @@ -1,5 +1,6 @@ using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Handlers; using Orchard.MediaLibrary.Models; namespace Orchard.MediaLibrary.Drivers { @@ -33,5 +34,10 @@ namespace Orchard.MediaLibrary.Drivers { part.Width = int.Parse(width) ); } + + protected override void Cloning(ImagePart originalPart, ImagePart clonePart, CloneContentContext context) { + clonePart.Height = originalPart.Height; + clonePart.Width = originalPart.Width; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryExplorerLocalizationExtensionsPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryExplorerLocalizationExtensionsPartDriver.cs new file mode 100644 index 000000000..b518d4705 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaLibraryExplorerLocalizationExtensionsPartDriver.cs @@ -0,0 +1,19 @@ +using Orchard.ContentManagement.Drivers; +using Orchard.Environment.Extensions; +using Orchard.Localization.Services; +using Orchard.MediaLibrary.Models; + +namespace Orchard.MediaLibrary.Drivers { + [OrchardFeature("Orchard.MediaLibrary.LocalizationExtensions")] + public class MediaLibraryExplorerLocalizationExtensionsPartDriver : ContentPartDriver { + private readonly ICultureManager _cultureManager; + public MediaLibraryExplorerLocalizationExtensionsPartDriver(ICultureManager cultureManager) { + _cultureManager = cultureManager; + + } + protected override DriverResult Display(MediaLibraryExplorerPart part, string displayType, dynamic shapeHelper) { + var cultures = _cultureManager.ListCultures(); + return ContentShape("Parts_MediaLibraryLocalization_Actions", () => shapeHelper.Parts_MediaLibraryLocalization_Actions(Cultures: cultures)); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs index 47ab58a61..6aa91d1d9 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/MediaPartDriver.cs @@ -1,11 +1,11 @@ using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Handlers; using Orchard.Localization; using Orchard.MediaLibrary.Models; namespace Orchard.MediaLibrary.Drivers { public class MediaPartDriver : ContentPartDriver { - protected override string Prefix { get { return "MediaPart"; } } @@ -27,7 +27,7 @@ namespace Orchard.MediaLibrary.Drivers { } protected override DriverResult Editor(MediaPart part, IUpdateModel updater, dynamic shapeHelper) { - updater.TryUpdateModel(part, Prefix, new[] {"Caption", "AlternateText"}, null); + updater.TryUpdateModel(part, Prefix, new[] { "Caption", "AlternateText" }, null); return Editor(part, shapeHelper); } @@ -74,5 +74,14 @@ namespace Orchard.MediaLibrary.Drivers { context.Element(part.PartDefinition.Name).SetAttributeValue("FileName", part.FileName); context.Element(part.PartDefinition.Name).SetAttributeValue("LogicalType", part.LogicalType); } + + protected override void Cloning(MediaPart originalPart, MediaPart clonePart, CloneContentContext context) { + clonePart.Caption = originalPart.Caption; + clonePart.FileName = originalPart.FileName; + clonePart.FolderPath = originalPart.FolderPath; + clonePart.LogicalType = originalPart.LogicalType; + clonePart.AlternateText = originalPart.AlternateText; + clonePart.MimeType = originalPart.MimeType; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/OEmbedPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/OEmbedPartDriver.cs index 76f7d920e..81da1f09b 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/OEmbedPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/OEmbedPartDriver.cs @@ -4,9 +4,10 @@ using Orchard.ContentManagement.FieldStorage.InfosetStorage; using Orchard.MediaLibrary.Models; using System.Xml; using System.Xml.Linq; +using Orchard.ContentManagement.Handlers; +using System.Collections; -namespace Orchard.MediaLibrary.Drivers -{ +namespace Orchard.MediaLibrary.Drivers { public class OEmbedPartDriver : ContentPartDriver { protected override DriverResult Display(OEmbedPart part, string displayType, dynamic shapeHelper) { return Combined( @@ -55,5 +56,26 @@ namespace Orchard.MediaLibrary.Drivers partElement.Add(xmlElement.Elements()); } } + + protected override void Cloning(OEmbedPart originalPart, OEmbedPart clonePart, CloneContentContext context) { + var partName = XmlConvert.EncodeName(typeof(OEmbedPart).Name); + + var infosetOriginalPart = originalPart.As(); + var infosetClonePart = clonePart.As(); + if (infosetOriginalPart != null && infosetClonePart != null) { + // OEmbedPart is not versionable thats why using Infoset.Element instead of VersionInfoset.Element + var originalElement = infosetOriginalPart.Infoset.Element; + var partOriginalElement = originalElement.Element(partName); + var cloneElement = infosetClonePart.Infoset.Element; + var partCloneElement = cloneElement.Element(partName); + + if (partCloneElement != null) + partCloneElement.Remove(); + + partCloneElement = new XElement(partName); + cloneElement.Add(partCloneElement); + partCloneElement.Add(partOriginalElement.Elements()); + } + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VectorImagePartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VectorImagePartDriver.cs index 6163658e9..35a15abca 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VectorImagePartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VectorImagePartDriver.cs @@ -1,4 +1,5 @@ using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Handlers; using Orchard.MediaLibrary.Models; namespace Orchard.MediaLibrary.Drivers { @@ -12,5 +13,9 @@ namespace Orchard.MediaLibrary.Drivers { ContentShape("Parts_VectorImage_SummaryAdmin", () => shapeHelper.Parts_VectorImage_SummaryAdmin()) ); } + + protected override void Cloning(VectorImagePart originalPart, VectorImagePart clonePart, CloneContentContext context) { + // nothing todo at the moment cause the part is only defined + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs index 0aa2923e1..2c21dd1ab 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Drivers/VideoPartDriver.cs @@ -1,4 +1,5 @@ using Orchard.ContentManagement.Drivers; +using Orchard.ContentManagement.Handlers; using Orchard.MediaLibrary.Models; namespace Orchard.MediaLibrary.Drivers { @@ -26,5 +27,9 @@ namespace Orchard.MediaLibrary.Drivers { part.Length = int.Parse(length) ); } + + protected override void Cloning(VideoPart originalPart, VideoPart clonePart, CloneContentContext context) { + clonePart.Length = originalPart.Length; + } } } \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaLibraryPickerFieldLocalizationExtensionHandler.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaLibraryPickerFieldLocalizationExtensionHandler.cs new file mode 100644 index 000000000..3494ab2ad --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaLibraryPickerFieldLocalizationExtensionHandler.cs @@ -0,0 +1,129 @@ +using System.Collections.Generic; +using System.Linq; +using Orchard.ContentManagement; +using Orchard.ContentManagement.Handlers; +using Orchard.Environment.Extensions; +using Orchard.Localization; +using Orchard.Localization.Models; +using Orchard.Localization.Services; +using Orchard.MediaLibrary.Fields; +using Orchard.MediaLibrary.Models; +using Orchard.MediaLibrary.Settings; +using Orchard.UI.Notify; + +namespace Orchard.MediaLibrary.Handlers { + [OrchardFeature("Orchard.MediaLibrary.LocalizationExtensions")] + public class MediaLibraryPickerFieldLocalizationExtensionHandler : ContentHandler { + private readonly IContentManager _contentManager; + private readonly ILocalizationService _localizationServices; + private readonly IOrchardServices _orchardServices; + + public MediaLibraryPickerFieldLocalizationExtensionHandler( + IOrchardServices orchardServices, + IContentManager contentManager, + ILocalizationService localizationServices) { + _contentManager = contentManager; + _orchardServices = orchardServices; + _localizationServices = localizationServices; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + + protected override void UpdateEditorShape(UpdateEditorContext context) { + //Here we implement the logic based on the settings introduced in MediaLibraryPickerFieldLocalizationSettings + //These settings should only be active if the ContentItem that is being updated has a LocalizationPart + if (context.ContentItem.Parts.Any(part => part is LocalizationPart)) { + var lPart = (LocalizationPart)context.ContentItem.Parts.Single(part => part is LocalizationPart); + var fields = context.ContentItem.Parts.SelectMany(x => x.Fields.Where(f => f.FieldDefinition.Name == typeof(MediaLibraryPickerField).Name)).Cast(); + var contentCulture = context.ContentItem.As().Culture != null ? context.ContentItem.As().Culture.Culture : null; + foreach (var field in fields) { + var fieldSettings = field.PartFieldDefinition.Settings.GetModel(); + var settings = field.PartFieldDefinition.Settings.GetModel(); + + if (settings.TryToLocalizeMedia) { + //try to replace items in the field with their translation + var itemsInField = _contentManager.GetMany(field.Ids, VersionOptions.Latest, QueryHints.Empty); + var mediaIds = new List(); + foreach (var item in itemsInField) { + // negatives id whoud be localized + var mediaItem = _contentManager.Get(item.Id, VersionOptions.Latest); + var mediaIsLocalizable = mediaItem.As() != null; + var mediaCulture = mediaIsLocalizable && mediaItem.As().Culture != null ? mediaItem.As().Culture.Culture : null; + if (mediaItem != null && mediaIsLocalizable) { + // The media is localizable + if (contentCulture == mediaCulture) { + // The content culture and the media culture match + mediaIds.Add(mediaItem.Id); + } + else { + if (mediaCulture == null) { + // The media has not a culture, so it takes the content culture + _localizationServices.SetContentCulture(mediaItem, contentCulture); + mediaIds.Add(mediaItem.Id); + _orchardServices.Notifier.Warning(T( + "{0}: the media item {1} was culture neutral and it has been localized", + field.DisplayName, + mediaItem.As().FileName)); + } + else { + // The media has a culture + var localizedMedia = _localizationServices.GetLocalizedContentItem(mediaItem, contentCulture); + if (localizedMedia != null) { + // The media has a translation, so the field will replace current media with the right localized one. + mediaIds.Add(localizedMedia.Id); + _orchardServices.Notifier.Warning(T( + "{0}: the media item {1} has been replaced by its localized version", + field.DisplayName, + mediaItem.As().FileName)); + } + else { + if (!settings.RemoveItemsWithoutLocalization) { + // The media supports translations but have not a localized version, so it will be cloned in the right language + var clonedMedia = _contentManager.Clone(mediaItem); + var mediaLocalizationPart = mediaItem.As(); + if (mediaLocalizationPart != null) { + _localizationServices.SetContentCulture(clonedMedia, contentCulture); + clonedMedia.As().MasterContentItem = mediaLocalizationPart.MasterContentItem == null ? mediaItem : mediaLocalizationPart.MasterContentItem; + } + _contentManager.Publish(clonedMedia); + mediaIds.Add(clonedMedia.Id); + _orchardServices.Notifier.Warning(T( + "{0}: a localized version of media item {1} has been created", + field.DisplayName, + mediaItem.As().FileName)); + } + else { + _orchardServices.Notifier.Warning(T( + "{0}: the media item {1} has been removed from the field because its culture differs from content's culture", + field.DisplayName, + mediaItem.As().FileName)); + } + } + } + } + } + else if (mediaItem != null && !mediaIsLocalizable) { + if (!settings.RemoveItemsWithNoLocalizationPart) { + mediaIds.Add(mediaItem.Id); + } + else { + _orchardServices.Notifier.Warning(T( + "{0}: the media item {1} has been removed from the field because culture neutral", + field.DisplayName, + mediaItem.As().FileName)); + } + } + } + + field.Ids = mediaIds.Distinct().ToArray(); + + if (field.Ids.Length == 0 && fieldSettings.Required) { + context.Updater.AddModelError("Id", T("The {0} field is required.", field.DisplayName)); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs index 2e73d8209..4cbfc17db 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Handlers/MediaPartHandler.cs @@ -15,15 +15,18 @@ namespace Orchard.MediaLibrary.Handlers { private readonly IMediaLibraryService _mediaLibraryService; private readonly IStorageProvider _storageProvider; private readonly IContentDefinitionManager _contentDefinitionManager; + private readonly IContentManager _contentManager; public MediaPartHandler( IStorageProvider storageProvider, IMediaLibraryService mediaLibraryService, IRepository repository, - IContentDefinitionManager contentDefinitionManager) { + IContentDefinitionManager contentDefinitionManager, + IContentManager contentManager) { _storageProvider = storageProvider; _mediaLibraryService = mediaLibraryService; _contentDefinitionManager = contentDefinitionManager; + _contentManager = contentManager; Filters.Add(StorageFilter.For(repository)); Filters.Add(new ActivatingFilter(contentType => { @@ -113,7 +116,13 @@ namespace Orchard.MediaLibrary.Handlers { protected void RemoveMedia(MediaPart part) { if (!string.IsNullOrEmpty(part.FileName)) { - _mediaLibraryService.DeleteFile(part.FolderPath, part.FileName); + var mediaItemsUsingTheFile = _contentManager.Query() + .ForVersion(VersionOptions.Latest) + .Where(x => x.FolderPath == part.FolderPath && x.FileName == part.FileName) + .Count(); + if (mediaItemsUsingTheFile == 1) { // if the file is referenced only by the deleted media content, the file too can be removed. + _mediaLibraryService.DeleteFile(part.FolderPath, part.FileName); + } } } diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/MediaLocalizationMigrations.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/MediaLocalizationMigrations.cs new file mode 100644 index 000000000..f79a55e80 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/MediaLocalizationMigrations.cs @@ -0,0 +1,22 @@ +using System.Linq; +using Orchard.ContentManagement.MetaData; +using Orchard.Core.Contents.Extensions; +using Orchard.Data.Migration; +using Orchard.Environment.Extensions; +using Orchard.Localization.Models; + +namespace Orchard.MediaLibrary { + + [OrchardFeature("Orchard.MediaLibrary.LocalizationExtensions")] + public class MediaLocalizationMigrations : DataMigrationImpl { + public int Create() { + var mediaContentTypes = ContentDefinitionManager.ListTypeDefinitions().Where(x => x.Settings.ContainsKey("Stereotype") && x.Settings["Stereotype"].Equals("Media", System.StringComparison.InvariantCultureIgnoreCase)); + // adds LocalizationPart to all "Media" stereotypes + foreach (var mediaCT in mediaContentTypes) { + ContentDefinitionManager.AlterTypeDefinition(mediaCT.Name, td => td + .WithPart("LocalizationPart")); + } + return 1; + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt index 2c83eb1b8..128cf1e17 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Module.txt @@ -11,3 +11,8 @@ Features: Description: Provides enhanced Media management tools. Dependencies: Title, Orchard.ContentTypes, Orchard.MediaProcessing, Orchard.Tokens, Orchard.Resources Category: Media + Orchard.MediaLibrary.LocalizationExtensions: + Name: Media Library Localization Extensions + Description: Provides settings to enable advanced localization behaviours for Media Library and Media Library Picker Field. + Dependencies: Orchard.MediaLibrary, Orchard.Localization + Category: Media diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj index b17a7f989..65da142d8 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Orchard.MediaLibrary.csproj @@ -128,13 +128,17 @@ + + + + @@ -159,6 +163,10 @@ {0E7646E8-FE8F-43C1-8799-D97860925EC4} Orchard.ContentTypes + + {FBC8B571-ED50-49D8-8D9D-64AB7454A0D6} + Orchard.Localization + {6f759635-13d7-4e94-bcc9-80445d63f117} Orchard.Tokens @@ -215,6 +223,8 @@ + + @@ -416,6 +426,28 @@ + + + + + + + + + + + + + + + + + + + + + + 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Placement.info b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Placement.info index 74448a7a3..5e9bea14e 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Placement.info +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Placement.info @@ -132,4 +132,10 @@ Parts_MediaLibrary_Navigation="Navigation:5" /> + + + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/media-library.js b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/media-library.js index d72741fa8..c65234dd7 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/media-library.js +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Scripts/media-library.js @@ -118,8 +118,10 @@ $(function () { return css; }); - self.publicationStatus = ko.computed(function() { - return self.data.published ? "" : draftText; + self.mediaInfos = ko.computed(function () { + var pubStatus = self.data.published ? "" : draftText; + var localization = (self.data.localization != "" ? "(" + self.data.localization + ")" : ""); + return pubStatus + " " + localization; }); // operations diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/MediaLibraryService.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/MediaLibraryService.cs index 5d888bdc9..b6e69e6cd 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/MediaLibraryService.cs +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Services/MediaLibraryService.cs @@ -80,7 +80,8 @@ namespace Orchard.MediaLibrary.Services { return BuildGetMediaContentItemsQuery(_orchardServices.ContentManager, folderPath, true, mediaType: mediaType, versionOptions: versionOptions) .Count(); } - + + //TODO: extract the logic from MediaLibraryService and add a method definition into IMediaLibraryService in order to give a point of extension private static IContentQuery BuildGetMediaContentItemsQuery( IContentManager contentManager, string folderPath = null, bool recursive = false, string order = null, string mediaType = null, VersionOptions versionOptions = null) { diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Settings/MediaLibraryPickerFieldLocalizationEditorEvents.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Settings/MediaLibraryPickerFieldLocalizationEditorEvents.cs new file mode 100644 index 000000000..66950d8a9 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Settings/MediaLibraryPickerFieldLocalizationEditorEvents.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Globalization; +using Orchard.ContentManagement; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Builders; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.ContentManagement.ViewModels; +using Orchard.Environment.Extensions; + +namespace Orchard.MediaLibrary.Settings { + [OrchardFeature("Orchard.MediaLibrary.LocalizationExtensions")] + public class MediaLibraryPickerFieldLocalizationEditorEvents : ContentDefinitionEditorEventsBase { + + public override IEnumerable PartFieldEditor(ContentPartFieldDefinition definition) { + if (definition.FieldDefinition.Name == "MediaLibraryPickerField") { + var model = definition.Settings.GetModel(); + yield return DefinitionTemplate(model); + } + } + + public override IEnumerable PartFieldEditorUpdate(ContentPartFieldDefinitionBuilder builder, IUpdateModel updateModel) { + if (builder.FieldType != "MediaLibraryPickerField") { + yield break; + } + + var model = new MediaLibraryPickerFieldLocalizationSettings(); + if (updateModel.TryUpdateModel(model, "MediaLibraryPickerFieldLocalizationSettings", null, null)) { + builder.WithSetting("MediaLibraryPickerFieldLocalizationSettings.TryToLocalizeMedia", model.TryToLocalizeMedia.ToString(CultureInfo.InvariantCulture)); + builder.WithSetting("MediaLibraryPickerFieldLocalizationSettings.RemoveItemsWithoutLocalization", model.RemoveItemsWithoutLocalization.ToString(CultureInfo.InvariantCulture)); + builder.WithSetting("MediaLibraryPickerFieldLocalizationSettings.RemoveItemsWithNoLocalizationPart", model.RemoveItemsWithNoLocalizationPart.ToString(CultureInfo.InvariantCulture)); + } + + yield return DefinitionTemplate(model); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Settings/MediaLibraryPickerFieldLocalizationSettings.cs b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Settings/MediaLibraryPickerFieldLocalizationSettings.cs new file mode 100644 index 000000000..a68371774 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Settings/MediaLibraryPickerFieldLocalizationSettings.cs @@ -0,0 +1,17 @@ +using Orchard.Environment.Extensions; + +namespace Orchard.MediaLibrary.Settings { + [OrchardFeature("Orchard.MediaLibrary.LocalizationExtensions")] + public class MediaLibraryPickerFieldLocalizationSettings { + + public MediaLibraryPickerFieldLocalizationSettings() { + TryToLocalizeMedia = true; + RemoveItemsWithoutLocalization = false; + RemoveItemsWithNoLocalizationPart = false; + + } + public bool TryToLocalizeMedia { get; set; } + public bool RemoveItemsWithoutLocalization { get; set; } + public bool RemoveItemsWithNoLocalizationPart { get; set; } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/media-library-picker-admin.css b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/media-library-picker-admin.css index 5313f9180..730f874aa 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/media-library-picker-admin.css +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Styles/media-library-picker-admin.css @@ -42,15 +42,19 @@ text-align: right; font-size: 12px; opacity: 0.6; + height: 40px; } .overlay h3 { padding-right:5px; font-size: 12px; - height: 40px; overflow: hidden; } +.overlay .pubblication-status { + padding-right:5px; + overflow: hidden; +} .media-thumbnail { width: 120px; height: 120px; diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml index 4c3d56d4f..c1f9d8278 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/Index.cshtml @@ -43,7 +43,7 @@

-

+

@@ -52,9 +52,12 @@

@T("PROPERTIES")

-
- -
+
+
+ +
+ @Html.AntiForgeryTokenOrchard() +
@@ -115,7 +118,7 @@ var mediaLibrarySettings = {
  • - +
    diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaItems.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaItems.cshtml index d7238347a..7b5bd07e0 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaItems.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Admin/MediaItems.cshtml @@ -1,4 +1,6 @@ @using Orchard.Utility.Extensions +@using Orchard.Localization.Models +@using Orchard.ContentManagement @model Orchard.MediaLibrary.ViewModels.MediaManagerMediaItemsViewModel @{ Response.ContentType = "text/json"; @@ -6,21 +8,21 @@ new { mediaItemsCount = Model.MediaItemsCount, mediaItems = Model.MediaItems.Select(x => new { - id = x.MediaPart.Id, - contentType = x.MediaPart.ContentItem.ContentType, - contentTypeClass = x.MediaPart.ContentItem.ContentType.HtmlClassify(), + id = x.MediaPart.Id, + contentType = x.MediaPart.ContentItem.ContentType, + contentTypeClass = x.MediaPart.ContentItem.ContentType.HtmlClassify(), title = x.MediaPart.Title, published = x.MediaPart.ContentItem.VersionRecord.Published, - alternateText = x.MediaPart.AlternateText, - caption = x.MediaPart.Caption, - resource = x.MediaPart.MediaUrl, - mimeType = x.MediaPart.MimeType, - mimeTypeClass = x.MediaPart.MimeType.HtmlClassify(), + alternateText = x.MediaPart.AlternateText, + caption = x.MediaPart.Caption, + resource = x.MediaPart.MediaUrl, + mimeType = x.MediaPart.MimeType, + mimeTypeClass = x.MediaPart.MimeType.HtmlClassify(), thumbnail = Display(x.Shape).ToString(), - editLink = Url.ItemEditUrl(x.MediaPart) + editLink = Url.ItemEditUrl(x.MediaPart), + localization = (((dynamic)x.MediaPart.ContentItem).LocalizationPart != null && ((dynamic)x.MediaPart.ContentItem).LocalizationPart.Culture != null) ? ((dynamic)x.MediaPart.ContentItem).LocalizationPart.CultureField.Value.Culture : "" }).ToArray(), folderPath = Model.FolderPath })) } - \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/DefinitionTemplates/MediaLibraryPickerFieldLocalizationSettings.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/DefinitionTemplates/MediaLibraryPickerFieldLocalizationSettings.cshtml new file mode 100644 index 000000000..6f9d0b74b --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/DefinitionTemplates/MediaLibraryPickerFieldLocalizationSettings.cshtml @@ -0,0 +1,15 @@ +@model Orchard.MediaLibrary.Settings.MediaLibraryPickerFieldLocalizationSettings + +
    + @Html.CheckBoxFor(m => m.TryToLocalizeMedia) + + @T("Check to attempt to replace media items selected in this field with their translation in the main ContentItem's culture. This only applies if the main ContentItem has a LocalizationPart.") +
    + @Html.CheckBoxFor(m => m.RemoveItemsWithoutLocalization) + + @T("Check to remove media items from the MediaLibraryPickerField when the items selected do not have a version in the correct culture (they have a LocalizationPart, but not a translation in the main ContentItem's culture').") + @Html.CheckBoxFor(m => m.RemoveItemsWithNoLocalizationPart) + + @T("Check to remove media items from the MediaLibraryPickerField when the items selected cannot be localized (do not have a LocalizationPart).") +
    +
    diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Localization.ContentTranslations.SummaryAdmin.ForMedia.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Localization.ContentTranslations.SummaryAdmin.ForMedia.cshtml new file mode 100644 index 000000000..1cd119e0c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Localization.ContentTranslations.SummaryAdmin.ForMedia.cshtml @@ -0,0 +1,22 @@ +@using Orchard.Core.Contents; +@using Orchard.Localization.Models; +@if (AuthorizedFor(Permissions.PublishContent)) { + Style.Require("LocalizationAdmin"); + IEnumerable localizations = Model.Localizations; + var localizationLinks = Html.UnorderedList(localizations, (c, i) => Html.ItemEditLink(c.Culture.Culture, c, new { ReturnUrl = Request.UrlReferrer }), "localizations"); +
    + @if (Model.Culture != null) { +
    @T("Culture: {0}", Model.Culture)
    + } else { +
    @T("Culture: {0}", T("Undefined"))
    + } + @if (localizations.Count() > 0) + { +

    @T("Translations:")

    @localizationLinks
    + } + @if (Model.Culture != null && !((IEnumerable)Model.SiteCultures).All(c => c == Model.Culture || localizations.Any(l => c == l.Culture.Culture))) + { +
    @Html.ActionLink(T("+ New translation").Text, "Translate", "Admin", new { area = "Orchard.Localization", id = Model.MasterId, ReturnUrl = Request.UrlReferrer }, new { itemprop = "UnsafeUrl" })
    + } +
    +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/LocalizedMedia/MediaItems.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/LocalizedMedia/MediaItems.cshtml new file mode 100644 index 000000000..65966a307 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/LocalizedMedia/MediaItems.cshtml @@ -0,0 +1,27 @@ +@using Orchard.Utility.Extensions + +@model Orchard.MediaLibrary.ViewModels.MediaManagerMediaItemsViewModel +@{ + Response.ContentType = "text/json"; + @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject( + new { + mediaItemsCount = Model.MediaItemsCount, + mediaItems = Model.MediaItems.Select(x => new { + id = x.MediaPart.Id, + contentType = x.MediaPart.ContentItem.ContentType, + contentTypeClass = x.MediaPart.ContentItem.ContentType.HtmlClassify(), + title = x.MediaPart.Title, + published = x.MediaPart.ContentItem.VersionRecord.Published, + alternateText = x.MediaPart.AlternateText, + caption = x.MediaPart.Caption, + resource = x.MediaPart.MediaUrl, + mimeType = x.MediaPart.MimeType, + mimeTypeClass = x.MediaPart.MimeType.HtmlClassify(), + thumbnail = Display(x.Shape).ToString(), + editLink = Url.ItemEditUrl(x.MediaPart), + localization = (((dynamic)x.MediaPart.ContentItem).LocalizationPart != null && ((dynamic)x.MediaPart.ContentItem).LocalizationPart.Culture != null) ? ((dynamic)x.MediaPart.ContentItem).LocalizationPart.CultureField.Value.Culture : "" + }).ToArray(), + folderPath = Model.FolderPath + })) +} + diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/MediaLibraryPicker.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/MediaLibraryPicker.cshtml index f91c62d10..97127ba15 100644 --- a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/MediaLibraryPicker.cshtml +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/MediaLibraryPicker.cshtml @@ -1,4 +1,5 @@ @using Orchard.ContentManagement +@using Orchard.Localization.Models; @using Orchard.Utility.Extensions; @{ @@ -8,12 +9,12 @@ Script.Require("jQueryColorBox").AtFoot(); Script.Include("media-library-picker.js").AtFoot(); - var fieldName = (string) Model.FieldName; - var displayName = (string) Model.DisplayName; + var fieldName = (string)Model.FieldName; + var displayName = (string)Model.DisplayName; var multiple = (bool)(Model.Multiple ?? false); var required = (bool)(Model.Required ?? false); - var hint = (string) Model.Hint; - var promptOnNavigate = (bool) (Model.PromptOnNavigate ?? true); + var hint = (string)Model.Hint; + var promptOnNavigate = (bool)(Model.PromptOnNavigate ?? true); var showSaveWarning = (bool)(Model.ShowSaveWarning); var contentItems = (IEnumerable)Model.ContentItems ?? Enumerable.Empty(); var contentManager = WorkContext.Resolve(); @@ -31,7 +32,7 @@ data-return-url="@HttpUtility.JavaScriptStringEncode(Request.RawUrl)" data-prompt-on-navigate="@promptOnNavigate.ToString().ToLower()" data-show-save-warning="@showSaveWarning.ToString().ToLower()"> - +
    @T("You need to save your changes.")
      @@ -46,6 +47,15 @@ @Display(BuildDisplay(contentItem, "Thumbnail"))

      @Html.ItemDisplayText(contentItem)

      +

      + @(contentItem.IsPublished() ? "" : T("Draft").Text) + @{ + var localizationPart = contentItem.As(); + if (localizationPart != null && localizationPart.Culture != null) { + @(string.Format(" ({0})", localizationPart.Culture.Culture)) + } + } +

    @@ -58,7 +68,7 @@
  • - } + }
    diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Audio.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Audio.cshtml new file mode 100644 index 000000000..ee01f976c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Audio.cshtml @@ -0,0 +1 @@ +@Display(New.Localization_ContentTranslations_SummaryAdmin_ForMedia(Localizations: Model.Localizations, Culture: Model.Culture,SiteCultures: Model.SiteCultures, MasterId:Model.MasterId)) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Document.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Document.cshtml new file mode 100644 index 000000000..ee01f976c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Document.cshtml @@ -0,0 +1 @@ +@Display(New.Localization_ContentTranslations_SummaryAdmin_ForMedia(Localizations: Model.Localizations, Culture: Model.Culture,SiteCultures: Model.SiteCultures, MasterId:Model.MasterId)) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Image.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Image.cshtml new file mode 100644 index 000000000..ee01f976c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Image.cshtml @@ -0,0 +1 @@ +@Display(New.Localization_ContentTranslations_SummaryAdmin_ForMedia(Localizations: Model.Localizations, Culture: Model.Culture,SiteCultures: Model.SiteCultures, MasterId:Model.MasterId)) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-OEmbed.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-OEmbed.cshtml new file mode 100644 index 000000000..ee01f976c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-OEmbed.cshtml @@ -0,0 +1 @@ +@Display(New.Localization_ContentTranslations_SummaryAdmin_ForMedia(Localizations: Model.Localizations, Culture: Model.Culture,SiteCultures: Model.SiteCultures, MasterId:Model.MasterId)) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-VectorImage.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-VectorImage.cshtml new file mode 100644 index 000000000..ee01f976c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-VectorImage.cshtml @@ -0,0 +1 @@ +@Display(New.Localization_ContentTranslations_SummaryAdmin_ForMedia(Localizations: Model.Localizations, Culture: Model.Culture,SiteCultures: Model.SiteCultures, MasterId:Model.MasterId)) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Video.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Video.cshtml new file mode 100644 index 000000000..ee01f976c --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/Localization.ContentTranslations.SummaryAdmin-Video.cshtml @@ -0,0 +1 @@ +@Display(New.Localization_ContentTranslations_SummaryAdmin_ForMedia(Localizations: Model.Localizations, Culture: Model.Culture,SiteCultures: Model.SiteCultures, MasterId:Model.MasterId)) diff --git a/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/MediaLibraryLocalization.Actions.cshtml b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/MediaLibraryLocalization.Actions.cshtml new file mode 100644 index 000000000..aca3a3179 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.MediaLibrary/Views/Parts/MediaLibraryLocalization.Actions.cshtml @@ -0,0 +1,39 @@ + +
    + + +
    + +@using (Script.Foot()) { + + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.Search/Views/Media/MediaItems.cshtml b/src/Orchard.Web/Modules/Orchard.Search/Views/Media/MediaItems.cshtml index 3dad0b9ef..d188f54aa 100644 --- a/src/Orchard.Web/Modules/Orchard.Search/Views/Media/MediaItems.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Search/Views/Media/MediaItems.cshtml @@ -6,20 +6,21 @@ new { mediaItemsCount = Model.MediaItemsCount, mediaItems = Model.MediaItems.Select(x => new { - id = x.MediaPart.Id, - contentType = x.MediaPart.ContentItem.ContentType, - contentTypeClass = x.MediaPart.ContentItem.ContentType.HtmlClassify(), - title = x.MediaPart.Title, - alternateText = x.MediaPart.AlternateText, - caption = x.MediaPart.Caption, - resource = x.MediaPart.MediaUrl, - mimeType = x.MediaPart.MimeType, - mimeTypeClass = x.MediaPart.MimeType.HtmlClassify(), + id = x.MediaPart.Id, + contentType = x.MediaPart.ContentItem.ContentType, + contentTypeClass = x.MediaPart.ContentItem.ContentType.HtmlClassify(), + title = x.MediaPart.Title, + published = x.MediaPart.ContentItem.VersionRecord.Published, + alternateText = x.MediaPart.AlternateText, + caption = x.MediaPart.Caption, + resource = x.MediaPart.MediaUrl, + mimeType = x.MediaPart.MimeType, + mimeTypeClass = x.MediaPart.MimeType.HtmlClassify(), thumbnail = Display(x.Shape).ToString(), - editLink = Url.ItemEditUrl(x.MediaPart) + editLink = Url.ItemEditUrl(x.MediaPart), + localization = (((dynamic)x.MediaPart.ContentItem).LocalizationPart != null && ((dynamic)x.MediaPart.ContentItem).LocalizationPart.Culture != null) ? ((dynamic)x.MediaPart.ContentItem).LocalizationPart.CultureField.Value.Culture : "" }).ToArray(), folderPath = Model.FolderPath })) } -