diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Activities/FormSubmittedActivity.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Activities/FormSubmittedActivity.cs new file mode 100644 index 000000000..f051ebcbe --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Activities/FormSubmittedActivity.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Orchard.DynamicForms.Elements; +using Orchard.Localization; +using Orchard.Workflows.Models; +using Orchard.Workflows.Services; + +namespace Orchard.DynamicForms.Activities { + public class FormSubmittedActivity : Event { + + public const string EventName = "DynamicFormSubmitted"; + + public Localizer T { get; set; } + + public override bool CanStartWorkflow { + get { return true; } + } + + public override bool CanExecute(WorkflowContext workflowContext, ActivityContext activityContext) { + var state = activityContext.GetState("DynamicForms"); + + // "" means 'any'. + if (String.IsNullOrEmpty(state)) { + return true; + } + + var form = workflowContext.Tokens["DynamicForm"] as Form; + + if (form == null) { + return false; + } + + var formNames = state.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + return formNames.Any(x => x == form.Name); + } + + public override IEnumerable GetPossibleOutcomes(WorkflowContext workflowContext, ActivityContext activityContext) { + return new[] { T("Done") }; + } + + public override IEnumerable Execute(WorkflowContext workflowContext, ActivityContext activityContext) { + yield return T("Done"); + } + + public override string Form { + get { + return "SelectDynamicForms"; + } + } + + public override string Name { + get { return EventName; } + } + + public override LocalizedString Category { + get { return T("Forms"); } + } + + public override LocalizedString Description { + get { return T("A dynamic form is submitted."); } + } + } + +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Activities/SelectDynamicForms.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Activities/SelectDynamicForms.cs new file mode 100644 index 000000000..e7ce09fb8 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Activities/SelectDynamicForms.cs @@ -0,0 +1,37 @@ +using System; +using System.Linq; +using System.Web.Mvc; +using Orchard.ContentManagement; +using Orchard.DisplayManagement; +using Orchard.Forms.Services; +using Orchard.Localization; + +namespace Orchard.DynamicForms.Activities { + public class SelectDynamicForms : IFormProvider { + protected dynamic Shape { get; set; } + public Localizer T { get; set; } + + public SelectDynamicForms(IShapeFactory shapeFactory) { + Shape = shapeFactory; + T = NullLocalizer.Instance; + } + + public void Describe(DescribeContext context) { + context.Form("SelectDynamicForms", factory => { + var shape = (dynamic)factory; + var form = shape.Form( + Id: "AnyOfDynamicForms", + _Parts: Shape.Textbox( + Id: "dynamicforms", + Name: "DynamicForms", + Title: T("Dynamic Forms"), + Description: T("Enter a comma separated list of dynamic form names. Leave empty to handle all forms."), + Classes: new[] { "text", "large" }) + ); + + return form; + }); + + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/AdminMenu.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/AdminMenu.cs new file mode 100644 index 000000000..9b6a0de82 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/AdminMenu.cs @@ -0,0 +1,18 @@ +using Orchard.UI.Navigation; + +namespace Orchard.DynamicForms { + public class AdminMenu : Component, INavigationProvider { + public string MenuName { get { return "admin"; } } + + public void GetNavigation(NavigationBuilder builder) { + builder + .AddImageSet("dynamicforms") + .Add(T("Dynamic Forms"), "4", menu => menu + .Add(T("Manage Forms"), "1.0", + item => item + .Action("Index", "Admin", new { area = "Orchard.DynamicForms" }) + .Permission(Permissions.ManageForms)) + ); + } + } +} diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/BodyPartBindings.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/BodyPartBindings.cs new file mode 100644 index 000000000..c5d0b7d92 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/BodyPartBindings.cs @@ -0,0 +1,12 @@ +using Orchard.Core.Common.Models; +using Orchard.DynamicForms.Services; +using Orchard.DynamicForms.Services.Models; + +namespace Orchard.DynamicForms.Bindings { + public class BodyPartBindings : Component, IBindingProvider { + public void Describe(BindingDescribeContext context) { + context.For() + .Binding("Text", (part, s) => part.Text = s); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/TextFieldBindings.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/TextFieldBindings.cs new file mode 100644 index 000000000..eb81f1dc6 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/TextFieldBindings.cs @@ -0,0 +1,12 @@ +using Orchard.Core.Common.Fields; +using Orchard.DynamicForms.Services; +using Orchard.DynamicForms.Services.Models; + +namespace Orchard.DynamicForms.Bindings { + public class TextFieldBindings : Component, IBindingProvider { + public void Describe(BindingDescribeContext context) { + context.For() + .Binding("Text", (field, s) => field.Value = s); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/TitlePartBindings.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/TitlePartBindings.cs new file mode 100644 index 000000000..b4cadb80f --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/TitlePartBindings.cs @@ -0,0 +1,12 @@ +using Orchard.Core.Title.Models; +using Orchard.DynamicForms.Services; +using Orchard.DynamicForms.Services.Models; + +namespace Orchard.DynamicForms.Bindings { + public class TitlePartBindings : Component, IBindingProvider { + public void Describe(BindingDescribeContext context) { + context.For() + .Binding("Title", (part, s) => part.Title = s); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/UserPartBindings.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/UserPartBindings.cs new file mode 100644 index 000000000..ec0d3e9cb --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Bindings/UserPartBindings.cs @@ -0,0 +1,14 @@ +using Orchard.DynamicForms.Services; +using Orchard.DynamicForms.Services.Models; +using Orchard.Users.Models; + +namespace Orchard.DynamicForms.Bindings { + public class UserPartBindings : Component, IBindingProvider { + public void Describe(BindingDescribeContext context) { + context.For() + .Binding("UserName", (part, s) => part.UserName = s) + .Binding("Email", (part, s) => part.Email = s) + .Binding("Password", (part, s) => part.Password = s); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Controllers/AdminController.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Controllers/AdminController.cs new file mode 100644 index 000000000..e576341f7 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Controllers/AdminController.cs @@ -0,0 +1,21 @@ +using System.Linq; +using System.Web.Mvc; +using Orchard.DynamicForms.Services; +using Orchard.DynamicForms.ViewModels; + +namespace Orchard.DynamicForms.Controllers { + public class AdminController : Controller { + private readonly IFormService _formService; + public AdminController(IFormService formService) { + _formService = formService; + } + + public ActionResult Index() { + var forms = _formService.GetSubmissions().ToArray().GroupBy(x => x.FormName).ToArray(); + var viewModel = new FormsIndexViewModel { + Forms = forms + }; + return View(viewModel); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Controllers/FormController.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Controllers/FormController.cs new file mode 100644 index 000000000..4034f562a --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Controllers/FormController.cs @@ -0,0 +1,54 @@ +using System; +using System.Web.Mvc; +using Orchard.DynamicForms.Helpers; +using Orchard.DynamicForms.Services; +using Orchard.Layouts.Services; +using Orchard.Localization; +using Orchard.Logging; +using Orchard.UI.Notify; +using IController = Orchard.DynamicForms.Services.IController; + +namespace Orchard.DynamicForms.Controllers { + public class FormController : Controller, IController { + private readonly INotifier _notifier; + private readonly ILayoutManager _layoutManager; + private readonly IFormService _formService; + + public FormController( + INotifier notifier, + ILayoutManager layoutManager, + IFormService formService) { + + _notifier = notifier; + _layoutManager = layoutManager; + _formService = formService; + T = NullLocalizer.Instance; + Logger = NullLogger.Instance; + } + + public Localizer T { get; set; } + public ILogger Logger { get; set; } + + public ActionResult Submit(int contentId, string formName) { + var layoutPart = _layoutManager.GetLayout(contentId); + var form = _formService.FindForm(layoutPart, formName); + var urlReferrer = HttpContext.Request.UrlReferrer != null ? HttpContext.Request.UrlReferrer.ToString() : "~/"; + + if (form == null) { + Logger.Warning("The specified form \"{0}\" could not be found.", formName); + _notifier.Warning(T("The specified form \"{0}\" could not be found.")); + return Redirect(urlReferrer); + } + + var values = _formService.SubmitForm(form, ValueProvider, ModelState); + this.TransferFormSubmission(form, values); + + if(Response.IsRequestBeingRedirected) + return new EmptyResult(); + + var redirectUrl = !String.IsNullOrWhiteSpace(form.RedirectUrl) ? form.RedirectUrl : urlReferrer; + return Redirect(redirectUrl); + } + + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Controllers/SubmissionAdminController.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Controllers/SubmissionAdminController.cs new file mode 100644 index 000000000..956d78c35 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Controllers/SubmissionAdminController.cs @@ -0,0 +1,78 @@ +using System.Collections.Generic; +using System.Linq; +using System.Web.Mvc; +using Orchard.DynamicForms.Helpers; +using Orchard.DynamicForms.Services; +using Orchard.DynamicForms.ViewModels; +using Orchard.Localization; +using Orchard.Mvc; +using Orchard.UI.Admin; +using Orchard.UI.Navigation; +using Orchard.UI.Notify; + +namespace Orchard.DynamicForms.Controllers { + [Admin] + public class SubmissionAdminController : Controller { + private readonly IFormService _formService; + private readonly IOrchardServices _services; + + public SubmissionAdminController(IFormService formService, IOrchardServices services) { + _formService = formService; + _services = services; + T = NullLocalizer.Instance; + } + + public Localizer T { get; set; } + + public ActionResult Index(string id, PagerParameters pagerParameters) { + var pager = new Pager(_services.WorkContext.CurrentSite, pagerParameters); + var submissions = _formService.GetSubmissions(id, pager.GetStartIndex(), pager.PageSize); + var pagerShape = _services.New.Pager(pager).TotalItemCount(submissions.TotalItemCount); + var viewModel = new SubmissionsIndexViewModel { + FormName = id, + Submissions = _formService.GenerateDataTable(submissions), + Pager = pagerShape + }; + return View(viewModel); + } + + public ActionResult Details(int id) { + var submission = _formService.GetSubmission(id); + + if (submission == null) + return HttpNotFound(); + + var viewModel = new SubmissionViewModel { + Submission = submission, + NameValues = submission.ToNameValues() + }; + return View(viewModel); + } + + public ActionResult Delete(int id) { + var submission = _formService.GetSubmission(id); + + if (submission == null) + return HttpNotFound(); + + _formService.DeleteSubmission(submission); + _services.Notifier.Information(T("That submission has been deleted.")); + return Redirect(Request.UrlReferrer.ToString()); + } + + [FormValueRequired("submit.BulkEdit")] + [ActionName("Index")] + public ActionResult BulkDelete(IEnumerable submissionIds) { + if (submissionIds == null || !submissionIds.Any()) { + _services.Notifier.Error(T("Please select the submissions to delete.")); + + } + else { + var numDeletedSubmissions = _formService.DeleteSubmissions(submissionIds); + _services.Notifier.Information(T("{0} submissions have been deleted.", numDeletedSubmissions)); + } + + return Redirect(Request.UrlReferrer.ToString()); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/BindingsElementDriver.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/BindingsElementDriver.cs new file mode 100644 index 000000000..8f4fd3553 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/BindingsElementDriver.cs @@ -0,0 +1,45 @@ +using System; +using System.Linq; +using Orchard.ContentManagement.MetaData; +using Orchard.ContentManagement.MetaData.Models; +using Orchard.DynamicForms.Elements; +using Orchard.DynamicForms.Services; +using Orchard.DynamicForms.ViewModels; +using Orchard.Layouts.Framework.Drivers; + +namespace Orchard.DynamicForms.Drivers { + public class BindingsElementDriver : ElementDriver { + private readonly IBindingManager _bindingManager; + private readonly IContentDefinitionManager _contentDefinitionManager; + + public BindingsElementDriver( + IBindingManager bindingManager, + IContentDefinitionManager contentDefinitionManager) { + + _bindingManager = bindingManager; + _contentDefinitionManager = contentDefinitionManager; + } + + protected override EditorResult OnBuildEditor(FormElement element, ElementEditorContext context) { + var contentType = element.FormBindingContentType; + var contentTypeDefinition = !String.IsNullOrWhiteSpace(contentType) ? _contentDefinitionManager.GetTypeDefinition(contentType) : default(ContentTypeDefinition); + + if (contentTypeDefinition == null) + return null; + + var viewModel = new FormBindingSettings { + AvailableBindings = _bindingManager.DescribeBindingsFor(contentTypeDefinition).ToArray() + }; + + if (context.Updater != null) { + context.Updater.TryUpdateModel(viewModel, null, null, new[] {"AvailableBindings"}); + } + + var bindingsEditor = context.ShapeFactory.EditorTemplate(TemplateName: "FormBindings", Model: viewModel); + + bindingsEditor.Metadata.Position = "Bindings:10"; + + return Editor(context, bindingsEditor); + } + } +} \ No newline at end of file diff --git a/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/ButtonDriver.cs b/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/ButtonDriver.cs new file mode 100644 index 000000000..f6c06b287 --- /dev/null +++ b/src/Orchard.Web/Modules/Orchard.DynamicForms/Drivers/ButtonDriver.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using Orchard.DynamicForms.Elements; +using Orchard.Forms.Services; +using Orchard.Layouts.Framework.Drivers; + +namespace Orchard.DynamicForms.Drivers { + public class ButtonDriver : FormsElementDriver