diff --git a/Raven.Abstractions/Data/IndexStats.cs b/Raven.Abstractions/Data/IndexStats.cs index 1c4229107653..d1f03db5fc9e 100644 --- a/Raven.Abstractions/Data/IndexStats.cs +++ b/Raven.Abstractions/Data/IndexStats.cs @@ -37,15 +37,15 @@ public override string ToString() [Flags] public enum IndexingPriority { - Normal = 0, + Normal = 1, - Disabled = 1, + Disabled = 2, - Idle = 2, + Idle = 4, - Abandoned = 4, + Abandoned = 8, - Forced = 256, + Forced = 512, } public class IndexingPerformanceStats diff --git a/Raven.Client.Embedded/EmbeddedAsyncServerClient.cs b/Raven.Client.Embedded/EmbeddedAsyncServerClient.cs index 286691b1048f..d43c38409172 100644 --- a/Raven.Client.Embedded/EmbeddedAsyncServerClient.cs +++ b/Raven.Client.Embedded/EmbeddedAsyncServerClient.cs @@ -171,6 +171,11 @@ public Task GetIndexesAsync(int start, int pageSize) return new CompletedTask(databaseCommands.GetIndexes(start, pageSize)); } + public Task GetTransformersAsync(int start, int pageSize) + { + return new CompletedTask(databaseCommands.GetTransformers(start, pageSize)); + } + public Task ResetIndexAsync(string name) { databaseCommands.ResetIndex(name); @@ -182,6 +187,11 @@ public Task GetIndexAsync(string name) return new CompletedTask(databaseCommands.GetIndex(name)); } + public Task GetTransformerAsync(string name) + { + return new CompletedTask(databaseCommands.GetTransformer(name)); + } + public Task PutIndexAsync(string name, IndexDefinition indexDef, bool overwrite) { return new CompletedTask(databaseCommands.PutIndex(name, indexDef, overwrite)); @@ -204,6 +214,12 @@ public Task DeleteByIndexAsync(string indexName, IndexQuery queryToDelete, bool return new CompletedTask(); } + public Task DeleteTransformerAsync(string name) + { + databaseCommands.DeleteTransformer(name); + return new CompletedTask(); + } + public Task DeleteDocumentAsync(string id) { databaseCommands.Delete(id, null); diff --git a/Raven.Client.Embedded/EmbeddedDatabaseCommands.cs b/Raven.Client.Embedded/EmbeddedDatabaseCommands.cs index ef7b2a7e0e33..1dcd98283c97 100644 --- a/Raven.Client.Embedded/EmbeddedDatabaseCommands.cs +++ b/Raven.Client.Embedded/EmbeddedDatabaseCommands.cs @@ -307,6 +307,39 @@ public IndexDefinition[] GetIndexes(int start, int pageSize) .ToArray(); } + /// + /// Gets the transformers from the server + /// + /// Paging start + /// Size of the page. + public TransformerDefinition[] GetTransformers(int start, int pageSize) + { + return database.GetTransformers(start, pageSize) + .Select(x =>JsonConvert.DeserializeObject(((RavenJObject) x)["definition"].ToString(),new JsonToJsonConverter())) + .ToArray(); + + } + + /// + /// Gets the transformer definition for the specified name + /// + /// The name. + public TransformerDefinition GetTransformer(string name) + { + CurrentOperationContext.Headers.Value = OperationsHeaders; + return database.GetTransformerDefinition(name); + } + + /// + /// Deletes the transformer. + /// + /// The name. + public void DeleteTransformer(string name) + { + CurrentOperationContext.Headers.Value = OperationsHeaders; + database.DeleteTransfom(name); + } + /// /// Resets the specified index /// diff --git a/Raven.Client.Lightweight/Connection/Async/AsyncServerClient.cs b/Raven.Client.Lightweight/Connection/Async/AsyncServerClient.cs index 1b3e1d3e4260..bfc39b965718 100644 --- a/Raven.Client.Lightweight/Connection/Async/AsyncServerClient.cs +++ b/Raven.Client.Lightweight/Connection/Async/AsyncServerClient.cs @@ -152,6 +152,29 @@ public Task GetIndexesAsync(int start, int pageSize) }); } + /// + /// Gets the transformers from the server asynchronously + /// + public Task GetTransformersAsync(int start, int pageSize) + { + return ExecuteWithReplication("GET", operationUrl => + { + var url2 = (operationUrl + "/transformers?start=" + start + "&pageSize=" + pageSize).NoCache(); + var request = jsonRequestFactory.CreateHttpJsonRequest(new CreateHttpJsonRequestParams(this, url2, "GET", credentials, convention)); + request.AddReplicationStatusHeaders(url, operationUrl, replicationInformer, convention.FailoverBehavior, HandleReplicationStatusChanges); + + return request.ReadResponseJsonAsync() + .ContinueWith(task => + { + var json = ((RavenJArray)task.Result); + //NOTE: To review, I'm not confidence this is the correct way to deserialize the transformer definition + return json + .Select(x => JsonConvert.DeserializeObject(((RavenJObject)x)["definition"].ToString(), new JsonToJsonConverter())) + .ToArray(); + }); + }); + } + /// /// Resets the specified index asynchronously /// @@ -190,6 +213,28 @@ public Task GetIndexAsync(string name) }); } + /// + /// Gets the transformer definition for the specified name asynchronously + /// + /// The name. + public Task GetTransformerAsync(string name) + { + return ExecuteWithReplication("GET", operationUrl => + { + return operationUrl.Transformer(name) + .NoCache() + .ToJsonRequest(this, credentials, convention) + .AddReplicationStatusHeaders(url, operationUrl, replicationInformer, convention.FailoverBehavior, HandleReplicationStatusChanges) + .ReadResponseJsonAsync() + .ContinueWith(task => + { + var json = (RavenJObject)task.Result; + //NOTE: To review, I'm not confidence this is the correct way to deserialize the index definition + return convention.CreateSerializer().Deserialize(new RavenJTokenReader(json)); + }); + }); + } + /// /// Puts the index definition for the specified name asynchronously /// @@ -314,6 +359,14 @@ public Task DeleteByIndexAsync(string indexName, IndexQuery queryToDelete, bool }); } + public Task DeleteTransformerAsync(string name) + { + return ExecuteWithReplication("DELETE", operationUrl => operationUrl.Transformer(name) + .ToJsonRequest(this, credentials, convention, OperationsHeaders, "DELETE") + .AddReplicationStatusHeaders(url, operationUrl, replicationInformer, convention.FailoverBehavior, HandleReplicationStatusChanges) + .ExecuteRequestAsync()); + } + /// /// Deletes the document for the specified id asynchronously /// diff --git a/Raven.Client.Lightweight/Connection/Async/IAsyncDatabaseCommands.cs b/Raven.Client.Lightweight/Connection/Async/IAsyncDatabaseCommands.cs index ecd1d8ba3d54..e7a505cd4518 100644 --- a/Raven.Client.Lightweight/Connection/Async/IAsyncDatabaseCommands.cs +++ b/Raven.Client.Lightweight/Connection/Async/IAsyncDatabaseCommands.cs @@ -87,6 +87,11 @@ public interface IAsyncDatabaseCommands : IDisposable, IHoldProfilingInformation /// Size of the page. Task GetIndexesAsync(int start, int pageSize); + /// + /// Gets the transformers from the server asynchronously + /// + Task GetTransformersAsync(int start, int pageSize); + /// /// Resets the specified index asynchronously /// @@ -99,6 +104,12 @@ public interface IAsyncDatabaseCommands : IDisposable, IHoldProfilingInformation /// The name. Task GetIndexAsync(string name); + /// + /// Gets the transformer definition for the specified name asynchronously + /// + /// The name. + Task GetTransformerAsync(string name); + /// /// Puts the index definition for the specified name asynchronously /// @@ -108,7 +119,7 @@ public interface IAsyncDatabaseCommands : IDisposable, IHoldProfilingInformation Task PutIndexAsync(string name, IndexDefinition indexDef, bool overwrite); /// - /// Puts the transfomer definition for the specified name asynchronously + /// Puts the transformer definition for the specified name asynchronously /// Task PutTransfomerAsync(string name, TransformerDefinition transformerDefinition); @@ -126,6 +137,12 @@ public interface IAsyncDatabaseCommands : IDisposable, IHoldProfilingInformation /// if set to true allow the operation while the index is stale. Task DeleteByIndexAsync(string indexName, IndexQuery queryToDelete, bool allowStale); + /// + /// Deletes the transformer definition for the specified name asynchronously + /// + /// The name. + Task DeleteTransformerAsync(string name); + /// /// Deletes the document for the specified id asynchronously /// diff --git a/Raven.Client.Lightweight/Connection/IDatabaseCommands.cs b/Raven.Client.Lightweight/Connection/IDatabaseCommands.cs index 968199606615..dc19ffa50af9 100644 --- a/Raven.Client.Lightweight/Connection/IDatabaseCommands.cs +++ b/Raven.Client.Lightweight/Connection/IDatabaseCommands.cs @@ -450,7 +450,24 @@ public interface IDatabaseCommands : IHoldProfilingInformation /// ILowLevelBulkInsertOperation GetBulkInsertOperation(BulkInsertOptions options); #endif + /// + /// Gets the transformers from the server + /// + /// Paging start + /// Size of the page. + TransformerDefinition[] GetTransformers(int start, int pageSize); + /// + /// Gets the transformer definition for the specified name + /// + /// The name. + TransformerDefinition GetTransformer(string name); + + /// + /// Deletes the specified transformer + /// + /// The name. + void DeleteTransformer(string name); } } #endif diff --git a/Raven.Client.Lightweight/Connection/RavenUrlExtensions.cs b/Raven.Client.Lightweight/Connection/RavenUrlExtensions.cs index 5ba1a5665105..67cfeafb3079 100644 --- a/Raven.Client.Lightweight/Connection/RavenUrlExtensions.cs +++ b/Raven.Client.Lightweight/Connection/RavenUrlExtensions.cs @@ -26,6 +26,11 @@ public static string IndexDefinition(this string url, string index) return url + "/indexes/" + index + "?definition=yes"; } + public static string Transformer(this string url, string transformer) + { + return url + "/transformers/" + transformer; + } + public static string IndexNames(this string url, int start, int pageSize) { return url + "/indexes/?namesOnly=true&start=" + start + "&pageSize=" + pageSize; diff --git a/Raven.Client.Lightweight/Connection/ServerClient.cs b/Raven.Client.Lightweight/Connection/ServerClient.cs index 25a3de78e997..d307fa5e88f0 100644 --- a/Raven.Client.Lightweight/Connection/ServerClient.cs +++ b/Raven.Client.Lightweight/Connection/ServerClient.cs @@ -702,6 +702,70 @@ public IndexDefinition[] GetIndexes(int start, int pageSize) }); } + public TransformerDefinition[] GetTransformers(int start, int pageSize) + { + return ExecuteWithReplication("GET", operationUrl => + { + var url2 = (operationUrl + "/transformers?start=" + start + "&pageSize=" + pageSize).NoCache(); + var request = jsonRequestFactory.CreateHttpJsonRequest(new CreateHttpJsonRequestParams(this, url2, "GET", credentials, convention)); + request.AddReplicationStatusHeaders(url, operationUrl, replicationInformer, convention.FailoverBehavior, HandleReplicationStatusChanges); + + var result = request.ReadResponseJson(); + var json = ((RavenJArray)result); + //NOTE: To review, I'm not confidence this is the correct way to deserialize the transformer definition + return json + .Select(x => JsonConvert.DeserializeObject(((RavenJObject)x)["definition"].ToString(), new JsonToJsonConverter())) + .ToArray(); + }); + } + + public TransformerDefinition GetTransformer(string name) + { + EnsureIsNotNullOrEmpty(name, "name"); + return ExecuteWithReplication("GET", u => DirectGetTransformer(name, u)); + } + + public void DeleteTransformer(string name) + { + EnsureIsNotNullOrEmpty(name, "name"); + ExecuteWithReplication("DELETE", operationUrl => DirectDeleteTransformer(name, operationUrl)); + } + + private void DirectDeleteTransformer(string name, string operationUrl) + { + var request = jsonRequestFactory.CreateHttpJsonRequest( + new CreateHttpJsonRequestParams(this, operationUrl + "/transformers/" + name, "DELETE", credentials, convention) + .AddOperationHeaders(OperationsHeaders)) + .AddReplicationStatusHeaders(Url, operationUrl, replicationInformer, convention.FailoverBehavior, HandleReplicationStatusChanges); + + request.ExecuteRequest(); + } + + private TransformerDefinition DirectGetTransformer(string transformerName, string operationUrl) + { + var httpJsonRequest = jsonRequestFactory.CreateHttpJsonRequest( + new CreateHttpJsonRequestParams(this, operationUrl + "/transformers/" + transformerName, "GET", credentials, convention) + .AddOperationHeaders(OperationsHeaders)) + .AddReplicationStatusHeaders(Url, operationUrl, replicationInformer, convention.FailoverBehavior, HandleReplicationStatusChanges); + + RavenJToken transformerDef; + try + { + transformerDef = httpJsonRequest.ReadResponseJson(); + } + catch (WebException e) + { + var httpWebResponse = e.Response as HttpWebResponse; + if (httpWebResponse != null && + httpWebResponse.StatusCode == HttpStatusCode.NotFound) + return null; + throw; + } + + var value = transformerDef.Value("Transformer"); + return convention.CreateSerializer().Deserialize(new RavenJTokenReader(value)); + } + /// /// Resets the specified index /// @@ -753,8 +817,6 @@ private IndexDefinition DirectGetIndex(string indexName, string operationUrl) .AddOperationHeaders(OperationsHeaders)) .AddReplicationStatusHeaders(Url, operationUrl, replicationInformer, convention.FailoverBehavior, HandleReplicationStatusChanges); - - RavenJToken indexDef; try { @@ -1066,8 +1128,6 @@ private QueryResult DirectQuery(string index, IndexQuery query, string operation convention.FailoverBehavior, HandleReplicationStatusChanges); - - RavenJObject json; try { diff --git a/Raven.Database/DocumentDatabase.cs b/Raven.Database/DocumentDatabase.cs index e8c331bc6cce..de80e6203812 100644 --- a/Raven.Database/DocumentDatabase.cs +++ b/Raven.Database/DocumentDatabase.cs @@ -2305,5 +2305,10 @@ public JsonDocument GetWithTransformer(string key, string transformer, Transacti }); return result; } + + public TransformerDefinition GetTransformerDefinition(string name) + { + return IndexDefinitionStorage.GetTransformerDefinition(name); + } } } diff --git a/Raven.Database/Raven.Database.csproj b/Raven.Database/Raven.Database.csproj index 50d8862bce48..6d699f7729e5 100644 --- a/Raven.Database/Raven.Database.csproj +++ b/Raven.Database/Raven.Database.csproj @@ -699,7 +699,7 @@ - + diff --git a/Raven.Database/Server/Responders/Transformers.cs b/Raven.Database/Server/Responders/Transformers.cs index e41e2e71ae4f..df8ba25551bd 100644 --- a/Raven.Database/Server/Responders/Transformers.cs +++ b/Raven.Database/Server/Responders/Transformers.cs @@ -14,34 +14,30 @@ public override string UrlPattern public override string[] SupportedVerbs { - get { return new[] { "GET", "PUT" }; } + get { return new[] { "GET", "PUT", "DELETE" }; } } public override void Respond(IHttpContext context) { var match = urlMatcher.Match(context.GetRequestUrl()); - var index = match.Groups[1].Value; + var transformer = match.Groups[1].Value; switch (context.Request.HttpMethod) { case "GET": - if (string.IsNullOrEmpty(index) == false && index != "/") + if (string.IsNullOrEmpty(transformer) == false && transformer != "/") { - context.SetStatusToBadRequest(); - context.WriteJson(new - { - Error = "Cannot GET from a specific transformer but got a request for: " + index.Substring(0) - }); - return; + context.WriteJson(RavenJObject.FromObject(Database.GetTransformerDefinition(transformer))); + break; } var namesOnlyString = context.Request.QueryString["namesOnly"]; bool namesOnly; - RavenJArray indexes; + RavenJArray transformers; if (bool.TryParse(namesOnlyString, out namesOnly) && namesOnly) - indexes = Database.GetTransformerNames(context.GetStart(), context.GetPageSize(Database.Configuration.MaxPageSize)); + transformers = Database.GetTransformerNames(context.GetStart(), context.GetPageSize(Database.Configuration.MaxPageSize)); else - indexes = Database.GetTransformers(context.GetStart(), context.GetPageSize(Database.Configuration.MaxPageSize)); - context.WriteJson(indexes); + transformers = Database.GetTransformers(context.GetStart(), context.GetPageSize(Database.Configuration.MaxPageSize)); + context.WriteJson(transformers); break; case "PUT": var data = context.ReadJsonObject(); @@ -52,7 +48,11 @@ public override void Respond(IHttpContext context) return; } context.SetStatusToCreated("/transformers"); - context.WriteJson(new { Transfomer = Database.PutTransform(index, data) }); + context.WriteJson(new { Transfomer = Database.PutTransform(transformer, data) }); + break; + case "DELETE": + context.SetStatusToDeleted(); + Database.DeleteTransfom(transformer); break; } } diff --git a/Raven.Database/Storage/Esent/StorageActions/EsentUtil.cs b/Raven.Database/Storage/Esent/Debug/EsentUtil.cs similarity index 74% rename from Raven.Database/Storage/Esent/StorageActions/EsentUtil.cs rename to Raven.Database/Storage/Esent/Debug/EsentUtil.cs index ba3285c95630..d8315b5069f7 100644 --- a/Raven.Database/Storage/Esent/StorageActions/EsentUtil.cs +++ b/Raven.Database/Storage/Esent/Debug/EsentUtil.cs @@ -4,40 +4,37 @@ // // ----------------------------------------------------------------------- using System; -using System.Data; using System.IO; using Microsoft.Isam.Esent.Interop; using System.Linq; -namespace Raven.Storage.Esent.StorageActions +namespace Raven.Database.Storage.Esent.Debug { public class EsentUtil { public static void DumpTable(Session session, Table table, Stream stream) { - using (var writer = new StreamWriter(stream)) + var writer = new StreamWriter(stream); + var cols = Api.GetTableColumns(session, table).ToArray(); + foreach (var col in cols) + { + writer.Write(col); + writer.Write(","); + } + writer.WriteLine("#"); + Api.MoveBeforeFirst(session, table); + int count = 0; + while (Api.TryMoveNext(session, table)) { - var cols = Api.GetTableColumns(session, table).ToArray(); foreach (var col in cols) { - writer.Write(col); + var val = GetvalueFromTable(session, table, col) ?? "NULL"; + writer.Write(val); writer.Write(","); } - writer.WriteLine("#"); - Api.MoveBeforeFirst(session, table); - int count = 0; - while (Api.TryMoveNext(session, table)) - { - foreach (var col in cols) - { - var val = GetvalueFromTable(session, table, col) ?? "NULL"; - writer.Write(val); - writer.Write(","); - } - writer.WriteLine(++count); - } - writer.Flush(); + writer.WriteLine(++count); } + writer.Flush(); } private static object GetvalueFromTable(Session session, Table table, ColumnInfo col) diff --git a/Raven.Database/Storage/Esent/StorageActions/Indexing.cs b/Raven.Database/Storage/Esent/StorageActions/Indexing.cs index 146040416b41..443b5838a1d1 100644 --- a/Raven.Database/Storage/Esent/StorageActions/Indexing.cs +++ b/Raven.Database/Storage/Esent/StorageActions/Indexing.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Text; using Microsoft.Isam.Esent.Interop; @@ -17,6 +18,7 @@ using Raven.Database.Extensions; using Raven.Database.Indexing; using Raven.Database.Storage; +using Raven.Database.Storage.Esent.Debug; namespace Raven.Storage.Esent.StorageActions { @@ -241,7 +243,9 @@ public void SetIndexPriority(string index, IndexingPriority priority) Api.JetSetCurrentIndex(session, IndexesStats, "by_key"); Api.MakeKey(session, IndexesStats, index, Encoding.Unicode, MakeKeyGrbit.NewKey); if (Api.TrySeek(session, IndexesStats, SeekGrbit.SeekEQ) == false) - throw new IndexDoesNotExistsException("There is no index named: " + index); + { + throw new IndexDoesNotExistsException("There is no index named: " + index); + } using (var update = new Update(session, IndexesStats, JET_prep.Replace)) { diff --git a/Raven.Database/Storage/Esent/TransactionalStorage.cs b/Raven.Database/Storage/Esent/TransactionalStorage.cs index ed2fa4a56f49..aac5a7634525 100644 --- a/Raven.Database/Storage/Esent/TransactionalStorage.cs +++ b/Raven.Database/Storage/Esent/TransactionalStorage.cs @@ -22,6 +22,7 @@ using Raven.Database.Plugins; using System.Linq; using Raven.Database.Storage; +using Raven.Database.Storage.Esent.Debug; using Raven.Storage.Esent.Backup; using Raven.Storage.Esent.SchemaUpdates; using Raven.Storage.Esent.StorageActions; diff --git a/Raven.Studio/Assets/Images/Images.xaml b/Raven.Studio/Assets/Images/Images.xaml index a90b9b957f47..591bd0a489f9 100644 --- a/Raven.Studio/Assets/Images/Images.xaml +++ b/Raven.Studio/Assets/Images/Images.xaml @@ -7,6 +7,11 @@ + + + + + diff --git a/Raven.Studio/Assets/Images/transformer_add_tiny.png b/Raven.Studio/Assets/Images/transformer_add_tiny.png new file mode 100644 index 000000000000..13e5b12e3913 Binary files /dev/null and b/Raven.Studio/Assets/Images/transformer_add_tiny.png differ diff --git a/Raven.Studio/Assets/Images/transformer_delete_tiny.png b/Raven.Studio/Assets/Images/transformer_delete_tiny.png new file mode 100644 index 000000000000..895608b75a51 Binary files /dev/null and b/Raven.Studio/Assets/Images/transformer_delete_tiny.png differ diff --git a/Raven.Studio/Assets/Images/transformer_small.png b/Raven.Studio/Assets/Images/transformer_small.png new file mode 100644 index 000000000000..76cd271a71d3 Binary files /dev/null and b/Raven.Studio/Assets/Images/transformer_small.png differ diff --git a/Raven.Studio/Assets/Images/transformer_tiny.png b/Raven.Studio/Assets/Images/transformer_tiny.png new file mode 100644 index 000000000000..3523356a20af Binary files /dev/null and b/Raven.Studio/Assets/Images/transformer_tiny.png differ diff --git a/Raven.Studio/Assets/Images/transformers_edit_tiny.png b/Raven.Studio/Assets/Images/transformers_edit_tiny.png new file mode 100644 index 000000000000..805378087400 Binary files /dev/null and b/Raven.Studio/Assets/Images/transformers_edit_tiny.png differ diff --git a/Raven.Studio/Assets/Styles.xaml b/Raven.Studio/Assets/Styles.xaml index 81a45f9ee07a..c6bf028830c9 100644 --- a/Raven.Studio/Assets/Styles.xaml +++ b/Raven.Studio/Assets/Styles.xaml @@ -4330,6 +4330,10 @@ + + diff --git a/Raven.Studio/Features/Transformers/EditTransformerView.xaml b/Raven.Studio/Features/Transformers/EditTransformerView.xaml new file mode 100644 index 000000000000..a2b4decac322 --- /dev/null +++ b/Raven.Studio/Features/Transformers/EditTransformerView.xaml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The Transform function allows you to change the shape of individual result documents before the server returns them. It uses C# LINQ query syntax + + Example: + + + from order + in orders + + let region = Database.Load(result.RegionId) + + select new { + result.Date, + result.Amount, + Region = region.Name, + Manager = region.Manager + } + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Raven.Studio/Features/Transformers/EditTransformerView.xaml.cs b/Raven.Studio/Features/Transformers/EditTransformerView.xaml.cs new file mode 100644 index 000000000000..d3157355c258 --- /dev/null +++ b/Raven.Studio/Features/Transformers/EditTransformerView.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows.Controls; + +namespace Raven.Studio.Features.Transformers +{ + public partial class EditTransformerView : UserControl + { + public EditTransformerView() + { + InitializeComponent(); + } + } +} diff --git a/Raven.Studio/Features/Transformers/TransformersListView.xaml b/Raven.Studio/Features/Transformers/TransformersListView.xaml new file mode 100644 index 000000000000..d7fdbf55672d --- /dev/null +++ b/Raven.Studio/Features/Transformers/TransformersListView.xaml @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Raven.Studio/Features/Transformers/TransformersListView.xaml.cs b/Raven.Studio/Features/Transformers/TransformersListView.xaml.cs new file mode 100644 index 000000000000..298ff69cbfaa --- /dev/null +++ b/Raven.Studio/Features/Transformers/TransformersListView.xaml.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Shapes; + +namespace Raven.Studio.Features.Transformers +{ + public partial class TransformersListView : UserControl + { + public TransformersListView() + { + InitializeComponent(); + } + } +} diff --git a/Raven.Studio/Infrastructure/Converters/PriorityToFontColorConverter.cs b/Raven.Studio/Infrastructure/Converters/PriorityToFontColorConverter.cs index 09f0d8e10d2f..5e64eb99e829 100644 --- a/Raven.Studio/Infrastructure/Converters/PriorityToFontColorConverter.cs +++ b/Raven.Studio/Infrastructure/Converters/PriorityToFontColorConverter.cs @@ -1,6 +1,5 @@ using System; using System.Globalization; -using System.Windows; using System.Windows.Data; using System.Windows.Media; using Raven.Abstractions.Data; @@ -13,10 +12,7 @@ public object Convert(object value, Type targetType, object parameter, CultureIn { var priority = value is IndexingPriority ? (IndexingPriority)value : IndexingPriority.Normal; - if(priority.HasFlag(IndexingPriority.Disabled)) - return new SolidColorBrush(Colors.Gray); - - if (priority.HasFlag(IndexingPriority.Abandoned)) + if (priority.HasFlag(IndexingPriority.Abandoned) || priority.HasFlag(IndexingPriority.Disabled)) return new SolidColorBrush(Colors.LightGray); return new SolidColorBrush(Colors.Black); diff --git a/Raven.Studio/MainPage.xaml b/Raven.Studio/MainPage.xaml index 9c4e0b5430ef..308ad063c7db 100644 --- a/Raven.Studio/MainPage.xaml +++ b/Raven.Studio/MainPage.xaml @@ -178,7 +178,11 @@ Command="{StaticResource NavigateToCommand}" CommandParameter="/indexes" Style="{StaticResource Style_Hyperlink_InDropdown}" /> - + + @@ -381,6 +385,8 @@ MappedUri="/Views/IndexesErrors.xaml" /> + Header); + } + } + + public override void LoadModelParameters(string parameters) + { + var urlParser = new UrlParser(parameters); + if (urlParser.GetQueryParam("mode") == "new") + { + IsNewTransformer = true; + Header = "New Index"; + + UpdateFromTransformer(new TransformerDefinition()); + + return; + } + + var name = urlParser.Path; + if (string.IsNullOrWhiteSpace(name)) + HandleTransformerNotFound(null); + + Header = name; + OriginalName = name; + IsNewTransformer = false; + + DatabaseCommands.GetTransformerAsync(name) + .ContinueOnUIThread(task => + { + if (task.IsFaulted || task.Result == null) + { + HandleTransformerNotFound(name); + return; + } + + UpdateFromTransformer(task.Result); + }).Catch(); + } + + private string OriginalName { get; set; } + + private void UpdateFromTransformer(TransformerDefinition transformerDefinition) + { + Transformer = transformerDefinition; + + OnEverythingChanged(); + } + + private static void HandleTransformerNotFound(string name) + { + if (string.IsNullOrWhiteSpace(name) == false) + { + var notification = new Notification(string.Format("Could not find '{0}' transformer", name), NotificationLevel.Warning); + ApplicationModel.Current.AddNotification(notification); + } + UrlUtil.Navigate("/transformers"); + } + + public string PageTitle + { + get { return "Edit Transformer"; } + } + + private class SaveTransformerCommand : Command + { + private readonly TransformerDefinitionModel transformer; + + public SaveTransformerCommand(TransformerDefinitionModel transformer) + { + this.transformer = transformer; + } + + public override void Execute(object parameter) + { + if (string.IsNullOrWhiteSpace(transformer.Transformer.Name)) + { + ApplicationModel.Current.AddNotification(new Notification("Transformer must have a name!", NotificationLevel.Error)); + return; + } + + if (transformer.IsNewTransformer == false && transformer.OriginalName != transformer.Transformer.Name) + { + if (AskUser.Confirmation("Can not rename and transformer", + "If you wish to save a new transformer with this new name press OK, to cancel the save command press Cancel") == false) + { + ApplicationModel.Current.Notifications.Add(new Notification("Transformer Not Saved")); + return; + } + } + + ApplicationModel.Current.AddNotification(new Notification("saving transformer " + transformer.Transformer.Name)); + DatabaseCommands.PutTransfomerAsync(transformer.Transformer.Name, transformer.Transformer) + .ContinueOnSuccess(() => + { + ApplicationModel.Current.AddNotification( + new Notification("transformer " + transformer.Transformer.Name + " saved")); + PutTransformerNameInUrl(transformer.Transformer.Name); + }) + .Catch(); + } + + private void PutTransformerNameInUrl(string name) + { + if (transformer.IsNewTransformer || transformer.Header != name) + UrlUtil.Navigate("/transformers/" + name, true); + } + } + + private class DeleteTransformerCommand : Command + { + private readonly TransformerDefinitionModel model; + + public DeleteTransformerCommand(TransformerDefinitionModel model) + { + this.model = model; + } + + public override void Execute(object parameter) + { + AskUser.ConfirmationAsync("Confirm Delete", "Really delete '" + model.Transformer.Name + "' transformer?") + .ContinueWhenTrue(DeleteTransformer); + } + + private void DeleteTransformer() + { + DatabaseCommands + .DeleteTransformerAsync(model.Transformer.Name) + .ContinueOnUIThread(t => + { + if (t.IsFaulted) + { + ApplicationModel.Current.AddErrorNotification(t.Exception, "transformer " + model.Transformer.Name + " could not be deleted"); + } + else + { + ApplicationModel.Current.AddInfoNotification("transformer " + model.Transformer.Name + " successfully deleted"); + UrlUtil.Navigate("/transformers"); + } + }); + } + } + } + + +} diff --git a/Raven.Studio/Models/TransformersModel.cs b/Raven.Studio/Models/TransformersModel.cs new file mode 100644 index 000000000000..f52b32a0691b --- /dev/null +++ b/Raven.Studio/Models/TransformersModel.cs @@ -0,0 +1,67 @@ +using System.Collections.ObjectModel; +using System.Windows.Input; +using Raven.Abstractions.Indexing; +using Raven.Studio.Features.Input; +using Raven.Studio.Infrastructure; + +namespace Raven.Studio.Models +{ + public class TransformersModel : PageViewModel + { + public ObservableCollection Transformers { get; set; } + public ICommand DeleteTransformer + { + get { return new DeleteTransformerCommand(this); } + } + public TransformerDefinition ItemSelection { get; set; } + + public TransformersModel() + { + ModelUrl = "/transformers"; + Transformers = new ObservableCollection(); + ApplicationModel.Current.Server.Value.RawUrl = "databases/" + + ApplicationModel.Current.Server.Value.SelectedDatabase.Value.Name + + "/transformers"; + + DatabaseCommands.GetTransformersAsync(0, 256).ContinueOnSuccessInTheUIThread(transformers => + { + Transformers = new ObservableCollection(transformers); + OnPropertyChanged(() => Transformers); + } ); + } + + private class DeleteTransformerCommand : Command + { + private readonly TransformersModel model; + + public DeleteTransformerCommand(TransformersModel model) + { + this.model = model; + } + + public override void Execute(object parameter) + { + AskUser.ConfirmationAsync("Confirm Delete", "Really delete '" + model.ItemSelection.Name + "' transformer?") + .ContinueWhenTrue(DeleteTransformer); + } + + private void DeleteTransformer() + { + DatabaseCommands + .DeleteTransformerAsync(model.ItemSelection.Name) + .ContinueOnUIThread(t => + { + if (t.IsFaulted) + { + ApplicationModel.Current.AddErrorNotification(t.Exception, "transformer " + model.ItemSelection.Name + " could not be deleted"); + } + else + { + ApplicationModel.Current.AddInfoNotification("transformer " + model.ItemSelection.Name + " successfully deleted"); + UrlUtil.Navigate("/transformers"); + } + }); + } + } + } +} diff --git a/Raven.Studio/Raven.Studio.csproj b/Raven.Studio/Raven.Studio.csproj index 5862cb53a9df..12b2c65f5c27 100644 --- a/Raven.Studio/Raven.Studio.csproj +++ b/Raven.Studio/Raven.Studio.csproj @@ -273,6 +273,14 @@ SqlReplicationsSettingsSectionView.xaml + + EditTransformerView.xaml + + + TransformersListView.xaml + + + @@ -597,6 +605,12 @@ ToggleIndexing.xaml + + Transformer.xaml + + + Transformers.xaml + @@ -1040,6 +1054,14 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -1104,6 +1126,14 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + MSBuild:Compile Designer @@ -1352,6 +1382,11 @@ + + + + + diff --git a/Raven.Studio/Views/Transformer.xaml b/Raven.Studio/Views/Transformer.xaml new file mode 100644 index 000000000000..3468b073903d --- /dev/null +++ b/Raven.Studio/Views/Transformer.xaml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/Raven.Studio/Views/Transformer.xaml.cs b/Raven.Studio/Views/Transformer.xaml.cs new file mode 100644 index 000000000000..668b4272dbd5 --- /dev/null +++ b/Raven.Studio/Views/Transformer.xaml.cs @@ -0,0 +1,13 @@ +using System.Windows.Navigation; +using Raven.Studio.Infrastructure; + +namespace Raven.Studio.Views +{ + public partial class Transformer : PageView + { + public Transformer() + { + InitializeComponent(); + } + } +} diff --git a/Raven.Studio/Views/Transformers.xaml b/Raven.Studio/Views/Transformers.xaml new file mode 100644 index 000000000000..87e62799a14b --- /dev/null +++ b/Raven.Studio/Views/Transformers.xaml @@ -0,0 +1,11 @@ + + + + + diff --git a/Raven.Studio/Views/Transformers.xaml.cs b/Raven.Studio/Views/Transformers.xaml.cs new file mode 100644 index 000000000000..c8110637ace8 --- /dev/null +++ b/Raven.Studio/Views/Transformers.xaml.cs @@ -0,0 +1,13 @@ +using System.Windows.Navigation; +using Raven.Studio.Infrastructure; + +namespace Raven.Studio.Views +{ + public partial class Transformers : PageView + { + public Transformers() + { + InitializeComponent(); + } + } +}