Skip to content

Commit

Permalink
Merge pull request #201 from dainst/show_last_database_update
Browse files Browse the repository at this point in the history
Show last database update and svg icons for issue list
  • Loading branch information
the-last-pastafarian authored Nov 6, 2024
2 parents 75ad972 + 01e0f48 commit 9f46c60
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
otp-version: 26.0
elixir-version: 1.16.0
- name: Start CouchDB
run: docker-compose -f docker-compose.yml --env-file .env_template up -d
run: docker compose -f docker-compose.yml --env-file .env_template up -d
working-directory: server
- name: Sleep to await CouchDB startup
run: sleep 15s
Expand Down
115 changes: 99 additions & 16 deletions server/assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,33 @@
border: 1px solid transparent;
border-radius: 4px;
}

.alert-info {
color: #31708f;
background-color: #d9edf7;
border-color: #bce8f1;
}

.alert-warning {
color: #8a6d3b;
background-color: #fcf8e3;
border-color: #faebcc;
}

.alert-danger {
color: #a94442;
background-color: #f2dede;
border-color: #ebccd1;
}

.alert p {
margin-bottom: 0;
}

.alert:empty {
display: none;
}

.invalid-feedback {
color: #a94442;
display: block;
Expand All @@ -46,20 +52,20 @@
transition: opacity 1s ease-out;
}

.phx-loading{
.phx-loading {
cursor: wait;
}

.phx-modal {
opacity: 1!important;
opacity: 1 !important;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0,0,0,0.4);
background-color: rgba(0, 0, 0, 0.4);
}

