private IResolvedSetup <CollectionSetup> ConvertConfig(CollectionConfig config)
        {
            var collection = new CollectionSetup(
                config.Icon,
                config.Name,
                config.Alias,
                config.RepositoryType,
                isRecursive: config.Recursive,
                isResolverCachable: true) // TODO
            {
                DataViews       = config.DataViews,
                DataViewBuilder = config.DataViewBuilder
            };

            var cacheable = true;

            collection.EntityVariant = _entityVariantResolver.ResolveSetup(config.EntityVariant, collection).CheckIfCachable(ref cacheable);
            if (config.SubEntityVariants.Any())
            {
                collection.SubEntityVariants = _entityVariantResolver.ResolveSetup(config.SubEntityVariants, collection).CheckIfCachable(ref cacheable).ToList();
            }

            collection.TreeView = config.TreeView == null ? null : _treeViewResolver.ResolveSetup(config.TreeView, collection).CheckIfCachable(ref cacheable);

            collection.ListView   = config.ListView == null ? null : _listResolver.ResolveSetup(config.ListView, collection).CheckIfCachable(ref cacheable);
            collection.ListEditor = config.ListEditor == null ? null : _listResolver.ResolveSetup(config.ListEditor, collection).CheckIfCachable(ref cacheable);

            collection.NodeView   = config.NodeView == null ? null : _nodeResolver.ResolveSetup(config.NodeView, collection).CheckIfCachable(ref cacheable);
            collection.NodeEditor = config.NodeEditor == null ? null : _nodeResolver.ResolveSetup(config.NodeEditor, collection).CheckIfCachable(ref cacheable);

            collection.Collections = _treeElementResolver.ResolveSetup(config.CollectionsAndPages, collection).CheckIfCachable(ref cacheable).ToList();

            return(new ResolvedSetup <CollectionSetup>(collection, cacheable));
        }
Пример #2
0
        public async Task <TreeCollectionUI?> GetCollectionAsync(string alias, ParentPath?parentPath)
        {
            var collection = _collectionResolver.ResolveSetup(alias);

            if (collection == null)
            {
                throw new InvalidOperationException($"Failed to get collection for given alias ({alias}).");
            }

            var parent = await _parentService.GetParentAsync(parentPath);

            var testEntity = await _repositoryResolver.GetRepository(collection).NewAsync(parent, collection.EntityVariant.Type);

            var canEdit = collection.ListEditor != null && await _authService.IsUserAuthorizedAsync(Operations.Update, testEntity);

            var canView = collection.ListView != null && await _authService.IsUserAuthorizedAsync(Operations.Read, testEntity);

            if (!canEdit && !canView)
            {
                return(TreeCollectionUI.None);
            }

            var tree = new TreeCollectionUI(collection.Alias, collection.Name)
            {
                EntitiesVisible     = collection.TreeView?.EntityVisibility == EntityVisibilty.Visible,
                RootVisible         = collection.TreeView?.RootVisibility == CollectionRootVisibility.Visible,
                Icon                = collection.Icon ?? "list",
                DefaultOpenEntities = collection.TreeView?.DefaultOpenEntities ?? false
            };

            if (canEdit)
            {
                tree.State = new PageStateModel
                {
                    CollectionAlias = collection.Alias,
                    PageType        = PageType.Collection,
                    ParentPath      = parentPath,
                    UsageType       = UsageType.Edit
                };
            }
            else if (canView)
            {
                tree.State = new PageStateModel
                {
                    CollectionAlias = collection.Alias,
                    PageType        = PageType.Collection,
                    ParentPath      = parentPath,
                    UsageType       = UsageType.View
                };
            }

            return(tree);
        }
Пример #3
0
        public IResolvedSetup <ListSetup> ResolveSetup(ListConfig config, ICollectionSetup?collection = default)
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }

            if (config is IIsConventionBased isConventionBasedConfig)
            {
                config = _conventionListConfigResolver.ResolveByConvention(config.BaseType, isConventionBasedConfig.GetFeatures());
            }

            var cacheable = true;

            var panes   = _paneSetupResolver.ResolveSetup(config.Panes, collection).CheckIfCachable(ref cacheable).ToList();
            var buttons = _buttonSetupResolver.ResolveSetup(config.Buttons, collection).CheckIfCachable(ref cacheable).ToList();

            return(new ResolvedSetup <ListSetup>(new ListSetup(
                                                     config.PageSize,
                                                     config.SearchBarVisible,
                                                     config.ReorderingAllowed,
                                                     config.ListEditorType,
                                                     config.EmptyVariantColumnVisibility,
                                                     panes,
                                                     buttons), cacheable));
        }
