aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Web/Tango.MachineService
diff options
context:
space:
mode:
authorAvi Levkovich <avi@twine-s.com>2020-05-13 13:27:01 +0300
committerAvi Levkovich <avi@twine-s.com>2020-05-13 13:27:01 +0300
commit15dfc2cdcbc2e518c09c1ee75f32ff149d4a337d (patch)
tree4c0b49773706b85282e6f6b1ec3d2e949d3ca22e /Software/Visual_Studio/Web/Tango.MachineService
parent6a49e917c587dcbbfe8175b8dde73840b7d105fc (diff)
parentcd750d626d3780990797faf09446033bbaa4311c (diff)
downloadTango-15dfc2cdcbc2e518c09c1ee75f32ff149d4a337d.tar.gz
Tango-15dfc2cdcbc2e518c09c1ee75f32ff149d4a337d.zip
commit merge
Diffstat (limited to 'Software/Visual_Studio/Web/Tango.MachineService')
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/App_Start/RouteConfig.cs11
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEAccountController.cs67
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs192
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEDownloadsController.cs60
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs9
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract1.pngbin0 -> 11647 bytes
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract2.pngbin0 -> 153795 bytes
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Images/fse/download.pngbin0 -> 2382 bytes
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Images/fse/machine_full.pngbin0 -> 16884 bytes
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Images/fse/password_reset.pngbin0 -> 8106 bytes
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Images/fse/twine_logo_colored.pngbin0 -> 27285 bytes
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs4
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Styles/FSE/FSELayout.css175
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj17
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Views/FSEAccount/ResetPassword.cshtml26
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Views/FSEAccount/ResetPasswordVM.cs13
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/Index.cshtml39
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/IndexViewModel.cs27
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Views/Shared/_FSELayout.cshtml42
-rw-r--r--Software/Visual_Studio/Web/Tango.MachineService/Web.config3
20 files changed, 658 insertions, 27 deletions
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/App_Start/RouteConfig.cs b/Software/Visual_Studio/Web/Tango.MachineService/App_Start/RouteConfig.cs
index 613e83e72..51f476be5 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/App_Start/RouteConfig.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/App_Start/RouteConfig.cs
@@ -14,6 +14,17 @@ namespace Tango.MachineService
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
+ name: "fse",
+ url: "fse",
+ defaults: new
+ {
+ controller = "FSEDownloads",
+ action = "Index",
+ id = UrlParameter.Optional
+ }
+ );
+
+ routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Downloads", action = "Index", id = UrlParameter.Optional }
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEAccountController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEAccountController.cs
new file mode 100644
index 000000000..b7728af6a
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEAccountController.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using Tango.BL;
+using Tango.MachineService.Filters;
+using Tango.MachineService.Models;
+using Tango.Web.Helpers;
+using System.Data.Entity;
+using Tango.Web.Storage;
+using System.IO;
+using Microsoft.WindowsAzure.Storage.Blob;
+using System.Net.Http;
+using System.Net;
+using System.Net.Http.Headers;
+using System.Net.Mime;
+using Tango.MachineService.Views.FSEAccount;
+
+namespace Tango.MachineService.Controllers
+{
+ public class FSEAccountController : Controller
+ {
+ private static Random rnd = new Random();
+
+ public ActionResult ResetPassword(String id)
+ {
+ ResetPasswordVM vm = new ResetPasswordVM();
+ vm.FullName = "Full Name";
+ vm.Password = "Password";
+
+ var reset = FSEController.PendingPasswordResets.SingleOrDefault(x => x.ID == id);
+
+ if (reset != null)
+ {
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ var user = db.Users.SingleOrDefault(x => x.Guid == reset.UserGuid);
+
+ if (user != null)
+ {
+ String newPass = GenerateRandomPassword();
+ user.Password = Tango.BL.Entities.User.GetPasswordHash(newPass);
+ user.PasswordChangeRequired = true;
+ vm.Password = newPass;
+ vm.FullName = reset.FullName;
+ db.SaveChanges();
+ }
+ }
+ }
+
+ return View(vm);
+ }
+
+ private String GenerateRandomPassword()
+ {
+ String pass = String.Empty;
+
+ for (int i = 0; i < 4; i++)
+ {
+ pass += rnd.Next(0, 9).ToString();
+ }
+
+ return pass;
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs
index bb3ef588f..e471ed20c 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEController.cs
@@ -1,10 +1,13 @@
-using System;
+using SendGrid;
+using SendGrid.Helpers.Mail;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Authentication;
using System.Threading.Tasks;
+using System.Web;
using System.Web.Http;
using Tango.BL;
using Tango.BL.Builders;
@@ -20,22 +23,32 @@ using Tango.Web.Security;
using Tango.Web.SMO;
using Tango.Web.SQLServer;
using Tango.Web.Storage;
+using System.Data.Entity;
+using static Tango.MachineService.Controllers.FSEController;
namespace Tango.MachineService.Controllers
{
- public class FSEController : TangoController
+ public class FSEController : TangoController<TokenObject>
{
public class TokenObject
{
public String UserGuid { get; set; }
}
- /// <summary>
- /// Login to the service.
- /// </summary>
- /// <param name="request">The request.</param>
- /// <returns></returns>
- /// <exception cref="AuthenticationException"></exception>
+ public class PasswordReset
+ {
+ public String ID { get; set; }
+ public String UserGuid { get; set; }
+ public String FullName { get; set; }
+ }
+
+ public static List<PasswordReset> PendingPasswordResets { get; set; }
+
+ static FSEController()
+ {
+ PendingPasswordResets = new List<PasswordReset>();
+ }
+
[HttpPost]
public LoginResponse Login(LoginRequest request)
{
@@ -83,22 +96,6 @@ namespace Tango.MachineService.Controllers
AccessTokenExpiration = accessToken.ExpiresOn.UtcDateTime
};
-
- //Enforce Machine Studio Version ?
- //if (MachineServiceConfig.ENFORCE_MACHINE_STUDIO_VERSION)
- //{
- // using (var db = ObservablesContextHelper.CreateContext())
- // {
- // var latest_version = db.MachineStudioVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
-
- // if (latest_version != null && Version.Parse(latest_version.Version) != client_version)
- // {
- // versionChangeRequired = true;
- // requiredVersion = latest_version.Version;
- // }
- // }
- //}
-
//Return data source
return new LoginResponse()
{
@@ -179,5 +176,152 @@ namespace Tango.MachineService.Controllers
return response;
}
+
+ [HttpPost]
+ [JwtTokenFilter]
+ public CheckForUpdatesResponse CheckForUpdates(CheckForUpdatesRequest request)
+ {
+ CheckForUpdatesResponse response = new CheckForUpdatesResponse();
+
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ var versions = db.FseVersions.ToList();
+
+ FseVersion latestVersion = null;
+
+ latestVersion = versions.OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault();
+
+ Version currentVersion = Version.Parse(request.Version);
+
+ String comments = String.Join(Environment.NewLine, versions.OrderBy(x => Version.Parse(x.Version)).Where(x => Version.Parse(x.Version) > currentVersion).Select(x => x.Comments));
+
+ if (latestVersion != null && Version.Parse(latestVersion.Version) != currentVersion)
+ {
+ var manager = new BlobStorageManager();
+ var container = manager.GetContainer(MachineServiceConfig.FSE_VERSIONS_CONTAINER);
+ //var blob = container.GetBlockBlobReference(latestVersion.BlobName);
+ var installerBlob = container.GetBlockBlobReference(latestVersion.InstallerBlobName);
+
+ //response.BlobAddress = blob.GenerateReadSignature(TimeSpan.FromMinutes(60));
+
+ if (!String.IsNullOrWhiteSpace(MachineServiceConfig.CDN_ENDPOINT))
+ {
+ //response.CdnAddress = MachineServiceConfig.CDN_ENDPOINT + blob.Uri.AbsolutePath;
+ response.InstallerCdnAddress = MachineServiceConfig.CDN_ENDPOINT + installerBlob.Uri.AbsolutePath;
+ }
+
+ response.IsUpdateAvailable = true;
+ response.Version = latestVersion.Version;
+ response.Comments = latestVersion.Comments;
+ }
+ }
+
+ return response;
+ }
+
+ [HttpPost]
+ [JwtTokenFilter]
+ public RefreshTokenResponse RefreshToken(RefreshTokenRequest request)
+ {
+ SQLServerManager sqlServer = new SQLServerManager();
+ var accessToken = sqlServer.GetAccessToken();
+
+ return new RefreshTokenResponse()
+ {
+ AccessToken = accessToken.AccessToken,
+ Expiration = accessToken.ExpiresOn.UtcDateTime,
+ };
+ }
+
+ [HttpPost]
+ [JwtTokenFilter]
+ public UserInvitationEmailResponse SendUserInvitationEmail(UserInvitationEmailRequest request)
+ {
+ User user;
+
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ user = db.Users.Include(x => x.Contact).SingleOrDefault(x => x.Guid == request.UserGuid);
+
+ if (user == null)
+ {
+ throw new InvalidOperationException("User not found.");
+ }
+ }
+
+ var client = new SendGridClient(MachineServiceConfig.SEND_GRID_API_KEY);
+ SendGridMessage msg = new SendGridMessage();
+ msg.SetFrom("info@twine-s.com", "Twine Solutions LTD");
+ msg.AddTo(user.Email);
+ msg.Subject = "Welcome To Tango FSE";
+ msg.SetTemplateId("d-2af42ed0ea3c44b3abaa61016223555a");
+
+ var dynamicTemplateData = new
+ {
+ DownloadUrl = $"{request.MachineServiceAddress}/fse",
+ FullName = user.Contact.FirstName,
+ Password = request.Password,
+ };
+
+ msg.SetTemplateData(dynamicTemplateData);
+
+ var result = client.SendEmailAsync(msg).GetAwaiter().GetResult();
+
+ if (result.StatusCode != HttpStatusCode.Accepted)
+ {
+ throw new HttpException(result.StatusCode.ToString());
+ }
+
+ return new UserInvitationEmailResponse();
+ }
+
+ [HttpPost]
+ public ForgotPasswordResponse SendForgotPasswordEmail(ForgotPasswordRequest request)
+ {
+ User user;
+
+ using (ObservablesContext db = ObservablesContextHelper.CreateContext())
+ {
+ user = db.Users.Include(x => x.Contact).SingleOrDefault(x => x.Email.ToLower() == request.Email.ToLower());
+
+ if (user == null)
+ {
+ throw new InvalidOperationException("User not found.");
+ }
+ }
+
+ String resetId = Guid.NewGuid().ToString();
+
+ var client = new SendGridClient(MachineServiceConfig.SEND_GRID_API_KEY);
+ SendGridMessage msg = new SendGridMessage();
+ msg.SetFrom("info@twine-s.com", "Twine Solutions LTD");
+ msg.AddTo(request.Email);
+ msg.Subject = "Tango FSE Password Reset";
+ msg.SetTemplateId("d-18065487dae4456b8684d4b47a91e4a6");
+
+ var dynamicTemplateData = new
+ {
+ ResetPasswordUrl = $"{request.MachineServiceAddress}/FSEAccount/ResetPassword?id={resetId}",
+ FullName = user.Contact.FirstName,
+ };
+
+ msg.SetTemplateData(dynamicTemplateData);
+
+ var result = client.SendEmailAsync(msg).GetAwaiter().GetResult();
+
+ if (result.StatusCode != HttpStatusCode.Accepted)
+ {
+ throw new HttpException(result.StatusCode.ToString());
+ }
+
+ PendingPasswordResets.Add(new PasswordReset()
+ {
+ ID = resetId,
+ UserGuid = user.Guid,
+ FullName = user.Contact.FirstName,
+ });
+
+ return new ForgotPasswordResponse();
+ }
}
}
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEDownloadsController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEDownloadsController.cs
new file mode 100644
index 000000000..52eb2bbb5
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/FSEDownloadsController.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using Tango.BL;
+using Tango.MachineService.Filters;
+using Tango.MachineService.Models;
+using Tango.Web.Helpers;
+using System.Data.Entity;
+using Tango.Web.Storage;
+using System.IO;
+using Microsoft.WindowsAzure.Storage.Blob;
+using System.Net.Http;
+using System.Net;
+using System.Net.Http.Headers;
+using System.Net.Mime;
+using Tango.MachineService.Views.FSEDownloads;
+
+namespace Tango.MachineService.Controllers
+{
+ public class FSEDownloadsController : Controller
+ {
+ public ActionResult Index()
+ {
+ IndexViewModel model = new IndexViewModel();
+
+ using (var db = ObservablesContextHelper.CreateContext())
+ {
+ var versions = db.FseVersions.ToList().OrderByDescending(x => Version.Parse(x.Version)).Take(6).ToList();
+
+ var manager = new BlobStorageManager();
+ var container = manager.GetContainer(MachineServiceConfig.FSE_VERSIONS_CONTAINER);
+
+ foreach (var item in versions)
+ {
+ var installerBlob = container.GetBlockBlobReference(item.InstallerBlobName);
+
+ model.Downloads.Add(new FSEDownload()
+ {
+ Name = $"Tango FSE v{Version.Parse(item.Version).ToString(3)}",
+ Version = Version.Parse(item.Version).ToString(3),
+ Comments = item.Comments,
+ Date = item.LastUpdated.ToString("dddd, dd MMMM yyyy"),
+ Address = MachineServiceConfig.CDN_ENDPOINT + installerBlob.Uri.AbsolutePath
+ });
+ }
+
+ if (model.Downloads.Count > 0)
+ {
+ var latest = model.Downloads.First();
+ model.Downloads.Remove(latest);
+ model.LatestDownload = latest;
+ }
+ }
+
+ return View(model);
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
index 2049df665..28acb3647 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs
@@ -344,11 +344,14 @@ namespace Tango.MachineService.Controllers
response.IsUpdateAvailable = true;
}
- if (!String.IsNullOrWhiteSpace(request.FirmwareVersion))
+ if (!machine.IsDemo && machine.SetupFirmware)
{
- if (Version.Parse(latest_machine_version.FirmwareVersion) > Version.Parse(request.FirmwareVersion))
+ if (!String.IsNullOrWhiteSpace(request.FirmwareVersion))
{
- response.IsUpdateAvailable = true;
+ if (Version.Parse(latest_machine_version.FirmwareVersion) > Version.Parse(request.FirmwareVersion))
+ {
+ response.IsUpdateAvailable = true;
+ }
}
}
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract1.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract1.png
new file mode 100644
index 000000000..236545ae9
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract1.png
Binary files differ
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract2.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract2.png
new file mode 100644
index 000000000..2742c71e5
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/abstract2.png
Binary files differ
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/download.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/download.png
new file mode 100644
index 000000000..b5d626701
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/download.png
Binary files differ
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/machine_full.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/machine_full.png
new file mode 100644
index 000000000..ec4890e2e
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/machine_full.png
Binary files differ
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/password_reset.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/password_reset.png
new file mode 100644
index 000000000..c1d42d7c4
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/password_reset.png
Binary files differ
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/twine_logo_colored.png b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/twine_logo_colored.png
new file mode 100644
index 000000000..2204585dc
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Images/fse/twine_logo_colored.png
Binary files differ
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs b/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs
index 431d64200..bdddbab8f 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs
+++ b/Software/Visual_Studio/Web/Tango.MachineService/MachineServiceConfig.cs
@@ -11,6 +11,7 @@ namespace Tango.MachineService
{
public static String TANGO_VERSIONS_CONTAINER => ConfigurationManager.AppSettings[nameof(TANGO_VERSIONS_CONTAINER)].ToString();
public static String MACHINE_STUDIO_VERSIONS_CONTAINER => ConfigurationManager.AppSettings[nameof(MACHINE_STUDIO_VERSIONS_CONTAINER)].ToString();
+ public static String FSE_VERSIONS_CONTAINER => ConfigurationManager.AppSettings[nameof(FSE_VERSIONS_CONTAINER)].ToString();
public static bool ENFORCE_MACHINE_STUDIO_VERSION => bool.Parse(ConfigurationManager.AppSettings[nameof(ENFORCE_MACHINE_STUDIO_VERSION)].ToString());
public static String JWT_TOKEN_SECRET => ConfigurationManager.AppSettings[nameof(JWT_TOKEN_SECRET)].ToString();
public static String REFRESH_TOKENS_TABLE_NAME => ConfigurationManager.AppSettings[nameof(REFRESH_TOKENS_TABLE_NAME)].ToString();
@@ -20,6 +21,9 @@ namespace Tango.MachineService
public static String TFS_COLLECTION_URL => ConfigurationManager.AppSettings[nameof(TFS_COLLECTION_URL)].ToString();
public static String TFS_PERSONAL_TOKEN => ConfigurationManager.AppSettings[nameof(TFS_PERSONAL_TOKEN)].ToString();
+
public static String FSE_TFS_USER_EMAIL => ConfigurationManager.AppSettings[nameof(FSE_TFS_USER_EMAIL)].ToString();
+
+ public static String SEND_GRID_API_KEY => ConfigurationManager.AppSettings[nameof(SEND_GRID_API_KEY)].ToString();
}
} \ No newline at end of file
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Styles/FSE/FSELayout.css b/Software/Visual_Studio/Web/Tango.MachineService/Styles/FSE/FSELayout.css
new file mode 100644
index 000000000..8c268d7c8
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Styles/FSE/FSELayout.css
@@ -0,0 +1,175 @@
+body {
+ margin: 0;
+ padding: 0;
+ overflow-x: hidden;
+ font-family: 'Segoe UI';
+}
+
+.fse_primary_background {
+ background-color: #303030;
+}
+
+.fse_primary_accent_background {
+ background-color: #009FE7;
+}
+
+.fse_border_background {
+ background-color: #404040;
+}
+
+.fse_gray_foreground {
+ color: #808080;
+}
+
+.fse_primary_background_light {
+ background-color: #404040;
+}
+
+.fse_primary_foreground {
+ color: #EEEEEE;
+}
+
+.fse_primary_accent {
+ color: #009FE7;
+}
+
+.fse_header_back {
+ position: fixed;
+ padding: 20px;
+ box-shadow: black 1px 1px 10px 1px;
+ z-index: 100;
+ width: 100%;
+}
+
+.fse_machine_logo {
+ position: absolute;
+ left: 20px;
+ top: 20px;
+ width: 120px;
+ float: left;
+}
+
+.fse_twine_logo {
+ height: 80px;
+ display: block;
+ margin: auto auto;
+}
+
+.fse_container {
+ position: absolute;
+ margin-top: 100px;
+ overflow: hidden;
+ clear: both;
+ width:100%;
+}
+
+.fse_side_abstract {
+ position: fixed;
+ width: 60px;
+ height: 100%;
+ float: left;
+ background-image: url('../../Images/fse/abstract1.png');
+ background-repeat: repeat;
+}
+
+.fse_side_abstract_top {
+ position: absolute;
+ box-shadow: black 0px 3px 10px 2px;
+ width: 100%;
+}
+
+.fse_history_downloads_container {
+ float: left;
+ margin-left: 150px;
+ margin-top: 20px;
+ width: 500px;
+}
+
+.fse_history_download {
+ clear: both;
+ margin-top: 60px;
+}
+
+.fse_download_title {
+ vertical-align: baseline middle;
+}
+
+.fse_download_image {
+ height: 32px;
+}
+
+.fse_download_name {
+ margin-top: 5px;
+ margin-left: 5px;
+ vertical-align: top;
+ display: inline-block;
+}
+
+.fse_download_date {
+ float: right;
+ margin-top: 5px;
+ vertical-align: top;
+ display: inline-block;
+}
+
+.fse_download_separator {
+ clear: both;
+ height: 1px;
+ margin-top: 5px;
+}
+
+.fse_download_commets {
+ font-size: 12px;
+ margin-top: 10px;
+}
+
+.fse_download_link {
+ float: right;
+ text-decoration: none;
+ padding: 3px 15px;
+ border-radius: 2px;
+ font-size: 14px;
+}
+
+.fse_latest_version_container {
+ border-radius: 5px;
+ float: left;
+ margin-top: 100px;
+ margin-left: 200px;
+ width: 400px;
+ text-align: center;
+ box-shadow: black 0px 0px 5px 0px;
+}
+
+.fse_download_image_latest {
+ width: 64px;
+ margin-top: 20px;
+}
+
+.fse_download_title_latest {
+ margin-top: 10px;
+ font-size: 20px;
+ font-weight: 400;
+ text-align: center;
+}
+
+.fse_download_button_latest {
+ display: block;
+ padding: 15px 20px;
+ margin: 30px;
+ margin-top: 90px;
+ font-weight: 700;
+ border-radius: 25px;
+ text-decoration: none;
+ box-shadow: black 0px 0px 5px 0px;
+}
+
+.fse_title {
+ position: absolute;
+ display: inline-block;
+ float: left;
+ margin-left: 140px;
+ margin-top: 20px;
+ font-size: 25px;
+ font-weight: 400;
+}
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj
index ee5f3440e..9b25a25a8 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Tango.MachineService.csproj
@@ -188,6 +188,9 @@
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
+ <Reference Include="SendGrid">
+ <HintPath>..\..\Referenced Assemblies\SendGrid\SendGrid.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
@@ -313,6 +316,8 @@
</Compile>
<Compile Include="App_Start\BundleConfig.cs" />
<Compile Include="App_Start\FilterConfig.cs" />
+ <Compile Include="Controllers\FSEAccountController.cs" />
+ <Compile Include="Controllers\FSEDownloadsController.cs" />
<Compile Include="Controllers\DownloadsController.cs" />
<Compile Include="Controllers\AccountController.cs" />
<Compile Include="Controllers\FSEController.cs" />
@@ -333,6 +338,8 @@
</Compile>
<Compile Include="Models\SessionVariables.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Views\FSEAccount\ResetPasswordVM.cs" />
+ <Compile Include="Views\FSEDownloads\IndexViewModel.cs" />
<None Include="Security\RefreshTokenEncoder.cs" />
<None Include="Security\RefreshTokenEntity.cs" />
<None Include="Security\RefreshTokensManager.cs" />
@@ -340,6 +347,16 @@
<Compile Include="Security\TokenManager.cs" />
<Compile Include="Startup.cs" />
<Compile Include="Views\Downloads\IndexViewModel.cs" />
+ <Content Include="Images\fse\abstract1.png" />
+ <Content Include="Images\fse\abstract2.png" />
+ <Content Include="Images\fse\download.png" />
+ <Content Include="Images\fse\machine_full.png" />
+ <Content Include="Images\fse\password_reset.png" />
+ <Content Include="Images\fse\twine_logo_colored.png" />
+ <Content Include="Styles\FSE\FSELayout.css" />
+ <Content Include="Views\FSEDownloads\Index.cshtml" />
+ <Content Include="Views\Shared\_FSELayout.cshtml" />
+ <Content Include="Views\FSEAccount\ResetPassword.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Global.asax" />
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEAccount/ResetPassword.cshtml b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEAccount/ResetPassword.cshtml
new file mode 100644
index 000000000..f0281d462
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEAccount/ResetPassword.cshtml
@@ -0,0 +1,26 @@
+@model Tango.MachineService.Views.FSEAccount.ResetPasswordVM
+
+@{
+ Layout = "~/Views/Shared/_FSELayout.cshtml";
+}
+
+<style>
+ .center-div {
+ position:relative;
+ clear: both;
+ margin-top: 100px;
+ text-align:center;
+ }
+</style>
+
+<div class="center-div">
+ <img src="~/Images/fse/password_reset.png" />
+ <h2>Hello @Model.FullName,</h2>
+ <br />
+ <h3>Your Tango FSE password was successfully reset</h3>
+ <div>Your new temporary password is:</div>
+ <div style="color:darkorange;font-weight:400">@Model.Password</div>
+ <br/>
+ <div style="color:gray">Please login to your account using the Tango FSE software to complete the process</div>
+</div>
+
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEAccount/ResetPasswordVM.cs b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEAccount/ResetPasswordVM.cs
new file mode 100644
index 000000000..c1a1a3106
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEAccount/ResetPasswordVM.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace Tango.MachineService.Views.FSEAccount
+{
+ public class ResetPasswordVM
+ {
+ public String FullName { get; set; }
+ public String Password { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/Index.cshtml b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/Index.cshtml
new file mode 100644
index 000000000..7353ab76e
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/Index.cshtml
@@ -0,0 +1,39 @@
+@model Tango.MachineService.Views.FSEDownloads.IndexViewModel
+
+@{
+ Layout = "~/Views/Shared/_FSELayout.cshtml";
+}
+
+
+<div class="fse_history_downloads_container">
+
+ @foreach (var item in Model.Downloads)
+ {
+ <div class="fse_history_download">
+ <div class="fse_download_title">
+ <img class="fse_download_image" src="~/Images/fse/download.png" />
+ <span class="fse_download_name">@item.Name</span>
+ <span class="fse_download_date">@item.Date</span>
+ </div>
+ <div class="fse_download_separator fse_border_background">
+
+ </div>
+ <div class="fse_download_commets fse_gray_foreground">
+ @item.Comments
+ </div>
+
+ <a class="fse_download_link fse_primary_background_light fse_primary_accent" href="@item.Address">
+ Download
+ </a>
+ </div>
+ }
+</div>
+
+<div class="fse_latest_version_container fse_primary_background_light">
+ <img class="fse_download_image_latest" src="~/Images/fse/download.png" />
+ <div class="fse_download_title_latest">Download Latest Version</div>
+ <div class="fse_download_title_latest fse_primary_accent" style="margin-top:5px;">v@(Model.LatestDownload.Version)</div>
+ <div class="fse_download_commets fse_gray_foreground">@Model.LatestDownload.Comments</div>
+ <a class="fse_download_button_latest fse_primary_accent_background fse_primary_foreground" href="@Model.LatestDownload.Address">DOWNLOAD</a>
+</div>
+
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/IndexViewModel.cs b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/IndexViewModel.cs
new file mode 100644
index 000000000..398b5fcc1
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Views/FSEDownloads/IndexViewModel.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace Tango.MachineService.Views.FSEDownloads
+{
+ public class IndexViewModel
+ {
+ public List<FSEDownload> Downloads { get; set; }
+ public FSEDownload LatestDownload { get; set; }
+
+ public IndexViewModel()
+ {
+ Downloads = new List<FSEDownload>();
+ }
+ }
+
+ public class FSEDownload
+ {
+ public String Name { get; set; }
+ public String Version { get; set; }
+ public String Date { get; set; }
+ public String Comments { get; set; }
+ public String Address { get; set; }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Views/Shared/_FSELayout.cshtml b/Software/Visual_Studio/Web/Tango.MachineService/Views/Shared/_FSELayout.cshtml
new file mode 100644
index 000000000..15ca9f651
--- /dev/null
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Views/Shared/_FSELayout.cshtml
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8" />
+ <meta name="viewport" content="width=device-width" />
+ <title>@ViewBag.Title</title>
+ @*@Styles.Render("~/Content/css")*@
+ @*@Scripts.Render("~/bundles/modernizr")*@
+
+ <link rel="stylesheet" href="~/Styles/FSE/FSELayout.css">
+ @RenderSection("styles", required: false)
+</head>
+<body class="fse_primary_background fse_primary_foreground">
+
+ <header class="header"></header>
+
+ <div>
+
+ <div id="fseAbstract" class="fse_side_abstract">
+ <div class="fse_side_abstract_top">
+
+ </div>
+ </div>
+
+ <div class="fse_header_back fse_primary_background_light">
+ <img src="~/Images/fse/machine_full.png" class="fse_machine_logo" />
+ <span class="fse_title">Tango FSE</span>
+ <img src="~/Images/fse/twine_logo_colored.png" class="fse_twine_logo" />
+ </div>
+
+ <div>
+ <div class="fse_container">
+ @RenderBody()
+ </div>
+ </div>
+ </div>
+
+ @Scripts.Render("~/bundles/jquery")
+ @*@Scripts.Render("~/bundles/bootstrap")*@
+ @RenderSection("scripts", required: false)
+</body>
+</html>
diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Web.config b/Software/Visual_Studio/Web/Tango.MachineService/Web.config
index 291145d36..9cfdc9ccd 100644
--- a/Software/Visual_Studio/Web/Tango.MachineService/Web.config
+++ b/Software/Visual_Studio/Web/Tango.MachineService/Web.config
@@ -23,6 +23,7 @@
<add key="APP_SECRET" value="54)019A7wv+#86l*PQcQWYKu%fd4Dv!@G=VhCiDI5rD+H4BTH" />
<add key="TANGO_VERSIONS_CONTAINER" value="tango-versions-dev" />
<add key="MACHINE_STUDIO_VERSIONS_CONTAINER" value="machine-studio-versions-dev" />
+ <add key="FSE_VERSIONS_CONTAINER" value="fse-versions-dev" />
<add key="DEPLOYMENT_SLOT" value="DEV" />
<add key="ENVIRONMENT_GROUP" value="Tango DEV" />
<add key="ENFORCE_MACHINE_STUDIO_VERSION" value="false" />
@@ -35,6 +36,8 @@
<add key="TFS_COLLECTION_URL" value="https://twinetfs.visualstudio.com" />
<add key="TFS_PERSONAL_TOKEN" value="pyulwgs7m3v7pizz3oxusypdkdfw43txggo5mjwu2ouyv2qwprhq" />
<add key="FSE_TFS_USER_EMAIL" value="fse@twine-s.com" />
+
+ <add key="SEND_GRID_API_KEY" value="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" />
</appSettings>
<!--
For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.