Example #1
0
        /// <summary>
        /// Retrieves fluent configuration wrapper for form field
        /// </summary>
        /// <typeparam name="TData">Field type</typeparam>
        /// <param name="field">Field expression</param>
        /// <returns>Formwatch field configuration builder</returns>
        public FormWatchFieldBuilder <TData> Field <TData>(Expression <Func <TFormViewModel, TData> > field)
        {
            var prop = LambdaHelpers.ParsePropertyLambda(field);

            AssureFieldConfiguration <TData>(prop);
            return((FormWatchFieldBuilder <TData>)_fieldsConfig[prop.Name]);
        }
Example #2
0
        private Func <object, string> GetConverterForType(Type propertyType)
        {
            if (propertyType.IsEnum)
            {
                return(o => ((Enum)o).GetDisplayName());
            }
            if (typeof(string).IsAssignableFrom(propertyType))
            {
                return(o => (string)o); //Prevent futher conversion
            }

            var enumerableArg = LambdaHelpers.GetEnumerableType(propertyType);

            if (enumerableArg != null)
            {
                return(LambdaHelpers.GetEnumerableConvertor(GetConverterForType(enumerableArg)));
            }

            if (typeof(IEnumerable).IsAssignableFrom(propertyType))
            {
                return(LambdaHelpers.GetEnumerableConvertor(item => item.ToString()));
            }
            return
                (DisplayFunctions.Where(
                     displayFunction => displayFunction.Key.IsAssignableFrom(propertyType))
                 .Select(kv => kv.Value)
                 .FirstOrDefault() ?? (arg => arg?.ToString()));
        }
Example #3
0
 /// <summary>
 /// Filters specified target table field with form field treated as ValueFilter.
 /// Warning! ValueFilter should be configured for column
 /// </summary>
 /// <param name="expr">Property expression</param>
 /// <param name="af">Filter</param>
 public static void FilterValueExpr <TCol, TForm>(this FormWatchAutofilterConfiguration <TCol, TForm> af, LambdaExpression expr)
 {
     af.Update(new FormWatchFilteringsMappings()
     {
         FilterType = 0,
         FieldKeys  = new[] { LambdaHelpers.ParsePropertyLambda(expr).Name }
     });
 }
Example #4
0
 /// <summary>
 /// Filters specified target table field with form field treated as Range Filter.
 /// In this case field is list or array (e.g. mapped to multiple select)
 /// Warning! SelectFilter with multiple options should be configured for column
 /// </summary>
 /// <param name="field">Fields that will be merged into multiple filter values</param>
 public static void FilterMultiple <TCol, TForm>(this FormWatchAutofilterConfiguration <TCol, TForm> af, Expression <Func <TForm, IEnumerable <TCol> > > field)
 {
     af.Update(new FormWatchFilteringsMappings()
     {
         FilterType = 2,
         FieldKeys  = new [] { LambdaHelpers.ParsePropertyLambda(field).Name }
     });
 }
Example #5
0
 /// <summary>
 /// Filters specified target table field with form field treated as Range Filter.
 /// Warning! SelectFilter with multiple options should be configured for column
 /// </summary>
 /// <param name="fields">Fields that will be merged into multiple filter values</param>
 public static void FilterMultiple <TCol, TForm>(this FormWatchAutofilterConfiguration <TCol, TForm> af, params Expression <Func <TForm, TCol> >[] fields)
 {
     af.Update(new FormWatchFilteringsMappings()
     {
         FilterType = 2,
         FieldKeys  = fields.Select(c => LambdaHelpers.ParsePropertyLambda(c).Name).ToArray()
     });
 }
Example #6
0
 /// <summary>
 /// Filters specified target table field with form field treated as Range Filter.
 /// Warning! RangeFilter should be configured for column
 /// </summary>
 /// <param name="expr">Property expression</param>
 /// <param name="af">Filter</param>
 public static void FilterRangeExpr <TCol, TForm>(this FormWatchAutofilterConfiguration <TCol, TForm> af, LambdaExpression from, LambdaExpression to)
 {
     af.Update(new FormWatchFilteringsMappings()
     {
         FilterType = 1,
         FieldKeys  = new[] { LambdaHelpers.ParsePropertyLambda(from).Name,
                              LambdaHelpers.ParsePropertyLambda(to).Name, }
     });
 }