Пример #4
0
        public IResolvedSetup <PaneSetup> ResolveSetup(PaneConfig config, ICollectionSetup?collection = default)
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }

            var cacheable = true;

            var buttons                = _buttonSetupResolver.ResolveSetup(config.Buttons, collection).CheckIfCachable(ref cacheable).ToList();
            var fields                 = _fieldSetupResolver.ResolveSetup(config.Fields, collection).CheckIfCachable(ref cacheable).ToList();
            var subCollectionLists     = _subCollectionSetupResolver.ResolveSetup(config.SubCollectionLists, collection).CheckIfCachable(ref cacheable).ToList();
            var relatedCollectionLists = _relatedCollectionSetupResolver.ResolveSetup(config.RelatedCollectionLists, collection).CheckIfCachable(ref cacheable).ToList();

            return(new ResolvedSetup <PaneSetup>(new PaneSetup(
                                                     config.CustomType,
                                                     config.Label,
                                                     config.IsVisible,
                                                     config.VariantType,
                                                     buttons,
                                                     fields,
                                                     subCollectionLists,
                                                     relatedCollectionLists),
                                                 cacheable));
        }
Пример #5
0
        IPageSetup ISetupResolver <IPageSetup> .ResolveSetup(string alias)
        {
            if (_cache.TryGetValue(alias, out var pageSetup))
            {
                return(pageSetup);
            }

            var config = _cmsConfig.CollectionsAndPages.SelectNotNull(x => x as IPageConfig).FirstOrDefault(x => x.Alias == alias);

            if (config == null)
            {
                throw new InvalidOperationException($"Cannot find page with alias {alias}.");
            }

            var cacheable = true;

            pageSetup = new PageRegistrationSetup
            {
                Name     = config.Name,
                Alias    = config.Alias,
                Icon     = config.Icon,
                Sections = _typeRegistrationSetupResolver.ResolveSetup(config.SectionRegistrations).CheckIfCachable(ref cacheable).ToList()
            };

            if (cacheable)
            {
                _cache[alias] = pageSetup;
            }

            return(pageSetup);
        }
        public override async Task <CrudType> ButtonClickBeforeRepositoryActionAsync(IButton button, FormEditContext editContext, ButtonContext context)
        {
            var request = await _navigationHandler.CreateNavigationRequestAsync(button, editContext);

            if (request != null)
            {
                var collection = request.IsPage ? null : _collectionResolver.ResolveSetup(request.CollectionAlias);

                var pageType = request.IsPage ? PageType.Page
                    : request.IsList ? PageType.Collection
                    : PageType.Node;
                var usageType = request.IsNew ? UsageType.New
                    : request.IsEdit ? UsageType.Edit
                    : UsageType.View;

                _mediator.NotifyEvent(this, new NavigationEventArgs(new PageStateModel
                {
                    CollectionAlias = request.CollectionAlias,
                    Id           = request.Id,
                    PageType     = pageType,
                    ParentPath   = request.ParentPath,
                    UsageType    = usageType,
                    VariantAlias = request.VariantAlias ?? collection?.EntityVariant.Alias ?? string.Empty
                }, true));
            }

            return(CrudType.None);
        }
Пример #7
0
        public Task <INodeUIResolver> GetNodeUIResolverAsync(UsageType usageType, string collectionAlias)
        {
            var collection = _collectionResolver.ResolveSetup(collectionAlias);
            var node       = usageType.HasFlag(UsageType.View)
                ? collection.NodeView ?? collection.NodeEditor
                : collection.NodeEditor ?? collection.NodeView;

            if (node == null)
            {
                throw new InvalidOperationException($"Failed to get UI configuration from collection {collectionAlias} for action {usageType}");
            }

            INodeUIResolver nodeUI = new NodeUIResolver(node, _dataProviderResolver, _buttonActionHandlerResolver, _authService);

            return(Task.FromResult(nodeUI));
        }
        public IEditContext GetEditContextWrapper(EditContext editContext)
        {
            var collection = _collectionResolver.ResolveSetup(editContext.CollectionAlias);

            var contextType = typeof(FormEditContextWrapper <>).MakeGenericType(collection.EntityVariant.Type);
            var instance    = Activator.CreateInstance(contextType, editContext);

            return((IEditContext)instance);
        }
        public IEditContext GetEditContextWrapper(FormEditContext editContext)
        {
            var collection = _collectionResolver.ResolveSetup(editContext.CollectionAlias);

            var contextType = typeof(FormEditContextWrapper <>).MakeGenericType(collection.EntityVariant.Type);
            var instance    = Activator.CreateInstance(contextType, editContext);

            return(instance as IEditContext ?? throw new InvalidOperationException("Cannot create FormEditContextWrapper"));
        }
