-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/develop' into directoryGroupErro…
…rHandling
- Loading branch information
Showing
9 changed files
with
584 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# This workflow uses actions that are not certified by GitHub. | ||
# They are provided by a third-party and are governed by | ||
# separate terms of service, privacy policy, and support | ||
# documentation. | ||
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time | ||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle | ||
|
||
name: Java CI with Gradle | ||
|
||
on: | ||
push: | ||
branches: [ "develop" ] | ||
pull_request: | ||
branches: [ "develop" ] | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: read | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Set up JDK 17 | ||
uses: actions/setup-java@v4 | ||
with: | ||
java-version: '17' | ||
distribution: 'zulu' | ||
|
||
# Configure Gradle for optimal use in GiHub Actions, including caching of downloaded dependencies. | ||
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md | ||
- name: Setup Gradle | ||
uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 | ||
|
||
- name: Build with Gradle Wrapper | ||
run: ./gradlew build | ||
|
||
# NOTE: The Gradle Wrapper is the default and recommended way to run Gradle (https://docs.gradle.org/current/userguide/gradle_wrapper.html). | ||
# If your project does not have the Gradle Wrapper configured, you can use the following configuration to run Gradle with a specified version. | ||
# | ||
# - name: Setup Gradle | ||
# uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 | ||
# with: | ||
# gradle-version: '8.5' | ||
# | ||
# - name: Build with Gradle 8.5 | ||
# run: gradle build | ||
|
||
dependency-submission: | ||
|
||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Set up JDK 17 | ||
uses: actions/setup-java@v4 | ||
with: | ||
java-version: '17' | ||
distribution: 'zulu' | ||
|
||
# Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies. | ||
# See: https://github.com/gradle/actions/blob/main/dependency-submission/README.md | ||
- name: Generate and submit dependency graph | ||
uses: gradle/actions/dependency-submission@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
65 changes: 65 additions & 0 deletions
65
grails-app/services/io/xh/hoist/track/TrackLogAdminService.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package io.xh.hoist.track | ||
|
||
import grails.gorm.transactions.ReadOnly | ||
import io.xh.hoist.BaseService; | ||
import io.xh.hoist.config.ConfigService | ||
import io.xh.hoist.data.filter.Filter | ||
import io.xh.hoist.exception.DataNotAvailableException | ||
import org.hibernate.Criteria | ||
import org.hibernate.SessionFactory | ||
import java.time.LocalDate; | ||
|
||
import static io.xh.hoist.util.DateTimeUtils.appEndOfDay | ||
import static io.xh.hoist.util.DateTimeUtils.appStartOfDay | ||
import static org.hibernate.criterion.Order.desc | ||
import static org.hibernate.criterion.Restrictions.between | ||
|
||
class TrackLogAdminService extends BaseService { | ||
ConfigService configService | ||
SessionFactory sessionFactory | ||
|
||
Boolean getEnabled() { | ||
return conf.enabled == true | ||
} | ||
|
||
@ReadOnly | ||
List<TrackLog> queryTrackLog(LocalDate startDay, LocalDate endDay, Filter filter, Integer maxRows = null) { | ||
if (!enabled) throw new DataNotAvailableException('TrackService not available.') | ||
|
||
def maxDefault = conf.maxRows.default as Integer, | ||
maxLimit = conf.maxRows.limit as Integer | ||
|
||
maxRows = [(maxRows ? maxRows : maxDefault), maxLimit].min() | ||
|
||
def session = sessionFactory.currentSession | ||
Criteria c = session.createCriteria(TrackLog) | ||
c.maxResults = maxRows | ||
c.addOrder(desc('dateCreated')) | ||
c.add(between('dateCreated', appStartOfDay(startDay), appEndOfDay(endDay))) | ||
if (filter) { | ||
c.add(filter.criterion) | ||
} | ||
c.list() as List<TrackLog> | ||
} | ||
|
||
@ReadOnly | ||
Map lookups() {[ | ||
category: distinctVals('category'), | ||
browser: distinctVals('browser'), | ||
device: distinctVals('device'), | ||
username: distinctVals('username') | ||
] } | ||
|
||
//------------------------ | ||
// Implementation | ||
//------------------------ | ||
private List distinctVals(String property) { | ||
TrackLog.createCriteria().list { | ||
projections { distinct(property) } | ||
}.sort() | ||
} | ||
|
||
private Map getConf() { | ||
configService.getMap('xhActivityTrackingConfig') | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
src/main/groovy/io/xh/hoist/data/filter/CompoundFilter.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* This file belongs to Hoist, an application development toolkit | ||
* developed by Extremely Heavy Industries (www.xh.io | [email protected]) | ||
* | ||
* Copyright © 2024 Extremely Heavy Industries Inc. | ||
*/ | ||
|
||
package io.xh.hoist.data.filter | ||
|
||
import io.xh.hoist.json.JSONFormat | ||
import org.hibernate.criterion.Criterion | ||
|
||
/** | ||
* Combines multiple filters (including other nested CompoundFilters) via an AND or OR operator. | ||
*/ | ||
class CompoundFilter extends Filter implements JSONFormat { | ||
|
||
final List<Filter> filters | ||
final String op | ||
|
||
CompoundFilter(List filters, String op) { | ||
op = op ? op.toUpperCase() : 'AND' | ||
if (op != 'AND' && op != 'OR') throw new RuntimeException('CompoundFilter requires "op" value of "AND" or "OR"') | ||
this.filters = filters.collect { parse(it) }.findAll() | ||
this.op = op | ||
} | ||
|
||
Map formatForJSON() { | ||
return [ | ||
filters: filters, | ||
op: op | ||
] | ||
} | ||
|
||
//--------------------- | ||
// Overrides | ||
//---------------------- | ||
List<String> getAllFields() { | ||
filters.collectMany { it.allFields }.unique() | ||
} | ||
|
||
Criterion getCriterion() { | ||
op == 'AND' ? and(filters*.criterion) : or(filters*.criterion) | ||
} | ||
|
||
Closure<Boolean> getTestFn() { | ||
if (!filters) return { true } | ||
def tests = filters*.testFn | ||
return op == 'AND' ? | ||
{ tests.every { test -> test(it) } } : | ||
{ tests.any { test -> test(it) } } | ||
} | ||
|
||
boolean equals(Filter other) { | ||
if (other === this) return true; | ||
return ( | ||
other instanceof CompoundFilter && | ||
other.op == op && | ||
other.filters == filters | ||
) | ||
} | ||
} |
Oops, something went wrong.