├── src ├── RapidCMS.Core.Tests │ ├── .editorconfig │ └── Services │ │ └── Dispatchers │ │ └── TestClasses.cs ├── RapidCMS.UI │ ├── Components │ │ ├── Preview │ │ │ ├── NoPreview.razor │ │ │ └── BasePreview.cs │ │ ├── App.razor │ │ ├── Displays │ │ │ ├── LabelDisplay.razor │ │ │ ├── PreDisplay.razor │ │ │ └── LinkDisplay.razor │ │ ├── Shared │ │ │ ├── EmptyLayout.razor │ │ │ ├── MainLayout.razor │ │ │ ├── Tree │ │ │ │ ├── Page.razor │ │ │ │ └── Page.razor.cs │ │ │ ├── Login.razor │ │ │ ├── TopBar.razor │ │ │ └── NavMenu.razor │ │ ├── Panes │ │ │ ├── SidePane.razor │ │ │ └── BaseSidePane.cs │ │ ├── Editors │ │ │ ├── ReadonlyEditor.razor │ │ │ ├── BaseMultiplePickerEditor.cs │ │ │ ├── BaseRelationEditor.cs │ │ │ ├── TextBoxEditor.razor │ │ │ ├── BaseDataEditor.cs │ │ │ ├── TextAreaEditor.razor │ │ │ ├── CheckboxEditor.razor │ │ │ └── DateEditor.razor │ │ ├── Pages │ │ │ ├── UnauthorizedPage.razor │ │ │ ├── CmsPage.razor │ │ │ └── CmsPage.razor.cs │ │ ├── Icons │ │ │ └── Icon.razor │ │ ├── Sections │ │ │ ├── UnauthorizedSection.razor │ │ │ ├── BaseSection.cs │ │ │ ├── BasePageContextSection.cs │ │ │ └── BaseEditContextSection.cs │ │ ├── Forms │ │ │ ├── CascadingPageContext.razor │ │ │ └── CascadingEditContext.razor │ │ ├── Buttons │ │ │ └── DefaultButton.razor │ │ └── Parts │ │ │ ├── ButtonBar.razor │ │ │ └── ButtonCell.razor │ ├── wwwroot │ │ └── js │ │ │ └── interop.js │ ├── Models │ │ └── ButtonClickEventArgs.cs │ └── Extensions │ │ ├── DisplayTypeExtensions.cs │ │ ├── CustomRegistrationRenderFragmentExtensions.cs │ │ └── SectionUIExtensions.cs ├── RapidCMS.Core │ ├── Models │ │ ├── Setup │ │ │ ├── RelationSetup.cs │ │ │ ├── TypeRegistrationSetup.cs │ │ │ ├── ResolvedSetup.cs │ │ │ ├── ValidationSetup.cs │ │ │ ├── PageSetup.cs │ │ │ ├── ConcreteDataProviderRelationSetup.cs │ │ │ ├── DataProviderRelationSetup.cs │ │ │ ├── RelatedCollectionListSetup.cs │ │ │ ├── RelationDataProviderRelationSetup.cs │ │ │ ├── SubCollectionListSetup.cs │ │ │ ├── ElementSetup.cs │ │ │ ├── TreeElementSetup.cs │ │ │ ├── PropertyFieldSetup.cs │ │ │ ├── CustomPropertyFieldSetup.cs │ │ │ ├── CustomExpressionFieldSetup.cs │ │ │ └── ButtonSetup.cs │ │ ├── Config │ │ │ ├── RelationConfig.cs │ │ │ ├── DefaultButtonConfig.cs │ │ │ ├── Api │ │ │ │ ├── ApiAdvancedConfig.cs │ │ │ │ ├── FileUploadHandlerConfig.cs │ │ │ │ ├── ApiDataViewBuilderConfig.cs │ │ │ │ └── ApiRepositoryConfig.cs │ │ │ ├── ReferencedCollectionListConfig.cs │ │ │ ├── CmsAdvancedConfig.cs │ │ │ ├── NavigationButtonConfig.cs │ │ │ ├── PaneButtonConfig.cs │ │ │ ├── ValidationConfig.cs │ │ │ ├── ReferencedCollectionConfig.cs │ │ │ ├── TreeViewConfig.cs │ │ │ ├── ConcreteDataProviderRelationConfig.cs │ │ │ ├── NodeConfig.cs │ │ │ ├── DataProviderRelationConfig.cs │ │ │ ├── Convention │ │ │ │ ├── ConventionNodeEditorConfig.cs │ │ │ │ ├── ConventionNodeViewConfig.cs │ │ │ │ ├── ConventionListEditorConfig.cs │ │ │ │ └── ConventionListViewConfig.cs │ │ │ ├── EntityVariantConfig.cs │ │ │ ├── CustomButtonConfig.cs │ │ │ ├── RelationDataProviderRelationConfig.cs │ │ │ ├── CollectionListConfig.cs │ │ │ ├── ElementConfig.cs │ │ │ ├── CustomTypeRegistrationConfig.cs │ │ │ ├── ButtonConfig.cs │ │ │ └── ListConfig.cs │ │ ├── Configuration │ │ │ ├── Link.cs │ │ │ └── Picker.cs │ │ ├── Response │ │ │ ├── ApiCommandResponseModel.cs │ │ │ ├── ListViewCommandResponseModel.cs │ │ │ ├── NodeViewCommandResponseModel.cs │ │ │ ├── ListEditorCommandResponseModel.cs │ │ │ ├── FileUploadResponseModel.cs │ │ │ ├── NodeInListViewCommandResponseModel.cs │ │ │ ├── FileUploadValidationResponseModel.cs │ │ │ ├── ViewCommandResponseModel.cs │ │ │ ├── EntitiesResponseModel.cs │ │ │ └── ApiPersistEntityResponseModel.cs │ │ ├── Request │ │ │ ├── Api │ │ │ │ ├── DeleteEntityRequestModel.cs │ │ │ │ ├── PersistReorderRequestModel.cs │ │ │ │ ├── GetEntitiesOfParentRequestModel.cs │ │ │ │ ├── GetEntityRequestModel.cs │ │ │ │ ├── GetEntitiesOfRelationRequestModel.cs │ │ │ │ ├── GetEntitiesRequestModel.cs │ │ │ │ ├── PersistRelatedEntityRequestModel.cs │ │ │ │ ├── PersistEntityRequestModel.cs │ │ │ │ └── EntityDescriptor.cs │ │ │ └── Form │ │ │ │ ├── GetEntitiesOfParentRequestModel.cs │ │ │ │ ├── GetEntitiesOfRelationRequestModel.cs │ │ │ │ ├── PersistRelatedEntityRequestModel.cs │ │ │ │ ├── GetEntityOfPageRequestModel.cs │ │ │ │ ├── GetEntityRequestModel.cs │ │ │ │ ├── GetEntitiesRequestModel.cs │ │ │ │ ├── PersistEntityRequestModel.cs │ │ │ │ ├── PersistEntityCollectionRequestModel.cs │ │ │ │ └── PersistEntitiesRequestModel.cs │ │ ├── ApiBridge │ │ │ ├── Request │ │ │ │ ├── EntityDescriptorModel.cs │ │ │ │ ├── RelationContainerModel.cs │ │ │ │ ├── OrderModel.cs │ │ │ │ ├── DeleteModel.cs │ │ │ │ ├── RelationModel.cs │ │ │ │ ├── ReorderModel.cs │ │ │ │ ├── RelateModel.cs │ │ │ │ ├── UploadFileModel.cs │ │ │ │ ├── OrderByModel.cs │ │ │ │ └── RelatedQueryModel.cs │ │ │ └── Response │ │ │ │ └── EntitiesModel.cs │ │ ├── Data │ │ │ ├── Element.cs │ │ │ ├── ParentEntity.cs │ │ │ ├── RelatedEntity.cs │ │ │ └── OrderBy.cs │ │ ├── UI │ │ │ ├── TabUI.cs │ │ │ ├── TreeRootUI.cs │ │ │ ├── CustomExpressionFieldUI.cs │ │ │ ├── ExpressionFieldUI.cs │ │ │ ├── CustomPropertyFieldUI.cs │ │ │ ├── TreeNodesUI.cs │ │ │ ├── ElementUI.cs │ │ │ ├── PropertyFieldUI.cs │ │ │ ├── SectionUI.cs │ │ │ ├── SubCollectionUI.cs │ │ │ ├── RelatedCollectionUI.cs │ │ │ └── TreePageUI.cs │ │ ├── EventArgs │ │ │ ├── Mediators │ │ │ │ ├── ExceptionEventArgs.cs │ │ │ │ ├── PaneResponseEventArgs.cs │ │ │ │ ├── MessageEventArgs.cs │ │ │ │ ├── NavigationEventArgs.cs │ │ │ │ ├── RepositoryEventArgs.cs │ │ │ │ └── PaneRequestEventArgs.cs │ │ │ └── RowDragEventArgs.cs │ │ ├── Metadata │ │ │ ├── ExpressionMetadata.cs │ │ │ └── FullPropertyMetadata.cs │ │ └── CompositeValidationResult.cs │ ├── Enums │ │ ├── RelationType.cs │ │ ├── ListType.cs │ │ ├── EntityState.cs │ │ ├── EntityVisibilty.cs │ │ ├── ReorderedState.cs │ │ ├── CollectionRootVisibility.cs │ │ ├── EmptyVariantColumnVisibility.cs │ │ ├── MessageType.cs │ │ ├── OrderByType.cs │ │ ├── DisplayType.cs │ │ ├── PageType.cs │ │ ├── ValidationState.cs │ │ ├── Features.cs │ │ ├── CollectionConvention.cs │ │ ├── CrudType.cs │ │ └── UsageType.cs │ ├── Abstractions │ │ ├── Data │ │ │ ├── IEntity.cs │ │ │ ├── IRelated.cs │ │ │ ├── IDataValidationProvider.cs │ │ │ ├── IElement.cs │ │ │ ├── IDataViewBuilder.cs │ │ │ ├── IParent.cs │ │ │ ├── IFileInfo.cs │ │ │ ├── IRelation.cs │ │ │ ├── IRelationDataCollection.cs │ │ │ ├── IOrderBy.cs │ │ │ └── IDataView.cs │ │ ├── Mediators │ │ │ ├── IMediatorEventArgs.cs │ │ │ ├── IMediatorEventListener.cs │ │ │ ├── IMediatorRequestEventArgs.cs │ │ │ ├── IMediatorResponseEventArgs.cs │ │ │ └── IMediator.cs │ │ ├── Setup │ │ │ └── ICms.cs │ │ ├── UI │ │ │ ├── IWantConfiguration.cs │ │ │ ├── IRequireConfiguration.cs │ │ │ └── IBaseUI.cs │ │ ├── Resolvers │ │ │ ├── ILanguageResolver.cs │ │ │ ├── IResolvedSetup.cs │ │ │ ├── IUserResolver.cs │ │ │ ├── ICollectionAliasResolver.cs │ │ │ ├── IButtonActionHandlerResolver.cs │ │ │ ├── IEntityVariantResolver.cs │ │ │ ├── IDataProviderResolver.cs │ │ │ ├── IFieldConfigResolver.cs │ │ │ ├── IRepositoryTypeResolver.cs │ │ │ ├── IConventionBasedResolver.cs │ │ │ ├── IDataViewResolver.cs │ │ │ ├── IRepositoryResolver.cs │ │ │ ├── ISetupResolver.cs │ │ │ ├── INodeUIResolver.cs │ │ │ └── IListUIResolver.cs │ │ ├── Config │ │ │ ├── IOrderByConfig.cs │ │ │ ├── ITreeElementConfig.cs │ │ │ ├── IIsConventionBased.cs │ │ │ ├── IConventionConfig.cs │ │ │ ├── IHasOrderBy.cs │ │ │ ├── IFileUploadHandlerConfig.cs │ │ │ ├── IApiDataViewBuilderConfig.cs │ │ │ ├── ICollectionDetailPageEditorConfig.cs │ │ │ ├── INodeViewConfig.cs │ │ │ ├── INodeEditorConfig.cs │ │ │ ├── ISupportReordering.cs │ │ │ ├── IHasPageSize.cs │ │ │ ├── IAdvancedApiConfig.cs │ │ │ ├── IHasSearchBar.cs │ │ │ ├── IApiRepositoryConfig.cs │ │ │ ├── IHasPlaceholder.cs │ │ │ ├── IListViewConfig.cs │ │ │ ├── ISubCollectionListViewConfig.cs │ │ │ ├── IAdvancedCmsConfig.cs │ │ │ ├── ISubCollectionListEditorConfig.cs │ │ │ ├── IHasColumnVisibility.cs │ │ │ ├── IRelatedCollectionListViewConfig.cs │ │ │ ├── IRelatedCollectionListEditorConfig.cs │ │ │ ├── IListEditorConfig.cs │ │ │ └── IHasNameDescription.cs │ │ ├── Metadata │ │ │ ├── IFullPropertyMetadata.cs │ │ │ ├── IExpressionMetadata.cs │ │ │ └── IPropertyMetadata.cs │ │ ├── Services │ │ │ ├── IInteractionService.cs │ │ │ ├── IParentService.cs │ │ │ ├── IConcurrencyService.cs │ │ │ ├── IPresentationService.cs │ │ │ └── ITreeService.cs │ │ ├── Forms │ │ │ ├── IRelatedViewContext.cs │ │ │ ├── IViewContext.cs │ │ │ └── IRelationContainer.cs │ │ ├── Interactions │ │ │ ├── IButtonInteractionRequestModel.cs │ │ │ ├── IListButtonInteractionRequestModel.cs │ │ │ ├── IEditorInListInteractionRequestModel.cs │ │ │ ├── IDragInteraction.cs │ │ │ └── IButtonInteraction.cs │ │ ├── Dispatchers │ │ │ ├── IInteractionDispatcher.cs │ │ │ └── IPresentationDispatcher.cs │ │ ├── Handlers │ │ │ ├── INavigationHandler.cs │ │ │ └── IFileUploadHandler.cs │ │ ├── Factories │ │ │ ├── IUIResolverFactory.cs │ │ │ └── IEditContextResolver.cs │ │ ├── Validators │ │ │ ├── IEntityValidator.cs │ │ │ ├── IValidatorContext.cs │ │ │ └── IAsyncEntityValidator.cs │ │ └── Plugins │ │ │ └── IPlugin.cs │ ├── Attributes │ │ ├── ConfirmAttribute.cs │ │ ├── ValidFormAttribute.cs │ │ ├── RelationAttribute.cs │ │ ├── ActionsAttribute.cs │ │ ├── DefaultTypeAttribute.cs │ │ └── DefaultIconLabelAttribute.cs │ ├── Exceptions │ │ ├── InvalidEntityException.cs │ │ ├── NotFoundException.cs │ │ ├── NotUniqueException.cs │ │ ├── InvalidExpressionException.cs │ │ └── InvalidPropertyExpressionException.cs │ ├── Forms │ │ ├── ModelStateDictionary.cs │ │ ├── ValidationStateChangedEventArgs.cs │ │ ├── FieldChangedEventArgs.cs │ │ ├── ButtonContext.cs │ │ ├── RelatedViewContext.cs │ │ ├── PageContext.cs │ │ └── ViewContext.cs │ ├── Resolvers │ │ ├── Language │ │ │ └── LanguageResolver.cs │ │ ├── Repositories │ │ │ ├── CollectionAliasResolver.cs │ │ │ ├── RepositoryTypeResolverBase.cs │ │ │ └── EntityVariantResolver.cs │ │ ├── Setup │ │ │ ├── PluginTreeElementsSetupResolver.cs │ │ │ ├── ElementSetupResolver.cs │ │ │ └── TreeViewSetupResolver.cs │ │ └── Buttons │ │ │ └── ButtonActionHandlerResolver.cs │ ├── Extensions │ │ ├── ObjectExtensions.cs │ │ ├── ButtonSetupExtensions.cs │ │ ├── PropertyMetadataExtensions.cs │ │ └── ServiceProviderExtensions.cs │ ├── Helpers │ │ ├── EnumHelper.cs │ │ ├── UriHelper.cs │ │ └── EditorTypeHelper.cs │ ├── EqualityComparers │ │ └── FieldUIEqualityComparer.cs │ ├── Data │ │ └── DataViewBuilder.cs │ ├── Navigation │ │ └── CollectionState.cs │ ├── Authorization │ │ ├── AnonymousAuthenticationStateProvider.cs │ │ └── AllowAllAuthorizationHandler.cs │ ├── Validators │ │ ├── BaseEntityValidator.cs │ │ └── AsyncEntityValidator.cs │ ├── General.cs │ ├── Handlers │ │ └── OpenPaneButtonActionHandler.cs │ └── Services │ │ └── Interaction │ │ └── InteractionService.cs ├── RapidCMS.Api.WebApi │ ├── Controllers │ │ └── IFunctionExecutionContextAccessor.cs │ ├── Resolvers │ │ └── UserResolver.cs │ ├── Providers │ │ └── CollectionControllerFeatureProvider.cs │ ├── Extensions │ │ └── ApiResponseModelExtensions.cs │ └── Conventions │ │ └── CollectionControllerRouteConvention.cs ├── RapidCMS.Repositories │ └── IConverter.cs └── RapidCMS.Api.Core │ ├── Abstractions │ ├── IApiHandlerResolver.cs │ ├── IFileHandlerResolver.cs │ └── IFileHandler.cs │ ├── Models │ ├── ApiRequestModel.cs │ └── ApiResponseModel.cs │ ├── General.cs │ └── Resolvers │ └── AnonymousUserResolver.cs ├── examples ├── RapidCMS.Example.Github │ ├── App.razor │ ├── _Imports.razor │ ├── Entities │ │ ├── Country.cs │ │ ├── Person.cs │ │ ├── Relatable2Person.cs │ │ ├── CountryPerson.cs │ │ ├── RelatablePerson.cs │ │ └── ValidationPerson.cs │ ├── DataViewBuilders │ │ └── CountryDataViewBuilder.cs │ ├── Attributes │ │ └── BioValidationAttribute.cs │ └── wwwroot │ │ └── index.html ├── RapidCMS.Example.Server │ ├── App.razor │ ├── Pages │ │ ├── SignIn.cshtml │ │ ├── SignOut.cshtml │ │ ├── SignIn.cshtml.cs │ │ ├── SignOut.cshtml.cs │ │ └── _Host.cshtml │ ├── Components │ │ ├── LandingPage.razor │ │ ├── LoginScreen.razor │ │ └── LoginStatus.razor │ ├── appsettings.Development.json │ ├── Program.cs │ ├── RapidCMS.Example.Server.csproj │ └── _Imports.razor ├── RapidCMS.Example.WebAssembly │ ├── App.razor │ └── Components │ │ ├── LoginScreen.razor │ │ └── LoginStatus.razor ├── images │ ├── mm1.png │ ├── mm2.png │ ├── mm3.png │ ├── mm4.png │ ├── mm5.png │ ├── mm6.png │ ├── mm7.png │ ├── mm8.png │ ├── mm9.png │ ├── docs1.png │ ├── docs2.png │ ├── docs3.png │ ├── mm10.png │ ├── mm11.png │ ├── mm12.png │ ├── mm13.png │ ├── listview.png │ ├── nodeview.png │ ├── listeditor.png │ └── nodeeditor.png ├── RapidCMS.Example.Shared │ ├── Components │ │ ├── CustomSection.razor │ │ ├── DashboardSection.razor │ │ ├── ImagePreview.razor │ │ ├── CustomButton.razor │ │ └── CustomPageSection.razor │ ├── Handlers │ │ ├── IImageUploadHandler.cs │ │ ├── ITextUploadHandler.cs │ │ ├── Base64ApiImageUploadHandler.cs │ │ ├── Base64ApiTextUploadHandler.cs │ │ └── NavigateToPersonHandler.cs │ ├── Data │ │ ├── MappedEntity.cs │ │ ├── DatabaseEntity.cs │ │ ├── Counter.cs │ │ └── Mapper.cs │ └── AuthorizationHandlers │ │ └── VeryPermissiveAuthorizationHandler.cs └── RapidCMS.Example.WebAssembly.API │ ├── appsettings.Development.json │ ├── Program.cs │ └── RapidCMS.Example.WebAssembly.API.csproj └── SETUP_SERVERSIDE.md /src/RapidCMS.Core.Tests/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Preview/NoPreview.razor: -------------------------------------------------------------------------------- 1 | @inherits BasePreview -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/App.razor: -------------------------------------------------------------------------------- 1 | @layout RapidCMS.UI.Components.Shared.MainLayout -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/App.razor: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/App.razor: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.WebAssembly/App.razor: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/images/mm1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm1.png -------------------------------------------------------------------------------- /examples/images/mm2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm2.png -------------------------------------------------------------------------------- /examples/images/mm3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm3.png -------------------------------------------------------------------------------- /examples/images/mm4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm4.png -------------------------------------------------------------------------------- /examples/images/mm5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm5.png -------------------------------------------------------------------------------- /examples/images/mm6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm6.png -------------------------------------------------------------------------------- /examples/images/mm7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm7.png -------------------------------------------------------------------------------- /examples/images/mm8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm8.png -------------------------------------------------------------------------------- /examples/images/mm9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm9.png -------------------------------------------------------------------------------- /examples/images/docs1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/docs1.png -------------------------------------------------------------------------------- /examples/images/docs2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/docs2.png -------------------------------------------------------------------------------- /examples/images/docs3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/docs3.png -------------------------------------------------------------------------------- /examples/images/mm10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm10.png -------------------------------------------------------------------------------- /examples/images/mm11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm11.png -------------------------------------------------------------------------------- /examples/images/mm12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm12.png -------------------------------------------------------------------------------- /examples/images/mm13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/mm13.png -------------------------------------------------------------------------------- /examples/images/listview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/listview.png -------------------------------------------------------------------------------- /examples/images/nodeview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/nodeview.png -------------------------------------------------------------------------------- /examples/images/listeditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/listeditor.png -------------------------------------------------------------------------------- /examples/images/nodeeditor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasBleijendaal/RapidCMS/HEAD/examples/images/nodeeditor.png -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/RelationSetup.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Setup; 2 | 3 | public class RelationSetup 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/Pages/SignIn.cshtml: -------------------------------------------------------------------------------- 1 | @page "/SignIn" 2 | 3 | @model RapidCMS.Example.Server.Pages.SignInModel 4 | @{ 5 | } 6 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/Pages/SignOut.cshtml: -------------------------------------------------------------------------------- 1 | @page "/SignOut" 2 | 3 | @model RapidCMS.Example.Server.Pages.SignOutModel 4 | @{ 5 | } 6 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/RelationType.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Enums; 2 | 3 | public enum RelationType 4 | { 5 | One, 6 | Many 7 | } 8 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/RelationConfig.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RapidCMS.Core.Models.Config; 3 | 4 | internal class RelationConfig 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/ListType.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Enums; 2 | 3 | public enum ListType 4 | { 5 | Table = 0, 6 | Block = 1 7 | } 8 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Configuration/Link.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Configuration; 2 | 3 | public record Link(string? Label, bool NewTab); 4 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/EntityState.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RapidCMS.Core.Enums; 3 | 4 | public enum EntityState 5 | { 6 | IsNew, 7 | IsExisting 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Displays/LabelDisplay.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseDisplay 2 | 3 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/EntityVisibilty.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RapidCMS.Core.Enums; 3 | 4 | public enum EntityVisibilty 5 | { 6 | Visible, 7 | Hidden 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/ApiCommandResponseModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Response; 2 | 3 | public class ApiCommandResponseModel 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/ReorderedState.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RapidCMS.Core.Enums; 3 | 4 | public enum ReorderedState 5 | { 6 | Unmodified, 7 | Reordered 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IEntity.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Data; 2 | 3 | public interface IEntity 4 | { 5 | string? Id { get; set; } 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Mediators; 2 | 3 | public interface IMediatorEventArgs 4 | { 5 | } 6 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Shared/EmptyLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits Microsoft.AspNetCore.Components.LayoutComponentBase 2 | 3 | 6 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/wwwroot/js/interop.js: -------------------------------------------------------------------------------- 1 | window['RapidCMS'] = { 2 | scrollToTop: function (id) { 3 | document.getElementById(id).scroll(0, 0); 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Components/CustomSection.razor: -------------------------------------------------------------------------------- 1 |
2 |

Custom section

3 |

This section is just a Blazor Component.

4 |
-------------------------------------------------------------------------------- /src/RapidCMS.Core/Attributes/ConfirmAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Attributes; 4 | 5 | internal class ConfirmAttribute : Attribute 6 | { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/CollectionRootVisibility.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace RapidCMS.Core.Enums; 3 | 4 | public enum CollectionRootVisibility 5 | { 6 | Visible, 7 | Hidden 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.WebApi/Controllers/IFunctionExecutionContextAccessor.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Api.WebApi.Controllers; 2 | 3 | public interface IFunctionExecutionContextAccessor 4 | { 5 | } -------------------------------------------------------------------------------- /src/RapidCMS.Core/Attributes/ValidFormAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Attributes; 4 | 5 | internal class ValidFormAttribute : Attribute 6 | { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Components/DashboardSection.razor: -------------------------------------------------------------------------------- 1 |
2 |

Custom dashboard

3 |

This dashboard is custom blazor component.

4 |
-------------------------------------------------------------------------------- /src/RapidCMS.Core/Exceptions/InvalidEntityException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Exceptions; 4 | 5 | public class InvalidEntityException : Exception 6 | { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/EmptyVariantColumnVisibility.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Enums; 2 | 3 | public enum EmptyVariantColumnVisibility 4 | { 5 | Collapse = 0, 6 | Visible = 1 7 | } 8 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/MessageType.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Enums; 2 | 3 | public enum MessageType 4 | { 5 | Information, 6 | Success, 7 | Warning, 8 | Error 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Repositories/IConverter.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Repositories; 2 | 3 | public interface IConverter 4 | { 5 | TA Convert(TB obj); 6 | TB Convert(TA obj); 7 | } 8 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/Components/LandingPage.razor: -------------------------------------------------------------------------------- 1 |
2 |

Hi!

3 | 4 |

Welcome! Please wait until someone gives you the proper clearance.

5 |
-------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/ListViewCommandResponseModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Response; 2 | 3 | public class ListViewCommandResponseModel : ViewCommandResponseModel 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/NodeViewCommandResponseModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Response; 2 | 3 | public class NodeViewCommandResponseModel : ViewCommandResponseModel 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Panes/SidePane.razor: -------------------------------------------------------------------------------- 1 | @inherits DisposableComponent 2 | 3 | @if (Component != null) 4 | { 5 |
6 | @Component 7 |
8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Setup/ICms.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Setup; 2 | 3 | public interface ICms 4 | { 5 | string SiteName { get; } 6 | bool IsDevelopment { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/UI/IWantConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.UI; 2 | 3 | public interface IWantConfiguration : IBaseUIElement 4 | where TConfig : class 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Forms/ModelStateDictionary.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RapidCMS.Core.Forms; 4 | 5 | public class ModelStateDictionary : Dictionary 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/ListEditorCommandResponseModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Response; 2 | 3 | public class ListEditorCommandResponseModel : ViewCommandResponseModel 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Editors/ReadonlyEditor.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseEditor 2 | 3 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Pages/UnauthorizedPage.razor: -------------------------------------------------------------------------------- 1 | @page "/unauthorized" 2 | 3 | @layout EmptyLayout 4 | 5 |

Unauthorized

6 |

You are not authorized to view this data.

7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/ILanguageResolver.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Resolvers; 2 | 3 | public interface ILanguageResolver 4 | { 5 | string ResolveText(string originalText); 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/OrderByType.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Enums; 2 | 3 | public enum OrderByType 4 | { 5 | Disabled = 0, 6 | Ascending = 1, 7 | Descending = 2, 8 | None = 99 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/FileUploadResponseModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Response; 2 | 3 | public class FileUploadResponseModel 4 | { 5 | public object Result { get; set; } = default!; 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/NodeInListViewCommandResponseModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Response; 2 | 3 | public class NodeInListViewCommandResponseModel : ViewCommandResponseModel 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/Components/LoginScreen.razor: -------------------------------------------------------------------------------- 1 |

Hi!

2 | 3 |

Please sign in to access the CMS.

4 | 5 |
6 | 7 | Login via OIDC -------------------------------------------------------------------------------- /src/RapidCMS.Api.Core/Abstractions/IApiHandlerResolver.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Api.Core.Abstractions; 2 | 3 | public interface IApiHandlerResolver 4 | { 5 | IApiHandler GetApiHandler(string repositoryAlias); 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.Core/Models/ApiRequestModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Api.Core.Models; 2 | 3 | public class ApiRequestModel 4 | { 5 | public string? Id { get; set; } 6 | public string? Body { get; set; } 7 | } 8 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IOrderByConfig.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Config; 2 | 3 | public interface IOrderByConfig : IHasOrderBy> 4 | { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IResolvedSetup.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Resolvers; 2 | 3 | public interface IResolvedSetup 4 | { 5 | T Setup { get; } 6 | bool Cachable { get; } 7 | } 8 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/UI/IRequireConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.UI; 2 | 3 | public interface IRequireConfiguration : IBaseUIElement 4 | where TConfig : class 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/DisplayType.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Enums; 2 | 3 | public enum DisplayType 4 | { 5 | None = -99, 6 | Custom = -1, 7 | 8 | Label = 0, 9 | Pre, 10 | Link 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.Core/Abstractions/IFileHandlerResolver.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Api.Core.Abstractions; 2 | 3 | public interface IFileHandlerResolver 4 | { 5 | IFileHandler GetFileHandler(string uploadHandlerAlias); 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/ITreeElementConfig.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Config; 2 | 3 | public interface ITreeElementConfig 4 | { 5 | string Alias { get; } 6 | string Name { get; } 7 | } 8 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.Core/General.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("RapidCMS.Api.Functions")] 4 | [assembly: InternalsVisibleTo("RapidCMS.Api.WebApi")] 5 | 6 | namespace RapidCMS.Api.Core; 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IIsConventionBased.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | internal interface IIsConventionBased 6 | { 7 | Features GetFeatures(); 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IUserResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | 3 | namespace RapidCMS.Core.Abstractions.Resolvers; 4 | 5 | internal interface IUserResolver 6 | { 7 | ClaimsPrincipal? GetUser(); 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Api/DeleteEntityRequestModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Request.Api; 2 | 3 | public class DeleteEntityRequestModel 4 | { 5 | public EntityDescriptor Descriptor { get; set; } = default!; 6 | } 7 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Handlers/IImageUploadHandler.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Handlers; 2 | 3 | namespace RapidCMS.Example.Shared.Handlers; 4 | 5 | public interface IImageUploadHandler : IFileUploadHandler 6 | { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Handlers/ITextUploadHandler.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Handlers; 2 | 3 | namespace RapidCMS.Example.Shared.Handlers; 4 | 5 | public interface ITextUploadHandler : IFileUploadHandler 6 | { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/PageType.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Enums; 2 | 3 | public enum PageType 4 | { 5 | Node = 1, 6 | Collection = 2, 7 | Page = 3, 8 | Dashboard = 4, 9 | Error = 5, 10 | Unauthorized = 6 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Pages/CmsPage.razor: -------------------------------------------------------------------------------- 1 | @inherits DisposableComponent 2 | 3 | @attribute [Authorize] 4 | 5 | @layout MainLayout 6 | 7 | @page "/{*PageRoute}" 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Components/ImagePreview.razor: -------------------------------------------------------------------------------- 1 | @inherits BasePreview 2 | 3 | @if (PreviewValue is string base64String) 4 | { 5 |
6 | 7 |
8 | } -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Editors/BaseMultiplePickerEditor.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.UI.Components.Editors; 2 | 3 | public abstract class BaseMultiplePickerEditor : BasePicker 4 | { 5 | protected override bool IsMultiple { get; set; } = true; 6 | } 7 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IRelated.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Data; 2 | 3 | public interface IRelated 4 | { 5 | IParent? Parent { get; } 6 | IEntity Entity { get; } 7 | 8 | string RepositoryAlias { get; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IConventionConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | public interface IConventionConfig 6 | where TEntity : IEntity 7 | { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Mediators/IMediatorEventListener.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Abstractions.Mediators; 4 | 5 | public interface IMediatorEventListener : IDisposable 6 | { 7 | void RegisterListener(IMediator mediator); 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Metadata/IFullPropertyMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Abstractions.Metadata; 4 | 5 | public interface IFullPropertyMetadata : IPropertyMetadata 6 | { 7 | Action Setter { get; } 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/DefaultButtonConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | 3 | namespace RapidCMS.Core.Models.Config; 4 | 5 | internal class DefaultButtonConfig : ButtonConfig 6 | { 7 | internal DefaultButtonType ButtonType { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IHasOrderBy.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Config; 2 | 3 | public interface IHasOrderBy : 4 | IHasOrderByEntity, 5 | IHasOrderByDatabaseEntity 6 | { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IDataValidationProvider.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Metadata; 2 | 3 | namespace RapidCMS.Core.Abstractions.Data; 4 | 5 | internal interface IDataValidationProvider 6 | { 7 | IPropertyMetadata Property { get; } 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IElement.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RapidCMS.Core.Abstractions.Data; 4 | 5 | public interface IElement 6 | { 7 | object Id { get; } 8 | 9 | IEnumerable Labels { get; } 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Exceptions/NotFoundException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Exceptions; 4 | 5 | public class NotFoundException : Exception 6 | { 7 | public NotFoundException(string message) : base(message) 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Configuration/Picker.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Configuration; 2 | 3 | public record Picker( 4 | bool EnableSelectAll = false, 5 | bool EnableUnselectAll = false, 6 | bool EnableReset = false, 7 | int PageSize = 25); 8 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.WebAssembly.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IFileUploadHandlerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | public interface IFileUploadHandlerConfig 6 | { 7 | string Alias { get; } 8 | Type HandlerType { get; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Mediators/IMediatorRequestEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Abstractions.Mediators; 4 | 5 | public interface IMediatorRequestEventArgs : IMediatorEventArgs 6 | { 7 | Guid RequestId { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IApiDataViewBuilderConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | public interface IApiDataViewBuilderConfig 6 | { 7 | string Alias { get; } 8 | Type DataViewBuilder { get; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Services/IInteractionService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace RapidCMS.Core.Abstractions.Services; 4 | 5 | public interface IInteractionService 6 | { 7 | Task InteractAsync(TRequest request); 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Api/PersistReorderRequestModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Request.Api; 2 | 3 | public class PersistReorderRequestModel 4 | { 5 | public string? BeforeId { get; set; } 6 | public EntityDescriptor Subject { get; set; } = default!; 7 | } 8 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.WebAssembly/Components/LoginScreen.razor: -------------------------------------------------------------------------------- 1 | @inject NavigationManager Navigation 2 | 3 |

Hi!

4 | 5 |

Please sign in to access the CMS.

6 | 7 |
8 | 9 | Login via OIDC 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Metadata/IExpressionMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Abstractions.Metadata; 4 | 5 | public interface IExpressionMetadata 6 | { 7 | string PropertyName { get; } 8 | Func StringGetter { get; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/ValidationState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Enums; 4 | 5 | [Flags] 6 | public enum ValidationState 7 | { 8 | None = 0, 9 | 10 | NotValidated = 1, 11 | Valid = 2, 12 | Invalid = 4, 13 | 14 | Modified = 128 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/Api/ApiAdvancedConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Config; 2 | 3 | namespace RapidCMS.Core.Models.Config.Api; 4 | 5 | internal class ApiAdvancedConfig : IAdvancedApiConfig 6 | { 7 | public bool RemoveDataAnnotationEntityValidator { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IDataViewBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace RapidCMS.Core.Abstractions.Data; 5 | 6 | public interface IDataViewBuilder 7 | { 8 | Task> GetDataViewsAsync(); 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IParent.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Models.Data; 2 | 3 | namespace RapidCMS.Core.Abstractions.Data; 4 | 5 | public interface IParent 6 | { 7 | IParent? Parent { get; } 8 | IEntity Entity { get; } 9 | 10 | ParentPath? GetParentPath(); 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/ICollectionAliasResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RapidCMS.Core.Abstractions.Resolvers; 4 | 5 | internal interface ICollectionAliasResolver 6 | { 7 | public IReadOnlyList GetAlias(string repositoryAlias); 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/Features.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Enums; 4 | 5 | [Flags] 6 | public enum Features 7 | { 8 | None = 0, 9 | CanGoToView = 1, 10 | CanGoToEdit = 2, 11 | CanView = 4, 12 | CanEdit = 8, 13 | IsBlockList = 65536 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfParentRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Models.Data; 2 | 3 | namespace RapidCMS.Core.Models.Request.Api; 4 | 5 | public class GetEntitiesOfParentRequestModel : GetEntitiesRequestModel 6 | { 7 | public string? ParentPath { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/FileUploadValidationResponseModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RapidCMS.Core.Models.Response; 4 | 5 | public class FileUploadValidationResponseModel 6 | { 7 | public IEnumerable ErrorMessages { get; set; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfParentRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Models.Data; 2 | 3 | namespace RapidCMS.Core.Models.Request.Form; 4 | 5 | public class GetEntitiesOfParentRequestModel : GetEntitiesRequestModel 6 | { 7 | public ParentPath? ParentPath { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Icons/Icon.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | @code { 4 | [Parameter] public string? Name { get; set; } 5 | [Parameter] public string? Color { get; set; } 6 | } -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/CollectionConvention.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Enums; 2 | 3 | public enum CollectionConvention 4 | { 5 | ListView = 1, 6 | ListViewNodeView = 2, 7 | ListViewNodeEditor = 3, 8 | ListEditor = 4, 9 | ListBlockEditor = 5, 10 | ListEditorNodeEditor = 6 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/EntityDescriptorModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.ApiBridge.Request; 2 | 3 | public class EntityDescriptorModel 4 | { 5 | public string? Id { get; set; } 6 | public string? RepositoryAlias { get; set; } 7 | public string? ParentPath { get; set; } 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/ReferencedCollectionListConfig.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Config; 2 | 3 | internal class ReferencedCollectionListConfig : CollectionListConfig 4 | { 5 | internal ReferencedCollectionListConfig(string collectionAlias) : base(collectionAlias) 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Form/GetEntitiesOfRelationRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Models.Request.Form; 4 | 5 | public class GetEntitiesOfRelationRequestModel : GetEntitiesRequestModel 6 | { 7 | public IRelated Related { get; set; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Form/PersistRelatedEntityRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Models.Request.Form; 4 | 5 | public class PersistRelatedEntityRequestModel : PersistEntityRequestModel 6 | { 7 | public IRelated Related { get; set; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Sections/UnauthorizedSection.razor: -------------------------------------------------------------------------------- 1 |
2 |

Unauthorized

3 |

You are unauthorized to perform the requested action.

4 |

Return to home and start again.

5 |
-------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Api/GetEntityRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | 3 | namespace RapidCMS.Core.Models.Request.Api; 4 | 5 | public class GetEntityRequestModel 6 | { 7 | public UsageType UsageType { get; set; } 8 | public EntityDescriptor Subject { get; set; } = default!; 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Mediators/IMediatorResponseEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Abstractions.Mediators; 4 | 5 | public interface IMediatorResponseEventArgs : IMediatorEventArgs 6 | { 7 | Guid RequestId { get; set; } 8 | TResponse Response { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Api/GetEntitiesOfRelationRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Models.Request.Api; 4 | 5 | public class GetEntitiesOfRelationRequestModel : GetEntitiesRequestModel 6 | { 7 | public EntityDescriptor Related { get; set; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Form/GetEntityOfPageRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Models.Data; 2 | 3 | namespace RapidCMS.Core.Models.Request.Form; 4 | 5 | public class GetEntityOfPageRequestModel 6 | { 7 | public string PageAlias { get; set; } 8 | public ParentPath? ParentPath { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Exceptions/NotUniqueException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Exceptions; 4 | 5 | public class NotUniqueException : Exception 6 | { 7 | public NotUniqueException(string attribute) : base($"Value of {attribute} is not globally unique in this context.") 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using Microsoft.AspNetCore.Components.WebAssembly.Http 7 | @using Microsoft.JSInterop 8 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/Components/LoginStatus.razor: -------------------------------------------------------------------------------- 1 | 2 |
3 |
Hi, @context.User.Identity?.Name!
4 | Logout 5 |
6 | 7 |
8 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/ICollectionDetailPageEditorConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | public interface ICollectionDetailPageEditorConfig : INodeEditorConfig 6 | where TDetailEntity : IEntity 7 | { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Forms/ValidationStateChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Forms; 2 | 3 | public class ValidationStateChangedEventArgs 4 | { 5 | public ValidationStateChangedEventArgs(bool? isValid = null) 6 | { 7 | IsValid = isValid; 8 | } 9 | 10 | public bool? IsValid { get; private set; } 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/CmsAdvancedConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Config; 2 | 3 | namespace RapidCMS.Core.Models.Config; 4 | 5 | internal class CmsAdvancedConfig : IAdvancedCmsConfig 6 | { 7 | public int SemaphoreCount { get; set; } 8 | public bool RemoveDataAnnotationEntityValidator { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Forms/IRelatedViewContext.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Abstractions.Forms; 4 | 5 | public interface IRelatedViewContext : IViewContext 6 | { 7 | /// 8 | /// The related entity 9 | /// 10 | IRelated Related { get; } 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Data/Element.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Core.Models.Data; 5 | 6 | public class Element : IElement 7 | { 8 | public object Id { get; set; } = default!; 9 | public IEnumerable Labels { get; set; } = default!; 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Resolvers/Language/LanguageResolver.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Resolvers; 2 | 3 | namespace RapidCMS.Core.Resolvers.Language; 4 | 5 | internal class LanguageResolver : ILanguageResolver 6 | { 7 | public string ResolveText(string originalText) 8 | { 9 | return originalText; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Services/IParentService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Models.Data; 4 | 5 | namespace RapidCMS.Core.Abstractions.Services; 6 | 7 | public interface IParentService 8 | { 9 | Task GetParentAsync(ParentPath? parentPath); 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/RelationContainerModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace RapidCMS.Core.Models.ApiBridge.Request; 5 | 6 | public class RelationContainerModel 7 | { 8 | public IEnumerable Relations { get; set; } = Enumerable.Empty(); 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/ViewCommandResponseModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RapidCMS.Core.Models.Response; 4 | 5 | public class ViewCommandResponseModel 6 | { 7 | public IEnumerable RefreshIds { get; internal set; } = new List(); 8 | public bool NoOp { get; internal set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 5 |
6 | 7 | 10 | 11 |
12 | 13 | 14 | 15 | @Body 16 |
17 | 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Response/EntitiesModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RapidCMS.Core.Models.ApiBridge.Response; 4 | 5 | public class EntitiesModel 6 | { 7 | public IEnumerable> Entities { get; set; } = default!; 8 | public bool MoreDataAvailable { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Models/ButtonClickEventArgs.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Forms; 2 | 3 | namespace RapidCMS.UI.Models; 4 | 5 | public class ButtonClickEventArgs 6 | { 7 | public ButtonViewModel ViewModel { get; set; } = default!; 8 | public FormEditContext EditContext { get; set; } = default!; 9 | public object? Data { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Interactions/IButtonInteractionRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Forms; 2 | 3 | namespace RapidCMS.Core.Abstractions.Interactions; 4 | 5 | public interface IEditorButtonInteractionRequestModel 6 | { 7 | string ActionId { get; } 8 | FormEditContext EditContext { get; } 9 | object? CustomData { get; } 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Interactions/IListButtonInteractionRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Forms; 2 | 3 | namespace RapidCMS.Core.Abstractions.Interactions; 4 | 5 | public interface IListButtonInteractionRequestModel 6 | { 7 | string ActionId { get; } 8 | ListContext ListContext { get; } 9 | object? CustomData { get; } 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IButtonActionHandlerResolver.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Handlers; 2 | using RapidCMS.Core.Models.Setup; 3 | 4 | namespace RapidCMS.Core.Abstractions.Resolvers; 5 | 6 | internal interface IButtonActionHandlerResolver 7 | { 8 | IButtonActionHandler GetButtonActionHandler(ButtonSetup button); 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IEntityVariantResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace RapidCMS.Core.Abstractions.Resolvers; 5 | 6 | public interface IEntityVariantResolver 7 | { 8 | (Type? baseType, IReadOnlyList? derivedTypes) GetValidVariantsForRepository(string repositoryAlias); 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Attributes/RelationAttribute.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | using System; 3 | 4 | namespace RapidCMS.Core.Attributes; 5 | 6 | public class RelationAttribute : Attribute 7 | { 8 | public RelationAttribute(RelationType type) 9 | { 10 | Type = type; 11 | } 12 | 13 | public RelationType Type { get; } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Forms/CascadingPageContext.razor: -------------------------------------------------------------------------------- 1 | 2 | @ChildContent 3 | 4 | 5 | @code { 6 | [Parameter] public RenderFragment ChildContent { get; set; } = default!; 7 | [Parameter] public PageContext PageContext { get; set; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Preview/BasePreview.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Microsoft.AspNetCore.Components; 5 | 6 | namespace RapidCMS.UI.Components.Preview; 7 | 8 | public class BasePreview : ComponentBase 9 | { 10 | [Parameter] 11 | public object? PreviewValue { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Forms/CascadingEditContext.razor: -------------------------------------------------------------------------------- 1 | 2 | @ChildContent 3 | 4 | 5 | @code { 6 | [Parameter] public RenderFragment ChildContent { get; set; } = default!; 7 | [Parameter] public FormEditContext EditContext { get; set; } = default!; 8 | } 9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/INodeViewConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | public interface INodeViewConfig 6 | : IHasButtons>, 7 | IHasDisplayPanes> 8 | where TEntity : IEntity 9 | { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IDataProviderResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Models.Setup; 3 | using RapidCMS.Core.Providers; 4 | 5 | namespace RapidCMS.Core.Abstractions.Resolvers; 6 | 7 | internal interface IDataProviderResolver 8 | { 9 | Task GetDataProviderAsync(FieldSetup field); 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Services/IConcurrencyService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace RapidCMS.Core.Abstractions.Services; 5 | 6 | public interface IConcurrencyService 7 | { 8 | Task EnsureCorrectConcurrencyAsync(Func function); 9 | Task EnsureCorrectConcurrencyAsync(Func> function); 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Exceptions/InvalidExpressionException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Exceptions; 4 | 5 | public class InvalidExpressionException : Exception 6 | { 7 | public InvalidExpressionException(string attribute) : base($"Cannot process expression in {attribute} to Func (StringGetter).") 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/OrderModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | 3 | namespace RapidCMS.Core.Models.ApiBridge.Request; 4 | 5 | public class OrderModel 6 | { 7 | public string PropertyName { get; set; } = default!; 8 | public string Fingerprint { get; set; } = default!; 9 | public OrderByType OrderByType { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/NavigationButtonConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Config; 4 | 5 | internal class NavigationButtonConfig : ButtonConfig 6 | { 7 | internal NavigationButtonConfig(Type handlerType) 8 | { 9 | HandlerType = handlerType; 10 | } 11 | 12 | internal Type HandlerType { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/INodeEditorConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | public interface INodeEditorConfig 6 | : IHasButtons>, 7 | IHasEditorPanes> 8 | where TEntity : IEntity 9 | { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/ISupportReordering.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Config; 2 | 3 | public interface ISupportReordering 4 | { 5 | /// 6 | /// Allows entities to be reordered in the ListEditor. 7 | /// 8 | /// 9 | TReturn AllowReordering(bool allowReordering); 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IFileInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace RapidCMS.Core.Abstractions.Data; 5 | 6 | public interface IFileInfo 7 | { 8 | string Name { get; } 9 | long Size { get; } 10 | string Type { get; } 11 | long? LastModified { get; } 12 | DateTime? LastModifiedDate { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Extensions/ObjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Extensions; 4 | 5 | public static class ObjectExtensions 6 | { 7 | public static T If(this T subject, bool shouldDo, Func method) 8 | { 9 | return shouldDo 10 | ? method.Invoke(subject) 11 | : subject; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IHasPageSize.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Config; 2 | 3 | public interface IHasPageSize 4 | { 5 | /// 6 | /// Sets the pagesize of the ListEditor. 7 | /// 8 | /// 9 | /// 10 | TReturn SetPageSize(int pageSize); 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/Api/FileUploadHandlerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Config; 3 | 4 | namespace RapidCMS.Core.Models.Config.Api; 5 | 6 | internal class FileUploadHandlerConfig : IFileUploadHandlerConfig 7 | { 8 | public string Alias { get; set; } = default!; 9 | public Type HandlerType { get; set; } = default!; 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/EntitiesResponseModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Core.Models.Response; 5 | 6 | public class EntitiesResponseModel 7 | { 8 | public IEnumerable Entities { get; set; } = default!; 9 | 10 | public bool MoreDataAvailable { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Attributes/ActionsAttribute.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | using System; 3 | 4 | namespace RapidCMS.Core.Attributes; 5 | 6 | internal class ActionsAttribute : Attribute 7 | { 8 | public ActionsAttribute(params UsageType[] usages) 9 | { 10 | Usages = usages; 11 | } 12 | 13 | public UsageType[] Usages { get; private set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IFieldConfigResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RapidCMS.Core.Enums; 4 | using RapidCMS.Core.Models.Config; 5 | 6 | namespace RapidCMS.Core.Abstractions.Resolvers; 7 | 8 | internal interface IFieldConfigResolver 9 | { 10 | IEnumerable GetFields(Type subject, Features features); 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Dispatchers/IInteractionDispatcher.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace RapidCMS.Core.Abstractions.Dispatchers; 4 | 5 | internal interface IInteractionDispatcher 6 | { 7 | } 8 | 9 | internal interface IInteractionDispatcher : IInteractionDispatcher 10 | { 11 | Task InvokeAsync(TRequest request); 12 | } 13 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/Api/ApiDataViewBuilderConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Config; 3 | 4 | namespace RapidCMS.Core.Models.Config.Api; 5 | 6 | internal class ApiDataViewBuilderConfig : IApiDataViewBuilderConfig 7 | { 8 | public string Alias { get; set; } = default!; 9 | 10 | public Type DataViewBuilder { get; set; } = default!; 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/TabUI.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Navigation; 2 | 3 | namespace RapidCMS.Core.Models.UI; 4 | 5 | public class TabUI 6 | { 7 | public TabUI(int id) 8 | { 9 | Id = id; 10 | } 11 | 12 | public int Id { get; private set; } 13 | public string? Label { get; internal set; } 14 | public SortBag? DefaultSorts { get; internal set; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IAdvancedApiConfig.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Config; 2 | 3 | public interface IAdvancedApiConfig 4 | { 5 | /// 6 | /// Setting this true prevents DataAnnotationEntityValidator from being added to all repositories automatically. 7 | /// 8 | bool RemoveDataAnnotationEntityValidator { get; set; } 9 | } 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Attributes/DefaultTypeAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace RapidCMS.Core.Attributes; 5 | 6 | internal class DefaultTypeAttribute : Attribute 7 | { 8 | public DefaultTypeAttribute(params Type[] types) 9 | { 10 | Types = types; 11 | } 12 | 13 | public IEnumerable Types { get; private set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Helpers/EnumHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace RapidCMS.Core.Helpers; 6 | 7 | internal static class EnumHelper 8 | { 9 | public static IEnumerable GetValues() 10 | where TEnum : Enum 11 | { 12 | return Enum.GetValues(typeof(TEnum)).Cast(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/PaneButtonConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Config; 4 | 5 | internal class PaneButtonConfig : ButtonConfig 6 | { 7 | internal PaneButtonConfig(Type paneType) 8 | { 9 | PaneType = paneType ?? throw new ArgumentNullException(nameof(paneType)); 10 | } 11 | 12 | internal Type PaneType { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Response/ApiPersistEntityResponseModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Forms; 3 | 4 | namespace RapidCMS.Core.Models.Response; 5 | 6 | public class ApiPersistEntityResponseModel : ApiCommandResponseModel 7 | { 8 | public IEntity? NewEntity { get; set; } 9 | public ModelStateDictionary? ValidationErrors { get; set; } 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/TypeRegistrationSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace RapidCMS.Core.Models.Setup; 5 | 6 | public class TypeRegistrationSetup 7 | { 8 | public Type Type { get; set; } = default!; 9 | public string Alias { get; set; } = default!; 10 | public Dictionary? Parameters { get; set; } = default!; 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Interactions/IEditorInListInteractionRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Forms; 2 | 3 | namespace RapidCMS.Core.Abstractions.Interactions; 4 | 5 | public interface IEditorInListInteractionRequestModel 6 | { 7 | string ActionId { get; } 8 | FormEditContext EditContext { get; } 9 | ListContext ListContext { get; } 10 | object? CustomData { get; } 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/TreeRootUI.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Models.UI; 5 | 6 | public class TreeRootUI : TreeNodeUI 7 | { 8 | public TreeRootUI(string id, string repositoryAlias, string name, List<(string alias, PageType type)> collections) : base(id, repositoryAlias, name, collections) 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Components/CustomButton.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseButton 2 | 3 | @using RapidCMS.UI.Components.Buttons 4 | 5 | 8 | 9 | @code { 10 | private async void DoItAsync() 11 | { 12 | await ButtonClickAsync(); 13 | } 14 | } -------------------------------------------------------------------------------- /examples/RapidCMS.Example.WebAssembly/Components/LoginStatus.razor: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Components.Authorization 2 | 3 | 4 |
5 |
Hi, @context.User.Identity?.Name!
6 | Logout 7 |
8 |
9 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryTypeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Abstractions.Resolvers; 4 | 5 | public interface IRepositoryTypeResolver 6 | { 7 | public Type GetType(string repositoryAlias); 8 | public (Type entityType, Type databaseType) GetEntityTypes(string repositoryAlias); 9 | public string GetAlias(Type originallyRegisterdType); 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IHasSearchBar.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Config; 2 | 3 | public interface IHasSearchBar 4 | { 5 | /// 6 | /// Sets the visibility of the search bar atop of the ListEditor. 7 | /// 8 | /// 9 | /// 10 | TReturn SetSearchBarVisibility(bool visible); 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Forms/FieldChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Metadata; 2 | 3 | namespace RapidCMS.Core.Forms; 4 | 5 | public class FieldChangedEventArgs 6 | { 7 | public FieldChangedEventArgs(IPropertyMetadata fullPropertyMetadata) 8 | { 9 | FullPropertyMetadata = fullPropertyMetadata; 10 | } 11 | 12 | public IPropertyMetadata FullPropertyMetadata { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Api/GetEntitiesRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Models.Request.Api; 5 | 6 | public class GetEntitiesRequestModel 7 | { 8 | public UsageType UsageType { get; set; } 9 | public string RepositoryAlias { get; set; } = default!; 10 | public IView View { get; set; } = default!; 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IApiRepositoryConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Validators; 3 | 4 | namespace RapidCMS.Core.Abstractions.Config; 5 | 6 | public interface IApiRepositoryConfig 7 | { 8 | string Alias { get; } 9 | Type EntityType { get; } 10 | Type? DatabaseType { get; } 11 | Type RepositoryType { get; } 12 | Type ApiRepositoryType { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IHasPlaceholder.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Config; 2 | 3 | public interface IHasPlaceholder 4 | { 5 | /// 6 | /// Sets the placeholder of this field, displayed in the editor. 7 | /// 8 | /// 9 | /// 10 | TReturn SetPlaceholder(string placeholder); 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/UI/IBaseUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using RapidCMS.Core.Abstractions.Data; 4 | using RapidCMS.Core.Enums; 5 | 6 | namespace RapidCMS.Core.Abstractions.UI; 7 | 8 | public interface IBaseUIElement 9 | { 10 | IEntity Entity { get; } 11 | EntityState EntityState { get; } 12 | Func>? Configuration { get; } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Displays/PreDisplay.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseDisplay 2 | 3 |
@value
4 | 5 | @code { 6 | private string? value { get; set; } 7 | 8 | protected override void OnParametersSet() 9 | { 10 | value = GetValueAsString(); 11 | 12 | if (string.IsNullOrWhiteSpace(value)) 13 | { 14 | value = " "; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Dispatchers/IPresentationDispatcher.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace RapidCMS.Core.Abstractions.Dispatchers; 4 | 5 | internal interface IPresentationDispatcher 6 | { 7 | 8 | } 9 | 10 | internal interface IPresentationDispatcher : IPresentationDispatcher 11 | where TResponse : class 12 | { 13 | Task GetAsync(TRequest request); 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Handlers/INavigationHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Forms; 3 | using RapidCMS.Core.Models.Request; 4 | using RapidCMS.Core.Models.Setup; 5 | 6 | namespace RapidCMS.Core.Abstractions.Handlers; 7 | 8 | public interface INavigationHandler 9 | { 10 | Task CreateNavigationRequestAsync(ButtonSetup button, FormEditContext editContext); 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IConventionBasedResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using RapidCMS.Core.Enums; 4 | using RapidCMS.Core.Models.Setup; 5 | 6 | namespace RapidCMS.Core.Abstractions.Resolvers; 7 | 8 | public interface IConventionBasedResolver 9 | { 10 | Task ResolveByConventionAsync(Type subject, Features features, CollectionSetup? collection); 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Exceptions/InvalidPropertyExpressionException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Exceptions; 4 | 5 | public class InvalidPropertyExpressionException : Exception 6 | { 7 | public InvalidPropertyExpressionException(string attribute) : base($"Cannot process property expression in {attribute} to Func and Action (Getter and Setter).") 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/DeleteModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Models.ApiBridge.Request; 4 | 5 | public class DeleteModel 6 | { 7 | public DeleteModel() { } 8 | 9 | public DeleteModel(IParent? parent) 10 | { 11 | ParentPath = parent?.GetParentPath()?.ToPathString(); 12 | } 13 | 14 | public string? ParentPath { get; set; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/EventArgs/Mediators/ExceptionEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Mediators; 3 | 4 | namespace RapidCMS.Core.Models.EventArgs.Mediators; 5 | 6 | public class ExceptionEventArgs : IMediatorEventArgs 7 | { 8 | public ExceptionEventArgs(Exception exception) 9 | { 10 | Exception = exception; 11 | } 12 | 13 | public Exception Exception { get; } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IDataViewResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using RapidCMS.Core.Abstractions.Data; 5 | 6 | namespace RapidCMS.Core.Abstractions.Resolvers; 7 | 8 | internal interface IDataViewResolver 9 | { 10 | Task> GetDataViewsAsync(string collectionAlias); 11 | Task ApplyDataViewToViewAsync(IView view); 12 | } 13 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/RelationModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace RapidCMS.Core.Models.ApiBridge.Request; 5 | 6 | public class RelationModel 7 | { 8 | public string VariantAlias { get; set; } = default!; 9 | public string PropertyName { get; set; } = default!; 10 | public IEnumerable Elements { get; set; } = Enumerable.Empty(); 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Shared/Tree/Page.razor: -------------------------------------------------------------------------------- 1 | @inject ITreeService TreeService 2 | 3 | @if (UI == null) 4 | { 5 |
  • Loading tree..
  • 6 | } 7 | else if (!string.IsNullOrWhiteSpace(Error)) 8 | { 9 |
  • @Error
  • 10 | } 11 | else 12 | { 13 | 16 | } 17 | 18 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Handlers/Base64ApiImageUploadHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using RapidCMS.Core.Handlers; 3 | 4 | namespace RapidCMS.Example.Shared.Handlers; 5 | 6 | public class Base64ApiImageUploadHandler : ApiFileUploadHandler, IImageUploadHandler 7 | { 8 | public Base64ApiImageUploadHandler(IHttpClientFactory httpClientFactory) : base(httpClientFactory) 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Handlers/Base64ApiTextUploadHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using RapidCMS.Core.Handlers; 3 | 4 | namespace RapidCMS.Example.Shared.Handlers; 5 | 6 | public class Base64ApiTextUploadHandler : ApiFileUploadHandler, ITextUploadHandler 7 | { 8 | public Base64ApiTextUploadHandler(IHttpClientFactory httpClientFactory) : base(httpClientFactory) 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IRelation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RapidCMS.Core.Abstractions.Metadata; 4 | 5 | namespace RapidCMS.Core.Abstractions.Data; 6 | 7 | public interface IRelation 8 | { 9 | Type RelatedEntityType { get; } 10 | IPropertyMetadata Property { get; } 11 | IReadOnlyList RelatedElementIds { get; } 12 | IReadOnlyList RelatedElementIdsAs(); 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/CustomExpressionFieldUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Models.Setup; 3 | 4 | namespace RapidCMS.Core.Models.UI; 5 | 6 | public class CustomExpressionFieldUI : ExpressionFieldUI 7 | { 8 | internal CustomExpressionFieldUI(CustomExpressionFieldSetup field) : base(field) 9 | { 10 | CustomType = field.CustomType; 11 | } 12 | 13 | public Type CustomType { get; private set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Editors/BaseRelationEditor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.UI.Components.Editors; 5 | 6 | public class BaseRelationEditor : BaseEditor 7 | { 8 | [Parameter] public IDataCollection? DataCollection { get; set; } 9 | 10 | public IRelationDataCollection? RelationDataCollection => DataCollection as IRelationDataCollection; 11 | } 12 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Forms/ButtonContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Core.Forms; 5 | 6 | public sealed class ButtonContext 7 | { 8 | public ButtonContext(IParent? parent, object? customData) 9 | { 10 | Parent = parent; 11 | CustomData = customData; 12 | } 13 | 14 | public IParent? Parent { get; set; } 15 | public object? CustomData { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.Core/Abstractions/IFileHandler.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Threading.Tasks; 3 | using RapidCMS.Api.Core.Models; 4 | using RapidCMS.Core.Models.ApiBridge.Request; 5 | 6 | namespace RapidCMS.Api.Core.Abstractions; 7 | 8 | public interface IFileHandler 9 | { 10 | Task ValidateFileAsync(UploadFileModel request); 11 | Task SaveFileAsync(UploadFileModel request, Stream fileStream); 12 | } 13 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Handlers/IFileUploadHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Threading.Tasks; 4 | using RapidCMS.Core.Abstractions.Data; 5 | 6 | namespace RapidCMS.Core.Abstractions.Handlers; 7 | 8 | public interface IFileUploadHandler 9 | { 10 | Task> ValidateFileAsync(IFileInfo fileInfo); 11 | 12 | Task SaveFileAsync(IFileInfo fileInfo, Stream stream); 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Api/PersistRelatedEntityRequestModel.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Request.Api; 2 | 3 | public class PersistRelatedEntityRequestModel 4 | { 5 | public EntityDescriptor Subject { get; set; } = default!; 6 | public EntityDescriptor Related { get; set; } = default!; 7 | 8 | public Actions Action { get; set; } 9 | 10 | public enum Actions 11 | { 12 | Add, 13 | Remove 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/ResolvedSetup.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Resolvers; 2 | 3 | namespace RapidCMS.Core.Models.Setup; 4 | 5 | public struct ResolvedSetup : IResolvedSetup 6 | { 7 | public ResolvedSetup(T setup, bool cachable) 8 | { 9 | Setup = setup; 10 | Cachable = cachable; 11 | } 12 | 13 | public T Setup { get; private set; } 14 | 15 | public bool Cachable { get; private set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/ValidationSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Setup; 4 | 5 | public class ValidationSetup 6 | { 7 | public ValidationSetup(Type type, object? configuration) 8 | { 9 | Type = type ?? throw new ArgumentNullException(nameof(type)); 10 | Configuration = configuration; 11 | } 12 | 13 | public Type Type { get; set; } 14 | public object? Configuration { get; set; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/ExpressionFieldUI.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | using RapidCMS.Core.Models.Setup; 3 | 4 | namespace RapidCMS.Core.Models.UI; 5 | 6 | public class ExpressionFieldUI : FieldUI 7 | { 8 | internal ExpressionFieldUI(ExpressionFieldSetup field) : base(field) 9 | { 10 | Expression = field.Expression; 11 | Type = field.DisplayType; 12 | } 13 | 14 | public DisplayType Type { get; private set; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/PageSetup.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace RapidCMS.Core.Models.Setup; 4 | 5 | internal class PageSetup 6 | { 7 | public string Name { get; set; } = default!; 8 | public string Alias { get; set; } = default!; 9 | public string Icon { get; set; } = default!; 10 | public string Color { get; set; } = default!; 11 | public List Sections { get; set; } = default!; 12 | } 13 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Forms/IViewContext.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Abstractions.Forms; 4 | 5 | public interface IViewContext 6 | { 7 | /// 8 | /// Alias of the collection this view is used 9 | /// 10 | string? CollectionAlias { get; } 11 | 12 | /// 13 | /// Possible parent(s) of the subject 14 | /// 15 | IParent? Parent { get; } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/ValidationConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Config; 4 | 5 | internal class ValidationConfig 6 | { 7 | public ValidationConfig(Type type, object? configuration) 8 | { 9 | Type = type ?? throw new ArgumentNullException(nameof(type)); 10 | Configuration = configuration; 11 | } 12 | 13 | public Type Type { get; set; } 14 | public object? Configuration { get; set; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Metadata/IPropertyMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace RapidCMS.Core.Abstractions.Metadata; 5 | 6 | public interface IPropertyMetadata 7 | { 8 | Type PropertyType { get; } 9 | string PropertyName { get; } 10 | Type ObjectType { get; } 11 | Func Getter { get; } 12 | 13 | string Fingerprint { get; } 14 | 15 | LambdaExpression OriginalExpression { get; } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/EventArgs/RowDragEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.EventArgs; 4 | 5 | public sealed class RowDragEventArgs 6 | { 7 | public RowDragEventArgs(string subjectId, string? targetId) 8 | { 9 | SubjectId = subjectId ?? throw new ArgumentNullException(nameof(subjectId)); 10 | TargetId = targetId; 11 | } 12 | 13 | public string SubjectId { get; } 14 | public string? TargetId { get; } 15 | } 16 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/Entities/Country.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Example.Github.Entities; 5 | 6 | internal class Country : IEntity, ICloneable 7 | { 8 | public string? Id { get; set; } 9 | public string? Name { get; set; } 10 | 11 | public object Clone() 12 | { 13 | return new Country 14 | { 15 | Id = Id, 16 | Name = Name 17 | }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IRepositoryResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Repositories; 3 | using RapidCMS.Core.Models.Setup; 4 | 5 | namespace RapidCMS.Core.Abstractions.Resolvers; 6 | 7 | public interface IRepositoryResolver 8 | { 9 | internal IRepository GetRepository(CollectionSetup collection); 10 | public IRepository GetRepository(string repositoryAlias); 11 | public IRepository GetRepository(Type repositoryType); 12 | } 13 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Shared/Login.razor: -------------------------------------------------------------------------------- 1 | @if (CustomElement != null) 2 | { 3 | @CustomElement 4 | } 5 | else 6 | { 7 |

    User login required

    8 |

    9 | Configure a login component using config.SetCustomLoginScreen(typeof(YourLoginControl)), or 10 | use config.AllowAnonymousUser() to allow any user. 11 |

    12 | } 13 | 14 | @code { 15 | [Parameter] 16 | public RenderFragment? CustomElement { get; set; } 17 | } -------------------------------------------------------------------------------- /src/RapidCMS.Api.Core/Resolvers/AnonymousUserResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using RapidCMS.Core.Abstractions.Resolvers; 3 | 4 | namespace RapidCMS.Api.Core.Resolvers; 5 | 6 | internal class AnonymousUserResolver : IUserResolver 7 | { 8 | public ClaimsPrincipal? GetUser() 9 | { 10 | var id = new ClaimsIdentity("anonymous"); 11 | id.AddClaim(new Claim(ClaimTypes.Name, "Anonymous")); 12 | 13 | return new ClaimsPrincipal(id); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/ReferencedCollectionConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Abstractions.Repositories; 3 | 4 | namespace RapidCMS.Core.Models.Config; 5 | 6 | internal class ReferencedCollectionConfig : CollectionConfig 7 | { 8 | internal ReferencedCollectionConfig(string alias) 9 | : base(alias, default, default, default, "reference", typeof(IRepository), new EntityVariantConfig("", typeof(IEntity))) 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Form/GetEntityRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | using RapidCMS.Core.Models.Data; 3 | 4 | namespace RapidCMS.Core.Models.Request.Form; 5 | 6 | public class GetEntityRequestModel 7 | { 8 | public UsageType UsageType { get; set; } 9 | public string CollectionAlias { get; set; } = default!; 10 | public string? VariantAlias { get; set; } 11 | public ParentPath? ParentPath { get; set; } 12 | public string? Id { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Editors/TextBoxEditor.razor: -------------------------------------------------------------------------------- 1 | @inherits BasePropertyEditor 2 | 3 | SetValueFromStringAsync(((string?)args.Value) ?? "")) 5 | disabled=@IsDisabled 6 | placeholder=@Placeholder 7 | class="form-control @(CssHelper.GetValidationClass(State))" /> 8 | 9 | @foreach (var message in GetValidationMessages()) 10 | { 11 |
    12 | @message 13 |
    14 | } -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/Pages/SignIn.cshtml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Mvc.RazorPages; 4 | 5 | namespace RapidCMS.Example.Server.Pages; 6 | 7 | public class SignInModel : PageModel 8 | { 9 | public IActionResult OnGet() 10 | { 11 | return Challenge(new AuthenticationProperties 12 | { 13 | RedirectUri = Url.Content("~/") 14 | }, "OpenIdConnect"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IListViewConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | public interface IListViewConfig 6 | : IHasButtons>, 7 | IHasPageSize>, 8 | IHasSearchBar>, 9 | IHasDisplayTable>, 10 | IHasColumnVisibility> 11 | where TEntity : IEntity 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Form/GetEntitiesRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Models.Request.Form; 5 | 6 | public class GetEntitiesRequestModel 7 | { 8 | public UsageType UsageType { get; set; } 9 | public bool IsEmbedded { get; set; } 10 | public string CollectionAlias { get; set; } = default!; 11 | public string? VariantAlias { get; set; } 12 | public IView View { get; set; } = default!; 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Editors/BaseDataEditor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.UI.Components.Editors; 5 | 6 | public class BaseDataEditor : BasePropertyEditor 7 | { 8 | [Parameter] public IDataCollection? DataCollection { get; set; } 9 | 10 | // TODO: check if this is needed 11 | public override void Dispose() 12 | { 13 | base.Dispose(); 14 | 15 | DataCollection?.Dispose(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/Pages/SignOut.cshtml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authentication; 2 | using Microsoft.AspNetCore.Mvc; 3 | using Microsoft.AspNetCore.Mvc.RazorPages; 4 | 5 | namespace RapidCMS.Example.Server.Pages; 6 | 7 | public class SignOutModel : PageModel 8 | { 9 | public IActionResult OnGet() 10 | { 11 | return SignOut(new AuthenticationProperties 12 | { 13 | RedirectUri = Url.Content("~/") 14 | }, "Cookies", "OpenIdConnect"); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/CustomPropertyFieldUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Models.Setup; 3 | using RapidCMS.Core.Providers; 4 | 5 | namespace RapidCMS.Core.Models.UI; 6 | 7 | public class CustomPropertyFieldUI : PropertyFieldUI 8 | { 9 | internal CustomPropertyFieldUI(CustomPropertyFieldSetup field, FormDataProvider? dataProvider) : base(field, dataProvider) 10 | { 11 | CustomType = field.CustomType; 12 | } 13 | 14 | public Type CustomType { get; private set; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Attributes/DefaultIconLabelAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Attributes; 4 | 5 | internal class DefaultIconLabelAttribute : Attribute 6 | { 7 | public DefaultIconLabelAttribute(string icon, string label) 8 | { 9 | Icon = icon ?? throw new ArgumentNullException(nameof(icon)); 10 | Label = label ?? throw new ArgumentNullException(nameof(label)); 11 | } 12 | 13 | public string Icon { get; set; } 14 | public string Label { get; set; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/TreeNodesUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace RapidCMS.Core.Models.UI; 5 | 6 | public class TreeNodesUI 7 | { 8 | public TreeNodesUI(List nodes, bool moreDataAvailable) 9 | { 10 | Nodes = nodes ?? throw new ArgumentNullException(nameof(nodes)); 11 | MoreDataAvailable = moreDataAvailable; 12 | } 13 | 14 | public List Nodes { get; set; } 15 | public bool MoreDataAvailable { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Editors/TextAreaEditor.razor: -------------------------------------------------------------------------------- 1 | @inherits BasePropertyEditor 2 | 3 | 8 | 9 | @foreach (var message in GetValidationMessages()) 10 | { 11 |
    12 | @message 13 |
    14 | } -------------------------------------------------------------------------------- /src/RapidCMS.Core/EqualityComparers/FieldUIEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using RapidCMS.Core.Models.UI; 3 | 4 | namespace RapidCMS.Core.EqualityComparers; 5 | 6 | internal class FieldUIEqualityComparer : IEqualityComparer 7 | { 8 | public bool Equals(FieldUI? x, FieldUI? y) 9 | { 10 | return x?.Name?.Equals(y?.Name) ?? false; 11 | } 12 | 13 | public int GetHashCode(FieldUI obj) 14 | { 15 | return obj.Name?.GetHashCode() ?? default; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Data/MappedEntity.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Example.Shared.Data; 5 | 6 | public class MappedEntity : IEntity 7 | { 8 | public string? Id { get; set; } 9 | 10 | [Required] 11 | [MinLength(5)] 12 | [MaxLength(20)] 13 | public string? Name { get; set; } 14 | 15 | [Required] 16 | [MinLength(10)] 17 | [MaxLength(1000)] 18 | public string? Description { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/CrudType.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Enums; 2 | 3 | public enum CrudType 4 | { 5 | // none 6 | None = 0, 7 | 8 | // viewers 9 | View = 1, 10 | List = 1, 11 | Create = 2, 12 | Edit = 3, 13 | 14 | // modifiers 15 | Insert = 4, 16 | Update = 5, 17 | Delete = 6, 18 | 19 | // list action 20 | Add = 100, 21 | Remove = 101, 22 | Pick = 102, 23 | 24 | // navigation actions 25 | Return = 1000, 26 | Refresh = 1001, 27 | Up = 1002 28 | } 29 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Extensions/ButtonSetupExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using RapidCMS.Core.Extensions; 4 | using RapidCMS.Core.Models.Setup; 5 | 6 | namespace RapidCMS.Core.Extensions; 7 | 8 | internal static class ButtonSetupExtensions 9 | { 10 | public static IEnumerable GetAllButtons(this IEnumerable buttons) 11 | { 12 | return buttons.SelectMany(x => x.Buttons.Any() ? x.Buttons.AsEnumerable() : new[] { x }).ToList(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/TreeViewConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Metadata; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Models.Config; 5 | 6 | internal class TreeViewConfig 7 | { 8 | internal EntityVisibilty EntityVisibilty { get; set; } 9 | internal CollectionRootVisibility RootVisibility { get; set; } 10 | internal bool DefaultOpenEntities { get; set; } 11 | internal bool DefaultOpenCollections { get; set; } 12 | internal IExpressionMetadata? Name { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/ConcreteDataProviderRelationSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Core.Models.Setup; 5 | 6 | public class ConcreteDataProviderRelationSetup : RelationSetup 7 | { 8 | public ConcreteDataProviderRelationSetup(IDataCollection dataCollection) 9 | { 10 | DataCollection = dataCollection ?? throw new ArgumentNullException(nameof(dataCollection)); 11 | } 12 | 13 | public IDataCollection DataCollection { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/Api/ApiRepositoryConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Config; 3 | 4 | namespace RapidCMS.Core.Models.Config.Api; 5 | 6 | internal class ApiRepositoryConfig : IApiRepositoryConfig 7 | { 8 | public string Alias { get; set; } = default!; 9 | public Type EntityType { get; set; } = default!; 10 | public Type? DatabaseType { get; set; } 11 | public Type RepositoryType { get; set; } = default!; 12 | public Type ApiRepositoryType { get; set; } = default!; 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/ConcreteDataProviderRelationConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Core.Models.Config; 5 | 6 | internal class ConcreteDataProviderRelationConfig : RelationConfig 7 | { 8 | internal ConcreteDataProviderRelationConfig(IDataCollection dataCollection) 9 | { 10 | DataCollection = dataCollection ?? throw new ArgumentNullException(nameof(dataCollection)); 11 | } 12 | 13 | internal IDataCollection DataCollection { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Sections/BaseSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Components; 3 | using RapidCMS.Core.Models.UI; 4 | 5 | namespace RapidCMS.UI.Components.Sections; 6 | 7 | /// 8 | /// Use this section on the dashboard and in pages nested in collections that do not require access to the entity. 9 | /// 10 | public class BaseSection : ComponentBase 11 | { 12 | [Parameter] public SectionUI? Section { get; set; } 13 | 14 | protected Guid SectionId { get; } = Guid.NewGuid(); 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Enums/UsageType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Enums; 4 | 5 | [Flags] 6 | public enum UsageType 7 | { 8 | None = 0, 9 | 10 | View = 1, 11 | New = 2, 12 | Edit = 4, 13 | Add = 8, 14 | Pick = 16, 15 | Reordered = 32, 16 | 17 | List = 65536, 18 | Node = 131072, 19 | Details = 262144, 20 | 21 | // Root = root of page 22 | Root = 2097152, 23 | // NotRoot = embedded collection on a page 24 | NotRoot = 4194304, 25 | 26 | ViewOrEdit = View | Edit 27 | } 28 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Forms/RelatedViewContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Abstractions.Forms; 4 | 5 | namespace RapidCMS.Core.Forms; 6 | 7 | internal class RelatedViewContext : ViewContext, IRelatedViewContext 8 | { 9 | public RelatedViewContext(IRelated related, string? collectionAlias, IParent? parent) : base(collectionAlias, parent) 10 | { 11 | Related = related ?? throw new ArgumentNullException(nameof(related)); 12 | } 13 | 14 | public IRelated Related { get; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/ISetupResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Models.Setup; 3 | 4 | namespace RapidCMS.Core.Abstractions.Resolvers; 5 | 6 | public interface ISetupResolver 7 | { 8 | Task ResolveSetupAsync(); 9 | Task ResolveSetupAsync(string alias); 10 | } 11 | 12 | public interface ISetupResolver 13 | where TConfig : notnull 14 | { 15 | Task> ResolveSetupAsync(TConfig config, CollectionSetup? collection = default); 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/NodeConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace RapidCMS.Core.Models.Config; 5 | 6 | internal class NodeConfig 7 | { 8 | internal NodeConfig(Type baseType) 9 | { 10 | BaseType = baseType ?? throw new ArgumentNullException(nameof(baseType)); 11 | } 12 | 13 | internal Type BaseType { get; set; } 14 | internal List Buttons { get; set; } = new List(); 15 | internal List Panes { get; set; } = new List(); 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/DataProviderRelationSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Setup; 4 | 5 | public class DataProviderRelationSetup : RelationSetup 6 | { 7 | public DataProviderRelationSetup(Type dataCollectionType, object? configuration) 8 | { 9 | DataCollectionType = dataCollectionType ?? throw new ArgumentNullException(nameof(dataCollectionType)); 10 | Configuration = configuration; 11 | } 12 | 13 | public Type DataCollectionType { get; } 14 | public object? Configuration { get; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Factories/IUIResolverFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using RapidCMS.Core.Abstractions.Resolvers; 4 | using RapidCMS.Core.Navigation; 5 | 6 | namespace RapidCMS.Core.Abstractions.Factories; 7 | 8 | public interface IUIResolverFactory 9 | { 10 | Task GetNodeUIResolverAsync(NavigationState navigationState); 11 | 12 | Task GetListUIResolverAsync(NavigationState navigationState); 13 | 14 | Task GetConventionNodeUIResolverAsync(Type model); 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/INodeUIResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using RapidCMS.Core.Forms; 4 | using RapidCMS.Core.Models.UI; 5 | using RapidCMS.Core.Navigation; 6 | 7 | namespace RapidCMS.Core.Abstractions.Resolvers; 8 | 9 | public interface INodeUIResolver 10 | { 11 | Task> GetButtonsForEditContextAsync(FormEditContext editContext); 12 | Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState); 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Services/IPresentationService.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using RapidCMS.Core.Models.Setup; 4 | 5 | namespace RapidCMS.Core.Abstractions.Services; 6 | 7 | public interface IPresentationService 8 | { 9 | Task GetEntityAsync(TRequest request) where TResult : class; 10 | Task GetEntitiesAsync(TRequest request) where TResult : class; 11 | 12 | Task> GetPageAsync(string pageAlias); 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Forms/PageContext.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Forms; 4 | 5 | public sealed class PageContext 6 | { 7 | internal PageContext( 8 | string pageAlias, 9 | IEntity? entity, 10 | IParent? parent) 11 | { 12 | PageAlias = pageAlias; 13 | Entity = entity; 14 | Parent = parent; 15 | } 16 | 17 | public string PageAlias { get; private set; } 18 | public IEntity? Entity { get; private set; } 19 | public IParent? Parent { get; private set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/DataProviderRelationConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Config; 4 | 5 | internal class DataProviderRelationConfig : RelationConfig 6 | { 7 | internal DataProviderRelationConfig(Type dataCollectionType, object? configuration) 8 | { 9 | DataCollectionType = dataCollectionType ?? throw new ArgumentNullException(nameof(dataCollectionType)); 10 | Configuration = configuration; 11 | } 12 | 13 | public Type DataCollectionType { get; } 14 | public object? Configuration { get; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IRelationDataCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace RapidCMS.Core.Abstractions.Data; 6 | 7 | public interface IRelationDataCollection : IDataCollection 8 | { 9 | Task> GetRelatedElementsAsync(); 10 | 11 | void AddElement(object id); 12 | void RemoveElement(object id); 13 | 14 | bool IsRelated(object id); 15 | 16 | IReadOnlyList GetCurrentRelatedElementIds(); 17 | 18 | Type GetRelatedEntityType(); 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Services/ITreeService.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Models.Data; 3 | using RapidCMS.Core.Models.UI; 4 | 5 | namespace RapidCMS.Core.Abstractions.Services; 6 | 7 | public interface ITreeService 8 | { 9 | Task GetCollectionAsync(string alias, ParentPath? parentPath); 10 | Task GetPageAsync(string alias, ParentPath? parentPath); 11 | Task GetNodesAsync(string alias, ParentPath? parentPath, int pageNr, int pageSize); 12 | Task GetRootAsync(); 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Validators/IEntityValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using RapidCMS.Core.Abstractions.Data; 4 | 5 | namespace RapidCMS.Core.Abstractions.Validators; 6 | 7 | public interface IEntityValidator 8 | { 9 | IEnumerable Validate(IValidatorContext context); 10 | } 11 | 12 | public interface IEntityValidator : IEntityValidator 13 | where TEntity : IEntity 14 | { 15 | IEnumerable Validate(IValidatorContext context); 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Validators/IValidatorContext.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Abstractions.Forms; 3 | 4 | namespace RapidCMS.Core.Abstractions.Validators; 5 | 6 | public interface IValidatorContext 7 | { 8 | IEntity Entity { get; } 9 | IRelationContainer RelationContainer { get; } 10 | object? Configuration { get; } 11 | } 12 | 13 | public interface IValidatorContext 14 | { 15 | TEntity Entity { get; } 16 | IRelationContainer RelationContainer { get; } 17 | object? Configuration { get; } 18 | } 19 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/Convention/ConventionNodeEditorConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Config; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.Config.Convention; 6 | 7 | internal class ConventionNodeEditorConfig : NodeConfig, IIsConventionBased 8 | where TEntity : IEntity 9 | { 10 | public ConventionNodeEditorConfig() : base(typeof(TEntity)) 11 | { 12 | } 13 | 14 | public Features GetFeatures() 15 | { 16 | return Features.CanEdit; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/EventArgs/Mediators/PaneResponseEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Mediators; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.EventArgs.Mediators; 6 | 7 | public class PaneResponseEventArgs : IMediatorResponseEventArgs 8 | { 9 | public PaneResponseEventArgs(Guid requestId, CrudType response) 10 | { 11 | RequestId = requestId; 12 | Response = response; 13 | } 14 | 15 | public Guid RequestId { get; set; } 16 | public CrudType Response { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Form/PersistEntityRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Interactions; 2 | using RapidCMS.Core.Forms; 3 | using RapidCMS.Core.Navigation; 4 | 5 | namespace RapidCMS.Core.Models.Request.Form; 6 | 7 | public class PersistEntityRequestModel : IEditorButtonInteractionRequestModel 8 | { 9 | public FormEditContext EditContext { get; set; } = default!; 10 | public NavigationState NavigationState { get; set; } = default!; 11 | public string ActionId { get; set; } = default!; 12 | public object? CustomData { get; set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Extensions/DisplayTypeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Enums; 3 | using RapidCMS.UI.Components.Displays; 4 | 5 | namespace RapidCMS.UI.Extensions; 6 | 7 | public static class DisplayTypeExtensions 8 | { 9 | public static Type? GetDisplay(this DisplayType displayType) 10 | => displayType switch 11 | { 12 | DisplayType.Label => typeof(LabelDisplay), 13 | DisplayType.Pre => typeof(PreDisplay), 14 | DisplayType.Link => typeof(LinkDisplay), 15 | _ => null 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Forms/ViewContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Abstractions.Forms; 4 | 5 | namespace RapidCMS.Core.Forms; 6 | 7 | internal class ViewContext : IViewContext 8 | { 9 | public static ViewContext Default => new(null, default); 10 | 11 | public ViewContext(string? collectionAlias, IParent? parent) 12 | { 13 | CollectionAlias = collectionAlias; 14 | Parent = parent; 15 | } 16 | 17 | public string? CollectionAlias { get; } 18 | 19 | public IParent? Parent { get; } 20 | } 21 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/EntityVariantConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Config; 4 | 5 | internal class EntityVariantConfig 6 | { 7 | internal EntityVariantConfig(string name, Type type, string? icon = null) 8 | { 9 | Name = name ?? throw new ArgumentNullException(nameof(name)); 10 | Type = type ?? throw new ArgumentNullException(nameof(type)); 11 | Icon = icon; 12 | } 13 | 14 | internal string Name { get; set; } 15 | internal string? Icon { get; set; } 16 | internal Type Type { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/EventArgs/Mediators/MessageEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Mediators; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.EventArgs.Mediators; 6 | 7 | public class MessageEventArgs : IMediatorEventArgs 8 | { 9 | public MessageEventArgs(MessageType type, string content) 10 | { 11 | Type = type; 12 | Content = content ?? throw new ArgumentNullException(nameof(content)); 13 | } 14 | 15 | public MessageType Type { get; set; } 16 | public string Content { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Data/DatabaseEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Example.Shared.Data; 5 | 6 | public class DatabaseEntity : IEntity, ICloneable 7 | { 8 | public string? Id { get; set; } 9 | public string? Name { get; set; } 10 | public string? Description { get; set; } 11 | 12 | public object Clone() 13 | { 14 | return new DatabaseEntity 15 | { 16 | Id = Id, 17 | Description = Description, 18 | Name = Name 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/Convention/ConventionNodeViewConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Config; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.Config.Convention; 6 | 7 | internal class ConventionNodeViewConfig : NodeConfig, IIsConventionBased 8 | where TEntity : IEntity 9 | { 10 | public ConventionNodeViewConfig() : base(typeof(TEntity)) 11 | { 12 | } 13 | 14 | public Features GetFeatures() 15 | { 16 | return Features.CanView; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace RapidCMS.Example.Server; 5 | 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Plugins/IPlugin.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using RapidCMS.Core.Abstractions.Resolvers; 5 | using RapidCMS.Core.Models.Setup; 6 | 7 | namespace RapidCMS.Core.Abstractions.Plugins; 8 | 9 | public interface IPlugin 10 | { 11 | Task> GetTreeElementsAsync(); 12 | 13 | Task?> GetCollectionAsync(string collectionAlias); 14 | 15 | Type? GetRepositoryType(string collectionAlias); 16 | 17 | string CollectionPrefix { get; } 18 | } 19 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Api/PersistEntityRequestModel.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.Request.Api; 6 | 7 | public class PersistEntityRequestModel 8 | { 9 | public IEntity Entity { get; set; } = default!; 10 | public EntityDescriptor Descriptor { get; set; } = default!; 11 | public EntityState EntityState { get; set; } 12 | public IEnumerable<(string propertyName, string variantAlias, IEnumerable elements)> Relations { get; set; } = default!; 13 | } 14 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Data/Counter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Attributes; 4 | 5 | namespace RapidCMS.Example.Shared.Data; 6 | 7 | public class Counter : IEntity, ICloneable 8 | { 9 | public string? Id { get; set; } 10 | 11 | [Field(Name = "Current count", ListName = "Current count")] 12 | public int CurrentCount { get; set; } 13 | 14 | public object Clone() 15 | { 16 | return new Counter() 17 | { 18 | CurrentCount = CurrentCount, 19 | Id = Id 20 | }; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.WebApi/Resolvers/UserResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using Microsoft.AspNetCore.Http; 3 | using RapidCMS.Core.Abstractions.Resolvers; 4 | 5 | namespace RapidCMS.Api.WebApi.Resolvers; 6 | 7 | internal class UserResolver : IUserResolver 8 | { 9 | private readonly IHttpContextAccessor _httpContextAccessor; 10 | 11 | public UserResolver(IHttpContextAccessor httpContextAccessor) 12 | { 13 | _httpContextAccessor = httpContextAccessor; 14 | } 15 | 16 | public ClaimsPrincipal? GetUser() 17 | => _httpContextAccessor.HttpContext?.User; 18 | } 19 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/RelatedCollectionListSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Models.Setup; 5 | 6 | public class RelatedCollectionListSetup 7 | { 8 | public RelatedCollectionListSetup(int index, string collectionAlias) 9 | { 10 | Index = index; 11 | CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); 12 | } 13 | 14 | public int Index { get; set; } 15 | public string CollectionAlias { get; set; } 16 | 17 | public UsageType SupportsUsageType { get; set; } 18 | } 19 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/Entities/Person.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Example.Github.Entities; 5 | 6 | internal class Person : IEntity, ICloneable 7 | { 8 | public string? Id { get; set; } 9 | public string? Name { get; set; } 10 | public string? Email { get; set; } 11 | public string? Bio { get; set; } 12 | 13 | public object Clone() 14 | { 15 | return new Person 16 | { 17 | Bio = Bio, 18 | Email = Email, 19 | Id = Id, 20 | Name = Name 21 | }; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/RelationDataProviderRelationSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Setup; 4 | 5 | public class RelationDataProviderRelationSetup : RelationSetup 6 | { 7 | public RelationDataProviderRelationSetup(Type relationDataCollectionType, object? configuration) 8 | { 9 | RelationDataCollectionType = relationDataCollectionType ?? throw new ArgumentNullException(nameof(relationDataCollectionType)); 10 | Configuration = configuration; 11 | } 12 | 13 | public Type RelationDataCollectionType { get; } 14 | public object? Configuration { get; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/CustomButtonConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Models.Config; 3 | 4 | namespace RapidCMS.Core.Models.Config; 5 | 6 | internal class CustomButtonConfig : ButtonConfig 7 | { 8 | internal CustomButtonConfig(Type customButtonType, Type actionHandler) 9 | { 10 | CustomType = customButtonType ?? throw new ArgumentNullException(nameof(customButtonType)); 11 | ActionHandler = actionHandler ?? throw new ArgumentNullException(nameof(actionHandler)); 12 | } 13 | 14 | internal Type CustomType { get; set; } 15 | internal Type ActionHandler { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Buttons/DefaultButton.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseButton 2 | 3 | 19 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/RelationDataProviderRelationConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Config; 4 | 5 | internal class RelationDataProviderRelationConfig : RelationConfig 6 | { 7 | internal RelationDataProviderRelationConfig(Type relationDataCollectionType, object? configuration) 8 | { 9 | RelationDataCollectionType = relationDataCollectionType ?? throw new ArgumentNullException(nameof(relationDataCollectionType)); 10 | Configuration = configuration; 11 | } 12 | 13 | public Type RelationDataCollectionType { get; } 14 | public object? Configuration { get; } 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Resolvers/Repositories/CollectionAliasResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using RapidCMS.Core.Abstractions.Resolvers; 3 | 4 | namespace RapidCMS.Core.Resolvers.Repositories; 5 | 6 | internal class CollectionAliasResolver : ICollectionAliasResolver 7 | { 8 | private readonly IReadOnlyDictionary> _aliases; 9 | 10 | public CollectionAliasResolver(IReadOnlyDictionary> aliases) 11 | { 12 | _aliases = aliases; 13 | } 14 | 15 | public IReadOnlyList GetAlias(string repositoryAlias) 16 | => _aliases[repositoryAlias]; 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Forms/IRelationContainer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using RapidCMS.Core.Abstractions.Data; 5 | 6 | namespace RapidCMS.Core.Abstractions.Forms; 7 | 8 | public interface IRelationContainer 9 | { 10 | IEnumerable Relations { get; } 11 | 12 | IReadOnlyList? GetRelatedElementIdsFor(Expression> propertyExpression) 13 | where TEntity : IEntity; 14 | 15 | IReadOnlyList? GetRelatedElementIdsFor() 16 | where TRelatedEntity : IEntity; 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/EventArgs/Mediators/NavigationEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Mediators; 3 | using RapidCMS.Core.Navigation; 4 | 5 | namespace RapidCMS.Core.Models.EventArgs.Mediators; 6 | 7 | public class NavigationEventArgs : IMediatorEventArgs 8 | { 9 | internal NavigationEventArgs(NavigationState? oldState, NavigationState newState) 10 | { 11 | OldState = oldState; 12 | NewState = newState ?? throw new ArgumentNullException(nameof(newState)); 13 | } 14 | 15 | public NavigationState? OldState { get; set; } 16 | public NavigationState NewState { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Sections/BasePageContextSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Components; 3 | using RapidCMS.Core.Forms; 4 | using RapidCMS.Core.Models.UI; 5 | 6 | namespace RapidCMS.UI.Components.Sections; 7 | 8 | /// 9 | /// Use this section on pages nested in collections. 10 | /// 11 | public class BasePageContextSection : ComponentBase 12 | { 13 | [Parameter] public SectionUI? Section { get; set; } 14 | 15 | [CascadingParameter(Name = "PageContext")] public PageContext PageContext { get; set; } = default!; 16 | 17 | protected Guid SectionId { get; } = Guid.NewGuid(); 18 | } 19 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Validators/IAsyncEntityValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.Threading.Tasks; 4 | using RapidCMS.Core.Abstractions.Data; 5 | 6 | namespace RapidCMS.Core.Abstractions.Validators; 7 | 8 | public interface IAsyncEntityValidator 9 | { 10 | Task> ValidateAsync(IValidatorContext context); 11 | } 12 | 13 | public interface IAsyncEntityValidator : IAsyncEntityValidator 14 | where TEntity : IEntity 15 | { 16 | Task> ValidateAsync(IValidatorContext context); 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Data/DataViewBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using RapidCMS.Core.Abstractions.Data; 5 | using RapidCMS.Core.Models.Data; 6 | 7 | namespace RapidCMS.Core.Data; 8 | 9 | public abstract class DataViewBuilder : IDataViewBuilder 10 | { 11 | public abstract Task>> GetDataViewsAsync(); 12 | 13 | async Task> IDataViewBuilder.GetDataViewsAsync() 14 | { 15 | var elements = await GetDataViewsAsync(); 16 | return elements.AsEnumerable(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/ElementUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Models.UI; 5 | 6 | public class ElementUI 7 | { 8 | internal ElementUI(Func isVisible, Func isDisabled) 9 | { 10 | IsVisible = isVisible ?? throw new ArgumentNullException(nameof(isVisible)); 11 | IsDisabled = isDisabled ?? throw new ArgumentNullException(nameof(isDisabled)); 12 | } 13 | 14 | public Func IsVisible { get; private set; } 15 | public Func IsDisabled { get; private set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Editors/CheckboxEditor.razor: -------------------------------------------------------------------------------- 1 | @inherits BasePropertyEditor 2 | 3 |
    4 | 11 | 12 | @foreach (var message in GetValidationMessages()) 13 | { 14 |
    15 | @message 16 |
    17 | } 18 |
    -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Api/EntityDescriptor.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Models.Request.Api; 2 | 3 | public class EntityDescriptor 4 | { 5 | public EntityDescriptor(string? id, string? repositoryAlias, string? parentPath, string? variantAlias) 6 | { 7 | Id = id; 8 | RepositoryAlias = repositoryAlias; 9 | ParentPath = parentPath; 10 | VariantAlias = variantAlias; 11 | } 12 | 13 | public string? Id { get; private set; } 14 | public string? RepositoryAlias { get; private set; } 15 | public string? ParentPath { get; private set; } 16 | public string? VariantAlias { get; private set; } 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/SubCollectionListSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Setup; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.Setup; 6 | 7 | public class SubCollectionListSetup 8 | { 9 | public SubCollectionListSetup(int index, string collectionAlias) 10 | { 11 | Index = index; 12 | CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); 13 | } 14 | 15 | public int Index { get; set; } 16 | public string CollectionAlias { get; set; } 17 | 18 | public UsageType SupportsUsageType { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Navigation/CollectionState.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Helpers; 2 | 3 | namespace RapidCMS.Core.Navigation; 4 | 5 | public record CollectionState( 6 | int? ActiveTab = default, 7 | string? SearchTerm = default, 8 | int CurrentPage = 1, 9 | int? MaxPage = default, 10 | SortBag? Sorts = default) 11 | { 12 | public override string ToString() 13 | { 14 | return UriHelper.CombineQueryString( 15 | ("tab", ActiveTab?.ToString()), 16 | ("q", SearchTerm), 17 | ("p", CurrentPage == 1 ? null : CurrentPage.ToString()), 18 | ("s", Sorts?.ToString())); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Form/PersistEntityCollectionRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Interactions; 2 | using RapidCMS.Core.Forms; 3 | using RapidCMS.Core.Navigation; 4 | 5 | namespace RapidCMS.Core.Models.Request.Form; 6 | 7 | public class PersistEntityCollectionRequestModel : IEditorInListInteractionRequestModel 8 | { 9 | public FormEditContext EditContext { get; set; } = default!; 10 | public ListContext ListContext { get; set; } = default!; 11 | public NavigationState NavigationState { get; set; } = default!; 12 | public string ActionId { get; set; } = default!; 13 | public object? CustomData { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/ElementSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RapidCMS.Core.Abstractions.Metadata; 4 | 5 | namespace RapidCMS.Core.Models.Setup; 6 | 7 | public class ElementSetup 8 | { 9 | public ElementSetup(IPropertyMetadata id, IReadOnlyList labels) 10 | { 11 | IdProperty = id ?? throw new ArgumentNullException(nameof(id)); 12 | DisplayProperties = labels ?? throw new ArgumentNullException(nameof(labels)); 13 | } 14 | 15 | public IPropertyMetadata IdProperty { get; set; } 16 | public IReadOnlyList DisplayProperties { get; set; } 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Resolvers/IListUIResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using RapidCMS.Core.Forms; 4 | using RapidCMS.Core.Models.UI; 5 | using RapidCMS.Core.Navigation; 6 | 7 | namespace RapidCMS.Core.Abstractions.Resolvers; 8 | 9 | public interface IListUIResolver 10 | { 11 | ListUI GetListDetails(); 12 | Task> GetButtonsForEditContextAsync(FormEditContext editContext); 13 | Task> GetSectionsForEditContextAsync(FormEditContext editContext, NavigationState navigationState); 14 | Task?> GetTabsAsync(string collectionAlias); 15 | } 16 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Components/CustomPageSection.razor: -------------------------------------------------------------------------------- 1 | @inherits BasePageContextSection 2 | 3 |
    4 |

    Custom section

    5 |

    This section is just a Blazor Component, but because it is nested under a collection it has access to the Parent and Entity, 6 | making it work just like a Detail Page but gives absolute freedom of what to put in this section. 7 |

    8 | 9 |

    ParentId: @this.PageContext.Parent?.Entity?.Id

    10 |

    Entity: @this.PageContext.Entity?.Id

    11 | 12 |

    Email: @Person.Details.Email

    13 |
    14 | 15 | @code { 16 | Person? Person => PageContext.Entity as Person; 17 | } -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/ReorderModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Models.ApiBridge.Request; 4 | 5 | public class ReorderModel 6 | { 7 | public ReorderModel() { } 8 | 9 | public ReorderModel(string? beforeId, string id, IParent? parent) 10 | { 11 | BeforeId = beforeId; 12 | Subject = new EntityDescriptorModel 13 | { 14 | Id = id, 15 | ParentPath = parent?.GetParentPath()?.ToPathString() 16 | }; 17 | } 18 | 19 | public string? BeforeId { get; set; } 20 | 21 | public EntityDescriptorModel Subject { get; set; } = default!; 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Metadata/ExpressionMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Metadata; 3 | 4 | namespace RapidCMS.Core.Models.Metadata; 5 | 6 | internal class ExpressionMetadata : IExpressionMetadata 7 | { 8 | public ExpressionMetadata(string propertyName, Func stringGetter) 9 | { 10 | PropertyName = propertyName ?? throw new ArgumentNullException(nameof(propertyName)); 11 | StringGetter = stringGetter ?? throw new ArgumentNullException(nameof(stringGetter)); 12 | } 13 | 14 | public string PropertyName { get; private set; } 15 | public Func StringGetter { get; private set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Request/Form/PersistEntitiesRequestModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Abstractions.Interactions; 3 | using RapidCMS.Core.Forms; 4 | using RapidCMS.Core.Navigation; 5 | 6 | namespace RapidCMS.Core.Models.Request.Form; 7 | 8 | public class PersistEntitiesRequestModel : IListButtonInteractionRequestModel 9 | { 10 | public ListContext ListContext { get; set; } = default!; 11 | public NavigationState NavigationState { get; set; } = default!; 12 | public string ActionId { get; set; } = default!; 13 | public object? CustomData { get; set; } 14 | public IRelated? Related { get; set; } = default!; 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/TreeElementSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Models.Setup; 5 | 6 | public class TreeElementSetup 7 | { 8 | public TreeElementSetup(string alias, string name, PageType type) 9 | { 10 | Alias = alias ?? throw new ArgumentNullException(nameof(alias)); 11 | Name = name ?? throw new ArgumentNullException(nameof(alias)); 12 | Type = type; 13 | } 14 | 15 | public string Alias { get; } 16 | 17 | public string Name { get; } 18 | 19 | public PageType Type { get; } 20 | 21 | public CollectionRootVisibility RootVisibility { get; internal set; } 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/CollectionListConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Models.Config; 4 | 5 | internal class CollectionListConfig 6 | { 7 | internal CollectionListConfig(string collectionAlias) 8 | { 9 | CollectionAlias = collectionAlias ?? throw new ArgumentNullException(nameof(collectionAlias)); 10 | } 11 | 12 | internal int Index { get; set; } 13 | 14 | internal string CollectionAlias { get; set; } 15 | 16 | internal Type? RepositoryType { get; set; } 17 | internal Type? EntityType { get; set; } 18 | internal ListConfig? ListEditor { get; set; } 19 | internal ListConfig? ListView { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/PropertyFieldUI.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Enums; 3 | using RapidCMS.Core.Models.Setup; 4 | using RapidCMS.Core.Providers; 5 | 6 | namespace RapidCMS.Core.Models.UI; 7 | 8 | public class PropertyFieldUI : FieldUI 9 | { 10 | internal PropertyFieldUI(PropertyFieldSetup field, FormDataProvider? dataProvider) : base(field) 11 | { 12 | Type = field.EditorType; 13 | Property = field.Property; 14 | DataCollection = dataProvider?.Collection; 15 | } 16 | 17 | public EditorType Type { get; internal set; } 18 | 19 | public IDataCollection? DataCollection { get; internal set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Parts/ButtonBar.razor: -------------------------------------------------------------------------------- 1 | @if (Buttons != null && Buttons.Any()) 2 | { 3 |
    4 | @foreach (var button in Buttons) 5 | { 6 | if (button.IsVisible?.Invoke(EditContext.Entity, EditContext.EntityState) ?? true) 7 | { 8 | var model = button.ToViewModel(); 9 | model.OnClick = OnButtonClick; 10 | 11 | @button.ToRenderFragment(model); 12 | } 13 | } 14 |
    15 | } 16 | 17 | @code { 18 | [Parameter] public IEnumerable? Buttons { get; set; } 19 | [Parameter] public EventCallback OnButtonClick { get; set; } 20 | [Parameter] public FormEditContext EditContext { get; set; } = default!; 21 | } 22 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/CompositeValidationResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace RapidCMS.Core.Models; 5 | 6 | public class CompositeValidationResult : ValidationResult 7 | { 8 | public string? MemberName { get; private set; } 9 | public List Results { get; private set; } = new List(); 10 | 11 | public CompositeValidationResult(string errorMessage, string? memberName = default) : base(errorMessage) { MemberName = memberName; } 12 | 13 | public void AddResult(ValidationResult validationResult) 14 | { 15 | Results.Add(validationResult); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Authorization/AnonymousAuthenticationStateProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Components.Authorization; 4 | 5 | namespace RapidCMS.Core.Authorization; 6 | 7 | internal class AnonymousAuthenticationStateProvider : AuthenticationStateProvider 8 | { 9 | public override Task GetAuthenticationStateAsync() 10 | { 11 | var id = new ClaimsIdentity("anonymous"); 12 | id.AddClaim(new Claim(ClaimTypes.Name, "Anonymous")); 13 | 14 | var principal = new ClaimsPrincipal(id); 15 | 16 | return Task.FromResult(new AuthenticationState(principal)); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/PropertyFieldSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Enums; 3 | using RapidCMS.Core.Models.Config; 4 | 5 | namespace RapidCMS.Core.Models.Setup; 6 | 7 | public class PropertyFieldSetup : FieldSetup 8 | { 9 | internal PropertyFieldSetup(FieldConfig field) : base(field) 10 | { 11 | Property = field.Property ?? throw new ArgumentNullException(nameof(field.Property)); 12 | EditorType = field.EditorType; 13 | } 14 | 15 | public PropertyFieldSetup() : base(default) 16 | { 17 | 18 | } 19 | 20 | public EditorType EditorType { get; set; } = EditorType.Readonly; 21 | 22 | public RelationSetup? Relation { get; set; } 23 | } 24 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/DataViewBuilders/CountryDataViewBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using RapidCMS.Core.Data; 5 | using RapidCMS.Core.Models.Data; 6 | using RapidCMS.Example.Github.Entities; 7 | 8 | namespace RapidCMS.Example.Github.DataViewBuilders; 9 | 10 | internal class CountryDataViewBuilder : DataViewBuilder 11 | { 12 | public override Task>> GetDataViewsAsync() 13 | { 14 | return Task.FromResult(Enumerable.Range(1, 10).Select(index => new DataView(index, $"{index}-letter country", x => x.Name != null && x.Name.Length == index))); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/ElementConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using RapidCMS.Core.Abstractions.Metadata; 5 | 6 | namespace RapidCMS.Core.Models.Config; 7 | 8 | internal class ElementConfig 9 | { 10 | public ElementConfig(IPropertyMetadata id, params IExpressionMetadata[] labels) 11 | { 12 | IdProperty = id ?? throw new ArgumentNullException(nameof(id)); 13 | DisplayProperties = labels?.ToList() ?? throw new ArgumentNullException(nameof(labels)); 14 | } 15 | 16 | internal IPropertyMetadata IdProperty { get; set; } 17 | 18 | internal IReadOnlyList DisplayProperties { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/CustomPropertyFieldSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Models.Config; 3 | 4 | namespace RapidCMS.Core.Models.Setup; 5 | 6 | public class CustomPropertyFieldSetup : PropertyFieldSetup 7 | { 8 | internal CustomPropertyFieldSetup(FieldConfig field, Type customFieldType) : base(field) 9 | { 10 | CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); 11 | } 12 | 13 | public CustomPropertyFieldSetup(Type customFieldType) : base() 14 | { 15 | CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); 16 | } 17 | 18 | public Type CustomType { get; set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Extensions/PropertyMetadataExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using RapidCMS.Core.Abstractions.Metadata; 4 | 5 | namespace RapidCMS.Core.Extensions; 6 | 7 | internal static class PropertyMetadataExtensions 8 | { 9 | public static IEnumerable GetAttributes(this IPropertyMetadata property) 10 | { 11 | return property.ObjectType 12 | .GetProperties() 13 | .FirstOrDefault(x => x.Name == property.PropertyName) 14 | ?.GetCustomAttributes(true) 15 | .Where(x => x.GetType().IsSameTypeOrDerivedFrom(typeof(T))) 16 | .Cast() 17 | ?? Enumerable.Empty(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Data/ParentEntity.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Models.Data; 4 | 5 | internal class ParentEntity : IParent 6 | { 7 | private readonly string _repositoryAlias; 8 | 9 | public ParentEntity(IParent? parent, IEntity entity, string repositoryAlias) 10 | { 11 | Parent = parent; 12 | Entity = entity; 13 | _repositoryAlias = repositoryAlias; 14 | } 15 | 16 | public IParent? Parent { get; } 17 | public IEntity Entity { get; private set; } 18 | 19 | public ParentPath? GetParentPath() 20 | { 21 | return ParentPath.AddLevel(Parent?.GetParentPath(), _repositoryAlias, Entity.Id!); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/SectionUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.UI; 6 | 7 | public class SectionUI 8 | { 9 | public SectionUI(Func isVisible) 10 | { 11 | IsVisible = isVisible ?? throw new ArgumentNullException(nameof(isVisible)); 12 | } 13 | 14 | public List? Buttons { get; internal set; } 15 | 16 | public List? Elements { get; internal set; } 17 | public Func IsVisible { get; private set; } 18 | public string? Label { get; internal set; } 19 | 20 | public Type? CustomType { get; internal set; } 21 | } 22 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Resolvers/Repositories/RepositoryTypeResolverBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Resolvers.Repositories; 4 | 5 | internal class RepositoryTypeResolverBase 6 | { 7 | protected Type[]? GetGenericParametersOfBaseType(Type type, Type baseTypeToFind) 8 | { 9 | if (type.IsGenericType && type.GetGenericTypeDefinition() == baseTypeToFind) 10 | { 11 | return type.GetGenericArguments(); 12 | } 13 | else if (type.BaseType != null) 14 | { 15 | return GetGenericParametersOfBaseType(type.BaseType, baseTypeToFind); 16 | } 17 | else 18 | { 19 | return null; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Data/Mapper.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Repositories; 2 | 3 | namespace RapidCMS.Example.Shared.Data; 4 | 5 | public class Mapper : IConverter 6 | { 7 | public MappedEntity Convert(DatabaseEntity obj) 8 | { 9 | return new MappedEntity 10 | { 11 | Description = obj.Description, 12 | Id = obj.Id, 13 | Name = obj.Name 14 | }; 15 | } 16 | 17 | public DatabaseEntity Convert(MappedEntity obj) 18 | { 19 | return new DatabaseEntity 20 | { 21 | Description = obj.Description, 22 | Id = obj.Id, 23 | Name = obj.Name 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Resolvers/Setup/PluginTreeElementsSetupResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using RapidCMS.Core.Abstractions.Plugins; 4 | using RapidCMS.Core.Abstractions.Resolvers; 5 | using RapidCMS.Core.Models.Setup; 6 | 7 | namespace RapidCMS.Core.Resolvers.Setup; 8 | 9 | internal class PluginTreeElementsSetupResolver : ISetupResolver, IPlugin> 10 | { 11 | public async Task>> ResolveSetupAsync(IPlugin config, CollectionSetup? collection = null) 12 | { 13 | return new ResolvedSetup>(await config.GetTreeElementsAsync(), false); 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Extensions/CustomRegistrationRenderFragmentExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using RapidCMS.Core.Models.Setup; 3 | 4 | namespace RapidCMS.UI.Extensions; 5 | 6 | public static class CustomRegistrationRenderFragmentExtensions 7 | { 8 | public static RenderFragment? ToRenderFragment(this TypeRegistrationSetup? registration) 9 | { 10 | if (registration != null) 11 | { 12 | return builder => 13 | { 14 | builder.OpenComponent(0, registration.Type); 15 | builder.CloseComponent(); 16 | }; 17 | } 18 | else 19 | { 20 | return default; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/RelateModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Models.ApiBridge.Request; 4 | 5 | public class RelateModel 6 | { 7 | public RelateModel() { } 8 | 9 | public RelateModel(IRelated related, string id) 10 | { 11 | Id = id; 12 | Related = new EntityDescriptorModel 13 | { 14 | RepositoryAlias = related.RepositoryAlias, 15 | Id = related.Entity.Id!, 16 | ParentPath = related.Parent?.GetParentPath()?.ToPathString() 17 | }; 18 | } 19 | 20 | public string Id { get; set; } = default!; 21 | 22 | public EntityDescriptorModel Related { get; set; } = default!; 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Resolvers/Setup/ElementSetupResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Abstractions.Resolvers; 3 | using RapidCMS.Core.Models.Config; 4 | using RapidCMS.Core.Models.Setup; 5 | 6 | namespace RapidCMS.Core.Resolvers.Setup; 7 | 8 | internal class ElementSetupResolver : ISetupResolver 9 | { 10 | public Task> ResolveSetupAsync(ElementConfig config, CollectionSetup? collection = default) 11 | { 12 | return Task.FromResult>(new ResolvedSetup(new ElementSetup( 13 | config.IdProperty, 14 | config.DisplayProperties), 15 | true)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/Pages/_Host.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @namespace RapidCMS.Example.Server 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | 5 | 6 | 7 | 8 | 9 | 10 | RapidCMS.Example.Server 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/AuthorizationHandlers/VeryPermissiveAuthorizationHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Authorization.Infrastructure; 4 | using RapidCMS.Core.Abstractions.Data; 5 | 6 | namespace RapidCMS.Example.Shared.AuthorizationHandlers; 7 | 8 | public class VeryPermissiveAuthorizationHandler : AuthorizationHandler 9 | { 10 | protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, IEntity resource) 11 | { 12 | context.Succeed(requirement); 13 | 14 | return Task.CompletedTask; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.WebApi/Providers/CollectionControllerFeatureProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Reflection; 3 | using Microsoft.AspNetCore.Mvc.ApplicationParts; 4 | using Microsoft.AspNetCore.Mvc.Controllers; 5 | using RapidCMS.Api.WebApi.Controllers; 6 | 7 | namespace RapidCMS.Api.WebApi.Providers; 8 | 9 | public class CollectionControllerFeatureProvider : IApplicationFeatureProvider 10 | { 11 | public void PopulateFeature(IEnumerable parts, ControllerFeature feature) 12 | { 13 | feature.Controllers.Add(typeof(ApiRepositoryController).GetTypeInfo()); 14 | feature.Controllers.Add(typeof(ApiFileUploadController).GetTypeInfo()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/SubCollectionUI.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | using RapidCMS.Core.Models.Setup; 3 | using RapidCMS.Core.Navigation; 4 | 5 | namespace RapidCMS.Core.Models.UI; 6 | 7 | public class SubCollectionUI : ElementUI 8 | { 9 | internal SubCollectionUI(SubCollectionListSetup subCollection, NavigationState nestedNavigationState) 10 | : base((x, state) => state == EntityState.IsExisting, (x, y) => false) 11 | { 12 | CollectionAlias = subCollection.CollectionAlias; 13 | NestedNavigationState = nestedNavigationState; 14 | } 15 | 16 | public string CollectionAlias { get; private set; } 17 | 18 | public NavigationState? NestedNavigationState { get; private set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Validators/BaseEntityValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using RapidCMS.Core.Abstractions.Data; 4 | using RapidCMS.Core.Abstractions.Validators; 5 | 6 | namespace RapidCMS.Core.Validators; 7 | 8 | public abstract class BaseEntityValidator : IEntityValidator, IEntityValidator 9 | where TEntity : IEntity 10 | { 11 | public abstract IEnumerable Validate(IValidatorContext context); 12 | 13 | IEnumerable IEntityValidator.Validate(IValidatorContext context) 14 | => Validate(new ValidatorContext(context.Entity, context.RelationContainer, context.Configuration)); 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Extensions/SectionUIExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using RapidCMS.Core.Models.UI; 3 | using RapidCMS.UI.Components.Sections; 4 | 5 | namespace RapidCMS.UI.Extensions; 6 | 7 | public static class SectionUIExtensions 8 | { 9 | public static RenderFragment? ToRenderFragment(this SectionUI section) 10 | { 11 | if (section.CustomType == null) 12 | 13 | { 14 | return null; 15 | } 16 | 17 | return builder => 18 | { 19 | builder.OpenComponent(0, section.CustomType); 20 | 21 | builder.AddAttribute(1, nameof(BaseSection.Section), section); 22 | 23 | builder.CloseComponent(); 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/ISubCollectionListViewConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Abstractions.Repositories; 4 | 5 | namespace RapidCMS.Core.Abstractions.Config; 6 | 7 | public interface ISubCollectionListViewConfig 8 | where TSubRepository : IRepository 9 | where TSubEntity : IEntity 10 | { 11 | /// 12 | /// Sets the ListView of this related collection 13 | /// 14 | /// Action used to configure the ListView 15 | /// 16 | ISubCollectionListViewConfig SetListView(Action> configure); 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/CustomTypeRegistrationConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace RapidCMS.Core.Models.Config; 5 | 6 | public sealed class CustomTypeRegistrationConfig 7 | { 8 | internal CustomTypeRegistrationConfig(Type type, Dictionary? parameters = null) 9 | { 10 | Type = type ?? throw new ArgumentNullException(nameof(type)); 11 | Alias = type.FullName ?? throw new InvalidOperationException($"The given type ({type}) must have a FullName"); 12 | Parameters = parameters; 13 | } 14 | 15 | public Type Type { get; set; } 16 | public string Alias { get; set; } 17 | public Dictionary? Parameters { get; set; } 18 | } 19 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Helpers/UriHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Web; 3 | using RapidCMS.Core.Extensions; 4 | 5 | namespace RapidCMS.Core.Helpers; 6 | 7 | internal static class UriHelper 8 | { 9 | public static string CombinePath(params string?[] elements) 10 | => string.Join("/", elements.SelectNotNull(x => x)); 11 | 12 | public static string CombineQueryString(params (string key, string? value)[] elements) 13 | => string.Join("&", elements 14 | .Where(x => !string.IsNullOrWhiteSpace(x.value)) 15 | .Select(x => $"{x.key}={HttpUtility.UrlEncode(x.value)}")) 16 | is string query && !string.IsNullOrWhiteSpace(query) 17 | ? $"?{query}" 18 | : ""; 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IAdvancedCmsConfig.cs: -------------------------------------------------------------------------------- 1 | namespace RapidCMS.Core.Abstractions.Config; 2 | 3 | public interface IAdvancedCmsConfig 4 | { 5 | /// 6 | /// This count controls the amount of concurrent repository calls that can be 7 | /// performed at the same time. For some scenarios (like server-side blazor with EF without MARS), 8 | /// this number should be strictly 1, but can be higher for other scenarios. 9 | /// 10 | int SemaphoreCount { get; set; } 11 | 12 | /// 13 | /// Setting this true prevents DataAnnotationEntityValidator from being added to all collections automatically. 14 | /// 15 | bool RemoveDataAnnotationEntityValidator { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/ISubCollectionListEditorConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Abstractions.Repositories; 4 | 5 | namespace RapidCMS.Core.Abstractions.Config; 6 | 7 | public interface ISubCollectionListEditorConfig 8 | where TSubRepository : IRepository 9 | where TSubEntity : IEntity 10 | { 11 | /// 12 | /// Sets the ListEditor of this related collection 13 | /// 14 | /// Action used to configure the ListEditor 15 | /// 16 | ISubCollectionListEditorConfig SetListEditor(Action> configure); 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Interactions/IDragInteraction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Components.Web; 3 | using RapidCMS.Core.Models.EventArgs; 4 | 5 | namespace RapidCMS.Core.Abstractions.Interactions; 6 | 7 | public interface IDragInteraction 8 | { 9 | void DragStart(DragEventArgs args, string id); 10 | void DragEnd(DragEventArgs args); 11 | 12 | void DragEnter(DragEventArgs args, string id); 13 | 14 | void EndZoneDragEnter(DragEventArgs args, Guid guid); 15 | 16 | bool IsDragged(string? id); 17 | bool IsDraggedOver(string? id); 18 | bool IsDraggedOverEndZone(Guid guid); 19 | 20 | event EventHandler DragCompletion; 21 | event EventHandler DragStateChange; 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Mediators/IMediator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace RapidCMS.Core.Abstractions.Mediators; 5 | 6 | public interface IMediator 7 | { 8 | void NotifyEvent(object sender, IMediatorEventArgs @event); 9 | 10 | Task NotifyEventAsync(object sender, IMediatorRequestEventArgs @event); 11 | 12 | event EventHandler OnEvent; 13 | 14 | IDisposable RegisterCallback(Func callback) 15 | where TMediatorEventArgs : IMediatorEventArgs; 16 | 17 | TMediatorEventArgs? GetLatestEventArgs() 18 | where TMediatorEventArgs : IMediatorEventArgs; 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/RelatedCollectionUI.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | using RapidCMS.Core.Models.Setup; 3 | using RapidCMS.Core.Navigation; 4 | 5 | namespace RapidCMS.Core.Models.UI; 6 | 7 | public class RelatedCollectionUI : ElementUI 8 | { 9 | internal RelatedCollectionUI(RelatedCollectionListSetup relatedCollection, NavigationState nestedNavigationState) 10 | : base((x, state) => state == EntityState.IsExisting, (x, y) => false) 11 | { 12 | CollectionAlias = relatedCollection.CollectionAlias; 13 | NestedNavigationState = nestedNavigationState; 14 | } 15 | 16 | public string CollectionAlias { get; private set; } 17 | 18 | public NavigationState? NestedNavigationState { get; internal set; } 19 | } 20 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Shared/TopBar.razor: -------------------------------------------------------------------------------- 1 | @inject ITreeService TreeService 2 | 3 | 16 | 17 | @code { 18 | TreeRootUI? TreeRoot; 19 | 20 | [CascadingParameter(Name = "CustomLoginStatus")] 21 | private RenderFragment? CustomLoginStatus { get; set; } 22 | 23 | protected override async Task OnInitializedAsync() 24 | { 25 | TreeRoot = await TreeService.GetRootAsync(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/Entities/Relatable2Person.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RapidCMS.Core.Abstractions.Data; 4 | 5 | namespace RapidCMS.Example.Github.Entities; 6 | 7 | internal class Relatable2Person : IEntity, ICloneable 8 | { 9 | public string? Id { get; set; } 10 | public string? Name { get; set; } 11 | public string? Email { get; set; } 12 | public string? Bio { get; set; } 13 | 14 | public List Countries { get; } = new List(); 15 | 16 | public object Clone() 17 | { 18 | return new Relatable2Person 19 | { 20 | Bio = Bio, 21 | Email = Email, 22 | Id = Id, 23 | Name = Name 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IHasColumnVisibility.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Enums; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | public interface IHasColumnVisibility 6 | { 7 | /// 8 | /// Controls whether empty columns in the table should be collapsed. Only required when the 9 | /// collection uses multiple EntityVariants, with separate sets of properties which are not shared between the variants. Collapsing 10 | /// the empty cell will reduce the number of columns required, and makes the table more readable. 11 | /// 12 | /// 13 | /// 14 | TReturn SetColumnVisibility(EmptyVariantColumnVisibility columnVisibility); 15 | } 16 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.WebApi/Extensions/ApiResponseModelExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc; 2 | using RapidCMS.Api.Core.Models; 3 | 4 | namespace RapidCMS.Api.WebApi.Extensions; 5 | 6 | public static class ApiResponseModelExtensions 7 | { 8 | public static ContentResult ToContentResult(this ApiResponseModel model) 9 | { 10 | if (model.ResponseBody == null) 11 | { 12 | return new ContentResult 13 | { 14 | StatusCode = (int)model.StatusCode 15 | }; 16 | } 17 | 18 | return new ContentResult 19 | { 20 | Content = model.ResponseBody, 21 | ContentType = "application/json", 22 | StatusCode = (int)model.StatusCode 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListViewConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Abstractions.Repositories; 4 | 5 | namespace RapidCMS.Core.Abstractions.Config; 6 | 7 | public interface IRelatedCollectionListViewConfig 8 | where TRelatedRepository : IRepository 9 | where TRelatedEntity : IEntity 10 | { 11 | /// 12 | /// Sets the ListView of this related collection 13 | /// 14 | /// Action used to configure the ListView 15 | /// 16 | IRelatedCollectionListViewConfig SetListView(Action> configure); 17 | } 18 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Data/RelatedEntity.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Forms; 3 | 4 | namespace RapidCMS.Core.Models.Data; 5 | 6 | public class RelatedEntity : IRelated 7 | { 8 | public RelatedEntity(IParent? parent, IEntity relatedEntity, string repositoryAlias) 9 | { 10 | Parent = parent; 11 | Entity = relatedEntity; 12 | RepositoryAlias = repositoryAlias; 13 | } 14 | 15 | public RelatedEntity(FormEditContext editContext) : this(editContext.Parent, editContext.Entity, editContext.RepositoryAlias) 16 | { 17 | 18 | } 19 | 20 | public IParent? Parent { get; private set; } 21 | public IEntity Entity { get; private set; } 22 | public string RepositoryAlias { get; private set; } 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/General.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("RapidCMS.Core.Tests")] 4 | [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] 5 | 6 | [assembly: InternalsVisibleTo("RapidCMS.Repositories")] 7 | [assembly: InternalsVisibleTo("RapidCMS.Api.Core")] 8 | [assembly: InternalsVisibleTo("RapidCMS.Api.Functions")] 9 | [assembly: InternalsVisibleTo("RapidCMS.Api.WebApi")] 10 | 11 | [assembly: InternalsVisibleTo("RapidCMS.ModelMaker")] 12 | 13 | namespace RapidCMS.Core; 14 | 15 | public class Constants 16 | { 17 | public const string Add = "add"; 18 | public const string Edit = "edit"; 19 | public const string New = "new"; 20 | public const string Pick = "pick"; 21 | public const string View = "view"; 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Editors/DateEditor.razor: -------------------------------------------------------------------------------- 1 | @inherits BasePropertyEditor 2 | 3 | @{ 4 | var date = (DateTime?)GetValueAsObject(); 5 | 6 | if (!date.HasValue || date.Value == DateTime.MinValue) 7 | { 8 | date = DateTime.UtcNow.Date; 9 | } 10 | } 11 | 12 | SetValueFromObjectAsync((DateTime.TryParse(((string?)args.Value) ?? "", out var result) ? result : DateTime.UtcNow))) 15 | class="form-control @(CssHelper.GetValidationClass(State))" 16 | placeholder=@Placeholder 17 | type="date" /> 18 | 19 | @foreach (var message in GetValidationMessages()) 20 | { 21 |
    22 | @message 23 |
    24 | } -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Parts/ButtonCell.razor: -------------------------------------------------------------------------------- 1 | 2 | @if (Buttons != null && Buttons.Any()) 3 | { 4 | @foreach (var button in Buttons) 5 | { 6 | if (button.IsVisible?.Invoke(EditContext.Entity, EditContext.EntityState) ?? true) 7 | { 8 | var model = button.ToViewModel(); 9 | model.OnClick = OnButtonClick; 10 | 11 | @button.ToRenderFragment(model); 12 | } 13 | } 14 | } 15 | 16 | 17 | @code { 18 | [Parameter] public IEnumerable? Buttons { get; set; } 19 | [Parameter] public EventCallback OnButtonClick { get; set; } 20 | [Parameter] public FormEditContext EditContext { get; set; } = default!; 21 | } 22 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IRelatedCollectionListEditorConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Abstractions.Repositories; 4 | 5 | namespace RapidCMS.Core.Abstractions.Config; 6 | 7 | public interface IRelatedCollectionListEditorConfig 8 | where TRelatedRepository : IRepository 9 | where TRelatedEntity : IEntity 10 | { 11 | /// 12 | /// Sets the ListEditor of this related collection 13 | /// 14 | /// Action used to configure the ListEditor 15 | /// 16 | IRelatedCollectionListEditorConfig SetListEditor(Action> configure); 17 | } 18 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/Attributes/BioValidationAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace RapidCMS.Example.Github.Attributes; 4 | 5 | internal class BioValidationAttribute : ValidationAttribute 6 | { 7 | public override bool RequiresValidationContext => true; 8 | 9 | protected override ValidationResult IsValid(object? value, ValidationContext validationContext) 10 | { 11 | if (value is string bio) 12 | { 13 | if (bio.Contains("fdsa")) 14 | { 15 | return new ValidationResult("Bio's cannot contain 'fdsa'.", validationContext.MemberName == null ? null : new[] { validationContext.MemberName }); 16 | } 17 | } 18 | 19 | return ValidationResult.Success!; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/CustomExpressionFieldSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Metadata; 3 | using RapidCMS.Core.Models.Config; 4 | 5 | namespace RapidCMS.Core.Models.Setup; 6 | 7 | public class CustomExpressionFieldSetup : ExpressionFieldSetup 8 | { 9 | internal CustomExpressionFieldSetup(FieldConfig field, IExpressionMetadata expression, Type customFieldType) : base(field, expression) 10 | { 11 | CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); 12 | } 13 | 14 | public CustomExpressionFieldSetup(Type customFieldType) : base() 15 | { 16 | CustomType = customFieldType ?? throw new ArgumentNullException(nameof(customFieldType)); 17 | } 18 | 19 | public Type CustomType { get; set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Resolvers/Buttons/ButtonActionHandlerResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Handlers; 3 | using RapidCMS.Core.Abstractions.Resolvers; 4 | using RapidCMS.Core.Extensions; 5 | using RapidCMS.Core.Models.Setup; 6 | 7 | namespace RapidCMS.Core.Resolvers.Buttons; 8 | 9 | internal class ButtonActionHandlerResolver : IButtonActionHandlerResolver 10 | { 11 | private readonly IServiceProvider _serviceProvider; 12 | 13 | public ButtonActionHandlerResolver(IServiceProvider serviceProvider) 14 | { 15 | _serviceProvider = serviceProvider; 16 | } 17 | 18 | public IButtonActionHandler GetButtonActionHandler(ButtonSetup button) 19 | { 20 | return _serviceProvider.GetService(button.ButtonHandlerType); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.WebAssembly.API/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.Hosting; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace RapidCMS.Example.WebAssembly.API; 11 | 12 | public class Program 13 | { 14 | public static void Main(string[] args) 15 | { 16 | CreateHostBuilder(args).Build().Run(); 17 | } 18 | 19 | public static IHostBuilder CreateHostBuilder(string[] args) => 20 | Host.CreateDefaultBuilder(args) 21 | .ConfigureWebHostDefaults(webBuilder => 22 | { 23 | webBuilder.UseStartup(); 24 | }); 25 | } 26 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.Core/Models/ApiResponseModel.cs: -------------------------------------------------------------------------------- 1 | using System.Net; 2 | using Newtonsoft.Json; 3 | 4 | namespace RapidCMS.Api.Core.Models; 5 | 6 | public class ApiResponseModel 7 | { 8 | public ApiResponseModel(HttpStatusCode statusCode) 9 | { 10 | StatusCode = statusCode; 11 | } 12 | 13 | public ApiResponseModel(HttpStatusCode statusCode, object responseBody) : this(statusCode) 14 | { 15 | ResponseBody = JsonConvert.SerializeObject(responseBody, new JsonSerializerSettings 16 | { 17 | ReferenceLoopHandling = ReferenceLoopHandling.Ignore, 18 | PreserveReferencesHandling = PreserveReferencesHandling.All 19 | }); 20 | } 21 | 22 | public HttpStatusCode StatusCode { get; set; } 23 | public string? ResponseBody { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Interactions/IButtonInteraction.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Enums; 3 | using RapidCMS.Core.Models.Setup; 4 | 5 | namespace RapidCMS.Core.Abstractions.Interactions; 6 | 7 | internal interface IButtonInteraction 8 | { 9 | Task ValidateButtonInteractionAsync(IEditorButtonInteractionRequestModel request); 10 | Task CompleteButtonInteractionAsync(IEditorButtonInteractionRequestModel request); 11 | 12 | Task ValidateButtonInteractionAsync(IEditorInListInteractionRequestModel request); 13 | 14 | Task<(CrudType crudType, EntityVariantSetup? entityVariant)> ValidateButtonInteractionAsync(IListButtonInteractionRequestModel request); 15 | Task CompleteButtonInteractionAsync(IListButtonInteractionRequestModel request); 16 | } 17 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/ButtonConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.Config; 6 | 7 | internal class ButtonConfig 8 | { 9 | internal string Id { get; set; } = Guid.NewGuid().ToString(); 10 | internal string? Label { get; set; } 11 | internal string? Icon { get; set; } 12 | internal bool IsPrimary { get; set; } 13 | internal Func? IsVisible { get; private set; } 14 | 15 | internal ButtonConfig VisibleWhen(Func? predicate) 16 | { 17 | if (predicate != null) 18 | { 19 | IsVisible = (entity, state) => predicate.Invoke((IEntity)entity, state); 20 | } 21 | 22 | return this; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Validators/AsyncEntityValidator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.Threading.Tasks; 4 | using RapidCMS.Core.Abstractions.Data; 5 | using RapidCMS.Core.Abstractions.Validators; 6 | 7 | namespace RapidCMS.Core.Validators; 8 | 9 | public abstract class BaseAsyncEntityValidator : IAsyncEntityValidator, IAsyncEntityValidator 10 | where TEntity : IEntity 11 | { 12 | public abstract Task> ValidateAsync(IValidatorContext context); 13 | 14 | Task> IAsyncEntityValidator.ValidateAsync(IValidatorContext context) 15 | => ValidateAsync(new ValidatorContext(context.Entity, context.RelationContainer, context.Configuration)); 16 | } 17 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Shared/Handlers/NavigateToPersonHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Abstractions.Handlers; 3 | using RapidCMS.Core.Abstractions.Setup; 4 | using RapidCMS.Core.Forms; 5 | using RapidCMS.Core.Models.Request; 6 | using RapidCMS.Core.Models.Setup; 7 | 8 | namespace RapidCMS.Example.Shared.Handlers; 9 | 10 | public class NavigateToPersonHandler : INavigationHandler 11 | { 12 | public Task CreateNavigationRequestAsync(ButtonSetup button, FormEditContext editContext) 13 | { 14 | // this method can return a NavigationRequest to instruct the CMS to go to that page 15 | // if null is returned, the action is canceled. 16 | return Task.FromResult(NavigationRequest.NavigateToCreateNewEntity("person", default))!; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.WebAssembly.API/RapidCMS.Example.WebAssembly.API.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | ASP.NET Core 10.0 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/ListConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.Config; 6 | 7 | internal class ListConfig 8 | { 9 | public ListConfig(Type baseType) 10 | { 11 | BaseType = baseType; 12 | } 13 | 14 | public Type BaseType { get; } 15 | internal int? PageSize { get; set; } 16 | internal bool? SearchBarVisible { get; set; } 17 | internal bool? ReorderingAllowed { get; set; } 18 | internal ListType ListEditorType { get; set; } 19 | internal EmptyVariantColumnVisibility EmptyVariantColumnVisibility { get; set; } 20 | internal List Buttons { get; set; } = new List(); 21 | internal List Panes { get; set; } = new List(); 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/UI/TreePageUI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Navigation; 3 | 4 | namespace RapidCMS.Core.Models.UI; 5 | 6 | public class TreePageUI 7 | { 8 | public TreePageUI(string name, string icon, string color, NavigationState navigateTo) 9 | { 10 | Name = name ?? throw new ArgumentNullException(nameof(name)); 11 | Icon = icon ?? throw new ArgumentNullException(nameof(icon)); 12 | Color = color ?? throw new ArgumentNullException(nameof(color)); 13 | NavigateTo = navigateTo ?? throw new ArgumentNullException(nameof(navigateTo)); 14 | } 15 | 16 | public string Name { get; private set; } 17 | public string Icon { get; private set; } 18 | public string Color { get; private set; } 19 | public NavigationState NavigateTo { get; private set; } 20 | } 21 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Sections/BaseEditContextSection.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using RapidCMS.Core.Models.UI; 3 | 4 | namespace RapidCMS.UI.Components.Sections; 5 | 6 | public class BaseEditContextSection : EditContextComponentBase 7 | { 8 | [Parameter] public SectionUI? Section { get; set; } 9 | 10 | protected override void AttachListener() 11 | { 12 | EditContext.OnFieldChanged += EditContext_OnFieldChangedAsync; 13 | } 14 | 15 | private async void EditContext_OnFieldChangedAsync(object? sender, Core.Forms.FieldChangedEventArgs e) 16 | { 17 | await InvokeAsync(() => StateHasChanged()); 18 | } 19 | 20 | protected override void DetachListener() 21 | { 22 | EditContext.OnFieldChanged -= EditContext_OnFieldChangedAsync; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Helpers/EditorTypeHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using RapidCMS.Core.Attributes; 4 | using RapidCMS.Core.Enums; 5 | using RapidCMS.Core.Extensions; 6 | 7 | namespace RapidCMS.Core.Helpers; 8 | 9 | internal static class EditorTypeHelper 10 | { 11 | public static EditorType TryFindDefaultEditorType(Type editorType) 12 | { 13 | foreach (var type in EnumHelper.GetValues()) 14 | { 15 | if (type.GetCustomAttribute()?.Types.Contains(editorType) ?? false) 16 | { 17 | return type; 18 | } 19 | } 20 | 21 | if (typeof(Enum).IsAssignableFrom(editorType)) 22 | { 23 | return EditorType.Select; 24 | } 25 | 26 | return default; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/wwwroot/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | RapidCMS.Example.WebAssembly 8 | 9 | 10 | 11 | 12 | 13 |
    Loading...
    14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Setup/ButtonSetup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.Setup; 6 | 7 | public class ButtonSetup 8 | { 9 | public DefaultButtonType DefaultButtonType { get; set; } 10 | 11 | public string ButtonId { get; set; } = default!; 12 | public Type? CustomType { get; set; } 13 | public Type ButtonHandlerType { get; set; } = default!; 14 | 15 | public string Label { get; set; } = default!; 16 | public string Icon { get; set; } = default!; 17 | public bool IsPrimary { get; set; } 18 | 19 | public Func? IsVisible { get; set; } 20 | 21 | public IEnumerable Buttons { get; set; } = default!; 22 | 23 | public EntityVariantSetup? EntityVariant { get; set; } 24 | } 25 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/RapidCMS.Example.Server.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net10.0 5 | enable 6 | ASP.NET Core 10.0 Razor Pages 7 | 10.0 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/EventArgs/Mediators/RepositoryEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Mediators; 3 | using RapidCMS.Core.Enums; 4 | using RapidCMS.Core.Models.Data; 5 | 6 | namespace RapidCMS.Core.Models.EventArgs.Mediators; 7 | 8 | public class RepositoryEventArgs : IMediatorEventArgs 9 | { 10 | public RepositoryEventArgs(Type repositoryType, ParentPath? parentPath, string? id, CrudType action) 11 | { 12 | RepositoryType = repositoryType ?? throw new ArgumentNullException(nameof(repositoryType)); 13 | ParentPath = parentPath; 14 | Id = id; 15 | Action = action; 16 | } 17 | 18 | public Type RepositoryType { get; set; } 19 | public ParentPath? ParentPath { get; set; } 20 | public string? Id { get; set; } 21 | public CrudType Action { get; set; } 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Resolvers/Repositories/EntityVariantResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using RapidCMS.Core.Abstractions.Resolvers; 4 | 5 | namespace RapidCMS.Core.Resolvers.Repositories; 6 | 7 | internal class EntityVariantResolver : IEntityVariantResolver 8 | { 9 | private readonly IReadOnlyDictionary derivedTypes)> _entityVariants; 10 | 11 | public EntityVariantResolver(IReadOnlyDictionary derivedTypes)> entityVariants) 12 | { 13 | _entityVariants = entityVariants; 14 | } 15 | 16 | public (Type? baseType, IReadOnlyList? derivedTypes) GetValidVariantsForRepository(string repositoryAlias) 17 | => _entityVariants.TryGetValue(repositoryAlias, out var value) ? value : default; 18 | } 19 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Displays/LinkDisplay.razor: -------------------------------------------------------------------------------- 1 | @inherits BaseDisplay 2 | @implements IRequireConfiguration 3 | 4 | 14 | 15 | @code { 16 | private Link? Config { get; set; } 17 | 18 | private string? value { get; set; } 19 | 20 | protected override async Task OnParametersSetAsync() 21 | { 22 | value = GetValueAsString(); 23 | 24 | if (string.IsNullOrWhiteSpace(value)) 25 | { 26 | value = " "; 27 | } 28 | 29 | Config = await this.GetConfigAsync(); 30 | 31 | StateHasChanged(); 32 | } 33 | } -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Panes/BaseSidePane.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Components; 3 | using RapidCMS.Core.Abstractions.Mediators; 4 | using RapidCMS.Core.Enums; 5 | using RapidCMS.Core.Forms; 6 | using RapidCMS.Core.Models.EventArgs.Mediators; 7 | 8 | namespace RapidCMS.UI.Components.Panes; 9 | 10 | public abstract class BaseSidePane : ComponentBase 11 | { 12 | [Inject] private IMediator Mediator { get; set; } = default!; 13 | 14 | [Parameter] public FormEditContext? EditContext { get; set; } 15 | [Parameter] public ButtonContext ButtonContext { get; set; } = default!; 16 | [Parameter] public Guid RequestId { get; set; } = default!; 17 | 18 | protected void ButtonClicked(CrudType crudType) 19 | { 20 | Mediator.NotifyEvent(this, new PaneResponseEventArgs(RequestId, crudType)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/EventArgs/Mediators/PaneRequestEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Mediators; 3 | using RapidCMS.Core.Enums; 4 | using RapidCMS.Core.Forms; 5 | 6 | namespace RapidCMS.Core.Models.EventArgs.Mediators; 7 | 8 | public class PaneRequestEventArgs : IMediatorRequestEventArgs 9 | { 10 | public PaneRequestEventArgs(Type paneType, FormEditContext? editContext, ButtonContext buttonContext) 11 | { 12 | PaneType = paneType; 13 | EditContext = editContext; 14 | ButtonContext = buttonContext ?? throw new ArgumentNullException(nameof(buttonContext)); 15 | } 16 | 17 | public Guid RequestId { get; set; } 18 | 19 | public Type PaneType { get; set; } 20 | public FormEditContext? EditContext { get; set; } 21 | public ButtonContext ButtonContext { get; set; } 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Metadata/FullPropertyMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using RapidCMS.Core.Abstractions.Metadata; 4 | 5 | namespace RapidCMS.Core.Models.Metadata; 6 | 7 | internal class FullPropertyMetadata : PropertyMetadata, IFullPropertyMetadata 8 | { 9 | public FullPropertyMetadata( 10 | LambdaExpression originalExpression, 11 | Type propertyType, 12 | string propertyName, 13 | Func getter, 14 | Action setter, 15 | Type objectType, 16 | string fingerprint) : base(originalExpression, propertyType, propertyName, getter, objectType, fingerprint) 17 | { 18 | Setter = setter ?? throw new ArgumentNullException(nameof(setter)); 19 | } 20 | 21 | public Action Setter { get; private set; } 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Resolvers/Setup/TreeViewSetupResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Abstractions.Resolvers; 3 | using RapidCMS.Core.Models.Config; 4 | using RapidCMS.Core.Models.Setup; 5 | 6 | namespace RapidCMS.Core.Resolvers.Setup; 7 | 8 | internal class TreeViewSetupResolver : ISetupResolver 9 | { 10 | public Task> ResolveSetupAsync(TreeViewConfig config, CollectionSetup? collection = default) 11 | { 12 | return Task.FromResult>(new ResolvedSetup(new TreeViewSetup( 13 | config.EntityVisibilty, 14 | config.RootVisibility, 15 | config.DefaultOpenEntities, 16 | config.DefaultOpenCollections, 17 | config.Name), 18 | true)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IOrderBy.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Metadata; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Abstractions.Data; 5 | 6 | public interface IOrderBy 7 | { 8 | /// 9 | /// Direction of this order by. 10 | /// 11 | OrderByType OrderByType { get; } 12 | 13 | /// 14 | /// Expression specifying how the sorting is done. 15 | /// 16 | IPropertyMetadata OrderByExpression { get; } 17 | 18 | /// 19 | /// Property to which this order by is applied (when used in Editor). 20 | /// 21 | IPropertyMetadata? Property { get; } 22 | 23 | /// 24 | /// Expression to which this order by is applied (when used in View). 25 | /// 26 | IExpressionMetadata? Expression { get; } 27 | } 28 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/UploadFileModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using RapidCMS.Core.Abstractions.Data; 4 | 5 | namespace RapidCMS.Core.Models.ApiBridge.Request; 6 | 7 | public class UploadFileModel : IFileInfo 8 | { 9 | [Required] 10 | public string Name { get; set; } = default!; 11 | 12 | [Required] 13 | [Range(1, long.MaxValue)] 14 | public long Size { get; set; } 15 | 16 | [Required] 17 | public string Type { get; set; } = default!; 18 | 19 | public long? LastModified { get; set; } 20 | 21 | public DateTime? LastModifiedDate 22 | { 23 | get => DateTimeOffset.FromUnixTimeMilliseconds(LastModified ?? 0).UtcDateTime; 24 | set => LastModified = !value.HasValue ? 0 : new DateTimeOffset(value.Value).ToUnixTimeMilliseconds(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Authorization/AllowAllAuthorizationHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Authorization.Infrastructure; 4 | using RapidCMS.Core.Abstractions.Data; 5 | 6 | namespace RapidCMS.Core.Authorization; 7 | 8 | internal class AllowAllAuthorizationHandler : AuthorizationHandler 9 | { 10 | protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OperationAuthorizationRequirement requirement, IEntity resource) 11 | { 12 | if (context.User.Identity?.AuthenticationType == "anonymous") 13 | { 14 | context.Succeed(requirement); 15 | } 16 | else 17 | { 18 | context.Fail(); 19 | } 20 | 21 | return Task.CompletedTask; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Handlers/OpenPaneButtonActionHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using RapidCMS.Core.Abstractions.Mediators; 3 | using RapidCMS.Core.Enums; 4 | using RapidCMS.Core.Forms; 5 | using RapidCMS.Core.Models.EventArgs.Mediators; 6 | using RapidCMS.Core.Models.Setup; 7 | 8 | namespace RapidCMS.Core.Handlers; 9 | 10 | public class OpenPaneButtonActionHandler : DefaultButtonActionHandler 11 | { 12 | private readonly IMediator _mediator; 13 | 14 | public OpenPaneButtonActionHandler(IMediator mediator) 15 | { 16 | _mediator = mediator; 17 | } 18 | 19 | public override Task ButtonClickBeforeRepositoryActionAsync(ButtonSetup button, FormEditContext editContext, ButtonContext context) 20 | => _mediator.NotifyEventAsync(this, new PaneRequestEventArgs(typeof(TSidePane), editContext, context)); 21 | } 22 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/Convention/ConventionListEditorConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Config; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Models.Config.Convention; 5 | 6 | internal class ConventionListEditorConfig : ListConfig, IIsConventionBased 7 | { 8 | public ConventionListEditorConfig(bool canGoToNodeEditor, ListType type) : base(typeof(TEntity)) 9 | { 10 | Type = type; 11 | CanGoToNodeEditor = canGoToNodeEditor; 12 | } 13 | 14 | public ListType Type { get; } 15 | 16 | public bool CanGoToNodeEditor { get; } 17 | 18 | public Features GetFeatures() 19 | { 20 | return Features.CanEdit | 21 | (CanGoToNodeEditor ? Features.CanGoToEdit : Features.None) | 22 | ((Type == ListType.Block) ? Features.IsBlockList : Features.None); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Data/OrderBy.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Abstractions.Metadata; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.Data; 6 | 7 | internal class OrderBy : IOrderBy 8 | { 9 | public OrderBy(OrderByType orderByType, IPropertyMetadata orderByExpression, IPropertyMetadata? property, IExpressionMetadata? expression) 10 | { 11 | OrderByType = orderByType; 12 | OrderByExpression = orderByExpression; 13 | Expression = expression; 14 | Property = property; 15 | } 16 | 17 | public OrderByType OrderByType { get; private set; } 18 | 19 | public IPropertyMetadata OrderByExpression { get; private set; } 20 | 21 | public IPropertyMetadata? Property { get; private set; } 22 | public IExpressionMetadata? Expression { get; private set; } 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Data/IDataView.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq.Expressions; 3 | using RapidCMS.Core.Abstractions.Metadata; 4 | using RapidCMS.Core.Enums; 5 | 6 | namespace RapidCMS.Core.Abstractions.Data; 7 | 8 | public interface IDataView 9 | { 10 | /// 11 | /// Id of the data view. 12 | /// 13 | int Id { get; } 14 | 15 | /// 16 | /// Display label of the data view. 17 | /// 18 | string Label { get; } 19 | 20 | /// 21 | /// Associated query expression of this data view. 22 | /// 23 | LambdaExpression QueryExpression { get; } 24 | 25 | /// 26 | /// Default sorts for this data view. 27 | /// 28 | IEnumerable> DefaultOrderBys { get; } 29 | } 30 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Extensions/ServiceProviderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace RapidCMS.Core.Extensions; 4 | 5 | internal static class ServiceProviderExtensions 6 | { 7 | public static T GetService(this IServiceProvider serviceProvider, Type type) 8 | where T : class 9 | { 10 | return (serviceProvider.GetService(type) ?? throw new InvalidOperationException($"Failed to resolve instance of type {type}")) 11 | as T ?? throw new InvalidOperationException($"Resolved instance of type {type}, but failed to cast it as {typeof(T)}"); 12 | } 13 | 14 | public static T GetService(this IServiceProvider serviceProvider) 15 | where T : class 16 | { 17 | return serviceProvider.GetService(typeof(T)) as T ?? throw new InvalidOperationException($"Failed to resolve instance of type {typeof(T)}"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/Entities/CountryPerson.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | 4 | namespace RapidCMS.Example.Github.Entities; 5 | 6 | internal class CountryPerson : IEntity, ICloneable 7 | { 8 | public string? Id { get; set; } 9 | public string? Name { get; set; } 10 | public string? Email { get; set; } 11 | public string? Bio { get; set; } 12 | 13 | public string? FavouriteCountryId1 { get; set; } 14 | public string? FavouriteCountryId2 { get; set; } 15 | 16 | public object Clone() 17 | { 18 | return new CountryPerson 19 | { 20 | Bio = Bio, 21 | Email = Email, 22 | Id = Id, 23 | Name = Name, 24 | FavouriteCountryId1 = FavouriteCountryId1, 25 | FavouriteCountryId2 = FavouriteCountryId2 26 | }; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/RapidCMS.Core.Tests/Services/Dispatchers/TestClasses.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace RapidCMS.Core.Tests.Services.Dispatchers; 5 | 6 | public class DefaultEntityVariant : IEntity 7 | { 8 | public string? Id { get; set; } 9 | } 10 | public class SubEntityVariant1 : DefaultEntityVariant 11 | { 12 | } 13 | public class SubEntityVariant2 : DefaultEntityVariant 14 | { 15 | } 16 | public class SubEntityVariant3 : DefaultEntityVariant 17 | { 18 | } 19 | 20 | public class ValidEntity : IEntity 21 | { 22 | public string? Id { get; set; } 23 | 24 | [Required] 25 | public string Name { get; set; } = "Something"; 26 | } 27 | 28 | public class InvalidEntity : IEntity 29 | { 30 | public string? Id { get; set; } 31 | 32 | [Required] 33 | public string Name { get; set; } = default!; 34 | } 35 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Pages/CmsPage.razor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Components; 4 | using RapidCMS.Core.Abstractions.Mediators; 5 | using RapidCMS.Core.Abstractions.Navigation; 6 | 7 | namespace RapidCMS.UI.Components.Pages; 8 | 9 | [Authorize] 10 | public partial class CmsPage 11 | { 12 | [Inject] private INavigationStateProvider NavigationState { get; set; } = default!; 13 | 14 | [Inject] private IMediator Mediator { get; set; } = default!; 15 | [Inject] private NavigationManager NavigationManager { get; set; } = default!; 16 | 17 | [Parameter] public string? PageRoute { get; set; } 18 | 19 | protected override void OnInitialized() 20 | { 21 | base.OnInitialized(); 22 | 23 | NavigationState.Initialize(PageRoute ?? "", new Uri(NavigationManager.Uri).Query); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/Entities/RelatablePerson.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using RapidCMS.Core.Abstractions.Data; 5 | using RapidCMS.Core.Extensions; 6 | 7 | namespace RapidCMS.Example.Github.Entities; 8 | 9 | internal class RelatablePerson : IEntity, ICloneable 10 | { 11 | public string? Id { get; set; } 12 | public string? Name { get; set; } 13 | public string? Email { get; set; } 14 | public string? Bio { get; set; } 15 | 16 | public List Countries { get; set; } = new List(); 17 | 18 | public object Clone() 19 | { 20 | return new RelatablePerson 21 | { 22 | Bio = Bio, 23 | Email = Email, 24 | Id = Id, 25 | Name = Name, 26 | Countries = Countries.ToList(x => (Country)x.Clone()) 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Github/Entities/ValidationPerson.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.DataAnnotations; 3 | using RapidCMS.Core.Abstractions.Data; 4 | using RapidCMS.Example.Github.Attributes; 5 | 6 | namespace RapidCMS.Example.Github.Entities; 7 | 8 | internal class ValidationPerson : IEntity, ICloneable 9 | { 10 | public string? Id { get; set; } 11 | 12 | [Required] 13 | [MinLength(10)] 14 | public string? Name { get; set; } 15 | 16 | [EmailAddress] 17 | [Required] 18 | public string? Email { get; set; } 19 | 20 | [Required] 21 | [BioValidation] 22 | public string? Bio { get; set; } 23 | 24 | public object Clone() 25 | { 26 | return new ValidationPerson 27 | { 28 | Bio = Bio, 29 | Email = Email, 30 | Id = Id, 31 | Name = Name 32 | }; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/RapidCMS.Api.WebApi/Conventions/CollectionControllerRouteConvention.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Mvc.ApplicationModels; 2 | using RapidCMS.Api.WebApi.Controllers; 3 | using RapidCMS.Core.Extensions; 4 | 5 | namespace RapidCMS.Api.WebApi.Conventions; 6 | 7 | public class CollectionControllerRouteConvention : IControllerModelConvention 8 | { 9 | public const string RouteTemplatePrefix = "/api/"; 10 | 11 | public void Apply(ControllerModel controller) 12 | { 13 | if (controller.ControllerType.In(typeof(ApiRepositoryController), typeof(ApiFileUploadController))) 14 | { 15 | controller.Selectors.Add(new SelectorModel 16 | { 17 | AttributeRouteModel = new AttributeRouteModel 18 | { 19 | Template = RouteTemplatePrefix 20 | } 21 | }); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/OrderByModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Abstractions.Metadata; 4 | using RapidCMS.Core.Enums; 5 | 6 | namespace RapidCMS.Core.Models.ApiBridge.Request; 7 | 8 | public class OrderByModel : IOrderBy 9 | { 10 | public OrderByModel(OrderByType type, IPropertyMetadata property) 11 | { 12 | OrderByType = type; 13 | OrderByExpression = property; 14 | } 15 | 16 | public OrderByType OrderByType { get; private set; } 17 | 18 | public IPropertyMetadata OrderByExpression { get; private set; } 19 | 20 | public IPropertyMetadata? Property => throw new InvalidOperationException("Cannot access this property when using in Api"); 21 | 22 | public IExpressionMetadata? Expression => throw new InvalidOperationException("Cannot access this property when using in Api"); 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Shared/NavMenu.razor: -------------------------------------------------------------------------------- 1 | @inject ITreeService TreeService 2 | @inject NavigationManager NavigationManager 3 | 4 | 22 | 23 | @code { 24 | TreeRootUI? TreeRoot; 25 | 26 | protected override async Task OnInitializedAsync() 27 | { 28 | TreeRoot = await TreeService.GetRootAsync(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IListEditorConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | using RapidCMS.Core.Enums; 3 | 4 | namespace RapidCMS.Core.Abstractions.Config; 5 | 6 | public interface IListEditorConfig 7 | : IHasButtons>, 8 | IHasPageSize>, 9 | IHasSearchBar>, 10 | IHasEditorPanes>, 11 | ISupportReordering>, 12 | IHasColumnVisibility> 13 | where TEntity : IEntity 14 | { 15 | /// 16 | /// Controls how the ListEditor is displayed: each entity as a row in a table, or as a block in a list 17 | /// 18 | /// 19 | /// 20 | IListEditorConfig SetListType(ListType listType); 21 | } 22 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/Config/Convention/ConventionListViewConfig.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Config; 2 | using RapidCMS.Core.Abstractions.Data; 3 | using RapidCMS.Core.Enums; 4 | 5 | namespace RapidCMS.Core.Models.Config.Convention; 6 | 7 | internal class ConventionListViewConfig : ListConfig, IIsConventionBased 8 | where TEntity : IEntity 9 | { 10 | public ConventionListViewConfig(bool canGoToNodeEditor, bool canGoToNodeView) : base(typeof(TEntity)) 11 | { 12 | CanGoToNodeEditor = canGoToNodeEditor; 13 | CanGoToNodeView = canGoToNodeView; 14 | } 15 | 16 | public bool CanGoToNodeEditor { get; } 17 | public bool CanGoToNodeView { get; } 18 | 19 | public Features GetFeatures() 20 | { 21 | return CanGoToNodeEditor ? Features.CanGoToEdit : CanGoToNodeView ? Features.CanGoToView : Features.None; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Factories/IEditContextResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using RapidCMS.Core.Abstractions.Data; 5 | using RapidCMS.Core.Abstractions.Forms; 6 | using RapidCMS.Core.Enums; 7 | using RapidCMS.Core.Forms; 8 | 9 | namespace RapidCMS.Core.Abstractions.Factories; 10 | 11 | // TODO: this factory has too much parameters 12 | internal interface IEditContextFactory 13 | { 14 | Task GetEditContextWrapperAsync(FormEditContext editContext); 15 | Task GetEditContextWrapperAsync( 16 | UsageType usageType, 17 | EntityState entityState, 18 | Type repositoryEntityType, 19 | IEntity updatedEntity, 20 | IEntity referenceEntity, 21 | IParent? parent, 22 | IEnumerable<(string propertyName, string typeName, IEnumerable elements)> relations); 23 | } 24 | -------------------------------------------------------------------------------- /src/RapidCMS.UI/Components/Shared/Tree/Page.razor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Microsoft.AspNetCore.Components; 4 | using RapidCMS.Core.Models.Data; 5 | using RapidCMS.Core.Models.UI; 6 | 7 | namespace RapidCMS.UI.Components.Shared.Tree; 8 | 9 | public partial class Page 10 | { 11 | [Parameter] public string PageAlias { get; set; } = default!; 12 | [Parameter] public ParentPath? ParentPath { get; set; } = null; 13 | 14 | private TreePageUI? UI { get; set; } 15 | private string? Error { get; set; } 16 | 17 | protected override async Task OnParametersSetAsync() 18 | { 19 | try 20 | { 21 | UI = await TreeService.GetPageAsync(PageAlias, ParentPath); 22 | } 23 | catch (Exception ex) 24 | { 25 | UI = null; 26 | Error = ex.Message; 27 | } 28 | 29 | StateHasChanged(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Models/ApiBridge/Request/RelatedQueryModel.cs: -------------------------------------------------------------------------------- 1 | using RapidCMS.Core.Abstractions.Data; 2 | 3 | namespace RapidCMS.Core.Models.ApiBridge.Request; 4 | 5 | public class RelatedQueryModel : QueryModel 6 | { 7 | public RelatedQueryModel() { } 8 | 9 | public RelatedQueryModel(IRelated related) 10 | { 11 | Related = new EntityDescriptorModel 12 | { 13 | RepositoryAlias = related.RepositoryAlias, 14 | Id = related.Entity.Id!, 15 | ParentPath = related.Parent?.GetParentPath()?.ToPathString() 16 | }; 17 | } 18 | 19 | public RelatedQueryModel(IRelated related, IView view) : this(related) 20 | { 21 | Skip = view.Skip; 22 | Take = view.Take; 23 | SearchTerm = view.SearchTerm; 24 | 25 | CollectionAlias = view.CollectionAlias; 26 | } 27 | 28 | public EntityDescriptorModel Related { get; set; } = default!; 29 | } 30 | -------------------------------------------------------------------------------- /SETUP_SERVERSIDE.md: -------------------------------------------------------------------------------- 1 | # Install RapidCMS server-side 2 | 3 | 1. Create a new ASP.NET Core Blazor Server-App project. 4 | 2. Install NuGet-package: `RapidCMS.UI`. 5 | 3. Add `builder.Services.AddRapidCMSServer(config => { config.AllowAnonymousUser(); })` before `var app = builder.Build();` in `Program.cs`. 6 | 4. Replace the `` in `App.razor` with ``. 7 | 5. Replace the `` tags in `_Layout.cshtml` with `` and remove any other css. Add `` at the end of the body tag. 8 | 6. Hit `F5`: you're now running a completely empty RapidCMS instance. 9 | 7. Start building your CMS by expanding `config => {}`. For reference, browse the [Examples](https://github.com/ThomasBleijendaal/RapidCMS/tree/master/examples) to see all the options. 10 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Services/Interaction/InteractionService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using RapidCMS.Core.Abstractions.Dispatchers; 5 | using RapidCMS.Core.Abstractions.Services; 6 | using RapidCMS.Core.Extensions; 7 | 8 | namespace RapidCMS.Core.Services.Persistence; 9 | 10 | internal class InteractionService : IInteractionService 11 | { 12 | private readonly IEnumerable _dispatchers; 13 | 14 | public InteractionService(IEnumerable dispatchers) 15 | { 16 | _dispatchers = dispatchers; 17 | } 18 | 19 | public Task InteractAsync(TRequest request) 20 | => _dispatchers.GetTypeFromList>()?.InvokeAsync(request) 21 | ?? throw new InvalidOperationException("Could not find the correct interaction dispatcher."); 22 | } 23 | -------------------------------------------------------------------------------- /src/RapidCMS.Core/Abstractions/Config/IHasNameDescription.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace RapidCMS.Core.Abstractions.Config; 4 | 5 | public interface IHasNameDescription 6 | { 7 | /// 8 | /// Sets the name of this field, used in table and list views. 9 | /// 10 | /// 11 | /// 12 | TReturn SetName(string name); 13 | 14 | /// 15 | /// Sets the description of this field, displayed under the name. 16 | /// 17 | /// 18 | /// 19 | TReturn SetDescription(string description); 20 | 21 | /// 22 | /// Sets the details of this field, displayed under the control. 23 | /// 24 | /// 25 | /// 26 | TReturn SetDetails(MarkupString details); 27 | } 28 | -------------------------------------------------------------------------------- /examples/RapidCMS.Example.Server/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Http 3 | @using Microsoft.AspNetCore.Components 4 | @using Microsoft.AspNetCore.Components.Authorization 5 | @using Microsoft.AspNetCore.Components.Forms 6 | @using Microsoft.AspNetCore.Components.Routing 7 | @using Microsoft.AspNetCore.Components.Web 8 | @using Microsoft.JSInterop 9 | 10 | @using RapidCMS.Core.Abstractions.Forms 11 | @using RapidCMS.Core.Abstractions.Repositories 12 | @using RapidCMS.Core.Enums 13 | @using RapidCMS.Core.Models.Data 14 | 15 | @using RapidCMS.Example.Shared 16 | @using RapidCMS.Example.Shared.Data 17 | 18 | @using RapidCMS.Repositories 19 | 20 | @using RapidCMS.UI.Components.Displays 21 | @using RapidCMS.UI.Components.Editors 22 | @using RapidCMS.UI.Components.Icons 23 | @using RapidCMS.UI.Components.Panes 24 | @using RapidCMS.UI.Components.Preview 25 | @using RapidCMS.UI.Components.Router 26 | @using RapidCMS.UI.Helpers 27 | --------------------------------------------------------------------------------