Пример #1
0
        public override Task <string> BuildOutputAsync()
        {
            var b = new HtmlCodeBuilder();

            b.Line("@using IntelliTect.Coalesce.Knockout.Helpers");
            b.Line();

            BuildOutput(b);
            return(Task.FromResult(b.ToString()));
        }
Пример #2
0
        public static HtmlString ModalFor(MethodViewModel method, string elementId = null, bool includeWithBinding = true)
        {
            if (elementId == null)
            {
                elementId = $"method-{method.Name}";
            }

            var b = new HtmlCodeBuilder();

            b.Line($"<!-- Modal for method: {method.Name} -->");
            var withBinding = includeWithBinding ? $"with: {method.JsVariable}" : null;

            using (b
                   .TagBlock("div", new { @class = "modal fade", id = elementId, tabindex = -1, role = "dialog", data_bind = withBinding })
                   .TagBlock("div", "modal-dialog")
                   .TagBlock("div", "modal-content")
                   )
            {
                using (b.TagBlock("div", "modal-header"))
                {
                    b.Line("<button type='button' class='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>&times;</span></button>");
                    b.Line($"<h4 class='modal-title'>{method.Name.ToProperCase()}</h4>");
                }

                using (b.TagBlock("div", "modal-body form-horizontal", "with: args"))
                {
                    foreach (ParameterViewModel arg in method.ClientParameters)
                    {
                        using (b.TagBlock("div", "form-group"))
                        {
                            b.Line($"<label class='col-md-4 control-label'>{arg.Name.ToProperCase()}</label>");
                            using (b.TagBlock("div", "col-md-8"))
                            {
                                b.Line($"<input type='text' class='form-control' data-bind='value: {arg.JsVariable}'>");
                            }
                        }
                    }
                }

                using (b.TagBlock("div", "modal-footer"))
                {
                    b.Line("<button type='button' class='btn btn-default' data-dismiss='modal'>Cancel</button>");
                    b.Line(@"<button type='button' class='btn btn-primary btn-ok'");
                    b.Indented(@"data-bind=""click: invokeWithArgs.bind(this, args, function(){jQuery($element).closest('.modal').modal('hide')}, null)"">");
                    b.Indented("OK");
                    b.Line("</button>");
                }
            }

            return(new HtmlString(b.ToString()));
        }
Пример #3
0
        protected void WriteListViewObjectButtons(HtmlCodeBuilder b)
        {
            // Dropdown for invoking instance methods.
            WriteInstanceMethodsDropdownButton(b);

            if (Model.SecurityInfo.IsEditAllowed())
            {
                using (b.TagBlock("a", "btn btn-sm btn-default", "attr: { href: editUrl }"))
                {
                    b.Line("<i class=\"fa fa-pencil\"></i>");
                }
            }

            if (Model.SecurityInfo.IsDeleteAllowed())
            {
                using (b.TagBlock("button", "btn btn-sm btn-danger", "click: deleteItemWithConfirmation"))
                {
                    b.Line("<i class=\"fa fa-remove\"></i>");
                }
            }
        }
