Map
Changes
ModelData/WebModel/WebDataManager.cs 29(+18 -11)
Tools/Tools.csproj 2(+2 -0)
Tools/Users/User.cs 17(+17 -0)
Tools/Users/UserContext.cs 46(+46 -0)
web-map/Content/Site.css 59(+44 -15)
web-map/Controllers/AccountController.cs 103(+103 -0)
web-map/Controllers/BaseController.cs 24(+24 -0)
web-map/Controllers/MapController.cs 2(+1 -1)
web-map/Models/AuthModel.cs 17(+17 -0)
web-map/Scripts/SiteScripts/Events.js 165(+86 -79)
web-map/Scripts/SiteScripts/Init.js 73(+39 -34)
web-map/Scripts/SiteScripts/Output.js 16(+10 -6)
web-map/Views/Account/Index.cshtml 11(+11 -0)
web-map/Views/Account/Login.cshtml 27(+27 -0)
web-map/Views/Map/Map.cshtml 48(+37 -11)
web-map/Views/Shared/_Layout.cshtml 51(+44 -7)
web-map/Web.config 6(+6 -0)
web-map/web-map.csproj 9(+6 -3)
Details
diff --git a/ModelData/BusinessModel/MainEntities/MapPoint.cs b/ModelData/BusinessModel/MainEntities/MapPoint.cs
index 3db420f..5a85c23 100644
--- a/ModelData/BusinessModel/MainEntities/MapPoint.cs
+++ b/ModelData/BusinessModel/MainEntities/MapPoint.cs
@@ -19,7 +19,7 @@ namespace ModelData.BusinessModel.MainEntities
/// \author Denis
/// \date 31.03.2019
- public class MapPoint : BaseAndInterface.BaseOntologyEntity
+ public class MapPoint : BaseAndInterface.BaseOntologyEntity, IComparable<MapPoint>
{
/// \property public string Position
///
@@ -39,7 +39,7 @@ namespace ModelData.BusinessModel.MainEntities
/// Установлен атрибут IndexAttrib со значением 3.
/// \returns The population.
- [IndexAttrib(3)] public string Population { set; get; }
+ [IndexAttrib(3)] public int Population { set; get; }
@@ -95,12 +95,27 @@ namespace ModelData.BusinessModel.MainEntities
["URL"] = this.URL ?? "",
["Название"] = this.Title ?? "",
["Координаты"] = this.Position ?? "",
- ["Количество населения"] = this.Population,
+ ["Количество населения"] = this.Population.ToString(),
["Тип поселения"] = Concat(this.Type),
["В составе региона"] = Concat(this.Region)
};
}
+
+
+ /// \fn public int CompareTo(MapPoint p)
+ ///
+ /// \brief Функция сравнения двух объектов
+ /// Реализует интерфейс IComparable<MapPoint> для сравнения двух объектов и выполнения сортировки массива объектов.
+ /// \warning Сортировка выполняется по убыванию!
+ /// \author Denis
+ /// \date 03.05.2019
+ ///
+ public int CompareTo(MapPoint p)
+ {
+ return (-1) * this.Population.CompareTo(p.Population);
+ }
+
}
/// @}
}
diff --git a/ModelData/BusinessModel/UnitOfWork/Context.cs b/ModelData/BusinessModel/UnitOfWork/Context.cs
index 19e98a5..8a110b0 100644
--- a/ModelData/BusinessModel/UnitOfWork/Context.cs
+++ b/ModelData/BusinessModel/UnitOfWork/Context.cs
@@ -47,7 +47,7 @@ namespace ModelData.BusinessModel.UnitOfWork
URL = str,
Title = Convert(elem["title"])/*elem["title"].ToString()*/,
Position = Convert(elem["long"]) + " " + Convert(elem["lat"]),
- Population = Convert(elem["maxPop"])
+ Population = Int32.Parse(Convert(elem["maxPop"]))
};
MapPoints.Add(mapPoint);
}
ModelData/WebModel/WebDataManager.cs 29(+18 -11)
diff --git a/ModelData/WebModel/WebDataManager.cs b/ModelData/WebModel/WebDataManager.cs
index 8d22479..f7e5ba8 100644
--- a/ModelData/WebModel/WebDataManager.cs
+++ b/ModelData/WebModel/WebDataManager.cs
@@ -41,14 +41,15 @@ namespace ModelData.WebModel
public Model GetMapPoints(int YearMin, int YearMax)
{
Model model = new Model();
-
- int maxPop = 0, pop;
+
List<string> temp = new List<string>();
BusinessDataManager businessData = BusinessDataManager.Get();
- var context = businessData.GetSettlements(YearMin, YearMax);
+ var context = businessData.GetSettlements(YearMin, YearMax);
model.arraySettlements = context.MapPoints.ToArray();
+ // Сортировка массива по убыванию количества населения
+ Array.Sort(model.arraySettlements);
foreach (var type in context.SettlementTypes)
temp.Add(type.Title);
@@ -58,18 +59,24 @@ namespace ModelData.WebModel
foreach (var region in context.Regions)
temp.Add(region.Title);
model.arrayNameRegions = temp.ToArray();
- temp.Clear();
+ temp.Clear();
foreach (var settlement in context.MapPoints)
- {
- pop = int.Parse(settlement.Population);
- if (pop > maxPop) maxPop = pop;
-
temp.Add(settlement.Title);
- }
model.arrayNameSettlements = temp.ToArray();
-
- model.InitZoom(maxPop);
+ // Инициализация уровней приближения убрана в связи с тем, что не найдено решения для оптимального отображения на карте
+ // Вместо этого будут отображаться первые 40-50-100 самых крупных поселений (значение регулируется в JS коде)
+ // Для этого в c# коде производится сортировка списка поселений по количеству населения
+
+ //int maxPop = 0;
+ //foreach (var settlement in context.MapPoints)
+ //{
+ // if (settlement.Population > maxPop)
+ // maxPop = settlement.Population;
+
+ // temp.Add(settlement.Title);
+ //}
+ //model.InitZoom(maxPop);
return model;
}
Tools/Tools.csproj 2(+2 -0)
diff --git a/Tools/Tools.csproj b/Tools/Tools.csproj
index 9dca9fe..4ff2472 100644
--- a/Tools/Tools.csproj
+++ b/Tools/Tools.csproj
@@ -76,6 +76,8 @@
<Compile Include="Interfaces\I_MySerializable.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Main\SerializeService.cs" />
+ <Compile Include="Users\User.cs" />
+ <Compile Include="Users\UserContext.cs" />
<Compile Include="Word\DocXWrite.cs" />
</ItemGroup>
<ItemGroup>
Tools/Users/User.cs 17(+17 -0)
diff --git a/Tools/Users/User.cs b/Tools/Users/User.cs
new file mode 100644
index 0000000..4d2fe16
--- /dev/null
+++ b/Tools/Users/User.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tools.Users
+{
+ public class User
+ {
+ public string Login { set; get; }
+ public string Password { set; get; }
+
+ //Пользователь уже авторизован
+ public bool IsAuth { set; get; }
+ }
+}
Tools/Users/UserContext.cs 46(+46 -0)
diff --git a/Tools/Users/UserContext.cs b/Tools/Users/UserContext.cs
new file mode 100644
index 0000000..5eb600c
--- /dev/null
+++ b/Tools/Users/UserContext.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tools.Config;
+
+namespace Tools.Users
+{
+ public class UserContext
+ {
+
+ private static UserContext context;
+
+ public static UserContext Get()
+ {
+ if (context == null)
+ context = new UserContext();
+
+ return context;
+ }
+
+ private UserContext()
+ {
+ ConfigManager configManager = ConfigManager.Get();
+ Users = new List<User>(new User[]
+ {
+
+ new User()
+ {
+ Login = configManager.ModeratorName,
+ Password = configManager.ModeratorPassword
+ }
+ });
+
+
+ }
+
+
+
+ public List<User> Users { private set; get; }
+
+
+
+ }
+}
web-map/Content/Site.css 59(+44 -15)
diff --git a/web-map/Content/Site.css b/web-map/Content/Site.css
index 79de3a0..46ca91d 100644
--- a/web-map/Content/Site.css
+++ b/web-map/Content/Site.css
@@ -25,9 +25,9 @@ textarea {
/* ---------------------------------------------------
- SIDEBAR STYLE
+ sidebar-left STYLE
----------------------------------------------------- */
-#sidebar {
+#sidebar-left {
width: 250px;
position: fixed;
top: 55px;
@@ -41,56 +41,63 @@ textarea {
overflow-y: auto;
}
-#sidebar.active {
+#sidebar-left.active {
transform: translateX(-115%);
}
-#sidebar .sidebar-header {
+#sidebar-left .sidebar-left-header {
position: sticky;
top: 0px;
padding: 15px;
background: #4d4d4d; /*#343a40;*/ /*.bg-dark*/
}
-#sidebar .sidebar-text {
+#sidebar-left .sidebar-left-text {
padding: 0.2rem 0.2rem;
}
-#sidebar-text .sidebar-text-element {
+#sidebar-left-text .sidebar-left-text-element {
margin-bottom: 0.5rem;
padding: 0.5rem 0.5rem;
background-color: #696969;
border-radius: .3rem;
}
-#sidebar p {
+/*цвет ссылки в панели*/
+.sidebar-left-text-element p a,
+.sidebar-left-text-element a {
+ color: #32CD32;
+}
+
+#sidebar-left p {
margin-bottom: 0.2rem;
}
-#sidebar ul.components {
+#sidebar-left ul.components {
padding: 20px 0;
border-bottom: 1px solid #47748b;
}
-#sidebar ul p {
+#sidebar-left ul p {
color: #fff;
padding: 10px;
}
-#sidebar ul li a {
+#sidebar-left ul li a {
padding: 10px;
font-size: 1.1em;
display: block;
}
- #sidebar ul li a:hover {
+ #sidebar-left ul li a:hover {
color: #7386D5;
background: #fff;
}
-#sidebar ul li.active > a, a[aria-expanded="true"] {
+#sidebar-left ul li.active > a, a[aria-expanded="true"] {
color: #fff;
- background: #6d7fcc;
+ /*бэкграунд меняет цвет элемента в навбаре при выборе (например при выборе дроп-даун меню)*/
+ /*background: #6d7fcc;*/
}
@@ -99,7 +106,7 @@ a[data-toggle="collapse"] {
}
a[aria-expanded="false"]::before, a[aria-expanded="true"]::before {
- content: '\e259';
+ /*content: '\e259';*/
display: block;
position: absolute;
right: 20px;
@@ -108,7 +115,7 @@ a[aria-expanded="false"]::before, a[aria-expanded="true"]::before {
}
a[aria-expanded="true"]::before {
- content: '\e260';
+ /*content: '\e260';*/
}
@@ -151,3 +158,25 @@ a.article, a.article:hover {
.hideLine [type="checkbox"]:checked ~ p {
display: block;
}
+
+
+/* ---------------------------------------------------
+ sidebar-right STYLE
+ ----------------------------------------------------- */
+#sidebar-right {
+ width: 250px;
+ position: fixed;
+ top: 55px;
+ right: 0px;
+ bottom: 30px;
+ z-index: 999;
+ background: #5a6268; /*#6c757d;*/ /*.bg-secondary*/
+ color: #fff;
+ transition: all 0.3s;
+ overflow-x: auto;
+ overflow-y: auto;
+}
+
+#sidebar-right.active {
+ transform: translateX(+115%);
+}
web-map/Controllers/AccountController.cs 103(+103 -0)
diff --git a/web-map/Controllers/AccountController.cs b/web-map/Controllers/AccountController.cs
new file mode 100644
index 0000000..05d43ca
--- /dev/null
+++ b/web-map/Controllers/AccountController.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Security;
+
+using Tools.Users;
+using web_map.Models;
+
+namespace web_map.Controllers
+{
+ public class AccountController : BaseController
+ {
+ UserContext userContext = UserContext.Get();
+
+
+ [HttpGet]
+ public ActionResult Index()
+ {
+ //if (User.Identity.IsAuthenticated)
+ // ViewBag.User = User.Identity.Name;
+ //else
+ // ViewBag.User = "NoAuth";
+
+ return View();
+ }
+
+
+ [HttpGet]
+ public ActionResult Login()
+ {
+ if (User.Identity.IsAuthenticated)
+ Redirect("/Home/Index");
+ //RedirectToAction("Index");
+
+ return View(new AuthModel());
+ }
+
+ [HttpPost]
+ [ValidateAntiForgeryToken]
+ public ActionResult Login(AuthModel model)
+ {
+ if (User.Identity.IsAuthenticated)
+ Redirect("/Home/Index");
+ //RedirectToAction("Index");
+
+ // поиск пользователя в бд
+ var user = userContext.Users.
+ FirstOrDefault(e => e.Login == model.Login
+ && e.Password == model.Password);
+
+ if (user != null)
+ {
+ if (!user.IsAuth)
+ {
+ FormsAuthentication.SetAuthCookie(user.Login, true);
+ user.IsAuth = true;
+ return Redirect("/Home/Index");
+ //RedirectToAction("Index");
+ }
+ else
+ {
+ return View(new AuthModel
+ {
+ AuthError = true,
+ ErrorMsg = "Пользователь уже авторизован"
+ });
+ }
+ }
+ else
+ {
+ return View(new AuthModel
+ {
+ AuthError = true,
+ ErrorMsg = "Пользователя с таким логином и паролем нет"
+ });
+ }
+
+ }
+
+
+ [HttpGet]
+ public ActionResult Logoff()
+ {
+
+ if (User.Identity.IsAuthenticated)
+ {
+ // поиск пользователя в бд
+ var user = userContext.Users.
+ FirstOrDefault(e => e.Login == User.Identity.Name);
+
+ if (user != null)
+ user.IsAuth = false;
+ }
+
+ FormsAuthentication.SignOut();
+ return Redirect("/Home/Index");
+ //RedirectToAction("Index");
+ }
+
+ }
+}
\ No newline at end of file
web-map/Controllers/BaseController.cs 24(+24 -0)
diff --git a/web-map/Controllers/BaseController.cs b/web-map/Controllers/BaseController.cs
new file mode 100644
index 0000000..83d35bb
--- /dev/null
+++ b/web-map/Controllers/BaseController.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+
+using System.Web.Security;
+using System.Web.Routing;
+
+namespace web_map.Controllers
+{
+ public abstract class BaseController : Controller
+ {
+
+ protected override void Initialize(RequestContext requestContext)
+ {
+ base.Initialize(requestContext);
+
+ ViewBag.isAuth = User.Identity.IsAuthenticated;
+ ViewBag.UserName = (User.Identity.IsAuthenticated) ? User.Identity.Name : "NoAuth";
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/web-map/Controllers/HomeController.cs b/web-map/Controllers/HomeController.cs
index f9e7cf0..afc3531 100644
--- a/web-map/Controllers/HomeController.cs
+++ b/web-map/Controllers/HomeController.cs
@@ -8,7 +8,7 @@ using Tools.Word;
namespace web_map.Controllers
{
- public class HomeController : Controller
+ public class HomeController : BaseController
{
//SerialazService serialazService =
// new SerialazService();
web-map/Controllers/MapController.cs 2(+1 -1)
diff --git a/web-map/Controllers/MapController.cs b/web-map/Controllers/MapController.cs
index b0c1b54..b398a78 100644
--- a/web-map/Controllers/MapController.cs
+++ b/web-map/Controllers/MapController.cs
@@ -7,7 +7,7 @@ using System.Web.Mvc;
namespace web_map.Controllers
{
- public class MapController : Controller
+ public class MapController : BaseController
{
// GET: Map
public ActionResult Map()
web-map/Models/AuthModel.cs 17(+17 -0)
diff --git a/web-map/Models/AuthModel.cs b/web-map/Models/AuthModel.cs
new file mode 100644
index 0000000..97cad2c
--- /dev/null
+++ b/web-map/Models/AuthModel.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+
+namespace web_map.Models
+{
+ public class AuthModel
+ {
+ public string Login { set; get; }
+ public string Password { set; get; }
+
+ public bool AuthError { set; get; }
+ public string ErrorMsg { set; get; }
+
+ }
+}
\ No newline at end of file
diff --git a/web-map/Scripts/SiteScripts/AjaxQuery.js b/web-map/Scripts/SiteScripts/AjaxQuery.js
index c971e0d..48e8f6a 100644
--- a/web-map/Scripts/SiteScripts/AjaxQuery.js
+++ b/web-map/Scripts/SiteScripts/AjaxQuery.js
@@ -37,16 +37,16 @@ function GetAllPoints(YearMin, YearMax) {
},
success: function (data) {
// Заполнить массивы из полученного результата
- FillDataArrays(data);
- // Выбрать, какие именно данные нужно отобразить
+ // Заполнить коллекцию геообъектами
+ //
// Затем:
- // Загрузить получившийся массив в коллекцию
+ // Нужно ли делать выборку
// |
// |
// | Выгрузить коллекцию на карту
// | |
// | |
- SelectDataFromArrays(true, true);
+ FillDataArrays(data, true, true);
},
error: function (response) {
web-map/Scripts/SiteScripts/Events.js 165(+86 -79)
diff --git a/web-map/Scripts/SiteScripts/Events.js b/web-map/Scripts/SiteScripts/Events.js
index 957b959..2161e9c 100644
--- a/web-map/Scripts/SiteScripts/Events.js
+++ b/web-map/Scripts/SiteScripts/Events.js
@@ -2,99 +2,76 @@
function SliderOnFinishMoving(data) {
CurrentMinYear = data.min;
CurrentMaxYear = data.max;
- console.log(CurrentMinYear + " " + CurrentMaxYear);
GetAllPoints(CurrentMinYear, CurrentMaxYear);
}
+function OnFindNameUsing(name) {
+ // Добавить в коллекцию, чтобы гарантировать что данный объект появится на карте
+ Collections.FindName = name;
+ // Найти метку в коллекции всех меток
+ var placemark = Collections.AllGeoObjects.search('options.Name = "' + name + '"').get(0);
+ // Установить новый цвет
+ placemark.options.set('preset', 'islands#greenStretchyIcon');
+ // Отцентрировать карту и приблизить
+ Map.setCenter(placemark.geometry.getCoordinates(), 13);
+ // Через 5 секунд вернуть обратно прежний цвет
+ setTimeout(changePlacemarkPreset, 5000, placemark, 'islands#redStretchyIcon');
+}
+
+function changePlacemarkPreset(placemark, preset) {
+ placemark.options.set('preset', preset);
+}
+
// Заполнение массивов из исходного (response.data)
// В соответствии с параметрами поселения
-function FillDataArrays(fromData) {
+function FillDataArrays(fromData, isNeedSelect = false, isNeedPlaceCollection = false) {
+
+ Collections.AllGeoObjects.removeFromMap(Map);
+
Collections.All = new Array();
+ Collections.AllGeoObjects = new ymaps.geoQuery();
Collections.SettlementTypes = new Array();
Collections.Regions = new Array();
- Collections.Zoom_8 = new Array();
- Collections.Zoom_9 = new Array();
- Collections.Zoom_10 = new Array();
- Collections.Zoom_11 = new Array();
- Collections.Zoom_12 = new Array();
- Collections.Zoom_13 = new Array();
- Collections.Zoom_14 = new Array();
- Collections.Zoom_15 = new Array();
- Collections.Zoom_16 = new Array();
- Collections.Zoom_17 = new Array();
- Collections.Zoom_18 = new Array();
- Collections.Zoom_19 = new Array();
Collections.Names = new Array();
+ Collections.FindName = '';
+ console.log('Количество загруженных поселений ' + fromData.arraySettlements.length);
+
Collections.Names = fromData.arrayNameSettlements;
Collections.SettlementTypes = fromData.arrayNameTypes;
- Collections.Regions = fromData.arrayNameRegions;
-
- console.log(fromData.arraySettlements.length);
-
- fromData.arraySettlements.forEach(function (element)
- {
- //Collections.All.push(element); // В массив All идут все данные
- var pop = Number.parseInt(element.Population); // Получить числовое представления для сравнения с ключом константы
- // Для каждой константы (пара ключ-значение, где
- // ключ = имя массива, в который нужно добавить поселение
- // значение = минимальное количество населения для попадания в массив
- // )
- // Выполнить сравнение количества населения и, если удовлетворяет условию, внести поселение в массив
- for (var key in fromData.ZoomLevel)
- {
- var value = fromData.ZoomLevel[key];
- if (pop > value)
- Collections[key].push(element);
- }
- });
-
+ Collections.Regions = fromData.arrayNameRegions;
AutoCompleteInit(Collections.Names);
-}
-function OnFindNameUsing(name)
-{
- console.log(name);
+ Collections.All = fromData.arraySettlements;
+ LoadCollection(fromData.arraySettlements, isNeedSelect, isNeedPlaceCollection);
}
+// Функция заполнения Яндекс-коллекций Яндекс-объектами из JSON массива
+function LoadCollection(fromData, isNeedSelect = false, isNeedPlaceCollection = false) {
+ fromData.forEach(function (element) {
+ Collections.AllGeoObjects = Collections.AllGeoObjects.add(CreateYandexPlacemark(element)); // Добавление
+ });
+ if (isNeedSelect)
+ SelectDataFromArrays(isNeedPlaceCollection);
+}
// Согласно текущим установленным фильтрам собрать нужный массив данных
-function SelectDataFromArrays(isNeedLoadCollection = false, isNeedPlaceCollection = false) {
- var ResultDataArray = new Array();
-
- switch (CurrentZoom) {
- case 8: { ResultDataArray = Collections.Zoom_8; break; }
- case 9: { ResultDataArray = Collections.Zoom_9; break; }
- case 10: { ResultDataArray = Collections.Zoom_10; break; }
- case 11: { ResultDataArray = Collections.Zoom_11; break; }
- case 12: { ResultDataArray = Collections.Zoom_12; break; }
- case 13: { ResultDataArray = Collections.Zoom_13; break; }
- case 14: { ResultDataArray = Collections.Zoom_14; break; }
- case 15: { ResultDataArray = Collections.Zoom_15; break; }
- case 16: { ResultDataArray = Collections.Zoom_16; break; }
- case 17: { ResultDataArray = Collections.Zoom_17; break; }
- case 18: { ResultDataArray = Collections.Zoom_18; break; }
- case 19: { ResultDataArray = Collections.Zoom_19; break; }
- default: ResultDataArray = new Array()/*Collections.All*/;
- }
-
- if (isNeedLoadCollection)
- LoadCollection(ResultDataArray, isNeedPlaceCollection);
+function SelectDataFromArrays(isNeedPlaceCollection = false) {
+ var ResultDataArray = new Array();
+
+ var CollectionVisible = Collections.AllGeoObjects.searchInside(Map).slice(0, Collections.VisibleCount).addToMap(Map);
+ // Оставшиеся объекты будем удалять с карты.
+ Collections.AllGeoObjects.remove(CollectionVisible).removeFromMap(Map).getLength();
+
+ //for (var i = 0; i < Collections.All.length && i < Collections.VisibleCount; i++) {
+ // ResultDataArray.push(Collections.All[i]);
+ //}
+
+ //if (isNeedPlaceCollection)
+ // PlaceFromCollection(geo_query);
return ResultDataArray;
}
-// Функция заполнения Яндекс-коллекций Яндекс-объектами из JSON массива
-function LoadCollection(fromData, bool = false)
-{
- // Очистка коллекции от старых элементов. Параметры остаются прежними
- CollectionVisible.removeAll();
- fromData.forEach(function (element)
- {
- CollectionVisible.add(CreateYandexPlacemark(element)); // Добавление
- });
- if (bool)
- PlaceFromCollection();
-}
// Функция создания Яндекс-объекта из одного элемента JSON массива
function CreateYandexPlacemark(fromElement) {
@@ -103,34 +80,38 @@ function CreateYandexPlacemark(fromElement) {
{
iconContent: fromElement.Title, // Содержимое названия
hintContent: fromElement.Position// Содержимое подписи при наведении
+ },
+ {
+ preset: 'islands#redStretchyIcon'
}
);
//Добавить свойство - Имя поселения
placemark.options.set('Name', fromElement.Title);
placemark.options.set('URL', fromElement.URL);
+ placemark.options.set('Population', fromElement.Population);
+ placemark.options.set('Types', fromElement.Type);
+ placemark.options.set('Regions', fromElement.Region);
// Переопределяем стадартный обработчик нажатия
placemark.events.add('click', function (e) {
e.preventDefault(); // Запрещаем стандартный обработчик
- var targetName = e.get('target').options.get('Name');
var targetURL = e.get('target').options.get('URL');
// Вызов запроса на получение данных о поселении
GetInfoAboutSettlement(targetURL, PrintInfoAboutSettlement);
-
// Показать боковую панель
- if ($('#sidebar, #content').hasClass('active')) {
+ if ($('#sidebar-left, #content').hasClass('active')) {
// Панель скрыта. Должна выехать
- $('#sidebar, #content').removeClass('active');
+ $('#sidebar-left, #content').removeClass('active');
$('.collapse.in').toggleClass('in');
$('a[aria-expanded=true]').attr('aria-expanded', 'false');
}
else
// Панель есть. Выбор, нужно ли её скрывать
- if (targetName == document.getElementById('sidebar-header').getElementsByTagName('*')[0].innerHTML) {
- $('#sidebar, #content').addClass('active');
+ if (targetURL == document.getElementById('settlement-url').innerHTML) {
+ $('#sidebar-left, #content').addClass('active');
$('.collapse.in').toggleClass('in');
$('a[aria-expanded=true]').attr('aria-expanded', 'false');
}
@@ -138,4 +119,30 @@ function CreateYandexPlacemark(fromElement) {
});
return placemark;
-}
\ No newline at end of file
+}
+
+
+// функция динамической сортировки
+function compareValues(key, order = 'asc') {
+ return function (a, b) {
+ if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) {
+ // свойства нет ни в одном из объектов
+ return 0;
+ }
+
+ const varA = (typeof a[key] === 'string') ?
+ a[key].toUpperCase() : a[key];
+ const varB = (typeof b[key] === 'string') ?
+ b[key].toUpperCase() : b[key];
+
+ let comparison = 0;
+ if (varA > varB) {
+ comparison = 1;
+ } else if (varA < varB) {
+ comparison = -1;
+ }
+ return (
+ (order == 'desc') ? (comparison * -1) : comparison
+ );
+ };
+}
\ No newline at end of file
web-map/Scripts/SiteScripts/Init.js 73(+39 -34)
diff --git a/web-map/Scripts/SiteScripts/Init.js b/web-map/Scripts/SiteScripts/Init.js
index 596ec21..eb4cf0f 100644
--- a/web-map/Scripts/SiteScripts/Init.js
+++ b/web-map/Scripts/SiteScripts/Init.js
@@ -9,7 +9,6 @@ function MapInit()
}
var Collections;
-var CollectionVisible;
var Map;
var CurrentZoom;
@@ -42,12 +41,20 @@ function YandexMapInit()
// Будем отслеживать зум карты при смене видимых границ (движение карты и смена zoom)
Map.events.add('boundschange', function (event)
{
- CurrentZoom = event.get('newZoom');
- if (CurrentZoom != event.get('oldZoom'))
- {
- //console.log(event.get('oldZoom') + " " + CurrentZoom);
- SelectDataFromArrays(true, true);
- }
+ // фильтрация поселений в принципе при движении по карте
+
+ // Выгрузить коллекцию на карту
+ // |
+ // |
+ SelectDataFromArrays(true);
+
+ // фильтрация поселений при зуммировании
+ //CurrentZoom = event.get('newZoom');
+ //if (CurrentZoom != event.get('oldZoom'))
+ //{
+ // //console.log(event.get('oldZoom') + " " + CurrentZoom);
+ // SelectDataFromArrays(true, true);
+ //}
});
// Загрузим регионы.
@@ -153,12 +160,31 @@ function SliderInit() {
OnFindNameUsing(resultName);
});
- // Обработчик кнопки скорытия боковой панели
- $('#sidebar-close').bind('click', function () {
- $('#sidebar, #content').addClass('active');
+ // Обработчик кнопки сокрытия левой боковой панели
+ $('#sidebar-left-close').bind('click', function () {
+ $('#sidebar-left, #content').addClass('active');
$('.collapse.in').toggleClass('in');
$('a[aria-expanded=true]').attr('aria-expanded', 'false');
});
+
+ // Кнопка сокрытия правой боковой панели
+ $('#sidebar-right-export').bind('click', OpenCloseRightPanel);
+
+}
+
+// Обработчик кнопки сокрытия правой боковой панели
+function OpenCloseRightPanel() {
+ if ($('#sidebar-right, #content').hasClass('active')) {
+ // Панель скрыта. Должна выехать
+ $('#sidebar-right, #content').removeClass('active');
+ $('.collapse.in').toggleClass('in');
+ $('a[aria-expanded=true]').attr('aria-expanded', 'false');
+ }
+ else {
+ $('#sidebar-right, #content').addClass('active');
+ $('.collapse.in').toggleClass('in');
+ $('a[aria-expanded=true]').attr('aria-expanded', 'false');
+ }
}
function AutoCompleteInit(data) {
@@ -174,11 +200,6 @@ function AutoCompleteInit(data) {
})
response(results.slice(0, 10));
},
- //source: function (request, response) {
- // var results = $.ui.autocomplete.filter(data, request.term);
-
- // response(results.slice(0, 10));
- //},
minLength: 2,
delay: 300,
select: function(event, ui) {
@@ -194,27 +215,11 @@ function CollectionsInit() {
Collections = new Object();
Collections.All = new Array();
+ Collections.AllGeoObjects = new ymaps.geoQuery();
Collections.SettlementTypes = new Array();
Collections.Regions = new Array();
- Collections.Zoom_8 = new Array();
- Collections.Zoom_9 = new Array();
- Collections.Zoom_10 = new Array();
- Collections.Zoom_11 = new Array();
- Collections.Zoom_12 = new Array();
- Collections.Zoom_13 = new Array();
- Collections.Zoom_14 = new Array();
- Collections.Zoom_15 = new Array();
- Collections.Zoom_16 = new Array();
- Collections.Zoom_17 = new Array();
- Collections.Zoom_18 = new Array();
- Collections.Zoom_19 = new Array();
- Collections.FindName = new Array();
+ Collections.FindName = '';
+ Collections.VisibleCount = 50;
Collections.Names = new Array();
Collections.Export = new Array();
- // Коллекция для отражения данных на карте.
- CollectionVisible = new ymaps.GeoObjectCollection({},
- {
- // Параметр коллекции всех элементов, отображающий название в красной рамке
- preset: 'islands#redStretchyIcon'
- });
}
\ No newline at end of file
web-map/Scripts/SiteScripts/Output.js 16(+10 -6)
diff --git a/web-map/Scripts/SiteScripts/Output.js b/web-map/Scripts/SiteScripts/Output.js
index f2b9377..935e892 100644
--- a/web-map/Scripts/SiteScripts/Output.js
+++ b/web-map/Scripts/SiteScripts/Output.js
@@ -4,10 +4,11 @@ function PrintInfoAboutSettlement(info)
// ВНИМАНИЕ! я никудышный верстальщик, поэтому делаю как умею. никогда этому не учился, и никто меня не учил
document.getElementById('settlement-title').innerHTML = info.Title;
+ document.getElementById('settlement-url').innerHTML = info.URL;
//jumbotron
- var text = '<div class="sidebar-text-element">';
+ var text = '<div class="sidebar-left-text-element">';
text += '<p>' + 'Координаты: ' + info.Coordinate.Lat + ' ' + info.Coordinate.Long + '</p>';
if (info.Founder != null)
text += '<p>' + 'Основатель: ' + info.Founder + '</p>';
@@ -15,16 +16,18 @@ function PrintInfoAboutSettlement(info)
if (info.Legend != null)
{
//text += '<p>' + 'Легенда:</p>';
- text += '<div class="hideLine"><label for="hideLine1">Легенда: [показать]</label><input type="checkbox" id="hideLine1"/>';
+ // тут часть текста ("показать") выделяется другим цветом
+ text += '<div class="hideLine"><label for="hideLine1">Легенда: <span style="color: #32CD32">[показать]</span></label><input type="checkbox" id="hideLine1"/>';
text += '<p class="content">' + info.Legend + '</p></div>';
}
if (info.hasBeginning != null)
text += '<p>' + 'Время основания: ' + info.hasBeginning + '</p>';
- text += '</div>';
+ text += '</div>';
+ text += '<hr style="border: none; background-color: #32CD32; color: #32CD32; height: 2px;">';
if (info.EditedSettlements != null)
info.EditedSettlements.forEach(function (element) {
- text += '<div class="sidebar-text-element">';
+ text += '<div class="sidebar-left-text-element">';
if (element.PopulationAll != null)
text += '<p>' + 'Количество населения: ' + element.PopulationAll + '</p>';
@@ -48,12 +51,13 @@ function PrintInfoAboutSettlement(info)
text += '</div>';
});
- document.getElementById('sidebar-text').innerHTML = text;
+ document.getElementById('sidebar-left-text').innerHTML = text;
}
// Функция выгружает все гео-объекты из данной коллекции на карту
function PlaceFromCollection() {
- Map.geoObjects.add(CollectionVisible);
+ CollectionVisible.addToMap(Map);
+ //Map.geoObjects.add(CollectionVisible);
//var arr = [];
//var i = 0;
web-map/Views/Account/Index.cshtml 11(+11 -0)
diff --git a/web-map/Views/Account/Index.cshtml b/web-map/Views/Account/Index.cshtml
new file mode 100644
index 0000000..540d01a
--- /dev/null
+++ b/web-map/Views/Account/Index.cshtml
@@ -0,0 +1,11 @@
+@{
+ ViewBag.Title = "Index";
+}
+
+<h3>Index</h3>
+
+<p>Login: @ViewBag.UserName;</p>
+<p>тут можно будет изменить пароль</p>
+
+
+
web-map/Views/Account/Login.cshtml 27(+27 -0)
diff --git a/web-map/Views/Account/Login.cshtml b/web-map/Views/Account/Login.cshtml
new file mode 100644
index 0000000..4b1ae16
--- /dev/null
+++ b/web-map/Views/Account/Login.cshtml
@@ -0,0 +1,27 @@
+@model web_map.Models.AuthModel
+
+@{
+ ViewBag.Title = "Login";
+}
+
+
+<form class="px-4 py-4" action="/Account/Login" method="post">
+
+ @if (Model.AuthError)
+ {
+ <div class="control-group error">
+ <span class="text-danger"><b>@Model.ErrorMsg</b></span>
+ </div>
+ }
+ @Html.AntiForgeryToken()
+ @Html.ValidationSummary(true)
+ <div class="form-group">
+ <label for="Login"><b>Login</b></label>
+ <input type="text" class="form-control" id="Login" name="Login" placeholder="Ваш логин" value="">
+ </div>
+ <div class="form-group">
+ <label for="Password"><b>Password</b></label>
+ <input type="password" class="form-control" id="Password" name="Password" placeholder="Ваш пароль" value="">
+ </div>
+ <button type="submit" class="btn btn-secondary">Вход</button>
+</form>
\ No newline at end of file
web-map/Views/Map/Map.cshtml 48(+37 -11)
diff --git a/web-map/Views/Map/Map.cshtml b/web-map/Views/Map/Map.cshtml
index 2ac0702..f6a2cbd 100644
--- a/web-map/Views/Map/Map.cshtml
+++ b/web-map/Views/Map/Map.cshtml
@@ -3,27 +3,53 @@
}
<div class="wrapper">
- <!-- боковая панель -->
- <nav id="sidebar" class="active rounded-right">
- <div id="sidebar-header" class="sidebar-header display-3 rounded-right">
+ <!-- боковая левая панель -->
+ <nav id="sidebar-left" class="active rounded-right">
+ <div id="sidebar-left-header" class="sidebar-left-header display-3 rounded-right">
<h2 id="settlement-title" class="text-center"></h2>
+ <label id="settlement-url" hidden>111111</label>
<div class="d-flex justify-content-center btn-group w-100" role="group">
- <button id="sidebar-close" class="btn btn-secondary" type="button">Скрыть<br>панель</button>
+ <button id="sidebar-left-close" class="btn btn-secondary" type="button">Скрыть<br>панель</button>
<button id="add-to-export-group" class="btn btn-secondary" type="button">Добавить<br>в экспорт</button>
</div>
</div>
- <div id="sidebar-text" class="sidebar-text">
+ <div id="sidebar-left-text" class="sidebar-left-text">
</div>
</nav>
</div>
-<div class="input-group mt-3 mb-2">
- <span class="input-group-btn">
- <button id="buttonSearch" class="btn btn-secondary" type="button">Найти</button>
- </span>
- <input id="inputName" type="text" class="form-control" placeholder="Введите название">
+<div class="wrapper">
+ <!-- боковая правая панель -->
+ <nav id="sidebar-right" class="active rounded-right">
+ @*<div id="sidebar-right-header" class="sidebar-right-header display-3 rounded-right">
+ <h2 id="settlement-title" class="text-center"></h2>
+ <label id="settlement-url" hidden>111111</label>
+ <div class="d-flex justify-content-center btn-group w-100" role="group">
+ <button id="sidebar-right-close" class="btn btn-secondary" type="button">Скрыть<br>панель</button>
+ <button id="add-to-export-group" class="btn btn-secondary" type="button">Добавить<br>в экспорт</button>
+ </div>
+ </div>
+ <div id="sidebar-right-text" class="sidebar-right-text">
+ </div>*@
+ <h2>тут что-то есть</h2>
+ </nav>
</div>
+<div class="row">
+ <div class="input-group mt-3 mb-2 col-md-6">
+ <span class="input-group-btn">
+ <button id="buttonSearch" class="btn btn-secondary" type="button">Найти</button>
+ </span>
+ <input id="inputName" type="text" class="form-control" placeholder="Введите название">
+ </div>
+ <div class="btn-group mt-3 mb-2 col-md-6" role="group">
+ <button id="sidebar-right-export" type="button" class="btn btn-secondary">Экспорт</button>
+ @if ((bool)ViewBag.isAuth)
+ {
+ <button id="sidebar-import-export" type="button" class="btn btn-secondary">Импорт</button>
+ }
+ </div>
+</div>
<div id="slider"></div>
<div class="input-group w-100 mb-3 mt-1">
@@ -47,4 +73,4 @@
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
<link rel="stylesheet" href="http://bootstraptema.ru/plugins/2018/irs/ion.rangeSlider.css" />
-<link rel="stylesheet" href="http://bootstraptema.ru/plugins/2018/irs/ion.rangeSlider.skin.css" />
\ No newline at end of file
+<link rel="stylesheet" href="http://bootstraptema.ru/plugins/2018/irs/ion.rangeSlider.skin.css" />
web-map/Views/Shared/_Layout.cshtml 51(+44 -7)
diff --git a/web-map/Views/Shared/_Layout.cshtml b/web-map/Views/Shared/_Layout.cshtml
index 574b37d..a1afbee 100644
--- a/web-map/Views/Shared/_Layout.cshtml
+++ b/web-map/Views/Shared/_Layout.cshtml
@@ -10,18 +10,55 @@
</head>
<body>
<nav class="navbar navbar-expand-sm navbar-dark fixed-top bg-dark">
- <div class="container">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
- <div class="navbar-collapse collapse" id="navbarSupportedContent">
- <ul class="nav navbar-nav mr-auto">
- <li class="nav-item">@Html.ActionLink("О проекте", "Index", "Home", null, new { @class = "nav-link" })</li>
- <li class="nav-item">@Html.ActionLink("Карта", "Map", "Map", null, new { @class = "nav-link" })</li>
- <li class="nav-item">@Html.ActionLink("Инструкция", "FAQ", "Home", null, new { @class = "nav-link" })</li>
+
+ <div class="collapse navbar-collapse" id="navbarSupportedContent">
+ <ul class="navbar-nav mr-auto">
+ <li class="nav-item">
+ <a class="nav-link" href="/Home">О проекте@*<span class="sr-only">(current)</span>*@</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/Map/Map">Карта</a>
+ </li>
+ <li class="nav-item">
+ <a class="nav-link" href="/Home/FAQ">Инструкция</a>
+ </li>
+ <li class="nav-item dropdown">
+ <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown1" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Аккаунт</a>
+ <div class="dropdown-menu" aria-labelledby="navbarDropdown1">
+
+ @if ((bool)ViewBag.isAuth)
+ {
+ <a class="dropdown-item" href="/Account"><b>@ViewBag.UserName</b></a>
+ <div class="dropdown-divider"></div>
+ <a class="dropdown-item" href="/Account/Logoff">Выход</a>
+ }
+ else
+ {
+ <form class="px-3 py-3" action="/Account/Login" method="post">
+ @Html.AntiForgeryToken()
+ @Html.ValidationSummary(true)
+ <div class="form-group">
+ <label for="Login"><b>Login</b></label>
+ <input type="text" class="form-control" id="Login" name="Login" placeholder="Ваш логин" value="">
+ </div>
+ <div class="form-group">
+ <label for="Password"><b>Password</b></label>
+ <input type="password" class="form-control" id="Password" name="Password" placeholder="Ваш пароль" value="">
+ </div>
+ <button type="submit" class="btn btn-secondary">Вход</button>
+ </form>
+ }
+ </div>
+ </li>
</ul>
+ @*<form class="form-inline my-2 my-lg-0">
+ <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
+ <button class="btn btn-outline-info my-2 my-sm-0" type="submit">Search</button>
+ </form>*@
</div>
- </div>
</nav>
<div class="container body-content">
@RenderBody()
web-map/Web.config 6(+6 -0)
diff --git a/web-map/Web.config b/web-map/Web.config
index 0d45d2a..3d3854b 100644
--- a/web-map/Web.config
+++ b/web-map/Web.config
@@ -25,6 +25,12 @@
<add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" />
<add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" />
</httpModules>
+
+ <!--Auth -->
+ <authentication mode="Forms">
+ <forms name="AuthCookies" timeout="120" loginUrl="~/Account/Login" />
+ </authentication>
+
</system.web>
<system.webServer>
<modules>
web-map/web-map.csproj 9(+6 -3)
diff --git a/web-map/web-map.csproj b/web-map/web-map.csproj
index c2f92bd..b986cad 100644
--- a/web-map/web-map.csproj
+++ b/web-map/web-map.csproj
@@ -162,12 +162,15 @@
<Compile Include="App_Start\FilterConfig.cs" />
<Compile Include="App_Start\RouteConfig.cs" />
<Compile Include="App_Start\WebApiConfig.cs" />
+ <Compile Include="Controllers\AccountController.cs" />
+ <Compile Include="Controllers\BaseController.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Controllers\MapAPIController.cs" />
<Compile Include="Controllers\MapController.cs" />
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
+ <Compile Include="Models\AuthModel.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
@@ -184,7 +187,6 @@
<Content Include="Content\jquery-ui\jquery-ui.structure.min.css" />
<Content Include="Content\jquery-ui\jquery-ui.theme.css" />
<Content Include="Content\jquery-ui\jquery-ui.theme.min.css" />
- <Content Include="Content\bootstrap-slider.min.css" />
<Content Include="favicon.ico" />
<Content Include="Global.asax" />
<Content Include="Content\Site.css" />
@@ -199,7 +201,6 @@
<Content Include="Content\bootstrap-grid.css.map" />
<None Include="packages.config" />
<None Include="Properties\PublishProfiles\FolderProfile.pubxml" />
- <Content Include="Scripts\bootstrap-slider.min.js" />
<Content Include="Scripts\bootstrap.bundle.js" />
<Content Include="Scripts\bootstrap.bundle.min.js" />
<Content Include="Scripts\bootstrap.js" />
@@ -267,10 +268,12 @@
<Content Include="Scripts\popper.js.map" />
<Content Include="Scripts\popper-utils.min.js.map" />
<Content Include="Scripts\popper-utils.js.map" />
+ <Content Include="Views\Account\Index.cshtml" />
+ <Content Include="Views\Account\Login.cshtml" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
- <Folder Include="Models\" />
+ <Folder Include="Views\Base\" />
<Folder Include="Views\MapAPI\" />
</ItemGroup>
<ItemGroup>