Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/VirtoCommerce.ContentModule.Core/Services/IContentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,27 @@ public interface IContentService
Task CopyContentAsync(string contentType, string storeId, string srcPath, string destPath);
Task<ContentFile> GetFileAsync(string contentType, string storeId, string relativeUrl);
Task<IndexableContentFile> GetFileContentAsync(string contentType, string storeId, string relativeUrl);

/// <summary>
/// Asynchronously retrieves the content of a file identified by the specified ID.
/// </summary>
/// <param name="id">The unique identifier of the file to retrieve. Cannot be null or empty. It is used as documentId for fulltext search service.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains an <see
/// cref="IndexableContentFile"/> representing the file content if found; otherwise, <see langword="null"/>.</returns>
Task<IndexableContentFile> GetFileContentAsync(string id);
Task CreateFolderAsync(string contentType, string storeId, ContentFolder folder);

Task<bool> ItemExistsAsync(string contentType, string storeId, string relativeUrl);
Task<Stream> GetItemStreamAsync(string contentType, string storeId, string relativeUrl);

/// <summary>
/// Asynchronously retrieves a stream for reading the content of the item with the specified identifier.
/// </summary>
/// <param name="id">The unique identifier of the item to retrieve. Cannot be null or empty. It is used as documentId for fulltext search service also.</param>
/// <returns>A task that represents the asynchronous operation. The task result contains a stream for reading the item's
/// content.</returns>
Task<Stream> GetItemStreamAsync(string id);

Task UnpackAsync(string contentType, string storeId, string archivePath, string destPath);