Example #7
0
 /// <summary>
 /// Filters specified target table field with form field treated as Range Filter.
 /// Warning! RangeFilter should be configured for column
 /// </summary>
 /// <param name="from">Field containig from value</param>
 /// <param name="to">Field containing to value</param>
 public static void FilterRange <TCol, TForm>(this FormWatchAutofilterConfiguration <TCol, TForm> af, Expression <Func <TForm, IEnumerable <TCol?> > > values)
     where TCol : struct
 {
     af.Update(new FormWatchFilteringsMappings()
     {
         FilterType = 1,
         FieldKeys  = new[] { LambdaHelpers.ParsePropertyLambda(values).Name }
     });
 }
Example #8
0
 private TableColumn GetTableColumn([NotNull] PropertyInfo propertyInfo)
 {
     return(new TableColumn
     {
         Getter = LambdaHelpers.CompileGetter(propertyInfo, TargetType),
         Name = propertyInfo.GetDisplayName(),
         Converter = GetConverterForType(propertyInfo.PropertyType),
     });
 }
Example #9
0
        /// <summary>
        /// Adds client total calculator function to totals
        /// Calculator function type: (data:IClientDataResults)=>any
        /// data: data prepared on client side. Consists of 4 collections: Source, Filtered, Ordered, Displaying all of type any[] containing corresponding JSONed TTableData
        /// </summary>
        /// <param name="column">Table column to provide total with</param>
        /// <param name="function">Client calculator function</param>
        /// <returns></returns>
        public TotalCalculatorBuilder <TSourceData, TTableData> AddClientCalculator <TTableColumn>(
            Expression <Func <TTableData, TTableColumn> > column,
            string function
            )
        {
            var name = LambdaHelpers.ParsePropertyLambda(column).Name;

            _clientCalculators.Add(name, function);
            return(this);
        }
Example #10
0
        private IQueryable <string> SelectCheckboxes(PowerTablesData data)
        {
            var column     = data.Request.Query.AdditionalData["SelectionColumn"];
            var columnProp = data.Configuration.SourceType.GetProperty(column);
            var selection  = LambdaHelpers.MemberExpression(columnProp);
            var q          = ReflectionCache.CallSelect(data.Ordered, selection, data.Configuration.SourceType,
                                                        columnProp.PropertyType);

            return(q.Cast <object>().Select(c => c.ToString()));
        }
Example #11
0
        /// <summary>
        /// Adds only template for total cell
        /// </summary>
        /// <param name="column">Table column to provide total with</param>
        /// <param name="templateBuilder">Template builder like for usual column, but here is only self reference ('{@}') available </param>
        /// <returns></returns>
        public TotalCalculatorBuilder <TSourceData, TTableData> AddTemplate <TTableColumn>(
            Expression <Func <TTableData, TTableColumn> > column,
            Action <CellTemplateBuilder> templateBuilder
            )
        {
            var name = LambdaHelpers.ParsePropertyLambda(column).Name;
            CellTemplateBuilder ctb = new CellTemplateBuilder(null);

            templateBuilder(ctb);
            _valueFunctions.Add(name, ctb.Build());
            return(this);
        }
Example #12
0
        /// <summary>
        /// Exclude specified column
        /// </summary>
        /// <typeparam name="TTableColumn"></typeparam>
        /// <param name="column">Column</param>
        /// <returns>Fluent</returns>
        public ColumnListBuilder <TSourceData, TTableData> Except <TTableColumn>(
            Expression <Func <TTableData, TTableColumn> > column)
        {
            var info = LambdaHelpers.ParsePropertyLambda(column);

            if (!_colNames.Contains(info.Name))
            {
                return(this);
            }
            _colNames.Remove(info.Name);
            return(this);
        }
