diff --git a/Squidex.sln.DotSettings b/Squidex.sln.DotSettings index 235489b1a..3698200b1 100644 --- a/Squidex.sln.DotSettings +++ b/Squidex.sln.DotSettings @@ -36,12 +36,12 @@ <?xml version="1.0" encoding="utf-16"?><Profile name="Header"><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile> <?xml version="1.0" encoding="utf-16"?><Profile name="Namespaces"><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSUpdateFileHeader>True</CSUpdateFileHeader></Profile> <?xml version="1.0" encoding="utf-16"?><Profile name="Typescript"><JsInsertSemicolon>True</JsInsertSemicolon><FormatAttributeQuoteDescriptor>True</FormatAttributeQuoteDescriptor><CorrectVariableKindsDescriptor>True</CorrectVariableKindsDescriptor><VariablesToInnerScopesDescriptor>True</VariablesToInnerScopesDescriptor><StringToTemplatesDescriptor>True</StringToTemplatesDescriptor><RemoveRedundantQualifiersTs>True</RemoveRedundantQualifiersTs><OptimizeImportsTs>True</OptimizeImportsTs></Profile> + False ========================================================================== - $FILENAME$ Squidex Headless CMS ========================================================================== - Copyright (c) Squidex Group - All rights reserved. + Copyright (c) Squidex UG (haftungsbeschraenkt) + All rights reserved. Licensed under the MIT license. ========================================================================== \ No newline at end of file diff --git a/src/Squidex.Domain.Apps.Core.Model/Rules/Actions/AlgoliaAction.cs b/src/Squidex.Domain.Apps.Core.Model/Rules/Actions/AlgoliaAction.cs new file mode 100644 index 000000000..e8040e57d --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Model/Rules/Actions/AlgoliaAction.cs @@ -0,0 +1,66 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using Squidex.Infrastructure; + +namespace Squidex.Domain.Apps.Core.Rules.Actions +{ + [TypeName(nameof(AlgoliaAction))] + public sealed class AlgoliaAction : RuleAction + { + private string appId; + private string apiKey; + private string indexName; + + public string AppId + { + get + { + return appId; + } + set + { + ThrowIfFrozen(); + + appId = value; + } + } + + public string ApiKey + { + get + { + return apiKey; + } + set + { + ThrowIfFrozen(); + + apiKey = value; + } + } + + public string IndexName + { + get + { + return indexName; + } + set + { + ThrowIfFrozen(); + + indexName = value; + } + } + + public override T Accept(IRuleActionVisitor visitor) + { + return visitor.Visit(this); + } + } +} diff --git a/src/Squidex.Domain.Apps.Core.Model/Rules/IRuleActionVisitor.cs b/src/Squidex.Domain.Apps.Core.Model/Rules/IRuleActionVisitor.cs index 41f68b54e..44651d1fe 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Rules/IRuleActionVisitor.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Rules/IRuleActionVisitor.cs @@ -11,6 +11,8 @@ namespace Squidex.Domain.Apps.Core.Rules { public interface IRuleActionVisitor { + T Visit(AlgoliaAction action); + T Visit(WebhookAction action); } } diff --git a/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Actions/AlgoliaActionHandler.cs b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Actions/AlgoliaActionHandler.cs new file mode 100644 index 000000000..2d19a7278 --- /dev/null +++ b/src/Squidex.Domain.Apps.Core.Operations/HandleRules/Actions/AlgoliaActionHandler.cs @@ -0,0 +1,141 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.Collections.Concurrent; +using System.Threading.Tasks; +using Algolia.Search; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Squidex.Domain.Apps.Core.Rules; +using Squidex.Domain.Apps.Core.Rules.Actions; +using Squidex.Domain.Apps.Events; +using Squidex.Domain.Apps.Events.Contents; +using Squidex.Infrastructure; +using Squidex.Infrastructure.EventSourcing; + +namespace Squidex.Domain.Apps.Core.HandleRules.Actions +{ + public sealed class AlgoliaActionHandler : RuleActionHandler + { + private readonly ConcurrentDictionary<(string AppId, string ApiKey, string IndexName), Index> clients = new ConcurrentDictionary<(string AppId, string ApiKey, string IndexName), Index>(); + private readonly JsonSerializer serializer; + + public AlgoliaActionHandler(JsonSerializer serializer) + { + Guard.NotNull(serializer, nameof(serializer)); + + this.serializer = serializer; + } + + protected override (string Description, RuleJobData Data) CreateJob(Envelope @event, string eventName, AlgoliaAction action) + { + var ruleDescription = string.Empty; + var ruleData = new RuleJobData + { + ["AppId"] = action.AppId, + ["ApiKey"] = action.ApiKey, + ["IndexName"] = action.IndexName + }; + + if (@event.Payload is ContentEvent contentEvent) + { + ruleData["ContentId"] = contentEvent.ContentId.ToString(); + ruleData["Operation"] = "Upsert"; + + switch (@event.Payload) + { + case ContentCreated created: + { + ruleDescription = $"Add entry to Algolia index: {action.IndexName}"; + ruleData["Content"] = new JObject( + new JProperty("data", JObject.FromObject(created.Data, serializer))); + break; + } + + case ContentUpdated updated: + { + ruleDescription = $"Update entry in Algolia index: {action.IndexName}"; + ruleData["Content"] = new JObject( + new JProperty("data", JObject.FromObject(updated.Data, serializer))); + break; + } + + case ContentStatusChanged statusChanged: + { + ruleDescription = $"Update entry in Algolia index: {action.IndexName}"; + ruleData["Content"] = new JObject( + new JProperty("status", statusChanged.Status.ToString())); + break; + } + + case ContentDeleted deleted: + { + ruleDescription = $"Delete entry from Index: {action.IndexName}"; + ruleData["Content"] = new JObject(); + break; + } + } + } + + return (ruleDescription, ruleData); + } + + public override async Task<(string Dump, Exception Exception)> ExecuteJobAsync(RuleJobData job) + { + var appId = (string)job["AppId"]; + var apiKey = (string)job["ApiKey"]; + var indexName = (string)job["IndexName"]; + + var index = clients.GetOrAdd((appId, apiKey, indexName), s => + { + var client = new AlgoliaClient(appId, apiKey); + + return client.InitIndex(indexName); + }); + + var operation = (string)job["Operation"]; + var content = (JObject)job["Content"]; + var contentId = (string)job["ContentId"]; + + try + { + switch (operation) + { + case "Upsert": + { + content["objectID"] = contentId; + + var resonse = await index.PartialUpdateObjectAsync(content); + + return (resonse.ToString(Formatting.Indented), null); + } + + case "Delete": + { + var resonse = await index.DeleteObjectAsync(contentId); + + return (resonse.ToString(Formatting.Indented), null); + } + + default: + { + return ("Nothing to do!", null); + } + } + } + catch (AlgoliaException ex) + { + return (ex.Message, ex); + } + catch (Exception ex) + { + return (null, ex); + } + } + } +} diff --git a/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj b/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj index 1932d0681..631f0b094 100644 --- a/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj +++ b/src/Squidex.Domain.Apps.Core.Operations/Squidex.Domain.Apps.Core.Operations.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs b/src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs index a871182b2..2e786f76c 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/Guards/RuleActionValidator.cs @@ -24,6 +24,28 @@ namespace Squidex.Domain.Apps.Entities.Rules.Guards return action.Accept(visitor); } + public Task> Visit(AlgoliaAction action) + { + var errors = new List(); + + if (string.IsNullOrWhiteSpace(action.ApiKey)) + { + errors.Add(new ValidationError("Api key must be defined.", nameof(action.ApiKey))); + } + + if (string.IsNullOrWhiteSpace(action.AppId)) + { + errors.Add(new ValidationError("Application ID key must be defined.", nameof(action.AppId))); + } + + if (string.IsNullOrWhiteSpace(action.IndexName)) + { + errors.Add(new ValidationError("Index name key must be defined.", nameof(action.ApiKey))); + } + + return Task.FromResult>(errors); + } + public Task> Visit(WebhookAction action) { var errors = new List(); diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/Actions/AlgoliaActionDto.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/Actions/AlgoliaActionDto.cs new file mode 100644 index 000000000..38c9b1d67 --- /dev/null +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/Actions/AlgoliaActionDto.cs @@ -0,0 +1,43 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschränkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System; +using System.ComponentModel.DataAnnotations; +using NJsonSchema.Annotations; +using Squidex.Domain.Apps.Core.Rules; +using Squidex.Domain.Apps.Core.Rules.Actions; +using Squidex.Infrastructure.Reflection; + +namespace Squidex.Areas.Api.Controllers.Rules.Models.Actions +{ + [JsonSchema("Algolia")] + public sealed class AlgoliaActionDto : RuleActionDto + { + /// + /// The application ID. + /// + [Required] + public string AppId { get; set; } + + /// + /// The API key to grant access to Squidex. + /// + [Required] + public string ApiKey { get; set; } + + /// + /// The name of the index. + /// + [Required] + public string IndexName { get; set; } + + public override RuleAction ToAction() + { + return SimpleMapper.Map(this, new AlgoliaAction()); + } + } +} diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleActionDtoFactory.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleActionDtoFactory.cs index 264298fee..22b85de66 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleActionDtoFactory.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/Converters/RuleActionDtoFactory.cs @@ -25,6 +25,11 @@ namespace Squidex.Areas.Api.Controllers.Rules.Models.Converters return properties.Accept(Instance); } + public RuleActionDto Visit(AlgoliaAction action) + { + return SimpleMapper.Map(action, new AlgoliaActionDto()); + } + public RuleActionDto Visit(WebhookAction action) { return SimpleMapper.Map(action, new WebhookActionDto()); diff --git a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionDto.cs b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionDto.cs index 629781317..6e8591440 100644 --- a/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionDto.cs +++ b/src/Squidex/Areas/Api/Controllers/Rules/Models/RuleActionDto.cs @@ -13,6 +13,7 @@ using Squidex.Domain.Apps.Core.Rules; namespace Squidex.Areas.Api.Controllers.Rules.Models { [JsonConverter(typeof(JsonInheritanceConverter), "actionType")] + [KnownType(typeof(AlgoliaActionDto))] [KnownType(typeof(WebhookActionDto))] public abstract class RuleActionDto { diff --git a/src/Squidex/Config/Domain/ReadServices.cs b/src/Squidex/Config/Domain/ReadServices.cs index e1a4da864..ac5cd1df0 100644 --- a/src/Squidex/Config/Domain/ReadServices.cs +++ b/src/Squidex/Config/Domain/ReadServices.cs @@ -92,6 +92,9 @@ namespace Squidex.Config.Domain services.AddSingletonAs() .As(); + services.AddSingletonAs() + .As(); + services.AddSingletonAs() .As(); diff --git a/src/Squidex/Squidex.csproj b/src/Squidex/Squidex.csproj index 422b68ef3..367d22302 100644 --- a/src/Squidex/Squidex.csproj +++ b/src/Squidex/Squidex.csproj @@ -48,6 +48,7 @@ + diff --git a/src/Squidex/app/features/rules/declarations.ts b/src/Squidex/app/features/rules/declarations.ts index f955e0400..938940695 100644 --- a/src/Squidex/app/features/rules/declarations.ts +++ b/src/Squidex/app/features/rules/declarations.ts @@ -5,6 +5,7 @@ * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. */ +export * from './pages/rules/actions/algolia-action.component'; export * from './pages/rules/actions/webhook-action.component'; export * from './pages/rules/triggers/content-changed-trigger.component'; export * from './pages/rules/rule-wizard.component'; diff --git a/src/Squidex/app/features/rules/module.ts b/src/Squidex/app/features/rules/module.ts index 856ee69ed..7fe03a653 100644 --- a/src/Squidex/app/features/rules/module.ts +++ b/src/Squidex/app/features/rules/module.ts @@ -14,6 +14,7 @@ import { } from 'shared'; import { + AlgoliaActionComponent, ContentChangedTriggerComponent, RuleEventsPageComponent, RulesPageComponent, @@ -41,6 +42,7 @@ const routes: Routes = [ RouterModule.forChild(routes) ], declarations: [ + AlgoliaActionComponent, ContentChangedTriggerComponent, RuleEventsPageComponent, RulesPageComponent, diff --git a/src/Squidex/app/features/rules/pages/rules/actions/algolia-action.component.html b/src/Squidex/app/features/rules/pages/rules/actions/algolia-action.component.html new file mode 100644 index 000000000..204eeadf5 --- /dev/null +++ b/src/Squidex/app/features/rules/pages/rules/actions/algolia-action.component.html @@ -0,0 +1,43 @@ + + + App ID + + + + + + + + The ID to you algolia application. + + + + + + Api Key + + + + + + + + The API Key to access you algolia app. + + + + + + Index Name + + + + + + + + The name of the index. Use $SCHEMA_NAME as a placeholder + + + + \ No newline at end of file diff --git a/src/Squidex/app/features/rules/pages/rules/actions/algolia-action.component.scss b/src/Squidex/app/features/rules/pages/rules/actions/algolia-action.component.scss new file mode 100644 index 000000000..fbb752506 --- /dev/null +++ b/src/Squidex/app/features/rules/pages/rules/actions/algolia-action.component.scss @@ -0,0 +1,2 @@ +@import '_vars'; +@import '_mixins'; \ No newline at end of file diff --git a/src/Squidex/app/features/rules/pages/rules/actions/algolia-action.component.ts b/src/Squidex/app/features/rules/pages/rules/actions/algolia-action.component.ts new file mode 100644 index 000000000..40992ae89 --- /dev/null +++ b/src/Squidex/app/features/rules/pages/rules/actions/algolia-action.component.ts @@ -0,0 +1,62 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved. + */ + +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FormBuilder, Validators } from '@angular/forms'; + +@Component({ + selector: 'sqx-algolia-action', + styleUrls: ['./algolia-action.component.scss'], + templateUrl: './algolia-action.component.html' +}) +export class AlgoliaActionComponent implements OnInit { + @Input() + public action: any; + + @Output() + public actionChanged = new EventEmitter(); + + public actionFormSubmitted = false; + public actionForm = + this.formBuilder.group({ + appId: ['', + [ + Validators.required + ]], + apiKey: ['', + [ + Validators.required + ]], + indexName: ['$SCHEMA_NAME', + [ + Validators.required + ]] + }); + + constructor( + private readonly formBuilder: FormBuilder + ) { + } + + public ngOnInit() { + this.action = Object.assign({}, { appId: '', apiKey: '', indexName: '$SCHEMA_NAME' }, this.action || {}); + + this.actionFormSubmitted = false; + this.actionForm.reset(); + this.actionForm.setValue(this.action); + } + + public save() { + this.actionFormSubmitted = true; + + if (this.actionForm.valid) { + const action = this.actionForm.value; + + this.actionChanged.emit(action); + } + } +} \ No newline at end of file diff --git a/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.html b/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.html index 88bc0b3a7..0472353d0 100644 --- a/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.html +++ b/src/Squidex/app/features/rules/pages/rules/rule-wizard.component.html @@ -62,6 +62,12 @@ + + + + - Font Name: icomoon (Glyphs: 79) + Font Name: icomoon (Glyphs: 80) Grid Size: Unknown + + + + + + icon-action-Algolia + + + + + + + liga: + + + diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.eot b/src/Squidex/app/theme/icomoon/fonts/icomoon.eot index 35232346a..76dc93458 100644 Binary files a/src/Squidex/app/theme/icomoon/fonts/icomoon.eot and b/src/Squidex/app/theme/icomoon/fonts/icomoon.eot differ diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg index 3fa9b2d05..a9ff806ec 100644 --- a/src/Squidex/app/theme/icomoon/fonts/icomoon.svg +++ b/src/Squidex/app/theme/icomoon/fonts/icomoon.svg @@ -83,6 +83,7 @@ + diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf b/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf index 6ab61f820..8e08f6e96 100644 Binary files a/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf and b/src/Squidex/app/theme/icomoon/fonts/icomoon.ttf differ diff --git a/src/Squidex/app/theme/icomoon/fonts/icomoon.woff b/src/Squidex/app/theme/icomoon/fonts/icomoon.woff index 80281cba8..ca6fd6ece 100644 Binary files a/src/Squidex/app/theme/icomoon/fonts/icomoon.woff and b/src/Squidex/app/theme/icomoon/fonts/icomoon.woff differ diff --git a/src/Squidex/app/theme/icomoon/icons/algolia.svg b/src/Squidex/app/theme/icomoon/icons/algolia.svg new file mode 100644 index 000000000..4f1539080 --- /dev/null +++ b/src/Squidex/app/theme/icomoon/icons/algolia.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + algolia-new-logo copy + + diff --git a/src/Squidex/app/theme/icomoon/selection.json b/src/Squidex/app/theme/icomoon/selection.json index e9e8c0849..8a16e22e4 100644 --- a/src/Squidex/app/theme/icomoon/selection.json +++ b/src/Squidex/app/theme/icomoon/selection.json @@ -1,6 +1,35 @@ { "IcoMoonType": "selection", "icons": [ + { + "icon": { + "paths": [ + "M512 26.947c-267.728 0-485.053 217.059-485.053 485.053s217.069 485.053 485.053 485.053c267.983 0 485.053-217.314 485.053-485.308s-217.069-484.797-485.053-484.797zM512 853.496c-188.747 0-341.745-152.988-341.745-341.752 0-188.745 152.998-341.733 341.745-341.733 188.765 0 341.745 152.988 341.745 341.733 0 188.763-152.98 341.752-341.745 341.752zM512 240.522v254.585c0 7.443 7.957 12.405 14.654 8.939l225.774-117.231c5.042-2.659 6.844-8.986 3.96-13.901-46.936-82.204-133.855-138.576-234.205-142.298z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "isMulticolor2": false, + "grid": 0, + "tags": [ + "algolia-mark-white" + ] + }, + "attrs": [ + {} + ], + "properties": { + "order": 101, + "id": 1, + "name": "action-Algolia", + "prevSize": 32, + "code": 59724 + }, + "setIdx": 0, + "setId": 2, + "iconIdx": 0 + }, { "icon": { "paths": [ @@ -52,7 +81,7 @@ "code": 59722 }, "setIdx": 1, - "setId": 2, + "setId": 1, "iconIdx": 0 }, { @@ -80,9 +109,9 @@ "prevSize": 32, "code": 59652 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 22 + "iconIdx": 1 }, { "icon": { @@ -109,9 +138,9 @@ "prevSize": 32, "code": 59653 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 23 + "iconIdx": 2 }, { "icon": { @@ -138,9 +167,9 @@ "prevSize": 32, "code": 59654 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 24 + "iconIdx": 3 }, { "icon": { @@ -167,9 +196,9 @@ "prevSize": 32, "code": 59655 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 25 + "iconIdx": 4 }, { "icon": { @@ -196,9 +225,9 @@ "prevSize": 32, "code": 59656 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 26 + "iconIdx": 5 }, { "icon": { @@ -225,9 +254,9 @@ "prevSize": 32, "code": 59657 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 27 + "iconIdx": 6 }, { "icon": { @@ -254,9 +283,9 @@ "prevSize": 32, "code": 59658 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 28 + "iconIdx": 7 }, { "icon": { @@ -283,9 +312,9 @@ "prevSize": 32, "code": 59659 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 29 + "iconIdx": 8 }, { "icon": { @@ -312,9 +341,9 @@ "prevSize": 32, "code": 59660 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 30 + "iconIdx": 9 }, { "icon": { @@ -341,9 +370,9 @@ "prevSize": 32, "code": 59661 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 31 + "iconIdx": 10 }, { "icon": { @@ -370,9 +399,9 @@ "prevSize": 32, "code": 59662 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 32 + "iconIdx": 11 }, { "icon": { @@ -399,9 +428,9 @@ "prevSize": 32, "code": 59663 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 33 + "iconIdx": 12 }, { "icon": { @@ -428,9 +457,9 @@ "prevSize": 32, "code": 59664 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 34 + "iconIdx": 13 }, { "icon": { @@ -463,9 +492,9 @@ "prevSize": 32, "code": 59665 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 35 + "iconIdx": 14 }, { "icon": { @@ -492,9 +521,9 @@ "prevSize": 32, "code": 59666 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 36 + "iconIdx": 15 }, { "icon": { @@ -521,9 +550,9 @@ "prevSize": 32, "code": 59667 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 37 + "iconIdx": 16 }, { "icon": { @@ -550,9 +579,9 @@ "prevSize": 32, "code": 59668 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 38 + "iconIdx": 17 }, { "icon": { @@ -579,9 +608,9 @@ "prevSize": 32, "code": 59669 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 39 + "iconIdx": 18 }, { "icon": { @@ -608,9 +637,9 @@ "prevSize": 32, "code": 59670 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 40 + "iconIdx": 19 }, { "icon": { @@ -637,9 +666,9 @@ "prevSize": 32, "code": 59671 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 41 + "iconIdx": 20 }, { "icon": { @@ -666,9 +695,9 @@ "prevSize": 32, "code": 59672 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 42 + "iconIdx": 21 }, { "icon": { @@ -696,9 +725,9 @@ "prevSize": 32, "code": 59713 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 43 + "iconIdx": 22 }, { "icon": { @@ -725,9 +754,9 @@ "prevSize": 32, "code": 59673 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 44 + "iconIdx": 23 }, { "icon": { @@ -754,9 +783,9 @@ "prevSize": 32, "code": 59675 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 45 + "iconIdx": 24 }, { "icon": { @@ -783,9 +812,9 @@ "prevSize": 32, "code": 59676 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 46 + "iconIdx": 25 }, { "icon": { @@ -812,9 +841,9 @@ "prevSize": 32, "code": 59677 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 47 + "iconIdx": 26 }, { "icon": { @@ -841,9 +870,9 @@ "prevSize": 32, "code": 59678 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 48 + "iconIdx": 27 }, { "icon": { @@ -870,9 +899,9 @@ "prevSize": 32, "code": 59679 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 49 + "iconIdx": 28 }, { "icon": { @@ -899,9 +928,9 @@ "prevSize": 32, "code": 59680 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 50 + "iconIdx": 29 }, { "icon": { @@ -937,9 +966,9 @@ "prevSize": 32, "code": 59681 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 51 + "iconIdx": 30 }, { "icon": { @@ -966,9 +995,9 @@ "prevSize": 32, "code": 59682 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 52 + "iconIdx": 31 }, { "icon": { @@ -995,9 +1024,9 @@ "prevSize": 32, "code": 59683 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 53 + "iconIdx": 32 }, { "icon": { @@ -1024,9 +1053,9 @@ "prevSize": 32, "code": 59684 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 54 + "iconIdx": 33 }, { "icon": { @@ -1053,9 +1082,9 @@ "prevSize": 32, "code": 59685 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 55 + "iconIdx": 34 }, { "icon": { @@ -1082,9 +1111,9 @@ "prevSize": 32, "code": 59674 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 56 + "iconIdx": 35 }, { "icon": { @@ -1111,9 +1140,9 @@ "prevSize": 32, "code": 59686 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 57 + "iconIdx": 36 }, { "icon": { @@ -1140,9 +1169,9 @@ "prevSize": 32, "code": 59687 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 58 + "iconIdx": 37 }, { "icon": { @@ -1169,9 +1198,9 @@ "prevSize": 32, "code": 59688 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 59 + "iconIdx": 38 }, { "icon": { @@ -1198,9 +1227,9 @@ "prevSize": 32, "code": 59723 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 0 + "iconIdx": 39 }, { "icon": { @@ -1230,9 +1259,9 @@ "prevSize": 32, "code": 59721 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 1 + "iconIdx": 40 }, { "icon": { @@ -1262,9 +1291,9 @@ "prevSize": 32, "code": 59711 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 2 + "iconIdx": 41 }, { "icon": { @@ -1292,9 +1321,9 @@ "code": 59648, "name": "angle-down" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 3 + "iconIdx": 42 }, { "icon": { @@ -1322,9 +1351,9 @@ "code": 59649, "name": "angle-left" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 4 + "iconIdx": 43 }, { "icon": { @@ -1352,9 +1381,9 @@ "code": 59697, "name": "angle-right" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 5 + "iconIdx": 44 }, { "icon": { @@ -1382,9 +1411,9 @@ "code": 59651, "name": "angle-up" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 6 + "iconIdx": 45 }, { "icon": { @@ -1423,9 +1452,9 @@ "prevSize": 32, "code": 59717 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 7 + "iconIdx": 46 }, { "icon": { @@ -1458,9 +1487,9 @@ "prevSize": 32, "code": 59720 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 8 + "iconIdx": 47 }, { "icon": { @@ -1488,9 +1517,9 @@ "code": 59709, "name": "bug" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 9 + "iconIdx": 48 }, { "icon": { @@ -1518,9 +1547,9 @@ "code": 59692, "name": "caret-down" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 10 + "iconIdx": 49 }, { "icon": { @@ -1548,9 +1577,9 @@ "code": 59690, "name": "caret-left" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 11 + "iconIdx": 50 }, { "icon": { @@ -1578,9 +1607,9 @@ "code": 59689, "name": "caret-right" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 12 + "iconIdx": 51 }, { "icon": { @@ -1608,9 +1637,9 @@ "code": 59691, "name": "caret-up" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 13 + "iconIdx": 52 }, { "icon": { @@ -1646,9 +1675,9 @@ "prevSize": 32, "code": 59718 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 14 + "iconIdx": 53 }, { "icon": { @@ -1675,9 +1704,9 @@ "prevSize": 32, "code": 59702 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 15 + "iconIdx": 54 }, { "icon": { @@ -1704,9 +1733,9 @@ "prevSize": 32, "code": 59703 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 16 + "iconIdx": 55 }, { "icon": { @@ -1733,9 +1762,9 @@ "prevSize": 32, "code": 59704 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 17 + "iconIdx": 56 }, { "icon": { @@ -1760,9 +1789,9 @@ "prevSize": 32, "code": 61450 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 18 + "iconIdx": 57 }, { "icon": { @@ -1789,9 +1818,9 @@ "prevSize": 32, "code": 61641 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 19 + "iconIdx": 58 }, { "icon": { @@ -1818,9 +1847,9 @@ "prevSize": 32, "code": 59698 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 20 + "iconIdx": 59 }, { "icon": { @@ -1868,9 +1897,9 @@ "prevSize": 32, "code": 59719 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 21 + "iconIdx": 60 }, { "icon": { @@ -1905,9 +1934,9 @@ "prevSize": 32, "code": 59650 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 60 + "iconIdx": 61 }, { "icon": { @@ -1938,9 +1967,9 @@ "prevSize": 32, "code": 59850 }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 61 + "iconIdx": 62 }, { "icon": { @@ -1971,9 +2000,9 @@ "code": 59715, "name": "elapsed" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 62 + "iconIdx": 63 }, { "icon": { @@ -2001,9 +2030,9 @@ "code": 59707, "name": "google" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 63 + "iconIdx": 64 }, { "icon": { @@ -2033,9 +2062,9 @@ "code": 59700, "name": "lock" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 64 + "iconIdx": 65 }, { "icon": { @@ -2064,9 +2093,9 @@ "code": 59712, "name": "microsoft" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 65 + "iconIdx": 66 }, { "icon": { @@ -2094,9 +2123,9 @@ "code": 59695, "name": "pause" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 66 + "iconIdx": 67 }, { "icon": { @@ -2124,9 +2153,9 @@ "code": 59696, "name": "play" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 67 + "iconIdx": 68 }, { "icon": { @@ -2163,9 +2192,9 @@ "code": 59694, "name": "reset" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 68 + "iconIdx": 69 }, { "icon": { @@ -2198,9 +2227,9 @@ "code": 59693, "name": "settings2" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 69 + "iconIdx": 70 }, { "icon": { @@ -2232,9 +2261,9 @@ "code": 59716, "name": "timeout" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 70 + "iconIdx": 71 }, { "icon": { @@ -2262,9 +2291,9 @@ "code": 59699, "name": "unlocked" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 71 + "iconIdx": 72 }, { "icon": { @@ -2295,9 +2324,9 @@ "code": 59701, "name": "browser" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 72 + "iconIdx": 73 }, { "icon": { @@ -2327,9 +2356,9 @@ "code": 59714, "name": "checkmark" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 73 + "iconIdx": 74 }, { "icon": { @@ -2357,9 +2386,9 @@ "code": 59706, "name": "control-Stars" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 74 + "iconIdx": 75 }, { "icon": { @@ -2386,9 +2415,9 @@ "code": 59705, "name": "control-RichText" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 75 + "iconIdx": 76 }, { "icon": { @@ -2415,9 +2444,9 @@ "code": 59710, "name": "download" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 76 + "iconIdx": 77 }, { "icon": { @@ -2444,9 +2473,9 @@ "code": 59708, "name": "info" }, - "setIdx": 2, + "setIdx": 1, "setId": 1, - "iconIdx": 77 + "iconIdx": 78 } ], "height": 1024, diff --git a/src/Squidex/app/theme/icomoon/style.css b/src/Squidex/app/theme/icomoon/style.css index 119b3b79a..281b8bfc5 100644 --- a/src/Squidex/app/theme/icomoon/style.css +++ b/src/Squidex/app/theme/icomoon/style.css @@ -1,10 +1,10 @@ @font-face { font-family: 'icomoon'; - src: url('fonts/icomoon.eot?pcikfl'); - src: url('fonts/icomoon.eot?pcikfl#iefix') format('embedded-opentype'), - url('fonts/icomoon.ttf?pcikfl') format('truetype'), - url('fonts/icomoon.woff?pcikfl') format('woff'), - url('fonts/icomoon.svg?pcikfl#icomoon') format('svg'); + src: url('fonts/icomoon.eot?t1gkof'); + src: url('fonts/icomoon.eot?t1gkof#iefix') format('embedded-opentype'), + url('fonts/icomoon.ttf?t1gkof') format('truetype'), + url('fonts/icomoon.woff?t1gkof') format('woff'), + url('fonts/icomoon.svg?t1gkof#icomoon') format('svg'); font-weight: normal; font-style: normal; } @@ -24,6 +24,9 @@ -moz-osx-font-smoothing: grayscale; } +.icon-action-Algolia:before { + content: "\e94c"; +} .icon-type-Tags:before { content: "\e94a"; color: #c1c6c8;