Compare commits
2 Commits
d06433e2f6
...
8f7c704a90
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f7c704a90 | ||
|
|
b849c6feb6 |
@@ -28,6 +28,8 @@ public static class Constants
|
|||||||
public const string HeaderActionLabel = "HeaderActionLabel";
|
public const string HeaderActionLabel = "HeaderActionLabel";
|
||||||
public const string HeaderActionTarget = "HeaderActionTarget";
|
public const string HeaderActionTarget = "HeaderActionTarget";
|
||||||
public const string CreatePersonModel = "CreatePersonModel";
|
public const string CreatePersonModel = "CreatePersonModel";
|
||||||
|
public const string PeopleCountryOptions = "PeopleCountryOptions";
|
||||||
|
public const string PeopleCountryFilter = "PeopleCountryFilter";
|
||||||
public const string Prefix = "Prefix";
|
public const string Prefix = "Prefix";
|
||||||
public const string CanRemoveRows = "CanRemoveRows";
|
public const string CanRemoveRows = "CanRemoveRows";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class CountriesController : Controller
|
|||||||
private readonly ISieveProcessor sieveProcessor;
|
private readonly ISieveProcessor sieveProcessor;
|
||||||
private readonly PagingSettings pagingSettings;
|
private readonly PagingSettings pagingSettings;
|
||||||
|
|
||||||
public CountriesController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptions<PagingSettings> pagingSettings)
|
public CountriesController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptionsSnapshot<PagingSettings> pagingSettings)
|
||||||
{
|
{
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.sieveProcessor = sieveProcessor;
|
this.sieveProcessor = sieveProcessor;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class EventsController : Controller
|
|||||||
private readonly ISieveProcessor sieveProcessor;
|
private readonly ISieveProcessor sieveProcessor;
|
||||||
private readonly PagingSettings pagingSettings;
|
private readonly PagingSettings pagingSettings;
|
||||||
|
|
||||||
public EventsController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptions<PagingSettings> pagingSettings)
|
public EventsController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptionsSnapshot<PagingSettings> pagingSettings)
|
||||||
{
|
{
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.sieveProcessor = sieveProcessor;
|
this.sieveProcessor = sieveProcessor;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class PeopleController : Controller
|
|||||||
private readonly ISieveProcessor sieveProcessor;
|
private readonly ISieveProcessor sieveProcessor;
|
||||||
private readonly PagingSettings pagingSettings;
|
private readonly PagingSettings pagingSettings;
|
||||||
|
|
||||||
public PeopleController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptions<PagingSettings> pagingSettings)
|
public PeopleController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptionsSnapshot<PagingSettings> pagingSettings)
|
||||||
{
|
{
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.sieveProcessor = sieveProcessor;
|
this.sieveProcessor = sieveProcessor;
|
||||||
@@ -40,6 +40,7 @@ public class PeopleController : Controller
|
|||||||
return RedirectToAction("Index", "Countries");
|
return RedirectToAction("Index", "Countries");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await PopulatePeopleCountryFilterViewDataAsync(sieveModel.Filters);
|
||||||
var viewModel = await BuildPeopleListAsync(sieveModel);
|
var viewModel = await BuildPeopleListAsync(sieveModel);
|
||||||
if (Request.Headers.ContainsKey(Constants.HtmxHeaders.Request))
|
if (Request.Headers.ContainsKey(Constants.HtmxHeaders.Request))
|
||||||
{
|
{
|
||||||
@@ -155,6 +156,7 @@ public class PeopleController : Controller
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await PopulatePeopleCountryFilterViewDataAsync(sieveModel.Filters);
|
||||||
var viewModel = await BuildPeopleListAsync(sieveModel);
|
var viewModel = await BuildPeopleListAsync(sieveModel);
|
||||||
return PartialView("_PeopleList", viewModel);
|
return PartialView("_PeopleList", viewModel);
|
||||||
}
|
}
|
||||||
@@ -248,16 +250,16 @@ public class PeopleController : Controller
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await PopulatePeopleCountryFilterViewDataAsync(sieveModel.Filters);
|
||||||
var viewModel = await BuildPeopleListAsync(sieveModel);
|
var viewModel = await BuildPeopleListAsync(sieveModel);
|
||||||
return PartialView("_PeopleList", viewModel);
|
return PartialView("_PeopleList", viewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<PeoplePageViewModel> BuildPeopleListAsync(SieveModel sieveModel)
|
private async Task<PagedList<PersonViewModel>> BuildPeopleListAsync(SieveModel sieveModel)
|
||||||
{
|
{
|
||||||
sieveModel.SetDefaultPagingAndSorting(pagingSettings.PageSize, "LastNameTranscription");
|
sieveModel.SetDefaultPagingAndSorting(pagingSettings.PageSize, "LastNameTranscription");
|
||||||
var normalizedFilters = sieveModel.Filters?.Trim() ?? string.Empty;
|
var normalizedFilters = sieveModel.Filters?.Trim() ?? string.Empty;
|
||||||
var nameFilter = SieveModelExtensions.ExtractFilterValue(normalizedFilters, "FullNameTranscription");
|
var nameFilter = SieveModelExtensions.ExtractFilterValue(normalizedFilters, "FullNameTranscription");
|
||||||
var countryFilter = SieveModelExtensions.ExtractFilterValue(normalizedFilters, "CountryCode", "==");
|
|
||||||
|
|
||||||
var baseQuery = ctx.People
|
var baseQuery = ctx.People
|
||||||
.Select(p => new PersonViewModel
|
.Select(p => new PersonViewModel
|
||||||
@@ -308,12 +310,7 @@ public class PeopleController : Controller
|
|||||||
.Apply(sieveModel, baseQuery)
|
.Apply(sieveModel, baseQuery)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
return new PeoplePageViewModel
|
return new PagedList<PersonViewModel>(people, pagingInfo);
|
||||||
{
|
|
||||||
People = new PagedList<PersonViewModel>(people, pagingInfo),
|
|
||||||
CountryOptions = await GetCountryOptionsAsync(countryFilter),
|
|
||||||
CountryFilter = countryFilter
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<List<SelectListItem>> GetCountryOptionsAsync(string? selectedCode = null)
|
private async Task<List<SelectListItem>> GetCountryOptionsAsync(string? selectedCode = null)
|
||||||
@@ -329,4 +326,11 @@ public class PeopleController : Controller
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task PopulatePeopleCountryFilterViewDataAsync(string? filters)
|
||||||
|
{
|
||||||
|
var countryFilter = SieveModelExtensions.ExtractFilterValue(filters?.Trim() ?? string.Empty, "CountryCode", "==");
|
||||||
|
ViewData[Constants.ViewDataKeys.PeopleCountryOptions] = await GetCountryOptionsAsync(countryFilter);
|
||||||
|
ViewData[Constants.ViewDataKeys.PeopleCountryFilter] = countryFilter;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class RegistrationsController : Controller
|
|||||||
private readonly ISieveProcessor sieveProcessor;
|
private readonly ISieveProcessor sieveProcessor;
|
||||||
private readonly PagingSettings pagingSettings;
|
private readonly PagingSettings pagingSettings;
|
||||||
|
|
||||||
public RegistrationsController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptions<PagingSettings> pagingSettings)
|
public RegistrationsController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptionsSnapshot<PagingSettings> pagingSettings)
|
||||||
{
|
{
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.sieveProcessor = sieveProcessor;
|
this.sieveProcessor = sieveProcessor;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class SportsController : Controller
|
|||||||
private readonly ISieveProcessor sieveProcessor;
|
private readonly ISieveProcessor sieveProcessor;
|
||||||
private readonly PagingSettings pagingSettings;
|
private readonly PagingSettings pagingSettings;
|
||||||
|
|
||||||
public SportsController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptions<PagingSettings> pagingSettings)
|
public SportsController(EventsContext ctx, ISieveProcessor sieveProcessor, IOptionsSnapshot<PagingSettings> pagingSettings)
|
||||||
{
|
{
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.sieveProcessor = sieveProcessor;
|
this.sieveProcessor = sieveProcessor;
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
||||||
|
|
||||||
namespace Events.MVC.Models.People;
|
|
||||||
|
|
||||||
public class PeoplePageViewModel
|
|
||||||
{
|
|
||||||
public PagedList<PersonViewModel> People { get; set; } = new([], new PagingInfo());
|
|
||||||
|
|
||||||
public List<SelectListItem> CountryOptions { get; set; } = [];
|
|
||||||
|
|
||||||
public string CountryFilter { get; set; } = string.Empty;
|
|
||||||
}
|
|
||||||
@@ -14,7 +14,7 @@ public class PagerTagHelper : TagHelper
|
|||||||
private readonly IUrlHelperFactory urlHelperFactory;
|
private readonly IUrlHelperFactory urlHelperFactory;
|
||||||
private readonly PagingSettings pagingSettings;
|
private readonly PagingSettings pagingSettings;
|
||||||
|
|
||||||
public PagerTagHelper(IUrlHelperFactory urlHelperFactory, IOptions<PagingSettings> pagingSettings)
|
public PagerTagHelper(IUrlHelperFactory urlHelperFactory, IOptionsSnapshot<PagingSettings> pagingSettings)
|
||||||
{
|
{
|
||||||
this.urlHelperFactory = urlHelperFactory;
|
this.urlHelperFactory = urlHelperFactory;
|
||||||
this.pagingSettings = pagingSettings.Value;
|
this.pagingSettings = pagingSettings.Value;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@model Events.MVC.Models.People.PeoplePageViewModel
|
@model PagedList<Events.MVC.Models.People.PersonViewModel>
|
||||||
|
|
||||||
@{
|
@{
|
||||||
ViewData[Constants.ViewDataKeys.Title] = "People";
|
ViewData[Constants.ViewDataKeys.Title] = "People";
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
@model Events.MVC.Models.People.PeoplePageViewModel
|
@model PagedList<Events.MVC.Models.People.PersonViewModel>
|
||||||
|
@{
|
||||||
|
var countryFilter = ViewData[Constants.ViewDataKeys.PeopleCountryFilter] as string ?? string.Empty;
|
||||||
|
var countryOptions = ViewData[Constants.ViewDataKeys.PeopleCountryOptions] as IEnumerable<SelectListItem>
|
||||||
|
?? Enumerable.Empty<SelectListItem>();
|
||||||
|
}
|
||||||
|
|
||||||
<section class="card border-0 shadow-sm" id="people-list">
|
<section class="card border-0 shadow-sm" id="people-list">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div id="people-state" class="d-none">
|
<div id="people-state" class="d-none">
|
||||||
<input type="hidden" name="page" value="@Model.People.PagingInfo.CurrentPage" />
|
<input type="hidden" name="page" value="@Model.PagingInfo.CurrentPage" />
|
||||||
<input type="hidden" name="pageSize" value="@Model.People.PagingInfo.ItemsPerPage" />
|
<input type="hidden" name="pageSize" value="@Model.PagingInfo.ItemsPerPage" />
|
||||||
<input type="hidden" name="sorts" value="@Model.People.PagingInfo.Sorts" />
|
<input type="hidden" name="sorts" value="@Model.PagingInfo.Sorts" />
|
||||||
<input type="hidden" name="filters" value="@Model.People.PagingInfo.Filters" />
|
<input type="hidden" name="filters" value="@Model.PagingInfo.Filters" />
|
||||||
<input type="hidden" name="countryFilter" value="@Model.CountryFilter" />
|
<input type="hidden" name="countryFilter" value="@countryFilter" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form
|
<form
|
||||||
@@ -20,40 +25,40 @@
|
|||||||
hx-push-url="true"
|
hx-push-url="true"
|
||||||
onsubmit="var input=this.querySelector('[data-name-filter-input]'); var country=this.querySelector('[name=countryFilter]'); var filters=this.querySelector('[name=filters]'); var values=[]; if (input && input.value.trim()) { values.push('FullNameTranscription' + String.fromCharCode(64) + '=*' + input.value.trim()); } if (country && country.value) { values.push('CountryCode==' + country.value); } filters.value=values.join(','); this.querySelector('[name=page]').value='1';">
|
onsubmit="var input=this.querySelector('[data-name-filter-input]'); var country=this.querySelector('[name=countryFilter]'); var filters=this.querySelector('[name=filters]'); var values=[]; if (input && input.value.trim()) { values.push('FullNameTranscription' + String.fromCharCode(64) + '=*' + input.value.trim()); } if (country && country.value) { values.push('CountryCode==' + country.value); } filters.value=values.join(','); this.querySelector('[name=page]').value='1';">
|
||||||
<input type="hidden" name="page" value="1" />
|
<input type="hidden" name="page" value="1" />
|
||||||
<input type="hidden" name="pageSize" value="@Model.People.PagingInfo.ItemsPerPage" />
|
<input type="hidden" name="pageSize" value="@Model.PagingInfo.ItemsPerPage" />
|
||||||
<input type="hidden" name="sorts" value="@Model.People.PagingInfo.Sorts" />
|
<input type="hidden" name="sorts" value="@Model.PagingInfo.Sorts" />
|
||||||
<input type="hidden" name="filters" value="@Model.People.PagingInfo.Filters" />
|
<input type="hidden" name="filters" value="@Model.PagingInfo.Filters" />
|
||||||
|
|
||||||
<div class="d-flex align-items-center gap-3 pt-2">
|
<div class="d-flex align-items-center gap-3 pt-2">
|
||||||
<h2 class="h5 mb-0">People list</h2>
|
<h2 class="h5 mb-0">People list</h2>
|
||||||
<span class="badge text-bg-light">@(Model.People.PagingInfo.IsFiltered ? $"{Model.People.PagingInfo.FilteredItemsCount} / {Model.People.PagingInfo.TotalItemsCount}" : Model.People.PagingInfo.TotalItemsCount.ToString())</span>
|
<span class="badge text-bg-light">@(Model.PagingInfo.IsFiltered ? $"{Model.PagingInfo.FilteredItemsCount} / {Model.PagingInfo.TotalItemsCount}" : Model.PagingInfo.TotalItemsCount.ToString())</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex align-items-center gap-2 flex-nowrap ms-auto">
|
<div class="d-flex align-items-center gap-2 flex-nowrap ms-auto">
|
||||||
<input
|
<input
|
||||||
id="personNameFilter"
|
id="personNameFilter"
|
||||||
value="@Model.People.PagingInfo.NameFilter"
|
value="@Model.PagingInfo.NameFilter"
|
||||||
data-name-filter-input
|
data-name-filter-input
|
||||||
class="form-control"
|
class="form-control"
|
||||||
style="max-width: 18rem;"
|
style="max-width: 18rem;"
|
||||||
placeholder="Search by transcribed full name"
|
placeholder="Search by transcribed full name"
|
||||||
aria-label="Filter by transcribed full name" />
|
aria-label="Filter by transcribed full name" />
|
||||||
|
|
||||||
<select name="countryFilter" asp-items="Model.CountryOptions" class="form-select" style="max-width: 14rem;" aria-label="Filter by country">
|
<select name="countryFilter" asp-items="countryOptions" class="form-select" style="max-width: 14rem;" aria-label="Filter by country">
|
||||||
<option value="">All countries</option>
|
<option value="">All countries</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-outline-primary">Filter</button>
|
<button type="submit" class="btn btn-outline-primary">Filter</button>
|
||||||
@if (Model.People.PagingInfo.IsFiltered)
|
@if (Model.PagingInfo.IsFiltered)
|
||||||
{
|
{
|
||||||
<a
|
<a
|
||||||
asp-action="Index"
|
asp-action="Index"
|
||||||
asp-route-page="1"
|
asp-route-page="1"
|
||||||
asp-route-pageSize="@Model.People.PagingInfo.ItemsPerPage"
|
asp-route-pageSize="@Model.PagingInfo.ItemsPerPage"
|
||||||
asp-route-sorts="@Model.People.PagingInfo.Sorts"
|
asp-route-sorts="@Model.PagingInfo.Sorts"
|
||||||
asp-route-filters=""
|
asp-route-filters=""
|
||||||
class="btn btn-outline-secondary"
|
class="btn btn-outline-secondary"
|
||||||
hx-get="@Url.Action("Index", "People", new { page = 1, pageSize = Model.People.PagingInfo.ItemsPerPage, sorts = Model.People.PagingInfo.Sorts, filters = string.Empty })"
|
hx-get="@Url.Action("Index", "People", new { page = 1, pageSize = Model.PagingInfo.ItemsPerPage, sorts = Model.PagingInfo.Sorts, filters = string.Empty })"
|
||||||
hx-target="#people-list"
|
hx-target="#people-list"
|
||||||
hx-swap="outerHTML"
|
hx-swap="outerHTML"
|
||||||
hx-push-url="true">
|
hx-push-url="true">
|
||||||
@@ -68,41 +73,41 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
<a asp-action="Index" asp-route-page="@Model.People.PagingInfo.CurrentPage" asp-route-pageSize="@Model.People.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.People.PagingInfo.ToggleSort("Id")" asp-route-filters="@Model.People.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.People.PagingInfo.CurrentPage, pageSize = Model.People.PagingInfo.ItemsPerPage, sorts = Model.People.PagingInfo.ToggleSort("Id"), filters = Model.People.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
<a asp-action="Index" asp-route-page="@Model.PagingInfo.CurrentPage" asp-route-pageSize="@Model.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.PagingInfo.ToggleSort("Id")" asp-route-filters="@Model.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.PagingInfo.CurrentPage, pageSize = Model.PagingInfo.ItemsPerPage, sorts = Model.PagingInfo.ToggleSort("Id"), filters = Model.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
||||||
ID@(Model.People.PagingInfo.IsSortedBy("Id") ? (Model.People.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
ID@(Model.PagingInfo.IsSortedBy("Id") ? (Model.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a asp-action="Index" asp-route-page="@Model.People.PagingInfo.CurrentPage" asp-route-pageSize="@Model.People.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.People.PagingInfo.ToggleSort("FirstNameTranscription")" asp-route-filters="@Model.People.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.People.PagingInfo.CurrentPage, pageSize = Model.People.PagingInfo.ItemsPerPage, sorts = Model.People.PagingInfo.ToggleSort("FirstNameTranscription"), filters = Model.People.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
<a asp-action="Index" asp-route-page="@Model.PagingInfo.CurrentPage" asp-route-pageSize="@Model.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.PagingInfo.ToggleSort("FirstNameTranscription")" asp-route-filters="@Model.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.PagingInfo.CurrentPage, pageSize = Model.PagingInfo.ItemsPerPage, sorts = Model.PagingInfo.ToggleSort("FirstNameTranscription"), filters = Model.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
||||||
First name@(Model.People.PagingInfo.IsSortedBy("FirstNameTranscription") ? (Model.People.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
First name@(Model.PagingInfo.IsSortedBy("FirstNameTranscription") ? (Model.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a asp-action="Index" asp-route-page="@Model.People.PagingInfo.CurrentPage" asp-route-pageSize="@Model.People.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.People.PagingInfo.ToggleSort("LastNameTranscription")" asp-route-filters="@Model.People.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.People.PagingInfo.CurrentPage, pageSize = Model.People.PagingInfo.ItemsPerPage, sorts = Model.People.PagingInfo.ToggleSort("LastNameTranscription"), filters = Model.People.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
<a asp-action="Index" asp-route-page="@Model.PagingInfo.CurrentPage" asp-route-pageSize="@Model.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.PagingInfo.ToggleSort("LastNameTranscription")" asp-route-filters="@Model.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.PagingInfo.CurrentPage, pageSize = Model.PagingInfo.ItemsPerPage, sorts = Model.PagingInfo.ToggleSort("LastNameTranscription"), filters = Model.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
||||||
Last name@(Model.People.PagingInfo.IsSortedBy("LastNameTranscription") ? (Model.People.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
Last name@(Model.PagingInfo.IsSortedBy("LastNameTranscription") ? (Model.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
<th>
|
<th>
|
||||||
<a asp-action="Index" asp-route-page="@Model.People.PagingInfo.CurrentPage" asp-route-pageSize="@Model.People.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.People.PagingInfo.ToggleSort("BirthDate")" asp-route-filters="@Model.People.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.People.PagingInfo.CurrentPage, pageSize = Model.People.PagingInfo.ItemsPerPage, sorts = Model.People.PagingInfo.ToggleSort("BirthDate"), filters = Model.People.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
<a asp-action="Index" asp-route-page="@Model.PagingInfo.CurrentPage" asp-route-pageSize="@Model.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.PagingInfo.ToggleSort("BirthDate")" asp-route-filters="@Model.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.PagingInfo.CurrentPage, pageSize = Model.PagingInfo.ItemsPerPage, sorts = Model.PagingInfo.ToggleSort("BirthDate"), filters = Model.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
||||||
Birth date@(Model.People.PagingInfo.IsSortedBy("BirthDate") ? (Model.People.PagingInfo.IsDescending() ? " v" : " ^") : "")
|
Birth date@(Model.PagingInfo.IsSortedBy("BirthDate") ? (Model.PagingInfo.IsDescending() ? " v" : " ^") : "")
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a asp-action="Index" asp-route-page="@Model.People.PagingInfo.CurrentPage" asp-route-pageSize="@Model.People.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.People.PagingInfo.ToggleSort("CountryName")" asp-route-filters="@Model.People.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.People.PagingInfo.CurrentPage, pageSize = Model.People.PagingInfo.ItemsPerPage, sorts = Model.People.PagingInfo.ToggleSort("CountryName"), filters = Model.People.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
<a asp-action="Index" asp-route-page="@Model.PagingInfo.CurrentPage" asp-route-pageSize="@Model.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.PagingInfo.ToggleSort("CountryName")" asp-route-filters="@Model.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.PagingInfo.CurrentPage, pageSize = Model.PagingInfo.ItemsPerPage, sorts = Model.PagingInfo.ToggleSort("CountryName"), filters = Model.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
||||||
Country@(Model.People.PagingInfo.IsSortedBy("CountryName") ? (Model.People.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
Country@(Model.PagingInfo.IsSortedBy("CountryName") ? (Model.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a asp-action="Index" asp-route-page="@Model.People.PagingInfo.CurrentPage" asp-route-pageSize="@Model.People.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.People.PagingInfo.ToggleSort("RegistrationsCount")" asp-route-filters="@Model.People.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.People.PagingInfo.CurrentPage, pageSize = Model.People.PagingInfo.ItemsPerPage, sorts = Model.People.PagingInfo.ToggleSort("RegistrationsCount"), filters = Model.People.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
<a asp-action="Index" asp-route-page="@Model.PagingInfo.CurrentPage" asp-route-pageSize="@Model.PagingInfo.ItemsPerPage" asp-route-sorts="@Model.PagingInfo.ToggleSort("RegistrationsCount")" asp-route-filters="@Model.PagingInfo.Filters" class="link-dark link-underline-opacity-0" hx-get="@Url.Action("Index", "People", new { page = Model.PagingInfo.CurrentPage, pageSize = Model.PagingInfo.ItemsPerPage, sorts = Model.PagingInfo.ToggleSort("RegistrationsCount"), filters = Model.PagingInfo.Filters })" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
||||||
Registrations@(Model.People.PagingInfo.IsSortedBy("RegistrationsCount") ? (Model.People.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
Registrations@(Model.PagingInfo.IsSortedBy("RegistrationsCount") ? (Model.PagingInfo.IsDescending() ? " ↓" : " ↑") : "")
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th class="text-end"></th>
|
<th class="text-end"></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@if (Model.People.Data.Count == 0)
|
@if (Model.Data.Count == 0)
|
||||||
{
|
{
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="8" class="text-body-secondary">No people to display.</td>
|
<td colspan="8" class="text-body-secondary">No people to display.</td>
|
||||||
@@ -110,7 +115,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@foreach (var person in Model.People.Data)
|
@foreach (var person in Model.Data)
|
||||||
{
|
{
|
||||||
<partial name="_PersonRow" model="person" />
|
<partial name="_PersonRow" model="person" />
|
||||||
}
|
}
|
||||||
@@ -121,24 +126,24 @@
|
|||||||
|
|
||||||
<div class="d-flex justify-content-between align-items-center mt-4 gap-3 flex-wrap">
|
<div class="d-flex justify-content-between align-items-center mt-4 gap-3 flex-wrap">
|
||||||
<div class="d-flex align-items-center gap-2 flex-wrap">
|
<div class="d-flex align-items-center gap-2 flex-wrap">
|
||||||
<small class="text-body-secondary">Page @Model.People.PagingInfo.CurrentPage of @Model.People.PagingInfo.TotalPages</small>
|
<small class="text-body-secondary">Page @Model.PagingInfo.CurrentPage of @Model.PagingInfo.TotalPages</small>
|
||||||
<form asp-action="Index" method="get" class="d-inline-flex align-items-center gap-2" hx-get="@Url.Action("Index", "People")" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
<form asp-action="Index" method="get" class="d-inline-flex align-items-center gap-2" hx-get="@Url.Action("Index", "People")" hx-target="#people-list" hx-swap="outerHTML" hx-push-url="true">
|
||||||
<input type="hidden" name="page" value="1" />
|
<input type="hidden" name="page" value="1" />
|
||||||
<input type="hidden" name="sorts" value="@Model.People.PagingInfo.Sorts" />
|
<input type="hidden" name="sorts" value="@Model.PagingInfo.Sorts" />
|
||||||
<input type="hidden" name="filters" value="@Model.People.PagingInfo.Filters" />
|
<input type="hidden" name="filters" value="@Model.PagingInfo.Filters" />
|
||||||
<select name="pageSize" class="form-select form-select-sm" style="width: auto;" aria-label="Items per page" onchange="this.form.requestSubmit()">
|
<select name="pageSize" class="form-select form-select-sm" style="width: auto;" aria-label="Items per page" onchange="this.form.requestSubmit()">
|
||||||
@{
|
@{
|
||||||
int[] pageSizeOptions = [10, 20, 50, 100];
|
int[] pageSizeOptions = [10, 20, 50, 100];
|
||||||
}
|
}
|
||||||
@foreach (var option in pageSizeOptions)
|
@foreach (var option in pageSizeOptions)
|
||||||
{
|
{
|
||||||
<option value="@option" selected="@(Model.People.PagingInfo.ItemsPerPage == option)">@option</option>
|
<option value="@option" selected="@(Model.PagingInfo.ItemsPerPage == option)">@option</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<pager
|
<pager
|
||||||
page-info="@Model.People.PagingInfo"
|
page-info="@Model.PagingInfo"
|
||||||
page-action="Index"
|
page-action="Index"
|
||||||
page-title="Enter a page number and press Enter"
|
page-title="Enter a page number and press Enter"
|
||||||
page-target="#people-list"
|
page-target="#people-list"
|
||||||
|
|||||||
@@ -56,11 +56,7 @@ internal sealed class UiTestHarness : IAsyncDisposable
|
|||||||
CreateNoWindow = true
|
CreateNoWindow = true
|
||||||
};
|
};
|
||||||
startInfo.Environment["ASPNETCORE_ENVIRONMENT"] = "UITest";
|
startInfo.Environment["ASPNETCORE_ENVIRONMENT"] = "UITest";
|
||||||
#if POSTGRES
|
|
||||||
startInfo.Environment["ConnectionStrings__EventsPostgres"] = ResolveUiTestConnectionString();
|
startInfo.Environment["ConnectionStrings__EventsPostgres"] = ResolveUiTestConnectionString();
|
||||||
#else
|
|
||||||
startInfo.Environment["ConnectionStrings__EventsMssql"] = ResolveUiTestConnectionString();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var appProcess = Process.Start(startInfo)
|
var appProcess = Process.Start(startInfo)
|
||||||
?? throw new InvalidOperationException("Failed to start the MVC app process for UI tests.");
|
?? throw new InvalidOperationException("Failed to start the MVC app process for UI tests.");
|
||||||
@@ -171,11 +167,11 @@ internal sealed class UiTestHarness : IAsyncDisposable
|
|||||||
.AddUserSecrets<Program>(optional: true)
|
.AddUserSecrets<Program>(optional: true)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var connectionString = configuration.GetConnectionString("EventDB-Test");
|
var connectionString = configuration.GetConnectionString("EventsPostgres-Test");
|
||||||
if (string.IsNullOrWhiteSpace(connectionString))
|
if (string.IsNullOrWhiteSpace(connectionString))
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
"The EventDB-Test connection string must be available so UI tests can connect to the selected provider's test database.");
|
"The EventsPostgres-Test connection string must be available so UI tests can connect to the PostgreSQL test database on port 5433.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return connectionString;
|
return connectionString;
|
||||||
|
|||||||
@@ -39,5 +39,5 @@ dotnet test Events-MVC\Tests\Events.Tests.UITests\Events.Tests.UITests.csproj --
|
|||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- The UI test harness starts the MVC application automatically
|
- The UI test harness starts the MVC application automatically
|
||||||
- UI tests connect the MVC application to the selected provider's test database from `ConnectionStrings:EventDB-Test`
|
- UI tests connect the MVC application to the PostgreSQL test database on port `5433` from `ConnectionStrings:EventsPostgres-Test`
|
||||||
- The browser is currently configured in headless mode
|
- The browser is currently configured in headless mode
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Events.MVC.Models;
|
|||||||
using Events.MVC.Models.People;
|
using Events.MVC.Models.People;
|
||||||
using Events.Tests.UnitTests.Infrastructure;
|
using Events.Tests.UnitTests.Infrastructure;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Sieve.Models;
|
using Sieve.Models;
|
||||||
|
|
||||||
@@ -59,8 +60,8 @@ public class PeopleControllerShould
|
|||||||
|
|
||||||
var partial = Assert.IsType<PartialViewResult>(result);
|
var partial = Assert.IsType<PartialViewResult>(result);
|
||||||
Assert.Equal("_PeopleList", partial.ViewName);
|
Assert.Equal("_PeopleList", partial.ViewName);
|
||||||
var model = Assert.IsType<PeoplePageViewModel>(partial.Model);
|
var model = Assert.IsType<PagedList<PersonViewModel>>(partial.Model);
|
||||||
Assert.Contains(model.People.Data, p => p.FullName == "Ana Kovac" && p.CountryName == "Croatia");
|
Assert.Contains(model.Data, p => p.FullName == "Ana Kovac" && p.CountryName == "Croatia");
|
||||||
Assert.Contains("was added successfully", controller.Response.Headers[Events.MVC.Constants.HtmxHeaders.Trigger].ToString());
|
Assert.Contains("was added successfully", controller.Response.Headers[Events.MVC.Constants.HtmxHeaders.Trigger].ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,8 +101,8 @@ public class PeopleControllerShould
|
|||||||
|
|
||||||
var partial = Assert.IsType<PartialViewResult>(result);
|
var partial = Assert.IsType<PartialViewResult>(result);
|
||||||
Assert.Equal("_PeopleList", partial.ViewName);
|
Assert.Equal("_PeopleList", partial.ViewName);
|
||||||
var model = Assert.IsType<PeoplePageViewModel>(partial.Model);
|
var model = Assert.IsType<PagedList<PersonViewModel>>(partial.Model);
|
||||||
var person = Assert.Single(model.People.Data);
|
var person = Assert.Single(model.Data);
|
||||||
Assert.Equal("Ana Kovac", person.FullName);
|
Assert.Equal("Ana Kovac", person.FullName);
|
||||||
Assert.Equal("Croatia", person.CountryName);
|
Assert.Equal("Croatia", person.CountryName);
|
||||||
}
|
}
|
||||||
@@ -178,8 +179,8 @@ public class PeopleControllerShould
|
|||||||
});
|
});
|
||||||
|
|
||||||
var view = Assert.IsType<ViewResult>(result);
|
var view = Assert.IsType<ViewResult>(result);
|
||||||
var model = Assert.IsType<PeoplePageViewModel>(view.Model);
|
var model = Assert.IsType<PagedList<PersonViewModel>>(view.Model);
|
||||||
var people = Assert.Single(model.People.Data);
|
var people = Assert.Single(model.Data);
|
||||||
Assert.Equal(1, people.Id);
|
Assert.Equal(1, people.Id);
|
||||||
Assert.Equal("Ђорђе Петровић", people.FullName);
|
Assert.Equal("Ђорђе Петровић", people.FullName);
|
||||||
}
|
}
|
||||||
@@ -203,11 +204,12 @@ public class PeopleControllerShould
|
|||||||
});
|
});
|
||||||
|
|
||||||
var view = Assert.IsType<ViewResult>(result);
|
var view = Assert.IsType<ViewResult>(result);
|
||||||
var model = Assert.IsType<PeoplePageViewModel>(view.Model);
|
var model = Assert.IsType<PagedList<PersonViewModel>>(view.Model);
|
||||||
var person = Assert.Single(model.People.Data);
|
var person = Assert.Single(model.Data);
|
||||||
Assert.Equal("Ana Novak", person.FullName);
|
Assert.Equal("Ana Novak", person.FullName);
|
||||||
Assert.Equal("SI", model.CountryFilter);
|
Assert.Equal("SI", Assert.IsType<string>(view.ViewData[Events.MVC.Constants.ViewDataKeys.PeopleCountryFilter]));
|
||||||
Assert.Contains(model.CountryOptions, option => option.Value == "SI" && option.Selected);
|
var countryOptions = Assert.IsAssignableFrom<IEnumerable<SelectListItem>>(view.ViewData[Events.MVC.Constants.ViewDataKeys.PeopleCountryOptions]);
|
||||||
|
Assert.Contains(countryOptions, option => option.Value == "SI" && option.Selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public class SportsControllerShould
|
|||||||
new Sport { Id = 3, Name = "Cycling" });
|
new Sport { Id = 3, Name = "Cycling" });
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
|
|
||||||
var optionsMock = new Mock<IOptions<PagingSettings>>();
|
var optionsMock = new Mock<IOptionsSnapshot<PagingSettings>>();
|
||||||
optionsMock
|
optionsMock
|
||||||
.SetupGet(options => options.Value)
|
.SetupGet(options => options.Value)
|
||||||
.Returns(new PagingSettings { PageSize = 2 });
|
.Returns(new PagingSettings { PageSize = 2 });
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ internal static class ControllerTestContext
|
|||||||
return new EventsContext(options);
|
return new EventsContext(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IOptions<PagingSettings> CreatePagingOptions(int pageSize = 10)
|
public static IOptionsSnapshot<PagingSettings> CreatePagingOptions(int pageSize = 10)
|
||||||
{
|
{
|
||||||
return Options.Create(new PagingSettings { PageSize = pageSize });
|
return new TestOptionsSnapshot<PagingSettings>(new PagingSettings { PageSize = pageSize });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SieveModel EmptySieveModel()
|
public static SieveModel EmptySieveModel()
|
||||||
@@ -95,4 +95,12 @@ internal static class ControllerTestContext
|
|||||||
Name = name
|
Name = name
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class TestOptionsSnapshot<TOptions>(TOptions value) : IOptionsSnapshot<TOptions>
|
||||||
|
where TOptions : class
|
||||||
|
{
|
||||||
|
public TOptions Value => value;
|
||||||
|
|
||||||
|
public TOptions Get(string? name) => value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ public class ProviderSpecificQueryShould
|
|||||||
ctx.People.Add(ControllerTestContext.CreatePerson());
|
ctx.People.Add(ControllerTestContext.CreatePerson());
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
|
|
||||||
var people = await ctx.People
|
var people = await ctx.People
|
||||||
.Where(person => person.FirstName != null && Microsoft.EntityFrameworkCore.EF.Functions.ILike(person.FirstName, "%iv%"))
|
.Where(person => person.FirstName != null && Microsoft.EntityFrameworkCore.EF.Functions.ILike(person.FirstName, "%iv%"))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
Assert.Single(people);
|
Assert.Single(people);
|
||||||
Assert.Equal("Ivan", people[0].FirstName);
|
Assert.Equal("Ivan", people[0].FirstName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ThrowInvalidOperationExceptionWhenUsingILikeWithInMemoryProvider()
|
public async Task ThrowInvalidOperationExceptionWhenUsingILikeWithInMemoryProvider()
|
||||||
@@ -47,10 +47,10 @@ public class ProviderSpecificQueryShould
|
|||||||
.AddUserSecrets<ProviderSpecificQueryShould>(optional: true)
|
.AddUserSecrets<ProviderSpecificQueryShould>(optional: true)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var productionConnectionString = configuration.GetConnectionString("EventDB-Test");
|
var productionConnectionString = configuration.GetConnectionString("EventsPostgres");
|
||||||
Assert.False(
|
Assert.False(
|
||||||
string.IsNullOrWhiteSpace(productionConnectionString),
|
string.IsNullOrWhiteSpace(productionConnectionString),
|
||||||
"The EventDB-Test connection string must be available so the PostgreSQL-backed provider test can connect to the PostgreSQL copy.");
|
"The EventsPostgres connection string must be available so the PostgreSQL-backed provider test can connect to the PostgreSQL copy.");
|
||||||
|
|
||||||
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(productionConnectionString)
|
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(productionConnectionString)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ConnectionStrings": {
|
"ConnectionStrings": {
|
||||||
"EventDB-Test": "Host=localhost;Port=5433;Database=events;Username=sport;Persist Security Info=True;"
|
"EventsPostgres": "Host=localhost;Port=5433;Database=events;Username=sport;Persist Security Info=True;"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
docker-definitions/postgres-eventsdb-test/.env.example
Normal file
9
docker-definitions/postgres-eventsdb-test/.env.example
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# PostgreSQL admin (superuser)
|
||||||
|
POSTGRES_USER=bib
|
||||||
|
POSTGRES_PASSWORD=change-me
|
||||||
|
POSTGRES_DB=events
|
||||||
|
POSTGRES_PORT=5433
|
||||||
|
|
||||||
|
# App user
|
||||||
|
APP_DB_USER=sport
|
||||||
|
APP_DB_PASSWORD=change-me
|
||||||
26
docker-definitions/postgres-eventsdb-test/docker-compose.yml
Normal file
26
docker-definitions/postgres-eventsdb-test/docker-compose.yml
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:18
|
||||||
|
container_name: postgres_db_test
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
|
||||||
|
environment:
|
||||||
|
# custom varijable za init skripte (.sh)
|
||||||
|
APP_DB_USER: ${APP_DB_USER}
|
||||||
|
APP_DB_PASSWORD: ${APP_DB_PASSWORD}
|
||||||
|
|
||||||
|
ports:
|
||||||
|
- "${POSTGRES_PORT}:5432"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- postgres_data:/var/lib/postgresql
|
||||||
|
- ./backup:/backup
|
||||||
|
#chmod +x init/01-roles.sh na linuxu
|
||||||
|
- ./init:/docker-entrypoint-initdb.d
|
||||||
|
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres_data:
|
||||||
7
docker-definitions/postgres-eventsdb-test/init/01-roles.sh
Executable file
7
docker-definitions/postgres-eventsdb-test/init/01-roles.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||||
|
CREATE USER ${APP_DB_USER} WITH PASSWORD '${APP_DB_PASSWORD}';
|
||||||
|
GRANT CONNECT ON DATABASE ${POSTGRES_DB} TO ${APP_DB_USER};
|
||||||
|
EOSQL
|
||||||
61
docker-definitions/postgres-eventsdb-test/init/02-schema.sql
Normal file
61
docker-definitions/postgres-eventsdb-test/init/02-schema.sql
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
-- COUNTRIES
|
||||||
|
CREATE TABLE country (
|
||||||
|
code VARCHAR(3) PRIMARY KEY,
|
||||||
|
alpha3 CHAR(3) NOT NULL,
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
translations JSONB,
|
||||||
|
|
||||||
|
UNIQUE (name)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- PERSONS
|
||||||
|
CREATE TABLE person (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
first_name VARCHAR(100),
|
||||||
|
last_name VARCHAR(100),
|
||||||
|
first_name_transcription VARCHAR(100) NOT NULL,
|
||||||
|
last_name_transcription VARCHAR(100) NOT NULL,
|
||||||
|
address_line VARCHAR(200),
|
||||||
|
postal_code VARCHAR(20),
|
||||||
|
city VARCHAR(100),
|
||||||
|
address_country VARCHAR(100),
|
||||||
|
email VARCHAR(255),
|
||||||
|
contact_phone VARCHAR(50),
|
||||||
|
birth_date DATE NOT NULL,
|
||||||
|
document_number VARCHAR(50) NOT NULL,
|
||||||
|
country_code VARCHAR(3) NOT NULL,
|
||||||
|
|
||||||
|
FOREIGN KEY (country_code) REFERENCES country(code),
|
||||||
|
|
||||||
|
-- UNIQUE dokument po državi
|
||||||
|
UNIQUE (document_number, country_code)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- SPORTS
|
||||||
|
CREATE TABLE sport (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
UNIQUE (name)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- EVENTS
|
||||||
|
CREATE TABLE event (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(150) NOT NULL,
|
||||||
|
event_date DATE NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- REGISTRATIONS
|
||||||
|
CREATE TABLE registration (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
person_id INT NOT NULL,
|
||||||
|
sport_id INT NOT NULL,
|
||||||
|
event_id INT NOT NULL,
|
||||||
|
registered_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
|
||||||
|
FOREIGN KEY (person_id) REFERENCES person(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (sport_id) REFERENCES sport(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (event_id) REFERENCES event(id) ON DELETE CASCADE,
|
||||||
|
|
||||||
|
UNIQUE (person_id, sport_id, event_id)
|
||||||
|
);
|
||||||
15
docker-definitions/postgres-eventsdb-test/init/03-permissions.sh
Executable file
15
docker-definitions/postgres-eventsdb-test/init/03-permissions.sh
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Ova datoteka mora imati LF, a ne CRLF
|
||||||
|
DB_NAME="${POSTGRES_DB}"
|
||||||
|
APP_USER="${APP_DB_USER}"
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$DB_NAME" <<-EOSQL
|
||||||
|
GRANT USAGE ON SCHEMA public TO ${APP_USER};
|
||||||
|
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO ${APP_USER};
|
||||||
|
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO ${APP_USER};
|
||||||
|
|
||||||
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO ${APP_USER};
|
||||||
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO ${APP_USER};
|
||||||
|
EOSQL
|
||||||
251
docker-definitions/postgres-eventsdb-test/init/04-countries.sql
Normal file
251
docker-definitions/postgres-eventsdb-test/init/04-countries.sql
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
INSERT INTO country (code, alpha3, name, translations) VALUES
|
||||||
|
('AD', 'AND', 'Andorra', '{"hr": "Andora", "mk": "Андора"}'),
|
||||||
|
('AE', 'ARE', 'United Arab Emirates', '{"hr": "Ujedinjeni Arapski Emirati", "mk": "Обединети Арапски Емирати"}'),
|
||||||
|
('AF', 'AFG', 'Afghanistan', '{"hr": "Afganistan", "mk": "Авганистан"}'),
|
||||||
|
('AG', 'ATG', 'Antigua and Barbuda', '{"hr": "Antigva i Barbuda", "mk": "Антига и Барбуда"}'),
|
||||||
|
('AI', 'AIA', 'Anguilla', '{"hr": "Angvila", "mk": "Ангвила"}'),
|
||||||
|
('AL', 'ALB', 'Albania', '{"hr": "Albanija", "mk": "Албанија"}'),
|
||||||
|
('AM', 'ARM', 'Armenia', '{"hr": "Armenija", "mk": "Ерменија"}'),
|
||||||
|
('AO', 'AGO', 'Angola', '{"hr": "Angola", "mk": "Ангола"}'),
|
||||||
|
('AQ', 'ATA', 'Antarctica', '{"hr": "Antarktika", "mk": "Антарктик"}'),
|
||||||
|
('AR', 'ARG', 'Argentina', '{"hr": "Argentina", "mk": "Аргентина"}'),
|
||||||
|
('AS', 'ASM', 'American Samoa', '{"hr": "Američka Samoa", "mk": "Американска Самоа"}'),
|
||||||
|
('AT', 'AUT', 'Austria', '{"hr": "Austrija", "mk": "Австрија"}'),
|
||||||
|
('AU', 'AUS', 'Australia', '{"hr": "Australija", "mk": "Австралија"}'),
|
||||||
|
('AW', 'ABW', 'Aruba', '{"hr": "Aruba", "mk": "Аруба"}'),
|
||||||
|
('AX', 'ALA', 'Åland Islands', '{"hr": "Ålandski otoci", "mk": "Оландски Острови"}'),
|
||||||
|
('AZ', 'AZE', 'Azerbaijan', '{"hr": "Azerbajdžan", "mk": "Азербејџан"}'),
|
||||||
|
('BA', 'BIH', 'Bosnia and Herzegovina', '{"hr": "Bosna i Hercegovina", "mk": "Босна и Херцеговина"}'),
|
||||||
|
('BB', 'BRB', 'Barbados', '{"hr": "Barbados", "mk": "Барбадос"}'),
|
||||||
|
('BD', 'BGD', 'Bangladesh', '{"hr": "Bangladeš", "mk": "Бангладеш"}'),
|
||||||
|
('BE', 'BEL', 'Belgium', '{"hr": "Belgija", "mk": "Белгија"}'),
|
||||||
|
('BF', 'BFA', 'Burkina Faso', '{"hr": "Burkina Faso", "mk": "Буркина Фасо"}'),
|
||||||
|
('BG', 'BGR', 'Bulgaria', '{"hr": "Bugarska", "mk": "Бугарија"}'),
|
||||||
|
('BH', 'BHR', 'Bahrain', '{"hr": "Bahrein", "mk": "Бахреин"}'),
|
||||||
|
('BI', 'BDI', 'Burundi', '{"hr": "Burundi", "mk": "Бурунди"}'),
|
||||||
|
('BJ', 'BEN', 'Benin', '{"hr": "Benin", "mk": "Бенин"}'),
|
||||||
|
('BL', 'BLM', 'Saint Barthélemy', '{"hr": "Saint Barthélemy", "mk": "Свети Вартоломеј"}'),
|
||||||
|
('BM', 'BMU', 'Bermuda', '{"hr": "Bermudi", "mk": "Бермуди"}'),
|
||||||
|
('BN', 'BRN', 'Brunei Darussalam', '{"hr": "Brunej", "mk": "Брунеј"}'),
|
||||||
|
('BO', 'BOL', 'Bolivia', '{"hr": "Bolivija", "mk": "Боливија"}'),
|
||||||
|
('BQ', 'BES', 'Bonaire, Sint Eustatius and Saba', '{"hr": "Karipski otoci Nizozemske", "mk": "Карипска Холандија"}'),
|
||||||
|
('BR', 'BRA', 'Brazil', '{"hr": "Brazil", "mk": "Бразил"}'),
|
||||||
|
('BS', 'BHS', 'Bahamas', '{"hr": "Bahami", "mk": "Бахами"}'),
|
||||||
|
('BT', 'BTN', 'Bhutan', '{"hr": "Butan", "mk": "Бутан"}'),
|
||||||
|
('BV', 'BVT', 'Bouvet Island', '{"hr": "Otok Bouvet", "mk": "Остров Буве"}'),
|
||||||
|
('BW', 'BWA', 'Botswana', '{"hr": "Bocvana", "mk": "Боцвана"}'),
|
||||||
|
('BY', 'BLR', 'Belarus', '{"hr": "Bjelorusija", "mk": "Белорусија"}'),
|
||||||
|
('BZ', 'BLZ', 'Belize', '{"hr": "Belize", "mk": "Белизе"}'),
|
||||||
|
('CA', 'CAN', 'Canada', '{"hr": "Kanada", "mk": "Канада"}'),
|
||||||
|
('CC', 'CCK', 'Cocos (Keeling) Islands', '{"hr": "Kokosovi (Keelingovi) Otoci", "mk": "Кокосови (Килиншки) Острови"}'),
|
||||||
|
('CD', 'COD', 'Congo, The Democratic Republic of the', '{"hr": "Kongo - Kinshasa", "mk": "Конго - Киншаса"}'),
|
||||||
|
('CF', 'CAF', 'Central African Republic', '{"hr": "Srednjoafrička Republika", "mk": "Централноафриканска Република"}'),
|
||||||
|
('CG', 'COG', 'Congo', '{"hr": "Kongo - Brazzaville", "mk": "Конго - Бразавил"}'),
|
||||||
|
('CH', 'CHE', 'Switzerland', '{"hr": "Švicarska", "mk": "Швајцарија"}'),
|
||||||
|
('CI', 'CIV', 'Côte d''Ivoire', '{"hr": "Obala Bjelokosti", "mk": "Брегот на Слоновата Коска"}'),
|
||||||
|
('CK', 'COK', 'Cook Islands', '{"hr": "Cookovi Otoci", "mk": "Кукови Острови"}'),
|
||||||
|
('CL', 'CHL', 'Chile', '{"hr": "Čile", "mk": "Чиле"}'),
|
||||||
|
('CM', 'CMR', 'Cameroon', '{"hr": "Kamerun", "mk": "Камерун"}'),
|
||||||
|
('CN', 'CHN', 'China', '{"hr": "Kina", "mk": "Кина"}'),
|
||||||
|
('CO', 'COL', 'Colombia', '{"hr": "Kolumbija", "mk": "Колумбија"}'),
|
||||||
|
('CR', 'CRI', 'Costa Rica', '{"hr": "Kostarika", "mk": "Костарика"}'),
|
||||||
|
('CU', 'CUB', 'Cuba', '{"hr": "Kuba", "mk": "Куба"}'),
|
||||||
|
('CV', 'CPV', 'Cabo Verde', '{"hr": "Zelenortska Republika", "mk": "Кабо Верде"}'),
|
||||||
|
('CW', 'CUW', 'Curaçao', '{"hr": "Curaçao", "mk": "Курасао"}'),
|
||||||
|
('CX', 'CXR', 'Christmas Island', '{"hr": "Božićni Otok", "mk": "Божиќен Остров"}'),
|
||||||
|
('CY', 'CYP', 'Cyprus', '{"hr": "Cipar", "mk": "Кипар"}'),
|
||||||
|
('CZ', 'CZE', 'Czechia', '{"hr": "Češka", "mk": "Чешка"}'),
|
||||||
|
('DE', 'DEU', 'Germany', '{"hr": "Njemačka", "mk": "Германија"}'),
|
||||||
|
('DJ', 'DJI', 'Djibouti', '{"hr": "Džibuti", "mk": "Џибути"}'),
|
||||||
|
('DK', 'DNK', 'Denmark', '{"hr": "Danska", "mk": "Данска"}'),
|
||||||
|
('DM', 'DMA', 'Dominica', '{"hr": "Dominika", "mk": "Доминика"}'),
|
||||||
|
('DO', 'DOM', 'Dominican Republic', '{"hr": "Dominikanska Republika", "mk": "Доминиканска Република"}'),
|
||||||
|
('DZ', 'DZA', 'Algeria', '{"hr": "Alžir", "mk": "Алжир"}'),
|
||||||
|
('EC', 'ECU', 'Ecuador', '{"hr": "Ekvador", "mk": "Еквадор"}'),
|
||||||
|
('EE', 'EST', 'Estonia', '{"hr": "Estonija", "mk": "Естонија"}'),
|
||||||
|
('EG', 'EGY', 'Egypt', '{"hr": "Egipat", "mk": "Египет"}'),
|
||||||
|
('EH', 'ESH', 'Western Sahara', '{"hr": "Zapadna Sahara", "mk": "Западна Сахара"}'),
|
||||||
|
('ER', 'ERI', 'Eritrea', '{"hr": "Eritreja", "mk": "Еритреја"}'),
|
||||||
|
('ES', 'ESP', 'Spain', '{"hr": "Španjolska", "mk": "Шпанија"}'),
|
||||||
|
('ET', 'ETH', 'Ethiopia', '{"hr": "Etiopija", "mk": "Етиопија"}'),
|
||||||
|
('FI', 'FIN', 'Finland', '{"hr": "Finska", "mk": "Финска"}'),
|
||||||
|
('FJ', 'FJI', 'Fiji', '{"hr": "Fidži", "mk": "Фиџи"}'),
|
||||||
|
('FK', 'FLK', 'Falkland Islands (Malvinas)', '{"hr": "Falklandski Otoci", "mk": "Фолкландски Острови"}'),
|
||||||
|
('FM', 'FSM', 'Micronesia, Federated States of', '{"hr": "Mikronezija", "mk": "Микронезија"}'),
|
||||||
|
('FO', 'FRO', 'Faroe Islands', '{"hr": "Ovčji Otoci", "mk": "Фарски Острови"}'),
|
||||||
|
('FR', 'FRA', 'France', '{"hr": "Francuska", "mk": "Франција"}'),
|
||||||
|
('GA', 'GAB', 'Gabon', '{"hr": "Gabon", "mk": "Габон"}'),
|
||||||
|
('GB', 'GBR', 'United Kingdom', '{"hr": "Ujedinjeno Kraljevstvo", "mk": "Обединето Кралство"}'),
|
||||||
|
('GD', 'GRD', 'Grenada', '{"hr": "Grenada", "mk": "Гренада"}'),
|
||||||
|
('GE', 'GEO', 'Georgia', '{"hr": "Gruzija", "mk": "Грузија"}'),
|
||||||
|
('GF', 'GUF', 'French Guiana', '{"hr": "Francuska Gijana", "mk": "Француска Гвајана"}'),
|
||||||
|
('GG', 'GGY', 'Guernsey', '{"hr": "Guernsey", "mk": "Гернзи"}'),
|
||||||
|
('GH', 'GHA', 'Ghana', '{"hr": "Gana", "mk": "Гана"}'),
|
||||||
|
('GI', 'GIB', 'Gibraltar', '{"hr": "Gibraltar", "mk": "Гибралтар"}'),
|
||||||
|
('GL', 'GRL', 'Greenland', '{"hr": "Grenland", "mk": "Гренланд"}'),
|
||||||
|
('GM', 'GMB', 'Gambia', '{"hr": "Gambija", "mk": "Гамбија"}'),
|
||||||
|
('GN', 'GIN', 'Guinea', '{"hr": "Gvineja", "mk": "Гвинеја"}'),
|
||||||
|
('GP', 'GLP', 'Guadeloupe', '{"hr": "Guadalupe", "mk": "Гвадалупе"}'),
|
||||||
|
('GQ', 'GNQ', 'Equatorial Guinea', '{"hr": "Ekvatorska Gvineja", "mk": "Екваторска Гвинеја"}'),
|
||||||
|
('GR', 'GRC', 'Greece', '{"hr": "Grčka", "mk": "Грција"}'),
|
||||||
|
('GS', 'SGS', 'South Georgia and the South Sandwich Islands', '{"hr": "Južna Georgia i Otoci Južni Sandwich", "mk": "Јужна Џорџија и Јужни Сендвички Острови"}'),
|
||||||
|
('GT', 'GTM', 'Guatemala', '{"hr": "Gvatemala", "mk": "Гватемала"}'),
|
||||||
|
('GU', 'GUM', 'Guam', '{"hr": "Guam", "mk": "Гуам"}'),
|
||||||
|
('GW', 'GNB', 'Guinea-Bissau', '{"hr": "Gvineja Bisau", "mk": "Гвинеја Бисао"}'),
|
||||||
|
('GY', 'GUY', 'Guyana', '{"hr": "Gvajana", "mk": "Гвајана"}'),
|
||||||
|
('HK', 'HKG', 'Hong Kong', '{"hr": "PUP Hong Kong Kina", "mk": "Хонгконг САР Кина"}'),
|
||||||
|
('HM', 'HMD', 'Heard Island and McDonald Islands', '{"hr": "Otoci Heard i McDonald", "mk": "Остров Херд и Острови Мекдоналд"}'),
|
||||||
|
('HN', 'HND', 'Honduras', '{"hr": "Honduras", "mk": "Хондурас"}'),
|
||||||
|
('HR', 'HRV', 'Croatia', '{"hr": "Hrvatska", "mk": "Хрватска"}'),
|
||||||
|
('HT', 'HTI', 'Haiti', '{"hr": "Haiti", "mk": "Хаити"}'),
|
||||||
|
('HU', 'HUN', 'Hungary', '{"hr": "Mađarska", "mk": "Унгарија"}'),
|
||||||
|
('ID', 'IDN', 'Indonesia', '{"hr": "Indonezija", "mk": "Индонезија"}'),
|
||||||
|
('IE', 'IRL', 'Ireland', '{"hr": "Irska", "mk": "Ирска"}'),
|
||||||
|
('IL', 'ISR', 'Israel', '{"hr": "Izrael", "mk": "Израел"}'),
|
||||||
|
('IM', 'IMN', 'Isle of Man', '{"hr": "Otok Man", "mk": "Остров Ман"}'),
|
||||||
|
('IN', 'IND', 'India', '{"hr": "Indija", "mk": "Индија"}'),
|
||||||
|
('IO', 'IOT', 'British Indian Ocean Territory', '{"hr": "Britanski Indijskooceanski Teritorij", "mk": "Британска Индоокеанска Територија"}'),
|
||||||
|
('IQ', 'IRQ', 'Iraq', '{"hr": "Irak", "mk": "Ирак"}'),
|
||||||
|
('IR', 'IRN', 'Iran', '{"hr": "Iran", "mk": "Иран"}'),
|
||||||
|
('IS', 'ISL', 'Iceland', '{"hr": "Island", "mk": "Исланд"}'),
|
||||||
|
('IT', 'ITA', 'Italy', '{"hr": "Italija", "mk": "Италија"}'),
|
||||||
|
('JE', 'JEY', 'Jersey', '{"hr": "Jersey", "mk": "Џерси"}'),
|
||||||
|
('JM', 'JAM', 'Jamaica', '{"hr": "Jamajka", "mk": "Јамајка"}'),
|
||||||
|
('JO', 'JOR', 'Jordan', '{"hr": "Jordan", "mk": "Јордан"}'),
|
||||||
|
('JP', 'JPN', 'Japan', '{"hr": "Japan", "mk": "Јапонија"}'),
|
||||||
|
('KE', 'KEN', 'Kenya', '{"hr": "Kenija", "mk": "Кенија"}'),
|
||||||
|
('KG', 'KGZ', 'Kyrgyzstan', '{"hr": "Kirgistan", "mk": "Киргистан"}'),
|
||||||
|
('KH', 'KHM', 'Cambodia', '{"hr": "Kambodža", "mk": "Камбоџа"}'),
|
||||||
|
('KI', 'KIR', 'Kiribati', '{"hr": "Kiribati", "mk": "Кирибати"}'),
|
||||||
|
('KM', 'COM', 'Comoros', '{"hr": "Komori", "mk": "Коморски Острови"}'),
|
||||||
|
('KN', 'KNA', 'Saint Kitts and Nevis', '{"hr": "Sveti Kristofor i Nevis", "mk": "Свети Китс и Невис"}'),
|
||||||
|
('KP', 'PRK', 'North Korea', '{"hr": "Sjeverna Koreja", "mk": "Северна Кореја"}'),
|
||||||
|
('KR', 'KOR', 'South Korea', '{"hr": "Južna Koreja", "mk": "Јужна Кореја"}'),
|
||||||
|
('KW', 'KWT', 'Kuwait', '{"hr": "Kuvajt", "mk": "Кувајт"}'),
|
||||||
|
('KY', 'CYM', 'Cayman Islands', '{"hr": "Kajmanski Otoci", "mk": "Кајмански Острови"}'),
|
||||||
|
('KZ', 'KAZ', 'Kazakhstan', '{"hr": "Kazahstan", "mk": "Казахстан"}'),
|
||||||
|
('LA', 'LAO', 'Laos', '{"hr": "Laos", "mk": "Лаос"}'),
|
||||||
|
('LB', 'LBN', 'Lebanon', '{"hr": "Libanon", "mk": "Либан"}'),
|
||||||
|
('LC', 'LCA', 'Saint Lucia', '{"hr": "Sveta Lucija", "mk": "Сент Лусија"}'),
|
||||||
|
('LI', 'LIE', 'Liechtenstein', '{"hr": "Lihtenštajn", "mk": "Лихтенштајн"}'),
|
||||||
|
('LK', 'LKA', 'Sri Lanka', '{"hr": "Šri Lanka", "mk": "Шри Ланка"}'),
|
||||||
|
('LR', 'LBR', 'Liberia', '{"hr": "Liberija", "mk": "Либерија"}'),
|
||||||
|
('LS', 'LSO', 'Lesotho', '{"hr": "Lesoto", "mk": "Лесото"}'),
|
||||||
|
('LT', 'LTU', 'Lithuania', '{"hr": "Litva", "mk": "Литванија"}'),
|
||||||
|
('LU', 'LUX', 'Luxembourg', '{"hr": "Luksemburg", "mk": "Луксембург"}'),
|
||||||
|
('LV', 'LVA', 'Latvia', '{"hr": "Latvija", "mk": "Латвија"}'),
|
||||||
|
('LY', 'LBY', 'Libya', '{"hr": "Libija", "mk": "Либија"}'),
|
||||||
|
('MA', 'MAR', 'Morocco', '{"hr": "Maroko", "mk": "Мароко"}'),
|
||||||
|
('MC', 'MCO', 'Monaco', '{"hr": "Monako", "mk": "Монако"}'),
|
||||||
|
('MD', 'MDA', 'Moldova', '{"hr": "Moldavija", "mk": "Молдавија"}'),
|
||||||
|
('ME', 'MNE', 'Montenegro', '{"hr": "Crna Gora", "mk": "Црна Гора"}'),
|
||||||
|
('MF', 'MAF', 'Saint Martin (French part)', '{"hr": "Saint Martin", "mk": "Сент Мартин"}'),
|
||||||
|
('MG', 'MDG', 'Madagascar', '{"hr": "Madagaskar", "mk": "Мадагаскар"}'),
|
||||||
|
('MH', 'MHL', 'Marshall Islands', '{"hr": "Maršalovi Otoci", "mk": "Маршалски Острови"}'),
|
||||||
|
('MK', 'MKD', 'North Macedonia', '{"hr": "Sjeverna Makedonija", "mk": "Северна Македонија"}'),
|
||||||
|
('ML', 'MLI', 'Mali', '{"hr": "Mali", "mk": "Мали"}'),
|
||||||
|
('MM', 'MMR', 'Myanmar', '{"hr": "Mjanmar (Burma)", "mk": "Мјанмар (Бурма)"}'),
|
||||||
|
('MN', 'MNG', 'Mongolia', '{"hr": "Mongolija", "mk": "Монголија"}'),
|
||||||
|
('MO', 'MAC', 'Macao', '{"hr": "PUP Makao Kina", "mk": "Макао САР"}'),
|
||||||
|
('MP', 'MNP', 'Northern Mariana Islands', '{"hr": "Sjevernomarijanski Otoci", "mk": "Северни Маријански Острови"}'),
|
||||||
|
('MQ', 'MTQ', 'Martinique', '{"hr": "Martinik", "mk": "Мартиник"}'),
|
||||||
|
('MR', 'MRT', 'Mauritania', '{"hr": "Mauretanija", "mk": "Мавританија"}'),
|
||||||
|
('MS', 'MSR', 'Montserrat', '{"hr": "Montserrat", "mk": "Монсерат"}'),
|
||||||
|
('MT', 'MLT', 'Malta', '{"hr": "Malta", "mk": "Малта"}'),
|
||||||
|
('MU', 'MUS', 'Mauritius', '{"hr": "Mauricijus", "mk": "Маврициус"}'),
|
||||||
|
('MV', 'MDV', 'Maldives', '{"hr": "Maldivi", "mk": "Малдиви"}'),
|
||||||
|
('MW', 'MWI', 'Malawi', '{"hr": "Malavi", "mk": "Малави"}'),
|
||||||
|
('MX', 'MEX', 'Mexico', '{"hr": "Meksiko", "mk": "Мексико"}'),
|
||||||
|
('MY', 'MYS', 'Malaysia', '{"hr": "Malezija", "mk": "Малезија"}'),
|
||||||
|
('MZ', 'MOZ', 'Mozambique', '{"hr": "Mozambik", "mk": "Мозамбик"}'),
|
||||||
|
('NA', 'NAM', 'Namibia', '{"hr": "Namibija", "mk": "Намибија"}'),
|
||||||
|
('NC', 'NCL', 'New Caledonia', '{"hr": "Nova Kaledonija", "mk": "Нова Каледонија"}'),
|
||||||
|
('NE', 'NER', 'Niger', '{"hr": "Niger", "mk": "Нигер"}'),
|
||||||
|
('NF', 'NFK', 'Norfolk Island', '{"hr": "Otok Norfolk", "mk": "Норфолшки Остров"}'),
|
||||||
|
('NG', 'NGA', 'Nigeria', '{"hr": "Nigerija", "mk": "Нигерија"}'),
|
||||||
|
('NI', 'NIC', 'Nicaragua', '{"hr": "Nikaragva", "mk": "Никарагва"}'),
|
||||||
|
('NL', 'NLD', 'Netherlands', '{"hr": "Nizozemska", "mk": "Холандија"}'),
|
||||||
|
('NO', 'NOR', 'Norway', '{"hr": "Norveška", "mk": "Норвешка"}'),
|
||||||
|
('NP', 'NPL', 'Nepal', '{"hr": "Nepal", "mk": "Непал"}'),
|
||||||
|
('NR', 'NRU', 'Nauru', '{"hr": "Nauru", "mk": "Науру"}'),
|
||||||
|
('NU', 'NIU', 'Niue', '{"hr": "Niue", "mk": "Ниује"}'),
|
||||||
|
('NZ', 'NZL', 'New Zealand', '{"hr": "Novi Zeland", "mk": "Нов Зеланд"}'),
|
||||||
|
('OM', 'OMN', 'Oman', '{"hr": "Oman", "mk": "Оман"}'),
|
||||||
|
('PA', 'PAN', 'Panama', '{"hr": "Panama", "mk": "Панама"}'),
|
||||||
|
('PE', 'PER', 'Peru', '{"hr": "Peru", "mk": "Перу"}'),
|
||||||
|
('PF', 'PYF', 'French Polynesia', '{"hr": "Francuska Polinezija", "mk": "Француска Полинезија"}'),
|
||||||
|
('PG', 'PNG', 'Papua New Guinea', '{"hr": "Papua Nova Gvineja", "mk": "Папуа Нова Гвинеја"}'),
|
||||||
|
('PH', 'PHL', 'Philippines', '{"hr": "Filipini", "mk": "Филипини"}'),
|
||||||
|
('PK', 'PAK', 'Pakistan', '{"hr": "Pakistan", "mk": "Пакистан"}'),
|
||||||
|
('PL', 'POL', 'Poland', '{"hr": "Poljska", "mk": "Полска"}'),
|
||||||
|
('PM', 'SPM', 'Saint Pierre and Miquelon', '{"hr": "Sveti Petar i Mikelon", "mk": "Сент Пјер и Микелан"}'),
|
||||||
|
('PN', 'PCN', 'Pitcairn', '{"hr": "Pitcairnovi Otoci", "mk": "Питкернски Острови"}'),
|
||||||
|
('PR', 'PRI', 'Puerto Rico', '{"hr": "Portoriko", "mk": "Порторико"}'),
|
||||||
|
('PS', 'PSE', 'Palestine, State of', '{"hr": "Palestinsko područje", "mk": "Палестински Територии"}'),
|
||||||
|
('PT', 'PRT', 'Portugal', '{"hr": "Portugal", "mk": "Португалија"}'),
|
||||||
|
('PW', 'PLW', 'Palau', '{"hr": "Palau", "mk": "Палау"}'),
|
||||||
|
('PY', 'PRY', 'Paraguay', '{"hr": "Paragvaj", "mk": "Парагвај"}'),
|
||||||
|
('QA', 'QAT', 'Qatar', '{"hr": "Katar", "mk": "Катар"}'),
|
||||||
|
('RE', 'REU', 'Réunion', '{"hr": "Réunion", "mk": "Рејунион"}'),
|
||||||
|
('RO', 'ROU', 'Romania', '{"hr": "Rumunjska", "mk": "Романија"}'),
|
||||||
|
('RS', 'SRB', 'Serbia', '{"hr": "Srbija", "mk": "Србија"}'),
|
||||||
|
('RU', 'RUS', 'Russian Federation', '{"hr": "Rusija", "mk": "Русија"}'),
|
||||||
|
('RW', 'RWA', 'Rwanda', '{"hr": "Ruanda", "mk": "Руанда"}'),
|
||||||
|
('SA', 'SAU', 'Saudi Arabia', '{"hr": "Saudijska Arabija", "mk": "Саудиска Арабија"}'),
|
||||||
|
('SB', 'SLB', 'Solomon Islands', '{"hr": "Salomonovi Otoci", "mk": "Соломонски Острови"}'),
|
||||||
|
('SC', 'SYC', 'Seychelles', '{"hr": "Sejšeli", "mk": "Сејшели"}'),
|
||||||
|
('SD', 'SDN', 'Sudan', '{"hr": "Sudan", "mk": "Судан"}'),
|
||||||
|
('SE', 'SWE', 'Sweden', '{"hr": "Švedska", "mk": "Шведска"}'),
|
||||||
|
('SG', 'SGP', 'Singapore', '{"hr": "Singapur", "mk": "Сингапур"}'),
|
||||||
|
('SH', 'SHN', 'Saint Helena, Ascension and Tristan da Cunha', '{"hr": "Sveta Helena", "mk": "Света Елена"}'),
|
||||||
|
('SI', 'SVN', 'Slovenia', '{"hr": "Slovenija", "mk": "Словенија"}'),
|
||||||
|
('SJ', 'SJM', 'Svalbard and Jan Mayen', '{"hr": "Svalbard i Jan Mayen", "mk": "Свалбард и Јан Мајен"}'),
|
||||||
|
('SK', 'SVK', 'Slovakia', '{"hr": "Slovačka", "mk": "Словачка"}'),
|
||||||
|
('SL', 'SLE', 'Sierra Leone', '{"hr": "Sijera Leone", "mk": "Сиера Леоне"}'),
|
||||||
|
('SM', 'SMR', 'San Marino', '{"hr": "San Marino", "mk": "Сан Марино"}'),
|
||||||
|
('SN', 'SEN', 'Senegal', '{"hr": "Senegal", "mk": "Сенегал"}'),
|
||||||
|
('SO', 'SOM', 'Somalia', '{"hr": "Somalija", "mk": "Сомалија"}'),
|
||||||
|
('SR', 'SUR', 'Suriname', '{"hr": "Surinam", "mk": "Суринам"}'),
|
||||||
|
('SS', 'SSD', 'South Sudan', '{"hr": "Južni Sudan", "mk": "Јужен Судан"}'),
|
||||||
|
('ST', 'STP', 'Sao Tome and Principe', '{"hr": "Sveti Toma i Princip", "mk": "Саун Томе и Принсип"}'),
|
||||||
|
('SV', 'SLV', 'El Salvador', '{"hr": "Salvador", "mk": "Ел Салвадор"}'),
|
||||||
|
('SX', 'SXM', 'Sint Maarten (Dutch part)', '{"hr": "Sint Maarten", "mk": "Свети Мартин"}'),
|
||||||
|
('SY', 'SYR', 'Syria', '{"hr": "Sirija", "mk": "Сирија"}'),
|
||||||
|
('SZ', 'SWZ', 'Eswatini', '{"hr": "Esvatini", "mk": "Свазиленд"}'),
|
||||||
|
('TC', 'TCA', 'Turks and Caicos Islands', '{"hr": "Otoci Turks i Caicos", "mk": "Острови Туркс и Каикос"}'),
|
||||||
|
('TD', 'TCD', 'Chad', '{"hr": "Čad", "mk": "Чад"}'),
|
||||||
|
('TF', 'ATF', 'French Southern Territories', '{"hr": "Francuski Južni Teritoriji", "mk": "Француски Јужни Територии"}'),
|
||||||
|
('TG', 'TGO', 'Togo', '{"hr": "Togo", "mk": "Того"}'),
|
||||||
|
('TH', 'THA', 'Thailand', '{"hr": "Tajland", "mk": "Тајланд"}'),
|
||||||
|
('TJ', 'TJK', 'Tajikistan', '{"hr": "Tadžikistan", "mk": "Таџикистан"}'),
|
||||||
|
('TK', 'TKL', 'Tokelau', '{"hr": "Tokelau", "mk": "Токелау"}'),
|
||||||
|
('TL', 'TLS', 'Timor-Leste', '{"hr": "Timor-Leste", "mk": "Тимор Лесте"}'),
|
||||||
|
('TM', 'TKM', 'Turkmenistan', '{"hr": "Turkmenistan", "mk": "Туркменистан"}'),
|
||||||
|
('TN', 'TUN', 'Tunisia', '{"hr": "Tunis", "mk": "Тунис"}'),
|
||||||
|
('TO', 'TON', 'Tonga', '{"hr": "Tonga", "mk": "Тонга"}'),
|
||||||
|
('TR', 'TUR', 'Türkiye', '{"hr": "Turska", "mk": "Турција"}'),
|
||||||
|
('TT', 'TTO', 'Trinidad and Tobago', '{"hr": "Trinidad i Tobago", "mk": "Тринидад и Тобаго"}'),
|
||||||
|
('TV', 'TUV', 'Tuvalu', '{"hr": "Tuvalu", "mk": "Тувалу"}'),
|
||||||
|
('TW', 'TWN', 'Taiwan', '{"hr": "Tajvan", "mk": "Тајван"}'),
|
||||||
|
('TZ', 'TZA', 'Tanzania', '{"hr": "Tanzanija", "mk": "Танзанија"}'),
|
||||||
|
('UA', 'UKR', 'Ukraine', '{"hr": "Ukrajina", "mk": "Украина"}'),
|
||||||
|
('UG', 'UGA', 'Uganda', '{"hr": "Uganda", "mk": "Уганда"}'),
|
||||||
|
('UM', 'UMI', 'United States Minor Outlying Islands', '{"hr": "Mali udaljeni otoci SAD-a", "mk": "Американски територии во Пацификот"}'),
|
||||||
|
('US', 'USA', 'United States', '{"hr": "Sjedinjene Američke Države", "mk": "Соединети Американски Држави"}'),
|
||||||
|
('UY', 'URY', 'Uruguay', '{"hr": "Urugvaj", "mk": "Уругвај"}'),
|
||||||
|
('UZ', 'UZB', 'Uzbekistan', '{"hr": "Uzbekistan", "mk": "Узбекистан"}'),
|
||||||
|
('VA', 'VAT', 'Holy See (Vatican City State)', '{"hr": "Vatikan", "mk": "Ватикан"}'),
|
||||||
|
('VC', 'VCT', 'Saint Vincent and the Grenadines', '{"hr": "Sveti Vincent i Grenadini", "mk": "Сент Винсент и Гренадини"}'),
|
||||||
|
('VE', 'VEN', 'Venezuela', '{"hr": "Venezuela", "mk": "Венецуела"}'),
|
||||||
|
('VG', 'VGB', 'Virgin Islands, British', '{"hr": "Britanski Djevičanski Otoci", "mk": "Британски Девствени Острови"}'),
|
||||||
|
('VI', 'VIR', 'Virgin Islands, U.S.', '{"hr": "Američki Djevičanski Otoci", "mk": "Американски Девствени Острови"}'),
|
||||||
|
('VN', 'VNM', 'Vietnam', '{"hr": "Vijetnam", "mk": "Виетнам"}'),
|
||||||
|
('VU', 'VUT', 'Vanuatu', '{"hr": "Vanuatu", "mk": "Вануату"}'),
|
||||||
|
('WF', 'WLF', 'Wallis and Futuna', '{"hr": "Wallis i Futuna", "mk": "Валис и Футуна"}'),
|
||||||
|
('WS', 'WSM', 'Samoa', '{"hr": "Samoa", "mk": "Самоа"}'),
|
||||||
|
('XK', 'XKX', 'Kosovo', '{"hr": "Kosovo", "mk": "Косово"}'),
|
||||||
|
('YE', 'YEM', 'Yemen', '{"hr": "Jemen", "mk": "Јемен"}'),
|
||||||
|
('YT', 'MYT', 'Mayotte', '{"hr": "Mayotte", "mk": "Мајот"}'),
|
||||||
|
('ZA', 'ZAF', 'South Africa', '{"hr": "Južnoafrička Republika", "mk": "Јужноафриканска Република"}'),
|
||||||
|
('ZM', 'ZMB', 'Zambia', '{"hr": "Zambija", "mk": "Замбија"}'),
|
||||||
|
('ZW', 'ZWE', 'Zimbabwe', '{"hr": "Zimbabve", "mk": "Зимбабве"}');
|
||||||
10
docker-definitions/postgres-eventsdb-test/init/05-sports.sql
Normal file
10
docker-definitions/postgres-eventsdb-test/init/05-sports.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
INSERT INTO sport (name) VALUES
|
||||||
|
('Running'),
|
||||||
|
('Darts'),
|
||||||
|
('Bowling'),
|
||||||
|
('Table Tennis'),
|
||||||
|
('Chess'),
|
||||||
|
('Pikado'),
|
||||||
|
('Mini Golf'),
|
||||||
|
('Swimming'),
|
||||||
|
('Cycling');
|
||||||
1950
docker-definitions/postgres-eventsdb-test/init/06-people.sql
Normal file
1950
docker-definitions/postgres-eventsdb-test/init/06-people.sql
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
|||||||
|
INSERT INTO event (name, event_date) VALUES
|
||||||
|
('Union Games', '2026-03-12'),
|
||||||
|
('Faculty Meetup', '2026-04-25'),
|
||||||
|
('City Cup', '2026-06-03'),
|
||||||
|
('Research Forum', '2026-09-18');
|
||||||
Reference in New Issue
Block a user