Skip to content
Merged

Dev #2510

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f841476
AB#32696: Applicant Profile - Payments Tab
aurelio-aot May 27, 2026
4319403
[AB#32785] Fix tag menu slider overflow and height issues
plavoie-BC May 28, 2026
f8a8802
[AB#32785] Refactor tag menu slider styles for consistency
plavoie-BC May 28, 2026
6dc7f8e
[AB#32785] Consolidate tag table selectors
plavoie-BC May 28, 2026
025a1de
Merge pull request #2503 from bcgov/bugfix/AB#32785-tag-menu-slider
JamesPasta May 28, 2026
1b88e93
AB#32218 split out attachments query
AndreGAot May 28, 2026
e7eeb74
Merge pull request #2504 from bcgov/bugfix/AB#32218-err-incomplete-chunk
AndreGAot May 28, 2026
ed4b260
[AB#32773] Rename PaymentTagsInput for namespace conflict
plavoie-BC May 28, 2026
480b2a1
AB#33235 Replace GH_API_TOKEN → GITHUB_TOKEN
DarylTodosichuk May 28, 2026
68e2673
AB#33235 Switch sonarsource-scan.yml java-version distribution to tem…
DarylTodosichuk May 28, 2026
440b52b
Merge pull request #2505 from bcgov/feature/AB#33235-Replace-GH_API_T…
DarylTodosichuk May 28, 2026
d53c020
[AB#32773] Tag Input SonarQube fixes
plavoie-BC May 28, 2026
e8a5613
initial commit
May 28, 2026
14fe289
[AB#32773] Refactor event listeners to use arrow functions
plavoie-BC May 28, 2026
2bee953
AB#33254 Fix chefs smoke test to validate pre-auth DOM only
May 28, 2026
c768f2a
AB#32696: Fix bug on export button
aurelio-aot May 29, 2026
86a855e
AB#32696: Fix sonarqube issues
aurelio-aot May 29, 2026
c10cfd3
[AB#32773] Update modal save button based on permissions
plavoie-BC May 29, 2026
3d627aa
Merge branch 'dev' into bugfix/AB#32773-tag-modal-permission
plavoie-BC May 29, 2026
4ee7948
AB#33235 Apply token GH_API_TOKEN at PushVariables job level
DarylTodosichuk May 29, 2026
f5d89a9
Merge pull request #2509 from bcgov/feature/AB#33235-Replace-GH_API_T…
DarylTodosichuk May 29, 2026
7aec920
Merge pull request #2507 from bcgov/feature/AB#33254_fix_chefs_dev
DarylTodosichuk May 29, 2026
2f0e663
Merge pull request #2508 from bcgov/feature/AB#32696-ApplicantProfile…
JamesPasta May 29, 2026
74bbde8
Merge pull request #2506 from bcgov/bugfix/AB#32773-tag-modal-permission
JamesPasta May 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/manual-trigger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ on:
type: string
env:
TARGET_ENV: ${{ inputs.name }}
GH_TOKEN: ${{secrets.GH_API_TOKEN}}
GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
OC_CLUSTER: ${{ vars.OPENSHIFT_CLUSTER }}
OC_REGISTRY: ${{ vars.OPENSHIFT_REGISTRY }}
OC_AUTH_TOKEN: ${{ secrets.OPENSHIFT_TOKEN }}
Expand Down Expand Up @@ -89,6 +89,8 @@ jobs:
permissions:
actions: write
contents: read
env:
GH_TOKEN: ${{ secrets.GH_API_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@v6
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sonarsource-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
uses: actions/setup-java@v5
with:
java-version: 17
distribution: 'zulu'
distribution: 'temurin'

- uses: actions/checkout@v6
with:
Expand Down
23 changes: 16 additions & 7 deletions applications/Unity.AutoUI/cypress/e2e/library/chefs.cy.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
describe('Chefs Login and Logout', () => {
describe("Chefs Login and Logout", () => {
it("Verify that Chefs is online.", () => {
cy.getChefsDetail("chefsBaseURL").then((baseURL) => {
cy.visit(baseURL);

it('Verify that Chefs is online.', () => {
cy.chefsLogin();
cy.contains("My Forms").should('exist').click();
cy.chefsLogout();
})
})
cy.contains("button, a, [role='button']", /log\s*in|login/i)
.should("exist")
.click({ force: true });

cy.location("pathname").should("include", "/app/login");
cy.contains("button, a, [role='button']", /IDIR/i).should("exist");
cy.contains("button, a, [role='button']", /BC Services Card/i).should(
"exist",
);
});
});
});
214 changes: 122 additions & 92 deletions applications/Unity.AutoUI/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,39 @@ Cypress.Commands.add("getChefsDetail", (key: string) => {
Cypress.Commands.add("chefsLogin", () => {
cy.getChefsDetail("chefsBaseURL").then((baseURL) => {
cy.visit(baseURL); // Visit the URL fetched from chefs.json
cy.get("#app > div > main > header > header > div > div.d-print-none")
.should("exist")
.click(); // click the login button
cy.get("body").then(($body) => {
// Prefer resilient text-based selectors over brittle full DOM paths.
if ($body.find("button:contains('LOGIN'), a:contains('LOGIN')").length) {
cy.contains("button, a", /^LOGIN$/i)
.first()
.click({ force: true });
} else if (
$body.find(
"#app > div > main > header > header > div > div.d-print-none",
).length
) {
cy.get("#app > div > main > header > header > div > div.d-print-none")
.should("exist")
.click({ force: true });
}
});
cy.wait(1000);
cy.get(
"#app > div > main > div.v-container.v-locale--is-ltr.text-center.main > div > div:nth-child(2) > div > button",
)
.should("exist")
.click(); // click the idir buttton
cy.get("body").then(($body) => {
// Some pages show an IDIR choice button before the credential form.
if ($body.find("button:contains('IDIR'), a:contains('IDIR')").length) {
cy.contains("button, a", /IDIR/i).first().click({ force: true });
} else if (
$body.find(
"#app > div > main > div.v-container.v-locale--is-ltr.text-center.main > div > div:nth-child(2) > div > button",
).length
) {
cy.get(
"#app > div > main > div.v-container.v-locale--is-ltr.text-center.main > div > div:nth-child(2) > div > button",
)
.should("exist")
.click({ force: true });
}
});
cy.wait(1000);
cy.get("body").then(($body) => {
// Check if you're already logged in.
Expand Down Expand Up @@ -246,11 +270,14 @@ function fetchGrantApplications(): Cypress.Chainable<GrantApplication[]> {
.then((response) => {
if (response.status !== 200) {
throw new Error(
`API request failed with status ${response.status}: ${JSON.stringify(response.body)}`
`API request failed with status ${response.status}: ${JSON.stringify(response.body)}`,
);
}
const data = response.body as GrantApplicationResponse;
Cypress.log({ name: "fetch", message: `📋 Fetched ${data.items?.length || 0} applications` });
Cypress.log({
name: "fetch",
message: `📋 Fetched ${data.items?.length || 0} applications`,
});
return data.items || [];
});
});
Expand All @@ -262,89 +289,92 @@ Cypress.Commands.add(
return fetchGrantApplications().then((allApplications) => {
let applications = allApplications;

Cypress.log({ name: "fetch", message: `📋 Fetched ${applications.length} applications from API` });

// Filter by category if specified (e.g., 'Data Seeder')
if (options.categoryFilter) {
applications = applications.filter((app) =>
app.category === options.categoryFilter
);
Cypress.log({
name: "filter",
message: `📋 Filtered to ${applications.length} applications with category: ${options.categoryFilter}`,
});
}

// Filter by status if specified (e.g., 'Submitted', 'Under Assessment', 'Approved')
if (options.statusFilter && options.statusFilter.length > 0) {
applications = applications.filter((app) =>
options.statusFilter!.includes(app.status)
);
Cypress.log({
name: "filter",
message: `📋 Filtered to ${applications.length} applications with status: ${options.statusFilter.join(", ")}`,
});
}

// Filter by max age if specified
if (options.maxAge) {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - options.maxAge);
applications = applications.filter((app) => {
const submissionDate = new Date(app.submissionDate);
return submissionDate >= cutoffDate;
});
Cypress.log({
name: "filter",
message: `📋 Filtered to ${applications.length} applications within ${options.maxAge} days`,
});
}

if (applications.length === 0) {
throw new Error(
"No applications found matching the specified criteria"
);
}

// Sort applications (default: by submissionDate descending for latest first)
const sortBy = options.sortBy || 'submissionDate';
const sortOrder = options.sortOrder || 'desc';
applications.sort((a, b) => {
let aVal: number | string;
let bVal: number | string;

if (sortBy === 'submissionDate') {
aVal = new Date(a.submissionDate).getTime();
bVal = new Date(b.submissionDate).getTime();
} else {
aVal = a[sortBy] as number;
bVal = b[sortBy] as number;
}

if (sortOrder === 'desc') {
return bVal > aVal ? 1 : bVal < aVal ? -1 : 0;
} else {
return aVal > bVal ? 1 : aVal < bVal ? -1 : 0;
}
});

// Get the submission at the specified index (default: 0 = first/latest)
const index = options.index || 0;
if (index >= applications.length) {
throw new Error(
`Index ${index} out of range. Only ${applications.length} applications available.`
);
}

const selectedApp = applications[index];
Cypress.log({
name: "selected",
message: `✅ Selected submission: ${selectedApp.referenceNo} (Status: ${selectedApp.status}, Category: ${selectedApp.category})`,
});

return selectedApp.referenceNo;
Cypress.log({
name: "fetch",
message: `📋 Fetched ${applications.length} applications from API`,
});

// Filter by category if specified (e.g., 'Data Seeder')
if (options.categoryFilter) {
applications = applications.filter(
(app) => app.category === options.categoryFilter,
);
Cypress.log({
name: "filter",
message: `📋 Filtered to ${applications.length} applications with category: ${options.categoryFilter}`,
});
}

// Filter by status if specified (e.g., 'Submitted', 'Under Assessment', 'Approved')
if (options.statusFilter && options.statusFilter.length > 0) {
applications = applications.filter((app) =>
options.statusFilter!.includes(app.status),
);
Cypress.log({
name: "filter",
message: `📋 Filtered to ${applications.length} applications with status: ${options.statusFilter.join(", ")}`,
});
}

// Filter by max age if specified
if (options.maxAge) {
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - options.maxAge);
applications = applications.filter((app) => {
const submissionDate = new Date(app.submissionDate);
return submissionDate >= cutoffDate;
});
}
Cypress.log({
name: "filter",
message: `📋 Filtered to ${applications.length} applications within ${options.maxAge} days`,
});
}

if (applications.length === 0) {
throw new Error(
"No applications found matching the specified criteria",
);
}

// Sort applications (default: by submissionDate descending for latest first)
const sortBy = options.sortBy || "submissionDate";
const sortOrder = options.sortOrder || "desc";
applications.sort((a, b) => {
let aVal: number | string;
let bVal: number | string;

if (sortBy === "submissionDate") {
aVal = new Date(a.submissionDate).getTime();
bVal = new Date(b.submissionDate).getTime();
} else {
aVal = a[sortBy] as number;
bVal = b[sortBy] as number;
}

if (sortOrder === "desc") {
return bVal > aVal ? 1 : bVal < aVal ? -1 : 0;
} else {
return aVal > bVal ? 1 : aVal < bVal ? -1 : 0;
}
});

// Get the submission at the specified index (default: 0 = first/latest)
const index = options.index || 0;
if (index >= applications.length) {
throw new Error(
`Index ${index} out of range. Only ${applications.length} applications available.`,
);
}

const selectedApp = applications[index];
Cypress.log({
name: "selected",
message: `✅ Selected submission: ${selectedApp.referenceNo} (Status: ${selectedApp.status}, Category: ${selectedApp.category})`,
});

return selectedApp.referenceNo;
});
},
);

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ $(function () {

this.arr.push({ Id: id, Name: tagText });

let tagInput = this;

let tag = document.createElement('span');
tag.className = this.options.tagClass + ' ' + tagClass;
Expand All @@ -61,13 +60,13 @@ $(function () {
let closeIcon = document.createElement('a');
closeIcon.innerHTML = '&times;';

closeIcon.addEventListener('click', function (e) {
closeIcon.addEventListener('click', (e) => {
e.preventDefault();
let tag = this.parentNode;
let tag = e.currentTarget.parentNode;

let tagIndex = Array.from(tagInput.wrapper.childNodes).indexOf(tag);
let tagIndex = Array.from(this.wrapper.childNodes).indexOf(tag);
if (tagIndex !== -1) {
tagInput.deleteTag(tag, tagIndex);
this.deleteTag(tag, tagIndex);
}
})

Expand All @@ -82,23 +81,21 @@ $(function () {
}

TagsInput.prototype.deleteTag = function (tag, i) {
let self = this;

if (this.arr[i] && this.arr[i].Name === 'Uncommon Tags') {
if (this.arr[i]?.Name === 'Uncommon Tags') {
abp.message.confirm('Are you sure you want to delete all the uncommon tags?')
.then(function (confirmed) {
.then((confirmed) => {
if (confirmed) {
tag.remove();
self.arr.splice(i, 1);
self.orignal_input.value = JSON.stringify(self.arr);
updateSelectedTagsInput(self.arr);
this.arr.splice(i, 1);
this.orignal_input.value = JSON.stringify(this.arr);
updateSelectedTagsInput(this.arr);

// Expand input if no tags remain
if (self.arr.length === 0) {
self.input.classList.add('expanded');
if (this.arr.length === 0) {
this.input.classList.add('expanded');
}

return self;
return this;
}
});
} else {
Expand Down Expand Up @@ -134,10 +131,8 @@ $(function () {
}

TagsInput.prototype.addData = function (array) {
let plugin = this;

array.forEach(function (string) {
plugin.addTag(string);
array.forEach((string) => {
this.addTag(string);
})
return this;
}
Expand All @@ -154,14 +149,13 @@ $(function () {
this.orignal_input.removeAttribute('hidden');

delete this.orignal_input;
let self = this;

Object.keys(this).forEach(function (key) {
if (self[key] instanceof HTMLElement)
self[key].remove();
Object.keys(this).forEach((key) => {
if (this[key] instanceof HTMLElement)
this[key].remove();

if (key != 'options')
delete self[key];
delete this[key];
});

this.initialized = false;
Expand Down Expand Up @@ -355,5 +349,5 @@ $(function () {
duplicate: false
}

window.TagsInput = TagsInput;
globalThis.PaymentTagsInput = TagsInput;
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ $(function () {
});

tagPaymentModal.onOpen(async function () {
let tagInput = new TagsInput({
let tagInput = new PaymentTagsInput({
selector: 'SelectedTags',
duplicate: false,
max: 50
Expand Down
Loading
Loading