Пример #10
0
        public CmsSetup(
            CmsConfig config,
            ISetupResolver <ITypeRegistration, CustomTypeRegistrationConfig> typeRegistrationSetupResolver)
        {
            _typeRegistrationSetupResolver = typeRegistrationSetupResolver;

            SiteName      = config.SiteName;
            IsDevelopment = config.IsDevelopment;

            if (config.CustomLoginScreenRegistration != null)
            {
                CustomLoginScreenRegistration = _typeRegistrationSetupResolver.ResolveSetup(config.CustomLoginScreenRegistration).Setup;
            }
            if (config.CustomLoginStatusRegistration != null)
            {
                CustomLoginStatusRegistration = _typeRegistrationSetupResolver.ResolveSetup(config.CustomLoginStatusRegistration).Setup;
            }
        }
Пример #11
0
        private IResolvedSetup <CollectionSetup> ConvertConfig(CollectionConfig config)
        {
            var repositoryAlias = _repositoryTypeResolver.GetAlias(config.RepositoryType);

            var collection = new CollectionSetup(
                config.Icon,
                config.Color,
                config.Name,
                config.Alias,
                repositoryAlias,
                isRecursive: config.Recursive,
                isResolverCachable: true) // TODO
            {
                DataViews       = config.DataViews,
                DataViewBuilder = config.DataViewBuilder,
                UsageType       = GetCollectionUsage(config)
            };

            var cacheable = true;

            if (!string.IsNullOrWhiteSpace(config.ParentAlias) && _collectionMap.TryGetValue(config.ParentAlias, out var collectionConfig))
            {
                collection.Parent = new TreeElementSetup(collectionConfig.Alias, PageType.Collection); // TODO: enum
            }
            collection.Collections = _treeElementResolver.ResolveSetup(config.CollectionsAndPages, collection).CheckIfCachable(ref cacheable).ToList();

            collection.EntityVariant = _entityVariantResolver.ResolveSetup(config.EntityVariant, collection).CheckIfCachable(ref cacheable);
            if (config.SubEntityVariants.Any())
            {
                collection.SubEntityVariants = _entityVariantResolver.ResolveSetup(config.SubEntityVariants, collection).CheckIfCachable(ref cacheable).ToList();
            }

            collection.TreeView = config.TreeView == null ? null : _treeViewResolver.ResolveSetup(config.TreeView, collection).CheckIfCachable(ref cacheable);

            collection.ListView   = config.ListView == null ? null : _listResolver.ResolveSetup(config.ListView, collection).CheckIfCachable(ref cacheable);
            collection.ListEditor = config.ListEditor == null ? null : _listResolver.ResolveSetup(config.ListEditor, collection).CheckIfCachable(ref cacheable);

            collection.NodeView   = config.NodeView == null ? null : _nodeResolver.ResolveSetup(config.NodeView, collection).CheckIfCachable(ref cacheable);
            collection.NodeEditor = config.NodeEditor == null ? null : _nodeResolver.ResolveSetup(config.NodeEditor, collection).CheckIfCachable(ref cacheable);

            return(new ResolvedSetup <CollectionSetup>(collection, cacheable));
        }
        private async Task <T> InvokeAsync <T>(PersistEntityRequestModel request, T response, IPageState pageState)
            where T : ViewCommandResponseModel
        {
            var collection = _collectionResolver.ResolveSetup(request.EditContext.CollectionAlias);
            var repository = _repositoryResolver.GetRepository(collection);

            var entityVariant = collection.GetEntityVariant(request.EditContext.Entity);

            var crudType = await _buttonInteraction.ValidateButtonInteractionAsync(request);

            switch (crudType)
            {
            case CrudType.View:
                pageState.PushState(new PageStateModel
                {
                    PageType  = PageType.Node,
                    UsageType = UsageType.View,

                    CollectionAlias = request.EditContext.CollectionAlias,
                    VariantAlias    = entityVariant.Alias,
                    ParentPath      = request.EditContext.Parent?.GetParentPath(),
                    Id = request.EditContext.Entity.Id
                });
                break;

            case CrudType.Edit:
                pageState.PushState(new PageStateModel
                {
                    PageType  = PageType.Node,
                    UsageType = UsageType.Edit,

                    CollectionAlias = request.EditContext.CollectionAlias,
                    VariantAlias    = entityVariant.Alias,
                    ParentPath      = request.EditContext.Parent?.GetParentPath(),
                    Id = request.EditContext.Entity.Id
                });
                break;

            case CrudType.Update:
                var updateContext = _editContextFactory.GetEditContextWrapper(request.EditContext);
                if (!updateContext.IsValid())
                {
                    throw new InvalidEntityException();
                }

                await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.UpdateAsync(updateContext));

                if (request.EditContext.IsReordered())
                {
                    await _concurrencyService.EnsureCorrectConcurrencyAsync(
                        () => repository.ReorderAsync(request.EditContext.ReorderedBeforeId, request.EditContext.Entity.Id !, request.EditContext.Parent));
                }

                response.RefreshIds = new[] { request.EditContext.Entity.Id ! };
Пример #13
0
        public FormDataProvider?GetDataProvider(FieldSetup field)
        {
            if (!(field is PropertyFieldSetup propertyField && propertyField.Relation != null))
            {
                return(null);
            }

            switch (propertyField.Relation)
            {
            case RepositoryRelationSetup collectionRelation:

                var repo = collectionRelation.RepositoryAlias != null
                            ? _repositoryResolver.GetRepository(collectionRelation.RepositoryAlias)
                            : collectionRelation.CollectionAlias != null
                                ? _repositoryResolver.GetRepository(_collectionSetupResolver.ResolveSetup(collectionRelation.CollectionAlias))
                                : default;

                if (repo == null)
                {
                    throw new InvalidOperationException($"Field {propertyField.Property!.PropertyName} has incorrectly configure relation, cannot find repository for alias {(collectionRelation.CollectionAlias ?? collectionRelation.RepositoryAlias)}.");
                }

                var provider = new CollectionDataProvider(
                    repo,
                    collectionRelation.RelatedEntityType,

                    propertyField.Property !,
                    collectionRelation.RelatedElementsGetter,

                    collectionRelation.RepositoryParentSelector,
                    collectionRelation.EntityAsParent,
                    collectionRelation.IdProperty,
                    collectionRelation.DisplayProperties,

                    _memoryCache);

                var validator = new RelationValidationAttributeValidator(propertyField.Property !);

                return(new FormDataProvider(
                           propertyField.Property !,
                           provider,
                           validator));

            case DataProviderRelationSetup dataProviderRelation:

                return(new FormDataProvider(propertyField.Property !, _serviceProvider.GetService <IDataCollection>(dataProviderRelation.DataCollectionType), default));

            default:
                throw new InvalidOperationException();
            }
            ;
        }
        public async Task ApplyDataViewToQueryAsync(IQuery query)
        {
            if (string.IsNullOrEmpty(query.CollectionAlias))
            {
                throw new ArgumentNullException($"{nameof(query)}.{nameof(query.CollectionAlias)}");
            }

            var collection = _collectionResolver.ResolveSetup(query.CollectionAlias);

            if (collection.DataViewBuilder != null || collection.DataViews?.Count > 0)
            {
                var dataViews = await GetDataViewsAsync(collection);

                var dataView = dataViews.FirstOrDefault(x => x.Id == query.ActiveTab)
                               ?? dataViews.FirstOrDefault();

                if (dataView != null)
                {
                    query.SetDataView(dataView);
                }
            }
        }
Пример #15
0
        private (IButtonActionHandler handler, IButtonSetup button) FindButtonHandler(string collectionAlias, string buttonId)
        {
            var collection = _collectionResolver.ResolveSetup(collectionAlias);

            var button = collection.FindButton(buttonId);

            if (button == null)
            {
                throw new Exception($"Cannot determine which button triggered action for collection {collectionAlias}");
            }

            return(_buttonActionHandlerResolver.GetButtonActionHandler(button), button);
        }
Пример #16
0
        public async Task <ListContext> GetAsync(GetEntitiesRequestModel request)
        {
            var collection = _collectionResolver.ResolveSetup(request.CollectionAlias);
            var variant    = collection.GetEntityVariant(request.VariantAlias);
            var repository = _repositoryResolver.GetRepository(collection);

            var requestedEntityVariantIsDefaultVariant = variant.Alias == collection.EntityVariant.Alias;

            var parent = request is GetEntitiesOfParentRequestModel parentRequest ? await _parentService.GetParentAsync(parentRequest.ParentPath) : default;

            var relatedEntity = (request as GetEntitiesOfRelationRequestModel)?.Related;

            var protoEntity = await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.NewAsync(parent, collection.EntityVariant.Type));

            var newEntity = requestedEntityVariantIsDefaultVariant
                ? protoEntity
                : await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.NewAsync(parent, variant.Type));

            await _authService.EnsureAuthorizedUserAsync(request.UsageType, protoEntity);

            await _dataViewResolver.ApplyDataViewToQueryAsync(request.Query);

            var action = (request.UsageType & ~(UsageType.List | UsageType.Root | UsageType.NotRoot)) switch
            {
                UsageType.Add when relatedEntity != null => () => repository.GetAllNonRelatedAsync(relatedEntity !, request.Query),
                _ when relatedEntity != null => () => repository.GetAllRelatedAsync(relatedEntity !, request.Query),
                _ when relatedEntity == null => () => repository.GetAllAsync(parent, request.Query),

                _ => default(Func <Task <IEnumerable <IEntity> > >)
            };

            if (action == default)
            {
                throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method");
            }

            var existingEntities = await _concurrencyService.EnsureCorrectConcurrencyAsync(action);

            var protoEditContext = new EditContext(request.CollectionAlias, collection.RepositoryAlias, collection.EntityVariant.Alias, protoEntity, parent, request.UsageType | UsageType.List, _serviceProvider);
            var newEditContext   = new EditContext(request.CollectionAlias, collection.RepositoryAlias, variant.Alias, newEntity, parent, request.UsageType | UsageType.Node, _serviceProvider);

            return(new ListContext(
                       request.CollectionAlias,
                       protoEditContext,
                       parent,
                       request.UsageType,
                       ConvertEditContexts(request, protoEditContext, newEditContext, existingEntities),
                       _serviceProvider));
        }
