Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
220731137a
|
||
|
|
4472fa82e5
|
||
|
|
8912dfe49b
|
||
|
|
52661a5a9e
|
||
|
|
43bad706ec | ||
|
|
1232edaa61 |
No files matched your search
@@ -11,4 +11,4 @@ workflows:
|
|||||||
branches:
|
branches:
|
||||||
ignore: automation/qbit-rc-pending
|
ignore: automation/qbit-rc-pending
|
||||||
tags:
|
tags:
|
||||||
only: /^v\d+\.\d+\.\d+$/
|
only: /v.*/
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
name: build
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
jobs:
|
|
||||||
maven:
|
|
||||||
uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/maven.yaml@v1
|
|
||||||
secrets: inherit
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Standard QRun release caller (v2, thin contract): every push and manual dispatch delegates to the protected qrun-release-v1 channel. Do not edit per repository.
|
||||||
|
name: qrun-release
|
||||||
|
on:
|
||||||
|
push: {}
|
||||||
|
workflow_dispatch: {}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
actions: read
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
uses: self:KofTwentyTwo/platform-ci/.gitea/workflows/java-maven.yaml@qrun-release-v1
|
||||||
|
with:
|
||||||
|
runner: linux-small
|
||||||
|
browsers: true
|
||||||
|
browser-runner: browser-build
|
||||||
|
postpublish:
|
||||||
|
if: ${{ needs.release.outputs.capture == 'true' }}
|
||||||
|
needs: release
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
actions: write
|
||||||
|
uses: self:KofTwentyTwo/platform-ci/.gitea/workflows/qrun-source-version.yaml@qrun-release-v1
|
||||||
|
with:
|
||||||
|
runner: linux-small
|
||||||
@@ -1 +0,0 @@
|
|||||||
* @KofTwentyTwo
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
name: Release candidate
|
|
||||||
'on':
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
dry_run:
|
|
||||||
description: Plan a cut without changing release state
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
finalize:
|
|
||||||
description: Retry finalization of an existing cut; do not cut another RC
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
recover:
|
|
||||||
description: Recover the same published RC after a deployment timeout; never
|
|
||||||
reupload
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
circle_build:
|
|
||||||
description: Original Circle publisher build number (recovery only)
|
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
merge_sha:
|
|
||||||
description: Existing cut merge_sha (finalize retry only)
|
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
bump_sha:
|
|
||||||
description: Existing cut bump_sha (finalize retry only)
|
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
branch:
|
|
||||||
description: Existing cut branch (finalize retry only)
|
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
version:
|
|
||||||
description: Existing cut version (finalize retry only)
|
|
||||||
type: string
|
|
||||||
default: ''
|
|
||||||
pull_request:
|
|
||||||
types:
|
|
||||||
- closed
|
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
repository_dispatch:
|
|
||||||
types:
|
|
||||||
- qbit-rc-published
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
actions: read
|
|
||||||
checks: read
|
|
||||||
jobs:
|
|
||||||
release-rc:
|
|
||||||
if: github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch'
|
|
||||||
|| (github.event_name == 'pull_request' && github.event.pull_request.merged
|
|
||||||
== true && github.event.pull_request.base.ref == 'develop' && contains(github.event.pull_request.labels.*.name,
|
|
||||||
'release:rc'))
|
|
||||||
uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@cc30f599e63c8e41629c99d23395bac1adb8bc44
|
|
||||||
with:
|
|
||||||
dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false
|
|
||||||
}}
|
|
||||||
finalize: ${{ github.event_name == 'repository_dispatch' || (github.event_name
|
|
||||||
== 'workflow_dispatch' && inputs.finalize) }}
|
|
||||||
recover: ${{ github.event_name == 'workflow_dispatch' && inputs.recover || false
|
|
||||||
}}
|
|
||||||
circle_build: ${{ github.event_name == 'workflow_dispatch' && inputs.circle_build
|
|
||||||
|| '' }}
|
|
||||||
merge_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.merge_sha
|
|
||||||
|| inputs.merge_sha || '' }}
|
|
||||||
bump_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.bump_sha
|
|
||||||
|| inputs.bump_sha || '' }}
|
|
||||||
branch: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.branch
|
|
||||||
|| inputs.branch || '' }}
|
|
||||||
version: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.version
|
|
||||||
|| inputs.version || '' }}
|
|
||||||
secrets: inherit
|
|
||||||
+4
-4
@@ -5,12 +5,12 @@ java_version: '21'
|
|||||||
browsers: true
|
browsers: true
|
||||||
api_checks: false
|
api_checks: false
|
||||||
docs_only: false
|
docs_only: false
|
||||||
release_on_main: false
|
release_on_main: true
|
||||||
release_tag_policy: stable
|
release_tag_policy: v-prefix
|
||||||
test_branch_policy: non-release
|
test_branch_policy: feature-no-hotfix
|
||||||
publish:
|
publish:
|
||||||
snapshot: true
|
snapshot: true
|
||||||
release_candidate: true
|
release_candidate: true
|
||||||
release: true
|
release: true
|
||||||
|
hotfix: true
|
||||||
asciidoc: false
|
asciidoc: false
|
||||||
release_completion: true
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
# qbit-customizable-table-views
|
|
||||||
|
|
||||||
## Knowledge base
|
|
||||||
|
|
||||||
A reviewed dossier for this repo lives in the second-brain vault:
|
|
||||||
|
|
||||||
- Hub / start here: `R:/Git.Local/KofTwentyTwo/second-brain/knowledge/qqq/qqq-hub.md`
|
|
||||||
- This repo's dossier: `R:/Git.Local/KofTwentyTwo/second-brain/knowledge/qqq/repos/qbit-customizable-table-views.md`
|
|
||||||
- QBit mechanics refresher: `R:/Git.Local/KofTwentyTwo/second-brain/knowledge/qqq/architecture/metadata-model.md`
|
|
||||||
|
|
||||||
Reviewed at commit `6a0f548afa8e` (branch `develop`, 2026-05-21). If HEAD has moved
|
|
||||||
significantly past that commit, treat the dossier as potentially stale.
|
|
||||||
|
|
||||||
Notes for agents working here:
|
|
||||||
|
|
||||||
- The README describes a "saved views" API (`QSavedViewMetaData`, `saved_view` tables) that
|
|
||||||
does NOT exist in this code — trust the source, not the README. CHANGELOG.md and
|
|
||||||
CONTRIBUTING.md are copy-pasted from qbit-user-role-permissions.
|
|
||||||
- Licensing metadata is contradictory (LICENSE/NOTICE = Apache-2.0; pom, file headers,
|
|
||||||
checkstyle template = AGPL-3.0; README footer says proprietary). Open PR #5 fixes the pom.
|
|
||||||
- Default builds take the qqq version only from `qbit-build-parent` (2.0.0 = qqq 4.0.0);
|
|
||||||
do not add an always-on `qqq-bom-pom` import (ADR-0007). To check the next qqq line, run
|
|
||||||
`mvn -B verify -Pqqq-snapshot` (4.1.0-SNAPSHOT; override with `-Dqqq.snapshot.version`).
|
|
||||||
@@ -38,7 +38,7 @@ This QBit lets users save these configurations as named views. Create a view, ad
|
|||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- QQQ application (v4.1.0+)
|
- QQQ application (v0.35.0+)
|
||||||
- QQQ dashboard deployed
|
- QQQ dashboard deployed
|
||||||
- Database backend configured
|
- Database backend configured
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.kingsrook</groupId>
|
<groupId>com.kingsrook</groupId>
|
||||||
<artifactId>qbit-build-parent</artifactId>
|
<artifactId>qbit-build-parent</artifactId>
|
||||||
<version>2.2.1</version>
|
<version>1.5.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>com.kingsrook.qbits</groupId>
|
<groupId>com.kingsrook.qbits</groupId>
|
||||||
@@ -65,17 +65,15 @@
|
|||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>0.5.0-SNAPSHOT</revision>
|
<revision>0.4.0</revision>
|
||||||
<qqq.version>4.1.0-RC.26</qqq.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- Published QQQ 4.1 core (minimum QQQ 4.1), imported ahead of the parent's BOM. -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.kingsrook.qqq</groupId>
|
<groupId>com.kingsrook.qqq</groupId>
|
||||||
<artifactId>qqq-bom-pom</artifactId>
|
<artifactId>qqq-bom-pom</artifactId>
|
||||||
<version>${qqq.version}</version>
|
<version>0.40.0</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -112,4 +110,11 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>sonatype-snapshots</id>
|
||||||
|
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
+2
-3
@@ -36,7 +36,6 @@ import com.kingsrook.qqq.backend.core.model.data.QRecord;
|
|||||||
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
import com.kingsrook.qqq.backend.core.model.metadata.fields.QFieldMetaData;
|
||||||
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
|
import com.kingsrook.qqq.backend.core.model.statusmessages.BadInputStatusMessage;
|
||||||
import com.kingsrook.qqq.backend.core.model.statusmessages.SystemErrorStatusMessage;
|
import com.kingsrook.qqq.backend.core.model.statusmessages.SystemErrorStatusMessage;
|
||||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@@ -58,8 +57,8 @@ public class TableViewFieldCustomizer implements TableCustomizerInterface
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Integer id = record.getValueInteger("id");
|
Integer id = record.getValueInteger("id");
|
||||||
String fieldName = ValueUtils.getValueAsString(RecordCustomizerUtilityInterface.getValueFromRecordElseFromOldRecord("fieldName", record, id, oldRecordMap));
|
String fieldName = RecordCustomizerUtilityInterface.getValueFromRecordOrOldRecord("fieldName", record, id, oldRecordMap);
|
||||||
String accessLevelId = ValueUtils.getValueAsString(RecordCustomizerUtilityInterface.getValueFromRecordElseFromOldRecord("accessLevel", record, id, oldRecordMap));
|
String accessLevelId = RecordCustomizerUtilityInterface.getValueFromRecordOrOldRecord("accessLevel", record, id, oldRecordMap);
|
||||||
|
|
||||||
String[] parts = fieldName.split("\\.");
|
String[] parts = fieldName.split("\\.");
|
||||||
String tableName = parts[0];
|
String tableName = parts[0];
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class BaseTest
|
|||||||
// basic definition of an instance //
|
// basic definition of an instance //
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
QInstance qInstance = new QInstance();
|
QInstance qInstance = new QInstance();
|
||||||
qInstance.withInstanceDefaultAuthentication(new QAuthenticationMetaData().withType(QAuthenticationType.FULLY_ANONYMOUS));
|
qInstance.setAuthentication(new QAuthenticationMetaData().withType(QAuthenticationType.FULLY_ANONYMOUS));
|
||||||
qInstance.addBackend(new RDBMSBackendMetaData()
|
qInstance.addBackend(new RDBMSBackendMetaData()
|
||||||
.withName(RDBMS_BACKEND_NAME)
|
.withName(RDBMS_BACKEND_NAME)
|
||||||
.withVendor("h2")
|
.withVendor("h2")
|
||||||
|
|||||||
-26
@@ -96,32 +96,6 @@ class TableViewFieldCustomizerTest extends BaseTest
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** a sparse update (e.g., only accessLevel set) must validate against the
|
|
||||||
** fieldName from the old record.
|
|
||||||
*******************************************************************************/
|
|
||||||
@Test
|
|
||||||
void testSparseUpdateUsesOldRecordValues() throws QException
|
|
||||||
{
|
|
||||||
QContext.getQInstance().addTable(new QTableMetaData()
|
|
||||||
.withName("testTable3")
|
|
||||||
.withField(new QFieldMetaData("mandatory", QFieldType.STRING).withIsRequired(true))
|
|
||||||
.withField(new QFieldMetaData("optional", QFieldType.STRING)));
|
|
||||||
|
|
||||||
Optional<List<QRecord>> oldRecordList = Optional.of(List.of(
|
|
||||||
new TableViewField().withId(1).withFieldName("testTable3.mandatory").withAccessLevel(FieldAccessLevel.EDITABLE_REQUIRED).toQRecord(),
|
|
||||||
new TableViewField().withId(2).withFieldName("testTable3.optional").withAccessLevel(FieldAccessLevel.EDITABLE_OPTIONAL).toQRecord()));
|
|
||||||
|
|
||||||
QRecord mandatoryToReadOnly = new QRecord().withValue("id", 1).withValue("accessLevel", FieldAccessLevel.READ_ONLY.getId());
|
|
||||||
QRecord optionalToReadOnly = new QRecord().withValue("id", 2).withValue("accessLevel", FieldAccessLevel.READ_ONLY.getId());
|
|
||||||
new TableViewFieldCustomizer().preInsertOrUpdate(null, List.of(mandatoryToReadOnly, optionalToReadOnly), false, oldRecordList);
|
|
||||||
|
|
||||||
assertThat(mandatoryToReadOnly.getErrors()).hasSizeGreaterThan(0);
|
|
||||||
assertThat(optionalToReadOnly.getErrors()).isNullOrEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|||||||
Reference in new issue
Block a user