mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 05:10:45 +00:00
Checkpoint to get cypress working - auth-type from backend, less hard-coded auth0, improvements on query screen (less redundant fetches)
This commit is contained in:
1
cypress/.gitignore
vendored
Normal file
1
cypress/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
videos
|
105
cypress/e2e/entity-list.spec.cy.ts
Normal file
105
cypress/e2e/entity-list.spec.cy.ts
Normal file
@ -0,0 +1,105 @@
|
||||
/// <reference types="cypress-wait-for-stable-dom" />
|
||||
|
||||
describe("table query screen", () =>
|
||||
{
|
||||
|
||||
before(() =>
|
||||
{
|
||||
cy.intercept("GET", "/metaData/authentication", {fixture: "metaData/authentication.json"}).as("authenticationMetaData");
|
||||
cy.intercept("GET", "/metaData", {fixture: "metaData/index.json"}).as("metaData");
|
||||
cy.intercept("GET", "/metaData/table/person", {fixture: "metaData/table/person.json"}).as("personMetaData");
|
||||
cy.intercept("POST", "/data/person/query?*", {fixture: "data/person/index.json"}).as("personQuery");
|
||||
cy.intercept("POST", "/data/person/count", {fixture: "data/person/count.json"}).as("personCount");
|
||||
cy.intercept("POST", "/data/city/count", {fixture: "data/city/count.json"}).as("cityCount");
|
||||
|
||||
cy.intercept("GET", "/metaData/process/person.bulkEdit", {fixture: "metaData/process/person.bulkEdit.json"}).as("personBulkEditMetaData");
|
||||
cy.intercept("POST", "/processes/person.bulkEdit/init?recordsParam=recordIds&recordIds=1,2,3,4,5", {fixture: "processes/person.bulkEdit/init.json"}).as("personBulkEditInit");
|
||||
cy.intercept("POST", "/processes/person.bulkEdit/74a03a7d-2f53-4784-9911-3a21f7646c43/step/edit", {fixture: "processes/person.bulkEdit/step/edit.json"}).as("personBulkEditStepEdit");
|
||||
cy.intercept("GET", "/processes/person.bulkEdit/74a03a7d-2f53-4784-9911-3a21f7646c43/records?skip=0&limit=10", {fixture: "processes/person.bulkEdit/records.json"}).as("personBulkEditRecords");
|
||||
cy.intercept("GET", "/widget/* ", {fixture: "widget/empty.json"}).as("emptyWidget");
|
||||
});
|
||||
|
||||
it("can be loaded from app screen", () =>
|
||||
{
|
||||
cy.visit("https://localhost:3000/peopleApp/greetingsApp/");
|
||||
cy.contains("Person").click();
|
||||
cy.location().should((loc) =>
|
||||
{
|
||||
expect(loc.pathname).to.eq("/peopleApp/greetingsApp/person");
|
||||
});
|
||||
});
|
||||
|
||||
it.only("can add query filters", () =>
|
||||
{
|
||||
/////////////////////////////////////////////////////////////
|
||||
// go to table, wait for filter to run, and rows to appear //
|
||||
/////////////////////////////////////////////////////////////
|
||||
cy.visit("https://localhost:3000/peopleApp/greetingsApp/person");
|
||||
cy.wait(["@personQuery", "@personCount"]);
|
||||
cy.get(".MuiDataGrid-virtualScrollerRenderZone").children().should("have.length.greaterThan", 3);
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// open the filter window, enter a value, wait for query to re-run //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
cy.contains("Filters").click();
|
||||
cy.get(".MuiDataGrid-filterForm input.MuiInput-input").should("be.focused").type("1");
|
||||
cy.wait(["@personQuery", "@personCount"]);
|
||||
|
||||
///////////////////////////////////////
|
||||
// click away from the filter window //
|
||||
///////////////////////////////////////
|
||||
cy.get("#root").click("topLeft", {force: true});
|
||||
cy.contains(".MuiBadge-root", "1").should("be.visible");
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
// click the 'x' clear icon, then yes, then expect another query //
|
||||
///////////////////////////////////////////////////////////////////
|
||||
cy.waitForStableDOM();
|
||||
cy.get("#clearFiltersButton").should("be.visible").click();
|
||||
cy.contains("button", "Yes").click();
|
||||
cy.wait(["@personQuery", "@personCount"]);
|
||||
cy.contains(".MuiDataGrid-toolbarContainer .MuiBadge-root", "1").should("not.exist");
|
||||
});
|
||||
|
||||
|
||||
xit("todo delete", () =>
|
||||
{
|
||||
// cy.get(".MuiDataGrid-columnHeaders input[type='checkbox']").click();
|
||||
// cy.contains("button", "Bulk Actions").click();
|
||||
// cy.contains("li", "Bulk Edit").click();
|
||||
|
||||
// ////////////////////////////
|
||||
// // bulk edit process init //
|
||||
// ////////////////////////////
|
||||
// cy.location().should((loc) =>
|
||||
// {
|
||||
// expect(loc.pathname).to.eq("/processes/person.bulkEdit");
|
||||
// expect(loc.search).to.eq("?recordsParam=recordIds&recordIds=1,2,3,4,5");
|
||||
// });
|
||||
// cy.wait(["@personBulkEditMetaData"]);
|
||||
// cy.wait(["@personBulkEditInit"]);
|
||||
|
||||
// cy.contains("p[variation='h5']", "Edit Values");
|
||||
// cy.get("#bulkEditSwitch-firstName").click();
|
||||
// cy.get("input[name='firstName']").click()
|
||||
// .type("Kahhhhn");
|
||||
// cy.contains("button", "next").click();
|
||||
|
||||
// ///////////////////////////
|
||||
// // bulk edit review step //
|
||||
// ///////////////////////////
|
||||
// cy.contains("p[variation='h5']", "Review");
|
||||
// cy.contains(".MuiDataGrid-cellContent", "Kahhhhn");
|
||||
|
||||
// cy.contains("button", "submit").click();
|
||||
// cy.wait(["@personBulkEditStepEdit"]);
|
||||
// cy.wait(["@personBulkEditRecords"]);
|
||||
|
||||
// ////////////////////////////
|
||||
// // bulk edit result step //
|
||||
// ////////////////////////////
|
||||
// cy.contains("p[variation='h5']", "Results");
|
||||
// cy.wait(["@personBulkEditRecords"]);
|
||||
});
|
||||
|
||||
});
|
@ -1,72 +0,0 @@
|
||||
// noinspection ES6UnusedImports
|
||||
import * as cypress from "cypress";
|
||||
|
||||
describe("empty spec", () =>
|
||||
{
|
||||
it("passes", () =>
|
||||
{
|
||||
cy.intercept("GET", "/metaData", {fixture: "metaData/index.json"}).as("metaData");
|
||||
cy.intercept("GET", "/data/person?*", {fixture: "data/person/index.json"}).as("personQuery");
|
||||
cy.intercept("GET", "/data/person/count?*", {fixture: "data/person/count.json"}).as("personCount")
|
||||
cy.intercept("GET", "/metaData/process/person.bulkEdit", {fixture: "metaData/process/person.bulkEdit.json"}).as("personBulkEditMetaData")
|
||||
cy.intercept("POST", "/processes/person.bulkEdit/init?recordsParam=recordIds&recordIds=1,2,3,4,5", {fixture: "processes/person.bulkEdit/init.json"}).as("personBulkEditInit")
|
||||
cy.intercept("POST", "/processes/person.bulkEdit/74a03a7d-2f53-4784-9911-3a21f7646c43/step/edit", {fixture: "processes/person.bulkEdit/step/edit.json"}).as("personBulkEditStepEdit")
|
||||
cy.intercept("GET", "/processes/person.bulkEdit/74a03a7d-2f53-4784-9911-3a21f7646c43/records?skip=0&limit=10", {fixture: "processes/person.bulkEdit/records.json"}).as("personBulkEditRecords")
|
||||
|
||||
/////////////////
|
||||
// home screen //
|
||||
/////////////////
|
||||
cy.visit("http://localhost:3000/");
|
||||
cy.wait(["@metaData"])
|
||||
|
||||
cy.contains(".MuiListItem-root", "Tables").click();
|
||||
cy.contains(".MuiListItem-root", "Person").click();
|
||||
|
||||
/////////////////////////
|
||||
// person query screen //
|
||||
/////////////////////////
|
||||
cy.location().should((loc) =>
|
||||
{
|
||||
expect(loc.pathname).to.eq("/person")
|
||||
});
|
||||
cy.wait(["@personQuery", "@personCount"])
|
||||
|
||||
cy.get(".MuiDataGrid-columnHeaders input[type='checkbox']").click();
|
||||
cy.contains("button", "Bulk Actions").click();
|
||||
cy.contains("li", "Bulk Edit").click();
|
||||
|
||||
////////////////////////////
|
||||
// bulk edit process init //
|
||||
////////////////////////////
|
||||
cy.location().should((loc) =>
|
||||
{
|
||||
expect(loc.pathname).to.eq("/processes/person.bulkEdit");
|
||||
expect(loc.search).to.eq("?recordsParam=recordIds&recordIds=1,2,3,4,5");
|
||||
});
|
||||
cy.wait(["@personBulkEditMetaData"])
|
||||
cy.wait(["@personBulkEditInit"])
|
||||
|
||||
cy.contains("p[variation='h5']", "Edit Values");
|
||||
cy.get("#bulkEditSwitch-firstName").click();
|
||||
cy.get("input[name='firstName']").click()
|
||||
.type("Kahhhhn");
|
||||
cy.contains("button", "next").click();
|
||||
|
||||
///////////////////////////
|
||||
// bulk edit review step //
|
||||
///////////////////////////
|
||||
cy.contains("p[variation='h5']", "Review");
|
||||
cy.contains(".MuiDataGrid-cellContent", "Kahhhhn");
|
||||
|
||||
cy.contains("button", "submit").click();
|
||||
cy.wait(["@personBulkEditStepEdit"])
|
||||
cy.wait(["@personBulkEditRecords"])
|
||||
|
||||
////////////////////////////
|
||||
// bulk edit result step //
|
||||
////////////////////////////
|
||||
cy.contains("p[variation='h5']", "Results");
|
||||
cy.wait(["@personBulkEditRecords"])
|
||||
});
|
||||
|
||||
});
|
3
cypress/fixtures/data/city/count.json
Normal file
3
cypress/fixtures/data/city/count.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"count": 101406
|
||||
}
|
2235876
cypress/fixtures/data/city/index.json
Normal file
2235876
cypress/fixtures/data/city/index.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,3 @@
|
||||
{
|
||||
"count": 5
|
||||
"count": 101406
|
||||
}
|
||||
|
4
cypress/fixtures/metaData/authentication.json
Normal file
4
cypress/fixtures/metaData/authentication.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "mock",
|
||||
"type": "MOCK"
|
||||
}
|
@ -1,102 +1,550 @@
|
||||
{
|
||||
"tables": {
|
||||
"carrier": {
|
||||
"name": "carrier",
|
||||
"label": "Carrier",
|
||||
"isHidden": false
|
||||
},
|
||||
"city": {
|
||||
"name": "city",
|
||||
"label": "Cities",
|
||||
"isHidden": true
|
||||
},
|
||||
"person": {
|
||||
"name": "person",
|
||||
"label": "Person",
|
||||
"isHidden": false
|
||||
}
|
||||
},
|
||||
"processes": {
|
||||
"person.bulkInsert": {
|
||||
"name": "person.bulkInsert",
|
||||
"label": "Person Bulk Insert",
|
||||
"tableName": "person",
|
||||
"isHidden": true
|
||||
},
|
||||
"carrier.bulkInsert": {
|
||||
"name": "carrier.bulkInsert",
|
||||
"label": "Carrier Bulk Insert",
|
||||
"tableName": "carrier",
|
||||
"isHidden": true
|
||||
},
|
||||
"simpleSleep": {
|
||||
"name": "simpleSleep",
|
||||
"label": "Simple Sleep",
|
||||
"isHidden": true
|
||||
},
|
||||
"carrier.bulkDelete": {
|
||||
"name": "carrier.bulkDelete",
|
||||
"label": "Carrier Bulk Delete",
|
||||
"tableName": "carrier",
|
||||
"isHidden": true
|
||||
},
|
||||
"greet": {
|
||||
"name": "greet",
|
||||
"label": "Greet People",
|
||||
"tableName": "person",
|
||||
"isHidden": true
|
||||
},
|
||||
"city.bulkDelete": {
|
||||
"name": "city.bulkDelete",
|
||||
"label": "Cities Bulk Delete",
|
||||
"tableName": "city",
|
||||
"isHidden": true
|
||||
},
|
||||
"person.bulkDelete": {
|
||||
"name": "person.bulkDelete",
|
||||
"label": "Person Bulk Delete",
|
||||
"tableName": "person",
|
||||
"isHidden": true
|
||||
},
|
||||
"carrier.bulkEdit": {
|
||||
"name": "carrier.bulkEdit",
|
||||
"label": "Carrier Bulk Edit",
|
||||
"tableName": "carrier",
|
||||
"isHidden": true
|
||||
},
|
||||
"person.bulkEdit": {
|
||||
"name": "person.bulkEdit",
|
||||
"label": "Person Bulk Edit",
|
||||
"tableName": "person",
|
||||
"isHidden": true
|
||||
},
|
||||
"greetInteractive": {
|
||||
"name": "greetInteractive",
|
||||
"label": "Greet Interactive",
|
||||
"tableName": "person",
|
||||
"isHidden": false
|
||||
},
|
||||
"city.bulkEdit": {
|
||||
"name": "city.bulkEdit",
|
||||
"label": "Cities Bulk Edit",
|
||||
"tableName": "city",
|
||||
"isHidden": true
|
||||
},
|
||||
"simpleThrow": {
|
||||
"name": "simpleThrow",
|
||||
"label": "Simple Throw",
|
||||
"isHidden": false
|
||||
},
|
||||
"sleepInteractive": {
|
||||
"name": "sleepInteractive",
|
||||
"label": "Sleep Interactive",
|
||||
"isHidden": false
|
||||
},
|
||||
"city.bulkInsert": {
|
||||
"name": "city.bulkInsert",
|
||||
"label": "Cities Bulk Insert",
|
||||
"tableName": "city",
|
||||
"isHidden": true
|
||||
}
|
||||
}
|
||||
"tables": {
|
||||
"carrier": {
|
||||
"name": "carrier",
|
||||
"label": "Carrier",
|
||||
"isHidden": false,
|
||||
"iconName": "local_shipping",
|
||||
"capabilities": [
|
||||
"TABLE_COUNT",
|
||||
"TABLE_GET",
|
||||
"TABLE_QUERY",
|
||||
"TABLE_UPDATE",
|
||||
"TABLE_INSERT",
|
||||
"TABLE_DELETE"
|
||||
]
|
||||
},
|
||||
"person": {
|
||||
"name": "person",
|
||||
"label": "Person",
|
||||
"isHidden": false,
|
||||
"iconName": "person",
|
||||
"capabilities": [
|
||||
"TABLE_COUNT",
|
||||
"TABLE_GET",
|
||||
"TABLE_QUERY",
|
||||
"TABLE_UPDATE",
|
||||
"TABLE_INSERT",
|
||||
"TABLE_DELETE"
|
||||
]
|
||||
},
|
||||
"city": {
|
||||
"name": "city",
|
||||
"label": "Cities",
|
||||
"isHidden": true,
|
||||
"iconName": "location_city",
|
||||
"capabilities": [
|
||||
"TABLE_COUNT",
|
||||
"TABLE_GET",
|
||||
"TABLE_QUERY",
|
||||
"TABLE_UPDATE",
|
||||
"TABLE_INSERT",
|
||||
"TABLE_DELETE"
|
||||
]
|
||||
}
|
||||
},
|
||||
"processes": {
|
||||
"greet": {
|
||||
"name": "greet",
|
||||
"label": "Greet People",
|
||||
"tableName": "person",
|
||||
"isHidden": true,
|
||||
"iconName": "emoji_people"
|
||||
},
|
||||
"greetInteractive": {
|
||||
"name": "greetInteractive",
|
||||
"label": "Greet Interactive",
|
||||
"tableName": "person",
|
||||
"isHidden": false,
|
||||
"iconName": "waving_hand"
|
||||
},
|
||||
"clonePeople": {
|
||||
"name": "clonePeople",
|
||||
"label": "Clone People",
|
||||
"tableName": "person",
|
||||
"isHidden": false,
|
||||
"iconName": "content_copy"
|
||||
},
|
||||
"simpleSleep": {
|
||||
"name": "simpleSleep",
|
||||
"label": "Simple Sleep",
|
||||
"isHidden": true
|
||||
},
|
||||
"sleepInteractive": {
|
||||
"name": "sleepInteractive",
|
||||
"label": "Sleep Interactive",
|
||||
"isHidden": false
|
||||
},
|
||||
"simpleThrow": {
|
||||
"name": "simpleThrow",
|
||||
"label": "Simple Throw",
|
||||
"isHidden": false
|
||||
},
|
||||
"carrier.bulkInsert": {
|
||||
"name": "carrier.bulkInsert",
|
||||
"label": "Carrier Bulk Insert",
|
||||
"tableName": "carrier",
|
||||
"isHidden": true
|
||||
},
|
||||
"carrier.bulkEdit": {
|
||||
"name": "carrier.bulkEdit",
|
||||
"label": "Carrier Bulk Edit",
|
||||
"tableName": "carrier",
|
||||
"isHidden": true
|
||||
},
|
||||
"carrier.bulkDelete": {
|
||||
"name": "carrier.bulkDelete",
|
||||
"label": "Carrier Bulk Delete",
|
||||
"tableName": "carrier",
|
||||
"isHidden": true
|
||||
},
|
||||
"person.bulkInsert": {
|
||||
"name": "person.bulkInsert",
|
||||
"label": "Person Bulk Insert",
|
||||
"tableName": "person",
|
||||
"isHidden": true
|
||||
},
|
||||
"person.bulkEdit": {
|
||||
"name": "person.bulkEdit",
|
||||
"label": "Person Bulk Edit",
|
||||
"tableName": "person",
|
||||
"isHidden": true
|
||||
},
|
||||
"person.bulkDelete": {
|
||||
"name": "person.bulkDelete",
|
||||
"label": "Person Bulk Delete",
|
||||
"tableName": "person",
|
||||
"isHidden": true
|
||||
},
|
||||
"city.bulkInsert": {
|
||||
"name": "city.bulkInsert",
|
||||
"label": "Cities Bulk Insert",
|
||||
"tableName": "city",
|
||||
"isHidden": true
|
||||
},
|
||||
"city.bulkEdit": {
|
||||
"name": "city.bulkEdit",
|
||||
"label": "Cities Bulk Edit",
|
||||
"tableName": "city",
|
||||
"isHidden": true
|
||||
},
|
||||
"city.bulkDelete": {
|
||||
"name": "city.bulkDelete",
|
||||
"label": "Cities Bulk Delete",
|
||||
"tableName": "city",
|
||||
"isHidden": true
|
||||
}
|
||||
},
|
||||
"apps": {
|
||||
"greetingsApp": {
|
||||
"name": "greetingsApp",
|
||||
"label": "Greetings App",
|
||||
"iconName": "emoji_people",
|
||||
"widgets": [
|
||||
"PersonsByCreateDateBarChart",
|
||||
"QuickSightChartRenderer"
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "greet",
|
||||
"label": "Greet People",
|
||||
"iconName": "emoji_people"
|
||||
},
|
||||
{
|
||||
"type": "TABLE",
|
||||
"name": "person",
|
||||
"label": "Person",
|
||||
"iconName": "person"
|
||||
},
|
||||
{
|
||||
"type": "TABLE",
|
||||
"name": "city",
|
||||
"label": "Cities",
|
||||
"iconName": "location_city"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "greetInteractive",
|
||||
"label": "Greet Interactive",
|
||||
"iconName": "waving_hand"
|
||||
}
|
||||
],
|
||||
"childMap": {
|
||||
"greetInteractive": {
|
||||
"type": "PROCESS",
|
||||
"name": "greetInteractive",
|
||||
"label": "Greet Interactive",
|
||||
"iconName": "waving_hand"
|
||||
},
|
||||
"city": {
|
||||
"type": "TABLE",
|
||||
"name": "city",
|
||||
"label": "Cities",
|
||||
"iconName": "location_city"
|
||||
},
|
||||
"person": {
|
||||
"type": "TABLE",
|
||||
"name": "person",
|
||||
"label": "Person",
|
||||
"iconName": "person"
|
||||
},
|
||||
"greet": {
|
||||
"type": "PROCESS",
|
||||
"name": "greet",
|
||||
"label": "Greet People",
|
||||
"iconName": "emoji_people"
|
||||
}
|
||||
},
|
||||
"sections": [
|
||||
{
|
||||
"name": "greetingsApp",
|
||||
"label": "Greetings App",
|
||||
"icon": {
|
||||
"name": "badge"
|
||||
},
|
||||
"tables": [
|
||||
"person",
|
||||
"city"
|
||||
],
|
||||
"processes": [
|
||||
"greet",
|
||||
"greetInteractive"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"peopleApp": {
|
||||
"name": "peopleApp",
|
||||
"label": "People App",
|
||||
"iconName": "person",
|
||||
"widgets": [],
|
||||
"children": [
|
||||
{
|
||||
"type": "APP",
|
||||
"name": "greetingsApp",
|
||||
"label": "Greetings App",
|
||||
"iconName": "emoji_people"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "clonePeople",
|
||||
"label": "Clone People",
|
||||
"iconName": "content_copy"
|
||||
}
|
||||
],
|
||||
"childMap": {
|
||||
"greetingsApp": {
|
||||
"type": "APP",
|
||||
"name": "greetingsApp",
|
||||
"label": "Greetings App",
|
||||
"iconName": "emoji_people"
|
||||
},
|
||||
"clonePeople": {
|
||||
"type": "PROCESS",
|
||||
"name": "clonePeople",
|
||||
"label": "Clone People",
|
||||
"iconName": "content_copy"
|
||||
}
|
||||
},
|
||||
"sections": [
|
||||
{
|
||||
"name": "peopleApp",
|
||||
"label": "People App",
|
||||
"icon": {
|
||||
"name": "badge"
|
||||
},
|
||||
"processes": [
|
||||
"clonePeople"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"miscellaneous": {
|
||||
"name": "miscellaneous",
|
||||
"label": "Miscellaneous",
|
||||
"iconName": "stars",
|
||||
"widgets": [],
|
||||
"children": [
|
||||
{
|
||||
"type": "TABLE",
|
||||
"name": "carrier",
|
||||
"label": "Carrier",
|
||||
"iconName": "local_shipping"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "simpleSleep",
|
||||
"label": "Simple Sleep"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "sleepInteractive",
|
||||
"label": "Sleep Interactive"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "simpleThrow",
|
||||
"label": "Simple Throw"
|
||||
}
|
||||
],
|
||||
"childMap": {
|
||||
"carrier": {
|
||||
"type": "TABLE",
|
||||
"name": "carrier",
|
||||
"label": "Carrier",
|
||||
"iconName": "local_shipping"
|
||||
},
|
||||
"simpleSleep": {
|
||||
"type": "PROCESS",
|
||||
"name": "simpleSleep",
|
||||
"label": "Simple Sleep"
|
||||
},
|
||||
"simpleThrow": {
|
||||
"type": "PROCESS",
|
||||
"name": "simpleThrow",
|
||||
"label": "Simple Throw"
|
||||
},
|
||||
"sleepInteractive": {
|
||||
"type": "PROCESS",
|
||||
"name": "sleepInteractive",
|
||||
"label": "Sleep Interactive"
|
||||
}
|
||||
},
|
||||
"sections": [
|
||||
{
|
||||
"name": "miscellaneous",
|
||||
"label": "Miscellaneous",
|
||||
"icon": {
|
||||
"name": "badge"
|
||||
},
|
||||
"tables": [
|
||||
"carrier"
|
||||
],
|
||||
"processes": [
|
||||
"simpleSleep",
|
||||
"sleepInteractive",
|
||||
"simpleThrow"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"appTree": [
|
||||
{
|
||||
"type": "APP",
|
||||
"name": "peopleApp",
|
||||
"label": "People App",
|
||||
"children": [
|
||||
{
|
||||
"type": "APP",
|
||||
"name": "greetingsApp",
|
||||
"label": "Greetings App",
|
||||
"children": [
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "greet",
|
||||
"label": "Greet People",
|
||||
"iconName": "emoji_people"
|
||||
},
|
||||
{
|
||||
"type": "TABLE",
|
||||
"name": "person",
|
||||
"label": "Person",
|
||||
"iconName": "person"
|
||||
},
|
||||
{
|
||||
"type": "TABLE",
|
||||
"name": "city",
|
||||
"label": "Cities",
|
||||
"iconName": "location_city"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "greetInteractive",
|
||||
"label": "Greet Interactive",
|
||||
"iconName": "waving_hand"
|
||||
}
|
||||
],
|
||||
"iconName": "emoji_people"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "clonePeople",
|
||||
"label": "Clone People",
|
||||
"iconName": "content_copy"
|
||||
}
|
||||
],
|
||||
"iconName": "person"
|
||||
},
|
||||
{
|
||||
"type": "APP",
|
||||
"name": "miscellaneous",
|
||||
"label": "Miscellaneous",
|
||||
"children": [
|
||||
{
|
||||
"type": "TABLE",
|
||||
"name": "carrier",
|
||||
"label": "Carrier",
|
||||
"iconName": "local_shipping"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "simpleSleep",
|
||||
"label": "Simple Sleep"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "sleepInteractive",
|
||||
"label": "Sleep Interactive"
|
||||
},
|
||||
{
|
||||
"type": "PROCESS",
|
||||
"name": "simpleThrow",
|
||||
"label": "Simple Throw"
|
||||
}
|
||||
],
|
||||
"iconName": "stars"
|
||||
}
|
||||
],
|
||||
"branding": {
|
||||
"logo": "/kr-logo.png",
|
||||
"icon": "/kr-icon.png"
|
||||
},
|
||||
"widgets": {
|
||||
"parcelTrackingDetails": {
|
||||
"name": "parcelTrackingDetails",
|
||||
"label": "Tracking Details",
|
||||
"type": "childRecordList"
|
||||
},
|
||||
"deposcoSalesOrderLineItems": {
|
||||
"name": "deposcoSalesOrderLineItems",
|
||||
"label": "Line Items",
|
||||
"type": "childRecordList"
|
||||
},
|
||||
"TotalShipmentsByDayBarChart": {
|
||||
"name": "TotalShipmentsByDayBarChart",
|
||||
"label": "Total Shipments By Day",
|
||||
"type": "chart"
|
||||
},
|
||||
"TotalShipmentsByMonthLineChart": {
|
||||
"name": "TotalShipmentsByMonthLineChart",
|
||||
"label": "Total Shipments By Month",
|
||||
"type": "chart"
|
||||
},
|
||||
"YTDShipmentsByCarrierPieChart": {
|
||||
"name": "YTDShipmentsByCarrierPieChart",
|
||||
"label": "Shipments By Carrier Year To Date",
|
||||
"type": "chart"
|
||||
},
|
||||
"TodaysShipmentsStatisticsCard": {
|
||||
"name": "TodaysShipmentsStatisticsCard",
|
||||
"label": "Today's Shipments",
|
||||
"type": "statistics"
|
||||
},
|
||||
"ShipmentsInTransitStatisticsCard": {
|
||||
"name": "ShipmentsInTransitStatisticsCard",
|
||||
"label": "Shipments In Transit",
|
||||
"type": "statistics"
|
||||
},
|
||||
"OpenOrdersStatisticsCard": {
|
||||
"name": "OpenOrdersStatisticsCard",
|
||||
"label": "Open Orders",
|
||||
"type": "statistics"
|
||||
},
|
||||
"ShippingExceptionsStatisticsCard": {
|
||||
"name": "ShippingExceptionsStatisticsCard",
|
||||
"label": "Shipping Exceptions",
|
||||
"type": "statistics"
|
||||
},
|
||||
"WarehouseLocationCards": {
|
||||
"name": "WarehouseLocationCards",
|
||||
"type": "location"
|
||||
},
|
||||
"TotalShipmentsStatisticsCard": {
|
||||
"name": "TotalShipmentsStatisticsCard",
|
||||
"label": "Total Shipments",
|
||||
"type": "statistics"
|
||||
},
|
||||
"SuccessfulDeliveriesStatisticsCard": {
|
||||
"name": "SuccessfulDeliveriesStatisticsCard",
|
||||
"label": "Successful Deliveries",
|
||||
"type": "statistics"
|
||||
},
|
||||
"ServiceFailuresStatisticsCard": {
|
||||
"name": "ServiceFailuresStatisticsCard",
|
||||
"label": "Service Failures",
|
||||
"type": "statistics"
|
||||
},
|
||||
"CarrierVolumeLineChart": {
|
||||
"name": "CarrierVolumeLineChart",
|
||||
"label": "Carrier Volume By Month",
|
||||
"type": "lineChart"
|
||||
},
|
||||
"YTDSpendByCarrierTable": {
|
||||
"name": "YTDSpendByCarrierTable",
|
||||
"label": "Spend By Carrier Year To Date",
|
||||
"type": "table"
|
||||
},
|
||||
"TimeInTransitBarChart": {
|
||||
"name": "TimeInTransitBarChart",
|
||||
"label": "Time In Transit Last 30 Days",
|
||||
"type": "chart"
|
||||
},
|
||||
"OpenBillingWorksheetsTable": {
|
||||
"name": "OpenBillingWorksheetsTable",
|
||||
"label": "Open Billing Worksheets",
|
||||
"type": "table"
|
||||
},
|
||||
"AssociatedParcelInvoicesTable": {
|
||||
"name": "AssociatedParcelInvoicesTable",
|
||||
"label": "Associated Parcel Invoices",
|
||||
"type": "table",
|
||||
"icon": "receipt"
|
||||
},
|
||||
"BillingWorksheetLinesTable": {
|
||||
"name": "BillingWorksheetLinesTable",
|
||||
"label": "Billing Worksheet Lines",
|
||||
"type": "table"
|
||||
},
|
||||
"RatingIssuesWidget": {
|
||||
"name": "RatingIssuesWidget",
|
||||
"label": "Rating Issues",
|
||||
"type": "html",
|
||||
"icon": "warning",
|
||||
"gridColumns": 6
|
||||
},
|
||||
"UnassignedParcelInvoicesTable": {
|
||||
"name": "UnassignedParcelInvoicesTable",
|
||||
"label": "Unassigned Parcel Invoices",
|
||||
"type": "table"
|
||||
},
|
||||
"ParcelInvoiceSummaryWidget": {
|
||||
"name": "ParcelInvoiceSummaryWidget",
|
||||
"label": "Parcel Invoice Summary",
|
||||
"type": "multiStatistics"
|
||||
},
|
||||
"ParcelInvoiceLineExceptionsSummaryWidget": {
|
||||
"name": "ParcelInvoiceLineExceptionsSummaryWidget",
|
||||
"label": "Parcel Invoice Line Exceptions",
|
||||
"type": "multiStatistics"
|
||||
},
|
||||
"BillingWorksheetStatusStepper": {
|
||||
"name": "BillingWorksheetStatusStepper",
|
||||
"label": "Billing Worksheet Progress",
|
||||
"type": "stepper",
|
||||
"icon": "refresh",
|
||||
"gridColumns": 6
|
||||
},
|
||||
"PersonsByCreateDateBarChart": {
|
||||
"name": "PersonsByCreateDateBarChart",
|
||||
"label": "Persons By Create Date",
|
||||
"type": "barChart"
|
||||
},
|
||||
"QuickSightChartRenderer": {
|
||||
"name": "QuickSightChartRenderer",
|
||||
"label": "Quick Sight",
|
||||
"type": "quickSightChart"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,8 @@
|
||||
"backendName": "first_name",
|
||||
"type": "STRING",
|
||||
"isRequired": true,
|
||||
"isEditable": true
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "lastName",
|
||||
@ -35,7 +36,8 @@
|
||||
"backendName": "last_name",
|
||||
"type": "STRING",
|
||||
"isRequired": true,
|
||||
"isEditable": true
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "birthDate",
|
||||
@ -43,14 +45,44 @@
|
||||
"backendName": "birth_date",
|
||||
"type": "DATE",
|
||||
"isRequired": false,
|
||||
"isEditable": true
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "email",
|
||||
"label": "Email",
|
||||
"backendName": "email",
|
||||
"type": "STRING",
|
||||
"isRequired": false,
|
||||
"isEditable": true
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "isEmployed",
|
||||
"label": "Is Employed",
|
||||
"backendName": "is_employed",
|
||||
"type": "BOOLEAN",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "annualSalary",
|
||||
"label": "Annual Salary",
|
||||
"backendName": "annual_salary",
|
||||
"type": "DECIMAL",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "$%,.2f"
|
||||
},
|
||||
{
|
||||
"name": "daysWorked",
|
||||
"label": "Days Worked",
|
||||
"backendName": "days_worked",
|
||||
"type": "INTEGER",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%,d"
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -60,19 +92,7 @@
|
||||
"stepType": "frontend",
|
||||
"components": [
|
||||
{
|
||||
"type": "HELP_TEXT",
|
||||
"values": {
|
||||
"text": "The records below will be updated if you click Submit."
|
||||
}
|
||||
}
|
||||
],
|
||||
"viewFields": [
|
||||
{
|
||||
"name": "valuesBeingUpdated",
|
||||
"label": "Values Being Updated",
|
||||
"type": "STRING",
|
||||
"isRequired": false,
|
||||
"isEditable": true
|
||||
"type": "VALIDATION_REVIEW_SCREEN"
|
||||
}
|
||||
],
|
||||
"recordListFields": [
|
||||
@ -82,7 +102,8 @@
|
||||
"backendName": "first_name",
|
||||
"type": "STRING",
|
||||
"isRequired": true,
|
||||
"isEditable": true
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "lastName",
|
||||
@ -90,7 +111,8 @@
|
||||
"backendName": "last_name",
|
||||
"type": "STRING",
|
||||
"isRequired": true,
|
||||
"isEditable": true
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "birthDate",
|
||||
@ -98,83 +120,54 @@
|
||||
"backendName": "birth_date",
|
||||
"type": "DATE",
|
||||
"isRequired": false,
|
||||
"isEditable": true
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "email",
|
||||
"label": "Email",
|
||||
"backendName": "email",
|
||||
"type": "STRING",
|
||||
"isRequired": false,
|
||||
"isEditable": true
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "isEmployed",
|
||||
"label": "Is Employed",
|
||||
"backendName": "is_employed",
|
||||
"type": "BOOLEAN",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
{
|
||||
"name": "annualSalary",
|
||||
"label": "Annual Salary",
|
||||
"backendName": "annual_salary",
|
||||
"type": "DECIMAL",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "$%,.2f"
|
||||
},
|
||||
{
|
||||
"name": "daysWorked",
|
||||
"label": "Days Worked",
|
||||
"backendName": "days_worked",
|
||||
"type": "INTEGER",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%,d"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "results",
|
||||
"label": "Results",
|
||||
"name": "result",
|
||||
"label": "Result",
|
||||
"stepType": "frontend",
|
||||
"components": [
|
||||
{
|
||||
"type": "HELP_TEXT",
|
||||
"values": {
|
||||
"text": "The records below have been updated."
|
||||
}
|
||||
}
|
||||
],
|
||||
"recordListFields": [
|
||||
{
|
||||
"name": "id",
|
||||
"label": "Id",
|
||||
"type": "INTEGER",
|
||||
"isRequired": false,
|
||||
"isEditable": false
|
||||
},
|
||||
{
|
||||
"name": "createDate",
|
||||
"label": "Create Date",
|
||||
"backendName": "create_date",
|
||||
"type": "DATE_TIME",
|
||||
"isRequired": false,
|
||||
"isEditable": false
|
||||
},
|
||||
{
|
||||
"name": "modifyDate",
|
||||
"label": "Modify Date",
|
||||
"backendName": "modify_date",
|
||||
"type": "DATE_TIME",
|
||||
"isRequired": false,
|
||||
"isEditable": false
|
||||
},
|
||||
{
|
||||
"name": "firstName",
|
||||
"label": "First Name",
|
||||
"backendName": "first_name",
|
||||
"type": "STRING",
|
||||
"isRequired": true,
|
||||
"isEditable": true
|
||||
},
|
||||
{
|
||||
"name": "lastName",
|
||||
"label": "Last Name",
|
||||
"backendName": "last_name",
|
||||
"type": "STRING",
|
||||
"isRequired": true,
|
||||
"isEditable": true
|
||||
},
|
||||
{
|
||||
"name": "birthDate",
|
||||
"label": "Birth Date",
|
||||
"backendName": "birth_date",
|
||||
"type": "DATE",
|
||||
"isRequired": false,
|
||||
"isEditable": true
|
||||
},
|
||||
{
|
||||
"name": "email",
|
||||
"label": "Email",
|
||||
"type": "STRING",
|
||||
"isRequired": false,
|
||||
"isEditable": true
|
||||
"type": "PROCESS_SUMMARY_RESULTS"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
155
cypress/fixtures/metaData/table/person.json
Normal file
155
cypress/fixtures/metaData/table/person.json
Normal file
@ -0,0 +1,155 @@
|
||||
{
|
||||
"table": {
|
||||
"name": "person",
|
||||
"label": "Person",
|
||||
"isHidden": false,
|
||||
"primaryKeyField": "id",
|
||||
"iconName": "person",
|
||||
"fields": {
|
||||
"firstName": {
|
||||
"name": "firstName",
|
||||
"label": "First Name",
|
||||
"type": "STRING",
|
||||
"isRequired": true,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
"lastName": {
|
||||
"name": "lastName",
|
||||
"label": "Last Name",
|
||||
"type": "STRING",
|
||||
"isRequired": true,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
"annualSalary": {
|
||||
"name": "annualSalary",
|
||||
"label": "Annual Salary",
|
||||
"type": "DECIMAL",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "$%,.2f"
|
||||
},
|
||||
"modifyDate": {
|
||||
"name": "modifyDate",
|
||||
"label": "Modify Date",
|
||||
"type": "DATE_TIME",
|
||||
"isRequired": false,
|
||||
"isEditable": false,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
"daysWorked": {
|
||||
"name": "daysWorked",
|
||||
"label": "Days Worked",
|
||||
"type": "INTEGER",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%,d"
|
||||
},
|
||||
"id": {
|
||||
"name": "id",
|
||||
"label": "Id",
|
||||
"type": "INTEGER",
|
||||
"isRequired": false,
|
||||
"isEditable": false,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
"birthDate": {
|
||||
"name": "birthDate",
|
||||
"label": "Birth Date",
|
||||
"type": "DATE",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
"isEmployed": {
|
||||
"name": "isEmployed",
|
||||
"label": "Is Employed",
|
||||
"type": "BOOLEAN",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"label": "Email",
|
||||
"type": "STRING",
|
||||
"isRequired": false,
|
||||
"isEditable": true,
|
||||
"displayFormat": "%s"
|
||||
},
|
||||
"createDate": {
|
||||
"name": "createDate",
|
||||
"label": "Create Date",
|
||||
"type": "DATE_TIME",
|
||||
"isRequired": false,
|
||||
"isEditable": false,
|
||||
"displayFormat": "%s"
|
||||
}
|
||||
},
|
||||
"sections": [
|
||||
{
|
||||
"name": "identity",
|
||||
"label": "Identity",
|
||||
"tier": "T1",
|
||||
"fieldNames": [
|
||||
"id",
|
||||
"firstName",
|
||||
"lastName"
|
||||
],
|
||||
"icon": {
|
||||
"name": "badge"
|
||||
},
|
||||
"isHidden": false
|
||||
},
|
||||
{
|
||||
"name": "basicInfo",
|
||||
"label": "Basic Info",
|
||||
"tier": "T2",
|
||||
"fieldNames": [
|
||||
"email",
|
||||
"birthDate"
|
||||
],
|
||||
"icon": {
|
||||
"name": "dataset"
|
||||
},
|
||||
"isHidden": false
|
||||
},
|
||||
{
|
||||
"name": "employmentInfo",
|
||||
"label": "Employment Info",
|
||||
"tier": "T2",
|
||||
"fieldNames": [
|
||||
"isEmployed",
|
||||
"annualSalary",
|
||||
"daysWorked"
|
||||
],
|
||||
"icon": {
|
||||
"name": "work"
|
||||
},
|
||||
"isHidden": false
|
||||
},
|
||||
{
|
||||
"name": "dates",
|
||||
"label": "Dates",
|
||||
"tier": "T3",
|
||||
"fieldNames": [
|
||||
"createDate",
|
||||
"modifyDate"
|
||||
],
|
||||
"icon": {
|
||||
"name": "calendar_month"
|
||||
},
|
||||
"isHidden": false
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
"TABLE_COUNT",
|
||||
"TABLE_GET",
|
||||
"TABLE_QUERY",
|
||||
"TABLE_DELETE",
|
||||
"TABLE_INSERT",
|
||||
"TABLE_UPDATE"
|
||||
]
|
||||
}
|
||||
}
|
3
cypress/fixtures/processes/person.bulkEdit/records.json
Normal file
3
cypress/fixtures/processes/person.bulkEdit/records.json
Normal file
@ -0,0 +1,3 @@
|
||||
[
|
||||
{}
|
||||
]
|
1
cypress/fixtures/widget/empty.json
Normal file
1
cypress/fixtures/widget/empty.json
Normal file
@ -0,0 +1 @@
|
||||
{}
|
@ -35,3 +35,7 @@
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
import {registerCommand} from "cypress-wait-for-stable-dom";
|
||||
|
||||
registerCommand({pollInterval: 100, timeout: 3000});
|
||||
|
Binary file not shown.
@ -13,7 +13,7 @@
|
||||
"@fullcalendar/interaction": "5.10.0",
|
||||
"@fullcalendar/react": "5.10.0",
|
||||
"@fullcalendar/timegrid": "5.10.0",
|
||||
"@kingsrook/qqq-frontend-core": "1.0.35",
|
||||
"@kingsrook/qqq-frontend-core": "1.0.36",
|
||||
"@mui/icons-material": "5.4.1",
|
||||
"@mui/material": "5.4.1",
|
||||
"@mui/styled-engine": "5.4.1",
|
||||
@ -105,7 +105,8 @@
|
||||
"@types/uuid": "8.3.4",
|
||||
"@typescript-eslint/eslint-plugin": "5.10.2",
|
||||
"@typescript-eslint/parser": "5.10.2",
|
||||
"cypress": "10.3.1",
|
||||
"cypress": "11.0.1",
|
||||
"cypress-wait-for-stable-dom": "0.1.0",
|
||||
"eslint": "8.8.0",
|
||||
"eslint-config-airbnb": "19.0.4",
|
||||
"eslint-import-resolver-typescript": "2.5.0",
|
||||
|
66
src/App.tsx
66
src/App.tsx
@ -23,6 +23,7 @@ import {useAuth0} from "@auth0/auth0-react";
|
||||
import {QException} from "@kingsrook/qqq-frontend-core/lib/exceptions/QException";
|
||||
import {QAppNodeType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QAppNodeType";
|
||||
import {QAppTreeNode} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QAppTreeNode";
|
||||
import {QAuthenticationMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QAuthenticationMetaData";
|
||||
import {QBrandingMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QBrandingMetaData";
|
||||
import {QInstance} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QInstance";
|
||||
import CssBaseline from "@mui/material/CssBaseline";
|
||||
@ -86,6 +87,7 @@ function getStaticRoutes()
|
||||
];
|
||||
}
|
||||
|
||||
const qController = QClient.getInstance();
|
||||
export const SESSION_ID_COOKIE_NAME = "sessionId";
|
||||
LicenseInfo.setLicenseKey(process.env.REACT_APP_MATERIAL_UI_LICENSE_KEY);
|
||||
|
||||
@ -105,24 +107,51 @@ export default function App()
|
||||
return;
|
||||
}
|
||||
setLoadingToken(true);
|
||||
|
||||
(async () =>
|
||||
{
|
||||
try
|
||||
const authenticationMetaData: QAuthenticationMetaData = await qController.getAuthenticationMetaData();
|
||||
|
||||
if (authenticationMetaData.type === "AUTH_0")
|
||||
{
|
||||
console.log("Loading token...");
|
||||
await getAccessTokenSilently();
|
||||
const idToken = await getIdTokenClaims();
|
||||
setCookie(SESSION_ID_COOKIE_NAME, idToken.__raw, {path: "/"});
|
||||
setIsFullyAuthenticated(true);
|
||||
console.log("Token load complete.");
|
||||
/////////////////////////////////////////
|
||||
// use auth0 if auth type is ... auth0 //
|
||||
/////////////////////////////////////////
|
||||
try
|
||||
{
|
||||
console.log("Loading token...");
|
||||
await getAccessTokenSilently();
|
||||
const idToken = await getIdTokenClaims();
|
||||
setCookie(SESSION_ID_COOKIE_NAME, idToken.__raw, {path: "/"});
|
||||
setIsFullyAuthenticated(true);
|
||||
console.log("Token load complete.");
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
console.log(`Error loading token: ${JSON.stringify(e)}`);
|
||||
removeCookie(SESSION_ID_COOKIE_NAME);
|
||||
qController.clearAuthenticationMetaDataLocalStorage();
|
||||
logout();
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (e)
|
||||
else if (authenticationMetaData.type === "FULLY_ANONYMOUS" || authenticationMetaData.type === "MOCK")
|
||||
{
|
||||
console.log(`Error loading token: ${JSON.stringify(e)}`);
|
||||
removeCookie(SESSION_ID_COOKIE_NAME);
|
||||
logout();
|
||||
/////////////////////////////////////////////
|
||||
// use a random token if anonymous or mock //
|
||||
/////////////////////////////////////////////
|
||||
console.log("Generating random token...");
|
||||
setIsFullyAuthenticated(true);
|
||||
setCookie(SESSION_ID_COOKIE_NAME, Md5.hashStr(`${new Date()}`), {path: "/"});
|
||||
console.log("Token generation complete.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log(`Unrecognized authenticationMetaData.type: ${authenticationMetaData.type}`);
|
||||
qController.clearAuthenticationMetaDataLocalStorage();
|
||||
}
|
||||
|
||||
})();
|
||||
}, [loadingToken]);
|
||||
|
||||
@ -265,7 +294,7 @@ export default function App()
|
||||
|
||||
routeList.push({
|
||||
name: `${app.label}`,
|
||||
key: `${app.name}.dev`,
|
||||
key: `${app.name}.record.dev`,
|
||||
route: `${path}/:id/dev`,
|
||||
component: <EntityDeveloperView table={table} />,
|
||||
});
|
||||
@ -342,13 +371,13 @@ export default function App()
|
||||
|
||||
let profileRoutes = {};
|
||||
const gravatarBase = "https://www.gravatar.com/avatar/";
|
||||
const hash = Md5.hashStr(user.email);
|
||||
const hash = Md5.hashStr(user?.email || "user");
|
||||
const profilePicture = `${gravatarBase}${hash}`;
|
||||
profileRoutes = {
|
||||
type: "collapse",
|
||||
name: user.name,
|
||||
key: user.name,
|
||||
icon: <MDAvatar src={profilePicture} alt="{user.name}" size="sm" />,
|
||||
name: user?.name,
|
||||
key: "username",
|
||||
icon: <MDAvatar src={profilePicture} alt="{user?.name}" size="sm" />,
|
||||
collapse: [
|
||||
{
|
||||
name: "My Profile",
|
||||
@ -388,11 +417,16 @@ export default function App()
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
console.error(e);
|
||||
if (e instanceof QException)
|
||||
{
|
||||
if ((e as QException).message.indexOf("status code 401") !== -1)
|
||||
{
|
||||
removeCookie(SESSION_ID_COOKIE_NAME);
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// todo - this is auth0 logout... make more generic //
|
||||
//////////////////////////////////////////////////////
|
||||
logout();
|
||||
return;
|
||||
}
|
||||
|
@ -19,11 +19,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {Auth0Provider, useAuth0} from "@auth0/auth0-react";
|
||||
import {useAuth0} from "@auth0/auth0-react";
|
||||
import React, {useEffect} from "react";
|
||||
import {useCookies} from "react-cookie";
|
||||
import {SESSION_ID_COOKIE_NAME} from "App";
|
||||
import {AUTH0_CLIENT_ID, AUTH0_DOMAIN} from "index";
|
||||
|
||||
interface Props
|
||||
{
|
||||
@ -44,11 +43,7 @@ function HandleAuthorizationError({errorMessage}: Props)
|
||||
});
|
||||
|
||||
return (
|
||||
<Auth0Provider domain={AUTH0_DOMAIN} clientId={AUTH0_CLIENT_ID}>
|
||||
<div>
|
||||
<div>{errorMessage}</div>
|
||||
</div>
|
||||
</Auth0Provider>
|
||||
<div>{errorMessage}</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
import {Auth0Provider} from "@auth0/auth0-react";
|
||||
import {QAuthenticationMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QAuthenticationMetaData";
|
||||
import React from "react";
|
||||
import {render} from "react-dom";
|
||||
import {BrowserRouter, useNavigate, useSearchParams} from "react-router-dom";
|
||||
@ -28,52 +29,73 @@ import "qqq/styles/qqq-override-styles.css";
|
||||
import {MaterialUIControllerProvider} from "context";
|
||||
import HandleAuthorizationError from "HandleAuthorizationError";
|
||||
import ProtectedRoute from "qqq/auth0/protected-route";
|
||||
import QClient from "qqq/utils/QClient";
|
||||
|
||||
export const AUTH0_DOMAIN = process.env.REACT_APP_AUTH0_DOMAIN;
|
||||
export const AUTH0_CLIENT_ID = process.env.REACT_APP_AUTH0_CLIENT_ID;
|
||||
const qController = QClient.getInstance();
|
||||
const authenticationMetaDataPromise: Promise<QAuthenticationMetaData> = qController.getAuthenticationMetaData()
|
||||
|
||||
// @ts-ignore
|
||||
function Auth0ProviderWithRedirectCallback({children, ...props})
|
||||
authenticationMetaDataPromise.then((authenticationMetaData) =>
|
||||
{
|
||||
const navigate = useNavigate();
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
// @ts-ignore
|
||||
const onRedirectCallback = (appState) =>
|
||||
function Auth0ProviderWithRedirectCallback({children, ...props})
|
||||
{
|
||||
navigate((appState && appState.returnTo) || window.location.pathname);
|
||||
};
|
||||
if (searchParams.get("error"))
|
||||
const navigate = useNavigate();
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
// @ts-ignore
|
||||
const onRedirectCallback = (appState) =>
|
||||
{
|
||||
navigate((appState && appState.returnTo) || window.location.pathname);
|
||||
};
|
||||
if (searchParams.get("error"))
|
||||
{
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Auth0Provider {...props}>
|
||||
<HandleAuthorizationError errorMessage={searchParams.get("error_description")} />
|
||||
</Auth0Provider>
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Auth0Provider onRedirectCallback={onRedirectCallback} {...props}>
|
||||
{children}
|
||||
</Auth0Provider>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticationMetaData.type === "AUTH_0")
|
||||
{
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Auth0Provider {...props}>
|
||||
<HandleAuthorizationError errorMessage={searchParams.get("error_description")} />
|
||||
</Auth0Provider>
|
||||
const domain = process.env.REACT_APP_AUTH0_DOMAIN;
|
||||
const clientId = process.env.REACT_APP_AUTH0_CLIENT_ID;
|
||||
|
||||
render(
|
||||
<BrowserRouter>
|
||||
<Auth0ProviderWithRedirectCallback
|
||||
domain={domain}
|
||||
clientId={clientId}
|
||||
redirectUri={`${window.location.origin}/dashboards/overview`}
|
||||
>
|
||||
<MaterialUIControllerProvider>
|
||||
<ProtectedRoute component={App} />
|
||||
</MaterialUIControllerProvider>
|
||||
</Auth0ProviderWithRedirectCallback>
|
||||
</BrowserRouter>,
|
||||
document.getElementById("root"),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Auth0Provider onRedirectCallback={onRedirectCallback} {...props}>
|
||||
{children}
|
||||
</Auth0Provider>
|
||||
);
|
||||
render(
|
||||
<BrowserRouter>
|
||||
<MaterialUIControllerProvider>
|
||||
<App />
|
||||
</MaterialUIControllerProvider>
|
||||
</BrowserRouter>
|
||||
, document.getElementById("root"));
|
||||
}
|
||||
}
|
||||
|
||||
render(
|
||||
<BrowserRouter>
|
||||
<Auth0ProviderWithRedirectCallback
|
||||
domain={AUTH0_DOMAIN}
|
||||
clientId={AUTH0_CLIENT_ID}
|
||||
redirectUri={`${window.location.origin}/dashboards/overview`}
|
||||
>
|
||||
<MaterialUIControllerProvider>
|
||||
<ProtectedRoute component={App} />
|
||||
</MaterialUIControllerProvider>
|
||||
</Auth0ProviderWithRedirectCallback>
|
||||
</BrowserRouter>,
|
||||
document.getElementById("root"),
|
||||
);
|
||||
})
|
||||
|
@ -19,12 +19,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {AdornmentType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/AdornmentType";
|
||||
import {Capability} from "@kingsrook/qqq-frontend-core/lib/model/metaData/Capability";
|
||||
import {QFieldType} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QFieldType";
|
||||
import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
|
||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||
import {QRecord} from "@kingsrook/qqq-frontend-core/lib/model/QRecord";
|
||||
import {QFilterCriteria} from "@kingsrook/qqq-frontend-core/lib/model/query/QFilterCriteria";
|
||||
import {QFilterOrderBy} from "@kingsrook/qqq-frontend-core/lib/model/query/QFilterOrderBy";
|
||||
import {QQueryFilter} from "@kingsrook/qqq-frontend-core/lib/model/query/QQueryFilter";
|
||||
@ -44,10 +41,9 @@ import Menu from "@mui/material/Menu";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Modal from "@mui/material/Modal";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import {DataGridPro, getGridDateOperators, GridCallbackDetails, GridColDef, GridColumnOrderChangeParams, GridColumnVisibilityModel, GridDensity, GridEventListener, GridExportMenuItemProps, GridFilterModel, GridLinkOperator, GridPinnedColumns, gridPreferencePanelStateSelector, GridRowId, GridRowParams, GridRowsProp, GridSelectionModel, GridSortItem, GridSortModel, GridState, GridToolbarColumnsButton, GridToolbarContainer, GridToolbarDensitySelector, GridToolbarExportContainer, GridToolbarFilterButton, MuiEvent, useGridApiContext, useGridApiEventHandler, useGridSelector} from "@mui/x-data-grid-pro";
|
||||
import {GridFilterOperator} from "@mui/x-data-grid/models/gridFilterOperator";
|
||||
import {DataGridPro, GridCallbackDetails, GridColDef, GridColumnOrderChangeParams, GridColumnVisibilityModel, GridDensity, GridEventListener, GridExportMenuItemProps, GridFilterModel, GridLinkOperator, GridPinnedColumns, gridPreferencePanelStateSelector, GridRowId, GridRowParams, GridRowsProp, GridSelectionModel, GridSortItem, GridSortModel, GridState, GridToolbarColumnsButton, GridToolbarContainer, GridToolbarDensitySelector, GridToolbarExportContainer, GridToolbarFilterButton, MuiEvent, useGridApiContext, useGridApiEventHandler, useGridSelector} from "@mui/x-data-grid-pro";
|
||||
import React, {useContext, useEffect, useReducer, useRef, useState} from "react";
|
||||
import {Link, useLocation, useNavigate, useSearchParams} from "react-router-dom";
|
||||
import {useLocation, useNavigate, useSearchParams} from "react-router-dom";
|
||||
import QContext from "QContext";
|
||||
import DashboardLayout from "qqq/components/DashboardLayout";
|
||||
import Footer from "qqq/components/Footer";
|
||||
@ -55,7 +51,6 @@ import Navbar from "qqq/components/Navbar";
|
||||
import {QActionsMenuButton, QCreateNewButton} from "qqq/components/QButtons";
|
||||
import MDAlert from "qqq/components/Temporary/MDAlert";
|
||||
import MDBox from "qqq/components/Temporary/MDBox";
|
||||
import {buildQGridPvsOperators, QGridBooleanOperators, QGridNumericOperators, QGridStringOperators} from "qqq/pages/entity-list/QGridFilterOperators";
|
||||
import ProcessRun from "qqq/pages/process-run";
|
||||
import DataGridUtils from "qqq/utils/DataGridUtils";
|
||||
import QClient from "qqq/utils/QClient";
|
||||
@ -237,7 +232,7 @@ function EntityList({table, launchProcess}: Props): JSX.Element
|
||||
|
||||
const [activeModalProcess, setActiveModalProcess] = useState(null as QProcessMetaData);
|
||||
const [launchingProcess, setLaunchingProcess] = useState(launchProcess);
|
||||
const [recordIdsForProcess, setRecordIdsForProcess] = useState(null as string | QQueryFilter)
|
||||
const [recordIdsForProcess, setRecordIdsForProcess] = useState(null as string | QQueryFilter);
|
||||
|
||||
const instance = useRef({timer: null});
|
||||
|
||||
@ -355,13 +350,26 @@ function EntityList({table, launchProcess}: Props): JSX.Element
|
||||
return qFilter;
|
||||
};
|
||||
|
||||
const getTableMetaData = async (): Promise<QTableMetaData> =>
|
||||
{
|
||||
if(tableMetaData !== null)
|
||||
{
|
||||
return(new Promise((resolve) =>
|
||||
{
|
||||
resolve(tableMetaData)
|
||||
}));
|
||||
}
|
||||
|
||||
return (qController.loadTableMetaData(tableName));
|
||||
}
|
||||
|
||||
const updateTable = () =>
|
||||
{
|
||||
setLoading(true);
|
||||
setRows([]);
|
||||
(async () =>
|
||||
{
|
||||
const tableMetaData = await qController.loadTableMetaData(tableName);
|
||||
const tableMetaData = await getTableMetaData();
|
||||
setPageHeader(tableMetaData.label);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -530,7 +538,7 @@ function EntityList({table, launchProcess}: Props): JSX.Element
|
||||
|
||||
const handlePinnedColumnsChange = (pinnedColumns: GridPinnedColumns) =>
|
||||
{
|
||||
setPinnedColumns(pinnedColumns)
|
||||
setPinnedColumns(pinnedColumns);
|
||||
localStorage.setItem(pinnedColumnsLocalStorageKey, JSON.stringify(pinnedColumns));
|
||||
};
|
||||
|
||||
@ -1080,7 +1088,14 @@ function EntityList({table, launchProcess}: Props): JSX.Element
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
useEffect(() =>
|
||||
{
|
||||
updateTable();
|
||||
if(latestQueryId > 0)
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// to avoid both this useEffect and the one below from both doing an "initial query", //
|
||||
// only run this one if at least 1 query has already been ran //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
updateTable();
|
||||
}
|
||||
}, [ pageNumber, rowsPerPage, columnSortModel ]);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -32,6 +32,7 @@ class QClient
|
||||
|
||||
private static handleException(exception: QException)
|
||||
{
|
||||
// todo - check for 401 and clear cookie et al & logout?
|
||||
console.log(`Caught Exception: ${JSON.stringify(exception)}`);
|
||||
throw (exception);
|
||||
}
|
||||
|
@ -32,30 +32,36 @@ class QProcessUtils
|
||||
public static getProcessesForTable(metaData: QInstance, tableName: string, includeHidden = false): QProcessMetaData[]
|
||||
{
|
||||
const matchingProcesses: QProcessMetaData[] = [];
|
||||
const processKeys = [...metaData.processes.keys()];
|
||||
processKeys.forEach((key) =>
|
||||
if (metaData.processes)
|
||||
{
|
||||
const process = metaData.processes.get(key);
|
||||
if (process.tableName === tableName && (includeHidden || !process.isHidden))
|
||||
const processKeys = [...metaData.processes.keys()];
|
||||
processKeys.forEach((key) =>
|
||||
{
|
||||
matchingProcesses.push(process);
|
||||
}
|
||||
});
|
||||
const process = metaData.processes.get(key);
|
||||
if (process.tableName === tableName && (includeHidden || !process.isHidden))
|
||||
{
|
||||
matchingProcesses.push(process);
|
||||
}
|
||||
});
|
||||
}
|
||||
return matchingProcesses;
|
||||
}
|
||||
|
||||
public static getReportsForTable(metaData: QInstance, tableName: string, includeHidden = false): QReportMetaData[]
|
||||
{
|
||||
const matchingReports: QReportMetaData[] = [];
|
||||
const reportKeys = [...metaData.reports.keys()];
|
||||
reportKeys.forEach((key) =>
|
||||
if (metaData.reports)
|
||||
{
|
||||
const process = metaData.reports.get(key);
|
||||
if (process.tableName === tableName)
|
||||
const reportKeys = [...metaData.reports.keys()];
|
||||
reportKeys.forEach((key) =>
|
||||
{
|
||||
matchingReports.push(process);
|
||||
}
|
||||
});
|
||||
const process = metaData.reports.get(key);
|
||||
if (process.tableName === tableName)
|
||||
{
|
||||
matchingReports.push(process);
|
||||
}
|
||||
});
|
||||
}
|
||||
return matchingReports;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user