Пример #17
0
        public Task <TreePageUI?> GetPageAsync(string alias)
        {
            var page = _pageResolver.ResolveSetup(alias);

            if (page == null)
            {
                throw new InvalidOperationException($"Failed to get page for given alias ({alias}).");
            }

            return(Task.FromResult(new TreePageUI(page.Name, page.Icon, new PageStateModel
            {
                CollectionAlias = page.Alias,
                PageType = PageType.Page
            })) !);
        }
Пример #18
0
        public CmsSetup(CmsConfig config,
                        ISetupResolver <IPageSetup> pageResolver,
                        ISetupResolver <ICollectionSetup> collectionResolver,
                        ISetupResolver <IEnumerable <ITreeElementSetup> > treeElementsResolver,
                        ISetupResolver <ITypeRegistration, CustomTypeRegistrationConfig> typeRegistrationSetupResolver)
        {
            _pageResolver                  = pageResolver;
            _collectionResolver            = collectionResolver;
            _treeElementsResolver          = treeElementsResolver;
            _typeRegistrationSetupResolver = typeRegistrationSetupResolver;

            // TODO: resolve?
            SiteName      = config.SiteName;
            IsDevelopment = config.IsDevelopment;

            if (config.CustomLoginScreenRegistration != null)
            {
                CustomLoginScreenRegistration = _typeRegistrationSetupResolver.ResolveSetup(config.CustomLoginScreenRegistration).Setup;
            }
            if (config.CustomLoginStatusRegistration != null)
            {
                CustomLoginStatusRegistration = _typeRegistrationSetupResolver.ResolveSetup(config.CustomLoginStatusRegistration).Setup;
            }
        }
