Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
mattbrailsford committed Jun 19, 2018
2 parents afdd0cb + ea68992 commit 1f881af
Show file tree
Hide file tree
Showing 29 changed files with 302 additions and 81 deletions.
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
os: Visual Studio 2015

# version format
version: 1.0.2.{build}
version: 1.0.3.{build}

# UMBRACO_PACKAGE_PRERELEASE_SUFFIX if a rtm release build this should be blank, otherwise if empty will default to alpha
# example UMBRACO_PACKAGE_PRERELEASE_SUFFIX=beta
Expand Down
1 change: 1 addition & 0 deletions docs/_pages/01-overview-02-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Then, create the associated poco model:

````csharp
[TableName("Person")]
[PrimaryKey("Id")]
public class Person
{
[PrimaryKeyColumn]
Expand Down
6 changes: 3 additions & 3 deletions docs/_pages/02-api-04-collections-00-list-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ listViewConfig.AddBulkAction(new ExportBulkAction());
### Changing the list view layout
{: .mt}

By default the list view will use the built in Umbraco table and grid list view layouts however you can provide your own custom layouts. If you provide a layout, then it will replace the defaults, so if you still want the defaults as options, you'll need to add these again explicitly.
By default the list view will use the built in Umbraco table and grid list view layouts however you can provide your own custom layouts. If you provide a layout, then it will replace the defaults, so if you still want the defaults as options, you'll need to add these again explicitly. To do this, you'll need to call `AddLayout<TListViewLayoutType>` for each one you want to add with a `TListViewLayoutType` parameter of `FluidityTableListViewLayout` or `FluidityGridListViewLayout`.

#### AddLayout<TListViewLayoutType>() *: FluidityListViewConfig<TEntityType>*
{: .signature}
Expand Down Expand Up @@ -131,7 +131,7 @@ listViewConfig.AddField(p => p.FirstName, fieldConfig => {
### Changing the heading of a field
{: .mt}

#### SetHeadng(string heading) *: FluidityListViewFieldConfig<TEntityType, TValueType>*
#### SetHeading(string heading) *: FluidityListViewFieldConfig<TEntityType, TValueType>*
{: .signature}

Sets the heading for the list view field.
Expand All @@ -152,4 +152,4 @@ Sets the format expression for the list view field.
````csharp
// Example
fieldConfig.SetFormat((v, p) => $"{v} years old");
````
````
4 changes: 2 additions & 2 deletions docs/_pages/02-api-04-collections-01-editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Sets the default value via a function that gets evaluated at time of entity crea

````csharp
// Example
fieldConfig.SetDefaultValue(() => DateTime.Now));
fieldConfig.SetDefaultValue(() => DateTime.Now);
````

### Making a field read only
Expand Down Expand Up @@ -207,4 +207,4 @@ Set the value mapper for the current field. See [Value Mapper API documentation]
````csharp
// Example
fieldConfig.SetValueMapper(new MyValueMapper());
````
````
28 changes: 28 additions & 0 deletions docs/_pages/02-api-04-collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,34 @@ Adds the given property to the searchable properties collection. Property must b
collectionConfig.AddSearchableProperty(p => p.FirstName);
````

### Defining encrypted properties
{: .mt}

#### AddEncryptedProperty(Lambda encryptedPropertyExpression) *: FluidityCollectionConfig<TEntityType>*
{: .signature}

Adds the given property to the encrypted properties collection. Property must be of type `String`. When set, the property will be encrypted/decrypted on write/read respectively.

````csharp
// Example
collectionConfig.AddEncryptedProperty(p => p.Email);
````

### Applying a global filter
{: .mt}

Sometimes you may only want to work with a sub-set of data within a given table so this is where the `SetFilter` method comes in handy, allowing you to define a global filter to apply to all queries for the given collection.

#### SetFilter(Lambda whereClauseExression) *: FluidityCollectionConfig<TEntityType>*
{: .signature}

Sets the filter where clause expression. Expression must be a `boolean` expression.

````csharp
// Example
collectionConfig.SetFilter(p => p.Current);
````

### Defining menu items
{: .mt}
See [Menu Items API documentation]({{ site.baseurl }}/api/menu-items/) for more info.
Expand Down
4 changes: 2 additions & 2 deletions docs/_pages/02-api-06-data-views-builders.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class PersonDataViewsBuilder : FluidityDataViewsBuilder<Person>

public override Expression<Func<Person, bool>> GetDataViewWhereClause(string dataViewAlias)
{
// Return a where clause expression for the suplied data view alias
// Return a where clause expression for the supplied data view alias
}
}
````
Expand All @@ -35,4 +35,4 @@ The required methods are:
### Setting the data views builder of a list view
{: .mt}

A data views builder is assigned to a list view as part of the list view configuration. See [List View API Documentation]({{ site.baseurl }}/api/collections/list-view/#defining-data-views) for more info.
A data views builder is assigned to a list view as part of the list view configuration. See [List View API Documentation]({{ site.baseurl }}/api/collections/list-view/#defining-data-views) for more info.
4 changes: 2 additions & 2 deletions docs/_pages/02-api-10-repositories.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class PersonRepository : FluidityRepository<Person, int> {
...
}

protected override PagedResult<Person> GetPagedImpl(int pageNumber, int pageSize, Expression<Func<Person, bool>> whereClause, Expression<Func<Person, object>> orderBy, SortDirection orderDirection);
protected override PagedResult<Person> GetPagedImpl(int pageNumber, int pageSize, Expression<Func<Person, bool>> whereClause, Expression<Func<Person, object>> orderBy, SortDirection orderDirection) {
...
}

Expand Down Expand Up @@ -55,7 +55,7 @@ A repository is assigned to a collection as part of the collection configuration
### Accessing a repository in code
{: .mt}

If you have created your own repository implementation, then accessing the repository can be as simple as instanttiating a new instance of the repository class, however if you are using the built in repository, unfortunately a new instance can't be created in this way.
If you have created your own repository implementation, then accessing the repository can be as simple as instantiating a new instance of the repository class, however if you are using the built in repository, unfortunately a new instance can't be created in this way.

To help with accessing a repository (default or custom) Fluidity has a couple of factory methods to create the repository instances for you.

Expand Down
16 changes: 8 additions & 8 deletions docs/_pages/02-api-11-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ Fluidity fires a number of standard .NET events during regular operation to allo

### Repository events

#### Saving(object sender, SavingEntityEventArgs args)
#### SavingEntity(object sender, SavingEntityEventArgs args)
{: .signature}

Raised when the repository `Save` method is called and before the entity has been saved. The `args` param contains an `Entity` property with `Before` and `After` inner properties providing access to a copy of the currently persisted entity (or null if a new entity) and the updated entity about to be saved. Changes can be made to the `After` entity and they will be persisted as part of the save opperation. If the `Cancel` property of `args` is set to `true` then the save operation will be canceled and no changes will be saved.

````csharp
// Example
Fluidity.Saving += (sender, args) => {
Fluidity.SavingEntity += (sender, args) => {
var person = args.Entity.After as Person;
if (person != null){
...
Expand All @@ -27,14 +27,14 @@ Fluidity.Saving += (sender, args) => {
---


#### Saved(object sender, SavedEntityEventArgs args)
#### SavedEntity(object sender, SavedEntityEventArgs args)
{: .signature}

Raised when the repository `Save` method is called and after the entity has been saved. The `args` param contains an `Entity` property with `Before` and `After` inner properties providing access to a copy of the previously persisted entity (or null if a new entity) and the updated entity just saved.

````csharp
// Example
Fluidity.Saved += (sender, args) => {
Fluidity.SavedEntity += (sender, args) => {
var person = args.Entity.After as Person;
if (person != null){
...
Expand All @@ -45,14 +45,14 @@ Fluidity.Saved += (sender, args) => {
---


#### Deleting(object sender, DeletingEntityEventArgs args)
#### DeletingEntity(object sender, DeletingEntityEventArgs args)
{: .signature}

Raised when the repository `Delete` method is called and before the entity is deleted. The `args` param contains an `Entity` property providing access to a copy of the entity about to be deleted. If the `Cancel` property of `args` is set to `true` then the delete operation will be canceled and entity won't be deleted.

````csharp
// Example
Fluidity.Deleting += (sender, args) => {
Fluidity.DeletingEntity += (sender, args) => {
var person = args.Entity as Person;
if (person != null){
...
Expand All @@ -62,14 +62,14 @@ Fluidity.Deleting += (sender, args) => {

---

#### Deleted(object sender, DeletedEntityEventArgs args)
#### DeletedEntity(object sender, DeletedEntityEventArgs args)
{: .signature}

Raised when the repository `Delete` method is called and after the entity has been deleted. The `args` param contains an `Entity` property providing access to a copy of the entity just deleted.

````csharp
// Example
Fluidity.Deleted += (sender, args) => {
Fluidity.DeletedEntity += (sender, args) => {
var person = args.Entity as Person;
if (person != null){
...
Expand Down
2 changes: 1 addition & 1 deletion docs/_pages/03-property-editors-00-entity-picker.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ foreach(var p in Model.Content.People.Cast<Person>()){
}
````

**Note:** Due to the fact that the property editor can link to any entity type, the returned value type from the value converter will be `IEnumrable<object>` and so will require the entities to be cast to the desired concrete type.
**Note:** Due to the fact that the property editor can link to any entity type, the returned value type from the value converter will be `IEnumerable<object>` and so will require the entities to be cast to the desired concrete type.
11 changes: 9 additions & 2 deletions src/Fluidity/Configuration/FluidityCollectionConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public abstract class FluidityCollectionConfig : FluidityTreeItemConfig
protected string _description;
internal string Description => _description;

protected string _connectionStringg;
internal string ConnectionString => _connectionStringg;
protected string _connectionString;
internal string ConnectionString => _connectionString;

protected Type _entityType;
internal Type EntityType => _entityType;
Expand Down Expand Up @@ -92,6 +92,12 @@ public abstract class FluidityCollectionConfig : FluidityTreeItemConfig
protected List<FluidityPropertyConfig> _searchableProperties;
internal IEnumerable<FluidityPropertyConfig> SearchableProperties => _searchableProperties;

protected List<FluidityPropertyConfig> _encryptedProperties;
internal IEnumerable<FluidityPropertyConfig> EncryptedProperties => _encryptedProperties;

protected LambdaExpression _filterExpression;
internal LambdaExpression FilterExpression => _filterExpression;

/// <summary>
/// Initializes a new instance of the <see cref="FluidityCollectionConfig"/> class.
/// </summary>
Expand All @@ -117,6 +123,7 @@ protected FluidityCollectionConfig(Type entityType, LambdaExpression idPropertyE
_containerMenuItems = new List<MenuItem>();
_entityMenuItems = new List<MenuItem>();
_searchableProperties = new List<FluidityPropertyConfig>();
_encryptedProperties = new List<FluidityPropertyConfig>();
}
}
}
24 changes: 23 additions & 1 deletion src/Fluidity/Configuration/FluidityCollectionConfig`T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public FluidityCollectionConfig<TEntityType> SetNameFormat(Func<TEntityType, str
/// <returns>The collection configuration.</returns>
public FluidityCollectionConfig<TEntityType> SetConnectionString(string connectionStringName)
{
_connectionStringg = connectionStringName;
_connectionString = connectionStringName;
return this;
}

Expand Down Expand Up @@ -183,6 +183,17 @@ public FluidityCollectionConfig<TEntityType> SetSortProperty(Expression<Func<TEn
return this;
}

/// <summary>
/// Sets a filter for the collection.
/// </summary>
/// <param name="filterExpression">The filter where clause expression.</param>
/// <returns>The collection configuration.</returns>
public FluidityCollectionConfig<TEntityType> SetFilter(Expression<Func<TEntityType, bool>> whereClause)
{
_filterExpression = whereClause;
return this;
}

/// <summary>
/// Shows the collection on the section dashboard.
/// </summary>
Expand Down Expand Up @@ -281,6 +292,17 @@ public FluidityCollectionConfig<TEntityType> AddSearchableProperty(Expression<Fu
return this;
}

/// <summary>
/// Adds a property that will be encrypted / decrypted when retrived from the repository.
/// </summary>
/// <param name="encryptedPropertyExpression">The encrypted property expression.</param>
/// <returns>The collection configuration.</returns>
public FluidityCollectionConfig<TEntityType> AddEncryptedProperty(Expression<Func<TEntityType, string>> encryptedPropertyExpression)
{
_encryptedProperties.Add(encryptedPropertyExpression);
return this;
}

/// <summary>
/// Sets which property to use as the Date Created property.
/// </summary>
Expand Down
24 changes: 20 additions & 4 deletions src/Fluidity/Configuration/FluidityEditorFieldConfig`T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,22 +160,38 @@ public FluidityEditorFieldConfig<TEntityType, TValueType> SetDefaultValue(Func<T
/// Makes the the field readonly, disabling editing in the UI.
/// </summary>
/// <returns>The editor field configuration.</returns>
public FluidityEditorFieldConfig<TEntityType, TValueType> MakeReadonly()
public FluidityEditorFieldConfig<TEntityType, TValueType> MakeReadOnly()
{
//TODO: Create defaults for different primitives
return MakeReadonly(type => type?.ToString());
return MakeReadOnly(type => type?.ToString());
}

/// <summary>
/// Makes the the field readonly, disabling editing in the UI.
/// </summary>
/// <param name="format">A format function.</param>
/// <returns>The editor field configuration.</returns>
public FluidityEditorFieldConfig<TEntityType, TValueType> MakeReadonly(Func<TValueType, string> format) {
public FluidityEditorFieldConfig<TEntityType, TValueType> MakeReadOnly(Func<TValueType, string> format) {
_valueMapper = new ReadOnlyValueMapper(value => format((TValueType)value));
_dataTypeId = -92;
_isReadOnly = true;
return this;
}

#region Obsoletes

[Obsolete("Inconsistent casing, use MakeReadOnly instead")]
public FluidityEditorFieldConfig<TEntityType, TValueType> MakeReadonly()
{
return MakeReadOnly();
}

[Obsolete("Inconsistent casing, use MakeReadOnly instead")]
public FluidityEditorFieldConfig<TEntityType, TValueType> MakeReadonly(Func<TValueType, string> format)
{
return MakeReadOnly(format);
}

#endregion
}
}
}
39 changes: 35 additions & 4 deletions src/Fluidity/Data/DefaultFluidityRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,17 @@ public IEnumerable<object> GetAll(bool fireEvents = true)
{
var query = new Sql($"SELECT * FROM [{_collection.EntityType.GetTableName()}]");

bool hasWhere = false;
if (_collection.FilterExpression != null)
{
query.Where(_collection.EntityType, _collection.FilterExpression, SyntaxProvider);
hasWhere = true;
}

if (_collection.DeletedProperty != null)
{
query.Append($"WHERE {_collection.DeletedProperty.GetColumnName()} = 0");
var prefix = !hasWhere ? "WHERE" : "AND";
query.Append($" {prefix} {_collection.DeletedProperty.GetColumnName()} = 0 ");
}

if (_collection.SortProperty != null)
Expand All @@ -71,6 +79,16 @@ public PagedResult<object> GetPaged(int pageNumber, int pageSize, LambdaExpressi
var query = new Sql($"SELECT * FROM [{_collection.EntityType.GetTableName()}]");

// Where
if (_collection.FilterExpression != null && whereClause != null)
{
var body = Expression.AndAlso(whereClause.Body, _collection.FilterExpression.Body);
whereClause = Expression.Lambda(body, whereClause.Parameters[0]);
}
else if (_collection.FilterExpression != null)
{
whereClause = _collection.FilterExpression;
}

if (whereClause != null)
{
query.Where(_collection.EntityType, whereClause, SyntaxProvider);
Expand Down Expand Up @@ -182,14 +200,27 @@ public void Delete(object id, bool fireEvents = true)

public long GetTotalRecordCount(bool fireEvents = true)
{
var sql = $"SELECT COUNT(1) FROM [{_collection.EntityType.GetTableName()}]";
var query = new Sql($"SELECT COUNT(1) FROM [{_collection.EntityType.GetTableName()}]");

bool hasWhere = false;
if (_collection.FilterExpression != null)
{
query.Where(_collection.EntityType, _collection.FilterExpression, SyntaxProvider);
hasWhere = true;
}

if (_collection.DeletedProperty != null)
{
sql += $" WHERE {_collection.DeletedProperty.GetColumnName()} = 0";
var prefix = !hasWhere ? "WHERE" : "AND";
query.Append($" {prefix} {_collection.DeletedProperty.GetColumnName()} = 0 ");
}

return Db.ExecuteScalar<long>(sql);
return Db.ExecuteScalar<long>(query);
}

public void Dispose()
{
//No disposable resources
}
}
}
Loading

0 comments on commit 1f881af

Please sign in to comment.