Task<ContentFile> DownloadContentAsync(string contentType, string storeId, string srcUrl, string folderPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@
using System.Text;
using VirtoCommerce.ContentModule.Core.Model;

namespace VirtoCommerce.ContentModule.Data.Search
namespace VirtoCommerce.ContentModule.Data.Search;

internal static class DocumentIdentifierHelper
{
internal static class DocumentIdentifierHelper
public static string GenerateId(string storeId, string contentType, ContentItem file)
{
public static string GenerateId(string storeId, string contentType, ContentItem file)
{
return Convert.ToBase64String(Encoding.ASCII.GetBytes($"{storeId}::{contentType}::{file.RelativeUrl}")).Replace('=', '-');
}

public static (string storeId, string contentType, string relativeUrl) ParseId(string id)
{
var decoded = Encoding.ASCII.GetString(Convert.FromBase64String(id.Replace('-', '=')));
var result = decoded.Split(["::"], StringSplitOptions.RemoveEmptyEntries);
return Convert.ToBase64String(Encoding.ASCII.GetBytes($"{storeId}::{contentType}::{file.RelativeUrl}")).Replace('=', '-');
}

if (result.Length == 3)
{
return (result[0], result[1], result[2]);
}
public static (string storeId, string contentType, string relativeUrl) ParseId(string id)
{
var decoded = Encoding.ASCII.GetString(Convert.FromBase64String(id.Replace('-', '=')));
var result = decoded.Split(["::"], StringSplitOptions.RemoveEmptyEntries);

return (null, null, null);
if (result.Length == 3)
{
return (result[0], result[1], result[2]);
}

return (null, null, null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ protected virtual async Task<IList<IndexableContentFile>> GetItemsByPathsAsync(I

foreach (var document in documents)
{
var (storeId, contentType, relativeUrl) = DocumentIdentifierHelper.ParseId(document.Id);
var contentItem = await _contentService.GetFileContentAsync(contentType, storeId, relativeUrl);
var contentItem = await _contentService.GetFileContentAsync(document.Id);
if (contentItem != null)
{
contentItem.Id = document.Id;
Expand Down
13 changes: 13 additions & 0 deletions src/VirtoCommerce.ContentModule.Data/Services/ContentService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using VirtoCommerce.ContentModule.Core.Services;
using VirtoCommerce.ContentModule.Data.Extensions;
using VirtoCommerce.ContentModule.Data.Model;
using VirtoCommerce.ContentModule.Data.Search;
using VirtoCommerce.Platform.Core.Common;
using VirtoCommerce.Platform.Core.Events;
using UrlHelperExtensions = VirtoCommerce.Platform.Core.Extensions.UrlHelperExtensions;
Expand Down Expand Up @@ -102,6 +103,12 @@ public async Task<IndexableContentFile> GetFileContentAsync(string contentType,
return result;
}

public async Task<IndexableContentFile> GetFileContentAsync(string id)
{
var (storeId, contentType, relativeUrl) = DocumentIdentifierHelper.ParseId(id);
return await GetFileContentAsync(contentType, storeId, relativeUrl);
}

public async Task CreateFolderAsync(string contentType, string storeId, ContentFolder folder)
{
var storageProvider = GetStorageProvider(contentType, storeId);
Expand All @@ -123,6 +130,12 @@ public async Task<Stream> GetItemStreamAsync(string contentType, string storeId,
return fileStream;
}

public async Task<Stream> GetItemStreamAsync(string id)
{
var (storeId, contentType, relativeUrl) = DocumentIdentifierHelper.ParseId(id);
return await GetItemStreamAsync(contentType, storeId, relativeUrl);
}

public async Task UnpackAsync(string contentType, string storeId, string archivePath, string destPath)
{
var storageProvider = GetStorageProvider(contentType, storeId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ angular.module('virtoCommerce.contentModule')
canExecuteMethod: function () { return !isDirty(); }
};


if (!blade.isNew) {
toolbarCommands = [
{
Expand Down Expand Up @@ -351,17 +350,21 @@ angular.module('virtoCommerce.contentModule')
name: "content.commands.preview-page",
icon: 'fa fa-eye',
executeMethod: function () {
const urlListBlade = {
id: "storeUrlList",
storeId: blade.storeId,
contentType: blade.contentType,
relativeUrl: blade.currentEntity.relativeUrl,
headIcon: 'fa-plus-square-o',
controller: 'virtoCommerce.contentModule.storeUrlListController',
template: 'Modules/$(VirtoCommerce.Content)/Scripts/blades/pages/store-url-list.tpl.html'
var showPreview = function () {
var storeUrl = blade.storeUrl?.replace(/\/$/, '');
if (storeUrl) {
var documentId = filesDraftService.getDocumentId(blade, true);
window.open(`${storeUrl}/designer-preview?pageId=${encodeURIComponent(documentId)}`, '_blank');
} else {
var dialog = {
id: "noUrlInStore",
title: "content.dialogs.set-store-url.title",
message: "content.dialogs.set-store-url.message"
};
dialogService.showNotificationDialog(dialog);
}
};

bladeNavigationService.showBlade(urlListBlade, blade);
showPreview();
},
canExecuteMethod: function () { return true; }
}
Expand Down Expand Up @@ -404,8 +407,12 @@ angular.module('virtoCommerce.contentModule')
executeMethod: function () {
getDocumentIndex(function (data) {
var doc = getSearchDocumentInfo();
if (!doc) {
console.log('Document id error', blade);
return;
}
const searchBlade = {
id: 'sesarchDetails',
id: 'searchDetails',
currentEntityId: doc.documentId,
currentEntity: blade.currentEntity,
data: $scope.index,
Expand All @@ -418,11 +425,15 @@ angular.module('virtoCommerce.contentModule')
bladeNavigationService.showBlade(searchBlade, blade);
});
},
canExecuteMethod: function () { return true; }
canExecuteMethod: function () { return !!$scope.index; }
});
}

function updateIndexStatus(data, doc) {
if (!doc || !_.any(data)) {
$scope.index = null;
return;
}
if (_.any(data)) {
$scope.index = data[0];
$scope.indexDate = moment.utc($scope.index.indexationdate, momentFormat);
Expand All @@ -439,19 +450,25 @@ angular.module('virtoCommerce.contentModule')
}

function getSearchDocumentInfo() {
var relativeUrl = filesDraftService.undraftUrl(blade.currentEntity.relativeUrl);
var documentId = btoa(`${blade.storeId}::${blade.contentType}::${relativeUrl}`).replaceAll('=', '-');
var documentId = filesDraftService.getDocumentId(blade);
if (!documentId) {
return null;
}
var documentType = 'ContentFile';
return { documentType: documentType, documentId: documentId };
}

function getDocumentIndex(callback) {
if ($scope.searchEnabled) {
var doc = getSearchDocumentInfo();
searchApi.getDocIndex(doc, function (data) {
updateIndexStatus(data, doc);
callback && _.any(data) && callback();
});
if (!!doc) {
searchApi.getDocIndex(doc, function (data) {
updateIndexStatus(data, doc);
callback && _.any(data) && callback();
});
} else {
updateIndexStatus(null, null);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@ angular.module('virtoCommerce.contentModule')

var $this = this;

this.getDocumentId = function (blade, real) {
if (!blade || !blade.currentEntity) {
return null;
}
const relativeUrl = real ? $this.getRealFileName(blade) : $this.undraftUrl(blade.currentEntity.relativeUrl);
return btoa(`${blade.storeId}::${blade.contentType}::${relativeUrl}`).replaceAll('=', '-');
}

this.getRealFileName = function (blade) {
var relativeUrl = blade.currentEntity.relativeUrl;
var isDraft = blade.currentEntity.hasChanges;
if (!isDraft) {
return $this.undraftUrl(relativeUrl);
}
if (!relativeUrl.endsWith('-draft')) {
return $this.getDraftFileName(blade);
}
return relativeUrl;
}

this.getDraftFileName = function (blade) {
var relativeUrl = blade.currentEntity.relativeUrl;
// the draft page should be under editing in the designer
Expand Down
Loading