diff --git a/build/nightly-E2E-test-pipelines.yml b/build/nightly-E2E-test-pipelines.yml index 629b7ac841..405eb51aa4 100644 --- a/build/nightly-E2E-test-pipelines.yml +++ b/build/nightly-E2E-test-pipelines.yml @@ -9,7 +9,6 @@ schedules: branches: include: - v15/dev - - release/16.0 - main parameters: @@ -483,4 +482,4 @@ stages: testResultsFormat: 'JUnit' testResultsFiles: '*.xml' searchFolder: "tests/Umbraco.Tests.AcceptanceTest/results" - testRunTitle: "$(Agent.JobName)" + testRunTitle: "$(Agent.JobName)" \ No newline at end of file diff --git a/src/Umbraco.Core/PropertyEditors/PlainDateTimePropertyEditor.cs b/src/Umbraco.Core/PropertyEditors/PlainDateTimePropertyEditor.cs index 0bc559972e..737f5b4db2 100644 --- a/src/Umbraco.Core/PropertyEditors/PlainDateTimePropertyEditor.cs +++ b/src/Umbraco.Core/PropertyEditors/PlainDateTimePropertyEditor.cs @@ -13,7 +13,7 @@ namespace Umbraco.Cms.Core.PropertyEditors; public class PlainDateTimePropertyEditor : DataEditor { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public PlainDateTimePropertyEditor(IDataValueEditorFactory dataValueEditorFactory) : base(dataValueEditorFactory) diff --git a/src/Umbraco.Core/Services/ILogViewerRepository.cs b/src/Umbraco.Core/Services/ILogViewerRepository.cs index 770099668b..6d93928efc 100644 --- a/src/Umbraco.Core/Services/ILogViewerRepository.cs +++ b/src/Umbraco.Core/Services/ILogViewerRepository.cs @@ -1,8 +1,11 @@ -using Umbraco.Cms.Core.Logging; +using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Logging.Viewer; namespace Umbraco.Cms.Core.Services; +/// +/// Represents a repository for viewing logs in Umbraco. +/// public interface ILogViewerRepository { /// diff --git a/src/Umbraco.Core/Services/LogViewerService.cs b/src/Umbraco.Core/Services/LogViewerService.cs index 0780838416..5ca2a08785 100644 --- a/src/Umbraco.Core/Services/LogViewerService.cs +++ b/src/Umbraco.Core/Services/LogViewerService.cs @@ -1,212 +1,58 @@ -using System.Collections.ObjectModel; using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Logging.Viewer; -using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services.OperationStatus; -using Umbraco.Extensions; -using LogLevel = Umbraco.Cms.Core.Logging.LogLevel; namespace Umbraco.Cms.Core.Services; -public class LogViewerService : ILogViewerService +/// +/// Represents a service for viewing logs in Umbraco. +/// +public class LogViewerService : LogViewerServiceBase { private const int FileSizeCap = 100; - private readonly ILogViewerQueryRepository _logViewerQueryRepository; - private readonly ICoreScopeProvider _provider; private readonly ILoggingConfiguration _loggingConfiguration; - private readonly ILogViewerRepository _logViewerRepository; + /// + /// Initializes a new instance of the class. + /// public LogViewerService( ILogViewerQueryRepository logViewerQueryRepository, ICoreScopeProvider provider, ILoggingConfiguration loggingConfiguration, ILogViewerRepository logViewerRepository) + : base( + logViewerQueryRepository, + provider, + logViewerRepository) { - _logViewerQueryRepository = logViewerQueryRepository; - _provider = provider; _loggingConfiguration = loggingConfiguration; - _logViewerRepository = logViewerRepository; } /// - public Task?, LogViewerOperationStatus>> GetPagedLogsAsync( - DateTimeOffset? startDate, - DateTimeOffset? endDate, - int skip, - int take, - Direction orderDirection = Direction.Descending, - string? filterExpression = null, - string[]? logLevels = null) - { - LogTimePeriod logTimePeriod = GetTimePeriod(startDate, endDate); - - // We will need to stop the request if trying to do this on a 1GB file - if (CanViewLogs(logTimePeriod) == false) - { - return Task.FromResult(Attempt.FailWithStatus?, LogViewerOperationStatus>( - LogViewerOperationStatus.CancelledByLogsSizeValidation, - null)); - } - - - PagedModel filteredLogs = GetFilteredLogs(logTimePeriod, filterExpression, logLevels, orderDirection, skip, take); - - return Task.FromResult(Attempt.SucceedWithStatus?, LogViewerOperationStatus>( - LogViewerOperationStatus.Success, - filteredLogs)); - } + protected override string LoggerName => "UmbracoFile"; /// - public Task> GetSavedLogQueriesAsync(int skip, int take) + public override Task> CanViewLogsAsync(LogTimePeriod logTimePeriod) { - using ICoreScope scope = _provider.CreateCoreScope(autoComplete: true); - ILogViewerQuery[] savedLogQueries = _logViewerQueryRepository.GetMany().ToArray(); - var pagedModel = new PagedModel(savedLogQueries.Length, savedLogQueries.Skip(skip).Take(take)); - return Task.FromResult(pagedModel); - } - - /// - public Task GetSavedLogQueryByNameAsync(string name) - { - using ICoreScope scope = _provider.CreateCoreScope(autoComplete: true); - return Task.FromResult(_logViewerQueryRepository.GetByName(name)); - } - - /// - public async Task> AddSavedLogQueryAsync(string name, string query) - { - ILogViewerQuery? logViewerQuery = await GetSavedLogQueryByNameAsync(name); - - if (logViewerQuery is not null) - { - return Attempt.FailWithStatus(LogViewerOperationStatus.DuplicateLogSearch, null); - } - - logViewerQuery = new LogViewerQuery(name, query); - - using ICoreScope scope = _provider.CreateCoreScope(autoComplete: true); - _logViewerQueryRepository.Save(logViewerQuery); - - return Attempt.SucceedWithStatus(LogViewerOperationStatus.Success, logViewerQuery); - } - - /// - public async Task> DeleteSavedLogQueryAsync(string name) - { - ILogViewerQuery? logViewerQuery = await GetSavedLogQueryByNameAsync(name); - - if (logViewerQuery is null) - { - return Attempt.FailWithStatus(LogViewerOperationStatus.NotFoundLogSearch, null); - } - - using ICoreScope scope = _provider.CreateCoreScope(autoComplete: true); - _logViewerQueryRepository.Delete(logViewerQuery); - - return Attempt.SucceedWithStatus(LogViewerOperationStatus.Success, logViewerQuery); - } - - /// - public Task> CanViewLogsAsync(DateTimeOffset? startDate, DateTimeOffset? endDate) - { - LogTimePeriod logTimePeriod = GetTimePeriod(startDate, endDate); bool isAllowed = CanViewLogs(logTimePeriod); if (isAllowed == false) { - return Task.FromResult(Attempt.FailWithStatus(LogViewerOperationStatus.CancelledByLogsSizeValidation, isAllowed)); + return Task.FromResult(Attempt.FailWithStatus( + LogViewerOperationStatus.CancelledByLogsSizeValidation, + isAllowed)); } return Task.FromResult(Attempt.SucceedWithStatus(LogViewerOperationStatus.Success, isAllowed)); } - /// - public Task> GetLogLevelCountsAsync(DateTimeOffset? startDate, DateTimeOffset? endDate) - { - LogTimePeriod logTimePeriod = GetTimePeriod(startDate, endDate); - - // We will need to stop the request if trying to do this on a 1GB file - if (CanViewLogs(logTimePeriod) == false) - { - return Task.FromResult(Attempt.FailWithStatus( - LogViewerOperationStatus.CancelledByLogsSizeValidation, - null)); - } - - LogLevelCounts counter = _logViewerRepository.GetLogCount(logTimePeriod); - - return Task.FromResult(Attempt.SucceedWithStatus( - LogViewerOperationStatus.Success, - counter)); - } - - /// - public Task, LogViewerOperationStatus>> GetMessageTemplatesAsync(DateTimeOffset? startDate, DateTimeOffset? endDate, int skip, int take) - { - LogTimePeriod logTimePeriod = GetTimePeriod(startDate, endDate); - - // We will need to stop the request if trying to do this on a 1GB file - if (CanViewLogs(logTimePeriod) == false) - { - return Task.FromResult(Attempt.FailWithStatus, LogViewerOperationStatus>( - LogViewerOperationStatus.CancelledByLogsSizeValidation, - null!)); - } - - LogTemplate[] messageTemplates = _logViewerRepository.GetMessageTemplates(logTimePeriod); - - return Task.FromResult(Attempt.SucceedWithStatus( - LogViewerOperationStatus.Success, - new PagedModel(messageTemplates.Length, messageTemplates.Skip(skip).Take(take)))); - } - - /// - public ReadOnlyDictionary GetLogLevelsFromSinks() - { - var configuredLogLevels = new Dictionary - { - { "Global", GetGlobalMinLogLevel() }, - { "UmbracoFile", _logViewerRepository.RestrictedToMinimumLevel() }, - }; - - return configuredLogLevels.AsReadOnly(); - } - - /// - public LogLevel GetGlobalMinLogLevel() => _logViewerRepository.GetGlobalMinLogLevel(); - - /// - /// Returns a representation from a start and end date for filtering log files. - /// - /// The start date for the date range (can be null). - /// The end date for the date range (can be null). - /// The LogTimePeriod object used to filter logs. - private LogTimePeriod GetTimePeriod(DateTimeOffset? startDate, DateTimeOffset? endDate) - { - if (startDate is null || endDate is null) - { - DateTime now = DateTime.Now; - if (startDate is null) - { - startDate = now.AddDays(-1); - } - - if (endDate is null) - { - endDate = now; - } - } - - return new LogTimePeriod(startDate.Value.LocalDateTime, endDate.Value.LocalDateTime); - } - /// /// Returns a value indicating whether to stop a GET request that is attempting to fetch logs from a 1GB file. /// /// The time period to filter the logs. - /// The value whether or not you are able to view the logs. + /// Whether you are able to view the logs. private bool CanViewLogs(LogTimePeriod logTimePeriod) { // Number of entries @@ -230,52 +76,5 @@ public class LogViewerService : ILogViewerService return logSizeAsMegabytes <= FileSizeCap; } - private PagedModel GetFilteredLogs( - LogTimePeriod logTimePeriod, - string? filterExpression, - string[]? logLevels, - Direction orderDirection, - int skip, - int take) - { - IEnumerable logs = _logViewerRepository.GetLogs(logTimePeriod, filterExpression).ToArray(); - - // This is user used the checkbox UI to toggle which log levels they wish to see - // If an empty array or null - its implied all levels to be viewed - if (logLevels?.Length > 0) - { - var logsAfterLevelFilters = new List(); - var validLogType = true; - foreach (var level in logLevels) - { - // Check if level string is part of the LogEventLevel enum - if (Enum.IsDefined(typeof(LogLevel), level)) - { - validLogType = true; - logsAfterLevelFilters.AddRange(logs.Where(x => - string.Equals(x.Level.ToString(), level, StringComparison.InvariantCultureIgnoreCase))); - } - else - { - validLogType = false; - } - } - - if (validLogType) - { - logs = logsAfterLevelFilters; - } - } - - return new PagedModel - { - Total = logs.Count(), - Items = logs - .OrderBy(l => l.Timestamp, orderDirection) - .Skip(skip) - .Take(take), - }; - } - - private string GetSearchPattern(DateTime day) => $"*{day:yyyyMMdd}*.json"; + private static string GetSearchPattern(DateTime day) => $"*{day:yyyyMMdd}*.json"; } diff --git a/src/Umbraco.Core/Services/LogViewerServiceBase.cs b/src/Umbraco.Core/Services/LogViewerServiceBase.cs new file mode 100644 index 0000000000..0b69e964e1 --- /dev/null +++ b/src/Umbraco.Core/Services/LogViewerServiceBase.cs @@ -0,0 +1,269 @@ +using System.Collections.ObjectModel; +using Umbraco.Cms.Core.Logging.Viewer; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Persistence.Repositories; +using Umbraco.Cms.Core.Scoping; +using Umbraco.Cms.Core.Services.OperationStatus; +using Umbraco.Extensions; +using LogLevel = Umbraco.Cms.Core.Logging.LogLevel; + +namespace Umbraco.Cms.Core.Services; + +/// +/// Base class for log viewer services that provides common functionality for managing log entries and queries. +/// +public abstract class LogViewerServiceBase : ILogViewerService +{ + private readonly ILogViewerQueryRepository _logViewerQueryRepository; + private readonly ICoreScopeProvider _provider; + + /// + /// Initializes a new instance of the class. + /// + protected LogViewerServiceBase( + ILogViewerQueryRepository logViewerQueryRepository, + ICoreScopeProvider provider, + ILogViewerRepository logViewerRepository) + { + _logViewerQueryRepository = logViewerQueryRepository; + _provider = provider; + LogViewerRepository = logViewerRepository; + } + + /// + /// Gets the . + /// + protected ILogViewerRepository LogViewerRepository { get; } + + /// + /// Gets the name of the logger. + /// + protected abstract string LoggerName { get; } + + /// + public virtual ReadOnlyDictionary GetLogLevelsFromSinks() + { + var configuredLogLevels = new Dictionary + { + { "Global", GetGlobalMinLogLevel() }, + { LoggerName, LogViewerRepository.RestrictedToMinimumLevel() }, + }; + + return configuredLogLevels.AsReadOnly(); + } + + /// + public virtual LogLevel GetGlobalMinLogLevel() => LogViewerRepository.GetGlobalMinLogLevel(); + + /// + public virtual Task GetSavedLogQueryByNameAsync(string name) + { + using ICoreScope scope = _provider.CreateCoreScope(autoComplete: true); + return Task.FromResult(_logViewerQueryRepository.GetByName(name)); + } + + /// + public virtual async Task> AddSavedLogQueryAsync(string name, string query) + { + ILogViewerQuery? logViewerQuery = await GetSavedLogQueryByNameAsync(name); + + if (logViewerQuery is not null) + { + return Attempt.FailWithStatus( + LogViewerOperationStatus.DuplicateLogSearch, null); + } + + logViewerQuery = new LogViewerQuery(name, query); + + using ICoreScope scope = _provider.CreateCoreScope(autoComplete: true); + _logViewerQueryRepository.Save(logViewerQuery); + + return Attempt.SucceedWithStatus( + LogViewerOperationStatus.Success, + logViewerQuery); + } + + /// + public virtual async Task> DeleteSavedLogQueryAsync(string name) + { + ILogViewerQuery? logViewerQuery = await GetSavedLogQueryByNameAsync(name); + + if (logViewerQuery is null) + { + return Attempt.FailWithStatus( + LogViewerOperationStatus.NotFoundLogSearch, null); + } + + using ICoreScope scope = _provider.CreateCoreScope(autoComplete: true); + _logViewerQueryRepository.Delete(logViewerQuery); + + return Attempt.SucceedWithStatus( + LogViewerOperationStatus.Success, + logViewerQuery); + } + + /// + public virtual Task> GetSavedLogQueriesAsync(int skip, int take) + { + using ICoreScope scope = _provider.CreateCoreScope(autoComplete: true); + ILogViewerQuery[] savedLogQueries = _logViewerQueryRepository.GetMany().ToArray(); + var pagedModel = new PagedModel(savedLogQueries.Length, savedLogQueries.Skip(skip).Take(take)); + return Task.FromResult(pagedModel); + } + + /// + public virtual async Task> GetLogLevelCountsAsync( + DateTimeOffset? startDate, DateTimeOffset? endDate) + { + LogTimePeriod logTimePeriod = GetTimePeriod(startDate, endDate); + + Attempt canViewLogs = await CanViewLogsAsync(logTimePeriod); + + // We will need to stop the request if trying to do this on a 1GB file + if (canViewLogs.Success == false) + { + return Attempt.FailWithStatus( + LogViewerOperationStatus.CancelledByLogsSizeValidation, + null); + } + + LogLevelCounts counter = LogViewerRepository.GetLogCount(logTimePeriod); + + return Attempt.SucceedWithStatus( + LogViewerOperationStatus.Success, + counter); + } + + /// + public virtual async Task, LogViewerOperationStatus>> GetMessageTemplatesAsync( + DateTimeOffset? startDate, DateTimeOffset? endDate, int skip, int take) + { + LogTimePeriod logTimePeriod = GetTimePeriod(startDate, endDate); + + Attempt canViewLogs = await CanViewLogsAsync(logTimePeriod); + + // We will need to stop the request if trying to do this on a 1GB file + if (canViewLogs.Success == false) + { + return Attempt.FailWithStatus, LogViewerOperationStatus>( + LogViewerOperationStatus.CancelledByLogsSizeValidation, + null!); + } + + LogTemplate[] messageTemplates = LogViewerRepository.GetMessageTemplates(logTimePeriod); + + return Attempt.SucceedWithStatus( + LogViewerOperationStatus.Success, + new PagedModel(messageTemplates.Length, messageTemplates.Skip(skip).Take(take))); + } + + /// + public virtual async Task?, LogViewerOperationStatus>> GetPagedLogsAsync( + DateTimeOffset? startDate, + DateTimeOffset? endDate, + int skip, + int take, + Direction orderDirection = Direction.Descending, + string? filterExpression = null, + string[]? logLevels = null) + { + LogTimePeriod logTimePeriod = GetTimePeriod(startDate, endDate); + + Attempt canViewLogs = await CanViewLogsAsync(logTimePeriod); + + // We will need to stop the request if trying to do this on a 1GB file + if (canViewLogs.Success == false) + { + return Attempt.FailWithStatus?, LogViewerOperationStatus>( + LogViewerOperationStatus.CancelledByLogsSizeValidation, + null); + } + + PagedModel filteredLogs = + GetFilteredLogs(logTimePeriod, filterExpression, logLevels, orderDirection, skip, take); + + return Attempt.SucceedWithStatus?, LogViewerOperationStatus>( + LogViewerOperationStatus.Success, + filteredLogs); + } + + /// + public virtual Task> CanViewLogsAsync( + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => CanViewLogsAsync(GetTimePeriod(startDate, endDate)); + + /// + /// Checks if the logs for the specified time period can be viewed. + /// + public abstract Task> CanViewLogsAsync(LogTimePeriod logTimePeriod); + + + /// + /// Returns a representation from a start and end date for filtering log files. + /// + /// The start date for the date range (can be null). + /// The end date for the date range (can be null). + /// The LogTimePeriod object used to filter logs. + protected virtual LogTimePeriod GetTimePeriod(DateTimeOffset? startDate, DateTimeOffset? endDate) + { + if (startDate is null || endDate is null) + { + DateTime now = DateTime.Now; + startDate ??= now.AddDays(-1); + endDate ??= now; + } + + return new LogTimePeriod(startDate.Value.LocalDateTime, endDate.Value.LocalDateTime); + } + + /// + /// Gets a filtered page of logs from storage based on the provided parameters. + /// + protected PagedModel GetFilteredLogs( + LogTimePeriod logTimePeriod, + string? filterExpression, + string[]? logLevels, + Direction orderDirection, + int skip, + int take) + { + IEnumerable logs = LogViewerRepository.GetLogs(logTimePeriod, filterExpression).ToArray(); + + // This is user used the checkbox UI to toggle which log levels they wish to see + // If an empty array or null - its implied all levels to be viewed + if (logLevels?.Length > 0) + { + var logsAfterLevelFilters = new List(); + var validLogType = true; + foreach (var level in logLevels) + { + // Check if level string is part of the LogEventLevel enum + if (Enum.IsDefined(typeof(LogLevel), level)) + { + validLogType = true; + logsAfterLevelFilters.AddRange(logs.Where(x => + string.Equals(x.Level.ToString(), level, StringComparison.InvariantCultureIgnoreCase))); + } + else + { + validLogType = false; + } + } + + if (validLogType) + { + logs = logsAfterLevelFilters; + } + } + + return new PagedModel + { + Total = logs.Count(), + Items = logs + .OrderBy(l => l.Timestamp, orderDirection) + .Skip(skip) + .Take(take), + }; + } +} diff --git a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs index f899f311f5..19b6bc05d5 100644 --- a/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs +++ b/src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.Uniques.cs @@ -195,6 +195,7 @@ public static partial class UmbracoBuilderExtensions /// /// The type of the log viewer. /// The builder. + [Obsolete("No longer used. Scheduled removal in Umbraco 18.")] public static IUmbracoBuilder SetLogViewer(this IUmbracoBuilder builder) where T : class, ILogViewer { @@ -207,6 +208,7 @@ public static partial class UmbracoBuilderExtensions /// /// The builder. /// A function creating a log viewer. + [Obsolete("No longer used. Scheduled removal in Umbraco 18.")] public static IUmbracoBuilder SetLogViewer(this IUmbracoBuilder builder, Func factory) { builder.Services.AddUnique(factory); @@ -218,6 +220,7 @@ public static partial class UmbracoBuilderExtensions /// /// A builder. /// A log viewer. + [Obsolete("No longer used. Scheduled removal in Umbraco 18.")] public static IUmbracoBuilder SetLogViewer(this IUmbracoBuilder builder, ILogViewer viewer) { builder.Services.AddUnique(viewer); diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs index 9d3213bd2a..4006c7ca16 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/LoggerConfigExtensions.cs @@ -22,7 +22,7 @@ namespace Umbraco.Extensions /// Such as adding ProcessID, Thread, AppDomain etc /// It is highly recommended that you keep/use this default in your own logging config customizations /// - [Obsolete("Please use an alternative method. This will be removed in Umbraco 13.")] + [Obsolete("Please use an alternative method. Scheduled for removal from Umbraco 13.")] public static LoggerConfiguration MinimalConfiguration( this LoggerConfiguration logConfig, Umbraco.Cms.Core.Hosting.IHostingEnvironment hostingEnvironment, @@ -37,7 +37,7 @@ namespace Umbraco.Extensions /// Such as adding ProcessID, Thread, AppDomain etc /// It is highly recommended that you keep/use this default in your own logging config customizations /// - [Obsolete("Please use an alternative method. This will be removed in Umbraco 13.")] + [Obsolete("Please use an alternative method. Scheduled for removal from Umbraco 13.")] public static LoggerConfiguration MinimalConfiguration( this LoggerConfiguration logConfig, Umbraco.Cms.Core.Hosting.IHostingEnvironment hostingEnvironment, @@ -68,7 +68,7 @@ namespace Umbraco.Extensions umbFileConfiguration = umbracoFileConfiguration; logConfig.WriteTo.UmbracoFile( - path : umbracoFileConfiguration.GetPath(loggingConfiguration.LogDirectory), + path: umbracoFileConfiguration.GetPath(loggingConfiguration.LogDirectory), fileSizeLimitBytes: umbracoFileConfiguration.FileSizeLimitBytes, restrictedToMinimumLevel: umbracoFileConfiguration.RestrictedToMinimumLevel, rollingInterval: umbracoFileConfiguration.RollingInterval, @@ -79,7 +79,6 @@ namespace Umbraco.Extensions return logConfig; } - /// /// This configures Serilog with some defaults /// Such as adding ProcessID, Thread, AppDomain etc @@ -108,14 +107,17 @@ namespace Umbraco.Extensions .Enrich.With() .Enrich.FromLogContext(); // allows us to dynamically enrich - logConfig.WriteTo.UmbracoFile( - path: umbracoFileConfiguration.GetPath(loggingConfiguration.LogDirectory, loggingConfiguration.LogFileNameFormat, loggingConfiguration.GetLogFileNameFormatArguments()), - fileSizeLimitBytes: umbracoFileConfiguration.FileSizeLimitBytes, - restrictedToMinimumLevel: umbracoFileConfiguration.RestrictedToMinimumLevel, - rollingInterval: umbracoFileConfiguration.RollingInterval, - flushToDiskInterval: umbracoFileConfiguration.FlushToDiskInterval, - rollOnFileSizeLimit: umbracoFileConfiguration.RollOnFileSizeLimit, - retainedFileCountLimit: umbracoFileConfiguration.RetainedFileCountLimit); + if (umbracoFileConfiguration.Enabled) + { + logConfig.WriteTo.UmbracoFile( + path: umbracoFileConfiguration.GetPath(loggingConfiguration.LogDirectory, loggingConfiguration.LogFileNameFormat, loggingConfiguration.GetLogFileNameFormatArguments()), + fileSizeLimitBytes: umbracoFileConfiguration.FileSizeLimitBytes, + restrictedToMinimumLevel: umbracoFileConfiguration.RestrictedToMinimumLevel, + rollingInterval: umbracoFileConfiguration.RollingInterval, + flushToDiskInterval: umbracoFileConfiguration.FlushToDiskInterval, + rollOnFileSizeLimit: umbracoFileConfiguration.RollOnFileSizeLimit, + retainedFileCountLimit: umbracoFileConfiguration.RetainedFileCountLimit); + } return logConfig; } @@ -127,7 +129,7 @@ namespace Umbraco.Extensions /// /// The log level you wish the JSON file to collect - default is Verbose (highest) /// - [Obsolete("Will be removed in Umbraco 13.")] + [Obsolete("Scheduled for removal from Umbraco 13.")] public static LoggerConfiguration OutputDefaultTextFile( this LoggerConfiguration logConfig, Umbraco.Cms.Core.Hosting.IHostingEnvironment hostingEnvironment, @@ -136,7 +138,7 @@ namespace Umbraco.Extensions //Main .txt logfile - in similar format to older Log4Net output //Ends with ..txt as Date is inserted before file extension substring logConfig.WriteTo.File( - Path.Combine(hostingEnvironment.MapPathContentRoot(Cms.Core.Constants.SystemDirectories.LogFiles), $"UmbracoTraceLog.{Environment.MachineName}..txt"), + Path.Combine(hostingEnvironment.MapPathContentRoot(Cms.Core.Constants.SystemDirectories.LogFiles), $"UmbracoTraceLog.{Environment.MachineName}..txt"), shared: true, rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: minimumLevel, @@ -213,7 +215,6 @@ namespace Umbraco.Extensions null)); } - /// /// Outputs a CLEF format JSON log at /App_Data/Logs/ /// @@ -222,7 +223,7 @@ namespace Umbraco.Extensions /// The log level you wish the JSON file to collect - default is Verbose (highest) /// /// The number of days to keep log files. Default is set to null which means all logs are kept - [Obsolete("Will be removed in Umbraco 13.")] + [Obsolete("Scheduled for removal from Umbraco 13.")] public static LoggerConfiguration OutputDefaultJsonFile( this LoggerConfiguration logConfig, Umbraco.Cms.Core.Hosting.IHostingEnvironment hostingEnvironment, @@ -234,7 +235,7 @@ namespace Umbraco.Extensions // Ends with ..txt as Date is inserted before file extension substring logConfig.WriteTo.File( new CompactJsonFormatter(), - Path.Combine(hostingEnvironment.MapPathContentRoot(Cms.Core.Constants.SystemDirectories.LogFiles) ,$"UmbracoTraceLog.{Environment.MachineName}..json"), + Path.Combine(hostingEnvironment.MapPathContentRoot(Cms.Core.Constants.SystemDirectories.LogFiles), $"UmbracoTraceLog.{Environment.MachineName}..json"), shared: true, rollingInterval: RollingInterval.Day, // Create a new JSON file every day retainedFileCountLimit: retainedFileCount, // Setting to null means we keep all files - default is 31 days @@ -270,6 +271,5 @@ namespace Umbraco.Extensions return logConfig; } - } } diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs index 6f1877f321..8d1f8fecf4 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/SerilogLogger.cs @@ -19,7 +19,7 @@ public class SerilogLogger : IDisposable public ILogger SerilogLog { get; } - [Obsolete] + [Obsolete("Scheduled for removal in Umbraco 17.")] public static SerilogLogger CreateWithDefaultConfiguration( IHostingEnvironment hostingEnvironment, ILoggingConfiguration loggingConfiguration, @@ -32,7 +32,7 @@ public class SerilogLogger : IDisposable /// Creates a logger with some pre-defined configuration and remainder from config file /// /// Used by UmbracoApplicationBase to get its logger. - [Obsolete] + [Obsolete("Scheduled for removal in Umbraco 17.")] public static SerilogLogger CreateWithDefaultConfiguration( IHostingEnvironment hostingEnvironment, ILoggingConfiguration loggingConfiguration, diff --git a/src/Umbraco.Infrastructure/Logging/Serilog/UmbracoFileConfiguration.cs b/src/Umbraco.Infrastructure/Logging/Serilog/UmbracoFileConfiguration.cs index 5d650dac07..33a6b549af 100644 --- a/src/Umbraco.Infrastructure/Logging/Serilog/UmbracoFileConfiguration.cs +++ b/src/Umbraco.Infrastructure/Logging/Serilog/UmbracoFileConfiguration.cs @@ -22,6 +22,7 @@ public class UmbracoFileConfiguration { IConfigurationSection? args = umbracoFileAppSettings.GetSection("Args"); + Enabled = args.GetValue(nameof(Enabled), Enabled); RestrictedToMinimumLevel = args.GetValue(nameof(RestrictedToMinimumLevel), RestrictedToMinimumLevel); FileSizeLimitBytes = args.GetValue(nameof(FileSizeLimitBytes), FileSizeLimitBytes); RollingInterval = args.GetValue(nameof(RollingInterval), RollingInterval); @@ -31,6 +32,8 @@ public class UmbracoFileConfiguration } } + public bool Enabled { get; set; } = true; + public LogEventLevel RestrictedToMinimumLevel { get; set; } = LogEventLevel.Verbose; public long FileSizeLimitBytes { get; set; } = 1073741824; diff --git a/src/Umbraco.Infrastructure/Logging/Viewer/ILogViewer.cs b/src/Umbraco.Infrastructure/Logging/Viewer/ILogViewer.cs index 00d0f0517d..82d2277dc8 100644 --- a/src/Umbraco.Infrastructure/Logging/Viewer/ILogViewer.cs +++ b/src/Umbraco.Infrastructure/Logging/Viewer/ILogViewer.cs @@ -2,6 +2,7 @@ using Umbraco.Cms.Core.Models; namespace Umbraco.Cms.Core.Logging.Viewer; +[Obsolete("Use ILogViewerService instead. Scheduled removal in Umbraco 18.")] public interface ILogViewer { bool CanHandleLargeLogs { get; } diff --git a/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs b/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs deleted file mode 100644 index 9c8dace1cf..0000000000 --- a/src/Umbraco.Infrastructure/Logging/Viewer/SerilogJsonLogViewer.cs +++ /dev/null @@ -1,133 +0,0 @@ -using Microsoft.Extensions.Logging; -using Serilog.Events; -using Serilog.Formatting.Compact.Reader; -using ILogger = Serilog.ILogger; - -namespace Umbraco.Cms.Core.Logging.Viewer; - -internal sealed class SerilogJsonLogViewer : SerilogLogViewerSourceBase -{ - private const int FileSizeCap = 100; - private readonly ILogger _logger; - private readonly string _logsPath; - - public SerilogJsonLogViewer( - ILogger logger, - ILogViewerConfig logViewerConfig, - ILoggingConfiguration loggingConfiguration, - ILogLevelLoader logLevelLoader, - ILogger serilogLog) - : base(logViewerConfig, logLevelLoader, serilogLog) - { - _logger = logger; - _logsPath = loggingConfiguration.LogDirectory; - } - - public override bool CanHandleLargeLogs => false; - - [Obsolete("Use ILogViewerService.CanViewLogsAsync instead. Scheduled for removal in Umbraco 15.")] - public override bool CheckCanOpenLogs(LogTimePeriod logTimePeriod) - { - // Log Directory - var logDirectory = _logsPath; - - // Number of entries - long fileSizeCount = 0; - - // foreach full day in the range - see if we can find one or more filenames that end with - // yyyyMMdd.json - Ends with due to MachineName in filenames - could be 1 or more due to load balancing - for (DateTime day = logTimePeriod.StartTime.Date; day.Date <= logTimePeriod.EndTime.Date; day = day.AddDays(1)) - { - // Filename ending to search for (As could be multiple) - var filesToFind = GetSearchPattern(day); - - var filesForCurrentDay = Directory.GetFiles(logDirectory, filesToFind); - - fileSizeCount += filesForCurrentDay.Sum(x => new FileInfo(x).Length); - } - - // The GetLogSize call on JsonLogViewer returns the total file size in bytes - // Check if the log size is not greater than 100Mb (FileSizeCap) - var logSizeAsMegabytes = fileSizeCount / 1024 / 1024; - return logSizeAsMegabytes <= FileSizeCap; - } - - protected override IReadOnlyList GetLogs(LogTimePeriod logTimePeriod, ILogFilter filter, int skip, - int take) - { - var logs = new List(); - - var count = 0; - - // foreach full day in the range - see if we can find one or more filenames that end with - // yyyyMMdd.json - Ends with due to MachineName in filenames - could be 1 or more due to load balancing - for (DateTime day = logTimePeriod.StartTime.Date; day.Date <= logTimePeriod.EndTime.Date; day = day.AddDays(1)) - { - // Filename ending to search for (As could be multiple) - var filesToFind = GetSearchPattern(day); - - var filesForCurrentDay = Directory.GetFiles(_logsPath, filesToFind); - - // Foreach file we find - open it - foreach (var filePath in filesForCurrentDay) - { - // Open log file & add contents to the log collection - // Which we then use LINQ to page over - using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - { - using (var stream = new StreamReader(fs)) - { - var reader = new LogEventReader(stream); - while (TryRead(reader, out LogEvent? evt)) - { - // We may get a null if log line is malformed - if (evt == null) - { - continue; - } - - if (count > skip + take) - { - break; - } - - if (count < skip) - { - count++; - continue; - } - - if (filter.TakeLogEvent(evt)) - { - logs.Add(evt); - } - - count++; - } - } - } - } - } - - return logs; - } - - private static string GetSearchPattern(DateTime day) => $"*{day:yyyyMMdd}*.json"; - - private bool TryRead(LogEventReader reader, out LogEvent? evt) - { - try - { - return reader.TryRead(out evt); - } - catch (Exception ex) - { - // As we are reading/streaming one line at a time in the JSON file - // Thus we can not report the line number, as it will always be 1 - _logger.LogError(ex, "Unable to parse a line in the JSON log file"); - - evt = null; - return true; - } - } -} diff --git a/src/Umbraco.Infrastructure/Logging/Viewer/SerilogLogViewerSourceBase.cs b/src/Umbraco.Infrastructure/Logging/Viewer/SerilogLogViewerSourceBase.cs index d2f21cf5d0..cd485e7660 100644 --- a/src/Umbraco.Infrastructure/Logging/Viewer/SerilogLogViewerSourceBase.cs +++ b/src/Umbraco.Infrastructure/Logging/Viewer/SerilogLogViewerSourceBase.cs @@ -6,6 +6,7 @@ using Umbraco.Extensions; namespace Umbraco.Cms.Core.Logging.Viewer; +[Obsolete("Use ILogViewerService instead. Scheduled removal in Umbraco 18.")] public abstract class SerilogLogViewerSourceBase : ILogViewer { private readonly ILogLevelLoader _logLevelLoader; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs index f9be27e551..89415fb258 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/RichTextPropertyEditor.cs @@ -263,8 +263,6 @@ public class RichTextPropertyEditor : DataEditor richTextEditorValue?.EnsurePropertyTypePopulatedOnBlocks(_elementTypeCache); currentRichTextEditorValue?.EnsurePropertyTypePopulatedOnBlocks(_elementTypeCache); - RichTextEditorValue cleanedUpRichTextEditorValue = CleanAndMapBlocks(richTextEditorValue, blockValue => MapBlockValueFromEditor(blockValue, currentRichTextEditorValue?.Blocks, editorValue.ContentKey)); - if (string.IsNullOrWhiteSpace(richTextEditorValue?.Markup)) { return null; @@ -284,6 +282,7 @@ public class RichTextPropertyEditor : DataEditor var sanitized = _htmlSanitizer.Sanitize(editorValueWithMediaUrlsRemoved); richTextEditorValue.Markup = sanitized.NullOrWhiteSpaceAsNull() ?? string.Empty; + RichTextEditorValue cleanedUpRichTextEditorValue = CleanAndMapBlocks(richTextEditorValue, blockValue => MapBlockValueFromEditor(blockValue, currentRichTextEditorValue?.Blocks, editorValue.ContentKey)); // return json return RichTextPropertyEditorHelper.SerializeRichTextEditorValue(cleanedUpRichTextEditorValue, _jsonSerializer); diff --git a/src/Umbraco.Infrastructure/Serialization/JsonObjectConverter.cs b/src/Umbraco.Infrastructure/Serialization/JsonObjectConverter.cs index d8c9778461..0fc0aefd7d 100644 --- a/src/Umbraco.Infrastructure/Serialization/JsonObjectConverter.cs +++ b/src/Umbraco.Infrastructure/Serialization/JsonObjectConverter.cs @@ -101,8 +101,15 @@ public sealed class JsonObjectConverter : JsonConverter JsonTokenType.Number when reader.TryGetInt32(out int i) => i, JsonTokenType.Number when reader.TryGetInt64(out long l) => l, JsonTokenType.Number => reader.GetDouble(), - JsonTokenType.String when reader.TryGetDateTimeOffset(out DateTimeOffset datetime) => datetime, - JsonTokenType.String when reader.TryGetDateTime(out DateTime datetime) => datetime, + + // DateTime and DateTimeOffset are not handled here, as in doing so we would convert strings that look like dates into dates, + // which, if coming fron a content property based on a text string property editor, isn't what we want. + // The date picker property editors work with strings, so this is fine. + // Testing also suggests other dates like for content content schedules aren't affected. + // See: + // - https://github.com/umbraco/Umbraco-CMS/issues/19360 + // - https://github.com/umbraco/Umbraco-CMS/pull/19807 + JsonTokenType.String => reader.GetString(), _ => JsonDocument.ParseValue(ref reader).RootElement.Clone() }; diff --git a/src/Umbraco.Infrastructure/Services/Implement/LogViewerRepository.cs b/src/Umbraco.Infrastructure/Services/Implement/LogViewerRepository.cs index e1aac6486a..70f4588922 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/LogViewerRepository.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/LogViewerRepository.cs @@ -1,83 +1,40 @@ -using Microsoft.Extensions.Logging; -using Serilog; +using Microsoft.Extensions.Logging; using Serilog.Events; using Serilog.Formatting.Compact.Reader; using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Logging.Viewer; using Umbraco.Cms.Core.Serialization; -using Umbraco.Cms.Core.Services; using Umbraco.Cms.Infrastructure.Logging.Serilog; using LogLevel = Umbraco.Cms.Core.Logging.LogLevel; namespace Umbraco.Cms.Infrastructure.Services.Implement; -public class LogViewerRepository : ILogViewerRepository +/// +/// Repository for accessing log entries from the Umbraco log files stored on disk. +/// +public class LogViewerRepository : LogViewerRepositoryBase { private readonly ILoggingConfiguration _loggingConfiguration; private readonly ILogger _logger; private readonly IJsonSerializer _jsonSerializer; - private readonly UmbracoFileConfiguration _umbracoFileConfig; - public LogViewerRepository(ILoggingConfiguration loggingConfiguration, ILogger logger, IJsonSerializer jsonSerializer, UmbracoFileConfiguration umbracoFileConfig) + /// + /// Initializes a new instance of the class. + /// + public LogViewerRepository( + ILoggingConfiguration loggingConfiguration, + ILogger logger, + IJsonSerializer jsonSerializer, + UmbracoFileConfiguration umbracoFileConfig) + : base(umbracoFileConfig) { _loggingConfiguration = loggingConfiguration; _logger = logger; _jsonSerializer = jsonSerializer; - _umbracoFileConfig = umbracoFileConfig; } - /// - public IEnumerable GetLogs(LogTimePeriod logTimePeriod, string? filterExpression = null) - { - var expressionFilter = new ExpressionFilter(filterExpression); - - return GetLogs(logTimePeriod, expressionFilter); - } - - /// - public LogLevelCounts GetLogCount(LogTimePeriod logTimePeriod) - { - var counter = new CountingFilter(); - - GetLogs(logTimePeriod, counter); - - return counter.Counts; - } - - /// - public LogTemplate[] GetMessageTemplates(LogTimePeriod logTimePeriod) - { - var messageTemplates = new MessageTemplateFilter(); - - GetLogs(logTimePeriod, messageTemplates); - - return messageTemplates.Counts - .Select(x => new LogTemplate { MessageTemplate = x.Key, Count = x.Value }) - .OrderByDescending(x => x.Count).ToArray(); - } - - /// - public LogLevel GetGlobalMinLogLevel() - { - LogEventLevel logLevel = GetGlobalLogLevelEventMinLevel(); - - return Enum.Parse(logLevel.ToString()); - } - - public LogLevel RestrictedToMinimumLevel() - { - LogEventLevel minLevel = _umbracoFileConfig.RestrictedToMinimumLevel; - return Enum.Parse(minLevel.ToString()); - } - - private LogEventLevel GetGlobalLogLevelEventMinLevel() => - Enum.GetValues(typeof(LogEventLevel)) - .Cast() - .Where(Log.IsEnabled) - .DefaultIfEmpty(LogEventLevel.Information) - .Min(); - - private IEnumerable GetLogs(LogTimePeriod logTimePeriod, ILogFilter logFilter) + /// + protected override IEnumerable GetLogs(LogTimePeriod logTimePeriod, ILogFilter logFilter) { var logs = new List(); @@ -163,7 +120,7 @@ public class LogViewerRepository : ILogViewerRepository return result.AsReadOnly(); } - private string GetSearchPattern(DateTime day) => $"*{day:yyyyMMdd}*.json"; + private static string GetSearchPattern(DateTime day) => $"*{day:yyyyMMdd}*.json"; private bool TryRead(LogEventReader reader, out LogEvent? evt) { diff --git a/src/Umbraco.Infrastructure/Services/Implement/LogViewerRepositoryBase.cs b/src/Umbraco.Infrastructure/Services/Implement/LogViewerRepositoryBase.cs new file mode 100644 index 0000000000..95d650ac6a --- /dev/null +++ b/src/Umbraco.Infrastructure/Services/Implement/LogViewerRepositoryBase.cs @@ -0,0 +1,84 @@ +using Serilog; +using Serilog.Events; +using Umbraco.Cms.Core.Logging.Viewer; +using Umbraco.Cms.Core.Services; +using Umbraco.Cms.Infrastructure.Logging.Serilog; +using LogLevel = Umbraco.Cms.Core.Logging.LogLevel; + +namespace Umbraco.Cms.Infrastructure.Services.Implement; + +/// +/// Provides a base class for log viewer repository implementations. +/// +public abstract class LogViewerRepositoryBase : ILogViewerRepository +{ + private readonly UmbracoFileConfiguration _umbracoFileConfig; + + /// + /// Initializes a new instance of the class. + /// + /// + public LogViewerRepositoryBase(UmbracoFileConfiguration umbracoFileConfig) => _umbracoFileConfig = umbracoFileConfig; + + /// + public virtual IEnumerable GetLogs(LogTimePeriod logTimePeriod, string? filterExpression = null) + { + var expressionFilter = new ExpressionFilter(filterExpression); + + return GetLogs(logTimePeriod, expressionFilter); + } + + /// + public virtual LogLevelCounts GetLogCount(LogTimePeriod logTimePeriod) + { + var counter = new CountingFilter(); + + GetLogs(logTimePeriod, counter); + + return counter.Counts; + } + + /// + public virtual LogTemplate[] GetMessageTemplates(LogTimePeriod logTimePeriod) + { + var messageTemplates = new MessageTemplateFilter(); + + GetLogs(logTimePeriod, messageTemplates); + + return messageTemplates.Counts + .Select(x => new LogTemplate { MessageTemplate = x.Key, Count = x.Value }) + .OrderByDescending(x => x.Count).ToArray(); + } + + /// + public virtual LogLevel GetGlobalMinLogLevel() + { + LogEventLevel logLevel = GetGlobalLogLevelEventMinLevel(); + + return Enum.Parse(logLevel.ToString()); + } + + /// + /// Gets the minimum-level log value from the config file. + /// + public virtual LogLevel RestrictedToMinimumLevel() + { + LogEventLevel minLevel = _umbracoFileConfig.RestrictedToMinimumLevel; + return Enum.Parse(minLevel.ToString()); + } + + /// + /// Gets the minimum log level from the global Serilog configuration. + /// + protected virtual LogEventLevel GetGlobalLogLevelEventMinLevel() => + Enum.GetValues(typeof(LogEventLevel)) + .Cast() + .Where(Log.IsEnabled) + .DefaultIfEmpty(LogEventLevel.Information) + .Min(); + + /// + /// Retrieves the logs for a specified time period and filter. + /// + protected abstract IEnumerable GetLogs(LogTimePeriod logTimePeriod, ILogFilter logFilter); +} diff --git a/src/Umbraco.Web.UI.Client/.storybook/preview.js b/src/Umbraco.Web.UI.Client/.storybook/preview.js index 4dbb21c98a..cc2ef5ce52 100644 --- a/src/Umbraco.Web.UI.Client/.storybook/preview.js +++ b/src/Umbraco.Web.UI.Client/.storybook/preview.js @@ -10,11 +10,8 @@ import { setCustomElements } from '@storybook/web-components-vite'; import { startMockServiceWorker } from '../src/mocks'; import '../src/libs/controller-api/controller-host-provider.element'; +import { UmbExtensionsApiInitializer } from '../src/libs/extension-api/index'; import { UmbModalManagerContext } from '../src/packages/core/modal'; -import { UmbDataTypeTreeStore } from '../src/packages/data-type/tree/data-type-tree.store'; -import { UmbDocumentDetailStore } from '../src/packages/documents/documents/repository/detail/document-detail.store'; -import { UmbDocumentTreeStore } from '../src/packages/documents/documents/tree/document-tree.store'; -import { UmbCurrentUserStore } from '../src/packages/user/current-user/repository/current-user.store'; import { umbExtensionsRegistry } from '../src/packages/core/extension-registry'; import { UmbIconRegistry } from '../src/packages/core/icon-registry/icon.registry'; import { UmbLitElement } from '../src/packages/core/lit-element'; @@ -25,27 +22,128 @@ import icons from '../src/packages/core/icon-registry/icons'; import '../src/libs/context-api/provide/context-provider.element'; import '../src/packages/core/components'; +import { manifests as blockManifests } from '../src/packages/block/manifests'; +import { manifests as clipboardManifests } from '../src/packages/clipboard/manifests'; +import { manifests as codeEditorManifests } from '../src/packages/code-editor/manifests'; +import { manifests as contentManifests } from '../src/packages/content/manifests'; +import { manifests as coreManifests } from '../src/packages/core/manifests'; +import { manifests as dataTypeManifests } from '../src/packages/data-type/manifests'; +import { manifests as dictionaryManifests } from '../src/packages/dictionary/manifests'; import { manifests as documentManifests } from '../src/packages/documents/manifests'; -import { manifests as localizationManifests } from '../src/packages/core/localization/manifests'; +import { manifests as embeddedMediaManifests } from '../src/packages/embedded-media/manifests'; +import { manifests as extensionInsightsManifests } from '../src/packages/extension-insights/manifests'; +import { manifests as healthCheckManifests } from '../src/packages/health-check/manifests'; +import { manifests as helpManifests } from '../src/packages/help/manifests'; +import { manifests as languageManifests } from '../src/packages/language/manifests'; +import { manifests as logViewerManifests } from '../src/packages/log-viewer/manifests'; +import { manifests as markdownEditorManifests } from '../src/packages/markdown-editor/manifests'; +import { manifests as mediaManifests } from '../src/packages/media/manifests'; +import { manifests as memberManifests } from '../src/packages/members/manifests'; +import { manifests as modelsBuilderManifests } from '../src/packages/models-builder/manifests'; +import { manifests as multiUrlPickerManifests } from '../src/packages/multi-url-picker/manifests'; +import { manifests as packageManifests } from '../src/packages/packages/manifests'; +import { manifests as performanceProfilingManifests } from '../src/packages/performance-profiling/manifests'; +import { manifests as propertyEditorManifests } from '../src/packages/property-editors/manifests'; +import { manifests as publishCacheManifests } from '../src/packages/publish-cache/manifests'; +import { manifests as relationsManifests } from '../src/packages/relations/manifests'; +import { manifests as rteManifests } from '../src/packages/rte/manifests'; +import { manifests as searchManifests } from '../src/packages/search/manifests'; +import { manifests as segmentManifests } from '../src/packages/segment/manifests'; +import { manifests as settingsManifests } from '../src/packages/settings/manifests'; +import { manifests as staticFileManifests } from '../src/packages/static-file/manifests'; +import { manifests as sysInfoManifests } from '../src/packages/sysinfo/manifests'; +import { manifests as tagManifests } from '../src/packages/tags/manifests'; +import { manifests as telemetryManifests } from '../src/packages/telemetry/manifests'; +import { manifests as templatingManifests } from '../src/packages/templating/manifests'; +import { manifests as tipTapManifests } from '../src/packages/tiptap/manifests'; +import { manifests as translationManifests } from '../src/packages/translation/manifests'; +import { manifests as ufmManifests } from '../src/packages/ufm/manifests'; +//import { manifests as umbracoNewsManifests } from '../src/packages/umbraco-news/manifests'; +import { manifests as userManifests } from '../src/packages/user/manifests'; +import { manifests as webhookManifests } from '../src/packages/webhook/manifests'; + import { UmbNotificationContext } from '../src/packages/core/notification'; +import { UmbContextBase } from '../src/libs/class-api/index'; +import { UmbBooleanState } from '../src/libs/observable-api/index'; +import { UMB_APP_LANGUAGE_CONTEXT } from '../src/packages/language/constants'; // MSW startMockServiceWorker({ serviceWorker: { url: (import.meta.env.VITE_BASE_PATH ?? '/') + 'mockServiceWorker.js' } }); +class UmbStoryBookAuthContext extends UmbContextBase { + #isAuthorized = new UmbBooleanState(true); + isAuthorized = this.#isAuthorized.asObservable(); + + constructor(host) { + super(host, 'UmbAuthContext'); + } +} + class UmbStoryBookElement extends UmbLitElement { _umbIconRegistry = new UmbIconRegistry(); + #manifests = [ + ...blockManifests, + ...clipboardManifests, + ...codeEditorManifests, + ...contentManifests, + ...coreManifests, + ...dataTypeManifests, + ...dictionaryManifests, + ...documentManifests, + ...embeddedMediaManifests, + ...extensionInsightsManifests, + ...healthCheckManifests, + ...helpManifests, + ...languageManifests, + ...logViewerManifests, + ...markdownEditorManifests, + ...mediaManifests, + ...memberManifests, + ...modelsBuilderManifests, + ...multiUrlPickerManifests, + ...packageManifests, + ...performanceProfilingManifests, + ...propertyEditorManifests, + ...publishCacheManifests, + ...relationsManifests, + ...rteManifests, + ...searchManifests, + ...segmentManifests, + ...settingsManifests, + ...staticFileManifests, + ...sysInfoManifests, + ...tagManifests, + ...telemetryManifests, + ...templatingManifests, + ...tipTapManifests, + ...translationManifests, + ...ufmManifests, + //...umbracoNewsManifests, + ...userManifests, + ...webhookManifests, + ]; + constructor() { super(); + new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'globalContext', [this]); + new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'store', [this]); + new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'treeStore', [this]); + new UmbExtensionsApiInitializer(this, umbExtensionsRegistry, 'itemStore', [this]); + this._umbIconRegistry.setIcons(icons); this._umbIconRegistry.attach(this); - this._registerExtensions(documentManifests); + this._registerExtensions(this.#manifests); + + new UmbStoryBookAuthContext(this); new UmbModalManagerContext(this); - new UmbCurrentUserStore(this); new UmbNotificationContext(this); - this._registerExtensions(localizationManifests); umbLocalizationRegistry.loadLanguage('en-us'); // register default language + + this.consumeContext(UMB_APP_LANGUAGE_CONTEXT, (appLanguageContext) => { + appLanguageContext.setLanguage('en-us'); // set default language + }); } _registerExtensions(manifests) { @@ -66,26 +164,8 @@ customElements.define('umb-storybook', UmbStoryBookElement); const storybookProvider = (story) => html` ${story()} `; -const dataTypeStoreProvider = (story) => html` - new UmbDataTypeTreeStore(host)} - >${story()} -`; - -const documentStoreProvider = (story) => html` - new UmbDocumentDetailStore(host)} - >${story()} -`; - -const documentTreeStoreProvider = (story) => html` - new UmbDocumentTreeStore(host)} - >${story()} -`; - // Provide the MSW addon decorator globally -export const decorators = [documentStoreProvider, documentTreeStoreProvider, dataTypeStoreProvider, storybookProvider]; +export const decorators = [storybookProvider]; export const parameters = { docs: { @@ -98,28 +178,7 @@ export const parameters = { storySort: { method: 'alphabetical', includeNames: true, - order: [ - 'Guides', - [ - 'Getting started', - 'Extending the Backoffice', - [ - 'Intro', - 'Registration', - 'Header Apps', - 'Sections', - ['Intro', 'Sidebar', 'Views', '*'], - 'Entity Actions', - 'Workspaces', - ['Intro', 'Views', 'Actions', '*'], - 'Property Editors', - 'Repositories', - '*', - ], - '*', - ], - '*', - ], + order: ['Generic Components', 'Extension Type', 'Entity', 'Guides'], }, }, controls: { diff --git a/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.test.ts b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.test.ts new file mode 100644 index 0000000000..9b23526ebc --- /dev/null +++ b/src/Umbraco.Web.UI.Client/examples/workspace-context-counter/counter-workspace-context.test.ts @@ -0,0 +1,318 @@ +import { WorkspaceContextCounterElement, EXAMPLE_COUNTER_CONTEXT } from './counter-workspace-context.js'; +import { ExampleCounterWorkspaceView } from './counter-workspace-view.js'; +import { ExampleCounterStatusFooterAppElement } from './counter-status-footer-app.element.js'; +import { expect, fixture, defineCE } from '@open-wc/testing'; +import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +class TestHostElement extends UmbLitElement {} +const testHostElement = defineCE(TestHostElement); + +describe('WorkspaceContextCounterElement', () => { + let element: UmbLitElement; + let context: WorkspaceContextCounterElement; + + beforeEach(async () => { + element = await fixture(`<${testHostElement}>`); + context = new WorkspaceContextCounterElement(element); + }); + + describe('Counter functionality', () => { + it('initializes with counter value of 0', (done) => { + context.counter.subscribe((value) => { + expect(value).to.equal(0); + done(); + }); + }); + + it('increments counter value when increment method is called', (done) => { + let callbackCount = 0; + + context.counter.subscribe((value) => { + callbackCount++; + if (callbackCount === 1) { + expect(value).to.equal(0); + context.increment(); + } else if (callbackCount === 2) { + expect(value).to.equal(1); + done(); + } + }); + }); + + it('increments counter multiple times correctly', (done) => { + let callbackCount = 0; + + context.counter.subscribe((value) => { + callbackCount++; + if (callbackCount === 1) { + expect(value).to.equal(0); + context.increment(); + context.increment(); + context.increment(); + } else if (callbackCount === 4) { + expect(value).to.equal(3); + done(); + } + }); + }); + }); + + describe('Reset functionality', () => { + it('resets counter to 0 when reset method is called', (done) => { + let callbackCount = 0; + + context.counter.subscribe((value) => { + callbackCount++; + if (callbackCount === 1) { + expect(value).to.equal(0); + // First increment the counter + context.increment(); + context.increment(); + } else if (callbackCount === 3) { + expect(value).to.equal(2); + // Then reset it + context.reset(); + } else if (callbackCount === 4) { + expect(value).to.equal(0); + done(); + } + }); + }); + + it('can reset from any counter value', (done) => { + let callbackCount = 0; + + context.counter.subscribe((value) => { + callbackCount++; + if (callbackCount === 1) { + expect(value).to.equal(0); + // Increment to a higher number + context.increment(); + context.increment(); + context.increment(); + context.increment(); + context.increment(); + } else if (callbackCount === 6) { + expect(value).to.equal(5); + context.reset(); + } else if (callbackCount === 7) { + expect(value).to.equal(0); + done(); + } + }); + }); + + it('reset works when counter is already at 0', (done) => { + context.counter.subscribe((value) => { + expect(value).to.equal(0); + // Reset when already at 0 - should not cause issues + context.reset(); + // Verify it's still 0 + expect(value).to.equal(0); + done(); + }); + }); + }); + + describe('Increment and Reset interaction', () => { + it('can increment after reset', (done) => { + let callbackCount = 0; + + context.counter.subscribe((value) => { + callbackCount++; + if (callbackCount === 1) { + expect(value).to.equal(0); + context.increment(); + } else if (callbackCount === 2) { + expect(value).to.equal(1); + context.reset(); + } else if (callbackCount === 3) { + expect(value).to.equal(0); + context.increment(); + } else if (callbackCount === 4) { + expect(value).to.equal(1); + done(); + } + }); + }); + }); + + describe('Context integration', () => { + it('provides context that can be consumed by other components', () => { + // Verify context is available for consumption + expect(EXAMPLE_COUNTER_CONTEXT).to.not.be.undefined; + }); + }); +}); + +describe('ExampleCounterWorkspaceView', () => { + let element: ExampleCounterWorkspaceView; + let context: WorkspaceContextCounterElement; + let hostElement: UmbLitElement; + + beforeEach(async () => { + hostElement = await fixture(`<${testHostElement}>`); + context = new WorkspaceContextCounterElement(hostElement); + + element = await fixture(html``, { + parentNode: hostElement, + }); + + // Wait for context consumption + await element.updateComplete; + }); + + describe('Counter value display', () => { + it('shows initial counter value', async () => { + await element.updateComplete; + const displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Current count value: 0'); + }); + + it('reflects counter value changes when incremented', async () => { + context.increment(); + await element.updateComplete; + + const displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Current count value: 1'); + }); + + it('reflects counter value changes when incremented multiple times', async () => { + context.increment(); + context.increment(); + context.increment(); + await element.updateComplete; + + const displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Current count value: 3'); + }); + + it('reflects counter value changes when reset', async () => { + context.increment(); + context.increment(); + await element.updateComplete; + + let displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Current count value: 2'); + + context.reset(); + await element.updateComplete; + + displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Current count value: 0'); + }); + + it('maintains correct value display through increment and reset cycles', async () => { + // Test a complete workflow cycle + context.increment(); + context.increment(); + context.increment(); + await element.updateComplete; + expect(element.shadowRoot?.textContent).to.include('Current count value: 3'); + + context.reset(); + await element.updateComplete; + expect(element.shadowRoot?.textContent).to.include('Current count value: 0'); + + context.increment(); + await element.updateComplete; + expect(element.shadowRoot?.textContent).to.include('Current count value: 1'); + }); + }); +}); + +describe('ExampleCounterStatusFooterAppElement', () => { + let element: ExampleCounterStatusFooterAppElement; + let context: WorkspaceContextCounterElement; + let hostElement: UmbLitElement; + + beforeEach(async () => { + hostElement = await fixture(`<${testHostElement}>`); + context = new WorkspaceContextCounterElement(hostElement); + + element = await fixture(html``, { + parentNode: hostElement, + }); + + // Wait for context consumption + await element.updateComplete; + }); + + describe('Status display', () => { + it('shows initial counter status', async () => { + await element.updateComplete; + const displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Counter: 0'); + }); + + it('reflects counter state changes when incremented', async () => { + context.increment(); + await element.updateComplete; + + const displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Counter: 1'); + }); + + it('reflects counter state changes when incremented multiple times', async () => { + context.increment(); + context.increment(); + context.increment(); + context.increment(); + context.increment(); + await element.updateComplete; + + const displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Counter: 5'); + }); + + it('reflects counter state changes when reset', async () => { + context.increment(); + context.increment(); + context.increment(); + await element.updateComplete; + + let displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Counter: 3'); + + context.reset(); + await element.updateComplete; + + displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Counter: 0'); + }); + + it('maintains accurate status display through complete workflow cycles', async () => { + // Test comprehensive state change tracking + await element.updateComplete; + expect(element.shadowRoot?.textContent).to.include('Counter: 0'); + + context.increment(); + context.increment(); + await element.updateComplete; + expect(element.shadowRoot?.textContent).to.include('Counter: 2'); + + context.reset(); + await element.updateComplete; + expect(element.shadowRoot?.textContent).to.include('Counter: 0'); + + context.increment(); + await element.updateComplete; + expect(element.shadowRoot?.textContent).to.include('Counter: 1'); + }); + + it('synchronizes with context state changes across multiple increments and resets', async () => { + // Test synchronization with rapid state changes + context.increment(); + context.increment(); + context.increment(); + context.reset(); + context.increment(); + context.increment(); + await element.updateComplete; + + const displayText = element.shadowRoot?.textContent; + expect(displayText).to.include('Counter: 2'); + }); + }); +}); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index a36435f118..5a9f40bea1 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -191,6 +191,10 @@ "test:dev-watch": "npm run generate:check-const-test && web-test-runner --watch --config ./web-test-runner.dev.config.mjs", "test:watch": "npm run generate:check-const-test && web-test-runner --watch", "test": "npm run generate:check-const-test && npm run check:module-dependencies && web-test-runner", + "test:examples": "npm run generate:check-const-test && web-test-runner --files \"./examples/**/*.test.ts\"", + "test:examples:dev": "npm run generate:check-const-test && web-test-runner --config ./web-test-runner.dev.config.mjs --files \"./examples/**/*.test.ts\"", + "test:examples:watch": "npm run generate:check-const-test && web-test-runner --watch --config ./web-test-runner.dev.config.mjs --files \"./examples/**/*.test.ts\"", + "test:examples:browser": "npm run generate:check-const-test && web-test-runner --config ./web-test-runner.dev.config.mjs --files \"./examples/**/*.test.ts\" --manual", "wc-analyze:vscode": "wca **/*.element.ts --format vscode --outFile dist-cms/vscode-html-custom-data.json", "wc-analyze": "wca **/*.element.ts --outFile dist-cms/custom-elements.json", "generate:tsconfig": "node ./devops/tsconfig/index.js", diff --git a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.stories.ts deleted file mode 100644 index a3efa3acd7..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/backoffice/backoffice.stories.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { UmbBackofficeElement } from './backoffice.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './backoffice.element.js'; - -export default { - title: 'Apps/Backoffice', - component: 'umb-backoffice', - id: 'umb-backoffice', -} as Meta; - -export const AAAOverview: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/consent/installer-consent.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/consent/installer-consent.stories.ts deleted file mode 100644 index 55fd5d23fd..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/consent/installer-consent.stories.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { installerContextProvider } from '../shared/utils.story-helpers.js'; -import type { UmbInstallerConsentElement } from './installer-consent.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; -import './installer-consent.element.js'; - -export default { - title: 'Apps/Installer/Steps', - component: 'umb-installer-consent', - id: 'umb-installer-consent', - decorators: [(story) => installerContextProvider(story)], -} as Meta; - -export const Step2Telemetry: StoryFn = () => - html``; -Step2Telemetry.storyName = 'Step 2: Telemetry data'; diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/database/installer-database.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/database/installer-database.stories.ts deleted file mode 100644 index 83ee8b9a50..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/database/installer-database.stories.ts +++ /dev/null @@ -1,17 +0,0 @@ -import './installer-database.element.js'; - -import { installerContextProvider } from '../shared/utils.story-helpers.js'; -import type { UmbInstallerDatabaseElement } from './installer-database.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'Apps/Installer/Steps', - component: 'umb-installer-database', - id: 'umb-installer-database', - decorators: [(story) => installerContextProvider(story)], -} as Meta; - -export const Step3Database: StoryFn = () => - html``; -Step3Database.storyName = 'Step 3: Database'; diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.stories.ts deleted file mode 100644 index 1a85324266..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/error/installer-error.stories.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { installerContextProvider } from '../shared/utils.story-helpers.js'; -import { UmbInstallerContext } from '../installer.context.js'; -import type { UmbInstallerErrorElement } from './installer-error.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './installer-error.element.js'; -import type { UmbControllerHostElement } from '@umbraco-cms/backoffice/controller-api'; - -const error = { - type: 'validation', - status: 400, - detail: 'The form did not pass validation', - title: 'Validation error', - errors: { - 'user.password': [ - 'The password must be at least 6 characters long', - 'The password must contain at least one number', - ], - databaseName: ['The database name is required'], - }, -}; - -const installerContextMethod = (host: UmbControllerHostElement) => { - const installerContext = new UmbInstallerContext(host); - installerContext.setInstallStatus(error); - return installerContext; -}; - -export default { - title: 'Apps/Installer/Steps', - component: 'umb-installer-error', - id: 'umb-installer-error', - decorators: [(story) => installerContextProvider(story, installerContextMethod)], -} as Meta; - -export const Step5Error: StoryFn = () => html``; -Step5Error.storyName = 'Step 5: Error'; diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/installer.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/installer.stories.ts deleted file mode 100644 index 86e848a543..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/installer.stories.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Meta } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './index.js'; - -export default { - title: 'Apps/Installer', - component: 'umb-installer', - id: 'umb-installer', -} as Meta; - -export const Installer = () => html``; diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/installing/installer-installing.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/installing/installer-installing.stories.ts deleted file mode 100644 index ec03c78e6e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/installing/installer-installing.stories.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { installerContextProvider } from '../shared/utils.story-helpers.js'; -import type { UmbInstallerInstallingElement } from './installer-installing.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; -import './installer-installing.element.js'; - -export default { - title: 'Apps/Installer/Steps', - component: 'umb-installer-installing', - id: 'umb-installer-installing', - decorators: [(story) => installerContextProvider(story)], -} as Meta; - -export const Step4Installing: StoryFn = () => - html``; -Step4Installing.storyName = 'Step 4: Installing'; diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/shared/layout/installer-layout.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/shared/layout/installer-layout.stories.ts deleted file mode 100644 index 3fc5837c27..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/shared/layout/installer-layout.stories.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { UmbInstallerLayoutElement } from './installer-layout.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './installer-layout.element.js'; - -export default { - title: 'Apps/Installer/Shared', - component: 'umb-installer-layout', - id: 'umb-installer-layout', -} as Meta; - -export const Layout: StoryFn = () => html``; diff --git a/src/Umbraco.Web.UI.Client/src/apps/installer/user/installer-user.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/installer/user/installer-user.stories.ts deleted file mode 100644 index 556bedc89d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/installer/user/installer-user.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { installerContextProvider } from '../shared/utils.story-helpers.js'; -import type { UmbInstallerUserElement } from './installer-user.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; -import './installer-user.element.js'; - -export default { - title: 'Apps/Installer/Steps', - component: 'umb-installer-user', - id: 'umb-installer-user', - decorators: [(story) => installerContextProvider(story)], -} as Meta; - -export const Step1User: StoryFn = () => html``; -Step1User.storyName = 'Step 1: User'; diff --git a/src/Umbraco.Web.UI.Client/src/apps/preview/preview.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/preview/preview.stories.ts deleted file mode 100644 index 766b8f8940..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/preview/preview.stories.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { Meta } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'Apps/Preview', - component: 'umb-preview', - id: 'umb-preview', -} satisfies Meta; - -export const Preview = () => html``; diff --git a/src/Umbraco.Web.UI.Client/src/apps/upgrader/upgrader.stories.ts b/src/Umbraco.Web.UI.Client/src/apps/upgrader/upgrader.stories.ts deleted file mode 100644 index f340206f69..0000000000 --- a/src/Umbraco.Web.UI.Client/src/apps/upgrader/upgrader.stories.ts +++ /dev/null @@ -1,56 +0,0 @@ -import './upgrader-view.element.js'; - -import type { UmbUpgraderViewElement } from './upgrader-view.element.js'; -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'Apps/Upgrader/States', - component: 'umb-upgrader-view', - args: { - errorMessage: '', - upgrading: false, - fetching: false, - settings: { - currentState: '2b20c6e7', - newState: '2b20c6e8', - oldVersion: '12.0.0', - newVersion: '13.0.0', - reportUrl: 'https://our.umbraco.com/download/releases/1000', - }, - }, - parameters: { - actions: { - handles: ['onAuthorizeUpgrade'], - }, - }, - decorators: [ - (story) => - html`
- ${story()} -
`, - ], -} satisfies Meta; - -type Story = StoryObj; - -export const Overview: Story = {}; - -export const Upgrading: Story = { - args: { - upgrading: true, - }, -}; - -export const Fetching: Story = { - args: { - fetching: true, - }, -}; - -export const Error: Story = { - args: { - errorMessage: 'Something went wrong', - }, -}; diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/da.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/da.ts index 8e1be50660..c6b003ac84 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/da.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/da.ts @@ -2705,7 +2705,7 @@ export default { trainingDescription: '\n

Want to master Umbraco? Spend a couple of minutes learning some best practices by watching one of these videos about using Umbraco. And visit umbraco.tv for even more Umbraco videos

\n ', learningBaseDescription: - '

Vil du mestre Umbraco? Brug et par minutter på at lære nogle best practices ved at besøge Umbraco Learning Base YouTube-kanalen. Her finder du en masse videoer, der dækker mange aspekter af Umbraco.

', + '

Vil du mestre Umbraco? Brug et par minutter på at lære nogle best practices ved at besøge Umbraco Learning Base YouTube-kanalen. Her finder du en masse videoer, der dækker mange aspekter af Umbraco.

', getStarted: 'To get you started', }, settingsDashboard: { @@ -2790,9 +2790,8 @@ export default { tiptap: { anchor: 'Anker', anchor_input: 'Indtast anker-ID', - config_dimensions_description: 'Sæt den maksimale bredde og højde på editoren. Dette ekskluderer værktøjslinjens højde.', - maxDimensions: 'Maksimale dimensioner', - minDimensions: 'Minimale dimensioner', + config_dimensions_description: + 'Angiver en fast bredde og højde for editoren. Dette ekskluderer værktøjslinjens og statuslinjens højder.', config_extensions: 'Funktioner', config_statusbar: 'Statuslinje', config_toolbar: 'Værktøjslinje', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts index 616ede082d..ed9c609e9a 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/en.ts @@ -2781,7 +2781,8 @@ export default { tiptap: { anchor: 'Anchor', anchor_input: 'Enter an anchor ID', - config_dimensions_description: 'Set the maximum width and height of the editor. This excludes the toolbar height.', + config_dimensions_description: + 'Sets the fixed width and height of the editor. This excludes the toolbar and statusbar heights.', config_extensions: 'Capabilities', config_statusbar: 'Statusbar', config_toolbar: 'Toolbar', diff --git a/src/Umbraco.Web.UI.Client/src/assets/lang/pt.ts b/src/Umbraco.Web.UI.Client/src/assets/lang/pt.ts index c830525cbc..f94d631f89 100644 --- a/src/Umbraco.Web.UI.Client/src/assets/lang/pt.ts +++ b/src/Umbraco.Web.UI.Client/src/assets/lang/pt.ts @@ -2789,7 +2789,7 @@ export default { anchor: 'Âncora', anchor_input: 'Introduza um ID de âncora', config_dimensions_description: - 'Defina a largura e altura máximas do editor. Isto exclui a altura da barra de ferramentas.', + 'Definir uma largura e altura fixas para o editor. Isso exclui as alturas da barra de ferramentas e da barra de estado.', config_extensions: 'Capacidades', config_statusbar: 'Barra de estado', config_toolbar: 'Barra de ferramentas', diff --git a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.data.ts b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.data.ts index 55597474c2..c24be4f14b 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.data.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/data/member/member.data.ts @@ -25,7 +25,7 @@ export const data: Array = [ { culture: 'en-us', segment: null, - name: 'The Simplest Member', + name: 'Member 1', createDate: '2023-02-06T15:32:05.350038', updateDate: '2023-02-06T15:32:24.957009', }, @@ -36,7 +36,7 @@ export const data: Array = [ email: 'member2@member.com', failedPasswordAttempts: 0, groups: [], - id: '6ff6f75a-c14e-4172-a80b-d3ffcbc37979', + id: 'fffe28f4-268a-41aa-a14d-309a2ab790d0', isApproved: true, isLockedOut: false, isTwoFactorEnabled: false, @@ -50,7 +50,7 @@ export const data: Array = [ { culture: 'en-us', segment: null, - name: 'The Simplest Member', + name: 'Member 2', createDate: '2023-02-06T15:32:05.350038', updateDate: '2023-02-06T15:32:24.957009', }, @@ -61,7 +61,7 @@ export const data: Array = [ email: 'member3@member.com', failedPasswordAttempts: 0, groups: [], - id: '6ff6f75a-c14e-4172-a80b-d3ffcbc37979', + id: 'f63f89f2-5a06-4b32-973e-68efb392f7fd', isApproved: false, isLockedOut: false, isTwoFactorEnabled: false, diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/language/item.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/language/item.handlers.ts index 833d499e1c..546fb7d292 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/language/item.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/language/item.handlers.ts @@ -5,7 +5,7 @@ import { umbracoPath } from '@umbraco-cms/backoffice/utils'; export const itemHandlers = [ rest.get(umbracoPath(`/item${UMB_SLUG}`), (req, res, ctx) => { - const isoCodes = req.url.searchParams.getAll('id'); + const isoCodes = req.url.searchParams.getAll('isoCode'); if (!isoCodes) return; const items = umbLanguageMockDb.item.getItems(isoCodes); return res(ctx.status(200), ctx.json(items)); diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/static-file/item.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/static-file/item.handlers.ts index 08f87bab50..90e1743e8b 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/static-file/item.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/static-file/item.handlers.ts @@ -5,7 +5,7 @@ import { umbracoPath } from '@umbraco-cms/backoffice/utils'; export const itemHandlers = [ rest.get(umbracoPath(`/item${UMB_SLUG}`), (req, res, ctx) => { - const paths = req.url.searchParams.getAll('paths'); + const paths = req.url.searchParams.getAll('path'); if (!paths) return res(ctx.status(400, 'no body found')); const items = umbStaticFileMockDb.item.getItems(paths); return res(ctx.status(200), ctx.json(items)); diff --git a/src/Umbraco.Web.UI.Client/src/mocks/handlers/user/item.handlers.ts b/src/Umbraco.Web.UI.Client/src/mocks/handlers/user/item.handlers.ts index 51c4c66db1..e7ab718517 100644 --- a/src/Umbraco.Web.UI.Client/src/mocks/handlers/user/item.handlers.ts +++ b/src/Umbraco.Web.UI.Client/src/mocks/handlers/user/item.handlers.ts @@ -1,5 +1,5 @@ const { rest } = window.MockServiceWorker; -import { umbDocumentMockDb } from '../../data/document/document.db.js'; +import { umbUserMockDb } from '../../data/user/user.db.js'; import { UMB_SLUG } from './slug.js'; import { umbracoPath } from '@umbraco-cms/backoffice/utils'; @@ -7,7 +7,7 @@ export const itemHandlers = [ rest.get(umbracoPath(`/item${UMB_SLUG}`), (req, res, ctx) => { const ids = req.url.searchParams.getAll('id'); if (!ids) return; - const items = umbDocumentMockDb.item.getItems(ids); + const items = umbUserMockDb.item.getItems(ids); return res(ctx.status(200), ctx.json(items)); }), ]; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.element.ts index ce094fbe31..d0f47ea891 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.element.ts @@ -1,8 +1,10 @@ import { UmbBlockGridAreaConfigEntryContext } from './block-grid-area-config-entry.context.js'; +import { css, customElement, html, property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { html, css, customElement, property, state } from '@umbraco-cms/backoffice/external/lit'; import type { UmbPropertyEditorUiElement } from '@umbraco-cms/backoffice/property-editor'; +import '../block-scale-handler/block-scale-handler.element.js'; + /** * @element umb-block-area-config-entry */ diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts index 78e52ed147..34e767b5c0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-areas-config/property-editor-ui-block-grid-areas-config.element.ts @@ -1,17 +1,21 @@ import { UMB_BLOCK_GRID_DEFAULT_LAYOUT_STYLESHEET, type UmbBlockGridTypeAreaType } from '../../index.js'; import { UMB_BLOCK_GRID_AREA_TYPE_WORKSPACE_MODAL } from '../../components/block-grid-area-config-entry/constants.js'; +import type { UmbBlockGridAreaConfigEntryElement } from '../../../block-grid/components/block-grid-area-config-entry/block-grid-area-config-entry.element.js'; import { UmbBlockGridAreaTypeEntriesContext } from './block-grid-area-type-entries.context.js'; +import { css, customElement, html, property, repeat, state } from '@umbraco-cms/backoffice/external/lit'; +import { incrementString } from '@umbraco-cms/backoffice/utils'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { html, customElement, property, state, repeat } from '@umbraco-cms/backoffice/external/lit'; +import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; +import { UmbSorterController, UmbSorterResolvePlacementAsGrid } from '@umbraco-cms/backoffice/sorter'; +import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbPropertyEditorUiElement, UmbPropertyEditorConfigCollection, } from '@umbraco-cms/backoffice/property-editor'; -import { UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; -import { UmbModalRouteRegistrationController } from '@umbraco-cms/backoffice/router'; -import { incrementString } from '@umbraco-cms/backoffice/utils'; import '../../components/block-grid-area-config-entry/block-grid-area-config-entry.element.js'; + @customElement('umb-property-editor-ui-block-grid-areas-config') export class UmbPropertyEditorUIBlockGridAreasConfigElement extends UmbLitElement @@ -23,9 +27,28 @@ export class UmbPropertyEditorUIBlockGridAreasConfigElement #defaultAreaGridColumns: number = 12; #valueOfAreaGridColumns?: number | null; + #sorter = new UmbSorterController(this, { + itemSelector: 'umb-block-area-config-entry', + containerSelector: '.umb-block-grid__area-container', + resolvePlacement: UmbSorterResolvePlacementAsGrid, + getUniqueOfElement: (element) => { + return element.key; + }, + getUniqueOfModel: (modelEntry) => { + return modelEntry.key; + }, + onChange: ({ model }) => { + const oldValue = this._value; + this._value = model; + this.requestUpdate('_value', oldValue); + this.dispatchEvent(new UmbChangeEvent()); + }, + }); + @property({ type: Array }) public set value(value: Array) { this._value = value ?? []; + this.#sorter.setModel(this._value); } public get value(): Array { return this._value; @@ -133,6 +156,14 @@ export class UmbPropertyEditorUIBlockGridAreasConfigElement ` : ''; } + + static override styles = [ + css` + .umb-block-grid__area { + cursor: move; + } + `, + ]; } export default UmbPropertyEditorUIBlockGridAreasConfigElement; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-column-span/property-editor-ui-block-grid-column-span.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-column-span/property-editor-ui-block-grid-column-span.stories.ts index 36b7dc7963..a637d39c3b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-column-span/property-editor-ui-block-grid-column-span.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-column-span/property-editor-ui-block-grid-column-span.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-block-grid-column-span.element.js'; export default { - title: 'Property Editor UIs/Block Grid Column Span', + title: 'Extension Type/Property Editor UI/Block/Block Grid Column Span', component: 'umb-property-editor-ui-block-grid-column-span', id: 'umb-property-editor-ui-block-grid-column-span', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.stories.ts deleted file mode 100644 index 77fa2b666a..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-editor/property-editor-ui-block-grid.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUIBlockGridElement } from './property-editor-ui-block-grid.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-block-grid.element.js'; - -export default { - title: 'Property Editor UIs/Block Grid', - component: 'umb-property-editor-ui-block-grid', - id: 'umb-property-editor-ui-block-grid', -} as Meta; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts deleted file mode 100644 index c266d421b2..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-group-configuration/property-editor-ui-block-grid-group-configuration.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUIBlockGridGroupConfigurationElement } from './property-editor-ui-block-grid-group-configuration.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-block-grid-group-configuration.element.js'; - -export default { - title: 'Property Editor UIs/Block Grid Group Configuration', - component: 'umb-property-editor-ui-block-grid-group-configuration', - id: 'umb-property-editor-ui-block-grid-group-configuration', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.stories.ts index 3c847ffe8c..c80c72fb47 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-layout-stylesheet/property-editor-ui-block-grid-layout-stylesheet.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-block-grid-layout-stylesheet.element.js'; export default { - title: 'Property Editor UIs/Block Grid Layout Stylesheet', + title: 'Extension Type/Property Editor UI/Block/Block Grid Layout Stylesheet', component: 'umb-property-editor-ui-block-grid-layout-stylesheet', id: 'umb-property-editor-ui-block-grid-layout-stylesheet', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.stories.ts deleted file mode 100644 index 26a90366c9..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-grid/property-editors/block-grid-type-configuration/property-editor-ui-block-grid-type-configuration.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUIBlockGridTypeConfigurationElement } from './property-editor-ui-block-grid-type-configuration.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-block-grid-type-configuration.element.js'; - -export default { - title: 'Property Editor UIs/Block Grid Block Configuration', - component: 'umb-property-editor-ui-block-grid-type-configuration', - id: 'umb-property-editor-ui-block-grid-type-configuration', -} as Meta; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.stories.ts deleted file mode 100644 index f99e324053..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUIBlockListElement } from './property-editor-ui-block-list.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-block-list.element.js'; - -export default { - title: 'Property Editor UIs/Block List', - component: 'umb-property-editor-ui-block-list', - id: 'umb-property-editor-ui-block-list', -} as Meta; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.stories.ts deleted file mode 100644 index 5a42b6e113..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-type-configuration/property-editor-ui-block-list-type-configuration.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUIBlockListBlockConfigurationElement } from './property-editor-ui-block-list-type-configuration.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-block-list-type-configuration.element.js'; - -export default { - title: 'Property Editor UIs/Block List Block Configuration', - component: 'umb-property-editor-ui-block-list-type-configuration', - id: 'umb-property-editor-ui-block-list-type-configuration', -} as Meta; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts index 22c06fcb87..f1a2209417 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/block-rte-entry/block-rte-entry.element.ts @@ -354,13 +354,14 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert :host { position: relative; display: block; - user-select: none; + user-select: all; user-drag: auto; white-space: nowrap; } + :host(.ProseMirror-selectednode) { umb-ref-rte-block { - cursor: not-allowed; + --uui-color-default-contrast: initial; outline: 3px solid var(--uui-color-focus); } } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/ref-rte-block/ref-rte-block.element.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/ref-rte-block/ref-rte-block.element.ts index ff927ad854..002b82272a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/ref-rte-block/ref-rte-block.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/block/block-rte/components/ref-rte-block/ref-rte-block.element.ts @@ -49,6 +49,7 @@ export class UmbRefRteBlockElement extends UmbLitElement { const blockValue = { ...this.content, $settings: this.settings }; return html` + @@ -60,13 +61,34 @@ export class UmbRefRteBlockElement extends UmbLitElement { :host { display: block; } + uui-ref-node { min-height: var(--uui-size-16); } + :host([unpublished]) umb-icon, :host([unpublished]) umb-ufm-render { opacity: 0.6; } + + /* HACK: Stretches a space character ( ) to be full-width to make the RTE block appear text-selectable. [LK,NL] */ + .selection-background { + position: absolute; + pointer-events: none; + font-size: 100vw; + inset: 0; + overflow: hidden; + z-index: 0; + } + + umb-icon, + umb-ufm-render { + z-index: 1; + + &::selection { + color: var(--uui-color-default-contrast); + } + } `, ]; } diff --git a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.stories.ts deleted file mode 100644 index 1baa932257..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/block/block-type/components/input-block-type/input-block-type.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-block-type.element.js'; -import type { UmbInputBlockTypeElement } from './input-block-type.element.js'; - -const meta: Meta = { - title: 'Components/Inputs/BlockType', - component: 'umb-input-media', -}; - -export default meta; -type Story = StoryObj; - -export const Overview: Story = { - args: {}, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.stories.ts deleted file mode 100644 index 4098bfd19d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/code-editor/code-editor-modal/code-editor-modal.stories.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { UmbCodeEditorModalData } from './code-editor-modal.token.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'API/Modals/Layouts/Code Editor', - component: 'umb-code-editor-modal', - id: 'umb-code-editor-modal', -} as Meta; - -const data: UmbCodeEditorModalData = { - headline: 'Code editor modal example', - content: `This example opens an HTML string in the Code Editor modal.`, - language: 'html', -}; - -export const Overview: StoryFn = () => html` - - -`; diff --git a/src/Umbraco.Web.UI.Client/src/packages/code-editor/components/code-editor.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/components/code-editor.stories.ts index a31e07ce1f..a9de2faeb0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/code-editor/components/code-editor.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/components/code-editor.stories.ts @@ -7,7 +7,7 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './code-editor.element.js'; const meta: Meta = { - title: 'Components/Code Editor', + title: 'Generic Components/Code Editor', component: 'umb-code-editor', decorators: [(story) => html`
${story()}
`], parameters: { layout: 'fullscreen' }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/code-editor/property-editor/property-editor-ui-code-editor.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/code-editor/property-editor/property-editor-ui-code-editor.stories.ts index 4eee51cd8d..3f19262ed6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/code-editor/property-editor/property-editor-ui-code-editor.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/code-editor/property-editor/property-editor-ui-code-editor.stories.ts @@ -5,7 +5,7 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-code-editor.element.js'; const meta: Meta = { - title: 'Property Editor UIs/Code Editor', + title: 'Extension Type/Property Editor UI/Code Editor', component: 'umb-property-editor-ui-code-editor', id: 'umb-property-editor-ui-code-editor', decorators: [(story) => html`
${story()}
`], @@ -14,4 +14,4 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts index 8432f1c8cf..bac7610e64 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/content/content/workspace/views/edit/content-editor.element.ts @@ -131,10 +131,10 @@ export class UmbContentWorkspaceViewEditElement extends UmbLitElement implements ${this._hasRootGroups && this._tabs.length > 0 ? html` + href=${this._routerPath + '/root'}> ` : ''} ${repeat( @@ -143,10 +143,10 @@ export class UmbContentWorkspaceViewEditElement extends UmbLitElement implements (tab, index) => { const path = this._routerPath + '/tab/' + encodeFolderName(tab.name || ''); return html``; + href=${path}>`; }, )} ` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.stories.ts index b94eb5b60f..70f46f608d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/body-layout/body-layout.stories.ts @@ -1,18 +1,18 @@ +import type { UmbBodyLayoutElement } from './body-layout.element.js'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; import './body-layout.element.js'; -import type { UmbBodyLayoutElement } from './body-layout.element.js'; const meta: Meta = { - title: 'Components/Workspace Layout', + title: 'Generic Components/Body Layout', component: 'umb-body-layout', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { render: () => html`
Header slot
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.stories.ts index f705537393..f34008d7ea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/code-block/code-block.stories.ts @@ -1,24 +1,18 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './code-block.element.js'; import type { UmbCodeBlockElement } from './code-block.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; +import './code-block.element.js'; + const meta: Meta = { - title: 'Components/Code Block', + title: 'Generic Components/Code Block', component: 'umb-code-block', - parameters: { - layout: 'centered', - }, }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: {}, -}; - -export const WithCode: Story = { - decorators: [], render: () => html` // Lets write some javascript alert("Hello World"); `, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/dropdown/dropdown.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/dropdown/dropdown.stories.ts new file mode 100644 index 0000000000..1f73051add --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/dropdown/dropdown.stories.ts @@ -0,0 +1,36 @@ +import type { UmbDropdownElement } from './dropdown.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import './dropdown.element.js'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +const meta: Meta = { + title: 'Generic Components/Dropdown', + component: 'umb-dropdown', + render: (args) => + html` + ${args.label} +
Dropdown Content
+
`, +}; + +export default meta; +type Story = StoryObj; + +export const Docs: Story = { + args: { + open: false, + label: 'Dropdown', + look: 'default', + color: 'default', + placement: 'bottom-start', + compact: false, + hideExpand: false, + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.stories.ts new file mode 100644 index 0000000000..d85e4342f2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/entity-actions-bundle/entity-actions-bundle.stories.ts @@ -0,0 +1,23 @@ +import type { UmbEntityActionsBundleElement } from './entity-actions-bundle.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; +import './entity-actions-bundle.element.js'; + +const meta: Meta = { + title: 'Extension Type/Entity Action/Components/Entity Actions Bundle', + component: 'umb-entity-actions-bundle', + render: (args) => + html` `, +}; + +export default meta; +type Story = StoryObj; + +export const Docs: Story = { + args: { + entityType: 'document', + unique: '1234', + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/footer-layout/footer-layout.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/footer-layout/footer-layout.stories.ts index d6820725f5..84e5e2889f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/footer-layout/footer-layout.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/footer-layout/footer-layout.stories.ts @@ -5,16 +5,15 @@ import type { Meta, StoryFn } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; export default { - title: 'Workspaces/Shared/Footer Layout', + title: 'Generic Components/Footer Layout', component: 'umb-footer-layout', id: 'umb-footer-layout', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html`
Footer slotActions slot
`; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/header-app/header-app.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/header-app/header-app.stories.ts deleted file mode 100644 index 8218f1ab7d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/header-app/header-app.stories.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './header-app-button.element.js'; -import type { UmbHeaderAppButtonElement } from './header-app-button.element.js'; - -const meta: Meta = { - title: 'Components/Header App Button', - component: 'umb-header-app-button', -}; - -export default meta; -type Story = StoryObj; - -export const Overview: Story = { - args: { - manifest: { - name: 'Some Manifest', - alias: 'someManifestAlias', - type: 'headerApp', - kind: 'button', - meta: { - label: 'Some Header', - icon: 'icon-home', - href: '/some/path', - }, - }, - }, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/history/history-list.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/history/history-list.stories.ts deleted file mode 100644 index 87fbc0899c..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/history/history-list.stories.ts +++ /dev/null @@ -1,36 +0,0 @@ -import './history-list.element.js'; -import './history-item.element.js'; - -import type { UmbHistoryListElement } from './history-list.element.js'; -import type { UmbHistoryItemElement } from './history-item.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'Components/History UI', - component: 'umb-history-list', - id: 'umb-history-list', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` - - Default slot - Action slot - - - Default slot - Action slot - - - Default slot - Action slot - - `; -AAAOverview.storyName = 'Overview'; - -export const Node: StoryFn = () => - html` - Default slot - Action slot - `; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/icon/icon.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/icon/icon.element.ts index e50830421e..35f31347b2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/icon/icon.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/icon/icon.element.ts @@ -21,8 +21,9 @@ export class UmbIconElement extends UmbLitElement { private _style: StyleInfo = {}; /** - * Color alias or a color code directly.\ + * Color alias or a color code directly. * If a color has been set via the name property, this property will override it. + * Example **color-pink** */ @property({ type: String }) public set color(value: string) { @@ -34,7 +35,7 @@ export class UmbIconElement extends UmbLitElement { } /** - * The icon name. Can be appended with a color.\ + * The icon name. Can be appended with a color. * Example **icon-heart color-red** */ @property({ type: String }) diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/icon/icon.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/icon/icon.stories.ts index c34120296f..5a535168d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/icon/icon.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/icon/icon.stories.ts @@ -1,18 +1,19 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './icon.element.js'; import type { UmbIconElement } from './icon.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; + +import './icon.element.js'; const meta: Meta = { - title: 'Components/Inputs/Icon', + title: 'Generic Components/Icon/Icon', component: 'umb-icon', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { name: 'icon-wand', - color: 'color-pink', + color: '', }, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.stories.ts index 47033e76ae..348fae9aec 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-color/input-color.stories.ts @@ -1,10 +1,13 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-color.element.js'; import type { UmbInputColorElement } from './input-color.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './input-color.element.js'; const meta: Meta = { - title: 'Components/Inputs/Color', + title: 'Generic Components/Inputs/Color', component: 'umb-input-color', + render: (args) => html``, }; export default meta; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.stories.ts index f99e300e19..578db83a97 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-date/input-date.stories.ts @@ -1,16 +1,18 @@ import type { UmbInputDateElement } from './input-date.element.js'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; import './input-date.element.js'; const meta: Meta = { - title: 'Components/Inputs/Date', + title: 'Generic Components/Inputs/Date', component: 'umb-input-date', + render: (args) => html``, }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { type: 'datetime-local', value: '2023-04-01T10:00:00Z', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.stories.ts index 6e29445802..1ea0c5d5bf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-dropdown/input-dropdown-list.stories.ts @@ -3,14 +3,14 @@ import './input-dropdown-list.element.js'; import type { UmbInputDropdownListElement } from './input-dropdown-list.element.js'; const meta: Meta = { - title: 'Components/Inputs/Dropdown List', + title: 'Generic Components/Inputs/Dropdown List', component: 'umb-input-dropdown-list', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { options: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-eye-dropper/input-eye-dropper.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-eye-dropper/input-eye-dropper.stories.ts index 97de0206e4..4263bb2828 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-eye-dropper/input-eye-dropper.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-eye-dropper/input-eye-dropper.stories.ts @@ -1,16 +1,22 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-eye-dropper.element.js'; import type { UmbInputEyeDropperElement } from './input-eye-dropper.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; +import './input-eye-dropper.element.js'; const meta: Meta = { - title: 'Components/Inputs/Eye Dropper', + title: 'Generic Components/Inputs/Eye Dropper', component: 'umb-input-eye-dropper', + render: (args) => + html``, }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: {}, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-number-range/input-number-range.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-number-range/input-number-range.stories.ts index d053fa1094..b1e5c3e1a9 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-number-range/input-number-range.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-number-range/input-number-range.stories.ts @@ -1,17 +1,21 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-number-range.element.js'; import type { UmbInputNumberRangeElement } from './input-number-range.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; + +import './input-number-range.element.js'; const meta: Meta = { - title: 'Components/Inputs/Number Range Picker', + title: 'Generic Components/Inputs/Number Range Picker', component: 'umb-input-number-range', }; export default meta; type Story = StoryObj; -export const Overview: Story = { - args: {}, +export const Docs: Story = { + args: { + minValue: undefined, + maxValue: undefined, + }, }; export const WithMinMax: Story = { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-radio-button-list/input-radio-button-list.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-radio-button-list/input-radio-button-list.stories.ts index d6870a3892..9ac049f9c6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-radio-button-list/input-radio-button-list.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-radio-button-list/input-radio-button-list.stories.ts @@ -1,16 +1,16 @@ +import type { UmbInputRadioButtonListElement } from './input-radio-button-list.element.js'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; import './input-radio-button-list.element.js'; -import type { UmbInputRadioButtonListElement } from './input-radio-button-list.element.js'; const meta: Meta = { - title: 'Components/Inputs/Radio Button List', + title: 'Generic Components/Inputs/Radio Button List', component: 'umb-input-radio-button-list', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { list: [ { label: 'One', value: '1' }, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-slider/input-slider.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-slider/input-slider.stories.ts index 8567ed5f4b..c9230bcba7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-slider/input-slider.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-slider/input-slider.stories.ts @@ -1,16 +1,25 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-slider.element.js'; import type { UmbInputSliderElement } from './input-slider.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; +import './input-slider.element.js'; const meta: Meta = { - title: 'Components/Inputs/Slider', + title: 'Generic Components/Inputs/Slider', component: 'umb-input-slider', + render: (args) => + html``, }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { min: 0, max: 100, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-toggle/input-toggle.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-toggle/input-toggle.stories.ts index 0b08836656..e87e430f7e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-toggle/input-toggle.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-toggle/input-toggle.stories.ts @@ -3,14 +3,14 @@ import './input-toggle.element.js'; import type { UmbInputToggleElement } from './input-toggle.element.js'; const meta: Meta = { - title: 'Components/Inputs/Toggle', + title: 'Generic Components/Inputs/Toggle', component: 'umb-input-toggle', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { checked: true, showLabels: true, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/input-with-alias/input-with-alias.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-with-alias/input-with-alias.stories.ts new file mode 100644 index 0000000000..0ea1a580b5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/input-with-alias/input-with-alias.stories.ts @@ -0,0 +1,21 @@ +import type { UmbInputWithAliasElement } from './input-with-alias.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import './input-with-alias.element.js'; + +const meta: Meta = { + title: 'Generic Components/Inputs/With Alias', + component: 'umb-input-with-alias', +}; + +export default meta; +type Story = StoryObj; + +export const Docs: Story = { + args: { + label: 'Input with Alias', + value: 'Some value', + alias: 'someAlias', + required: true, + autoGenerateAlias: true, + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/multiple-text-string-input/input-multiple-text-string.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/multiple-text-string-input/input-multiple-text-string.stories.ts new file mode 100644 index 0000000000..f315e674ab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/multiple-text-string-input/input-multiple-text-string.stories.ts @@ -0,0 +1,28 @@ +import type { UmbInputMultipleTextStringElement } from './input-multiple-text-string.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './input-multiple-text-string.element.js'; + +const meta: Meta = { + title: 'Generic Components/Inputs/Multiple Text String', + component: 'umb-input-multiple-text-string', + render: (args) => + html``, +}; + +export default meta; +type Story = StoryObj; + +export const Docs: Story = { + args: { + min: 0, + max: 10, + minMessage: 'This field needs more items', + maxMessage: 'This field has too many items', + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/popover-layout/popover-layout.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/popover-layout/popover-layout.stories.ts new file mode 100644 index 0000000000..cc6dd52e5c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/popover-layout/popover-layout.stories.ts @@ -0,0 +1,18 @@ +import type { UmbPopoverLayoutElement } from './popover-layout.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './popover-layout.element.js'; + +const meta: Meta = { + title: 'Generic Components/Popover/Popover Layout', + component: 'umb-popover-layout', + render: () => html`
Popover Content
`, +}; + +export default meta; +type Story = StoryObj; + +export const Docs: Story = { + args: {}, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/split-panel/split-panel.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/split-panel/split-panel.stories.ts index d93df4574a..456f2f6c8b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/split-panel/split-panel.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/split-panel/split-panel.stories.ts @@ -4,7 +4,7 @@ import type { UmbSplitPanelElement } from './split-panel.element.js'; import { html } from '@umbraco-cms/backoffice/external/lit'; const meta: Meta = { - title: 'Components/Split Panel', + title: 'Generic Components/Split Panel', component: 'umb-split-panel', argTypes: { lock: { options: ['none', 'start', 'end'] }, @@ -21,7 +21,7 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { render: (props) => html`
Start
diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/stack/stack.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/stack/stack.stories.ts index 248f5674b5..cf37aea919 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/stack/stack.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/stack/stack.stories.ts @@ -1,20 +1,23 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './stack.element.js'; import type { UmbStackElement } from './stack.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './stack.element.js'; const meta: Meta = { - title: 'Components/Stack', + title: 'Generic Components/Stack', component: 'umb-stack', + render: (args) => + html` +
Element 1
+
Element 2
+
Element 3
+
`, }; export default meta; - type Story = StoryObj; -export const Default: Story = { - args: {}, -}; - export const Divide: Story = { args: { divide: true, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/components/table/table.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/components/table/table.stories.ts index 890bf588cd..b97611cc00 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/components/table/table.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/components/table/table.stories.ts @@ -5,7 +5,7 @@ import { UmbId } from '@umbraco-cms/backoffice/id'; import './table.element.js'; const meta: Meta = { - title: 'Components/Table', + title: 'Generic Components/Table', component: 'umb-table', }; @@ -70,7 +70,7 @@ const items: Array = [ }, ]; -export const Overview: Story = { +export const Docs: Story = { args: { items: items, columns: columns, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/culture/components/input-culture-select/input-culture-select.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/culture/components/input-culture-select/input-culture-select.stories.ts index c1bfc7789a..8233df1787 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/culture/components/input-culture-select/input-culture-select.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/culture/components/input-culture-select/input-culture-select.stories.ts @@ -3,14 +3,14 @@ import './input-culture-select.element.js'; import type { UmbInputCultureSelectElement } from './input-culture-select.element.js'; const meta: Meta = { - title: 'Components/Inputs/Culture Select', + title: 'Generic Components/Inputs/Culture Select', component: 'umb-input-culture-select', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { readonly: false, disabled: false, diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action-list.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action-list.stories.ts new file mode 100644 index 0000000000..695dbbff13 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/entity-action/entity-action-list.stories.ts @@ -0,0 +1,21 @@ +import type { UmbEntityActionListElement } from './entity-action-list.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; +import './entity-action-list.element.js'; + +const meta: Meta = { + title: 'Extension Type/Entity Action/Components/Entity Action List', + component: 'umb-entity-action-list', + render: (args) => + html` `, +}; + +export default meta; +type Story = StoryObj; + +export const Docs: Story = { + args: { + entityType: 'document', + unique: '1234', + }, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.stories.ts index 1103f6cec1..b40eb7fe0f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon-picker-modal/icon-picker-modal.stories.ts @@ -6,7 +6,7 @@ import type { Meta, StoryFn } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; export default { - title: 'API/Modals/Layouts/Icon Picker', + title: 'Extension Type/Modal/Icon Picker', component: 'umb-icon-picker-modal', id: 'umb-icon-picker-modal', } as Meta; @@ -16,7 +16,7 @@ const value: UmbIconPickerModalValue = { icon: undefined, }; -export const Overview: StoryFn = () => html` +export const Docs: StoryFn = () => html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon.stories.ts index 899475e9d6..7f0bb924e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/icon-registry/icon.stories.ts @@ -3,7 +3,7 @@ import type { Meta, StoryFn } from '@storybook/web-components-vite'; import { html, repeat } from '@umbraco-cms/backoffice/external/lit'; export default { - title: 'API/Icons', + title: 'Generic Components/Icon/All Icons', id: 'umb-icons', } as Meta; @@ -38,4 +38,4 @@ const Template: StoryFn = () => { `; }; -export const Overview = Template.bind({}); +export const Docs = Template.bind({}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localization.mdx b/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localization.mdx index 97483ad8b4..42516cdb53 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localization.mdx +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localization.mdx @@ -2,7 +2,7 @@ import { Canvas, Meta } from '@storybook/addon-docs/blocks'; import * as LocalizeStories from './localize.element.stories'; - + # Localization @@ -155,4 +155,4 @@ Out of the box, Umbraco ships with the following languages denoted by their ISO - `tr-TR` - Turkish (Turkey) - `ua-UA` - Ukrainian (Ukraine) - `zh` - Chinese (China) -- `zh-TW` - Chinese (Taiwan) +- `zh-TW` - Chinese (Taiwan) \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localize.element.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localize.element.stories.ts index ee7942b457..3277dc56b5 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localize.element.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/localization/stories/localize.element.stories.ts @@ -4,7 +4,7 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import '../localize.element.js'; const meta: Meta = { - title: 'API/Localization/UmbLocalizeElement', + title: 'Guides/Localization/UmbLocalizeElement', component: 'umb-localize', args: { key: 'general_areyousure', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu-with-entity-actions/section-sidebar-menu-with-entity-actions.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu-with-entity-actions/section-sidebar-menu-with-entity-actions.stories.ts index d67234efaa..2877a55470 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu-with-entity-actions/section-sidebar-menu-with-entity-actions.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu-with-entity-actions/section-sidebar-menu-with-entity-actions.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './section-sidebar-menu-with-entity-actions.element.js'; export default { - title: 'Sections/Shared/Section Sidebar Menu With Entity Actions', + title: 'Extension Type/Section/Components/Section Sidebar Menu With Entity Actions', component: 'umb-section-sidebar-menu-with-entity-actions', id: 'umb-section-sidebar-menu-with-entity-actions', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.stories.ts index 132ea947d1..4088618074 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/menu/section-sidebar-menu/section-sidebar-menu.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './section-sidebar-menu.element.js'; export default { - title: 'Sections/Shared/Section Sidebar Menu', + title: 'Extension Type/Section/Components/Section Sidebar Menu', component: 'umb-section-sidebar-menu', id: 'umb-section-sidebar-menu', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.stories.ts index 22cb6bb4c6..b9a249babe 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/confirm/confirm-modal.stories.ts @@ -7,7 +7,7 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import type { UmbConfirmModalData } from '@umbraco-cms/backoffice/modal'; export default { - title: 'API/Modals/Layouts/Confirm', + title: 'Extension Type/Modal/Confirm', component: 'umb-confirm-modal', id: 'umb-confirm-modal', } as Meta; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/discard-changes-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/discard-changes-modal.stories.ts new file mode 100644 index 0000000000..d8d4ac7ff1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/discard-changes/discard-changes-modal.stories.ts @@ -0,0 +1,15 @@ +import type { UmbDiscardChangesModalElement } from './discard-changes-modal.element.js'; +import type { Meta, StoryFn } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './discard-changes-modal.element.js'; + +export default { + title: 'Extension Type/Modal/Discard Changes', + component: 'umb-discard-changes-modal', + id: 'umb-discard-changes-modal', +} as Meta; + +export const DiscardChanges: StoryFn = () => html` + +`; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/error-viewer/error-viewer-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/error-viewer/error-viewer-modal.stories.ts new file mode 100644 index 0000000000..97df6f4c18 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/modal/common/error-viewer/error-viewer-modal.stories.ts @@ -0,0 +1,21 @@ +import type { UmbErrorViewerModalElement } from './error-viewer-modal.element.js'; +import type { UmbErrorViewerModalData } from './error-viewer-modal.token.js'; +import type { Meta, StoryFn } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './error-viewer-modal.element.js'; + +export default { + title: 'Extension Type/Modal/Error Viewer', + component: 'umb-error-viewer-modal', + id: 'umb-error-viewer-modal', +} as Meta; + +const errorData: UmbErrorViewerModalData = { + headline: 'Error', + message: 'An unexpected error occurred while processing your request.', +}; + +export const ErrorViewer: StoryFn = () => html` + +`; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/layouts/default/notification-layout-default.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/layouts/default/notification-layout-default.stories.ts deleted file mode 100644 index 118af5eb2a..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/layouts/default/notification-layout-default.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { UmbNotificationLayoutDefaultElement } from './notification-layout-default.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './notification-layout-default.element.js'; - -export default { - title: 'API/Notifications/Layouts/Default', - component: 'umb-notification-layout-default', - id: 'notification-layout-default', - args: { - data: { - headline: 'Headline', - message: 'This is a default notification', - }, - }, -} as Meta; - -const Template: StoryFn = (props) => html` - - - -`; - -export const Default = Template.bind({}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/stories/notification.mdx b/src/Umbraco.Web.UI.Client/src/packages/core/notification/stories/notification.mdx deleted file mode 100644 index 048cc1f45f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/stories/notification.mdx +++ /dev/null @@ -1,177 +0,0 @@ -import { Meta } from '@storybook/addon-docs/blocks'; - - - -# Notifications - -Notifications appear in the bottom right corner of the Backoffice. There are two types of notifications: "Peek" and "Stay". - -**Peek notifications** -Goes away automatically and should be used as feedback on user actions. - -**Stay notifications** -Stays on the screen until dismissed by the user or custom code. Stay notification should be used when you need user feedback or want to control when the notification disappears. - -## Basic usage - -### Consume UmbNotificationContext from an element - -The UmbNotification context can be used to open notifications. - -```ts -import { html, LitElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/element'; -import type { UmbNotificationContext, UMB_NOTIFICATION_CONTEXT_ALIAS } from '@umbraco-cms/notification'; - -class MyElement extends UmbLitElement { - private _notificationContext?: UmbNotificationContext; - - constructor() { - super(); - - this.consumeContext(UMB_NOTIFICATION_CONTEXT_ALIAS, (instance) => { - this._notificationContext = notificationContext; - // notificationContext is now ready to be used - }); - } -} -``` - -### Open a notification - -A notification is opened by calling one of the helper methods on the UmbNotificationContext. The methods will return an instance of UmbNotificationHandler. - -```ts -import { html, LitElement } from '@umbraco-cms/backoffice/external/lit'; -import { state } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/element'; -import type { - UmbNotificationContext, - UmbNotificationDefaultData, - UMB_NOTIFICATION_CONTEXT_ALIAS, -} from '@umbraco-cms/notification'; - -class MyElement extends UmbLitElement { - private _notificationContext?: UmbNotificationContext; - - constructor() { - super(); - - this.consumeContext(UMB_NOTIFICATION_CONTEXT_ALIAS, (notificationContext) => { - this._notificationContext = notificationContext; - // notificationContext is now ready to be used - }); - } - - private _handleClick() { - const data: UmbNotificationDefaultData = { headline: 'Look at this', message: 'Something good happened' }; - const notificationHandler = this._notificationContext?.peek('positive', { data }); - - notificationHandler.onClose().then(() => { - // if you need any logic when the notification is closed you can run it here - }); - } - - override render() { - return html``; - } -} -``` - -## Advanced usage: creating custom layouts - -The default layout will cover most cases, but there might be situations where we want a more complex layout. You can create a new Custom Element to use as the layout. - -### Custom layout element - -```ts -import { html, LitElement } from '@umbraco-cms/backoffice/external/lit'; -import { property } from '@umbraco-cms/backoffice/external/lit'; -import { UmbTextStyles } from '@umbraco-cms/backoffice/style'; -import type { UmbNotificationHandler } from '@umbraco-cms/notification'; - -export interface UmbNotificationCustomData { - headline: string; - user: { - name: string; - }; -} - -export class UmbNotificationLayoutCustom extends LitElement { - static styles = [UmbTextStyles]; - - @property({ attribute: false }) - public notificationHandler: UmbNotificationHandler; - - @property({ type: Object }) - public data: UmbNotificationCustomData; - - private _handleConfirm() { - this.notificationHandler.close(true); - } - - override render() { - return html` - - ${this.data.user.name} - Confirm - - `; - } -} -``` - -### Open notification with custom layout - -```ts -import { html, LitElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbContextInjectMixin } from '@umbraco-cms/context-api'; -import type { - UmbNotificationContext, - UmbNotificationOptions, - UMB_NOTIFICATION_CONTEXT_ALIAS, -} from '@umbraco-cms/notification'; -import type { UmbNotificationCustomData } from './custom-notification-layout.js'; - -class MyElement extends LitElement { - private _notificationContext?: UmbNotificationContext; - - constructor() { - super(); - - this.consumeContext(UMB_NOTIFICATION_CONTEXT_ALIAS, (instance) => { - this._notificationContext = instance; - // notificationContext is now ready to be used - }); - } - - private _handleClick() { - const options: UmbNotificationOptions = { - elementName: 'umb-notification-layout-custom', - data: { - headline: 'Attention', - user: { name: 'Peter Parker' }, - }, - }; - - const notificationHandler = this._notificationContext?.stay('default', options); - - notificationHandler.onClose().then((result) => { - if (result) { - console.log('She agreed!'); - } - }); - } - - override render() { - return html``; - } -} -``` - -## Best practices - -- Keep messages in notifications short and friendly. -- Only use headlines when you need extra attention to the notification -- If a custom notification layout is only used in one module keep the files layout files local to that module. -- If a custom notification will be used across the project. Create it as a layout in the notification folder and add a helper method to the UmbNotificationContext. diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/stories/notification.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/stories/notification.stories.ts deleted file mode 100644 index f7fc8d5d14..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/stories/notification.stories.ts +++ /dev/null @@ -1,39 +0,0 @@ -import './story-notification-default-example.element.js'; - -import { UmbNotificationContext } from '../notification.context.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'API/Notifications/Overview', - component: 'umb-notification-layout-default', - decorators: [ - (story) => - html` new UmbNotificationContext(host)}> - ${story()} - `, - ], -} as Meta; - -const Template: StoryFn = () => html``; - -export const Default = Template.bind({}); -Default.parameters = { - docs: { - source: { - language: 'js', - code: ` -const options: UmbNotificationOptions = { - data: { - headline: 'Headline', - message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit' - } -}; - -this._notificationContext?.peek('positive', options); -`, - }, - }, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/notification/stories/story-notification-default-example.element.ts b/src/Umbraco.Web.UI.Client/src/packages/core/notification/stories/story-notification-default-example.element.ts deleted file mode 100644 index 3dbbcfb05f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/notification/stories/story-notification-default-example.element.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { UMB_NOTIFICATION_CONTEXT, type UmbNotificationContext } from '../notification.context.js'; -import type { UmbNotificationColor, UmbNotificationOptions } from '../types.js'; -import { html, customElement } from '@umbraco-cms/backoffice/external/lit'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; - -@customElement('umb-story-notification-default-example') -export class UmbStoryNotificationDefaultExampleElement extends UmbLitElement { - private _notificationContext?: UmbNotificationContext; - - override connectedCallback(): void { - super.connectedCallback(); - - this.consumeContext(UMB_NOTIFICATION_CONTEXT, (instance) => { - this._notificationContext = instance; - }); - } - - private _handleNotification = (color: UmbNotificationColor) => { - const options: UmbNotificationOptions = { - data: { - headline: 'Headline', - message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit', - }, - }; - this._notificationContext?.peek(color, options); - }; - - override render() { - return html` - - - - - - - `; - } -} - -declare global { - interface HTMLElementTagNameMap { - 'umb-story-notification-default-example': UmbStoryNotificationDefaultExampleElement; - } -} diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/components/ref-property-editor-ui/ref-property-editor-ui.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/components/ref-property-editor-ui/ref-property-editor-ui.stories.ts index 2db21beb4a..d45fbaab86 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/components/ref-property-editor-ui/ref-property-editor-ui.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/components/ref-property-editor-ui/ref-property-editor-ui.stories.ts @@ -5,14 +5,14 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './ref-property-editor-ui.element.js'; const meta: Meta = { - title: 'Components/Ref Property Editor UI', + title: 'Extension Type/Property Editor UI/Components/Ref Property Editor UI', component: 'umb-ref-property-editor-ui', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { name: 'Custom Property Editor UI', alias: 'Umb.PropertyEditorUi.CustomUI', diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.stories.ts deleted file mode 100644 index c2f0f2dffd..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property-editor/ui-picker-modal/property-editor-ui-picker-modal.stories.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { UmbPropertyEditorUIPickerModalElement } from './property-editor-ui-picker-modal.element.js'; -import type { UmbPropertyEditorUIPickerModalValue } from './property-editor-ui-picker-modal.token.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-picker-modal.element.js'; -import '../../components/body-layout/body-layout.element.js'; - -export default { - title: 'API/Modals/Layouts/Property Editor UI Picker', - component: 'umb-property-editor-ui-picker-modal', - id: 'umb-property-editor-ui-picker-modal', -} as Meta; - -const data: UmbPropertyEditorUIPickerModalValue = { selection: [] }; - -export const Overview: StoryFn = () => html` - -`; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property-layout/property-layout.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property-layout/property-layout.stories.ts index 6b778c68d2..d9b3b1e15b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property-layout/property-layout.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property-layout/property-layout.stories.ts @@ -5,7 +5,7 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-layout.element.js'; const meta: Meta = { - title: 'Workspaces/Property Layout', + title: 'Generic Components/Property Layout', id: 'umb-property-layout', component: 'umb-property-layout', args: { @@ -49,7 +49,7 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; export const Vertical: Story = { args: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.stories.ts index 20caf29aae..494a619f00 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/property/components/property/property.stories.ts @@ -5,16 +5,15 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property.element.js'; export default { - title: 'Components/Property', + title: 'Generic Components/Property', component: 'umb-property', id: 'umb-property', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-main/section-main.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-main/section-main.stories.ts index 17c801ee73..d3c8940f55 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-main/section-main.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-main/section-main.stories.ts @@ -5,12 +5,11 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './section-main.element.js'; export default { - title: 'Sections/Shared/Section Main', + title: 'Extension Type/Section/Components/Section Main', component: 'umb-section-main', id: 'umb-section-main', } as Meta; -export const AAAOverview: StoryFn = () => html` +export const Docs: StoryFn = () => html` Section Main Area `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.stories.ts index e17d977583..fbd4180ae6 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/section/section-sidebar/section-sidebar.stories.ts @@ -5,12 +5,11 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './section-sidebar.element.js'; export default { - title: 'Sections/Shared/Section Sidebar', + title: 'Extension Type/Section/Components/Section Sidebar', component: 'umb-section-sidebar', id: 'umb-section-sidebar', } as Meta; -export const AAAOverview: StoryFn = () => html` +export const Docs: StoryFn = () => html` Section Sidebar Area `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.stories.ts deleted file mode 100644 index 296deb93d6..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/core/tree/tree.stories.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './default/default-tree.element.js'; -import type { UmbTreeElement } from './tree.element.js'; - -const meta: Meta = { - title: 'Components/Tree/Tree', - component: 'umb-tree', -}; - -export default meta; -type Story = StoryObj; - -// TODO: This does not display anything - need help -export const Overview: Story = { - args: { - alias: 'Umb.Tree.Document', - }, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.stories.ts index 1d8b65145d..33df352c8e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-editor/workspace-editor.stories.ts @@ -5,12 +5,12 @@ import type { Meta, StoryFn } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; export default { - title: 'Workspaces/Shared/Workspace Editor', + title: 'Extension Type/Workspace/Components/Workspace Editor', component: 'umb-workspace-editor', id: 'umb-workspace-editor', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html`
Icon slot
Name slot
@@ -18,4 +18,3 @@ export const AAAOverview: StoryFn = () =>
Actions slot
Default slot
`; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.stories.ts index 5d18189ff9..988eecb2c8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/workspace/components/workspace-footer/workspace-footer.stories.ts @@ -6,14 +6,13 @@ import type { Meta, StoryFn } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; export default { - title: 'Workspaces/Shared/Footer Layout', + title: 'Extension Type/Workspace/Components/Workspace Footer', component: 'umb-workspace-footer', id: 'umb-workspace-footer', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html`
Footer slot
Actions slot
`; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-input/data-type-input.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-input/data-type-input.stories.ts new file mode 100644 index 0000000000..69b3149ed5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/data-type-input/data-type-input.stories.ts @@ -0,0 +1,18 @@ +import type { UmbDataTypeInputElement } from './data-type-input.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './data-type-input.element.js'; + +const meta: Meta = { + title: 'Entity/Data Type/Components/Input Data Type', + component: 'umb-data-type-input', + render: () => html``, +}; + +export default meta; +type Story = StoryObj; + +export const Docs: Story = { + args: {}, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.stories.ts deleted file mode 100644 index c57f88387e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/property-editor-config/property-editor-config.stories.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { UmbPropertyEditorConfigElement } from './property-editor-config.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-config.element.js'; - -export default { - title: 'Property Editors/Shared/Property Editor Config', - component: 'umb-property-editor-config', - id: 'umb-property-editor-config', -} as Meta; - -const data = [ - { - alias: 'maxChars', - value: 100, - }, -]; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/ref-data-type/ref-data-type.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/ref-data-type/ref-data-type.stories.ts index cb1907be3e..f0f854ede2 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/components/ref-data-type/ref-data-type.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/data-type/components/ref-data-type/ref-data-type.stories.ts @@ -5,14 +5,14 @@ import { UMB_PROPERTY_EDITOR_SCHEMA_ALIAS_DEFAULT } from '@umbraco-cms/backoffic import './ref-data-type.element.js'; const meta: Meta = { - title: 'Components/Ref Data Type', + title: 'Entity/Data Type/Components/Ref Data Type', component: 'umb-ref-property-editor-ui', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { name: 'Custom Data Type', propertyEditorUiAlias: 'Umb.DataTypeInput.CustomUI', diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/details/data-type-details-workspace-view.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/details/data-type-details-workspace-view.stories.ts deleted file mode 100644 index 93c689499d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/details/data-type-details-workspace-view.stories.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { UmbDataTypeDetailsWorkspaceViewEditElement } from './data-type-details-workspace-view.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -//import { data } from '../../../../../core/mocks/data/data-type.data.js'; - -import './data-type-details-workspace-view.element.js'; -//import { UmbDataTypeWorkspaceContext } from '../../workspace-data-type.context.js'; - -export default { - title: 'Workspaces/Data Type/Views/Edit', - component: 'umb-data-type-workspace-view-edit', - id: 'umb-data-type-workspace-view-edit', - decorators: [ - () => { - return html`TODO: make use of mocked workspace context??`; - /*html` - ${story()} - `,*/ - }, - ], -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/workspace-view-data-type-info.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/workspace-view-data-type-info.stories.ts deleted file mode 100644 index ae71461e76..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/data-type/workspace/views/info/workspace-view-data-type-info.stories.ts +++ /dev/null @@ -1,26 +0,0 @@ -import './workspace-view-data-type-info.element.js'; - -import type { UmbWorkspaceViewDataTypeInfoElement } from './workspace-view-data-type-info.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -//import { data } from '../../../../../core/mocks/data/data-type.data.js'; -//import { UmbDataTypeContext } from '../../data-type.context.js'; - -export default { - title: 'Workspaces/Data Type/Views/Info', - component: 'umb-workspace-view-data-type-info', - id: 'umb-workspace-view-data-type-info', - decorators: [ - () => { - return html`TODO: make use of mocked workspace context??`; - /*html` - ${story()} - `,*/ - }, - ], -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/views/workspace-view-dictionary-editor.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/views/workspace-view-dictionary-editor.stories.ts deleted file mode 100644 index e80718d56c..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/dictionary/workspace/views/workspace-view-dictionary-editor.stories.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { UmbWorkspaceViewDictionaryEditorElement } from './workspace-view-dictionary-editor.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; -//import { data } from '../../../../../core/mocks/data/dictionary.data.js'; -import './workspace-view-dictionary-editor.element.js'; -//import { UmbWorkspaceDictionaryContext } from '../../workspace-dictionary.context.js'; - -export default { - title: 'Workspaces/Dictionary/Views/Edit', - component: 'umb-workspace-view-dictionary-editor', - id: 'umb-workspace-view-dictionary-editor', - decorators: [ - () => { - return html`TODO: make use of mocked workspace context??`; - /*html` - ${story()} - `,*/ - }, - ], -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; - -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/dashboard-redirect-management.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/dashboard-redirect-management.stories.ts deleted file mode 100644 index 240f8042ef..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-redirect-management/dashboard-redirect-management.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import './dashboard-redirect-management.element.js'; - -import type { UmbDashboardRedirectManagementElement } from './dashboard-redirect-management.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'Dashboards/Redirect Management', - component: 'umb-dashboard-redirect-management', - id: 'umb-dashboard-redirect-management', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/property-editors/document-type-picker/property-editor-ui-document-type-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/property-editors/document-type-picker/property-editor-ui-document-type-picker.stories.ts index 4c640ec24e..505fc16fce 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/property-editors/document-type-picker/property-editor-ui-document-type-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/document-types/property-editors/document-type-picker/property-editor-ui-document-type-picker.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-document-type-picker.element.js'; export default { - title: 'Property Editor UIs/Document Type Picker', + title: 'Extension Type/Property Editor UI/Document Type Picker', component: 'umb-property-editor-ui-document-type-picker', id: 'umb-property-editor-ui-document-type-picker', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.stories.ts index 6c93ac3b72..f2ea3c7c56 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/components/input-document/input-document.stories.ts @@ -1,14 +1,15 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-document.element.js'; import type { UmbInputDocumentElement } from './input-document.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; + +import './input-document.element.js'; const meta: Meta = { - title: 'Components/Inputs/Document', + title: 'Entity/Document/Components/Input Document', component: 'umb-input-document', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: {}, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.stories.ts index 70b574c40f..f5e0d3faae 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/modals/save-modal/document-save-modal.stories.ts @@ -88,7 +88,7 @@ const modalValue: UmbDocumentSaveModalValue = { }; const meta: Meta = { - title: 'Workspaces/Document/Modals/Save', + title: 'Entity/Document/Modals/Save', component: 'umb-document-save-modal', id: 'umb-document-save-modal', args: { @@ -166,4 +166,4 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => { export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-editors/document-picker/property-editor-ui-document-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-editors/document-picker/property-editor-ui-document-picker.stories.ts index 2065fe8af9..4289d8fa2a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-editors/document-picker/property-editor-ui-document-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/property-editors/document-picker/property-editor-ui-document-picker.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-document-picker.element.js'; export default { - title: 'Property Editor UIs/Document Picker', + title: 'Extension Type/Property Editor UI/Document Picker', component: 'umb-property-editor-ui-document-picker', id: 'umb-property-editor-ui-document-picker', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/modal/document-publish-with-descendants-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/modal/document-publish-with-descendants-modal.stories.ts index 145871d796..54a9d07742 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/modal/document-publish-with-descendants-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish-with-descendants/modal/document-publish-with-descendants-modal.stories.ts @@ -91,7 +91,7 @@ const modalValue: UmbDocumentPublishWithDescendantsModalValue = { }; const meta: Meta = { - title: 'Workspaces/Document/Modals/Publish With Descendants Modal', + title: 'Entity/Document/Modals/Publish With Descendants Modal', component: 'umb-document-publish-with-descendants-modal', id: 'umb-document-publish-with-descendants-modal', args: { @@ -169,7 +169,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => { export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; export const Invariant: Story = { args: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/modal/document-publish-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/modal/document-publish-modal.stories.ts index 054968431c..8d32c68d3e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/modal/document-publish-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/publish/modal/document-publish-modal.stories.ts @@ -88,7 +88,7 @@ const modalValue: UmbDocumentPublishModalValue = { }; const meta: Meta = { - title: 'Workspaces/Document/Modals/Publish', + title: 'Entity/Document/Modals/Publish', component: 'umb-document-publish-modal', id: 'umb-document-publish-modal', args: { @@ -166,4 +166,4 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => { export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.stories.ts index eb41d10976..84453c2efc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/schedule-publish/modal/document-schedule-modal.stories.ts @@ -66,7 +66,7 @@ const modalValue: UmbDocumentScheduleModalValue = { }; const meta: Meta = { - title: 'Workspaces/Document/Modals/Schedule', + title: 'Entity/Document/Modals/Schedule', component: 'umb-document-schedule-modal', id: 'umb-document-schedule-modal', args: { @@ -125,7 +125,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => { export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; export const WithoutVariants: Story = { args: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/modal/document-unpublish-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/modal/document-unpublish-modal.stories.ts index a65c48ea92..40ef10377f 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/modal/document-unpublish-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/publishing/unpublish/modal/document-unpublish-modal.stories.ts @@ -91,7 +91,7 @@ const modalValue: UmbDocumentUnpublishModalValue = { }; const meta: Meta = { - title: 'Workspaces/Document/Modals/Unpublish', + title: 'Entity/Document/Modals/Unpublish', component: 'umb-document-unpublish-modal', id: 'umb-document-unpublish-modal', args: { @@ -169,7 +169,7 @@ this.consumeContext(UMB_MODAL_MANAGER_CONTEXT, (modalManager) => { export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; export const WithTrackedReferences: Story = { args: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/components/document-reference-table.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/components/document-reference-table.stories.ts deleted file mode 100644 index cc995da4db..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/reference/components/document-reference-table.stories.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { UmbDocumentReferenceTableElement } from './document-reference-table.element.js'; -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './document-reference-table.element.js'; - -const meta: Meta = { - id: 'umb-document-reference-table', - title: 'Components/Document/Reference Table', - component: 'umb-document-reference-table', - args: { - unique: '1234', - }, - parameters: { - actions: { - disabled: true, - }, - docs: { - source: { - language: 'html', - code: ` - - `, - }, - }, - }, -}; - -export default meta; - -type Story = StoryObj; - -export const Overview: Story = {}; - -export const SlimTable: Story = { - decorators: [ - (story) => { - return html`
${story()}
`; - }, - ], - parameters: { - docs: { - source: { - language: 'html', - code: ` - - `, - }, - }, - }, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.stories.ts deleted file mode 100644 index 3e279b6874..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/documents/documents/workspace/views/info/document-workspace-view-info.stories.ts +++ /dev/null @@ -1,26 +0,0 @@ -import './document-workspace-view-info.element.js'; - -import type { UmbDocumentWorkspaceViewInfoElement } from './document-workspace-view-info.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -// import { data } from '../../../../../../core/mocks/data/document.data.js'; -// import { UmbNodeContext } from '../../node.context.js'; - -export default { - title: 'Workspaces/Documents/Views/Info', - component: 'umb-document-workspace-view-info', - id: 'umb-document-workspace-view-info', - decorators: [ - () => { - return html`TODO: make use of mocked workspace context??`; - /*html` - ${story()} - `,*/ - }, - ], -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.stories.ts index 3a786e9516..94c81fe490 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/embedded-media/modal/embedded-media-modal.stories.ts @@ -5,7 +5,7 @@ import type { Meta } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; export default { - title: 'API/Modals/Layouts/Embedded Media', + title: 'Extension Type/Modal/Embedded Media', component: 'umb-embedded-media-modal', id: 'umb-embedded-media-modal', } as Meta; @@ -17,7 +17,7 @@ const data: UmbEmbeddedMediaModalData = { constrain: true, }; -export const Overview = () => html` +export const Docs = () => html` diff --git a/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.stories.ts deleted file mode 100644 index 3061d5877c..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/health-check/dashboard-health-check.stories.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { UmbDashboardHealthCheckOverviewElement } from './views/health-check-overview.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './views/health-check-overview.element.js'; - -import type { UmbDashboardHealthCheckGroupElement } from './views/health-check-group.element.js'; -import './views/health-check-group.element.js'; - -export default { - title: 'Dashboards/Health Check', - component: 'umb-dashboard-health-check-overview', - id: 'umb-dashboard-health-check', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; - -export const Group: StoryFn = () => - html` `; diff --git a/src/Umbraco.Web.UI.Client/src/packages/language/components/input-language/input-language.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/language/components/input-language/input-language.stories.ts index 7e7a01282d..1fb76f7826 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/language/components/input-language/input-language.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/language/components/input-language/input-language.stories.ts @@ -1,15 +1,18 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-language.element.js'; import type { UmbInputLanguageElement } from './input-language.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './input-language.element.js'; const meta: Meta = { - title: 'Components/Inputs/Language Picker', - component: 'umb-input-language-picker', + title: 'Entity/Language/Components/Input Language', + component: 'umb-input-language', + render: () => html``, }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: {}, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/components/donut-chart/donut-chart.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/components/donut-chart/donut-chart.stories.ts index 34368b9a1f..be2b9bb13c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/log-viewer/components/donut-chart/donut-chart.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/log-viewer/components/donut-chart/donut-chart.stories.ts @@ -1,21 +1,20 @@ -import './donut-slice.element.js'; -import './donut-chart.element.js'; - import type { Meta } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; +import './donut-slice.element.js'; +import './donut-chart.element.js'; + export default { - title: 'Components/Donut chart', + title: 'Generic Components/Donut chart', component: 'umb-donut-chart', id: 'umb-donut-chart', tags: ['autodocs'], } as Meta; -export const AAAOverview = () => +export const Docs = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.stories.ts index 5dc6dfeec6..caaad063e7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/components/input-markdown-editor/input-markdown.stories.ts @@ -1,9 +1,9 @@ +import type { UmbInputMarkdownElement } from './input-markdown.element.js'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; import './input-markdown.element.js'; -import type { UmbInputMarkdownElement } from './input-markdown.element.js'; const meta: Meta = { - title: 'Components/Inputs/Markdown', + title: 'Generic Components/Inputs/Markdown', component: 'umb-input-markdown', args: { preview: false, @@ -13,4 +13,4 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/property-editor-ui-markdown-editor.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/property-editor-ui-markdown-editor.stories.ts index f259b4725a..e7678bff04 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/property-editor-ui-markdown-editor.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/markdown-editor/property-editors/markdown-editor/property-editor-ui-markdown-editor.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-markdown-editor.element.js'; export default { - title: 'Property Editor UIs/Markdown Editor', + title: 'Extension Type/Property Editor UI/Markdown Editor', component: 'umb-property-editor-ui-markdown-editor', id: 'umb-property-editor-ui-markdown-editor', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/dropzone/components/input-dropzone/input-dropzone.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/dropzone/components/input-dropzone/input-dropzone.stories.ts index 0c3ac171f0..d6be61eae7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/dropzone/components/input-dropzone/input-dropzone.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/dropzone/components/input-dropzone/input-dropzone.stories.ts @@ -6,7 +6,7 @@ import './input-dropzone.element.js'; const meta: Meta = { id: 'umb-input-dropzone', - title: 'Components/Inputs/Dropzone', + title: 'Entity/Media/Components/Input Dropzone', component: 'umb-input-dropzone', args: { disabled: false, @@ -25,7 +25,7 @@ export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; export const WithDisabled: Story = { args: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/property-editors/media-type-picker/property-editor-ui-media-type-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/property-editors/media-type-picker/property-editor-ui-media-type-picker.stories.ts index 09b77e116e..00f2758cba 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media-types/property-editors/media-type-picker/property-editor-ui-media-type-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media-types/property-editors/media-type-picker/property-editor-ui-media-type-picker.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-media-type-picker.element.js'; export default { - title: 'Property Editor UIs/Media Type Picker', + title: 'Extension Type/Property Editor UI/Media Type Picker', component: 'umb-property-editor-ui-media-type-picker', id: 'umb-property-editor-ui-media-type-picker', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts index c027c36009..3461dcc59c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/collection/views/table/media-table-collection-view.element.ts @@ -108,6 +108,7 @@ export class UmbMediaTableCollectionViewElement extends UmbLitElement { name: this.localize.string(item.header), alias: item.alias, elementName: item.elementName, + labelTemplate: item.nameTemplate, allowSorting: true, }; }); diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.stories.ts index 2c84f64cab..7bef224673 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-media/input-media.stories.ts @@ -3,13 +3,13 @@ import './input-media.element.js'; import type { UmbInputMediaElement } from './input-media.element.js'; const meta: Meta = { - title: 'Components/Inputs/Media', + title: 'Entity/Media/Components/Input Media', component: 'umb-input-media', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: {}, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-upload-field/input-upload-field.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-upload-field/input-upload-field.stories.ts index 039de9488f..32526b889a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-upload-field/input-upload-field.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/components/input-upload-field/input-upload-field.stories.ts @@ -3,13 +3,13 @@ import './input-upload-field.element.js'; import type { UmbInputUploadFieldElement } from './input-upload-field.element.js'; const meta: Meta = { - title: 'Components/Inputs/Upload Field', + title: 'Entity/Media/Components/Input Upload Field', component: 'umb-input-upload-field', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: {}, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-cropper/property-editor-ui-image-cropper.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-cropper/property-editor-ui-image-cropper.stories.ts index 135b89fd6c..cf1f46d8b1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-cropper/property-editor-ui-image-cropper.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-cropper/property-editor-ui-image-cropper.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-image-cropper.element.js'; export default { - title: 'Property Editor UIs/Image Cropper', + title: 'Extension Type/Property Editor UI/Image Cropper', component: 'umb-property-editor-ui-image-cropper', id: 'umb-property-editor-ui-image-cropper', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.stories.ts index cb17439cd3..b9bb292a3a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/image-crops/property-editor-ui-image-crops.stories.ts @@ -4,7 +4,7 @@ import type { Meta, StoryObj } from '@storybook/web-components-vite'; import './property-editor-ui-image-crops.element.js'; const meta: Meta = { - title: 'Property Editor UIs/Image Crops', + title: 'Extension Type/Property Editor UI/Image Crops', id: 'umb-property-editor-ui-image-crops', component: 'umb-property-editor-ui-image-crops', }; @@ -12,4 +12,4 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Overview: Story = {}; +export const Docs: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-picker/property-editor-ui-media-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-picker/property-editor-ui-media-picker.stories.ts index 2221016dbf..a415ec7a21 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-picker/property-editor-ui-media-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/media-picker/property-editor-ui-media-picker.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-media-picker.element.js'; export default { - title: 'Property Editor UIs/Media Picker', + title: 'Extension Type/Property Editor UI/Media Picker', component: 'umb-property-editor-ui-media-picker', id: 'umb-property-editor-ui-media-picker', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/upload-field/property-editor-ui-upload-field.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/upload-field/property-editor-ui-upload-field.stories.ts index 1f0fbcd696..6abad8ecb4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/upload-field/property-editor-ui-upload-field.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/media/media/property-editors/upload-field/property-editor-ui-upload-field.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-upload-field.element.js'; export default { - title: 'Property Editor UIs/Upload Field', + title: 'Extension Type/Property Editor UI/Upload Field', component: 'umb-property-editor-ui-upload-field', id: 'umb-property-editor-ui-upload-field', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/property-editor-ui-member-group-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/property-editor-ui-member-group-picker.stories.ts index 148dfe8a34..afbfc6cdb0 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/property-editor-ui-member-group-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member-group/property-editor/member-group-picker/property-editor-ui-member-group-picker.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-member-group-picker.element.js'; export default { - title: 'Property Editor UIs/Member Group Picker', + title: 'Extension Type/Property Editor UI/Member Group Picker', component: 'umb-property-editor-ui-member-group-picker', id: 'umb-property-editor-ui-member-group-picker', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.stories.ts index 20a632ed3d..44f43f5826 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/components/input-member/input-member.stories.ts @@ -3,12 +3,12 @@ import './input-member.element.js'; import type { UmbInputMemberElement } from './input-member.element.js'; const meta: Meta = { - title: 'Components/Inputs/Member', + title: 'Entity/Member/Components/Input Member', component: 'umb-input-member', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: {}, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/members/member/property-editor/member-picker/property-editor-ui-member-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/members/member/property-editor/member-picker/property-editor-ui-member-picker.stories.ts index f8bee20bda..6eb6ca316d 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/members/member/property-editor/member-picker/property-editor-ui-member-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/members/member/property-editor/member-picker/property-editor-ui-member-picker.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-member-picker.element.js'; export default { - title: 'Property Editor UIs/Member Picker', + title: 'Extension Type/Property Editor UI/Member Picker', component: 'umb-property-editor-ui-member-picker', id: 'umb-property-editor-ui-member-picker', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/models-builder/models-builder-dashboard.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/models-builder/models-builder-dashboard.stories.ts deleted file mode 100644 index 92df018324..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/models-builder/models-builder-dashboard.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbModelsBuilderDashboardElement } from './models-builder-dashboard.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './models-builder-dashboard.element.js'; - -export default { - title: 'Dashboards/Models Builder', - component: 'umb-models-builder-dashboard', - id: 'umb-models-builder-dashboard', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts deleted file mode 100644 index ee359054a5..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/components/input-multi-url/input-multi-url.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-multi-url.element.js'; -import type { UmbInputMultiUrlElement } from './input-multi-url.element.js'; - -const meta: Meta = { - title: 'Components/Inputs/Multi URL', - component: 'umb-input-multi-url', -}; - -export default meta; -type Story = StoryObj; - -export const Overview: Story = { - args: {}, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/link-picker-modal/link-picker-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/link-picker-modal/link-picker-modal.stories.ts deleted file mode 100644 index 48afaddc19..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/link-picker-modal/link-picker-modal.stories.ts +++ /dev/null @@ -1,19 +0,0 @@ -import '../../core/components/body-layout/body-layout.element.js'; -import './link-picker-modal.element.js'; - -import type { UmbLinkPickerModalElement } from './link-picker-modal.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'API/Modals/Layouts/Link Picker', - component: 'umb-link-picker-modal', - id: 'umb-link-picker-modal', -} as Meta; - -export const Overview: StoryFn = () => html` - - -`; diff --git a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.stories.ts deleted file mode 100644 index c14f693351..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/multi-url-picker/property-editor/property-editor-ui-multi-url-picker.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUIMultiUrlPickerElement } from './property-editor-ui-multi-url-picker.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-multi-url-picker.element.js'; - -export default { - title: 'Property Editor UIs/Multi Url Picker', - component: 'umb-property-editor-ui-multi-url-picker', - id: 'umb-property-editor-ui-multi-url-picker', -} as Meta; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/performance-profiling/dashboard-performance-profiling.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/performance-profiling/dashboard-performance-profiling.stories.ts deleted file mode 100644 index c16a893d39..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/performance-profiling/dashboard-performance-profiling.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbDashboardPerformanceProfilingElement } from './dashboard-performance-profiling.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './dashboard-performance-profiling.element.js'; - -export default { - title: 'Dashboards/Performance Profiling', - component: 'umb-dashboard-performance-profiling', - id: 'umb-dashboard-performance-profiling', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/accepted-types/property-editor-ui-accepted-upload-types.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/accepted-types/property-editor-ui-accepted-upload-types.stories.ts index 49873abde8..83f4a6f85a 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/accepted-types/property-editor-ui-accepted-upload-types.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/accepted-types/property-editor-ui-accepted-upload-types.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-accepted-upload-types.element.js'; export default { - title: 'Property Editor UIs/Accepted Upload Types', + title: 'Extension Type/Property Editor UI/Accepted Upload Types', component: 'umb-property-editor-ui-accepted-upload-types', id: 'umb-property-editor-ui-accepted-upload-types', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/checkbox-list/components/input-checkbox-list/input-checkbox-list.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/checkbox-list/components/input-checkbox-list/input-checkbox-list.stories.ts index c8051d5022..836e914ae7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/checkbox-list/components/input-checkbox-list/input-checkbox-list.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/checkbox-list/components/input-checkbox-list/input-checkbox-list.stories.ts @@ -1,16 +1,17 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-checkbox-list.element.js'; import type { UmbInputCheckboxListElement } from './input-checkbox-list.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; + +import './input-checkbox-list.element.js'; const meta: Meta = { - title: 'Components/Inputs/Checkbox List', + title: 'Generic Components/Inputs/Checkbox List', component: 'umb-input-checkbox-list', }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: { list: [ { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/checkbox-list/property-editor-ui-checkbox-list.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/checkbox-list/property-editor-ui-checkbox-list.stories.ts index 828182ef1c..ac58905f2e 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/checkbox-list/property-editor-ui-checkbox-list.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/checkbox-list/property-editor-ui-checkbox-list.stories.ts @@ -1,15 +1,26 @@ import type { UmbPropertyEditorUICheckboxListElement } from './property-editor-ui-checkbox-list.element.js'; import type { Meta, StoryFn } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; +import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import './property-editor-ui-checkbox-list.element.js'; export default { - title: 'Property Editor UIs/Checkbox List', + title: 'Extension Type/Property Editor UI/Checkbox List', component: 'umb-property-editor-ui-checkbox-list', id: 'umb-property-editor-ui-checkbox-list', } as Meta; -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; +const config = new UmbPropertyEditorConfigCollection([ + { + alias: 'items', + value: [ + { name: 'Option 1', value: 'option1' }, + { name: 'Option 2', value: 'option2' }, + { name: 'Option 3', value: 'option3' }, + ], + }, +]); + +export const Docs: StoryFn = () => + html``; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/bulk-action-permissions/permissions.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/bulk-action-permissions/permissions.stories.ts index f21d4971b3..6f6d5d42c1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/bulk-action-permissions/permissions.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/bulk-action-permissions/permissions.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './permissions.element.js'; export default { - title: 'Property Editor UIs/Collection Bulk Action Permissions', + title: 'Extension Type/Property Editor UI/Collection Bulk Action Permissions', component: 'umb-property-editor-ui-collection-permissions', id: 'umb-property-editor-ui-collection-permissions', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/column/column-configuration.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/column/column-configuration.stories.ts index c0b1367102..c10ed2c5e4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/column/column-configuration.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/column/column-configuration.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './column-configuration.element.js'; export default { - title: 'Property Editor UIs/Collection Column Configuration', + title: 'Extension Type/Property Editor UI/Collection Column Configuration', component: 'umb-property-editor-ui-collection-column-configuration', id: 'umb-property-editor-ui-collection-column-configuration', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/layout/layout-configuration.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/layout/layout-configuration.stories.ts index 4c81463f31..b96aaba156 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/layout/layout-configuration.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/layout/layout-configuration.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './layout-configuration.element.js'; export default { - title: 'Property Editor UIs/Collection Layout Configuration', + title: 'Extension Type/Property Editor UI/Collection Layout Configuration', component: 'umb-property-editor-ui-collection-layout-configuration', id: 'umb-property-editor-ui-collection-layout-configuration', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/order-by/order-by.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/order-by/order-by.stories.ts deleted file mode 100644 index 9fc2d5b0d2..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/config/order-by/order-by.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUICollectionOrderByElement } from './order-by.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './order-by.element.js'; - -export default { - title: 'Property Editor UIs/Collection Order By', - component: 'umb-property-editor-ui-collection-order-by', - id: 'umb-property-editor-ui-collection-order-by', -} as Meta; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/property-editor-ui-collection-view.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/property-editor-ui-collection-view.stories.ts deleted file mode 100644 index c581e73d56..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/collection/property-editor-ui-collection-view.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUICollectionElement } from './property-editor-ui-collection.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-collection.element.js'; - -export default { - title: 'Property Editor UIs/Collection', - component: 'umb-property-editor-ui-collection', - id: 'umb-property-editor-ui-collection', -} as Meta; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/property-editor-ui-color-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/property-editor-ui-color-picker.stories.ts deleted file mode 100644 index 5dca0e5e1d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/color-picker/property-editor-ui-color-picker.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUIColorPickerElement } from './property-editor-ui-color-picker.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-color-picker.element.js'; - -export default { - title: 'Property Editor UIs/Color Picker', - component: 'umb-property-editor-ui-color-picker', - id: 'umb-property-editor-ui-color-picker', -} as Meta; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.stories.ts deleted file mode 100644 index 7510aac743..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/components/input-content/input-content.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-content.element.js'; -import type { UmbInputContentElement } from './input-content.element.js'; - -const meta: Meta = { - title: 'Components/Inputs/Content', - component: 'umb-input-content', -}; - -export default meta; -type Story = StoryObj; - -export const Overview: Story = { - args: {}, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-content/property-editor-ui-content-picker-source.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-content/property-editor-ui-content-picker-source.stories.ts index ca5f6a086e..0fe0f60239 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-content/property-editor-ui-content-picker-source.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/config/source-content/property-editor-ui-content-picker-source.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-content-picker-source.element.js'; export default { - title: 'Property Editor UIs/Content Picker Start Node', + title: 'Extension Type/Property Editor UI/Content Picker/Content Picker Start Node', component: 'umb-property-editor-ui-content-picker-source', id: 'umb-property-editor-ui-content-picker-source', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.stories.ts index ed1c7a3648..c4e25a5f81 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/content-picker/property-editor-ui-content-picker.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-content-picker.element.js'; export default { - title: 'Property Editor UIs/Content Picker', + title: 'Extension Type/Property Editor UI/Content Picker/Content Picker', component: 'umb-property-editor-ui-content-picker', id: 'umb-property-editor-ui-content-picker', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/date-picker/property-editor-ui-date-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/date-picker/property-editor-ui-date-picker.stories.ts index 2f4f6ddf8f..eff6bcaf32 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/date-picker/property-editor-ui-date-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/date-picker/property-editor-ui-date-picker.stories.ts @@ -6,7 +6,7 @@ import './property-editor-ui-date-picker.element.js'; import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; export default { - title: 'Property Editor UIs/Date Picker', + title: 'Extension Type/Property Editor UI/Date Picker', component: 'umb-property-editor-ui-date-picker', id: 'umb-property-editor-ui-date-picker', args: { @@ -22,7 +22,7 @@ export default { const Template: StoryFn = ({ config, value }) => html``; -export const Overview = Template.bind({}); +export const Docs = Template.bind({}); export const WithDateValue = Template.bind({}); WithDateValue.args = { diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/dimensions/property-editor-ui-dimensions.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/dimensions/property-editor-ui-dimensions.stories.ts index aa1ddb7aeb..45715d03ea 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/dimensions/property-editor-ui-dimensions.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/dimensions/property-editor-ui-dimensions.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-dimensions.element.js'; export default { - title: 'Property Editor UIs/Dimensions', + title: 'Extension Type/Property Editor UI/Dimensions', component: 'umb-property-editor-ui-dimensions', id: 'umb-property-editor-ui-dimensions', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/dropdown/property-editor-ui-dropdown.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/dropdown/property-editor-ui-dropdown.stories.ts index 9d0be36c2b..a939403182 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/dropdown/property-editor-ui-dropdown.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/dropdown/property-editor-ui-dropdown.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-dropdown.element.js'; export default { - title: 'Property Editor UIs/Dropdown', + title: 'Extension Type/Property Editor UI/Dropdown', component: 'umb-property-editor-ui-dropdown', id: 'umb-property-editor-ui-dropdown', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/eye-dropper/property-editor-ui-eye-dropper.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/eye-dropper/property-editor-ui-eye-dropper.stories.ts index 5dda76c7b3..cc44c9e273 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/eye-dropper/property-editor-ui-eye-dropper.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/eye-dropper/property-editor-ui-eye-dropper.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-eye-dropper.element.js'; export default { - title: 'Property Editor UIs/Eye Dropper', + title: 'Extension Type/Property Editor UI/Eye Dropper', component: 'umb-property-editor-ui-eye-dropper', id: 'umb-property-editor-ui-eye-dropper', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.stories.ts index e1dd406dba..035e41eb9c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/icon-picker/property-editor-ui-icon-picker.stories.ts @@ -5,17 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-icon-picker.element.js'; export default { - title: 'Property Editor UIs/Icon Picker', + title: 'Extension Type/Property Editor UI/Icon Picker', component: 'umb-property-editor-ui-icon-picker', id: 'umb-property-editor-ui-icon-picker', } as Meta; -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; -AAAOverview.decorators = [ - (story) => - html`
- ${story()} -
`, -]; +export const Docs: StoryFn = () => + html``; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/label/property-editor-ui-label.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/label/property-editor-ui-label.stories.ts deleted file mode 100644 index 263deb2453..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/label/property-editor-ui-label.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbPropertyEditorUILabelElement } from './property-editor-ui-label.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './property-editor-ui-label.element.js'; - -export default { - title: 'Property Editor UIs/Label', - component: 'umb-property-editor-ui-label', - id: 'umb-property-editor-ui-label', -} as Meta; - -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/multiple-text-string/property-editor-ui-multiple-text-string.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/multiple-text-string/property-editor-ui-multiple-text-string.stories.ts index 9bdf4c5abd..7952be4e58 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/multiple-text-string/property-editor-ui-multiple-text-string.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/multiple-text-string/property-editor-ui-multiple-text-string.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-multiple-text-string.element.js'; export default { - title: 'Property Editor UIs/Multiple Text String', + title: 'Extension Type/Property Editor UI/Multiple Text String', component: 'umb-property-editor-ui-multiple-text-string', id: 'umb-property-editor-ui-multiple-text-string', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/number-range/property-editor-ui-number-range.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/number-range/property-editor-ui-number-range.stories.ts index 984e0b5fcc..2dcc406759 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/number-range/property-editor-ui-number-range.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/number-range/property-editor-ui-number-range.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-number-range.element.js'; export default { - title: 'Property Editor UIs/Number Range', + title: 'Extension Type/Property Editor UI/Number Range', component: 'umb-property-editor-ui-number-range', id: 'umb-property-editor-ui-number-range', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/number/property-editor-ui-number.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/number/property-editor-ui-number.stories.ts index 693433985d..531f995b64 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/number/property-editor-ui-number.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/number/property-editor-ui-number.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-number.element.js'; export default { - title: 'Property Editor UIs/Number', + title: 'Extension Type/Property Editor UI/Number', component: 'umb-property-editor-ui-number', id: 'umb-property-editor-ui-number', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/order-direction/property-editor-ui-order-direction.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/order-direction/property-editor-ui-order-direction.stories.ts index ffc39c4656..64f315506b 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/order-direction/property-editor-ui-order-direction.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/order-direction/property-editor-ui-order-direction.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-order-direction.element.js'; export default { - title: 'Property Editor UIs/Order Direction', + title: 'Extension Type/Property Editor UI/Order Direction', component: 'umb-property-editor-ui-order-direction', id: 'umb-property-editor-ui-order-direction', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/overlay-size/property-editor-ui-overlay-size.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/overlay-size/property-editor-ui-overlay-size.stories.ts index 945025c35e..4779298582 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/overlay-size/property-editor-ui-overlay-size.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/overlay-size/property-editor-ui-overlay-size.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-overlay-size.element.js'; export default { - title: 'Property Editor UIs/Overlay Size', + title: 'Extension Type/Property Editor UI/Overlay Size', component: 'umb-property-editor-ui-overlay-size', id: 'umb-property-editor-ui-overlay-size', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/radio-button-list/property-editor-ui-radio-button-list.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/radio-button-list/property-editor-ui-radio-button-list.stories.ts index 91709a5c13..b08bed3c46 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/radio-button-list/property-editor-ui-radio-button-list.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/radio-button-list/property-editor-ui-radio-button-list.stories.ts @@ -1,15 +1,26 @@ import type { UmbPropertyEditorUIRadioButtonListElement } from './property-editor-ui-radio-button-list.element.js'; import type { Meta, StoryFn } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; +import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import './property-editor-ui-radio-button-list.element.js'; export default { - title: 'Property Editor UIs/Radio Button List', + title: 'Extension Type/Property Editor UI/Radio Button List', component: 'umb-property-editor-ui-radio-button-list', id: 'umb-property-editor-ui-radio-button-list', } as Meta; -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; +const config = new UmbPropertyEditorConfigCollection([ + { + alias: 'items', + value: [ + { name: 'Option 1', value: 'option1' }, + { name: 'Option 2', value: 'option2' }, + { name: 'Option 3', value: 'option3' }, + ], + }, +]); + +export const Docs: StoryFn = () => + html``; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/select/property-editor-ui-select.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/select/property-editor-ui-select.stories.ts index 7bc2ad6766..ada3fbb8ed 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/select/property-editor-ui-select.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/select/property-editor-ui-select.stories.ts @@ -1,15 +1,26 @@ import type { UmbPropertyEditorUISelectElement } from './property-editor-ui-select.element.js'; import type { Meta, StoryFn } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; +import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import './property-editor-ui-select.element.js'; export default { - title: 'Property Editor UIs/Select', + title: 'Extension Type/Property Editor UI/Select', component: 'umb-property-editor-ui-select', id: 'umb-property-editor-ui-select', } as Meta; -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; +const config = new UmbPropertyEditorConfigCollection([ + { + alias: 'items', + value: [ + { name: 'Option 1', value: 'option1' }, + { name: 'Option 2', value: 'option2' }, + { name: 'Option 3', value: 'option3' }, + ], + }, +]); + +export const Docs: StoryFn = () => + html``; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/slider/property-editor-ui-slider.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/slider/property-editor-ui-slider.stories.ts index ee5c7d3675..b5a721a92c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/slider/property-editor-ui-slider.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/slider/property-editor-ui-slider.stories.ts @@ -1,19 +1,26 @@ import type { UmbPropertyEditorUISliderElement } from './property-editor-ui-slider.element.js'; import type { Meta, StoryFn } from '@storybook/web-components-vite'; import { html } from '@umbraco-cms/backoffice/external/lit'; +import { UmbPropertyEditorConfigCollection } from '@umbraco-cms/backoffice/property-editor'; import './property-editor-ui-slider.element.js'; export default { - title: 'Property Editor UIs/Slider', + title: 'Extension Type/Property Editor UI/Slider', component: 'umb-property-editor-ui-slider', id: 'umb-property-editor-ui-slider', } as Meta; -export const AAAOverview: StoryFn = () => - html``; -AAAOverview.storyName = 'Overview'; +const config = new UmbPropertyEditorConfigCollection([ + { + alias: 'maxVal', + value: 100, + }, + { + alias: 'step', + value: 10, + }, +]); + +export const Docs: StoryFn = () => + html``; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.stories.ts index 73d5dbc8bf..f880c73a2c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/text-box/property-editor-ui-text-box.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-text-box.element.js'; export default { - title: 'Property Editor UIs/Text Box', + title: 'Extension Type/Property Editor UI/Text Box', component: 'umb-property-editor-ui-text-box', id: 'umb-property-editor-ui-text-box', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/textarea/property-editor-ui-textarea.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/textarea/property-editor-ui-textarea.stories.ts index 69d8257571..c0830ae790 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/textarea/property-editor-ui-textarea.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/textarea/property-editor-ui-textarea.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-textarea.element.js'; export default { - title: 'Property Editor UIs/Textarea', + title: 'Extension Type/Property Editor UI/Textarea', component: 'umb-property-editor-ui-textarea', id: 'umb-property-editor-ui-textarea', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/toggle/property-editor-ui-toggle.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/toggle/property-editor-ui-toggle.stories.ts index 1f1023edd3..ae252baef8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/toggle/property-editor-ui-toggle.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/toggle/property-editor-ui-toggle.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-toggle.element.js'; export default { - title: 'Property Editor UIs/Toggle', + title: 'Extension Type/Property Editor UI/Toggle', component: 'umb-property-editor-ui-toggle', id: 'umb-property-editor-ui-toggle', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/property-editors/value-type/property-editor-ui-value-type.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/property-editors/value-type/property-editor-ui-value-type.stories.ts index 92a17606b6..03282a51bc 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/property-editors/value-type/property-editor-ui-value-type.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/property-editors/value-type/property-editor-ui-value-type.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-value-type.element.js'; export default { - title: 'Property Editor UIs/Value Type', + title: 'Extension Type/Property Editor UI/Value Type', component: 'umb-property-editor-ui-value-type', id: 'umb-property-editor-ui-value-type', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/publish-cache/dashboard-published-status.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/publish-cache/dashboard-published-status.stories.ts deleted file mode 100644 index 67a06efe35..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/publish-cache/dashboard-published-status.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbDashboardPublishedStatusElement } from './dashboard-published-status.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './dashboard-published-status.element.js'; - -export default { - title: 'Dashboards/Published Status', - component: 'umb-dashboard-published-status', - id: 'umb-dashboard-published-status', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts b/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts index ecc7c2e453..602ea5fcf7 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/rte/components/rte-base.element.ts @@ -1,22 +1,23 @@ import type { UmbPropertyEditorRteValueType } from '../types.js'; import { UMB_BLOCK_RTE_PROPERTY_EDITOR_SCHEMA_ALIAS } from '../constants.js'; -import { property, state } from '@umbraco-cms/backoffice/external/lit'; import { observeMultiple } from '@umbraco-cms/backoffice/observable-api'; +import { property, state } from '@umbraco-cms/backoffice/external/lit'; import { UmbBlockRteEntriesContext, UmbBlockRteManagerContext } from '@umbraco-cms/backoffice/block-rte'; +import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; +import { + UmbFormControlMixin, + UmbValidationContext, + UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, +} from '@umbraco-cms/backoffice/validation'; import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; +import { UMB_CONTENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content'; import { UMB_PROPERTY_CONTEXT, UMB_PROPERTY_DATASET_CONTEXT } from '@umbraco-cms/backoffice/property'; import type { UmbBlockRteTypeModel } from '@umbraco-cms/backoffice/block-rte'; import type { UmbPropertyEditorUiElement, UmbPropertyEditorConfigCollection, } from '@umbraco-cms/backoffice/property-editor'; -import { - UMB_VALIDATION_EMPTY_LOCALIZATION_KEY, - UmbFormControlMixin, - UmbValidationContext, -} from '@umbraco-cms/backoffice/validation'; -import { UmbChangeEvent } from '@umbraco-cms/backoffice/event'; -import { UMB_CONTENT_WORKSPACE_CONTEXT } from '@umbraco-cms/backoffice/content'; +import type { StyleInfo } from '@umbraco-cms/backoffice/external/lit'; export abstract class UmbPropertyEditorUiRteElementBase extends UmbFormControlMixin(UmbLitElement) @@ -31,6 +32,12 @@ export abstract class UmbPropertyEditorUiRteElementBase this.#managerContext.setBlockTypes(blocks); this.#managerContext.setEditorConfiguration(config); + + const dimensions = config.getValueByAlias<{ width?: number; height?: number }>('dimensions'); + this._css = { + '--umb-rte-max-width': dimensions?.width ? `${dimensions.width}px` : '100%', + '--umb-rte-height': dimensions?.height ? `${dimensions.height}px` : 'unset', + }; } @property({ @@ -94,8 +101,12 @@ export abstract class UmbPropertyEditorUiRteElementBase @state() protected _config?: UmbPropertyEditorConfigCollection; + @state() + protected _css: StyleInfo = {}; + /** * @deprecated _value is depreacated, use `super.value` instead. + * @returns {UmbPropertyEditorRteValueType | undefined} The value of the property editor. */ @state() protected get _value(): UmbPropertyEditorRteValueType | undefined { diff --git a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/dashboard-examine-management.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/dashboard-examine-management.stories.ts deleted file mode 100644 index 227750e665..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/search/examine-management-dashboard/dashboard-examine-management.stories.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -//import type { UmbDashboardExamineManagementElement } from './dashboard-examine-management.element.js'; -import './dashboard-examine-management.element.js'; -import type { UmbDashboardExamineOverviewElement } from './views/section-view-examine-overview.js'; -import './views/section-view-examine-overview.js'; -import type { UmbDashboardExamineIndexElement } from './views/section-view-examine-indexers.js'; -import './views/section-view-examine-indexers.js'; -import type { UmbDashboardExamineSearcherElement } from './views/section-view-examine-searchers.js'; -import './views/section-view-examine-searchers.js'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'Dashboards/Examine Management', - component: 'umb-dashboard-examine-management', - id: 'umb-dashboard-examine-management', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; - -export const Index: StoryFn = () => - html` `; - -export const Searcher: StoryFn = () => - html` `; diff --git a/src/Umbraco.Web.UI.Client/src/packages/settings/welcome/settings-welcome-dashboard.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/settings/welcome/settings-welcome-dashboard.stories.ts deleted file mode 100644 index b75966f460..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/settings/welcome/settings-welcome-dashboard.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbSettingsWelcomeDashboardElement } from './settings-welcome-dashboard.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './settings-welcome-dashboard.element.js'; - -export default { - title: 'Dashboards/Settings Welcome', - component: 'umb-dashboard-settings-welcome', - id: 'umb-dashboard-settings-welcome', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/static-file/components/input-static-file/input-static-file.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/static-file/components/input-static-file/input-static-file.stories.ts deleted file mode 100644 index 95610d69a5..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/static-file/components/input-static-file/input-static-file.stories.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './input-static-file.element.js'; -import type { UmbInputStaticFileElement } from './input-static-file.element.js'; - -const meta: Meta = { - title: 'Components/Inputs/Static File', - component: 'umb-input-static-file', -}; - -export default meta; -type Story = StoryObj; -export const Overview: Story = { - args: {}, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/static-file/property-editors/static-file-picker/property-editor-ui-static-file-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/static-file/property-editors/static-file-picker/property-editor-ui-static-file-picker.stories.ts index 35e99889ee..4984a10784 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/static-file/property-editors/static-file-picker/property-editor-ui-static-file-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/static-file/property-editors/static-file-picker/property-editor-ui-static-file-picker.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-static-file-picker.element.js'; export default { - title: 'Property Editor UIs/Static File Picker', + title: 'Extension Type/Property Editor UI/Static File Picker', component: 'umb-property-editor-ui-static-file-picker', id: 'umb-property-editor-ui-static-file-picker', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.stories.ts deleted file mode 100644 index 80980e7f8f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/tags/components/tags-input/tags-input.stories.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './tags-input.element.js'; -import type { UmbTagsInputElement } from './tags-input.element.js'; - -const meta: Meta = { - title: 'Components/Inputs/Tags', - component: 'umb-tags-input', -}; - -export default meta; -type Story = StoryObj; - -export const Overview: Story = { - args: { - group: 'Fruits', - items: [], - }, -}; - -export const WithTags: Story = { - args: { - group: 'default', - items: ['Flour', 'Eggs', 'Butter', 'Sugar', 'Salt', 'Milk'], - }, -}; - -export const WithTags2: Story = { - args: { - group: 'default', - items: [ - 'Cranberry', - 'Kiwi', - 'Blueberries', - 'Watermelon', - 'Tomato', - 'Mango', - 'Strawberry', - 'Water Chestnut', - 'Papaya', - 'Orange Rind', - 'Olives', - 'Pear', - 'Sultana', - 'Mulberry', - 'Lychee', - 'Lemon', - 'Apple', - 'Banana', - 'Dragonfruit', - 'Blackberry', - 'Raspberry', - ], - }, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.stories.ts index b9e757f36f..7354823aa4 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tags/property-editors/tags/property-editor-ui-tags.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-tags.element.js'; export default { - title: 'Property Editor UIs/Tags', + title: 'Extension Type/Property Editor UI/Tags', component: 'umb-property-editor-ui-tags', id: 'umb-property-editor-ui-tags', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/telemetry/dashboard-telemetry.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/telemetry/dashboard-telemetry.stories.ts deleted file mode 100644 index 691de20778..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/telemetry/dashboard-telemetry.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { UmbDashboardTelemetryElement } from './dashboard-telemetry.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './dashboard-telemetry.element.js'; - -export default { - title: 'Dashboards/Telemetry', - component: 'umb-dashboard-telemetry', - id: 'umb-dashboard-telemetry', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.stories.ts deleted file mode 100644 index b237e95438..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/modals/templating-page-field-builder/components/template-field-dropdown-list/template-field-dropdown-list.stories.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './template-field-dropdown-list.element.js'; -import type { UmbTemplateFieldDropdownListElement } from './template-field-dropdown-list.element.js'; - -const meta: Meta = { - title: 'Components/Inputs/Field Dropdown List', - component: 'umb-template-field-dropdown-list', -}; - -export default meta; -type Story = StoryObj; - -export const Overview: Story = { - args: { - excludeMediaType: false, - }, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/global-components/stylesheet-input/stylesheet-input.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/global-components/stylesheet-input/stylesheet-input.stories.ts new file mode 100644 index 0000000000..fbda26c4a0 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/global-components/stylesheet-input/stylesheet-input.stories.ts @@ -0,0 +1,18 @@ +import type { UmbStylesheetInputElement } from './stylesheet-input.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './stylesheet-input.element.js'; + +const meta: Meta = { + title: 'Entity/Stylesheet/Components/Input Stylesheet', + component: 'umb-stylesheet-input', + render: () => html``, +}; + +export default meta; +type Story = StoryObj; + +export const Docs: Story = { + args: {}, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/property-editors/stylesheet-picker/property-editor-ui-stylesheet-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/property-editors/stylesheet-picker/property-editor-ui-stylesheet-picker.stories.ts index fb83b5a4f8..5304fcd1a8 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/property-editors/stylesheet-picker/property-editor-ui-stylesheet-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/templating/stylesheets/property-editors/stylesheet-picker/property-editor-ui-stylesheet-picker.stories.ts @@ -8,14 +8,14 @@ import './property-editor-ui-stylesheet-picker.element.js'; const dataTypeData = umbDataTypeMockDb.read('dt-richTextEditor') as unknown as UmbDataTypeDetailModel; export default { - title: 'Property Editor UIs/Stylesheet Picker', + title: 'Extension Type/Property Editor UI/Stylesheet Picker', component: 'umb-property-editor-ui-stylesheet-picker', id: 'umb-property-editor-ui-stylesheet-picker', } as Meta; -export const AAAOverview = ({ value }: any) => +export const Docs = ({ value }: any) => html``; -AAAOverview.storyName = 'Overview'; -AAAOverview.args = { + +Docs.args = { value: dataTypeData?.values?.find((x) => x.alias === 'stylesheets')?.value ?? [], }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/template-card/template-card.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/template-card/template-card.stories.ts deleted file mode 100644 index 110294e35d..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/templating/templates/global-components/template-card/template-card.stories.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { UmbTemplateCardElement } from './template-card.element.js'; -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; -import './template-card.element.js'; - -const meta: Meta = { - title: 'Components/Template Card', - component: 'umb-template-card', -}; - -export default meta; -type Story = StoryObj; - -export const Overview: Story = { - args: { - name: 'Template with a name ', - }, -}; - -export const Default: Story = { - args: { - name: 'Just a template', - }, -}; - -export const LongName: Story = { - args: { - name: 'Another template that someone gave a way way too long name without really thinking twice about it', - }, -}; - -export const TemplateCardList: Story = { - render: () => - html`
- - - - -
`, -}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts index 0fbe9f5480..c40c27012c 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/input-tiptap/input-tiptap.element.ts @@ -134,14 +134,6 @@ export class UmbInputTiptapElement extends UmbFormControlMixin('dimensions'); - if (dimensions?.width) { - this.setAttribute('style', `max-width: ${dimensions.width}px;`); - } - if (dimensions?.height) { - element.setAttribute('style', `height: ${dimensions.height}px;`); - } - const stylesheets = this.configuration?.getValueByAlias>('stylesheets'); if (stylesheets?.length) { stylesheets.forEach((stylesheet) => { @@ -247,6 +239,10 @@ export class UmbInputTiptapElement extends UmbFormControlMixin = { - title: 'Property Editor UIs/Tiptap', + title: 'Extension Type/Property Editor UI/Tiptap', component: 'umb-property-editor-ui-tiptap', id: 'umb-property-editor-ui-tiptap', args: { diff --git a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts index 4ef5cf573e..f0337968d1 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/ufm/components/ufm-render/ufm-render.element.ts @@ -50,6 +50,10 @@ export class UmbUfmRenderElement extends UmbLitElement { static override styles = [ UmbTextStyles, css` + :host { + position: relative; + } + * { max-width: 100%; word-wrap: break-word; diff --git a/src/Umbraco.Web.UI.Client/src/packages/umbraco-news/umbraco-news-dashboard.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/umbraco-news/umbraco-news-dashboard.stories.ts deleted file mode 100644 index 16071a328f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/umbraco-news/umbraco-news-dashboard.stories.ts +++ /dev/null @@ -1,15 +0,0 @@ -import './umbraco-news-dashboard.element.js'; - -import type { UmbUmbracoNewsDashboardElement } from './umbraco-news-dashboard.element.js'; -import type { Meta, StoryFn } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -export default { - title: 'Dashboards/Umbraco News', - component: 'umb-umbraco-news-dashboard', - id: 'umb-umbraco-news-dashboard', -} as Meta; - -export const AAAOverview: StoryFn = () => - html` `; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/external-login/modals/external-login-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/external-login/modals/external-login-modal.stories.ts deleted file mode 100644 index 3ff60a1b21..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/external-login/modals/external-login-modal.stories.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { UmbCurrentUserExternalLoginModalElement } from './external-login-modal.element.js'; -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; -import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; - -import './external-login-modal.element.js'; - -class UmbServerExtensionsHostElement extends UmbLitElement { - constructor() { - super(); - new UmbServerExtensionRegistrator(this, umbExtensionsRegistry).registerPublicExtensions(); - } - - override render() { - return html``; - } -} - -if (window.customElements.get('umb-server-extensions-host') === undefined) { - customElements.define('umb-server-extensions-host', UmbServerExtensionsHostElement); -} - -const meta: Meta = { - title: 'Current User/External Login/Configure External Login Providers', - component: 'umb-current-user-external-login-modal', - decorators: [ - (Story) => - html` - ${Story()} - `, - ], - parameters: { - layout: 'centered', - actions: { - disabled: true, - }, - }, -}; - -export default meta; - -type Story = StoryObj; - -export const Overview: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.stories.ts deleted file mode 100644 index 08ad165a29..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-disable/current-user-mfa-disable-modal.stories.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { UmbCurrentUserMfaDisableModalElement } from './current-user-mfa-disable-modal.element.js'; -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; - -import './current-user-mfa-disable-modal.element.js'; - -const meta: Meta = { - title: 'Current User/MFA/Disable MFA', - component: 'umb-current-user-mfa-disable-modal', - decorators: [(Story) => html`
${Story()}
`], - args: { - data: { - providerName: 'SMS', - displayName: 'SMS', - }, - }, - parameters: { - layout: 'centered', - actions: { - disabled: true, - }, - }, -}; - -export default meta; - -type Story = StoryObj; - -export const Overview: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.stories.ts deleted file mode 100644 index db233eb55e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa-enable/current-user-mfa-enable-modal.stories.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { UmbCurrentUserMfaEnableModalElement } from './current-user-mfa-enable-modal.element.js'; -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; -import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; - -import './current-user-mfa-enable-modal.element.js'; - -class UmbServerExtensionsHostElement extends UmbLitElement { - constructor() { - super(); - new UmbServerExtensionRegistrator(this, umbExtensionsRegistry).registerAllExtensions(); - } - - override render() { - return html``; - } -} - -if (window.customElements.get('umb-server-extensions-host') === undefined) { - customElements.define('umb-server-extensions-host', UmbServerExtensionsHostElement); -} - -const meta: Meta = { - title: 'Current User/MFA/Enable MFA', - component: 'umb-current-user-mfa-enable-modal', - decorators: [ - (Story) => - html` - ${Story()} - `, - ], - args: { - data: { - providerName: 'SMS', - displayName: 'SMS', - }, - }, - parameters: { - layout: 'centered', - actions: { - disabled: true, - }, - }, -}; - -export default meta; - -type Story = StoryObj; - -export const Overview: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa/current-user-mfa-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa/current-user-mfa-modal.stories.ts deleted file mode 100644 index f65e55abc9..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/current-user/modals/current-user-mfa/current-user-mfa-modal.stories.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { UmbCurrentUserMfaModalElement } from './current-user-mfa-modal.element.js'; -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; -import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; - -import './current-user-mfa-modal.element.js'; - -class UmbServerExtensionsHostElement extends UmbLitElement { - constructor() { - super(); - new UmbServerExtensionRegistrator(this, umbExtensionsRegistry).registerAllExtensions(); - } - - override render() { - return html``; - } -} - -if (window.customElements.get('umb-server-extensions-host') === undefined) { - customElements.define('umb-server-extensions-host', UmbServerExtensionsHostElement); -} - -const meta: Meta = { - title: 'Current User/MFA/Configure MFA Providers', - component: 'umb-current-user-mfa-modal', - decorators: [ - (Story) => - html` - ${Story()} - `, - ], - parameters: { - layout: 'centered', - actions: { - disabled: true, - }, - }, -}; - -export default meta; - -type Story = StoryObj; - -export const Overview: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/input-user-group/user-group-input.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/input-user-group/user-group-input.stories.ts index a69082f511..60cc60ae87 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/input-user-group/user-group-input.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/input-user-group/user-group-input.stories.ts @@ -1,29 +1,18 @@ import type { UmbUserGroupInputElement } from './user-group-input.element.js'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + import './user-group-input.element.js'; const meta: Meta = { - title: 'User Group/Components/User Group Input', + title: 'Entity/User Group/Components/User Group Input', component: 'umb-user-group-input', - argTypes: { - // modalType: { - // control: 'inline-radio', - // options: ['dialog', 'sidebar'], - // defaultValue: 'sidebar', - // description: 'The type of modal to use when selecting user groups', - // }, - // modalSize: { - // control: 'select', - // options: ['small', 'medium', 'large', 'full'], - // defaultValue: 'small', - // description: 'The size of the modal to use when selecting user groups, only applicable to sidebar not dialog', - // }, - }, + render: () => html``, }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: {}, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/user-group-ref/user-group-ref.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/user-group-ref/user-group-ref.stories.ts new file mode 100644 index 0000000000..c77c563440 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user-group/components/user-group-ref/user-group-ref.stories.ts @@ -0,0 +1,38 @@ +import type { UmbUserGroupRefElement } from './user-group-ref.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './user-group-ref.element.js'; + +const meta: Meta = { + title: 'Entity/User Group/Components/User Group Ref', + component: 'umb-user-group-ref', +}; + +export default meta; +type Story = StoryObj; + +export const Docs: Story = { + args: { + name: 'Administrators', + documentRootAccess: true, + mediaRootAccess: true, + }, +}; + +export const WithSlots: Story = { + args: { + name: 'Custom Data Type', + }, + render: (args) => html` + +
+ + + + + +
+
+ `, +}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.stories.ts index 42629ff171..9a2992ea35 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/components/user-input/user-input.stories.ts @@ -1,31 +1,18 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import './user-input.element.js'; import type { UmbUserInputElement } from './user-input.element.js'; +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from '@umbraco-cms/backoffice/external/lit'; + +import './user-input.element.js'; const meta: Meta = { - title: 'Components/Inputs/User', + title: 'Entity/User/Components/Input User', component: 'umb-user-input', - argTypes: { - /* - modalType: { - control: 'inline-radio', - options: ['dialog', 'sidebar'], - defaultValue: 'sidebar', - description: 'The type of modal to use when selecting users', - }, - modalSize: { - control: 'select', - options: ['small', 'medium', 'large', 'full'], - defaultValue: 'small', - description: 'The size of the modal to use when selecting users, only applicable to sidebar not dialog', - }, - */ - }, + render: () => html``, }; export default meta; type Story = StoryObj; -export const Overview: Story = { +export const Docs: Story = { args: {}, }; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/user-mfa/user-mfa-modal.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/user-mfa/user-mfa-modal.stories.ts deleted file mode 100644 index 9950faac72..0000000000 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/modals/user-mfa/user-mfa-modal.stories.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { UmbUserMfaModalElement } from './user-mfa-modal.element.js'; -import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html } from '@umbraco-cms/backoffice/external/lit'; -import { UmbServerExtensionRegistrator } from '@umbraco-cms/backoffice/extension-api'; -import { UmbLitElement } from '@umbraco-cms/backoffice/lit-element'; -import { umbExtensionsRegistry } from '@umbraco-cms/backoffice/extension-registry'; - -import './user-mfa-modal.element.js'; - -class UmbServerExtensionsHostElement extends UmbLitElement { - constructor() { - super(); - new UmbServerExtensionRegistrator(this, umbExtensionsRegistry).registerAllExtensions(); - } - - override render() { - return html``; - } -} - -if (window.customElements.get('umb-server-extensions-host') === undefined) { - customElements.define('umb-server-extensions-host', UmbServerExtensionsHostElement); -} - -const meta: Meta = { - title: 'User/MFA/Configure MFA Providers', - component: 'umb-user-mfa-modal', - decorators: [ - (Story) => - html` - ${Story()} - `, - ], - parameters: { - layout: 'centered', - actions: { - disabled: true, - }, - }, -}; - -export default meta; - -type Story = StoryObj; - -export const Overview: Story = {}; diff --git a/src/Umbraco.Web.UI.Client/src/packages/user/user/property-editor/user-picker/property-editor-ui-user-picker.stories.ts b/src/Umbraco.Web.UI.Client/src/packages/user/user/property-editor/user-picker/property-editor-ui-user-picker.stories.ts index 12039f72fb..0d193167bf 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/user/user/property-editor/user-picker/property-editor-ui-user-picker.stories.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/user/user/property-editor/user-picker/property-editor-ui-user-picker.stories.ts @@ -5,11 +5,10 @@ import { html } from '@umbraco-cms/backoffice/external/lit'; import './property-editor-ui-user-picker.element.js'; export default { - title: 'Property Editor UIs/User Picker', + title: 'Extension Type/Property Editor UI/User Picker', component: 'umb-property-editor-ui-user-picker', id: 'umb-property-editor-ui-user-picker', } as Meta; -export const AAAOverview: StoryFn = () => +export const Docs: StoryFn = () => html``; -AAAOverview.storyName = 'Overview'; diff --git a/src/Umbraco.Web.UI.Login/package-lock.json b/src/Umbraco.Web.UI.Login/package-lock.json index 9313ad8493..e13ddcd52b 100644 --- a/src/Umbraco.Web.UI.Login/package-lock.json +++ b/src/Umbraco.Web.UI.Login/package-lock.json @@ -3298,9 +3298,9 @@ } }, "node_modules/linkifyjs": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.1.tgz", - "integrity": "sha512-DRSlB9DKVW04c4SUdGvKK5FR6be45lTU9M76JnngqPeeGDqPwYc0zdUErtsNVMtxPXgUWV4HbXbnC4sNyBxkYg==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.2.tgz", + "integrity": "sha512-NT1CJtq3hHIreOianA8aSXn6Cw0JzYOuDQbOrSPe7gqFnCpKP++MQe3ODgO3oh2GJFORkAAdqredOa60z63GbA==", "dev": true, "license": "MIT", "peer": true diff --git a/templates/UmbracoProject/.template.config/template.json b/templates/UmbracoProject/.template.config/template.json index fefc0f7b26..9d7879efe9 100644 --- a/templates/UmbracoProject/.template.config/template.json +++ b/templates/UmbracoProject/.template.config/template.json @@ -98,7 +98,7 @@ }, { "condition": "(UmbracoRelease == 'LTS')", - "value": "13.9.1" + "value": "13.9.3" } ] } diff --git a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json index 905449f0db..d337791026 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json @@ -8,7 +8,7 @@ "hasInstallScript": true, "dependencies": { "@umbraco/json-models-builders": "^2.0.37", - "@umbraco/playwright-testhelpers": "^16.0.29", + "@umbraco/playwright-testhelpers": "^16.0.32", "camelize": "^1.0.0", "dotenv": "^16.3.1", "node-fetch": "^2.6.7" @@ -61,14 +61,15 @@ "version": "2.0.37", "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-2.0.37.tgz", "integrity": "sha512-97cRUrD+oeEno9I+qFjq7lWVS0+aDEK44lQQYWmVPAkCuAG1HMpBTEblS45CflrmLtgrDuZx68WIVVGpk9JzgQ==", + "license": "MIT", "dependencies": { "camelize": "^1.0.1" } }, "node_modules/@umbraco/playwright-testhelpers": { - "version": "16.0.29", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-16.0.29.tgz", - "integrity": "sha512-Zk0Ip2rZO0T15mbjQqu9SXI9TFckja/Y4KpHCRzwRgTbkDKr9pT7TENCcvegymVX2GpH6Cs9fu7OPvUABLK9cg==", + "version": "16.0.32", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-16.0.32.tgz", + "integrity": "sha512-HB/xHnu36XOyQjNnpSe1j9DoZ61tY7OvnkNQT73MhGcrhfnNdn/Hf+6nFN7gutUTcxn+L6COeXzexQclSjYr+g==", "dependencies": { "@umbraco/json-models-builders": "2.0.37", "node-fetch": "^2.6.7" diff --git a/tests/Umbraco.Tests.AcceptanceTest/package.json b/tests/Umbraco.Tests.AcceptanceTest/package.json index e2fe7731bc..4a143b243c 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package.json @@ -21,7 +21,7 @@ }, "dependencies": { "@umbraco/json-models-builders": "^2.0.37", - "@umbraco/playwright-testhelpers": "^16.0.29", + "@umbraco/playwright-testhelpers": "^16.0.32", "camelize": "^1.0.0", "dotenv": "^16.3.1", "node-fetch": "^2.6.7" diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/BlockGridArea.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/BlockGridArea.spec.ts index d92169baf2..c74f5cd821 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/BlockGridArea.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/BlockGridArea.spec.ts @@ -155,8 +155,7 @@ test('can create content with block grid area with row span', async ({umbracoApi await umbracoUi.content.doesBlockAreaContainRowSpan(firstElementTypeName, firstAreaName, rowSpan, 0); }); -// Remove fixme when this issue is fixed https://github.com/umbraco/Umbraco-CMS/issues/18639 -test.fixme('can create content with block grid area with min allowed', async ({umbracoApi, umbracoUi}) => { +test('can create content with block grid area with min allowed', async ({umbracoApi, umbracoUi}) => { // Arrange firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); const secondElementTypeId = await umbracoApi.documentType.createEmptyElementType(secondElementTypeName); @@ -169,7 +168,7 @@ test.fixme('can create content with block grid area with min allowed', async ({u await umbracoUi.content.goToContentWithName(contentName); // Act - await umbracoUi.content.clickAddBlockGridElementWithName(firstElementTypeName); + await umbracoUi.content.clickAddBlockGridElementWithName('content'); await umbracoUi.content.clickSelectBlockElementWithName(firstElementTypeName); await umbracoUi.content.clickLinkWithName(areaCreateLabel); await umbracoUi.content.clickSelectBlockElementInAreaWithName(secondElementTypeName); @@ -187,8 +186,7 @@ test.fixme('can create content with block grid area with min allowed', async ({u await umbracoApi.documentType.ensureNameNotExists(secondElementTypeName); }); -// Remove fixme when this issue is fixed https://github.com/umbraco/Umbraco-CMS/issues/18639 -test.fixme('can create content with block grid area with max allowed', async ({umbracoApi, umbracoUi}) => { +test('can create content with block grid area with max allowed', async ({umbracoApi, umbracoUi}) => { // Arrange firstElementTypeId = await umbracoApi.documentType.createEmptyElementType(firstElementTypeName); const secondElementTypeId = await umbracoApi.documentType.createEmptyElementType(secondElementTypeName); @@ -201,11 +199,11 @@ test.fixme('can create content with block grid area with max allowed', async ({u await umbracoUi.content.goToContentWithName(contentName); // Act - await umbracoUi.content.clickAddBlockGridElementWithName(firstElementTypeName); + await umbracoUi.content.clickAddBlockGridElementWithName('content'); await umbracoUi.content.clickSelectBlockElementWithName(firstElementTypeName); await umbracoUi.content.clickLinkWithName(areaCreateLabel); await umbracoUi.content.clickSelectBlockElementInAreaWithName(secondElementTypeName); - await umbracoUi.content.isTextWithExactNameVisible('Maximum 0 entries, 1 too many.'); + await umbracoUi.content.isTextWithExactNameVisible('Maximum 0 entries, you have entered 1 too many.'); await umbracoUi.content.clickSaveAndPublishButton(); await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished); await umbracoUi.content.removeBlockFromArea(firstElementTypeName, firstAreaName, secondElementTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/ComplexBlockGridTest.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/ComplexBlockGridTest.spec.ts index fba0b3acf2..4154aaf519 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/ComplexBlockGridTest.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/ComplexBlockGridTest.spec.ts @@ -95,7 +95,7 @@ test('can update property value nested in a block grid area with an RTE with a b await umbracoUi.content.clickAddBlockGridElementWithName(richTextEditorElementTypeName); await umbracoUi.content.clickExactLinkWithName(richTextEditorElementTypeName); await umbracoUi.content.clickInsertBlockButton(); - await umbracoUi.content.clickExactLinkWithName(blockListElementTypeName); + await umbracoUi.content.clickExactLinkWithName(blockListElementTypeName, true); await umbracoUi.content.clickAddBlockGridElementWithName(textStringElementTypeName); await umbracoUi.content.clickExactLinkWithName(textStringElementTypeName); // Enter text in the textstring block that won't match regex @@ -108,7 +108,7 @@ test('can update property value nested in a block grid area with an RTE with a b await umbracoUi.content.isFailedStateButtonVisible(); await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished, true, true); // Updates the textstring block with the correct value - await umbracoUi.content.clickBlockElementWithName(blockListElementTypeName); + await umbracoUi.content.clickBlockElementInRTEWithName(blockListElementTypeName); await umbracoUi.content.clickEditBlockListEntryWithName(textStringElementTypeName); await umbracoUi.content.enterPropertyValue(textStringElementDataTypeName, correctPropertyValue); await umbracoUi.content.clickUpdateButtonForModalWithElementTypeNameAndGroupName(textStringElementTypeName, textStringElementGroupName); @@ -124,7 +124,7 @@ test('can update property value nested in a block grid area with an RTE with a b await umbracoUi.reloadPage(); // Waits to make sure the page has loaded await umbracoUi.waitForTimeout(2000); - await umbracoUi.content.clickBlockElementWithName(blockListElementTypeName); + await umbracoUi.content.clickBlockElementInRTEWithName(blockListElementTypeName); // Needs to wait to make sure it has loaded await umbracoUi.waitForTimeout(2000); await umbracoUi.content.clickEditBlockListEntryWithName(textStringElementTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/ContentWithBlockGrid.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/ContentWithBlockGrid.spec.ts index 23742c85e5..0bf8876761 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/ContentWithBlockGrid.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/ContentWithBlockGrid.spec.ts @@ -227,8 +227,7 @@ test('can set the number of columns for the layout in the content', async ({umbr expect(layoutValue[0].columnSpan).toBe(gridColumns); }); -// TODO: Remove skip when front-end is ready. Currently, it is impossible to create content with blockgrid that has a setting model -test.skip('can add settings model for the block in the content', async ({umbracoApi, umbracoUi}) => { +test('can add settings model for the block in the content', async ({umbracoApi, umbracoUi}) => { // Arrange const contentBlockInputText = 'This is textstring'; const settingBlockInputText = 'This is textarea'; @@ -308,7 +307,112 @@ test('can add a block element with inline editing mode enabled', async ({umbraco expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); const contentData = await umbracoApi.document.getByName(contentName); expect(contentData.values[0].value.contentData[0].values[0].value).toEqual(inputText); - const blockListValue = contentData.values.find(item => item.editorAlias === "Umbraco.BlockGrid")?.value; - expect(blockListValue).toBeTruthy(); + const blockGridValue = contentData.values.find(item => item.editorAlias === "Umbraco.BlockGrid")?.value; + expect(blockGridValue).toBeTruthy(); await umbracoUi.content.doesPropertyContainValue(propertyInBlock, inputText); }); + +test('can add an invariant block element with an invariant RTE Tiptap in the content', async ({umbracoApi, umbracoUi}) => { + // Arrange + const inputText = 'This is block test'; + const customRTEDataTypeName = 'TestRTETiptap'; + const customElementTypeName = 'BlockGridWithRTEElement'; + const customRTEDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customRTEDataTypeName); + const customElementTypeId = await umbracoApi.documentType.createDefaultElementType(customElementTypeName, groupName, customRTEDataTypeName, customRTEDataTypeId); + const customDataTypeId = await umbracoApi.dataType.createBlockGridWithPermissions(customDataTypeName, customElementTypeId, true, true); + const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId); + await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.goToContentWithName(contentName); + await umbracoUi.content.clickAddBlockElementButton(); + await umbracoUi.content.clickTextButtonWithName(customElementTypeName); + await umbracoUi.content.enterRTETipTapEditor(inputText); + await umbracoUi.content.clickCreateModalButton(); + await umbracoUi.content.clickSaveButtonForContent(); + + // Assert + await umbracoUi.content.isSuccessStateVisibleForSaveButton(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value.contentData[0].values[0].value.markup).toContain(inputText); + const blockGridValue = contentData.values.find(item => item.editorAlias === "Umbraco.BlockGrid")?.value; + expect(blockGridValue).toBeTruthy(); + + // Clean + await umbracoApi.dataType.ensureNameNotExists(customRTEDataTypeName); + await umbracoApi.documentType.ensureNameNotExists(customElementTypeName); +}); + +test('can add a variant block element with variant RTE Tiptap in the content', async ({umbracoApi, umbracoUi}) => { + // Arrange + const inputText = 'This is block test'; + const customRTEDataTypeName = 'TestRTETiptap'; + const customElementTypeName = 'BlockGridWithRTEElement'; + await umbracoApi.language.createDanishLanguage(); + const customRTEDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customRTEDataTypeName); + const customElementTypeId = await umbracoApi.documentType.createDefaultElementType(customElementTypeName, groupName, customRTEDataTypeName, customRTEDataTypeId); + const customDataTypeId = await umbracoApi.dataType.createBlockGridWithPermissions(customDataTypeName, customElementTypeId, true, true); + const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId, 'testGroup', true); + await umbracoApi.document.createDefaultDocumentWithCulture(contentName, documentTypeId, 'en-US'); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.goToContentWithName(contentName); + await umbracoUi.content.clickAddBlockElementButton(); + await umbracoUi.content.clickTextButtonWithName(customElementTypeName); + await umbracoUi.content.enterRTETipTapEditor(inputText); + await umbracoUi.content.clickCreateModalButton(); + await umbracoUi.content.clickSaveButtonForContent(); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessStateVisibleForSaveButton(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value.contentData[0].values[0].value.markup).toContain(inputText); + const blockGridValue = contentData.values.find(item => item.editorAlias === "Umbraco.BlockGrid")?.value; + expect(blockGridValue).toBeTruthy(); + + // Clean + await umbracoApi.dataType.ensureNameNotExists(customRTEDataTypeName); + await umbracoApi.documentType.ensureNameNotExists(customElementTypeName); + await umbracoApi.language.ensureNameNotExists('Danish'); +}); + +test('can add a variant block element with invariant RTE Tiptap in the content', async ({umbracoApi, umbracoUi}) => { + // Arrange + const inputText = 'This is block test'; + const customRTEDataTypeName = 'TestRTETiptap'; + const customElementTypeName = 'BlockGridWithRTEElement'; + await umbracoApi.language.createDanishLanguage(); + const customRTEDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customRTEDataTypeName); + const customElementTypeId = await umbracoApi.documentType.createDefaultElementType(customElementTypeName, groupName, customRTEDataTypeName, customRTEDataTypeId); + const customDataTypeId = await umbracoApi.dataType.createBlockGridWithPermissions(customDataTypeName, customElementTypeId, true, true); + const documentTypeId = await umbracoApi.documentType.createVariantDocumentTypeWithInvariantPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId, 'testGroup', true); + await umbracoApi.document.createDefaultDocumentWithCulture(contentName, documentTypeId, 'en-US'); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.goToContentWithName(contentName); + await umbracoUi.content.clickAddBlockElementButton(); + await umbracoUi.content.clickTextButtonWithName(customElementTypeName); + await umbracoUi.content.enterRTETipTapEditor(inputText); + await umbracoUi.content.clickCreateModalButton(); + await umbracoUi.content.clickSaveButtonForContent(); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessStateVisibleForSaveButton(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value.contentData[0].values[0].value.markup).toContain(inputText); + const blockGridValue = contentData.values.find(item => item.editorAlias === "Umbraco.BlockGrid")?.value; + expect(blockGridValue).toBeTruthy(); + + // Clean + await umbracoApi.dataType.ensureNameNotExists(customRTEDataTypeName); + await umbracoApi.documentType.ensureNameNotExists(customElementTypeName); + await umbracoApi.language.ensureNameNotExists('Danish'); +}); \ No newline at end of file diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/VariantBlockGrid.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/VariantBlockGrid.spec.ts index d1eb3ce3d7..57c0d11346 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/VariantBlockGrid.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockGrid/VariantBlockGrid.spec.ts @@ -80,7 +80,6 @@ test('can not create unsupported invariant document type with invariant block gr // Assert await umbracoUi.content.isFailedStateButtonVisible(); - await umbracoUi.content.isErrorNotificationVisible(); await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeFalsy(); }); @@ -101,7 +100,6 @@ test('can not create unsupported invariant document type with invariant block gr // Assert await umbracoUi.content.isFailedStateButtonVisible(); - await umbracoUi.content.isErrorNotificationVisible(); await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeFalsy(); }); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockList/ContentWithBlockList.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockList/ContentWithBlockList.spec.ts index 8626684d54..49ba06fed3 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockList/ContentWithBlockList.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockList/ContentWithBlockList.spec.ts @@ -1,4 +1,4 @@ -import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; import {expect} from "@playwright/test"; const contentName = 'TestContent'; @@ -178,8 +178,7 @@ test('can set the label of block element in the content', async ({umbracoApi, um await umbracoUi.content.doesBlockElementHaveName(blockLabel); }); -// TODO: Remove skip when front-end is ready. Currently, it is impossible to create content with blocklist that has a setting model -test.skip('can add settings model for the block in the content', async ({umbracoApi, umbracoUi}) => { +test('can add settings model for the block in the content', async ({umbracoApi, umbracoUi}) => { // Arrange const contentBlockInputText = 'This is textstring'; const settingBlockInputText = 'This is textarea'; @@ -260,3 +259,108 @@ test('can add a block element with inline editing mode enabled', async ({umbraco const blockListValue = contentData.values.find(item => item.editorAlias === "Umbraco.BlockList")?.value; expect(blockListValue).toBeTruthy(); }); + +test('can add an invariant block element with invariant RTE Tiptap in the content', async ({umbracoApi, umbracoUi}) => { + // Arrange + const inputText = 'This is block test'; + const customRTEDataTypeName = 'TestRTETiptap'; + const customElementTypeName = 'BlockListWithRTEElement'; + const customRTEDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customRTEDataTypeName); + const customElementTypeId = await umbracoApi.documentType.createDefaultElementType(customElementTypeName, groupName, customRTEDataTypeName, customRTEDataTypeId); + const customDataTypeId = await umbracoApi.dataType.createBlockListDataTypeWithABlock(customDataTypeName, customElementTypeId, true, true); + const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId); + await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.goToContentWithName(contentName); + await umbracoUi.content.clickAddBlockElementButton(); + await umbracoUi.content.clickTextButtonWithName(customElementTypeName); + await umbracoUi.content.enterRTETipTapEditor(inputText); + await umbracoUi.content.clickCreateModalButton(); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessStateVisibleForSaveButton(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value.contentData[0].values[0].value.markup).toContain(inputText); + const blockListValue = contentData.values.find(item => item.editorAlias === "Umbraco.BlockList")?.value; + expect(blockListValue).toBeTruthy(); + + // Clean + await umbracoApi.dataType.ensureNameNotExists(customRTEDataTypeName); + await umbracoApi.documentType.ensureNameNotExists(customElementTypeName); +}); + +test('can add a variant block element with variant RTE Tiptap in the content', async ({umbracoApi, umbracoUi}) => { + // Arrange + const inputText = 'This is block test'; + const customRTEDataTypeName = 'TestRTETiptap'; + const customElementTypeName = 'BlockListWithRTEElement'; + await umbracoApi.language.createDanishLanguage(); + const customRTEDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customRTEDataTypeName); + const customElementTypeId = await umbracoApi.documentType.createDefaultElementType(customElementTypeName, groupName, customRTEDataTypeName, customRTEDataTypeId); + const customDataTypeId = await umbracoApi.dataType.createBlockListDataTypeWithABlock(customDataTypeName, customElementTypeId, true, true); + const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId, 'testGroup', true); + await umbracoApi.document.createDefaultDocumentWithCulture(contentName, documentTypeId, 'en-US'); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.goToContentWithName(contentName); + await umbracoUi.content.clickAddBlockElementButton(); + await umbracoUi.content.clickTextButtonWithName(customElementTypeName); + await umbracoUi.content.enterRTETipTapEditor(inputText); + await umbracoUi.content.clickCreateModalButton(); + await umbracoUi.content.clickSaveButtonForContent(); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessStateVisibleForSaveButton(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value.contentData[0].values[0].value.markup).toContain(inputText); + const blockListValue = contentData.values.find(item => item.editorAlias === "Umbraco.BlockList")?.value; + expect(blockListValue).toBeTruthy(); + + // Clean + await umbracoApi.dataType.ensureNameNotExists(customRTEDataTypeName); + await umbracoApi.documentType.ensureNameNotExists(customElementTypeName); + await umbracoApi.language.ensureNameNotExists('Danish'); +}); + +test('can add a variant block element with invariant RTE Tiptap in the content', async ({umbracoApi, umbracoUi}) => { + // Arrange + const inputText = 'This is block test'; + const customRTEDataTypeName = 'TestRTETiptap'; + const customElementTypeName = 'BlockListWithRTEElement'; + await umbracoApi.language.createDanishLanguage(); + const customRTEDataTypeId = await umbracoApi.dataType.createDefaultTiptapDataType(customRTEDataTypeName); + const customElementTypeId = await umbracoApi.documentType.createDefaultElementType(customElementTypeName, groupName, customRTEDataTypeName, customRTEDataTypeId); + const customDataTypeId = await umbracoApi.dataType.createBlockListDataTypeWithABlock(customDataTypeName, customElementTypeId, true, true); + const documentTypeId = await umbracoApi.documentType.createVariantDocumentTypeWithInvariantPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId, 'testGroup', true); + await umbracoApi.document.createDefaultDocumentWithCulture(contentName, documentTypeId, 'en-US'); + await umbracoUi.goToBackOffice(); + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + + // Act + await umbracoUi.content.goToContentWithName(contentName); + await umbracoUi.content.clickAddBlockElementButton(); + await umbracoUi.content.clickTextButtonWithName(customElementTypeName); + await umbracoUi.content.enterRTETipTapEditor(inputText); + await umbracoUi.content.clickCreateModalButton(); + await umbracoUi.content.clickSaveButtonForContent(); + await umbracoUi.content.clickSaveButton(); + + // Assert + await umbracoUi.content.isSuccessStateVisibleForSaveButton(); + const contentData = await umbracoApi.document.getByName(contentName); + expect(contentData.values[0].value.contentData[0].values[0].value.markup).toContain(inputText); + const blockListValue = contentData.values.find(item => item.editorAlias === "Umbraco.BlockList")?.value; + expect(blockListValue).toBeTruthy(); + + // Clean + await umbracoApi.dataType.ensureNameNotExists(customRTEDataTypeName); + await umbracoApi.documentType.ensureNameNotExists(customElementTypeName); + await umbracoApi.language.ensureNameNotExists('Danish'); +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockList/VariantBlockList.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockList/VariantBlockList.spec.ts index a6f7c78730..63ff826e6b 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockList/VariantBlockList.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/BlockList/VariantBlockList.spec.ts @@ -80,7 +80,6 @@ test('can not create unsupported invariant document type with invariant block li // Assert await umbracoUi.content.isFailedStateButtonVisible(); - await umbracoUi.content.isErrorNotificationVisible(); await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeFalsy(); }); @@ -100,7 +99,6 @@ test('can not create unsupported invariant document type with invariant block li // Assert await umbracoUi.content.isFailedStateButtonVisible(); - await umbracoUi.content.isErrorNotificationVisible(); await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeFalsy(); }); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithContentPicker.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithContentPicker.spec.ts index 3eae342652..927e2cded4 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithContentPicker.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithContentPicker.spec.ts @@ -1,4 +1,4 @@ -import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; import {expect} from "@playwright/test"; const contentName = 'TestContent'; @@ -92,7 +92,7 @@ test('can open content picker in the content', async ({umbracoApi, umbracoUi}) = await umbracoApi.dataType.ensureNameNotExists(customDataTypeName); }); -test('can choose start node for the content picker in the content', async ({umbracoApi, umbracoUi}) => { +test('can create content with content picker without ignore start node', async ({umbracoApi, umbracoUi}) => { // Arrange const customDataTypeName = 'CustomContentPicker'; const childContentPickerDocumentTypeName = 'ChildDocumentTypeForContentPicker'; @@ -111,11 +111,11 @@ test('can choose start node for the content picker in the content', async ({umbr // Act await umbracoUi.content.goToContentWithName(contentName); - await umbracoUi.content.clickChooseButton(); + await umbracoUi.content.addContentPicker(childContentPickerName); + await umbracoUi.content.clickSaveAndPublishButton(); // Assert - await umbracoUi.content.isContentNameVisible(childContentPickerName); - await umbracoUi.content.isContentNameVisible(contentPickerName, false); + await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.published); // Clean await umbracoApi.dataType.ensureNameNotExists(customDataTypeName); @@ -123,7 +123,7 @@ test('can choose start node for the content picker in the content', async ({umbr await umbracoApi.documentType.ensureNameNotExists(childContentPickerDocumentTypeName); }); -test.skip('can ignore user start node for the content picker in the content', async ({umbracoApi, umbracoUi}) => { +test('can create content with content picker with ignore start node', async ({umbracoApi, umbracoUi}) => { // Arrange const customDataTypeName = 'CustomContentPicker'; const childContentPickerDocumentTypeName = 'ChildDocumentTypeForContentPicker'; @@ -142,11 +142,11 @@ test.skip('can ignore user start node for the content picker in the content', as // Act await umbracoUi.content.goToContentWithName(contentName); - await umbracoUi.content.clickChooseButton(); + await umbracoUi.content.addContentPicker(childContentPickerName); + await umbracoUi.content.clickSaveAndPublishButton(); // Assert - await umbracoUi.content.isContentNameVisible(childContentPickerName); - await umbracoUi.content.isContentNameVisible(contentPickerName); + await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.published); // Clean await umbracoApi.dataType.ensureNameNotExists(customDataTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithCustomDataType.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithCustomDataType.spec.ts index 896f3eff04..6323370e94 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithCustomDataType.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithCustomDataType.spec.ts @@ -107,8 +107,7 @@ test('can add decimal number to the decimal in the content section', async ({umb expect(contentData.values[0].value).toEqual(decimal); }); -// Skip this test as currently there is no code editor property editor available. -test.skip('can create content with the custom data type with code editor property editor', async ({umbracoApi, umbracoUi}) => { +test('can create content with the custom data type with code editor property editor', async ({umbracoApi, umbracoUi}) => { // Arrange customDataTypeName = 'Code Editor'; const customDataTypeId = await umbracoApi.dataType.createCodeEditorDataType(customDataTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithImageMediaPicker.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithImageMediaPicker.spec.ts index e55fb00f3e..b4bdc32674 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithImageMediaPicker.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithImageMediaPicker.spec.ts @@ -142,7 +142,8 @@ test.skip('image count can not be more than max amount set in image media picker // Act await umbracoUi.content.goToContentWithName(contentName); - await umbracoUi.content.clickChooseButtonAndSelectMediaWithName(mediaName); + await umbracoUi.content.clickChooseButton(); + await umbracoUi.content.clickMediaWithName(mediaName); await umbracoUi.content.clickSubmitButton(); await umbracoUi.content.clickSaveButton(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithMultiURLPicker.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithMultiURLPicker.spec.ts index 7f18baf83c..33d71b8531 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithMultiURLPicker.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithMultiURLPicker.spec.ts @@ -82,6 +82,7 @@ test('can publish content with the document link', async ({umbracoApi, umbracoUi await umbracoUi.content.clickAddMultiURLPickerButton(); await umbracoUi.content.clickDocumentLinkButton(); await umbracoUi.content.selectLinkByName(linkedDocumentName); + await umbracoUi.waitForTimeout(500); // Wait for the document link to be selected await umbracoUi.content.clickButtonWithName('Choose'); await umbracoUi.content.clickAddButton(); await umbracoUi.content.clickSaveAndPublishButton(); @@ -350,9 +351,7 @@ test.skip('cannot submit an empty link using spacebar', async ({umbracoApi, umbr await umbracoUi.content.isTextWithMessageVisible(ConstantHelper.validationMessages.emptyLinkPicker); }); -// TODO: Remove skip when the front-end ready. Currently it is impossible to link to unpublished document -// Issue link: https://github.com/umbraco/Umbraco-CMS/issues/17974 -test.skip('can create content with the link to an unpublished document', async ({umbracoApi, umbracoUi}) => { +test('can create content with the link to an unpublished document', async ({umbracoApi, umbracoUi}) => { // Arrange const expectedState = 'Draft'; const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithPropertyEditors.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithPropertyEditors.spec.ts deleted file mode 100644 index 46181dd242..0000000000 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithPropertyEditors.spec.ts +++ /dev/null @@ -1,92 +0,0 @@ -import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; -import {expect} from "@playwright/test"; - -const contentName = 'TestContent'; -const documentTypeName = 'TestDocumentTypeForContent'; - -test.beforeEach(async ({umbracoApi}) => { - await umbracoApi.documentType.ensureNameNotExists(documentTypeName); - await umbracoApi.document.ensureNameNotExists(contentName); -}); - -test.afterEach(async ({umbracoApi}) => { - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.documentType.ensureNameNotExists(documentTypeName); -}); - -// TODO: Skip this test as TinyMCE is replaced by Tiptap. This test should be updated. -test.skip('can create content with the Rich Text Editor datatype', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { - // Arrange - const dataTypeName = 'Richtext editor'; - const contentText = 'This is Rich Text Editor content!'; - const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); - await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); - await umbracoUi.goToBackOffice(); - await umbracoUi.content.goToSection(ConstantHelper.sections.content); - - // Act - await umbracoUi.content.clickActionsMenuAtRoot(); - await umbracoUi.content.clickCreateActionMenuOption(); - await umbracoUi.content.chooseDocumentType(documentTypeName); - await umbracoUi.content.enterContentName(contentName); - await umbracoUi.content.enterRichTextArea(contentText); - await umbracoUi.content.clickSaveAndPublishButton(); - - // Assert - await umbracoUi.content.isSuccessStateVisibleForSaveAndPublishButton(); - expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); - const contentData = await umbracoApi.document.getByName(contentName); - expect(contentData.values[0].value.markup).toEqual('

' + contentText + '

'); -}); - -// TODO: Remove skip when the front-end is ready. Currently it returns error when publishing a content -test.skip('can create content with the upload file datatype', async ({umbracoApi, umbracoUi}) => { - // Arrange - const dataTypeName = 'Upload File'; - const uploadFilePath = 'Umbraco.png'; - const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); - await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); - await umbracoUi.goToBackOffice(); - await umbracoUi.content.goToSection(ConstantHelper.sections.content); - - // Act - await umbracoUi.content.clickActionsMenuAtRoot(); - await umbracoUi.content.clickCreateActionMenuOption(); - await umbracoUi.content.chooseDocumentType(documentTypeName); - await umbracoUi.content.enterContentName(contentName); - await umbracoUi.content.uploadFile('./fixtures/mediaLibrary/' + uploadFilePath); - await umbracoUi.content.clickSaveAndPublishButton(); - - // Assert - await umbracoUi.content.isSuccessStateVisibleForSaveAndPublishButton(); - expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); - const contentData = await umbracoApi.document.getByName(contentName); - expect(contentData.values[0].value.src).toContainEqual(uploadFilePath); -}); - -// TODO: Remove skip and update the test when the front-end is ready. Currently the list of content is not displayed. -test.skip('can create content with the list view - content datatype', async ({umbracoApi, umbracoUi}) => { - // Arrange - const dataTypeName = 'List View - Content'; - const contentListViewName = 'TestListViewContent'; - const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); - const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataTypeData.id); - const contentPickerId = await umbracoApi.document.createDefaultDocument(contentListViewName, documentTypeId); - await umbracoUi.goToBackOffice(); - await umbracoUi.content.goToSection(ConstantHelper.sections.content); - - // Act - await umbracoUi.content.clickActionsMenuAtRoot(); - await umbracoUi.content.clickCreateActionMenuOption(); - await umbracoUi.content.chooseDocumentType(documentTypeName); - await umbracoUi.content.enterContentName(contentName); - // TODO: add step to interact with the list - await umbracoUi.content.clickSaveAndPublishButton(); - - // Assert - await umbracoUi.content.isSuccessStateVisibleForSaveAndPublishButton(); - expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); - - // Clean - await umbracoApi.document.delete(contentPickerId); -}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadArticle.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadArticle.spec.ts index 45ccef76cd..182d3ee83d 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadArticle.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadArticle.spec.ts @@ -88,8 +88,7 @@ for (const uploadFile of uploadFiles) { }); } -// TODO: Remove skip when the front-end is ready. Currently the uploaded file still displays after removing. -test.skip('can remove an article file in the content', async ({umbracoApi, umbracoUi}) => { +test('can remove an article file in the content', async ({umbracoApi, umbracoUi}) => { // Arrange const uploadFileName = 'Article.pdf'; const mimeType = 'application/pdf'; diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadAudio.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadAudio.spec.ts index 22774235e1..a8180c09e3 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadAudio.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadAudio.spec.ts @@ -89,8 +89,7 @@ for (const uploadFile of uploadFiles) { }); } -// TODO: Remove skip when the front-end is ready. Currently the uploaded file still displays after removing. -test.skip('can remove an audio file in the content', async ({umbracoApi, umbracoUi}) => { +test('can remove an audio file in the content', async ({umbracoApi, umbracoUi}) => { // Arrange const uploadFileName = 'Audio.mp3'; const mineType = 'audio/mpeg'; diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadFile.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadFile.spec.ts index fc619145e2..0a19ba7ff8 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadFile.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadFile.spec.ts @@ -87,8 +87,7 @@ for (const uploadFile of uploadFiles) { }); } -// TODO: Remove skip when the front-end is ready. Currently the uploaded file still displays after removing. -test.skip('can remove a text file in the content', async ({umbracoApi, umbracoUi}) => { +test('can remove a text file in the content', async ({umbracoApi, umbracoUi}) => { // Arrange const uploadFileName = 'File.txt'; const mineType = 'text/plain'; diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadVideo.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadVideo.spec.ts index 5caafc4356..8824220a4f 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadVideo.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/ContentWithUploadVideo.spec.ts @@ -77,6 +77,7 @@ for (const uploadVideo of uploadVideos) { // Act await umbracoUi.content.goToContentWithName(contentName); await umbracoUi.content.uploadFile(uploadVideoPath + uploadVideo.fileName); + await umbracoUi.waitForTimeout(500); await umbracoUi.content.clickSaveButton(); // Assert @@ -88,8 +89,7 @@ for (const uploadVideo of uploadVideos) { }); } -// TODO: Remove skip when the front-end is ready. Currently the uploaded video still displays after removing. -test.skip('can remove a mp4 file in the content', async ({umbracoApi, umbracoUi}) => { +test('can remove a mp4 file in the content', async ({umbracoApi, umbracoUi}) => { // Arrange const uploadFileName = 'Video.mp4'; const mineType = 'video/mp4'; diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/CultureAndHostnames.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/CultureAndHostnames.spec.ts index 80b302f3e2..cbeb2def15 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/CultureAndHostnames.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/CultureAndHostnames.spec.ts @@ -46,7 +46,7 @@ test('can add a culture', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { }); // Really flaky tests, only occurs on pipeline -test('can add a domain', async ({umbracoApi, umbracoUi}) => { +test.skip('can add a domain', async ({umbracoApi, umbracoUi}) => { // Act await umbracoUi.content.clickActionsMenuForContent(contentName); await umbracoUi.content.clickCultureAndHostnamesActionMenuOption(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/IssueWithScheduledPublishing.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/IssueWithScheduledPublishing.spec.ts index c2845760e5..b29250dd89 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/IssueWithScheduledPublishing.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/IssueWithScheduledPublishing.spec.ts @@ -18,8 +18,7 @@ test.afterEach(async ({umbracoApi}) => { await umbracoApi.language.ensureNameNotExists(languageName); }); -// https://github.com/umbraco/Umbraco-CMS/issues/18555 -test.skip('Can schedule publish after unselecting all languages', async ({umbracoUi}) => { +test('can schedule publish after unselecting all languages', async ({umbracoUi}) => { // Arrange await umbracoUi.goToBackOffice(); await umbracoUi.content.goToSection(ConstantHelper.sections.content); @@ -30,12 +29,12 @@ test.skip('Can schedule publish after unselecting all languages', async ({umbrac await umbracoUi.content.goToContentWithName('(' + contentName + ')'); await umbracoUi.content.enterContentName('Tester'); await umbracoUi.content.clickViewMoreOptionsButton(); - await umbracoUi.content.clickScheduleButton(); + await umbracoUi.content.clickSchedulePublishButton(); await umbracoUi.waitForTimeout(500); await umbracoUi.content.clickSelectAllCheckbox(); await umbracoUi.waitForTimeout(500); await umbracoUi.content.clickSelectAllCheckbox(); - await umbracoUi.content.clickButtonWithName(contentName); + await umbracoUi.content.clickSchedulePublishLanguageButton(languageName); // Assert await umbracoUi.content.doesSchedulePublishModalButtonContainDisabledTag(false); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RedirectManagement.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RedirectManagement.spec.ts index 197a882e4f..a840fd03ff 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RedirectManagement.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RedirectManagement.spec.ts @@ -5,27 +5,28 @@ const disableStatus = 'Disabled'; const enableStatus = 'Enabled'; let documentTypeId = ''; let contentId = ''; -const contentName = 'TestContent'; +const contentName = 'TestContentRedirectURL'; const documentTypeName = 'TestDocumentType'; const updatedContentName = 'UpdatedContentName'; +const rootDocumentName = 'RootDocument'; test.beforeEach(async ({umbracoApi, umbracoUi}) => { await umbracoApi.redirectManagement.setStatus(enableStatus); - await umbracoUi.goToBackOffice(); - // Create a content await umbracoApi.documentType.ensureNameNotExists(documentTypeName); documentTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeName); + await umbracoUi.goToBackOffice(); + // Create a published root document + const rootDocumentId = await umbracoApi.document.createDefaultDocument(rootDocumentName, documentTypeId); + await umbracoApi.document.publish(rootDocumentId); + // Create a published content contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - // Publish the content - await umbracoUi.content.goToSection(ConstantHelper.sections.content); - await umbracoUi.content.clickActionsMenuForContent(contentName); - await umbracoUi.content.clickPublishActionMenuOption(); - await umbracoUi.content.clickConfirmToPublishButton(); + await umbracoApi.document.publish(contentId); }); test.afterEach(async ({umbracoApi}) => { await umbracoApi.redirectManagement.setStatus(enableStatus); await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.document.ensureNameNotExists(rootDocumentName); await umbracoApi.documentType.ensureNameNotExists(documentTypeName); }); @@ -35,15 +36,15 @@ test('can disable URL tracker', async ({umbracoApi, umbracoUi}) => { await umbracoUi.redirectManagement.clickRedirectManagementTab(); await umbracoUi.redirectManagement.clickDisableURLTrackerButton(); await umbracoUi.redirectManagement.clickDisableButton(); - - // Assert - // Verify that if renaming a published page, there are no redirects have been made - // rename the published content + // Rename the published content await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); await umbracoUi.content.enterContentName(updatedContentName); await umbracoUi.content.clickSaveAndPublishButton(); - // verify that there is no redirects have been made + + // Assert + await umbracoUi.content.isSuccessStateVisibleForSaveAndPublishButton(); + // Verify that there is no redirects have been made const contentUrl = await umbracoApi.document.getDocumentUrl(contentId); await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.redirectManagement.clickRedirectManagementTab(); @@ -53,8 +54,7 @@ test('can disable URL tracker', async ({umbracoApi, umbracoUi}) => { expect(statusData.status).toBe(disableStatus); }); -// TODO: Remove skip when the frond-end is ready. Currently there is no redirect have been made after renaming a published page -test.skip('can re-enable URL tracker', async ({umbracoApi, umbracoUi}) => { +test('can re-enable URL tracker', async ({umbracoApi, umbracoUi}) => { // Arrange await umbracoApi.redirectManagement.setStatus(disableStatus); @@ -62,15 +62,15 @@ test.skip('can re-enable URL tracker', async ({umbracoApi, umbracoUi}) => { await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.redirectManagement.clickRedirectManagementTab(); await umbracoUi.redirectManagement.clickEnableURLTrackerButton(); - - // Assert - // Verify that if renaming a published page, there are one redirects have been made - // rename the published content + // Rename the published content await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); await umbracoUi.content.enterContentName(updatedContentName); await umbracoUi.content.clickSaveAndPublishButton(); - // verify that there is one redirects have been made + + // Assert + await umbracoUi.content.isSuccessStateVisibleForSaveAndPublishButton(); + // Verify that there is one redirects have been made const contentUrl = await umbracoApi.document.getDocumentUrl(contentId); await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.redirectManagement.clickRedirectManagementTab(); @@ -80,11 +80,15 @@ test.skip('can re-enable URL tracker', async ({umbracoApi, umbracoUi}) => { expect(statusData.status).toBe(enableStatus); }); -// TODO: Remove skip and update this when the front-end is ready. Currently it always return "No redirects matching this search criteria" when searching. -test.skip('can search for original URL', async ({umbracoUi}) => { +test('can search for original URL', async ({umbracoApi, umbracoUi}) => { // Arrange - const searchKeyword = '/test-content/'; - // TODO: rename content to add an item in the redirect url management + const searchKeyword = 'redirect'; + // Rename the published content + await umbracoUi.content.goToSection(ConstantHelper.sections.content); + await umbracoUi.content.goToContentWithName(contentName); + await umbracoUi.content.enterContentName(updatedContentName); + await umbracoUi.content.clickSaveAndPublishButton(); + await umbracoUi.content.isSuccessStateVisibleForSaveAndPublishButton(); // Act await umbracoUi.content.goToSection(ConstantHelper.sections.content); @@ -93,24 +97,27 @@ test.skip('can search for original URL', async ({umbracoUi}) => { await umbracoUi.redirectManagement.clickSearchButton(); // Assert - // TODO: verify the search result + await umbracoUi.redirectManagement.doesRedirectManagementRowsHaveCount(1); + const contentUrl = await umbracoApi.document.getDocumentUrl(contentId); + await umbracoUi.redirectManagement.isTextWithExactNameVisible(contentUrl); }); -// TODO: Remove skip when the frond-end is ready. Currently there is no redirect have been made after renaming a published page -test.skip('can delete a redirect', async ({umbracoApi, umbracoUi}) => { +test('can delete a redirect', async ({umbracoApi, umbracoUi}) => { // Arrange // Rename the published content await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.content.goToContentWithName(contentName); await umbracoUi.content.enterContentName(updatedContentName); await umbracoUi.content.clickSaveAndPublishButton(); + await umbracoUi.content.isSuccessStateVisibleForSaveAndPublishButton(); + const contentUrl = await umbracoApi.document.getDocumentUrl(contentId); // Act await umbracoUi.content.goToSection(ConstantHelper.sections.content); await umbracoUi.redirectManagement.clickRedirectManagementTab(); + await umbracoUi.redirectManagement.isTextWithExactNameVisible(contentUrl); await umbracoUi.redirectManagement.deleteFirstRedirectURL(); // Assert - const contentUrl = await umbracoApi.document.getDocumentUrl(contentId); await umbracoUi.redirectManagement.isTextWithExactNameVisible(contentUrl, false); }); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/ContentWithTiptap.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/ContentWithTiptap.spec.ts index 5feb94ba38..1b83e2a2f6 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/ContentWithTiptap.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/ContentWithTiptap.spec.ts @@ -1,4 +1,4 @@ -import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; import {expect} from "@playwright/test"; const contentName = 'TestContent'; @@ -85,131 +85,3 @@ test('can publish content with RTE Tiptap property editor', async ({umbracoApi, expect(contentData.variants[0].state).toBe(expectedState); expect(contentData.values[0].value.markup).toEqual('

' + inputText + '

'); }); - -test('can add a media in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => { - // Arrange - const iconTitle = 'Media Picker'; - const imageName = 'Test Image For Content'; - await umbracoApi.media.ensureNameNotExists(imageName); - await umbracoApi.media.createDefaultMediaWithImage(imageName); - const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId); - await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); - await umbracoUi.content.goToSection(ConstantHelper.sections.content); - - // Act - await umbracoUi.content.goToContentWithName(contentName); - await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle); - // fix this - await umbracoUi.content.selectMediaWithName(imageName); - await umbracoUi.content.clickChooseModalButton(); - await umbracoUi.content.clickMediaCaptionAltTextModalSubmitButton(); - await umbracoUi.content.clickSaveButton(); - - // Assert - await umbracoUi.content.isSuccessStateVisibleForSaveButton(); - expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); - const contentData = await umbracoApi.document.getByName(contentName); - expect(contentData.values[0].value.markup).toContain(' { - // Arrange - const iconTitle = 'Embed'; - const videoURL = 'https://www.youtube.com/watch?v=Yu29dE-0OoI'; - const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId); - await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); - await umbracoUi.content.goToSection(ConstantHelper.sections.content); - - // Act - await umbracoUi.content.goToContentWithName(contentName); - await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle); - await umbracoUi.content.enterEmbeddedURL(videoURL); - await umbracoUi.content.clickEmbeddedRetrieveButton(); - await umbracoUi.content.waitForEmbeddedPreviewVisible(); - await umbracoUi.content.clickEmbeddedMediaModalConfirmButton(); - await umbracoUi.content.clickSaveButton(); - - // Assert - await umbracoUi.content.isSuccessStateVisibleForSaveButton(); - expect(await umbracoApi.document.doesNameExist(contentName)).toBeTruthy(); - const contentData = await umbracoApi.document.getByName(contentName); - expect(contentData.values[0].value.markup).toContain('data-embed-url'); - expect(contentData.values[0].value.markup).toContain(videoURL); -}); - -test('cannot submit an empty link in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => { - // Arrange - const iconTitle = 'Link'; - const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId); - await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); - await umbracoUi.content.goToSection(ConstantHelper.sections.content); - - // Act - await umbracoUi.content.goToContentWithName(contentName); - await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle); - await umbracoUi.content.clickManualLinkButton(); - await umbracoUi.content.enterLink(''); - await umbracoUi.content.enterAnchorOrQuerystring(''); - await umbracoUi.content.enterLinkTitle(''); - await umbracoUi.content.clickAddButton(); - - // Assert - await umbracoUi.content.isTextWithMessageVisible(ConstantHelper.validationMessages.emptyLinkPicker); -}); - -test('cannot submit an empty URL with an anchor or querystring in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => { - // Arrange - const iconTitle = 'Link'; - const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId); - await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoUi.goToBackOffice(); - await umbracoUi.content.goToSection(ConstantHelper.sections.content); - - // Act - await umbracoUi.content.goToContentWithName(contentName); - await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle); - await umbracoUi.content.clickManualLinkButton(); - await umbracoUi.content.enterLink(''); - await umbracoUi.content.enterAnchorOrQuerystring('#value'); - await umbracoUi.content.clickAddButton(); - - // Assert - await umbracoUi.content.isTextWithMessageVisible(ConstantHelper.validationMessages.emptyLinkPicker); -}); - -test('can insert a link to an unpublished document in RTE Tiptap property editor', async ({umbracoApi, umbracoUi}) => { - // Arrange - const iconTitle = 'Link'; - const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId); - await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - // Create a document to link - const documentTypeForLinkedDocumentName = 'TestDocumentType'; - const documentTypeForLinkedDocumentId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(documentTypeForLinkedDocumentName); - const linkedDocumentName = 'LinkedDocument'; - await umbracoApi.document.createDefaultDocument(linkedDocumentName, documentTypeForLinkedDocumentId); - await umbracoUi.goToBackOffice(); - await umbracoUi.content.goToSection(ConstantHelper.sections.content); - - // Act - await umbracoUi.content.goToContentWithName(contentName); - await umbracoUi.content.clickTipTapToolbarIconWithTitle(iconTitle); - await umbracoUi.content.clickDocumentLinkButton(); - await umbracoUi.content.selectLinkByName(linkedDocumentName); - await umbracoUi.content.clickButtonWithName('Choose'); - await umbracoUi.content.clickAddButton(); - await umbracoUi.content.clickSaveButton(); - - // Assert - await umbracoUi.content.waitForContentToBeCreated(); - - // Clean - await umbracoApi.documentType.ensureNameNotExists(documentTypeForLinkedDocumentName); - await umbracoApi.document.ensureNameNotExists(linkedDocumentName); -}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/TiptapToolbar.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/TiptapToolbar.spec.ts index dc4a77ffe9..9c61a24955 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/TiptapToolbar.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/TiptapToolbar.spec.ts @@ -1,4 +1,4 @@ -import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; import {expect} from "@playwright/test"; const contentName = 'TestContent'; @@ -137,6 +137,7 @@ test('can insert a link to an unpublished document in RTE Tiptap property editor await umbracoUi.content.clickDocumentLinkButton(); await umbracoUi.content.selectLinkByName(linkedDocumentName); await umbracoUi.content.clickButtonWithName('Choose'); + await umbracoUi.waitForTimeout(500); // Wait for the link to be inserted await umbracoUi.content.clickAddButton(); await umbracoUi.content.clickSaveButton(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/VariantTipTapBlocks.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/VariantTipTapBlocks.spec.ts index e52c3f502b..84dc1ed91c 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/VariantTipTapBlocks.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/RichTextEditor/VariantTipTapBlocks.spec.ts @@ -61,7 +61,7 @@ test('invariant document type with invariant tiptap RTE with invariant block wit await umbracoUi.content.isSuccessStateVisibleForSaveAndPublishButton(); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeTruthy(); await umbracoUi.reloadPage(); - await umbracoUi.content.clickBlockElementWithName(blockName); + await umbracoUi.content.clickBlockElementInRTEWithName(blockName); await umbracoUi.content.doesPropertyContainValue(textStringName, textStringText); }); @@ -80,7 +80,6 @@ test('can not create unsupported invariant document type with invariant tiptap R // Assert await umbracoUi.content.isFailedStateButtonVisible(); - await umbracoUi.content.isErrorNotificationVisible(); await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeFalsy(); }); @@ -101,7 +100,6 @@ test('can not create unsupported invariant document type with invariant tiptap R // Assert await umbracoUi.content.isFailedStateButtonVisible(); - await umbracoUi.content.isErrorNotificationVisible(); await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeFalsy(); }); @@ -128,7 +126,7 @@ test('variant document type with variant tiptap RTE with variant block with an v await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.published); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeTruthy(); await umbracoUi.reloadPage(); - await umbracoUi.content.clickBlockElementWithName(blockName); + await umbracoUi.content.clickBlockElementInRTEWithName(blockName); await umbracoUi.content.doesPropertyContainValue(textStringName, textStringText); }); @@ -154,7 +152,7 @@ test('variant document type with invariant tiptap RTE with variant block with an await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.published); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeTruthy(); await umbracoUi.reloadPage(); - await umbracoUi.content.clickBlockElementWithName(blockName); + await umbracoUi.content.clickBlockElementInRTEWithName(blockName); await umbracoUi.content.doesPropertyContainValue(textStringName, textStringText); }); @@ -180,6 +178,6 @@ test('variant document type with invariant tiptap RTE with variant block with an await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.published); expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeTruthy(); await umbracoUi.reloadPage(); - await umbracoUi.content.clickBlockElementWithName(blockName); + await umbracoUi.content.clickBlockElementInRTEWithName(blockName); await umbracoUi.content.doesPropertyContainValue(textStringName, textStringText); }); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/Block/BlockGridBlockAdvanced.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/Block/BlockGridBlockAdvanced.spec.ts index d05b35237c..be267b18ff 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/Block/BlockGridBlockAdvanced.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/Block/BlockGridBlockAdvanced.spec.ts @@ -42,7 +42,7 @@ test.skip('can remove a custom view from a block', async ({umbracoApi, umbracoUi await umbracoUi.dataType.goToBlockAdvancedTab(); }); -// TODO: Remove skip and update test when the front-end is ready. Currently stylesheets are saved as arrays +// TODO: Remove skip and update test when the front-end is ready. Currently it is not possible to add a custom stylesheet to a block test.skip('can remove a custom stylesheet from a block', async ({umbracoApi, umbracoUi}) => { // Arrange const stylesheetName = 'TestStylesheet.css' diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/BlockGridEditor.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/BlockGridEditor.spec.ts index e1c0b28fb3..f255bdc861 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/BlockGridEditor.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockGrid/BlockGridEditor.spec.ts @@ -392,5 +392,22 @@ test('can update grid columns in a block grid editor', async ({umbracoApi, umbra test.skip('can add a stylesheet a block grid editor', async ({umbracoApi, umbracoUi}) => { }); -test.skip('can remove a stylesheet in a block grid editor', async ({umbracoApi, umbracoUi}) => { +test('can remove a stylesheet in a block grid editor', async ({umbracoApi, umbracoUi}) => { + // Arrange + const stylesheetName = 'TestStylesheet.css'; + await umbracoApi.stylesheet.createDefaultStylesheet(stylesheetName); + await umbracoApi.dataType.createBlockGridWithLayoutStylesheet(blockGridEditorName, stylesheetName); + + // Act + await umbracoUi.dataType.goToDataType(blockGridEditorName); + await umbracoUi.dataType.clickRemoveStylesheetButton(stylesheetName); + await umbracoUi.dataType.clickConfirmRemoveButton(); + await umbracoUi.dataType.clickSaveButton(); + + // Assert + await umbracoUi.dataType.isSuccessStateVisibleForSaveButton(); + expect(await umbracoApi.dataType.doesBlockGridContainLayoutStylesheet(blockGridEditorName, stylesheetName)).toBeFalsy(); + + // Clean + await umbracoApi.stylesheet.ensureNameNotExists(stylesheetName); }); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockListEditor/BlockListBlocks.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockListEditor/BlockListBlocks.spec.ts index e2f5be0f5e..49f502c462 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockListEditor/BlockListBlocks.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/BlockListEditor/BlockListBlocks.spec.ts @@ -111,7 +111,7 @@ test('can open content model in a block', async ({umbracoApi, umbracoUi}) => { await umbracoUi.dataType.isElementWorkspaceOpenInBlock(elementTypeName); }); -// TODO: Skip this test as it is impossible to remove a content model +// Skip this test as it is impossible to remove a content model in front-end test.skip('can remove a content model from a block', async ({umbracoApi, umbracoUi}) => { // Arrange const textStringData = await umbracoApi.dataType.getByName(dataTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/ImageCropper.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/ImageCropper.spec.ts index a801abc0df..5583ac494d 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/ImageCropper.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/ImageCropper.spec.ts @@ -18,57 +18,64 @@ test.afterEach(async ({umbracoApi}) => { test('can add crop', async ({umbracoApi, umbracoUi}) => { // Arrange - const cropData = ['Test Label', 'Test Alias', 100, 50]; + const cropObject = {label: 'Test Label', alias: AliasHelper.toAlias('Test Label'), width: 100, height: 50}; await umbracoApi.dataType.createDefaultImageCropperDataType(customDataTypeName); await umbracoUi.dataType.goToDataType(customDataTypeName); // Act + await umbracoUi.dataType.clickCreateCropButton(); await umbracoUi.dataType.enterCropValues( - cropData[0].toString(), - cropData[1].toString(), - cropData[2].toString(), - cropData[3].toString() + cropObject.label, + cropObject.alias, + cropObject.width.toString(), + cropObject.height.toString() ); - await umbracoUi.dataType.clickAddCropButton(); + await umbracoUi.dataType.clickCreateCropButton(); await umbracoUi.dataType.clickSaveButton(); // Assert await umbracoUi.dataType.isSuccessStateVisibleForSaveButton(); - expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, cropData[0], cropData[1], cropData[2], cropData[3])).toBeTruthy(); + expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, cropObject.label, cropObject.alias, cropObject.width, cropObject.height)).toBeTruthy(); }); test('can edit crop', async ({umbracoApi, umbracoUi}) => { // Arrange - const cropData = ['Test Label', AliasHelper.toAlias('Test Label'), 100, 50]; - const updatedCropData = ['Updated Label', AliasHelper.toAlias('Updated Label'), 80, 30]; - await umbracoApi.dataType.createImageCropperDataTypeWithOneCrop(customDataTypeName, cropData[0], cropData[2], cropData[3]); + const cropObject = {label: 'Test Label', alias: AliasHelper.toAlias('Test Label'), width: 100, height: 50}; + const updatedCropObject = {label: 'Updated Label', alias: AliasHelper.toAlias('Updated Label'), width: 80, height: 30}; + + await umbracoApi.dataType.createImageCropperDataTypeWithOneCrop(customDataTypeName, cropObject.label, cropObject.width, cropObject.height); await umbracoUi.dataType.goToDataType(customDataTypeName); // Act - await umbracoUi.dataType.editCropByAlias(cropData[0]); - await umbracoUi.dataType.enterCropValues(updatedCropData[0], updatedCropData[1], updatedCropData[2].toString(), updatedCropData[3].toString()); - await umbracoUi.dataType.clickSaveCropButton(); + await umbracoUi.dataType.editCropByAlias(cropObject.alias); + await umbracoUi.dataType.enterCropValues( + updatedCropObject.label, + updatedCropObject.alias, + updatedCropObject.width.toString(), + updatedCropObject.height.toString() + ); + await umbracoUi.dataType.clickEditCropButton(); await umbracoUi.dataType.clickSaveButton(); // Assert await umbracoUi.dataType.isSuccessStateVisibleForSaveButton(); - expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, updatedCropData[0], updatedCropData[1], updatedCropData[2], updatedCropData[3])).toBeTruthy(); - expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, cropData[0], cropData[1], cropData[2], cropData[3])).toBeFalsy(); + expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, updatedCropObject.label, updatedCropObject.alias, updatedCropObject.width, updatedCropObject.height)).toBeTruthy(); + expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, cropObject.label, cropObject.alias, cropObject.width, cropObject.height)).toBeFalsy(); }); test('can delete crop', async ({umbracoApi, umbracoUi}) => { // Arrange - const cropData = ['Deleted Alias', AliasHelper.toAlias('Deleted Alias'), 50, 100]; - await umbracoApi.dataType.createImageCropperDataTypeWithOneCrop(customDataTypeName, cropData[0], cropData[2], cropData[3]); + const cropObject = {label: 'Deleted Label', alias: AliasHelper.toAlias('Deleted Label'), width: 50, height: 100}; + await umbracoApi.dataType.createImageCropperDataTypeWithOneCrop(customDataTypeName, cropObject.label, cropObject.width, cropObject.height); await umbracoUi.dataType.goToDataType(customDataTypeName); // Act - await umbracoUi.dataType.removeCropByAlias(cropData[0].toString()); + await umbracoUi.dataType.removeCropByAlias(cropObject.alias); await umbracoUi.dataType.clickSaveButton(); // Assert await umbracoUi.dataType.isSuccessStateVisibleForSaveButton(); - expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, cropData[0], cropData[1], cropData[2], cropData[3])).toBeFalsy(); + expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, cropObject.label, cropObject.alias, cropObject.width, cropObject.height)).toBeFalsy(); }); test('the default configuration is correct', async ({umbracoApi, umbracoUi}) => { diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/MediaPicker.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/MediaPicker.spec.ts index 747751d49d..b15983c854 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/MediaPicker.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/MediaPicker.spec.ts @@ -1,4 +1,4 @@ -import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {AliasHelper, ConstantHelper, test} from '@umbraco/playwright-testhelpers'; import {expect} from "@playwright/test"; const mediaPickerTypes = [ @@ -67,23 +67,25 @@ test('can update enable focal point', async ({umbracoApi, umbracoUi}) => { test('can add image crop', async ({umbracoApi, umbracoUi}) => { // Arrange - const cropData = ['Test Label', 'testAlias', 100, 50]; + const cropObject = {label: 'Test Label', alias: AliasHelper.toAlias('Test Label'), width: 100, height: 50}; await umbracoApi.dataType.createDefaultMediaPickerDataType(customDataTypeName); await umbracoUi.dataType.goToDataType(customDataTypeName); // Act + await umbracoUi.dataType.clickCreateCropButton(); + await umbracoUi.dataType.enterCropValues( - cropData[0].toString(), - cropData[1].toString(), - cropData[2].toString(), - cropData[3].toString() + cropObject.label, + cropObject.alias, + cropObject.width.toString(), + cropObject.height.toString() ); - await umbracoUi.dataType.clickAddCropButton(); + await umbracoUi.dataType.clickCreateCropButton(); await umbracoUi.dataType.clickSaveButton(); // Assert await umbracoUi.dataType.isSuccessStateVisibleForSaveButton(); - expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, cropData[0], cropData[1], cropData[2], cropData[3])).toBeTruthy(); + expect(await umbracoApi.dataType.doesDataTypeHaveCrops(customDataTypeName, cropObject.label, cropObject.alias, cropObject.width, cropObject.height)).toBeTruthy(); }); test('can update ignore user start nodes', async ({umbracoApi, umbracoUi}) => { diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/MultiUrlPicker.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/MultiUrlPicker.spec.ts index 599c94b185..ac0661264a 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/MultiUrlPicker.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/MultiUrlPicker.spec.ts @@ -90,6 +90,7 @@ test('can update hide anchor/query string input', async ({umbracoApi, umbracoUi} }); // TODO: Remove skip when the front-end is ready. Currently you still can update the minimum greater than the maximum. +// Issue link: https://github.com/umbraco/Umbraco-CMS/issues/17509 test.skip('cannot update the minimum number of items greater than the maximum', async ({umbracoApi, umbracoUi}) => { // Arrange const minimumValue = 5; diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/Numeric.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/Numeric.spec.ts index 5ca6b71eb8..93a9837faf 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/Numeric.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/Numeric.spec.ts @@ -77,6 +77,7 @@ test.skip('can allow decimals', async ({umbracoApi, umbracoUi}) => { }); // TODO: Remove skip when the front-end is ready. Currently you still can update the minimum greater than the maximum. +// Issue link: https://github.com/umbraco/Umbraco-CMS/issues/17509 test.skip('cannot update the minimum greater than the maximum', async ({umbracoApi, umbracoUi}) => { // Arrange const minimumValue = 5; diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/Textstring.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/Textstring.spec.ts index 02821b3d50..2123e8a631 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/Textstring.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/DataType/Textstring.spec.ts @@ -31,8 +31,9 @@ test('can update maximum allowed characters value', async ({umbracoApi, umbracoU expect(await umbracoApi.dataType.doesDataTypeHaveValue(customDataTypeName, 'maxChars', maxCharsValue)).toBeTruthy(); }); -// Remove fixme when the front-end is ready. The "Input type" should be removed. -test.fixme('the default configuration is correct', async ({umbracoApi, umbracoUi}) => { +// Remove .skip when the front-end is ready. The "Input type" should be removed. +// Issue link: https://github.com/umbraco/Umbraco-CMS/issues/19340 +test.skip('the default configuration is correct', async ({umbracoApi, umbracoUi}) => { // Act await umbracoUi.dataType.goToDataType(dataTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Dictionary/Dictionary.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Dictionary/Dictionary.spec.ts index c8155e889c..f77000d4e9 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Dictionary/Dictionary.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Dictionary/Dictionary.spec.ts @@ -169,7 +169,7 @@ test('can import a dictionary item with descendants', {tag: '@smoke'}, async ({u }); // Skip this test as the search function is removed -test.skip('can search a dictionary item in list when have results', async ({umbracoApi, umbracoUi}) => { +test('can search a dictionary item in list when have results', async ({umbracoApi, umbracoUi}) => { // Arrange await umbracoApi.dictionary.ensureNameNotExists(dictionaryName); await umbracoApi.dictionary.create(dictionaryName); @@ -182,10 +182,9 @@ test.skip('can search a dictionary item in list when have results', async ({umbr expect(await umbracoUi.dictionary.doesDictionaryListHaveText(dictionaryName)).toBeTruthy(); }); -// Skip this test as the search function is removed -test.skip('can search a dictionary item in list when have no results', async ({umbracoApi, umbracoUi}) => { +test('can search a dictionary item in list when have no results', async ({umbracoApi, umbracoUi}) => { // Arrange - const emptySearchResultMessage = 'No Dictionary items to choose from'; + const emptySearchResultMessage = 'No items'; await umbracoApi.dictionary.ensureNameNotExists(dictionaryName); await umbracoApi.dictionary.create(dictionaryName); await umbracoUi.dictionary.goToSection(ConstantHelper.sections.dictionary); @@ -195,4 +194,4 @@ test.skip('can search a dictionary item in list when have no results', async ({u // Assert await umbracoUi.dictionary.isSearchResultMessageDisplayEmpty(emptySearchResultMessage); -}); +}); \ No newline at end of file diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/ListViewMedia.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/ListViewMedia.spec.ts index f33a608668..9ec4658c46 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/ListViewMedia.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/ListViewMedia.spec.ts @@ -114,8 +114,7 @@ test('can allow bulk trash in the media section', async ({umbracoApi, umbracoUi} await umbracoUi.media.isItemVisibleInRecycleBin(secondMediaFileName, true, false); }); -// TODO: Remove fixme when update code to select media successfully. -test.fixme('can allow bulk move in the media section', async ({umbracoApi, umbracoUi}) => { +test('can allow bulk move in the media section', async ({umbracoApi, umbracoUi}) => { // Arrange const mediaFolderName = 'Test Folder Name'; await umbracoApi.media.ensureNameNotExists(mediaFolderName); @@ -125,10 +124,12 @@ test.fixme('can allow bulk move in the media section', async ({umbracoApi, umbra await umbracoUi.media.goToSection(ConstantHelper.sections.media); await umbracoUi.media.selectMediaWithName(firstMediaFileName); await umbracoUi.media.selectMediaWithName(secondMediaFileName); + await umbracoUi.waitForTimeout(200); await umbracoUi.media.clickBulkMoveToButton(); await umbracoUi.media.clickCaretButtonForName('Media'); await umbracoUi.media.clickModalTextByName(mediaFolderName); await umbracoUi.media.clickChooseModalButton(); + await umbracoUi.waitForTimeout(500); // Assert await umbracoUi.media.waitForMediaToBeMoved(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/Media.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/Media.spec.ts index ada2e6f149..14ec1d0fe5 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/Media.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Media/Media.spec.ts @@ -67,6 +67,7 @@ for (const mediaFileType of mediaFileTypes) { await umbracoUi.media.clickCreateMediaWithType(mediaFileType.fileName); await umbracoUi.media.enterMediaItemName(mediaFileType.fileName); await umbracoUi.media.uploadFile('./fixtures/mediaLibrary/' + mediaFileType.filePath); + await umbracoUi.waitForTimeout(500); // Wait for the file to be uploaded await umbracoUi.media.clickSaveButton(); // Assert @@ -219,7 +220,7 @@ test('can delete a media item from the recycle bin', async ({umbracoApi, umbraco await umbracoUi.media.goToSection(ConstantHelper.sections.media); // Act - await umbracoUi.media.isItemVisibleInRecycleBin(mediaFileName); + await umbracoUi.media.isItemVisibleInRecycleBin(mediaFileName, true, true); await umbracoUi.media.deleteMediaItem(mediaFileName); // Assert @@ -237,13 +238,13 @@ test('can empty the recycle bin', async ({umbracoApi, umbracoUi}) => { await umbracoUi.media.goToSection(ConstantHelper.sections.media); // Act - await umbracoUi.media.isItemVisibleInRecycleBin(mediaFileName); + await umbracoUi.media.isItemVisibleInRecycleBin(mediaFileName, true, true); await umbracoUi.media.clickEmptyRecycleBinButton(); await umbracoUi.media.clickConfirmEmptyRecycleBinButton(); // Assert + await umbracoUi.media.waitForRecycleBinToBeEmptied(); await umbracoUi.media.isItemVisibleInRecycleBin(mediaFileName, false, false); - await umbracoUi.media.doesSuccessNotificationHaveText(NotificationConstantHelper.success.emptiedRecycleBin); expect(await umbracoApi.media.doesNameExist(mediaFileName)).toBeFalsy(); expect(await umbracoApi.media.doesMediaItemExistInRecycleBin(mediaFileName)).toBeFalsy(); }); @@ -260,7 +261,7 @@ test('can trash a media node with a relation', async ({umbracoApi, umbracoUi}) = // Act await umbracoUi.media.clickActionsMenuForName(mediaFileName); - await umbracoUi.media.clickTrashButton(); + await umbracoUi.media.clickTrashActionMenuOption(); // Verify the references list await umbracoUi.media.doesReferenceHeadlineHaveText(ConstantHelper.trashDeleteDialogMessage.referenceHeadline); await umbracoUi.media.doesReferenceItemsHaveCount(1); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Members/Members.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Members/Members.spec.ts index 6bbc40f1dd..c959d876c3 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Members/Members.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Members/Members.spec.ts @@ -1,4 +1,4 @@ -import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; import {expect} from "@playwright/test"; let memberId = ''; @@ -39,6 +39,7 @@ test('can create a member', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => // Assert await umbracoUi.member.waitForMemberToBeCreated(); + await umbracoUi.member.isSuccessStateIconVisible() await umbracoUi.member.clickMembersSidebarButton(); await umbracoUi.member.isMemberWithNameVisible(memberName, true); expect(await umbracoApi.member.doesNameExist(memberName)).toBeTruthy(); @@ -244,8 +245,7 @@ test('cannot create member with invalid email', async ({umbracoApi, umbracoUi}) expect(await umbracoApi.member.doesNameExist(memberName)).toBeFalsy(); }); -// TODO: Remove skip when the front-end is ready. Currently it is possible to update member with invalid email. -test.skip('cannot update email to an invalid email', async ({umbracoApi, umbracoUi}) => { +test('cannot update email to an invalid email', async ({umbracoApi, umbracoUi}) => { // Arrange const invalidEmail = 'invalidemail'; memberTypeId = await umbracoApi.memberType.createDefaultMemberType(memberTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/InstalledPackages.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/InstalledPackages.spec.ts index fbd11c8cfd..9164b496f5 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/InstalledPackages.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/InstalledPackages.spec.ts @@ -1,6 +1,6 @@ import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; -test.skip('can see the umbraco package is installed', async ({umbracoUi}) => { +test('can see the umbraco package is installed', async ({umbracoUi}) => { // Arrange await umbracoUi.goToBackOffice(); await umbracoUi.package.goToSection(ConstantHelper.sections.packages); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/PackagesPackages.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/PackagesPackages.spec.ts index 19b4f74a99..ac91cf55d6 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/PackagesPackages.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Packages/PackagesPackages.spec.ts @@ -1,14 +1,12 @@ import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; -// TODO: There is currently an issue with playwright and the Iframe in the marketplace, look into this. // The MarketPlace is a iFrame we are using from the DXP team, so it is not something we should test. This test is just checking if we have the IFrame -test.skip('can see the marketplace', async ({umbracoUi}) => { +test('can see the marketplace', async ({umbracoUi}) => { // Arrange await umbracoUi.goToBackOffice(); - await umbracoUi.package.goToSection(ConstantHelper.sections.packages); // Act - await umbracoUi.package.clickPackagesTab(); + await umbracoUi.package.goToSection(ConstantHelper.sections.packages); // Assert await umbracoUi.package.isMarketPlaceIFrameVisible(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/RelationTypes/RelationTypes.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/RelationTypes/RelationTypes.spec.ts index f831ca285e..536cf77f5d 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/RelationTypes/RelationTypes.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/RelationTypes/RelationTypes.spec.ts @@ -1,7 +1,6 @@ import {test} from '@umbraco/playwright-testhelpers'; import {expect} from "@playwright/test"; -// Skip all tests as this feature is removed const relationTypeName = 'Test Relation Type'; const objectTypeName = 'Document'; let relationTypeId = ''; @@ -18,6 +17,7 @@ test.afterEach(async ({umbracoApi}) => { await umbracoApi.relationType.ensureNameNotExists(relationTypeName); }); +// Skip all tests as this feature is removed test.skip('can create a relation type', async ({umbracoApi, umbracoUi}) => { // Act await umbracoUi.relationType.clickActionsMenuAtRoot(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/RenderingContent/RenderingContentWithMultipleMediaPicker.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/RenderingContent/RenderingContentWithMultipleMediaPicker.spec.ts index 6b516df736..0d231bd569 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/RenderingContent/RenderingContentWithMultipleMediaPicker.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/RenderingContent/RenderingContentWithMultipleMediaPicker.spec.ts @@ -40,8 +40,7 @@ test('can render content with multiple media picker value', async ({umbracoApi, await umbracoUi.contentRender.doesContentRenderValueContainText(secondMediaFileName); }); -// Remove .fixme when the issue is fixed: https://github.com/umbraco/Umbraco-CMS/issues/18531 -test.fixme('can render content with multiple image media picker value', async ({umbracoApi, umbracoUi}) => { +test('can render content with multiple image media picker value', async ({umbracoApi, umbracoUi}) => { // Arrange const dataTypeName = 'Multiple Image Media Picker'; const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/ExamineManagement.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/ExamineManagement.spec.ts index b5b61a5faf..c8fdd1fb24 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/ExamineManagement.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/ExamineManagement.spec.ts @@ -7,7 +7,7 @@ test.beforeEach(async ({umbracoUi}) => { await umbracoUi.examineManagement.clickExamineManagementTab(); }); -test.skip('can view indexers information', async ({umbracoApi, umbracoUi}) => { +test('can view indexers information', async ({umbracoApi, umbracoUi}) => { // Arrange const allIndexersData = await umbracoApi.indexer.getAll(); const indexerCount = allIndexersData.total; diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/Profiling.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/Profiling.spec.ts index be7ae4e21d..7f5d864ba4 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/Profiling.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/Profiling.spec.ts @@ -1,12 +1,11 @@ import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; -test.beforeEach(async ({umbracoUi}) => { +test('can update value of activate the profiler by default', async ({umbracoUi}) => { + // Arrange await umbracoUi.goToBackOffice(); await umbracoUi.profiling.goToSection(ConstantHelper.sections.settings); await umbracoUi.profiling.clickProfilingTab(); -}); -test('can update value of activate the profiler by default', async ({umbracoUi}) => { // Act await umbracoUi.profiling.clickActivateProfilerByDefaultToggle(); await umbracoUi.reloadPage(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/Telemetry.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/Telemetry.spec.ts index 09595139c2..dc116934d7 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/Telemetry.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Dashboard/Telemetry.spec.ts @@ -16,7 +16,9 @@ test('can change telemetry level', async ({page, umbracoApi, umbracoUi}) => { const expectedLevel = "Minimal"; const levelValue = "1"; await umbracoUi.telemetryData.clickTelemetryDataTab(); + await umbracoUi.waitForTimeout(500); await umbracoUi.telemetryData.changeTelemetryDataLevelValue(levelValue); + await umbracoUi.waitForTimeout(500); // We wait until we are sure that the Telemetry level has been saved before we continue. await Promise.all([ @@ -27,8 +29,7 @@ test('can change telemetry level', async ({page, umbracoApi, umbracoUi}) => { // Assert // UI await umbracoUi.reloadPage(); - await expect(page.locator('[name="telemetryLevel"] >> input[id=input]')).toHaveValue(levelValue, {timeout: 20000}); - // await umbracoUi.telemetryData.doesTelemetryDataLevelHaveValue(levelValue); + await umbracoUi.telemetryData.doesTelemetryDataLevelHaveValue(levelValue); // API expect(await umbracoApi.telemetry.getLevel() == expectedLevel).toBeTruthy(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeCollectionWorkspace.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeCollectionWorkspace.spec.ts index 3001fe9c99..85edfa5c21 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeCollectionWorkspace.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeCollectionWorkspace.spec.ts @@ -1,4 +1,4 @@ -import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; import {expect} from '@playwright/test'; const documentTypeName = 'TestDocumentType'; @@ -93,8 +93,6 @@ test('can create a document type folder using create options', async ({umbracoAp // Assert await umbracoUi.documentType.waitForDocumentTypeToBeCreated(); - const folder = await umbracoApi.documentType.getByName(documentFolderName); - expect(folder.name).toBe(documentFolderName); // Check if the created document type folder is displayed in the collection view and has correct icon await umbracoUi.documentType.clickDocumentTypesMenu(); await umbracoUi.documentType.doesCollectionTreeItemTableRowHaveName(documentFolderName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeDesignTab.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeDesignTab.spec.ts index c4c317d3e2..6f085a9bd5 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeDesignTab.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeDesignTab.spec.ts @@ -258,7 +258,8 @@ test('can remove a composition from a document type', async ({umbracoApi, umbrac await umbracoApi.documentType.ensureNameNotExists(compositionDocumentTypeName); }); -test('can reorder groups in a document type', async ({umbracoApi, umbracoUi}) => { +// Skip this flaky tests as sometimes the properties are not dragged correctly. +test.skip('can reorder groups in a document type', async ({umbracoApi, umbracoUi}) => { // Arrange const dataTypeData = await umbracoApi.dataType.getByName(dataTypeName); const secondGroupName = 'SecondGroup'; @@ -268,7 +269,9 @@ test('can reorder groups in a document type', async ({umbracoApi, umbracoUi}) => // Act await umbracoUi.documentType.clickReorderButton(); - const groupValues = await umbracoUi.documentType.reorderTwoGroups(); + + // Drag and Drop + const groupValues = await umbracoUi.documentType.reorderTwoGroups(groupName, secondGroupName); const firstGroupValue = groupValues.firstGroupValue; const secondGroupValue = groupValues.secondGroupValue; await umbracoUi.documentType.clickIAmDoneReorderingButton(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeTemplatesTab.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeTemplatesTab.spec.ts index 8d0aeb57b7..2fb5eb9f9a 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeTemplatesTab.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/DocumentType/DocumentTypeTemplatesTab.spec.ts @@ -60,8 +60,7 @@ test('can set an allowed template as default for document type', async ({umbraco await umbracoApi.template.ensureNameNotExists(secondTemplateName); }); -// TODO: Remove skip when the front-end is ready. Currently the error displays when remove an allowed template -test.skip('can remove an allowed template from a document type', async ({umbracoApi, umbracoUi}) => { +test('can remove an allowed template from a document type', async ({umbracoApi, umbracoUi}) => { // Arrange await umbracoApi.documentType.createDocumentTypeWithAllowedTemplate(documentTypeName, templateId); await umbracoUi.documentType.goToSection(ConstantHelper.sections.settings); @@ -69,7 +68,7 @@ test.skip('can remove an allowed template from a document type', async ({umbraco // Act await umbracoUi.documentType.goToDocumentType(documentTypeName); await umbracoUi.documentType.clickDocumentTypeTemplatesTab(); - await umbracoUi.documentType.clickRemoveWithName(templateName, true); + await umbracoUi.documentType.clickRemoveWithName(templateName); await umbracoUi.documentType.clickSaveButton(); // Assert diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/PartialView/PartialView.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/PartialView/PartialView.spec.ts index fb975529e6..8c77f463f4 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/PartialView/PartialView.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/PartialView/PartialView.spec.ts @@ -1,4 +1,4 @@ -import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; import {expect} from "@playwright/test"; const partialViewName = 'TestPartialView'; @@ -111,8 +111,7 @@ test('can update a partial view content', {tag: '@smoke'}, async ({umbracoApi, u expect(updatedPartialView.content).toBe(updatedPartialViewContent); }); -// Remove .fixme when the issue is fixed: https://github.com/umbraco/Umbraco-CMS/issues/18536 -test.fixme('can use query builder with Order By statement for a partial view', async ({umbracoApi, umbracoUi}) => { +test('can use query builder with Order By statement for a partial view', async ({umbracoApi, umbracoUi}) => { //Arrange const propertyAliasValue = 'UpdateDate'; const isAscending = true; @@ -151,8 +150,7 @@ test.fixme('can use query builder with Order By statement for a partial view', a expect(updatedPartialView.content).toBe(expectedTemplateContent); }); -// Remove .fixme when the issue is fixed: https://github.com/umbraco/Umbraco-CMS/issues/18536 -test.fixme('can use query builder with Where statement for a partial view', async ({umbracoApi, umbracoUi}) => { +test('can use query builder with Where statement for a partial view', async ({umbracoApi, umbracoUi}) => { //Arrange const propertyAliasValue = 'Name'; const operatorValue = 'is'; @@ -194,17 +192,16 @@ test.fixme('can use query builder with Where statement for a partial view', asyn test('can insert dictionary item into a partial view', async ({umbracoApi, umbracoUi}) => { // Arrange + const partialViewContent = '@Umbraco.GetDictionaryValue("' + dictionaryName + '")' + defaultPartialViewContent; await umbracoApi.partialView.create(partialViewFileName, defaultPartialViewContent, '/'); expect(await umbracoApi.partialView.doesExist(partialViewFileName)).toBeTruthy(); - await umbracoApi.dictionary.ensureNameNotExists(dictionaryName); await umbracoApi.dictionary.create(dictionaryName); - const partialViewContent = '@Umbraco.GetDictionaryValue("' + dictionaryName + '")' + defaultPartialViewContent; - // Act await umbracoUi.partialView.openPartialViewAtRoot(partialViewFileName); await umbracoUi.partialView.insertDictionaryItem(dictionaryName); + await umbracoUi.waitForTimeout(500); // Wait for the dictionary item to be inserted await umbracoUi.partialView.clickSaveButton(); // Assert @@ -250,8 +247,7 @@ test('can delete a partial view', {tag: '@smoke'}, async ({umbracoApi, umbracoUi await umbracoUi.partialView.isPartialViewRootTreeItemVisible(partialViewFileName, false, false); }); -// TODO: Remove skip when the front-end is ready. Currently the returned items count is not updated after choosing the root content. -test.skip('can show returned items in query builder ', async ({umbracoApi, umbracoUi}) => { +test('can show returned items in query builder ', async ({umbracoApi, umbracoUi}) => { //Arrange // Create content at root with a child const documentTypeName = 'ParentDocumentType'; @@ -261,12 +257,14 @@ test.skip('can show returned items in query builder ', async ({umbracoApi, umbra const childDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(childDocumentTypeName); const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNode(documentTypeName, childDocumentTypeId); const contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoApi.document.createDefaultDocumentWithParent(childContentName, childDocumentTypeId, contentId); + const childContentId = await umbracoApi.document.createDefaultDocumentWithParent(childContentName, childDocumentTypeId, contentId); + await umbracoApi.document.publish(contentId); + await umbracoApi.document.publish(childContentId); // Create partial view await umbracoApi.partialView.create(partialViewFileName, partialViewFileName, '/'); expect(await umbracoApi.partialView.doesExist(partialViewFileName)).toBeTruthy(); - //Act + // Act await umbracoUi.partialView.openPartialViewAtRoot(partialViewFileName); await umbracoUi.partialView.clickQueryBuilderButton(); await umbracoUi.partialView.chooseRootContentInQueryBuilder(contentName); @@ -277,6 +275,9 @@ test.skip('can show returned items in query builder ', async ({umbracoApi, umbra // Clean await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + await umbracoApi.documentType.ensureNameNotExists(childDocumentTypeName); + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.document.ensureNameNotExists(childContentName); }); test('cannot create a partial view with an empty name', async ({umbracoApi, umbracoUi}) => { diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Stylesheet/Stylesheet.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Stylesheet/Stylesheet.spec.ts index be9657a16e..0667fdce87 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Stylesheet/Stylesheet.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Stylesheet/Stylesheet.spec.ts @@ -2,9 +2,7 @@ import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwri import {expect} from '@playwright/test'; const stylesheetName = 'TestStyleSheetFile.css'; -const styleName = 'TestStyleName'; -const styleSelector = 'h1'; -const styleStyles = 'color:red'; +const stylesheetContent = 'TestContent'; test.beforeEach(async ({umbracoUi,umbracoApi}) => { await umbracoUi.goToBackOffice(); @@ -34,7 +32,6 @@ test('can create a empty stylesheet', {tag: '@smoke'}, async ({umbracoApi, umbra test('can create a stylesheet with content', async ({umbracoApi, umbracoUi}) => { // Arrange - const stylesheetContent = 'TestContent'; await umbracoUi.stylesheet.goToSection(ConstantHelper.sections.settings); //Act @@ -53,21 +50,22 @@ test('can create a stylesheet with content', async ({umbracoApi, umbracoUi}) => await umbracoUi.stylesheet.isStylesheetRootTreeItemVisible(stylesheetName); }); -test.skip('can update a stylesheet', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { +test('can update a stylesheet', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { // Arrange - const stylesheetContent = '/**umb_name:' + styleName + '*/\n' + styleSelector + ' {\n\t' + styleStyles + '\n}'; - await umbracoApi.stylesheet.create(stylesheetName, '', '/'); + const updatedContent = 'UpdatedTestContent'; + await umbracoApi.stylesheet.create(stylesheetName, stylesheetContent, '/'); expect(await umbracoApi.stylesheet.doesExist(stylesheetName)).toBeTruthy(); await umbracoUi.stylesheet.goToSection(ConstantHelper.sections.settings); //Act await umbracoUi.stylesheet.openStylesheetByNameAtRoot(stylesheetName); + await umbracoUi.stylesheet.enterStylesheetContent(updatedContent); await umbracoUi.stylesheet.clickSaveButton(); // Assert await umbracoUi.stylesheet.isSuccessStateVisibleForSaveButton(); const stylesheetData = await umbracoApi.stylesheet.getByName(stylesheetName); - expect(stylesheetData.content).toEqual(stylesheetContent); + expect(stylesheetData.content).toEqual(updatedContent); }); test('can delete a stylesheet', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Template/Templates.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Template/Templates.spec.ts index bdca513e24..17d89c475a 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Template/Templates.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/Template/Templates.spec.ts @@ -136,8 +136,7 @@ test('can remove a master template', async ({umbracoApi, umbracoUi}) => { await umbracoApi.template.ensureNameNotExists(childTemplateName); }); -// Remove skip when the front-end is ready. Currently this function is not stable, sometimes the shown code is not updated after choosing Order By -test.skip('can use query builder with Order By statement for a template', async ({umbracoApi, umbracoUi}) => { +test('can use query builder with Order By statement for a template', async ({umbracoApi, umbracoUi}) => { // Arrange const propertyAliasValue = 'UpdateDate'; const isAscending = true; @@ -175,8 +174,7 @@ test.skip('can use query builder with Order By statement for a template', async expect(templateData.content).toBe(expectedTemplateContent); }); -// Remove .fixme when the issue is fixed: https://github.com/umbraco/Umbraco-CMS/issues/18536 -test.fixme('can use query builder with Where statement for a template', async ({umbracoApi, umbracoUi}) => { +test('can use query builder with Where statement for a template', async ({umbracoApi, umbracoUi}) => { // Arrange const propertyAliasValue = 'Name'; const operatorValue = 'is'; @@ -330,25 +328,26 @@ test('can insert value into a template', async ({umbracoApi, umbracoUi}) => { expect(templateData.content).toBe(templateContent); }); -// TODO: Remove skip when the front-end is ready. Currently the returned items count is not updated after choosing the root content. -test.skip('can show returned items in query builder ', async ({umbracoApi, umbracoUi}) => { +test('can show returned items in query builder ', async ({umbracoApi, umbracoUi}) => { // Arrange // Create content at root with a child const documentTypeName = 'ParentDocumentType'; const childDocumentTypeName = 'ChildDocumentType'; - const contentName = 'ContentName'; - const childContentName = 'ChildContentName'; + const contentName = 'ContentNameTemplate'; + const childContentName = 'ChildContentNameTemplate'; const childDocumentTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(childDocumentTypeName); const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNode(documentTypeName, childDocumentTypeId); const contentId = await umbracoApi.document.createDefaultDocument(contentName, documentTypeId); - await umbracoApi.document.createDefaultDocumentWithParent(childContentName, childDocumentTypeId, contentId); + const childContentId = await umbracoApi.document.createDefaultDocumentWithParent(childContentName, childDocumentTypeId, contentId); + await umbracoApi.document.publish(contentId); + await umbracoApi.document.publish(childContentId); // Create template await umbracoApi.template.createDefaultTemplate(templateName); // Act await umbracoUi.template.goToTemplate(templateName); await umbracoUi.template.clickQueryBuilderButton(); - await umbracoUi.template.chooseRootContentInQueryBuilder('(' + contentName + ')'); + await umbracoUi.template.chooseRootContentInQueryBuilder(contentName); // Assert await umbracoUi.template.doesReturnedItemsHaveCount(1); @@ -356,6 +355,9 @@ test.skip('can show returned items in query builder ', async ({umbracoApi, umbra // Clean await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + await umbracoApi.documentType.ensureNameNotExists(childDocumentTypeName); + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.document.ensureNameNotExists(childContentName); }); test('cannot create a template with an empty name', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => { diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/User/ContentStartNodes.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/User/ContentStartNodes.spec.ts index 70bd76fcca..ea84ad5161 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/User/ContentStartNodes.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/User/ContentStartNodes.spec.ts @@ -69,9 +69,7 @@ test('can see parent of start node but not access it', async ({umbracoApi, umbra // Assert await umbracoUi.content.isContentInTreeVisible(rootDocumentName); await umbracoUi.content.goToContentWithName(rootDocumentName); - await umbracoUi.content.isErrorNotificationVisible(); - // TODO: Uncomment this when this issue is fixed https://github.com/umbraco/Umbraco-CMS/issues/18533 - //await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.noAccessToResource); + await umbracoUi.content.doesDocumentWorkspaceHaveText('Access denied'); await umbracoUi.content.clickCaretButtonForContentName(rootDocumentName); await umbracoUi.content.isChildContentInTreeVisible(rootDocumentName, childDocumentOneName); await umbracoUi.content.isChildContentInTreeVisible(rootDocumentName, childDocumentTwoName, false); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/User/MediaStartNodes.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/User/MediaStartNodes.spec.ts index bc9637b05a..c8720a7a41 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/User/MediaStartNodes.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/User/MediaStartNodes.spec.ts @@ -61,11 +61,8 @@ test('can see parent of start node but not access it', async ({umbracoApi, umbra // Assert await umbracoUi.media.isMediaTreeItemVisible(rootFolderName); - await umbracoUi.waitForTimeout(500); await umbracoUi.media.goToMediaWithName(rootFolderName); - await umbracoUi.content.isErrorNotificationVisible(); - // TODO: Uncomment this when this issue is fixed https://github.com/umbraco/Umbraco-CMS/issues/18533 - //await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.noAccessToResource); + await umbracoUi.media.doesMediaWorkspaceHaveText('Access denied'); await umbracoUi.media.clickCaretButtonForMediaName(rootFolderName); await umbracoUi.media.isChildMediaVisible(rootFolderName, childFolderOneName); await umbracoUi.media.isChildMediaVisible(rootFolderName, childFolderTwoName, false); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/ContentStartNodes.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/ContentStartNodes.spec.ts index 09c8ed8e39..1648b0e6ff 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/ContentStartNodes.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/ContentStartNodes.spec.ts @@ -1,4 +1,4 @@ -import {ConstantHelper, NotificationConstantHelper, test} from '@umbraco/playwright-testhelpers'; +import {ConstantHelper, test} from '@umbraco/playwright-testhelpers'; const testUser = ConstantHelper.testUserCredentials; let testUserCookieAndToken = {cookie: "", accessToken: "", refreshToken: ""}; @@ -71,9 +71,7 @@ test('can see parent of start node but not access it', async ({umbracoApi, umbra // Assert await umbracoUi.content.isContentInTreeVisible(rootDocumentName); await umbracoUi.content.goToContentWithName(rootDocumentName); - await umbracoUi.content.isErrorNotificationVisible(); - // TODO: Uncomment this when this issue is fixed https://github.com/umbraco/Umbraco-CMS/issues/18533 - //await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.noAccessToResource); + await umbracoUi.content.doesDocumentWorkspaceHaveText('Access denied'); await umbracoUi.content.clickCaretButtonForContentName(rootDocumentName); await umbracoUi.content.isChildContentInTreeVisible(rootDocumentName, childDocumentOneName); await umbracoUi.content.isChildContentInTreeVisible(rootDocumentName, childDocumentTwoName, false); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DefaultPermissionsInContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DefaultPermissionsInContent.spec.ts index 4778d60401..11aad82ae3 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DefaultPermissionsInContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DefaultPermissionsInContent.spec.ts @@ -76,9 +76,7 @@ test('can not browse content node with permission disabled', async ({umbracoApi, await umbracoUi.content.goToContentWithName(rootDocumentName); // Assert - await umbracoUi.content.isErrorNotificationVisible(); - // TODO: Uncomment this when this issue is fixed https://github.com/umbraco/Umbraco-CMS/issues/18533 - //await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.noAccessToResource); + await umbracoUi.content.doesDocumentWorkspaceHaveText('Not found'); }); test('can create document blueprint with permission enabled', async ({umbracoApi, umbracoUi}) => { @@ -127,7 +125,8 @@ test('can delete content with delete permission enabled', async ({umbracoApi, um await umbracoUi.content.clickConfirmTrashButton(); // Assert - await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.movedToRecycleBin); + await umbracoUi.content.waitForContentToBeTrashed(); + await umbracoUi.content.isItemVisibleInRecycleBin(rootDocumentName); }); test('can not delete content with delete permission disabled', async ({umbracoApi, umbracoUi}) => { @@ -159,7 +158,8 @@ test('can empty recycle bin with delete permission enabled', async ({umbracoApi, await umbracoUi.content.clickConfirmEmptyRecycleBinButton(); // Assert - await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.emptiedRecycleBin); + await umbracoUi.content.waitForRecycleBinToBeEmptied(); + await umbracoUi.content.isItemVisibleInRecycleBin(rootDocumentName, false, false); }); test('can not empty recycle bin with delete permission disabled', async ({umbracoApi, umbracoUi}) => { @@ -270,7 +270,8 @@ test('can not publish content with publish permission disabled', async ({umbraco await umbracoUi.content.isActionsMenuForNameVisible(rootDocumentName, false); }); -// Bug, does nothing in the frontend. +// Remove .skip when the front-end is ready. Currently there is no "Permissions" menu item displays +// Issue link: https://github.com/umbraco/Umbraco-CMS/issues/19339 test.skip('can set permissions with set permissions permission enabled', async ({umbracoApi, umbracoUi}) => { // Arrange userGroupId = await umbracoApi.userGroup.createUserGroupWithSetPermissionsPermission(userGroupName); @@ -539,8 +540,7 @@ test('can not set culture and hostnames with culture and hostnames permission di await umbracoUi.content.isActionsMenuForNameVisible(rootDocumentName, false); }); -// TODO: Notification is not correct 'Public access setting created' should be 'access' -test.skip('can set public access with public access permission enabled', async ({umbracoApi, umbracoUi}) => { +test('can set public access with public access permission enabled', async ({umbracoApi, umbracoUi}) => { // Arrange userGroupId = await umbracoApi.userGroup.createUserGroupWithPublicAccessPermission(userGroupName); const testMemberGroup = 'TestMemberGroup'; @@ -593,6 +593,7 @@ test('can rollback content with rollback permission enabled', async ({umbracoApi await umbracoUi.content.doesDocumentPropertyHaveValue(dataTypeName, updatedTextStringText); await umbracoUi.content.clickInfoTab(); await umbracoUi.content.clickRollbackButton(); + await umbracoUi.waitForTimeout(700); // Wait for the rollback items to load await umbracoUi.content.clickLatestRollBackItem(); await umbracoUi.content.clickRollbackContainerButton(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DocumentPropertyValueGranularPermission.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DocumentPropertyValueGranularPermission.spec.ts index 8541d8d9d1..dd7ef6ebdc 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DocumentPropertyValueGranularPermission.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DocumentPropertyValueGranularPermission.spec.ts @@ -50,7 +50,7 @@ test('can only see property values for specific document with read UI enabled', await umbracoUi.content.isPropertyEditorUiWithNameReadOnly(firstPropertyName[1]); await umbracoUi.content.isPropertyEditorUiWithNameReadOnly(secondPropertyName[1]); await umbracoUi.content.goToContentWithName(secondDocumentName); - await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.permissionDenied); + await umbracoUi.content.doesDocumentWorkspaceHaveText('Access denied'); }); test('cannot see specific property value without UI read permission enabled', async ({umbracoApi, umbracoUi}) => { @@ -101,7 +101,7 @@ test('can see property with UI read enabled but not another property with UI rea await umbracoUi.content.isPropertyEditorUiWithNameVisible(secondPropertyName[1], false); }); -// Remove .skip when the front-end is ready. +// Remove .skip when the front-end is ready. // Issue link: https://github.com/umbraco/Umbraco-CMS/issues/19395 test.skip('can edit specific property values with UI read and write permission enabled', async ({umbracoApi, umbracoUi}) => { // Arrange diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DocumentPropertyValuePermission.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DocumentPropertyValuePermission.spec.ts index 4b558f8397..47a1703c9c 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DocumentPropertyValuePermission.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/DocumentPropertyValuePermission.spec.ts @@ -70,7 +70,7 @@ test('cannot open content without document read permission even with UI read per await umbracoUi.content.goToContentWithName(documentName); // Assert - await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.permissionDenied); + await umbracoUi.content.doesDocumentWorkspaceHaveText('Access denied'); }); test('cannot edit property values without UI write permission', async ({umbracoApi, umbracoUi}) => { @@ -122,4 +122,4 @@ test('cannot see property values with only UI write but no UI read permission', // Assert await umbracoUi.content.isPropertyEditorUiWithNameVisible('text-box', false); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/GranularPermissionsInContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/GranularPermissionsInContent.spec.ts index 450d94b528..e2cb5eedef 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/GranularPermissionsInContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/GranularPermissionsInContent.spec.ts @@ -269,6 +269,7 @@ test('can set culture and hostnames for a specific content with culture and host // Assert await umbracoUi.content.waitForDomainToBeCreated(); + await umbracoUi.waitForTimeout(500); // Wait for the domain to be set const document = await umbracoApi.document.getByName(firstDocumentName); const domains = await umbracoApi.document.getDomains(document.id); expect(domains.domains[0].domainName).toEqual(domainName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/Languages.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/Languages.spec.ts index e27f43c25e..29dd874a10 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/Languages.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/Languages.spec.ts @@ -62,7 +62,8 @@ test.afterEach(async ({umbracoApi}) => { await umbracoApi.documentType.ensureNameNotExists(documentTypeName); }); -test.fixme('can rename content with language set in userGroup', async ({umbracoApi, umbracoUi}) => { +// Remove .skip when the front-end is ready. Currently the content name is read-only so cannot remane it. +test.skip('can rename content with language set in userGroup', async ({umbracoApi, umbracoUi}) => { // Arrange const updatedContentName = 'UpdatedContentName'; userGroupId = await umbracoApi.userGroup.createUserGroupWithLanguageAndContentSection(userGroupName, englishIsoCode); @@ -75,7 +76,6 @@ test.fixme('can rename content with language set in userGroup', async ({umbracoA // Act await umbracoUi.content.isDocumentReadOnly(false); await umbracoUi.content.enterContentName(updatedContentName); - // Fix this later. Currently the "Save" button changed to "Save..." button await umbracoUi.content.clickSaveButton(); await umbracoUi.content.clickSaveAndCloseButton(); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/MediaStartNodes.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/MediaStartNodes.spec.ts index 1a72772e3b..ac284c12ba 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/MediaStartNodes.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/MediaStartNodes.spec.ts @@ -62,11 +62,8 @@ test('can see parent of start node but not access it', async ({umbracoApi, umbra // Assert await umbracoUi.media.isMediaTreeItemVisible(rootFolderName); - await umbracoUi.waitForTimeout(500); await umbracoUi.media.goToMediaWithName(rootFolderName); - await umbracoUi.content.isErrorNotificationVisible(); - // TODO: Uncomment this when this issue is fixed https://github.com/umbraco/Umbraco-CMS/issues/18533 - //await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.noAccessToResource); + await umbracoUi.media.doesMediaWorkspaceHaveText('Access denied'); await umbracoUi.media.clickCaretButtonForMediaName(rootFolderName); await umbracoUi.media.isChildMediaVisible(rootFolderName, childFolderOneName); await umbracoUi.media.isChildMediaVisible(rootFolderName, childFolderTwoName, false); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/MemberSection.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/MemberSection.spec.ts index 47d0b2d1ea..f0233c05bc 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/MemberSection.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/Permissions/UserGroup/MemberSection.spec.ts @@ -46,8 +46,7 @@ test('can access members section with section enabled', async ({umbracoApi, umbr await umbracoUi.member.doesErrorNotificationHaveText(NotificationConstantHelper.error.noAccessToResource, false); }); -// TODO: unskip when member creation is fixed -test.skip('can create member with members section set', async ({umbracoApi, umbracoUi}) => { +test('can create member with members section set', async ({umbracoApi, umbracoUi}) => { // Arrange userGroupId = await umbracoApi.userGroup.createUserGroupWithMemberSection(userGroupName); await umbracoApi.user.setUserPermissions(testUser.name, testUser.email, testUser.password, userGroupId, [], true, [], false, 'en-us'); @@ -57,7 +56,7 @@ test.skip('can create member with members section set', async ({umbracoApi, umbr await umbracoUi.member.clickMembersMenu(); // Act - await umbracoUi.member.clickCreateButton(); + await umbracoUi.member.clickCreateMembersButton(); await umbracoUi.member.enterMemberName(memberName); await umbracoUi.member.clickInfoTab(); await umbracoUi.member.enterUsername(username); @@ -74,8 +73,7 @@ test.skip('can create member with members section set', async ({umbracoApi, umbr expect(await umbracoApi.member.doesNameExist(memberName)).toBeTruthy(); }); -// TODO: unskip when member creation is fixed -test.skip('can update member with members section set', async ({umbracoApi, umbracoUi}) => { +test('can update member with members section set', async ({umbracoApi, umbracoUi}) => { // Arrange userGroupId = await umbracoApi.userGroup.createUserGroupWithMemberSection(userGroupName); memberTypeId = await umbracoApi.memberType.createDefaultMemberType(memberTypeName); @@ -85,6 +83,7 @@ test.skip('can update member with members section set', async ({umbracoApi, umbr testUserCookieAndToken = await umbracoApi.user.loginToUser(testUser.name, testUser.email, testUser.password); await umbracoUi.goToBackOffice(); await umbracoUi.member.goToSection(ConstantHelper.sections.members, false); + await umbracoUi.member.clickMembersMenu(); // Act await umbracoUi.member.clickMemberLinkByName(memberName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/User.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/User.spec.ts index 32c7d55344..6feac90525 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/User.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/User.spec.ts @@ -113,14 +113,14 @@ test('can remove a user group from a user', {tag: '@smoke'}, async ({umbracoApi, test('can update culture for a user', async ({umbracoApi, umbracoUi}) => { // Arrange - const danishIsoCode = 'da-dk'; + const danishIsoCode = 'da'; const userGroup = await umbracoApi.userGroup.getByName(defaultUserGroupName); await umbracoApi.user.createDefaultUser(nameOfTheUser, userEmail, [userGroup.id]); await umbracoUi.user.goToUsers(); // Act await umbracoUi.user.clickUserWithName(nameOfTheUser); - await umbracoUi.user.selectUserLanguage('Dansk (Danmark)'); + await umbracoUi.user.selectUserLanguage(danishIsoCode); await umbracoUi.user.clickSaveButton(); // Assert diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/UserGroups.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/UserGroups.spec.ts index 1d54792e0c..c1aba1e0a4 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/UserGroups.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Users/UserGroups.spec.ts @@ -3,7 +3,7 @@ import {expect} from "@playwright/test"; const allPermissions = { uiPermission: - ['Browse', + ['Read', 'Create Document Blueprint', 'Delete', 'Create', diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Webhook/WebhookTrigger.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Webhook/WebhookTrigger.spec.ts index 5b9f22d45a..9d4f1c68a2 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Webhook/WebhookTrigger.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Webhook/WebhookTrigger.spec.ts @@ -63,7 +63,7 @@ test('can trigger when content is deleted', async ({umbracoApi, umbracoUi}) => { await umbracoUi.content.clickConfirmEmptyRecycleBinButton(); // Assert - await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.emptiedRecycleBin); + await umbracoUi.content.waitForRecycleBinToBeEmptied(); const webhookSiteData = await umbracoApi.webhook.getWebhookSiteRequestResponse(webhookSiteToken); expect(webhookSiteData[0].content).toContain(contentId); }); @@ -123,7 +123,7 @@ test('can trigger when media is deleted', async ({umbracoApi, umbracoUi}) => { await umbracoUi.webhook.goToSection(ConstantHelper.sections.media); // Act - await umbracoUi.media.isItemVisibleInRecycleBin(mediaName); + await umbracoUi.media.isItemVisibleInRecycleBin(mediaName, true, true); await umbracoUi.media.deleteMediaItem(mediaName); await umbracoUi.media.waitForMediaToBeTrashed(); @@ -147,7 +147,7 @@ test('can trigger the webhook for a specific media type', async ({umbracoApi, um await umbracoUi.webhook.goToSection(ConstantHelper.sections.media); // Act - await umbracoUi.media.isItemVisibleInRecycleBin(mediaName); + await umbracoUi.media.isItemVisibleInRecycleBin(mediaName, true, true); await umbracoUi.media.deleteMediaItem(mediaName); await umbracoUi.media.deleteMediaItem(secondMediaName); @@ -239,4 +239,4 @@ test('can custom header for the webhook request', async ({umbracoApi, umbracoUi} // Assert const webhookSiteData = await umbracoApi.webhook.getWebhookSiteRequestResponse(webhookSiteToken); expect(webhookSiteData[0].headers[headerName]).toEqual([headerValue]); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Logging/LogviewerTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Logging/LogviewerTests.cs deleted file mode 100644 index fe199b3cf4..0000000000 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Logging/LogviewerTests.cs +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright (c) Umbraco. -// See LICENSE for more details. - -using System.Diagnostics; -using Microsoft.Extensions.Logging; -using Moq; -using NUnit.Framework; -using Serilog; -using Umbraco.Cms.Core; -using Umbraco.Cms.Core.Logging.Viewer; -using Umbraco.Cms.Core.Models; -using Umbraco.Cms.Core.Persistence.Querying; -using Umbraco.Cms.Core.Persistence.Repositories; -using Umbraco.Cms.Infrastructure.Migrations.Install; -using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement; -using Umbraco.Cms.Tests.UnitTests.TestHelpers; -using File = System.IO.File; - -namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Logging; - -[TestFixture] -public class LogviewerTests -{ - [OneTimeSetUp] - public void Setup() - { - var testRoot = TestContext.CurrentContext.TestDirectory.Split("bin")[0]; - - // Create an example JSON log file to check results - // As a one time setup for all tets in this class/fixture - var ioHelper = TestHelper.IOHelper; - var hostingEnv = TestHelper.GetHostingEnvironment(); - - var loggingConfiguration = TestHelper.GetLoggingConfiguration(hostingEnv); - - var exampleLogfilePath = Path.Combine(testRoot, "TestHelpers", "Assets", LogfileName); - _newLogfileDirPath = loggingConfiguration.LogDirectory; - _newLogfilePath = Path.Combine(_newLogfileDirPath, LogfileName); - - // Create/ensure Directory exists - ioHelper.EnsurePathExists(_newLogfileDirPath); - - // Copy the sample files - File.Copy(exampleLogfilePath, _newLogfilePath, true); - - var logger = Mock.Of>(); - var logViewerConfig = new LogViewerConfig(LogViewerQueryRepository, TestHelper.ScopeProvider); - var logLevelLoader = Mock.Of(); - _logViewer = - new SerilogJsonLogViewer(logger, logViewerConfig, loggingConfiguration, logLevelLoader, Log.Logger); - } - - [OneTimeTearDown] - public void TearDown() - { - // Cleanup & delete the example log & search files off disk - // Once all tests in this class/fixture have run - if (File.Exists(_newLogfilePath)) - { - File.Delete(_newLogfilePath); - } - } - - private ILogViewer _logViewer; - - private const string LogfileName = "UmbracoTraceLog.UNITTEST.20181112.json"; - - private string _newLogfilePath; - private string _newLogfileDirPath; - - private readonly LogTimePeriod _logTimePeriod = new( - new DateTime(2018, 11, 12, 0, 0, 0), - new DateTime(2018, 11, 13, 0, 0, 0)); - - private ILogViewerQueryRepository LogViewerQueryRepository { get; } = new TestLogViewerQueryRepository(); - - [Test] - public void Logs_Contain_Correct_Error_Count() - { - var numberOfErrors = _logViewer.GetNumberOfErrors(_logTimePeriod); - - // Our dummy log should contain 2 errors - Assert.AreEqual(1, numberOfErrors); - } - - [Test] - public void Logs_Contain_Correct_Log_Level_Counts() - { - var logCounts = _logViewer.GetLogLevelCounts(_logTimePeriod); - - Assert.AreEqual(55, logCounts.Debug); - Assert.AreEqual(1, logCounts.Error); - Assert.AreEqual(0, logCounts.Fatal); - Assert.AreEqual(38, logCounts.Information); - Assert.AreEqual(6, logCounts.Warning); - } - - [Test] - public void Logs_Contains_Correct_Message_Templates() - { - var templates = _logViewer.GetMessageTemplates(_logTimePeriod).ToArray(); - - // Count no of templates - Assert.AreEqual(25, templates.Count()); - - // Verify all templates & counts are unique - CollectionAssert.AllItemsAreUnique(templates); - - // Ensure the collection contains LogTemplate objects - CollectionAssert.AllItemsAreInstancesOfType(templates, typeof(LogTemplate)); - - // Get first item & verify its template & count are what we expect - var popularTemplate = templates.FirstOrDefault(); - - Assert.IsNotNull(popularTemplate); - Assert.AreEqual("{EndMessage} ({Duration}ms) [Timing {TimingId}]", popularTemplate.MessageTemplate); - Assert.AreEqual(26, popularTemplate.Count); - } - - [Test] - public void Logs_Can_Open_As_Small_File() - { - // We are just testing a return value (as we know the example file is less than 200MB) - // But this test method does not test/check that - var canOpenLogs = _logViewer.CheckCanOpenLogs(_logTimePeriod); - Assert.IsTrue(canOpenLogs); - } - - [Test] - public void Logs_Can_Be_Queried() - { - var sw = new Stopwatch(); - sw.Start(); - - // Should get me the most 100 recent log entries & using default overloads for remaining params - var allLogs = _logViewer.GetLogs(_logTimePeriod, 1); - - sw.Stop(); - - // Check we get 100 results back for a page & total items all good :) - Assert.AreEqual(100, allLogs.Items.Count()); - Assert.AreEqual(102, allLogs.TotalItems); - Assert.AreEqual(2, allLogs.TotalPages); - - // Check collection all contain same object type - CollectionAssert.AllItemsAreInstancesOfType(allLogs.Items, typeof(LogMessage)); - - // Check first item is newest - var newestItem = allLogs.Items.First(); - DateTimeOffset.TryParse("2018-11-12T08:39:18.1971147Z", out var newDate); - Assert.AreEqual(newDate, newestItem.Timestamp); - - // Check we call method again with a smaller set of results & in ascending - var smallQuery = _logViewer.GetLogs(_logTimePeriod, 1, 10, Direction.Ascending); - Assert.AreEqual(10, smallQuery.Items.Count()); - Assert.AreEqual(11, smallQuery.TotalPages); - - // Check first item is oldest - var oldestItem = smallQuery.Items.First(); - DateTimeOffset.TryParse("2018-11-12T08:34:45.8371142Z", out var oldDate); - Assert.AreEqual(oldDate, oldestItem.Timestamp); - - // Check invalid log levels - // Rather than expect 0 items - get all items back & ignore the invalid levels - string[] invalidLogLevels = { "Invalid", "NotALevel" }; - var queryWithInvalidLevels = _logViewer.GetLogs(_logTimePeriod, 1, logLevels: invalidLogLevels); - Assert.AreEqual(102, queryWithInvalidLevels.TotalItems); - - // Check we can call method with an array of logLevel (error & warning) - string[] logLevels = { "Warning", "Error" }; - var queryWithLevels = _logViewer.GetLogs(_logTimePeriod, 1, logLevels: logLevels); - Assert.AreEqual(7, queryWithLevels.TotalItems); - - // Query @Level='Warning' BUT we pass in array of LogLevels for Debug & Info (Expect to get 0 results) - string[] logLevelMismatch = { "Debug", "Information" }; - var filterLevelQuery = _logViewer.GetLogs( - _logTimePeriod, - 1, - filterExpression: "@Level='Warning'", - logLevels: logLevelMismatch); - Assert.AreEqual(0, filterLevelQuery.TotalItems); - } - - [TestCase("", 102)] - [TestCase("Has(@Exception)", 1)] - [TestCase("Has(@x)", 1)] - [TestCase("Has(Duration) and Duration > 1000", 2)] - [TestCase("Not(@Level = 'Verbose') and Not(@Level = 'Debug')", 45)] - [TestCase("Not(@l = 'Verbose') and Not(@l = 'Debug')", 45)] - [TestCase("StartsWith(SourceContext, 'Umbraco.Core')", 86)] - [TestCase("@MessageTemplate = '{EndMessage} ({Duration}ms) [Timing {TimingId}]'", 26)] - [TestCase("@mt = '{EndMessage} ({Duration}ms) [Timing {TimingId}]'", 26)] - [TestCase("SortedComponentTypes[?] = 'Umbraco.Web.Search.ExamineComponent'", 1)] - [TestCase("Contains(SortedComponentTypes[?], 'DatabaseServer')", 1)] - [TestCase("@Message like '%definition%'", 6)] - [TestCase("definition", 6)] - [Test] - public void Logs_Can_Query_With_Expressions(string queryToVerify, int expectedCount) - { - var testQuery = _logViewer.GetLogs(_logTimePeriod, 1, filterExpression: queryToVerify); - Assert.AreEqual(expectedCount, testQuery.TotalItems); - } - - [Test] - public void Log_Search_Can_Persist() - { - // Add a new search - _logViewer.AddSavedSearch("Unit Test Example", "Has(UnitTest)"); - - var searches = _logViewer.GetSavedSearches(); - - // Check if we can find the newly added item from the results we get back - var findItem = searches.Where(x => x.Name == "Unit Test Example" && x.Query == "Has(UnitTest)"); - - Assert.IsNotNull(findItem, "We should have found the saved search, but get no results"); - Assert.AreEqual(1, findItem.Count(), "Our list of searches should only contain one result"); - - // TODO: Need someone to help me find out why these don't work - // CollectionAssert.Contains(searches, savedSearch, "Can not find the new search that was saved"); - // Assert.That(searches, Contains.Item(savedSearch)); - - // Remove the search from above & ensure it no longer exists - _logViewer.DeleteSavedSearch("Unit Test Example"); - - searches = _logViewer.GetSavedSearches(); - findItem = searches.Where(x => x.Name == "Unit Test Example" && x.Query == "Has(UnitTest)"); - Assert.IsEmpty(findItem, "The search item should no longer exist"); - } -} - -internal class TestLogViewerQueryRepository : ILogViewerQueryRepository -{ - public TestLogViewerQueryRepository() => - Store = new List(DatabaseDataCreator._defaultLogQueries.Select(LogViewerQueryModelFactory.BuildEntity)); - - private IList Store { get; } - - private LogViewerQueryRepository.LogViewerQueryModelFactory LogViewerQueryModelFactory { get; } = new(); - - public ILogViewerQuery Get(int id) => Store.FirstOrDefault(x => x.Id == id); - - public IEnumerable GetMany(params int[] ids) => - ids.Any() ? Store.Where(x => ids.Contains(x.Id)) : Store; - - public bool Exists(int id) => Get(id) is not null; - - public void Save(ILogViewerQuery entity) - { - var item = Get(entity.Id); - - if (item is null) - { - Store.Add(entity); - } - else - { - item.Name = entity.Name; - item.Query = entity.Query; - } - } - - public void Delete(ILogViewerQuery entity) - { - var item = Get(entity.Id); - - if (item is not null) - { - Store.Remove(item); - } - } - - public IEnumerable Get(IQuery query) => throw new NotImplementedException(); - - public int Count(IQuery query) => throw new NotImplementedException(); - - public ILogViewerQuery GetByName(string name) => Store.FirstOrDefault(x => x.Name == name); -}