.phx-modal-content {
Expand Down Expand Up @@ -95,28 +101,53 @@
.fade-in {
animation: 0.2s ease-out 0s normal forwards 1 fade-in-keys;
}

.fade-out {
animation: 0.2s ease-out 0s normal forwards 1 fade-out-keys;
}

@keyframes fade-in-scale-keys{
0% { scale: 0.95; opacity: 0; }
100% { scale: 1.0; opacity: 1; }
@keyframes fade-in-scale-keys {
0% {
scale: 0.95;
opacity: 0;
}

100% {
scale: 1.0;
opacity: 1;
}
}

@keyframes fade-out-scale-keys{
0% { scale: 1.0; opacity: 1; }
100% { scale: 0.95; opacity: 0; }
@keyframes fade-out-scale-keys {
0% {
scale: 1.0;
opacity: 1;
}

100% {
scale: 0.95;
opacity: 0;
}
}

@keyframes fade-in-keys{
0% { opacity: 0; }
100% { opacity: 1; }
@keyframes fade-in-keys {
0% {
opacity: 0;
}

100% {
opacity: 1;
}
}

@keyframes fade-out-keys{
0% { opacity: 1; }
100% { opacity: 0; }
@keyframes fade-out-keys {
0% {
opacity: 1;
}

100% {
opacity: 0;
}
}

:root {
Expand Down Expand Up @@ -172,6 +203,18 @@ nav {
display: none;
}

.issue-group h3 div img {
position: relative;
width: 1em;
height: 1em;
top: 0.1em;
margin-right: 0.25em;
}

.issue-group h3 div {
cursor: pointer;
}

.monitoring-issue {
text-align: center;
border-radius: 5px;
Expand All @@ -187,7 +230,7 @@ nav {
}

.monitoring-issue.error {
background-color: rgb(253, 53, 53);
background-color: rgb(253, 53, 53);
color: white;
}

Expand All @@ -213,11 +256,51 @@ nav {
border-color: transparent #000000 transparent #000000;
display: block;
}

@keyframes issue-loading-anim {
0% {
transform: rotate(0deg);
}

100% {
transform: rotate(360deg);
}
}

.row-compact {
color:#3f4246;
line-height: 0%;
font-size: small;
}


.column-date-time {
width: 11em;
}

.row-head{
color: #3f4246;
font-size: small;
}

.column-last-changes-slider {
width: 9em;
}

.slider-container {
width: 100%;
}

.slider {
width: 100%;
background: #cdcccc;
outline: none;
opacity: 0.7;
-webkit-transition: .2s;
transition: opacity .2s;
accent-color: #0069d9;
}

.slider:hover {
opacity: 1;
}
80 changes: 79 additions & 1 deletion server/lib/field_hub/couch_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ defmodule FieldHub.CouchService do
@moduledoc """
Bundles functions for directly interacting with the CouchDB.
"""

require Logger

@doc """
Expand Down Expand Up @@ -337,6 +336,85 @@ defmodule FieldHub.CouchService do
)
end

@doc """
Returns up to n last changes for the specified project.
If the project has less than n changes or is new, less or no change would be returned.
__Parameters__
- `project_identifier` - The name of the project.
## Example
iex> get_last_n_changes("project_a",1)
[
%{
"changes" => [%{"rev" => "2-4f773e67d44d4bc99008713d9f9d164f"}],
"doc" => %{
"_id" => "988d0107-952f-4eaf-8c1f-4a25a0c5b15c",
"_rev" => "2-4f773e67d44d4bc99008713d9f9d164f",
"created" => %{
"date" => "2023-10-17T14:56:31.120Z",
"user" => "anonymous"
},
"modified" => [
%{"date" => "2023-10-17T14:57:55.929Z", "user" => "anonymous"}
],
"resource" => %{
"category" => "Survey",
"id" => "988d0107-952f-4eaf-8c1f-4a25a0c5b15c",
"identifier" => "area 190",
"relations" => %{}
}
},
"id" => "988d0107-952f-4eaf-8c1f-4a25a0c5b15c",
"seq" => "6-g1AAAACLeJzLYWBgYMpgTmHgzcvPy09JdcjLz8gvLskBCScyJNX___8_K4M5kTkXKMBuYW5iaZpkgK4Yh_Y8FiDJ0ACk_qOaYpJmlpSSiq4nCwA51yqW"
}
]
"""
def get_last_n_changes(project_identifier, n) do
HTTPoison.get!(
"#{base_url()}/#{project_identifier}/_changes?descending=true&limit=100&include_docs=true",
get_user_credentials()
|> headers()
)
|> Map.get(:body)
|> Jason.decode!()
|> Map.get("results")
|> Enum.reject(fn change ->
doc = change["doc"]
Map.has_key?(doc, "_deleted")
end)
|> Enum.sort_by(
&extract_most_recent_change_info/1,
&compare_change_info/2
)
|> Enum.take(n)
end

def extract_most_recent_change_info(%{"doc" => %{"modified" => []}} = change) do
{:ok, creation_date, _seconds} = DateTime.from_iso8601(change["doc"]["created"]["date"])
user_name = change["doc"]["created"]["user"]

{:created, creation_date, user_name}
end

def extract_most_recent_change_info(change) do
last_modification = List.last(change["doc"]["modified"])

{:ok, modification_date, _seconds} = DateTime.from_iso8601(last_modification["date"])
user_name = last_modification["user"]

{:modified, modification_date, user_name}
end

defp compare_change_info({_, a, _}, {_, b, _}) do
if DateTime.compare(a, b) == :gt do
true
else
false
end
end

@doc """
Returns the result of a `_all_docs` CouchDB query for the provided list of ids.
Expand Down
8 changes: 7 additions & 1 deletion server/lib/field_hub/project.ex
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ defmodule FieldHub.Project do
name: "development"
}
"""
def evaluate_project(project_identifier) do
def evaluate_project(project_identifier, n_changes_to_display \\ 2) do
project_identifier
|> evaluate_database()
|> case do
Expand All @@ -201,6 +201,12 @@ defmodule FieldHub.Project do
db_statistics ->
file_statistics = evaluate_file_store(project_identifier)

changes = CouchService.get_last_n_changes(project_identifier, n_changes_to_display)

db_statistics =
db_statistics
|> Map.put(:last_n_changes, changes)

%{
name: project_identifier,
database: db_statistics,
Expand Down
22 changes: 20 additions & 2 deletions server/lib/field_hub_web/live/project_show_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ defmodule FieldHubWeb.ProjectShowLive do
# access via websocket. In the normal application flow this will be unnesseary
# because the http plug will already have caught unauthorized access before switching protocols.
# See https://hexdocs.pm/phoenix_live_view/security-model.html#mounting-considerations

user_name =
user_token
|> UserAuth.get_user_by_session_token()
Expand All @@ -50,6 +51,7 @@ defmodule FieldHubWeb.ProjectShowLive do
|> assign(:confirm_project_name, "")
|> assign(:delete_files, false)
|> assign(:hide_cache_cleared_message, true)
|> assign(:n_changes_to_display, 5)
|> read_project_doc()
}

Expand All @@ -58,11 +60,14 @@ defmodule FieldHubWeb.ProjectShowLive do
end
end

def handle_info(:update_overview, %{assigns: %{project: project}} = socket) do
def handle_info(
:update_overview,
%{assigns: %{project: project, n_changes_to_display: number_of_changes}} = socket
) do
# Evaluate the project asynchronously. Once the task finishes, it will get picked up
# by another handle_info/2 below.
Task.async(fn ->
{:overview_task, Project.evaluate_project(project)}
{:overview_task, Project.evaluate_project(project, number_of_changes)}
end)

{:noreply, socket}
Expand Down Expand Up @@ -130,6 +135,19 @@ defmodule FieldHubWeb.ProjectShowLive do
{:noreply, assign(socket, :new_password, password)}
end

def handle_event("change_count_select", %{"n-last-changes" => n} = _values, socket) do
{n_integer, _remainder} = Integer.parse(n)

stats = Project.evaluate_project(socket.assigns.project, n_integer)

socket =
socket
|> assign(:stats, stats)
|> assign(:n_changes_to_display, n_integer)

{:noreply, socket}
end

def handle_event("delete_cache", _values, %{assigns: %{project: project}} = socket) do
{:ok, true} = FieldHub.FileStore.clear_cache(project)

Expand Down
Loading

0 comments on commit 9f46c60

Please sign in to comment.