Example #13
0
        /// <summary>
        /// Adds total calculator to table
        /// </summary>
        /// <param name="column">Table column to provide total with</param>
        /// <param name="calculator">Total calculator consuming ready-to-send table data and producing some value</param>
        /// <param name="valueFunction">Function that will be used to format total in the table.
        /// Function type is (v:any) => string
        /// v: value that you have calculated previously
        /// </param>
        /// <returns></returns>
        public TotalCalculatorBuilder <TSourceData, TTableData> AddTotal <TTableColumn, TTotalType>(
            Expression <Func <TTableData, TTableColumn> > column,
            Func <PowerTablesData <TSourceData, TTableData>, TTotalType> calculator,
            string valueFunction = null
            )
        {
            var name = LambdaHelpers.ParsePropertyLambda(column).Name;

            _calculators.Add(name, calculator);
            _valueFunctions.Add(name, valueFunction);
            return(this);
        }
Example #14
0
        protected override IQueryable <TSourceData> DefaultFilter(IQueryable <TSourceData> source, IEnumerable <TVal> key)
        {
            var anyNulls = key.Any(c => c == null);

            var expr = ReflectionCache.CallContainsMethod(key.ToArray(), _sourceExpression);

            if (anyNulls)
            {
                var nullcmp = LambdaHelpers.ConstantBinaryLambdaExpression(ExpressionType.Equal, _sourceExpression, null);
                expr = LambdaHelpers.BinaryLambdaExpression(ExpressionType.Or, expr, nullcmp);
            }
            return(ReflectionCache.CallWhere(source, expr));
        }
Example #15
0
        /// <summary>
        /// Retrieves column configurator
        /// </summary>
        /// <typeparam name="TColType">Column type</typeparam>
        /// <param name="column">Column</param>
        /// <returns>Corresponding column configurator</returns>
        public ColumnUsage <TSourceData, TTableData, TColType> Column <TColType>(Expression <Func <TTableData, TColType> > column)
        {
            var targetProperty = LambdaHelpers.ParsePropertyLambda(column);

            targetProperty = _tableColumnsDictionary[targetProperty.Name];
            if (_configurators.ContainsKey(targetProperty))
            {
                return((ColumnUsage <TSourceData, TTableData, TColType>)_configurators[targetProperty]);
            }
            ColumnUsage <TSourceData, TTableData, TColType> usage = new ColumnUsage <TSourceData, TTableData, TColType>(this, column, GetColumnConfiguration(targetProperty));

            _configurators[targetProperty] = usage;
            return(usage);
        }
Example #16
0
        /// <summary>
        /// Adds client total calculator that produces count of rows
        /// </summary>
        /// <param name="conf">Configuration</param>
        /// <param name="column">Table column to provide total with</param>
        /// <param name="clientDataSet">Client data set to perform calculations on</param>
        /// <param name="template">Tempalte for total cell</param>
        /// <returns></returns>
        public static TotalCalculatorBuilder <TSourceData, TTableData> AddClientCount <TSourceData, TTableData, TTableColumn>(
            this TotalCalculatorBuilder <TSourceData, TTableData> conf,
            Expression <Func <TTableData, TTableColumn> > column,
            ClientDataSet clientDataSet,
            Action <CellTemplateBuilder> template = null
            ) where TTableData : new()
        {
            var name     = LambdaHelpers.ParsePropertyLambda(column).Name;
            var function = string.Format("function(v){{ return v.{0}.length; }}", clientDataSet);

            conf.ClientCalculators.Add(name, function);
            if (template != null)
            {
                conf.AddTemplate(column, template);
            }
            return(conf);
        }
Example #17
0
        /// <summary>
        /// Adds client total calculator that produces maximum of supplied row values
        /// </summary>
        /// <param name="conf">Configuration</param>
        /// <param name="column">Table column to provide total with</param>
        /// <param name="expression">`{@}`-syntax expression minimum of which will be found</param>
        /// <param name="clientDataSet">Client data set to perform calculations on</param>
        /// <param name="template">Tempalte for total cell</param>
        /// <returns></returns>
        public static TotalCalculatorBuilder <TSourceData, TTableData> AddClientMax <TSourceData, TTableData, TTableColumn>(
            this TotalCalculatorBuilder <TSourceData, TTableData> conf,
            Expression <Func <TTableData, TTableColumn> > column,
            string expression,
            ClientDataSet clientDataSet,
            Action <CellTemplateBuilder> template = null
            ) where TTableData : new()
        {
            var name     = LambdaHelpers.ParsePropertyLambda(column).Name;
            var function = CreateExtremumFunction(expression, true, clientDataSet);

            conf.ClientCalculators.Add(name, function);
            if (template != null)
            {
                conf.AddTemplate(column, template);
            }
            return(conf);
        }
