Геодб

This commit is contained in:
n1rwana 2023-08-02 00:42:03 +03:00
parent a2384cc231
commit 8e7ed7c503
43 changed files with 5275 additions and 14 deletions

View file

@ -0,0 +1,67 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\GeodbCountries;
use openvk\Web\Models\Repositories\GeodbLogs;
use openvk\Web\Models\Repositories\Users;
use openvk\Web\Models\RowModel;
class GeodbCity extends RowModel
{
protected $tableName = "geodb_cities";
function getId(): int
{
return (int) $this->getRecord()->id;
}
function getCountry(): GeodbCountry
{
return (new GeodbCountries)->get($this->getRecord()->country);
}
function getName(): string
{
return $this->getRecord()->name;
}
function getNativeName(): ?string
{
return $this->getRecord()->native_name;
}
function getCanonicalName(): string
{
return $this->getNativeName() ?? $this->getName();
}
function getSimplified(): array
{
return [
"id" => $this->getId(),
"name" => $this->getName(),
"native_name" => $this->getNativeName()
];
}
function getRequestSender(): ?User
{
return (new Users)->get((int) $this->getRecord()->is_request);
}
function save(User $user, $table): void
{
if(is_null($this->record)) {
$this->record = $table->insert($this->changes);
(new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
} else if($this->deleted) {
(new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
$this->record = $table->insert((array) $this->record);
} else {
(new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
$table->get($this->record->id)->update($this->changes);
$this->record = $table->get($this->record->id);
}
$this->changes = [];
}
}

View file

@ -0,0 +1,114 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\GeodbCities;
use openvk\Web\Models\Repositories\GeodbEducation;
use openvk\Web\Models\Repositories\GeodbLogs;
use openvk\Web\Models\Repositories\GeodbRights;
use openvk\Web\Models\RowModel;
class GeodbCountry extends RowModel
{
protected $tableName = "geodb_countries";
function getId(): int
{
return (int) $this->getRecord()->id;
}
function getCode(): string
{
return $this->getRecord()->code;
}
function getFlagURL(): string
{
return "/assets/packages/static/openvk/img/flags/" . $this->getRecord()->flag . ".gif";
}
function getName(): string
{
return $this->getRecord()->name;
}
function getNativeName(): ?string
{
return $this->getRecord()->native_name;
}
function getCanonicalName(): string
{
return $this->getNativeName() ?? $this->getName();
}
function getEditors(): \Traversable
{
return (new GeodbRights)->getList(NULL, $this->getId());
}
function getUserRights(int $user_id): ?GeodbEditor
{
return (new GeodbRights)->getCountryPermission($user_id, $this->getId());
}
function isUserCanEditEducation(int $user_id): bool
{
$rights = $this->getUserRights($user_id);
if (!$rights) return false;
return $rights->canEditEducation();
}
function isUserCanEditCities(int $user_id): bool
{
$rights = $this->getUserRights($user_id);
if (!$rights) return false;
return $rights->canEditCities();
}
function getSimplified(): array
{
return [
"id" => $this->getId(),
"name" => $this->getName(),
"native_name" => $this->getNativeName()
];
}
function getCitiesCount(): int
{
return count(iterator_to_array((new GeodbCities)->getList($this->getId())));
}
function getSchoolsCount(): int
{
return count(iterator_to_array((new GeodbEducation)->getSchools($this->getId())));
}
function getUniversitiesCount(): int
{
return count(iterator_to_array((new GeodbEducation)->getUniversities($this->getId())));
}
function getFlagCode(): string
{
return $this->getRecord()->flag;
}
function save(User $user, $table, ?bool $new = false): void
{
if(is_null($this->record)) {
$this->record = $table->insert($this->changes);
(new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
} else if($this->deleted) {
(new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes, $new);
$this->record = $table->insert((array) $this->record);
} else {
(new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes, $new);
$table->get($this->record->id)->update($this->changes);
$this->record = $table->get($this->record->id);
}
$this->changes = [];
}
}

View file

@ -0,0 +1,58 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\GeodbCountries;
use openvk\Web\Models\Repositories\GeodbLogs;
use openvk\Web\Models\Repositories\Users;
use openvk\Web\Models\RowModel;
class GeodbEditor extends RowModel
{
protected $tableName = "geodb_editors";
function getId(): int
{
return (int) $this->getRecord()->id;
}
function getUser(): User
{
return (new Users)->get((int) $this->getRecord()->uid);
}
function getCountry(): ?GeodbCountry
{
return (new GeodbCountries)->get((int) $this->getRecord()->country);
}
function canEditEducation(): bool
{
return (bool) $this->getRecord()->edu;
}
function canEditCities(): bool
{
return (bool) $this->getRecord()->cities;
}
function save(User $user, $table): void
{
if(is_null($this->record)) {
$this->record = $table->insert($this->changes);
(new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
} else if($this->deleted) {
(new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
$this->record = $table->insert((array) $this->record);
} else {
(new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
$table->get($this->record->id)->update($this->changes);
$this->record = $table->get($this->record->id);
}
$this->changes = [];
}
function getName(): string
{
return $this->getUser()->getCanonicalName() . " (" . ($this->getCountry()->getCanonicalName()) . ")";
}
}

View file

@ -0,0 +1,74 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\GeodbCities;
use openvk\Web\Models\Repositories\GeodbCountries;
use openvk\Web\Models\Repositories\GeodbEducation;
use openvk\Web\Models\Repositories\GeodbLogs;
use openvk\Web\Models\Repositories\GeodbSpecializations;
use openvk\Web\Models\Repositories\Users;
use openvk\Web\Models\RowModel;
class GeodbFaculty extends RowModel
{
protected $tableName = "geodb_faculties";
function getId(): int
{
return (int) $this->getRecord()->id;
}
function getUniversity(): GeodbUniversity
{
return (new GeodbEducation)->getUniversity((int) $this->getRecord()->university);
}
function getName(): string
{
return $this->getRecord()->name;
}
function getSimplified(): array
{
return [
"id" => $this->getId(),
"name" => $this->getName()
];
}
function getSpecializations(?bool $needDeleted = false, ?bool $simplified = false): \Traversable
{
return (new GeodbSpecializations)->getList($this->getId(), $needDeleted, $simplified);
}
function getRequestSender(): ?User
{
return (new Users)->get((int) $this->getRecord()->is_request);
}
function getCountry(): ?GeodbCountry
{
return $this->getUniversity()->getCountry();
}
function getCity(): ?GeodbCity
{
return $this->getUniversity()->getCity();
}
function save(User $user, $table): void
{
if(is_null($this->record)) {
$this->record = $table->insert($this->changes);
(new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
} else if($this->deleted) {
(new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
$this->record = $table->insert((array) $this->record);
} else {
(new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
$table->get($this->record->id)->update($this->changes);
$this->record = $table->get($this->record->id);
}
$this->changes = [];
}
}

View file

@ -0,0 +1,81 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use Chandler\Database\DatabaseConnection;
use openvk\Web\Models\Repositories\GeodbCities;
use openvk\Web\Models\Repositories\GeodbCountries;
use openvk\Web\Models\Repositories\GeodbEducation;
use openvk\Web\Models\Repositories\GeodbSpecializations;
use openvk\Web\Models\Repositories\Users;
use openvk\Web\Models\RowModel;
class GeodbLog extends RowModel
{
protected $tableName = "geodb_logs";
function getId(): int
{
return (int) $this->getRecord()->id;
}
function getUser(): ?User
{
return (new Users)->get((int) $this->getRecord()->user);
}
function getObjectTable(): string
{
return $this->getRecord()->object_table;
}
function getObjectId(): int
{
return $this->getRecord()->object_id;
}
function getObject()
{
$model = $this->getRecord()->object_model;
return new $model(DatabaseConnection::i()->getContext()->table($this->getObjectTable())->get($this->getObjectId()));
}
function getType(): string
{
return ["добавил", "отредактировал", "удалил", "восстановил"][$this->getRecord()->type];
}
function getObjectType(): string
{
return [
"geodb_countries" => "страну",
"geodb_cities" => "город",
"geodb_schools" => "школу",
"geodb_universities" => "университет",
"geodb_faculties" => "факультет",
"geodb_specializations" => "специальность",
"geodb_editors" => "редактора базы",
][$this->getRecord()->object_table];
}
function getObjectName(): string
{
return in_array($this->getObjectTable(), ["geodb_cities", "geodb_countries"]) ? $this->getObject()->getNativeName() : $this->getObject()->getName();
}
function getLogsText(): string
{
return $this->getRecord()->logs_text;
}
function getObjectURL(): string
{
switch ($this->getObjectTable()) {
case "geodb_countries": return "/editdb?act=country&id=" . $this->getObjectId();
case "geodb_cities": return "/editdb?act=city&id=" . $this->getObjectId();
case "geodb_schools": return "/editdb?act=school&id=" . $this->getObjectId();
case "geodb_universities": return "/editdb?act=university&id=" . $this->getObjectId();
case "geodb_editors": return $this->getObject()->getUser()->getURL();
case "geodb_faculties" || "geodb_specializations": return "/editdb?act=university&id=" . $this->getObject()->getUniversity()->getId();
default: return "/err404.php?id=" . $this->getObjectId();
}
}
}

View file

@ -0,0 +1,62 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\GeodbCities;
use openvk\Web\Models\Repositories\GeodbCountries;
use openvk\Web\Models\Repositories\GeodbLogs;
use openvk\Web\Models\Repositories\Users;
use openvk\Web\Models\RowModel;
class GeodbSchool extends RowModel
{
protected $tableName = "geodb_schools";
function getId(): int
{
return (int) $this->getRecord()->id;
}
function getCountry(): GeodbCountry
{
return (new GeodbCountries)->get($this->getRecord()->country);
}
function getCity(): GeodbCity
{
return (new GeodbCities)->get($this->getRecord()->city);
}
function getName(): string
{
return $this->getRecord()->name;
}
function getSimplified(): array
{
return [
"id" => $this->getId(),
"name" => $this->getName()
];
}
function getRequestSender(): ?User
{
return (new Users)->get((int) $this->getRecord()->is_request);
}
function save(User $user, $table): void
{
if(is_null($this->record)) {
$this->record = $table->insert($this->changes);
(new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
} else if($this->deleted) {
(new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
$this->record = $table->insert((array) $this->record);
} else {
(new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
$table->get($this->record->id)->update($this->changes);
$this->record = $table->get($this->record->id);
}
$this->changes = [];
}
}

View file

@ -0,0 +1,71 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\GeodbCities;
use openvk\Web\Models\Repositories\GeodbCountries;
use openvk\Web\Models\Repositories\GeodbEducation;
use openvk\Web\Models\Repositories\GeodbFaculties;
use openvk\Web\Models\Repositories\GeodbLogs;
use openvk\Web\Models\Repositories\Users;
use openvk\Web\Models\RowModel;
class GeodbSpecialization extends RowModel
{
protected $tableName = "geodb_specializations";
function getId(): int
{
return $this->getRecord()->id;
}
function getName(): string
{
return $this->getRecord()->name;
}
function getFaculty(): GeodbFaculty
{
return (new GeodbFaculties)->get((int) $this->getRecord()->faculty);
}
function getUniversity(): GeodbUniversity
{
return $this->getFaculty()->getUniversity();
}
function getRequestSender(): ?User
{
return (new Users)->get((int) $this->getRecord()->is_request);
}
function getCity(): ?GeodbCity
{
return $this->getUniversity()->getCity();
}
function getCountry(): ?GeodbCountry
{
return $this->getUniversity()->getCountry();
}
function getSimplified(): array
{
return [ "id" => $this->getId(), "name" => $this->getName() ];
}
function save(User $user, $table): void
{
if(is_null($this->record)) {
$this->record = $table->insert($this->changes);
(new GeodbLogs)->create($user, $this->tableName, 0, $this->getRecord()->toArray(), $this->changes);
} else if($this->deleted) {
(new GeodbLogs)->create($user, $this->tableName, 2, $this, $this->changes);
$this->record = $table->insert((array) $this->record);
} else {
(new GeodbLogs)->create($user, $this->tableName, 1, $this, $this->changes);
$table->get($this->record->id)->update($this->changes);
$this->record = $table->get($this->record->id);
}
$this->changes = [];
}
}

View file

@ -0,0 +1,18 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Entities;
use openvk\Web\Models\Repositories\GeodbFaculties;
class GeodbUniversity extends GeodbSchool
{
protected $tableName = "geodb_universities";
function getFaculties(?bool $need_deleted = false, ?bool $simplified = false): \Traversable
{
$faculties = (new GeodbFaculties)->getList($this->getId(), $need_deleted);
foreach ($faculties as $faculty) {
$response = $faculty;
if ($simplified) $response = $response->getSimplified();
yield $response;
}
}
}

View file

@ -5,7 +5,18 @@ use openvk\Web\Themes\{Themepack, Themepacks};
use openvk\Web\Util\DateTime;
use openvk\Web\Models\RowModel;
use openvk\Web\Models\Entities\{Photo, Message, Correspondence, Gift};
use openvk\Web\Models\Repositories\{Photos, Users, Clubs, Albums, Gifts, Notifications};
use openvk\Web\Models\Repositories\{GeodbCities,
GeodbCountries,
GeodbEducation,
GeodbFaculties,
GeodbRights,
GeodbSpecializations,
Photos,
Users,
Clubs,
Albums,
Gifts,
Notifications};
use openvk\Web\Models\Exceptions\InvalidUserNameException;
use Nette\Database\Table\ActiveRow;
use Chandler\Database\DatabaseConnection;
@ -349,9 +360,31 @@ class User extends RowModel
return $this->getRecord()->fav_quote;
}
function getCity(): ?string
function getCity(?bool $for_option = false)
{
return $this->getRecord()->city;
$id = (int) $this->getRecord()->city_id;
$city = (new GeodbCities)->get($id);
if ($for_option) {
if (!$city) return null;
return ["id" => $city->getId(), "name" => $city->getName(), "native_name" => $city->getNativeName()];
} else {
if ($city && !$city->isDeleted()) return $city->getCanonicalName();
else return "DELETED";
}
}
function getCountry(?bool $for_option = false)
{
$id = (int) $this->getRecord()->country_id;
$country = (new GeodbCountries)->get($id);
if (!$country) return null;
if ($for_option) {
return ["id" => $country->getId(), "name" => $country->getName(), "native_name" => $country->getNativeName()];
} else {
return ($country->getCanonicalName() ?? "DELETED");
}
}
function getPhysicalAddress(): ?string
@ -1031,7 +1064,7 @@ class User extends RowModel
function adminNotify(string $message): bool
{
$admId = OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
$admId = (int) OPENVK_ROOT_CONF["openvk"]["preferences"]["support"]["adminAccount"];
if(!$admId)
return false;
else if(is_null($admin = (new Users)->get($admId)))
@ -1126,6 +1159,50 @@ class User extends RowModel
return $res;
}
function canEditGeodb(): bool
{
return sizeof((new GeodbRights)->getList($this->getId())) > 0 || $this->getChandlerUser()->can("write")->model("openvk\Web\Models\Entities\GeodbCountry")->whichBelongsTo(0);
}
function getSchool(): ?GeodbSchool
{
return (new GeodbEducation)->getSchool((int) $this->getRecord()->school_id);
}
function getSchoolYears(): array
{
if (!$this->getRecord()->school_years) return [NULL, NULL, NULL];
return explode("**", $this->getRecord()->school_years);
}
function getSchoolSpecialization(): ?string
{
return $this->getRecord()->school_specialization;
}
function getUniversityYears(): array
{
if (!$this->getRecord()->university_years) return [NULL, NULL, NULL];
return explode("**", $this->getRecord()->university_years);
}
function getUniversitySpecialization(): ?GeodbSpecialization
{
return (new GeodbSpecializations)->get((int) $this->getRecord()->university_specialization);
}
function getUniversity(): ?GeodbUniversity
{
return (new GeodbEducation)->getUniversity((int) $this->getRecord()->university);
}
function getUniversityFaculty(): ?GeodbFaculty
{
return (new GeodbFaculties)->get($this->getRecord()->university_faculty);
}
use Traits\TBackDrops;
use Traits\TSubscribable;

View file

@ -0,0 +1,58 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Chandler\Database\DatabaseConnection;
use Nette\Database\Table\ActiveRow;
use openvk\Web\Models\Entities\GeodbCity;
use openvk\Web\Models\Entities\User;
class GeodbCities
{
private $context;
private $cities;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->cities = $this->context->table("geodb_cities");
}
private function toGeodbCity(?ActiveRow $ar): ?GeodbCity
{
return is_null($ar) ? NULL : new GeodbCity($ar);
}
function get(int $id): ?GeodbCity
{
return $this->toGeodbCity($this->cities->get($id));
}
function getList(int $cid, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
{
$filter = ["country" => $cid];
$filter["deleted"] = $needDeleted;
foreach ($this->cities->where($filter) as $city) {
$response = new GeodbCity($city);
if ($needRequests && (!$response->getRequestSender())) continue;
if (!$needRequests && ($response->getRequestSender())) continue;
if ($simplified) $response = $response->getSimplified();
yield $response;
}
}
function find($q): ?GeodbCity
{
return $this->toGeodbCity($this->context->table("geodb_cities")->where("deleted = 0 AND is_request = 0 AND (id LIKE ? OR name LIKE ? OR native_name LIKE ?)", $q, $q, $q)->fetch());
}
function getRequestsCount(): int
{
return $this->cities->where("is_request != 0 && deleted = 0")->count();
}
function getTable()
{
return $this->cities;
}
}

View file

@ -0,0 +1,54 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Chandler\Database\DatabaseConnection;
use Nette\Database\Table\ActiveRow;
use openvk\Web\Models\Entities\GeodbCountry;
class GeodbCountries
{
private $context;
private $countries;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->countries = $this->context->table("geodb_countries");
}
private function toGeodbCountry(?ActiveRow $ar): ?GeodbCountry
{
return is_null($ar) ? NULL : new GeodbCountry($ar);
}
function get(int $id): ?GeodbCountry
{
return $this->toGeodbCountry($this->countries->get($id));
}
function getList(?bool $simplified = false, ?bool $needDeleted = false): \Traversable
{
foreach ($this->countries as $country) {
$response = new GeodbCountry($country);
if (!$needDeleted && $response->isDeleted()) continue;
if ($needDeleted && !$response->isDeleted()) continue;
if ($simplified) $response = $response->getSimplified();
yield $response;
}
}
function getByCode($code): ?GeodbCountry
{
return $this->toGeodbCountry($this->countries->where("code", $code)->fetch());
}
function find($q): ?GeodbCountry
{
return $this->toGeodbCountry($this->context->table("geodb_countries")->where("deleted = 0 AND is_request = 0 AND (id LIKE ? OR name LIKE ? OR native_name LIKE ?)", $q, $q, $q)->fetch());
}
function getTable()
{
return $this->countries;
}
}

View file

@ -0,0 +1,88 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Chandler\Database\DatabaseConnection;
use Nette\Database\Table\ActiveRow;
use openvk\Web\Models\Entities\GeodbCity;
use openvk\Web\Models\Entities\GeodbSchool;
use openvk\Web\Models\Entities\GeodbUniversity;
class GeodbEducation
{
private $context;
private $schools;
private $universities;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->schools = $this->context->table("geodb_schools");
$this->universities = $this->context->table("geodb_universities");
}
private function toGeodbSchool(?ActiveRow $ar): ?GeodbSchool
{
return is_null($ar) ? NULL : new GeodbSchool($ar);
}
private function toGeodbUniversity(?ActiveRow $ar): ?GeodbUniversity
{
return is_null($ar) ? NULL : new GeodbUniversity($ar);
}
function getSchool(int $id): ?GeodbSchool
{
return $this->toGeodbSchool($this->schools->get($id));
}
function getUniversity(int $id): ?GeodbUniversity
{
return $this->toGeodbUniversity($this->universities->get($id));
}
function getSchools(int $country_id, ?int $city_id = NULL, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
{
$filter = ["country" => $country_id];
if ($city_id) $filter["city"] = $city_id;
$filter["deleted"] = $needDeleted;
foreach ($this->schools->where($filter) as $school) {
$response = new GeodbSchool($school);
if ($needRequests && (!$response->getRequestSender())) continue;
if (!$needRequests && ($response->getRequestSender())) continue;
if ($simplified) $response = $response->getSimplified();
yield $response;
}
}
function getUniversities(int $country_id, ?int $city_id = NULL, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
{
$filter = ["country" => $country_id];
if ($city_id) $filter["city"] = $city_id;
$filter["deleted"] = $needDeleted;
foreach ($this->universities->where($filter) as $university) {
$response = new GeodbUniversity($university);
if ($needRequests && (!$response->getRequestSender())) continue;
if (!$needRequests && ($response->getRequestSender())) continue;
if ($simplified) $response = $response->getSimplified();
yield $response;
}
}
function getSchoolsRequestsCount(): int
{
return $this->schools->where("is_request != 0 && deleted = 0")->count();
}
function getUniversitiesRequestsCount(): int
{
return $this->universities->where("is_request != 0 && deleted = 0")->count();
}
function getTable(string $view) {
return ($view === "universities") ? $this->universities : $this->schools;
}
}

View file

@ -0,0 +1,54 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Chandler\Database\DatabaseConnection;
use Nette\Database\Table\ActiveRow;
use openvk\Web\Models\Entities\GeodbCity;
use openvk\Web\Models\Entities\GeodbFaculty;
use openvk\Web\Models\Entities\GeodbUniversity;
class GeodbFaculties
{
private $context;
private $faculties;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->faculties = $this->context->table("geodb_faculties");
}
private function toGeodbFaculty(?ActiveRow $ar): ?GeodbFaculty
{
return is_null($ar) ? NULL : new GeodbFaculty($ar);
}
function get(int $id): ?GeodbFaculty
{
return $this->toGeodbFaculty($this->faculties->get($id));
}
function getList(int $uid, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
{
$filter = ["university" => $uid];
$filter["deleted"] = $needDeleted;
foreach ($this->faculties->where($filter) as $city) {
$response = new GeodbFaculty($city);
if ($needRequests && (!$response->getRequestSender())) continue;
if (!$needRequests && ($response->getRequestSender())) continue;
if ($simplified) $response = $response->getSimplified();
yield $response;
}
}
function getRequestsCount(): int
{
return $this->faculties->where("is_request != 0 && deleted = 0")->count();
}
function getTable()
{
return $this->faculties;
}
}

View file

@ -0,0 +1,90 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Chandler\Database\DatabaseConnection;
use Nette\Database\Table\ActiveRow;
use openvk\Web\Models\Entities\GeodbCountry;
use openvk\Web\Models\Entities\GeodbEditor;
use openvk\Web\Models\Entities\GeodbLog;
use openvk\Web\Models\Entities\User;
class GeodbLogs
{
private $context;
private $logs;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->logs = $this->context->table("geodb_logs");
}
private function toGeodbLog(?ActiveRow $ar): ?GeodbLog
{
return is_null($ar) ? NULL : new GeodbLog($ar);
}
function get(int $id): ?GeodbLog
{
return $this->toGeodbLog($this->logs->get($id));
}
function getList(int $uid): \Traversable
{
$filter = [];
if ($uid) $filter["user"] = $uid;
foreach ($this->logs->where($filter)->order("id DESC") as $log)
yield new GeodbLog($log);
}
function create(User $user, string $table, int $type, $object, $changes): void
{
$model = "openvk\\Web\\Models\\Entities\\" . [
"geodb_countries" => "GeodbCountry",
"geodb_cities" => "GeodbCity",
"geodb_schools" => "GeodbSchool",
"geodb_universities" => "GeodbUniversity",
"geodb_faculties" => "GeodbFaculty",
"geodb_specializations" => "GeodbSpecialization",
"geodb_editors" => "GeodbEditor",
][$table];
$fields = [
"name" => "Название",
"native_name" => "Родное название",
"code" => "Код",
"flag" => "Флаг",
"country" => "Страна",
"city" => "Город",
"university" => "Университет",
"faculty" => "Факультет",
"deleted" => "Удалено",
"uid" => "ID пользователя",
"edu" => "Образование",
"cities" => "Города"
];
$fobject = (is_array($object) ? $object : $object->unwrap());
$text = "";
foreach ($fobject as $field => $value) {
if ($changes[$field] === NULL) continue;
if (in_array($field, ["id", "is_log"])) continue;
if ($changes[$field] == $value && !is_array($object)) continue;
if (is_array($object)) {
$text .= "<b>" . ($fields[$field] ?? $field) . "</b>: $value<br/>";
} else {
$text .= "<b>" . ($fields[$field] ?? $field) . "</b>: $value$changes[$field]<br/>";
}
}
$log = new GeodbLog;
$log->setUser($user->getId());
$log->setType($type);
$log->setObject_Table($table);
$log->setObject_Model($model);
$log->setObject_Id(is_array($object) ? $object["id"] : $object->getId());
$log->setLogs_Text($text);
$log->save();
}
}

View file

@ -0,0 +1,140 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Chandler\Database\DatabaseConnection;
use Nette\Database\Table\ActiveRow;
use openvk\Web\Models\Entities\GeodbCountry;
use openvk\Web\Models\Entities\GeodbEditor;
class GeodbRights
{
private $context;
private $editors;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->editors = $this->context->table("geodb_editors");
}
private function toGeodbRight(?ActiveRow $ar): ?GeodbEditor
{
return is_null($ar) ? NULL : new GeodbEditor($ar);
}
function get(int $id): ?GeodbEditor
{
return $this->toGeodbRight($this->editors->get($id));
}
function getList(?int $uid = NULL, ?int $cid = NULL, ?string $q = NULL): array
{
$filter = ["deleted" => 0];
if ($uid) $filter["uid"] = $uid;
if ($cid) $filter["country"] = $cid;
if ($uid && $cid) {
$editor = $this->toGeodbRight($this->context->table("geodb_editors")->where($filter)->fetch());
if (!$editor) return [];
return [$editor, $editor->getCountry()];
}
$users = [];
$editors = [];
$rights = $this->context->table("geodb_editors")->where($filter);
foreach ($rights as $editor) {
$editor = $this->toGeodbRight($editor);
if (in_array($editor->getUser()->getId(), $users)) {
foreach ($editors as $key => $value) {
if ($value[0]->getUser()->getId() === $editor->getUser()->getId()) {
$editors[$key][1][] = $editor->getCountry();
}
}
} else {
if ($q) {
$_editors = $editors;
foreach ($_editors as $key => $value) {
$name = trim(mb_strtolower($value[0]->getUser()->getCanonicalName()));
$name_matches = [];
preg_match('/' . $q . '/i', $name, $name_matches);
if (!str_contains($name, trim(mb_strtolower($q))) && count($name_matches) === 0)
continue;
$editors[] = [$editor, [$editor->getCountry()]];
$users[] = $editor->getUser()->getId();
}
} else {
$editors[] = [$editor, [$editor->getCountry()]];
$users[] = $editor->getUser()->getId();
}
}
}
return $editors;
}
function getUserCountriesCount(int $user): int
{
return $this->context->table("geodb_editors")->where(["uid" => $user, "deleted" => 0])->count();
}
function getUserCountries(int $user): \Traversable
{
foreach ($this->context->table("geodb_editors")->where(["uid" => $user, "deleted" => 0]) as $editor) {
$editor = new GeodbEditor($editor);
if (!$editor->getCountry()->isDeleted()) {
yield $editor->getCountry();
}
}
}
function getCountryPermission(int $user, int $country): ?GeodbEditor
{
return $this->toGeodbRight($this->context->table("geodb_editors")->where(["uid" => $user, "country" => $country, "deleted" => 0])->fetch());
}
function search(string $q): array
{
$ids = [];
$r = [];
foreach ($this->editors->where("deleted", 0) as $_editor) {
$e = (new GeodbEditor($_editor));
$u = $e->getUser();
if (in_array($u->getId(), $ids)) {
foreach ($r as $key => $value) {
if ($value[0]->getUser()->getId() === $u->getId()) {
$r[$key][1][] = $e->getCountry();
}
}
} else {
$name = trim(mb_strtolower($u->getCanonicalName()));
$name_matches = [];
preg_match('/' . $q . '/i', $name, $name_matches);
if (!str_contains($name, trim(mb_strtolower($q))) && count($name_matches) === 0) continue;
$ids[] = $u->getId();
$r[] = [$e, [$e->getCountry()]];
}
}
return $r;
}
function getRequestsCount(): int
{
return (new GeodbCities)->getRequestsCount()
+ (new GeodbEducation)->getSchoolsRequestsCount()
+ (new GeodbEducation)->getUniversitiesRequestsCount()
+ (new GeodbFaculties)->getRequestsCount()
+ (new GeodbSpecializations)->getRequestsCount();
}
function getTable()
{
return $this->editors;
}
}

View file

@ -0,0 +1,55 @@
<?php declare(strict_types=1);
namespace openvk\Web\Models\Repositories;
use Chandler\Database\DatabaseConnection;
use Nette\Database\Table\ActiveRow;
use openvk\Web\Models\Entities\GeodbCity;
use openvk\Web\Models\Entities\GeodbFaculty;
use openvk\Web\Models\Entities\GeodbSpecialization;
use openvk\Web\Models\Entities\GeodbUniversity;
class GeodbSpecializations
{
private $context;
private $specializations;
function __construct()
{
$this->context = DatabaseConnection::i()->getContext();
$this->specializations = $this->context->table("geodb_specializations");
}
private function toGeodbSpecialization(?ActiveRow $ar): ?GeodbSpecialization
{
return is_null($ar) ? NULL : new GeodbSpecialization($ar);
}
function get(int $id): ?GeodbSpecialization
{
return $this->toGeodbSpecialization($this->specializations->get($id));
}
function getList(?int $fid = NULL, ?bool $needDeleted = false, ?bool $simplified = false, ?bool $needRequests = false): \Traversable
{
$filter[($fid < 0 ? "country" : "faculty")] = ($fid < 0 ? ($fid * -1) : $fid);
$filter["deleted"] = $needDeleted;
foreach ($this->specializations->where($filter) as $specialization) {
$response = new GeodbSpecialization($specialization);
if ($needRequests && (!$response->getRequestSender())) continue;
if (!$needRequests && ($response->getRequestSender())) continue;
if ($simplified) $response = $response->getSimplified();
yield $response;
}
}
function getRequestsCount(): int
{
return $this->specializations->where("is_request != 0 && deleted = 0")->count();
}
function getTable()
{
return $this->specializations;
}
}

View file

@ -71,8 +71,13 @@ class Users
case "hometown":
$result->where("hometown LIKE ?", $paramValue);
break;
case "country":
$country = (new GeodbCountries)->find($paramValue);
if ($country) $result->where("country_id LIKE ?", $country->getId());
break;
case "city":
$result->where("city LIKE ?", $paramValue);
$country = (new GeodbCities)->find($paramValue);
if ($country) $result->where("city_id LIKE ?", $country->getId());
break;
case "maritalstatus":
$result->where("marital_status ?", $paramValue);

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@ use Chandler\Security\Authenticator;
use Latte\Engine as TemplatingEngine;
use openvk\Web\Models\Entities\IP;
use openvk\Web\Themes\Themepacks;
use openvk\Web\Models\Repositories\{IPs, Users, APITokens, Tickets};
use openvk\Web\Models\Repositories\{GeodbRights, IPs, Users, APITokens, Tickets};
use WhichBrowser;
abstract class OpenVKPresenter extends SimplePresenter
@ -261,6 +261,9 @@ abstract class OpenVKPresenter extends SimplePresenter
$this->template->ticketAnsweredCount = (new Tickets)->getTicketsCountByUserId($this->user->id, 1);
if($user->can("write")->model("openvk\Web\Models\Entities\TicketReply")->whichBelongsTo(0))
$this->template->helpdeskTicketNotAnsweredCount = (new Tickets)->getTicketCount(0);
if ($this->user->identity->canEditGeodb())
$this->template->geodbRequestsCount = (new GeodbRights)->getRequestsCount();
}
header("X-OpenVK-User-Validated: $userValidated");

View file

@ -1,7 +1,7 @@
<?php declare(strict_types=1);
namespace openvk\Web\Presenters;
use openvk\Web\Models\Entities\{User, Club};
use openvk\Web\Models\Repositories\{Users, Clubs, Posts, Comments, Videos, Applications, Notes};
use openvk\Web\Models\Repositories\{GeodbCities, Users, Clubs, Posts, Comments, Videos, Applications, Notes};
use Chandler\Database\DatabaseConnection;
final class SearchPresenter extends OpenVKPresenter
@ -68,6 +68,7 @@ final class SearchPresenter extends OpenVKPresenter
$parameters = [
"type" => $this->queryParam("type"),
"city" => $this->queryParam("city") != "" ? $this->queryParam("city") : NULL,
"country" => $this->queryParam("country") != "" ? $this->queryParam("country") : NULL,
"maritalstatus" => $this->queryParam("maritalstatus") != 0 ? $this->queryParam("maritalstatus") : NULL,
"with_photo" => $this->queryParam("with_photo"),
"status" => $this->queryParam("status") != "" ? $this->queryParam("status") : NULL,

View file

@ -3,9 +3,20 @@ namespace openvk\Web\Presenters;
use Nette\InvalidStateException;
use openvk\Web\Util\Sms;
use openvk\Web\Themes\Themepacks;
use openvk\Web\Models\Entities\{Photo, Post, EmailChangeVerification};
use openvk\Web\Models\Entities\{GeodbFaculty, Photo, Post, EmailChangeVerification};
use openvk\Web\Models\Entities\Notifications\{CoinsTransferNotification, RatingUpNotification};
use openvk\Web\Models\Repositories\{Users, Clubs, Albums, Videos, Notes, Vouchers, EmailChangeVerifications};
use openvk\Web\Models\Repositories\{GeodbCities,
GeodbCountries,
GeodbEducation,
GeodbFaculties,
GeodbSpecializations,
Users,
Clubs,
Albums,
Videos,
Notes,
Vouchers,
EmailChangeVerifications};
use openvk\Web\Models\Exceptions\InvalidUserNameException;
use openvk\Web\Util\Validator;
use Chandler\Security\Authenticator;
@ -202,6 +213,24 @@ final class UserPresenter extends OpenVKPresenter
$user->setWebsite(NULL);
else
$user->setWebsite((!parse_url($website, PHP_URL_SCHEME) ? "https://" : "") . $website);
$country_id = $this->postParam("country-id") ?? 0;
if ($country_id) {
$country = (new GeodbCountries)->get((int) $country_id);
if ($country) {
$user->setCountry_Id($country_id);
$city_id = $this->postParam("city-id") ?? 0;
if ($city_id) {
$city = (new GeodbCities)->get((int) $city_id);
if ($city) {
if ($city->getCountry()->getId() === $country->getId()) {
$user->setCity_Id($city->getId());
}
}
}
}
}
} elseif($_GET['act'] === "interests") {
$user->setInterests(empty($this->postParam("interests")) ? NULL : ovk_proc_strtr($this->postParam("interests"), 300));
$user->setFav_Music(empty($this->postParam("fav_music")) ? NULL : ovk_proc_strtr($this->postParam("fav_music"), 300));
@ -246,6 +275,51 @@ final class UserPresenter extends OpenVKPresenter
$this->returnJson([
"success" => true
]);
} elseif($_GET['act'] === "education") {
if ($this->requestParam("school-id")) {
$school = (new GeodbEducation)->getSchool((int) $this->postParam("school-id"));
if ($school) {
$user->setSchool_Id($school->getId());
}
$years = implode("**", [
((int)$this->postParam("edu_start")) ?? NULL,
((int)$this->postParam("edu_end")) ?? NULL,
((int)$this->postParam("edu_graduation")) ?? NULL,
]);
$user->setSchool_Years($years);
$user->setSchool_Specialization(mb_strlen(trim($this->postParam("edu_specialization"))) > 0 ? $this->postParam("edu_specialization") : NULL);
} else if ($this->requestParam("university-id")) {
$university = (new GeodbEducation)->getUniversity((int) $this->postParam("university-id"));
if ($university) {
$user->setUniversity($university->getId());
if ($this->postParam("faculty-id")) {
$faculty = (new GeodbFaculties)->get((int)$this->postParam("faculty-id"));
if ($faculty && ($faculty->getUniversity()->getId() === $university->getId())) {
$user->setUniversity_Faculty($faculty->getId());
if ($this->postParam("specialization-id")) {
$specialization = (new GeodbSpecializations)->get((int) $this->postParam("specialization-id"));
if ($specialization && ($specialization->getFaculty()->getId() === $faculty->getId()) && ($specialization->getUniversity()->getId() === $university->getId())) {
$user->setUniversity_Specialization($specialization->getId());
}
}
}
}
$years = implode("**", [
((int)$this->postParam("edu_university_start")) ?? NULL,
((int)$this->postParam("edu_university_end")) ?? NULL,
((int)$this->postParam("edu_university_graduation")) ?? NULL,
]);
$user->setUniversity_Years($years);
}
} else {
$this->flashFail("err", tr("error"), "Вы не выбрали школу или университет");
}
}
try {
@ -261,7 +335,7 @@ final class UserPresenter extends OpenVKPresenter
}
$this->template->mode = in_array($this->queryParam("act"), [
"main", "contacts", "interests", "avatar", "backdrop"
"main", "contacts", "education", "interests", "avatar", "backdrop"
]) ? $this->queryParam("act")
: "main";

View file

@ -201,9 +201,17 @@
{var $canAccessAdminPanel = $thisUser->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)}
{var $canAccessHelpdesk = $thisUser->getChandlerUser()->can("write")->model('openvk\Web\Models\Entities\TicketReply')->whichBelongsTo(0)}
{var $canEditGeodb = $thisUser->canEditGeodb()}
{var $menuLinksAvaiable = sizeof(OPENVK_ROOT_CONF['openvk']['preferences']['menu']['links']) > 0 && $thisUser->getLeftMenuItemStatus('links')}
<div n:if="$canAccessAdminPanel || $canAccessHelpdesk || $menuLinksAvaiable" class="menu_divider"></div>
<a href="/admin" class="link" n:if="$canAccessAdminPanel" title="{_admin} [Alt+Shift+A]" accesskey="a">{_admin}</a>
<a href="/editdb?act=requests" class="link" n:if="$canEditGeodb">
Заявки Геодб
{if $geodbRequestsCount > 0}
(<b>{$geodbRequestsCount}</b>)
{/if}
</a>
<a href="/editdb?act=countries" class="link" n:if="$canEditGeodb">Страны</a>
<a href="/support/tickets" class="link" n:if="$canAccessHelpdesk">{_helpdesk}
{if $helpdeskTicketNotAnsweredCount > 0}
(<b>{$helpdeskTicketNotAnsweredCount}</b>)

View file

@ -0,0 +1,19 @@
{extends "../@layout.xml"}
{block title}Добавить город{/block}
{block header}{include title}{/block}
{block content}
{include "./tabs.xml", mode => $mode, country => $country}
<br />
<div>
<h4><a href="/editdb?act=country&id={$country->getId()}">{$country->getCanonicalName()}</a> → Добавить город</h4>
<form id="add-country-form" method="post">
<input type="text" name="name" placeholder="Название на английском"/>
<input type="text" name="native_name" placeholder="Родное название"/>
<input type="hidden" name="hash" value="{$csrfToken}"/>
<input type="submit" value="{_create}" class="button" style="float: right;"/>
</form>
</div>
{/block}

View file

@ -0,0 +1,41 @@
{extends "../@layout.xml"}
{block title}Добавить страну{/block}
{block header}{include title}{/block}
{block content}
{include "./tabs.xml", mode => $mode, country => $country}
<br />
<div>
<h4>Добавить страну</h4>
<form id="add-country-form" method="post">
<input type="text" name="code" placeholder="Код страны" n:attr="value => $country ? $country->getCode() : ''"/>
<input type="text" name="flag" placeholder="Флаг" onInput="onCreateCountryFormFlagChanged(this)" n:attr="value => $country ? $country->getFlagCode() : ''"/>
<div>
<b>Флаг:</b> <img id="createCountryFormFlag" n:attr="src => $country ? $country->getFlagURL() : ''" />
</div>
<input type="text" name="name" placeholder="Название на английском" n:attr="value => $country ? $country->getName() : ''"/>
<input type="text" name="native_name" placeholder="Родное название" n:attr="value => $country ? $country->getNativeName() : ''"/>
<input type="hidden" name="hash" value="{$csrfToken}"/>
<input type="submit" n:attr="value => $country ? tr('save') : tr('create')" class="button" style="float: right;"/>
</form>
<script>
let check_flag_timer = 0;
function onCreateCountryFormFlagChanged(e) {
clearTimeout(check_flag_timer);
check_flag_timer = setTimeout(() => {
let image_src = "/assets/packages/static/openvk/img/flags/" + e.value + ".gif";
$.get({ url: image_src}).done((data) => {
if (data.includes("error"))
$("#createCountryFormFlag").attr("src", "/assets/packages/static/openvk/img/flags/europeanunion.gif");
else
$("#createCountryFormFlag").attr("src", image_src);
})
}, 500)
}
</script>
</div>
{/block}

View file

@ -0,0 +1,41 @@
{extends "../@layout.xml"}
{block title}{$title}{/block}
{block header}{include title}{/block}
{block content}
{include "./tabs.xml", mode => $mode, country => $country}
<br />
<div n:if="$mode === 'add_edu'">
<div>
<h4><a href="/editdb?act=country&id={$country->getId()}&edu=1{if $view === 'universities'}&view=universities{/if}">{$country->getCanonicalName()}</a> → {include title}</h4>
<form id="add-country-form" method="post">
<div id="cities-list-td-input">
<td width="120" valign="top">
<span class="nobold">Город: </span>
</td>
<td>
<input type="text" name="city" placeholder="Начните вводить название" id="city"
onInput="onChangeCityInput()"/>
</td>
</div>
<div id="cities-list-td" style="display: none !important">
<d width="120" valign="top">
<span class="nobold"></span>
</d>
<td>
<center id="cities-not-found">Ничего не найдено</center>
<select id="cities-list" name="city-id" value="1" style="display: none;">
</select>
</td>
</div>
<input type="text" name="name" placeholder="Название"/>
<input type="hidden" name="hash" value="{$csrfToken}"/>
<input type="submit" value="{_create}" class="button" style="float: right;"/>
</form>
</div>
</div>
{include "./GeodbForAdmins.js.xml", view => $view}
{/block}

View file

@ -0,0 +1,19 @@
{extends "../@layout.xml"}
{block title}Редактировать город{/block}
{block header}{include title}{/block}
{block content}
{include "./tabs.xml", mode => $mode, country => $country}
<br />
<div>
<h4><a href="/editdb?act=country&id={$country->getId()}">{$country->getCanonicalName()}</a> → {$city->getCanonicalName()}</h4>
<form id="add-country-form" method="post">
<input type="text" name="name" placeholder="Название на английском" value="{$city->getName()}"/>
<input type="text" name="native_name" placeholder="Родное название" value="{$city->getNativeName()}"/>
<input type="hidden" name="hash" value="{$csrfToken}"/>
<input type="submit" value="{_save}" class="button" style="float: right;"/>
</form>
</div>
{/block}

View file

@ -0,0 +1,63 @@
{extends "../@layout.xml"}
{block title}Страны{/block}
{block header}{include title}{/block}
{block content}
{include "./tabs.xml", mode => $mode, country => $country}
<div>
<div n:if="$can_view_deleted">
<br />
<div class="tabs">
<div n:attr="id => (!$is_deleted ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => (!$is_deleted ? 'act_tab_a' : 'ki')" href="/editdb?act=countries">Активные</a>
</div>
<div n:attr="id => ($is_deleted ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($is_deleted ? 'act_tab_a' : 'ki')" href="/editdb?act=countries&deleted=1">Удаленные</a>
</div>
</div>
<br />
</div>
<div style="margin-top: 10px;">
<div n:if="sizeof($countries) <= 0">
{include "../components/nothing.xml"}
</div>
<div n:if="sizeof($countries) > 0">
<div n:foreach="$countries as $country" style="display: flex; border-bottom: 1px solid #E8EBEE; justify-content: space-between; align-items: center;" id="country-{$country->getId()}">
<a style="cursor: pointer; flex: 1 1 0; text-align: left;" href="/editdb?act=country&id={$country->getId()}">
<h4 style="padding: 8px; border: none;">
<img src="{$country->getFlagURL()}"/>
[#{$country->getId()}] {$country->getCanonicalName()}
</h4>
</a>
<div style="flex: 1 1 0; display: flex; justify-content: space-between;">
<div style="flex: 1 1 0; text-align: center;">
<a href="/editdb?act=country&id={$country->getId()}">{tr("geodb_cities",
$country->getCitiesCount())}
</a>
</div>
<div>|</div>
<div style="flex: 1 1 0; text-align: center;">
<a href="/editdb?act=country&id={$country->getId()}&edu=1">{tr("geodb_schools",
$country->getSchoolsCount())}
</a>
</div>
<div>|</div>
<div style="flex: 1 1 0; text-align: center;">
<a href="/editdb?act=country&id={$country->getId()}&edu=1">{tr("geodb_schools",
$country->getSchoolsCount())}
</a>
</div>
</div>
<div style="flex: 1 1 0; display: flex; justify-content: flex-end; gap: 8px;">
<a n:if="!$is_deleted && $can_view_deleted" onClick="deleteCountry({$country->getId()})"><div class="icon delete-icon"/></a>
<a n:if="$is_deleted && $can_view_deleted" onClick="deleteCountry({$country->getId()}, true)"><div class="icon plus-icon"/></a>
<a n:if="!$is_deleted && $can_view_deleted" href="/editdb?act=add_country&id={$country->getId()}"><div class="icon edit-icon"/></a>
<a n:if="!$is_deleted" href="/editdb?act=requests&cid={$country->getId()}"><div class="icon list-icon" /></a>
</div>
</div>
</div>
</div>
{include "./GeodbForAdmins.js.xml", countries => $countries}
</div>
{/block}

View file

@ -0,0 +1,199 @@
{extends "../@layout.xml"}
{block title}Страна{/block}
{block header}{include title}{/block}
{block content}
{include "./tabs.xml", mode => $mode, country => $country}
<br />
<div>
<h4 style="padding: 8px;">
<a href="/editdb?act=countries">{$country->getCanonicalName()}</a>
<span id="current-city-block" style="color: inherit; font-weight: unset; {if !$city}display: none;{/if}">
<a id="current-city-name">
{if $city}{$city->getName()}{/if}
</a>
</span>
</h4>
<div>
<br />
<div class="tabs">
<div n:if="$can_edit_cities" n:attr="id => (!$is_edu ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => (!$is_edu ? 'act_tab_a' : 'ki')" href="/editdb?act=country&id={$country->getId()}">Города</a>
</div>
<div n:if="$can_edit_edu" n:attr="id => ($is_edu ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($is_edu ? 'act_tab_a' : 'ki')" href="/editdb?act=country&id={$country->getId()}&edu=1">Образование</a>
</div>
</div>
<br />
</div>
<div n:if="$is_edu">
<br />
<div class="tabs">
<div n:attr="id => ($view === 'schools' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($view === 'schools' ? 'act_tab_a' : 'ki')" href="/editdb?act=country&id={$country->getId()}&edu=1">Школы</a>
</div>
<div n:attr="id => ($view === 'universities' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($view === 'universities' ? 'act_tab_a' : 'ki')" href="/editdb?act=country&id={$country->getId()}&edu=1&view=universities">Вузы</a>
</div>
</div>
<br />
</div>
<div n:if="$can_view_deleted">
<br />
<div class="tabs">
<div n:attr="id => (!$is_deleted ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => (!$is_deleted ? 'act_tab_a' : 'ki')" href="/editdb?act=country&id={$country->getId()}{if $is_edu}&edu=1&view={$view}{/if}">Активные</a>
</div>
<div n:attr="id => ($is_deleted ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($is_deleted ? 'act_tab_a' : 'ki')" href="/editdb?act=country&id={$country->getId()}&deleted=1{if $is_edu}&edu=1&view={$view}{/if}">Удаленные</a>
</div>
</div>
<br />
</div>
<div n:if="$is_edu">
<div id="cities-list-td-input">
<td width="120" valign="top">
<span class="nobold">Город: </span>
</td>
<td>
<input type="text" name="city" placeholder="Начните вводить название" id="city"
onInput="onChangeCityInput()" {if $city}value="{$city->getCanonicalName()}"{/if}/>
</td>
</div>
<div id="cities-list-td" style="display: none">
<d width="120" valign="top">
<span class="nobold"></span>
</d>
<td>
<center id="cities-not-found">Ничего не найдено</center>
<select id="cities-list" name="city-id" value="1" onChange="onChangeCitySelect()">
{if $city}
<option value="{$city->getId()}">{$city->getNativeName()} ({$city->getName()})</option>
{/if}
</select>
</td>
</div>
</div>
<div style="margin-top: 10px;" n:if="!$is_edu">
<div n:if="sizeof($cities) <= 0">
{include "../components/nothing.xml"}
</div>
<ul n:if="sizeof($cities) > 0" style="padding-inline-start: 18px;">
<li n:foreach="$cities as $city">
<a n:if="sizeof($cities) > 0" style="cursor: pointer;" href="/editdb?act=city&id={$city->getId()}">
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE;">
<h4 style="padding: 8px; margin-bottom: 4px; border: none;">
[#{$city->getId()}] {$city->getCanonicalName()}
</h4>
<div style="display: flex; gap: 8px; align-self: center;">
<a href="/editdb?act=city&id={$city->getId()}"><div class="icon edit-icon"/></a>
<a n:if="!$is_deleted" onClick="deleteCity({$city->getId()}, {$city->getCanonicalName()})"><div class="icon delete-icon"/></a>
<a n:if="$is_deleted" onClick="restoreCity({$city->getId()}, {$city->getCanonicalName()})"><div class="icon plus-icon"/></a>
</div>
</div>
</a>
</li>
</ul>
<script>
function deleteCity(id, name) {
DelCityMsgTxt = "Вы собираетесь удалить город <b>" + name + "</b>";
MessageBox("Вы уверены?", DelCityMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=city&id=" + id + "&delete=1",
data: {
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Город удален", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
setTimeout(() => { window.location.href = "/editdb?act=country&id={$country->getId()}&deleted=1" }, 500);
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
},
fail: () => NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png")
});
}),
Function.noop
]);
}
function restoreCity(id, name) {
DelCityMsgTxt = "Вы собираетесь восстановить город <b>" + name + "</b>";
MessageBox("Вы уверены?", DelCityMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=city&id=" + id + "&restore=1",
data: {
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Город восстановлен", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
setTimeout(() => { window.location.href = "/editdb?act=country&id={$country->getId()}" }, 500);
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
},
fail: () => NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png")
});
}),
Function.noop
])
}
</script>
</div>
<div style="margin-top: 10px;" n:if="$is_edu">
<div n:if="$view === 'schools'">
<div n:if="sizeof($schools) <= 0">
{include "../components/nothing.xml"}
</div>
<ul n:if="sizeof($schools) > 0" style="padding-inline-start: 18px;" id="schools">
<li n:foreach="$schools as $school" id="school-{$school->getId()}">
<a n:if="sizeof($schools) > 0" style="cursor: pointer;" href="/editdb?act=school&id={$school->getId()}">
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE;">
<h4 style="padding: 8px; margin-bottom: 4px; border: none;">
[#{$school->getId()}] {$school->getName()}
</h4>
<div style="display: flex; gap: 8px; align-self: center;">
<a href="/editdb?act=school&id={$school->getId()}"><div class="icon edit-icon"/></a>
<a n:if="!$is_deleted" onClick="deleteSchool({$school->getId()}, {$school->getName()})"><div class="icon delete-icon"/></a>
<a n:if="$is_deleted" onClick="deleteSchool({$school->getId()}, {$school->getName()}, true)"><div class="icon plus-icon"/></a>
</div>
</div>
</a>
</li>
</ul>
</div>
<div n:if="$view === 'universities'">
<div n:if="sizeof($universities) <= 0">
{include "../components/nothing.xml"}
</div>
<ul n:if="sizeof($universities) > 0" style="padding-inline-start: 18px;" id="universities">
<li n:foreach="$universities as $university" id="university-{$university->getId()}">
<a n:if="sizeof($universities) > 0" style="cursor: pointer;" href="/editdb?act=university&id={$university->getId()}">
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE;">
<h4 style="padding: 8px; margin-bottom: 4px; border: none;">
[#{$university->getId()}] {$university->getName()}
</h4>
<div style="display: flex; gap: 8px; align-self: center;">
<a href="/editdb?act=university&id={$university->getId()}"><div class="icon edit-icon"/></a>
<a n:if="!$is_deleted" onClick="deleteUniversity({$university->getId()}, {$university->getName()})"><div class="icon delete-icon"/></a>
<a n:if="$is_deleted" onClick="deleteUniversity({$university->getId()}, {$university->getName()}, true)"><div class="icon plus-icon"/></a>
</div>
</div>
</a>
</li>
</ul>
</div>
{include "./GeodbForAdmins.js.xml", country => $country, city => $city}
</div>
</div>
{/block}

View file

@ -0,0 +1,153 @@
{extends "../@layout.xml"}
{block title}Редакторы базы{/block}
{block header}{include title}{/block}
{block content}
{include "./tabs.xml", mode => $mode, country => $country}
<div style="margin-top: 16px;">
<div style="border: 8px solid #D9E3EA;">
<center style="padding: 16px;">
<a style="border-bottom: 1px dotted;" onClick="$('#add-editor-form').toggle()">Добавить редактора базы</a>
</center>
<div id="add-editor-form" style="display: none; padding: 0 16px 16px 16px;">
<table cellspacing="7" cellpadding="0" width="60%" border="0">
<tbody>
<tr>
<td width="120" valign="top">
<b>Ссылка на страницу: </b>
</td>
<td>
<input type="text" name="link" id="new-editor-link"/>
</td>
</tr>
<tr>
<td width="120" valign="top">
<b>Страна: </b>
</td>
<td>
<select name="country" id="new-editor-country">
<option n:foreach="$countries as $country" value="{$country->getCode()}">
[{$country->getCode()}] {$country->getCanonicalName()}
</option>
</select>
</td>
</tr>
<tr>
<td width="120" valign="top">
<b>Права: </b>
</td>
<td>
<table cellspacing="0" cellpadding="0" width="100%" border="0">
<tbody>
<tr>
<td width="" valign="top" align="left">
<input type="checkbox" name="can_access_edu" value="1" id="new-editor-edu"/>
</td>
<td style="width: 100%;">
<span class="nobold">Образование</span>
</td>
</tr>
<tr>
<td width="120" valign="top" align="right">
<input type="checkbox" name="can_access_cities" value="1" id="new-editor-cities"/>
</td>
<td style="width: 100%;">
<span class="nobold">Города</span>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
</td>
<td>
<input type="hidden" name="hash" value="{$csrfToken}"/>
<button type="submit" class="button" onClick="addNewEditor()">Добавить редактора</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<br/>
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE; padding: 8px 0;">
<h4 style="border: none;">Редакторы базы</h4>
<div n:if="sizeof($editors) > 0">
<input id="searchEditors" class="sr" type="search" placeholder="Начните вводить имя редактора"/>
</div>
</div>
<div style="margin-top: 10px;" id="editors">
<div n:if="sizeof($editors) <= 0">
{include "../components/nothing.xml"}
</div>
<div n:if="sizeof($editors) > 0" n:foreach="$editors as $editor" id="{$editor[0]->getUser()->getId()}-editor">
{var $user = $editor[0]->getUser()}
<table cellpadding="7">
<tbody>
<tr>
<td valign="top">
<a href="{$user->getURL()}">
<img src="{$user->getAvatarUrl('normal')}" width="48" alt="Фотография профиля" style="border: 1px solid #EBF0F4;"/>
</a>
</td>
<td valign="top" style="width: 100%">
<div style="display: flex; flex-direction: column; justify-content: space-between; height: 48px;">
<div style="display: flex; justify-content: space-between;">
<a href="{$user->getURL()}">{$user->getFullName()}</a>
<a class="link" onclick="addCountry({$editor[0]->getUser()->getId()})">Добавить страну</a>
</div>
<a href="/editdb?act=logs&uid={$editor[0]->getUser()->getId()}">лог действий</a>
</div>
</td>
</tr>
</tbody>
</table>
<div style="padding: 8px;" id="{$user->getId()}-countries">
<div n:foreach="$editor[1] as $country" href="/editdb?act=country&id={$country->getId()}" id="{$user->getId()}-country-{$country->getCode()}">
<h4 style="padding: 8px 0;">
<div style="display: flex; justify-content: space-between;">
<a href="/editdb?act=country&id={$country->getId()}" style="width: 33%;">
<img src="{$country->getFlagURL()}"/>
{$country->getCanonicalName()}
</a>
<div class="nobold" style="width: 33%;">
<tr>
<td width="120" valign="top" align="right">
<input type="checkbox" name="can_edit_education"
n:attr="checked => $country->isUserCanEditEducation($user->getId())"
id="{$user->getId()}_can_edit_education_{=$country->getCode()}"
onclick="onEditorCheckboxClick({$user->getId()}, {$country->getCode()})"/>
</td>
<td>
<span class="nobold">образование</span>
</td>
</tr>
<tr>
<td width="120" valign="top" align="right">
<input type="checkbox" name="can_edit_cities"
n:attr="checked => $country->isUserCanEditCities($user->getId())"
id="{$user->getId()}_can_edit_cities_{=$country->getCode()}"
onclick="onEditorCheckboxClick({$user->getId()}, {$country->getCode()})"/>
</td>
<td>
<span class="nobold">города</span>
</td>
</tr>
</div>
<a class="link" style="font-weight: normal !important; width: 33%; text-align: right;"
onclick="deleteEditorCountry([{$editor[0]->getUser()->getId()}, {$editor[0]->getUser()->getCanonicalName()}], [{$country->getCode()}, {$country->getCanonicalName()}])">
Удалить
</a>
</div>
</h4>
</div>
</div>
</div>
</div>
{include "./GeodbForAdmins.js.xml", countries => $countries, country => $country}
</div>
{/block}

View file

@ -0,0 +1,951 @@
{block content}
<script>
$("#cities-not-found").hide();
$("#cities-list-td").show();
let change_country_input_timeout = 0;
{if $country}
function onChangeCityInput() {
clearTimeout(change_country_input_timeout);
change_country_input_timeout = setTimeout(() => {
let q = $("#city").val();
$.ajax({
type: "POST",
url: "/geodb?act=cities",
data: {
country: {$country->getId()},
q: q,
hash: {=$csrfToken}
},
success: (response) => {
$("#cities-not-found").hide();
$("#cities-list").empty();
if (response.list.length > 0) {
response.list.forEach((city) => {
$("#cities-list").append(`<option value="${ city.id}">${ city.native_name} (${ city.name})</option>`);
});
$("#cities-list").show();
} else {
$("#cities-not-found").show();
$("#cities-list").hide();
}
$("#cities-list-td").show();
}
});
}, 500);
}
{/if}
{if $mode === 'university'}
function getFacultyBlock(id, name) {
return `<li id="faculty-${ id}">
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE;">
<h4 style="padding: 8px; margin-bottom: 4px; border: none;">
<span style="color: inherit; font-weight: unset;" id="faculty-${ id}-name">${ name}</span>
<input type="text" value="${ name}" name="name" id="faculty-${ id}-name-input" style="display: none;">
</h4>
<div style="display: flex; gap: 8px; align-self: center;">
<a id="faculty-${ id}-edit-icon" onclick="editFaculty(${ id})">
<div class="icon edit-icon"></div>
</a>
<a id="faculty-${ id}-save-icon" style="display: none;" onclick="saveFaculty(${ id})">
<div class="icon save-icon"></div>
</a>
<a onclick="deleteFaculty(${ id}, '${ name}')">
<div class="icon delete-icon"></div>
</a>
</div>
</div>
</li>`;
}
function addFaculty() {
AddFacultyMsgTxt = "Вы собираетесь добавить факультет в университет <b>" + {$school->getName()} + "</b>";
AddFacultyMsgTxt += "<br/><br/><input id='new-faculty-name' placeholder='Название факультета' type='text' />";
MessageBox("Добавить факультет", AddFacultyMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=add_faculty&uid=" + {$school->getId()} + "",
data: {
name: $("#new-faculty-name").val(),
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Факультет добавлен", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
if (response.reload) {
setTimeout(() => window.location.reload(), 500)
} else {
$("#faculties").append(getFacultyBlock(response.payload.id, response.payload.name));
}
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
function editFaculty(id) {
let faculty = ("#faculty-" + id);
$(faculty + "-name").toggle();
$(faculty + "-edit-icon").toggle();
$(faculty + "-name-input").toggle();
$(faculty + "-save-icon").toggle();
}
function saveFaculty(id) {
let faculty = ("#faculty-" + id);
$.ajax({
type: "POST",
url: "/editdb?act=faculty&id=" + id,
data: {
name: $(faculty + "-name-input").val(),
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
$(faculty + "-name").text($(faculty + "-name-input").val());
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
editFaculty(id);
}
});
}
function deleteFaculty(id, name) {
DeleteFacultyMsgTxt = "Вы собираетесь удалить факультет <b>" + name + "</b>";
MessageBox("Вы уверены?", DeleteFacultyMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=faculty&delete=1",
data: {
id: id,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Факультет удален", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
if (response.reload) {
setTimeout(() => window.location.reload(), 500)
} else {
let elem = $("#faculty-" + response.payload);
elem.hide("slow", () => elem.remove());
}
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
{if $can_view_deleted}
function restoreFaculty(id, name) {
RestoreFacultyMsgTxt = "Вы собираетесь восстановить факультет <b>" + name + "</b>";
MessageBox("Вы уверены?", RestoreFacultyMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=faculty&restore=1",
data: {
id: id,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Факультет восстановлен", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
if (response.reload) {
setTimeout(() => window.location.reload(), 500)
} else {
let elem = $("#faculty-" + response.payload);
elem.hide("slow", () => elem.remove());
}
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
function restoreSpecialization(id, name) {
DeleteSpecializationMsgTxt = "Вы собираетесь восстановить специализацию <b>" + name + "</b>";
MessageBox("Восстановить специализацию", DeleteSpecializationMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=specialization&restore=1",
data: {
id: id,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Специализация восстановлена", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
let elem = $("#specialization-" + response.payload.id);
elem.hide('slow', () => elem.remove());
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
{/if}
function getSpecializationBlock(id, name, is_deleted) {
return `<li id="specialization-${ id}">
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE;">
<h4 style="padding: 8px; margin-bottom: 4px; border: none;">
<span style="color: inherit; font-weight: unset;" id="specialization-${ id}-name">[#${ id}] ${ name}</span>
<input type="text" value="${ name}" name="name" id="specialization-${ id}-name-input" style="display: none;">
</h4>
<div style="display: flex; gap: 8px; align-self: center;">
<a id="specialization-${ id}-edit-icon" onclick="editSpecialization(${ id})">
<div class="icon edit-icon"></div>
</a>
<a id="specialization-${ id}-save-icon" style="display: none;" onclick="saveSpecialization(${ id})">
<div class="icon save-icon"></div>
</a>
${ !is_deleted ? `<a onclick="deleteSpecialization(${ id}, '${ name}')">
<div class="icon delete-icon"></div>
</a>` : ''}
${ is_deleted ? `<a onclick="restoreSpecialization(${ id}, '${ name}')">
<div class="icon plus-icon"></div>
</a>` : ''}
</div>
</div>
</li>`;
}
function getSpecializations(id, deleted, alreadyShown, is_deleted) {
if (!alreadyShown) {
$("#faculty-" + id + "-specializations").toggle();
}
$("#faculty-" + id + "-specializations-error").remove();
if (!$("#faculty-" + id + "-specializations").is(":hidden")) {
$.ajax({
type: "POST",
url: "/editdb?act=specializations&deleted=" + deleted,
data: {
fid: id,
hash: {=$csrfToken}
},
success: (response) => {
$("#faculty-" + id + "-specializations-list").empty();
if (response.success) {
if (response.list.length > 0) {
response.list.forEach((specialization) => {
$("#faculty-" + id + "-specializations-list").append(getSpecializationBlock(specialization.id, specialization.name, is_deleted));
});
} else {
$("#faculty-" + id + "-specializations-list").append("<center id='faculty-" + id + "-specializations-error' style='padding: 42px;'>Ничего не найдено :(</center>");
}
} else {
$("#faculty-" + id + "-specializations").append("<center id='faculty-" + id + "-specializations-error' style='padding: 42px;'>" + (response?.error ?? "Неизвестная ошибка") + "</center>");
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}
}
function editSpecialization(id) {
let specialization = ("#specialization-" + id);
$(specialization + "-name").toggle();
$(specialization + "-edit-icon").toggle();
$(specialization + "-name-input").toggle();
$(specialization + "-save-icon").toggle();
}
function saveSpecialization(id) {
let specialization = ("#specialization-" + id);
$.ajax({
type: "POST",
url: "/editdb?act=specialization&id=" + id,
data: {
name: $(specialization + "-name-input").val(),
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
$(specialization + "-name").text($(specialization + "-name-input").val());
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
editSpecialization(id);
}
});
}
function addSpecialization(fid, name) {
AddSpecializationMsgTxt = "Вы собираетесь добавить специализацию в университет <b>" + name + "</b>";
AddSpecializationMsgTxt += "<br/><br/><input id='new-specialization-name' placeholder='Название специализации' type='text' />";
MessageBox("Добавить специализацию", AddSpecializationMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=add_specialization&fid=" + fid + "",
data: {
name: $("#new-specialization-name").val(),
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Специализация добавлена", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
$("#faculty-" + fid + "-specializations-list").append(getSpecializationBlock(response.payload.id, response.payload.name));
$("#faculty-" + fid + "-specializations-error").remove();
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
function deleteSpecialization(id, name) {
DeleteSpecializationMsgTxt = "Вы собираетесь удалить специализацию <b>" + name + "</b>";
MessageBox("Удалить специализацию", DeleteSpecializationMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=specialization&delete=1",
data: {
id: id,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Специализация удалена", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
let elem = $("#specialization-" + response.payload.id);
elem.hide('slow', () => elem.remove());
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
{/if}
let change_city_select_timeout = 0;
{if $city}
$("#cities-not-found").hide();
$("#cities-list-td").show();
{/if}
function getSchoolDiv(id, title) {
return `
<li id="school-${ id}">
<a style="cursor: pointer;">
</a>
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE;">
<a style="cursor: pointer;">
<h4 style="padding: 8px; margin-bottom: 4px; border: none;">
${ title}
</h4>
</a>
<div style="display: flex; gap: 8px; align-self: center;">
<a style="cursor: pointer;">
</a>
<a href="/editdb?act=school&id=${ id}">
<div class="icon edit-icon"></div>
</a>
<a onclick="deleteSchool(${ id}, '${ title}')">
<div class="icon delete-icon"></div>
</a>
</div>
</div>
</li>
`;
}
function getUniversityDiv(id, title) {
return `
<li id="university-${ id}">
<a style="cursor: pointer;">
</a>
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE;">
<a style="cursor: pointer;">
<h4 style="padding: 8px; margin-bottom: 4px; border: none;">
${ title}
</h4>
</a>
<div style="display: flex; gap: 8px; align-self: center;">
<a style="cursor: pointer;">
</a>
<a href="/editdb?act=univetsity&id=${ id}">
<div class="icon edit-icon"></div>
</a>
<a onclick="deleteUniversity(${ id}, '${ title}')">
<div class="icon delete-icon"></div>
</a>
</div>
</div>
</li>
`;
}
{if $country}
function onChangeCityInput() {
clearTimeout(change_country_input_timeout);
change_country_input_timeout = setTimeout(() => {
let q = $("#city").val();
$.ajax({
type: "POST",
url: "/geodb?act=cities",
data: {
country: {$country->getId()},
q: q,
hash: {=$csrfToken}
},
success: (response) => {
$("#cities-not-found").hide();
$("#cities-list").empty();
if (response.list.length > 0) {
response.list.forEach((city) => {
$("#cities-list").append(`<option value="${ city.id}">${ city.native_name} (${ city.name})</option>`);
});
$("#cities-list").show();
onChangeCitySelect($("#cities-list").val());
} else {
$("#cities-not-found").show();
$("#cities-list").hide();
}
$("#cities-list-td").show();
}
});
}, 500);
}
function searchSchools(city) {
$.ajax({
type: "POST",
url: "/editdb?act=country&id={$country->getId()}&edu=1&city=" + city + "&view=" + {$view},
data: {
hash: {=$csrfToken}
},
success: (response) => {
console.log(response);
$("#schools").empty();
$("#universities").empty();
if (response.success) {
$("#current-city-name").text(response.city).show();
$("#current-city-block").show();
if (response.list.length > 0) {
response.list.forEach((school) => {
$("#schools").append(getSchoolDiv(school.id, school.name));
$("#universities").append(getUniversityDiv(school.id, school.name));
});
} else {
$("#schools").append("<center style='padding: 32px;'>Ничего не найдено :(</center>");
$("#universities").append("<center style='padding: 32px;'>Ничего не найдено :(</center>");
}
} else {
$("#schools").append("<center style='padding: 32px;'>" + tr("error") + "</center>");
$("#universities").append("<center style='padding: 32px;'>" + tr("error") + "</center>");
}
}
});
}
{/if}
function onChangeCitySelect(cityOverride) {
clearTimeout(change_city_select_timeout);
change_city_select_timeout = setTimeout(() => {
searchSchools($("#cities-list").val());
}, 500)
}
function deleteSchool(id, name, isRestore = false) {
DeleteSchoolMsgTxt = "Вы собираетесь " + (isRestore ? "восстановить" : "удалить") + " школу <b>" + name + "</b>";
MessageBox("Вы уверены?", DeleteSchoolMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=school" + (isRestore ? "&restore=1" : "&delete=1"),
data: {
id: id,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Школа " + (isRestore ? "восстановлена" : "удалена"), "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
if (response.reload) {
setTimeout(() => window.location.reload(), 500)
} else {
let elem = $("#school-" + response.payload);
elem.hide("slow", () => elem.remove());
}
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
function deleteUniversity(id, name, isRestore = false) {
DeleteUniversityMsgTxt = "Вы собираетесь " + (isRestore ? "восстановить" : "удалить") + " университет <b>" + name + "</b>";
MessageBox("Вы уверены?", DeleteUniversityMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=university" + (isRestore ? "&restore=1" : "&delete=1"),
data: {
id: id,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Университет " + (isRestore ? "восстановлен" : "удален"), "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
if (response.reload) {
setTimeout(() => window.location.reload(), 500)
} else {
let elem = $("#university-" + response.payload);
elem.hide("slow", () => elem.remove());
}
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
let search_editors_timer = 0;
$("#searchEditors").on("input", function(e) {
clearTimeout(search_editors_timer);
search_editors_timer = setTimeout(() => {
console.log(e);
$.ajax({
type: "POST",
url: "/editdb?act=editors",
data: {
q: (e.target.value ? e.target.value : " "),
hash: {=$csrfToken}
},
success: (response) => {
console.log(response);
$("#editors").empty();
if (response.editors.length > 0) {
response.editors.forEach((editor) => {
let user = editor[0];
let countries = editor[1];
$("#editors").append(getEditorDiv(user.id, user.name, user.link, user.avatar));
countries.forEach((country) => {
$("#" + user.id + "-countries").append(getCountryDiv(country.id, user.id, country.name, user.name, country.code, country.flag, country.edu, country.cities));
});
});
} else {
$("#editors").append("<center style='padding: 32px;'>Ничего не найдено :(</center>");
}
}
});
}, 500);
});
function getEditorDiv(id, name, link, avatar) {
return `<div id="${ id}-editor">
<table cellpadding="7">
<tbody>
<tr>
<td valign="top">
<a href="${ link}">
<img src="${ avatar}" width="48" alt="Фотография профиля" style="border: 1px solid #EBF0F4;"/>
</a>
</td>
<td valign="top" style="width: 100%">
<div style="display: flex; flex-direction: column; justify-content: space-between; height: 48px;">
<div style="display: flex; justify-content: space-between;">
<a href="${ link}">${ name} </a>
<a class="link" onclick="addCountry(${ id})">Добавить страну</a>
</div>
<a>лог действий</a>
</div>
</td>
</tr>
</tbody>
</table>
<div style="padding: 8px;" id="${ id}-countries"></div>
</div>`
}
function getCountryDiv(id, user, name, user_name, code, flag, edu, cities) {
return `<div href="/editdb?act=country&id=${ id}" id="${ user}-country-${ code}">
<h4 style="padding: 8px 0;">
<div style="display: flex; justify-content: space-between;">
<a href="/editdb?act=country&id=${ id}" style="width: 33%;">
<img src="${ flag}"/>
${ name}
</a>
<div class="nobold" style="width: 33%;">
<tr>
<td width="120" valign="top" align="right">
<input type="checkbox" name="can_edit_education"
id="${ user}_can_edit_education_${ code}"
onclick="onEditorCheckboxClick(${ user}, '${ code}')"
${ edu ? "checked='true'" : ""}
/>
</td>
<td>
<span class="nobold">образование</span>
</td>
</tr>
<tr>
<td width="120" valign="top" align="right">
<input type="checkbox" name="can_edit_cities"
id="${ user}_can_edit_cities_${ code}"
onclick="onEditorCheckboxClick(${ user}, '${ code}')"
${ cities ? "checked='true'" : ""}
/>
</td>
<td>
<span class="nobold">города</span>
</td>
</tr>
</div>
<a class="link" style="font-weight: normal !important; width: 33%; text-align: right;"
onclick="deleteEditorCountry([${ user}, '${ user_name}'], ['${ code}', '${ name}'])">
Удалить
</a>
</div>
</h4>
</div>`;
}
function addNewEditor() {
const link = $("#new-editor-link").val();
const country = $("#new-editor-country").val();
const edu = $("#new-editor-edu").is(":checked");
const cities = $("#new-editor-cities").is(":checked");
$.ajax({
type: "POST",
url: "/editdb?act=editors",
data: {
link: link,
country: country,
can_access_edu: edu ? 1 : 0,
can_access_cities: cities ? 1 : 0,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Редактор базы добавлен", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
let r = response.payload;
if (!r.user_exists)
$("#editors").append(getEditorDiv(r.user, r.user_name, r.link, r.avatar));
$("#" + r.user + "-countries").append(getCountryDiv(r.id, r.user, r.name, r.user_name, r.code, r.flag, r.edu, r.cities));
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}
function addCountry(user) {
AddCountryMsgTxt = "<select name='country' id='" + user + "-add-country-code'>";
{foreach $countries as $country}
AddCountryMsgTxt += "<option value='" + {$country->getCode()} + "'>[" + {=$country->getCode()} + "] " + {=$country->getCanonicalName()} + "</option>";
{/foreach}
AddCountryMsgTxt += "</select>";
AddCountryMsgTxt += "<div class='nobold'>";
AddCountryMsgTxt += "<input type='checkbox' id='" + user + "-can-access-edu' /><a class='link'>образование</a>";
AddCountryMsgTxt += "<input type='checkbox' id='" + user + "-can-access-cities' style='margin-left: 16px;' /><a class='link'>города</a>";
AddCountryMsgTxt += "</div>";
MessageBox("Добавить страну", AddCountryMsgTxt, ["Подтвердить", "Отмена"], [
(function() {
$.ajax({
type: "POST",
url: "/editdb?act=editor&id=" + user,
data: {
country: $("#" + user + "-add-country-code").val(),
can_access_edu: $("#" + user + "-can-access-edu").is(":checked") ? 1 : 0,
can_access_cities: $("#" + user + "-can-access-cities").is(":checked") ? 1 : 0,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Права доступа редактора обновлены", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
let r = response.payload;
$("#" + user + "-countries").append(getCountryDiv(r.id, r.user, r.name, r.user_name, r.code, r.flag, r.edu, r.cities));
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
]);
}
function deleteEditorCountry(user, country) {
DelCountryMsgTxt = "Вы собираетесь исключить " + user[1] + " из редакторов страны " + country[1];
MessageBox("Вы уверены?", DelCountryMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=editor&id=" + user[0] + "&delete=1",
data: {
country: country[0],
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Права доступа редактора обновлены", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
let elem = $("#" + user[0] + "-country-" + country[0]);
elem.hide('slow', () => elem.remove());
if (response?.payload?.delete_user) {
elem = $("#" + user[0] + "-editor");
elem.hide('slow', () => elem.remove());
}
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
function onEditorCheckboxClick(user, country) {
let edu_elem = $("#" + user + "_can_edit_education_" + country);
let edu = edu_elem.is(":checked");
let cities_elem = $("#" + user + "_can_edit_cities_" + country);
let cities = cities_elem.is(":checked");
edu_elem.prop('disabled', true);
cities_elem.prop('disabled', true);
$.ajax({
type: "POST",
url: "/editdb?act=editor&id=" + user + "&edit=1",
data: {
country: country,
can_access_edu: edu ? 1 : 0,
can_access_cities: cities ? 1 : 0,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Права доступа редактора обновлены", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
setTimeout(() => {
edu_elem.prop('disabled', false);
cities_elem.prop('disabled', false);
}, 500);
}
});
}
function editRequest(id, save) {
$("#" + id + "-info-block").toggle();
$("#" + id + "-edit-block").toggle();
$("#" + id + "-edit-button").toggle();
$("#" + id + "-save-button").toggle();
if (save) {
$.ajax({
type: "POST",
url: "/editdb?act=requests&tab=" + {$mode} + "&edit=1",
data: {
rid: id,
name: $("#" + id + "-name").val(),
native_name: $("#" + id + "-native_name").val(),
city_id: $("#" + id + "-city_id").val(),
university_id: $("#" + id + "-university_id").val(),
faculty_id: $("#" + id + "-faculty_id").val(),
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Заявка отредактирована", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
setTimeout(() => window.location.reload(), 500)
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}
}
function getRequestBlock(id, user, item) {
return `
<div id="request-${ id}">
<div style="border: 8px solid #D9E3EA; margin: 16px 0;">
<div>
<table cellpadding="7">
<tbody>
<tr>
<td valign="top">
<a href="${ user.url}">
<img src="${ user.avatar}" width="48"
alt="Фотография профиля" style="border: 1px solid #EBF0F4;">
</a>
</td>
<td valign="top" style="width: 100%">
<div>
<div style="display: flex; justify-content: space-between;">
<a href="${ user.url}">${ user.name}</a>
</div>
предлагает добавить ${ item.type}
<b>${ item.title}</b>
<ul>
${ item.name}
${ item.native_name}
</ul>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<center style="padding: 16px;">
<button class="button">Добавить</button>
<button class="button">Отклонить</button>
</center>
</div>
</div>
`;
}
$("#country-select").on('change', (e) => {
window.location.href = "/editdb?act=requests&cid=" + e.target.value + "&tab=" + {$mode};
});
function performRequestAction(rid, isAccept) {
$.ajax({
type: "POST",
url: "/editdb?act=requests&tab=" + {$mode} + (isAccept ? '&accept=1' : '&decline=1'),
data: {
rid: rid,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Заявка " + (isAccept ? "одобрена" : "отклонена"), "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
let elem = $("#request-" + response.payload);
elem.hide('slow', () => elem.remove());
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}
function searchSchools(city) {
$.ajax({
type: "POST",
url: "/editdb?act=country&id={$country->getId()}&edu=1&city=" + city + "&view=" + {$view},
data: {
hash: {=$csrfToken}
},
success: (response) => {
console.log(response);
$("#schools").empty();
$("#universities").empty();
if (response.success) {
$("#current-city-name").text(response.city).show();
$("#current-city-block").show();
if (response.list.length > 0) {
response.list.forEach((school) => {
$("#schools").append(getSchoolDiv(school.id, school.name));
$("#universities").append(getUniversityDiv(school.id, school.name));
});
} else {
$("#schools").append("<center style='padding: 32px;'>Ничего не найдено :(</center>");
$("#universities").append("<center style='padding: 32px;'>Ничего не найдено :(</center>");
}
} else {
$("#schools").append("<center style='padding: 32px;'>" + tr("error") + "</center>");
$("#universities").append("<center style='padding: 32px;'>" + tr("error") + "</center>");
}
}
});
}
function onChangeCitySelect(cityOverride) {
clearTimeout(change_city_select_timeout);
change_city_select_timeout = setTimeout(() => {
searchSchools($("#cities-list").val());
}, 500)
}
function deleteCountry(id, restore) {
MessageBox((restore ? "Восстановить" : "Удалить") + " страну", "Вы уверены?", ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/editdb?act=country&id=" + id + (restore ? "&restore=1" : "&delete=1"),
data: {
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Страна " + (restore ? "восстановлена" : "удалена"), "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
let elem = $("#country-" + response.payload);
elem.hide('slow', () => elem.remove());
} else {
NewNotification("Ошибка", (response.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png")
}
}
});
}),
Function.noop
])
}
</script>
{/block}

View file

@ -0,0 +1,591 @@
{block content}
<script>
let change_country_input_timeout = 0;
let change_city_select_timeout = 0;
{if $user->getCountry()}
$("#countries-not-found").hide();
$("#countries-list-td").show();
{if $user->getCity()}
$("#cities-not-found").hide();
$("#cities-list-td-input").show();
$("#cities-list-td").show();
{/if}
{/if}
function onChangeCountryInput() {
clearTimeout(change_country_input_timeout);
change_country_input_timeout = setTimeout(() => {
let q = $("#country").val();
$.ajax({
type: "POST",
url: "/geodb?act=countries",
data: {
q: q,
hash: {=$csrfToken}
},
success: (response) => {
$("#countries-not-found").hide();
$("#countries-list").empty();
console.log(response.list.length);
if (response.list.length > 0) {
response.list.forEach((country) => {
$("#countries-list").append(`<option value="${ country.id}">${ country.native_name} (${ country.name})</option>`);
});
$("#countries-list").show();
$("#cities-list-td-input").show();
$("#city").val("");
$("#cities-list-td").hide();
} else {
$("#countries-not-found").show();
$("#countries-list").hide();
}
$("#countries-list-td").show();
}
});
}, 500);
}
function onChangeCityInput() {
clearTimeout(change_country_input_timeout);
change_country_input_timeout = setTimeout(() => {
let q = $("#city").val();
$.ajax({
type: "POST",
url: "/geodb?act=cities",
data: {
country: $("#countries-list").val(),
q: q,
hash: {=$csrfToken}
},
success: (response) => {
$("#cities-not-found").hide();
$("#cities-list").empty();
console.log(response, response.list, response.list.length);
if (response.list.length > 0) {
response.list.forEach((city) => {
$("#cities-list").append(`<option value="${ city.id}">${ city.native_name} (${ city.name})</option>`);
});
$("#cities-list").show();
} else {
$("#cities-not-found").show();
$("#cities-list").hide();
}
$("#cities-list-td").show();
}
});
}, 500);
}
function getSchoolDiv(id, title) {
return `<option value='${ id}'>${ title}</option>`;
}
function getUniversityDiv(id, title) {
return `<option value='${ id}'>${ title}</option>`;
}
function hideAndShowElements(hideElement, showElement) {
$(hideElement).hide();
$(showElement).show();
}
{if $user->getSchool()}
hideAndShowElements("#school-cities-not-found", "#school-cities-list-td");
$("#school-cities-list").append(getSchoolDiv({$user->getSchool()->getCity()->getId()}, {$user->getSchool()->getCity()->getNativeName()}));
hideAndShowElements("#schools-not-found", "#school-info, #schools-list-td");
$("#schools-list").append(getSchoolDiv({$user->getSchool()->getId()}, {$user->getSchool()->getName()}));
$("#schools").show();
$(".school-additional").show();
{/if}
{if $user->getUniversity()}
hideAndShowElements("#university-cities-not-found", "#university-cities-list-td");
$("#university-cities-list").append(getUniversityDiv({$user->getUniversity()->getCity()->getId()}, {$user->getUniversity()->getCity()->getNativeName()}));
hideAndShowElements("#universities-not-found", "#university-info, #universities-list-td");
$("#universities-list").append(getUniversityDiv({$user->getUniversity()->getId()}, {$user->getUniversity()->getName()}));
$("#universities").show();
{if $user->getUniversityFaculty()}
hideAndShowElements("#faculties-not-found", "#faculty-info, #faculties-list-td");
$("#faculties-list").append(getUniversityDiv({$user->getUniversityFaculty()->getId()}, {$user->getUniversityFaculty()->getName()}));
$("#faculties").show();
{/if}
{if $user->getUniversitySpecialization()}
hideAndShowElements("#specializations-not-found", "#specializations-list-td");
$("#specializations-list").append(getUniversityDiv({$user->getUniversitySpecialization()->getId()}, {$user->getUniversitySpecialization()->getName()}));
$("#specializations").show();
{/if}
$(".university-additional").show();
{/if}
function onChangeSchoolCityInput(prefix) {
clearTimeout(change_country_input_timeout);
change_country_input_timeout = setTimeout(() => {
let q = $("#city").val();
$.ajax({
type: "POST",
url: "/geodb?act=cities",
data: {
country: {$user->getCountry(true)["id"]},
q: q,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
hideAndShowElements("#school-cities-not-found", "#school-cities-list-td");
$("#school-cities-list").empty();
if (response.list.length > 0) {
console.log('ok');
response.list.forEach((city) => {
$("#school-cities-list").append(`<option value="${ city.id}">${ city.native_name} (${ city.name})</option>`);
});
$("#school-cities-list").show();
onChangeCitySelect($("#school-cities-list").val());
} else {
hideAndShowElements("#school-cities-list", "#school-cities-not-found");
}
} else {
$("#school-cities-list").hide();
$("#school-cities-not-found").text(response.error);
$("#school-cities-list-td").show();
}
}
});
}, 500);
}
function searchSchools(city) {
console.log("s", city);
$.ajax({
type: "POST",
url: "/geodb?act=country&id={$user->getCountry(true)["id"]}&edu=1&city=" + city,
data: {
hash: {=$csrfToken}
},
success: (response) => {
console.log(response);
$("#schools").show();
$("#schools-list").hide();
$("#schools-not-found").hide();
$("#schools-list").empty();
if (response.success) {
if (response.list.length > 0) {
response.list.forEach((school) => {
$("#schools-list").append(getSchoolDiv(school.id, school.name));
});
$("#schools-list").show();
$("#schools-not-found").hide();
$(".school-additional").show();
} else {
$("#schools-not-found").text("Ничего не найдено :(");
$("#schools-not-found").show();
$(".school-additional").hide();
}
} else {
$("#schools-not-found").text(tr("error"));
$("#schools-not-found").show();
}
}
});
}
function onChangeCitySelect(cityOverride) {
clearTimeout(change_city_select_timeout);
change_city_select_timeout = setTimeout(() => {
searchSchools($("#school-cities-list").val());
}, 500)
}
function onChangeUniversityCityInput() {
clearTimeout(change_country_input_timeout);
change_country_input_timeout = setTimeout(() => {
let q = $("#university-city").val();
$.ajax({
type: "POST",
url: "/geodb?act=cities",
data: {
country: {$user->getCountry(true)["id"]},
q: q,
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
hideAndShowElements("#university-cities-not-found", "#university-cities-list-td");
$("#university-cities-list").empty();
if (response.list.length > 0) {
response.list.forEach((city) => {
$("#university-cities-list").append(`<option value="${ city.id}">${ city.native_name} (${ city.name})</option>`);
});
$("#university-cities-list").show();
onChangeUniversityCitySelect($("#university-cities-list").val());
} else {
hideAndShowElements("#university-cities-list", "#university-cities-not-found");
}
} else {
$("#university-cities-list").hide();
$("#university-cities-not-found").text(response.error);
$("#university-cities-list-td").show();
}
}
});
}, 500);
}
function searchUniversities(city) {
$.ajax({
type: "POST",
url: "/geodb?act=country&id={$user->getCountry(true)["id"]}&edu=1&city=" + city + "&view=universities",
data: {
hash: {=$csrfToken}
},
success: (response) => {
console.log(response);
$("#universities").show();
$("#universities-list").hide();
$("#universities-not-found").hide();
$("#universities-list").empty();
if (response.success) {
if (response.list.length > 0) {
$("#faculties-list").empty();
$("#specializations-list").empty();
response.list.forEach((university) => {
$("#universities-list").append(getUniversityDiv(university.id, university.name));
});
response.list[0].faculties.forEach((faculty) => {
$("#faculties-list").append(getUniversityDiv(faculty.id, faculty.name));
faculty.specializations.forEach((specialization) => {
$("#specializations-list").append(getUniversityDiv(specialization.id, specialization.name));
});
});
$("#universities-list").show();
$("#universities-not-found").hide();
$(".university-additional").show();
$("#faculties-not-found").hide();
$("#faculties").show();
$("#specializations-not-found").hide();
$("#specializations").show();
} else {
$("#universities-not-found").text("Ничего не найдено :(");
$("#universities-not-found").show();
$(".university-additional").hide();
$("#faculties").hide();
$("#specializations").hide();
}
} else {
$("#universities-not-found").text(tr("error"));
$("#universities-not-found").show();
}
}
});
}
function onChangeUniversityCitySelect(cityOverride) {
clearTimeout(change_city_select_timeout);
change_city_select_timeout = setTimeout(() => {
searchUniversities($("#university-cities-list").val());
}, 500)
}
$("#universities-list").on('change', (e) => {
$.ajax({
type: "POST",
url: "/geodb?act=country&id={$user->getCountry(true)["id"]}&edu=1&view=universities&uid=" + e.target.value + "&n=faculties",
data: {
hash: {=$csrfToken}
},
success: (response) => {
$("#faculties-not-found").hide();
$("#faculties-list").show();
console.log(response);
if (response.success) {
$("#faculties-list").empty();
$("#specializations-list").empty();
if (response.list.length > 0) {
response.list.forEach((faculty) => {
$("#faculties-list").append(getUniversityDiv(faculty.id, faculty.name));
faculty.specializations.forEach((specialization) => {
$("#specializations-list").append(getUniversityDiv(specialization.id, specialization.name));
});
});
} else {
$("#faculties-list").hide();
$("#faculties-not-found").show();
}
} else {
$("#faculties-list").hide();
$("#faculties-not-found").text(tr("error"));
$("#faculties-not-found").show();
}
}
});
});
$("#faculties-list").on('change', (e) => {
$.ajax({
type: "POST",
url: "/geodb?act=country&id={$user->getCountry(true)["id"]}&edu=1&view=universities&fid=" + e.target.value + "&n=specializations",
data: {
hash: {=$csrfToken}
},
success: (response) => {
$("#specializations-not-found").hide();
$("#specializations-list").show();
console.log(response);
if (response.success) {
$("#specializations-list").empty();
if (response.list.length > 0) {
response.list.forEach((specialization) => {
$("#specializations-list").append(getUniversityDiv(specialization.id, specialization.name));
});
} else {
$("#specializations-list").hide();
$("#specializations-not-found").show();
}
} else {
$("#specializations-list").hide();
$("#specializations-not-found").text(tr("error"));
$("#specializations-not-found").show();
}
}
});
});
function onChangeAddItemCountryInput(type) {
clearTimeout(change_country_input_timeout);
change_country_input_timeout = setTimeout(() => {
let q = $("#geodb-country").val();
$.ajax({
type: "POST",
url: "/geodb?act=countries",
data: {
q: q,
hash: {=$csrfToken}
},
success: (response) => {
$("#geodb-countries-not-found").hide();
$("#geodb-countries-list").empty();
console.log(response.list.length);
if (response.list.length > 0) {
response.list.forEach((country) => {
$("#geodb-countries-list").append(`<option value="${ country.id}">${ country.native_name} (${ country.name})</option>`);
});
$("#geodb-countries-list").show();
if (type !== "cities")
$("#geodb-city-div").show();
} else {
$("#geodb-countries-not-found").show();
$("#geodb-countries-list").hide();
}
$("#geodb-countries-list-td").show();
}
});
}, 500);
}
function getFaculties(country) {
let _country = country ?? $("#geodb-countries-list").val() ?? {$user->getCountry(true)["id"]};
let city = $("#geodb-cities-list").val() ?? {$user->getCity(true)["id"]};
let university = $("#geodb-universities-list").val();
$.ajax({
type: "POST",
url: "/geodb?act=country&id=" + _country + "&edu=1&view=faculties&n=faculties" + (city ? ("&city=" + city) : "") + "&uid=" + university,
data: {
hash: {=$csrfToken}
},
success: (response) => {
hideAndShowElements("#geodb-faculties-not-found", "#geodb-faculties-list-td");
$("#geodb-faculties-list").empty();
if (response.success) {
if (response.list.length > 0) {
response.list.forEach((faculty) => {
$("#geodb-faculties-list").append(`<option value="${ faculty.id}">${ faculty.name}</option>`);
});
$("#geodb-faculties-list-td").show();
$("#geodb-faculties-list").show();
} else {
$("#geodb-faculties-not-found").text("Ничего не найдено :(");
$("#geodb-faculties-not-found").show();
$("#geodb-faculties-list").hide();
}
} else {
$("#geodb-faculties-not-found").text(tr("error"));
$("#geodb-faculties-not-found").show();
$("#geodb-faculties-list").hide();
}
}
});
}
function getUniversities(country, _getFaculties) {
let _country = country ?? $("#geodb-countries-list").val() ?? {$user->getCountry(true)["id"]};
let city = $("#geodb-cities-list").val() ?? {$user->getCity(true)["id"]};
$.ajax({
type: "POST",
url: "/geodb?act=country&id=" + _country + "&edu=1&city=" + city + "&view=universities" + (city ? ("&city=" + city) : ""),
data: {
hash: {=$csrfToken}
},
success: (response) => {
hideAndShowElements("#geodb-universities-not-found", "#geodb-universities-list-td");
$("#geodb-universities-list").empty();
if (response.success) {
if (response.list.length > 0) {
response.list.forEach((university) => {
$("#geodb-universities-list").append(`<option value="${ university.id}">${ university.name}</option>`);
});
$("#geodb-universities-list").show();
} else {
$("#geodb-universities-not-found").text("Ничего не найдено :(");
$("#geodb-universities-not-found").show();
$("#geodb-universities-list").hide();
}
} else {
$("#geodb-universities-not-found").text(tr("error"));
$("#geodb-universities-not-found").show();
}
if (_getFaculties) {
getFaculties(_country);
}
}
});
}
function onCountryChange(e) {
console.log($(e).val());
onChangeAddItemCityInput($(e).val(), true)
}
function onChangeAddItemCityInput(country, _getUniversities) {
clearTimeout(change_country_input_timeout);
let city = $("#geodb-cities-list").val();
change_country_input_timeout = setTimeout(() => {
let q = $("#geodb-city").val();
$.ajax({
type: "POST",
url: "/geodb?act=cities",
data: {
country: (country ?? $("#geodb-countries-list").val() ?? {$user->getCountry(true)['name']}),
q: q,
hash: {=$csrfToken}
},
success: (response) => {
hideAndShowElements("#geodb-cities-not-found", "#geodb-cities-list-td");
$("#geodb-cities-list").empty();
if (response.list.length > 0) {
response.list.forEach((city) => {
$("#geodb-cities-list").append(`<option value="${ city.id}">${ city.native_name} (${ city.name})</option>`);
});
$("#geodb-cities-list").show();
$("#geodb-universities-list-td").show();
} else {
hideAndShowElements("#geodb-cities-list", "#geodb-cities-not-found");
}
if (_getUniversities && response.list.length > 0) {
getUniversities(country ?? $("#geodb-countries-list").val(), true);
getFaculties(country ?? $("#geodb-countries-list").val());
}
}
});
}, 500);
}
function geodbRequest(type) {
GeodbReqMsgTxt = "Здесь вы можете подать заявку на добавление в базу данных школы, вуза, факультета, специальности и улицы.";
GeodbReqMsgTxt += "";
GeodbReqMsgTxt += "<br/><br/><input id='geodb-name' type='text' placeholder='" + (type === "cities" ? "Название на английском" : "Название") + "' name='name' />";
if (type === "cities") {
GeodbReqMsgTxt += "<br/><br/><input id='geodb-native_name' type='text' placeholder='Родное название' name='native_name' />";
}
GeodbReqMsgTxt += "<br/><br/><b>Страна</b><br/><input type='text' name='country-input' placeholder='Начните вводить название' id='geodb-country' onInput='onChangeAddItemCountryInput(`" + type + "`)' n:attr='value => ($user->getCountry()->getNativeName() ?? NULL)'/>";
GeodbReqMsgTxt += "<div id='geodb-countries-list-td'></div><center id='geodb-countries-not-found' style='display: none;'>Ничего не найдено</center>\
<select style='display: none;' id='geodb-countries-list' name='country' value='1' onchange='onCountryChange(this)'>\
{if $user->getCountry()}\
<option selected value='" + {$user->getCountry(true)['id']} + "'>" + {$user->getCountry(true)['native_name']} + "\
(" + {$user->getCountry(true)['name']} + ")\
</option>\
{/if}\
</select>";
GeodbReqMsgTxt += "<div style='display: none;' id='geodb-city-div'><br/><br/><b>Город</b><br/><input type='text' name='city' placeholder='Начните вводить название' id='geodb-city' onInput='onChangeAddItemCityInput(null, true)' n:attr='value => ($user->getCity()->getNativeName() ?? NULL)'/>";
GeodbReqMsgTxt += "<div id='geodb-cities-list-td'></div><center id='geodb-cities-not-found' style='display: none;'>Ничего не найдено</center>\
<select style='display: none;' id='geodb-cities-list' name='city-id' value='1' onchange='getUniversities(null, true); getFaculties();'>\
{if $user->getCity()}\
<option value='" + {$user->getCity(true)['id']} + "'>" + {$user->getCity(true)['native_name']} + "\
(" + {$user->getCity(true)['name']} + ")\
</option>\
{/if}\
</select></div>";
if (type === 'faculties' || type === "specializations") {
if ($("#geodb-universities-list").val()) {
getUniversities();
}
GeodbReqMsgTxt += "<div id='geodb-universities-list-td' style='display: none;'><br/><br/><b>Университет</b><br/>";
GeodbReqMsgTxt += "<center id='geodb-universities-not-found' style='display: none;'>Ничего не найдено</center>\
<select id='geodb-universities-list' onchange='getFaculties();' name='university-id' value='1'>\
{if $user->getUniversity()}\
<option value='" + {$user->getUniversity()->getId()} + "'>" + {$user->getUniversity()->getName()} + "\
(" + {$user->getUniversity()->getName()} + ")\
</option>\
{/if}\
</select></div>";
}
if (type === "specializations") {
if ($("#geodb-universities-list").val()) {
getUniversities();
}
GeodbReqMsgTxt += "<div id='geodb-faculties-list-td' style='display: none;'><br/><br/><b>Факультет</b><br/>";
GeodbReqMsgTxt += "<center id='geodb-faculties-not-found' style='display: none;'>Ничего не найдено</center>\
<select id='geodb-faculties-list' name='faculty-id' value='1'>\
{if $user->getUniversityFaculty()}\
<option value='" + {$user->getUniversityFaculty()->getId()} + "'>" + {$user->getUniversityFaculty()->getName()} + "\
(" + {$user->getUniversityFaculty()->getName()} + ")\
</option>\
{/if}\
</select></div>";
}
MessageBox("Добавить", GeodbReqMsgTxt, ["Подтвердить", "Отмена"], [
(function () {
$.ajax({
type: "POST",
url: "/geodb?act=new_request&tab=" + type,
data: {
country: $("#geodb-countries-list").val() ?? {$user->getCountry(true)["id"]},
city: $("#geodb-cities-list").val(),
name: $("#geodb-name").val(),
native_name: $("#geodb-native_name").val(),
uid: $("#geodb-universities-list").val(),
fid: $("#geodb-faculties-list").val(),
hash: {=$csrfToken}
},
success: (response) => {
if (response.success) {
NewNotification("Успех", "Запрос отправлен. Вы получите оповещение при изменении статуса.", "/assets/packages/static/openvk/img/oxygen-icons/64x64/actions/dialog-ok.png");
} else {
NewNotification("Ошибка", (response?.error ?? "Неизвестная ошибка"), "/assets/packages/static/openvk/img/error.png");
}
}
});
}),
Function.noop
])
}
</script>
{/block}

View file

@ -0,0 +1,43 @@
{extends "../@layout.xml"}
{block title}Логи{/block}
{block header}{include title}{/block}
{block content}
{include "./tabs.xml", mode => $mode, country => $country}
<div>
<div n:if="$count <= 0">
<br />
{include "../components/nothing.xml"}
</div>
<div n:if="$count > 0">
<div n:foreach="$logs as $log" style="border: 8px solid #D9E3EA; margin: 16px 0;">
{var $user = $log->getUser()}
<table cellpadding="7">
<tbody>
<tr>
<td valign="top">
<a href="{$user->getURL()}">
<img src="{$user->getAvatarUrl('normal')}" width="48" alt="Фотография профиля" style="border: 1px solid #EBF0F4;"/>
</a>
</td>
<td valign="top" style="width: 100%">
<div>
<div style="display: flex; justify-content: space-between;">
<a href="{$user->getURL()}">{$user->getFullName()}</a>
</div>
<div>
<b>{$log->getType()}</b> {$log->getObjectType()} <a href="{$log->getObjectURL()}">{$log->getObjectName()}</a>
</div>
<div style="margin-left: -39px;">
<blockquote style="background-color: #f3f3f3; border-bottom: 5px solid #969696; padding: 10px;">{$log->getLogsText()|noescape}</blockquote>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
{/block}

View file

@ -0,0 +1,104 @@
{extends "../@layout.xml"}
{block title}Заявки Геодб{/block}
{block header}{include title}{/block}
{block content}
<div>
<select placeholder="Страна" id="country-select">
<option n:foreach="$countries as $country" value="{$country->getId()}"
n:attr="selected => ($current_country ? ($country->getId() === $current_country->getId()) : false)">[{$country->getCode()}]
{$country->getNativeName()}
</option>
</select>
</div>
<div n:if="$country || $current_country">
<div class="tabs">
<br/>
<div n:if="$can_view_cities" n:attr="id => ($mode === 'cities' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($mode === 'cities' ? 'act_tab_a' : 'ki')" href="/editdb?act=requests&cid={$current_country->getId()}&tab=cities">Города</a>
</div>
<div n:if="$can_view_education" n:attr="id => ($mode === 'schools' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($mode === 'schools' ? 'act_tab_a' : 'ki')" href="/editdb?act=requests&cid={$current_country->getId()}&tab=schools">Школы</a>
</div>
<div n:if="$can_view_education" n:attr="id => ($mode === 'universities' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($mode === 'universities' ? 'act_tab_a' : 'ki')" href="/editdb?act=requests&cid={$current_country->getId()}&tab=universities">Университеты</a>
</div>
<div n:if="$can_view_education" n:attr="id => ($mode === 'faculties' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($mode === 'faculties' ? 'act_tab_a' : 'ki')" href="/editdb?act=requests&cid={$current_country->getId()}&tab=faculties">Факультеты</a>
</div>
<div n:if="$can_view_education" n:attr="id => ($mode === 'specializations' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($mode === 'specializations' ? 'act_tab_a' : 'ki')" href="/editdb?act=requests&cid={$current_country->getId()}&tab=specializations">Специализации</a>
</div>
</div>
<div id="requests" style="margin-top: 8px;">
<div id="requests-placeholder" n:if="count($requests) === 0">{include "../components/nothing.xml"}</div>
<div id="requests-list" n:attr="style => count($requests) === 0 ? 'display: none;' : ''">
<div n:foreach="$requests as $request" id="request-{$request[0]->getId()}">
<div style="border: 8px solid #D9E3EA; margin: 16px 0;">
<div>
<table cellpadding="7">
<tbody>
<tr>
<td valign="top">
<a href="{$request[1]->getURL()}">
<img src="{$request[1]->getAvatarURL()}" width="48"
alt="Фотография профиля" style="border: 1px solid #EBF0F4;">
</a>
</td>
<td valign="top" style="width: 100%">
<div>
<div style="display: flex; justify-content: space-between;">
<a href="{$request[1]->getURL()}">{$request[1]->getCanonicalName()}</a>
</div>
предлагает добавить {$type}
<b>{$mode === "cities" ? $request[0]->getNativeName() : $request[0]->getName()}</b>
<ul id="{$request[0]->getId()}-info-block">
<div n:if="$mode === 'cities'">
<li>Название на английском: <b>{$request[0]->getName()}</b></li>
<li>Родное название: <b>{$request[0]->getNativeName()}</b></li>
</div>
<div n:if="$mode !== 'cities'">
<li>Город:
<a href="/editdb?act=city&id={$request[0]->getCity()->getId()}">{$request[0]->getCity()->getNativeName()}</a>
</li>
<li n:if="$mode === 'faculties' || $mode === 'specializations'">
Университет:
<a href="/editdb?act=university&id={$request[0]->getUniversity()->getId()}">
{$request[0]->getUniversity()->getName()}
</a>
</li>
<li n:if="$mode === 'specializations'">
Факультет:
<a href="/editdb?act=university&id={$request[0]->getUniversity()->getId()}">{$request[0]->getFaculty()->getName()}</a>
</li>
</div>
</ul>
<div id="{$request[0]->getId()}-edit-block" style="display: none;">
<input n:attr="placeholder => ($mode === 'cities' ? 'Название на английском' : 'Название')" name="name" type="text" value="{$request[0]->getName()}" id="{$request[0]->getId()}-name" />
<input n:if="$mode === 'cities'" placeholder="Родное название" name="name" type="text" value="{$request[0]->getNativeName()}" id="{$request[0]->getId()}-native_name" />
<input n:if="$mode !== 'cities'" placeholder="ID города" name="city-id" type="text" value="{$request[0]->getCity()->getId()}" id="{$request[0]->getId()}-city_id" />
<input n:if="$mode === 'faculties' || $mode === 'specializations'" placeholder="ID университета" name="university-id" type="text" value="{$request[0]->getUniversity()->getId()}" id="{$request[0]->getId()}-university_id" />
<input n:if="$mode === 'specializations'" placeholder="ID факультета" name="faculty-id" type="text" value="{$request[0]->getFaculty()->getId()}" id="{$request[0]->getId()}-faculty_id" />
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<center style="padding: 16px;">
<button class="button" onClick="performRequestAction({$request[0]->getId()}, true)">Добавить</button>
<button class="button" onClick="performRequestAction({$request[0]->getId()}, false)">Отклонить</button>
<button id="{$request[0]->getId()}-edit-button" class="button" onClick="editRequest({$request[0]->getId()})">Редактировать</button>
<button id="{$request[0]->getId()}-save-button" class="button" onClick="editRequest({$request[0]->getId()}, 1)" style="display: none;">Сохранить</button>
</center>
</div>
</div>
</div>
</div>
</div>
{if $country || $current_country}
{include "./GeodbForAdmins.js.xml", countries => $countries}
{/if}
{/block}

View file

@ -0,0 +1,96 @@
{extends "../@layout.xml"}
{block title}{$title}{/block}
{block header}{include title}{/block}
{block content}
{include "./tabs.xml", mode => $mode, country => $country}
<br />
<div">
<h4><a href="/editdb?act=country&id={$country->getId()}&edu=1&city={$school->getCity()->getId()}{if $mode === 'university'}&view=universities{/if}">{$school->getCity()->getNativeName()}</a> → {$school->getName()}</h4>
<form id="add-country-form" method="post">
<div id="cities-list-td-input">
<td width="120" valign="top">
<span class="nobold">Город: </span>
</td>
<td>
<input type="text" name="city" placeholder="Начните вводить название" id="city"
onInput="onChangeCityInput()" value="{$school->getCity()->getCanonicalName()}"/>
</td>
</div>
<div id="cities-list-td" style="display: none !important">
<div width="120" valign="top">
<span class="nobold"></span>
</div>
<td>
<center id="cities-not-found">Ничего не найдено</center>
<select id="cities-list" name="city-id" value="1">
<option value="{$school->getCity()->getId()}">{$school->getCity()->getNativeName()} ({$school->getCity()->getName()})</option>
</select>
</td>
</div>
<input type="text" name="name" placeholder="Название" value="{$school->getName()}"/>
<input type="hidden" name="hash" value="{$csrfToken}"/>
<div style="display: flex; justify-content: flex-end;">
<input type="submit" value="{_save}" class="button"/>
</div>
</form>
<div n:if="$mode === 'university'">
<div style="height: 1px; border-bottom: 1px solid #E8EBEE; margin: 8px 0;"/>
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE; padding: 8px 0;">
<h4 style="border: none;">Факультеты</h4>
<button class="button" onClick="addFaculty()">Добавить</button>
</div>
<div n:if="$can_view_deleted" class="tabs">
<div n:attr="id => !$is_deleted ? 'activetabs' : 'ki'" class="tab">
<a n:attr="id => !$is_deleted ? 'act_tab_a' : 'ki'"
href="/editdb?act=university&id={$school->getId()}">Активные</a>
</div>
<div n:attr="id => $is_deleted ? 'activetabs' : 'ki'" class="tab">
<a n:attr="id => $is_deleted ? 'act_tab_a' : 'ki'"
href="/editdb?act=university&id={$school->getId()}&deleted=1">Удаленные
</a>
</div>
</div>
<div n:if="count($faculties) <= 0" style="padding: 8px 0;">
{include "../components/nothing.xml"}
</div>
<ul n:if="count($faculties) > 0" style="padding-inline-start: 18px;" id="faculties">
<li n:foreach="$faculties as $faculty" id="faculty-{$faculty->getId()}">
<div style="display: flex; justify-content: space-between; border-bottom: 1px solid #E8EBEE;">
<h4 style="padding: 8px; margin-bottom: 4px; border: none;">
<span style="color: inherit; font-weight: unset;" id="faculty-{$faculty->getId()}-name">[#{$faculty->getId()}] {$faculty->getName()}</span>
<input type="text" value="{$faculty->getName()}" name="name" id="faculty-{$faculty->getId()}-name-input" style="display: none;" />
</h4>
<div style="display: flex; gap: 8px; align-self: center;">
<a id="faculty-{$faculty->getId()}-edit-icon" onClick="editFaculty({$faculty->getId()})">
<div class="icon edit-icon"/>
</a>
<a id="faculty-{$faculty->getId()}-save-icon" style="display: none;" onClick="saveFaculty({$faculty->getId()})">
<div class="icon save-icon" />
</a>
<a n:if="!$is_deleted" onClick="deleteFaculty({$faculty->getId()}, {$faculty->getName()})">
<div class="icon delete-icon"/>
</a>
<a n:if="$is_deleted" onClick="restoreFaculty({$faculty->getId()}, {$faculty->getName()})">
<div class="icon plus-icon"/>
</a>
<a n:if="!$is_deleted" onClick="getSpecializations({$faculty->getId()}, 0, false, false)">
<div class="icon list-icon"/>
</a>
</div>
</div>
<div id="faculty-{$faculty->getId()}-specializations" style="display: none;">
<a onClick="getSpecializations({$faculty->getId()}, 0, true, false)">Активные</a>
<span n:if="$can_view_deleted" style="color: inherit;">| <a onClick="getSpecializations({$faculty->getId()}, 1, true, true)">Удаленные</a></span>
| <a onClick="addSpecialization({$faculty->getId()}, {$faculty->getName()})">Добавить</a>
<ul id="faculty-{$faculty->getId()}-specializations-list"></ul>
</div>
</li>
</ul>
</div>
{include "./GeodbForAdmins.js.xml", mode => $mode}
</div>
{/block}

View file

@ -0,0 +1,61 @@
{block tabs}
<style>
#searchEditors {
height: 20px;
background: url("/assets/packages/static/openvk/img/search_icon.png") 3px 4px no-repeat rgb(255, 255, 255);
padding-left: 18px;
width: 200px;
}
#add-country-form > input {
margin: 8px 0;
}
.icon {
width: 12px;
height: 12px;
background: url("/assets/packages/static/openvk/img/common.png");
}
.delete-icon {
background-position: 0 -29px;
}
.edit-icon {
background-position: 0 -44px;
}
.plus-icon {
background-position: 0 0;
}
.save-icon {
background-position: 0 -15.5px;
}
.list-icon {
background-position: 0 -92.5px;
}
</style>
<div class="tabs">
<div n:attr="id => (($mode === 'countries' || $mode === 'country') ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => (($mode === 'countries' || $mode === 'country') ? 'act_tab_a' : 'ki')" href="/editdb?act=countries">Страны</a>
</div>
<div n:if="$isGeodbAdmin" n:attr="id => ($mode === 'editors' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($mode === 'editors' ? 'act_tab_a' : 'ki')" href="/editdb?act=editors">Редакторы</a>
</div>
<div n:if="$isGeodbAdmin" n:attr="id => ($mode === 'logs' ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($mode === 'logs' ? 'act_tab_a' : 'ki')" href="/editdb?act=logs">Логи</a>
</div>
<div n:if="($mode === 'countries' || $mode === 'add_country') && $can_add_country"
n:attr="id => ($mode === 'add_country' ? 'activetabs' : 'ki')" style="float: right" class="tab">
<a n:attr="id => ($mode === 'add_country' ? 'act_tab_a' : 'ki')" href="/editdb?act=add_country">Создать</a>
</div>
<div n:if="($mode === 'country' && !$is_edu)" n:attr="id => ($mode === 'add_city' ? 'activetabs' : 'ki')" style="float: right" class="tab">
<a n:attr="id => ($mode === 'add_city' ? 'act_tab_a' : 'ki')" href="/editdb?act=add_city&id={$country->getId()}">Создать</a>
</div>
<div n:if="($mode === 'country' && $is_edu)" n:attr="id => ($mode === 'add_edu' ? 'activetabs' : 'ki')" style="float: right" class="tab">
<a n:attr="id => ($mode === 'add_edu' ? 'act_tab_a' : 'ki')" href="/editdb?act=add_edu&id={$country->getId()}&view={$view}">Создать</a>
</div>
</div>
{/block}

View file

@ -51,7 +51,7 @@
</tr>
{/if}
{if !is_null($_GET['city']) && $_GET['city'] != "" && $x->getPrivacySetting("page.info.read") > 1}
<tr>
<tr n:if="$x->getCity() !== 'DELETED'">
<td><span class="nobold">{_city}:</span></td>
<td>{$x->getCity()}</td>
</tr>
@ -293,6 +293,7 @@
<div class="searchOptionName" id="n_main" onclick="hideParams('main')"><img src="/assets/packages/static/openvk/img/hide.png" class="searchHide">{_main}</div>
<div class="searchOptionBlock" id="s_main">
<input type="text" value="{if !is_null($_GET['status'])}{$_GET['status']}{/if}" form="searcher" placeholder="{_status}" name="status">
<input type="text" value="{if !is_null($_GET['city'])}{$_GET['country']}{/if}" form="searcher" placeholder="Страна" name="country">
<input type="text" value="{if !is_null($_GET['city'])}{$_GET['city']}{/if}" form="searcher" placeholder="{_city}" name="city">
<input type="text" value="{if !is_null($_GET['hometown'])}{$_GET['hometown']}{/if}" form="searcher" placeholder="{_hometown}" name="hometown">
<input name="is_online" type="checkbox" {if !is_null($_GET['is_online']) && $_GET['is_online'] == "1"}checked{/if} form="searcher" value="1">{_s_now_on_site}

View file

@ -12,6 +12,7 @@
{block content}
{var $isMain = $mode === 'main'}
{var $isContacts = $mode === 'contacts'}
{var $isEducation = $mode === 'education'}
{var $isInterests = $mode === 'interests'}
{var $isAvatar = $mode === 'avatar'}
{var $isBackDrop = $mode === 'backdrop'}
@ -28,6 +29,9 @@
<div n:attr="id => ($isContacts ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($isContacts ? 'act_tab_a' : 'ki')" href="/edit?act=contacts">{_contacts}</a>
</div>
<div n:attr="id => ($isEducation ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($isEducation ? 'act_tab_a' : 'ki')" href="/edit?act=education">Образование</a>
</div>
<div n:attr="id => ($isInterests ? 'activetabs' : 'ki')" class="tab">
<a n:attr="id => ($isInterests ? 'act_tab_a' : 'ki')" href="/edit?act=interests">{_interests}</a>
</div>
@ -205,10 +209,51 @@
</tr>
<tr>
<td width="120" valign="top">
<span class="nobold">{_city}: </span>
<span class="nobold">Страна: </span>
</td>
<td>
<input type="text" name="city" value="{$user->getCity()}" />
<input type="text" name="country" placeholder="Начните вводить название" id="country"
onInput="onChangeCountryInput()"
{if $user->getCountry()}value='{$user->getCountry()}'{/if} />
</td>
</tr>
<tr id="countries-list-td" style="display: none">
<td width="120" valign="top">
<span class="nobold"></span>
</td>
<td>
<center id="countries-not-found">Ничего не найдено</center>
<select id="countries-list" name="country-id" value="1">
{if $user->getCountry()}
<option value="{$user->getCountry(true)['id']}">{$user->getCountry(true)['native_name']}
({$user->getCountry(true)['name']})
</option>
{/if}
</select>
</td>
</tr>
<tr id="cities-list-td-input" style="display: none">
<td width="120" valign="top">
<span class="nobold">Город: </span>
</td>
<td>
<input type="text" name="city" placeholder="Начните вводить название" id="city" onInput="onChangeCityInput()" {if $user->getCity()}value='{$user->getCity()}'{/if} />
<a onClick="geodbRequest('cities')">Я не могу найти свой город</a>
</td>
</tr>
<tr id="cities-list-td" style="display: none">
<td width="120" valign="top">
<span class="nobold"></span>
</td>
<td>
<center id="cities-not-found">Ничего не найдено</center>
<select id="cities-list" name="city-id" value="1">
{if $user->getCity()}
<option value="{$user->getCity(true)['id']}">{$user->getCity(true)['native_name']}
({$user->getCity(true)['name']})
</option>
{/if}
</select>
</td>
</tr>
<tr>
@ -231,6 +276,198 @@
</tbody>
</table>
</form>
{include "../Geodb/GeodbForEdit.js.xml", user => $user}
{elseif $isEducation}
<style>.school-additional { display: none } .university-additional { display: none }</style>
<h4>Школа</h4>
<form action="/edit?act=education&type=school" method="POST" enctype="multipart/form-data">
<table cellspacing="7" cellpadding="0" width="60%" border="0" align="center">
<tbody>
<tr id="school-cities-list-td-input">
<td width="120" valign="top">
<span class="nobold">Город: </span>
</td>
<td>
<input type="text" name="city" placeholder="Начните вводить название" id="city"
onInput="onChangeSchoolCityInput(0)"/>
</td>
</tr>
<tr id="school-cities-list-td" style="display: none">
<td width="120" valign="top">
<span class="nobold"></span>
</td>
<td>
<center id="school-cities-not-found">Ничего не найдено</center>
<select id="school-cities-list" name="city-id" value="1" onchange="onChangeCitySelect(null, 0)">
</select>
</td>
</tr>
<div id="school-info" style="display: none;">
<tr id="schools" style="display: none;">
<td width="120" valign="top">
<span class="nobold">Школа:</span>
</td>
<td id="schools-block">
<center id="schools-not-found" style="padding: 16px;">Ничего не найдено</center>
<select id="schools-list" name="school-id" value="1">
</select>
</td>
</tr>
</div>
<tr class="school-additional-0" style="display: none;">
<td width="120" valign="top">
<span class="nobold">Год начала обучения:</span>
</td>
<td>
<input type="text" name="edu_start"
n:attr="value => $user->getSchoolYears()[0] != 0 ? $user->getSchoolYears()[0] : NULL"/>
</td>
</tr>
<tr class="school-additional-0" style="display: none;">
<td width="120" valign="top">
<span class="nobold">Год окончания обучения:</span>
</td>
<td>
<input type="text" name="edu_end"
n:attr="value => $user->getSchoolYears()[1] != 0 ? $user->getSchoolYears()[1] : NULL"/>
</td>
</tr>
<tr class="school-additional-0" style="display: none;">
<td width="120" valign="top">
<span class="nobold">Год выпуска:</span>
</td>
<td>
<input type="text" name="edu_graduation"
n:attr="value => $user->getSchoolYears()[2] != 0 ? $user->getSchoolYears()[2] : NULL"/>
</td>
</tr>
<tr class="school-additional-0" style="display: none;">
<td width="120" valign="top">
<span class="nobold">Специальность:</span>
</td>
<td>
<input type="text" name="edu_specialization" n:attr="value => $user->getSchoolSpecialization() ?? NULL" />
</td>
</tr>
<tr>
<td>
</td>
<td>
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" value="{_save}" class="button" />
<div><a onClick="geodbRequest('schools')">Я не могу найти свою школу</a></div>
</td>
</tr>
</tbody>
</table>
</form>
<h4>Университет</h4>
<form action="/edit?act=education&type=university" method="POST" enctype="multipart/form-data">
<table cellspacing="7" cellpadding="0" width="60%" border="0" align="center">
<tbody>
<tr id="university-cities-list-td-input">
<td width="120" valign="top">
<span class="nobold">Город: </span>
</td>
<td>
<input type="text" name="city" placeholder="Начните вводить название" id="university-city"
onInput="onChangeUniversityCityInput()"/>
</td>
</tr>
<tr id="university-cities-list-td" style="display: none">
<td width="120" valign="top">
<span class="nobold"></span>
</td>
<td>
<center id="university-cities-not-found">Ничего не найдено</center>
<select id="university-cities-list" name="city-id" value="1" onchange="onChangeUniversityCitySelect()">
</select>
</td>
</tr>
<div id="university-info">
<tr id="universities" style="display: none;">
<td width="120" valign="top">
<span class="nobold">Университет:</span>
</td>
<td id="universities-block">
<center id="universities-not-found" style="padding: 16px;">Ничего не найдено</center>
<select id="universities-list" name="university-id" value="1">
</select>
</td>
</tr>
</div>
<div id="faculty-info">
<tr id="faculties" style="display: none;">
<td width="120" valign="top">
<span class="nobold">Факультет:</span>
</td>
<td id="faculties-block">
<center id="faculties-not-found" style="padding: 16px;">Ничего не найдено</center>
<select id="faculties-list" name="faculty-id" value="1">
</select>
</td>
</tr>
</div>
<div id="specialization-info">
<tr id="specializations" style="display: none;">
<td width="120" valign="top">
<span class="nobold">Специализация:</span>
</td>
<td id="specializations-block">
<center id="specializations-not-found" style="padding: 16px;">Ничего не найдено</center>
<select id="specializations-list" name="specialization-id" value="1" onchange="onChangeSpecializationsCitySelect()">
</select>
</td>
</tr>
</div>
<tr class="university-additional">
<td width="120" valign="top">
<span class="nobold">Год начала обучения:</span>
</td>
<td>
<input type="text" name="edu_university_start"
n:attr="value => $user->getUniversityYears()[0] != 0 ? $user->getUniversityYears()[0] : NULL"/>
</td>
</tr>
<tr class="university-additional">
<td width="120" valign="top">
<span class="nobold">Год окончания обучения:</span>
</td>
<td>
<input type="text" name="edu_university_end"
n:attr="value => $user->getUniversityYears()[1] != 0 ? $user->getUniversityYears()[1] : NULL"/>
</td>
</tr>
<tr class="university-additional">
<td width="120" valign="top">
<span class="nobold">Год выпуска:</span>
</td>
<td>
<input type="text" name="edu_university_graduation"
n:attr="value => $user->getUniversityYears()[2] != 0 ? $user->getUniversityYears()[2] : NULL"/>
</td>
</tr>
<tr>
<td>
</td>
<td>
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" value="{_save}" class="button" />
<div>
<a onClick="geodbRequest('universities')">Я не могу найти свой университет</a>,
<a onClick="geodbRequest('faculties')">факультет</a>,
<a onClick="geodbRequest('specializations')">специальность</a>
</div>
</td>
</tr>
</tbody>
</table>
</form>
{include "../Geodb/GeodbForEdit.js.xml", user => $user}
{elseif $isInterests}

View file

@ -468,9 +468,13 @@
</a>
</td>
</tr>
<tr n:if="!is_null($user->getCountry())">
<td class="label"><span class="nobold">Страна:</span></td>
<td class="data"><a href="/search?type=users&query=&country={$user->getCountry(true)['id']}">{$user->getCountry()}</a></td>
</tr>
<tr n:if="!is_null($user->getCity())">
<td class="label"><span class="nobold">{_city}:</span></td>
<td class="data"><a href="/search?type=users&query=&city={$user->getCity()}">{$user->getCity()}</a></td>
<td class="data"><a href="/search?type=users&query=&city={$user->getCity(true)['id']}">{$user->getCity()}</a></td>
</tr>
<tr n:if="!is_null($user->getPhysicalAddress())">
<td class="label"><span class="nobold">{_address}:</span></td>
@ -543,6 +547,128 @@
</tr>
</tbody>
</table>
{/capture}
{capture $uInfo_Education}
<table class="ugc-table" border="0" cellspacing="0" cellpadding="0" border="0" cellspacing="0"
cellpadding="0" n:ifcontent>
<tbody n:ifcontent>
<tr>
<tr n:if="!is_null($user->getSchool())">
<td class="label">
<b>Школа:</b>
</td>
<td>
<a rel="ugc">
{$user->getSchool()->getName()}
</a>
</td>
</tr>
<tr n:if="!is_null($user->getSchoolYears()[0])">
<td class="label">
<span class="nobold">Год начала обучения:</span>
</td>
<td>
<a rel="ugc">
{$user->getSchoolYears()[0]}
</a>
</td>
</tr>
<tr n:if="!is_null($user->getSchoolYears()[1])">
<td class="label">
<span class="nobold">Год окончания обучения:</span>
</td>
<td>
<a rel="ugc">
{$user->getSchoolYears()[1]}
</a>
</td>
</tr>
<tr n:if="!is_null($user->getSchoolYears()[2])">
<td class="label">
<span class="nobold">Год выпуска:</span>
</td>
<td>
<a rel="ugc">
{$user->getSchoolYears()[2]}
</a>
</td>
</tr>
<tr n:if="!is_null($user->getSchoolSpecialization())">
<td class="label">
<span class="nobold">Специализация:</span>
</td>
<td>
<a rel="ugc">
{$user->getSchoolSpecialization()}
</a>
</td>
</tr>
</tr>
<tr n:if="!is_null($user->getUniversity())">
<tr>
<td class="label">
<b>Университет:</b>
</td>
<td>
<a rel="ugc">
{$user->getUniversity()->getName()}
</a>
</td>
</tr>
<tr n:if="!is_null($user->getUniversityYears()[0])">
<td class="label">
<span class="nobold">Год начала обучения:</span>
</td>
<td>
<a rel="ugc">
{$user->getUniversityYears()[0]}
</a>
</td>
</tr>
<tr n:if="!is_null($user->getUniversityYears()[1])">
<td class="label">
<span class="nobold">Год окончания обучения:</span>
</td>
<td>
<a rel="ugc">
{$user->getUniversityYears()[1]}
</a>
</td>
</tr>
<tr n:if="!is_null($user->getUniversityYears()[2])">
<td class="label">
<span class="nobold">Год выпуска:</span>
</td>
<td>
<a rel="ugc">
{$user->getUniversityYears()[2]}
</a>
</td>
</tr>
<tr n:if="!is_null($user->getUniversityFaculty())">
<td class="label">
<span class="nobold">Факультет:</span>
</td>
<td>
<a rel="ugc">
{$user->getUniversityFaculty()->getName()}
</a>
</td>
</tr>
<tr n:if="!is_null($user->getUniversitySpecialization())">
<td class="label">
<span class="nobold">Специализация:</span>
</td>
<td>
<a rel="ugc">
{$user->getUniversitySpecialization()->getName()}
</a>
</td>
</tr>
</tr>
</tbody>
</table>
{/capture}
<div>
<div style="padding: 10px 8px 15px 8px;" n:ifcontent>
@ -560,6 +686,17 @@
<div style="padding-top: 15px;color:gray;text-align: center;">{_no_information_provided}</div>
{/if}
</div>
<div style="padding: 10px 8px 15px 8px;" n:ifcontent>
<h4 style="border-bottom: none; font-size: 11px; padding: 0; display: inline-block;">
Образование {ifset $thisUser}{if $thisUser->getId() == $user->getId()}<a
href="/edit?act=education" class="edit_link">[ {_edit} ]</a>{/if}{/ifset}
</h4>
{if !empty($uInfo_Education)}
{$uInfo_Education|noescape}
{else}
<div style="padding: 15px;color:gray;text-align: center;">{_no_information_provided}</div>
{/if}
</div>
</div>
</div>

View file

@ -49,3 +49,11 @@ services:
- openvk\Web\Models\Repositories\BannedLinks
- openvk\Web\Models\Repositories\ChandlerGroups
- openvk\Web\Presenters\MaintenancePresenter
- openvk\Web\Presenters\GeodbPresenter
- openvk\Web\Models\Repositories\GeodbRights
- openvk\Web\Models\Repositories\GeodbCountries
- openvk\Web\Models\Repositories\GeodbCities
- openvk\Web\Models\Repositories\GeodbLogs
- openvk\Web\Models\Repositories\GeodbEducation
- openvk\Web\Models\Repositories\GeodbFaculties
- openvk\Web\Models\Repositories\GeodbSpecializations

View file

@ -349,6 +349,10 @@ routes:
handler: "About->dev"
- url: "/tour"
handler: "About->tour"
- url: "/editdb"
handler: "Geodb->index"
- url: "/geodb"
handler: "Geodb->forUser"
- url: "/{?shortCode}"
handler: "UnknownTextRouteStrategy->delegate"
placeholders:

BIN
Web/static/img/common.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -0,0 +1,141 @@
CREATE TABLE `geodb_cities` (
`id` bigint(20) UNSIGNED NOT NULL,
`country` bigint(20) UNSIGNED NOT NULL,
`name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`native_name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT 0,
`is_request` bigint(20) UNSIGNED DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `geodb_cities` (`id`, `country`, `name`, `native_name`, `deleted`, `is_request`) VALUES
(1, 1, 'Voskresensk', 'Воскресенск', 0, 0),
(2, 2, 'Los Angeles', 'Лос-Анджелес', 0, 0);
CREATE TABLE `geodb_countries` (
`id` bigint(20) UNSIGNED NOT NULL,
`code` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`flag` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`native_name` tinytext COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT 0,
`is_log` tinyint(1) NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `geodb_countries` (`id`, `code`, `flag`, `name`, `native_name`, `deleted`, `is_log`) VALUES
(1, 'ru', 'ru', 'Russia', 'Россия', 0, 0),
(2, 'us', 'us', 'USA', 'США', 0, 0);
CREATE TABLE `geodb_editors` (
`id` bigint(20) UNSIGNED NOT NULL,
`uid` bigint(20) UNSIGNED NOT NULL,
`country` bigint(20) UNSIGNED NOT NULL,
`edu` tinyint(1) NOT NULL DEFAULT 0,
`cities` tinyint(1) NOT NULL DEFAULT 0,
`deleted` tinyint(1) NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `geodb_faculties` (
`id` bigint(20) UNSIGNED NOT NULL,
`university` bigint(20) UNSIGNED NOT NULL,
`name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT 0,
`is_request` bigint(20) NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `geodb_logs` (
`id` bigint(20) UNSIGNED NOT NULL,
`user` bigint(20) UNSIGNED NOT NULL,
`type` int(11) NOT NULL,
`object_table` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
`object_model` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
`object_id` bigint(20) NOT NULL,
`logs_text` longtext COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `geodb_schools` (
`id` bigint(20) UNSIGNED NOT NULL,
`country` bigint(20) UNSIGNED NOT NULL,
`city` bigint(20) UNSIGNED NOT NULL,
`name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT 0,
`is_request` bigint(20) UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `geodb_specializations` (
`id` bigint(20) UNSIGNED NOT NULL,
`country` bigint(20) UNSIGNED NOT NULL,
`faculty` bigint(20) UNSIGNED NOT NULL,
`name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT 0,
`is_request` bigint(20) UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `geodb_universities` (
`id` bigint(20) UNSIGNED NOT NULL,
`country` bigint(20) UNSIGNED NOT NULL,
`city` bigint(20) UNSIGNED NOT NULL,
`name` tinytext COLLATE utf8mb4_unicode_ci NOT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT 0,
`is_request` bigint(20) UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `geodb_cities`
ADD PRIMARY KEY (`id`);
ALTER TABLE `geodb_countries`
ADD PRIMARY KEY (`id`);
ALTER TABLE `geodb_editors`
ADD PRIMARY KEY (`id`);
ALTER TABLE `geodb_faculties`
ADD PRIMARY KEY (`id`);
ALTER TABLE `geodb_logs`
ADD PRIMARY KEY (`id`);
ALTER TABLE `geodb_schools`
ADD PRIMARY KEY (`id`);
ALTER TABLE `geodb_specializations`
ADD PRIMARY KEY (`id`);
ALTER TABLE `geodb_universities`
ADD PRIMARY KEY (`id`);
ALTER TABLE `geodb_cities`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
ALTER TABLE `geodb_countries`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
ALTER TABLE `geodb_editors`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `geodb_faculties`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `geodb_logs`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `geodb_schools`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `geodb_specializations`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `geodb_universities`
MODIFY `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `profiles`
ADD `country` VARCHAR(60) NOT NULL AFTER `activated`,
ADD `country_id` BIGINT UNSIGNED NOT NULL AFTER `country`,
ADD `city_id` BIGINT UNSIGNED NOT NULL AFTER `country_id`,
ADD `school_id` BIGINT UNSIGNED NOT NULL AFTER `city_id`,
ADD `school_years` TINYTEXT NOT NULL AFTER `school_id`,
ADD `school_specialization` TINYTEXT NOT NULL AFTER `school_years`,
ADD `university_years` TINYTEXT NOT NULL AFTER `school_specialization`,
ADD `university_specialization` TINYTEXT NOT NULL AFTER `university_years`,
ADD `university` BIGINT UNSIGNED NOT NULL AFTER `university_specialization`,
ADD `university_faculty` BIGINT UNSIGNED NOT NULL AFTER `university`;

View file

@ -1430,3 +1430,22 @@
"mobile_like" = "Нравится";
"mobile_user_info_hide" = "Скрыть";
"mobile_user_info_show_details" = "Показать подробнее";
/* Geodb */
"geodb_cities_zero" = "нет городов";
"geodb_cities_one" = "$1 город";
"geodb_cities_few" = "$1 города";
"geodb_cities_many" = "$1 городов";
"geodb_cities_other" = "$1 городов";
"geodb_schools_zero" = "нет школ";
"geodb_schools_one" = "$1 школа";
"geodb_schools_few" = "$1 школы";
"geodb_schools_many" = "$1 школ";
"geodb_schools_other" = "$1 школ";
"geodb_university_zero" = "нет вузов";
"geodb_university_one" = "$1 вуз";
"geodb_university_few" = "$1 вуза";
"geodb_university_many" = "$1 вузов";
"geodb_university_other" = "$1 вузов";