Пример #19
0
        public async Task <IEntity> GetAsync(GetEntityRequestModel request)
        {
            if (string.IsNullOrWhiteSpace(request.Subject.Id) && (request.UsageType.HasFlag(UsageType.View) || request.UsageType.HasFlag(UsageType.Edit)))
            {
                throw new InvalidOperationException($"Cannot View/Edit Node when id is null");
            }
            if (!string.IsNullOrWhiteSpace(request.Subject.Id) && request.UsageType.HasFlag(UsageType.New))
            {
                throw new InvalidOperationException($"Cannot New Node when id is not null");
            }

            var repository = _repositoryResolver.GetRepository(request.Subject.RepositoryAlias ?? throw new ArgumentNullException());

            var parent = await _parentService.GetParentAsync(ParentPath.TryParse(request.Subject.ParentPath));

            var entityVariant = request.Subject.VariantAlias == null ? default : _entityVariantResolver.ResolveSetup(request.Subject.VariantAlias);

                                var action = (request.UsageType & ~(UsageType.Node | UsageType.Root | UsageType.NotRoot)) switch
                                {
                                    UsageType.View => () => repository.GetByIdAsync(request.Subject.Id !, parent),
                                    UsageType.Edit => () => repository.GetByIdAsync(request.Subject.Id !, parent),
                                    UsageType.New => () => repository.NewAsync(parent, entityVariant?.Type) !,

                                    _ => default(Func <Task <IEntity?> >)
                                };

                                if (action == default)
                                {
                                    throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method");
                                }

                                var entity = await action.Invoke();

                                if (entity == null)
                                {
                                    throw new NotFoundException("Failed to get entity for given id");
                                }

                                await _authService.EnsureAuthorizedUserAsync(request.UsageType, entity);

                                return(entity);
        }
    }
