diff --git a/.gitignore b/.gitignore index b4765763..686f5c12 100644 --- a/.gitignore +++ b/.gitignore @@ -23,11 +23,13 @@ _ReSharper*/ umbraco.config *.vs10x +*OurUmbraco.Site/web.config *OurUmbraco.Site/App_Data/TEMP*/ *OurUmbraco.Site/App_Data/ClientDependency*/ *OurUmbraco.Site/App_Data/Logs*/ *OurUmbraco.Site/App_Data/Preview*/ *OurUmbraco.Site/install*/ +*OurUmbraco.Site/media/ _BuildOutput/* *.ncrunchsolution @@ -38,3 +40,4 @@ build/*.nupkg /packages/* !packages/repositories.config +OurUmbraco.Site/App_Data/YouTrack diff --git a/OurUmbraco.Site/OurUmbraco.Site.csproj b/OurUmbraco.Site/OurUmbraco.Site.csproj index aa24f03a..5146c59c 100644 --- a/OurUmbraco.Site/OurUmbraco.Site.csproj +++ b/OurUmbraco.Site/OurUmbraco.Site.csproj @@ -133,7 +133,7 @@ ..\dependencies\Our\MarkdownDeep.dll - ..\dependencies\Our\MarkdownSharp.dll + ..\packages\MarkdownSharp.1.13.0.0\lib\35\MarkdownSharp.dll ..\dependencies\Marketplace.dll @@ -157,6 +157,7 @@ ..\dependencies\4.9.1\Microsoft.ApplicationBlocks.Data.dll + ..\packages\microsoft-web-helpers.1.0\lib\Microsoft.Web.Helpers.dll @@ -381,8 +382,10 @@ + + @@ -512,7 +515,10 @@ - + + + + @@ -3236,10 +3242,16 @@ - - + + Designer + + + Designer + - + + Designer + @@ -3285,7 +3297,9 @@ - + + Designer + @@ -3311,6 +3325,9 @@ + + + web.config @@ -3416,11 +3433,11 @@ MD "$(TargetDir)\legacy\" XCOPY "$(ProjectDir)..\dependencies\legacy\*.dll" "$(TargetDir)\legacy\" /S /Y - \ No newline at end of file diff --git a/OurUmbraco.Site/config/UrlRewriting.config b/OurUmbraco.Site/config/UrlRewriting.config index fe52dfc5..ff180807 100644 --- a/OurUmbraco.Site/config/UrlRewriting.config +++ b/OurUmbraco.Site/config/UrlRewriting.config @@ -89,10 +89,5 @@ destinationUrl="/wiki/umbraco-help/translation" ignoreCase="true" /> - diff --git a/OurUmbraco.Site/config/umbracoSettings.config b/OurUmbraco.Site/config/umbracoSettings.config index 2af3432b..e1a02a01 100644 --- a/OurUmbraco.Site/config/umbracoSettings.config +++ b/OurUmbraco.Site/config/umbracoSettings.config @@ -181,7 +181,8 @@ - + + diff --git a/OurUmbraco.Site/macroScripts/Releases-ListDownloads.cshtml b/OurUmbraco.Site/macroScripts/Releases-ListDownloads.cshtml new file mode 100644 index 00000000..2175c60a --- /dev/null +++ b/OurUmbraco.Site/macroScripts/Releases-ListDownloads.cshtml @@ -0,0 +1,16 @@ +@* +LIST CHILDREN BY TYPE +================================= +This snippet shows how simple it is to fetch only children of a certain Document Type using Razor. Instead of +calling .Children, simply call .AliasOfDocumentType (even works in plural for readability)! +For instance .Textpage or .Textpages (you can find the alias of your Document Type by editing it in the +Settings section). + +NOTE: It is safe to remove this comment (anything between @ * * @), the code that generates the list is only the below! +*@ +
    + @foreach (var item in @Model.Downloads.Where("Visible")) + { +
  • @item.Name
  • + } +
\ No newline at end of file diff --git a/OurUmbraco.Site/masterpages/ArchivedRelease.master b/OurUmbraco.Site/masterpages/ArchivedRelease.master new file mode 100644 index 00000000..ce118ee7 --- /dev/null +++ b/OurUmbraco.Site/masterpages/ArchivedRelease.master @@ -0,0 +1,74 @@ +<%@ Master Language="C#" MasterPageFile="~/masterpages/Master.master" AutoEventWireup="true" %> + + + + + + + + + + + + + +
+
+ +
+ +

+ Umbraco v + Status: Archived +

+ +
+

+ 100% Complete + 0% In Progress +

+ +
+
 
+
+
+ + + @if(Model.HasValue("bodyText")) + { +
+

Archived release

+ @Model.BodyText +
+ } +
+ + + @{ + var downloads = Model.ReleaseDownload.Where("Visible"); + var countIsOdd = ((downloads.Count() & 1) != 0) ? true : false; + if(downloads.Any()) + { +

+

Available downloads

+
    + @foreach (var item in downloads) + { + var background = item.IsFirst() ? "/images/releases/download.png" : "/media/2483095/download.png"; + var width = (item.IsLast() && countIsOdd) ? 895 : 380; + var numberOfDownloads = 0; + int.TryParse(item.NumberOfDownloads, out numberOfDownloads); + +
  • +
    +

    @item.Name

    +

    Downloaded @numberOfDownloads times - uploaded @item.UploadDate.ToString("D")

    +
    +
  • + } +
+ } + } +
+
+
\ No newline at end of file diff --git a/OurUmbraco.Site/masterpages/Release.master b/OurUmbraco.Site/masterpages/Release.master index fd0738eb..70a22c0c 100644 --- a/OurUmbraco.Site/masterpages/Release.master +++ b/OurUmbraco.Site/masterpages/Release.master @@ -1,109 +1,159 @@ <%@ Master Language="C#" MasterPageFile="~/masterpages/Master.master" AutoEventWireup="true" %> - + - + - +
- +

Loading release details...

- Umbraco v<%= Request["v"] %> - Status: + Umbraco v + Status: Status: Released

- +

-
 
+
 
 
-

Target release date:

-

Download it now!

-

Summary:

-

+

Target release date:

+ + + @{ + var downloads = Model.ReleaseDownload.Where("Visible"); + var countIsOdd = ((downloads.Count() & 1) != 0) ? true : false; + if(downloads.Any()) + { +

+

Available downloads

+
    + @foreach (var item in downloads) + { + var background = item.IsFirst() ? "/images/releases/download.png" : "/media/2483095/download.png"; + var width = (item.IsLast() && countIsOdd) ? 895 : 380; + var numberOfDownloads = 0; + int.TryParse(item.NumberOfDownloads, out numberOfDownloads); + +
  • +
    +

    @item.Name

    +

    Downloaded @numberOfDownloads times - uploaded @item.UploadDate.ToString("D")

    +
    +
  • + } +
+ } + } +
+ +
+ +

Summary

+

+
+ + + @if(Model.HasValue("bodyText")) { +

Release notes

+ @Model.BodyText + } +
+ + +

Related changes from the issue tracker

- -

Features

No items to display

-
    +

      Breaking Changes

      No items to display

      -
        +

          Issues & Tasks

          No items to display

          -
            +
              - - <%-- -

              Activity stream

              -
                -
              • updated the issue . -
                  -
                • was updated from to
                • -
                -
              • -
              - - --%> - - -
              -
              -

              Feature Proposals

              -

              Open for your comments

              -
              +
              +
              +

              Getting started

              +

              Make sure to give the installation instructions a read.

              +

              Check the free foundation videos on how to get started building Umbraco sites. They're available from:
              +

              +

              World's best community

              +

              You'll find our über active community working hard to help each other at Our Umbraco: http://our.umbraco.org

              +

              Upgrading from older versions

              +

              Make sure to read the upgrade instructions before you attempt an upgrade.

              + + +

              Found a bug?

              +

              We're happy to help you with any problems you encounter, so please report them in the issue tracker and use the “Affected versions” field to set it to @Model.Name.
              Do a search first though, if the issue already exists, give it an extra vote.

              + + @if(Model.HasValue("linkToChangeset")) { +

              Source code

              +

              The source for this specific release is available for download from the repository (click the "ZIP" button).

              + } +
              +
              +
              - + + \ No newline at end of file diff --git a/OurUmbraco.Site/masterpages/ReleaseLanding.master b/OurUmbraco.Site/masterpages/ReleaseLanding.master index 2fa616c7..5ec07590 100644 --- a/OurUmbraco.Site/masterpages/ReleaseLanding.master +++ b/OurUmbraco.Site/masterpages/ReleaseLanding.master @@ -1,81 +1,127 @@ <%@ Master Language="C#" MasterPageFile="~/masterpages/Master.master" AutoEventWireup="true" %> - + - + - +
              - +
              -

              - +

              +

              Loading...

              - + -

              Loading...

              -
              +

              Current:

              Version
              Changes
              Release Date
              -
              +
              -
              +

              In Progress:

              Version
              Changes
              Release Date
              -
              +
              -
              +

              Planned:

              Version
              Changes
              Release Date
              -
              +
              -
              +

              Upcoming patch releases:

              Version
              Changes
              Release Date
              -
              +
              + + + +
              + +

              Historical releases:

              + +
                + @using uRelease + @{ + var properlySortedVersions = new Dictionary(); + foreach(var release in Model.Children) { + if(release.ReleaseStatus == "Released" && release.RecommendedRelease == false) { + properlySortedVersions.Add(new System.Version(release.Name), release); + } + } + } + + @foreach(var item in properlySortedVersions.OrderByDescending(x => x.Key)) + { + umbraco.MacroEngines.DynamicNode release = item.Value; +
              • +
                +
                +
                +

                + @* Archived releases don't exist on YouTrack, so they need an alternative template *@ + @if(release.GetProperty("Archived") != null && release.GetProperty("Archived").Value == "1"){ + @release.Name + } else { + @release.Name + } +

                +
                +
                +
                +
              • + } +
              +
              - + +
              - - + // Apply bindings + ko.applyBindings(viewModel); + // Load data + loadAllData(); + + }); + + + \ No newline at end of file diff --git a/OurUmbraco.Site/masterpages/RoadMap.master b/OurUmbraco.Site/masterpages/RoadMap.master index ebd806d7..2a9b2d00 100644 --- a/OurUmbraco.Site/masterpages/RoadMap.master +++ b/OurUmbraco.Site/masterpages/RoadMap.master @@ -8,7 +8,7 @@ - + @@ -67,7 +67,7 @@ // Apply bindings ko.applyBindings(viewModel); // Load data - loadData('all'); + loadAllData(); }); diff --git a/OurUmbraco.Site/scripts/app.js b/OurUmbraco.Site/scripts/app.js index dc5d9a93..6eea8fc1 100644 --- a/OurUmbraco.Site/scripts/app.js +++ b/OurUmbraco.Site/scripts/app.js @@ -118,7 +118,7 @@ var viewModel = { viewModel.currentReleases = ko.computed(function(){ return ko.utils.arrayFilter(viewModel.versions(), function (ver) { - return ver.latestRelease(); + return ver.currentRelease(); }); },viewModel); @@ -131,7 +131,7 @@ viewModel.inProgressReleases = ko.computed(function(){ viewModel.futureReleases = ko.computed(function(){ return ko.utils.arrayFilter(viewModel.versions(), function (ver) { - return (!ver.inProgressRelease() && !ver.released() && !ver.isPatch()); + return ver.plannedRelease(); }); },viewModel); @@ -153,6 +153,12 @@ viewModel.patchReleases = ko.computed(function(){ }); },viewModel); +viewModel.historicalReleases = ko.computed(function(){ + return ko.utils.arrayFilter(viewModel.versions(), function (ver) { + return (ver.released() && !ver.latestRelease()); + }); + },viewModel); + // Declare loader function loadData = function (versionId) { @@ -179,6 +185,31 @@ loadData = function (versionId) { }); }; +// Declare loader function +loadAllData = function () { + $.getJSON("/api/GetAllFromFile/", function (data) { + + // Parse result + ko.mapping.fromJS(data, versionMappingOptions, viewModel.versions); + + // Reload data + //setTimeout(loadData, 60000); + + $('.progress span').each(function(i,e){ + var progressItem = $(this); + if(progressItem.attr('title') > 0){ + progressItem.countTo({ + from: 0, + to: progressItem.attr('title'), + speed: 1200, + refreshInterval: 50, + }); + } + }); + + }); +}; + // Initialize // Knockout extentions @@ -186,6 +217,20 @@ ko.observable.fn.prettyDate = function () { return humaneDate(new Date(this())); }; +ko.bindingHandlers.slideVisible = { + init: function (element, valueAccessor) { + // Initially set the element to be instantly visible/hidden depending on the value + var value = valueAccessor(); + $(element).toggle(ko.utils.unwrapObservable(value)); // Use "unwrapObservable" so we can handle values that may or may not be observable + }, + update: function (element, valueAccessor) { + // Whenever the value subsequently changes, slowly fade the element in or out + var value = valueAccessor(); + ko.utils.unwrapObservable(value) ? $(element).slideDown() : $(element).slideUp(); + } +}; + + (function($) { $.fn.countTo = function(options) { // merge the default plugin settings with the custom options diff --git a/OurUmbraco.Site/xslt/RFC-TopicList.xslt b/OurUmbraco.Site/xslt/RFC-TopicList.xslt index 01449f23..7f642ef1 100644 --- a/OurUmbraco.Site/xslt/RFC-TopicList.xslt +++ b/OurUmbraco.Site/xslt/RFC-TopicList.xslt @@ -52,39 +52,6 @@ - -
              - - - - - - - - - - - - -
              - - - Pages: -
                - -
              • - - current - - - - -
              • -
                -
              -
              - -
              diff --git a/uRelease/Controllers/ApiController.cs b/uRelease/Controllers/ApiController.cs index 9f25651e..7a87ee9b 100644 --- a/uRelease/Controllers/ApiController.cs +++ b/uRelease/Controllers/ApiController.cs @@ -1,15 +1,17 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using System.Web.Mvc; using System.Collections; using System.Collections.Concurrent; using System.Threading.Tasks; -using System.Web.UI; +using System.Web.Script.Serialization; using RestSharp; using uRelease.Models; using YouTrackSharp.Infrastructure; +using umbraco.NodeFactory; using Issue = uRelease.Models.Issue; using System.Configuration; using Version = uRelease.Models.Version; @@ -25,9 +27,9 @@ namespace uRelease.Controllers private static readonly string Login = ConfigurationManager.AppSettings["uReleaseUsername"]; private static readonly string Password = ConfigurationManager.AppSettings["uReleasePassword"]; + private static readonly string ReleasesPageNodeId = ConfigurationManager.AppSettings["uReleaseParentNodeId"]; + private const string YouTrackJsonFile = "~/App_Data/YouTrack/all.json"; - - [OutputCache(Duration = 30, Location = OutputCacheLocation.ServerAndClient)] public JsonResult Aggregate(string ids) { var idArray = new ArrayList(); @@ -59,13 +61,35 @@ namespace uRelease.Controllers .ToArray(); } + var currentReleases = new List(); + var plannedReleases = new List(); + var inProgressReleases = new List(); - //figure out which is the latest v4 and v6 release - var latestReleasev4 = orderedVersions.Where(x => x.Released && x.Value.AsFullVersion().Major == 4).OrderByDescending(x => x.ReleaseDate).FirstOrDefault(); - var latestReleasev6 = orderedVersions.Where(x => x.Released && x.Value.AsFullVersion().Major == 6).OrderByDescending(x => x.ReleaseDate).FirstOrDefault(); + var releasesNode = new Node(int.Parse(ReleasesPageNodeId)); + foreach (Node release in releasesNode.Children) + { + if (release.GetProperty("recommendedRelease") != null && release.GetProperty("recommendedRelease").Value == "1") + { + var version = orderedVersions.FirstOrDefault(x => x.Value.ToString(CultureInfo.InvariantCulture) == release.Name); + if (version != null) + currentReleases.Add(version); + } - var inprogressRelease = orderedVersions.Where(x => x.Released == false && x.Value.AsFullVersion().Major == 6 && x.Value.AsFullVersion().Build == 0).OrderBy(x => x.ReleaseDate).FirstOrDefault(); + if (release.GetProperty("releaseStatus") != null && release.GetProperty("releaseStatus").Value == "Planning") + { + var version = orderedVersions.FirstOrDefault(x => x.Value.ToString(CultureInfo.InvariantCulture) == release.Name); + if (version != null) + plannedReleases.Add(version); + } + if (release.GetProperty("releaseStatus") != null && release.GetProperty("releaseStatus").Value == "Unreleased") + { + var version = orderedVersions.FirstOrDefault(x => x.Value.ToString(CultureInfo.InvariantCulture) == release.Name); + if (version != null) + inProgressReleases.Add(version); + } + } + // Just used to make sure we don't make repeated API requests for keys var versionCache = new ConcurrentDictionary>(); @@ -73,13 +97,14 @@ namespace uRelease.Controllers { var item = new AggregateView { - latestRelease = (latestReleasev4 != null && version.Value == latestReleasev4.Value || latestReleasev6 != null && version.Value == latestReleasev6.Value), - inProgressRelease = (inprogressRelease != null && version.Value == inprogressRelease.Value), + inProgressRelease = inProgressReleases.FirstOrDefault(x => x.Value == version.Value) != null, version = version.Value, isPatch = version.Value.AsFullVersion().Build != 0, releaseDescription = version.Description ?? string.Empty, released = version.Released, - releaseDate = version.ReleaseDate == 0 ? "" : new DateTime(1970, 1, 1).AddMilliseconds(version.ReleaseDate).ToString(CultureInfo.InvariantCulture) + releaseDate = version.ReleaseDate == 0 ? "" : ConvertDate(version.ReleaseDate).ToString(CultureInfo.InvariantCulture), + currentRelease = currentReleases.FirstOrDefault(x => x.Value == version.Value) != null, + plannedRelease = plannedReleases.FirstOrDefault(x => x.Value == version.Value) != null }; // /rest/issue/byproject/{project}?{filter} @@ -104,18 +129,50 @@ namespace uRelease.Controllers var activitiesDateDesc = activityView.Where(x => x.changes.Any()).OrderByDescending(x => x.date); var issueIdsFromActivities = activitiesDateDesc.Select(x => x.id).Distinct() - .Concat(issueView.Where(y => y != null && !activitiesDateDesc.Select(z => z.id).Contains(y.id)).Select(y => y.id)); // Add issues for which there is no activity + .Concat(issueView.Where(y => y != null && activitiesDateDesc.Select(z => z.id).Contains(y.id) == false).Select(y => y.id)); // Add issues for which there is no activity item.issues = issueIdsFromActivities.Select(x => issueView.Single(y => y != null && y.id == x)).OrderBy(x => x.id); item.activities = activitiesDateDesc.Take(5); - - + toReturn.Add(item); } return new JsonResult { Data = toReturn, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } + public JsonResult GetAllFromFile() + { + if (System.IO.File.Exists(Server.MapPath(YouTrackJsonFile)) == false) + SaveAllToFile(); + + var allText = System.IO.File.ReadAllText(Server.MapPath(YouTrackJsonFile)); + + return new JsonResult { Data = new JavaScriptSerializer().DeserializeObject(allText), JsonRequestBehavior = JsonRequestBehavior.AllowGet }; + } + + public string SaveAllToFile() + { + try + { + var result = new JavaScriptSerializer().Serialize(Aggregate("all").Data); + using (var streamWriter = new StreamWriter(Server.MapPath(YouTrackJsonFile), false)) + { + streamWriter.WriteLine(result); + } + } + catch (Exception exception) + { + return string.Format("{0} {1}", exception.Message, exception.StackTrace); + } + + return string.Format("Results succesfully written to {0} at {1}", Server.MapPath(YouTrackJsonFile), DateTime.Now); + } + + private static DateTime ConvertDate(long date) + { + return new DateTime(1970, 1, 1).AddMilliseconds(date); + } + private static string GetFieldFromIssue(Issue issue, string fieldName) { var findField = issue.Fields.FirstOrDefault(x => x.Name == fieldName); diff --git a/uRelease/Models/AggregateView.cs b/uRelease/Models/AggregateView.cs index 389cba0e..f471845c 100644 --- a/uRelease/Models/AggregateView.cs +++ b/uRelease/Models/AggregateView.cs @@ -26,6 +26,10 @@ namespace uRelease.Models public IEnumerable issues { get; set; } public IEnumerable activities { get; set; } + + public bool currentRelease { get; set; } + + public bool plannedRelease { get; set; } } public class IssuesWrapper diff --git a/uRelease/uRelease.csproj b/uRelease/uRelease.csproj index 03bc0b9f..14e7a827 100644 --- a/uRelease/uRelease.csproj +++ b/uRelease/uRelease.csproj @@ -47,6 +47,9 @@ ..\packages\EasyHttp.1.6.29.0\lib\net40\EasyHttp.dll + + ..\dependencies\4.9.1\interfaces.dll + ..\packages\JsonFx.2.0.1209.2802\lib\net40\JsonFx.dll @@ -81,6 +84,9 @@ + + ..\dependencies\4.9.1\umbraco.dll + ..\packages\YouTrackSharp.2.0.11.0\lib\net40\YouTrackSharp.dll