)> {
- var fp = FilePathEmbedded.New({
- binaryFile: info.binaryFile,
- entityId: info.imageId,
- mListRowId: null,
- fileType: getSymbol(FileTypeSymbol, this.pr.member!.defaultFileTypeInfo!.key),
- rootType: this.pr.findRootType().name,
- propertyRoute: this.pr.propertyPath()
- });
-
- if (fp.entityId == null && fp.binaryFile == null)
- return {JSON.stringify(info)}
;
-
- return ;
+ renderImage(info: ImageInfo): React.ReactElement {
+ return ;
}
toHtml(val: ImageInfo): string | undefined {
if (val.binaryFile)
return `
`;
- if (val.imageId)
- return `
`;
+ if (val.key)
+ return `
`;
return undefined;
}
@@ -72,12 +62,39 @@ export class HelpImageHandler implements ImageHandlerBase {
fromElement(element: HTMLDivElement): ImageInfo | undefined {
if (element.tagName == "IMG") {
return {
- binaryFile: element.dataset["binaryFile"],
- fileName: element.dataset["fileName"],
- imageId: element.dataset["helpImageId"],
+ binaryFile: element.getAttribute("data-binary-file") ?? undefined,
+ fileName: element.getAttribute("data-file-name") ?? undefined,
+ key: element.getAttribute("data-help-image-guid") ?? undefined,
};
}
return undefined;
}
}
+
+function InlineImage(p: { info: ImageInfo, pr: PropertyRoute }): React.ReactElement | undefined
+{
+ const imageId = useAPI(() => p.info.key && HelpClient.API.getImageId(p.info.key), []);
+
+ if (!imageId && !p.info.binaryFile)
+ return (
+
+
+
+ {HelpMessage.LoadingImage.niceToString()}...
+
+
+ );
+
+ const fp = FilePathEmbedded.New({
+ binaryFile: p.info.binaryFile,
+ entityId: imageId,
+ mListRowId: null,
+ fileType: getSymbol(FileTypeSymbol, p.pr.member!.defaultFileTypeInfo!.key),
+ rootType: p.pr.findRootType().name,
+ propertyRoute: p.pr.propertyPath()
+ });
+
+ return ;
+
+}
diff --git a/Extensions/Signum.Help/Editor/HelpImageNode.tsx b/Extensions/Signum.Help/Editor/HelpImageNode.tsx
index e3bc1d3eff..21f3283b98 100644
--- a/Extensions/Signum.Help/Editor/HelpImageNode.tsx
+++ b/Extensions/Signum.Help/Editor/HelpImageNode.tsx
@@ -4,8 +4,8 @@ import { ImageInfo } from '../../Signum.HtmlEditor/Extensions/ImageExtension/Ima
export class HelpImageNode extends ImageNodeBase {
static {
- this.converter = new HelpImageHandler();
- this.dataImageIdAttribute = "data-help-image-id";
+ this.handler = new HelpImageHandler();
+ this.dataImageIdAttribute = "data-help-image-guid";
}
static getType(): string {
diff --git a/Extensions/Signum.Help/HelpClient.tsx b/Extensions/Signum.Help/HelpClient.tsx
index 29d8b66778..d064dc2e4d 100644
--- a/Extensions/Signum.Help/HelpClient.tsx
+++ b/Extensions/Signum.Help/HelpClient.tsx
@@ -12,6 +12,7 @@ import { NamespaceHelpEntity, TypeHelpEntity, AppendixHelpEntity, QueryHelpEntit
import { QueryString } from '@framework/QueryString';
import { OmniboxClient } from '../Signum.Omnibox/OmniboxClient';
import HelpOmniboxProvider from './HelpOmniboxProvider';
+import * as OmniboxSpecialAction from '@framework/OmniboxSpecialAction'
import { CultureInfoEntity } from '@framework/Signum.Basics';
import { WidgetContext, onWidgets } from '@framework/Frames/Widgets';
import { HelpIcon, HelpWidget } from './HelpWidget';
@@ -28,6 +29,12 @@ export namespace HelpClient {
OmniboxClient.registerProvider(new HelpOmniboxProvider());
+ OmniboxSpecialAction.registerSpecialAction({
+ allowed: () => AppContext.isPermissionAuthorized(HelpPermissions.ExportHelp),
+ key: "ImportHelp",
+ onClick: () => Promise.resolve("/help/import")
+ });
+
options.routes.push({ path: "/help", element: import("./Pages/HelpIndexPage")} /> });
options.routes.push({ path: "/help/namespace/:namespace", element: import("./Pages/NamespaceHelpPage")} /> });
options.routes.push({ path: "/help/type/:cleanName", element: import("./Pages/TypeHelpPage")} /> });
@@ -164,6 +171,9 @@ export namespace HelpClient {
return ajaxPost({ url: "/api/help/applyImport" }, { file, model });
}
+ export function getImageId(guid: string): Promise {
+ return ajaxGet({ url: `/api/help/getImageId?guid=${guid}`, cache: 'default' as RequestCache });
+ }
}
diff --git a/Extensions/Signum.Help/HelpCommon.cs b/Extensions/Signum.Help/HelpCommon.cs
index a662a1fa0c..730d3d5ed6 100644
--- a/Extensions/Signum.Help/HelpCommon.cs
+++ b/Extensions/Signum.Help/HelpCommon.cs
@@ -164,7 +164,8 @@ public enum HelpMessage
SelectedFile,
HelpZipContents,
NewKey,
- ActionStatus
+ ActionStatus,
+ LoadingImage,
}
public enum HelpKindMessage
diff --git a/Extensions/Signum.Help/HelpController.cs b/Extensions/Signum.Help/HelpController.cs
index d25f544cf1..3b501d39bb 100644
--- a/Extensions/Signum.Help/HelpController.cs
+++ b/Extensions/Signum.Help/HelpController.cs
@@ -1,10 +1,9 @@
+using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Net.Http.Headers;
using Signum.API.Filters;
-using Signum.Basics;
using Signum.Files;
-using Signum.UserAssets;
using System.ComponentModel.DataAnnotations;
-using System.Globalization;
using System.IO;
namespace Signum.Help;
@@ -155,6 +154,19 @@ public FileStreamResult Export([Required, FromBody] Lite[] lites)
return MimeMapping.GetFileStreamResult(new MemoryStream(bytes), fileName);
}
+ [HttpGet("api/help/getImageId")]
+ public ActionResult GetImageId([Required, FromQuery] Guid guid)
+ {
+ Response.GetTypedHeaders().CacheControl = new CacheControlHeaderValue
+ {
+ Public = true,
+ MaxAge = TimeSpan.FromDays(365),
+ };
+
+ var id = HelpLogic.GetImageId(guid);
+ return id is null ? NotFound() : id.Value.ToString();
+ }
+
[HttpPost("api/help/importPreview")]
public HelpImportPreviewModel ImportPreview([Required, FromBody] FileUpload file)
{
diff --git a/Extensions/Signum.Help/HelpExportImport.cs b/Extensions/Signum.Help/HelpExportImport.cs
index 64a555e2d2..6c62021ffe 100644
--- a/Extensions/Signum.Help/HelpExportImport.cs
+++ b/Extensions/Signum.Help/HelpExportImport.cs
@@ -65,7 +65,7 @@ public enum ImportExecutionMode
private static FileContent[] GetImageContents(IHelpEntity entity) =>
[.. Database.Query().Where(a => a.Target.Is(entity))
- .Select(i => new FileContent(i.Id + "." + i.File.FileName, i.File.GetByteArray()))];
+ .Select(i => new FileContent(i.Guid + "." + i.File.FileName, i.File.GetByteArray()))];
private static byte[] ToBytes(this XDocument doc)
{
@@ -870,14 +870,16 @@ private static void ImportImages(IHelpEntity entity, HelpContent content)
Synchronizer.Synchronize(
newDictionary: content.Images.ToDictionaryEx(i => i.FileName),
- oldDictionary: oldImages.EmptyIfNull().ToDictionaryEx(o => o.Id + "." + o.File.FileName),
+ oldDictionary: oldImages.EmptyIfNull().ToDictionaryEx(o => o.Guid + "." + o.File.FileName),
createNew: (k, n) =>
{
- Administrator.SaveDisableIdentity(new HelpImageEntity
+ new HelpImageEntity
{
Target = (entity).ToLite(),
- File = new FilePathEmbedded(HelpImageFileType.Image, n.FileName.After("."), n.Bytes)
- }.SetId(Guid.Parse(n.FileName.Before("."))));
+ File = new FilePathEmbedded(HelpImageFileType.Image, n.FileName.After("."), n.Bytes),
+ Guid = Guid.Parse(n.FileName.Before("."))
+ }.Save();
+
SafeConsole.WriteColor(ConsoleColor.Green, '.');
},
removeOld: (k, o) =>
@@ -890,12 +892,6 @@ private static void ImportImages(IHelpEntity entity, HelpContent content)
});
}
-/* public static string TypesDirectory = "Types";
- public static string QueriesDirectory = "Query";
- public static string OperationsDirectory = "Operation";
- public static string NamespacesDirectory = "Namespace";
- public static string AppendicesDirectory = "Appendix";*/
-
#region Export methods
public static void ExportAll(string path)
diff --git a/Extensions/Signum.Help/HelpImage.cs b/Extensions/Signum.Help/HelpImage.cs
index 84f8cff575..c7acccaa1e 100644
--- a/Extensions/Signum.Help/HelpImage.cs
+++ b/Extensions/Signum.Help/HelpImage.cs
@@ -3,7 +3,6 @@
namespace Signum.Help;
[EntityKind(EntityKind.Part, EntityData.Master)]
-[PrimaryKey(typeof(Guid))]
public class HelpImageEntity : Entity
{
[ImplementedBy(typeof(AppendixHelpEntity), typeof(NamespaceHelpEntity), typeof(QueryHelpEntity), typeof(TypeHelpEntity))]
@@ -13,6 +12,10 @@ public class HelpImageEntity : Entity
[DefaultFileType(nameof(HelpImageFileType.Image), nameof(HelpImageFileType))]
public FilePathEmbedded File { get; set; }
+
+ [UniqueIndex]
+ public Guid Guid { get; set; } = Guid.NewGuid();
+
}
[AutoInit]
diff --git a/Extensions/Signum.Help/HelpLogic.cs b/Extensions/Signum.Help/HelpLogic.cs
index a0ede92b15..d2913fed5f 100644
--- a/Extensions/Signum.Help/HelpLogic.cs
+++ b/Extensions/Signum.Help/HelpLogic.cs
@@ -7,11 +7,8 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using Signum.Engine.Sync;
-using Signum.Basics;
using Signum.Omnibox;
using Signum.Files;
-using Signum.Entities;
-using DocumentFormat.OpenXml.Vml.Office;
using Signum.API;
namespace Signum.Help;
@@ -237,7 +234,10 @@ public static CultureInfo GetCulture()
throw new InvalidOperationException("No compatible CultureInfo found in the database for {0}".FormatWith(ci.Name));
}
-
+ public static PrimaryKey? GetImageId(Guid guid)
+ {
+ return Database.Query().Single((HelpImageEntity a) => a.Guid == guid).Id;
+ }
public static List AllTypes()
{
diff --git a/Extensions/Signum.Help/InlineImagesLogic.cs b/Extensions/Signum.Help/InlineImagesLogic.cs
index 765759d2e5..6f53ef3878 100644
--- a/Extensions/Signum.Help/InlineImagesLogic.cs
+++ b/Extensions/Signum.Help/InlineImagesLogic.cs
@@ -11,16 +11,16 @@ public static class InlineImagesLogic
public static IQueryable Images(this IHelpEntity e) =>
As.Expression(() => Database.Query().Where(a => a.Target.Is(e)));
- public static Regex ImgRegex = new Regex(@"
[\w\-]+)\s*=\s*""(?[^""]+)"")+\s*/?>");
+ public static Regex ImgRegex = new(@"
[\w\-]+)\s*=\s*""(?[^""]+)"")+\s*/?>");
public static bool SynchronizeInlineImages(IHelpEntity entity)
{
using (OperationLogic.AllowSave())
{
- var toDeleteImages = entity.IsNew ? new Dictionary>() :
- entity.Images().Select(a => a.ToLite()).ToDictionaryEx(a => a.Id) ;
+ var toDeleteImages = entity.IsNew ? [] :
+ entity.Images().Select(a => new { lite = a.ToLite(), a.Guid }).ToDictionaryEx(a => a.Guid) ;
- List newImages = new List();
+ List newImages = [];
var hasChanges = entity.ForeachHtmlField(text =>
{
@@ -28,9 +28,9 @@ public static bool SynchronizeInlineImages(IHelpEntity entity)
{
Dictionary atts = GetTagAttributes(m);
var newAtts = atts.ToDictionary();
- if (atts.TryGetValue("data-help-image-id", out var imageId))
+ if (atts.TryGetValue("data-help-image-guid", out var imageGuid))
{
- toDeleteImages.Remove(PrimaryKey.Parse(imageId, typeof(HelpImageEntity)));
+ toDeleteImages.Remove(Guid.Parse(imageGuid));
}
if (atts.TryGetValue("data-binary-file", out var base64Data))
@@ -53,7 +53,7 @@ public static bool SynchronizeInlineImages(IHelpEntity entity)
else
{
image.Save();
- newAtts.Add("data-help-image-id", image.Id.ToString());
+ newAtts.Add("data-help-image-guid", image.Guid.ToString());
}
}
@@ -64,7 +64,7 @@ public static bool SynchronizeInlineImages(IHelpEntity entity)
});
if (toDeleteImages.Any())
- Database.DeleteList(toDeleteImages.Values.ToList());
+ Database.DeleteList(toDeleteImages.Values.Select(a => a.lite).ToList());
if (!hasChanges)
return false;
@@ -74,7 +74,7 @@ public static bool SynchronizeInlineImages(IHelpEntity entity)
entity.Save();
newImages.SaveList();
- var hashToHelpImageId = newImages.ToDictionary(a => a.File.Hash!, a => a.Id);
+ var hashToHelpImageId = newImages.ToDictionary(a => a.File.Hash!, a => a.Guid);
entity.ForeachHtmlField(text => ImgRegex.Replace(text?? "", m =>
{
@@ -83,7 +83,7 @@ public static bool SynchronizeInlineImages(IHelpEntity entity)
if (atts.TryGetValue("data-hash", out var hash))
{
atts.Remove("data-hash");
- atts.Add("data-help-image-id", hashToHelpImageId.GetOrThrow(hash).ToString());
+ atts.Add("data-help-image-guid", hashToHelpImageId.GetOrThrow(hash).ToString());
}
return $"
$"{a.Key}=\"{a.Value}\"", " ")}/>";
diff --git a/Extensions/Signum.Help/Signum.Help.csproj b/Extensions/Signum.Help/Signum.Help.csproj
index 86335a0089..bd5b5a8b2f 100644
--- a/Extensions/Signum.Help/Signum.Help.csproj
+++ b/Extensions/Signum.Help/Signum.Help.csproj
@@ -15,7 +15,7 @@
-
+