Пример #4
0
        protected void WriteInstanceMethodsDropdownButton(HtmlCodeBuilder b)
        {
            if (Model.ClientMethods.Any(f => !f.IsHidden(HiddenAttribute.Areas.List) && !f.IsStatic))
            {
                b.Line("<!-- Action buttons -->");

                using (b.TagBlock("div", new { @class = "btn-group", role = "group" }))
                {
                    b.Line("<button type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">");
                    b.Indented("Actions <span class=\"caret\"></span>");
                    b.Line("</button>");
                    using (b.TagBlock("ul", "dropdown-menu"))
                    {
                        foreach (var method in Model.ClientMethods.Where(f => !f.IsHidden(HiddenAttribute.Areas.List) && !f.IsStatic))
                        {
                            b.Line($"<li>{Display.MethodHelper(method)}</li>");
                        }
                    }
                }
            }
        }
Пример #5
0
        public override void BuildOutput(HtmlCodeBuilder b)
        {
            b.Line("@{ ViewBag.Fluid = true; }");

            b.Line();
            using (b.TagBlock("style"))
            {
                b.Lines(
                    "td div a {",
                    "    display: block;",
                    "}",
                    "th.sortable-header {",
                    "    cursor: pointer;",
                    "}",
                    "th.sortable-header:hover {",
                    "    background-color: #e6e6e6",
                    "}",
                    ".table-view-header {",
                    "    padding: 10px 15px;",
                    "}"
                    );
            }

            using (b.TagBlock("div", $"table-view obj-{Model.ClientTypeName.ToCamelCase()}"))
            {
                WriteAdminTableControls(b, "table", additionalButtons: () =>
                {
                    b.Line("@if (ViewBag.Editable)");
                    b.Line("{");
                    b.Indented($"<a href=\"~/{Model.ControllerName}/Table?@(ViewBag.Query)\" role=\"button\" class=\"btn btn-sm btn-default \"><i class=\"fa fa-lock\"></i> Make Read-only</a>");
                    b.Line("}");
                    if (Model.SecurityInfo.IsEditAllowed())
                    {
                        b.Line("else");
                        b.Line("{");
                        b.Indented($"<a href=\"~/{Model.ControllerName}/[email protected]\" role=\"button\" class=\"btn btn-sm btn-default \"><i class=\"fa fa-pencil\"></i> Make Editable</a>");
                        b.Line("}");
                    }
                });

                b.Line("<hr />");

                using (b
                       .TagBlock("div", "card table-view-body")
                       .TagBlock("div", "card-body")
                       .TagBlock("table", "table @(ViewBag.Editable ? \"editable\" : \"\" )")
                       )
                {
                    using (b.TagBlock("thead").TagBlock("tr"))
                    {
                        // Data column headers
                        foreach (var prop in Model.ClientProperties.Where(f => !f.IsHidden(HiddenAttribute.Areas.List)).OrderBy(f => f.EditorOrder))
                        {
                            if (!prop.Type.IsCollection)
                            {
                                using (b.TagBlock("th", "sortable-header", dataBind: $"click: function(){{orderByToggle('{prop.Name}')}}"))
                                {
                                    b.Line(prop.DisplayName);
                                    b.Line($"<i class=\"pull-right fa\" data-bind=\"css:{{'fa-caret-up': orderBy() == '{prop.Name}', 'fa-caret-down': orderByDescending() == '{prop.Name}'}}\"></i>");
                                }
                            }
                            else
                            {
                                b.Line($"<th>{prop.DisplayName}</th>");
                            }
                        }

                        // Buttons column header
                        b.Line("<th style=\"width: 1%\">");
                        b.Line("</th>");
                    }

                    using (b
                           .TagBlock("tbody", dataBind: "foreach: items")
                           .TagBlock("tr", dataBind: $"css: {{'btn-warning': errorMessage()}}, attr: {{id: {Model.PrimaryKey.Name.ToCamelCase()}}}")
                           )
                    {
                        var properties = Model.ClientProperties
                                         .Where(f => !f.IsHidden(HiddenAttribute.Areas.List))
                                         .OrderBy(f => f.EditorOrder);


                        b.Line("@if (@ViewBag.Editable)");
                        b.Line("{");
                        foreach (var prop in properties)
                        {
                            // Edit mode -- display property inputs
                            b.Indented($"<td class=\"prop-{prop.JsonName}\">{Display.PropertyHelper(prop, !prop.IsReadOnly, null, true)}</td>");
                        }
                        b.Line("}");
                        b.Line("else");
                        b.Line("{");
                        foreach (var prop in properties)
                        {
                            // Read-only mode -- display properties only
                            b.Indented($"<td class=\"prop-{prop.JsonName}\">{Display.PropertyHelper(prop, false, null, true)}</td>");
                        }
                        b.Line("}");

                        // Edit/Delete buttons, and instance method dropdown.
                        using (b.TagBlock("td"))
                        {
                            b.Line("<!-- Editor buttons -->");
                            using (b.TagBlock("div", new { @class = "btn-group pull-right", role = "group", style = "display: inline-flex" }))
                            {
                                WriteListViewObjectButtons(b);
                            }
                            b.Line("<div class=\"form-control-static\" data-bind=\"text: errorMessage\"></div>");
                        }
                    }
                }
            }

            b.Line();
            WriteMethodsCard(b, Model.ClientMethods.Where(f => f.IsStatic));

            b.Line();
            foreach (var method in Model.ClientMethods.Where(f => f.IsStatic && f.ClientParameters.Any()))
            {
                b.Line(IntelliTect.Coalesce.Knockout.Helpers.Knockout.ModalFor(method).ToString());
            }

            WriteListViewScript(b);
        }
Пример #6
0
        public override void BuildOutput(HtmlCodeBuilder b)
        {
            string viewModelsNamespace = "ViewModels";

            if (!string.IsNullOrWhiteSpace(AreaName))
            {
                viewModelsNamespace = AreaName + "." + viewModelsNamespace;
            }
            if (!string.IsNullOrWhiteSpace(ModulePrefix))
            {
                viewModelsNamespace = ModulePrefix + "." + viewModelsNamespace;
            }

            using (b.TagBlock("div", "card"))
            {
                using (b.TagBlock("div", "card-heading"))
                {
                    using (b.TagBlock("div", "btn-group pull-right"))
                    {
                        b.Line("<button onclick=\"window.history.back()\" class=\"btn btn-xs btn-default\"><i class=\"fa fa-arrow-left\"></i> Back</button>");
                        b.Line("<button data-bind=\"click:function() { load(); }\" class=\"btn btn-xs btn-default\"><i class=\"fa fa-refresh\"></i> Refresh</button>");
                    }
                    b.Line($"<h1 class=\"card-title clearfix\" style=\"display:inline-block;\">{Model.DisplayName}</h1>");
                    b.Line("<span class=\"label label-info\" data-bind=\"fadeVisible: isLoading()\">Loading...</span>");
                }

                using (b.TagBlock("div", "card-body").TagBlock("div", "form-horizontal"))
                {
                    using (b.TagBlock("div", "form-group btn-warning", dataBind: "if: errorMessage(), visible: errorMessage()", style: "display: none"))
                    {
                        b.Line("<label class=\"col-md-4 control-label\">Error</label>");
                        b.Line("<div class=\"col-md-8\">");
                        b.Indented("<div class=\"form-control-static\" data-bind=\"text: errorMessage\"></div>");
                        b.Line("</div>");
                    }

                    foreach (var prop in Model.ClientProperties.Where(f => !f.IsHidden(HiddenAttribute.Areas.Edit)).OrderBy(f => f.EditorOrder))
                    {
                        using (b.TagBlock("div", "form-group"))
                        {
                            b.Line($"<label class=\"col-md-4 control-label\">{prop.DisplayName}</label>");
                            if (prop.IsPOCO && prop.PureTypeOnContext)
                            {
                                b.Line(Display.PropertyHelperWithSurroundingDiv(prop, !prop.IsReadOnly, AreaName, 7));
                                b.Line($"<div class=\"col-md-1\" data-bind=\"with: {prop.JsVariableForBinding()}\">");
                                b.Indented("<a data-bind=\"attr: {href: editUrl}\" class=\"btn btn-default pull-right\"><i class=\"fa fa-ellipsis-h \"></i></a>");
                                b.Line("</div>");
                            }
                            else
                            {
                                b.Line(Display.PropertyHelperWithSurroundingDiv(prop, !prop.IsReadOnly, AreaName, 8));
                            }
                        }
                    }
                }
            }

            b.Line();
            WriteMethodsCard(b, Model.ClientMethods.Where(f => !f.IsStatic));

            b.Line();
            foreach (var method in Model.ClientMethods.Where(f => !f.IsStatic && f.ClientParameters.Any()))
            {
                b.Line(IntelliTect.Coalesce.Knockout.Helpers.Knockout.ModalFor(method).ToString());
            }

            b.Line();
            b.Line("@section Scripts");
            b.Line("{");
            b.Line("<script>");
            b.Line($"    var model = new {viewModelsNamespace}.{Model.ViewModelClassName}();");
            b.Line("    model.includes = \"Editor\";");
            b.Line("    model.saveCallbacks.push(function(obj){");
            b.Line("        // If there is a new id, set the one for this page");
            b.Line("        if (!Coalesce.Utilities.GetUrlParameter('id')){");
            b.Line("            if (model.myId) {");
            b.Line("                var newUrl = Coalesce.Utilities.SetUrlParameter(window.location.href, \"id\", model.myId);");
            b.Line("                window.history.replaceState(null, window.document.title, newUrl);");
            b.Line("            }");
            b.Line("        }");
            b.Line("    });");
            b.Line("    @if (ViewBag.Id != null)");
            b.Line("    {");
            b.Line("        @:model.load(\'@ViewBag.Id\');");
            b.Line("    }");
            b.Line("    @foreach (var kvp in ViewBag.ParentIds)");
            b.Line("    {");
            b.Line("        @:model.@(((string)(@kvp.Key)))(@kvp.Value);");
            b.Line("    }");
            b.Line();
            b.Line("    window.onbeforeunload = function(){");
            b.Line("        if (model.isDirty()) model.save();");
            b.Line("    }");
            b.Line("    model.coalesceConfig.autoSaveEnabled(false);");
            b.Line("    model.loadChildren(function() {");
            b.Line("        ko.applyBindings(model);");
            b.Line("        model.coalesceConfig.autoSaveEnabled(true);");
            b.Line("    });");
            b.Line("</script>");
            b.Line("}");
        }
Пример #7
0
        public override void BuildOutput(HtmlCodeBuilder b)
        {
            b.Line("@{ ViewBag.Fluid = true; }");

            b.Line();
            using (b.TagBlock("style"))
            {
                b.Lines(
                    ".card-view-header {",
                    "    padding: 10px 15px;",
                    "}"
                    );
            }

            b.Line();
            using (b.TagBlock("div", $"card-view obj-{Model.ClientTypeName.ToCamelCase()}"))
            {
                WriteAdminTableControls(b, "card");

                b.Line();
                b.EmptyTag("hr");

                b.Line();
                using (b.TagBlock("div",
                                  @class: "flex-card-container card-view-body",
                                  dataBind: "foreach: items, visible: isLoaded",
                                  style: "display: none"))
                {
                    var titleProp = Model.ListTextProperty;

                    // The card for each object.
                    using (b.TagBlock("div", "flex-card"))
                    {
                        if (titleProp != null)
                        {
                            using (b.TagBlock("div", "card-heading").TagBlock("h3", "card-title"))
                            {
                                b.Line($"<span data-bind=\"text: {titleProp.JsVariableForBinding()}\"></span>");
                            }
                        }

                        using (b.TagBlock("div", "card-body flex"))
                        {
                            // List of all data properties on the object
                            using (b.TagBlock("dl"))
                            {
                                var properties = Model.ClientProperties
                                                 .Where(f => !f.IsHidden(HiddenAttribute.Areas.List))
                                                 .OrderBy(f => f.EditorOrder)
                                                 .ToList();
                                foreach (var prop in properties)
                                {
                                    b.Line($"<dt>{prop.DisplayName}</dt>");
                                    b.Line("<dd>");
                                    b.Indented($"{Display.PropertyHelper(prop, false)}");
                                    b.Line("</dd>");
                                }
                            }

                            // Edit/Delete buttons, and instance method dropdown.
                            b.Line();
                            using (b.TagBlock("div", style: "margin-top: auto"))
                            {
                                b.Line("<!-- Editor buttons -->");
                                using (b.TagBlock("div", new { @class = "pull-right", role = "group" }))
                                {
                                    WriteListViewObjectButtons(b);
                                }
                                b.Line("<span class=\"form-control-static\" data-bind=\"text: errorMessage\"></span>");
                            }
                        }
                    }
                }
            }

            b.Line();
            WriteMethodsCard(b, Model.ClientMethods.Where(f => f.IsStatic));

            b.Line();
            foreach (var method in Model.ClientMethods.Where(f => f.IsStatic && f.ClientParameters.Any()))
            {
                b.Line(IntelliTect.Coalesce.Knockout.Helpers.Knockout.ModalFor(method).ToString());
            }

            WriteListViewScript(b);
        }
Пример #8
0
        protected void WriteAdminTableControls(HtmlCodeBuilder b, string classPrefix, Action additionalButtons = null)
        {
            using (b.TagBlock("div", $"{classPrefix}-view-header"))
            {
                using (b
                       .TagBlock("div", "clearfix")
                       .TagBlock("h1", style: "display: inline-block")
                       )
                {
                    b.Line($"{Model.DisplayName} List");
                    b.Line($"<span style=\"font-size: .5em; padding-left: 20px;\"><a href=\"~/{Model.ControllerName}/Docs\">API Docs</a></span>");
                }

                using (b.TagBlock("div", "clearfix"))
                {
                    using (b.TagBlock("div", style: "display: inline-block; font-size: 1.1em; margin-right: 10px;"))
                    {
                        b.Line("<i class=\"fa fa-arrow-circle-left\" data-bind=\"enabled: previousPageEnabled() && !isLoading(), click: previousPage\"></i>");
                        b.Line("Page");
                        b.Line("<input data-bind=\"value: page\" style=\"width: 35px\">");
                        b.Line("of");
                        b.Line("<span data-bind=\"text: pageCount\"></span>");
                        b.Line("<i class=\"fa fa-arrow-circle-right\" data-bind=\"enabled: nextPageEnabled() && !isLoading(), click: nextPage\"></i>");
                    }

                    // Page size dropdown
                    using (b.TagBlock("select", "form-control", dataBind: "value: pageSize", style: "width: 100px; display: inline-block;"))
                    {
                        foreach (var n in new[] { 1, 5, 10, 50, 100, 500, 1000 })
                        {
                            b.Line($"<option value=\"{n}\">{n}</option>");
                        }
                    }

                    b.Line("<input class=\"form-control pull-right\" style=\"width: 250px; margin-left: 20px\" data-bind=\"textInput: search\" placeholder=\"Search\" />");

                    // Create / Refresh / CSV buttons
                    using (b.TagBlock("div", "btn-group pull-right"))
                    {
                        if (Model.SecurityInfo.IsCreateAllowed())
                        {
                            b.Line($"<a href=\"~/{Model.ControllerName}/CreateEdit?@(ViewBag.Query)\" role=\"button\" class=\"btn btn-sm btn-default \"><i class=\"fa fa-plus\"></i> Create</a>");
                        }
                        b.Line("<button data-bind=\"click:load\" class=\"btn btn-sm btn-default \"><i class=\"fa fa-refresh\"></i> Refresh</button>");

                        additionalButtons?.Invoke();

                        b.Line("<a href=\"#\" role=\"button\" class=\"btn btn-sm btn-default \" data-bind=\"attr:{href: downloadAllCsvUrl}\"><i class=\"fa fa-download\"></i> CSV</a>");
                        if (Model.SecurityInfo.IsCreateAllowed() && Model.SecurityInfo.IsEditAllowed())
                        {
                            b.Line("<button role=\"button\" class=\"btn btn-sm btn-default \" data-bind=\"click: csvUploadUi\"><i class=\"fa fa-upload\"></i> CSV</button>");
                        }
                    }
                }
            }
        }
Пример #9
0
        protected void WriteListViewScript(HtmlCodeBuilder b)
        {
            b.Line("@section Scripts");
            b.Line("{");
            using (b.Indented())
            {
                using (b.TagBlock("script"))
                {
                    b.Line($"@if (!ViewBag.Editable)");
                    b.Line($"{{");
                    b.Line($"    @:Coalesce.GlobalConfiguration.viewModel.setupValidationAutomatically(false);");
                    b.Line($"}}");
                    b.Line($"var {Model.ListViewModelObjectName} = new ListViewModels.{Model.ListViewModelClassName}();");

                    b.Line();
                    b.Line($"// Set up parent info based on the URL.");
                    b.Line($"@if (ViewBag.Query != null)");
                    b.Line($"{{");
                    b.Line($"    @:{Model.ListViewModelObjectName}.queryString = \"@(ViewBag.Query)\";");
                    b.Line($"}}");

                    b.Line();
                    b.Line($"// Save and restore values from the URL:");
                    b.Line($"var urlVariables = ['page', 'pageSize', 'search', 'orderBy', 'orderByDescending'];");
                    b.Line($"$.each(urlVariables, function(){{");
                    b.Line($"    var param = Coalesce.Utilities.GetUrlParameter(this);");
                    b.Line($"    if (param) {{{Model.ListViewModelObjectName}[this](param);}}");
                    b.Line($"}})");
                    b.Line($"{Model.ListViewModelObjectName}.isLoading.subscribe(function(){{");
                    b.Line($"    var newUrl = window.location.href;");

                    b.Line();
                    b.Line($"    $.each(urlVariables, function(){{");
                    b.Line($"        var param = {Model.ListViewModelObjectName}[this]();");
                    b.Line($"        newUrl = Coalesce.Utilities.SetUrlParameter(newUrl, this, param);");
                    b.Line($"    }})");
                    b.Line($"    history.replaceState(null, document.title, newUrl);");
                    b.Line($"}});");

                    b.Line();
                    b.Line($"{Model.ListViewModelObjectName}.isSavingAutomatically = false;");
                    b.Line($"ko.applyBindings({Model.ListViewModelObjectName});");
                    b.Line($"{Model.ListViewModelObjectName}.isSavingAutomatically = true;");

                    b.Line();
                    b.Line($"{Model.ListViewModelObjectName}.includes = \"{Model.ListViewModelClassName}Gen\";");
                    b.Line($"{Model.ListViewModelObjectName}.load();");
                }
            }

            b.Line("}");
        }
Пример #10
0
        protected void WriteMethodsCard(HtmlCodeBuilder b, IEnumerable <MethodViewModel> methods)
        {
            if (!methods.Any())
            {
                return;
            }

            using (b.TagBlock("div", "card"))
            {
                using (b.TagBlock("div", "card-heading"))
                {
                    b.Line("<h3 class=\"card-title\">Actions</h3>");
                }

                using (b.TagBlock("div", "card-body").TagBlock("table", "table"))
                {
                    using (b.TagBlock("thead").TagBlock("tr"))
                    {
                        b.Line("<th style=\"width: 20%;\">Action</th>");
                        b.Line("<th style=\"width: 50%;\">Result</th>");
                        b.Line("<th style=\"width: 20%;\">Successful</th>");
                        b.Line("<th style=\"width: 10%;\"></th>");
                    }
                    using (b.TagBlock("tbody"))
                    {
                        foreach (MethodViewModel method in methods)
                        {
                            using (b.TagBlock("tr", dataBind: $"with: {method.JsVariable}"))
                            {
                                using (b.TagBlock("td"))
                                {
                                    string clickBinding = method.ClientParameters.Any()
                                        ? $"click: function(){{ $('#method-{method.Name}').modal() }}"
                                        : $"click: function(){{ invoke() }}";

                                    using (b.TagBlock("button", "btn btn-default btn-xs", dataBind: clickBinding))
                                    {
                                        b.Line(method.DisplayName);
                                    }
                                }

                                using (b.TagBlock("td"))
                                {
                                    if (method.ResultType.IsCollection)
                                    {
                                        b.Line("<ul data-bind=\"foreach: result\">");
                                        b.Indented("<li data-bind=\"text: $data\"></li>");
                                        b.Line("</ul>");
                                    }
                                    else if (method.ResultType.HasClassViewModel)
                                    {
                                        using (b.TagBlock("dl", "dl-horizontal", dataBind: "with: result"))
                                        {
                                            foreach (var prop in method.ResultType.ClassViewModel.ClientProperties.Where(f => !f.IsHidden(HiddenAttribute.Areas.Edit)))
                                            {
                                                b.Line($"<dt>{prop.DisplayName}</dt>");
                                                b.Line($"<dd data-bind=\"text: {prop.JsVariableForBinding()}\"></dd>");
                                            }
                                        }
                                    }
                                    else
                                    {
                                        b.Line("<span data-bind=\"text: result\"></span>");
                                    }
                                }
                                using (b.TagBlock("td"))
                                {
                                    b.Line("<span data-bind=\"text: wasSuccessful\"></span>");
                                    b.Line("<span data-bind=\"text: message\"></span>");
                                }
                                using (b.TagBlock("td"))
                                {
                                    b.Line("<span class=\"label label-info\" data-bind=\"fadeVisible: isLoading\">Loading</span>");
                                }
                            }
                        }
                    }
                }
            }
        }