diff --git a/src/main/java/io/linuxserver/fleet/v2/client/docker/AbstractDockerApiClient.java b/src/main/java/io/linuxserver/fleet/v2/client/docker/AbstractDockerApiClient.java new file mode 100644 index 0000000..5c73f42 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/v2/client/docker/AbstractDockerApiClient.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 LinuxServer.io + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.linuxserver.fleet.v2.client.docker; + +public abstract class AbstractDockerApiClient implements DockerApiClient { + + +} diff --git a/src/main/java/io/linuxserver/fleet/v2/client/docker/DockerApiClient.java b/src/main/java/io/linuxserver/fleet/v2/client/docker/DockerApiClient.java new file mode 100644 index 0000000..2e3d6a3 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/v2/client/docker/DockerApiClient.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 LinuxServer.io + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.linuxserver.fleet.v2.client.docker; + +public interface DockerApiClient { + + > RESPONSE executeRequest(REQUEST request); +} diff --git a/src/main/java/io/linuxserver/fleet/v2/client/docker/DockerApiRequest.java b/src/main/java/io/linuxserver/fleet/v2/client/docker/DockerApiRequest.java new file mode 100644 index 0000000..dab9c85 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/v2/client/docker/DockerApiRequest.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 LinuxServer.io + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.linuxserver.fleet.v2.client.docker; + +public interface DockerApiRequest { + + RESPONSE_TYPE performRequest(); +} diff --git a/src/main/java/io/linuxserver/fleet/v2/client/docker/converter/DockerResponseConverter.java b/src/main/java/io/linuxserver/fleet/v2/client/docker/converter/DockerResponseConverter.java new file mode 100644 index 0000000..a6df17f --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/v2/client/docker/converter/DockerResponseConverter.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 LinuxServer.io + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.linuxserver.fleet.v2.client.docker.converter; + +public interface DockerResponseConverter { + + INTERNAL_MODEL convert(final DOCKER_MODEL dockerModel); +} diff --git a/src/main/java/io/linuxserver/fleet/v2/types/Image.java b/src/main/java/io/linuxserver/fleet/v2/types/Image.java index 598a3f4..28435e2 100644 --- a/src/main/java/io/linuxserver/fleet/v2/types/Image.java +++ b/src/main/java/io/linuxserver/fleet/v2/types/Image.java @@ -31,6 +31,8 @@ import java.util.TreeSet; public class Image extends AbstractSyncItem { + private static final DateTimeFormatter DefaultImageTimeFormat = DateTimeFormatter.ofPattern("dd MMM yyyy HH:mm:ss"); + private final ImageCountData countData; private final String description; private final LocalDateTime lastUpdated; @@ -102,7 +104,7 @@ public class Image extends AbstractSyncItem { public final String getLastUpdatedAsString() { final LocalDateTime lastUpdated = parseDateTime(this.lastUpdated); - return null == lastUpdated ? null : DateTimeFormatter.ISO_DATE_TIME.format(lastUpdated); + return null == lastUpdated ? null : DefaultImageTimeFormat.format(lastUpdated); } public final List getTagBranches() { diff --git a/src/main/java/io/linuxserver/fleet/v2/web/routes/HomeController.java b/src/main/java/io/linuxserver/fleet/v2/web/routes/HomeController.java index 1e8c871..cc34329 100644 --- a/src/main/java/io/linuxserver/fleet/v2/web/routes/HomeController.java +++ b/src/main/java/io/linuxserver/fleet/v2/web/routes/HomeController.java @@ -23,8 +23,6 @@ import io.linuxserver.fleet.v2.service.RepositoryManager; import io.linuxserver.fleet.v2.types.Repository; import io.linuxserver.fleet.v2.web.PageModelSpec; -import java.util.Collections; - public class HomeController extends AbstractPageHandler { private final RepositoryManager repositoryManager; diff --git a/src/main/java/io/linuxserver/fleet/v2/web/routes/ImageController.java b/src/main/java/io/linuxserver/fleet/v2/web/routes/ImageController.java new file mode 100644 index 0000000..f4436c7 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/v2/web/routes/ImageController.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019 LinuxServer.io + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.linuxserver.fleet.v2.web.routes; + +import io.javalin.http.Context; +import io.linuxserver.fleet.v2.key.ImageLookupKey; +import io.linuxserver.fleet.v2.service.RepositoryManager; +import io.linuxserver.fleet.v2.web.PageModelSpec; + +public class ImageController extends AbstractPageHandler { + + private final RepositoryManager repositoryManager; + + public ImageController(final RepositoryManager repositoryManager) { + this.repositoryManager = repositoryManager; + } + + @Override + protected PageModelSpec handlePageLoad(final Context ctx) { + + final String imageLookupParam = ctx.queryParam("name"); + if (null != imageLookupParam) { + + final PageModelSpec modelSpec = new PageModelSpec("views/pages/image.ftl"); + modelSpec.addModelAttribute("image", repositoryManager.lookupImage(new ImageLookupKey(imageLookupParam))); + return modelSpec; + + } else { + return new PageModelSpec("views/pages/not-found.ftl"); + } + } + + @Override + protected PageModelSpec handleFormSubmission(final Context ctx) { + return new PageModelSpec("views/pages/unsupported.ftl"); + } +} diff --git a/src/main/resources/static/assets/css/app.css b/src/main/resources/static/assets/css/app.css index 1bdb5aa..39376ea 100644 --- a/src/main/resources/static/assets/css/app.css +++ b/src/main/resources/static/assets/css/app.css @@ -158,4 +158,17 @@ input:checked + .slider:before { table tbody th.is-half { width: 50%; +} + +table tbody tr td.is-vcentered { + vertical-align: middle; +} + +#ImageTable tr td { + white-space: nowrap; +} + +table tr th.tablesorter-header { + outline: none; + cursor: pointer; } \ No newline at end of file diff --git a/src/main/resources/views/pages/home.ftl b/src/main/resources/views/pages/home.ftl index 0c18b9e..28fce3e 100644 --- a/src/main/resources/views/pages/home.ftl +++ b/src/main/resources/views/pages/home.ftl @@ -19,49 +19,36 @@ <#import "../ui/components/message.ftl" as message /> <#import "../ui/elements/box.ftl" as box /> <#import "../prebuilt/base.ftl" as base /> -<#import "../prebuilt/image-list-item.ftl" as imageListItem /> +<#import "../ui/elements/table.ftl" as table /> +<#import "../ui/elements/button.ftl" as button /> + +<#import "../prebuilt/image-list-table-item.ftl" as imageListTableItem /> +<#import "../prebuilt/image-list-item.ftl" as imageListBoxItem /> <@base.base title="Images" context="home" showTitle=false> -
-
- -
-
- <@input.text id="SearchImages" icon="search" placeholder="Search..." /> -
-
- -
-
-
-
-
- <#if availableRepositories?has_content && availableRepositories?size > 0> - <@input.dropdown id="RepositorySelection" size="normal" icon="cubes"> - <#list availableRepositories as repository> - - - - <#else> - There are currently no available repositories. - -
-
+<#--
--> +<#--
--> +<#-- <#if availableRepositories?has_content && availableRepositories?size > 0>--> +<#-- <@input.dropdown id="RepositorySelection" size="normal" icon="cubes">--> +<#-- <#list availableRepositories as repository>--> +<#-- --> +<#-- --> +<#-- --> +<#-- <#else>--> +<#-- There are currently no available repositories.--> +<#-- --> +<#--
--> +<#--
--> <#if selectedRepository?has_content>
-
-

- ${selectedRepository.name}. -

-
-
+
+ +
+

+ ${selectedRepository.name}. +

+
+ +
+ <@input.text id="SearchImages" icon="search" placeholder="Search..." /> +
+
-
- <#if selectedRepository.images?has_content> +
+ +
+ <@button.buttons isGrouped=true isRightAligned=true> + <@button.button id="DisplayImageTable" colour="normal-colour" title="Display as table" extraClasses="is-active"> + + + <@button.button id="DisplayImageGrid" colour="normal-colour" title="Display as grid"> + + + +
+
+ + <#if selectedRepository.images?has_content> + +
+ +
+ <@table.table id="ImageTable" isFullWidth=true isScrollable=true extraClasses="table--sortable"> + + + Name + + Latest Version + Build Time + Pulls + Stars + + + + <#list selectedRepository.images as image> + <@imageListTableItem.imageListItem image=image /> + + + +
+ +
+ + + + <#else> +
No images - -
+
+ diff --git a/src/main/resources/views/pages/image.ftl b/src/main/resources/views/pages/image.ftl new file mode 100644 index 0000000..8cae3ed --- /dev/null +++ b/src/main/resources/views/pages/image.ftl @@ -0,0 +1,76 @@ +<#-- + Copyright (c) 2019 LinuxServer.io + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +--> + +<#import "../prebuilt/base.ftl" as base /> +<#import "../ui/layout/section.ftl" as section /> +<#import "../ui/layout/container.ftl" as container /> +<#import "../ui/elements/box.ftl" as box /> +<#import "../ui/elements/table.ftl" as table /> +<#import "../ui/elements/tag.ftl" as tag /> + +<@base.base title="${image.fullName}" context="image"> + + <@section.section> + <@container.container> + +
+ +
+

+ ${image.repositoryName}/${image.name}. + <#if image.deprecated> + <@tag.tag colour="warning" value="Deprecated" /> + +

+
+ <@tag.tag colour="light" value=' ${image.pullCount}' extraAttributes='title="Pulls"' /> + <@tag.tag colour="light" value=' ${image.starCount}' extraAttributes='title="Stars"' /> +
+ +
+ +
+ <@box.box extraClasses="is-paddingless is-clipped"> + +

Build Information

+ <@table.table isFullWidth=true isNarrow=true isStriped=true> + + <@table.halfDisplayRow title="Repository" value='${image.repositoryName}' /> + <@table.halfDisplayRow title="Build Time" value=image.lastUpdatedAsString /> + <@table.halfDisplayRow title="Stable" value=image.stable?string("Yes", "No") /> + <@table.halfDisplayRow title="Synchronised" value=image.syncEnabled?string("Yes", "No") /> + + + +

Tracked Tags

+ <@table.table isFullWidth=true isNarrow=true isStriped=true> + + <#list image.tagBranches as tagBranch> + <@table.halfDisplayRow title=' ${tagBranch.branchName}' value=(tagBranch.latestTag).version!"" /> + + + + + +
+ +
+ + + + + \ No newline at end of file diff --git a/src/main/resources/views/prebuilt/base.ftl b/src/main/resources/views/prebuilt/base.ftl index 03dbe34..ea42e59 100644 --- a/src/main/resources/views/prebuilt/base.ftl +++ b/src/main/resources/views/prebuilt/base.ftl @@ -57,6 +57,7 @@ <#nested> +