Пример #20
0
        public async Task <FormEditContext> GetAsync(GetEntityRequestModel request)
        {
            if (string.IsNullOrWhiteSpace(request.Id) && (request.UsageType.HasFlag(UsageType.View) || request.UsageType.HasFlag(UsageType.Edit)))
            {
                throw new InvalidOperationException($"Cannot View/Edit Node when id is null");
            }
            if (!string.IsNullOrWhiteSpace(request.Id) && request.UsageType.HasFlag(UsageType.New))
            {
                throw new InvalidOperationException($"Cannot New Node when id is not null");
            }

            var collection = _collectionResolver.ResolveSetup(request.CollectionAlias);
            var variant    = collection.GetEntityVariant(request.VariantAlias);
            var repository = _repositoryResolver.GetRepository(collection);

            var parent = await _parentService.GetParentAsync(request.ParentPath);

            var action = (request.UsageType & ~(UsageType.Node | UsageType.Root | UsageType.NotRoot)) switch
            {
                UsageType.View => () => repository.GetByIdAsync(request.Id !, parent),
                UsageType.Edit => () => repository.GetByIdAsync(request.Id !, parent),
                UsageType.New => () => repository.NewAsync(parent, variant.Type) !,

                _ => default(Func <Task <IEntity?> >)
            };

            if (action == default)
            {
                throw new InvalidOperationException($"UsageType {request.UsageType} is invalid for this method");
            }

            var entity = await _concurrencyService.EnsureCorrectConcurrencyAsync(action);

            if (entity == null)
            {
                throw new Exception("Failed to get entity for given id(s)");
            }

            await _authService.EnsureAuthorizedUserAsync(request.UsageType, entity);

            return(new FormEditContext(request.CollectionAlias, collection.RepositoryAlias, request.VariantAlias, entity, parent, request.UsageType | UsageType.Node, _serviceProvider));
        }
    }
        public IResolvedSetup <NodeSetup> ResolveSetup(NodeConfig config, ICollectionSetup?collection = default)
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }

            if (config is IIsConventionBased isConventionBasedConfig)
            {
                config = _conventionNodeConfigResolver.ResolveByConvention(config.BaseType, isConventionBasedConfig.GetFeatures(), collection);
            }

            var cacheable = true;

            var panes   = _paneSetupResolver.ResolveSetup(config.Panes, collection).CheckIfCachable(ref cacheable).ToList();
            var buttons = _buttonSetupResolver.ResolveSetup(config.Buttons, collection).CheckIfCachable(ref cacheable).ToList();

            return(new ResolvedSetup <NodeSetup>(new NodeSetup(
                                                     config.BaseType,
                                                     panes,
                                                     buttons),
                                                 cacheable));
        }
Пример #22
0
 IEnumerable <ITreeElementSetup> ISetupResolver <IEnumerable <ITreeElementSetup> > .ResolveSetup()
 {
     return(_treeElementResolver.ResolveSetup(_cmsConfig.CollectionsAndPages?.Skip(1) ?? Enumerable.Empty <ITreeElementConfig>()).Setup);
 }
