Skip to content
This repository has been archived by the owner on Feb 13, 2019. It is now read-only.

Multiple UI framework generator (includes Semantic) #571

Merged
merged 8 commits into from
Mar 14, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# generator-aspnet

[![Join the chat at https://gitter.im/jackjwilliams/generator-aspnet-semanticui](https://badges.gitter.im/jackjwilliams/generator-aspnet-semanticui.svg)](https://gitter.im/jackjwilliams/generator-aspnet-semanticui?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not badge for this repo
👎
The OmniSharp has just its own Omnisharp general repo for issues/talks.


[![Build Status](https://travis-ci.org/OmniSharp/generator-aspnet.svg?branch=master)](https://travis-ci.org/OmniSharp/generator-aspnet)
![Version](https://img.shields.io/npm/v/generator-aspnet.svg)
![Downloads per month](https://img.shields.io/npm/dm/generator-aspnet.svg)

Yeoman generator for ASP.NET 5 projects
Yeoman generator for ASP.NET 5 projects with Semantic UI
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this was correct for the experimental branch on this related project, but not here. This is still just Yeoman generator for ASP.NET 5 projects IMHO


[![](https://cloud.githubusercontent.com/assets/14539/10418056/b72ae284-7050-11e5-99db-5a0cda8f0ac1.gif)](https://github.com/OmniSharp/generator-aspnet 'ASP.NET 5 Generator')

Expand Down Expand Up @@ -50,7 +52,7 @@ The [Docker](https://www.docker.com/) support with `Dockerfile` configuration fi

The project type and application name can be specified as optional command line arguments:

yo aspnet [projecttype [applicationname]]
yo aspnet [projecttype [applicationname] [uiframework]]

The valid project types are:

Expand All @@ -63,7 +65,38 @@ The valid project types are:
- `classlib` for Class Library
- `unittest` Unit Test project

> Example: `yo aspnet webbasic "my test app"` will create a "Web Application Basic" project called "my test app"
The valid UI framework types are:

- `bootstrap` for Bootstrap (this is the default and does not have to be specified explicitly)
- `semantic` for Semantic UI

> Example: `yo aspnet webbasic "my semantic app" semantic` will create a "Web Application Basic" project called "my semantic app" using the Semantic UI framework.

> Example: `yo aspnet webbasic "my bootstrap app"` OR `yo aspnet webbasic "my bootstrap app" bootstrap` will create a "Web Application Basic" project called "my bootstrap app" using the Bootstrap framework.

## Additional UI Framework Notes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too long and too detailed IMHO. When people quickly scan readme's on NPM they want to got all information. The short note up to this point should be enough. As there is no release notes on generator-aspnet (yet), I think this long section should be moved/repeated in:

  • dedicated wiki page describing Why's/Hows of Bootstrap/SemanticUI split. How they are differnet, Which comes by default and why, etc.
  • a long PR/Commit desription - that is why PR/commits are extremelly usefull
  • if merged I think you could write a blog post on MSDN describing whys/hows of these changes
    tec.

There was already discussion/topic to review README.md and make it shorter and cleaner.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peterblazejewicz Is there anything I can do here or was this more directed towards @sayedihashimi ? I have no access to create Wiki pages, etc...

If you would like I could amend the PR notes with more details explaining the conversation we had, why the PR was requested, etc...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could move some part into README.md that is created within the project itself, to limit content added to project README.md.
My reservation is only to the length of added content to the project README.md. It is already lengthy one.

## Semantic UI

### CSS / JS
This generator uses the Semantic UI bower package. By default it includes the entire Semantic UI .css or .min.css
depending on the environment. You can read the Semantic UI documentation [here](http://semantic-ui.com/introduction/build-tools.html) to learn how to use just the components you need.

### Validation
In order for Semantic UI validation to play nicely with the jQuery unobtrusive validation, a helper has been added to
hook into the validation calls and update the fields. This module simply highlights the field, and displays a
validation summary.

For a form to be validated, add the `validate-me` class. To display the error messages use:

`<div asp-validation-summary="ValidationSummary.All" class="ui error message"></div>`

semantic.validation.js is where the magic happens. Upon error (highlight), find the nearest field element and add the error class.
When the error is cleared (unhighlight), remove the error class from the nearest field element.

### MenuLinkTagHelper
To assist with menu highlighting depending on the route, a MenuLinkTagHelper class has been included.


## Related yeoman generators

Expand Down
42 changes: 39 additions & 3 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ var AspnetGenerator = yeoman.generators.Base.extend({
defaults: false,
desc: 'Use the Grunt JavaScript task runner instead of Gulp in web projects.'
});

this.argument('type', { type: String, required: false, desc: 'the project type to create' });
this.argument('applicationName', { type: String, required: false, desc: 'the name of the application' });
this.argument('ui', {type: String, required: false, defaults: 'bootstrap', desc: 'the ui library to use (bootstrap OR semantic)'});
},


Expand Down Expand Up @@ -78,11 +79,32 @@ var AspnetGenerator = yeoman.generators.Base.extend({
value: 'unittest'
}
]
}];
},
{
type: 'list',
name: 'ui',
message: 'Which UI framework would you like to use?',
default: 'bootstrap',
choices: [
{
name: 'Bootstrap (3.3.5)',
value: 'bootstrap'
},
{
name: 'Semantic UI (2.1.8)',
value: 'semantic'
}
],
when: function (answers){
return answers.type === 'web' || answers.type === 'webbasic';
}

}
];

this.prompt(prompts, function (props) {
this.type = props.type;

this.ui = props.ui;
done();
}.bind(this));
}
Expand All @@ -94,6 +116,7 @@ var AspnetGenerator = yeoman.generators.Base.extend({
this.templatedata.guid = guid.v4();
this.templatedata.grunt = this.options.grunt || false;
this.templatedata.coreclr = this.options.coreclr || false;
this.templatedata.ui = this.ui;
},

askForName: function() {
Expand Down Expand Up @@ -210,9 +233,16 @@ var AspnetGenerator = yeoman.generators.Base.extend({
this.fs.copyTpl(this.templatePath('ViewModels/**/*'), this.applicationName + '/ViewModels', this.templatedata);
// Views
this.fs.copyTpl(this.templatePath('Views/**/*'), this.applicationName + '/Views', this.templatedata);

// wwwroot
// wwwroot - the content in the wwwroot does not include any direct references or imports
// So again it is copied 1-to-1 - but tests cover list of all files
this.fs.copy(this.templatePath('wwwroot/**/*'), this.applicationName + '/wwwroot');

// UI Component Overrides
// If the developer has placed anything in overrides/ui-module/project-type/**/* then use it
this.fs.copyTpl(this.templatePath('/../../overrides/' + this.ui + '/' + this.type + '/**/*'), this.applicationName + '/', this.templatedata);

break;
case 'webbasic':
this.sourceRoot(path.join(__dirname, '../templates/projects/' + this.type));
Expand All @@ -236,9 +266,15 @@ var AspnetGenerator = yeoman.generators.Base.extend({
this.fs.copyTpl(this.templatePath('Controllers/HomeController.cs'), this.applicationName + '/Controllers/HomeController.cs', this.templatedata);
// Views
this.fs.copyTpl(this.templatePath('Views/**/*'), this.applicationName + '/Views', this.templatedata);

// wwwroot - the content in the wwwroot does not include any direct references or imports
// So again it is copied 1-to-1 - but tests cover list of all files
this.fs.copy(this.templatePath('wwwroot/**/*'), this.applicationName + '/wwwroot');

// UI Component Overrides
// If the developer has placed anything in overrides/ui-module/project-type/**/* then use it
this.fs.copyTpl(this.templatePath('/../../overrides/' + this.ui + '/' + this.type + '/**/*'), this.applicationName + '/', this.templatedata);

break;
case 'nancy':
this.sourceRoot(path.join(__dirname, '../templates/projects/' + this.type));
Expand Down
63 changes: 63 additions & 0 deletions templates/overrides/semantic/web/TagHelpers/MenuLinkTagHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Html.Abstractions;
using Microsoft.AspNet.Mvc.TagHelpers;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.Razor.TagHelpers;
using Microsoft.Extensions.WebEncoders;

namespace <%= namespace %>.TagHelpers
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here put Why's for this class. It a different one that people can see in aspnet/Teplates. for example:

/// <summary>
/// 
/// </summary>

https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.TagHelpers/LinkTagHelper.cs#L20-L26

[HtmlTargetElement("menulink", Attributes = "controller-name, action-name, menu-text")]
public class MenuLinkTagHelper : TagHelper
{
public string ControllerName { get; set; }
public string ActionName { get; set; }
public string MenuText { get; set; }

[ViewContext]
public ViewContext ViewContext { get; set; }

public IUrlHelper _UrlHelper { get; set; }

public MenuLinkTagHelper(IUrlHelper urlHelper)
{
_UrlHelper = urlHelper;
}

public override void Process(TagHelperContext context, TagHelperOutput output)
{
string menuUrl = _UrlHelper.Action(ActionName, ControllerName);

output.TagName = "";

var a = new TagBuilder("a");

a.MergeAttribute("href", $"{menuUrl}");
a.MergeAttribute("class", "item");

a.InnerHtml.Append(MenuText);

var routeData = ViewContext.RouteData.Values;
var currentController = routeData["controller"];
var currentAction = routeData["action"];

if (String.Equals(ActionName, currentAction as string, StringComparison.OrdinalIgnoreCase)
&& String.Equals(ControllerName, currentController as string, StringComparison.OrdinalIgnoreCase))
{
a.AddCssClass("active");
a.AddCssClass("blue");
}

output.Content.SetContent(a);

}
}
}
10 changes: 10 additions & 0 deletions templates/overrides/semantic/web/Views/Account/ConfirmEmail.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@{
ViewData["Title"] = "Confirm Email";
}

<h2 class="ui header">@ViewData["Title"]</h2>
<div>
<p>
Thank you for confirming your email. Please <a asp-controller="Account" asp-action="Login">Click here to Log in</a>.
</p>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@model ExternalLoginConfirmationViewModel
@{
ViewData["Title"] = "Register";
}

<h2 class="ui header">@ViewData["Title"]</h2>
<h3 class="ui sub header">Associate your @ViewData["LoginProvider"] account</h3>

<form asp-controller="Account" asp-action="ExternalLoginConfirmation" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="ui small form validate-me" role="form">


<p class="content">
You've successfully authenticated with <strong>@ViewData["LoginProvider"]</strong>.
Please enter a user name for this site below and click the Register button to finish
logging in.
</p>
<div class="six wide field">
<div class="ui left icon input">
<i class="user icon"></i>
<input asp-for="Email" placeholder="Email address"/>
<div asp-validation-for="LoginModel.Email"></div>
</div>
</div>
<br/>
<input type="submit" class="ui large blue submit button" value="Register" />
<br />

<div asp-validation-summary="ValidationSummary.All" class="ui error message"></div>

</form>

@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@{
ViewData["Title"] = "Login Failure";
}

<h2 class="ui header">@ViewData["Title"]</h2>
<h3 class="ui sub header">Unsuccessful login with service.</h3>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@model ForgotPasswordViewModel
@{
ViewData["Title"] = "Forgot your password?";
}

<h2 class="ui header">@ViewData["Title"]</h2>
<p>
For more information on how to enable reset password please see this <a href="http://go.microsoft.com/fwlink/?LinkID=532713">article</a>.
</p>

@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@{
ViewData["Title"] = "Forgot Password Confirmation";
}

<h2 class="ui header">@ViewData["Title"]</h2>
<p>
Please check your email to reset your password.
</p>
5 changes: 5 additions & 0 deletions templates/overrides/semantic/web/Views/Account/Info.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@{
ViewBag.Title = "Info";
}
<h2>@ViewBag.Title.</h2>
<h3>@ViewBag.Message</h3>
6 changes: 6 additions & 0 deletions templates/overrides/semantic/web/Views/Account/Lockout.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@{
ViewData["Title"] = "Locked out";
}

<h1 class="ui header red">Locked out</h1>
<h2 class="ui sub header red">This account has been locked out, please try again later.</h2>
82 changes: 82 additions & 0 deletions templates/overrides/semantic/web/Views/Account/Login.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
@using System.Collections.Generic
@using Microsoft.AspNet.Http
@using Microsoft.AspNet.Http.Authentication
@model LoginViewModel
@inject SignInManager<ApplicationUser> SignInManager

@{
ViewData["Title"] = "Log in";
}

<div class="ui two column middle aligned very relaxed stackable grid" style="position:relative">
<div class="column">
<div class="ui form">
<h3 class="ui header centered">Local Account Log In</h3>

<form asp-controller="Account" asp-action="Login" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="ui large form validate-me" role="form" id="loginForm">
<div class="field">
<div class="ui left icon input">
<i class="user icon"></i>
<input asp-for="Email" placeholder="Email address"/>
<div asp-validation-for="LoginModel.Email"></div>
</div>
</div>
<div class="field">
<div class="ui left icon input">
<i class="lock icon"></i>
<input asp-for="Password" placeholder="Password"/>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input asp-for="RememberMe" type="checkbox" tabindex="0" class="hidden"/>
<label>Remember Me</label>
</div>
</div>
<input type="submit" class="ui large blue submit button" value="Login"/>
<br/>
<br/>
Forgot your password? Click <a asp-action="ForgotPassword" asp-controller="Account">here</a>.
<div asp-validation-summary="ValidationSummary.All" class="ui error message"></div>

</form>
</div>

</div>
<div class="ui vertical divider">
OR
</div>
<div class="center aligned column">
<h3 class="ui header centered">Use Another Service to Log In</h3>
@{
var loginProviders = SignInManager.GetExternalAuthenticationSchemes().ToList();
if (loginProviders.Count == 0)
{
<div>
<p>
There are no external authentication services configured. See <a href="http://go.microsoft.com/fwlink/?LinkID=532715">this article</a>
for details on setting up this ASP.NET application to support logging in via external services.
</p>
</div>
}
else
{
<form asp-controller="Account" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
<div>
<p>
@foreach (var provider in loginProviders)
{

<button type="submit" class="ui @provider.AuthenticationScheme.ToLower() button" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account"><i class="@provider.AuthenticationScheme.ToLower() icon"></i> @provider.AuthenticationScheme</button>
}
</p>
</div>
</form>
}
}
</div>
</div>

@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
Loading