Example #18
0
        protected override IQueryable <TSourceData> DefaultFilter(IQueryable <TSourceData> source, RangeTuple <TVal> key)
        {
            if (_sourceExpression == null)
            {
                throw new Exception("Trying to call FilterDelegate with null source expression");
            }

            if (TreatEqualDateAsWholeDay)
            {
                if (typeof(TVal) == typeof(DateTime) || typeof(TVal) == typeof(DateTime?))
                {
                    if (key.HasFrom && key.HasTo)
                    {
                        var from = (DateTime)(object)key.From;
                        var to   = (DateTime)(object)key.To;
                        if (from.Date == to.Date)
                        {
                            key.From = (TVal)(object)new DateTime(from.Year, from.Month, from.Day, 00, 00, 00);
                            key.To   = (TVal)(object)new DateTime(from.Year, from.Month, from.Day, 23, 59, 59);
                        }
                    }
                }
            }

            if (key.HasTo && key.HasFrom)
            {
                var between = LambdaHelpers.BetweenLambdaExpression(_sourceExpression, key.From.ExtractValueFromNullable(), key.To.ExtractValueFromNullable(), _inclusive);
                return(ReflectionCache.CallWhere(source, between));
            }
            if (key.HasTo)
            {
                ExpressionType lt   = _inclusive ? ExpressionType.LessThanOrEqual : ExpressionType.LessThan;
                var            less = LambdaHelpers.ConstantBinaryLambdaExpression(lt, _sourceExpression, key.To.ExtractValueFromNullable());
                return(ReflectionCache.CallWhere(source, less));
            }
            if (key.HasFrom)
            {
                ExpressionType gt      = _inclusive ? ExpressionType.GreaterThanOrEqual : ExpressionType.GreaterThan;
                var            greater = LambdaHelpers.ConstantBinaryLambdaExpression(gt, _sourceExpression, key.From.ExtractValueFromNullable());
                return(ReflectionCache.CallWhere(source, greater));
            }
            return(source);
        }
        /// <summary>
        /// Gets the Linq.Expression that will represent the AdvancedPaging query
        /// </summary>
        /// <param name="model">The AdvancedPageModel</param>
        /// <param name="genericType">The ParameterExpression that represents the Entity</param>
        /// <returns>The Expression for the AdvancedPage</returns>
        public Expression GetAdvancedSearchRestrictions(AdvancedPageModel model, ParameterExpression genericType)
        {
            Expression restrictions = null;

            if (model.AdvancedSearch == null)
            {
                return(restrictions);
            }
            foreach (var adv in model.AdvancedSearch)
            {
                var valueA = (object)(adv.IntValue.HasValue ? adv.IntValue.Value : adv.Value);
                var key    = typeof(TEntity).GetPropertyExpressionFromSubProperty(adv.PropertyName, genericType);

                //if (key.Type == typeof(int))
                //{
                //    key = ((MemberExpression)key).ConvertToType(TypeCode.String);
                //};

                var propertyType = typeof(TEntity).FollowPropertyPath(adv.PropertyName).PropertyType;
                var value        = valueA != null?Expression.Constant(LambdaHelpers.ChangeType(valueA, propertyType)) : null;

                Expression addedExpression = null;
                switch (adv.TypeOfSearch)
                {
                case AdvancedSearchType.IsNull:
                    addedExpression = LambdaHelpers.NullableEqual(key, Expression.Constant(null));
                    break;

                case AdvancedSearchType.IsNotNull:
                    addedExpression = LambdaHelpers.NullableNotEqual(key, Expression.Constant(null));
                    break;

                case AdvancedSearchType.In:
                    addedExpression = LambdaHelpers.InExpression <TEntity>(genericType, adv.PropertyName, adv.ListValue);
                    break;

                case AdvancedSearchType.Equal:
                    addedExpression = LambdaHelpers.NullableEqual(key, value);
                    break;

                case AdvancedSearchType.NotEqual:
                    addedExpression = LambdaHelpers.NullableNotEqual(key, value);
                    break;

                case AdvancedSearchType.LessThan:
                    addedExpression = LambdaHelpers.NullableLessThan(key, value);
                    break;

                case AdvancedSearchType.LessThanEqual:
                    addedExpression = LambdaHelpers.NullableLessThanOrEqualTo(key, value);
                    break;

                case AdvancedSearchType.GreaterThan:
                    addedExpression = LambdaHelpers.NullableGreaterThan(key, value);
                    break;

                case AdvancedSearchType.GreaterThanEqual:
                    addedExpression = LambdaHelpers.NullableGreaterThanOrEqualTo(key, value);
                    break;

                case AdvancedSearchType.Between:
                    var lowerBound = Expression.GreaterThanOrEqual(key, Expression.Constant(Convert.ChangeType(adv.Value, propertyType)));
                    var upperBound = Expression.LessThanOrEqual(key, Expression.Constant(Convert.ChangeType(adv.Value2, propertyType)));
                    addedExpression = Expression.AndAlso(lowerBound, upperBound);

                    break;

                case AdvancedSearchType.Like:
                default:
                    var method    = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                    var someValue = Expression.Constant(valueA, typeof(string));
                    addedExpression = Expression.Call(key, method, someValue);
                    break;
                }

                //add the new expression to the list
                restrictions = restrictions == null
                                            ? addedExpression
                                            : Expression.AndAlso(restrictions, addedExpression);
            }

            return(restrictions);
        }
        /// <summary>
        /// Creates an Linq.Expression for the Searchable properties
        /// </summary>
        /// <param name="searchCriteria">The search string</param>
        /// <param name="genericType">The ParameterExpression that represents the Entity</param>
        /// <returns>Expression</returns>
        public Expression GetSearchRestrictions(object searchCriteria, ParameterExpression genericType)
        {
            Expression restrictions = null;

            if (searchCriteria != null)
            {
                foreach (var sc in typeof(TEntity).GetProperties())
                {
                    if (sc.IsDefined(typeof(SearchAbleAttribute), true))
                    {
                        var searchAtts = (SearchAbleAttribute[])sc.GetCustomAttributes(typeof(SearchAbleAttribute), true);
                        //walk each searchable attribute on the property
                        foreach (var att in searchAtts)
                        {
                            var propertyName = string.IsNullOrEmpty(att.AliasName) ? sc.Name : att.AliasName;
                            var propertyType = typeof(TEntity).FollowPropertyPath(propertyName).PropertyType;

                            //check for special cases where a string cannot be converted to the type specifically
                            if (FieldCanBeSearch(propertyType, searchCriteria))
                            {
                                var        key             = typeof(TEntity).GetPropertyExpressionFromSubProperty(propertyName, genericType);
                                var        value           = Expression.Constant(LambdaHelpers.ChangeType(searchCriteria, propertyType));
                                Expression addedExpression = null;
                                switch (att.SearchType)
                                {
                                case SearchAbleType.Equal:
                                    addedExpression = LambdaHelpers.NullableEqual(key, value);
                                    break;

                                case SearchAbleType.NotEqual:
                                    addedExpression = LambdaHelpers.NullableNotEqual(key, value);
                                    break;

                                case SearchAbleType.GreaterThan:
                                    addedExpression = LambdaHelpers.NullableGreaterThan(key, value);
                                    break;

                                case SearchAbleType.GreaterThanEqual:
                                    addedExpression = LambdaHelpers.NullableGreaterThanOrEqualTo(key, value);
                                    break;

                                case SearchAbleType.LessThan:
                                    addedExpression = LambdaHelpers.NullableLessThan(key, value);
                                    break;

                                case SearchAbleType.LessThanEqual:
                                    addedExpression = LambdaHelpers.NullableLessThanOrEqualTo(key, value);
                                    break;

                                case SearchAbleType.Contains:
                                    var method    = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                                    var someValue = Expression.Constant(searchCriteria, typeof(string));
                                    addedExpression = Expression.Call(key, method, someValue);
                                    break;

                                case SearchAbleType.StartsWith:
                                    var methodsw = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
                                    var swValue  = Expression.Constant(searchCriteria, typeof(string));
                                    addedExpression = Expression.Call(key, methodsw, swValue);
                                    break;

                                case SearchAbleType.EndsWith:
                                    var methodew = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
                                    var ewValue  = Expression.Constant(searchCriteria, typeof(string));
                                    addedExpression = Expression.Call(key, methodew, ewValue);
                                    break;
                                }

                                //add the new expression to the list of restrictions
                                restrictions = restrictions == null
                                                    ? addedExpression
                                                    : Expression.OrElse(restrictions, addedExpression);
                            }
                        }
                    }
                }
            }

            return(restrictions);
        }