Пример #23
0
        private async Task <T> InvokeAsync <T>(PersistEntitiesRequestModel request, T response, IPageState pageState)
            where T : ViewCommandResponseModel
        {
            var collection = _collectionResolver.ResolveSetup(request.ListContext.CollectionAlias);
            var repository = _repositoryResolver.GetRepository(collection);

            var(crudType, entityVariant) = await _buttonInteraction.ValidateButtonInteractionAsync(request);

            switch (crudType)
            {
            case CrudType.Create:
                if (entityVariant == null)
                {
                    throw new InvalidOperationException($"Button of type {CrudType.Create} must have an EntityVariant.");
                }
                if (response is ListViewCommandResponseModel)
                {
                    pageState.PushState(new PageStateModel
                    {
                        PageType  = PageType.Node,
                        UsageType = UsageType.New,

                        CollectionAlias = request.ListContext.CollectionAlias,
                        VariantAlias    = entityVariant.Alias,
                        ParentPath      = request.ListContext.Parent?.GetParentPath()
                    });
                }
                else
                {
                    var currentState = pageState.GetCurrentState();

                    pageState.PushState(new PageStateModel
                    {
                        PageType  = PageType.Collection,
                        UsageType = UsageType.New,

                        CollectionAlias = request.ListContext.CollectionAlias,
                        VariantAlias    = entityVariant.Alias,
                        ParentPath      = request.ListContext.Parent?.GetParentPath(),

                        // is this the best place here?
                        ActiveTab   = currentState?.ActiveTab,
                        CurrentPage = currentState?.CurrentPage ?? 1,
                        MaxPage     = currentState?.MaxPage,
                        SearchTerm  = currentState?.SearchTerm,
                    });
                }
                break;

            case CrudType.Update:
                var affectedEntities = new List <IEntity>();

                foreach (var editContext in request.ListContext.EditContexts.Where(f => f.IsModified() || f.IsReordered()))
                {
                    var innerRequest = new PersistEntityCollectionRequestModel
                    {
                        ActionId    = request.ActionId,
                        CustomData  = request.CustomData,
                        EditContext = editContext,
                        ListContext = request.ListContext
                    };

                    await _buttonInteraction.ValidateButtonInteractionAsync(innerRequest);

                    if (editContext.IsModified())
                    {
                        await _concurrencyService.EnsureCorrectConcurrencyAsync(() => repository.UpdateAsync(editContext));
                    }
                    if (editContext.IsReordered())
                    {
                        await _concurrencyService.EnsureCorrectConcurrencyAsync(
                            () => repository.ReorderAsync(editContext.ReorderedBeforeId, editContext.Entity.Id !, editContext.Parent));
                    }

                    affectedEntities.Add(editContext.Entity);
                }

                response.RefreshIds = affectedEntities.SelectNotNull(x => x.Id);
                break;

            case CrudType.None:
                response.NoOp = true;
                break;

            case CrudType.Refresh:
                break;

            case CrudType.Return:
                if (pageState.PopState() == null)
                {
                    pageState.ReplaceState(new PageStateModel
                    {
                        PageType  = PageType.Collection,
                        UsageType = collection.ListEditor == null ? UsageType.View : UsageType.Edit,

                        CollectionAlias = request.ListContext.CollectionAlias,
                        ParentPath      = request.ListContext.Parent?.GetParentPath()
                    });
                }
                break;

            case CrudType.Up:
                if (pageState.PopState() == null)
                {
                    var(newParentPath, parentCollectionAlias, parentId) = ParentPath.RemoveLevel(request.ListContext.Parent?.GetParentPath());

                    if (parentCollectionAlias == null)
                    {
                        break;
                    }

                    var parentCollection = _collectionResolver.ResolveSetup(parentCollectionAlias);

                    pageState.ReplaceState(new PageStateModel
                    {
                        PageType  = PageType.Node,
                        UsageType = parentCollection.NodeEditor == null ? UsageType.View : UsageType.Edit,

                        CollectionAlias = parentCollectionAlias,
                        ParentPath      = newParentPath,
                        VariantAlias    = collection.EntityVariant.Alias,
                        Id = parentId
                    });
                }
                break;

            case CrudType.Add when request.Related != null:
                pageState.PushState(new PageStateModel
                {
                    PageType  = PageType.Collection,
                    UsageType = UsageType.Add,

                    CollectionAlias = request.ListContext.CollectionAlias,
                    Related         = request.Related
                });
                break;

            default:
                throw new InvalidOperationException();
            }

            await _buttonInteraction.CompleteButtonInteractionAsync(request);

            return(response);
        }
        public static IResolvedSetup <IEnumerable <TSetup> > ResolveSetup <TSetup, TConfig>(this ISetupResolver <TSetup, TConfig> resolver, IEnumerable <TConfig> configs, ICollectionSetup?collection = default)
            where TConfig : notnull
        {
            var allCachable = true;

            return(new ResolvedSetup <IEnumerable <TSetup> >(configs.Select(config => resolver.ResolveSetup(config, collection).CheckIfCachable(ref allCachable)), allCachable));
        }
