Changeset 12435
- Timestamp:
- 06/12/15 14:59:54 (9 years ago)
- Location:
- trunk/sources
- Files:
-
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataController.cs
r12428 r12435 1 using System; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System; 2 23 using System.Collections.Generic; 3 24 using System.Linq; … … 21 42 SELECT 22 43 DISTINCT UserId, 23 ISNULL((SELECT Count FROM UserTasks WHERE TaskState = 'Calculating' AND UserId = ut.UserId), 0) AS CalculatingTasks,24 ISNULL((SELECT Count FROM UserTasks WHERE TaskState = 'Waiting' AND UserId = ut.UserId), 0) AS WaitingTasks44 (SELECT Count FROM UserTasks WHERE TaskState = 'Calculating' AND UserId = ut.UserId) AS CalculatingTasks, 45 (SELECT Count FROM UserTasks WHERE TaskState = 'Waiting' AND UserId = ut.UserId) AS WaitingTasks 25 46 FROM UserTasks ut;"; 26 47 … … 41 62 CalculatingTasks = uts.CalculatingTasks, 42 63 WaitingTasks = uts.WaitingTasks 43 }) ;64 }).OrderBy(x => x.User.Name); 44 65 } 45 66 // end temporary quickfix … … 50 71 where slave.SlaveState == SlaveState.Calculating || slave.SlaveState == SlaveState.Idle 51 72 select slave).ToList(); 73 var activeSlaves = onlineSlaves.Where(s => s.IsAllowedToCalculate).ToList(); 74 var calculatingSlaves = activeSlaves.Where(s => s.SlaveState == SlaveState.Calculating).ToList(); 75 76 int calculatingMemory = calculatingSlaves.Any() ? (int)calculatingSlaves.Sum(s => s.Memory) / 1024 : 0; 77 int freeCalculatingMemory = calculatingSlaves.Any() ? (int)calculatingSlaves.Sum(s => s.FreeMemory) / 1024 : 0; 78 52 79 return new DTO.Status { 53 80 CoreStatus = new DTO.CoreStatus { 54 81 TotalCores = onlineSlaves.Sum(s => s.Cores ?? 0), 55 AvailableCores = onlineSlaves.Where(s => s.IsAllowedToCalculate).Sum(s => s.Cores ?? 0), 56 FreeCores = onlineSlaves.Sum(s => s.FreeCores ?? 0) 82 FreeCores = onlineSlaves.Sum(s => s.FreeCores ?? 0), // temporary for old chart data 83 ActiveCores = activeSlaves.Sum(s => s.Cores ?? 0), 84 CalculatingCores = calculatingSlaves.Sum(s => s.Cores ?? 0) 57 85 }, 58 86 CpuUtilizationStatus = new DTO.CpuUtilizationStatus { … … 60 88 ? Math.Round(onlineSlaves.Average(s => s.CpuUtilization), 2) 61 89 : 0.0, 62 UsedCpuUtilization = onlineSlaves.Any(x => x.IsAllowedToCalculate) 63 ? Math.Round(onlineSlaves.Where(x => x.IsAllowedToCalculate).Average(s => s.CpuUtilization), 2) 64 : 0.0 90 ActiveCpuUtilization = activeSlaves.Any() 91 ? Math.Round(activeSlaves.Average(s => s.CpuUtilization), 2) 92 : 0.0, 93 CalculatingCpuUtilization = calculatingSlaves.Any() 94 ? Math.Round(calculatingSlaves.Average(s => s.CpuUtilization), 2) 95 : 0.0 65 96 }, 66 97 MemoryStatus = new DTO.MemoryStatus { 67 98 TotalMemory = onlineSlaves.Any() ? (int)onlineSlaves.Sum(s => s.Memory) / 1024 : 0, 68 FreeMemory = onlineSlaves.Any() ? (int)onlineSlaves.Sum(s => s.FreeMemory) / 1024 : 0 99 FreeMemory = onlineSlaves.Any() ? (int)onlineSlaves.Sum(s => s.FreeMemory) / 1024 : 0, 100 ActiveMemory = activeSlaves.Any() ? (int)activeSlaves.Sum(s => s.Memory) / 1024 : 0, 101 UsedMemory = calculatingMemory - freeCalculatingMemory 69 102 }, 70 103 TasksStatus = GetTaskStatus(db), 71 SlavesCpuStatus = onlineSlaves.Select(x => new DTO.SlaveCpuStatus { 72 CpuUtilization = Math.Round(x.CpuUtilization, 2), 104 SlavesStatus = onlineSlaves.Select(x => new DTO.SlaveStatus { 73 105 Slave = new DTO.Slave { 74 106 Id = x.ResourceId.ToString(), 75 107 Name = x.Name 76 } 77 }), 108 }, 109 CpuUtilization = x.CpuUtilization, 110 Cores = x.Cores ?? 0, 111 FreeCores = x.FreeCores ?? 0, 112 Memory = (x.Memory ?? 0) / 1024, 113 FreeMemory = (x.FreeMemory ?? 0) / 1024, 114 IsAllowedToCalculate = x.IsAllowedToCalculate, 115 State = x.SlaveState.ToString() 116 }).OrderBy(x => x.Slave.Name), 78 117 Timestamp = JavascriptUtils.ToTimestamp(DateTime.Now) 79 118 }; … … 82 121 83 122 public IEnumerable<DTO.Status> GetStatusHistory(DateTime start, DateTime end) { 123 TimeSpan ts = end - start; 124 int increment = 1; 125 double totalMinutes = ts.TotalMinutes; 126 while (totalMinutes > 5761) { 127 totalMinutes -= 5761; 128 increment += 5; 129 } 84 130 using (var db = new HiveDataContext()) { 85 var statistics = db.Statistics.Where(s => s.Timestamp >= start && s.Timestamp <= end) 86 .OrderBy(x => x.Timestamp) 87 .ToList(); 131 var statistics = db.Statistics.Where(s => s.Timestamp >= start && s.Timestamp <= end); 132 var status = new DTO.Status { 133 CoreStatus = new DTO.CoreStatus(), 134 CpuUtilizationStatus = new DTO.CpuUtilizationStatus(), 135 MemoryStatus = new DTO.MemoryStatus() 136 }; 137 int freeCores = 0; 138 int freeMemory = 0; 139 int i = 1; 88 140 foreach (var statistic in statistics) { 89 yield return new DTO.Status { 90 CoreStatus = new DTO.CoreStatus { 91 TotalCores = statistic.SlaveStatistics.Sum(x => x.Cores), 92 AvailableCores = 0, 93 FreeCores = statistic.SlaveStatistics.Sum(x => x.FreeCores) 94 }, 95 CpuUtilizationStatus = new DTO.CpuUtilizationStatus { 96 TotalCpuUtilization = 0.0, 97 UsedCpuUtilization = statistic.SlaveStatistics.Any() ? statistic.SlaveStatistics.Average(x => x.CpuUtilization) : 0.0 98 }, 99 MemoryStatus = new DTO.MemoryStatus { 100 TotalMemory = statistic.SlaveStatistics.Sum(x => x.Memory) / 1024, 101 FreeMemory = statistic.SlaveStatistics.Sum(x => x.FreeMemory) / 1024 102 }, 103 Timestamp = JavascriptUtils.ToTimestamp(statistic.Timestamp) 104 }; 141 status.CoreStatus.TotalCores += statistic.SlaveStatistics.Sum(x => x.Cores); 142 freeCores += statistic.SlaveStatistics.Sum(x => x.FreeCores); 143 status.CpuUtilizationStatus.TotalCpuUtilization += statistic.SlaveStatistics.Any() 144 ? statistic.SlaveStatistics.Average(x => x.CpuUtilization) 145 : 0.0; 146 status.MemoryStatus.TotalMemory += statistic.SlaveStatistics.Sum(x => x.Memory) / 1024; 147 freeMemory += statistic.SlaveStatistics.Sum(x => x.FreeMemory) / 1024; 148 if (i >= increment) { 149 status.Timestamp = JavascriptUtils.ToTimestamp(statistic.Timestamp); 150 status.CoreStatus.TotalCores /= i; 151 freeCores /= i; 152 status.CpuUtilizationStatus.TotalCpuUtilization /= i; 153 status.MemoryStatus.TotalMemory /= i; 154 freeMemory /= i; 155 status.CoreStatus.ActiveCores = status.CoreStatus.TotalCores; 156 status.MemoryStatus.ActiveMemory = status.MemoryStatus.TotalMemory; 157 status.CpuUtilizationStatus.ActiveCpuUtilization = status.CpuUtilizationStatus.TotalCpuUtilization; 158 status.CpuUtilizationStatus.CalculatingCpuUtilization = status.CpuUtilizationStatus.CalculatingCpuUtilization; 159 status.CoreStatus.CalculatingCores = status.CoreStatus.TotalCores - freeCores; 160 status.MemoryStatus.UsedMemory = status.MemoryStatus.TotalMemory - freeMemory; 161 yield return status; 162 status = new DTO.Status { 163 CoreStatus = new DTO.CoreStatus(), 164 CpuUtilizationStatus = new DTO.CpuUtilizationStatus(), 165 MemoryStatus = new DTO.MemoryStatus() 166 }; 167 freeCores = 0; 168 freeMemory = 0; 169 i = 1; 170 } else { 171 i++; 172 } 105 173 } 106 174 } -
trunk/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataTransfer/Slave.cs
r12428 r12435 1 namespace HeuristicLab.Services.WebApp.Status.WebApi.DataTransfer { 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 namespace HeuristicLab.Services.WebApp.Status.WebApi.DataTransfer { 2 23 public class Slave { 3 24 public string Id { get; set; } // currently unused -
trunk/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataTransfer/Status.cs
r12428 r12435 1 using System.Collections.Generic; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System.Collections.Generic; 2 23 3 24 namespace HeuristicLab.Services.WebApp.Status.WebApi.DataTransfer { … … 5 26 public class CoreStatus { 6 27 public int TotalCores { get; set; } 7 public int AvailableCores { get; set; } 8 public int FreeCores { get; set; } 28 public int FreeCores { get; set; } // temporary quickfix for old chart data 29 public int ActiveCores { get; set; } 30 public int CalculatingCores { get; set; } 9 31 } 10 32 11 33 public class CpuUtilizationStatus { 12 34 public double TotalCpuUtilization { get; set; } 13 public double UsedCpuUtilization { get; set; } 35 public double ActiveCpuUtilization { get; set; } 36 public double CalculatingCpuUtilization { get; set; } 14 37 } 15 38 16 39 public class MemoryStatus { 17 40 public int TotalMemory { get; set; } 18 public int FreeMemory { get; set; } 41 public int FreeMemory { get; set; } // temporary quickfix for old chart data 42 public int ActiveMemory { get; set; } 43 public int UsedMemory { get; set; } 19 44 } 20 45 … … 25 50 } 26 51 27 public class Slave CpuStatus {52 public class SlaveStatus { 28 53 public Slave Slave { get; set; } 29 54 public double CpuUtilization { get; set; } 55 public int Cores { get; set; } 56 public int FreeCores { get; set; } 57 public int Memory { get; set; } 58 public int FreeMemory { get; set; } 59 public bool IsAllowedToCalculate { get; set; } 60 public string State { get; set; } 30 61 } 31 62 … … 35 66 public MemoryStatus MemoryStatus { get; set; } 36 67 public IEnumerable<TaskStatus> TasksStatus { get; set; } 37 public IEnumerable<Slave CpuStatus> SlavesCpuStatus { get; set; }68 public IEnumerable<SlaveStatus> SlavesStatus { get; set; } 38 69 public long Timestamp { get; set; } 39 70 } -
trunk/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApi/DataTransfer/User.cs
r12428 r12435 1 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 2 22 namespace HeuristicLab.Services.WebApp.Status.WebApi.DataTransfer { 3 23 public class User { -
trunk/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApi/JavascriptUtils.cs
r12428 r12435 1 using System; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System; 2 23 3 24 namespace HeuristicLab.Services.WebApp.Status.WebApi { … … 6 27 var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); 7 28 var time = input.Subtract(new TimeSpan(epoch.Ticks)); 8 return (long)(time.Ticks / 10000);29 return time.Ticks / 10000; 9 30 } 10 31 } -
trunk/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/history/history.cshtml
r12428 r12435 56 56 <div class="panel-body"> 57 57 <flot dataset="coreSeries" options="fillChartOptions"></flot> 58 <p>{{maxUpper}}</p> 59 <p>{{fromDateTime}}</p> 60 <p>{{toDateTime}}</p> 58 61 </div> 59 62 </div> -
trunk/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/history/historyCtrl.js
r12428 r12435 4 4 ['$scope', '$interval', 'app.status.data.service', 5 5 function ($scope, $interval, dataService) { 6 7 6 $scope.chartOptions = { 8 7 grid: { … … 59 58 }; 60 59 60 61 61 $scope.fromDate = new Date(); 62 62 $scope.toDate = new Date(); … … 89 89 90 90 var updateCharts = function () { 91 dataService.getStatusHistory({ start: ConvertFromDate($scope.fromDate), end: ConvertToDate($scope.toDate)}, function (status) {91 dataService.getStatusHistory({ start: ConvertFromDate($scope.fromDate), end: ConvertToDate($scope.toDate) }, function (status) { 92 92 var noOfStatus = status.length; 93 93 var cpuSeries = []; … … 96 96 for (var i = 0; i < noOfStatus; ++i) { 97 97 var curStatus = status[i]; 98 var cpuData = Math.round(curStatus.CpuUtilizationStatus.UsedCpuUtilization); 99 var usedCores = curStatus.CoreStatus.TotalCores - curStatus.CoreStatus.FreeCores; 100 var usedMemory = curStatus.MemoryStatus.TotalMemory - curStatus.MemoryStatus.FreeMemory; 98 var cpuData = Math.round(curStatus.CpuUtilizationStatus.ActiveCpuUtilization); 101 99 cpuSeries.push([curStatus.Timestamp, cpuData]); 102 coreSeries[0].push([curStatus.Timestamp, curStatus.CoreStatus. TotalCores]);103 coreSeries[1].push([curStatus.Timestamp, usedCores]);104 memorySeries[0].push([curStatus.Timestamp, curStatus.MemoryStatus. TotalMemory]);105 memorySeries[1].push([curStatus.Timestamp, usedMemory]);100 coreSeries[0].push([curStatus.Timestamp, curStatus.CoreStatus.ActiveCores]); 101 coreSeries[1].push([curStatus.Timestamp, curStatus.CoreStatus.CalculatingCores]); 102 memorySeries[0].push([curStatus.Timestamp, curStatus.MemoryStatus.ActiveMemory]); 103 memorySeries[1].push([curStatus.Timestamp, curStatus.MemoryStatus.UsedMemory]); 106 104 } 107 105 $scope.cpuSeries = [{ data: cpuSeries, label: " CPU Utilization", color: "#f7921d" }]; -
trunk/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/status.cshtml
r12428 r12435 11 11 12 12 <div class="default-view-container"> 13 <div class="row"> 14 <div class="col-lg-3 col-md-6"> 15 <div class="panel panel-default"> 16 <div class="panel-heading"> 17 <h3 class="panel-title">Cores</h3> 18 </div> 19 <div class="panel-body"> 20 <center> 21 <knob knob-data="core.knobData" knob-options="knobOptions"></knob> 22 </center> 23 <p>Total Cores: {{status.CoreStatus.TotalCores}}</p> 24 <p>Used Cores: {{status.CoreStatus.TotalCores - status.CoreStatus.FreeCores}}</p> 25 </div> 26 </div> 27 </div> 28 29 <div class="col-lg-3 col-md-6"> 30 <div class="panel panel-default"> 31 <div class="panel-heading"> 32 <h3 class="panel-title">CPU Utilization</h3> 33 </div> 34 <div class="panel-body"> 35 <center> 36 <knob knob-data="cpu.knobData" knob-options="knobOptions"></knob> 37 </center> 38 <p>Total Utilization: {{status.CpuUtilizationStatus.TotalCpuUtilization}} %</p> 39 <p>Used Utilization: {{status.CpuUtilizationStatus.UsedCpuUtilization}} %</p> 40 </div> 41 </div> 42 </div> 43 44 <div class="col-lg-3 col-md-6"> 45 <div class="panel panel-default"> 46 <div class="panel-heading"> 47 <h3 class="panel-title">Memory</h3> 48 </div> 49 <div class="panel-body"> 50 <center> 51 <knob knob-data="memory.knobData" knob-options="knobOptions"></knob> 52 </center> 53 <p>TotalMemory: {{status.MemoryStatus.TotalMemory}} GB</p> 54 <p>UsedMemory: {{status.MemoryStatus.TotalMemory - status.MemoryStatus.FreeMemory}} GB</p> 55 </div> 56 </div> 57 </div> 58 59 <div class="col-lg-3 col-md-6"> 60 <div class="panel panel-default"> 61 <div class="panel-heading"> 62 <h3 class="panel-title">Tasks</h3> 63 </div> 64 <div class="panel-body"> 65 <p>Total: {{tasks.WaitingTasks + tasks.CalculatingTasks}}</p> 66 <p>Waiting: {{tasks.WaitingTasks}}</p> 67 <p>Calculating: {{tasks.CalculatingTasks}}</p> 68 </div> 69 </div> 70 </div> 71 </div> 72 73 <div class="row"> 74 <div class="col-lg-12"> 75 <div class="panel panel-default"> 76 <div class="panel-heading"> 77 <h3 class="panel-title">CPU Utilization Chart</h3> 78 </div> 79 <div class="panel-body"> 80 <flot dataset="cpu.series" options="chartOptions"></flot> 81 </div> 82 </div> 83 </div> 84 </div> 85 86 <div class="row"> 87 <div class="col-lg-12"> 88 <div class="panel panel-default"> 89 <div class="panel-heading"> 90 <h3 class="panel-title">Core Chart</h3> 91 </div> 92 <div class="panel-body"> 93 <flot dataset="core.series" options="fillChartOptions"></flot> 94 </div> 95 </div> 96 </div> 97 </div> 98 99 <div class="row"> 100 <div class="col-lg-12"> 101 <div class="panel panel-default"> 102 <div class="panel-heading"> 103 <h3 class="panel-title">Memory Chart</h3> 104 </div> 105 <div class="panel-body"> 106 <flot dataset="memory.series" options="fillChartOptions"></flot> 107 </div> 108 </div> 109 </div> 110 </div> 111 112 <div class="row"> 113 <div class="col-lg-12"> 114 <div class="panel panel-default"> 115 <div class="panel-heading"> 116 <h3 class="panel-title">Tasks by User</h3> 117 </div> 13 <div class="row"> 14 <div class="col-lg-3 col-md-6"> 15 <div class="panel panel-default"> 16 <div class="panel-heading"> 17 <h3 class="panel-title">Cores</h3> 18 </div> 19 <div class="panel-body"> 20 <div class="text-center"> 21 <knob knob-data="core.knobData" knob-options="knobOptions"></knob> 22 </div> 23 <table class="table table-no-border table-condensed table-auto-width table-content"> 24 <tr data-toggle="tooltip" data-placement="bottom" title="All online slaves"> 25 <td class="text-left"> 26 Total: 27 </td> 28 <td class="text-right">{{status.CoreStatus.TotalCores | number}}</td> 29 </tr> 30 <tr data-toggle="tooltip" data-placement="bottom" title="All calculating and idle slaves that are allowed to calculate"> 31 <td class="text-left">Active:</td> 32 <td class="text-right">{{status.CoreStatus.ActiveCores | number}}</td> 33 </tr> 34 <tr data-toggle="tooltip" data-placement="bottom" title="All calculating slaves that are allowed to calculate"> 35 <td class="text-left">Calculating:</td> 36 <td class="text-right">{{status.CoreStatus.CalculatingCores | number}}</td> 37 </tr> 38 </table> 39 </div> 40 </div> 41 </div> 42 43 <div class="col-lg-3 col-md-6"> 44 <div class="panel panel-default"> 45 <div class="panel-heading"> 46 <h3 class="panel-title">CPU Utilization</h3> 47 </div> 48 <div class="panel-body"> 49 <div class="text-center"> 50 <knob knob-data="cpu.knobData" knob-options="knobOptions"></knob> 51 </div> 52 <table class="table table-no-border table-condensed table-auto-width table-content"> 53 <tr data-toggle="tooltip" data-placement="bottom" title="All online slaves"> 54 <td class="text-left">Total:</td> 55 <td class="text-right">{{status.CpuUtilizationStatus.TotalCpuUtilization | number: 2}} %</td> 56 </tr> 57 <tr data-toggle="tooltip" data-placement="bottom" title="All calculating and idle slaves that are allowed to calculate"> 58 <td class="text-left">Active:</td> 59 <td class="text-right">{{status.CpuUtilizationStatus.ActiveCpuUtilization | number: 2}} %</td> 60 </tr> 61 <tr data-toggle="tooltip" data-placement="bottom" title="All calculating slaves that are allowed to calculate"> 62 <td class="text-left">Calculating:</td> 63 <td class="text-right">{{status.CpuUtilizationStatus.CalculatingCpuUtilization | number: 2}} %</td> 64 </tr> 65 </table> 66 </div> 67 </div> 68 </div> 69 70 <div class="col-lg-3 col-md-6"> 71 <div class="panel panel-default"> 72 <div class="panel-heading"> 73 <h3 class="panel-title">Memory</h3> 74 </div> 75 <div class="panel-body"> 76 <div class="text-center"> 77 <knob knob-data="memory.knobData" knob-options="knobOptions"></knob> 78 </div> 79 <table class="table table-no-border table-condensed table-auto-width table-content"> 80 <tr data-toggle="tooltip" data-placement="bottom" title="All online slaves"> 81 <td class="text-left">Total:</td> 82 <td class="text-right">{{status.MemoryStatus.TotalMemory | number}} GB</td> 83 </tr> 84 <tr data-toggle="tooltip" data-placement="bottom" title="All calculating and idle slaves that are allowed to calculate"> 85 <td class="text-left">Active:</td> 86 <td class="text-right">{{status.MemoryStatus.ActiveMemory | number}} GB</td> 87 </tr> 88 <tr data-toggle="tooltip" data-placement="bottom" title="All calculating slaves that are allowed to calculate"> 89 <td class="text-left">Calculating:</td> 90 <td class="text-right">{{status.MemoryStatus.UsedMemory | number}} GB</td> 91 </tr> 92 </table> 93 </div> 94 </div> 95 </div> 96 97 <div class="col-lg-3 col-md-6"> 98 <div class="panel panel-default"> 99 <div class="panel-heading"> 100 <h3 class="panel-title">Tasks</h3> 101 </div> 102 <div class="panel-body"> 103 <table class="table table-no-border table-condensed table-auto-width table-content"> 104 <tr> 105 <td class="text-left">Total:</td> 106 <td class="text-right">{{tasks.WaitingTasks + tasks.CalculatingTasks | number}}</td> 107 </tr> 108 <tr> 109 <td class="text-left">Waiting:</td> 110 <td class="text-right">{{tasks.WaitingTasks | number}}</td> 111 </tr> 112 <tr> 113 <td class="text-left">Calculating:</td> 114 <td class="text-right">{{tasks.CalculatingTasks | number}}</td> 115 </tr> 116 </table> 117 </div> 118 </div> 119 </div> 120 </div> 121 122 <div class="row"> 123 <div class="col-lg-12"> 124 <div class="panel panel-default"> 125 <div class="panel-heading"> 126 <h3 class="panel-title">CPU Utilization Chart</h3> 127 </div> 128 <div class="panel-body"> 129 <flot dataset="cpu.series" options="chartOptions"></flot> 130 </div> 131 </div> 132 </div> 133 </div> 134 135 <div class="row"> 136 <div class="col-lg-12"> 137 <div class="panel panel-default"> 138 <div class="panel-heading"> 139 <h3 class="panel-title">Core Chart</h3> 140 </div> 141 <div class="panel-body"> 142 <flot dataset="core.series" options="fillChartOptions"></flot> 143 </div> 144 </div> 145 </div> 146 </div> 147 148 <div class="row"> 149 <div class="col-lg-12"> 150 <div class="panel panel-default"> 151 <div class="panel-heading"> 152 <h3 class="panel-title">Memory Chart</h3> 153 </div> 154 <div class="panel-body"> 155 <flot dataset="memory.series" options="fillChartOptions"></flot> 156 </div> 157 </div> 158 </div> 159 </div> 160 161 <div class="row"> 162 <div class="col-lg-12"> 163 <div class="panel panel-default"> 164 <div class="panel-heading"> 165 <h3 class="panel-title">Tasks by User</h3> 166 </div> 167 <div class="panel-body"> 168 <table class="table table-hover"> 169 <thead> 170 <tr> 171 <th>Username</th> 172 <th>Calculating Tasks</th> 173 <th>Waiting Tasks</th> 174 </tr> 175 </thead> 176 <tr ng-repeat="task in status.TasksStatus"> 177 <td>{{task.User.Name}}</td> 178 <td>{{task.CalculatingTasks | number}}</td> 179 <td>{{task.WaitingTasks | number}}</td> 180 </tr> 181 <tr ng-hide="status.TasksStatus.length"> 182 <td colspan="3" class="text-center"> 183 There are no waiting or calculating tasks available! 184 </td> 185 </tr> 186 </table> 187 </div> 188 </div> 189 </div> 190 </div> 191 192 <div class="row"> 193 <div class="col-lg-12"> 194 <div class="panel panel-default"> 195 <div class="panel-heading"> 196 <h3 class="panel-title"> 197 <a data-toggle="collapse" data-target="#collapseActiveCalculatingSlaves" 198 ng-href="#/status"> 199 Active Calculating Slaves 200 </a> 201 </h3> 202 </div> 203 <div id="collapseActiveCalculatingSlaves" 204 class="panel-collapse collapse in"> 118 205 <div class="panel-body"> 119 206 <table class="table table-hover"> 120 207 <thead> 121 <tr> 122 <th>Username</th> 123 <th>Calculating Tasks</th> 124 <th>Waiting Tasks</th> 125 </tr> 208 <tr> 209 <th ng-click="activeCalculatingSlavesOrderColumn='Slave.Name'; 210 activeCalculatingSlavesReverseSort=!activeCalculatingSlavesReverseSort"> 211 Slave 212 </th> 213 <th ng-click="activeCalculatingSlavesOrderColumn='CpuUtilization'; 214 activeCalculatingSlavesReverseSort=!activeCalculatingSlavesReverseSort"> 215 CPU Utilization 216 </th> 217 <th ng-click="activeCalculatingSlavesOrderColumn='Cores'; 218 activeCalculatingSlavesReverseSort=!activeCalculatingSlavesReverseSort"> 219 Cores 220 </th> 221 <th ng-click="activeCalculatingSlavesOrderColumn='Memory'; 222 activeCalculatingSlavesReverseSort=!activeCalculatingSlavesReverseSort"> 223 Memory 224 </th> 225 </tr> 126 226 </thead> 127 <tr ng-repeat="task in status.TasksStatus"> 128 <td>{{task.User.Name}}</td> 129 <td>{{task.CalculatingTasks}}</td> 130 <td>{{task.WaitingTasks}}</td> 227 <tr ng-repeat="slave in activeCalculatingSlaves = (status.SlavesStatus 228 | filter: { 229 IsAllowedToCalculate: true, 230 State: 'Calculating' 231 } 232 | orderBy: activeCalculatingSlavesOrderColumn:activeCalculatingSlavesReverseSort)"> 233 <td>{{slave.Slave.Name}}</td> 234 <td>{{slave.CpuUtilization | number: 2}} %</td> 235 <td>{{slave.Cores | number}}</td> 236 <td>{{slave.Memory | number}} GB</td> 237 </tr> 238 <tr ng-hide="activeCalculatingSlaves.length"> 239 <td colspan="4" class="text-center"> 240 There are no active calculating slaves available! 241 </td> 131 242 </tr> 132 243 </table> … … 135 246 </div> 136 247 </div> 137 138 <div class="row"> 139 <div class="col-lg-12"> 140 <div class="panel panel-default"> 141 <div class="panel-heading"> 142 <h3 class="panel-title">CPU Utilization by Slave</h3> 143 </div> 248 </div> 249 250 <div class="row"> 251 <div class="col-lg-12"> 252 <div class="panel panel-default"> 253 <div class="panel-heading"> 254 <h3 class="panel-title"> 255 <a data-toggle="collapse" data-target="#collapseActiveIdleSlaves" 256 ng-href="#/status" class="collapsed"> 257 Active Idle Slaves 258 </a> 259 </h3> 260 </div> 261 <div id="collapseActiveIdleSlaves" 262 class="panel-collapse collapse"> 144 263 <div class="panel-body"> 145 264 <table class="table table-hover"> 146 265 <thead> 147 <tr> 148 <th>Slave</th> 149 <th>CPU Utilization</th> 150 </tr> 266 <tr> 267 <th ng-click="activeIdleSlavesOrderColumn='Slave.Name'; 268 activeIdleSlavesReverseSort=!activeIdleSlavesReverseSort"> 269 Slave 270 </th> 271 <th ng-click="activeIdleSlavesOrderColumn='CpuUtilization'; 272 activeIdleSlavesReverseSort=!activeIdleSlavesReverseSort"> 273 CPU Utilization 274 </th> 275 <th ng-click="activeIdleSlavesOrderColumn='Cores'; 276 activeIdleSlavesReverseSort=!activeIdleSlavesReverseSort"> 277 Cores 278 </th> 279 <th ng-click="activeIdleSlavesOrderColumn='Memory'; 280 activeIdleSlavesReverseSort=!activeIdleSlavesReverseSort"> 281 Memory 282 </th> 283 </tr> 151 284 </thead> 152 <tr ng-repeat="slave in status.SlavesCpuStatus"> 285 <tr ng-repeat="slave in activeIdleSlaves = (status.SlavesStatus 286 | filter: { 287 IsAllowedToCalculate: true, 288 State: 'Idle' 289 } 290 | orderBy: activeIdleSlavesOrderColumn:activeIdleSlavesReverseSort)"> 153 291 <td>{{slave.Slave.Name}}</td> 154 <td>{{slave.CpuUtilization}} %</td> 292 <td>{{slave.CpuUtilization | number: 2}} %</td> 293 <td>{{slave.Cores | number}}</td> 294 <td>{{slave.Memory | number}} GB</td> 295 </tr> 296 <tr ng-hide="activeIdleSlaves.length"> 297 <td colspan="4" class="text-center"> 298 There are no active idle slaves available! 299 <td> 155 300 </tr> 156 301 </table> … … 160 305 </div> 161 306 </div> 307 308 <div class="row"> 309 <div class="col-lg-12"> 310 <div class="panel panel-default"> 311 <div class="panel-heading"> 312 <h3 class="panel-title"> 313 <a data-toggle="collapse" data-target="#collapseInactiveSlaves" 314 ng-href="#/status" class="collapsed"> 315 Inactive Slaves 316 </a> 317 </h3> 318 </div> 319 <div id="collapseInactiveSlaves" 320 class="panel-collapse collapse"> 321 <div class="panel-body"> 322 <table class="table table-hover"> 323 <thead> 324 <tr> 325 <th ng-click="inactiveSlavesOrderColumn='Slave.Name'; 326 inactiveSlavesReverseSort=!inactiveSlavesReverseSort"> 327 Slave 328 </th> 329 <th ng-click="inactiveSlavesOrderColumn='CpuUtilization'; 330 inactiveSlavesReverseSort=!inactiveSlavesReverseSort"> 331 CPU Utilization 332 </th> 333 <th ng-click="inactiveSlavesOrderColumn='Cores'; 334 inactiveSlavesReverseSort=!inactiveSlavesReverseSort"> 335 Cores 336 </th> 337 <th ng-click="inactiveSlavesOrderColumn='Memory'; 338 inactiveSlavesReverseSort=!inactiveSlavesReverseSort"> 339 Memory 340 </th> 341 </tr> 342 </thead> 343 <tr ng-repeat="slave in inactiveSlaves = (status.SlavesStatus 344 | filter: { 345 IsAllowedToCalculate: false 346 } 347 | orderBy: inactiveSlavesOrderColumn:inactiveSlavesReverseSort)"> 348 <td>{{slave.Slave.Name}}</td> 349 <td>{{slave.CpuUtilization | number: 2}} %</td> 350 <td>{{slave.Cores | number}}</td> 351 <td>{{slave.Memory | number}} GB</td> 352 </tr> 353 <tr ng-hide="inactiveSlaves.length"> 354 <td colspan="4" class="text-center">No inactive slaves available!</td> 355 </tr> 356 </table> 357 </div> 358 </div> 359 </div> 360 </div> 361 </div> 362 </div> 363 364 <script> 365 $(document).ready(function () { 366 $('[data-toggle="tooltip"]').tooltip(); 367 }); 368 </script> -
trunk/sources/HeuristicLab.Services.WebApp.Status/3.3/WebApp/status/statusCtrl.js
r12428 r12435 53 53 mode: "time", 54 54 twelveHourClock: false 55 }, 56 yaxis: { 57 min: 0 55 58 } 56 59 }; … … 82 85 }; 83 86 87 $scope.activeIdleSlaveFilter = function (slave) { 88 return (slave.IsAllowedToCalculate == true) && (slave.State == 'Idle'); 89 }; 90 91 $scope.activeCalculatingSlavesReverseSort = false; 92 $scope.activeCalculatingSlavesOrderColumn = 'slave.Slave.Name'; 93 94 $scope.activeIdleSlavesReverseSort = false; 95 $scope.activeIdleSlavesOrderColumn = 'slave.Slave.Name'; 96 97 $scope.inactiveSlavesReverseSort = false; 98 $scope.inactiveSlavesOrderColumn = 'slave.Slave.Name'; 99 100 84 101 var updateStatus = function () { 85 102 // update status data 86 103 dataService.getStatus({}, function (status) { 104 var oneDayInMs = 24 * 60 * 60 * 1000; 105 var today = new Date().getTime() - oneDayInMs; 87 106 // raw status data 88 107 $scope.status = status; … … 96 115 } 97 116 // knobs 98 $scope.cpu.knobData = Math.round(status.CpuUtilizationStatus.UsedCpuUtilization); 99 var usedCores = status.CoreStatus.TotalCores - status.CoreStatus.FreeCores; 100 $scope.core.knobData = Math.round(usedCores / status.CoreStatus.TotalCores * 100); 101 var usedMemory = status.MemoryStatus.TotalMemory - status.MemoryStatus.FreeMemory; 102 $scope.memory.knobData = Math.round(usedMemory / status.MemoryStatus.TotalMemory * 100); 117 $scope.cpu.knobData = Math.round(status.CpuUtilizationStatus.ActiveCpuUtilization); 118 $scope.core.knobData = Math.round(status.CoreStatus.CalculatingCores / status.CoreStatus.ActiveCores * 100); 119 $scope.memory.knobData = Math.round(status.MemoryStatus.UsedMemory / status.MemoryStatus.ActiveMemory * 100); 103 120 // chart series 104 121 var cpuSeries = $scope.cpu.series[0].data.splice(0); 105 if (cpuSeries.length > 2) {106 cpuSeries.splice(0, 1);107 }108 122 var coreSeries = [$scope.core.series[0].data, $scope.core.series[1].data]; 109 if (coreSeries[0].length > 2) {110 coreSeries[0].splice(0, 1);111 }112 if (coreSeries[1].length > 2) {113 coreSeries[1].splice(0, 1);114 }115 123 var memorySeries = [$scope.memory.series[0].data, $scope.memory.series[1].data]; 116 if (memorySeries[0].length > 2) { 117 memorySeries[0].splice(0, 1); 118 } 119 if (memorySeries[1].length > 2) { 120 memorySeries[1].splice(0, 1); 124 if ($scope.status.Timestamp < today) { 125 if (cpuSeries.length > 2) { 126 cpuSeries.splice(0, 1); 127 } 128 if (coreSeries[0].length > 2) { 129 coreSeries[0].splice(0, 1); 130 } 131 if (coreSeries[1].length > 2) { 132 coreSeries[1].splice(0, 1); 133 } 134 if (memorySeries[0].length > 2) { 135 memorySeries[0].splice(0, 1); 136 } 137 if (memorySeries[1].length > 2) { 138 memorySeries[1].splice(0, 1); 139 } 121 140 } 122 141 cpuSeries.push([$scope.status.Timestamp, $scope.cpu.knobData]); 142 143 // charts are currently filled with old total/used data 144 // start temporary 145 var usedCores = status.CoreStatus.TotalCores - status.getCoreStatus.FreeCores; 146 var usedMemory = status.MemoryStatus.TotalMemory - status.MemoryStatus.FreeMemory; 147 // end temporary 123 148 coreSeries[0].push([$scope.status.Timestamp, status.CoreStatus.TotalCores]); 124 149 coreSeries[1].push([$scope.status.Timestamp, usedCores]); … … 149 174 for (var i = 0; i < noOfStatus; ++i) { 150 175 var curStatus = status[i]; 151 var cpuData = Math.round(curStatus.CpuUtilizationStatus.UsedCpuUtilization); 152 var usedCores = curStatus.CoreStatus.TotalCores - curStatus.CoreStatus.FreeCores; 153 var usedMemory = curStatus.MemoryStatus.TotalMemory - curStatus.MemoryStatus.FreeMemory; 176 var cpuData = Math.round(curStatus.CpuUtilizationStatus.ActiveCpuUtilization); 154 177 cpuSeries.push([curStatus.Timestamp, cpuData]); 155 coreSeries[0].push([curStatus.Timestamp, curStatus.CoreStatus. TotalCores]);156 coreSeries[1].push([curStatus.Timestamp, usedCores]);157 memorySeries[0].push([curStatus.Timestamp, curStatus.MemoryStatus. TotalMemory]);158 memorySeries[1].push([curStatus.Timestamp, usedMemory]);178 coreSeries[0].push([curStatus.Timestamp, curStatus.CoreStatus.ActiveCores]); 179 coreSeries[1].push([curStatus.Timestamp, curStatus.CoreStatus.CalculatingCores]); 180 memorySeries[0].push([curStatus.Timestamp, curStatus.MemoryStatus.ActiveMemory]); 181 memorySeries[1].push([curStatus.Timestamp, curStatus.MemoryStatus.UsedMemory]); 159 182 } 160 183 $scope.cpu.series = [{ data: cpuSeries, label: " CPU Utilization", color: "#f7921d" }]; -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Configs/BundleConfig.cs
r12428 r12435 1 using System.Collections.Generic; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System.Collections.Generic; 2 23 using System.IO; 3 using System.Linq;4 using System.Web;5 24 using System.Web.Optimization; 6 25 7 26 namespace HeuristicLab.Services.WebApp.Configs { 8 27 public class BundleConfig { 28 9 29 public static void RegisterBundles(BundleCollection bundles) { 10 30 bundles.IgnoreList.Clear(); … … 61 81 "~/WebApp/app.css" 62 82 )); 63 AddOrUpdateWebAppBundle(); 83 84 bundles.Add(new ScriptBundle("~/Bundles/WebApp/Main").Include( 85 "~/WebApp/main.js" 86 )); 87 88 bundles.Add(new ScriptBundle("~/Bundles/WebApp/Shared") 89 .IncludeDirectory("~/WebApp/shared/services", "*.js", true) 90 .IncludeDirectory("~/WebApp/shared/directives", "*.js", true) 91 .IncludeDirectory("~/WebApp/shared/menu", "*.js", true) 92 ); 64 93 } 65 94 66 public static void AddOrUpdateWebAppBundle() { 67 var jsBundle = BundleTable.Bundles.GetBundleFor("~/Bundles/WebApp/js"); 68 if (jsBundle != null) { 69 BundleTable.Bundles.Remove(jsBundle); 95 public static IEnumerable<string> GetWebAppScripts() { 96 var jsFiles = new List<string> { 97 "WebApp/helper.js", 98 "WebApp/app.js" 99 }; 100 PluginManager pluginManager = PluginManager.Instance; 101 foreach (var plugin in pluginManager.GetPlugins()) { 102 if (File.Exists(string.Format(@"{0}\{1}\{1}.js", PluginManager.PluginsDirectory, plugin.Name))) { 103 jsFiles.Add(string.Format("WebApp/plugins/{0}/{0}.js", plugin.Name)); 104 } 70 105 } 71 var jsFiles = new List<string> { 72 "~/WebApp/helper.js", 73 "~/WebApp/app.js" 74 }; 75 var directories = Directory.GetDirectories(string.Format(@"{0}WebApp\plugins", HttpRuntime.AppDomainAppPath)); 76 jsFiles.AddRange(directories.Select(Path.GetFileName).Select(directory => string.Format("~/WebApp/plugins/{0}/{0}.js", directory))); 77 jsFiles.Add("~/WebApp/main.js"); 78 jsBundle = new ScriptBundle("~/Bundles/WebApp/js"); 79 jsBundle.Include(jsFiles.ToArray()); 80 jsBundle.IncludeDirectory("~/WebApp/shared/", "*.js", true); 81 BundleTable.Bundles.Add(jsBundle); 106 jsFiles.Add("WebApp/main.js"); 107 return jsFiles; 82 108 } 83 109 } -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Configs/FilterConfig.cs
r12428 r12435 1 using System.Web.Mvc; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System.Web.Mvc; 2 23 3 24 namespace HeuristicLab.Services.WebApp.Configs { -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Configs/RouteConfig.cs
r12428 r12435 1 using System.Web.Mvc; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System.Web.Mvc; 2 23 using System.Web.Routing; 3 24 -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Configs/WebApiConfig.cs
r12428 r12435 1 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 2 22 using System.Net.Http.Formatting; 3 23 using System.Web.Http; -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Controllers/AppController.cs
r12428 r12435 21 21 22 22 using System.Web.Mvc; 23 using HeuristicLab.Services.WebApp.Configs;24 23 25 24 namespace HeuristicLab.Services.WebApp.Controllers { … … 31 30 return RedirectPermanent(Request.Url + "/"); 32 31 } 33 BundleConfig.AddOrUpdateWebAppBundle();34 32 return View("~/WebApp/shared/layout/layout.cshtml"); 35 33 } -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Controllers/AuthenticationController.cs
r12428 r12435 1 using System.Web.Http; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System.Web.Http; 2 23 using System.Web.Security; 3 24 using HeuristicLab.Services.WebApp.Controllers.DataTransfer; -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Controllers/DataTransfer/Plugin.cs
r12428 r12435 1 using System; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System; 2 23 3 24 namespace HeuristicLab.Services.WebApp.Controllers.DataTransfer { -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Controllers/DataTransfer/User.cs
r12428 r12435 1 namespace HeuristicLab.Services.WebApp.Controllers.DataTransfer { 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 namespace HeuristicLab.Services.WebApp.Controllers.DataTransfer { 2 23 public class User { 3 24 public string Username { get; set; } -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Controllers/PluginController.cs
r12428 r12435 1 using System.Collections.Generic; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System.Collections.Generic; 2 23 using System.Linq; 3 24 using System.Web.Http; 25 using HeuristicLab.Services.Hive; 4 26 using DTO = HeuristicLab.Services.WebApp.Controllers.DataTransfer; 5 27 6 28 namespace HeuristicLab.Services.WebApp.Controllers { 7 29 8 [Authorize(Roles = "Hive Administrator")]30 [Authorize(Roles = HiveRoles.Administrator)] 9 31 public class PluginController : ApiController { 10 32 … … 21 43 22 44 public bool ReloadPlugin(string name) { 23 var plugin = PluginManager.Instance.GetPlugin(name); 45 var plugin = pluginManager.GetPlugin(name); 46 if (plugin == null) 47 return false; 24 48 plugin.ReloadControllers(); 25 49 return true; -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Controllers/WebAppControllerSelector.cs
r12428 r12435 1 using System; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System; 2 23 using System.Collections.Concurrent; 3 24 using System.Collections.Generic; … … 18 39 : base(configuration) { 19 40 this.configuration = configuration; 20 pluginManager.Configuration = configuration;21 41 controllers = new ConcurrentDictionary<string, HttpControllerDescriptor>(); 22 42 LoadAppControllers(); -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Global.asax.cs
r12428 r12435 8 8 public class MvcApplication : System.Web.HttpApplication { 9 9 protected void Application_Start() { 10 var pluginManager = PluginManager.Instance; 11 pluginManager.Configuration = GlobalConfiguration.Configuration; 12 pluginManager.DiscoverPlugins(); 10 13 AreaRegistration.RegisterAllAreas(); 11 14 GlobalConfiguration.Configure(WebApiConfig.Register); -
trunk/sources/HeuristicLab.Services.WebApp/3.3/Plugin.cs
r12428 r12435 1 using System; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System; 2 23 using System.Collections.Concurrent; 3 24 using System.Collections.Generic; … … 5 26 using System.Linq; 6 27 using System.Reflection; 7 using System.Text;8 28 using System.Web.Http; 9 29 using System.Web.Http.Controllers; … … 56 76 AssemblyName = Path.GetFileName(assemblyPath); 57 77 } 58 catch (ReflectionTypeLoadException ex) { 59 StringBuilder sb = new StringBuilder(); 60 foreach (Exception exSub in ex.LoaderExceptions) { 61 sb.AppendLine(exSub.Message); 62 FileNotFoundException exFileNotFound = exSub as FileNotFoundException; 63 if (exFileNotFound != null) { 64 if (!string.IsNullOrEmpty(exFileNotFound.FusionLog)) { 65 sb.AppendLine("Fusion Log:"); 66 sb.AppendLine(exFileNotFound.FusionLog); 67 } 68 } 69 sb.AppendLine(); 70 } 71 AssemblyName = "Error loading assembly: " + sb.ToString(); 78 catch (Exception) { 79 AssemblyName = "Error loading assembly"; 72 80 Controllers.Clear(); 73 81 } -
trunk/sources/HeuristicLab.Services.WebApp/3.3/PluginManager.cs
r12428 r12435 1 using System.Collections.Concurrent; 1 #region License Information 2 /* HeuristicLab 3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 4 * 5 * This file is part of HeuristicLab. 6 * 7 * HeuristicLab is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * HeuristicLab is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 #endregion 21 22 using System.Collections.Concurrent; 2 23 using System.Collections.Generic; 3 24 using System.IO; … … 17 38 public HttpConfiguration Configuration { get; set; } 18 39 19 p rivatestring PluginsDirectory {40 public static string PluginsDirectory { 20 41 get { return string.Format(@"{0}WebApp\plugins", HttpRuntime.AppDomainAppPath); } 21 42 } … … 23 44 public PluginManager() { 24 45 plugins = new ConcurrentDictionary<string, Plugin>(); 46 var fileWatcher = new FileSystemWatcher(PluginsDirectory, "*") { 47 IncludeSubdirectories = true, 48 EnableRaisingEvents = true 49 }; 50 fileWatcher.Created += OnFilesChanged; 51 fileWatcher.Changed += OnFilesChanged; 52 fileWatcher.Deleted += OnFilesChanged; 53 fileWatcher.Renamed += OnFilesChanged; 54 } 55 56 private void OnFilesChanged(object sender, FileSystemEventArgs args) { 57 string path = args.FullPath.Remove(0, PluginsDirectory.Length + 1); 58 var pathParts = path.Split('\\'); 59 string pluginName = pathParts[0]; 60 if (pathParts.Length == 1) { 61 switch (args.ChangeType) { 62 case WatcherChangeTypes.Created: 63 GetPlugin(pluginName); 64 break; 65 66 case WatcherChangeTypes.Deleted: 67 plugins.Remove(pluginName); 68 break; 69 70 case WatcherChangeTypes.Renamed: 71 RenamedEventArgs renamedArgs = (RenamedEventArgs)args; 72 string oldPath = renamedArgs.OldFullPath.Remove(0, PluginsDirectory.Length + 1); 73 var oldPathParts = oldPath.Split('\\'); 74 string oldPluginName = oldPathParts[0]; 75 plugins.Remove(oldPluginName); 76 GetPlugin(pluginName); 77 break; 78 79 case WatcherChangeTypes.Changed: 80 Plugin plugin = LookupPlugin(pluginName); 81 if (plugin != null) { 82 plugin.ReloadControllers(); 83 } 84 break; 85 } 86 } 25 87 } 26 88 27 89 public Plugin GetPlugin(string name) { 28 Plugin plugin; 29 plugins.TryGetValue(name, out plugin); 90 Plugin plugin = LookupPlugin(name); 30 91 if (plugin == null) { 31 92 string directory = string.Format(@"{0}\{1}", PluginsDirectory, name); … … 43 104 44 105 public IEnumerable<Plugin> GetPlugins() { 45 DiscoverPlugins();46 106 return plugins.Values; 47 107 } 48 108 49 p rivatevoid DiscoverPlugins() {109 public void DiscoverPlugins() { 50 110 var pluginDirectories = Directory.GetDirectories(PluginsDirectory); 51 111 foreach (var directory in pluginDirectories) { 52 112 string pluginName = Path.GetFileName(directory); 53 Plugin plugin; 54 plugins.TryGetValue(pluginName, out plugin); 113 Plugin plugin = LookupPlugin(pluginName); 55 114 if (plugin == null) { 56 115 plugin = new Plugin { … … 63 122 } 64 123 } 124 125 private Plugin LookupPlugin(string name) { 126 Plugin plugin; 127 plugins.TryGetValue(name, out plugin); 128 return plugin; 129 } 65 130 } 66 131 } -
trunk/sources/HeuristicLab.Services.WebApp/3.3/WebApp/app.css
r12428 r12435 79 79 80 80 #menu { 81 position: absolute; 82 min-height: inherit; 83 width: 250px; 81 position: relative; 84 82 background: #FAFAFA; 85 83 display: block; 86 84 overflow: hidden; 87 border-right: 1px solid #D3D3D3; 85 z-index: 10000; 86 width: 100%; 88 87 } 89 88 … … 101 100 #view { 102 101 position: relative; 103 left: 0 px;104 margin-left: 250px;102 left: 0; 103 margin-left: 0px; 105 104 display: block; 106 105 overflow: hidden; 107 106 } 107 108 108 109 109 .view-header { … … 124 124 } 125 125 126 .navbar-header {127 width: 250px;126 .navbar-header { 127 width: 100%; 128 128 background: #3c3a39; 129 129 color: #FFFFFF; 130 float: left; 131 } 132 133 134 @media (min-width: 768px) { 135 #view { 136 margin-left: 250px; 137 } 138 139 #menu { 140 visibility: visible; 141 position: absolute; 142 width: 250px; 143 min-height: inherit; 144 border-right: 1px solid #D3D3D3; 145 z-index: 0; 146 } 147 148 .navbar-header { 149 width: 250px; 150 } 151 } 152 .container-fluid .navbar-header { 153 margin: 0; 154 padding: 0; 155 } 156 157 .navbar-nav { 158 margin: 0; 159 padding: 0; 160 } 161 162 .navbar-right { 163 float: right!important 164 } 165 166 .navbar-nav>li>a { 167 padding-top: 15px; 168 padding-bottom: 15px; 169 } 170 171 .navbar-content { 172 padding-right: 15px; 173 } 174 175 .navbar-nav > li { 176 float: left; 130 177 } 131 178 … … 140 187 .nav-sidebar { 141 188 font-size: 12px; 189 padding-bottom: 30px; 142 190 } 143 191 … … 279 327 } 280 328 329 .table-no-border>thead>tr>th, 330 .table-no-border>tbody>tr>th, 331 .table-no-border>tfoot>tr>th, 332 .table-no-border>thead>tr>td, 333 .table-no-border>tbody>tr>td, 334 .table-no-border>tfoot>tr>td, 335 .table-no-border>tbody, 336 .table-no-border>thead, 337 .table-no-border>tfoot{ 338 border-top: none !important; 339 border-bottom: none !important; 340 } 341 342 .table-auto-width { 343 width: auto !important; 344 } 345 346 .center-element { 347 margin: 0 auto; 348 } 349 350 .table-content { 351 margin-bottom: 0; 352 } 281 353 282 354 #top-navbar { … … 311 383 312 384 .navbar-default .navbar-text { 385 display: block; 313 386 color: #ffffff; 314 387 text-shadow: none !important; 315 } 316 388 margin: 0; 389 padding: 15px; 390 } 391 392 .navbar-nav { 393 float:left; 394 margin:0 395 } 396 397 .navbar-nav>li { 398 float:left 399 } 400 401 .navbar-nav>li>a { 402 padding-top:15px; 403 padding-bottom:15px 404 } 405 406 .navbar-toggle { 407 border: none !important; 408 } 409 410 .navbar-toggle:focus { 411 background-color: transparent !important; 412 } 413 414 .navbar-toggle:hover { 415 background-color: #D3D3D3 !important; 416 } 417 418 #menu .navbar-collapse { 419 padding: 0; 420 margin: 0; 421 } 317 422 318 423 .default-view-container { 319 424 padding: 30px; 320 425 } 426 427 .panel-heading a:after { 428 font-family:'Glyphicons Halflings'; 429 content:"\e114"; 430 float: right; 431 color: grey; 432 } 433 .panel-heading a.collapsed:after { 434 content:"\e080"; 435 } 436 437 .panel-heading a:focus, a:hover { 438 text-decoration: none; 439 } -
trunk/sources/HeuristicLab.Services.WebApp/3.3/WebApp/shared/directives/flot.js
r12428 r12435 6 6 link: function (scope, element, attrs) { 7 7 var chart = null, opts = scope[attrs.options]; 8 var div = null; 8 9 9 10 scope.$watchCollection(attrs.dataset, function (newData, oldData) { 10 11 if (!chart) { 11 vardiv = element.append("<div>");12 div = element.append("<div>"); 12 13 div.bind("plotselected", function (event, ranges) { 13 14 $.each(chart.getXAxes(), function (_, axis) { -
trunk/sources/HeuristicLab.Services.WebApp/3.3/WebApp/shared/layout/layout.cshtml
r12428 r12435 1 @using HeuristicLab.Services.WebApp.Configs 1 @* HeuristicLab 2 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL) 3 * 4 * This file is part of HeuristicLab. 5 * 6 * HeuristicLab is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * HeuristicLab is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 18 *@ 19 20 @using HeuristicLab.Services.WebApp.Configs 2 21 <!DOCTYPE html> 3 22 <html lang="en" ng-app="app"> … … 15 34 <![endif]--> 16 35 @Scripts.Render("~/Bundles/Vendors/js") 17 @ {18 BundleTable.EnableOptimizations = false;36 @foreach (var script in BundleConfig.GetWebAppScripts()) { 37 <script src="@script"></script> 19 38 } 20 @Scripts.Render("~/Bundles/WebApp/js") 21 @{ 22 BundleTable.EnableOptimizations = true; 23 } 39 40 @Scripts.Render("~/Bundles/WebApp/Shared") 24 41 </head> 25 <body> 26 <div id="app"> 27 <header id="toolbar" class="navbar navbar-default navbar-static-top no-border no-padding-margin" 28 ng-controller="app.menu.ctrl"> 29 <nav> 30 <div class="container-fluid"> 31 <div class="navbar-header"> 32 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#top-navbar"> 42 <body ngcloak> 43 <div id="app"> 44 <header id="toolbar" class="navbar navbar-default navbar-static-top no-border no-padding-margin" 45 ng-controller="app.menu.ctrl"> 46 <nav> 47 <div class="container-fluid"> 48 <div class="navbar-header"> 49 <div class="center-block"> 50 <a class="navbar-brand" href="#"> 51 <img src="~/WebApp/shared/images/HeuristicLab-Logo.png" style="float: left; height: 100%; margin-right: 5px;"/> 52 <span style="color: #f7921d">HeuristicLab</span> 53 </a> 54 <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#menu .navbar-collapse"> 33 55 <span class="sr-only">Toggle navigation</span> 34 56 <span class="icon-bar"></span> … … 36 58 <span class="icon-bar"></span> 37 59 </button> 38 <a class="navbar-brand" href="#">39 <img src="~/WebApp/shared/images/HeuristicLab-Logo.png" style="float: left; height: 100%; margin-left: 25px; margin-right: 5px;" />40 Heuristic<span style="color: #f7921d">Lab</span>41 </a>42 </div>43 44 <div class="collapse navbar-collapse" id="top-navbar">45 <ul class="nav navbar-nav navbar-right">46 @if (Request.IsAuthenticated) {47 <li>48 <p class="navbar-text">Hello @User.Identity.Name!</p>49 </li>50 <li>51 <a ng-href="" data-ng-click="logout()">Logout</a>52 </li>53 } else {54 <li>55 <a ng-href="#/login">Login</a>56 </li>57 }58 </ul>59 60 </div> 60 61 </div> 61 </nav>62 </header>63 62 64 <aside id="menu" ng-controller="app.menu.ctrl"> 63 <div class="navbar-content"> 64 <ul class="nav navbar-nav navbar-right"> 65 @if (Request.IsAuthenticated) 66 { 67 <li> 68 <span class="navbar-text">Hello @User.Identity.Name!</span> 69 </li> 70 <li> 71 <a ng-href="" data-ng-click="logout()">Logout</a> 72 </li> 73 } 74 else 75 { 76 <li> 77 <a ng-href="#/login" data-ng-click="hideMenu()">Login</a> 78 </li> 79 } 80 </ul> 81 </div> 82 </div> 83 </nav> 84 </header> 85 86 <aside id="menu" ng-controller="app.menu.ctrl"> 87 <div class="navbar-collapse collapse"> 65 88 <ul class="nav nav-sidebar" 66 89 ng-include="'App/LoadSharedView?directory=menu&view=menu.cshtml&dateTime=@DateTime.Now'" 67 90 ng-init="entries = menuEntries;"></ul> 68 </aside> 91 </div> 92 </aside> 69 93 70 71 72 73 94 <section id="view"> 95 <ui-view/> 96 </section> 97 </div> 74 98 </body> 75 99 </html> -
trunk/sources/HeuristicLab.Services.WebApp/3.3/WebApp/shared/menu/menu.cshtml
r12428 r12435 1 1 <li ng-repeat="section in entries" ng-class="{'category':section.isCategory === true, 'active': isActive(section.route)}"> 2 <a ng-href="{{section.route}}" ng-if="!section.isCategory"> 2 <a ng-href="{{section.route}}" ng-if="!section.isCategory" 3 data-toggle="collapse" data-target="#menu .navbar-collapse"> 3 4 <span ng-if="section.icon != ''" ng-class="section.icon" style="padding-right: 10px;"></span> 4 5 <span>{{section.name}}</span> -
trunk/sources/HeuristicLab.Services.WebApp/3.3/WebApp/shared/menu/menuCtrl.js
r12428 r12435 27 27 }); 28 28 }; 29 30 $scope.hideMenu = function() { 31 $(".navbar-collapse").collapse('hide'); 32 }; 29 33 }] 30 34 );
Note: See TracChangeset
for help on using the changeset viewer.