Example #21
0
 internal ColumnUsage(Configurator <TSourceData, TTableData> configurator, Expression <Func <TTableData, TTableColumn> > tableColumnExpression, ColumnConfiguration columnConfiguration)
 {
     _columnProperty      = LambdaHelpers.ParsePropertyLambda(tableColumnExpression);
     _configurator        = configurator;
     _columnConfiguration = columnConfiguration;
 }
Example #22
0
        protected override IQueryable <TSourceData> DefaultFilter(IQueryable <TSourceData> source, TFilteringKey key)
        {
            LambdaExpression lambda = LambdaHelpers.ConstantBinaryLambdaExpression(ExpressionType.Equal, _sourceExpression, key.ExtractValueFromNullable());

            return(ReflectionCache.CallWhere(source, lambda));
        }
Example #23
0
        /// <summary>
        /// Places select checkboxes within every row
        /// </summary>
        /// <typeparam name="TSourceData"></typeparam>
        /// <typeparam name="TTableData"></typeparam>
        /// <typeparam name="TTableColumn"></typeparam>
        /// <param name="conf">Table configuration</param>
        /// <param name="column">Column that will be used as ID provider for select checkbox</param>
        /// <param name="selectAllBehavior">Behavior for "Select All" button</param>
        /// <param name="ui">UI configuration</param>
        /// <returns></returns>
        public static Configurator <TSourceData, TTableData> Checkboxify <TSourceData, TTableData, TTableColumn>(
            this Configurator <TSourceData, TTableData> conf,
            Expression <Func <TTableData, TTableColumn> > column,
            SelectAllBehavior selectAllBehavior = SelectAllBehavior.OnlyIfAllDataVisible,
            Action <PluginConfigurationWrapper <CheckboxifyClientConfig> > ui = null
            ) where TTableData : new()
        {
            var targetProp = LambdaHelpers.ParsePropertyLambda(column);
            var colName    = targetProp.Name;
            CheckboxifyClientConfig ccc = new CheckboxifyClientConfig
            {
                SelectionColumnName = colName
            };

            switch (selectAllBehavior)
            {
            case SelectAllBehavior.Disabled:
                ccc.EnableSelectAll = false;
                break;

            case SelectAllBehavior.CurrentPage:
                //ccc.ResetOnReload = true;
                ccc.EnableSelectAll = true;
                break;

            case SelectAllBehavior.OnlyIfAllDataVisible:
                ccc.EnableSelectAll        = true;
                ccc.SelectAllOnlyIfAllData = true;
                break;

            case SelectAllBehavior.AllLocal:
                ccc.EnableSelectAll = true;
                ccc.SelectAllSelectsClientUndisplayedData = true;
                break;

            case SelectAllBehavior.InvolveServer:
                try
                {
                    var p = typeof(TSourceData).GetProperty(colName);
                    if (p.PropertyType != targetProp.PropertyType)
                    {
                        throw new Exception();
                    }
                }
                catch (Exception ex)
                {
                    throw new Exception(
                              String.Format(
                                  "In case of using SelectAllBehavior.InvolveServer, please assure that property {0} exists on both {1} and {2} types and represents same data",
                                  colName, typeof(TSourceData).FullName, typeof(TTableData).FullName));
                }
                ccc.EnableSelectAll = true;
                ccc.SelectAllSelectsServerUndisplayedData = true;
                conf.RegisterCommandHandler <CheckboxifyCommandHandler>("checkboxify_all");

                break;
            }
            conf.TableConfiguration.ReplacePluginConfig(PluginId, ccc);
            conf.TableConfiguration.UpdatePluginConfig(PluginId, ui);
            return(conf);
        }