Пример #25
0
        public async Task <TreeCollectionUI?> GetCollectionAsync(string alias, ParentPath?parentPath)
        {
            var collection = _collectionResolver.ResolveSetup(alias);

            if (collection == null)
            {
                throw new InvalidOperationException($"Failed to get collection for given alias ({alias}).");
            }

            var parent = await _parentService.GetParentAsync(parentPath);

            var isList       = collection.UsageType.HasFlag(UsageType.List);
            var isListEditor = collection.ListEditor != null;
            var isListView   = collection.ListView != null;
            var isDetails    = collection.UsageType.HasFlag(UsageType.Details) && parent?.Entity != null;

            var entity = isList
                ? await _repositoryResolver.GetRepository(collection).NewAsync(parent, collection.EntityVariant.Type)
                : await _repositoryResolver.GetRepository(collection).GetByIdAsync(parent !.Entity.Id !, parent)
                         ?? throw new InvalidOperationException($"Failed to get detail entity for given alias ({alias}) -- a detail entity should always exist.");

            var canEdit = (isList && isListEditor && await _authService.IsUserAuthorizedAsync(Operations.Update, entity)) ||
                          (isDetails && await _authService.IsUserAuthorizedAsync(Operations.Update, parent !.Entity));
            var canView = isList && isListView && await _authService.IsUserAuthorizedAsync(Operations.Read, entity);

            if (!canEdit && !canView)
            {
                return(TreeCollectionUI.None);
            }

            var tree = new TreeCollectionUI(collection.Alias, collection.RepositoryAlias, collection.Name)
            {
                EntitiesVisible     = collection.TreeView?.EntityVisibility == EntityVisibilty.Visible,
                RootVisible         = collection.TreeView?.RootVisibility == CollectionRootVisibility.Visible,
                Icon                = collection.Icon ?? "Database",
                Color               = collection.Color,
                DefaultOpenEntities = collection.TreeView?.DefaultOpenEntities ?? false
            };

            if (canEdit)
            {
                if (isList)
                {
                    tree.State = new PageStateModel
                    {
                        CollectionAlias = collection.Alias,
                        PageType        = PageType.Collection,
                        ParentPath      = parentPath,
                        UsageType       = UsageType.Edit | ((parentPath != null) ? UsageType.NotRoot : UsageType.Root)
                    };
                }
                else if (isDetails)
                {
                    var entityVariant = collection.GetEntityVariant(entity);

                    tree.State = new PageStateModel
                    {
                        CollectionAlias = collection.Alias,
                        Id           = parent !.Entity.Id,
                        PageType     = PageType.Node,
                        ParentPath   = parentPath,
                        UsageType    = UsageType.Edit,
                        VariantAlias = entityVariant.Alias
                    };
                }
            }
            else if (canView)
            {
                tree.State = new PageStateModel
                {
                    CollectionAlias = collection.Alias,
                    PageType        = PageType.Collection,
                    ParentPath      = parentPath,
                    UsageType       = UsageType.View | ((parentPath != null) ? UsageType.NotRoot : UsageType.Root)
                };
            }

            return(tree);
        }
Пример #26
0
 public Task <IEnumerable <ITypeRegistration> > GetAsync(string request)
 {
     return(Task.FromResult(_pageResolver.ResolveSetup(request).Sections.AsEnumerable()));
 }
Пример #27
0
 IRepository IRepositoryResolver.GetRepository(string collectionAlias)
 {
     return((this as IRepositoryResolver).GetRepository(_collectionResolver.ResolveSetup(collectionAlias)));
 }
Пример #28
0
        public IDisposable SubscribeToRepositoryUpdates(string alias, Func <Task> asyncCallback)
        {
            var collection = _collectionResolver.ResolveSetup(alias);

            return(_repositoryResolver.GetRepository(collection).ChangeToken.RegisterChangeCallback((x) => asyncCallback.Invoke(), null));
        }