Skip to content

Commit

Permalink
Merge pull request #1449 from adpi2/rework-artifacts-page
Browse files Browse the repository at this point in the history
Rework artifacts page before deploying
  • Loading branch information
adpi2 authored Aug 22, 2024
2 parents fc2a691 + e2c1f24 commit c56029b
Show file tree
Hide file tree
Showing 26 changed files with 283 additions and 280 deletions.
4 changes: 1 addition & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,7 @@ lazy val server = project
"org.webjars.bower" % "select2" % "4.0.13"
),
Compile / unmanagedResourceDirectories += (Assets / WebKeys.public).value,
Compile / resourceGenerators += Def.task(
Seq((Assets / WebKeys.assets).value)
),
Compile / resourceGenerators += (Assets / WebKeys.assets).map(Seq(_)),
fork := true,
Compile / run / javaOptions ++= (infra / Compile / run / javaOptions).value,
reStart / javaOptions ++= (infra / Compile / run / javaOptions).value,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ final case class ProjectHeader(
def platforms(artifactName: Artifact.Name): Seq[Platform] =
artifacts.filter(_.artifactName == artifactName).map(_.platform).distinct.sorted(Platform.ordering.reverse)

def artifactsUrl: String = artifactsUrl(getDefaultArtifact(None, None), withBinaryVersion = false)
def versionsUrl: String = artifactsUrl(getDefaultArtifact(None, None), withBinaryVersion = false)

def artifactsUrl(language: Language): String = artifactsUrl(getDefaultArtifact(Some(language), None))
def versionsUrl(language: Language): String = artifactsUrl(getDefaultArtifact(Some(language), None))

def artifactsUrl(platform: Platform): String = artifactsUrl(getDefaultArtifact(None, Some(platform)))
def versionsUrl(platform: Platform): String = artifactsUrl(getDefaultArtifact(None, Some(platform)))

private def artifactsUrl(defaultArtifact: Artifact, withBinaryVersion: Boolean = true): String = {
val preReleaseFilter = Option.when(!preferStableVersion || !defaultArtifact.version.isStable)("pre-releases=true")
val preReleaseFilter = Option.when(preferStableVersion && defaultArtifact.version.isStable)("stable-only=true")
val binaryVersionFilter = Option.when(withBinaryVersion)(s"binary-versions=${defaultArtifact.binaryVersion.label}")
val filters = preReleaseFilter.toSeq ++ binaryVersionFilter
val queryParams = if (filters.nonEmpty) "?" + filters.mkString("&") else ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ trait WebDatabase {
def insertArtifact(artifact: Artifact): Future[Boolean]
def getArtifacts(groupId: Artifact.GroupId, artifactId: String): Future[Seq[Artifact]]
def getArtifacts(projectRef: Project.Reference): Future[Seq[Artifact]]
def getArtifacts(ref: Project.Reference, artifactName: Artifact.Name, preReleases: Boolean): Future[Seq[Artifact]]
def getArtifacts(ref: Project.Reference, artifactName: Artifact.Name, stableOnly: Boolean): Future[Seq[Artifact]]
def getArtifacts(ref: Project.Reference, artifactName: Artifact.Name, version: SemanticVersion): Future[Seq[Artifact]]
def getArtifactsByName(projectRef: Project.Reference, artifactName: Artifact.Name): Future[Seq[Artifact]]
def getLatestArtifacts(ref: Project.Reference): Future[Seq[Artifact]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import scaladex.core.model.BinaryVersion

case class ArtifactsPageParams(
binaryVersions: Seq[BinaryVersion],
preReleases: Boolean
stableOnly: Boolean
) {
def remove(b: BinaryVersion): ArtifactsPageParams = copy(binaryVersions = binaryVersions.filterNot(_ == b))
def withPreReleases(preReleases: Boolean): ArtifactsPageParams = copy(preReleases = preReleases)
def binaryVersionsSummary: Option[String] =
Option.when(binaryVersions.nonEmpty)(binaryVersions.mkString(", "))
}

object ArtifactsPageParams {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class SemanticVersionTests extends AsyncFunSpec with Matchers with TableDrivenPr
forAll(inputs)((lower, higher) => lower shouldBe <(higher))
}

it("should allow us to prefer releases over pre-releases") {
it("should allow us to prefer stable over pre-releases") {
val versions = Seq(`7.0.0`, `7.1.0`, `7.2.0-PREVIEW.1`)
versions.max shouldBe `7.2.0-PREVIEW.1`
versions.max(PreferStable) shouldBe `7.1.0`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,9 @@ class InMemoryDatabase extends SchedulerDatabase {
override def getArtifacts(
ref: Project.Reference,
artifactName: Artifact.Name,
preReleases: Boolean
stableOnly: Boolean
): Future[Seq[Artifact]] =
// TODO: use preReleases to filter
// TODO: use stableOnly to filter
Future.successful(allArtifacts.getOrElse(ref, Seq.empty).filter(_.artifactName == artifactName))
override def getProjectDependencies(
ref: Project.Reference,
Expand Down
4 changes: 2 additions & 2 deletions modules/infra/src/main/scala/scaladex/infra/SqlDatabase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@ class SqlDatabase(datasource: HikariDataSource, xa: doobie.Transactor[IO]) exten
override def getArtifacts(
ref: Project.Reference,
artifactName: Artifact.Name,
preReleases: Boolean
stableOnly: Boolean
): Future[Seq[Artifact]] =
run(ArtifactTable.selectArtifactByParams(preReleases).to[Seq](ref, artifactName))
run(ArtifactTable.selectArtifactByParams(stableOnly).to[Seq](ref, artifactName))

override def updateLatestVersion(ref: Artifact.MavenReference): Future[Unit] = {
val transaction = for {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ object ArtifactTable {
where = Seq("organization=?", "repository=?", "artifact_name=?", "version=?")
)

def selectArtifactByParams(preReleases: Boolean): Query[(Project.Reference, Artifact.Name), Artifact] = {
val preReleaseFilter = if (preReleases) "true" else "is_prerelease=false"
def selectArtifactByParams(stableOnly: Boolean): Query[(Project.Reference, Artifact.Name), Artifact] = {
val preReleaseFilter = if (stableOnly) "is_prerelease=false" else "true"
Query[(Project.Reference, Artifact.Name), Artifact](
s"""|SELECT ${fields.mkString(", ")}
|FROM $table
Expand Down
3 changes: 2 additions & 1 deletion modules/server/src/main/assets/css/main-8.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
// 3. Vendors Extensions
@import
'vendors-extensions/bootstrap',
'vendors-extensions/bootstrap-select';
'vendors-extensions/bootstrap-select',
'vendors-extensions/bootstrap-switch';

// 4. Base
@import
Expand Down
97 changes: 74 additions & 23 deletions modules/server/src/main/assets/css/partials/_project.scss
Original file line number Diff line number Diff line change
Expand Up @@ -273,28 +273,24 @@
}
}
}

.artifacts {
.artifacts-filter {
margin-top: -10px;
margin-bottom: 50px;
}

.artifacts, .versions {
.center {
@media (min-width: $screen-md-min) {
display: flex;
justify-content: center;
align-items: center;
}
}
.artifact-version {
font-size: 30px;
color: $brand-secondary;
&:active,
&:focus,
&:hover {
text-decoration: none;
color: $brand-primary;
}
.result-count {
margin-top: 24px;
font-size: 16px;
}
.panel {
margin-bottom: 12px
}
.panel-content {
padding: 0 0 6px 0;
}
.artifact-info {
@media (min-width: 600px) {
Expand All @@ -320,8 +316,13 @@
display: inline;
}
}
.filter-option-inner-inner {
color: white;
.btn-secondary {
.filter-option-inner-inner {
color: $headings-color;
}
.caret {
color: $headings-color;
}
}
.dropdown {
margin-right: 15px;
Expand All @@ -337,16 +338,66 @@
margin-right: 20px;
}
}
.result-count {
float: right;
font-size: 16px;
}

.artifacts {
.artifact-name, .artifact-version {
color: $brand-secondary;
&:active, &:focus, &:hover {
text-decoration: none;
color: $brand-primary;
}
}

.artifact-name {
font-size: 24px;
}

.artifact-version {
color: $headings-color;
font-size: 20px;
margin-left: 12px;
}
}

.versions {
h2 {
margin-top: 0;
margin-bottom: 24px;
color: $brand-secondary;
.bootstrap-select {
margin-left: 7px;
width: 150px;
}
.btn {
padding: 10px 10px 6px 10px;
}
.btn-default {
color: $gray-light;
}
.filter-option {
padding-right: 4px;
}
.caret {
top: 55%;
}
}

.artifact-version {
font-size: 30px;
color: $brand-secondary;
&:active,
&:focus,
&:hover {
text-decoration: none;
color: $brand-primary;
}
}
}

.artifact {
h3 {
h2 {
margin-top: 0;
font-size: 2em;
display: inline;
color: $brand-secondary;
a {
color: inherit;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.bootstrap-switch {
.bootstrap-switch-label {
padding: 7px;
font-size: 16px;
line-height:1.52857;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,47 @@ class ProjectPages(env: Env, database: SchedulerDatabase, searchEngine: SearchEn
routes = get {
path(projectM)(getProjectPage(_, user))
},
get {
path(projectM / "artifacts") { ref =>
artifactsParams { params =>
getProjectOrRedirect(ref, user) { project =>
for (header <- projectService.getProjectHeader(project)) yield {
val allArtifacts = header.toSeq.flatMap(_.artifacts)

val binaryVersions = allArtifacts
.map(_.binaryVersion)
.distinct
.sorted(BinaryVersion.ordering.reverse)

val groupedArtifacts = allArtifacts
.groupBy(_.artifactName)
.map {
case (name, artifacts) =>
val latestVersion = artifacts.maxBy(_.version).version
val filteredArtifacts = artifacts.filter(_.version == latestVersion)
(name, latestVersion, filteredArtifacts)
}
.filter {
case (_, _, artifacts) =>
params.binaryVersions
.forall(binaryVersion => artifacts.exists(_.binaryVersion == binaryVersion))
}
.toSeq
.sortBy { case (name, version, _) => (version, name) }(
Ordering.Tuple2(SemanticVersion.ordering.reverse, Artifact.Name.ordering)
)
val page = html.artifacts(env, user, project, header, groupedArtifacts, params, binaryVersions)
complete(page)
}
}
}
}
},
get {
path(projectM / "artifacts" / artifactNameM) { (ref, artifactName) =>
artifactsParams { params =>
getProjectOrRedirect(ref, user) { project =>
val artifactsF = database.getArtifacts(ref, artifactName, params.preReleases)
val artifactsF = database.getArtifacts(ref, artifactName, params.stableOnly)
val headerF = projectService.getProjectHeader(project).map(_.get)
for (artifacts <- artifactsF; header <- headerF) yield {
val binaryVersions = artifacts
Expand Down Expand Up @@ -113,57 +149,6 @@ class ProjectPages(env: Env, database: SchedulerDatabase, searchEngine: SearchEn
}
}
},
get {
path(projectM / "artifacts") { ref =>
artifactsParams { params =>
getProjectOrRedirect(ref, user) { project =>
val headerF = projectService.getProjectHeader(project)
for {
header <- headerF
} yield {
val allArtifacts = header.toSeq.flatMap(_.artifacts)

val binaryVersions = allArtifacts
.map(_.binaryVersion)
.distinct
.sorted(BinaryVersion.ordering.reverse)

// Group by artifact name
val artifactsByName = allArtifacts.groupBy(_.artifactName)

val groupedArtifacts = artifactsByName
.groupBy {
case (_, artifacts) =>
artifacts.maxBy(_.version).version
}
.map {
case (latestVersion, artifactsByName) =>
latestVersion -> artifactsByName
.map {
case (name, artifacts) =>
name -> artifacts
.filter(_.version == latestVersion)
}
.filter {
case (_, artifacts) =>
params.binaryVersions.forall(binaryVersion =>
artifacts
.exists(_.binaryVersion == binaryVersion)
)
}
}
.filter {
case (_, artifactsByName) =>
artifactsByName.nonEmpty
}

val page = html.artifacts(env, user, project, header, groupedArtifacts, params, binaryVersions)
complete(page)
}
}
}
}
},
get {
path(projectM / "version-matrix") { ref =>
getProjectOrRedirect(ref, user) { project =>
Expand Down Expand Up @@ -264,7 +249,7 @@ class ProjectPages(env: Env, database: SchedulerDatabase, searchEngine: SearchEn
private val artifactsParams: Directive1[ArtifactsPageParams] =
parameters(
"binary-versions".repeated,
"pre-releases".as[Boolean].withDefault(false)
"stable-only".as[Boolean].withDefault(false)
).tmap {
case (rawbinaryVersions, preReleases) =>
val binaryVersions = rawbinaryVersions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class BadgesUnitTests extends AnyFunSpec with Matchers {
) shouldBe "7.3.0 (Scala 3.x, 2.13), 7.2.0 (Scala 2.12), 7.1.0 (Scala 2.11)"
}

it("should prefer releases to pre-releases if both are available") {
it("should prefer stable to pre-releases if both are available") {
summaryOfLatestVersions(Map(`2.13` -> Seq(`7.0.0`, `7.1.0`, `7.2.0-PREVIEW.1`))) shouldBe "7.1.0 (Scala 2.13)"
}

Expand Down
11 changes: 11 additions & 0 deletions modules/template/src/main/scala/scaladex/view/ProjectTab.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package scaladex.view

sealed trait ProjectTab
object ProjectTab {
object Main extends ProjectTab
object Artifacts extends ProjectTab
object Versions extends ProjectTab
object Badges extends ProjectTab
object Settings extends ProjectTab
object VersionMatrix extends ProjectTab
}
Loading

0 comments on commit c56029b

Please sign in to comment.