element", () => {
- // https://on.cypress.io/select
-
- // at first, no option should be selected
- cy.get(".action-select").should("have.value", "--Select a fruit--");
-
- // Select option(s) with matching text content
- cy.get(".action-select").select("apples");
- // confirm the apples were selected
- // note that each value starts with "fr-" in our HTML
- cy.get(".action-select").should("have.value", "fr-apples");
-
- cy.get(".action-select-multiple")
- .select(["apples", "oranges", "bananas"])
- // when getting multiple values, invoke "val" method first
- .invoke("val")
- .should("deep.equal", ["fr-apples", "fr-oranges", "fr-bananas"]);
-
- // Select option(s) with matching value
- cy.get(".action-select")
- .select("fr-bananas")
- // can attach an assertion right away to the element
- .should("have.value", "fr-bananas");
-
- cy.get(".action-select-multiple")
- .select(["fr-apples", "fr-oranges", "fr-bananas"])
- .invoke("val")
- .should("deep.equal", ["fr-apples", "fr-oranges", "fr-bananas"]);
-
- // assert the selected values include oranges
- cy.get(".action-select-multiple").invoke("val").should("include", "fr-oranges");
- });
-
- it(".scrollIntoView() - scroll an element into view", () => {
- // https://on.cypress.io/scrollintoview
-
- // normally all of these buttons are hidden,
- // because they're not within
- // the viewable area of their parent
- // (we need to scroll to see them)
- cy.get("#scroll-horizontal button").should("not.be.visible");
-
- // scroll the button into view, as if the user had scrolled
- cy.get("#scroll-horizontal button").scrollIntoView().should("be.visible");
-
- cy.get("#scroll-vertical button").should("not.be.visible");
-
- // Cypress handles the scroll direction needed
- cy.get("#scroll-vertical button").scrollIntoView().should("be.visible");
-
- cy.get("#scroll-both button").should("not.be.visible");
-
- // Cypress knows to scroll to the right and down
- cy.get("#scroll-both button").scrollIntoView().should("be.visible");
- });
-
- it(".trigger() - trigger an event on a DOM element", () => {
- // https://on.cypress.io/trigger
-
- // To interact with a range input (slider)
- // we need to set its value & trigger the
- // event to signal it changed
-
- // Here, we invoke jQuery's val() method to set
- // the value and trigger the 'change' event
- cy.get(".trigger-input-range")
- .invoke("val", 25)
- .trigger("change")
- .get("input[type=range]")
- .siblings("p")
- .should("have.text", "25");
- });
-
- it("cy.scrollTo() - scroll the window or element to a position", () => {
- // https://on.cypress.io/scrollto
-
- // You can scroll to 9 specific positions of an element:
- // -----------------------------------
- // | topLeft top topRight |
- // | |
- // | |
- // | |
- // | left center right |
- // | |
- // | |
- // | |
- // | bottomLeft bottom bottomRight |
- // -----------------------------------
-
- // if you chain .scrollTo() off of cy, we will
- // scroll the entire window
- cy.scrollTo("bottom");
-
- cy.get("#scrollable-horizontal").scrollTo("right");
-
- // or you can scroll to a specific coordinate:
- // (x axis, y axis) in pixels
- cy.get("#scrollable-vertical").scrollTo(250, 250);
-
- // or you can scroll to a specific percentage
- // of the (width, height) of the element
- cy.get("#scrollable-both").scrollTo("75%", "25%");
-
- // control the easing of the scroll (default is 'swing')
- cy.get("#scrollable-vertical").scrollTo("center", { easing: "linear" });
-
- // control the duration of the scroll (in ms)
- cy.get("#scrollable-both").scrollTo("center", { duration: 2000 });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/aliasing.cy.js b/client/cypress/e2e/2-advanced-examples/aliasing.cy.js
deleted file mode 100644
index 152b8ece9..000000000
--- a/client/cypress/e2e/2-advanced-examples/aliasing.cy.js
+++ /dev/null
@@ -1,35 +0,0 @@
-///
-
-context("Aliasing", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/aliasing");
- });
-
- it(".as() - alias a DOM element for later use", () => {
- // https://on.cypress.io/as
-
- // Alias a DOM element for use later
- // We don't have to traverse to the element
- // later in our code, we reference it with @
-
- cy.get(".as-table").find("tbody>tr").first().find("td").first().find("button").as("firstBtn");
-
- // when we reference the alias, we place an
- // @ in front of its name
- cy.get("@firstBtn").click();
-
- cy.get("@firstBtn").should("have.class", "btn-success").and("contain", "Changed");
- });
-
- it(".as() - alias a route for later use", () => {
- // Alias the route to wait for its response
- cy.intercept("GET", "**/comments/*").as("getComment");
-
- // we have code that gets a comment when
- // the button is clicked in scripts.js
- cy.get(".network-btn").click();
-
- // https://on.cypress.io/wait
- cy.wait("@getComment").its("response.statusCode").should("eq", 200);
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/assertions.cy.js b/client/cypress/e2e/2-advanced-examples/assertions.cy.js
deleted file mode 100644
index 2bde3a9a0..000000000
--- a/client/cypress/e2e/2-advanced-examples/assertions.cy.js
+++ /dev/null
@@ -1,173 +0,0 @@
-///
-
-context("Assertions", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/assertions");
- });
-
- describe("Implicit Assertions", () => {
- it(".should() - make an assertion about the current subject", () => {
- // https://on.cypress.io/should
- cy.get(".assertion-table")
- .find("tbody tr:last")
- .should("have.class", "success")
- .find("td")
- .first()
- // checking the text of the element in various ways
- .should("have.text", "Column content")
- .should("contain", "Column content")
- .should("have.html", "Column content")
- // chai-jquery uses "is()" to check if element matches selector
- .should("match", "td")
- // to match text content against a regular expression
- // first need to invoke jQuery method text()
- // and then match using regular expression
- .invoke("text")
- .should("match", /column content/i);
-
- // a better way to check element's text content against a regular expression
- // is to use "cy.contains"
- // https://on.cypress.io/contains
- cy.get(".assertion-table")
- .find("tbody tr:last")
- // finds first element with text content matching regular expression
- .contains("td", /column content/i)
- .should("be.visible");
-
- // for more information about asserting element's text
- // see https://on.cypress.io/using-cypress-faq#How-do-I-get-an-element’s-text-contents
- });
-
- it(".and() - chain multiple assertions together", () => {
- // https://on.cypress.io/and
- cy.get(".assertions-link").should("have.class", "active").and("have.attr", "href").and("include", "cypress.io");
- });
- });
-
- describe("Explicit Assertions", () => {
- // https://on.cypress.io/assertions
- it("expect - make an assertion about a specified subject", () => {
- // We can use Chai's BDD style assertions
- expect(true).to.be.true;
- const o = { foo: "bar" };
-
- expect(o).to.equal(o);
- expect(o).to.deep.equal({ foo: "bar" });
- // matching text using regular expression
- expect("FooBar").to.match(/bar$/i);
- });
-
- it("pass your own callback function to should()", () => {
- // Pass a function to should that can have any number
- // of explicit assertions within it.
- // The ".should(cb)" function will be retried
- // automatically until it passes all your explicit assertions or times out.
- cy.get(".assertions-p")
- .find("p")
- .should(($p) => {
- // https://on.cypress.io/$
- // return an array of texts from all of the p's
- // @ts-ignore TS6133 unused variable
- const texts = $p.map((i, el) => Cypress.$(el).text());
-
- // jquery map returns jquery object
- // and .get() convert this to simple array
- const paragraphs = texts.get();
-
- // array should have length of 3
- expect(paragraphs, "has 3 paragraphs").to.have.length(3);
-
- // use second argument to expect(...) to provide clear
- // message with each assertion
- expect(paragraphs, "has expected text in each paragraph").to.deep.eq([
- "Some text from first p",
- "More text from second p",
- "And even more text from third p"
- ]);
- });
- });
-
- it("finds element by class name regex", () => {
- cy.get(".docs-header")
- .find("div")
- // .should(cb) callback function will be retried
- .should(($div) => {
- expect($div).to.have.length(1);
-
- const className = $div[0].className;
-
- expect(className).to.match(/heading-/);
- })
- // .then(cb) callback is not retried,
- // it either passes or fails
- .then(($div) => {
- expect($div, "text content").to.have.text("Introduction");
- });
- });
-
- it("can throw any error", () => {
- cy.get(".docs-header")
- .find("div")
- .should(($div) => {
- if ($div.length !== 1) {
- // you can throw your own errors
- throw new Error("Did not find 1 element");
- }
-
- const className = $div[0].className;
-
- if (!className.match(/heading-/)) {
- throw new Error(`Could not find class "heading-" in ${className}`);
- }
- });
- });
-
- it("matches unknown text between two elements", () => {
- /**
- * Text from the first element.
- * @type {string}
- */
- let text;
-
- /**
- * Normalizes passed text,
- * useful before comparing text with spaces and different capitalization.
- * @param {string} s Text to normalize
- */
- const normalizeText = (s) => s.replace(/\s/g, "").toLowerCase();
-
- cy.get(".two-elements")
- .find(".first")
- .then(($first) => {
- // save text from the first element
- text = normalizeText($first.text());
- });
-
- cy.get(".two-elements")
- .find(".second")
- .should(($div) => {
- // we can massage text before comparing
- const secondText = normalizeText($div.text());
-
- expect(secondText, "second text").to.equal(text);
- });
- });
-
- it("assert - assert shape of an object", () => {
- const person = {
- name: "Joe",
- age: 20
- };
-
- assert.isObject(person, "value is object");
- });
-
- it("retries the should callback until assertions pass", () => {
- cy.get("#random-number").should(($div) => {
- const n = parseFloat($div.text());
-
- expect(n).to.be.gte(1).and.be.lte(10);
- });
- });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/connectors.cy.js b/client/cypress/e2e/2-advanced-examples/connectors.cy.js
deleted file mode 100644
index 3cd60d308..000000000
--- a/client/cypress/e2e/2-advanced-examples/connectors.cy.js
+++ /dev/null
@@ -1,96 +0,0 @@
-///
-
-context("Connectors", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/connectors");
- });
-
- it(".each() - iterate over an array of elements", () => {
- // https://on.cypress.io/each
- cy.get(".connectors-each-ul>li").each(($el, index, $list) => {
- console.log($el, index, $list);
- });
- });
-
- it(".its() - get properties on the current subject", () => {
- // https://on.cypress.io/its
- cy.get(".connectors-its-ul>li")
- // calls the 'length' property yielding that value
- .its("length")
- .should("be.gt", 2);
- });
-
- it(".invoke() - invoke a function on the current subject", () => {
- // our div is hidden in our script.js
- // $('.connectors-div').hide()
-
- // https://on.cypress.io/invoke
- cy.get(".connectors-div")
- .should("be.hidden")
- // call the jquery method 'show' on the 'div.container'
- .invoke("show")
- .should("be.visible");
- });
-
- it(".spread() - spread an array as individual args to callback function", () => {
- // https://on.cypress.io/spread
- const arr = ["foo", "bar", "baz"];
-
- cy.wrap(arr).spread((foo, bar, baz) => {
- expect(foo).to.eq("foo");
- expect(bar).to.eq("bar");
- expect(baz).to.eq("baz");
- });
- });
-
- describe(".then()", () => {
- it("invokes a callback function with the current subject", () => {
- // https://on.cypress.io/then
- cy.get(".connectors-list > li").then(($lis) => {
- expect($lis, "3 items").to.have.length(3);
- expect($lis.eq(0), "first item").to.contain("Walk the dog");
- expect($lis.eq(1), "second item").to.contain("Feed the cat");
- expect($lis.eq(2), "third item").to.contain("Write JavaScript");
- });
- });
-
- it("yields the returned value to the next command", () => {
- cy.wrap(1)
- .then((num) => {
- expect(num).to.equal(1);
-
- return 2;
- })
- .then((num) => {
- expect(num).to.equal(2);
- });
- });
-
- it("yields the original subject without return", () => {
- cy.wrap(1)
- .then((num) => {
- expect(num).to.equal(1);
- // note that nothing is returned from this callback
- })
- .then((num) => {
- // this callback receives the original unchanged value 1
- expect(num).to.equal(1);
- });
- });
-
- it("yields the value yielded by the last Cypress command inside", () => {
- cy.wrap(1)
- .then((num) => {
- expect(num).to.equal(1);
- // note how we run a Cypress command
- // the result yielded by this Cypress command
- // will be passed to the second ".then"
- cy.wrap(2);
- })
- .then((num) => {
- // this callback receives the value yielded by "cy.wrap(2)"
- expect(num).to.equal(2);
- });
- });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/cookies.cy.js b/client/cypress/e2e/2-advanced-examples/cookies.cy.js
deleted file mode 100644
index 390ee76e2..000000000
--- a/client/cypress/e2e/2-advanced-examples/cookies.cy.js
+++ /dev/null
@@ -1,79 +0,0 @@
-///
-
-context("Cookies", () => {
- beforeEach(() => {
- Cypress.Cookies.debug(true);
-
- cy.visit("https://example.cypress.io/commands/cookies");
-
- // clear cookies again after visiting to remove
- // any 3rd party cookies picked up such as cloudflare
- cy.clearCookies();
- });
-
- it("cy.getCookie() - get a browser cookie", () => {
- // https://on.cypress.io/getcookie
- cy.get("#getCookie .set-a-cookie").click();
-
- // cy.getCookie() yields a cookie object
- cy.getCookie("token").should("have.property", "value", "123ABC");
- });
-
- it("cy.getCookies() - get browser cookies", () => {
- // https://on.cypress.io/getcookies
- cy.getCookies().should("be.empty");
-
- cy.get("#getCookies .set-a-cookie").click();
-
- // cy.getCookies() yields an array of cookies
- cy.getCookies()
- .should("have.length", 1)
- .should((cookies) => {
- // each cookie has these properties
- expect(cookies[0]).to.have.property("name", "token");
- expect(cookies[0]).to.have.property("value", "123ABC");
- expect(cookies[0]).to.have.property("httpOnly", false);
- expect(cookies[0]).to.have.property("secure", false);
- expect(cookies[0]).to.have.property("domain");
- expect(cookies[0]).to.have.property("path");
- });
- });
-
- it("cy.setCookie() - set a browser cookie", () => {
- // https://on.cypress.io/setcookie
- cy.getCookies().should("be.empty");
-
- cy.setCookie("foo", "bar");
-
- // cy.getCookie() yields a cookie object
- cy.getCookie("foo").should("have.property", "value", "bar");
- });
-
- it("cy.clearCookie() - clear a browser cookie", () => {
- // https://on.cypress.io/clearcookie
- cy.getCookie("token").should("be.null");
-
- cy.get("#clearCookie .set-a-cookie").click();
-
- cy.getCookie("token").should("have.property", "value", "123ABC");
-
- // cy.clearCookies() yields null
- cy.clearCookie("token").should("be.null");
-
- cy.getCookie("token").should("be.null");
- });
-
- it("cy.clearCookies() - clear browser cookies", () => {
- // https://on.cypress.io/clearcookies
- cy.getCookies().should("be.empty");
-
- cy.get("#clearCookies .set-a-cookie").click();
-
- cy.getCookies().should("have.length", 1);
-
- // cy.clearCookies() yields null
- cy.clearCookies();
-
- cy.getCookies().should("be.empty");
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/cypress_api.cy.js b/client/cypress/e2e/2-advanced-examples/cypress_api.cy.js
deleted file mode 100644
index 1cd9f975e..000000000
--- a/client/cypress/e2e/2-advanced-examples/cypress_api.cy.js
+++ /dev/null
@@ -1,208 +0,0 @@
-///
-
-context("Cypress.Commands", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- // https://on.cypress.io/custom-commands
-
- it(".add() - create a custom command", () => {
- Cypress.Commands.add(
- "console",
- {
- prevSubject: true
- },
- (subject, method) => {
- // the previous subject is automatically received
- // and the commands arguments are shifted
-
- // allow us to change the console method used
- method = method || "log";
-
- // log the subject to the console
- // @ts-ignore TS7017
- console[method]("The subject is", subject);
-
- // whatever we return becomes the new subject
- // we don't want to change the subject so
- // we return whatever was passed in
- return subject;
- }
- );
-
- // @ts-ignore TS2339
- cy.get("button")
- .console("info")
- .then(($button) => {
- // subject is still $button
- });
- });
-});
-
-context("Cypress.Cookies", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- // https://on.cypress.io/cookies
- it(".debug() - enable or disable debugging", () => {
- Cypress.Cookies.debug(true);
-
- // Cypress will now log in the console when
- // cookies are set or cleared
- cy.setCookie("fakeCookie", "123ABC");
- cy.clearCookie("fakeCookie");
- cy.setCookie("fakeCookie", "123ABC");
- cy.clearCookie("fakeCookie");
- cy.setCookie("fakeCookie", "123ABC");
- });
-
- it(".preserveOnce() - preserve cookies by key", () => {
- // normally cookies are reset after each test
- cy.getCookie("fakeCookie").should("not.be.ok");
-
- // preserving a cookie will not clear it when
- // the next test starts
- cy.setCookie("lastCookie", "789XYZ");
- Cypress.Cookies.preserveOnce("lastCookie");
- });
-
- it(".defaults() - set defaults for all cookies", () => {
- // now any cookie with the name 'session_id' will
- // not be cleared before each new test runs
- Cypress.Cookies.defaults({
- preserve: "session_id"
- });
- });
-});
-
-context("Cypress.arch", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get CPU architecture name of underlying OS", () => {
- // https://on.cypress.io/arch
- expect(Cypress.arch).to.exist;
- });
-});
-
-context("Cypress.config()", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get and set configuration options", () => {
- // https://on.cypress.io/config
- let myConfig = Cypress.config();
-
- expect(myConfig).to.have.property("animationDistanceThreshold", 5);
- expect(myConfig).to.have.property("baseUrl", null);
- expect(myConfig).to.have.property("defaultCommandTimeout", 4000);
- expect(myConfig).to.have.property("requestTimeout", 5000);
- expect(myConfig).to.have.property("responseTimeout", 30000);
- expect(myConfig).to.have.property("viewportHeight", 660);
- expect(myConfig).to.have.property("viewportWidth", 1000);
- expect(myConfig).to.have.property("pageLoadTimeout", 60000);
- expect(myConfig).to.have.property("waitForAnimations", true);
-
- expect(Cypress.config("pageLoadTimeout")).to.eq(60000);
-
- // this will change the config for the rest of your tests!
- Cypress.config("pageLoadTimeout", 20000);
-
- expect(Cypress.config("pageLoadTimeout")).to.eq(20000);
-
- Cypress.config("pageLoadTimeout", 60000);
- });
-});
-
-context("Cypress.dom", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- // https://on.cypress.io/dom
- it(".isHidden() - determine if a DOM element is hidden", () => {
- let hiddenP = Cypress.$(".dom-p p.hidden").get(0);
- let visibleP = Cypress.$(".dom-p p.visible").get(0);
-
- // our first paragraph has css class 'hidden'
- expect(Cypress.dom.isHidden(hiddenP)).to.be.true;
- expect(Cypress.dom.isHidden(visibleP)).to.be.false;
- });
-});
-
-context("Cypress.env()", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- // We can set environment variables for highly dynamic values
-
- // https://on.cypress.io/environment-variables
- it("Get environment variables", () => {
- // https://on.cypress.io/env
- // set multiple environment variables
- Cypress.env({
- host: "veronica.dev.local",
- api_server: "http://localhost:8888/v1/"
- });
-
- // get environment variable
- expect(Cypress.env("host")).to.eq("veronica.dev.local");
-
- // set environment variable
- Cypress.env("api_server", "http://localhost:8888/v2/");
- expect(Cypress.env("api_server")).to.eq("http://localhost:8888/v2/");
-
- // get all environment variable
- expect(Cypress.env()).to.have.property("host", "veronica.dev.local");
- expect(Cypress.env()).to.have.property("api_server", "http://localhost:8888/v2/");
- });
-});
-
-context("Cypress.log", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Control what is printed to the Command Log", () => {
- // https://on.cypress.io/cypress-log
- });
-});
-
-context("Cypress.platform", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get underlying OS name", () => {
- // https://on.cypress.io/platform
- expect(Cypress.platform).to.be.exist;
- });
-});
-
-context("Cypress.version", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get current version of Cypress being run", () => {
- // https://on.cypress.io/version
- expect(Cypress.version).to.be.exist;
- });
-});
-
-context("Cypress.spec", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/cypress-api");
- });
-
- it("Get current spec information", () => {
- // https://on.cypress.io/spec
- // wrap the object so we can inspect it easily by clicking in the command log
- cy.wrap(Cypress.spec).should("include.keys", ["name", "relative", "absolute"]);
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/files.cy.js b/client/cypress/e2e/2-advanced-examples/files.cy.js
deleted file mode 100644
index ad1bef656..000000000
--- a/client/cypress/e2e/2-advanced-examples/files.cy.js
+++ /dev/null
@@ -1,86 +0,0 @@
-///
-
-/// JSON fixture file can be loaded directly using
-// the built-in JavaScript bundler
-// @ts-ignore
-const requiredExample = require("../../fixtures/example");
-
-context("Files", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/files");
- });
-
- beforeEach(() => {
- // load example.json fixture file and store
- // in the test context object
- cy.fixture("example.json").as("example");
- });
-
- it("cy.fixture() - load a fixture", () => {
- // https://on.cypress.io/fixture
-
- // Instead of writing a response inline you can
- // use a fixture file's content.
-
- // when application makes an Ajax request matching "GET **/comments/*"
- // Cypress will intercept it and reply with the object in `example.json` fixture
- cy.intercept("GET", "**/comments/*", { fixture: "example.json" }).as("getComment");
-
- // we have code that gets a comment when
- // the button is clicked in scripts.js
- cy.get(".fixture-btn").click();
-
- cy.wait("@getComment")
- .its("response.body")
- .should("have.property", "name")
- .and("include", "Using fixtures to represent data");
- });
-
- it("cy.fixture() or require - load a fixture", function () {
- // we are inside the "function () { ... }"
- // callback and can use test context object "this"
- // "this.example" was loaded in "beforeEach" function callback
- expect(this.example, "fixture in the test context").to.deep.equal(requiredExample);
-
- // or use "cy.wrap" and "should('deep.equal', ...)" assertion
- cy.wrap(this.example).should("deep.equal", requiredExample);
- });
-
- it("cy.readFile() - read file contents", () => {
- // https://on.cypress.io/readfile
-
- // You can read a file and yield its contents
- // The filePath is relative to your project's root.
- cy.readFile("cypress.json").then((json) => {
- expect(json).to.be.an("object");
- });
- });
-
- it("cy.writeFile() - write to a file", () => {
- // https://on.cypress.io/writefile
-
- // You can write to a file
-
- // Use a response from a request to automatically
- // generate a fixture file for use later
- cy.request("https://jsonplaceholder.cypress.io/users").then((response) => {
- cy.writeFile("cypress/fixtures/users.json", response.body);
- });
-
- cy.fixture("users").should((users) => {
- expect(users[0].name).to.exist;
- });
-
- // JavaScript arrays and objects are stringified
- // and formatted into text.
- cy.writeFile("cypress/fixtures/profile.json", {
- id: 8739,
- name: "Jane",
- email: "jane@example.com"
- });
-
- cy.fixture("profile").should((profile) => {
- expect(profile.name).to.eq("Jane");
- });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/local_storage.cy.js b/client/cypress/e2e/2-advanced-examples/local_storage.cy.js
deleted file mode 100644
index 7007d02bf..000000000
--- a/client/cypress/e2e/2-advanced-examples/local_storage.cy.js
+++ /dev/null
@@ -1,58 +0,0 @@
-///
-
-context("Local Storage", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/local-storage");
- });
- // Although local storage is automatically cleared
- // in between tests to maintain a clean state
- // sometimes we need to clear the local storage manually
-
- it("cy.clearLocalStorage() - clear all data in local storage", () => {
- // https://on.cypress.io/clearlocalstorage
- cy.get(".ls-btn")
- .click()
- .should(() => {
- expect(localStorage.getItem("prop1")).to.eq("red");
- expect(localStorage.getItem("prop2")).to.eq("blue");
- expect(localStorage.getItem("prop3")).to.eq("magenta");
- });
-
- // clearLocalStorage() yields the localStorage object
- cy.clearLocalStorage().should((ls) => {
- expect(ls.getItem("prop1")).to.be.null;
- expect(ls.getItem("prop2")).to.be.null;
- expect(ls.getItem("prop3")).to.be.null;
- });
-
- cy.get(".ls-btn")
- .click()
- .should(() => {
- expect(localStorage.getItem("prop1")).to.eq("red");
- expect(localStorage.getItem("prop2")).to.eq("blue");
- expect(localStorage.getItem("prop3")).to.eq("magenta");
- });
-
- // Clear key matching string in Local Storage
- cy.clearLocalStorage("prop1").should((ls) => {
- expect(ls.getItem("prop1")).to.be.null;
- expect(ls.getItem("prop2")).to.eq("blue");
- expect(ls.getItem("prop3")).to.eq("magenta");
- });
-
- cy.get(".ls-btn")
- .click()
- .should(() => {
- expect(localStorage.getItem("prop1")).to.eq("red");
- expect(localStorage.getItem("prop2")).to.eq("blue");
- expect(localStorage.getItem("prop3")).to.eq("magenta");
- });
-
- // Clear keys matching regex in Local Storage
- cy.clearLocalStorage(/prop1|2/).should((ls) => {
- expect(ls.getItem("prop1")).to.be.null;
- expect(ls.getItem("prop2")).to.be.null;
- expect(ls.getItem("prop3")).to.eq("magenta");
- });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/location.cy.js b/client/cypress/e2e/2-advanced-examples/location.cy.js
deleted file mode 100644
index f5e6230d6..000000000
--- a/client/cypress/e2e/2-advanced-examples/location.cy.js
+++ /dev/null
@@ -1,32 +0,0 @@
-///
-
-context("Location", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/location");
- });
-
- it("cy.hash() - get the current URL hash", () => {
- // https://on.cypress.io/hash
- cy.hash().should("be.empty");
- });
-
- it("cy.location() - get window.location", () => {
- // https://on.cypress.io/location
- cy.location().should((location) => {
- expect(location.hash).to.be.empty;
- expect(location.href).to.eq("https://example.cypress.io/commands/location");
- expect(location.host).to.eq("example.cypress.io");
- expect(location.hostname).to.eq("example.cypress.io");
- expect(location.origin).to.eq("https://example.cypress.io");
- expect(location.pathname).to.eq("/commands/location");
- expect(location.port).to.eq("");
- expect(location.protocol).to.eq("https:");
- expect(location.search).to.be.empty;
- });
- });
-
- it("cy.url() - get the current URL", () => {
- // https://on.cypress.io/url
- cy.url().should("eq", "https://example.cypress.io/commands/location");
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/misc.cy.js b/client/cypress/e2e/2-advanced-examples/misc.cy.js
deleted file mode 100644
index 9ef98ae41..000000000
--- a/client/cypress/e2e/2-advanced-examples/misc.cy.js
+++ /dev/null
@@ -1,98 +0,0 @@
-///
-
-context("Misc", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/misc");
- });
-
- it(".end() - end the command chain", () => {
- // https://on.cypress.io/end
-
- // cy.end is useful when you want to end a chain of commands
- // and force Cypress to re-query from the root element
- cy.get(".misc-table").within(() => {
- // ends the current chain and yields null
- cy.contains("Cheryl").click().end();
-
- // queries the entire table again
- cy.contains("Charles").click();
- });
- });
-
- it("cy.exec() - execute a system command", () => {
- // execute a system command.
- // so you can take actions necessary for
- // your test outside the scope of Cypress.
- // https://on.cypress.io/exec
-
- // we can use Cypress.platform string to
- // select appropriate command
- // https://on.cypress/io/platform
- cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`);
-
- // on CircleCI Windows build machines we have a failure to run bash shell
- // https://github.com/cypress-io/cypress/issues/5169
- // so skip some of the tests by passing flag "--env circle=true"
- const isCircleOnWindows = Cypress.platform === "win32" && Cypress.env("circle");
-
- if (isCircleOnWindows) {
- cy.log("Skipping test on CircleCI");
-
- return;
- }
-
- // cy.exec problem on Shippable CI
- // https://github.com/cypress-io/cypress/issues/6718
- const isShippable = Cypress.platform === "linux" && Cypress.env("shippable");
-
- if (isShippable) {
- cy.log("Skipping test on ShippableCI");
-
- return;
- }
-
- cy.exec("echo Jane Lane").its("stdout").should("contain", "Jane Lane");
-
- if (Cypress.platform === "win32") {
- cy.exec("print cypress.json").its("stderr").should("be.empty");
- } else {
- cy.exec("cat cypress.json").its("stderr").should("be.empty");
-
- cy.exec("pwd").its("code").should("eq", 0);
- }
- });
-
- it("cy.focused() - get the DOM element that has focus", () => {
- // https://on.cypress.io/focused
- cy.get(".misc-form").find("#name").click();
- cy.focused().should("have.id", "name");
-
- cy.get(".misc-form").find("#description").click();
- cy.focused().should("have.id", "description");
- });
-
- context("Cypress.Screenshot", function () {
- it("cy.screenshot() - take a screenshot", () => {
- // https://on.cypress.io/screenshot
- cy.screenshot("my-image");
- });
-
- it("Cypress.Screenshot.defaults() - change default config of screenshots", function () {
- Cypress.Screenshot.defaults({
- blackout: [".foo"],
- capture: "viewport",
- clip: { x: 0, y: 0, width: 200, height: 200 },
- scale: false,
- disableTimersAndAnimations: true,
- screenshotOnRunFailure: true,
- onBeforeScreenshot() {},
- onAfterScreenshot() {}
- });
- });
- });
-
- it("cy.wrap() - wrap an object", () => {
- // https://on.cypress.io/wrap
- cy.wrap({ foo: "bar" }).should("have.property", "foo").and("include", "bar");
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/navigation.cy.js b/client/cypress/e2e/2-advanced-examples/navigation.cy.js
deleted file mode 100644
index a1993ee36..000000000
--- a/client/cypress/e2e/2-advanced-examples/navigation.cy.js
+++ /dev/null
@@ -1,56 +0,0 @@
-///
-
-context("Navigation", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io");
- cy.get(".navbar-nav").contains("Commands").click();
- cy.get(".dropdown-menu").contains("Navigation").click();
- });
-
- it("cy.go() - go back or forward in the browser's history", () => {
- // https://on.cypress.io/go
-
- cy.location("pathname").should("include", "navigation");
-
- cy.go("back");
- cy.location("pathname").should("not.include", "navigation");
-
- cy.go("forward");
- cy.location("pathname").should("include", "navigation");
-
- // clicking back
- cy.go(-1);
- cy.location("pathname").should("not.include", "navigation");
-
- // clicking forward
- cy.go(1);
- cy.location("pathname").should("include", "navigation");
- });
-
- it("cy.reload() - reload the page", () => {
- // https://on.cypress.io/reload
- cy.reload();
-
- // reload the page without using the cache
- cy.reload(true);
- });
-
- it("cy.visit() - visit a remote url", () => {
- // https://on.cypress.io/visit
-
- // Visit any sub-domain of your current domain
-
- // Pass options to the visit
- cy.visit("https://example.cypress.io/commands/navigation", {
- timeout: 50000, // increase total time for the visit to resolve
- onBeforeLoad(contentWindow) {
- // contentWindow is the remote page's window object
- expect(typeof contentWindow === "object").to.be.true;
- },
- onLoad(contentWindow) {
- // contentWindow is the remote page's window object
- expect(typeof contentWindow === "object").to.be.true;
- }
- });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/network_requests.cy.js b/client/cypress/e2e/2-advanced-examples/network_requests.cy.js
deleted file mode 100644
index 693e5395d..000000000
--- a/client/cypress/e2e/2-advanced-examples/network_requests.cy.js
+++ /dev/null
@@ -1,165 +0,0 @@
-///
-
-context("Network Requests", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/network-requests");
- });
-
- // Manage HTTP requests in your app
-
- it("cy.request() - make an XHR request", () => {
- // https://on.cypress.io/request
- cy.request("https://jsonplaceholder.cypress.io/comments").should((response) => {
- expect(response.status).to.eq(200);
- // the server sometimes gets an extra comment posted from another machine
- // which gets returned as 1 extra object
- expect(response.body).to.have.property("length").and.be.oneOf([500, 501]);
- expect(response).to.have.property("headers");
- expect(response).to.have.property("duration");
- });
- });
-
- it("cy.request() - verify response using BDD syntax", () => {
- cy.request("https://jsonplaceholder.cypress.io/comments").then((response) => {
- // https://on.cypress.io/assertions
- expect(response).property("status").to.equal(200);
- expect(response).property("body").to.have.property("length").and.be.oneOf([500, 501]);
- expect(response).to.include.keys("headers", "duration");
- });
- });
-
- it("cy.request() with query parameters", () => {
- // will execute request
- // https://jsonplaceholder.cypress.io/comments?postId=1&id=3
- cy.request({
- url: "https://jsonplaceholder.cypress.io/comments",
- qs: {
- postId: 1,
- id: 3
- }
- })
- .its("body")
- .should("be.an", "array")
- .and("have.length", 1)
- .its("0") // yields first element of the array
- .should("contain", {
- postId: 1,
- id: 3
- });
- });
-
- it("cy.request() - pass result to the second request", () => {
- // first, let's find out the userId of the first user we have
- cy.request("https://jsonplaceholder.cypress.io/users?_limit=1")
- .its("body") // yields the response object
- .its("0") // yields the first element of the returned list
- // the above two commands its('body').its('0')
- // can be written as its('body.0')
- // if you do not care about TypeScript checks
- .then((user) => {
- expect(user).property("id").to.be.a("number");
- // make a new post on behalf of the user
- cy.request("POST", "https://jsonplaceholder.cypress.io/posts", {
- userId: user.id,
- title: "Cypress Test Runner",
- body: "Fast, easy and reliable testing for anything that runs in a browser."
- });
- })
- // note that the value here is the returned value of the 2nd request
- // which is the new post object
- .then((response) => {
- expect(response).property("status").to.equal(201); // new entity created
- expect(response).property("body").to.contain({
- title: "Cypress Test Runner"
- });
-
- // we don't know the exact post id - only that it will be > 100
- // since JSONPlaceholder has built-in 100 posts
- expect(response.body).property("id").to.be.a("number").and.to.be.gt(100);
-
- // we don't know the user id here - since it was in above closure
- // so in this test just confirm that the property is there
- expect(response.body).property("userId").to.be.a("number");
- });
- });
-
- it("cy.request() - save response in the shared test context", () => {
- // https://on.cypress.io/variables-and-aliases
- cy.request("https://jsonplaceholder.cypress.io/users?_limit=1")
- .its("body")
- .its("0") // yields the first element of the returned list
- .as("user") // saves the object in the test context
- .then(function () {
- // NOTE 👀
- // By the time this callback runs the "as('user')" command
- // has saved the user object in the test context.
- // To access the test context we need to use
- // the "function () { ... }" callback form,
- // otherwise "this" points at a wrong or undefined object!
- cy.request("POST", "https://jsonplaceholder.cypress.io/posts", {
- userId: this.user.id,
- title: "Cypress Test Runner",
- body: "Fast, easy and reliable testing for anything that runs in a browser."
- })
- .its("body")
- .as("post"); // save the new post from the response
- })
- .then(function () {
- // When this callback runs, both "cy.request" API commands have finished
- // and the test context has "user" and "post" objects set.
- // Let's verify them.
- expect(this.post, "post has the right user id").property("userId").to.equal(this.user.id);
- });
- });
-
- it("cy.intercept() - route responses to matching requests", () => {
- // https://on.cypress.io/intercept
-
- let message = "whoa, this comment does not exist";
-
- // Listen to GET to comments/1
- cy.intercept("GET", "**/comments/*").as("getComment");
-
- // we have code that gets a comment when
- // the button is clicked in scripts.js
- cy.get(".network-btn").click();
-
- // https://on.cypress.io/wait
- cy.wait("@getComment").its("response.statusCode").should("be.oneOf", [200, 304]);
-
- // Listen to POST to comments
- cy.intercept("POST", "**/comments").as("postComment");
-
- // we have code that posts a comment when
- // the button is clicked in scripts.js
- cy.get(".network-post").click();
- cy.wait("@postComment").should(({ request, response }) => {
- expect(request.body).to.include("email");
- expect(request.headers).to.have.property("content-type");
- expect(response && response.body).to.have.property("name", "Using POST in cy.intercept()");
- });
-
- // Stub a response to PUT comments/ ****
- cy.intercept(
- {
- method: "PUT",
- url: "**/comments/*"
- },
- {
- statusCode: 404,
- body: { error: message },
- headers: { "access-control-allow-origin": "*" },
- delayMs: 500
- }
- ).as("putComment");
-
- // we have code that puts a comment when
- // the button is clicked in scripts.js
- cy.get(".network-put").click();
-
- cy.wait("@putComment");
-
- // our 404 statusCode logic in scripts.js executed
- cy.get(".network-put-comment").should("contain", message);
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/querying.cy.js b/client/cypress/e2e/2-advanced-examples/querying.cy.js
deleted file mode 100644
index 35cf7c24a..000000000
--- a/client/cypress/e2e/2-advanced-examples/querying.cy.js
+++ /dev/null
@@ -1,100 +0,0 @@
-///
-
-context("Querying", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/querying");
- });
-
- // The most commonly used query is 'cy.get()', you can
- // think of this like the '$' in jQuery
-
- it("cy.get() - query DOM elements", () => {
- // https://on.cypress.io/get
-
- cy.get("#query-btn").should("contain", "Button");
-
- cy.get(".query-btn").should("contain", "Button");
-
- cy.get("#querying .well>button:first").should("contain", "Button");
- // ↲
- // Use CSS selectors just like jQuery
-
- cy.get('[data-test-id="test-example"]').should("have.class", "example");
-
- // 'cy.get()' yields jQuery object, you can get its attribute
- // by invoking `.attr()` method
- cy.get('[data-test-id="test-example"]').invoke("attr", "data-test-id").should("equal", "test-example");
-
- // or you can get element's CSS property
- cy.get('[data-test-id="test-example"]').invoke("css", "position").should("equal", "static");
-
- // or use assertions directly during 'cy.get()'
- // https://on.cypress.io/assertions
- cy.get('[data-test-id="test-example"]')
- .should("have.attr", "data-test-id", "test-example")
- .and("have.css", "position", "static");
- });
-
- it("cy.contains() - query DOM elements with matching content", () => {
- // https://on.cypress.io/contains
- cy.get(".query-list").contains("bananas").should("have.class", "third");
-
- // we can pass a regexp to `.contains()`
- cy.get(".query-list").contains(/^b\w+/).should("have.class", "third");
-
- cy.get(".query-list").contains("apples").should("have.class", "first");
-
- // passing a selector to contains will
- // yield the selector containing the text
- cy.get("#querying").contains("ul", "oranges").should("have.class", "query-list");
-
- cy.get(".query-button").contains("Save Form").should("have.class", "btn");
- });
-
- it(".within() - query DOM elements within a specific element", () => {
- // https://on.cypress.io/within
- cy.get(".query-form").within(() => {
- cy.get("input:first").should("have.attr", "placeholder", "Email");
- cy.get("input:last").should("have.attr", "placeholder", "Password");
- });
- });
-
- it("cy.root() - query the root DOM element", () => {
- // https://on.cypress.io/root
-
- // By default, root is the document
- cy.root().should("match", "html");
-
- cy.get(".query-ul").within(() => {
- // In this within, the root is now the ul DOM element
- cy.root().should("have.class", "query-ul");
- });
- });
-
- it("best practices - selecting elements", () => {
- // https://on.cypress.io/best-practices#Selecting-Elements
- cy.get("[data-cy=best-practices-selecting-elements]").within(() => {
- // Worst - too generic, no context
- cy.get("button").click();
-
- // Bad. Coupled to styling. Highly subject to change.
- cy.get(".btn.btn-large").click();
-
- // Average. Coupled to the `name` attribute which has HTML semantics.
- cy.get("[name=submission]").click();
-
- // Better. But still coupled to styling or JS event listeners.
- cy.get("#main").click();
-
- // Slightly better. Uses an ID but also ensures the element
- // has an ARIA role attribute
- cy.get("#main[role=button]").click();
-
- // Much better. But still coupled to text content that may change.
- cy.contains("Submit").click();
-
- // Best. Insulated from all changes.
- cy.get("[data-cy=submit]").click();
- });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js b/client/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js
deleted file mode 100644
index 7c86af8fa..000000000
--- a/client/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js
+++ /dev/null
@@ -1,203 +0,0 @@
-///
-// remove no check once Cypress.sinon is typed
-// https://github.com/cypress-io/cypress/issues/6720
-
-context("Spies, Stubs, and Clock", () => {
- it("cy.spy() - wrap a method in a spy", () => {
- // https://on.cypress.io/spy
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
-
- const obj = {
- foo() {}
- };
-
- const spy = cy.spy(obj, "foo").as("anyArgs");
-
- obj.foo();
-
- expect(spy).to.be.called;
- });
-
- it("cy.spy() retries until assertions pass", () => {
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
-
- const obj = {
- /**
- * Prints the argument passed
- * @param x {any}
- */
- foo(x) {
- console.log("obj.foo called with", x);
- }
- };
-
- cy.spy(obj, "foo").as("foo");
-
- setTimeout(() => {
- obj.foo("first");
- }, 500);
-
- setTimeout(() => {
- obj.foo("second");
- }, 2500);
-
- cy.get("@foo").should("have.been.calledTwice");
- });
-
- it("cy.stub() - create a stub and/or replace a function with stub", () => {
- // https://on.cypress.io/stub
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
-
- const obj = {
- /**
- * prints both arguments to the console
- * @param a {string}
- * @param b {string}
- */
- foo(a, b) {
- console.log("a", a, "b", b);
- }
- };
-
- const stub = cy.stub(obj, "foo").as("foo");
-
- obj.foo("foo", "bar");
-
- expect(stub).to.be.called;
- });
-
- it("cy.clock() - control time in the browser", () => {
- // https://on.cypress.io/clock
-
- // create the date in UTC so its always the same
- // no matter what local timezone the browser is running in
- const now = new Date(Date.UTC(2017, 2, 14)).getTime();
-
- cy.clock(now);
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
- cy.get("#clock-div").click().should("have.text", "1489449600");
- });
-
- it("cy.tick() - move time in the browser", () => {
- // https://on.cypress.io/tick
-
- // create the date in UTC so its always the same
- // no matter what local timezone the browser is running in
- const now = new Date(Date.UTC(2017, 2, 14)).getTime();
-
- cy.clock(now);
- cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
- cy.get("#tick-div").click().should("have.text", "1489449600");
-
- cy.tick(10000); // 10 seconds passed
- cy.get("#tick-div").click().should("have.text", "1489449610");
- });
-
- it("cy.stub() matches depending on arguments", () => {
- // see all possible matchers at
- // https://sinonjs.org/releases/latest/matchers/
- const greeter = {
- /**
- * Greets a person
- * @param {string} name
- */
- greet(name) {
- return `Hello, ${name}!`;
- }
- };
-
- cy.stub(greeter, "greet")
- .callThrough() // if you want non-matched calls to call the real method
- .withArgs(Cypress.sinon.match.string)
- .returns("Hi")
- .withArgs(Cypress.sinon.match.number)
- .throws(new Error("Invalid name"));
-
- expect(greeter.greet("World")).to.equal("Hi");
- // @ts-ignore
- expect(() => greeter.greet(42)).to.throw("Invalid name");
- expect(greeter.greet).to.have.been.calledTwice;
-
- // non-matched calls goes the actual method
- // @ts-ignore
- expect(greeter.greet()).to.equal("Hello, undefined!");
- });
-
- it("matches call arguments using Sinon matchers", () => {
- // see all possible matchers at
- // https://sinonjs.org/releases/latest/matchers/
- const calculator = {
- /**
- * returns the sum of two arguments
- * @param a {number}
- * @param b {number}
- */
- add(a, b) {
- return a + b;
- }
- };
-
- const spy = cy.spy(calculator, "add").as("add");
-
- expect(calculator.add(2, 3)).to.equal(5);
-
- // if we want to assert the exact values used during the call
- expect(spy).to.be.calledWith(2, 3);
-
- // let's confirm "add" method was called with two numbers
- expect(spy).to.be.calledWith(Cypress.sinon.match.number, Cypress.sinon.match.number);
-
- // alternatively, provide the value to match
- expect(spy).to.be.calledWith(Cypress.sinon.match(2), Cypress.sinon.match(3));
-
- // match any value
- expect(spy).to.be.calledWith(Cypress.sinon.match.any, 3);
-
- // match any value from a list
- expect(spy).to.be.calledWith(Cypress.sinon.match.in([1, 2, 3]), 3);
-
- /**
- * Returns true if the given number is event
- * @param {number} x
- */
- const isEven = (x) => x % 2 === 0;
-
- // expect the value to pass a custom predicate function
- // the second argument to "sinon.match(predicate, message)" is
- // shown if the predicate does not pass and assertion fails
- expect(spy).to.be.calledWith(Cypress.sinon.match(isEven, "isEven"), 3);
-
- /**
- * Returns a function that checks if a given number is larger than the limit
- * @param {number} limit
- * @returns {(x: number) => boolean}
- */
- const isGreaterThan = (limit) => (x) => x > limit;
-
- /**
- * Returns a function that checks if a given number is less than the limit
- * @param {number} limit
- * @returns {(x: number) => boolean}
- */
- const isLessThan = (limit) => (x) => x < limit;
-
- // you can combine several matchers using "and", "or"
- expect(spy).to.be.calledWith(
- Cypress.sinon.match.number,
- Cypress.sinon.match(isGreaterThan(2), "> 2").and(Cypress.sinon.match(isLessThan(4), "< 4"))
- );
-
- expect(spy).to.be.calledWith(
- Cypress.sinon.match.number,
- Cypress.sinon.match(isGreaterThan(200), "> 200").or(Cypress.sinon.match(3))
- );
-
- // matchers can be used from BDD assertions
- cy.get("@add").should("have.been.calledWith", Cypress.sinon.match.number, Cypress.sinon.match(3));
-
- // you can alias matchers for shorter test code
- const { match: M } = Cypress.sinon;
-
- cy.get("@add").should("have.been.calledWith", M.number, M(3));
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/traversal.cy.js b/client/cypress/e2e/2-advanced-examples/traversal.cy.js
deleted file mode 100644
index e6b56fde1..000000000
--- a/client/cypress/e2e/2-advanced-examples/traversal.cy.js
+++ /dev/null
@@ -1,97 +0,0 @@
-///
-
-context("Traversal", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/traversal");
- });
-
- it(".children() - get child DOM elements", () => {
- // https://on.cypress.io/children
- cy.get(".traversal-breadcrumb").children(".active").should("contain", "Data");
- });
-
- it(".closest() - get closest ancestor DOM element", () => {
- // https://on.cypress.io/closest
- cy.get(".traversal-badge").closest("ul").should("have.class", "list-group");
- });
-
- it(".eq() - get a DOM element at a specific index", () => {
- // https://on.cypress.io/eq
- cy.get(".traversal-list>li").eq(1).should("contain", "siamese");
- });
-
- it(".filter() - get DOM elements that match the selector", () => {
- // https://on.cypress.io/filter
- cy.get(".traversal-nav>li").filter(".active").should("contain", "About");
- });
-
- it(".find() - get descendant DOM elements of the selector", () => {
- // https://on.cypress.io/find
- cy.get(".traversal-pagination").find("li").find("a").should("have.length", 7);
- });
-
- it(".first() - get first DOM element", () => {
- // https://on.cypress.io/first
- cy.get(".traversal-table td").first().should("contain", "1");
- });
-
- it(".last() - get last DOM element", () => {
- // https://on.cypress.io/last
- cy.get(".traversal-buttons .btn").last().should("contain", "Submit");
- });
-
- it(".next() - get next sibling DOM element", () => {
- // https://on.cypress.io/next
- cy.get(".traversal-ul").contains("apples").next().should("contain", "oranges");
- });
-
- it(".nextAll() - get all next sibling DOM elements", () => {
- // https://on.cypress.io/nextall
- cy.get(".traversal-next-all").contains("oranges").nextAll().should("have.length", 3);
- });
-
- it(".nextUntil() - get next sibling DOM elements until next el", () => {
- // https://on.cypress.io/nextuntil
- cy.get("#veggies").nextUntil("#nuts").should("have.length", 3);
- });
-
- it(".not() - remove DOM elements from set of DOM elements", () => {
- // https://on.cypress.io/not
- cy.get(".traversal-disabled .btn").not("[disabled]").should("not.contain", "Disabled");
- });
-
- it(".parent() - get parent DOM element from DOM elements", () => {
- // https://on.cypress.io/parent
- cy.get(".traversal-mark").parent().should("contain", "Morbi leo risus");
- });
-
- it(".parents() - get parent DOM elements from DOM elements", () => {
- // https://on.cypress.io/parents
- cy.get(".traversal-cite").parents().should("match", "blockquote");
- });
-
- it(".parentsUntil() - get parent DOM elements from DOM elements until el", () => {
- // https://on.cypress.io/parentsuntil
- cy.get(".clothes-nav").find(".active").parentsUntil(".clothes-nav").should("have.length", 2);
- });
-
- it(".prev() - get previous sibling DOM element", () => {
- // https://on.cypress.io/prev
- cy.get(".birds").find(".active").prev().should("contain", "Lorikeets");
- });
-
- it(".prevAll() - get all previous sibling DOM elements", () => {
- // https://on.cypress.io/prevall
- cy.get(".fruits-list").find(".third").prevAll().should("have.length", 2);
- });
-
- it(".prevUntil() - get all previous sibling DOM elements until el", () => {
- // https://on.cypress.io/prevuntil
- cy.get(".foods-list").find("#nuts").prevUntil("#veggies").should("have.length", 3);
- });
-
- it(".siblings() - get all sibling DOM elements", () => {
- // https://on.cypress.io/siblings
- cy.get(".traversal-pills .active").siblings().should("have.length", 2);
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/utilities.cy.js b/client/cypress/e2e/2-advanced-examples/utilities.cy.js
deleted file mode 100644
index c0c9e8196..000000000
--- a/client/cypress/e2e/2-advanced-examples/utilities.cy.js
+++ /dev/null
@@ -1,108 +0,0 @@
-///
-
-context("Utilities", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/utilities");
- });
-
- it("Cypress._ - call a lodash method", () => {
- // https://on.cypress.io/_
- cy.request("https://jsonplaceholder.cypress.io/users").then((response) => {
- let ids = Cypress._.chain(response.body).map("id").take(3).value();
-
- expect(ids).to.deep.eq([1, 2, 3]);
- });
- });
-
- it("Cypress.$ - call a jQuery method", () => {
- // https://on.cypress.io/$
- let $li = Cypress.$(".utility-jquery li:first");
-
- cy.wrap($li).should("not.have.class", "active").click().should("have.class", "active");
- });
-
- it("Cypress.Blob - blob utilities and base64 string conversion", () => {
- // https://on.cypress.io/blob
- cy.get(".utility-blob").then(($div) => {
- // https://github.com/nolanlawson/blob-util#imgSrcToDataURL
- // get the dataUrl string for the javascript-logo
- return Cypress.Blob.imgSrcToDataURL(
- "https://example.cypress.io/assets/img/javascript-logo.png",
- undefined,
- "anonymous"
- ).then((dataUrl) => {
- // create an element and set its src to the dataUrl
- let img = Cypress.$(" ", { src: dataUrl });
-
- // need to explicitly return cy here since we are initially returning
- // the Cypress.Blob.imgSrcToDataURL promise to our test
- // append the image
- $div.append(img);
-
- cy.get(".utility-blob img").click().should("have.attr", "src", dataUrl);
- });
- });
- });
-
- it("Cypress.minimatch - test out glob patterns against strings", () => {
- // https://on.cypress.io/minimatch
- let matching = Cypress.minimatch("/users/1/comments", "/users/*/comments", {
- matchBase: true
- });
-
- expect(matching, "matching wildcard").to.be.true;
-
- matching = Cypress.minimatch("/users/1/comments/2", "/users/*/comments", {
- matchBase: true
- });
-
- expect(matching, "comments").to.be.false;
-
- // ** matches against all downstream path segments
- matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/**", {
- matchBase: true
- });
-
- expect(matching, "comments").to.be.true;
-
- // whereas * matches only the next path segment
-
- matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/*", {
- matchBase: false
- });
-
- expect(matching, "comments").to.be.false;
- });
-
- it("Cypress.Promise - instantiate a bluebird promise", () => {
- // https://on.cypress.io/promise
- let waited = false;
-
- /**
- * @return Bluebird
- */
- function waitOneSecond() {
- // return a promise that resolves after 1 second
- // @ts-ignore TS2351 (new Cypress.Promise)
- return new Cypress.Promise((resolve, reject) => {
- setTimeout(() => {
- // set waited to true
- waited = true;
-
- // resolve with 'foo' string
- resolve("foo");
- }, 1000);
- });
- }
-
- cy.then(() => {
- // return a promise to cy.then() that
- // is awaited until it resolves
- // @ts-ignore TS7006
- return waitOneSecond().then((str) => {
- expect(str).to.eq("foo");
- expect(waited).to.be.true;
- });
- });
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/viewport.cy.js b/client/cypress/e2e/2-advanced-examples/viewport.cy.js
deleted file mode 100644
index 1d73b915d..000000000
--- a/client/cypress/e2e/2-advanced-examples/viewport.cy.js
+++ /dev/null
@@ -1,59 +0,0 @@
-///
-
-context("Viewport", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/viewport");
- });
-
- it("cy.viewport() - set the viewport size and dimension", () => {
- // https://on.cypress.io/viewport
-
- cy.get("#navbar").should("be.visible");
- cy.viewport(320, 480);
-
- // the navbar should have collapse since our screen is smaller
- cy.get("#navbar").should("not.be.visible");
- cy.get(".navbar-toggle").should("be.visible").click();
- cy.get(".nav").find("a").should("be.visible");
-
- // lets see what our app looks like on a super large screen
- cy.viewport(2999, 2999);
-
- // cy.viewport() accepts a set of preset sizes
- // to easily set the screen to a device's width and height
-
- // We added a cy.wait() between each viewport change so you can see
- // the change otherwise it is a little too fast to see :)
-
- cy.viewport("macbook-15");
- cy.wait(200);
- cy.viewport("macbook-13");
- cy.wait(200);
- cy.viewport("macbook-11");
- cy.wait(200);
- cy.viewport("ipad-2");
- cy.wait(200);
- cy.viewport("ipad-mini");
- cy.wait(200);
- cy.viewport("iphone-6+");
- cy.wait(200);
- cy.viewport("iphone-6");
- cy.wait(200);
- cy.viewport("iphone-5");
- cy.wait(200);
- cy.viewport("iphone-4");
- cy.wait(200);
- cy.viewport("iphone-3");
- cy.wait(200);
-
- // cy.viewport() accepts an orientation for all presets
- // the default orientation is 'portrait'
- cy.viewport("ipad-2", "portrait");
- cy.wait(200);
- cy.viewport("iphone-4", "landscape");
- cy.wait(200);
-
- // The viewport will be reset back to the default dimensions
- // in between tests (the default can be set in cypress.json)
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/waiting.cy.js b/client/cypress/e2e/2-advanced-examples/waiting.cy.js
deleted file mode 100644
index 49915ae75..000000000
--- a/client/cypress/e2e/2-advanced-examples/waiting.cy.js
+++ /dev/null
@@ -1,31 +0,0 @@
-///
-
-context("Waiting", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/waiting");
- });
- // BE CAREFUL of adding unnecessary wait times.
- // https://on.cypress.io/best-practices#Unnecessary-Waiting
-
- // https://on.cypress.io/wait
- it("cy.wait() - wait for a specific amount of time", () => {
- cy.get(".wait-input1").type("Wait 1000ms after typing");
- cy.wait(1000);
- cy.get(".wait-input2").type("Wait 1000ms after typing");
- cy.wait(1000);
- cy.get(".wait-input3").type("Wait 1000ms after typing");
- cy.wait(1000);
- });
-
- it("cy.wait() - wait for a specific route", () => {
- // Listen to GET to comments/1
- cy.intercept("GET", "**/comments/*").as("getComment");
-
- // we have code that gets a comment when
- // the button is clicked in scripts.js
- cy.get(".network-btn").click();
-
- // wait for GET comments/1
- cy.wait("@getComment").its("response.statusCode").should("be.oneOf", [200, 304]);
- });
-});
diff --git a/client/cypress/e2e/2-advanced-examples/window.cy.js b/client/cypress/e2e/2-advanced-examples/window.cy.js
deleted file mode 100644
index 9740ba049..000000000
--- a/client/cypress/e2e/2-advanced-examples/window.cy.js
+++ /dev/null
@@ -1,22 +0,0 @@
-///
-
-context("Window", () => {
- beforeEach(() => {
- cy.visit("https://example.cypress.io/commands/window");
- });
-
- it("cy.window() - get the global window object", () => {
- // https://on.cypress.io/window
- cy.window().should("have.property", "top");
- });
-
- it("cy.document() - get the document object", () => {
- // https://on.cypress.io/document
- cy.document().should("have.property", "charset").and("eq", "UTF-8");
- });
-
- it("cy.title() - get the title", () => {
- // https://on.cypress.io/title
- cy.title().should("include", "Kitchen Sink");
- });
-});
diff --git a/client/cypress/fixtures/example.json b/client/cypress/fixtures/example.json
deleted file mode 100644
index 02e425437..000000000
--- a/client/cypress/fixtures/example.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "name": "Using fixtures to represent data",
- "email": "hello@cypress.io",
- "body": "Fixtures are a great way to mock data for responses to routes"
-}
diff --git a/client/cypress/fixtures/profile.json b/client/cypress/fixtures/profile.json
deleted file mode 100644
index a95e88f9c..000000000
--- a/client/cypress/fixtures/profile.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
- "id": 8739,
- "name": "Jane",
- "email": "jane@example.com"
-}
diff --git a/client/cypress/fixtures/users.json b/client/cypress/fixtures/users.json
deleted file mode 100644
index fe51488c7..000000000
--- a/client/cypress/fixtures/users.json
+++ /dev/null
@@ -1 +0,0 @@
-[]
diff --git a/client/cypress/plugins/index.js b/client/cypress/plugins/index.js
deleted file mode 100644
index e03c48d6e..000000000
--- a/client/cypress/plugins/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-///
-// ***********************************************************
-// This example plugins/index.jsx can be used to load plugins
-//
-// You can change the location of this file or turn off loading
-// the plugins file with the 'pluginsFile' configuration option.
-//
-// You can read more here:
-// https://on.cypress.io/plugins-guide
-// ***********************************************************
-
-// This function is called when a project is opened or re-opened (e.g. due to
-// the project's config changing)
-
-/**
- * @type {Cypress.PluginConfig}
- */
-// eslint-disable-next-line no-unused-vars
-module.exports = (on, config) => {
- // `on` is used to hook into various events Cypress emits
- // `config` is the resolved Cypress config
-};
diff --git a/client/cypress/support/commands.js b/client/cypress/support/commands.js
deleted file mode 100644
index 81f195804..000000000
--- a/client/cypress/support/commands.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// ***********************************************
-// This example commands.js shows you how to
-// create various custom commands and overwrite
-// existing commands.
-//
-// For more comprehensive examples of custom
-// commands please read more here:
-// https://on.cypress.io/custom-commands
-// ***********************************************
-//
-//
-// -- This is a parent command --
-// Cypress.Commands.add('login', (email, password) => { ... })
-//
-//
-// -- This is a child command --
-// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
-//
-//
-// -- This is a dual command --
-// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
-//
-//
-// -- This will overwrite an existing command --
-// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
-
-import "@testing-library/cypress/add-commands";
diff --git a/client/cypress/support/e2e.js b/client/cypress/support/e2e.js
deleted file mode 100644
index e328a179b..000000000
--- a/client/cypress/support/e2e.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// ***********************************************************
-// This example support/index.jsx is processed and
-// loaded automatically before your test files.
-//
-// This is a great place to put global configuration and
-// behavior that modifies Cypress.
-//
-// You can change the location of this file or turn off
-// automatically serving support files with the
-// 'supportFile' configuration option.
-//
-// You can read more here:
-// https://on.cypress.io/configuration
-// ***********************************************************
-
-// Import commands.js using ES2015 syntax:
-import "./commands";
-
-// Alternatively you can use CommonJS syntax:
-// require('./commands')
diff --git a/client/cypress/tsconfig.json b/client/cypress/tsconfig.json
deleted file mode 100644
index 36de33dee..000000000
--- a/client/cypress/tsconfig.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "compilerOptions": {
- "allowJs": true,
- "baseUrl": "../node_modules",
- "types": ["cypress"]
- },
- "include": ["**/*.*"]
-}
diff --git a/client/package-lock.json b/client/package-lock.json
index a544dc7f2..66e922267 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -9,38 +9,43 @@
"version": "0.2.1",
"hasInstallScript": true,
"dependencies": {
- "@ant-design/pro-layout": "^7.22.0",
- "@apollo/client": "^3.12.6",
+ "@ant-design/pro-layout": "^7.22.3",
+ "@apollo/client": "^3.13.5",
"@emotion/is-prop-valid": "^1.3.1",
- "@fingerprintjs/fingerprintjs": "^4.5.1",
+ "@fingerprintjs/fingerprintjs": "^4.6.1",
+ "@firebase/analytics": "^0.10.12",
+ "@firebase/app": "^0.11.3",
+ "@firebase/auth": "^1.9.1",
+ "@firebase/firestore": "^4.7.10",
+ "@firebase/messaging": "^0.12.17",
"@jsreport/browser-client": "^3.1.0",
- "@reduxjs/toolkit": "^2.5.0",
- "@sentry/cli": "^2.40.0",
- "@sentry/react": "^7.114.0",
- "@splitsoftware/splitio-react": "^1.13.0",
+ "@reduxjs/toolkit": "^2.6.1",
+ "@sentry/cli": "^2.42.4",
+ "@sentry/react": "^9.9.0",
+ "@sentry/vite-plugin": "^3.2.2",
+ "@splitsoftware/splitio-react": "^2.0.1",
"@tanem/react-nprogress": "^5.0.53",
"@vitejs/plugin-react": "^4.3.4",
- "antd": "^5.23.1",
+ "antd": "^5.24.5",
"apollo-link-logger": "^2.0.1",
- "apollo-link-sentry": "^3.3.0",
+ "apollo-link-sentry": "^4.2.0",
"autosize": "^6.0.1",
- "axios": "^1.7.9",
+ "axios": "^1.8.4",
"classnames": "^2.5.1",
"css-box-model": "^1.2.1",
"dayjs": "^1.11.13",
- "dayjs-business-days2": "^1.2.3",
+ "dayjs-business-days2": "^1.3.0",
"dinero.js": "^1.9.1",
"dotenv": "^16.4.7",
"env-cmd": "^10.1.0",
"exifr": "^7.1.3",
- "firebase": "^10.13.2",
"graphql": "^16.10.0",
- "i18next": "^23.15.1",
- "i18next-browser-languagedetector": "^8.0.2",
+ "i18next": "^24.2.3",
+ "i18next-browser-languagedetector": "^8.0.4",
"immutability-helper": "^3.1.1",
- "libphonenumber-js": "^1.11.18",
- "logrocket": "^8.1.2",
- "markerjs2": "^2.32.3",
+ "libphonenumber-js": "^1.12.6",
+ "logrocket": "^9.0.2",
+ "markerjs2": "^2.32.4",
"memoize-one": "^6.0.0",
"normalize-url": "^8.0.1",
"object-hash": "^3.0.0",
@@ -48,25 +53,25 @@
"query-string": "^9.1.1",
"raf-schd": "^4.0.3",
"react": "^18.3.1",
- "react-big-calendar": "^1.17.1",
+ "react-big-calendar": "^1.18.0",
"react-color": "^2.19.3",
- "react-cookie": "^7.2.2",
+ "react-cookie": "^8.0.1",
"react-dom": "^18.3.1",
"react-drag-listview": "^2.0.0",
"react-grid-gallery": "^1.0.1",
"react-grid-layout": "1.3.4",
- "react-i18next": "^14.1.3",
- "react-icons": "^5.4.0",
+ "react-i18next": "^15.4.1",
+ "react-icons": "^5.5.0",
"react-image-lightbox": "^5.1.4",
- "react-markdown": "^9.0.3",
+ "react-markdown": "^10.1.0",
"react-number-format": "^5.4.3",
"react-popopo": "^2.1.9",
"react-product-fruits": "^2.2.61",
"react-redux": "^9.2.0",
"react-resizable": "^3.0.5",
- "react-router-dom": "^6.26.2",
+ "react-router-dom": "^6.30.0",
"react-sticky": "^6.0.3",
- "react-virtuoso": "^4.10.4",
+ "react-virtuoso": "^4.12.5",
"recharts": "^2.15.0",
"redux": "^5.0.1",
"redux-actions": "^3.0.3",
@@ -74,50 +79,45 @@
"redux-saga": "^1.3.0",
"redux-state-sync": "^3.1.4",
"reselect": "^5.1.1",
- "sass": "^1.83.4",
+ "sass": "^1.86.0",
"socket.io-client": "^4.8.1",
- "styled-components": "^6.1.14",
+ "styled-components": "^6.1.16",
"subscriptions-transport-ws": "^0.11.0",
"use-memo-one": "^1.1.3",
- "userpilot": "^1.3.6",
"vite-plugin-ejs": "^1.7.0",
"web-vitals": "^3.5.2"
},
"devDependencies": {
- "@ant-design/icons": "^5.5.2",
+ "@ant-design/icons": "^6.0.0",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/preset-react": "^7.26.3",
- "@dotenvx/dotenvx": "^1.33.0",
+ "@dotenvx/dotenvx": "^1.39.0",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/react": "^11.14.0",
- "@eslint/js": "^9.18.0",
- "@sentry/webpack-plugin": "^2.22.4",
- "@testing-library/cypress": "^10.0.2",
+ "@eslint/js": "^9.23.0",
+ "@sentry/webpack-plugin": "^3.2.2",
"browserslist": "^4.24.4",
"browserslist-to-esbuild": "^2.1.1",
"chalk": "^5.4.1",
- "cross-env": "^7.0.3",
- "cypress": "^13.17.0",
"eslint": "^8.57.1",
"eslint-config-react-app": "^7.0.1",
- "eslint-plugin-cypress": "^2.15.1",
"eslint-plugin-react": "^7.37.4",
- "globals": "^15.14.0",
+ "globals": "^15.15.0",
"memfs": "^4.17.0",
"os-browserify": "^0.3.0",
- "react-error-overlay": "6.0.11",
+ "react-error-overlay": "^6.1.0",
"redux-logger": "^3.0.6",
"source-map-explorer": "^2.5.3",
- "vite": "^6.0.7",
+ "vite": "^6.2.3",
"vite-plugin-babel": "^1.3.0",
"vite-plugin-eslint": "^1.8.1",
"vite-plugin-node-polyfills": "^0.23.0",
- "vite-plugin-pwa": "^0.21.1",
+ "vite-plugin-pwa": "^0.21.2",
"vite-plugin-style-import": "^2.0.0",
"workbox-window": "^7.3.0"
},
"engines": {
- "node": ">=18.18.2"
+ "node": ">=22.0.0"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "4.6.1"
@@ -192,16 +192,16 @@
}
},
"node_modules/@ant-design/icons": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.0.tgz",
- "integrity": "sha512-Mb6QkQmPLZsmIHJ6oBsoyKrrT8/kAUdQ6+8q38e2bQSclROi69SiDlI4zZroaIPseae1w110RJH0zGrphAvlSQ==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-6.0.0.tgz",
+ "integrity": "sha512-o0aCCAlHc1o4CQcapAwWzHeaW2x9F49g7P3IDtvtNXgHowtRWYb7kiubt8sQPFvfVIVU/jLw2hzeSlNt0FU+Uw==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@ant-design/colors": "^7.0.0",
+ "@ant-design/colors": "^8.0.0",
"@ant-design/icons-svg": "^4.4.0",
- "@babel/runtime": "^7.24.8",
- "classnames": "^2.2.6",
- "rc-util": "^5.31.1"
+ "@rc-component/util": "^1.2.1",
+ "classnames": "^2.2.6"
},
"engines": {
"node": ">=8"
@@ -217,16 +217,36 @@
"integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==",
"license": "MIT"
},
+ "node_modules/@ant-design/icons/node_modules/@ant-design/colors": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-8.0.0.tgz",
+ "integrity": "sha512-6YzkKCw30EI/E9kHOIXsQDHmMvTllT8STzjMb4K2qzit33RW2pqCJP0sk+hidBntXxE+Vz4n1+RvCTfBw6OErw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ant-design/fast-color": "^3.0.0"
+ }
+ },
+ "node_modules/@ant-design/icons/node_modules/@ant-design/fast-color": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-3.0.0.tgz",
+ "integrity": "sha512-eqvpP7xEDm2S7dUzl5srEQCBTXZMmY3ekf97zI+M2DHOYyKdJGH0qua0JACHTqbkRnD/KHFQP9J1uMJ/XWVzzA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.x"
+ }
+ },
"node_modules/@ant-design/pro-layout": {
- "version": "7.22.1",
- "resolved": "https://registry.npmjs.org/@ant-design/pro-layout/-/pro-layout-7.22.1.tgz",
- "integrity": "sha512-aOwdd/u/yz/0ZHPDpnoVUIDGneZUDw62lCo3C4s6o0SGQrCOkYvY0efG4yLC4RA8eSFvXwnMt5pB7ii7f46KLQ==",
+ "version": "7.22.3",
+ "resolved": "https://registry.npmjs.org/@ant-design/pro-layout/-/pro-layout-7.22.3.tgz",
+ "integrity": "sha512-di/EOMDuoMDRjBweqesYyCxEYr2LCmO82y6A4bSwmmJ6ehxN7HGC73Wx4RuBkzDR7kHLTOXt7WxI6875ENT8mg==",
"license": "MIT",
"dependencies": {
"@ant-design/cssinjs": "^1.21.1",
"@ant-design/icons": "^5.0.0",
"@ant-design/pro-provider": "2.15.3",
- "@ant-design/pro-utils": "2.16.3",
+ "@ant-design/pro-utils": "2.16.4",
"@babel/runtime": "^7.18.0",
"@umijs/route-utils": "^4.0.0",
"@umijs/use-params": "^1.0.9",
@@ -245,6 +265,26 @@
"react-dom": ">=17.0.0"
}
},
+ "node_modules/@ant-design/pro-layout/node_modules/@ant-design/icons": {
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz",
+ "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==",
+ "license": "MIT",
+ "dependencies": {
+ "@ant-design/colors": "^7.0.0",
+ "@ant-design/icons-svg": "^4.4.0",
+ "@babel/runtime": "^7.24.8",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.31.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "peerDependencies": {
+ "react": ">=16.0.0",
+ "react-dom": ">=16.0.0"
+ }
+ },
"node_modules/@ant-design/pro-provider": {
"version": "2.15.3",
"resolved": "https://registry.npmjs.org/@ant-design/pro-provider/-/pro-provider-2.15.3.tgz",
@@ -265,9 +305,9 @@
}
},
"node_modules/@ant-design/pro-utils": {
- "version": "2.16.3",
- "resolved": "https://registry.npmjs.org/@ant-design/pro-utils/-/pro-utils-2.16.3.tgz",
- "integrity": "sha512-uNjKh51v/SUlCJbWfhg2lRQB/TB0MyNMCQkFZ8mZBQ2rk3Ew47Sly6VssVVWMjIWBLE+g9fOgPg0C1IVeilIXA==",
+ "version": "2.16.4",
+ "resolved": "https://registry.npmjs.org/@ant-design/pro-utils/-/pro-utils-2.16.4.tgz",
+ "integrity": "sha512-PFxqF0fsUsLj8ORvJSuMgVv9NDHwAxZaglzPN/u3jZX7rWYcrHD04EMJEXooZaSyT6Q4+j7SqXDx6oBsdb9zNw==",
"license": "MIT",
"dependencies": {
"@ant-design/icons": "^5.0.0",
@@ -287,6 +327,26 @@
"react-dom": ">=17.0.0"
}
},
+ "node_modules/@ant-design/pro-utils/node_modules/@ant-design/icons": {
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz",
+ "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==",
+ "license": "MIT",
+ "dependencies": {
+ "@ant-design/colors": "^7.0.0",
+ "@ant-design/icons-svg": "^4.4.0",
+ "@babel/runtime": "^7.24.8",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.31.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "peerDependencies": {
+ "react": ">=16.0.0",
+ "react-dom": ">=16.0.0"
+ }
+ },
"node_modules/@ant-design/react-slick": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz",
@@ -322,9 +382,9 @@
}
},
"node_modules/@apollo/client": {
- "version": "3.12.8",
- "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.12.8.tgz",
- "integrity": "sha512-053z5eCM7zNl81Lxs/SqHv8e+x3sszrtmGS2TNuPW0ZTZzmKATMsIsoblx1Kt0E67Ze3jb99JSPiQHG9ozGc3g==",
+ "version": "3.13.5",
+ "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.5.tgz",
+ "integrity": "sha512-ceHa1lApLAiGmUur4V+G/CrjwVwHYujfB7U5HM++poCgHpfGn6eet8YGM93fgeWjYX85SaqwdZbQk18IVwhRHg==",
"license": "MIT",
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
@@ -343,7 +403,7 @@
},
"peerDependencies": {
"graphql": "^15.0.0 || ^16.0.0",
- "graphql-ws": "^5.5.5",
+ "graphql-ws": "^5.5.5 || ^6.0.3",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc",
"subscriptions-transport-ws": "^0.9.0 || ^0.11.0"
@@ -2278,9 +2338,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.26.7",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz",
- "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
+ "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
@@ -2343,17 +2403,6 @@
"node": ">=6.9.0"
}
},
- "node_modules/@colors/colors": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
- "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=0.1.90"
- }
- },
"node_modules/@ctrl/tinycolor": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
@@ -2363,71 +2412,10 @@
"node": ">=10"
}
},
- "node_modules/@cypress/request": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz",
- "integrity": "sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "aws-sign2": "~0.7.0",
- "aws4": "^1.8.0",
- "caseless": "~0.12.0",
- "combined-stream": "~1.0.6",
- "extend": "~3.0.2",
- "forever-agent": "~0.6.1",
- "form-data": "~4.0.0",
- "http-signature": "~1.4.0",
- "is-typedarray": "~1.0.0",
- "isstream": "~0.1.2",
- "json-stringify-safe": "~5.0.1",
- "mime-types": "~2.1.19",
- "performance-now": "^2.1.0",
- "qs": "6.13.1",
- "safe-buffer": "^5.1.2",
- "tough-cookie": "^5.0.0",
- "tunnel-agent": "^0.6.0",
- "uuid": "^8.3.2"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/@cypress/request/node_modules/uuid": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
- "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
- "node_modules/@cypress/xvfb": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz",
- "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "debug": "^3.1.0",
- "lodash.once": "^4.1.1"
- }
- },
- "node_modules/@cypress/xvfb/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
"node_modules/@dotenvx/dotenvx": {
- "version": "1.34.0",
- "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.34.0.tgz",
- "integrity": "sha512-+Dp/xaI3IZ4eKv+b2vg4V89VnqLKbmJ7UZ7unnZxMu9SNLOSc2jYaXey1YHCJM+67T0pOr2Gbej3TewnuoqTWQ==",
+ "version": "1.39.0",
+ "resolved": "https://registry.npmjs.org/@dotenvx/dotenvx/-/dotenvx-1.39.0.tgz",
+ "integrity": "sha512-qGfDpL/3S17MQYXpR3HkBS5xNQ7wiFlqLdpr+iIQzv17aMRcSlgL4EjMIsYFZ540Dq17J+y5FVElA1AkVoXiUA==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -2631,9 +2619,9 @@
"license": "MIT"
},
"node_modules/@esbuild/aix-ppc64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz",
- "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz",
+ "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==",
"cpu": [
"ppc64"
],
@@ -2648,9 +2636,9 @@
}
},
"node_modules/@esbuild/android-arm": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz",
- "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz",
+ "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==",
"cpu": [
"arm"
],
@@ -2665,9 +2653,9 @@
}
},
"node_modules/@esbuild/android-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz",
- "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz",
+ "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==",
"cpu": [
"arm64"
],
@@ -2682,9 +2670,9 @@
}
},
"node_modules/@esbuild/android-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz",
- "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz",
+ "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==",
"cpu": [
"x64"
],
@@ -2699,9 +2687,9 @@
}
},
"node_modules/@esbuild/darwin-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz",
- "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz",
+ "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==",
"cpu": [
"arm64"
],
@@ -2716,9 +2704,9 @@
}
},
"node_modules/@esbuild/darwin-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz",
- "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz",
+ "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==",
"cpu": [
"x64"
],
@@ -2733,9 +2721,9 @@
}
},
"node_modules/@esbuild/freebsd-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz",
- "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz",
+ "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==",
"cpu": [
"arm64"
],
@@ -2750,9 +2738,9 @@
}
},
"node_modules/@esbuild/freebsd-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz",
- "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz",
+ "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==",
"cpu": [
"x64"
],
@@ -2767,9 +2755,9 @@
}
},
"node_modules/@esbuild/linux-arm": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz",
- "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz",
+ "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==",
"cpu": [
"arm"
],
@@ -2784,9 +2772,9 @@
}
},
"node_modules/@esbuild/linux-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz",
- "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz",
+ "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==",
"cpu": [
"arm64"
],
@@ -2801,9 +2789,9 @@
}
},
"node_modules/@esbuild/linux-ia32": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz",
- "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz",
+ "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==",
"cpu": [
"ia32"
],
@@ -2818,9 +2806,9 @@
}
},
"node_modules/@esbuild/linux-loong64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz",
- "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz",
+ "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==",
"cpu": [
"loong64"
],
@@ -2835,9 +2823,9 @@
}
},
"node_modules/@esbuild/linux-mips64el": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz",
- "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz",
+ "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==",
"cpu": [
"mips64el"
],
@@ -2852,9 +2840,9 @@
}
},
"node_modules/@esbuild/linux-ppc64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz",
- "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz",
+ "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==",
"cpu": [
"ppc64"
],
@@ -2869,9 +2857,9 @@
}
},
"node_modules/@esbuild/linux-riscv64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz",
- "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz",
+ "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==",
"cpu": [
"riscv64"
],
@@ -2886,9 +2874,9 @@
}
},
"node_modules/@esbuild/linux-s390x": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz",
- "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz",
+ "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==",
"cpu": [
"s390x"
],
@@ -2903,9 +2891,9 @@
}
},
"node_modules/@esbuild/linux-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz",
- "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz",
+ "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==",
"cpu": [
"x64"
],
@@ -2920,9 +2908,9 @@
}
},
"node_modules/@esbuild/netbsd-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz",
- "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz",
+ "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==",
"cpu": [
"arm64"
],
@@ -2937,9 +2925,9 @@
}
},
"node_modules/@esbuild/netbsd-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz",
- "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz",
+ "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==",
"cpu": [
"x64"
],
@@ -2954,9 +2942,9 @@
}
},
"node_modules/@esbuild/openbsd-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz",
- "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz",
+ "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==",
"cpu": [
"arm64"
],
@@ -2971,9 +2959,9 @@
}
},
"node_modules/@esbuild/openbsd-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz",
- "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz",
+ "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==",
"cpu": [
"x64"
],
@@ -2988,9 +2976,9 @@
}
},
"node_modules/@esbuild/sunos-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz",
- "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz",
+ "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==",
"cpu": [
"x64"
],
@@ -3005,9 +2993,9 @@
}
},
"node_modules/@esbuild/win32-arm64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz",
- "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz",
+ "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==",
"cpu": [
"arm64"
],
@@ -3022,9 +3010,9 @@
}
},
"node_modules/@esbuild/win32-ia32": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz",
- "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz",
+ "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==",
"cpu": [
"ia32"
],
@@ -3038,6 +3026,23 @@
"node": ">=18"
}
},
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz",
+ "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
@@ -3141,9 +3146,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.19.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
- "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==",
+ "version": "9.23.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz",
+ "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -3151,139 +3156,59 @@
}
},
"node_modules/@fingerprintjs/fingerprintjs": {
- "version": "4.5.1",
- "resolved": "https://registry.npmjs.org/@fingerprintjs/fingerprintjs/-/fingerprintjs-4.5.1.tgz",
- "integrity": "sha512-hKJaRoLHNeUUPhb+Md3pTlY/Js2YR4aXjroaDHpxrjoM8kGnEFyZVZxXo6l3gRyKnQN52Uoqsycd3M73eCdMzw==",
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/@fingerprintjs/fingerprintjs/-/fingerprintjs-4.6.1.tgz",
+ "integrity": "sha512-62TPnX6fXXMlxS7SOR3DJWEOKab7rCALwSWkuKWYMRrnsZ/jD9Ju4CUyy9VWDUYuhQ2ZW1RGLwOZJXTXR6K1pg==",
"license": "BUSL-1.1",
"dependencies": {
"tslib": "^2.4.1"
}
},
"node_modules/@firebase/analytics": {
- "version": "0.10.8",
- "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.8.tgz",
- "integrity": "sha512-CVnHcS4iRJPqtIDc411+UmFldk0ShSK3OB+D0bKD8Ck5Vro6dbK5+APZpkuWpbfdL359DIQUnAaMLE+zs/PVyA==",
+ "version": "0.10.12",
+ "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.12.tgz",
+ "integrity": "sha512-iDCGnw6qdFqwI5ywkgece99WADJNoymu+nLIQI4fZM/vCZ3bEo4wlpEetW71s1HqGpI0hQStiPhqVjFxDb2yyw==",
"license": "Apache-2.0",
"dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/installations": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
+ "@firebase/component": "0.6.13",
+ "@firebase/installations": "0.6.13",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.11.0",
"tslib": "^2.1.0"
},
"peerDependencies": {
"@firebase/app": "0.x"
}
},
- "node_modules/@firebase/analytics-compat": {
- "version": "0.2.14",
- "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.14.tgz",
- "integrity": "sha512-unRVY6SvRqfNFIAA/kwl4vK+lvQAL2HVcgu9zTrUtTyYDmtIt/lOuHJynBMYEgLnKm39YKBDhtqdapP2e++ASw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/analytics": "0.10.8",
- "@firebase/analytics-types": "0.8.2",
- "@firebase/component": "0.6.9",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/analytics-types": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.2.tgz",
- "integrity": "sha512-EnzNNLh+9/sJsimsA/FGqzakmrAUKLeJvjRHlg8df1f97NLUlFidk9600y0ZgWOp3CAxn6Hjtk+08tixlUOWyw==",
- "license": "Apache-2.0"
- },
"node_modules/@firebase/app": {
- "version": "0.10.13",
- "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.10.13.tgz",
- "integrity": "sha512-OZiDAEK/lDB6xy/XzYAyJJkaDqmQ+BCtOEPLqFvxWKUz5JbBmej7IiiRHdtiIOD/twW7O5AxVsfaaGA/V1bNsA==",
+ "version": "0.11.3",
+ "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.11.3.tgz",
+ "integrity": "sha512-QlTZl/RcqPSonYxB87n8KgAUW2L6ZZz0W4D91PVmQ1tJPsKsKPrWAFHL0ii2cQW6FxTxfNjbZ7kucuIcKXk3tw==",
"license": "Apache-2.0",
"dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
+ "@firebase/component": "0.6.13",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.11.0",
"idb": "7.1.1",
"tslib": "^2.1.0"
- }
- },
- "node_modules/@firebase/app-check": {
- "version": "0.8.8",
- "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.8.8.tgz",
- "integrity": "sha512-O49RGF1xj7k6BuhxGpHmqOW5hqBIAEbt2q6POW0lIywx7emYtzPDeQI+ryQpC4zbKX646SoVZ711TN1DBLNSOQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
},
- "peerDependencies": {
- "@firebase/app": "0.x"
+ "engines": {
+ "node": ">=18.0.0"
}
},
- "node_modules/@firebase/app-check-compat": {
- "version": "0.3.15",
- "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.3.15.tgz",
- "integrity": "sha512-zFIvIFFNqDXpOT2huorz9cwf56VT3oJYRFjSFYdSbGYEJYEaXjLJbfC79lx/zjx4Fh+yuN8pry3TtvwaevrGbg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-check": "0.8.8",
- "@firebase/app-check-types": "0.5.2",
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/app-check-interop-types": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.2.tgz",
- "integrity": "sha512-LMs47Vinv2HBMZi49C09dJxp0QT5LwDzFaVGf/+ITHe3BlIhUiLNttkATSXplc89A2lAaeTqjgqVkiRfUGyQiQ==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/app-check-types": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.2.tgz",
- "integrity": "sha512-FSOEzTzL5bLUbD2co3Zut46iyPWML6xc4x+78TeaXMSuJap5QObfb+rVvZJtla3asN4RwU7elaQaduP+HFizDA==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/app-compat": {
- "version": "0.2.43",
- "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.2.43.tgz",
- "integrity": "sha512-HM96ZyIblXjAC7TzE8wIk2QhHlSvksYkQ4Ukh1GmEenzkucSNUmUX4QvoKrqeWsLEQ8hdcojABeCV8ybVyZmeg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app": "0.10.13",
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- }
- },
- "node_modules/@firebase/app-types": {
- "version": "0.9.2",
- "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.2.tgz",
- "integrity": "sha512-oMEZ1TDlBz479lmABwWsWjzHwheQKiAgnuKxE0pz0IXCVx7/rtlkx1fQ6GfgK24WCrxDKMplZrT50Kh04iMbXQ==",
- "license": "Apache-2.0"
- },
"node_modules/@firebase/auth": {
- "version": "1.7.9",
- "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.7.9.tgz",
- "integrity": "sha512-yLD5095kVgDw965jepMyUrIgDklD6qH/BZNHeKOgvu7pchOKNjVM+zQoOVYJIKWMWOWBq8IRNVU6NXzBbozaJg==",
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.9.1.tgz",
+ "integrity": "sha512-9KKo5SNVkyJzftsW+daS+PGDbeJ+MFJWXQFHDqqPPH3acWHtiNnGHH5HGpIJErEELrsm9xMPie5zfZ0XpGU8+w==",
"license": "Apache-2.0",
"dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0",
- "undici": "6.19.7"
+ "@firebase/component": "0.6.13",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.11.0",
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
},
"peerDependencies": {
"@firebase/app": "0.x",
@@ -3295,431 +3220,107 @@
}
}
},
- "node_modules/@firebase/auth-compat": {
- "version": "0.5.14",
- "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.5.14.tgz",
- "integrity": "sha512-2eczCSqBl1KUPJacZlFpQayvpilg3dxXLy9cSMTKtQMTQSmondUtPI47P3ikH3bQAXhzKLOE+qVxJ3/IRtu9pw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/auth": "1.7.9",
- "@firebase/auth-types": "0.12.2",
- "@firebase/component": "0.6.9",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0",
- "undici": "6.19.7"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/auth-interop-types": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.3.tgz",
- "integrity": "sha512-Fc9wuJGgxoxQeavybiuwgyi+0rssr76b+nHpj+eGhXFYAdudMWyfBHvFL/I5fEHniUM/UQdFzi9VXJK2iZF7FQ==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/auth-types": {
- "version": "0.12.2",
- "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.12.2.tgz",
- "integrity": "sha512-qsEBaRMoGvHO10unlDJhaKSuPn4pyoTtlQuP1ghZfzB6rNQPuhp/N/DcFZxm9i4v0SogjCbf9reWupwIvfmH6w==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@firebase/app-types": "0.x",
- "@firebase/util": "1.x"
- }
- },
"node_modules/@firebase/component": {
- "version": "0.6.9",
- "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.9.tgz",
- "integrity": "sha512-gm8EUEJE/fEac86AvHn8Z/QW8BvR56TBw3hMW0O838J/1mThYQXAIQBgUv75EqlCZfdawpWLrKt1uXvp9ciK3Q==",
+ "version": "0.6.13",
+ "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.13.tgz",
+ "integrity": "sha512-I/Eg1NpAtZ8AAfq8mpdfXnuUpcLxIDdCDtTzWSh+FXnp/9eCKJ3SNbOCKrUCyhLzNa2SiPJYruei0sxVjaOTeg==",
"license": "Apache-2.0",
"dependencies": {
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- }
- },
- "node_modules/@firebase/data-connect": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.1.0.tgz",
- "integrity": "sha512-vSe5s8dY13ilhLnfY0eYRmQsdTbH7PUFZtBbqU6JVX/j8Qp9A6G5gG6//ulbX9/1JFOF1IWNOne9c8S/DOCJaQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/auth-interop-types": "0.2.3",
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
+ "@firebase/util": "1.11.0",
"tslib": "^2.1.0"
},
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/database": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.8.tgz",
- "integrity": "sha512-dzXALZeBI1U5TXt6619cv0+tgEhJiwlUtQ55WNZY7vGAjv7Q1QioV969iYwt1AQQ0ovHnEW0YW9TiBfefLvErg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-check-interop-types": "0.3.2",
- "@firebase/auth-interop-types": "0.2.3",
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
- "faye-websocket": "0.11.4",
- "tslib": "^2.1.0"
- }
- },
- "node_modules/@firebase/database-compat": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-1.0.8.tgz",
- "integrity": "sha512-OpeWZoPE3sGIRPBKYnW9wLad25RaWbGyk7fFQe4xnJQKRzlynWeFBSRRAoLE2Old01WXwskUiucNqUUVlFsceg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/database": "1.0.8",
- "@firebase/database-types": "1.0.5",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- }
- },
- "node_modules/@firebase/database-types": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.5.tgz",
- "integrity": "sha512-fTlqCNwFYyq/C6W7AJ5OCuq5CeZuBEsEwptnVxlNPkWCo5cTTyukzAHRSO/jaQcItz33FfYrrFk1SJofcu2AaQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-types": "0.9.2",
- "@firebase/util": "1.10.0"
+ "engines": {
+ "node": ">=18.0.0"
}
},
"node_modules/@firebase/firestore": {
- "version": "4.7.3",
- "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.3.tgz",
- "integrity": "sha512-NwVU+JPZ/3bhvNSJMCSzfcBZZg8SUGyzZ2T0EW3/bkUeefCyzMISSt/TTIfEHc8cdyXGlMqfGe3/62u9s74UEg==",
+ "version": "4.7.10",
+ "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.7.10.tgz",
+ "integrity": "sha512-6nKsyo2U+jYSCcSE5sjMdDNA23DMUvYPUvsYGg09CNvcTO8GGKsPs7SpOhspsB91mbacq+u627CDAx3FUhPSSQ==",
"license": "Apache-2.0",
"dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
- "@firebase/webchannel-wrapper": "1.0.1",
+ "@firebase/component": "0.6.13",
+ "@firebase/logger": "0.4.4",
+ "@firebase/util": "1.11.0",
+ "@firebase/webchannel-wrapper": "1.0.3",
"@grpc/grpc-js": "~1.9.0",
"@grpc/proto-loader": "^0.7.8",
- "tslib": "^2.1.0",
- "undici": "6.19.7"
- },
- "engines": {
- "node": ">=10.10.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/firestore-compat": {
- "version": "0.3.38",
- "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.3.38.tgz",
- "integrity": "sha512-GoS0bIMMkjpLni6StSwRJarpu2+S5m346Na7gr9YZ/BZ/W3/8iHGNr9PxC+f0rNZXqS4fGRn88pICjrZEgbkqQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/firestore": "4.7.3",
- "@firebase/firestore-types": "3.0.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/firestore-types": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.2.tgz",
- "integrity": "sha512-wp1A+t5rI2Qc/2q7r2ZpjUXkRVPtGMd6zCLsiWurjsQpqPgFin3AhNibKcIzoF2rnToNa/XYtyWXuifjOOwDgg==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@firebase/app-types": "0.x",
- "@firebase/util": "1.x"
- }
- },
- "node_modules/@firebase/functions": {
- "version": "0.11.8",
- "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.11.8.tgz",
- "integrity": "sha512-Lo2rTPDn96naFIlSZKVd1yvRRqqqwiJk7cf9TZhUerwnPKgBzXy+aHE22ry+6EjCaQusUoNai6mU6p+G8QZT1g==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-check-interop-types": "0.3.2",
- "@firebase/auth-interop-types": "0.2.3",
- "@firebase/component": "0.6.9",
- "@firebase/messaging-interop-types": "0.2.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0",
- "undici": "6.19.7"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/functions-compat": {
- "version": "0.3.14",
- "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.3.14.tgz",
- "integrity": "sha512-dZ0PKOKQFnOlMfcim39XzaXonSuPPAVuzpqA4ONTIdyaJK/OnBaIEVs/+BH4faa1a2tLeR+Jy15PKqDRQoNIJw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/functions": "0.11.8",
- "@firebase/functions-types": "0.6.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/functions-types": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.2.tgz",
- "integrity": "sha512-0KiJ9lZ28nS2iJJvimpY4nNccV21rkQyor5Iheu/nq8aKXJqtJdeSlZDspjPSBBiHRzo7/GMUttegnsEITqR+w==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/installations": {
- "version": "0.6.9",
- "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.9.tgz",
- "integrity": "sha512-hlT7AwCiKghOX3XizLxXOsTFiFCQnp/oj86zp1UxwDGmyzsyoxtX+UIZyVyH/oBF5+XtblFG9KZzZQ/h+dpy+Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/util": "1.10.0",
- "idb": "7.1.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/installations-compat": {
- "version": "0.2.9",
- "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.9.tgz",
- "integrity": "sha512-2lfdc6kPXR7WaL4FCQSQUhXcPbI7ol3wF+vkgtU25r77OxPf8F/VmswQ7sgIkBBWtymn5ZF20TIKtnOj9rjb6w==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/installations": "0.6.9",
- "@firebase/installations-types": "0.5.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/installations-types": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.2.tgz",
- "integrity": "sha512-que84TqGRZJpJKHBlF2pkvc1YcXrtEDOVGiDjovP/a3s6W4nlbohGXEsBJo0JCeeg/UG9A+DEZVDUV9GpklUzA==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@firebase/app-types": "0.x"
- }
- },
- "node_modules/@firebase/logger": {
- "version": "0.4.2",
- "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.2.tgz",
- "integrity": "sha512-Q1VuA5M1Gjqrwom6I6NUU4lQXdo9IAQieXlujeHZWvRt1b7qQ0KwBaNAjgxG27jgF9/mUwsNmO8ptBCGVYhB0A==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
- "node_modules/@firebase/messaging": {
- "version": "0.12.12",
- "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.12.tgz",
- "integrity": "sha512-6q0pbzYBJhZEtUoQx7hnPhZvAbuMNuBXKQXOx2YlWhSrlv9N1m0ZzlNpBbu/ItTzrwNKTibdYzUyaaxdWLg+4w==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/installations": "0.6.9",
- "@firebase/messaging-interop-types": "0.2.2",
- "@firebase/util": "1.10.0",
- "idb": "7.1.1",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/messaging-compat": {
- "version": "0.2.12",
- "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.12.tgz",
- "integrity": "sha512-pKsiUVZrbmRgdImYqhBNZlkKJbqjlPkVdQRZGRbkTyX4OSGKR0F/oJeCt1a8jEg5UnBp4fdVwSWSp4DuCovvEQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/messaging": "0.12.12",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/messaging-interop-types": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.2.tgz",
- "integrity": "sha512-l68HXbuD2PPzDUOFb3aG+nZj5KA3INcPwlocwLZOzPp9rFM9yeuI9YLl6DQfguTX5eAGxO0doTR+rDLDvQb5tA==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/performance": {
- "version": "0.6.9",
- "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.6.9.tgz",
- "integrity": "sha512-PnVaak5sqfz5ivhua+HserxTJHtCar/7zM0flCX6NkzBNzJzyzlH4Hs94h2Il0LQB99roBqoE5QT1JqWqcLJHQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/installations": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/performance-compat": {
- "version": "0.2.9",
- "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.9.tgz",
- "integrity": "sha512-dNl95IUnpsu3fAfYBZDCVhXNkASE0uo4HYaEPd2/PKscfTvsgqFAOxfAXzBEDOnynDWiaGUnb5M1O00JQ+3FXA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/performance": "0.6.9",
- "@firebase/performance-types": "0.2.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/performance-types": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.2.tgz",
- "integrity": "sha512-gVq0/lAClVH5STrIdKnHnCo2UcPLjJlDUoEB/tB4KM+hAeHUxWKnpT0nemUPvxZ5nbdY/pybeyMe8Cs29gEcHA==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/remote-config": {
- "version": "0.4.9",
- "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.4.9.tgz",
- "integrity": "sha512-EO1NLCWSPMHdDSRGwZ73kxEEcTopAxX1naqLJFNApp4hO8WfKfmEpmjxmP5TrrnypjIf2tUkYaKsfbEA7+AMmA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/installations": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/remote-config-compat": {
- "version": "0.2.9",
- "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.9.tgz",
- "integrity": "sha512-AxzGpWfWFYejH2twxfdOJt5Cfh/ATHONegTd/a0p5flEzsD5JsxXgfkFToop+mypEL3gNwawxrxlZddmDoNxyA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/remote-config": "0.4.9",
- "@firebase/remote-config-types": "0.3.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/remote-config-types": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.3.2.tgz",
- "integrity": "sha512-0BC4+Ud7y2aPTyhXJTMTFfrGGLqdYXrUB9sJVAB8NiqJswDTc4/2qrE/yfUbnQJhbSi6ZaTTBKyG3n1nplssaA==",
- "license": "Apache-2.0"
- },
- "node_modules/@firebase/storage": {
- "version": "0.13.2",
- "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.13.2.tgz",
- "integrity": "sha512-fxuJnHshbhVwuJ4FuISLu+/76Aby2sh+44ztjF2ppoe0TELIDxPW6/r1KGlWYt//AD0IodDYYA8ZTN89q8YqUw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0",
- "undici": "6.19.7"
- },
- "peerDependencies": {
- "@firebase/app": "0.x"
- }
- },
- "node_modules/@firebase/storage-compat": {
- "version": "0.3.12",
- "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.3.12.tgz",
- "integrity": "sha512-hA4VWKyGU5bWOll+uwzzhEMMYGu9PlKQc1w4DWxB3aIErWYzonrZjF0icqNQZbwKNIdh8SHjZlFeB2w6OSsjfg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/component": "0.6.9",
- "@firebase/storage": "0.13.2",
- "@firebase/storage-types": "0.8.2",
- "@firebase/util": "1.10.0",
- "tslib": "^2.1.0"
- },
- "peerDependencies": {
- "@firebase/app-compat": "0.x"
- }
- },
- "node_modules/@firebase/storage-types": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.2.tgz",
- "integrity": "sha512-0vWu99rdey0g53lA7IShoA2Lol1jfnPovzLDUBuon65K7uKG9G+L5uO05brD9pMw+l4HRFw23ah3GwTGpEav6g==",
- "license": "Apache-2.0",
- "peerDependencies": {
- "@firebase/app-types": "0.x",
- "@firebase/util": "1.x"
- }
- },
- "node_modules/@firebase/util": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.10.0.tgz",
- "integrity": "sha512-xKtx4A668icQqoANRxyDLBLz51TAbDP9KRfpbKGxiCAW346d0BeJe5vN6/hKxxmWwnZ0mautyv39JxviwwQMOQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
- "node_modules/@firebase/vertexai-preview": {
- "version": "0.0.4",
- "resolved": "https://registry.npmjs.org/@firebase/vertexai-preview/-/vertexai-preview-0.0.4.tgz",
- "integrity": "sha512-EBSqyu9eg8frQlVU9/HjKtHN7odqbh9MtAcVz3WwHj4gLCLOoN9F/o+oxlq3CxvFrd3CNTZwu6d2mZtVlEInng==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/app-check-interop-types": "0.3.2",
- "@firebase/component": "0.6.9",
- "@firebase/logger": "0.4.2",
- "@firebase/util": "1.10.0",
"tslib": "^2.1.0"
},
"engines": {
"node": ">=18.0.0"
},
"peerDependencies": {
- "@firebase/app": "0.x",
- "@firebase/app-types": "0.x"
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/installations": {
+ "version": "0.6.13",
+ "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.13.tgz",
+ "integrity": "sha512-6ZpkUiaygPFwgVneYxuuOuHnSPnTA4KefLEaw/sKk/rNYgC7X6twaGfYb0sYLpbi9xV4i5jXsqZ3WO+yaguNgg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.13",
+ "@firebase/util": "1.11.0",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/logger": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.4.4.tgz",
+ "integrity": "sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@firebase/messaging": {
+ "version": "0.12.17",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.17.tgz",
+ "integrity": "sha512-W3CnGhTm6Nx8XGb6E5/+jZTuxX/EK8Vur4QXvO1DwZta/t0xqWMRgO9vNsZFMYBqFV4o3j4F9qK/iddGYwWS6g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@firebase/component": "0.6.13",
+ "@firebase/installations": "0.6.13",
+ "@firebase/messaging-interop-types": "0.2.3",
+ "@firebase/util": "1.11.0",
+ "idb": "7.1.1",
+ "tslib": "^2.1.0"
+ },
+ "peerDependencies": {
+ "@firebase/app": "0.x"
+ }
+ },
+ "node_modules/@firebase/messaging-interop-types": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz",
+ "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@firebase/util": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.11.0.tgz",
+ "integrity": "sha512-PzSrhIr++KI6y4P6C/IdgBNMkEx0Ex6554/cYd0Hm+ovyFSJtJXqb/3OSIdnBoa2cpwZT1/GW56EmRc5qEc5fQ==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
}
},
"node_modules/@firebase/webchannel-wrapper": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.1.tgz",
- "integrity": "sha512-jmEnr/pk0yVkA7mIlHNnxCi+wWzOFUg0WyIotgkKAb2u1J7fAeDBcVNSTjTihbAYNusCLQdW5s9IJ5qwnEufcQ==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz",
+ "integrity": "sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ==",
"license": "Apache-2.0"
},
"node_modules/@graphql-typed-document-node/core": {
@@ -3809,6 +3410,12 @@
"react": "*"
}
},
+ "node_modules/@ioredis/commands": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
+ "integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg==",
+ "license": "MIT"
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
@@ -3931,36 +3538,6 @@
"integrity": "sha512-AAeTkqyVJGdWLCA60aHDrh3s8h9z8TokyoR1tCpNtYatfe2cdocVdB0AaNquWTmddRWgAklmOBrowsMFQFY8hg==",
"license": "MIT"
},
- "node_modules/@ndhoule/each": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@ndhoule/each/-/each-2.0.1.tgz",
- "integrity": "sha512-wHuJw6x+rF6Q9Skgra++KccjBozCr9ymtna0FhxmV/8xT/hZ2ExGYR8SV8prg8x4AH/7mzDYErNGIVHuzHeybw==",
- "license": "MIT",
- "dependencies": {
- "@ndhoule/keys": "^2.0.0"
- }
- },
- "node_modules/@ndhoule/includes": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@ndhoule/includes/-/includes-2.0.1.tgz",
- "integrity": "sha512-Q8zN6f3yIhxgBwZ5ldLozHqJlc/fRQ5+hFFsPMFeC9SJvz0nq8vG9hoRXL1c1iaNFQd7yAZIy2igQpERoFqxqg==",
- "license": "MIT",
- "dependencies": {
- "@ndhoule/each": "^2.0.1"
- }
- },
- "node_modules/@ndhoule/keys": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@ndhoule/keys/-/keys-2.0.0.tgz",
- "integrity": "sha512-vtCqKBC1Av6dsBA8xpAO+cgk051nfaI+PnmTZep2Px0vYrDvpUmLxv7z40COlWH5yCpu3gzNhepk+02yiQiZNw==",
- "license": "MIT"
- },
- "node_modules/@ndhoule/pick": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@ndhoule/pick/-/pick-2.0.0.tgz",
- "integrity": "sha512-xkYtpf1pRd8egwvl5tJcdGu+GBd6ZZH3S/zoIQ9txEI+pHF9oTIlxMC9G4CB3sRugAeLgu8qYJGl3tnxWq74Qw==",
- "license": "MIT"
- },
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
"version": "5.1.1-v1",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
@@ -4594,6 +4171,27 @@
"react-dom": ">=16.9.0"
}
},
+ "node_modules/@rc-component/util": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@rc-component/util/-/util-1.2.1.tgz",
+ "integrity": "sha512-AUVu6jO+lWjQnUOOECwu8iR0EdElQgWW5NBv5vP/Uf9dWbAX3udhMutRlkVXjuac2E40ghkFy+ve00mc/3Fymg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "react-is": "^18.2.0"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
+ "node_modules/@rc-component/util/node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@redux-saga/core": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@redux-saga/core/-/core-1.3.0.tgz",
@@ -4651,9 +4249,9 @@
"license": "MIT"
},
"node_modules/@reduxjs/toolkit": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.5.1.tgz",
- "integrity": "sha512-UHhy3p0oUpdhnSxyDjaRDYaw8Xra75UiLbCiRozVPHjfDwNYkh0TsVm/1OmTW8Md+iDAJmYPWUKMvsMc2GtpNg==",
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.6.1.tgz",
+ "integrity": "sha512-SSlIqZNYhqm/oMkXbtofwZSt9lrncblzo6YcZ9zoX+zLngRBrCOjK4lNLdkNucJF58RHOWrD9txT3bT3piH7Zw==",
"license": "MIT",
"dependencies": {
"immer": "^10.0.3",
@@ -4675,9 +4273,9 @@
}
},
"node_modules/@remix-run/router": {
- "version": "1.22.0",
- "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.22.0.tgz",
- "integrity": "sha512-MBOl8MeOzpK0HQQQshKB7pABXbmyHizdTpqnrIseTbsv0nAepwC2ENZa1aaBExNQcpLoXmWthhak8SABLzvGPw==",
+ "version": "1.23.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
+ "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
@@ -5242,88 +4840,90 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@sentry-internal/feedback": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.120.3.tgz",
- "integrity": "sha512-ewJJIQ0mbsOX6jfiVFvqMjokxNtgP3dNwUv+4nenN+iJJPQsM6a0ocro3iscxwVdbkjw5hY3BUV2ICI5Q0UWoA==",
+ "node_modules/@sentry-internal/browser-utils": {
+ "version": "9.9.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.9.0.tgz",
+ "integrity": "sha512-V/YhKLis98JFkqBGZaEBlDNFpJHJjoCvNb05raAYXdITfDIl37Kxqj0zX+IzyRhqnswkQ+DBTyoEoci09IR2bQ==",
"license": "MIT",
"dependencies": {
- "@sentry/core": "7.120.3",
- "@sentry/types": "7.120.3",
- "@sentry/utils": "7.120.3"
+ "@sentry/core": "9.9.0"
},
"engines": {
- "node": ">=12"
+ "node": ">=18"
+ }
+ },
+ "node_modules/@sentry-internal/feedback": {
+ "version": "9.9.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.9.0.tgz",
+ "integrity": "sha512-hrxuOLm0Xsnx75hTNt3eLgNNjER3egrHZShdRzlMiakfKpA9f2X10z75vlZmT5ZUygDQnp9UVUnu28cDuVb9Zw==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry/core": "9.9.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@sentry-internal/replay": {
+ "version": "9.9.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.9.0.tgz",
+ "integrity": "sha512-EWczKMu3qiZ0SUUWU3zkGod+AWD/VQCLiQw+tw+PEpdHbRZIdYKsEptengZCFKthrwe2QmYpVCTSRxGvujJ/6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@sentry-internal/browser-utils": "9.9.0",
+ "@sentry/core": "9.9.0"
+ },
+ "engines": {
+ "node": ">=18"
}
},
"node_modules/@sentry-internal/replay-canvas": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.120.3.tgz",
- "integrity": "sha512-s5xy+bVL1eDZchM6gmaOiXvTqpAsUfO7122DxVdEDMtwVq3e22bS2aiGa8CUgOiJkulZ+09q73nufM77kOmT/A==",
+ "version": "9.9.0",
+ "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.9.0.tgz",
+ "integrity": "sha512-YK0ixGjquahGpNsQskCEVwycdHlwNBLCx9XJr1BmGnlOw6fUCmpyVetaGg/ZyhkzKGNXAGoTa4s7FUFnAG4bKg==",
"license": "MIT",
"dependencies": {
- "@sentry/core": "7.120.3",
- "@sentry/replay": "7.120.3",
- "@sentry/types": "7.120.3",
- "@sentry/utils": "7.120.3"
+ "@sentry-internal/replay": "9.9.0",
+ "@sentry/core": "9.9.0"
},
"engines": {
- "node": ">=12"
- }
- },
- "node_modules/@sentry-internal/tracing": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.120.3.tgz",
- "integrity": "sha512-Ausx+Jw1pAMbIBHStoQ6ZqDZR60PsCByvHdw/jdH9AqPrNE9xlBSf9EwcycvmrzwyKspSLaB52grlje2cRIUMg==",
- "license": "MIT",
- "dependencies": {
- "@sentry/core": "7.120.3",
- "@sentry/types": "7.120.3",
- "@sentry/utils": "7.120.3"
- },
- "engines": {
- "node": ">=8"
+ "node": ">=18"
}
},
"node_modules/@sentry/babel-plugin-component-annotate": {
- "version": "2.23.0",
- "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.23.0.tgz",
- "integrity": "sha512-+uLqaCKeYmH/W2YUV1XHkFEtpHdx/aFjCQahPVsvXyqg13dfkR6jaygPL4DB5DJtUSmPFCUE3MEk9ZO5JlhJYg==",
- "dev": true,
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.2.tgz",
+ "integrity": "sha512-D+SKQ266ra/wo87s9+UI/rKQi3qhGPCR8eSCDe0VJudhjHsqyNU+JJ5lnIGCgmZaWFTXgdBP/gdr1Iz1zqGs4Q==",
"license": "MIT",
"engines": {
"node": ">= 14"
}
},
"node_modules/@sentry/browser": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.120.3.tgz",
- "integrity": "sha512-i9vGcK9N8zZ/JQo1TCEfHHYZ2miidOvgOABRUc9zQKhYdcYQB2/LU1kqlj77Pxdxf4wOa9137d6rPrSn9iiBxg==",
+ "version": "9.9.0",
+ "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.9.0.tgz",
+ "integrity": "sha512-pIMdkOC+iggZefBs6ck5fL1mBhbLzjdw/8K99iqSeDh+lLvmlHVZajAhPlmw50xfH8CyQ1s22dhcL+zXbg3NKw==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/feedback": "7.120.3",
- "@sentry-internal/replay-canvas": "7.120.3",
- "@sentry-internal/tracing": "7.120.3",
- "@sentry/core": "7.120.3",
- "@sentry/integrations": "7.120.3",
- "@sentry/replay": "7.120.3",
- "@sentry/types": "7.120.3",
- "@sentry/utils": "7.120.3"
+ "@sentry-internal/browser-utils": "9.9.0",
+ "@sentry-internal/feedback": "9.9.0",
+ "@sentry-internal/replay": "9.9.0",
+ "@sentry-internal/replay-canvas": "9.9.0",
+ "@sentry/core": "9.9.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=18"
}
},
"node_modules/@sentry/bundler-plugin-core": {
- "version": "2.23.0",
- "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.23.0.tgz",
- "integrity": "sha512-Qbw+jZFK63w+V193l0eCFKLzGba2Iu93Fx8kCRzZ3uqjky002H8U3pu4mKgcc11J+u8QTjfNZGUyXsxz0jv2mg==",
- "dev": true,
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-3.2.2.tgz",
+ "integrity": "sha512-YGrtmqQ2jMixccX2slVG/Lw7pCGJL3DGB3clmY9mO8QBEBIN3/gEANiHJVWwRidpUOS/0b7yVVGAdwZ87oPwTg==",
"license": "MIT",
"dependencies": {
"@babel/core": "^7.18.5",
- "@sentry/babel-plugin-component-annotate": "2.23.0",
- "@sentry/cli": "2.39.1",
+ "@sentry/babel-plugin-component-annotate": "3.2.2",
+ "@sentry/cli": "2.42.2",
"dotenv": "^16.3.1",
"find-up": "^5.0.0",
"glob": "^9.3.2",
@@ -5335,10 +4935,9 @@
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli": {
- "version": "2.39.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.39.1.tgz",
- "integrity": "sha512-JIb3e9vh0+OmQ0KxmexMXg9oZsR/G7HMwxt5BUIKAXZ9m17Xll4ETXTRnRUBT3sf7EpNGAmlQk1xEmVN9pYZYQ==",
- "dev": true,
+ "version": "2.42.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.42.2.tgz",
+ "integrity": "sha512-spb7S/RUumCGyiSTg8DlrCX4bivCNmU/A1hcfkwuciTFGu8l5CDc2I6jJWWZw8/0enDGxuj5XujgXvU5tr4bxg==",
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -5355,20 +4954,19 @@
"node": ">= 10"
},
"optionalDependencies": {
- "@sentry/cli-darwin": "2.39.1",
- "@sentry/cli-linux-arm": "2.39.1",
- "@sentry/cli-linux-arm64": "2.39.1",
- "@sentry/cli-linux-i686": "2.39.1",
- "@sentry/cli-linux-x64": "2.39.1",
- "@sentry/cli-win32-i686": "2.39.1",
- "@sentry/cli-win32-x64": "2.39.1"
+ "@sentry/cli-darwin": "2.42.2",
+ "@sentry/cli-linux-arm": "2.42.2",
+ "@sentry/cli-linux-arm64": "2.42.2",
+ "@sentry/cli-linux-i686": "2.42.2",
+ "@sentry/cli-linux-x64": "2.42.2",
+ "@sentry/cli-win32-i686": "2.42.2",
+ "@sentry/cli-win32-x64": "2.42.2"
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-darwin": {
- "version": "2.39.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.39.1.tgz",
- "integrity": "sha512-kiNGNSAkg46LNGatfNH5tfsmI/kCAaPA62KQuFZloZiemTNzhy9/6NJP8HZ/GxGs8GDMxic6wNrV9CkVEgFLJQ==",
- "dev": true,
+ "version": "2.42.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.42.2.tgz",
+ "integrity": "sha512-GtJSuxER7Vrp1IpxdUyRZzcckzMnb4N5KTW7sbTwUiwqARRo+wxS+gczYrS8tdgtmXs5XYhzhs+t4d52ITHMIg==",
"license": "BSD-3-Clause",
"optional": true,
"os": [
@@ -5379,13 +4977,12 @@
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm": {
- "version": "2.39.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.39.1.tgz",
- "integrity": "sha512-DkENbxyRxUrfLnJLXTA4s5UL/GoctU5Cm4ER1eB7XN7p9WsamFJd/yf2KpltkjEyiTuplv0yAbdjl1KX3vKmEQ==",
+ "version": "2.42.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.2.tgz",
+ "integrity": "sha512-7udCw+YL9lwq+9eL3WLspvnuG+k5Icg92YE7zsteTzWLwgPVzaxeZD2f8hwhsu+wmL+jNqbpCRmktPteh3i2mg==",
"cpu": [
"arm"
],
- "dev": true,
"license": "BSD-3-Clause",
"optional": true,
"os": [
@@ -5397,13 +4994,12 @@
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm64": {
- "version": "2.39.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.39.1.tgz",
- "integrity": "sha512-5VbVJDatolDrWOgaffsEM7znjs0cR8bHt9Bq0mStM3tBolgAeSDHE89NgHggfZR+DJ2VWOy4vgCwkObrUD6NQw==",
+ "version": "2.42.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.2.tgz",
+ "integrity": "sha512-BOxzI7sgEU5Dhq3o4SblFXdE9zScpz6EXc5Zwr1UDZvzgXZGosUtKVc7d1LmkrHP8Q2o18HcDWtF3WvJRb5Zpw==",
"cpu": [
"arm64"
],
- "dev": true,
"license": "BSD-3-Clause",
"optional": true,
"os": [
@@ -5415,14 +5011,13 @@
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-i686": {
- "version": "2.39.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.39.1.tgz",
- "integrity": "sha512-pXWVoKXCRrY7N8vc9H7mETiV9ZCz+zSnX65JQCzZxgYrayQPJTc+NPRnZTdYdk5RlAupXaFicBI2GwOCRqVRkg==",
+ "version": "2.42.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.2.tgz",
+ "integrity": "sha512-Sw/dQp5ZPvKnq3/y7wIJyxTUJYPGoTX/YeMbDs8BzDlu9to2LWV3K3r7hE7W1Lpbaw4tSquUHiQjP5QHCOS7aQ==",
"cpu": [
"x86",
"ia32"
],
- "dev": true,
"license": "BSD-3-Clause",
"optional": true,
"os": [
@@ -5434,13 +5029,12 @@
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-x64": {
- "version": "2.39.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.39.1.tgz",
- "integrity": "sha512-IwayNZy+it7FWG4M9LayyUmG1a/8kT9+/IEm67sT5+7dkMIMcpmHDqL8rWcPojOXuTKaOBBjkVdNMBTXy0mXlA==",
+ "version": "2.42.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.2.tgz",
+ "integrity": "sha512-mU4zUspAal6TIwlNLBV5oq6yYqiENnCWSxtSQVzWs0Jyq97wtqGNG9U+QrnwjJZ+ta/hvye9fvL2X25D/RxHQw==",
"cpu": [
"x64"
],
- "dev": true,
"license": "BSD-3-Clause",
"optional": true,
"os": [
@@ -5452,14 +5046,13 @@
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-i686": {
- "version": "2.39.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.39.1.tgz",
- "integrity": "sha512-NglnNoqHSmE+Dz/wHeIVRnV2bLMx7tIn3IQ8vXGO5HWA2f8zYJGktbkLq1Lg23PaQmeZLPGlja3gBQfZYSG10Q==",
+ "version": "2.42.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.2.tgz",
+ "integrity": "sha512-iHvFHPGqgJMNqXJoQpqttfsv2GI3cGodeTq4aoVLU/BT3+hXzbV0x1VpvvEhncJkDgDicJpFLM8sEPHb3b8abw==",
"cpu": [
"x86",
"ia32"
],
- "dev": true,
"license": "BSD-3-Clause",
"optional": true,
"os": [
@@ -5470,13 +5063,12 @@
}
},
"node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-x64": {
- "version": "2.39.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.39.1.tgz",
- "integrity": "sha512-xv0R2CMf/X1Fte3cMWie1NXuHmUyQPDBfCyIt6k6RPFPxAYUgcqgMPznYwVMwWEA1W43PaOkSn3d8ZylsDaETw==",
+ "version": "2.42.2",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.2.tgz",
+ "integrity": "sha512-vPPGHjYoaGmfrU7xhfFxG7qlTBacroz5NdT+0FmDn6692D8IvpNXl1K+eV3Kag44ipJBBeR8g1HRJyx/F/9ACw==",
"cpu": [
"x64"
],
- "dev": true,
"license": "BSD-3-Clause",
"optional": true,
"os": [
@@ -5490,14 +5082,12 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true,
"license": "ISC"
},
"node_modules/@sentry/bundler-plugin-core/node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
"license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
@@ -5510,9 +5100,9 @@
}
},
"node_modules/@sentry/cli": {
- "version": "2.41.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.41.1.tgz",
- "integrity": "sha512-0GVmDiTV7R1492wkVY4bGcfC0fSmRmQjuxaaPI8CIV9B2VP9pBVCUizi1mevXaaE4I3fM60LI+XYrKFEneuVog==",
+ "version": "2.42.4",
+ "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.42.4.tgz",
+ "integrity": "sha512-BoSZDAWJiz/40tu6LuMDkSgwk4xTsq6zwqYoUqLU3vKBR/VsaaQGvu6EWxZXORthfZU2/5Agz0+t220cge6VQw==",
"hasInstallScript": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -5529,19 +5119,19 @@
"node": ">= 10"
},
"optionalDependencies": {
- "@sentry/cli-darwin": "2.41.1",
- "@sentry/cli-linux-arm": "2.41.1",
- "@sentry/cli-linux-arm64": "2.41.1",
- "@sentry/cli-linux-i686": "2.41.1",
- "@sentry/cli-linux-x64": "2.41.1",
- "@sentry/cli-win32-i686": "2.41.1",
- "@sentry/cli-win32-x64": "2.41.1"
+ "@sentry/cli-darwin": "2.42.4",
+ "@sentry/cli-linux-arm": "2.42.4",
+ "@sentry/cli-linux-arm64": "2.42.4",
+ "@sentry/cli-linux-i686": "2.42.4",
+ "@sentry/cli-linux-x64": "2.42.4",
+ "@sentry/cli-win32-i686": "2.42.4",
+ "@sentry/cli-win32-x64": "2.42.4"
}
},
"node_modules/@sentry/cli-darwin": {
- "version": "2.41.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.41.1.tgz",
- "integrity": "sha512-7pS3pu/SuhE6jOn3wptstAg6B5nUP878O6s+2svT7b5fKNfYUi/6NPK6dAveh2Ca0rwVq40TO4YFJabWMgTpdQ==",
+ "version": "2.42.4",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.42.4.tgz",
+ "integrity": "sha512-PZV4Y97VDWBR4rIt0HkJfXaBXlebIN2s/FDzC3iHINZE5OG62CDFsnC4/lbGlf2/UZLDaGGIK7mYwSHhTvN+HQ==",
"license": "BSD-3-Clause",
"optional": true,
"os": [
@@ -5552,9 +5142,9 @@
}
},
"node_modules/@sentry/cli-linux-arm": {
- "version": "2.41.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.41.1.tgz",
- "integrity": "sha512-wNUvquD6qjOCczvuBGf9OiD29nuQ6yf8zzfyPJa5Bdx1QXuteKsKb6HBrMwuIR3liyuu0duzHd+H/+p1n541Hg==",
+ "version": "2.42.4",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.4.tgz",
+ "integrity": "sha512-lBn0oeeg62h68/4Eo6zbPq99Idz5t0VRV48rEU/WKeM4MtQCvG/iGGQ3lBFW2yNiUBzXZIK9poXLEcgbwmcRVw==",
"cpu": [
"arm"
],
@@ -5569,9 +5159,9 @@
}
},
"node_modules/@sentry/cli-linux-arm64": {
- "version": "2.41.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.41.1.tgz",
- "integrity": "sha512-EzYCEnnENBnS5kpNW+2dBcrPZn1MVfywh2joGVQZTpmgDL5YFJ59VOd+K0XuEwqgFI8BSNI14KXZ75s4DD1/Vw==",
+ "version": "2.42.4",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.4.tgz",
+ "integrity": "sha512-Ex8vRnryyzC/9e43daEmEqPS+9uirY/l6Hw2lAvhBblFaL7PTWNx52H+8GnYGd9Zy2H3rWNyBDYfHwnErg38zA==",
"cpu": [
"arm64"
],
@@ -5586,9 +5176,9 @@
}
},
"node_modules/@sentry/cli-linux-i686": {
- "version": "2.41.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.41.1.tgz",
- "integrity": "sha512-urpQCWrdYnSAsZY3udttuMV88wTJzKZL10xsrp7sjD/Hd+O6qSLVLkxebIlxts70jMLLFHYrQ2bkRg5kKuX6Fg==",
+ "version": "2.42.4",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.4.tgz",
+ "integrity": "sha512-IBJg0aHjsLCL4LvcFa3cXIjA+4t5kPqBT9y+PoDu4goIFxYD8zl7mbUdGJutvJafTk8Akf4ss4JJXQBjg019zA==",
"cpu": [
"x86",
"ia32"
@@ -5604,9 +5194,9 @@
}
},
"node_modules/@sentry/cli-linux-x64": {
- "version": "2.41.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.41.1.tgz",
- "integrity": "sha512-ZqpYwHXAaK4MMEFlyaLYr6mJTmpy9qP6n30jGhLTW7kHKS3s6GPLCSlNmIfeClrInEt0963fM633ZRnXa04VPw==",
+ "version": "2.42.4",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.4.tgz",
+ "integrity": "sha512-gXI5OEiOSNiAEz7VCE6AZcAgHJ47mlgal3+NmbE8XcHmFOnyDws9FNie6PJAy8KZjXi3nqoBP9JVAbnmOix3uA==",
"cpu": [
"x64"
],
@@ -5621,9 +5211,9 @@
}
},
"node_modules/@sentry/cli-win32-i686": {
- "version": "2.41.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.41.1.tgz",
- "integrity": "sha512-AuRimCeVsx99DIOr9cwdYBHk39tlmAuPDdy2r16iNzY0InXs4xOys4gGzM7N4vlFQvFkzuc778Su0HkfasgprA==",
+ "version": "2.42.4",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.4.tgz",
+ "integrity": "sha512-vZuR3UPHKqOMniyrijrrsNwn9usaRysXq78F6WV0cL0ZyPLAmY+KBnTDSFk1Oig2pURnzaTm+RtcZu2fc8mlzg==",
"cpu": [
"x86",
"ia32"
@@ -5638,9 +5228,9 @@
}
},
"node_modules/@sentry/cli-win32-x64": {
- "version": "2.41.1",
- "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.41.1.tgz",
- "integrity": "sha512-6JcPvXGye61+wPp0xdzfc2YLE/Dcud8JdaK8VxLM3b/8+Em7E+UyliDu3uF8+YGUqizY5JYTd3fs17DC8DZhLw==",
+ "version": "2.42.4",
+ "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.4.tgz",
+ "integrity": "sha512-OIBj3uaQ6nAERSm5Dcf8UIhyElEEwMNsZEEppQpN4IKl0mrwb/57AznM23Dvpu6GR8WGbVQUSolt879YZR5E9g==",
"cpu": [
"x64"
],
@@ -5675,96 +5265,52 @@
}
},
"node_modules/@sentry/core": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.120.3.tgz",
- "integrity": "sha512-vyy11fCGpkGK3qI5DSXOjgIboBZTriw0YDx/0KyX5CjIjDDNgp5AGgpgFkfZyiYiaU2Ww3iFuKo4wHmBusz1uA==",
+ "version": "9.9.0",
+ "resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.9.0.tgz",
+ "integrity": "sha512-GxKvx8PSgoWhLLS+/WBGIXy7rsFcnJBPDqFXIfcAGy89k2j06d9IP0kiIc63qBGStSUkh5FFJLPTakZ5RXiFXA==",
"license": "MIT",
- "dependencies": {
- "@sentry/types": "7.120.3",
- "@sentry/utils": "7.120.3"
- },
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/@sentry/integrations": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.120.3.tgz",
- "integrity": "sha512-6i/lYp0BubHPDTg91/uxHvNui427df9r17SsIEXa2eKDwQ9gW2qRx5IWgvnxs2GV/GfSbwcx4swUB3RfEWrXrQ==",
- "license": "MIT",
- "dependencies": {
- "@sentry/core": "7.120.3",
- "@sentry/types": "7.120.3",
- "@sentry/utils": "7.120.3",
- "localforage": "^1.8.1"
- },
- "engines": {
- "node": ">=8"
+ "node": ">=18"
}
},
"node_modules/@sentry/react": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry/react/-/react-7.120.3.tgz",
- "integrity": "sha512-BcpoK9dwblfb20xwjn/1DRtplvPEXFc3XCRkYSnTfnfZNU8yPOcVX4X2X0I8R+/gsg+MWiFOdEtXJ3FqpJiJ4Q==",
+ "version": "9.9.0",
+ "resolved": "https://registry.npmjs.org/@sentry/react/-/react-9.9.0.tgz",
+ "integrity": "sha512-7BE2Lx5CNtHtlNSS7Z9HxKquohC0xhdFceO3NlMXlx+dZuVCMoQmLISB8SQEcHw+2VO24MvtP3LPEzdeNbkIfg==",
"license": "MIT",
"dependencies": {
- "@sentry/browser": "7.120.3",
- "@sentry/core": "7.120.3",
- "@sentry/types": "7.120.3",
- "@sentry/utils": "7.120.3",
+ "@sentry/browser": "9.9.0",
+ "@sentry/core": "9.9.0",
"hoist-non-react-statics": "^3.3.2"
},
"engines": {
- "node": ">=8"
+ "node": ">=18"
},
"peerDependencies": {
- "react": "15.x || 16.x || 17.x || 18.x"
+ "react": "^16.14.0 || 17.x || 18.x || 19.x"
}
},
- "node_modules/@sentry/replay": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.120.3.tgz",
- "integrity": "sha512-CjVq1fP6bpDiX8VQxudD5MPWwatfXk8EJ2jQhJTcWu/4bCSOQmHxnnmBM+GVn5acKUBCodWHBN+IUZgnJheZSg==",
+ "node_modules/@sentry/vite-plugin": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-3.2.2.tgz",
+ "integrity": "sha512-WSkHOhZszMrIE9zmx2l4JhMnMlZmN/yAoHyf59pwFLIMctuZak6lNPbTbIFkFHDzIJ9Nut5RAVsw1qjmWc1PTA==",
"license": "MIT",
"dependencies": {
- "@sentry-internal/tracing": "7.120.3",
- "@sentry/core": "7.120.3",
- "@sentry/types": "7.120.3",
- "@sentry/utils": "7.120.3"
+ "@sentry/bundler-plugin-core": "3.2.2",
+ "unplugin": "1.0.1"
},
"engines": {
- "node": ">=12"
- }
- },
- "node_modules/@sentry/types": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.120.3.tgz",
- "integrity": "sha512-C4z+3kGWNFJ303FC+FxAd4KkHvxpNFYAFN8iMIgBwJdpIl25KZ8Q/VdGn0MLLUEHNLvjob0+wvwlcRBBNLXOow==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@sentry/utils": {
- "version": "7.120.3",
- "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.120.3.tgz",
- "integrity": "sha512-UDAOQJtJDxZHQ5Nm1olycBIsz2wdGX8SdzyGVHmD8EOQYAeDZQyIlQYohDe9nazdIOQLZCIc3fU0G9gqVLkaGQ==",
- "license": "MIT",
- "dependencies": {
- "@sentry/types": "7.120.3"
- },
- "engines": {
- "node": ">=8"
+ "node": ">= 14"
}
},
"node_modules/@sentry/webpack-plugin": {
- "version": "2.23.0",
- "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-2.23.0.tgz",
- "integrity": "sha512-WxYUbTt/tNfeDm9apeUDXXKs6bEuuVrgYJeCDPDzjGQdmLTsZnbLxcX/b+zr4pceyzZNFEJujk60rRWCjFZY3w==",
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-3.2.2.tgz",
+ "integrity": "sha512-6OkVKNOjKk8P9j7oh6svZ+kEP1i9YIHBC2aGWL2XsgeZTIrMBxJAXtOf+qSrfMAxEtibSroGVOMQc/y3WJTQtg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@sentry/bundler-plugin-core": "2.23.0",
+ "@sentry/bundler-plugin-core": "3.2.2",
"unplugin": "1.0.1",
"uuid": "^9.0.0"
},
@@ -5782,15 +5328,13 @@
"license": "MIT"
},
"node_modules/@splitsoftware/splitio": {
- "version": "10.28.0",
- "resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-10.28.0.tgz",
- "integrity": "sha512-hzBnBZHmUTXvyMBbVTDUYtspLHjyjb/YqKtetNh7pAvkmj37vOXyXfF50Of5jr3Qmvdo0YFbKvMIOEXlXSGWaQ==",
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/@splitsoftware/splitio/-/splitio-11.0.3.tgz",
+ "integrity": "sha512-UtoixGfICCj52FfaVdI186Czw0qCvvEyCw/OtJVTsgM4Zq0k2mY8yKzQ7tSB/HJtzbUVnuPoxkwEcj0479stmg==",
"license": "Apache-2.0",
"dependencies": {
- "@splitsoftware/splitio-commons": "1.17.0",
- "@types/google.analytics": "0.0.40",
- "@types/ioredis": "^4.28.0",
- "bloom-filters": "^3.0.0",
+ "@splitsoftware/splitio-commons": "2.0.2",
+ "bloom-filters": "^3.0.4",
"ioredis": "^4.28.0",
"js-yaml": "^3.13.1",
"node-fetch": "^2.7.0",
@@ -5798,16 +5342,16 @@
"unfetch": "^4.2.0"
},
"engines": {
- "node": ">=6",
- "npm": ">=3"
+ "node": ">=14.0.0"
}
},
"node_modules/@splitsoftware/splitio-commons": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-1.17.0.tgz",
- "integrity": "sha512-rvP+0LGUN92bcTytiqyVxq9UzBG5kTkIYjU7b7AU2awBUYgM0bqT3xhQ9/MJ/2fsBbqC6QIsxoKDOz9pMgbAQw==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.0.2.tgz",
+ "integrity": "sha512-r2m3kwWnSuROT+7zTzhWBrM0DMRBGJNQcTyvXw8zLPPmBs/PnmAnxCy7uRpfMHOGbP9Q3Iju0bU/H5dG8svyiw==",
"license": "Apache-2.0",
"dependencies": {
+ "@types/ioredis": "^4.28.0",
"tslib": "^2.3.1"
},
"peerDependencies": {
@@ -5820,18 +5364,18 @@
}
},
"node_modules/@splitsoftware/splitio-react": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-1.13.0.tgz",
- "integrity": "sha512-P6TZyffkm2/g0QOxmZqAh5NG3mTOfrrfzjLkMl1FSFkRxP/fw3z43seWIQShPGEWWs0y/lRX9NqM93OgcGdS7A==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-react/-/splitio-react-2.0.1.tgz",
+ "integrity": "sha512-Jky3o46w+CO2+x6TN3kzQ4CoASKX4PqtDqSTHY6n5JXBC2CqhlXuvODoMYXKzolOsndku+aL7+Mlavbn7b+2lw==",
"license": "Apache-2.0",
"dependencies": {
- "@splitsoftware/splitio": "10.28.0",
+ "@splitsoftware/splitio": "11.0.3",
"memoize-one": "^5.1.1",
"shallowequal": "^1.1.0",
"tslib": "^2.3.1"
},
"peerDependencies": {
- "react": ">=16.3.0"
+ "react": ">=16.8.0"
}
},
"node_modules/@splitsoftware/splitio-react/node_modules/memoize-one": {
@@ -5877,97 +5421,6 @@
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
- "node_modules/@testing-library/cypress": {
- "version": "10.0.3",
- "resolved": "https://registry.npmjs.org/@testing-library/cypress/-/cypress-10.0.3.tgz",
- "integrity": "sha512-TeZJMCNtiS59cPWalra7LgADuufO5FtbqQBYxuAgdX6ZFAR2D9CtQwAG8VbgvFcchW3K414va/+7P4OkQ80UVg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.14.6",
- "@testing-library/dom": "^10.1.0"
- },
- "engines": {
- "node": ">=12",
- "npm": ">=6"
- },
- "peerDependencies": {
- "cypress": "^12.0.0 || ^13.0.0 || ^14.0.0"
- }
- },
- "node_modules/@testing-library/dom": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
- "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/code-frame": "^7.10.4",
- "@babel/runtime": "^7.12.5",
- "@types/aria-query": "^5.0.1",
- "aria-query": "5.3.0",
- "chalk": "^4.1.0",
- "dom-accessibility-api": "^0.5.9",
- "lz-string": "^1.5.0",
- "pretty-format": "^27.0.2"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@testing-library/dom/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/@testing-library/dom/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/@testing-library/dom/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@types/aria-query": {
- "version": "5.0.4",
- "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
- "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -6009,12 +5462,6 @@
"@babel/types": "^7.20.7"
}
},
- "node_modules/@types/cookie": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
- "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
- "license": "MIT"
- },
"node_modules/@types/d3-array": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
@@ -6113,12 +5560,6 @@
"@types/estree": "*"
}
},
- "node_modules/@types/google.analytics": {
- "version": "0.0.40",
- "resolved": "https://registry.npmjs.org/@types/google.analytics/-/google.analytics-0.0.40.tgz",
- "integrity": "sha512-R3HpnLkqmKxhUAf8kIVvDVGJqPtaaZlW4yowNwjOZUTmYUQEgHh8Nh5wkSXKMroNAuQM8gbXJHmNbbgA8tdb7Q==",
- "license": "MIT"
- },
"node_modules/@types/hast": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
@@ -6221,20 +5662,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/@types/sinonjs__fake-timers": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz",
- "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/sizzle": {
- "version": "2.3.9",
- "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz",
- "integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/stylis": {
"version": "4.2.5",
"resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz",
@@ -6266,17 +5693,6 @@
"integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==",
"license": "MIT"
},
- "node_modules/@types/yauzl": {
- "version": "2.10.3",
- "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz",
- "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==",
- "dev": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@types/node": "*"
- }
- },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.62.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
@@ -6648,7 +6064,6 @@
"version": "8.14.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
"integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
- "dev": true,
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -6679,20 +6094,6 @@
"node": ">= 6.0.0"
}
},
- "node_modules/aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -6710,32 +6111,6 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/ansi-colors": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
- "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/ansi-escapes": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
- "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.21.3"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -6745,30 +6120,17 @@
"node": ">=8"
}
},
- "node_modules/ansi-styles": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
- "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
"node_modules/antd": {
- "version": "5.23.3",
- "resolved": "https://registry.npmjs.org/antd/-/antd-5.23.3.tgz",
- "integrity": "sha512-xDvwl7C43/NZ9rTOS1bkbuKoSxqZKf6FlaSW/BRsV8QST3Ce2jGx7dJzYahKIZwe3WNSgvEXAlTrckBHMKHcgQ==",
+ "version": "5.24.5",
+ "resolved": "https://registry.npmjs.org/antd/-/antd-5.24.5.tgz",
+ "integrity": "sha512-1lAv/G+9ewQanyoAo3JumQmIlVxwo5QwWGb6QCHYc40Cq0NxC/EzITcjsgq1PSaTUpLkKq8A2l7Fjtu47vqQBg==",
"license": "MIT",
"dependencies": {
"@ant-design/colors": "^7.2.0",
"@ant-design/cssinjs": "^1.23.0",
"@ant-design/cssinjs-utils": "^1.1.3",
"@ant-design/fast-color": "^2.0.6",
- "@ant-design/icons": "^5.6.0",
+ "@ant-design/icons": "^5.6.1",
"@ant-design/react-slick": "~1.1.2",
"@babel/runtime": "^7.26.0",
"@rc-component/color-picker": "~2.0.1",
@@ -6779,38 +6141,38 @@
"classnames": "^2.5.1",
"copy-to-clipboard": "^3.3.3",
"dayjs": "^1.11.11",
- "rc-cascader": "~3.33.0",
+ "rc-cascader": "~3.33.1",
"rc-checkbox": "~3.5.0",
"rc-collapse": "~3.9.0",
"rc-dialog": "~9.6.0",
"rc-drawer": "~7.2.0",
"rc-dropdown": "~4.2.1",
"rc-field-form": "~2.7.0",
- "rc-image": "~7.11.0",
- "rc-input": "~1.7.2",
+ "rc-image": "~7.11.1",
+ "rc-input": "~1.7.3",
"rc-input-number": "~9.4.0",
"rc-mentions": "~2.19.1",
- "rc-menu": "~9.16.0",
+ "rc-menu": "~9.16.1",
"rc-motion": "^2.9.5",
- "rc-notification": "~5.6.2",
- "rc-pagination": "~5.0.0",
- "rc-picker": "~4.9.2",
+ "rc-notification": "~5.6.3",
+ "rc-pagination": "~5.1.0",
+ "rc-picker": "~4.11.3",
"rc-progress": "~4.0.0",
- "rc-rate": "~2.13.0",
+ "rc-rate": "~2.13.1",
"rc-resize-observer": "^1.4.3",
"rc-segmented": "~2.7.0",
"rc-select": "~14.16.6",
"rc-slider": "~11.1.8",
"rc-steps": "~6.0.1",
"rc-switch": "~4.1.0",
- "rc-table": "~7.50.2",
- "rc-tabs": "~15.5.0",
+ "rc-table": "~7.50.4",
+ "rc-tabs": "~15.5.1",
"rc-textarea": "~1.9.0",
- "rc-tooltip": "~6.3.2",
- "rc-tree": "~5.13.0",
+ "rc-tooltip": "~6.4.0",
+ "rc-tree": "~5.13.1",
"rc-tree-select": "~5.27.0",
"rc-upload": "~4.8.1",
- "rc-util": "^5.44.3",
+ "rc-util": "^5.44.4",
"scroll-into-view-if-needed": "^3.1.0",
"throttle-debounce": "^5.0.2"
},
@@ -6823,11 +6185,30 @@
"react-dom": ">=16.9.0"
}
},
+ "node_modules/antd/node_modules/@ant-design/icons": {
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz",
+ "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==",
+ "license": "MIT",
+ "dependencies": {
+ "@ant-design/colors": "^7.0.0",
+ "@ant-design/icons-svg": "^4.4.0",
+ "@babel/runtime": "^7.24.8",
+ "classnames": "^2.2.6",
+ "rc-util": "^5.31.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "peerDependencies": {
+ "react": ">=16.0.0",
+ "react-dom": ">=16.0.0"
+ }
+ },
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
"license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
@@ -6841,7 +6222,6 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -6864,43 +6244,22 @@
}
},
"node_modules/apollo-link-sentry": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/apollo-link-sentry/-/apollo-link-sentry-3.3.0.tgz",
- "integrity": "sha512-wLffWmo5sRw3rHN1Ck6azM0oxObvtaBBf3AC8cLX4SxhyjmkRIagGDji6CFkyAhxupPz0b9/H1u4Ocx+63lNug==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/apollo-link-sentry/-/apollo-link-sentry-4.2.0.tgz",
+ "integrity": "sha512-w8EUM4aEw1/VxIB3KOP11T8qz44oWRcbXRd2vJq/qHnfRMKS5HkMerSIYwKN2e8k9H8ubfkwBvStH51CVf4wwg==",
"license": "MIT",
"dependencies": {
"deepmerge": "^4.2.2",
- "dot-prop": "^6.0.0",
+ "dot-prop": "^6",
"tslib": "^2.0.3",
"zen-observable-ts": "^1.2.5"
},
"peerDependencies": {
"@apollo/client": "^3.2.3",
- "@sentry/browser": "^7.41.0",
- "graphql": "15 - 16"
+ "@sentry/core": "^8.33 || ^9",
+ "graphql": "^15 || ^16"
}
},
- "node_modules/arch": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
- "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
"node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -6910,16 +6269,6 @@
"sprintf-js": "~1.0.2"
}
},
- "node_modules/aria-query": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
- "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "dequal": "^2.0.3"
- }
- },
"node_modules/array-buffer-byte-length": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
@@ -7087,16 +6436,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/asn1": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
- "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "safer-buffer": "~2.1.0"
- }
- },
"node_modules/asn1.js": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
@@ -7130,16 +6469,6 @@
"util": "^0.12.5"
}
},
- "node_modules/assert-plus": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
- "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8"
- }
- },
"node_modules/ast-types-flow": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
@@ -7147,16 +6476,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/astral-regex": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
- "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/async": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
@@ -7211,23 +6530,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/aws-sign2": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
- "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/aws4": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
- "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/axe-core": {
"version": "4.10.2",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz",
@@ -7239,9 +6541,9 @@
}
},
"node_modules/axios": {
- "version": "1.7.9",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
- "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
+ "version": "1.8.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
+ "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
@@ -7417,16 +6719,6 @@
],
"license": "MIT"
},
- "node_modules/bcrypt-pbkdf": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
- "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "tweetnacl": "^0.14.3"
- }
- },
"node_modules/big-integer": {
"version": "1.6.52",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
@@ -7440,7 +6732,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -7449,13 +6740,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/blob-util": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz",
- "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==",
- "dev": true,
- "license": "Apache-2.0"
- },
"node_modules/bloom-filters": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/bloom-filters/-/bloom-filters-3.0.4.tgz",
@@ -7475,13 +6759,6 @@
"node": ">=12"
}
},
- "node_modules/bluebird": {
- "version": "3.7.2",
- "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
- "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/bn.js": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
@@ -7503,7 +6780,6 @@
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
@@ -7768,16 +7044,6 @@
"ieee754": "^1.1.13"
}
},
- "node_modules/buffer-crc32": {
- "version": "0.2.13",
- "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
- "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
@@ -7799,16 +7065,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/cachedir": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz",
- "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
@@ -7921,13 +7177,6 @@
"upper-case-first": "^2.0.2"
}
},
- "node_modules/caseless": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
- "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
- "dev": true,
- "license": "Apache-2.0"
- },
"node_modules/ccount": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
@@ -8012,16 +7261,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/check-more-types": {
- "version": "2.24.0",
- "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
- "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8.0"
- }
- },
"node_modules/chokidar": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
@@ -8037,22 +7276,6 @@
"url": "https://paulmillr.com/funding/"
}
},
- "node_modules/ci-info": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz",
- "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/cipher-base": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz",
@@ -8073,62 +7296,6 @@
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==",
"license": "MIT"
},
- "node_modules/clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/cli-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
- "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "restore-cursor": "^3.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cli-table3": {
- "version": "0.6.5",
- "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz",
- "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "string-width": "^4.2.0"
- },
- "engines": {
- "node": "10.* || >= 12.*"
- },
- "optionalDependencies": {
- "@colors/colors": "1.5.0"
- }
- },
- "node_modules/cli-truncate": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
- "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "slice-ansi": "^3.0.0",
- "string-width": "^4.2.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@@ -8179,13 +7346,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
- "node_modules/colorette": {
- "version": "2.0.20",
- "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
- "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -8228,11 +7388,6 @@
"node": ">=4.0.0"
}
},
- "node_modules/component-indexof": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz",
- "integrity": "sha512-puDQKvx/64HZXb4hBwIcvQLaLgux8o1CbWl39s41hrIIZDl1lJiD5jc22gj3RBeGK0ovxALDYpIbyjqDUUl0rw=="
- },
"node_modules/compute-scroll-into-view": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz",
@@ -8292,12 +7447,12 @@
"license": "MIT"
},
"node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz",
+ "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==",
"license": "MIT",
"engines": {
- "node": ">= 0.6"
+ "node": ">=18"
}
},
"node_modules/copy-to-clipboard": {
@@ -8409,25 +7564,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/cross-env": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
- "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.1"
- },
- "bin": {
- "cross-env": "src/bin/cross-env.js",
- "cross-env-shell": "src/bin/cross-env-shell.js"
- },
- "engines": {
- "node": ">=10.14",
- "npm": ">=6",
- "yarn": ">=1"
- }
- },
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -8541,191 +7677,6 @@
"integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==",
"license": "MIT"
},
- "node_modules/cypress": {
- "version": "13.17.0",
- "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.17.0.tgz",
- "integrity": "sha512-5xWkaPurwkIljojFidhw8lFScyxhtiFHl/i/3zov+1Z5CmY4t9tjIdvSXfu82Y3w7wt0uR9KkucbhkVvJZLQSA==",
- "dev": true,
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "@cypress/request": "^3.0.6",
- "@cypress/xvfb": "^1.2.4",
- "@types/sinonjs__fake-timers": "8.1.1",
- "@types/sizzle": "^2.3.2",
- "arch": "^2.2.0",
- "blob-util": "^2.0.2",
- "bluebird": "^3.7.2",
- "buffer": "^5.7.1",
- "cachedir": "^2.3.0",
- "chalk": "^4.1.0",
- "check-more-types": "^2.24.0",
- "ci-info": "^4.0.0",
- "cli-cursor": "^3.1.0",
- "cli-table3": "~0.6.1",
- "commander": "^6.2.1",
- "common-tags": "^1.8.0",
- "dayjs": "^1.10.4",
- "debug": "^4.3.4",
- "enquirer": "^2.3.6",
- "eventemitter2": "6.4.7",
- "execa": "4.1.0",
- "executable": "^4.1.1",
- "extract-zip": "2.0.1",
- "figures": "^3.2.0",
- "fs-extra": "^9.1.0",
- "getos": "^3.2.1",
- "is-installed-globally": "~0.4.0",
- "lazy-ass": "^1.6.0",
- "listr2": "^3.8.3",
- "lodash": "^4.17.21",
- "log-symbols": "^4.0.0",
- "minimist": "^1.2.8",
- "ospath": "^1.2.2",
- "pretty-bytes": "^5.6.0",
- "process": "^0.11.10",
- "proxy-from-env": "1.0.0",
- "request-progress": "^3.0.0",
- "semver": "^7.5.3",
- "supports-color": "^8.1.1",
- "tmp": "~0.2.3",
- "tree-kill": "1.2.2",
- "untildify": "^4.0.0",
- "yauzl": "^2.10.0"
- },
- "bin": {
- "cypress": "bin/cypress"
- },
- "engines": {
- "node": "^16.0.0 || ^18.0.0 || >=20.0.0"
- }
- },
- "node_modules/cypress/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/cypress/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/cypress/node_modules/chalk/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cypress/node_modules/commander": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
- "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/cypress/node_modules/execa": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
- "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cross-spawn": "^7.0.0",
- "get-stream": "^5.0.0",
- "human-signals": "^1.1.1",
- "is-stream": "^2.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^4.0.0",
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2",
- "strip-final-newline": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
- }
- },
- "node_modules/cypress/node_modules/get-stream": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
- "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pump": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/cypress/node_modules/human-signals": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
- "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8.12.0"
- }
- },
- "node_modules/cypress/node_modules/proxy-from-env": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
- "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/cypress/node_modules/semver": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.0.tgz",
- "integrity": "sha512-DrfFnPzblFmNrIZzg5RzHegbiRWg7KMR7btwi2yjHwx06zsUbO5g613sVwEV7FTwmzJu+Io0lJe2GJ3LxqpvBQ==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/d3-array": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
@@ -8854,19 +7805,6 @@
"dev": true,
"license": "BSD-2-Clause"
},
- "node_modules/dashdash": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
- "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assert-plus": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
"node_modules/data-view-buffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
@@ -8934,9 +7872,9 @@
"license": "MIT"
},
"node_modules/dayjs-business-days2": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/dayjs-business-days2/-/dayjs-business-days2-1.2.3.tgz",
- "integrity": "sha512-xNT6cjlERxb2zAByQ+60BIQmI+Jn3q333mUF6+2wImSwC2m6XZmNI9Yj+8EKgKJ0TdRk5Z0EaAp7I0hSy76jGw==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/dayjs-business-days2/-/dayjs-business-days2-1.3.0.tgz",
+ "integrity": "sha512-OgDBnsNmlk9+vmRQaP4yFisXs29WDk0ItUUctIagmO6OIoxhf4vArTov5i+G4vjT9Sz8NXOLMLrOVP0X0lG/Hw==",
"license": "MIT",
"dependencies": {
"dayjs": "^1.11.13"
@@ -9170,13 +8108,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/dom-accessibility-api": {
- "version": "0.5.16",
- "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
- "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
@@ -9260,17 +8191,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/ecc-jsbn": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
- "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.1.0"
- }
- },
"node_modules/eciesjs": {
"version": "0.4.13",
"resolved": "https://registry.npmjs.org/eciesjs/-/eciesjs-0.4.13.tgz",
@@ -9340,16 +8260,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/end-of-stream": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
- "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
"node_modules/engine.io-client": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
@@ -9389,20 +8299,6 @@
"node": ">=10.0.0"
}
},
- "node_modules/enquirer": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
- "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-colors": "^4.1.1",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
"node_modules/env-cmd": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/env-cmd/-/env-cmd-10.1.0.tgz",
@@ -9617,9 +8513,9 @@
}
},
"node_modules/esbuild": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz",
- "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==",
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
+ "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -9630,48 +8526,31 @@
"node": ">=18"
},
"optionalDependencies": {
- "@esbuild/aix-ppc64": "0.24.2",
- "@esbuild/android-arm": "0.24.2",
- "@esbuild/android-arm64": "0.24.2",
- "@esbuild/android-x64": "0.24.2",
- "@esbuild/darwin-arm64": "0.24.2",
- "@esbuild/darwin-x64": "0.24.2",
- "@esbuild/freebsd-arm64": "0.24.2",
- "@esbuild/freebsd-x64": "0.24.2",
- "@esbuild/linux-arm": "0.24.2",
- "@esbuild/linux-arm64": "0.24.2",
- "@esbuild/linux-ia32": "0.24.2",
- "@esbuild/linux-loong64": "0.24.2",
- "@esbuild/linux-mips64el": "0.24.2",
- "@esbuild/linux-ppc64": "0.24.2",
- "@esbuild/linux-riscv64": "0.24.2",
- "@esbuild/linux-s390x": "0.24.2",
- "@esbuild/linux-x64": "0.24.2",
- "@esbuild/netbsd-arm64": "0.24.2",
- "@esbuild/netbsd-x64": "0.24.2",
- "@esbuild/openbsd-arm64": "0.24.2",
- "@esbuild/openbsd-x64": "0.24.2",
- "@esbuild/sunos-x64": "0.24.2",
- "@esbuild/win32-arm64": "0.24.2",
- "@esbuild/win32-ia32": "0.24.2",
- "@esbuild/win32-x64": "0.24.2"
- }
- },
- "node_modules/esbuild/node_modules/@esbuild/win32-x64": {
- "version": "0.24.2",
- "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz",
- "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">=18"
+ "@esbuild/aix-ppc64": "0.25.0",
+ "@esbuild/android-arm": "0.25.0",
+ "@esbuild/android-arm64": "0.25.0",
+ "@esbuild/android-x64": "0.25.0",
+ "@esbuild/darwin-arm64": "0.25.0",
+ "@esbuild/darwin-x64": "0.25.0",
+ "@esbuild/freebsd-arm64": "0.25.0",
+ "@esbuild/freebsd-x64": "0.25.0",
+ "@esbuild/linux-arm": "0.25.0",
+ "@esbuild/linux-arm64": "0.25.0",
+ "@esbuild/linux-ia32": "0.25.0",
+ "@esbuild/linux-loong64": "0.25.0",
+ "@esbuild/linux-mips64el": "0.25.0",
+ "@esbuild/linux-ppc64": "0.25.0",
+ "@esbuild/linux-riscv64": "0.25.0",
+ "@esbuild/linux-s390x": "0.25.0",
+ "@esbuild/linux-x64": "0.25.0",
+ "@esbuild/netbsd-arm64": "0.25.0",
+ "@esbuild/netbsd-x64": "0.25.0",
+ "@esbuild/openbsd-arm64": "0.25.0",
+ "@esbuild/openbsd-x64": "0.25.0",
+ "@esbuild/sunos-x64": "0.25.0",
+ "@esbuild/win32-arm64": "0.25.0",
+ "@esbuild/win32-ia32": "0.25.0",
+ "@esbuild/win32-x64": "0.25.0"
}
},
"node_modules/escalade": {
@@ -9839,48 +8718,6 @@
"ms": "^2.1.1"
}
},
- "node_modules/eslint-plugin-cypress": {
- "version": "2.15.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.15.2.tgz",
- "integrity": "sha512-CtcFEQTDKyftpI22FVGpx8bkpKyYXBlNge6zSo0pl5/qJvBAnzaD76Vu2AsP16d6mTj478Ldn2mhgrWV+Xr0vQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "globals": "^13.20.0"
- },
- "peerDependencies": {
- "eslint": ">= 3.2.1"
- }
- },
- "node_modules/eslint-plugin-cypress/node_modules/globals": {
- "version": "13.24.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
- "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "type-fest": "^0.20.2"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint-plugin-cypress/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/eslint-plugin-flowtype": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz",
@@ -10345,13 +9182,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/eventemitter2": {
- "version": "6.4.7",
- "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz",
- "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
@@ -10403,19 +9233,6 @@
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
- "node_modules/executable": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz",
- "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pify": "^2.2.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
@@ -10434,53 +9251,6 @@
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
- "node_modules/extract-zip": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
- "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "debug": "^4.1.1",
- "get-stream": "^5.1.0",
- "yauzl": "^2.10.0"
- },
- "bin": {
- "extract-zip": "cli.js"
- },
- "engines": {
- "node": ">= 10.17.0"
- },
- "optionalDependencies": {
- "@types/yauzl": "^2.9.1"
- }
- },
- "node_modules/extract-zip/node_modules/get-stream": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
- "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pump": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/extsprintf": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
- "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
- "dev": true,
- "engines": [
- "node >=0.6.0"
- ],
- "license": "MIT"
- },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -10568,28 +9338,6 @@
"reusify": "^1.0.4"
}
},
- "node_modules/faye-websocket": {
- "version": "0.11.4",
- "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
- "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
- "license": "Apache-2.0",
- "dependencies": {
- "websocket-driver": ">=0.5.1"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/fd-slicer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
- "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pend": "~1.2.0"
- }
- },
"node_modules/fdir": {
"version": "6.4.3",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz",
@@ -10605,32 +9353,6 @@
}
}
},
- "node_modules/figures": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
- "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "escape-string-regexp": "^1.0.5"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/figures/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -10678,7 +9400,6 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
@@ -10710,7 +9431,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
"license": "MIT",
"dependencies": {
"locate-path": "^6.0.0",
@@ -10723,42 +9443,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/firebase": {
- "version": "10.14.1",
- "resolved": "https://registry.npmjs.org/firebase/-/firebase-10.14.1.tgz",
- "integrity": "sha512-0KZxU+Ela9rUCULqFsUUOYYkjh7OM1EWdIfG6///MtXd0t2/uUIf0iNV5i0KariMhRQ5jve/OY985nrAXFaZeQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@firebase/analytics": "0.10.8",
- "@firebase/analytics-compat": "0.2.14",
- "@firebase/app": "0.10.13",
- "@firebase/app-check": "0.8.8",
- "@firebase/app-check-compat": "0.3.15",
- "@firebase/app-compat": "0.2.43",
- "@firebase/app-types": "0.9.2",
- "@firebase/auth": "1.7.9",
- "@firebase/auth-compat": "0.5.14",
- "@firebase/data-connect": "0.1.0",
- "@firebase/database": "1.0.8",
- "@firebase/database-compat": "1.0.8",
- "@firebase/firestore": "4.7.3",
- "@firebase/firestore-compat": "0.3.38",
- "@firebase/functions": "0.11.8",
- "@firebase/functions-compat": "0.3.14",
- "@firebase/installations": "0.6.9",
- "@firebase/installations-compat": "0.2.9",
- "@firebase/messaging": "0.12.12",
- "@firebase/messaging-compat": "0.2.12",
- "@firebase/performance": "0.6.9",
- "@firebase/performance-compat": "0.2.9",
- "@firebase/remote-config": "0.4.9",
- "@firebase/remote-config-compat": "0.2.9",
- "@firebase/storage": "0.13.2",
- "@firebase/storage-compat": "0.3.12",
- "@firebase/util": "1.10.0",
- "@firebase/vertexai-preview": "0.0.4"
- }
- },
"node_modules/flat-cache": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
@@ -10817,16 +9501,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/forever-agent": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
- "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "*"
- }
- },
"node_modules/form-data": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
@@ -10867,7 +9541,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -11014,31 +9687,10 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/getos": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz",
- "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "async": "^3.2.0"
- }
- },
- "node_modules/getpass": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
- "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assert-plus": "^1.0.0"
- }
- },
"node_modules/glob": {
"version": "9.3.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz",
"integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==",
- "dev": true,
"license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
@@ -11070,7 +9722,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
@@ -11080,7 +9731,6 @@
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz",
"integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==",
- "dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
@@ -11092,31 +9742,15 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/global-dirs": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz",
- "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ini": "2.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/globalize": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/globalize/-/globalize-0.1.1.tgz",
"integrity": "sha512-5e01v8eLGfuQSOvx2MsDMOWS0GFtCx1wPzQSmcHw4hkxFzrQDBO3Xwg/m8Hr/7qXMrHeOIE29qWVzyv06u1TZA=="
},
"node_modules/globals": {
- "version": "15.14.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
- "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -11440,27 +10074,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/http-parser-js": {
- "version": "0.5.9",
- "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz",
- "integrity": "sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==",
- "license": "MIT"
- },
- "node_modules/http-signature": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz",
- "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "assert-plus": "^1.0.0",
- "jsprim": "^2.0.2",
- "sshpk": "^1.18.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
"node_modules/https-browserify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
@@ -11502,9 +10115,9 @@
}
},
"node_modules/i18next": {
- "version": "23.16.8",
- "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz",
- "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==",
+ "version": "24.2.3",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.2.3.tgz",
+ "integrity": "sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==",
"funding": [
{
"type": "individual",
@@ -11521,13 +10134,21 @@
],
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.23.2"
+ "@babel/runtime": "^7.26.10"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
}
},
"node_modules/i18next-browser-languagedetector": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.2.tgz",
- "integrity": "sha512-shBvPmnIyZeD2VU5jVGIOWP7u9qNG3Lj7mpaiPFpbJ3LVfHZJvVzKR4v1Cb91wAOFpNw442N+LGPzHOHsten2g==",
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.0.4.tgz",
+ "integrity": "sha512-f3frU3pIxD50/Tz20zx9TD9HobKYg47fmAETb117GKGPrhwcSSPJDoCposXlVycVebQ9GQohC3Efbpq7/nnJ5w==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.23.2"
@@ -11570,12 +10191,6 @@
"node": ">= 4"
}
},
- "node_modules/immediate": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
- "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
- "license": "MIT"
- },
"node_modules/immer": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz",
@@ -11625,16 +10240,6 @@
"node": ">=0.8.19"
}
},
- "node_modules/indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -11652,16 +10257,6 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
- "node_modules/ini": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
- "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/inline-style-parser": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz",
@@ -11702,11 +10297,12 @@
}
},
"node_modules/ioredis": {
- "version": "4.28.5",
- "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.28.5.tgz",
- "integrity": "sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A==",
+ "version": "4.29.1",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.29.1.tgz",
+ "integrity": "sha512-iq4u3AC9h9/P/gBXH1cUR7Ln0exKexqMaYDwUaoZJzkvvgJs9W5+CLQFS0APyG8uyvJJjn6q6Vx7LwmZQu3h5A==",
"license": "MIT",
"dependencies": {
+ "@ioredis/commands": "^1.0.2",
"cluster-key-slot": "^1.1.0",
"debug": "^4.3.1",
"denque": "^1.1.0",
@@ -11714,7 +10310,6 @@
"lodash.flatten": "^4.4.0",
"lodash.isarguments": "^3.1.0",
"p-map": "^2.1.0",
- "redis-commands": "1.7.0",
"redis-errors": "^1.2.0",
"redis-parser": "^3.0.0",
"standard-as-callback": "^2.1.0"
@@ -11727,15 +10322,6 @@
"url": "https://opencollective.com/ioredis"
}
},
- "node_modules/is": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/is/-/is-3.3.0.tgz",
- "integrity": "sha512-nW24QBoPcFGGHJGUwnfpI7Yc5CdqWNdsyHQszVE/z2pKHXzh7FZ5GWhJqSyaQ9wMkQnsTx+kAI8bHlCX4tKdbg==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
"node_modules/is-alphabetical": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
@@ -11842,7 +10428,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
@@ -11985,7 +10570,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -12039,7 +10623,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
@@ -12058,23 +10641,6 @@
"url": "https://github.com/sponsors/wooorm"
}
},
- "node_modules/is-installed-globally": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
- "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "global-dirs": "^3.0.0",
- "is-path-inside": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
@@ -12116,7 +10682,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "devOptional": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
@@ -12292,26 +10857,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-typedarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/is-unicode-supported": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
- "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/is-weakmap": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
@@ -12398,13 +10943,6 @@
"node": ">=10"
}
},
- "node_modules/isstream": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
- "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/iterall": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz",
@@ -12515,13 +11053,6 @@
"js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/jsbn": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
- "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
@@ -12569,13 +11100,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
- "dev": true,
- "license": "ISC"
- },
"node_modules/json2mq": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz",
@@ -12620,22 +11144,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/jsprim": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz",
- "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==",
- "dev": true,
- "engines": [
- "node >=0.6.0"
- ],
- "license": "MIT",
- "dependencies": {
- "assert-plus": "1.0.0",
- "extsprintf": "1.3.0",
- "json-schema": "0.4.0",
- "verror": "1.10.0"
- }
- },
"node_modules/jsx-ast-utils": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
@@ -12688,16 +11196,6 @@
"node": ">=0.10"
}
},
- "node_modules/lazy-ass": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz",
- "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "> 0.8"
- }
- },
"node_modules/leven": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
@@ -12723,20 +11221,11 @@
}
},
"node_modules/libphonenumber-js": {
- "version": "1.11.19",
- "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.11.19.tgz",
- "integrity": "sha512-bW/Yp/9dod6fmyR+XqSUL1N5JE7QRxQ3KrBIbYS1FTv32e5i3SEtQVX+71CYNv8maWNSOgnlCoNp9X78f/cKiA==",
+ "version": "1.12.6",
+ "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.12.6.tgz",
+ "integrity": "sha512-PJiS4ETaUfCOFLpmtKzAbqZQjCCKVu2OhTV4SVNNE7c2nu/dACvtCqj4L0i/KWNnIgRv7yrILvBj5Lonv5Ncxw==",
"license": "MIT"
},
- "node_modules/lie": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
- "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
- "license": "MIT",
- "dependencies": {
- "immediate": "~3.0.5"
- }
- },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
@@ -12744,64 +11233,10 @@
"dev": true,
"license": "MIT"
},
- "node_modules/listr2": {
- "version": "3.14.0",
- "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz",
- "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "cli-truncate": "^2.1.0",
- "colorette": "^2.0.16",
- "log-update": "^4.0.0",
- "p-map": "^4.0.0",
- "rfdc": "^1.3.0",
- "rxjs": "^7.5.1",
- "through": "^2.3.8",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "enquirer": ">= 2.3.0 < 3"
- },
- "peerDependenciesMeta": {
- "enquirer": {
- "optional": true
- }
- }
- },
- "node_modules/listr2/node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/localforage": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
- "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
- "license": "Apache-2.0",
- "dependencies": {
- "lie": "3.1.1"
- }
- },
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"p-locate": "^5.0.0"
@@ -12870,13 +11305,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/lodash.once": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
- "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -12884,141 +11312,10 @@
"dev": true,
"license": "MIT"
},
- "node_modules/log-symbols": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
- "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.1.0",
- "is-unicode-supported": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/log-symbols/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/log-symbols/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/log-symbols/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/log-update": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
- "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-escapes": "^4.3.0",
- "cli-cursor": "^3.1.0",
- "slice-ansi": "^4.0.0",
- "wrap-ansi": "^6.2.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/log-update/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/log-update/node_modules/slice-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
- "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "astral-regex": "^2.0.0",
- "is-fullwidth-code-point": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/slice-ansi?sponsor=1"
- }
- },
- "node_modules/log-update/node_modules/wrap-ansi": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
- "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/logrocket": {
- "version": "8.1.3",
- "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-8.1.3.tgz",
- "integrity": "sha512-lWuFhkWYMtARJ2BZUrxP54Dtn3TskpLZ0kDhp14BkrapFQihcN0GB8pvy2vP1OdRFFVh3pAG7AWo/BUbQ9SIbg==",
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/logrocket/-/logrocket-9.0.2.tgz",
+ "integrity": "sha512-DscsCEi9PLEEXPXWOsf+BGsmwZGIFzn9Ixo+lTezFpR2o3xzZxD7Qz3FWecYYuci6SKvalVciy6msVvMjD16PA==",
"license": "MIT"
},
"node_modules/long": {
@@ -13077,21 +11374,10 @@
"node": ">=12"
}
},
- "node_modules/lz-string": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
- "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "lz-string": "bin/bin.js"
- }
- },
"node_modules/magic-string": {
"version": "0.30.8",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
"integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
@@ -13101,9 +11387,9 @@
}
},
"node_modules/markerjs2": {
- "version": "2.32.3",
- "resolved": "https://registry.npmjs.org/markerjs2/-/markerjs2-2.32.3.tgz",
- "integrity": "sha512-D7oD4BT5NOsQbugdcO2TFmcw9ZMHp96Ih09A5f0UndxiQNWuz+j5zymtkTHs0WU+oOR8K6dyTufv4KtfJ6diBg==",
+ "version": "2.32.4",
+ "resolved": "https://registry.npmjs.org/markerjs2/-/markerjs2-2.32.4.tgz",
+ "integrity": "sha512-pk8gZMqSw0iDwSuH4Rt3jsYwA2J0EYUngIFIUvkHFVTiZPK+djuwrv4wfdK81I81FqnQ5iYp9buv/Sjg3Td0Tw==",
"license": "SEE LICENSE IN LICENSE"
},
"node_modules/material-colors": {
@@ -13910,7 +12196,6 @@
"version": "4.2.8",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz",
"integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==",
- "dev": true,
"license": "ISC",
"engines": {
"node": ">=8"
@@ -14091,7 +12376,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -14122,12 +12406,6 @@
"node": ">=8"
}
},
- "node_modules/obj-case": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/obj-case/-/obj-case-0.2.1.tgz",
- "integrity": "sha512-PquYBBTy+Y6Ob/O2574XHhDtHJlV1cJHMCgW+rDRc9J5hhmRelJB3k5dTK/3cVmFVtzvAKuENeuLpoyTzMzkOg==",
- "license": "MIT"
- },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -14370,13 +12648,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/ospath": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
- "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/own-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
@@ -14399,7 +12670,6 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"yocto-queue": "^0.1.0"
@@ -14415,7 +12685,6 @@
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"p-limit": "^3.0.2"
@@ -14562,7 +12831,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@@ -14597,7 +12865,6 @@
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
- "dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^10.2.0",
@@ -14614,14 +12881,12 @@
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true,
"license": "ISC"
},
"node_modules/path-scurry/node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "dev": true,
"license": "ISC",
"engines": {
"node": ">=16 || 14 >=14.17"
@@ -14670,13 +12935,6 @@
"node": ">=0.12"
}
},
- "node_modules/pend": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
- "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
@@ -14702,16 +12960,6 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/pkg-dir": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz",
@@ -14736,9 +12984,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.38",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
- "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
"funding": [
{
"type": "opencollective",
@@ -14756,8 +13004,8 @@
"license": "MIT",
"dependencies": {
"nanoid": "^3.3.7",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.2.0"
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
@@ -14792,28 +13040,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/pretty-format": {
- "version": "27.5.1",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
- "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1",
- "ansi-styles": "^5.0.0",
- "react-is": "^17.0.1"
- },
- "engines": {
- "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
- }
- },
- "node_modules/pretty-format/node_modules/react-is": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
- "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -14919,17 +13145,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/pump": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
- "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -15040,9 +13255,9 @@
}
},
"node_modules/rc-cascader": {
- "version": "3.33.0",
- "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.33.0.tgz",
- "integrity": "sha512-JvZrMbKBXIbEDmpIORxqvedY/bck6hGbs3hxdWT8eS9wSQ1P7//lGxbyKjOSyQiVBbgzNWriSe6HoMcZO/+0rQ==",
+ "version": "3.33.1",
+ "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.33.1.tgz",
+ "integrity": "sha512-Kyl4EJ7ZfCBuidmZVieegcbFw0RcU5bHHSbtEdmuLYd0fYHCAiYKZ6zon7fWAVyC6rWWOOib0XKdTSf7ElC9rg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.25.7",
@@ -15156,9 +13371,9 @@
}
},
"node_modules/rc-image": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.11.0.tgz",
- "integrity": "sha512-aZkTEZXqeqfPZtnSdNUnKQA0N/3MbgR7nUnZ+/4MfSFWPFHZau4p5r5ShaI0KPEMnNjv4kijSCFq/9wtJpwykw==",
+ "version": "7.11.1",
+ "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.11.1.tgz",
+ "integrity": "sha512-XuoWx4KUXg7hNy5mRTy1i8c8p3K8boWg6UajbHpDXS5AlRVucNfTi5YxTtPBTBzegxAZpvuLfh3emXFt6ybUdA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.2",
@@ -15174,9 +13389,9 @@
}
},
"node_modules/rc-input": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.7.2.tgz",
- "integrity": "sha512-g3nYONnl4edWj2FfVoxsU3Ec4XTE+Hb39Kfh2MFxMZjp/0gGyPUgy/v7ZhS27ZxUFNkuIDYXm9PJsLyJbtg86A==",
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.7.3.tgz",
+ "integrity": "sha512-A5w4egJq8+4JzlQ55FfQjDnPvOaAbzwC3VLOAdOytyek3TboSOP9qxN+Gifup+shVXfvecBLBbWBpWxmk02SWQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.1",
@@ -15225,9 +13440,9 @@
}
},
"node_modules/rc-menu": {
- "version": "9.16.0",
- "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.16.0.tgz",
- "integrity": "sha512-vAL0yqPkmXWk3+YKRkmIR8TYj3RVdEt3ptG2jCJXWNAvQbT0VJJdRyHZ7kG/l1JsZlB+VJq/VcYOo69VR4oD+w==",
+ "version": "9.16.1",
+ "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.16.1.tgz",
+ "integrity": "sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
@@ -15258,9 +13473,9 @@
}
},
"node_modules/rc-notification": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.2.tgz",
- "integrity": "sha512-Id4IYMoii3zzrG0lB0gD6dPgJx4Iu95Xu0BQrhHIbp7ZnAZbLqdqQ73aIWH0d0UFcElxwaKjnzNovTjo7kXz7g==",
+ "version": "5.6.3",
+ "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.3.tgz",
+ "integrity": "sha512-42szwnn8VYQoT6GnjO00i1iwqV9D1TTMvxObWsuLwgl0TsOokzhkYiufdtQBsJMFjJravS1hfDKVMHLKLcPE4g==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
@@ -15293,9 +13508,9 @@
}
},
"node_modules/rc-pagination": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-5.0.0.tgz",
- "integrity": "sha512-QjrPvbAQwps93iluvFM62AEYglGYhWW2q/nliQqmvkTi4PXP4HHoh00iC1Sa5LLVmtWQHmG73fBi2x6H6vFHRg==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-5.1.0.tgz",
+ "integrity": "sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
@@ -15308,9 +13523,9 @@
}
},
"node_modules/rc-picker": {
- "version": "4.9.2",
- "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.9.2.tgz",
- "integrity": "sha512-SLW4PRudODOomipKI0dvykxW4P8LOqtMr17MOaLU6NQJhkh9SZeh44a/8BMxwv5T6e3kiIeYc9k5jFg2Mv35Pg==",
+ "version": "4.11.3",
+ "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.11.3.tgz",
+ "integrity": "sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.24.7",
@@ -15362,9 +13577,9 @@
}
},
"node_modules/rc-rate": {
- "version": "2.13.0",
- "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.0.tgz",
- "integrity": "sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==",
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.1.tgz",
+ "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
@@ -15485,9 +13700,9 @@
}
},
"node_modules/rc-table": {
- "version": "7.50.2",
- "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.50.2.tgz",
- "integrity": "sha512-+nJbzxzstBriLb5sr9U7Vjs7+4dO8cWlouQbMwBVYghk2vr508bBdkHJeP/z9HVjAIKmAgMQKxmtbgDd3gc5wA==",
+ "version": "7.50.4",
+ "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.50.4.tgz",
+ "integrity": "sha512-Y+YuncnQqoS5e7yHvfvlv8BmCvwDYDX/2VixTBEhkMDk9itS9aBINp4nhzXFKiBP/frG4w0pS9d9Rgisl0T1Bw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
@@ -15506,9 +13721,9 @@
}
},
"node_modules/rc-tabs": {
- "version": "15.5.0",
- "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.5.0.tgz",
- "integrity": "sha512-NrDcTaUJLh9UuDdMBkjKTn97U9iXG44s9D03V5NHkhEDWO5/nC6PwC3RhkCWFMKB9hh+ryqgZ+TIr1b9Jd/hnQ==",
+ "version": "15.5.1",
+ "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.5.1.tgz",
+ "integrity": "sha512-yiWivLAjEo5d1v2xlseB2dQocsOhkoVSfo1krS8v8r+02K+TBUjSjXIf7dgyVSxp6wRIPv5pMi5hanNUlQMgUA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.2",
@@ -15545,14 +13760,15 @@
}
},
"node_modules/rc-tooltip": {
- "version": "6.3.2",
- "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.3.2.tgz",
- "integrity": "sha512-oA4HZIiZJbUQ5ojigM0y4XtWxaH/aQlJSzknjICRWNpqyemy1sL3X3iEQV2eSPBWEq+bqU3+aSs81z+28j9luA==",
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.4.0.tgz",
+ "integrity": "sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.11.2",
"@rc-component/trigger": "^2.0.0",
- "classnames": "^2.3.1"
+ "classnames": "^2.3.1",
+ "rc-util": "^5.44.3"
},
"peerDependencies": {
"react": ">=16.9.0",
@@ -15560,9 +13776,9 @@
}
},
"node_modules/rc-tree": {
- "version": "5.13.0",
- "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.0.tgz",
- "integrity": "sha512-2+lFvoVRnvHQ1trlpXMOWtF8BUgF+3TiipG72uOfhpL5CUdXCk931kvDdUkTL/IZVtNEDQKwEEmJbAYJSA5NnA==",
+ "version": "5.13.1",
+ "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.1.tgz",
+ "integrity": "sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.10.1",
@@ -15612,9 +13828,9 @@
}
},
"node_modules/rc-util": {
- "version": "5.44.3",
- "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.3.tgz",
- "integrity": "sha512-q6KCcOFk3rv/zD3MckhJteZxb0VjAIFuf622B7ElK4vfrZdAzs16XR5p3VTdy3+U5jfJU5ACz4QnhLSuAGe5dA==",
+ "version": "5.44.4",
+ "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz",
+ "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
@@ -15663,9 +13879,9 @@
}
},
"node_modules/react-big-calendar": {
- "version": "1.17.1",
- "resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.17.1.tgz",
- "integrity": "sha512-LltUAMSGODWQBKx4013bRe6R0jaINV9hrs970+F860KedpozwRGGMT66esV9mA3mAhfSKoazF/QH1WCyLkXYZA==",
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/react-big-calendar/-/react-big-calendar-1.18.0.tgz",
+ "integrity": "sha512-bGrCdyfnCGe2qnIdEoGkGgQdEFOiGO1Tq7RLkI1a2t8ZudyEAKekFtneO2/ltKQEQK6zH76YdJ7vR9UMyD+ULw==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.20.7",
@@ -15686,8 +13902,8 @@
"uncontrollable": "^7.2.1"
},
"peerDependencies": {
- "react": "^16.14.0 || ^17 || ^18",
- "react-dom": "^16.14.0 || ^17 || ^18"
+ "react": "^16.14.0 || ^17 || ^18 || ^19",
+ "react-dom": "^16.14.0 || ^17 || ^18 || ^19"
}
},
"node_modules/react-color": {
@@ -15709,14 +13925,14 @@
}
},
"node_modules/react-cookie": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-7.2.2.tgz",
- "integrity": "sha512-e+hi6axHcw9VODoeVu8WyMWyoosa1pzpyjfvrLdF7CexfU+WSGZdDuRfHa4RJgTpfv3ZjdIpHE14HpYBieHFhg==",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-8.0.1.tgz",
+ "integrity": "sha512-QNdAd0MLuAiDiLcDU/2s/eyKmmfMHtjPUKJ2dZ/5CcQ9QKUium4B3o61/haq6PQl/YWFqC5PO8GvxeHKhy3GFA==",
"license": "MIT",
"dependencies": {
- "@types/hoist-non-react-statics": "^3.3.5",
+ "@types/hoist-non-react-statics": "^3.3.6",
"hoist-non-react-statics": "^3.3.2",
- "universal-cookie": "^7.0.0"
+ "universal-cookie": "^8.0.0"
},
"peerDependencies": {
"react": ">= 16.3.0"
@@ -15760,9 +13976,9 @@
}
},
"node_modules/react-error-overlay": {
- "version": "6.0.11",
- "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
- "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.1.0.tgz",
+ "integrity": "sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==",
"dev": true,
"license": "MIT"
},
@@ -15793,12 +14009,12 @@
}
},
"node_modules/react-i18next": {
- "version": "14.1.3",
- "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz",
- "integrity": "sha512-wZnpfunU6UIAiJ+bxwOiTmBOAaB14ha97MjOEnLGac2RJ+h/maIYXZuTHlmyqQVX1UVHmU1YDTQ5vxLmwfXTjw==",
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-15.4.1.tgz",
+ "integrity": "sha512-ahGab+IaSgZmNPYXdV1n+OYky95TGpFwnKRflX/16dY04DsYYKHtVLjeny7sBSCREEcoMbAgSkFiGLF5g5Oofw==",
"license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.23.9",
+ "@babel/runtime": "^7.25.0",
"html-parse-stringify": "^3.0.1"
},
"peerDependencies": {
@@ -15815,9 +14031,9 @@
}
},
"node_modules/react-icons": {
- "version": "5.4.0",
- "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz",
- "integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==",
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz",
+ "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==",
"license": "MIT",
"peerDependencies": {
"react": "*"
@@ -15851,12 +14067,13 @@
"license": "MIT"
},
"node_modules/react-markdown": {
- "version": "9.0.3",
- "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.0.3.tgz",
- "integrity": "sha512-Yk7Z94dbgYTOrdk41Z74GoKA7rThnsbbqBTRYuxoe08qvfQ9tJVhmAKw6BJS/ZORG7kTy/s1QvYzSuaoBA1qfw==",
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-10.1.0.tgz",
+ "integrity": "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==",
"license": "MIT",
"dependencies": {
"@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
"devlop": "^1.0.0",
"hast-util-to-jsx-runtime": "^2.0.0",
"html-url-attributes": "^3.0.0",
@@ -15999,12 +14216,12 @@
}
},
"node_modules/react-router": {
- "version": "6.29.0",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.29.0.tgz",
- "integrity": "sha512-DXZJoE0q+KyeVw75Ck6GkPxFak63C4fGqZGNijnWgzB/HzSP1ZfTlBj5COaGWwhrMQ/R8bXiq5Ooy4KG+ReyjQ==",
+ "version": "6.30.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.0.tgz",
+ "integrity": "sha512-D3X8FyH9nBcTSHGdEKurK7r8OYE1kKFn3d/CF+CoxbSHkxU7o37+Uh7eAHRXr6k2tSExXYO++07PeXJtA/dEhQ==",
"license": "MIT",
"dependencies": {
- "@remix-run/router": "1.22.0"
+ "@remix-run/router": "1.23.0"
},
"engines": {
"node": ">=14.0.0"
@@ -16014,13 +14231,13 @@
}
},
"node_modules/react-router-dom": {
- "version": "6.29.0",
- "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.29.0.tgz",
- "integrity": "sha512-pkEbJPATRJ2iotK+wUwHfy0xs2T59YPEN8BQxVCPeBZvK7kfPESRc/nyxzdcxR17hXgUPYx2whMwl+eo9cUdnQ==",
+ "version": "6.30.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.0.tgz",
+ "integrity": "sha512-x30B78HV5tFk8ex0ITwzC9TTZMua4jGyA9IUlH1JLQYQTFyxr/ZxwOJq7evg1JX1qGVUcvhsmQSKdPncQrjTgA==",
"license": "MIT",
"dependencies": {
- "@remix-run/router": "1.22.0",
- "react-router": "6.29.0"
+ "@remix-run/router": "1.23.0",
+ "react-router": "6.30.0"
},
"engines": {
"node": ">=14.0.0"
@@ -16076,16 +14293,13 @@
}
},
"node_modules/react-virtuoso": {
- "version": "4.12.3",
- "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.12.3.tgz",
- "integrity": "sha512-6X1p/sU7hecmjDZMAwN+r3go9EVjofKhwkUbVlL8lXhBZecPv9XVCkZ/kBPYOr0Mv0Vl5+Ziwgexg9Kh7+NNXQ==",
+ "version": "4.12.5",
+ "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.12.5.tgz",
+ "integrity": "sha512-YeCbRRsC9CLf0buD0Rct7WsDbzf+yBU1wGbo05/XjbcN2nJuhgh040m3y3+6HVogTZxEqVm45ac9Fpae4/MxRQ==",
"license": "MIT",
- "engines": {
- "node": ">=10"
- },
"peerDependencies": {
- "react": ">=16 || >=17 || >= 18",
- "react-dom": ">=16 || >=17 || >= 18"
+ "react": ">=16 || >=17 || >= 18 || >= 19",
+ "react-dom": ">=16 || >=17 || >= 18 || >=19"
}
},
"node_modules/reactcss": {
@@ -16172,12 +14386,6 @@
"integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
"license": "MIT"
},
- "node_modules/redis-commands": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz",
- "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==",
- "license": "MIT"
- },
"node_modules/redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
@@ -16455,16 +14663,6 @@
"url": "https://opencollective.com/unified"
}
},
- "node_modules/request-progress": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
- "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "throttleit": "^1.0.0"
- }
- },
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -16527,20 +14725,6 @@
"node": ">=4"
}
},
- "node_modules/restore-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
- "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "onetime": "^5.1.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/reusify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
@@ -16552,13 +14736,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/rfdc": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
- "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -16698,16 +14875,6 @@
"queue-microtask": "^1.2.2"
}
},
- "node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
"node_modules/safe-array-concat": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
@@ -16732,6 +14899,7 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "dev": true,
"funding": [
{
"type": "github",
@@ -16792,17 +14960,10 @@
"node": ">=10"
}
},
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/sass": {
- "version": "1.83.4",
- "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.4.tgz",
- "integrity": "sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==",
+ "version": "1.86.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.0.tgz",
+ "integrity": "sha512-zV8vGUld/+mP4KbMLJMX7TyGCuUp7hnkOScgCMsWuHtns8CWBoz+vmEhoGMXsaJrbUP8gj+F1dLvVe79sK8UdA==",
"license": "MIT",
"dependencies": {
"chokidar": "^4.0.0",
@@ -17064,37 +15225,6 @@
"node": ">=8"
}
},
- "node_modules/slice-ansi": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
- "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "astral-regex": "^2.0.0",
- "is-fullwidth-code-point": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/slice-ansi/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
"node_modules/smob": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz",
@@ -17398,32 +15528,6 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"license": "BSD-3-Clause"
},
- "node_modules/sshpk": {
- "version": "1.18.0",
- "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
- "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "asn1": "~0.2.3",
- "assert-plus": "^1.0.0",
- "bcrypt-pbkdf": "^1.0.0",
- "dashdash": "^1.12.0",
- "ecc-jsbn": "~0.1.1",
- "getpass": "^0.1.1",
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.0.2",
- "tweetnacl": "~0.14.0"
- },
- "bin": {
- "sshpk-conv": "bin/sshpk-conv",
- "sshpk-sign": "bin/sshpk-sign",
- "sshpk-verify": "bin/sshpk-verify"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/standard-as-callback": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
@@ -17714,9 +15818,9 @@
}
},
"node_modules/styled-components": {
- "version": "6.1.14",
- "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.14.tgz",
- "integrity": "sha512-KtfwhU5jw7UoxdM0g6XU9VZQFV4do+KrM8idiVCH5h4v49W+3p3yMe0icYwJgZQZepa5DbH04Qv8P0/RdcLcgg==",
+ "version": "6.1.16",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.16.tgz",
+ "integrity": "sha512-KpWB6ORAWGmbWM10cDJfEV6sXc/uVkkkQV3SLwTNQ/E/PqWgNHIoMSLh1Lnk2FkB9+JHK7uuMq1i+9ArxDD7iQ==",
"license": "MIT",
"dependencies": {
"@emotion/is-prop-valid": "1.2.2",
@@ -17724,7 +15828,7 @@
"@types/stylis": "4.2.5",
"css-to-react-native": "3.2.0",
"csstype": "3.1.3",
- "postcss": "8.4.38",
+ "postcss": "8.4.49",
"shallowequal": "1.1.0",
"stylis": "4.3.2",
"tslib": "2.6.2"
@@ -17833,22 +15937,6 @@
}
}
},
- "node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
@@ -17863,9 +15951,9 @@
}
},
"node_modules/swr": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.0.tgz",
- "integrity": "sha512-NyZ76wA4yElZWBHzSgEJc28a0u6QZvhb6w0azeL2k7+Q1gAzVK+IqQYXhVOC/mzi+HZIozrZvBVeSeOZNR2bqA==",
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/swr/-/swr-2.3.2.tgz",
+ "integrity": "sha512-RosxFpiabojs75IwQ316DGoDRmOqtiAj0tg8wCcbEu4CiLZBs/a9QNtHV7TUfDXmmlgqij/NqzKq/eLelyv9xA==",
"license": "MIT",
"dependencies": {
"dequal": "^2.0.3",
@@ -18031,23 +16119,6 @@
"node": ">=12.22"
}
},
- "node_modules/throttleit": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz",
- "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/timers-browserify": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz",
@@ -18087,41 +16158,10 @@
"node": ">=12.0.0"
}
},
- "node_modules/tldts": {
- "version": "6.1.75",
- "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.75.tgz",
- "integrity": "sha512-+lFzEXhpl7JXgWYaXcB6DqTYXbUArvrWAE/5ioq/X3CdWLbDjpPP4XTrQBmEJ91y3xbe4Fkw7Lxv4P3GWeJaNg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "tldts-core": "^6.1.75"
- },
- "bin": {
- "tldts": "bin/cli.js"
- }
- },
- "node_modules/tldts-core": {
- "version": "6.1.75",
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.75.tgz",
- "integrity": "sha512-AOvV5YYIAFFBfransBzSTyztkc3IMfz5Eq3YluaRiEu55nn43Fzaufx70UqEKYr8BoLCach4q8g/bg6e5+/aFw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/tmp": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
- "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.14"
- }
- },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "devOptional": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
@@ -18136,19 +16176,6 @@
"integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==",
"license": "MIT"
},
- "node_modules/tough-cookie": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.0.tgz",
- "integrity": "sha512-rvZUv+7MoBYTiDmFPBrhL7Ujx9Sk+q9wwm22x8c8T5IJaR+Wsyc7TNxbVxo84kZoRJZZMazowFLqpankBEQrGg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "tldts": "^6.1.32"
- },
- "engines": {
- "node": ">=16"
- }
- },
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -18172,16 +16199,6 @@
"tslib": "2"
}
},
- "node_modules/tree-kill": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
- "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "tree-kill": "cli.js"
- }
- },
"node_modules/trim-lines": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
@@ -18276,26 +16293,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/tweetnacl": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
- "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
- "dev": true,
- "license": "Unlicense"
- },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -18309,19 +16306,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/type-fest": {
- "version": "0.21.3",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
- "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
- "dev": true,
- "license": "(MIT OR CC0-1.0)",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/typed-array-buffer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
@@ -18458,15 +16442,6 @@
"react": ">=15.0.0"
}
},
- "node_modules/undici": {
- "version": "6.19.7",
- "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.7.tgz",
- "integrity": "sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A==",
- "license": "MIT",
- "engines": {
- "node": ">=18.17"
- }
- },
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
@@ -18624,13 +16599,12 @@
}
},
"node_modules/universal-cookie": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-7.2.2.tgz",
- "integrity": "sha512-fMiOcS3TmzP2x5QV26pIH3mvhexLIT0HmPa3V7Q7knRfT9HG6kTwq02HZGLPw0sAOXrAmotElGRvTLCMbJsvxQ==",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-8.0.1.tgz",
+ "integrity": "sha512-B6ks9FLLnP1UbPPcveOidfvB9pHjP+wekP2uRYB9YDfKVpvcjKgy1W5Zj+cEXJ9KTPnqOKGfVDQBmn8/YCQfRg==",
"license": "MIT",
"dependencies": {
- "@types/cookie": "^0.6.0",
- "cookie": "^0.7.2"
+ "cookie": "^1.0.2"
}
},
"node_modules/universalify": {
@@ -18657,7 +16631,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz",
"integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"acorn": "^8.8.1",
@@ -18670,7 +16643,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
@@ -18695,7 +16667,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
@@ -18708,7 +16679,6 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
@@ -18721,7 +16691,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"picomatch": "^2.2.1"
@@ -18730,16 +16699,6 @@
"node": ">=8.10.0"
}
},
- "node_modules/untildify": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
- "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/upath": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
@@ -18850,19 +16809,6 @@
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
- "node_modules/userpilot": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/userpilot/-/userpilot-1.3.6.tgz",
- "integrity": "sha512-NK/4sQTnWrpER164PkWzLdLjUc2766B4yeLdLiFDoRfyLNAc3SecLWszZH6oPlv67B+XcYzqtmzEalE86bkljw==",
- "license": "MIT",
- "dependencies": {
- "@ndhoule/includes": "^2.0.1",
- "@ndhoule/pick": "^2.0.0",
- "component-indexof": "0.0.3",
- "is": "^3.1.0",
- "obj-case": "^0.2.0"
- }
- },
"node_modules/util": {
"version": "0.12.5",
"resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz",
@@ -18898,21 +16844,6 @@
"uuid": "dist/bin/uuid"
}
},
- "node_modules/verror": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
- "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
- "dev": true,
- "engines": [
- "node >=0.6.0"
- ],
- "license": "MIT",
- "dependencies": {
- "assert-plus": "^1.0.0",
- "core-util-is": "1.0.2",
- "extsprintf": "^1.2.0"
- }
- },
"node_modules/vfile": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
@@ -18964,15 +16895,15 @@
}
},
"node_modules/vite": {
- "version": "6.0.11",
- "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.11.tgz",
- "integrity": "sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==",
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz",
+ "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "esbuild": "^0.24.2",
- "postcss": "^8.4.49",
- "rollup": "^4.23.0"
+ "esbuild": "^0.25.0",
+ "postcss": "^8.5.3",
+ "rollup": "^4.30.1"
},
"bin": {
"vite": "bin/vite.js"
@@ -19108,9 +17039,9 @@
}
},
"node_modules/vite-plugin-pwa": {
- "version": "0.21.1",
- "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.21.1.tgz",
- "integrity": "sha512-rkTbKFbd232WdiRJ9R3u+hZmf5SfQljX1b45NF6oLA6DSktEKpYllgTo1l2lkiZWMWV78pABJtFjNXfBef3/3Q==",
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.21.2.tgz",
+ "integrity": "sha512-vFhH6Waw8itNu37hWUJxL50q+CBbNcMVzsKaYHQVrfxTt3ihk3PeLO22SbiP1UNWzcEPaTQv+YVxe4G0KOjAkg==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -19196,9 +17127,9 @@
}
},
"node_modules/vite/node_modules/postcss": {
- "version": "8.5.1",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz",
- "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==",
+ "version": "8.5.3",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
+ "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
"dev": true,
"funding": [
{
@@ -19265,7 +17196,6 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=10.13.0"
@@ -19275,32 +17205,8 @@
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz",
"integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==",
- "dev": true,
"license": "MIT"
},
- "node_modules/websocket-driver": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
- "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
- "license": "Apache-2.0",
- "dependencies": {
- "http-parser-js": ">=0.5.1",
- "safe-buffer": ">=5.1.0",
- "websocket-extensions": ">=0.1.1"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/websocket-extensions": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
- "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=0.8.0"
- }
- },
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
@@ -19874,22 +17780,10 @@
"node": ">=12"
}
},
- "node_modules/yauzl": {
- "version": "2.10.0",
- "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
- "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "buffer-crc32": "~0.2.3",
- "fd-slicer": "~1.1.0"
- }
- },
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">=10"
diff --git a/client/package.json b/client/package.json
index fff01743b..f7e354160 100644
--- a/client/package.json
+++ b/client/package.json
@@ -2,44 +2,49 @@
"name": "bodyshop",
"version": "0.2.1",
"engines": {
- "node": ">=18.18.2"
+ "node": ">=22.0.0"
},
"type": "module",
"private": true,
"proxy": "http://localhost:4000",
"dependencies": {
- "@ant-design/pro-layout": "^7.22.0",
- "@apollo/client": "^3.12.6",
+ "@ant-design/pro-layout": "^7.22.3",
+ "@apollo/client": "^3.13.5",
"@emotion/is-prop-valid": "^1.3.1",
- "@fingerprintjs/fingerprintjs": "^4.5.1",
+ "@fingerprintjs/fingerprintjs": "^4.6.1",
+ "@firebase/analytics": "^0.10.12",
+ "@firebase/app": "^0.11.3",
+ "@firebase/auth": "^1.9.1",
+ "@firebase/firestore": "^4.7.10",
+ "@firebase/messaging": "^0.12.17",
"@jsreport/browser-client": "^3.1.0",
- "@reduxjs/toolkit": "^2.5.0",
- "@sentry/cli": "^2.40.0",
- "@sentry/react": "^7.114.0",
- "@splitsoftware/splitio-react": "^1.13.0",
+ "@reduxjs/toolkit": "^2.6.1",
+ "@sentry/cli": "^2.42.4",
+ "@sentry/react": "^9.9.0",
+ "@sentry/vite-plugin": "^3.2.2",
+ "@splitsoftware/splitio-react": "^2.0.1",
"@tanem/react-nprogress": "^5.0.53",
"@vitejs/plugin-react": "^4.3.4",
- "antd": "^5.23.1",
+ "antd": "^5.24.5",
"apollo-link-logger": "^2.0.1",
- "apollo-link-sentry": "^3.3.0",
+ "apollo-link-sentry": "^4.2.0",
"autosize": "^6.0.1",
- "axios": "^1.7.9",
+ "axios": "^1.8.4",
"classnames": "^2.5.1",
"css-box-model": "^1.2.1",
"dayjs": "^1.11.13",
- "dayjs-business-days2": "^1.2.3",
+ "dayjs-business-days2": "^1.3.0",
"dinero.js": "^1.9.1",
"dotenv": "^16.4.7",
"env-cmd": "^10.1.0",
"exifr": "^7.1.3",
- "firebase": "^10.13.2",
"graphql": "^16.10.0",
- "i18next": "^23.15.1",
- "i18next-browser-languagedetector": "^8.0.2",
+ "i18next": "^24.2.3",
+ "i18next-browser-languagedetector": "^8.0.4",
"immutability-helper": "^3.1.1",
- "libphonenumber-js": "^1.11.18",
- "logrocket": "^8.1.2",
- "markerjs2": "^2.32.3",
+ "libphonenumber-js": "^1.12.6",
+ "logrocket": "^9.0.2",
+ "markerjs2": "^2.32.4",
"memoize-one": "^6.0.0",
"normalize-url": "^8.0.1",
"object-hash": "^3.0.0",
@@ -47,25 +52,25 @@
"query-string": "^9.1.1",
"raf-schd": "^4.0.3",
"react": "^18.3.1",
- "react-big-calendar": "^1.17.1",
+ "react-big-calendar": "^1.18.0",
"react-color": "^2.19.3",
- "react-cookie": "^7.2.2",
+ "react-cookie": "^8.0.1",
"react-dom": "^18.3.1",
"react-drag-listview": "^2.0.0",
"react-grid-gallery": "^1.0.1",
"react-grid-layout": "1.3.4",
- "react-i18next": "^14.1.3",
- "react-icons": "^5.4.0",
+ "react-i18next": "^15.4.1",
+ "react-icons": "^5.5.0",
"react-image-lightbox": "^5.1.4",
- "react-markdown": "^9.0.3",
+ "react-markdown": "^10.1.0",
"react-number-format": "^5.4.3",
"react-popopo": "^2.1.9",
"react-product-fruits": "^2.2.61",
"react-redux": "^9.2.0",
"react-resizable": "^3.0.5",
- "react-router-dom": "^6.26.2",
+ "react-router-dom": "^6.30.0",
"react-sticky": "^6.0.3",
- "react-virtuoso": "^4.10.4",
+ "react-virtuoso": "^4.12.5",
"recharts": "^2.15.0",
"redux": "^5.0.1",
"redux-actions": "^3.0.3",
@@ -73,12 +78,11 @@
"redux-saga": "^1.3.0",
"redux-state-sync": "^3.1.4",
"reselect": "^5.1.1",
- "sass": "^1.83.4",
+ "sass": "^1.86.0",
"socket.io-client": "^4.8.1",
- "styled-components": "^6.1.14",
+ "styled-components": "^6.1.16",
"subscriptions-transport-ws": "^0.11.0",
"use-memo-one": "^1.1.3",
- "userpilot": "^1.3.6",
"vite-plugin-ejs": "^1.7.0",
"web-vitals": "^3.5.2"
},
@@ -95,11 +99,8 @@
"build:test:rome": "env-cmd -f .env.test.rome npm run build",
"build:production:imex": "env-cmd -f .env.production.imex npm run build",
"build:production:rome": "env-cmd -f .env.production.rome npm run build",
- "test": "cypress open",
- "eject": "react-scripts eject",
"madge": "madge --image ./madge-graph.svg --extensions js,jsx,ts,tsx --circular .",
- "eulaize": "node src/utils/eulaize.js",
- "sentry:sourcemaps:imex": "sentry-cli sourcemaps inject --org imex --project imexonline ./build && sentry-cli sourcemaps upload --org imex --project imexonline ./build"
+ "eulaize": "node src/utils/eulaize.js"
},
"browserslist": {
"production": [
@@ -120,35 +121,31 @@
"@rollup/rollup-linux-x64-gnu": "4.6.1"
},
"devDependencies": {
- "@ant-design/icons": "^5.5.2",
+ "@ant-design/icons": "^6.0.0",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/preset-react": "^7.26.3",
- "@dotenvx/dotenvx": "^1.33.0",
+ "@dotenvx/dotenvx": "^1.39.0",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/react": "^11.14.0",
- "@eslint/js": "^9.18.0",
- "@sentry/webpack-plugin": "^2.22.4",
- "@testing-library/cypress": "^10.0.2",
+ "@eslint/js": "^9.23.0",
+ "@sentry/webpack-plugin": "^3.2.2",
"browserslist": "^4.24.4",
"browserslist-to-esbuild": "^2.1.1",
"chalk": "^5.4.1",
- "cross-env": "^7.0.3",
- "cypress": "^13.17.0",
"eslint": "^8.57.1",
"eslint-config-react-app": "^7.0.1",
- "eslint-plugin-cypress": "^2.15.1",
"eslint-plugin-react": "^7.37.4",
- "globals": "^15.14.0",
+ "globals": "^15.15.0",
"memfs": "^4.17.0",
"os-browserify": "^0.3.0",
- "react-error-overlay": "6.0.11",
+ "react-error-overlay": "^6.1.0",
"redux-logger": "^3.0.6",
"source-map-explorer": "^2.5.3",
- "vite": "^6.0.7",
+ "vite": "^6.2.3",
"vite-plugin-babel": "^1.3.0",
"vite-plugin-eslint": "^1.8.1",
"vite-plugin-node-polyfills": "^0.23.0",
- "vite-plugin-pwa": "^0.21.1",
+ "vite-plugin-pwa": "^0.21.2",
"vite-plugin-style-import": "^2.0.0",
"workbox-window": "^7.3.0"
}
diff --git a/client/src/App/App.container.jsx b/client/src/App/App.container.jsx
index d6f3a53fd..67fd0f444 100644
--- a/client/src/App/App.container.jsx
+++ b/client/src/App/App.container.jsx
@@ -1,29 +1,38 @@
import { ApolloProvider } from "@apollo/client";
-import { SplitFactoryProvider, SplitSdk } from "@splitsoftware/splitio-react";
+import { SplitFactoryProvider, useSplitClient } from "@splitsoftware/splitio-react";
import { ConfigProvider } from "antd";
import enLocale from "antd/es/locale/en_US";
-import React from "react";
+import { useEffect } from "react";
import { useTranslation } from "react-i18next";
+import { useSelector } from "react-redux";
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
import client from "../utils/GraphQLClient";
import App from "./App";
import * as Sentry from "@sentry/react";
-
import themeProvider from "./themeProvider";
-import { Userpilot } from "userpilot";
-
-// Initialize Userpilot
-if (import.meta.env.DEV) {
- Userpilot.initialize("NX-69145f08");
-}
+// Base Split configuration
const config = {
core: {
authorizationKey: import.meta.env.VITE_APP_SPLIT_API,
- key: "anon"
+ key: "anon" // Default key, overridden dynamically by SplitClientProvider
}
};
-export const factory = SplitSdk(config);
+
+// Custom provider to manage the Split client key based on imexshopid from Redux
+function SplitClientProvider({ children }) {
+ const imexshopid = useSelector((state) => state.user.imexshopid); // Access imexshopid from Redux store
+ const splitClient = useSplitClient({ key: imexshopid || "anon" }); // Use imexshopid or fallback to "anon"
+
+ useEffect(() => {
+ if (splitClient && imexshopid) {
+ // Log readiness for debugging; no need for ready() since isReady is available
+ console.log(`Split client initialized with key: ${imexshopid}, isReady: ${splitClient.isReady}`);
+ }
+ }, [splitClient, imexshopid]);
+
+ return children;
+}
function AppContainer() {
const { t } = useTranslation();
@@ -31,7 +40,6 @@ function AppContainer() {
return (
-
-
+
+
+
+
diff --git a/client/src/App/App.jsx b/client/src/App/App.jsx
index 26f44fc8d..1cf4a8a06 100644
--- a/client/src/App/App.jsx
+++ b/client/src/App/App.jsx
@@ -1,10 +1,10 @@
import { useSplitClient } from "@splitsoftware/splitio-react";
import { Button, Result } from "antd";
import LogRocket from "logrocket";
-import React, { lazy, Suspense, useEffect, useState } from "react";
+import { lazy, Suspense, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
-import { Route, Routes } from "react-router-dom";
+import { Route, Routes, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import DocumentEditorContainer from "../components/document-editor/document-editor.container";
import ErrorBoundary from "../components/error-boundary/error-boundary.component"; // Component Imports
@@ -21,7 +21,7 @@ import "./App.styles.scss";
import Eula from "../components/eula/eula.component";
import InstanceRenderMgr from "../utils/instanceRenderMgr";
import ProductFruitsWrapper from "./ProductFruitsWrapper.jsx";
-import { SocketProvider } from "../contexts/SocketIO/socketContext.jsx";
+import { SocketProvider } from "../contexts/SocketIO/useSocket.jsx";
import { NotificationProvider } from "../contexts/Notifications/notificationContext.jsx";
const ResetPassword = lazy(() => import("../pages/reset-password/reset-password.component"));
@@ -46,6 +46,7 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline
const client = useSplitClient().client;
const [listenersAdded, setListenersAdded] = useState(false);
const { t } = useTranslation();
+ const navigate = useNavigate();
useEffect(() => {
if (!navigator.onLine) {
@@ -200,7 +201,7 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline
path="/manage/*"
element={
-
+
@@ -212,7 +213,7 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline
path="/tech/*"
element={
-
+
diff --git a/client/src/App/App.styles.scss b/client/src/App/App.styles.scss
index a2cd5bea6..9ea0a8d24 100644
--- a/client/src/App/App.styles.scss
+++ b/client/src/App/App.styles.scss
@@ -180,3 +180,13 @@
.muted-button:hover {
color: darkgrey;
}
+
+.notification-alert-unordered-list {
+ cursor: pointer;
+ padding: 0;
+ margin: 0;
+
+ .notification-alert-unordered-list-item {
+ margin-right: 0;
+ }
+}
diff --git a/client/src/components/chat-affix/chat-affix.container.jsx b/client/src/components/chat-affix/chat-affix.container.jsx
index ec3c79cd7..c757598c6 100644
--- a/client/src/components/chat-affix/chat-affix.container.jsx
+++ b/client/src/components/chat-affix/chat-affix.container.jsx
@@ -1,9 +1,9 @@
import { useApolloClient } from "@apollo/client";
import { getToken } from "@firebase/messaging";
import axios from "axios";
-import React, { useContext, useEffect } from "react";
+import { useEffect } from "react";
import { useTranslation } from "react-i18next";
-import SocketContext from "../../contexts/SocketIO/socketContext";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
import { messaging, requestForToken } from "../../firebase/firebase.utils";
import ChatPopupComponent from "../chat-popup/chat-popup.component";
import "./chat-affix.styles.scss";
@@ -12,7 +12,7 @@ import { registerMessagingHandlers, unregisterMessagingHandlers } from "./regist
export function ChatAffixContainer({ bodyshop, chatVisible }) {
const { t } = useTranslation();
const client = useApolloClient();
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
useEffect(() => {
if (!bodyshop || !bodyshop.messagingservicesid) return;
diff --git a/client/src/components/chat-archive-button/chat-archive-button.component.jsx b/client/src/components/chat-archive-button/chat-archive-button.component.jsx
index 66d25b787..24eb9cea4 100644
--- a/client/src/components/chat-archive-button/chat-archive-button.component.jsx
+++ b/client/src/components/chat-archive-button/chat-archive-button.component.jsx
@@ -1,9 +1,9 @@
import { useMutation } from "@apollo/client";
import { Button } from "antd";
-import React, { useContext, useState } from "react";
+import { useState } from "react";
import { useTranslation } from "react-i18next";
import { TOGGLE_CONVERSATION_ARCHIVE } from "../../graphql/conversations.queries";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors.js";
import { connect } from "react-redux";
@@ -18,7 +18,7 @@ export function ChatArchiveButton({ conversation, bodyshop }) {
const [loading, setLoading] = useState(false);
const { t } = useTranslation();
const [updateConversation] = useMutation(TOGGLE_CONVERSATION_ARCHIVE);
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const handleToggleArchive = async () => {
setLoading(true);
diff --git a/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx b/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx
index 4203e8f5b..e85ed6270 100644
--- a/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx
+++ b/client/src/components/chat-conversation-title-tags/chat-conversation-title-tags.component.jsx
@@ -1,11 +1,10 @@
import { useMutation } from "@apollo/client";
import { Tag } from "antd";
-import React, { useContext } from "react";
import { Link } from "react-router-dom";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { REMOVE_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors.js";
import { connect } from "react-redux";
@@ -18,7 +17,7 @@ const mapDispatchToProps = () => ({});
export function ChatConversationTitleTags({ jobConversations, bodyshop }) {
const [removeJobConversation] = useMutation(REMOVE_CONVERSATION_TAG);
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const handleRemoveTag = async (jobId) => {
const convId = jobConversations[0].conversationid;
diff --git a/client/src/components/chat-conversation/chat-conversation.container.jsx b/client/src/components/chat-conversation/chat-conversation.container.jsx
index 4a2992f6d..853c4851f 100644
--- a/client/src/components/chat-conversation/chat-conversation.container.jsx
+++ b/client/src/components/chat-conversation/chat-conversation.container.jsx
@@ -1,10 +1,10 @@
import { gql, useApolloClient, useQuery, useSubscription } from "@apollo/client";
import axios from "axios";
-import React, { useCallback, useContext, useEffect, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
-import SocketContext from "../../contexts/SocketIO/socketContext";
-import { GET_CONVERSATION_DETAILS, CONVERSATION_SUBSCRIPTION_BY_PK } from "../../graphql/conversations.queries";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
+import { CONVERSATION_SUBSCRIPTION_BY_PK, GET_CONVERSATION_DETAILS } from "../../graphql/conversations.queries";
import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import ChatConversationComponent from "./chat-conversation.component";
@@ -16,7 +16,7 @@ const mapStateToProps = createStructuredSelector({
function ChatConversationContainer({ bodyshop, selectedConversation }) {
const client = useApolloClient();
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const [markingAsReadInProgress, setMarkingAsReadInProgress] = useState(false);
// Fetch conversation details
diff --git a/client/src/components/chat-label/chat-label.component.jsx b/client/src/components/chat-label/chat-label.component.jsx
index ddd367798..6fccd1390 100644
--- a/client/src/components/chat-label/chat-label.component.jsx
+++ b/client/src/components/chat-label/chat-label.component.jsx
@@ -1,10 +1,10 @@
import { PlusOutlined } from "@ant-design/icons";
import { useMutation } from "@apollo/client";
import { Input, Spin, Tag, Tooltip } from "antd";
-import React, { useContext, useState } from "react";
+import { useState } from "react";
import { useTranslation } from "react-i18next";
import { UPDATE_CONVERSATION_LABEL } from "../../graphql/conversations.queries";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors.js";
import { connect } from "react-redux";
@@ -20,7 +20,7 @@ export function ChatLabel({ conversation, bodyshop }) {
const [loading, setLoading] = useState(false);
const [editing, setEditing] = useState(false);
const [value, setValue] = useState(conversation.label);
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const notification = useNotification();
const { t } = useTranslation();
diff --git a/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx b/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx
index e45ffb9b6..8806974bf 100644
--- a/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx
+++ b/client/src/components/chat-new-conversation/chat-new-conversation.component.jsx
@@ -1,12 +1,11 @@
import { PlusCircleFilled } from "@ant-design/icons";
import { Button, Form, Popover } from "antd";
-import React, { useContext } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { openChatByPhone } from "../../redux/messaging/messaging.actions";
import PhoneFormItem, { PhoneItemFormatterValidation } from "../form-items-formatted/phone-form-item.component";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -18,7 +17,7 @@ const mapDispatchToProps = (dispatch) => ({
export function ChatNewConversation({ openChatByPhone }) {
const { t } = useTranslation();
const [form] = Form.useForm();
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const handleFinish = (values) => {
openChatByPhone({ phone_num: values.phoneNumber, socket });
diff --git a/client/src/components/chat-open-button/chat-open-button.component.jsx b/client/src/components/chat-open-button/chat-open-button.component.jsx
index 42cd5dc82..68b9cd8b2 100644
--- a/client/src/components/chat-open-button/chat-open-button.component.jsx
+++ b/client/src/components/chat-open-button/chat-open-button.component.jsx
@@ -1,5 +1,4 @@
import parsePhoneNumber from "libphonenumber-js";
-import React, { useContext } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { openChatByPhone } from "../../redux/messaging/messaging.actions";
@@ -8,7 +7,7 @@ import PhoneNumberFormatter from "../../utils/PhoneFormatter";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { searchingForConversation } from "../../redux/messaging/messaging.selectors";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
const mapStateToProps = createStructuredSelector({
@@ -22,7 +21,7 @@ const mapDispatchToProps = (dispatch) => ({
export function ChatOpenButton({ bodyshop, searchingForConversation, phone, jobid, openChatByPhone }) {
const { t } = useTranslation();
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const notification = useNotification();
if (!phone) return <>>;
diff --git a/client/src/components/chat-popup/chat-popup.component.jsx b/client/src/components/chat-popup/chat-popup.component.jsx
index 0226cc354..2ae16b129 100644
--- a/client/src/components/chat-popup/chat-popup.component.jsx
+++ b/client/src/components/chat-popup/chat-popup.component.jsx
@@ -1,7 +1,7 @@
import { InfoCircleOutlined, MessageOutlined, ShrinkOutlined, SyncOutlined } from "@ant-design/icons";
import { useApolloClient, useLazyQuery, useQuery } from "@apollo/client";
import { Badge, Card, Col, Row, Space, Tag, Tooltip, Typography } from "antd";
-import React, { useContext, useEffect, useState } from "react";
+import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
@@ -12,8 +12,9 @@ import ChatConversationListComponent from "../chat-conversation-list/chat-conver
import ChatConversationContainer from "../chat-conversation/chat-conversation.container";
import ChatNewConversation from "../chat-new-conversation/chat-new-conversation.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
+
import "./chat-popup.styles.scss";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
const mapStateToProps = createStructuredSelector({
selectedConversation: selectSelectedConversation,
@@ -27,7 +28,7 @@ const mapDispatchToProps = (dispatch) => ({
export function ChatPopupComponent({ chatVisible, selectedConversation, toggleChatVisible }) {
const { t } = useTranslation();
const [pollInterval, setPollInterval] = useState(0);
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const client = useApolloClient(); // Apollo Client instance for cache operations
// Lazy query for conversations
diff --git a/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx b/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx
index 63839b263..2a12d96db 100644
--- a/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx
+++ b/client/src/components/chat-tag-ro/chat-tag-ro.container.jsx
@@ -2,13 +2,13 @@ import { PlusOutlined } from "@ant-design/icons";
import { useLazyQuery, useMutation } from "@apollo/client";
import { Tag } from "antd";
import _ from "lodash";
-import React, { useContext, useState } from "react";
+import { useState } from "react";
import { useTranslation } from "react-i18next";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
import { SEARCH_FOR_JOBS } from "../../graphql/jobs.queries";
import ChatTagRo from "./chat-tag-ro.component";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors.js";
import { connect } from "react-redux";
@@ -22,7 +22,7 @@ const mapDispatchToProps = () => ({});
export function ChatTagRoContainer({ conversation, bodyshop }) {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const [loadRo, { loading, data }] = useLazyQuery(SEARCH_FOR_JOBS);
diff --git a/client/src/components/dashboard-grid/componentList.js b/client/src/components/dashboard-grid/componentList.js
new file mode 100644
index 000000000..015d3509e
--- /dev/null
+++ b/client/src/components/dashboard-grid/componentList.js
@@ -0,0 +1,132 @@
+import i18next from "i18next";
+import DashboardTotalProductionDollars from "../dashboard-components/total-production-dollars/total-production-dollars.component.jsx";
+import {
+ DashboardTotalProductionHours,
+ DashboardTotalProductionHoursGql
+} from "../dashboard-components/total-production-hours/total-production-hours.component.jsx";
+import DashboardProjectedMonthlySales, {
+ DashboardProjectedMonthlySalesGql
+} from "../dashboard-components/pojected-monthly-sales/projected-monthly-sales.component.jsx";
+import DashboardMonthlyRevenueGraph, {
+ DashboardMonthlyRevenueGraphGql
+} from "../dashboard-components/monthly-revenue-graph/monthly-revenue-graph.component.jsx";
+import DashboardMonthlyJobCosting from "../dashboard-components/monthly-job-costing/monthly-job-costing.component.jsx";
+import DashboardMonthlyPartsSales from "../dashboard-components/monthly-parts-sales/monthly-parts-sales.component.jsx";
+import DashboardMonthlyLaborSales from "../dashboard-components/monthly-labor-sales/monthly-labor-sales.component.jsx";
+import DashboardMonthlyEmployeeEfficiency, {
+ DashboardMonthlyEmployeeEfficiencyGql
+} from "../dashboard-components/monthly-employee-efficiency/monthly-employee-efficiency.component.jsx";
+import DashboardScheduledInToday, {
+ DashboardScheduledInTodayGql
+} from "../dashboard-components/scheduled-in-today/scheduled-in-today.component.jsx";
+import DashboardScheduledOutToday, {
+ DashboardScheduledOutTodayGql
+} from "../dashboard-components/scheduled-out-today/scheduled-out-today.component.jsx";
+import JobLifecycleDashboardComponent, {
+ JobLifecycleDashboardGQL
+} from "../dashboard-components/job-lifecycle/job-lifecycle-dashboard.component.jsx";
+
+const componentList = {
+ ProductionDollars: {
+ label: i18next.t("dashboard.titles.productiondollars"),
+ component: DashboardTotalProductionDollars,
+ gqlFragment: null,
+ w: 1,
+ h: 1,
+ minW: 2,
+ minH: 1
+ },
+ ProductionHours: {
+ label: i18next.t("dashboard.titles.productionhours"),
+ component: DashboardTotalProductionHours,
+ gqlFragment: DashboardTotalProductionHoursGql,
+ w: 3,
+ h: 1,
+ minW: 3,
+ minH: 1
+ },
+ ProjectedMonthlySales: {
+ label: i18next.t("dashboard.titles.projectedmonthlysales"),
+ component: DashboardProjectedMonthlySales,
+ gqlFragment: DashboardProjectedMonthlySalesGql,
+ w: 2,
+ h: 1,
+ minW: 2,
+ minH: 1
+ },
+ MonthlyRevenueGraph: {
+ label: i18next.t("dashboard.titles.monthlyrevenuegraph"),
+ component: DashboardMonthlyRevenueGraph,
+ gqlFragment: DashboardMonthlyRevenueGraphGql,
+ w: 4,
+ h: 2,
+ minW: 4,
+ minH: 2
+ },
+ MonthlyJobCosting: {
+ label: i18next.t("dashboard.titles.monthlyjobcosting"),
+ component: DashboardMonthlyJobCosting,
+ gqlFragment: null,
+ minW: 6,
+ minH: 3,
+ w: 6,
+ h: 3
+ },
+ MonthlyPartsSales: {
+ label: i18next.t("dashboard.titles.monthlypartssales"),
+ component: DashboardMonthlyPartsSales,
+ gqlFragment: null,
+ minW: 2,
+ minH: 2,
+ w: 2,
+ h: 2
+ },
+ MonthlyLaborSales: {
+ label: i18next.t("dashboard.titles.monthlylaborsales"),
+ component: DashboardMonthlyLaborSales,
+ gqlFragment: null,
+ minW: 2,
+ minH: 2,
+ w: 2,
+ h: 2
+ },
+ // Typo in Efficency should be Efficiency, but changing it would reset users dashboard settings
+ MonthlyEmployeeEfficency: {
+ label: i18next.t("dashboard.titles.monthlyemployeeefficiency"),
+ component: DashboardMonthlyEmployeeEfficiency,
+ gqlFragment: DashboardMonthlyEmployeeEfficiencyGql,
+ minW: 2,
+ minH: 2,
+ w: 2,
+ h: 2
+ },
+ ScheduleInToday: {
+ label: i18next.t("dashboard.titles.scheduledintoday"),
+ component: DashboardScheduledInToday,
+ gqlFragment: DashboardScheduledInTodayGql,
+ minW: 6,
+ minH: 2,
+ w: 10,
+ h: 3
+ },
+ ScheduleOutToday: {
+ label: i18next.t("dashboard.titles.scheduledouttoday"),
+ component: DashboardScheduledOutToday,
+ gqlFragment: DashboardScheduledOutTodayGql,
+ minW: 6,
+ minH: 2,
+ w: 10,
+ h: 3
+ },
+ JobLifecycle: {
+ label: i18next.t("dashboard.titles.joblifecycle"),
+ component: JobLifecycleDashboardComponent,
+ gqlFragment: JobLifecycleDashboardGQL,
+ minW: 6,
+ minH: 3,
+ w: 6,
+ h: 3
+ }
+};
+
+export default componentList;
diff --git a/client/src/components/dashboard-grid/createDashboardQuery.js b/client/src/components/dashboard-grid/createDashboardQuery.js
new file mode 100644
index 000000000..a37f4aa4a
--- /dev/null
+++ b/client/src/components/dashboard-grid/createDashboardQuery.js
@@ -0,0 +1,85 @@
+import { gql } from "@apollo/client";
+import dayjs from "../../utils/day.js";
+import componentList from "./componentList.js";
+
+const createDashboardQuery = (state) => {
+ const componentBasedAdditions =
+ state &&
+ Array.isArray(state.layout) &&
+ state.layout.map((item, index) => componentList[item.i].gqlFragment || "").join("");
+ return gql`
+ query QUERY_DASHBOARD_DETAILS { ${componentBasedAdditions || ""}
+ monthly_sales: jobs(where: {_and: [
+ { voided: {_eq: false}},
+ {date_invoiced: {_gte: "${dayjs()
+ .startOf("month")
+ .startOf("day")
+ .toISOString()}"}}, {date_invoiced: {_lte: "${dayjs().endOf("month").endOf("day").toISOString()}"}}]}) {
+ id
+ ro_number
+ date_invoiced
+ job_totals
+ rate_la1
+ rate_la2
+ rate_la3
+ rate_la4
+ rate_laa
+ rate_lab
+ rate_lad
+ rate_lae
+ rate_laf
+ rate_lag
+ rate_lam
+ rate_lar
+ rate_las
+ rate_lau
+ rate_ma2s
+ rate_ma2t
+ rate_ma3s
+ rate_mabl
+ rate_macs
+ rate_mahw
+ rate_mapa
+ rate_mash
+ rate_matd
+ joblines(where: { removed: { _eq: false } }) {
+ id
+ mod_lbr_ty
+ mod_lb_hrs
+ act_price
+ part_qty
+ part_type
+ }
+ }
+ production_jobs: jobs(where: { inproduction: { _eq: true } }) {
+ id
+ ro_number
+ ins_co_nm
+ job_totals
+ joblines(where: { removed: { _eq: false } }) {
+ id
+ mod_lbr_ty
+ mod_lb_hrs
+ act_price
+ part_qty
+ part_type
+ }
+ labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }) {
+ aggregate {
+ sum {
+ mod_lb_hrs
+ }
+ }
+ }
+ larhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAR" }, removed: { _eq: false } }) {
+ aggregate {
+ sum {
+ mod_lb_hrs
+ }
+ }
+ }
+ }
+ }`;
+};
+
+export default createDashboardQuery;
diff --git a/client/src/components/dashboard-grid/dashboard-grid.component.jsx b/client/src/components/dashboard-grid/dashboard-grid.component.jsx
index 6c3412a3d..082e404ac 100644
--- a/client/src/components/dashboard-grid/dashboard-grid.component.jsx
+++ b/client/src/components/dashboard-grid/dashboard-grid.component.jsx
@@ -1,11 +1,9 @@
import Icon, { SyncOutlined } from "@ant-design/icons";
-import { gql, useMutation, useQuery } from "@apollo/client";
+import { isEmpty, cloneDeep } from "lodash";
+import { useMutation, useQuery } from "@apollo/client";
import { Button, Dropdown, Space } from "antd";
import { PageHeader } from "@ant-design/pro-layout";
-import i18next from "i18next";
-import _ from "lodash";
-import dayjs from "../../utils/day";
-import React, { useState } from "react";
+import { useMemo, useState } from "react";
import { Responsive, WidthProvider } from "react-grid-layout";
import { useTranslation } from "react-i18next";
import { MdClose } from "react-icons/md";
@@ -15,38 +13,13 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
import { UPDATE_DASHBOARD_LAYOUT } from "../../graphql/user.queries";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
-import DashboardMonthlyEmployeeEfficiency, {
- DashboardMonthlyEmployeeEfficiencyGql
-} from "../dashboard-components/monthly-employee-efficiency/monthly-employee-efficiency.component";
-import DashboardMonthlyJobCosting from "../dashboard-components/monthly-job-costing/monthly-job-costing.component";
-import DashboardMonthlyLaborSales from "../dashboard-components/monthly-labor-sales/monthly-labor-sales.component";
-import DashboardMonthlyPartsSales from "../dashboard-components/monthly-parts-sales/monthly-parts-sales.component";
-import DashboardMonthlyRevenueGraph, {
- DashboardMonthlyRevenueGraphGql
-} from "../dashboard-components/monthly-revenue-graph/monthly-revenue-graph.component";
-import DashboardProjectedMonthlySales, {
- DashboardProjectedMonthlySalesGql
-} from "../dashboard-components/pojected-monthly-sales/projected-monthly-sales.component";
-import DashboardTotalProductionDollars from "../dashboard-components/total-production-dollars/total-production-dollars.component";
-import DashboardTotalProductionHours, {
- DashboardTotalProductionHoursGql
-} from "../dashboard-components/total-production-hours/total-production-hours.component";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
-//Combination of the following:
-// /node_modules/react-grid-layout/css/styles.css
-// /node_modules/react-resizable/css/styles.css
-import DashboardScheduledInToday, {
- DashboardScheduledInTodayGql
-} from "../dashboard-components/scheduled-in-today/scheduled-in-today.component";
-import DashboardScheduledOutToday, {
- DashboardScheduledOutTodayGql
-} from "../dashboard-components/scheduled-out-today/scheduled-out-today.component";
-import JobLifecycleDashboardComponent, {
- JobLifecycleDashboardGQL
-} from "../dashboard-components/job-lifecycle/job-lifecycle-dashboard.component";
-import "./dashboard-grid.styles.scss";
import { GenerateDashboardData } from "./dashboard-grid.utils";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
+import componentList from "./componentList.js";
+import createDashboardQuery from "./createDashboardQuery.js";
+
+import "./dashboard-grid.styles.scss";
const ResponsiveReactGridLayout = WidthProvider(Responsive);
@@ -54,6 +27,7 @@ const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
bodyshop: selectBodyshop
});
+
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
@@ -85,19 +59,21 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
layout: { ...state, layout, layouts }
}
});
- if (!!result.errors) {
- notification["error"]({
+
+ if (!isEmpty(result?.errors)) {
+ notification.error({
message: t("dashboard.errors.updatinglayout", {
message: JSON.stringify(result.errors)
})
});
}
};
+
const handleRemoveComponent = (key) => {
logImEXEvent("dashboard_remove_component", { name: key });
const idxToRemove = state.items.findIndex((i) => i.i === key);
- const items = _.cloneDeep(state.items);
+ const items = cloneDeep(state.items);
items.splice(idxToRemove, 1);
setState({ ...state, items });
@@ -120,7 +96,8 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
});
};
- const dashboarddata = React.useMemo(() => GenerateDashboardData(data), [data]);
+ const dashboardData = useMemo(() => GenerateDashboardData(data), [data]);
+
const existingLayoutKeys = state.items.map((i) => i.i);
const menuItems = Object.keys(componentList).map((key) => ({
@@ -156,7 +133,6 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
width="100%"
layouts={state.layouts}
onLayoutChange={handleLayoutChange}
- // onBreakpointChange={onBreakpointChange}
>
{state.items.map((item, index) => {
const TheComponent = componentList[item.i].component;
@@ -182,7 +158,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
}}
onClick={() => handleRemoveComponent(item.i)}
/>
-
+
);
@@ -193,189 +169,3 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
}
export default connect(mapStateToProps, mapDispatchToProps)(DashboardGridComponent);
-
-const componentList = {
- ProductionDollars: {
- label: i18next.t("dashboard.titles.productiondollars"),
- component: DashboardTotalProductionDollars,
- gqlFragment: null,
- w: 1,
- h: 1,
- minW: 2,
- minH: 1
- },
- ProductionHours: {
- label: i18next.t("dashboard.titles.productionhours"),
- component: DashboardTotalProductionHours,
- gqlFragment: DashboardTotalProductionHoursGql,
- w: 3,
- h: 1,
- minW: 3,
- minH: 1
- },
- ProjectedMonthlySales: {
- label: i18next.t("dashboard.titles.projectedmonthlysales"),
- component: DashboardProjectedMonthlySales,
- gqlFragment: DashboardProjectedMonthlySalesGql,
- w: 2,
- h: 1,
- minW: 2,
- minH: 1
- },
- MonthlyRevenueGraph: {
- label: i18next.t("dashboard.titles.monthlyrevenuegraph"),
- component: DashboardMonthlyRevenueGraph,
- gqlFragment: DashboardMonthlyRevenueGraphGql,
- w: 4,
- h: 2,
- minW: 4,
- minH: 2
- },
- MonthlyJobCosting: {
- label: i18next.t("dashboard.titles.monthlyjobcosting"),
- component: DashboardMonthlyJobCosting,
- gqlFragment: null,
- minW: 6,
- minH: 3,
- w: 6,
- h: 3
- },
- MonthlyPartsSales: {
- label: i18next.t("dashboard.titles.monthlypartssales"),
- component: DashboardMonthlyPartsSales,
- gqlFragment: null,
- minW: 2,
- minH: 2,
- w: 2,
- h: 2
- },
- MonthlyLaborSales: {
- label: i18next.t("dashboard.titles.monthlylaborsales"),
- component: DashboardMonthlyLaborSales,
- gqlFragment: null,
- minW: 2,
- minH: 2,
- w: 2,
- h: 2
- },
- // Typo in Efficency should be Efficiency, but changing it would reset users dashboard settings
- MonthlyEmployeeEfficency: {
- label: i18next.t("dashboard.titles.monthlyemployeeefficiency"),
- component: DashboardMonthlyEmployeeEfficiency,
- gqlFragment: DashboardMonthlyEmployeeEfficiencyGql,
- minW: 2,
- minH: 2,
- w: 2,
- h: 2
- },
- ScheduleInToday: {
- label: i18next.t("dashboard.titles.scheduledintoday"),
- component: DashboardScheduledInToday,
- gqlFragment: DashboardScheduledInTodayGql,
- minW: 6,
- minH: 2,
- w: 10,
- h: 3
- },
- ScheduleOutToday: {
- label: i18next.t("dashboard.titles.scheduledouttoday"),
- component: DashboardScheduledOutToday,
- gqlFragment: DashboardScheduledOutTodayGql,
- minW: 6,
- minH: 2,
- w: 10,
- h: 3
- },
- JobLifecycle: {
- label: i18next.t("dashboard.titles.joblifecycle"),
- component: JobLifecycleDashboardComponent,
- gqlFragment: JobLifecycleDashboardGQL,
- minW: 6,
- minH: 3,
- w: 6,
- h: 3
- }
-};
-
-const createDashboardQuery = (state) => {
- const componentBasedAdditions =
- state &&
- Array.isArray(state.layout) &&
- state.layout.map((item, index) => componentList[item.i].gqlFragment || "").join("");
- return gql`
- query QUERY_DASHBOARD_DETAILS { ${componentBasedAdditions || ""}
- monthly_sales: jobs(where: {_and: [
- { voided: {_eq: false}},
- {date_invoiced: {_gte: "${dayjs()
- .startOf("month")
- .startOf("day")
- .toISOString()}"}}, {date_invoiced: {_lte: "${dayjs()
- .endOf("month")
- .endOf("day")
- .toISOString()}"}}]}) {
- id
- ro_number
- date_invoiced
- job_totals
- rate_la1
- rate_la2
- rate_la3
- rate_la4
- rate_laa
- rate_lab
- rate_lad
- rate_lae
- rate_laf
- rate_lag
- rate_lam
- rate_lar
- rate_las
- rate_lau
- rate_ma2s
- rate_ma2t
- rate_ma3s
- rate_mabl
- rate_macs
- rate_mahw
- rate_mapa
- rate_mash
- rate_matd
- joblines(where: { removed: { _eq: false } }) {
- id
- mod_lbr_ty
- mod_lb_hrs
- act_price
- part_qty
- part_type
- }
- }
- production_jobs: jobs(where: { inproduction: { _eq: true } }) {
- id
- ro_number
- ins_co_nm
- job_totals
- joblines(where: { removed: { _eq: false } }) {
- id
- mod_lbr_ty
- mod_lb_hrs
- act_price
- part_qty
- part_type
- }
- labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }) {
- aggregate {
- sum {
- mod_lb_hrs
- }
- }
- }
- larhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAR" }, removed: { _eq: false } }) {
- aggregate {
- sum {
- mod_lb_hrs
- }
- }
- }
- }
- }`;
-};
diff --git a/client/src/components/error-boundary/error-boundary.component.jsx b/client/src/components/error-boundary/error-boundary.component.jsx
index 13525d7fe..ef6020ccc 100644
--- a/client/src/components/error-boundary/error-boundary.component.jsx
+++ b/client/src/components/error-boundary/error-boundary.component.jsx
@@ -123,7 +123,7 @@ class ErrorBoundary extends React.Component {
-
+
{this.state.error.message}
diff --git a/client/src/components/eula/eula.component.jsx b/client/src/components/eula/eula.component.jsx
index 389911961..ae503b09a 100644
--- a/client/src/components/eula/eula.component.jsx
+++ b/client/src/components/eula/eula.component.jsx
@@ -78,9 +78,7 @@ const Eula = ({ currentEula, currentUser, acceptEula }) => {
} catch (err) {
notification.error({
message: t("eula.errors.acceptance.message"),
- description: t("eula.errors.acceptance.description"),
- placement: "bottomRight",
- duration: 5000
+ description: t("eula.errors.acceptance.description")
});
console.log(`${t("eula.errors.acceptance.message")}`);
console.dir({
diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx
index edd444fd5..407bfd8a5 100644
--- a/client/src/components/header/header.component.jsx
+++ b/client/src/components/header/header.component.jsx
@@ -1,6 +1,7 @@
-import Icon, {
+import {
BankFilled,
BarChartOutlined,
+ BellFilled,
CarFilled,
CheckCircleOutlined,
ClockCircleFilled,
@@ -25,8 +26,10 @@ import Icon, {
UnorderedListOutlined,
UserOutlined
} from "@ant-design/icons";
+import { useQuery } from "@apollo/client";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
-import { Layout, Menu, Space } from "antd";
+import { Badge, Layout, Menu, Spin } from "antd";
+import { useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { BsKanban } from "react-icons/bs";
import { FaCalendarAlt, FaCarCrash, FaCreditCard, FaFileInvoiceDollar, FaTasks } from "react-icons/fa";
@@ -37,14 +40,19 @@ import { RiSurveyLine } from "react-icons/ri";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
+import { GET_UNREAD_COUNT } from "../../graphql/notifications.queries.js";
import { selectRecentItems, selectSelectedHeader } from "../../redux/application/application.selectors";
import { setModalContext } from "../../redux/modals/modals.actions";
import { signOutStart } from "../../redux/user/user.actions";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
+import day from "../../utils/day.js";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
import LockWrapper from "../lock-wrapper/lock-wrapper.component";
+import NotificationCenterContainer from "../notification-center/notification-center.container.jsx";
+// Redux mappings
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
recentItems: selectRecentItems,
@@ -53,43 +61,13 @@ const mapStateToProps = createStructuredSelector({
});
const mapDispatchToProps = (dispatch) => ({
- setBillEnterContext: (context) =>
- dispatch(
- setModalContext({
- context: context,
- modal: "billEnter"
- })
- ),
- setTimeTicketContext: (context) =>
- dispatch(
- setModalContext({
- context: context,
- modal: "timeTicket"
- })
- ),
- setPaymentContext: (context) => dispatch(setModalContext({ context: context, modal: "payment" })),
- setReportCenterContext: (context) =>
- dispatch(
- setModalContext({
- context: context,
- modal: "reportCenter"
- })
- ),
+ setBillEnterContext: (context) => dispatch(setModalContext({ context, modal: "billEnter" })),
+ setTimeTicketContext: (context) => dispatch(setModalContext({ context, modal: "timeTicket" })),
+ setPaymentContext: (context) => dispatch(setModalContext({ context, modal: "payment" })),
+ setReportCenterContext: (context) => dispatch(setModalContext({ context, modal: "reportCenter" })),
signOutStart: () => dispatch(signOutStart()),
- setCardPaymentContext: (context) =>
- dispatch(
- setModalContext({
- context: context,
- modal: "cardPayment"
- })
- ),
- setTaskUpsertContext: (context) =>
- dispatch(
- setModalContext({
- context: context,
- modal: "taskUpsert"
- })
- )
+ setCardPaymentContext: (context) => dispatch(setModalContext({ context, modal: "cardPayment" })),
+ setTaskUpsertContext: (context) => dispatch(setModalContext({ context, modal: "taskUpsert" }))
});
function Header({
@@ -115,24 +93,81 @@ function Header({
});
const { t } = useTranslation();
+ const { isConnected, scenarioNotificationsOn } = useSocket();
+ const [notificationVisible, setNotificationVisible] = useState(false);
+ const baseTitleRef = useRef(document.title || "");
+ const lastSetTitleRef = useRef("");
+ const userAssociationId = bodyshop?.associations?.[0]?.id;
- // const deleteBetaCookie = () => {
- // const cookieExists = document.cookie.split("; ").some((row) => row.startsWith(`betaSwitchImex=`));
- // if (cookieExists) {
- // const domain = window.location.hostname.split(".").slice(-2).join(".");
- // document.cookie = `betaSwitchImex=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.${domain}`;
- // }
- // };
- //
- // deleteBetaCookie();
+ const {
+ data: unreadData,
+ refetch: refetchUnread,
+ loading: unreadLoading
+ } = useQuery(GET_UNREAD_COUNT, {
+ variables: { associationid: userAssociationId },
+ fetchPolicy: "network-only",
+ pollInterval: isConnected ? 0 : day.duration(60, "seconds").asMilliseconds(),
+ skip: !userAssociationId || !scenarioNotificationsOn
+ });
- const accountingChildren = [];
+ const unreadCount = unreadData?.notifications_aggregate?.aggregate?.count ?? 0;
- accountingChildren.push(
+ useEffect(() => {
+ if (userAssociationId) {
+ refetchUnread().catch((e) => console.error(`Error fetching unread notifications: ${e?.message}`));
+ }
+ }, [refetchUnread, userAssociationId]);
+
+ useEffect(() => {
+ if (!isConnected && !unreadLoading && userAssociationId) {
+ refetchUnread().catch((e) => console.error(`Error fetching unread notifications: ${e?.message}`));
+ }
+ }, [isConnected, unreadLoading, refetchUnread, userAssociationId]);
+
+ // Keep The unread count in the title.
+ useEffect(() => {
+ const updateTitle = () => {
+ const currentTitle = document.title;
+ // Check if the current title differs from what we last set
+ if (currentTitle !== lastSetTitleRef.current) {
+ // Extract base title by removing any unread count prefix
+ const baseTitleMatch = currentTitle.match(/^\(\d+\)\s*(.*)$/);
+ baseTitleRef.current = baseTitleMatch ? baseTitleMatch[1] : currentTitle;
+ }
+
+ // Apply unread count to the base title
+ const newTitle = unreadCount > 0 ? `(${unreadCount}) ${baseTitleRef.current}` : baseTitleRef.current;
+
+ // Only update if the title has changed to avoid unnecessary DOM writes
+ if (document.title !== newTitle) {
+ document.title = newTitle;
+ lastSetTitleRef.current = newTitle; // Store what we set
+ }
+ };
+
+ // Initial update
+ updateTitle();
+
+ // Poll every 100ms to catch child component changes
+ const interval = setInterval(updateTitle, 100);
+
+ // Cleanup
+ return () => {
+ clearInterval(interval);
+ document.title = baseTitleRef.current; // Reset to base title on unmount
+ };
+ }, [unreadCount]); // Re-run when unreadCount changes
+
+ const handleNotificationClick = (e) => {
+ setNotificationVisible(!notificationVisible);
+ if (handleMenuClick) handleMenuClick(e);
+ };
+
+ const accountingChildren = [
{
key: "bills",
id: "header-accounting-bills",
- icon: ,
+ icon: ,
label: (
@@ -144,92 +179,60 @@ function Header({
{
key: "enterbills",
id: "header-accounting-enterbills",
- icon: ,
+ icon: ,
label: (
-
-
- {t("menus.header.enterbills")}
-
-
+
+ {t("menus.header.enterbills")}
+
),
- onClick: () => {
+ onClick: () =>
HasFeatureAccess({ featureName: "bills", bodyshop }) &&
- setBillEnterContext({
- actions: {},
- context: {}
- });
- }
- }
- );
-
- if (Simple_Inventory.treatment === "on") {
- accountingChildren.push(
- {
- type: "divider"
- },
- {
- key: "inventory",
- id: "header-accounting-inventory",
- icon: ,
- label: {t("menus.header.inventory")}
- }
- );
- }
-
- accountingChildren.push(
- {
- type: "divider"
+ setBillEnterContext({
+ actions: {},
+ context: {}
+ })
},
+ ...(Simple_Inventory.treatment === "on"
+ ? [
+ { type: "divider" },
+ {
+ key: "inventory",
+ id: "header-accounting-inventory",
+ icon: ,
+ label: {t("menus.header.inventory")}
+ }
+ ]
+ : []),
+ { type: "divider" },
{
key: "allpayments",
id: "header-accounting-allpayments",
icon: ,
- label: (
-
-
- {t("menus.header.allpayments")}
-
-
- )
+ label: {t("menus.header.allpayments")}
},
{
key: "enterpayments",
id: "header-accounting-enterpayments",
- icon: ,
- label: (
-
- {t("menus.header.enterpayment")}
-
- ),
- onClick: () => {
- HasFeatureAccess({ featureName: "payments", bodyshop }) &&
- setPaymentContext({
- actions: {},
- context: null
- });
- }
- }
- );
-
- if (ImEXPay.treatment === "on") {
- accountingChildren.push({
- key: "entercardpayments",
- id: "header-accounting-entercardpayments",
- icon: ,
- label: t("menus.header.entercardpayment"),
- onClick: () => {
- setCardPaymentContext({
+ icon: ,
+ label: t("menus.header.enterpayment"),
+ onClick: () =>
+ setPaymentContext({
actions: {},
- context: {}
- });
- }
- });
- }
-
- accountingChildren.push(
- {
- type: "divider"
+ context: null
+ })
},
+ ...(ImEXPay.treatment === "on"
+ ? [
+ {
+ key: "entercardpayments",
+ id: "header-accounting-entercardpayments",
+ icon: ,
+ label: t("menus.header.entercardpayment"),
+ onClick: () => setCardPaymentContext({ actions: {}, context: {} })
+ }
+ ]
+ : []),
+ { type: "divider" },
{
key: "timetickets",
id: "header-accounting-timetickets",
@@ -241,132 +244,124 @@ function Header({
)
- }
- );
-
- if (bodyshop?.md_tasks_presets?.use_approvals) {
- accountingChildren.push({
- key: "ttapprovals",
- id: "header-accounting-ttapprovals",
- icon: ,
- label: {t("menus.header.ttapprovals")}
- });
- }
- accountingChildren.push(
+ },
+ ...(bodyshop?.md_tasks_presets?.use_approvals
+ ? [
+ {
+ key: "ttapprovals",
+ id: "header-accounting-ttapprovals",
+ icon: ,
+ label: {t("menus.header.ttapprovals")}
+ }
+ ]
+ : []),
{
key: "entertimetickets",
- icon: ,
+ id: "header-accounting-entertimetickets",
+ icon: ,
label: (
{t("menus.header.entertimeticket")}
),
- id: "header-accounting-entertimetickets",
- onClick: () => {
+ onClick: () =>
HasFeatureAccess({ featureName: "timetickets", bodyshop }) &&
- setTimeTicketContext({
- actions: {},
- context: {
- created_by: currentUser.displayName
- ? currentUser.email.concat(" | ", currentUser.displayName)
- : currentUser.email
- }
- });
- }
+ setTimeTicketContext({
+ actions: {},
+ context: {
+ created_by: currentUser.displayName
+ ? `${currentUser.email} | ${currentUser.displayName}`
+ : currentUser.email
+ }
+ })
},
+ { type: "divider" },
{
- type: "divider"
- }
- );
-
- const accountingExportChildren = [
- {
- key: "receivables",
- id: "header-accounting-receivables",
+ key: "accountingexport",
+ id: "header-accounting-export",
+ icon: ,
label: (
-
-
- {t("menus.header.accounting-receivables")}
-
-
- )
+
+ {t("menus.header.export")}
+
+ ),
+ children: [
+ {
+ key: "receivables",
+ id: "header-accounting-receivables",
+ label: (
+
+
+ {t("menus.header.accounting-receivables")}
+
+
+ )
+ },
+ ...(!((bodyshop && bodyshop.cdk_dealerid) || (bodyshop && bodyshop.pbs_serialnumber)) ||
+ DmsAp.treatment === "on"
+ ? [
+ {
+ key: "payables",
+ id: "header-accounting-payables",
+ label: (
+
+
+ {t("menus.header.accounting-payables")}
+
+
+ )
+ }
+ ]
+ : []),
+ ...(!((bodyshop && bodyshop.cdk_dealerid) || (bodyshop && bodyshop.pbs_serialnumber))
+ ? [
+ {
+ key: "payments",
+ id: "header-accounting-payments",
+ label: (
+
+
+ {t("menus.header.accounting-payments")}
+
+
+ )
+ }
+ ]
+ : []),
+ { type: "divider" },
+ {
+ key: "exportlogs",
+ id: "header-accounting-exportlogs",
+ label: (
+
+
+ {t("menus.header.export-logs")}
+
+
+ )
+ }
+ ]
}
];
- if (!((bodyshop && bodyshop.cdk_dealerid) || (bodyshop && bodyshop.pbs_serialnumber)) || DmsAp.treatment === "on") {
- accountingExportChildren.push({
- key: "payables",
- id: "header-accounting-payables",
- label: (
-
-
- {t("menus.header.accounting-payables")}
-
-
- )
- });
- }
-
- if (!((bodyshop && bodyshop.cdk_dealerid) || (bodyshop && bodyshop.pbs_serialnumber))) {
- accountingExportChildren.push({
- key: "payments",
- id: "header-accounting-payments",
- label: (
-
-
- {t("menus.header.accounting-payments")}
-
-
- )
- });
- }
-
- accountingExportChildren.push(
- {
- type: "divider"
- },
- {
- key: "exportlogs",
- id: "header-accounting-exportlogs",
- label: (
-
-
- {t("menus.header.export-logs")}
-
-
- )
- }
- );
-
- accountingChildren.push({
- key: "accountingexport",
- id: "header-accounting-export",
- icon: ,
- label: (
-
- {t("menus.header.export")}
-
- ),
- children: accountingExportChildren
- });
-
- const menuItems = [
+ // Left menu items (includes original navigation items)
+ const leftMenuItems = [
{
key: "home",
- icon: ,
id: "header-home",
+ icon: ,
label: {t("menus.header.home")}
},
{
key: "schedule",
id: "header-schedule",
- icon: ,
+ icon: ,
label: {t("menus.header.schedule")}
},
{
key: "jobssubmenu",
id: "header-jobs",
- icon: ,
+ icon: ,
label: t("menus.header.jobs"),
children: [
{
@@ -399,31 +394,24 @@ function Header({
icon: ,
label: {t("menus.header.newjob")}
},
- {
- type: "divider",
- id: "header-jobs-divider"
- },
+ { type: "divider" },
{
key: "alljobs",
id: "header-all-jobs",
icon: ,
label: {t("menus.header.alljobs")}
},
- {
- type: "divider",
- id: "header-jobs-divider2"
- },
+ { type: "divider" },
{
key: "productionlist",
id: "header-production-list",
icon: ,
label: {t("menus.header.productionlist")}
},
-
{
key: "productionboard",
id: "header-production-board",
- icon: ,
+ icon: ,
label: (
@@ -432,11 +420,7 @@ function Header({
)
},
-
- {
- type: "divider",
- id: "header-jobs-divider3"
- },
+ { type: "divider" },
{
key: "scoreboard",
id: "header-scoreboard",
@@ -453,8 +437,8 @@ function Header({
},
{
key: "customers",
- icon: ,
id: "header-customers",
+ icon: ,
label: t("menus.header.customers"),
children: [
{
@@ -519,7 +503,6 @@ function Header({
}
]
},
-
...(accountingChildren.length > 0
? [
{
@@ -537,7 +520,6 @@ function Header({
icon: ,
label: {t("menus.header.phonebook")}
},
-
{
key: "temporarydocs",
id: "header-temporarydocs",
@@ -550,7 +532,6 @@ function Header({
)
},
-
{
key: "tasks",
id: "tasks",
@@ -562,12 +543,7 @@ function Header({
id: "header-create-task",
icon: ,
label: t("menus.header.create_task"),
- onClick: () => {
- setTaskUpsertContext({
- actions: {},
- context: {}
- });
- }
+ onClick: () => setTaskUpsertContext({ actions: {}, context: {} })
},
{
key: "mytasks",
@@ -592,7 +568,7 @@ function Header({
{
key: "shop",
id: "header-shop",
- icon: ,
+ icon: ,
label: {t("menus.header.shop_config")}
},
{
@@ -610,24 +586,18 @@ function Header({
id: "header-reportcenter",
icon: ,
label: t("menus.header.reportcenter"),
- onClick: () => {
- setReportCenterContext({
- actions: {},
- context: {}
- });
- }
+ onClick: () => setReportCenterContext({ actions: {}, context: {} })
},
{
key: "shop-vendors",
id: "header-shop-vendors",
- icon: ,
+ icon: ,
label: {t("menus.header.shop_vendors")}
},
-
{
key: "shop-csi",
id: "header-shop-csi",
- icon: ,
+ icon: ,
label: (
@@ -638,14 +608,27 @@ function Header({
}
]
},
+ {
+ key: "recent",
+ id: "header-recent",
+ icon: ,
+ label: t("menus.header.recent"),
+ children: recentItems.map((i, idx) => ({
+ key: idx,
+ id: `header-recent-${idx}`,
+ label: {i.label}
+ }))
+ },
{
key: "user",
- label: currentUser.displayName || currentUser.email || t("general.labels.unknown"),
+ id: "header-user",
+ icon: ,
+ label: t("menus.currentuser.profile"),
children: [
{
key: "signout",
id: "header-signout",
- icon: ,
+ icon: ,
danger: true,
label: t("user.actions.signout"),
onClick: () => signOutStart()
@@ -653,33 +636,25 @@ function Header({
{
key: "help",
id: "header-help",
- icon: ,
+ icon: ,
label: t("menus.header.help"),
- onClick: () => {
- window.open("https://help.imex.online/", "_blank");
- }
+ onClick: () => window.open("https://help.imex.online/", "_blank")
},
- ...(InstanceRenderManager({
- imex: true,
- rome: false
- })
+ ...(InstanceRenderManager({ imex: true, rome: false })
? [
{
key: "rescue",
id: "header-rescue",
- icon: ,
+ icon: ,
label: t("menus.header.rescueme"),
- onClick: () => {
- window.open("https://imexrescue.com/", "_blank");
- }
+ onClick: () => window.open("https://imexrescue.com/", "_blank")
}
]
: []),
-
{
key: "shiftclock",
id: "header-shiftclock",
- icon: ,
+ icon: ,
label: (
@@ -688,64 +663,79 @@ function Header({
)
},
-
{
key: "profile",
id: "header-profile",
icon: ,
label: {t("menus.currentuser.profile")}
}
- // {
- // key: 'langselecter',
- // label: t("menus.currentuser.languageselector"),
- // children: [
- // {
- // key: 'en-US',
- // label: t("general.languages.english"),
- // onClick: () => {
- // window.location.href = "/?lang=en-US";
- // }
- // },
- // {
- // key: 'fr-CA',
- // label: t("general.languages.french"),
- // onClick: () => {
- // window.location.href = "/?lang=fr-CA";
- // }
- // },
- // {
- // key: 'es-MX',
- // label: t("general.languages.spanish"),
- // onClick: () => {
- // window.location.href = "/?lang=es-MX";
- // }
- // },
- // ]
- // },
]
- },
- {
- key: "recent",
- icon: ,
- id: "header-recent",
- children: recentItems.map((i, idx) => ({
- key: idx,
- id: `header-recent-${idx}`,
- label: {i.label}
- }))
}
];
+ // Notifications item (always on the right)
+ const notificationItem = scenarioNotificationsOn
+ ? [
+ {
+ key: "notifications",
+ id: "header-notifications",
+ icon: unreadLoading ? (
+
+ ) : (
+
+
+
+ ),
+ onClick: handleNotificationClick
+ }
+ ]
+ : [];
+
return (
-
-
+
+
+
+ {scenarioNotificationsOn && (
+
+ )}
+
+ {scenarioNotificationsOn && (
+ setNotificationVisible(false)}
+ unreadCount={unreadCount}
+ />
+ )}
);
}
diff --git a/client/src/components/header/header.container.jsx b/client/src/components/header/header.container.jsx
index 6920348ed..4bdb1e015 100644
--- a/client/src/components/header/header.container.jsx
+++ b/client/src/components/header/header.container.jsx
@@ -1,30 +1,7 @@
import { connect } from "react-redux";
import HeaderComponent from "./header.component";
-// const mapDispatchToProps = (dispatch) => ({
-// setUserLanguage: (language) => dispatch(setUserLanguage(language))
-// });
-
-// setUserLanguage was removed from signature because it is not used in the component, and it is throwing a deprecation warning
export function HeaderContainer() {
- // Commented out the handleMenuClick function because it is not used in the component, and it is throwing a deprecation warning
-
- /* const handleMenuClick = (e) => {
- if (e.item.props.actiontype === "lang-select") {
- i18next.changeLanguage(e.key, (err, t) => {
- if (err) {
- logImEXEvent("language_change_error", { error: err });
-
- return console.log("Error encountered when changing languages.", err);
- }
- logImEXEvent("language_change", { language: e.key });
-
- setUserLanguage(e.key);
- });
- }
- };*/
- // return ;
-
return ;
}
diff --git a/client/src/components/job-at-change/schedule-event.component.jsx b/client/src/components/job-at-change/schedule-event.component.jsx
index 97eded476..eb53dffd4 100644
--- a/client/src/components/job-at-change/schedule-event.component.jsx
+++ b/client/src/components/job-at-change/schedule-event.component.jsx
@@ -3,12 +3,12 @@ import { useMutation } from "@apollo/client";
import { Button, Divider, Dropdown, Form, Input, Popover, Select, Space } from "antd";
import parsePhoneNumber from "libphonenumber-js";
import queryString from "query-string";
-import React, { useContext, useState } from "react";
+import { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries";
import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions";
import { setModalContext } from "../../redux/modals/modals.actions";
@@ -51,7 +51,7 @@ export function ScheduleEventComponent({
const searchParams = queryString.parse(useLocation().search);
const [updateAppointment] = useMutation(UPDATE_APPOINTMENT);
const [title, setTitle] = useState(event.title);
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const notification = useNotification();
const blockContent = (
diff --git a/client/src/components/job-close-ro-guard/job-close-ro-guard.container.jsx b/client/src/components/job-close-ro-guard/job-close-ro-guard.container.jsx
index 6beffacb3..0ec9a0311 100644
--- a/client/src/components/job-close-ro-guard/job-close-ro-guard.container.jsx
+++ b/client/src/components/job-close-ro-guard/job-close-ro-guard.container.jsx
@@ -216,7 +216,7 @@ export function JobCloseRoGuardContainer({ job, jobRO, bodyshop, form }) {
-
+
diff --git a/client/src/components/job-detail-cards/job-detail-cards.component.jsx b/client/src/components/job-detail-cards/job-detail-cards.component.jsx
index 33315f959..5e5df5b58 100644
--- a/client/src/components/job-detail-cards/job-detail-cards.component.jsx
+++ b/client/src/components/job-detail-cards/job-detail-cards.component.jsx
@@ -1,17 +1,21 @@
-import { PrinterFilled } from "@ant-design/icons";
-import { useQuery } from "@apollo/client";
+import { PauseCircleOutlined, PlayCircleOutlined, PrinterFilled } from "@ant-design/icons";
+import { useMutation, useQuery } from "@apollo/client";
import { Button, Card, Col, Divider, Drawer, Grid, Row, Space } from "antd";
import queryString from "query-string";
-import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
-import { QUERY_JOB_CARD_DETAILS } from "../../graphql/jobs.queries";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
+import { logImEXEvent } from "../../firebase/firebase.utils";
+import { QUERY_JOB_CARD_DETAILS, UPDATE_JOB } from "../../graphql/jobs.queries";
+import { insertAuditTrail } from "../../redux/application/application.actions.js";
import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
+import AuditTrailMapping from "../../utils/AuditTrailMappings.js";
import AlertComponent from "../alert/alert.component";
import JobSyncButton from "../job-sync-button/job-sync-button.component";
+import JobWatcherToggleContainer from "../job-watcher-toggle/job-watcher-toggle.container.jsx";
import JobsDetailHeader from "../jobs-detail-header/jobs-detail-header.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import JobDetailCardsDamageComponent from "./job-detail-cards.damage.component";
@@ -27,7 +31,15 @@ const mapStateToProps = createStructuredSelector({
});
const mapDispatchToProps = (dispatch) => ({
- setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" }))
+ setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" })),
+ insertAuditTrail: ({ jobid, operation, type }) =>
+ dispatch(
+ insertAuditTrail({
+ jobid,
+ operation,
+ type
+ })
+ )
});
const span = {
@@ -36,7 +48,9 @@ const span = {
xxl: { span: 8 }
};
-export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
+export function JobDetailCards({ bodyshop, setPrintCenterContext, insertAuditTrail }) {
+ const { scenarioNotificationsOn } = useSocket();
+ const [updateJob] = useMutation(UPDATE_JOB);
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
.filter((screen) => !!screen[1])
.slice(-1)[0];
@@ -78,12 +92,39 @@ export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
{data ? (
{data.jobs_by_pk.ro_number || t("general.labels.na")}
+
+ {scenarioNotificationsOn && }
+
+ {data.jobs_by_pk.ro_number || t("general.labels.na")}
+
+
}
extra={
-
+ {
+ logImEXEvent("production_toggle_alert");
+ updateJob({
+ variables: {
+ jobId: data.jobs_by_pk.id,
+ job: {
+ suspended: !data.jobs_by_pk.suspended
+ }
+ }
+ });
+ insertAuditTrail({
+ jobid: data.jobs_by_pk.id,
+ operation: AuditTrailMapping.jobsuspend(
+ data.jobs_by_pk.suspended ? !data.jobs_by_pk.suspended : true
+ ),
+ type: "jobsuspend"
+ });
+ }}
+ icon={data.jobs_by_pk.suspended ? : }
+ >
+ {data.jobs_by_pk.suspended ? t("production.actions.unsuspend") : t("production.actions.suspend")}
+
{
setPrintCenterContext({
@@ -95,8 +136,8 @@ export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
}
});
}}
+ icon={ }
>
-
{t("jobs.actions.printCenter")}
@@ -122,7 +163,11 @@ export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
{!bodyshop.uselocalmediaserver && (
-
+
)}
diff --git a/client/src/components/job-totals-table/job-totals-table.component.jsx b/client/src/components/job-totals-table/job-totals-table.component.jsx
index e475ef5fd..8f390105d 100644
--- a/client/src/components/job-totals-table/job-totals-table.component.jsx
+++ b/client/src/components/job-totals-table/job-totals-table.component.jsx
@@ -69,7 +69,7 @@ export function JobsTotalsTableComponent({ jobRO, currentUser, job }) {
-
+
{JSON.stringify(
diff --git a/client/src/components/job-watcher-toggle/job-watcher-toggle.component.jsx b/client/src/components/job-watcher-toggle/job-watcher-toggle.component.jsx
new file mode 100644
index 000000000..879b8c1f7
--- /dev/null
+++ b/client/src/components/job-watcher-toggle/job-watcher-toggle.component.jsx
@@ -0,0 +1,154 @@
+import React from "react";
+import { EyeFilled, EyeOutlined, UserOutlined } from "@ant-design/icons";
+import { Avatar, Button, Divider, List, Popover, Select, Tooltip, Typography } from "antd";
+import { useTranslation } from "react-i18next";
+import EmployeeSearchSelectComponent from "../../components/employee-search-select/employee-search-select.component.jsx";
+import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component.jsx";
+import { BiSolidTrash } from "react-icons/bi";
+
+const { Text } = Typography;
+
+export default function JobWatcherToggleComponent({
+ jobWatchers,
+ isWatching,
+ watcherLoading,
+ adding,
+ removing,
+ open,
+ setOpen,
+ selectedWatcher,
+ setSelectedWatcher,
+ selectedTeam,
+ bodyshop,
+ Enhanced_Payroll,
+ handleToggleSelf,
+ handleRemoveWatcher,
+ handleWatcherSelect,
+ handleTeamSelect
+}) {
+ const { t } = useTranslation();
+
+ const handleRenderItem = (watcher) => {
+ // Check if watcher is defined and has user_email
+ if (!watcher || !watcher.user_email) {
+ return null; // Skip rendering invalid watchers
+ }
+
+ const employee = bodyshop?.employees?.find((e) => e.user_email === watcher.user_email);
+ const displayName = employee ? `${employee.first_name} ${employee.last_name}` : watcher.user_email;
+
+ return (
+ }
+ onClick={() => handleRemoveWatcher(watcher.user_email)}
+ disabled={adding || removing} // Optional: Disable button during mutations
+ >
+ {t("notifications.actions.remove")}
+
+ ]}
+ >
+ } />}
+ title={{displayName} }
+ description={watcher.user_email}
+ />
+
+ );
+ };
+
+ const popoverContent = (
+
+
+ : }
+ size="medium"
+ onClick={handleToggleSelf}
+ loading={adding || removing}
+ >
+ {isWatching ? t("notifications.labels.unwatch") : t("notifications.labels.watch")}
+
+ ]}
+ >
+
+
+ {t("notifications.labels.watching-issue")}
+
+
+
+
+ {watcherLoading ? (
+
+ ) : jobWatchers && jobWatchers.length > 0 ? (
+
+ ) : (
+
{t("notifications.labels.no-watchers")}
+ )}
+
+
+
{t("notifications.labels.add-watchers")}
+
+ jobWatchers.every((w) => w.user_email !== e.user_email && e.active && e.user_email)
+ ) || []
+ }
+ placeholder={t("notifications.labels.employee-search")}
+ value={selectedWatcher}
+ onChange={(value) => {
+ setSelectedWatcher(value);
+ handleWatcherSelect(value);
+ }}
+ />
+ {Enhanced_Payroll && bodyshop?.employee_teams?.length > 0 && (
+ <>
+
+ {t("notifications.labels.add-watchers-team")}
+ {
+ const teamMembers = team.employee_team_members
+ .map((member) => {
+ const employee = bodyshop?.employees?.find((e) => e.id === member.employeeid);
+ return employee?.user_email && employee?.active ? employee.user_email : null;
+ })
+ .filter(Boolean);
+ return {
+ value: JSON.stringify(teamMembers),
+ label: team.name
+ };
+ }) || []
+ }
+ />
+ >
+ )}
+
+ );
+
+ return (
+
+
+ : }
+ loading={watcherLoading}
+ />
+
+
+ );
+}
diff --git a/client/src/components/job-watcher-toggle/job-watcher-toggle.container.jsx b/client/src/components/job-watcher-toggle/job-watcher-toggle.container.jsx
new file mode 100644
index 000000000..d57fa6c89
--- /dev/null
+++ b/client/src/components/job-watcher-toggle/job-watcher-toggle.container.jsx
@@ -0,0 +1,219 @@
+import { useCallback, useEffect, useMemo, useState } from "react";
+import { useMutation, useQuery } from "@apollo/client";
+import { ADD_JOB_WATCHER, GET_JOB_WATCHERS, REMOVE_JOB_WATCHER } from "../../graphql/jobs.queries.js";
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors.js";
+import { useSplitTreatments } from "@splitsoftware/splitio-react";
+import JobWatcherToggleComponent from "./job-watcher-toggle.component.jsx";
+
+const mapStateToProps = createStructuredSelector({
+ bodyshop: selectBodyshop,
+ currentUser: selectCurrentUser
+});
+
+function JobWatcherToggleContainer({ job, currentUser, bodyshop }) {
+ const {
+ treatments: { Enhanced_Payroll }
+ } = useSplitTreatments({
+ attributes: {},
+ names: ["Enhanced_Payroll"],
+ splitKey: bodyshop && bodyshop.imexshopid
+ });
+
+ const userEmail = currentUser.email;
+ const jobid = job.id;
+
+ const [open, setOpen] = useState(false);
+ const [selectedWatcher, setSelectedWatcher] = useState(null);
+ const [selectedTeam, setSelectedTeam] = useState(null);
+
+ // Fetch current watchers with refetch capability
+ const {
+ data: watcherData,
+ loading: watcherLoading,
+ refetch
+ } = useQuery(GET_JOB_WATCHERS, {
+ variables: { jobid },
+ fetchPolicy: "cache-and-network" // Ensure fresh data from server
+ });
+
+ // Refetch jobWatchers when the popover opens (open changes to true)
+ useEffect(() => {
+ if (open) {
+ refetch().catch((err) =>
+ console.error(`Something went wrong fetching Notification Watchers on popover open: ${err?.message}`, {
+ stack: err?.stack
+ })
+ );
+ }
+ }, [open, refetch]);
+
+ const jobWatchers = useMemo(() => (watcherData?.job_watchers ? [...watcherData.job_watchers] : []), [watcherData]);
+ const isWatching = jobWatchers.some((w) => w.user_email === userEmail);
+
+ const [addWatcher, { loading: adding }] = useMutation(ADD_JOB_WATCHER, {
+ onCompleted: () =>
+ refetch().catch((err) =>
+ console.error(`Something went wrong fetching Notification Watchers after add: ${err?.message}`, {
+ stack: err?.stack
+ })
+ ),
+ onError: (err) => {
+ if (err.graphQLErrors && err.graphQLErrors.length > 0) {
+ const errorMessage = err.graphQLErrors[0].message;
+ if (
+ errorMessage.includes("Uniqueness violation") ||
+ errorMessage.includes("idx_job_watchers_jobid_user_email_unique")
+ ) {
+ console.warn("Watcher already exists for this job and user.");
+ refetch().catch((err) =>
+ console.error(
+ `Something went wrong fetching Notification Watchers after uniqueness violation: ${err?.message}`,
+ { stack: err?.stack }
+ )
+ ); // Sync with server to ensure UI reflects actual state
+ } else {
+ console.error(`Error adding job watcher: ${errorMessage}`);
+ }
+ } else {
+ console.error(`Unexpected error adding job watcher: ${err.message || JSON.stringify(err)}`);
+ }
+ },
+ update(cache, { data }) {
+ if (!data || !data.insert_job_watchers_one) {
+ console.warn("No data or insert_job_watchers_one returned from mutation, skipping cache update.");
+ refetch().catch((err) =>
+ console.error(`Something went wrong updating Notification Watchers after add: ${err?.message}`, {
+ stack: err?.stack
+ })
+ );
+ return;
+ }
+
+ const insert_job_watchers_one = data.insert_job_watchers_one;
+ const existingData = cache.readQuery({
+ query: GET_JOB_WATCHERS,
+ variables: { jobid }
+ });
+
+ cache.writeQuery({
+ query: GET_JOB_WATCHERS,
+ variables: { jobid },
+ data: {
+ ...existingData,
+ job_watchers: [...(existingData?.job_watchers || []), insert_job_watchers_one]
+ }
+ });
+ }
+ });
+
+ const [removeWatcher, { loading: removing }] = useMutation(REMOVE_JOB_WATCHER, {
+ onCompleted: () =>
+ refetch().catch((err) =>
+ console.error(`Something went wrong fetching Notification Watchers after remove: ${err?.message}`, {
+ stack: err?.stack
+ })
+ ), // Refetch to sync with server after success
+ onError: (err) => console.error(`Error removing job watcher: ${err.message}`),
+ update(cache, { data: { delete_job_watchers } }) {
+ const existingData = cache.readQuery({
+ query: GET_JOB_WATCHERS,
+ variables: { jobid }
+ });
+
+ const deletedWatcher = delete_job_watchers.returning[0];
+ const updatedWatchers = deletedWatcher
+ ? (existingData?.job_watchers || []).filter((watcher) => watcher.user_email !== deletedWatcher.user_email)
+ : existingData?.job_watchers || [];
+
+ cache.writeQuery({
+ query: GET_JOB_WATCHERS,
+ variables: { jobid },
+ data: {
+ ...existingData,
+ job_watchers: updatedWatchers
+ }
+ });
+ }
+ });
+
+ const handleToggleSelf = useCallback(async () => {
+ if (adding || removing) return;
+ if (isWatching) {
+ await removeWatcher({ variables: { jobid, userEmail } });
+ } else {
+ await addWatcher({ variables: { jobid, userEmail } });
+ }
+ }, [isWatching, addWatcher, removeWatcher, jobid, userEmail, adding, removing]);
+
+ const handleRemoveWatcher = useCallback(
+ async (email) => {
+ if (removing) return;
+ await removeWatcher({ variables: { jobid, userEmail: email } });
+ },
+ [removeWatcher, jobid, removing]
+ );
+
+ const handleWatcherSelect = useCallback(
+ async (selectedUser) => {
+ if (adding || removing) return;
+ const employee = bodyshop.employees.find((e) => e.id === selectedUser);
+ if (!employee) return;
+
+ const email = employee.user_email;
+ const isAlreadyWatching = jobWatchers.some((w) => w.user_email === email);
+
+ if (isAlreadyWatching) {
+ await handleRemoveWatcher(email);
+ } else {
+ await addWatcher({ variables: { jobid, userEmail: email } });
+ }
+ setSelectedWatcher(null);
+ },
+ [jobWatchers, addWatcher, handleRemoveWatcher, jobid, bodyshop, adding, removing]
+ );
+
+ const handleTeamSelect = useCallback(
+ async (team) => {
+ if (adding) return;
+ const selectedTeamMembers = JSON.parse(team);
+ const newWatchers = selectedTeamMembers.filter(
+ (email) => !jobWatchers.some((watcher) => watcher.user_email === email)
+ );
+
+ if (newWatchers.length === 0) {
+ console.warn("All selected team members are already watchers.");
+ setSelectedTeam(null);
+ return;
+ }
+ await Promise.all(newWatchers.map((email) => addWatcher({ variables: { jobid, userEmail: email } })));
+ },
+ [jobWatchers, addWatcher, jobid, adding]
+ );
+
+ return (
+
+ );
+}
+
+export default connect(mapStateToProps)(JobWatcherToggleContainer);
diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx
index ee644654a..02a6b3494 100644
--- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx
+++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx
@@ -4,12 +4,12 @@ import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Button, Card, Dropdown, Form, Input, Modal, Popconfirm, Popover, Select, Space } from "antd";
import axios from "axios";
import parsePhoneNumber from "libphonenumber-js";
-import { useContext, useMemo, useState } from "react";
+import { useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
import { CANCEL_APPOINTMENTS_BY_JOB_ID, INSERT_MANUAL_APPT } from "../../graphql/appointments.queries";
import { GET_CURRENT_QUESTIONSET_ID, INSERT_CSI } from "../../graphql/csi.queries";
@@ -28,11 +28,11 @@ import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
import FormDateTimePickerComponent from "../form-date-time-picker/form-date-time-picker.component";
import LockerWrapperComponent from "../lock-wrapper/lock-wrapper.component";
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
+import ShareToTeamsButton from "../share-to-teams/share-to-teams.component.jsx";
import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
import JobsDetailHeaderActionsToggleProduction from "./jobs-detail-header-actions.toggle-production";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
-import ShareToTeamsButton from "../share-to-teams/share-to-teams.component.jsx";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -130,7 +130,7 @@ export function JobsDetailHeaderActions({
const [updateJob] = useMutation(UPDATE_JOB);
const [voidJob] = useMutation(VOID_JOB);
const [cancelAllAppointments] = useMutation(CANCEL_APPOINTMENTS_BY_JOB_ID);
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const notification = useNotification();
const {
@@ -775,15 +775,14 @@ export function JobsDetailHeaderActions({
key: "enterpayments",
id: "job-actions-enterpayments",
disabled: !job.converted,
- label: {t("menus.header.enterpayment")} ,
+ label: t("menus.header.enterpayment"),
onClick: () => {
logImEXEvent("job_header_enter_payment");
- HasFeatureAccess({ featureName: "payments", bodyshop }) &&
- setPaymentContext({
- actions: {},
- context: { jobid: job.id }
- });
+ setPaymentContext({
+ actions: {},
+ context: { jobid: job.id }
+ });
}
});
diff --git a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx
index ffe729b51..dd49ffee0 100644
--- a/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx
+++ b/client/src/components/jobs-detail-header/jobs-detail-header.component.jsx
@@ -119,7 +119,7 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
{job.cccontracts.map((c, index) => (
-
+
{`${c.agreementnumber} - ${c.courtesycar.fleetnumber} ${c.courtesycar.year} ${c.courtesycar.make} ${c.courtesycar.model}`}
{index !== job.cccontracts.length - 1 ? "," : null}
diff --git a/client/src/components/jobs-detail-rates/jobs-detail-rates.component.jsx b/client/src/components/jobs-detail-rates/jobs-detail-rates.component.jsx
index 98a76f7b5..300f45f5a 100644
--- a/client/src/components/jobs-detail-rates/jobs-detail-rates.component.jsx
+++ b/client/src/components/jobs-detail-rates/jobs-detail-rates.component.jsx
@@ -5,6 +5,7 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
+import InstanceRenderManager from "../../utils/instanceRenderMgr";
import CABCpvrtCalculator from "../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
@@ -14,9 +15,8 @@ import JobsDetailRatesLabor from "./jobs-detail-rates.labor.component";
import JobsDetailRatesMaterials from "./jobs-detail-rates.materials.component";
import JobsDetailRatesOther from "./jobs-detail-rates.other.component";
import JobsDetailRatesParts from "./jobs-detail-rates.parts.component";
-import JobsDetailRatesTaxes from "./jobs-detail-rates.taxes.component";
import JobsDetailRatesProfileOVerride from "./jobs-detail-rates.profile-override.component";
-import InstanceRenderManager from "../../utils/instanceRenderMgr";
+import JobsDetailRatesTaxes from "./jobs-detail-rates.taxes.component";
const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly,
@@ -66,14 +66,48 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
)}
-
+ {
+ if (checked) {
+ form.setFieldsValue({ flat_rate_ats: false });
+ form.setFieldsValue({ rate_ats: form.getFieldValue('rate_ats') || bodyshop.shoprates.rate_ats });
+ }
+ }}
+ />
-
prev.auto_add_ats !== cur.auto_add_ats}>
{() => {
if (form.getFieldValue("auto_add_ats"))
return (
-
+
+
+
+ );
+
+ return null;
+ }}
+
+
+ {
+ if (checked) {
+ form.setFieldsValue({ auto_add_ats: false });
+ form.setFieldsValue({ rate_ats_flat: form.getFieldValue('rate_ats_flat') || bodyshop.shoprates.rate_ats_flat });
+
+ }
+ }}
+ />
+
+ prev.flat_rate_ats !== cur.flat_rate_ats}>
+ {() => {
+ if (form.getFieldValue("flat_rate_ats"))
+ return (
+
);
diff --git a/client/src/components/notification-center/notification-center.component.jsx b/client/src/components/notification-center/notification-center.component.jsx
new file mode 100644
index 000000000..f72d2bd48
--- /dev/null
+++ b/client/src/components/notification-center/notification-center.component.jsx
@@ -0,0 +1,122 @@
+import { Virtuoso } from "react-virtuoso";
+import { Badge, Button, Space, Spin, Switch, Tooltip, Typography } from "antd";
+import { CheckCircleFilled, CheckCircleOutlined, EyeFilled, EyeOutlined } from "@ant-design/icons";
+import { useTranslation } from "react-i18next";
+import { useNavigate } from "react-router-dom";
+import "./notification-center.styles.scss";
+import day from "../../utils/day.js";
+import { forwardRef, useRef, useEffect } from "react";
+import { DateTimeFormat } from "../../utils/DateFormatter.jsx";
+
+const { Text, Title } = Typography;
+
+/**
+ * Notification Center Component
+ * @type {React.ForwardRefExoticComponent & React.RefAttributes>}
+ */
+const NotificationCenterComponent = forwardRef(
+ (
+ {
+ visible,
+ onClose,
+ notifications,
+ loading,
+ showUnreadOnly,
+ toggleUnreadOnly,
+ markAllRead,
+ loadMore,
+ onNotificationClick,
+ unreadCount
+ },
+ ref
+ ) => {
+ const { t } = useTranslation();
+ const navigate = useNavigate();
+ const virtuosoRef = useRef(null);
+
+ // Scroll to top when showUnreadOnly changes
+ useEffect(() => {
+ if (virtuosoRef.current) {
+ virtuosoRef.current.scrollToIndex({ index: 0, behavior: "smooth" });
+ }
+ }, [showUnreadOnly]);
+
+ const renderNotification = (index, notification) => {
+ const handleClick = () => {
+ if (!notification.read) {
+ onNotificationClick(notification.id);
+ }
+ navigate(`/manage/jobs/${notification.jobid}`);
+ };
+
+ return (
+
+
+
+
+
+ {t("notifications.labels.ro-number", { ro_number: notification.roNumber || t("general.labels.na") })}
+
+
+ {day(notification.created_at).fromNow()}
+
+
+
+
+ {notification.scenarioText.map((text, idx) => (
+ {text}
+ ))}
+
+
+
+
+
+ );
+ };
+
+ return (
+
+
+
+ {t("notifications.labels.notification-center")}
+ {loading && }
+
+
+
+
+ {showUnreadOnly ? (
+
+ ) : (
+
+ )}
+ toggleUnreadOnly(checked)} size="small" />
+
+
+
+ : }
+ onClick={markAllRead}
+ disabled={!unreadCount}
+ />
+
+
+
+
+
+ );
+ }
+);
+
+export default NotificationCenterComponent;
diff --git a/client/src/components/notification-center/notification-center.container.jsx b/client/src/components/notification-center/notification-center.container.jsx
new file mode 100644
index 000000000..ae12552f3
--- /dev/null
+++ b/client/src/components/notification-center/notification-center.container.jsx
@@ -0,0 +1,202 @@
+import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+import { useQuery } from "@apollo/client";
+import { connect } from "react-redux";
+import NotificationCenterComponent from "./notification-center.component";
+import { GET_NOTIFICATIONS } from "../../graphql/notifications.queries";
+import { INITIAL_NOTIFICATIONS, useSocket } from "../../contexts/SocketIO/useSocket.jsx";
+import { createStructuredSelector } from "reselect";
+import { selectBodyshop } from "../../redux/user/user.selectors.js";
+import day from "../../utils/day.js";
+
+// This will be used to poll for notifications when the socket is disconnected
+const NOTIFICATION_POLL_INTERVAL_SECONDS = 60;
+
+/**
+ * Notification Center Container
+ * @param visible
+ * @param onClose
+ * @param bodyshop
+ * @param unreadCount
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const NotificationCenterContainer = ({ visible, onClose, bodyshop, unreadCount }) => {
+ const [showUnreadOnly, setShowUnreadOnly] = useState(false);
+ const [notifications, setNotifications] = useState([]);
+ const [isLoading, setIsLoading] = useState(false);
+ const { isConnected, markNotificationRead, markAllNotificationsRead } = useSocket();
+ const notificationRef = useRef(null);
+
+ const userAssociationId = bodyshop?.associations?.[0]?.id;
+
+ const baseWhereClause = useMemo(() => {
+ return { associationid: { _eq: userAssociationId } };
+ }, [userAssociationId]);
+
+ const whereClause = useMemo(() => {
+ return showUnreadOnly ? { ...baseWhereClause, read: { _is_null: true } } : baseWhereClause;
+ }, [baseWhereClause, showUnreadOnly]);
+
+ const {
+ data,
+ fetchMore,
+ loading: queryLoading,
+ refetch
+ } = useQuery(GET_NOTIFICATIONS, {
+ variables: {
+ limit: INITIAL_NOTIFICATIONS,
+ offset: 0,
+ where: whereClause
+ },
+ fetchPolicy: "cache-and-network",
+ notifyOnNetworkStatusChange: true,
+ pollInterval: isConnected ? 0 : day.duration(NOTIFICATION_POLL_INTERVAL_SECONDS, "seconds").asMilliseconds(),
+ skip: !userAssociationId,
+ onError: (err) => {
+ console.error(`Error polling Notifications: ${err?.message || ""}`);
+ setTimeout(() => refetch(), day.duration(2, "seconds").asMilliseconds());
+ }
+ });
+
+ useEffect(() => {
+ const handleClickOutside = (event) => {
+ // Prevent open + close behavior from the header
+ if (event.target.closest("#header-notifications")) return;
+ if (visible && notificationRef.current && !notificationRef.current.contains(event.target)) {
+ onClose();
+ }
+ };
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => document.removeEventListener("mousedown", handleClickOutside);
+ }, [visible, onClose]);
+
+ useEffect(() => {
+ if (data?.notifications) {
+ const processedNotifications = data.notifications
+ .map((notif) => {
+ let scenarioText;
+ let scenarioMeta;
+ try {
+ scenarioText = notif.scenario_text ? JSON.parse(notif.scenario_text) : [];
+ scenarioMeta = notif.scenario_meta ? JSON.parse(notif.scenario_meta) : {};
+ } catch (e) {
+ console.error("Error parsing JSON for notification:", notif.id, e);
+ scenarioText = [notif.fcm_text || "Invalid notification data"];
+ scenarioMeta = {};
+ }
+ if (!Array.isArray(scenarioText)) scenarioText = [scenarioText];
+ const roNumber = notif.job.ro_number;
+ if (!Array.isArray(scenarioMeta)) scenarioMeta = [scenarioMeta];
+ return {
+ id: notif.id,
+ jobid: notif.jobid,
+ associationid: notif.associationid,
+ scenarioText,
+ scenarioMeta,
+ roNumber,
+ created_at: notif.created_at,
+ read: notif.read,
+ __typename: notif.__typename
+ };
+ })
+ .sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
+ setNotifications(processedNotifications);
+ }
+ }, [data]);
+
+ const loadMore = useCallback(() => {
+ if (!queryLoading && data?.notifications.length) {
+ setIsLoading(true); // Show spinner during fetchMore
+ fetchMore({
+ variables: { offset: data.notifications.length, where: whereClause },
+ updateQuery: (prev, { fetchMoreResult }) => {
+ if (!fetchMoreResult) return prev;
+ return {
+ notifications: [...prev.notifications, ...fetchMoreResult.notifications]
+ };
+ }
+ })
+ .catch((err) => {
+ console.error("Fetch more error:", err);
+ })
+ .finally(() => setIsLoading(false)); // Hide spinner when done
+ }
+ }, [data?.notifications?.length, fetchMore, queryLoading, whereClause]);
+
+ const handleToggleUnreadOnly = (value) => {
+ setShowUnreadOnly(value);
+ };
+
+ const handleMarkAllRead = useCallback(() => {
+ setIsLoading(true);
+ markAllNotificationsRead()
+ .then(() => {
+ const timestamp = new Date().toISOString();
+ setNotifications((prev) => {
+ const updatedNotifications = prev.map((notif) =>
+ notif.read === null && notif.associationid === userAssociationId
+ ? {
+ ...notif,
+ read: timestamp
+ }
+ : notif
+ );
+ // Filter out read notifications if in unread only mode
+ return showUnreadOnly ? updatedNotifications.filter((notif) => !notif.read) : updatedNotifications;
+ });
+ })
+ .catch((e) => console.error(`Error marking all notifications read: ${e?.message || ""}`))
+ .finally(() => setIsLoading(false));
+ }, [markAllNotificationsRead, userAssociationId, showUnreadOnly]);
+
+ const handleNotificationClick = useCallback(
+ (notificationId) => {
+ setIsLoading(true);
+ markNotificationRead({ variables: { id: notificationId } })
+ .then(() => {
+ const timestamp = new Date().toISOString();
+ setNotifications((prev) => {
+ const updatedNotifications = prev.map((notif) =>
+ notif.id === notificationId && !notif.read ? { ...notif, read: timestamp } : notif
+ );
+ // Filter out the read notification if in unread only mode
+ return showUnreadOnly ? updatedNotifications.filter((notif) => !notif.read) : updatedNotifications;
+ });
+ })
+ .catch((e) => console.error(`Error marking notification read: ${e?.message || ""}`))
+ .finally(() => setIsLoading(false));
+ },
+ [markNotificationRead, showUnreadOnly]
+ );
+
+ useEffect(() => {
+ if (visible && !isConnected) {
+ setIsLoading(true);
+ refetch()
+ .catch((err) => console.error(`Error re-fetching notifications: ${err?.message || ""}`))
+ .finally(() => setIsLoading(false));
+ }
+ }, [visible, isConnected, refetch]);
+
+ return (
+
+ );
+};
+
+const mapStateToProps = createStructuredSelector({
+ bodyshop: selectBodyshop
+});
+
+export default connect(mapStateToProps, null)(NotificationCenterContainer);
diff --git a/client/src/components/notification-center/notification-center.styles.scss b/client/src/components/notification-center/notification-center.styles.scss
new file mode 100644
index 000000000..89ae0beae
--- /dev/null
+++ b/client/src/components/notification-center/notification-center.styles.scss
@@ -0,0 +1,175 @@
+.notification-center {
+ position: absolute;
+ top: 64px;
+ right: 0;
+ width: 400px;
+ max-width: 400px;
+ background: #fff;
+ color: rgba(0, 0, 0, 0.85);
+ border: 1px solid #d9d9d9;
+ border-radius: 6px;
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08), 0 3px 6px rgba(0, 0, 0, 0.06);
+ z-index: 1000;
+ display: none;
+ overflow-x: hidden;
+
+ &.visible {
+ display: block;
+ }
+
+ .notification-header {
+ padding: 4px 16px;
+ border-bottom: 1px solid #f0f0f0;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ background: #fafafa;
+
+ h3 {
+ margin: 0;
+ font-size: 14px;
+ color: rgba(0, 0, 0, 0.85);
+ }
+
+ .notification-controls {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+
+ // Styles for the eye icon and switch (custom classes)
+ .notification-toggle {
+ align-items: center; // Ensure vertical alignment
+ }
+
+ .notification-toggle-icon {
+ font-size: 14px;
+ color: #1677ff;
+ vertical-align: middle;
+ }
+
+ .ant-switch {
+ &.ant-switch-small {
+ min-width: 28px;
+ height: 16px;
+ line-height: 16px;
+
+ .ant-switch-handle {
+ width: 12px;
+ height: 12px;
+ }
+
+ &.ant-switch-checked {
+ background-color: #1677ff;
+ .ant-switch-handle {
+ left: calc(100% - 14px);
+ }
+ }
+ }
+ }
+
+ // Styles for the "Mark All Read" button (restore original link button style)
+ .ant-btn-link {
+ padding: 0;
+ color: #1677ff;
+
+ &:hover {
+ color: #69b1ff;
+ }
+
+ &:disabled {
+ color: rgba(0, 0, 0, 0.25);
+ cursor: not-allowed;
+ }
+
+ &.active {
+ color: #0958d9;
+ }
+ }
+ }
+ }
+
+ .notification-read {
+ background: #fff;
+ color: rgba(0, 0, 0, 0.65);
+ }
+
+ .notification-unread {
+ background: #f5f5f5;
+ color: rgba(0, 0, 0, 0.85);
+ }
+
+ .notification-item {
+ padding: 12px 16px;
+ border-bottom: 1px solid #f0f0f0;
+ display: block;
+ overflow: visible;
+ width: 100%;
+ box-sizing: border-box;
+ cursor: pointer;
+
+ &:hover {
+ background: #fafafa;
+ }
+
+ .notification-content {
+ width: 100%;
+ }
+
+ .notification-title {
+ margin: 0;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ width: 100%;
+ box-sizing: border-box;
+
+ .ro-number {
+ margin: 0;
+ color: #1677ff;
+ flex-shrink: 0;
+ white-space: nowrap;
+ }
+
+ .relative-time {
+ margin: 0;
+ font-size: 12px;
+ color: rgba(0, 0, 0, 0.45);
+ white-space: nowrap;
+ flex-shrink: 0;
+ margin-left: auto;
+ }
+ }
+
+ .notification-body {
+ margin-top: 4px;
+
+ .ant-typography {
+ color: inherit;
+ }
+
+ ul {
+ margin: 0;
+ padding: 0;
+ }
+
+ li {
+ margin-bottom: 2px;
+ }
+ }
+ }
+
+ .ant-badge {
+ width: 100%;
+ }
+
+ .ant-alert {
+ margin: 8px;
+ background: #fff1f0;
+ color: rgba(0, 0, 0, 0.85);
+ border: 1px solid #ffa39e;
+
+ .ant-alert-message {
+ color: #ff4d4f;
+ }
+ }
+}
diff --git a/client/src/components/notification-settings/column-header-checkbox.component.jsx b/client/src/components/notification-settings/column-header-checkbox.component.jsx
new file mode 100644
index 000000000..5a857921e
--- /dev/null
+++ b/client/src/components/notification-settings/column-header-checkbox.component.jsx
@@ -0,0 +1,56 @@
+import { notificationScenarios } from "../../utils/jobNotificationScenarios.js";
+import { Checkbox, Form } from "antd";
+import { useTranslation } from "react-i18next";
+import PropTypes from "prop-types";
+
+/**
+ * ColumnHeaderCheckbox
+ * @param channel
+ * @param form
+ * @param disabled
+ * @param onHeaderChange
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const ColumnHeaderCheckbox = ({ channel, form, disabled = false, onHeaderChange }) => {
+ const { t } = useTranslation();
+
+ // Subscribe to all form values so that this component re-renders on changes.
+ const formValues = Form.useWatch([], form) || {};
+
+ // Determine if all scenarios for this channel are checked.
+ const allChecked =
+ notificationScenarios.length > 0 && notificationScenarios.every((scenario) => formValues[scenario]?.[channel]);
+
+ const onChange = (e) => {
+ const checked = e.target.checked;
+ // Get current form values.
+ const currentValues = form.getFieldsValue();
+ // Update each scenario for this channel.
+ const newValues = { ...currentValues };
+ notificationScenarios.forEach((scenario) => {
+ newValues[scenario] = { ...newValues[scenario], [channel]: checked };
+ });
+ // Update form values.
+ form.setFieldsValue(newValues);
+ // Manually mark the form as dirty.
+ if (onHeaderChange) {
+ onHeaderChange();
+ }
+ };
+
+ return (
+
+ {t(`notifications.channels.${channel}`)}
+
+ );
+};
+
+ColumnHeaderCheckbox.propTypes = {
+ channel: PropTypes.oneOf(["app", "email", "fcm"]).isRequired,
+ form: PropTypes.object.isRequired,
+ disabled: PropTypes.bool,
+ onHeaderChange: PropTypes.func
+};
+
+export default ColumnHeaderCheckbox;
diff --git a/client/src/components/notification-settings/notification-settings-form.component.jsx b/client/src/components/notification-settings/notification-settings-form.component.jsx
new file mode 100644
index 000000000..859826bbc
--- /dev/null
+++ b/client/src/components/notification-settings/notification-settings-form.component.jsx
@@ -0,0 +1,168 @@
+import { useMutation, useQuery } from "@apollo/client";
+import { useEffect, useState } from "react";
+import { Button, Card, Checkbox, Form, Space, Table } from "antd";
+import { useTranslation } from "react-i18next";
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import { selectCurrentUser } from "../../redux/user/user.selectors";
+import AlertComponent from "../alert/alert.component";
+import { QUERY_NOTIFICATION_SETTINGS, UPDATE_NOTIFICATION_SETTINGS } from "../../graphql/user.queries.js";
+import { notificationScenarios } from "../../utils/jobNotificationScenarios.js";
+import LoadingSpinner from "../loading-spinner/loading-spinner.component.jsx";
+import PropTypes from "prop-types";
+import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
+import ColumnHeaderCheckbox from "../notification-settings/column-header-checkbox.component.jsx";
+
+/**
+ * Notifications Settings Form
+ * @param currentUser
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const NotificationSettingsForm = ({ currentUser }) => {
+ const { t } = useTranslation();
+ const [form] = Form.useForm();
+ const [initialValues, setInitialValues] = useState({});
+ const [isDirty, setIsDirty] = useState(false);
+ const notification = useNotification();
+
+ // Fetch notification settings.
+ const { loading, error, data } = useQuery(QUERY_NOTIFICATION_SETTINGS, {
+ fetchPolicy: "network-only",
+ nextFetchPolicy: "network-only",
+ variables: { email: currentUser.email },
+ skip: !currentUser
+ });
+
+ const [updateNotificationSettings, { loading: saving }] = useMutation(UPDATE_NOTIFICATION_SETTINGS);
+
+ // Populate form with fetched data.
+ useEffect(() => {
+ if (data?.associations?.length > 0) {
+ const settings = data.associations[0].notification_settings || {};
+ // Ensure each scenario has an object with { app, email, fcm }.
+ const formattedValues = notificationScenarios.reduce((acc, scenario) => {
+ acc[scenario] = settings[scenario] ?? { app: false, email: false, fcm: false };
+ return acc;
+ }, {});
+
+ setInitialValues(formattedValues);
+ form.setFieldsValue(formattedValues);
+ setIsDirty(false); // Reset dirty state when new data loads.
+ }
+ }, [data, form]);
+
+ const handleSave = async (values) => {
+ if (data?.associations?.length > 0) {
+ const userId = data.associations[0].id;
+ // Save the updated notification settings.
+ const result = await updateNotificationSettings({ variables: { id: userId, ns: values } });
+ if (!result?.errors) {
+ notification.success({ message: t("notifications.labels.notification-settings-success") });
+ setInitialValues(values);
+ setIsDirty(false);
+ } else {
+ notification.error({ message: t("notifications.labels.notification-settings-failure") });
+ }
+ }
+ };
+
+ // Mark the form as dirty on any manual change.
+ const handleFormChange = () => {
+ setIsDirty(true);
+ };
+
+ const handleReset = () => {
+ form.setFieldsValue(initialValues);
+ setIsDirty(false);
+ };
+
+ if (error) return ;
+ if (loading) return ;
+
+ const columns = [
+ {
+ title: t("notifications.labels.scenario"),
+ dataIndex: "scenarioLabel",
+ key: "scenario",
+ render: (_, record) => t(`notifications.scenarios.${record.key}`),
+ width: "90%"
+ },
+ {
+ title: setIsDirty(true)} />,
+ dataIndex: "app",
+ key: "app",
+ align: "center",
+ render: (_, record) => (
+
+
+
+ )
+ },
+ {
+ title: setIsDirty(true)} />,
+ dataIndex: "email",
+ key: "email",
+ align: "center",
+ render: (_, record) => (
+
+
+
+ )
+ }
+ // TODO: Disabled for now until FCM is implemented.
+ // {
+ // title: setIsDirty(true)} />,
+ // dataIndex: "fcm",
+ // key: "fcm",
+ // align: "center",
+ // render: (_, record) => (
+ //
+ //
+ //
+ // )
+ // }
+ ];
+
+ const dataSource = notificationScenarios.map((scenario) => ({ key: scenario }));
+
+ return (
+
+ );
+};
+
+NotificationSettingsForm.propTypes = {
+ currentUser: PropTypes.shape({
+ email: PropTypes.string.isRequired
+ }).isRequired
+};
+
+const mapStateToProps = createStructuredSelector({
+ currentUser: selectCurrentUser
+});
+
+export default connect(mapStateToProps)(NotificationSettingsForm);
diff --git a/client/src/components/payments-generate-link/payments-generate-link.component.jsx b/client/src/components/payments-generate-link/payments-generate-link.component.jsx
index f9d84d10f..7e121621f 100644
--- a/client/src/components/payments-generate-link/payments-generate-link.component.jsx
+++ b/client/src/components/payments-generate-link/payments-generate-link.component.jsx
@@ -2,15 +2,15 @@ import { CopyFilled } from "@ant-design/icons";
import { Button, Form, message, Popover, Space } from "antd";
import axios from "axios";
import Dinero from "dinero.js";
-import { parsePhoneNumber } from "libphonenumber-js";
-import React, { useContext, useState } from "react";
+import { parsePhoneNumberWithError, ParseError } from "libphonenumber-js";
+import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -29,22 +29,34 @@ export function PaymentsGenerateLink({ bodyshop, currentUser, callback, job, ope
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [paymentLink, setPaymentLink] = useState(null);
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const handleFinish = async ({ amount }) => {
setLoading(true);
let p;
try {
- p = parsePhoneNumber(job.ownr_ph1 || "", "CA");
+ // Updated to use parsePhoneNumberWithError
+ p = parsePhoneNumberWithError(job.ownr_ph1 || "", "CA");
} catch (error) {
- console.log("Unable to parse phone number");
+ if (error instanceof ParseError) {
+ // Handle specific parsing errors
+ console.log(`Phone number parsing failed: ${error.message}`);
+ } else {
+ // Handle other unexpected errors
+ console.log("Unexpected error while parsing phone number:", error);
+ }
}
setLoading(true);
const response = await axios.post("/intellipay/generate_payment_url", {
bodyshop,
amount: amount,
account: job.ro_number,
- comment: btoa(JSON.stringify({ payments: [{ jobid: job.id, amount }], userEmail: currentUser.email }))
+ comment: btoa(
+ JSON.stringify({
+ payments: [{ jobid: job.id, amount }],
+ userEmail: currentUser.email
+ })
+ )
});
setLoading(false);
setPaymentLink(response.data.shorUrl);
@@ -106,7 +118,20 @@ export function PaymentsGenerateLink({ bodyshop, currentUser, callback, job, ope
{
- const p = parsePhoneNumber(job.ownr_ph1, "CA");
+ let p;
+ try {
+ // Updated second instance of phone parsing
+ p = parsePhoneNumberWithError(job.ownr_ph1, "CA");
+ } catch (error) {
+ if (error instanceof ParseError) {
+ // Handle specific parsing errors
+ console.log(`Phone number parsing failed: ${error.message}`);
+ } else {
+ // Handle other unexpected errors
+ console.log("Unexpected error while parsing phone number:", error);
+ }
+ return;
+ }
openChatByPhone({
phone_num: p.formatInternational(),
jobid: job.id,
diff --git a/client/src/components/production-board-kanban/production-board-kanban.component.jsx b/client/src/components/production-board-kanban/production-board-kanban.component.jsx
index 574ee1c5a..d8315f576 100644
--- a/client/src/components/production-board-kanban/production-board-kanban.component.jsx
+++ b/client/src/components/production-board-kanban/production-board-kanban.component.jsx
@@ -4,7 +4,7 @@ import { useApolloClient } from "@apollo/client";
import { Button, Skeleton, Space } from "antd";
import cloneDeep from "lodash/cloneDeep";
import isEqual from "lodash/isEqual";
-import React, { useCallback, useEffect, useMemo, useState } from "react";
+import { useCallback, useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
diff --git a/client/src/components/production-board-kanban/production-board-kanban.container.jsx b/client/src/components/production-board-kanban/production-board-kanban.container.jsx
index 07164c63c..3b0c4066f 100644
--- a/client/src/components/production-board-kanban/production-board-kanban.container.jsx
+++ b/client/src/components/production-board-kanban/production-board-kanban.container.jsx
@@ -1,4 +1,4 @@
-import React, { useContext, useEffect, useMemo, useRef } from "react";
+import { useEffect, useMemo, useRef } from "react";
import { useApolloClient, useQuery, useSubscription } from "@apollo/client";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
@@ -12,7 +12,7 @@ import { QUERY_KANBAN_SETTINGS } from "../../graphql/user.queries";
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
import ProductionBoardKanbanComponent from "./production-board-kanban.component";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -22,7 +22,7 @@ const mapStateToProps = createStructuredSelector({
function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionType = "direct" }) {
const fired = useRef(false);
const client = useApolloClient();
- const { socket } = useContext(SocketContext); // Get the socket from context
+ const { socket } = useSocket();
const reconnectTimeout = useRef(null); // To store the reconnect timeout
const disconnectTime = useRef(null); // To track disconnection time
const acceptableReconnectTime = 2000; // 2 seconds threshold
diff --git a/client/src/components/production-list-detail/production-list-detail.component.jsx b/client/src/components/production-list-detail/production-list-detail.component.jsx
index a5b06d109..7db55bd07 100644
--- a/client/src/components/production-list-detail/production-list-detail.component.jsx
+++ b/client/src/components/production-list-detail/production-list-detail.component.jsx
@@ -1,17 +1,20 @@
-import { PrinterFilled } from "@ant-design/icons";
-import { useQuery } from "@apollo/client";
-import { Button, Descriptions, Drawer, Space } from "antd";
+import { PauseCircleOutlined, PlayCircleOutlined, PrinterFilled } from "@ant-design/icons";
import { PageHeader } from "@ant-design/pro-layout";
+import { useMutation, useQuery } from "@apollo/client";
+import { Button, Descriptions, Drawer, Space } from "antd";
import queryString from "query-string";
-import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
-import { QUERY_JOB_CARD_DETAILS } from "../../graphql/jobs.queries";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
+import { logImEXEvent } from "../../firebase/firebase.utils.js";
+import { QUERY_JOB_CARD_DETAILS, UPDATE_JOB } from "../../graphql/jobs.queries";
+import { insertAuditTrail } from "../../redux/application/application.actions.js";
import { setModalContext } from "../../redux/modals/modals.actions";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
+import AuditTrailMapping from "../../utils/AuditTrailMappings.js";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateFormatter } from "../../utils/DateFormatter";
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
@@ -24,6 +27,7 @@ import JobDetailCardsPartsComponent from "../job-detail-cards/job-detail-cards.p
import CardTemplate from "../job-detail-cards/job-detail-cards.template.component";
import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container";
import ScoreboardAddButton from "../job-scoreboard-add-button/job-scoreboard-add-button.component";
+import JobWatcherToggleContainer from "../job-watcher-toggle/job-watcher-toggle.container.jsx";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ProductionRemoveButton from "../production-remove-button/production-remove-button.component";
@@ -33,14 +37,23 @@ const mapStateToProps = createStructuredSelector({
technician: selectTechnician
});
const mapDispatchToProps = (dispatch) => ({
- setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" }))
+ setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" })),
+ insertAuditTrail: ({ jobid, operation, type }) =>
+ dispatch(
+ insertAuditTrail({
+ jobid,
+ operation,
+ type
+ })
+ )
});
export default connect(mapStateToProps, mapDispatchToProps)(ProductionListDetail);
-export function ProductionListDetail({ bodyshop, jobs, setPrintCenterContext, technician }) {
+export function ProductionListDetail({ bodyshop, jobs, setPrintCenterContext, technician, insertAuditTrail }) {
const search = queryString.parse(useLocation().search);
const history = useNavigate();
const { selected } = search;
+ const { scenarioNotificationsOn } = useSocket();
const { t } = useTranslation();
const theJob = jobs.find((j) => j.id === selected) || {};
@@ -55,15 +68,44 @@ export function ProductionListDetail({ bodyshop, jobs, setPrintCenterContext, te
fetchPolicy: "network-only",
nextFetchPolicy: "network-only"
});
+ const [updateJob] = useMutation(UPDATE_JOB);
return (
+ {!technician && scenarioNotificationsOn && }
+ {theJob.ro_number}
+
+ }
extra={
{!technician ? : null}
+ {!technician && (
+ {
+ logImEXEvent("production_toggle_alert");
+ updateJob({
+ variables: {
+ jobId: theJob.id,
+ job: {
+ suspended: !theJob.suspended
+ }
+ }
+ });
+ insertAuditTrail({
+ jobid: theJob.id,
+ operation: AuditTrailMapping.jobsuspend(theJob.suspended ? !theJob.suspended : true),
+ type: "jobsuspend"
+ });
+ }}
+ icon={theJob.suspended ? : }
+ >
+ {theJob.suspended ? t("production.actions.unsuspend") : t("production.actions.suspend")}
+
+ )}
{
setPrintCenterContext({
@@ -75,8 +117,8 @@ export function ProductionListDetail({ bodyshop, jobs, setPrintCenterContext, te
}
});
}}
+ icon={ }
>
-
{t("jobs.actions.printCenter")}
{!technician ? : null}
diff --git a/client/src/components/production-list-table/production-list-table.container.jsx b/client/src/components/production-list-table/production-list-table.container.jsx
index aa0ccdd85..373222a65 100644
--- a/client/src/components/production-list-table/production-list-table.container.jsx
+++ b/client/src/components/production-list-table/production-list-table.container.jsx
@@ -1,5 +1,5 @@
import { useApolloClient, useQuery, useSubscription } from "@apollo/client";
-import React, { useContext, useEffect, useState, useRef } from "react";
+import { useEffect, useRef, useState } from "react";
import {
QUERY_EXACT_JOB_IN_PRODUCTION,
QUERY_EXACT_JOBS_IN_PRODUCTION,
@@ -10,11 +10,11 @@ import {
import ProductionListTable from "./production-list-table.component";
import _ from "lodash";
import { useSplitTreatments } from "@splitsoftware/splitio-react";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
export default function ProductionListTableContainer({ bodyshop, subscriptionType = "direct" }) {
const client = useApolloClient();
- const { socket } = useContext(SocketContext);
+ const { socket } = useSocket();
const [joblist, setJoblist] = useState([]);
const reconnectTimeout = useRef(null); // To store the reconnect timeout
const disconnectTime = useRef(null); // To store the time of disconnection
diff --git a/client/src/components/production-remove-button/production-remove-button.component.jsx b/client/src/components/production-remove-button/production-remove-button.component.jsx
index 9e13689f9..432136478 100644
--- a/client/src/components/production-remove-button/production-remove-button.component.jsx
+++ b/client/src/components/production-remove-button/production-remove-button.component.jsx
@@ -39,7 +39,7 @@ export default function ProductionRemoveButton({ jobId }) {
};
return (
-
+
{t("production.actions.remove")}
);
diff --git a/client/src/components/profile-my/profile-my.component.jsx b/client/src/components/profile-my/profile-my.component.jsx
index f53646bee..d17547cf0 100644
--- a/client/src/components/profile-my/profile-my.component.jsx
+++ b/client/src/components/profile-my/profile-my.component.jsx
@@ -1,6 +1,5 @@
import { Button, Card, Col, Form, Input } from "antd";
import { LockOutlined } from "@ant-design/icons";
-import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
@@ -9,6 +8,8 @@ import { selectCurrentUser } from "../../redux/user/user.selectors";
import { logImEXEvent, updateCurrentPassword } from "../../firebase/firebase.utils";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
+import NotificationSettingsForm from "../notification-settings/notification-settings-form.component.jsx";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser
@@ -22,6 +23,7 @@ export default connect(
)(function ProfileMyComponent({ currentUser, updateUserDetails }) {
const { t } = useTranslation();
const notification = useNotification();
+ const { scenarioNotificationsOn } = useSocket();
const handleFinish = (values) => {
logImEXEvent("profile_update");
@@ -117,6 +119,11 @@ export default connect(
+ {scenarioNotificationsOn && (
+
+
+
+ )}
>
);
});
diff --git a/client/src/components/profile-shops/profile-shops.container.jsx b/client/src/components/profile-shops/profile-shops.container.jsx
index 4c5150913..007c0ddc7 100644
--- a/client/src/components/profile-shops/profile-shops.container.jsx
+++ b/client/src/components/profile-shops/profile-shops.container.jsx
@@ -5,7 +5,7 @@ import { QUERY_ALL_ASSOCIATIONS, UPDATE_ACTIVE_ASSOCIATION } from "../../graphql
import AlertComponent from "../alert/alert.component";
import ProfileShopsComponent from "./profile-shops.component";
import axios from "axios";
-import { getToken } from "firebase/messaging";
+import { getToken } from "@firebase/messaging";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
diff --git a/client/src/components/shop-info/shop-info.laborrates.component.jsx b/client/src/components/shop-info/shop-info.laborrates.component.jsx
index 0c7c9b556..af8df9b34 100644
--- a/client/src/components/shop-info/shop-info.laborrates.component.jsx
+++ b/client/src/components/shop-info/shop-info.laborrates.component.jsx
@@ -1,6 +1,5 @@
import { DeleteFilled } from "@ant-design/icons";
-import { Button, Form, Input } from "antd";
-import React from "react";
+import { Button, Form, Input, Space } from "antd";
import { useTranslation } from "react-i18next";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
@@ -10,326 +9,338 @@ export default function ShopInfoLaborRates({ form }) {
const { t } = useTranslation();
return (
-
-
- {(fields, { add, remove, move }) => {
- return (
-
+
+ );
+ }}
+
+
+ >
);
}
diff --git a/client/src/components/shop-info/shop-intellipay-config.component.jsx b/client/src/components/shop-info/shop-intellipay-config.component.jsx
index 5c8ec7ee9..61529969d 100644
--- a/client/src/components/shop-info/shop-intellipay-config.component.jsx
+++ b/client/src/components/shop-info/shop-intellipay-config.component.jsx
@@ -1,11 +1,10 @@
-import { Alert, Form, Switch } from "antd";
-import React from "react";
+import { Alert, Form, Select, Switch } from "antd";
import { useTranslation } from "react-i18next";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
-import {connect} from "react-redux";
-import {createStructuredSelector} from "reselect";
-import {selectBodyshop} from "../../redux/user/user.selectors";
+import { connect } from "react-redux";
+import { createStructuredSelector } from "reselect";
+import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
@@ -16,17 +15,17 @@ const mapDispatchToProps = () => ({
export default connect(mapStateToProps, mapDispatchToProps)(ShopInfoIntellipay);
// noinspection JSUnusedLocalSymbols
-export function ShopInfoIntellipay({bodyshop, form}) {
- const {t} = useTranslation();
+export function ShopInfoIntellipay({ bodyshop, form }) {
+ const { t } = useTranslation();
return (
<>
{() => {
- const {intellipay_config} = form.getFieldsValue();
+ const { intellipay_config } = form.getFieldsValue();
if (intellipay_config?.enable_cash_discount)
- return ;
+ return ;
}}
@@ -36,7 +35,93 @@ export function ShopInfoIntellipay({bodyshop, form}) {
valuePropName="checked"
name={["intellipay_config", "enable_cash_discount"]}
>
-
+
+
+
+
+
+
+ {bodyshop.md_payment_types.map((item, idx) => (
+
+ {item}
+
+ ))}
+
+
+
+
+ {bodyshop.md_payment_types.map((item, idx) => (
+
+ {item}
+
+ ))}
+
+
+
+
+ {bodyshop.md_payment_types.map((item, idx) => (
+
+ {item}
+
+ ))}
+
+
+
+
+ {bodyshop.md_payment_types.map((item, idx) => (
+
+ {item}
+
+ ))}
+
+
+
+
+ {bodyshop.md_payment_types.map((item, idx) => (
+
+ {item}
+
+ ))}
+
+
+
+
+ {bodyshop.md_payment_types.map((item, idx) => (
+
+ {item}
+
+ ))}
+
+
+
+
+ {bodyshop.md_payment_types.map((item, idx) => (
+
+ {item}
+
+ ))}
+
>
diff --git a/client/src/components/update-alert/update-alert.component.jsx b/client/src/components/update-alert/update-alert.component.jsx
index 22b290a5c..e3273ded6 100644
--- a/client/src/components/update-alert/update-alert.component.jsx
+++ b/client/src/components/update-alert/update-alert.component.jsx
@@ -1,7 +1,7 @@
import { AlertOutlined } from "@ant-design/icons";
import { Alert, Button, Col, Row, Space } from "antd";
import i18n from "i18next";
-import React, { useCallback, useEffect, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
@@ -81,8 +81,7 @@ export function UpdateAlert({ updateAvailable }) {
imex: "$t(titles.imexonline)",
rome: "$t(titles.romeonline)"
})
- }),
- placement: "bottomRight"
+ })
});
}
if (needRefresh && timerStarted && timeLeft <= 0) {
diff --git a/client/src/contexts/Notifications/notificationContext.jsx b/client/src/contexts/Notifications/notificationContext.jsx
index 59bcdf4fe..e2dda9db8 100644
--- a/client/src/contexts/Notifications/notificationContext.jsx
+++ b/client/src/contexts/Notifications/notificationContext.jsx
@@ -1,5 +1,4 @@
-// NotificationProvider.jsx
-import React, { createContext, useContext } from "react";
+import { createContext, useContext } from "react";
import { notification } from "antd";
/**
@@ -22,7 +21,11 @@ export const useNotification = () => {
* - Provide `api` via the NotificationContext.
*/
export const NotificationProvider = ({ children }) => {
- const [api, contextHolder] = notification.useNotification();
+ const [api, contextHolder] = notification.useNotification({
+ placement: "bottomRight",
+ bottom: 70,
+ showProgress: true
+ });
return (
diff --git a/client/src/contexts/SocketIO/socketContext.jsx b/client/src/contexts/SocketIO/socketContext.jsx
deleted file mode 100644
index e0f0e61fc..000000000
--- a/client/src/contexts/SocketIO/socketContext.jsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import React, { createContext } from "react";
-import useSocket from "./useSocket"; // Import the custom hook
-
-// Create the SocketContext
-const SocketContext = createContext(null);
-
-export const SocketProvider = ({ children, bodyshop }) => {
- const { socket, clientId } = useSocket(bodyshop);
-
- return {children} ;
-};
-
-export default SocketContext;
diff --git a/client/src/contexts/SocketIO/useSocket.js b/client/src/contexts/SocketIO/useSocket.js
deleted file mode 100644
index c13141ca7..000000000
--- a/client/src/contexts/SocketIO/useSocket.js
+++ /dev/null
@@ -1,125 +0,0 @@
-import { useEffect, useRef, useState } from "react";
-import SocketIO from "socket.io-client";
-import { auth } from "../../firebase/firebase.utils";
-import { store } from "../../redux/store";
-import { addAlerts, setWssStatus } from "../../redux/application/application.actions";
-
-const useSocket = (bodyshop) => {
- const socketRef = useRef(null);
- const [clientId, setClientId] = useState(null);
-
- useEffect(() => {
- const initializeSocket = async (token) => {
- if (!bodyshop || !bodyshop.id) return;
-
- const endpoint = import.meta.env.PROD ? import.meta.env.VITE_APP_AXIOS_BASE_API_URL : "";
-
- const socketInstance = SocketIO(endpoint, {
- path: "/wss",
- withCredentials: true,
- auth: { token },
- reconnectionAttempts: Infinity,
- reconnectionDelay: 2000,
- reconnectionDelayMax: 10000
- });
-
- socketRef.current = socketInstance;
-
- // Handle socket events
- const handleBodyshopMessage = (message) => {
- if (!message || !message.type) return;
-
- switch (message.type) {
- case "alert-update":
- store.dispatch(addAlerts(message.payload));
- break;
- default:
- break;
- }
-
- if (!import.meta.env.DEV) return;
- console.log(`Received message for bodyshop ${bodyshop.id}:`, message);
- };
-
- const handleConnect = () => {
- socketInstance.emit("join-bodyshop-room", bodyshop.id);
- setClientId(socketInstance.id);
- store.dispatch(setWssStatus("connected"));
- };
-
- const handleReconnect = () => {
- store.dispatch(setWssStatus("connected"));
- };
-
- const handleConnectionError = (err) => {
- console.error("Socket connection error:", err);
-
- // Handle token expiration
- if (err.message.includes("auth/id-token-expired")) {
- console.warn("Token expired, refreshing...");
- auth.currentUser?.getIdToken(true).then((newToken) => {
- socketInstance.auth = { token: newToken }; // Update socket auth
- socketInstance.connect(); // Retry connection
- });
- } else {
- store.dispatch(setWssStatus("error"));
- }
- };
-
- const handleDisconnect = (reason) => {
- console.warn("Socket disconnected:", reason);
- store.dispatch(setWssStatus("disconnected"));
-
- // Manually trigger reconnection if necessary
- if (!socketInstance.connected && reason !== "io server disconnect") {
- setTimeout(() => {
- if (socketInstance.disconnected) {
- console.log("Manually triggering reconnection...");
- socketInstance.connect();
- }
- }, 2000); // Retry after 2 seconds
- }
- };
-
- // Register event handlers
- socketInstance.on("connect", handleConnect);
- socketInstance.on("reconnect", handleReconnect);
- socketInstance.on("connect_error", handleConnectionError);
- socketInstance.on("disconnect", handleDisconnect);
- socketInstance.on("bodyshop-message", handleBodyshopMessage);
- };
-
- const unsubscribe = auth.onIdTokenChanged(async (user) => {
- if (user) {
- const token = await user.getIdToken();
-
- if (socketRef.current) {
- // Update token if socket exists
- socketRef.current.emit("update-token", token);
- } else {
- // Initialize socket if not already connected
- initializeSocket(token);
- }
- } else {
- // User is not authenticated
- if (socketRef.current) {
- socketRef.current.disconnect();
- socketRef.current = null;
- }
- }
- });
-
- // Clean up on unmount
- return () => {
- unsubscribe();
- if (socketRef.current) {
- socketRef.current.disconnect();
- socketRef.current = null;
- }
- };
- }, [bodyshop]);
-
- return { socket: socketRef.current, clientId };
-};
-
-export default useSocket;
diff --git a/client/src/contexts/SocketIO/useSocket.jsx b/client/src/contexts/SocketIO/useSocket.jsx
new file mode 100644
index 000000000..70f52311f
--- /dev/null
+++ b/client/src/contexts/SocketIO/useSocket.jsx
@@ -0,0 +1,500 @@
+import { createContext, useContext, useEffect, useRef, useState } from "react";
+import SocketIO from "socket.io-client";
+import { auth } from "../../firebase/firebase.utils";
+import { store } from "../../redux/store";
+import { addAlerts, setWssStatus } from "../../redux/application/application.actions";
+import client from "../../utils/GraphQLClient";
+import { useNotification } from "../Notifications/notificationContext.jsx";
+import {
+ GET_NOTIFICATIONS,
+ GET_UNREAD_COUNT,
+ MARK_ALL_NOTIFICATIONS_READ,
+ MARK_NOTIFICATION_READ,
+ UPDATE_NOTIFICATIONS_READ_FRAGMENT
+} from "../../graphql/notifications.queries.js";
+import { useMutation } from "@apollo/client";
+import { useTranslation } from "react-i18next";
+import { useSplitTreatments } from "@splitsoftware/splitio-react";
+
+const SocketContext = createContext(null);
+
+const INITIAL_NOTIFICATIONS = 10;
+
+/**
+ * Socket Provider - Scenario Notifications / Web Socket related items
+ * @param children
+ * @param bodyshop
+ * @param navigate
+ * @param currentUser
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const SocketProvider = ({ children, bodyshop, navigate, currentUser }) => {
+ const socketRef = useRef(null);
+ const [clientId, setClientId] = useState(null);
+ const [isConnected, setIsConnected] = useState(false);
+ const notification = useNotification();
+ const userAssociationId = bodyshop?.associations?.[0]?.id;
+ const { t } = useTranslation();
+
+ const {
+ treatments: { Realtime_Notifications_UI }
+ } = useSplitTreatments({
+ attributes: {},
+ names: ["Realtime_Notifications_UI"],
+ splitKey: bodyshop?.imexshopid
+ });
+
+ const [markNotificationRead] = useMutation(MARK_NOTIFICATION_READ, {
+ update: (cache, { data: { update_notifications } }) => {
+ const timestamp = new Date().toISOString();
+ const updatedNotification = update_notifications.returning[0];
+
+ cache.modify({
+ fields: {
+ notifications(existing = [], { readField }) {
+ return existing.map((notif) =>
+ readField("id", notif) === updatedNotification.id
+ ? {
+ ...notif,
+ read: timestamp
+ }
+ : notif
+ );
+ }
+ }
+ });
+
+ const unreadCountQuery = cache.readQuery({
+ query: GET_UNREAD_COUNT,
+ variables: { associationid: userAssociationId }
+ });
+
+ if (unreadCountQuery?.notifications_aggregate?.aggregate?.count > 0) {
+ cache.writeQuery({
+ query: GET_UNREAD_COUNT,
+ variables: { associationid: userAssociationId },
+ data: {
+ notifications_aggregate: {
+ ...unreadCountQuery.notifications_aggregate,
+ aggregate: {
+ ...unreadCountQuery.notifications_aggregate.aggregate,
+ count: unreadCountQuery.notifications_aggregate.aggregate.count - 1
+ }
+ }
+ }
+ });
+ }
+
+ if (socketRef.current && isConnected) {
+ socketRef.current.emit("sync-notification-read", {
+ email: currentUser?.email,
+ bodyshopId: bodyshop.id,
+ notificationId: updatedNotification.id
+ });
+ }
+ },
+ onError: (err) =>
+ console.error("MARK_NOTIFICATION_READ error:", {
+ message: err?.message,
+ stack: err?.stack
+ })
+ });
+
+ const [markAllNotificationsRead] = useMutation(MARK_ALL_NOTIFICATIONS_READ, {
+ variables: { associationid: userAssociationId },
+ update: (cache) => {
+ const timestamp = new Date().toISOString();
+ cache.modify({
+ fields: {
+ notifications(existing = [], { readField }) {
+ return existing.map((notif) =>
+ readField("read", notif) === null && readField("associationid", notif) === userAssociationId
+ ? { ...notif, read: timestamp }
+ : notif
+ );
+ },
+ notifications_aggregate() {
+ return { aggregate: { count: 0, __typename: "notifications_aggregate_fields" } };
+ }
+ }
+ });
+
+ const baseWhereClause = { associationid: { _eq: userAssociationId } };
+ const cachedNotifications = cache.readQuery({
+ query: GET_NOTIFICATIONS,
+ variables: { limit: INITIAL_NOTIFICATIONS, offset: 0, where: baseWhereClause }
+ });
+
+ if (cachedNotifications?.notifications) {
+ cache.writeQuery({
+ query: GET_NOTIFICATIONS,
+ variables: { limit: INITIAL_NOTIFICATIONS, offset: 0, where: baseWhereClause },
+ data: {
+ notifications: cachedNotifications.notifications.map((notif) =>
+ notif.read === null ? { ...notif, read: timestamp } : notif
+ )
+ }
+ });
+ }
+
+ if (socketRef.current && isConnected) {
+ socketRef.current.emit("sync-all-notifications-read", {
+ email: currentUser?.email,
+ bodyshopId: bodyshop.id
+ });
+ }
+ },
+ onError: (err) => console.error("MARK_ALL_NOTIFICATIONS_READ error:", err)
+ });
+
+ useEffect(() => {
+ const initializeSocket = async (token) => {
+ if (!bodyshop || !bodyshop.id || socketRef.current) return;
+
+ const endpoint = import.meta.env.PROD ? import.meta.env.VITE_APP_AXIOS_BASE_API_URL : "";
+ const socketInstance = SocketIO(endpoint, {
+ path: "/wss",
+ withCredentials: true,
+ auth: { token, bodyshopId: bodyshop.id },
+ reconnectionAttempts: Infinity,
+ reconnectionDelay: 2000,
+ reconnectionDelayMax: 10000
+ });
+
+ socketRef.current = socketInstance;
+
+ const handleBodyshopMessage = (message) => {
+ if (!message || !message.type) return;
+ switch (message.type) {
+ case "alert-update":
+ store.dispatch(addAlerts(message.payload));
+ break;
+ default:
+ break;
+ }
+ };
+
+ const handleConnect = () => {
+ socketInstance.emit("join-bodyshop-room", bodyshop.id);
+ setClientId(socketInstance.id);
+ setIsConnected(true);
+ store.dispatch(setWssStatus("connected"));
+ };
+
+ const handleReconnect = () => {
+ setIsConnected(true);
+ store.dispatch(setWssStatus("connected"));
+ };
+
+ const handleConnectionError = (err) => {
+ console.error("Socket connection error:", err);
+ setIsConnected(false);
+ if (err.message.includes("auth/id-token-expired")) {
+ console.warn("Token expired, refreshing...");
+ auth.currentUser?.getIdToken(true).then((newToken) => {
+ socketInstance.auth = { token: newToken };
+ socketInstance.connect();
+ });
+ } else {
+ store.dispatch(setWssStatus("error"));
+ }
+ };
+
+ const handleDisconnect = (reason) => {
+ console.warn("Socket disconnected:", reason);
+ setIsConnected(false);
+ store.dispatch(setWssStatus("disconnected"));
+ if (!socketInstance.connected && reason !== "io server disconnect") {
+ setTimeout(() => {
+ if (socketInstance.disconnected) {
+ console.log("Manually triggering reconnection...");
+ socketInstance.connect();
+ }
+ }, 2000);
+ }
+ };
+
+ const handleNotification = (data) => {
+ // Scenario Notifications have been disabled, bail.
+ if (Realtime_Notifications_UI?.treatment !== "on") {
+ return;
+ }
+
+ const { jobId, jobRoNumber, notificationId, associationId, notifications } = data;
+ if (associationId !== userAssociationId) return;
+
+ const newNotification = {
+ __typename: "notifications",
+ id: notificationId,
+ jobid: jobId,
+ associationid: associationId,
+ scenario_text: JSON.stringify(notifications.map((notif) => notif.body)),
+ fcm_text: notifications.map((notif) => notif.body).join(". ") + ".",
+ scenario_meta: JSON.stringify(notifications.map((notif) => notif.variables || {})),
+ created_at: new Date(notifications[0].timestamp).toISOString(),
+ read: null,
+ job: { ro_number: jobRoNumber }
+ };
+
+ const baseVariables = {
+ limit: INITIAL_NOTIFICATIONS,
+ offset: 0,
+ where: { associationid: { _eq: userAssociationId } }
+ };
+
+ try {
+ const existingNotifications =
+ client.cache.readQuery({
+ query: GET_NOTIFICATIONS,
+ variables: baseVariables
+ })?.notifications || [];
+ if (!existingNotifications.some((n) => n.id === newNotification.id)) {
+ client.cache.writeQuery({
+ query: GET_NOTIFICATIONS,
+ variables: baseVariables,
+ data: {
+ notifications: [newNotification, ...existingNotifications].sort(
+ (a, b) => new Date(b.created_at) - new Date(a.created_at)
+ )
+ },
+ broadcast: true
+ });
+
+ const unreadVariables = {
+ ...baseVariables,
+ where: { ...baseVariables.where, read: { _is_null: true } }
+ };
+ const unreadNotifications =
+ client.cache.readQuery({
+ query: GET_NOTIFICATIONS,
+ variables: unreadVariables
+ })?.notifications || [];
+ if (newNotification.read === null && !unreadNotifications.some((n) => n.id === newNotification.id)) {
+ client.cache.writeQuery({
+ query: GET_NOTIFICATIONS,
+ variables: unreadVariables,
+ data: {
+ notifications: [newNotification, ...unreadNotifications].sort(
+ (a, b) => new Date(b.created_at) - new Date(a.created_at)
+ )
+ },
+ broadcast: true
+ });
+ }
+
+ client.cache.modify({
+ id: "ROOT_QUERY",
+ fields: {
+ notifications_aggregate(existing = { aggregate: { count: 0 } }) {
+ return {
+ ...existing,
+ aggregate: {
+ ...existing.aggregate,
+ count: existing.aggregate.count + (newNotification.read === null ? 1 : 0)
+ }
+ };
+ }
+ }
+ });
+
+ notification.info({
+ message: (
+ {
+ markNotificationRead({ variables: { id: notificationId } })
+ .then(() => navigate(`/manage/jobs/${jobId}`))
+ .catch((e) => console.error(`Error marking notification read: ${e?.message || ""}`));
+ }}
+ >
+ {t("notifications.labels.notification-popup-title", {
+ ro_number: jobRoNumber || t("general.labels.na")
+ })}
+
+ ),
+ description: (
+ {
+ markNotificationRead({ variables: { id: notificationId } })
+ .then(() => navigate(`/manage/jobs/${jobId}`))
+ .catch((e) => console.error(`Error marking notification read: ${e?.message || ""}`));
+ }}
+ >
+ {notifications.map((notif, index) => (
+
+ {notif.body}
+
+ ))}
+
+ )
+ });
+ }
+ } catch (error) {
+ console.error(`Error handling new notification: ${error?.message || ""}`);
+ }
+ };
+
+ const handleSyncNotificationRead = ({ notificationId, timestamp }) => {
+ // Scenario Notifications have been disabled, bail.
+ if (Realtime_Notifications_UI?.treatment !== "on") {
+ return;
+ }
+
+ try {
+ const notificationRef = client.cache.identify({
+ __typename: "notifications",
+ id: notificationId
+ });
+ client.cache.writeFragment({
+ id: notificationRef,
+ fragment: UPDATE_NOTIFICATIONS_READ_FRAGMENT,
+ data: { read: timestamp }
+ });
+
+ const unreadCountData = client.cache.readQuery({
+ query: GET_UNREAD_COUNT,
+ variables: { associationid: userAssociationId }
+ });
+ if (unreadCountData?.notifications_aggregate?.aggregate?.count > 0) {
+ const newCount = Math.max(unreadCountData.notifications_aggregate.aggregate.count - 1, 0);
+ client.cache.writeQuery({
+ query: GET_UNREAD_COUNT,
+ variables: { associationid: userAssociationId },
+ data: {
+ notifications_aggregate: {
+ __typename: "notifications_aggregate",
+ aggregate: {
+ __typename: "notifications_aggregate_fields",
+ count: newCount
+ }
+ }
+ }
+ });
+ }
+ } catch (error) {
+ console.error("Error in handleSyncNotificationRead:", error);
+ }
+ };
+
+ const handleSyncAllNotificationsRead = ({ timestamp }) => {
+ // Scenario Notifications have been disabled, bail.
+ if (Realtime_Notifications_UI?.treatment !== "on") {
+ return;
+ }
+
+ try {
+ const queryVars = {
+ limit: INITIAL_NOTIFICATIONS,
+ offset: 0,
+ where: { associationid: { _eq: userAssociationId } }
+ };
+ const cachedData = client.cache.readQuery({
+ query: GET_NOTIFICATIONS,
+ variables: queryVars
+ });
+
+ if (cachedData?.notifications) {
+ cachedData.notifications.forEach((notif) => {
+ if (!notif.read) {
+ const notifRef = client.cache.identify({ __typename: "notifications", id: notif.id });
+ client.cache.writeFragment({
+ id: notifRef,
+ fragment: UPDATE_NOTIFICATIONS_READ_FRAGMENT,
+ data: { read: timestamp }
+ });
+ }
+ });
+ }
+
+ client.cache.writeQuery({
+ query: GET_UNREAD_COUNT,
+ variables: { associationid: userAssociationId },
+ data: {
+ notifications_aggregate: {
+ __typename: "notifications_aggregate",
+ aggregate: {
+ __typename: "notifications_aggregate_fields",
+ count: 0
+ }
+ }
+ }
+ });
+ } catch (error) {
+ console.error(`Error In HandleSyncAllNotificationsRead: ${error?.message || ""}`);
+ }
+ };
+
+ socketInstance.on("connect", handleConnect);
+ socketInstance.on("reconnect", handleReconnect);
+ socketInstance.on("connect_error", handleConnectionError);
+ socketInstance.on("disconnect", handleDisconnect);
+ socketInstance.on("bodyshop-message", handleBodyshopMessage);
+ socketInstance.on("notification", handleNotification);
+ socketInstance.on("sync-notification-read", handleSyncNotificationRead);
+ socketInstance.on("sync-all-notifications-read", handleSyncAllNotificationsRead);
+ };
+
+ const unsubscribe = auth.onIdTokenChanged(async (user) => {
+ if (user) {
+ const token = await user.getIdToken();
+ if (socketRef.current) {
+ socketRef.current.emit("update-token", { token, bodyshopId: bodyshop.id });
+ } else {
+ initializeSocket(token).catch((err) =>
+ console.error(`Something went wrong Initializing Sockets: ${err?.message || ""}`)
+ );
+ }
+ } else {
+ if (socketRef.current) {
+ socketRef.current.disconnect();
+ socketRef.current = null;
+ setIsConnected(false);
+ }
+ }
+ });
+
+ return () => {
+ unsubscribe();
+ if (socketRef.current) {
+ socketRef.current.disconnect();
+ socketRef.current = null;
+ setIsConnected(false);
+ }
+ };
+ }, [
+ bodyshop,
+ notification,
+ userAssociationId,
+ markNotificationRead,
+ markAllNotificationsRead,
+ navigate,
+ currentUser,
+ Realtime_Notifications_UI,
+ t
+ ]);
+
+ return (
+
+ {children}
+
+ );
+};
+
+const useSocket = () => {
+ const context = useContext(SocketContext);
+ // NOTE: Not sure if we absolutely require this, does cause slipups on dev env
+ if (!context) throw new Error("useSocket must be used within a SocketProvider");
+ return context;
+};
+
+export { SocketContext, SocketProvider, INITIAL_NOTIFICATIONS, useSocket };
diff --git a/client/src/firebase/firebase.utils.js b/client/src/firebase/firebase.utils.js
index 9a7225b6d..9a09c8c73 100644
--- a/client/src/firebase/firebase.utils.js
+++ b/client/src/firebase/firebase.utils.js
@@ -1,8 +1,8 @@
-import { getAnalytics, logEvent } from "firebase/analytics";
-import { initializeApp } from "firebase/app";
-import { getAuth, updatePassword, updateProfile } from "firebase/auth";
-import { getFirestore } from "firebase/firestore";
-import { getMessaging, getToken, onMessage } from "firebase/messaging";
+import { getAnalytics, logEvent } from "@firebase/analytics";
+import { initializeApp } from "@firebase/app";
+import { getAuth, updatePassword, updateProfile } from "@firebase/auth";
+import { getFirestore } from "@firebase/firestore";
+import { getMessaging, getToken, onMessage } from "@firebase/messaging";
import { store } from "../redux/store";
const config = JSON.parse(import.meta.env.VITE_APP_FIREBASE_CONFIG);
diff --git a/client/src/graphql/apollo-error-handling.js b/client/src/graphql/apollo-error-handling.js
index 5e6e88691..3fdaa929c 100644
--- a/client/src/graphql/apollo-error-handling.js
+++ b/client/src/graphql/apollo-error-handling.js
@@ -1,12 +1,10 @@
import { onError } from "@apollo/client/link/error";
//https://stackoverflow.com/questions/57163454/refreshing-a-token-with-apollo-client-firebase-auth
-import * as Sentry from "@sentry/react";
const errorLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path }) => {
console.log(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`);
- Sentry.captureException({ message, locations, path });
});
}
if (networkError) console.log(`[Network error]: ${JSON.stringify(networkError)}`);
diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js
index 670fe963e..32a93980f 100644
--- a/client/src/graphql/bodyshop.queries.js
+++ b/client/src/graphql/bodyshop.queries.js
@@ -349,3 +349,13 @@ export const QUERY_STRIPE_ID = gql`
}
}
`;
+
+export const GET_ACTIVE_EMPLOYEES_IN_SHOP = gql`
+ query GetActiveEmployeesInShop($shopid: uuid!) {
+ associations(where: { shopid: { _eq: $shopid } }) {
+ id
+ useremail
+ shopid
+ }
+ }
+`;
diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js
index 6b417ba36..a9f16c111 100644
--- a/client/src/graphql/jobs.queries.js
+++ b/client/src/graphql/jobs.queries.js
@@ -509,6 +509,7 @@ export const GET_JOB_BY_PK = gql`
est_ct_ln
est_ea
est_ph1
+ flat_rate_ats
federal_tax_rate
id
inproduction
@@ -524,6 +525,10 @@ export const GET_JOB_BY_PK = gql`
invoice_final_note
iouparent
job_totals
+ job_watchers {
+ id
+ user_email
+ }
joblines(where: { removed: { _eq: false } }, order_by: { line_no: asc }) {
act_price
act_price_before_ppc
@@ -645,6 +650,7 @@ export const GET_JOB_BY_PK = gql`
policy_no
production_vars
rate_ats
+ rate_ats_flat
rate_la1
rate_la2
rate_la3
@@ -2567,3 +2573,34 @@ export const GET_JOB_BY_PK_QUICK_INTAKE = gql`
}
}
`;
+
+export const GET_JOB_WATCHERS = gql`
+ query GET_JOB_WATCHERS($jobid: uuid!) {
+ job_watchers(where: { jobid: { _eq: $jobid } }) {
+ id
+ user_email
+ }
+ }
+`;
+
+export const ADD_JOB_WATCHER = gql`
+ mutation ADD_JOB_WATCHER($jobid: uuid!, $userEmail: String!) {
+ insert_job_watchers_one(object: { jobid: $jobid, user_email: $userEmail }) {
+ id
+ jobid
+ user_email
+ }
+ }
+`;
+
+export const REMOVE_JOB_WATCHER = gql`
+ mutation REMOVE_JOB_WATCHER($jobid: uuid!, $userEmail: String!) {
+ delete_job_watchers(where: { jobid: { _eq: $jobid }, user_email: { _eq: $userEmail } }) {
+ affected_rows
+ returning {
+ id
+ user_email
+ }
+ }
+ }
+`;
diff --git a/client/src/graphql/notifications.queries.js b/client/src/graphql/notifications.queries.js
new file mode 100644
index 000000000..f223e0614
--- /dev/null
+++ b/client/src/graphql/notifications.queries.js
@@ -0,0 +1,58 @@
+import { gql } from "@apollo/client";
+
+export const GET_NOTIFICATIONS = gql`
+ query GetNotifications($limit: Int!, $offset: Int!, $where: notifications_bool_exp) {
+ notifications(limit: $limit, offset: $offset, order_by: { created_at: desc }, where: $where) {
+ id
+ jobid
+ associationid
+ scenario_text
+ fcm_text
+ scenario_meta
+ created_at
+ read
+ job {
+ id
+ ro_number
+ }
+ }
+ }
+`;
+
+export const GET_UNREAD_COUNT = gql`
+ query GetUnreadCount($associationid: uuid!) {
+ notifications_aggregate(where: { read: { _is_null: true }, associationid: { _eq: $associationid } }) {
+ aggregate {
+ count
+ }
+ }
+ }
+`;
+
+export const MARK_ALL_NOTIFICATIONS_READ = gql`
+ mutation MarkAllNotificationsRead($associationid: uuid!) {
+ update_notifications(
+ where: { read: { _is_null: true }, associationid: { _eq: $associationid } }
+ _set: { read: "now()" }
+ ) {
+ affected_rows
+ }
+ }
+`;
+
+export const MARK_NOTIFICATION_READ = gql`
+ mutation MarkNotificationRead($id: uuid!) {
+ update_notifications(where: { id: { _eq: $id } }, _set: { read: "now()" }) {
+ returning {
+ id
+ read
+ }
+ }
+ }
+`;
+
+export const UPDATE_NOTIFICATIONS_READ_FRAGMENT = gql`
+ fragment UpdateNotificationRead on notifications {
+ read
+ }
+`;
diff --git a/client/src/graphql/user.queries.js b/client/src/graphql/user.queries.js
index bd9b9b1cb..266059c09 100644
--- a/client/src/graphql/user.queries.js
+++ b/client/src/graphql/user.queries.js
@@ -85,3 +85,21 @@ export const UPDATE_KANBAN_SETTINGS = gql`
}
}
`;
+
+export const QUERY_NOTIFICATION_SETTINGS = gql`
+ query QUERY_NOTIFICATION_SETTINGS($email: String!) {
+ associations(where: { _and: { useremail: { _eq: $email }, active: { _eq: true } } }) {
+ id
+ notification_settings
+ }
+ }
+`;
+
+export const UPDATE_NOTIFICATION_SETTINGS = gql`
+ mutation UPDATE_NOTIFICATION_SETTINGS($id: uuid!, $ns: jsonb) {
+ update_associations_by_pk(pk_columns: { id: $id }, _set: { notification_settings: $ns }) {
+ id
+ notification_settings
+ }
+ }
+`;
diff --git a/client/src/index.jsx b/client/src/index.jsx
index 2e47b02d1..327d57e84 100644
--- a/client/src/index.jsx
+++ b/client/src/index.jsx
@@ -1,10 +1,12 @@
+import "./utils/sentry"; //Must be first.
import * as Sentry from "@sentry/react";
+import { ConfigProvider } from "antd";
import Dinero from "dinero.js";
-import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from "react-router-dom";
import { PersistGate } from "redux-persist/integration/react";
+import { registerSW } from "virtual:pwa-register";
import AppContainer from "./App/App.container";
import LoadingSpinner from "./components/loading-spinner/loading-spinner.component";
import "./index.css";
@@ -12,56 +14,18 @@ import { persistor, store } from "./redux/store";
import reportWebVitals from "./reportWebVitals";
import "./translations/i18n";
import "./utils/CleanAxios";
-import { ConfigProvider } from "antd";
-import InstanceRenderManager from "./utils/instanceRenderMgr";
-import { registerSW } from "virtual:pwa-register";
window.global ||= window;
registerSW({ immediate: true });
-//import { BrowserTracing } from "@sentry/tracing";
-//import "antd/dist/antd.css";
-// import "antd/dist/antd.less";
// Dinero.defaultCurrency = "CAD";
// Dinero.globalLocale = "en-CA";
Dinero.globalRoundingMode = "HALF_EVEN";
-if (import.meta.env.PROD) {
- Sentry.init({
- dsn: InstanceRenderManager({
- imex: "https://fd7e89369b6b4bdc9c6c4c9f22fa4ee4@o492140.ingest.sentry.io/5651027",
- rome: "https://a6acc91c073e414196014b8484627a61@o492140.ingest.sentry.io/4504561071161344"
- }),
+const sentryCreateBrowserRouter = Sentry.wrapCreateBrowserRouterV6(createBrowserRouter);
- ignoreErrors: [
- "ResizeObserver loop",
- "ResizeObserver loop limit exceeded",
- "Module specifier, 'fs' does not start",
- "Module specifier, 'zlib' does not start with"
- ],
- integrations: [
- Sentry.replayIntegration({
- maskAllText: false,
- blockAllMedia: true
- }),
- Sentry.browserTracingIntegration()
- ],
- tracePropagationTargets: [
- "api.imex.online",
- "api.test.imex.online",
- "db.imex.online",
- "api.romeonline.io",
- "api.test.romeonline.io",
- "db.romeonline.io"
- ],
- tracesSampleRate: 1.0,
- replaysOnErrorSampleRate: 1.0,
- environment: import.meta.env.MODE
- });
-}
-
-const router = createBrowserRouter(createRoutesFromElements( } />));
+const router = sentryCreateBrowserRouter(createRoutesFromElements( } />));
if (import.meta.env.DEV) {
let styles =
diff --git a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx
index 726156ac4..d5b6776ee 100644
--- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx
+++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx
@@ -56,6 +56,8 @@ import { DateTimeFormat } from "../../utils/DateFormatter";
import dayjs from "../../utils/day";
import UndefinedToNull from "../../utils/undefinedtonull";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
+import JobWatcherToggleContainer from "../../components/job-watcher-toggle/job-watcher-toggle.container.jsx";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -102,6 +104,7 @@ export function JobsDetailPage({
nextFetchPolicy: "network-only"
});
const notification = useNotification();
+ const { scenarioNotificationsOn } = useSocket();
useEffect(() => {
//form.setFieldsValue(transormJobToForm(job));
@@ -319,7 +322,13 @@ export function JobsDetailPage({
>
window.history.back()}
- title={job.ro_number || t("general.labels.na")}
+
+ title={
+
+ {scenarioNotificationsOn && }
+ {job.ro_number || t("general.labels.na")}
+
+ }
extra={menuExtra}
/>
diff --git a/client/src/pages/landing/landing.page.jsx b/client/src/pages/landing/landing.page.jsx
index 081418fdf..eccc9f6aa 100644
--- a/client/src/pages/landing/landing.page.jsx
+++ b/client/src/pages/landing/landing.page.jsx
@@ -13,7 +13,6 @@ export default connect(mapStateToProps, null)(LandingPage);
export function LandingPage({ currentUser }) {
const navigate = useNavigate();
- console.log("Main");
useEffect(() => {
navigate("/manage/jobs");
}, [currentUser, navigate]);
diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx
index 5dbf95dc5..e813eaae0 100644
--- a/client/src/pages/manage/manage.page.component.jsx
+++ b/client/src/pages/manage/manage.page.component.jsx
@@ -1,7 +1,7 @@
import { FloatButton, Layout, Spin } from "antd";
// import preval from "preval.macro";
-import React, { lazy, Suspense, useContext, useEffect, useState } from "react";
+import React, { lazy, Suspense, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, Route, Routes } from "react-router-dom";
@@ -20,7 +20,7 @@ import PartnerPingComponent from "../../components/partner-ping/partner-ping.com
import PrintCenterModalContainer from "../../components/print-center-modal/print-center-modal.container";
import ShopSubStatusComponent from "../../components/shop-sub-status/shop-sub-status.component";
import { requestForToken } from "../../firebase/firebase.utils";
-import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
+import { useSocket } from "../../contexts/SocketIO/useSocket.jsx";
import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.selectors";
import UpdateAlert from "../../components/update-alert/update-alert.component";
import InstanceRenderManager from "../../utils/instanceRenderMgr.js";
@@ -29,6 +29,7 @@ import WssStatusDisplayComponent from "../../components/wss-status-display/wss-s
import { selectAlerts } from "../../redux/application/application.selectors.js";
import { addAlerts } from "../../redux/application/application.actions.js";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
+
const JobsPage = lazy(() => import("../jobs/jobs.page"));
const CardPaymentModalContainer = lazy(
@@ -122,7 +123,7 @@ const mapDispatchToProps = (dispatch) => ({
export function Manage({ conflict, bodyshop, alerts, setAlerts }) {
const { t } = useTranslation();
const [chatVisible] = useState(false);
- const { socket, clientId } = useContext(SocketContext);
+ const { socket, clientId } = useSocket();
const notification = useNotification();
// State to track displayed alerts
@@ -142,11 +143,11 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) {
const fetchedAlerts = await response.json();
setAlerts(fetchedAlerts);
} catch (error) {
- console.error("Error fetching alerts:", error);
+ console.warn("Error fetching alerts:", error.message);
}
};
- fetchAlerts();
+ fetchAlerts().catch((err) => `Error fetching Bodyshop Alerts: ${err?.message || ""}`);
}, [setAlerts]);
// Use useEffect to watch for new alerts
@@ -166,7 +167,6 @@ export function Manage({ conflict, bodyshop, alerts, setAlerts }) {
description: alert.description,
type: alert.type || "info",
duration: 0,
- placement: "bottomRight",
closable: true,
onClose: () => {
// When the notification is closed, update displayed alerts state and localStorage
diff --git a/client/src/pages/payments-all/payments-all.container.page.jsx b/client/src/pages/payments-all/payments-all.container.page.jsx
index 2b67c4737..61105bed7 100644
--- a/client/src/pages/payments-all/payments-all.container.page.jsx
+++ b/client/src/pages/payments-all/payments-all.container.page.jsx
@@ -1,6 +1,6 @@
import { useQuery } from "@apollo/client";
import queryString from "query-string";
-import React, { useEffect } from "react";
+import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useLocation } from "react-router-dom";
@@ -10,23 +10,17 @@ import PaymentsListPaginated from "../../components/payments-list-paginated/paym
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
import { QUERY_ALL_PAYMENTS_PAGINATED } from "../../graphql/payments.queries";
import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions";
-import { selectBodyshop } from "../../redux/user/user.selectors";
import { pageLimit } from "../../utils/config";
-import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
-import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component";
-import { Card } from "antd";
-const mapStateToProps = createStructuredSelector({
- bodyshop: selectBodyshop
-});
+const mapStateToProps = createStructuredSelector({});
const mapDispatchToProps = (dispatch) => ({
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
setSelectedHeader: (key) => dispatch(setSelectedHeader(key))
});
-export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
+export function AllJobs({ setBreadcrumbs, setSelectedHeader }) {
const searchParams = queryString.parse(useLocation().search);
const { page, sortcolumn, sortorder, searchObj } = searchParams;
@@ -60,25 +54,15 @@ export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
if (error) return ;
return (
-
-
-
- }
- z
- >
-
-
-
-
+
+
+
);
}
diff --git a/client/src/redux/user/user.actions.js b/client/src/redux/user/user.actions.js
index f5393b6e9..01ba22534 100644
--- a/client/src/redux/user/user.actions.js
+++ b/client/src/redux/user/user.actions.js
@@ -118,3 +118,8 @@ export const setCurrentEula = (eula) => ({
export const acceptEula = () => ({
type: UserActionTypes.EULA_ACCEPTED
});
+
+export const setImexShopId = (imexshopid) => ({
+ type: UserActionTypes.SET_IMEX_SHOP_ID,
+ payload: imexshopid
+});
diff --git a/client/src/redux/user/user.reducer.js b/client/src/redux/user/user.reducer.js
index c117bd1c9..0042115ff 100644
--- a/client/src/redux/user/user.reducer.js
+++ b/client/src/redux/user/user.reducer.js
@@ -121,6 +121,11 @@ const userReducer = (state = INITIAL_STATE, action) => {
};
case UserActionTypes.SET_AUTH_LEVEL:
return { ...state, authLevel: action.payload };
+ case UserActionTypes.SET_IMEX_SHOP_ID:
+ return {
+ ...state,
+ imexshopid: action.payload
+ };
default:
return state;
}
diff --git a/client/src/redux/user/user.sagas.js b/client/src/redux/user/user.sagas.js
index 5e5259874..3b3a07c91 100644
--- a/client/src/redux/user/user.sagas.js
+++ b/client/src/redux/user/user.sagas.js
@@ -2,20 +2,19 @@ import FingerprintJS from "@fingerprintjs/fingerprintjs";
import * as Sentry from "@sentry/browser";
import { notification } from "antd";
import axios from "axios";
-import { setUserId, setUserProperties } from "firebase/analytics";
+import { setUserId, setUserProperties } from "@firebase/analytics";
import {
checkActionCode,
confirmPasswordReset,
sendPasswordResetEmail,
signInWithEmailAndPassword,
signOut
-} from "firebase/auth";
-import { arrayUnion, doc, getDoc, setDoc, updateDoc } from "firebase/firestore";
-import { getToken } from "firebase/messaging";
+} from "@firebase/auth";
+import { arrayUnion, doc, getDoc, setDoc, updateDoc } from "@firebase/firestore";
+import { getToken } from "@firebase/messaging";
import i18next from "i18next";
import LogRocket from "logrocket";
import { all, call, delay, put, select, takeLatest } from "redux-saga/effects";
-import { factory } from "../../App/App.container";
import {
analytics,
auth,
@@ -35,6 +34,7 @@ import {
sendPasswordResetFailure,
sendPasswordResetSuccess,
setAuthlevel,
+ setImexShopId,
setInstanceConflict,
setInstanceId,
setLocalFingerprint,
@@ -318,7 +318,8 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
console.log(error);
}
- factory.client(payload.imexshopid);
+ // Dispatch the imexshopid to Redux store
+ yield put(setImexShopId(payload.imexshopid));
const authRecord = payload.associations.filter((a) => a.useremail.toLowerCase() === userEmail.toLowerCase());
@@ -351,7 +352,7 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
? window.$crisp.push(["set", "session:segments", [["allAccess"]]])
: window.$crisp.push(["set", "session:segments", [["basic"]]]);
} catch (error) {
- console.error("Couldnt find $crisp.");
+ console.warn("Couldnt find $crisp.", error.message);
}
} catch (error) {
yield put(signInFailure(error.message));
diff --git a/client/src/redux/user/user.types.js b/client/src/redux/user/user.types.js
index 59a290ee5..d9cd6fe62 100644
--- a/client/src/redux/user/user.types.js
+++ b/client/src/redux/user/user.types.js
@@ -32,6 +32,7 @@ const UserActionTypes = {
CHECK_ACTION_CODE_SUCCESS: "CHECK_ACTION_CODE_SUCCESS",
CHECK_ACTION_CODE_FAILURE: "CHECK_ACTION_CODE_FAILURE",
SET_CURRENT_EULA: "SET_CURRENT_EULA",
- EULA_ACCEPTED: "EULA_ACCEPTED"
+ EULA_ACCEPTED: "EULA_ACCEPTED",
+ SET_IMEX_SHOP_ID: "SET_IMEX_SHOP_ID"
};
export default UserActionTypes;
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index 622b5ab42..ccf90fc10 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -1,3771 +1,3838 @@
{
- "translation": {
- "allocations": {
- "actions": {
- "assign": "Assign"
- },
- "errors": {
- "deleting": "Error encountered while deleting allocation. {{message}}",
- "saving": "Error while allocating. {{message}}",
- "validation": "Please ensure all fields are entered correctly. "
- },
- "fields": {
- "employee": "Allocated To"
- },
- "successes": {
- "deleted": "Allocation deleted successfully.",
- "save": "Allocated successfully. "
- }
- },
- "appointments": {
- "actions": {
- "block": "Block Day",
- "calculate": "Calculate SMART Dates",
- "cancel": "Cancel Appointment",
- "intake": "Intake",
- "new": "New Appointment",
- "preview": "Preview",
- "reschedule": "Reschedule",
- "sendreminder": "Send Reminder",
- "unblock": "Unblock",
- "viewjob": "View Job"
- },
- "errors": {
- "blocking": "Error creating block {{message}}.",
- "canceling": "Error canceling appointment. {{message}}",
- "saving": "Error scheduling appointment. {{message}}"
- },
- "fields": {
- "alt_transport": "Alt. Trans.",
- "color": "Appointment Color",
- "end": "End",
- "note": "Note",
- "start": "Start",
- "time": "Appointment Time",
- "title": "Title"
- },
- "labels": {
- "arrivedon": "Arrived on: ",
- "arrivingjobs": "Arriving Jobs",
- "blocked": "Blocked",
- "cancelledappointment": "Canceled appointment for: ",
- "completingjobs": "Completing Jobs",
- "dataconsistency": "<0>{{ro_number}}0> has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.",
- "expectedjobs": "Expected Jobs in Production: ",
- "expectedprodhrs": "Expected Production Hours:",
- "history": "History",
- "inproduction": "Jobs In Production",
- "manualevent": "Add Manual Appointment",
- "noarrivingjobs": "No Jobs are arriving.",
- "nocompletingjobs": "No Jobs scheduled for completion.",
- "nodateselected": "No date has been selected.",
- "priorappointments": "Previous Appointments",
- "reminder": "This is {{shopname}} reminding you about an appointment on {{date}} at {{time}}. Please let us know if you are not able to make the appointment. We look forward to seeing you soon. ",
- "scheduledfor": "Scheduled appointment for: ",
- "severalerrorsfound": "Several Jobs have issues which may prevent accurate smart scheduling. Click to expand.",
- "smartscheduling": "Smart Scheduling",
- "smspaymentreminder": "This is {{shopname}} reminding you about your remaining balance of {{amount}}. To pay for the said balance click the link {{payment_link}}.",
- "suggesteddates": "Suggested Dates"
- },
- "successes": {
- "canceled": "Appointment canceled successfully.",
- "created": "Appointment scheduled successfully.",
- "saved": "Appointment saved successfully."
- }
- },
- "associations": {
- "actions": {
- "activate": "Activate"
- },
- "fields": {
- "active": "Active?",
- "shopname": "Shop Name"
- },
- "labels": {
- "actions": "Actions"
- }
- },
- "audit": {
- "fields": {
- "cc": "CC",
- "contents": "Contents",
- "created": "Time",
- "operation": "Operation",
- "status": "Status",
- "subject": "Subject",
- "to": "To",
- "useremail": "User",
- "values": "Values"
- }
- },
- "audit_trail": {
- "messages": {
- "admin_job_remove_from_ar": "ADMIN: Remove from AR updated to: {{status}}",
- "admin_jobmarkexported": "ADMIN: Job marked as exported.",
- "admin_jobmarkforreexport": "ADMIN: Job marked for re-export.",
- "admin_jobuninvoice": "ADMIN: Job has been uninvoiced.",
- "admin_jobunvoid": "ADMIN: Job has been unvoided.",
- "alerttoggle": "Alert Toggle set to {{status}}",
- "appointmentcancel": "Appointment canceled. Lost Reason: {{lost_sale_reason}}.",
- "appointmentinsert": "Appointment created. Appointment Date: {{start}}.",
- "assignedlinehours": "Assigned job lines totaling {{hours}} units to {{team}}.",
- "billdeleted": "Bill with invoice number {{invoice_number}} deleted.",
- "billposted": "Bill with invoice number {{invoice_number}} posted.",
- "billupdated": "Bill with invoice number {{invoice_number}} updated.",
- "failedpayment": "Failed payment attempt.",
- "jobassignmentchange": "Employee {{name}} assigned to {{operation}}",
- "jobassignmentremoved": "Employee assignment removed for {{operation}}",
- "jobchecklist": "Checklist type \"{{type}}\" completed. In production set to {{inproduction}}. Status set to {{status}}.",
- "jobclosedwithbypass": "Job was invoiced using the master bypass password. ",
- "jobconverted": "Job converted and assigned number {{ro_number}}.",
- "jobdelivery": "Job intake completed. Status set to {{status}}. Actual completion is {{actual_completion}}.",
- "jobexported": "Job has been exported",
- "jobfieldchanged": "Job field $t(jobs.fields.{{field}}) changed to {{value}}.",
- "jobimported": "Job imported.",
- "jobinproductionchange": "Job production status set to {{inproduction}}",
- "jobintake": "Job intake completed. Status set to {{status}}. Scheduled completion is {{scheduled_completion}}.",
- "jobinvoiced": "Job has been invoiced.",
- "jobioucreated": "IOU Created.",
- "jobmodifylbradj": "Labor adjustments modified {{mod_lbr_ty}} / {{hours}}.",
- "jobnoteadded": "Note added to Job.",
- "jobnotedeleted": "Note deleted from Job.",
- "jobnoteupdated": "Note updated on Job.",
- "jobspartsorder": "Parts order {{order_number}} added to Job.",
- "jobspartsreturn": "Parts return {{order_number}} added to Job.",
- "jobstatuschange": "Job status changed to {{status}}.",
- "jobsupplement": "Job supplement imported.",
- "jobsuspend": "Suspend Toggle set to {{status}}",
- "jobvoid": "Job has been voided.",
- "tasks_completed": "Task '{{title}}' completed by {{completedBy}}",
- "tasks_created": "Task '{{title}}' created by {{createdBy}}",
- "tasks_deleted": "Task '{{title}}' deleted by {{deletedBy}}",
- "tasks_uncompleted": "Task '{{title}}' uncompleted by {{uncompletedBy}}",
- "tasks_undeleted": "Task '{{title}}' undeleted by {{undeletedBy}}",
- "tasks_updated": "Task '{{title}}' updated by {{updatedBy}}"
- }
- },
- "billlines": {
- "actions": {
- "newline": "New Line"
- },
- "fields": {
- "actual_cost": "Actual Cost",
- "actual_price": "Retail",
- "cost_center": "Cost Center",
- "federal_tax_applicable": "Fed. Tax?",
- "jobline": "Job Line",
- "line_desc": "Line Description",
- "local_tax_applicable": "Loc. Tax?",
- "location": "Location",
- "quantity": "Quantity",
- "state_tax_applicable": "St. Tax?"
- },
- "labels": {
- "deductedfromlbr": "Deduct from Labor?",
- "entered": "Entered",
- "from": "From",
- "mod_lbr_adjustment": "Adjustment Units",
- "other": "-- Not On Estimate --",
- "reconciled": "Reconciled!",
- "unreconciled": "Unreconciled"
- },
- "validation": {
- "atleastone": "At least one bill line must be entered."
- }
- },
- "bills": {
- "actions": {
- "deductallhours": "Deduct all",
- "edit": "Edit",
- "receive": "Receive Part",
- "return": "Return Items"
- },
- "errors": {
- "creating": "Error adding bill. {{error}}",
- "deleting": "Error deleting bill. {{error}}",
- "existinginventoryline": "This bill cannot be deleted as it is tied to items in inventory.",
- "exporting": "Error exporting payable(s). {{error}}",
- "exporting-partner": "Unable to connect to partner application. Please ensure it is running and logged in.",
- "invalidro": "Not a valid RO.",
- "invalidvendor": "Not a valid vendor.",
- "validation": "Please ensure all fields are entered correctly. "
- },
- "fields": {
- "allpartslocation": "Parts Bin",
- "date": "Bill Date",
- "exported": "Exported",
- "federal_tax_rate": "Federal Tax Rate",
- "invoice_number": "Invoice Number",
- "is_credit_memo": "Credit Memo?",
- "is_credit_memo_short": "CM",
- "local_tax_rate": "Local Tax Rate",
- "ro_number": "RO Number",
- "state_tax_rate": "State Tax Rate",
- "total": "Bill Total",
- "vendor": "Vendor",
- "vendorname": "Vendor Name"
- },
- "labels": {
- "actions": "Actions",
- "bill_lines": "Bill Lines",
- "bill_total": "Bill Total Amount",
- "billcmtotal": "Credit Memos",
- "bills": "Bills",
- "calculatedcreditsnotreceived": "Calculated CNR",
- "creditsnotreceived": "Credits Not Marked Received",
- "creditsreceived": "Credits Received",
- "dedfromlbr": "Labor Adjustments",
- "deleteconfirm": "Are you sure you want to delete this bill? It cannot be undone. If this bill has deductions from labors, manual changes may be required.",
- "discrepancy": "Discrepancy",
- "discrepwithcms": "Discrepancy including Credit Memos",
- "discrepwithlbradj": "Discrepancy including Lbr. Adj.",
- "editadjwarning": "This bill had lines which resulted in labor adjustments. Manual correction to adjustments may be required.",
- "entered_total": "Total of Entered Lines",
- "enteringcreditmemo": "You are entering a credit memo. Please ensure you are also entering positive values.",
- "federal_tax": "Federal Tax",
- "federal_tax_exempt": "Federal Tax Exempt?",
- "generatepartslabel": "Generate Parts Labels after Saving?",
- "iouexists": "An IOU exists that is associated to this RO.",
- "local_tax": "Local Tax",
- "markexported": "Mark Exported",
- "markforreexport": "Mark for Re-export",
- "new": "New Bill",
- "nobilllines": "No bills have been posted yet.",
- "noneselected": "No bill selected.",
- "onlycmforinvoiced": "Only credit memos can be entered for any Job that has been invoiced, exported, or voided.",
- "printlabels": "Print Labels",
- "retailtotal": "Bills Retail Total",
- "returnfrombill": "Return From Bill",
- "savewithdiscrepancy": "You are about to save this bill with a discrepancy. The system will continue to use the calculated amount using the bill lines. Press cancel to return to the bill.",
- "state_tax": "State Tax",
- "subtotal": "Subtotal",
- "totalreturns": "Total Returns"
- },
- "successes": {
- "created": "Invoice added successfully.",
- "deleted": "Bill deleted successfully.",
- "exported": "Bill(s) exported successfully.",
- "markexported": "Bill marked as exported.",
- "reexport": "Bill marked for re-export."
- },
- "validation": {
- "closingperiod": "This Bill Date is outside of the Closing Period.",
- "inventoryquantity": "Quantity must be greater than or equal to what has been added to inventory ({{number}}).",
- "manualinhouse": "Manual posting to the in house vendor is restricted. ",
- "unique_invoice_number": "This invoice number has already been entered for this vendor."
- }
- },
- "bodyshop": {
- "actions": {
- "add_task_preset": "Add Task Preset",
- "addapptcolor": "Add Appointment Color",
- "addbucket": "Add Definition",
- "addpartslocation": "Add Parts Location",
- "addpartsrule": "Add Parts Scan Rule",
- "addspeedprint": "Add Speed Print",
- "addtemplate": "Add Template",
- "newlaborrate": "New Labor Rate",
- "newsalestaxcode": "New Sales Tax Code",
- "newstatus": "Add Status",
- "testrender": "Test Render"
- },
- "errors": {
- "creatingdefaultview": "Error creating default view.",
- "loading": "Unable to load shop details. Please call technical support.",
- "saving": "Error encountered while saving. {{message}}"
- },
- "fields": {
- "ReceivableCustomField": "QBO Receivable Custom Field {{number}}",
- "address1": "Address 1",
- "address2": "Address 2",
- "appt_alt_transport": "Appointment Alternative Transportation Options",
- "appt_colors": {
- "color": "Color",
- "label": "Label"
- },
- "appt_length": "Default Appointment Length",
- "attach_pdf_to_email": "Attach PDF copy to sent emails?",
- "batchid": "ADP Batch ID",
- "bill_allow_post_to_closed": "Allow Bills to be posted to Closed Jobs",
- "bill_federal_tax_rate": "Bills - Federal Tax Rate %",
- "bill_local_tax_rate": "Bill - Local Tax Rate %",
- "bill_state_tax_rate": "Bill - Provincial/State Tax Rate %",
- "city": "City",
- "closingperiod": "Closing Period",
- "companycode": "ADP Company Code",
- "country": "Country",
- "dailybodytarget": "Scoreboard - Daily Body Target",
- "dailypainttarget": "Scoreboard - Daily Paint Target",
- "default_adjustment_rate": "Default Labor Deduction Adjustment Rate",
- "deliver": {
- "require_actual_delivery_date": "Require Actual Delivery",
- "templates": "Delivery Templates"
- },
- "dms": {
- "apcontrol": "AP Control Number",
- "appostingaccount": "AP Posting Account",
- "cashierid": "Cashier ID",
- "default_journal": "Default Journal",
- "disablebillwip": "Disable bill WIP for A/P Posting",
- "disablecontactvehiclecreation": "Disable Contact & Vehicle Updates/Creation",
- "dms_acctnumber": "DMS Account #",
- "dms_control_override": "Static Control # Override",
- "dms_wip_acctnumber": "DMS W.I.P. Account #",
- "generic_customer_number": "Generic Customer Number",
- "itc_federal": "Federal Tax is ITC?",
- "itc_local": "Local Tax is ITC?",
- "itc_state": "State Tax is ITC?",
- "mappingname": "DMS Mapping Name",
- "sendmaterialscosting": "Materials Cost as % of Sale",
- "srcco": "Source Company #/Dealer #"
- },
- "email": "General Shop Email",
- "enforce_class": "Enforce Class on Conversion?",
- "enforce_conversion_category": "Enforce Category on Conversion?",
- "enforce_conversion_csr": "Enforce CSR on Conversion?",
- "enforce_referral": "Enforce Referrals",
- "federal_tax_id": "Federal Tax ID (GST/HST)",
- "ignoreblockeddays": "Scoreboard - Ignore Blocked Days",
- "inhousevendorid": "In House Vendor ID",
- "insurance_vendor_id": "Insurance Vendor ID",
- "intake": {
- "next_contact_hours": "Automatic Next Contact Date - Hours from Intake",
- "templates": "Intake Templates"
- },
- "intellipay_config": {
- "cash_discount_percentage": "Cash Discount %",
- "enable_cash_discount": "Enable Cash Discounting"
- },
- "invoice_federal_tax_rate": "Invoices - Federal Tax Rate",
- "invoice_local_tax_rate": "Invoices - Local Tax Rate",
- "invoice_state_tax_rate": "Invoices - State Tax Rate",
- "jc_hourly_rates": {
- "mapa": "Job Costing - Paint Materials Hourly Cost Rate",
- "mash": "Job Costing - Shop Materials Hourly Cost Rate"
- },
- "last_name_first": "Display Owner Info as , ",
- "lastnumberworkingdays": "Scoreboard - Last Number of Working Days",
- "localmediaserverhttp": "Local Media Server - HTTP Path",
- "localmediaservernetwork": "Local Media Server - Network Path",
- "localmediatoken": "Local Media Server - Token",
- "logo_img_footer_margin": "Footer Margin (px)",
- "logo_img_header_margin": "Header Margin (px)",
- "logo_img_path": "Shop Logo",
- "logo_img_path_height": "Logo Image Height",
- "logo_img_path_width": "Logo Image Width",
- "md_categories": "Categories",
- "md_ccc_rates": "Courtesy Car Contract Rate Presets",
- "md_classes": "Classes",
- "md_ded_notes": "Deductible Notes",
- "md_email_cc": "Auto Email CC: $t(parts_orders.labels.{{template}})",
- "md_from_emails": "Additional From Emails",
- "md_functionality_toggles": {
- "parts_queue_toggle": "Auto Add Imported/Supplemented Jobs to Parts Queue"
- },
- "md_hour_split": {
- "paint": "Paint Hour Split",
- "prep": "Prep Hour Split"
- },
- "md_ins_co": {
- "city": "City",
- "name": "Insurance Company Name",
- "private": "Private",
- "state": "Province/State",
- "street1": "Street 1",
- "street2": "Street 2",
- "zip": "Zip/Postal Code"
- },
- "md_jobline_presets": "Jobline Presets",
- "md_lost_sale_reasons": "Lost Sale Reasons",
- "md_parts_order_comment": "Parts Orders Comments",
- "md_parts_scan": {
- "caseInsensitive": "Case Insensitive",
- "expression": "",
- "field": "Field",
- "flags": "",
- "mark_critical": "Mark Line as Critical?",
- "operation": "Operation",
- "update_field": "Field to Update",
- "update_value": "Update Value",
- "value": "Value"
- },
- "md_payment_types": "Payment Types",
- "md_referral_sources": "Referral Sources",
- "md_ro_guard": {
- "enabled": "RO Guard Enabled?",
- "enforce_ar": "Enforce AR Balance",
- "enforce_bills": "Enforce Bill Discrepancy",
- "enforce_cm": "Enforce Credit Memo Entry",
- "enforce_labor": "Enforce Labor Allocation",
- "enforce_ppd": "Enforce PPD Sync",
- "enforce_profit": "Enforce Profit Requirement",
- "enforce_sublet": "Enforce Sublet Completion",
- "masterbypass": "Master Bypass Password (not encrypted)",
- "totalgppercent_minimum": "Minimum Total Gross Profit %"
- },
- "md_tasks_presets": {
- "enable_tasks": "Enable Hour Flagging",
- "hourstype": "Hour Types",
- "memo": "Time Ticket Memo",
- "name": "Preset Name",
- "nextstatus": "Next Status",
- "percent": "Percent",
- "use_approvals": "Use Time Ticket Approval Queue"
- },
- "messaginglabel": "Messaging Preset Label",
- "messagingtext": "Messaging Preset Text",
- "noteslabel": "Note Label",
- "notestext": "Note Text",
- "partslocation": "Parts Location",
- "phone": "Phone",
- "prodtargethrs": "Production Target Hours",
- "rbac": {
- "accounting": {
- "exportlog": "Accounting -> Export Log",
- "payables": "Accounting -> Payables",
- "payments": "Accounting -> Payments",
- "receivables": "Accounting -> Receivables"
- },
- "bills": {
- "delete": "Bills -> Delete",
- "enter": "Bills -> Enter",
- "list": "Bills -> List",
- "reexport": "Bills -> Re-export",
- "view": "Bills -> View"
- },
- "contracts": {
- "create": "Contracts -> Create",
- "detail": "Contracts -> Detail",
- "list": "Contracts -> List"
- },
- "courtesycar": {
- "create": "Courtesy Car -> Create",
- "detail": "Courtesy Car -> Detail",
- "list": "Courtesy Car -> List"
- },
- "csi": {
- "export": "CSI -> Export",
- "page": "CSI -> Page"
- },
- "employee_teams": {
- "page": "Employee Teams -> List"
- },
- "employees": {
- "page": "Employees -> List"
- },
- "inventory": {
- "delete": "Inventory -> Delete",
- "list": "Inventory -> List"
- },
- "jobs": {
- "admin": "Jobs -> Admin",
- "available-list": "Jobs -> Available List",
- "checklist-view": "Jobs -> Checklist View",
- "close": "Jobs -> Close",
- "create": "Jobs -> Create",
- "deliver": "Jobs -> Deliver",
- "detail": "Jobs -> Detail",
- "intake": "Jobs -> Intake",
- "list-active": "Jobs -> List Active",
- "list-all": "Jobs -> List All",
- "list-ready": "Jobs -> List Ready",
- "partsqueue": "Jobs -> Parts Queue",
- "void": "Jobs -> Void"
- },
- "owners": {
- "detail": "Owners -> Detail",
- "list": "Owners -> List"
- },
- "payments": {
- "enter": "Payments -> Enter",
- "list": "Payments -> List"
- },
- "phonebook": {
- "edit": "Phonebook -> Edit",
- "view": "Phonebook -> View"
- },
- "production": {
- "board": "Production -> Board",
- "list": "Production -> List"
- },
- "schedule": {
- "view": "Schedule -> View"
- },
- "scoreboard": {
- "view": "Scoreboard -> View"
- },
- "shiftclock": {
- "view": "Shift Clock -> View"
- },
- "shop": {
- "config": "Shop -> Config",
- "dashboard": "Shop -> Dashboard",
- "rbac": "Shop -> RBAC",
- "reportcenter": "Shop -> Report Center",
- "templates": "Shop -> Templates",
- "vendors": "Shop -> Vendors"
- },
- "temporarydocs": {
- "view": "Temporary Docs -> View"
- },
- "timetickets": {
- "edit": "Time Tickets -> Edit",
- "editcommitted": "Time Tickets -> Edit Committed",
- "enter": "Time Tickets -> Enter",
- "list": "Time Tickets -> List",
- "shiftedit": "Time Tickets -> Shift Edit"
- },
- "ttapprovals": {
- "approve": "Time Ticket Approval -> Approve",
- "view": "Time Ticket Approval -> View"
- },
- "users": {
- "editaccess": "Users -> Edit access"
- }
- },
- "responsibilitycenter": "Responsibility Center",
- "responsibilitycenter_accountdesc": "Account Description",
- "responsibilitycenter_accountitem": "Item",
- "responsibilitycenter_accountname": "Account Name",
- "responsibilitycenter_accountnumber": "Account Number",
- "responsibilitycenter_rate": "Rate",
- "responsibilitycenter_tax_rate": "Tax {{typeNum}} Tier {{typeNumIterator}} Rate",
- "responsibilitycenter_tax_sur": "Tax {{typeNum}} Tier {{typeNumIterator}} Surcharge",
- "responsibilitycenter_tax_thres": "Tax {{typeNum}} Tier {{typeNumIterator}} Threshold",
- "responsibilitycenter_tax_tier": "Tax {{typeNum}} Tier {{typeNumIterator}}",
- "responsibilitycenter_tax_type": "Tax {{typeNum}} Type",
- "responsibilitycenters": {
- "ap": "Accounts Payable",
- "ar": "Accounts Receivable",
- "ats": "ATS",
- "federal_tax": "Federal Tax",
- "federal_tax_itc": "Federal Tax Credit",
- "gst_override": "GST Override Account #",
- "invoiceexemptcode": "QuickBooks US - Invoice Tax Exempt Code",
- "itemexemptcode": "QuickBooks US - Line Item Tax Exempt Code",
- "la1": "LA1",
- "la2": "LA2",
- "la3": "LA3",
- "la4": "LA4",
- "laa": "Aluminum",
- "lab": "Body",
- "lad": "Diagnostic",
- "lae": "Electrical",
- "laf": "Frame",
- "lag": "Glass",
- "lam": "Mechanical",
- "lar": "Refinish",
- "las": "Structural",
- "lau": "User Defined",
- "local_tax": "Local Tax",
- "mapa": "Paint Materials",
- "mash": "Shop Materials",
- "paa": "Aftermarket",
- "pac": "Chrome",
- "pag": "Glass",
- "pal": "LKQ",
- "pam": "Remanufactured",
- "pan": "OEM",
- "pao": "Other",
- "pap": "OEM Partial",
- "par": "Recored",
- "pas": "Sublet",
- "pasl": "Sublet (L)",
- "refund": "Refund",
- "sales_tax_codes": {
- "code": "Code",
- "description": "Description",
- "federal": "Federal Tax Applies",
- "local": "Local Tax Applies",
- "state": "State Tax Applies"
- },
- "state_tax": "State Tax",
- "tow": "Towing"
- },
- "schedule_end_time": "Schedule Ending Time",
- "schedule_start_time": "Schedule Starting Time",
- "shopname": "Shop Name",
- "speedprint": {
- "id": "Id",
- "label": "Label",
- "templates": "Templates"
- },
- "ss_configuration": {
- "dailyhrslimit": "Daily Incoming Hours Limit"
- },
- "ssbuckets": {
- "color": "Job Color",
- "gte": "Greater Than/Equal to (hrs)",
- "id": "ID",
- "label": "Label",
- "lt": "Less than (hrs)",
- "target": "Target (count)"
- },
- "state": "Province/State",
- "state_tax_id": "State Tax ID",
- "status": "Status Label",
- "statuses": {
- "active_statuses": "Active Statuses (Filtering for Active Jobs throughout system)",
- "additional_board_statuses": "Additional Status to Display on Production Board",
- "color": "Color",
- "default_arrived": "Default Arrived Status (Transition to Production)",
- "default_bo": "Default Backordered Status",
- "default_canceled": "Default Canceled Status",
- "default_completed": "Default Completed Status",
- "default_delivered": "Default Delivered Status (Transition to Post-Production)",
- "default_exported": "Default Exported Status",
- "default_imported": "Default Imported Status",
- "default_invoiced": "Default Invoiced Status",
- "default_ordered": "Default Ordered Status",
- "default_quote": "Default Quote Status",
- "default_received": "Default Received Status",
- "default_returned": "Default Returned",
- "default_scheduled": "Default Scheduled Status",
- "default_void": "Default Void",
- "open_statuses": "Open Statuses",
- "post_production_statuses": "Post-Production Statuses",
- "pre_production_statuses": "Pre-Production Statuses",
- "production_colors": "Production Status Colors",
- "production_statuses": "Production Statuses",
- "ready_statuses": "Ready Statuses"
- },
- "target_touchtime": "Target Touch Time",
- "timezone": "Timezone",
- "tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs",
- "tt_enforce_hours_for_tech_console": "Restrict Claimable Hours",
- "use_fippa": "Conceal Customer Information on Generated Documents?",
- "use_paint_scale_data": "Use Paint Scale Data for Job Costing?",
- "uselocalmediaserver": "Use Local Media Server?",
- "website": "Website",
- "zip_post": "Zip/Postal Code"
- },
- "labels": {
- "2tiername": "Name => RO",
- "2tiersetup": "2 Tier Setup",
- "2tiersource": "Source => RO",
- "accountingsetup": "Accounting Setup",
- "accountingtiers": "Number of Tiers to Use for Export",
- "alljobstatuses": "All Job Statuses",
- "allopenjobstatuses": "All Open Job Statuses",
- "apptcolors": "Appointment Colors",
- "businessinformation": "Business Information",
- "checklists": "Checklists",
- "csiq": "CSI Questions",
- "customtemplates": "Custom Templates",
- "defaultcostsmapping": "Default Costs Mapping",
- "defaultprofitsmapping": "Default Profits Mapping",
- "deliverchecklist": "Delivery Checklist",
- "dms": {
- "cdk": {
- "controllist": "Control Number List",
- "payers": "Payers"
- },
- "cdk_dealerid": "CDK Dealer ID",
- "costsmapping": "Costs Mapping",
- "dms_allocations": "DMS Allocations",
- "pbs_serialnumber": "PBS Serial Number",
- "profitsmapping": "Profits Mapping",
- "title": "DMS"
- },
- "emaillater": "Email Later",
- "employee_teams": "Employee Teams",
- "employees": "Employees",
- "estimators": "Estimators",
- "filehandlers": "Adjusters",
- "imexpay": "ImEX Pay",
- "insurancecos": "Insurance Companies",
- "intakechecklist": "Intake Checklist",
- "intellipay_cash_discount": "Please ensure that cash discounting has been enabled on your merchant account. Reach out to IntelliPay Support if you need assistance. ",
- "jobstatuses": "Job Statuses",
- "laborrates": "Labor Rates",
- "licensing": "Licensing",
- "md_parts_scan": "Parts Scan Rules",
- "md_ro_guard": "RO Guard",
- "md_tasks_presets": "Tasks Presets",
- "md_to_emails": "Preset To Emails",
- "md_to_emails_emails": "Emails",
- "messagingpresets": "Messaging Presets",
- "notemplatesavailable": "No templates available to add.",
- "notespresets": "Notes Presets",
- "orderstatuses": "Order Statuses",
- "partslocations": "Parts Locations",
- "partsscan": "Parts Scanning",
- "printlater": "Print Later",
- "qbo": "Use QuickBooks Online?",
- "qbo_departmentid": "QBO Department ID",
- "qbo_usa": "QBO USA Compatibility",
- "rbac": "Role Based Access Control",
- "responsibilitycenters": {
- "costs": "Cost Centers",
- "profits": "Profit Centers",
- "sales_tax_codes": "Sales Tax Codes",
- "tax_accounts": "Tax Accounts",
- "title": "Responsibility Centers",
- "ttl_adjustment": "Subtotal Adjustment Account",
- "ttl_tax_adjustment": "Tax Adjustment Account"
- },
- "roguard": {
- "title": "RO Guard"
- },
- "romepay": "Rome Pay",
- "scheduling": "SMART Scheduling",
- "scoreboardsetup": "Scoreboard Setup",
- "shop_enabled_features": "Shop Enabled Features",
- "shopinfo": "Shop Information",
- "speedprint": "Speed Print Configuration",
- "ssbuckets": "Job Size Definitions",
- "systemsettings": "System Settings",
- "task-presets": "Task Presets",
- "workingdays": "Working Days"
- },
- "operations": {
- "contains": "Contains",
- "ends_with": "Ends With",
- "equals": "Equals",
- "greater_than": "Greater Than",
- "less_than": "Less Than",
- "not_equals": "Not Equals",
- "starts_with": "Starts With"
- },
- "successes": {
- "areyousure": "Are you sure you want to continue?",
- "defaultviewcreated": "Default view created successfully.",
- "save": "Shop configuration saved successfully. ",
- "unsavedchanges": "Unsaved changes will be lost. Are you sure you want to continue?"
- },
- "tooltips": {
- "md_parts_scan": {
- "update_value_tooltip": "Some fields require coded values in order to function properly (e.g. labor and part types). Please reach out to support if you have any questions."
- }
- },
- "validation": {
- "centermustexist": "The chosen responsibility center does not exist.",
- "larsplit": "Refinish hour split must add up to 1.",
- "useremailmustexist": "This email is not a valid user."
- }
- },
- "checklist": {
- "actions": {
- "printall": "Print All Documents"
- },
- "errors": {
- "complete": "Error during Job checklist completion. {{error}}",
- "nochecklist": "No checklist has been configured for your shop. "
- },
- "labels": {
- "addtoproduction": "Add Job to Production?",
- "allow_text_message": "Permission to Text?",
- "checklist": "Checklist",
- "printpack": "Job Intake Print Pack",
- "removefromproduction": "Remove Job from Production?"
- },
- "successes": {
- "completed": "Job checklist completed."
- }
- },
- "contracts": {
- "actions": {
- "changerate": "Change Contract Rates",
- "convertoro": "Convert to RO",
- "decodelicense": "Decode License",
- "find": "Find Contract",
- "printcontract": "Print Contract",
- "senddltoform": "Insert Driver's License Information"
- },
- "errors": {
- "fetchingjobinfo": "Error fetching Job Info. {{error}}.",
- "returning": "Error returning Courtesy Car. {{error}}",
- "saving": "Error saving Contract. {{error}}",
- "selectjobandcar": "Please ensure both a car and job are selected."
- },
- "fields": {
- "actax": "A/C Tax",
- "actualreturn": "Actual Return Date",
- "agreementnumber": "Agreement Number",
- "cc_cardholder": "Cardholder Name",
- "cc_expiry": "Credit Card Expiry Date",
- "cc_num": "Credit Card Number",
- "cleanupcharge": "Clean Up Charge",
- "coverage": "Coverage",
- "dailyfreekm": "Daily Free Mileage",
- "dailyrate": "Daily Rate",
- "damage": "Existing Damage",
- "damagewaiver": "Damage Waiver",
- "driver": "Driver",
- "driver_addr1": "Driver Address 1",
- "driver_addr2": "Driver Address 2",
- "driver_city": "Driver City",
- "driver_dlexpiry": "Driver's License Expiration Date",
- "driver_dlnumber": "Driver's License Number",
- "driver_dlst": "Driver's License Province/State",
- "driver_dob": "Driver's DOB",
- "driver_fn": "Driver's First Name",
- "driver_ln": "Driver's Last Name",
- "driver_ph1": "Driver's Phone",
- "driver_state": "Driver's Province/State ",
- "driver_zip": "Driver's Postal/ZIP Code",
- "excesskmrate": "Excess Mileage",
- "federaltax": "Federal Taxes",
- "fuelin": "Fuel In",
- "fuelout": "Fuel Out",
- "kmend": "Mileage End",
- "kmstart": "Mileage Start",
- "length": "Length",
- "localtax": "Local Taxes",
- "refuelcharge": "Refuel Charge (per liter/gallon)",
- "scheduledreturn": "Scheduled Return",
- "start": "Contract Start",
- "statetax": "Provincial/State Taxes",
- "status": "Status"
- },
- "labels": {
- "agreement": "Agreement {{agreement_num}} - {{status}}",
- "availablecars": "Available Cars",
- "cardueforservice": "The courtesy car is due for servicing.",
- "convertform": {
- "applycleanupcharge": "Apply cleanup charge?",
- "refuelqty": "Refuel qty.?"
- },
- "correctdataonform": "Please review the information above. If any of it is not correct, you can fix it later.",
- "dateinpast": "Date is in the past.",
- "dlexpirebeforereturn": "The driver's license expires before the car is expected to return. ",
- "driverinformation": "Driver's Information",
- "findcontract": "Find Contract",
- "findermodal": "Contract Finder",
- "insuranceexpired": "The courtesy car insurance expires before the car is expected to return.",
- "noteconvertedfrom": "R.O. created from converted Courtesy Car Contract {{agreementnumber}}.",
- "populatefromjob": "Populate from Job",
- "rates": "Contract Rates",
- "time": "Time",
- "vehicle": "Vehicle",
- "waitingforscan": "Please scan driver's license barcode..."
- },
- "status": {
- "new": "New Contract",
- "out": "Out",
- "returned": "Returned"
- },
- "successes": {
- "saved": "Contract saved successfully. "
- }
- },
- "courtesycars": {
- "actions": {
- "new": "New Courtesy Car",
- "return": "Return Car"
- },
- "errors": {
- "saving": "Error saving Courtesy Car. {{error}}"
- },
- "fields": {
- "color": "Color",
- "dailycost": "Daily Cost to Rent",
- "damage": "Damage",
- "fleetnumber": "Fleet Number",
- "fuel": "Fuel Level",
- "insuranceexpires": "Insurance Expires On",
- "leaseenddate": "Lease Ends On",
- "make": "Make",
- "mileage": "Mileage",
- "model": "Model",
- "nextservicedate": "Next Service Date",
- "nextservicekm": "Next Service KMs",
- "notes": "Notes",
- "plate": "Plate Number",
- "purchasedate": "Purchase Date",
- "readiness": "Readiness",
- "registrationexpires": "Registration Expires On",
- "serviceenddate": "Usage End Date",
- "servicestartdate": "Usage Start Date",
- "status": "Status",
- "vin": "VIN",
- "year": "Year"
- },
- "labels": {
- "courtesycar": "Courtesy Car",
- "fuel": {
- "12": "1/2",
- "14": "1/4",
- "18": "1/8",
- "34": "3/4",
- "38": "3/8",
- "58": "5/8",
- "78": "7/8",
- "empty": "Empty",
- "full": "Full"
- },
- "outwith": "Out With",
- "return": "Return Courtesy Car",
- "status": "Status",
- "uniquefleet": "Enter a unique fleet number.",
- "usage": "Usage",
- "vehicle": "Vehicle Description"
- },
- "readiness": {
- "notready": "Not Ready",
- "ready": "Ready"
- },
- "status": {
- "in": "Available",
- "inservice": "Service/Maintenance",
- "leasereturn": "Lease Returned",
- "out": "Rented",
- "sold": "Sold",
- "unavailable": "Unavailable"
- },
- "successes": {
- "saved": "Courtesy Car saved successfully."
- }
- },
- "csi": {
- "actions": {
- "activate": "Activate"
- },
- "errors": {
- "creating": "Error creating survey {{message}}",
- "notconfigured": "You do not have any current CSI Question Sets configured.",
- "notfoundsubtitle": "We were unable to find a survey using the link you provided. Please ensure the URL is correct or reach out to your shop for more help.",
- "notfoundtitle": "No survey found.",
- "surveycompletesubtitle": "",
- "surveycompletetitle": ""
- },
- "fields": {
- "completedon": "Completed On",
- "created_at": "Created At",
- "surveyid": "",
- "validuntil": ""
- },
- "labels": {
- "copyright": "",
- "greeting": "",
- "intro": "",
- "nologgedinuser": "Please log out of {{app}}",
- "nologgedinuser_sub": "Users of {{app}} cannot complete CSI surveys while logged in. Please log out and try again.",
- "noneselected": "No response selected.",
- "title": "Customer Satisfaction Survey"
- },
- "successes": {
- "created": "CSI created successfully. ",
- "submitted": "Your responses have been submitted successfully.",
- "submittedsub": "Your input is highly appreciated."
- }
- },
- "dashboard": {
- "actions": {
- "addcomponent": "Add Component"
- },
- "errors": {
- "refreshrequired": "You must refresh the dashboard data to see this component.",
- "updatinglayout": "Error saving updated layout {{message}}"
- },
- "labels": {
- "bodyhrs": "Body Hrs",
- "dollarsinproduction": "Dollars in Production",
- "phone": "Phone",
- "prodhrs": "Production Hrs",
- "refhrs": "Refinish Hrs"
- },
- "titles": {
- "joblifecycle": "Job Life Cycles",
- "labhours": "Total Body Hours",
- "larhours": "Total Refinish Hours",
- "monthlyemployeeefficiency": "Monthly Employee Efficiency",
- "monthlyjobcosting": "Monthly Job Costing ",
- "monthlylaborsales": "Monthly Labor Sales",
- "monthlypartssales": "Monthly Parts Sales",
- "monthlyrevenuegraph": "Monthly Revenue Graph",
- "prodhrssummary": "Production Hours Summary",
- "productiondollars": "Total Dollars in Production",
- "productionhours": "Total Hours in Production",
- "projectedmonthlysales": "Projected Monthly Sales",
- "scheduledindate": "Scheduled In Today: {{date}}",
- "scheduledintoday": "Scheduled In Today",
- "scheduledoutdate": "Scheduled Out Today: {{date}}",
- "scheduledouttoday": "Scheduled Out Today",
- "tasks": "Tasks"
- }
- },
- "dms": {
- "errors": {
- "alreadyexported": "This job has already been sent to the DMS. If you need to resend it, please use admin permissions to mark the job for re-export."
- },
- "labels": {
- "refreshallocations": "Refresh to see DMS Allocataions."
- }
- },
- "documents": {
- "actions": {
- "delete": "Delete Selected Documents",
- "download": "Download Selected Images",
- "reassign": "Reassign to another Job",
- "selectallimages": "Select All Images",
- "selectallotherdocuments": "Select All Other Documents"
- },
- "errors": {
- "deletes3": "Error deleting document from storage. ",
- "deleting": "Error deleting documents {{error}}",
- "deleting_cloudinary": "Error deleting document from storage. {{message}}",
- "getpresignurl": "Error obtaining presigned URL for document. {{message}}",
- "insert": "Unable to upload file. {{message}}",
- "nodocuments": "There are no documents.",
- "updating": "Error updating document. {{error}}"
- },
- "labels": {
- "confirmdelete": "Are you sure you want to delete these documents. This CANNOT be undone.",
- "doctype": "Document Type",
- "dragtoupload": "Click or drag files to this area to upload",
- "newjobid": "Assign to Job",
- "openinexplorer": "Open in Explorer",
- "optimizedimage": "The below image is optimized. Click on the picture below to open in a new window and view it full size, or open it in explorer.",
- "reassign_limitexceeded": "Reassigning all selected documents will exceed the job storage limit for your shop. ",
- "reassign_limitexceeded_title": "Unable to reassign document(s)",
- "storageexceeded": "You've exceeded your storage limit for this job. Please remove documents, or increase your storage plan.",
- "storageexceeded_title": "Storage Limit Exceeded",
- "upload": "Upload",
- "upload_limitexceeded": "Uploading all selected documents will exceed the job storage limit for your shop. ",
- "upload_limitexceeded_title": "Unable to upload document(s)",
- "uploading": "Uploading...",
- "usage": "of Job storage used. ({{used}} / {{total}})"
- },
- "successes": {
- "delete": "Document(s) deleted successfully.",
- "edituploaded": "Edited document uploaded successfully. Please close this window and refresh the documents list.",
- "insert": "Uploaded document successfully. ",
- "updated": "Document updated successfully. "
- }
- },
- "emails": {
- "errors": {
- "notsent": "Email not sent. Error encountered while sending {{message}}"
- },
- "fields": {
- "cc": "CC",
- "from": "From",
- "subject": "Subject",
- "to": "To"
- },
- "labels": {
- "attachments": "Attachments",
- "documents": "Documents",
- "emailpreview": "Email Preview",
- "generatingemail": "Generating email...",
- "pdfcopywillbeattached": "A PDF copy of this email will be attached when it is sent.",
- "preview": "Email Preview"
- },
- "successes": {
- "sent": "Email sent successfully."
- }
- },
- "employee_teams": {
- "actions": {
- "new": "New Team",
- "newmember": "New Team Member"
- },
- "fields": {
- "active": "Active",
- "employeeid": "Employee",
- "max_load": "Max Load",
- "name": "Team Name",
- "percentage": "Percent"
- }
- },
- "employees": {
- "actions": {
- "addvacation": "Add Vacation",
- "new": "New Employee",
- "newrate": "New Rate"
- },
- "errors": {
- "delete": "Error encountered while deleting employee. {{message}}",
- "save": "Error encountered saving employee. {{message}}",
- "validation": "Please check all fields.",
- "validationtitle": "Unable to save employee."
- },
- "fields": {
- "active": "Active?",
- "base_rate": "Base Rate",
- "cost_center": "Cost Center",
- "employee_number": "Employee Number",
- "external_id": "External Employee ID",
- "first_name": "First Name",
- "flat_rate": "Flat Rate (Disabled is Straight Time)",
- "hire_date": "Hire Date",
- "last_name": "Last Name",
- "pin": "Tech Console PIN",
- "rate": "Rate",
- "termination_date": "Termination Date",
- "user_email": "User Email",
- "vacation": {
- "end": "Vacation End",
- "length": "Vacation Length",
- "start": "Vacation Start"
- }
- },
- "labels": {
- "actions": "Actions",
- "active": "Active",
- "endmustbeafterstart": "End date must be after start date.",
- "flat_rate": "Flat Rate",
- "inactive": "Inactive",
- "name": "Name",
- "rate_type": "Rate Type",
- "status": "Status",
- "straight_time": "Straight Time"
- },
- "successes": {
- "delete": "Employee deleted successfully.",
- "save": "Employee saved successfully.",
- "vacationadded": "Employee vacation added."
- },
- "validation": {
- "unique_employee_number": "You must enter a unique employee number."
- }
- },
- "eula": {
- "buttons": {
- "accept": "Accept EULA"
- },
- "content": {
- "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting."
- },
- "errors": {
- "acceptance": {
- "description": "Something went wrong while accepting the EULA. Please try again.",
- "message": "Eula Acceptance Error"
- }
- },
- "labels": {
- "accepted_terms": "I accept the terms and conditions of this agreement.",
- "address": "Address",
- "business_name": "Legal Business Name",
- "date_accepted": "Date Accepted",
- "first_name": "First Name",
- "last_name": "Last Name",
- "phone_number": "Phone Number"
- },
- "messages": {
- "accepted_terms": "Please accept the terms and conditions of this agreement.",
- "business_name": "Please enter your legal business name.",
- "date_accepted": "Please enter Today's Date.",
- "first_name": "Please enter your first name.",
- "last_name": "Please enter your last name.",
- "phone_number": "Please enter your phone number."
- },
- "titles": {
- "modal": "Terms and Conditions",
- "upper_card": "Acknowledgement"
- }
- },
- "exportlogs": {
- "fields": {
- "createdat": "Created At"
- },
- "labels": {
- "attempts": "Export Attempts",
- "priorsuccesfulexport": "This record has previously been exported successfully. Please make sure it has already been deleted in the target system."
- }
- },
- "general": {
- "actions": {
- "add": "Add",
- "autoupdate": "{{app}} will automatically update in {{time}} seconds. Please save all changes.",
- "calculate": "Calculate",
- "cancel": "Cancel",
- "clear": "Clear",
- "close": "Close",
- "copied": "Copied!",
- "copylink": "Copy Link",
- "create": "Create",
- "defaults": "Defaults",
- "delay": "Delay Update (5 mins)",
- "delete": "Delete",
- "deleteall": "Delete All",
- "deselectall": "Deselect All",
- "download": "Download",
- "edit": "Edit",
- "login": "Login",
- "next": "Next",
- "ok": "Ok",
- "previous": "Previous",
- "print": "Print",
- "refresh": "Refresh",
- "remove": "Remove",
- "remove_alert": "Are you sure you want to dismiss the alert?",
- "reset": "Reset your changes.",
- "resetpassword": "Reset Password",
- "save": "Save",
- "saveandnew": "Save and New",
- "saveas": "Save As",
- "selectall": "Select All",
- "send": "Send",
- "sendbysms": "Send by SMS",
- "senderrortosupport": "Send Error to Support",
- "sharetoteams": "Share to Teams",
- "submit": "Submit",
- "tryagain": "Try Again",
- "view": "View",
- "viewreleasenotes": "See What's Changed"
- },
- "errors": {
- "fcm": "You must allow notification permissions to have real time messaging. Click to try again.",
- "notfound": "No record was found.",
- "sizelimit": "The selected items exceed the size limit."
- },
- "itemtypes": {
- "contract": "CC Contract",
- "courtesycar": "Courtesy Car",
- "job": "Job",
- "owner": "Owner",
- "vehicle": "Vehicle"
- },
- "labels": {
- "actions": "Actions",
- "areyousure": "Are you sure?",
- "barcode": "Barcode",
- "cancel": "Are you sure you want to cancel? Your changes will not be saved.",
- "clear": "Clear",
- "confirmpassword": "Confirm Password",
- "created_at": "Created At",
- "date": "Select Date",
- "datetime": "Select Date & Time",
- "email": "Email",
- "errors": "Errors",
- "excel": "Excel",
- "exceptiontitle": "An error has occurred.",
- "friday": "Friday",
- "globalsearch": "Global Search",
- "help": "Help",
- "hours": "hrs",
- "in": "In",
- "instanceconflictext": "Your {{app}} account can only be used on one device at any given time. Refresh your session to take control.",
- "instanceconflictitle": "Your account is being used elsewhere.",
- "item": "Item",
- "label": "Label",
- "loading": "Loading...",
- "loadingapp": "Loading {{app}}",
- "loadingshop": "Loading shop data...",
- "loggingin": "Authorizing...",
- "markedexported": "Manually marked as exported.",
- "media": "Media",
- "message": "Message",
- "monday": "Monday",
- "na": "N/A",
- "newpassword": "New Password",
- "no": "No",
- "nointernet": "It looks like you're not connected to the internet.",
- "nointernet_sub": "Please check your connection and try again. ",
- "none": "None",
- "out": "Out",
- "password": "Password",
- "passwordresetsuccess": "A password reset link has been sent to you.",
- "passwordresetsuccess_sub": "You should receive this email in the next few minutes. Please check your email including any junk or spam folders. ",
- "passwordresetvalidatesuccess": "Password successfully reset. ",
- "passwordresetvalidatesuccess_sub": "You may now sign in again using your new password. ",
- "passwordsdonotmatch": "The passwords you have entered do not match.",
- "print": "Print",
- "refresh": "Refresh",
- "reports": "Reports",
- "required": "Required",
- "saturday": "Saturday",
- "search": "Search...",
- "searchresults": "Results for {{search}}",
- "selectdate": "Select date...",
- "sendagain": "Send Again",
- "sendby": "Send By",
- "signin": "Sign In",
- "sms": "SMS",
- "status": "Status",
- "sub_status": {
- "expired": "The subscription for this shop has expired. Please contact technical support to reactivate the subscription. "
- },
- "successful": "Successful",
- "sunday": "Sunday",
- "text": "Text",
- "thursday": "Thursday",
- "time": "Select Time",
- "total": "Total",
- "totals": "Totals",
- "tuesday": "Tuesday",
- "tvmode": "TV Mode",
- "unknown": "Unknown",
- "unsavedchanges": "Unsaved changes.",
- "username": "Username",
- "view": "View",
- "wednesday": "Wednesday",
- "yes": "Yes"
- },
- "languages": {
- "english": "English",
- "french": "French",
- "spanish": "Spanish"
- },
- "messages": {
- "exception": "{{app}} has encountered an error. Please try again. If the problem persists, please submit a support ticket or contact us.",
- "newversionmessage": "Click refresh below to update to the latest available version of {{app}}. Please make sure all other tabs and windows are closed.",
- "newversiontitle": "New version of {{app}} Available",
- "noacctfilepath": "There is no accounting file path set. You will not be able to export any items.",
- "nofeatureaccess": "You do not have access to this feature of {{app}}. Please contact support to request a license for this feature.",
- "noshop": "You do not have access to any shops. Please reach out to your shop manager or technical support. ",
- "notfoundsub": "Please make sure that you have access to the data or that the link is correct.",
- "notfoundtitle": "We couldn't find what you're looking for...",
- "partnernotrunning": "{{app}} has detected that the partner is not running. Please ensure it is running to enable full functionality.",
- "rbacunauth": "You are not authorized to view this content. Please reach out to your shop manager to change your access level.",
- "unsavedchanges": "You have unsaved changes.",
- "unsavedchangespopup": "You have unsaved changes. Are you sure you want to leave?"
- },
- "validation": {
- "dateRangeExceeded": "The date range has been exceeded.",
- "invalidemail": "Please enter a valid email.",
- "invalidphone": "Please enter a valid phone number.",
- "required": "{{label}} is required."
- }
- },
- "help": {
- "actions": {
- "connect": "Connect"
- },
- "labels": {
- "codeplacholder": "6 digit PIN code",
- "rescuedesc": "Enter the 6 digit code provided by {{app}} Support below and click connect.",
- "rescuetitle": "Rescue Me!"
- }
- },
- "intake": {
- "labels": {
- "printpack": "Intake Print Pack"
- }
- },
- "inventory": {
- "actions": {
- "addtoinventory": "Add to Inventory",
- "addtoro": "Add to RO",
- "consumefrominventory": "Consume from Inventory?",
- "edit": "Edit Inventory LIne",
- "new": "New Inventory Line"
- },
- "errors": {
- "inserting": "Error inserting inventory item. {{error}}"
- },
- "fields": {
- "comment": "Comment",
- "manualinvoicenumber": "Invoice Number",
- "manualvendor": "Vendor"
- },
- "labels": {
- "consumedbyjob": "Consumed by Job",
- "deleteconfirm": "Are you sure you want to delete this from inventory? The associated bill will not be modified or deleted. ",
- "frombillinvoicenumber": "Original Bill Invoice Number",
- "fromvendor": "Original Bill Vendor",
- "inventory": "Inventory",
- "showall": "Show All Inventory",
- "showavailable": "Show Only Available Inventory"
- },
- "successes": {
- "deleted": "Inventory lined deleted.",
- "inserted": "Added line to inventory.",
- "updated": "Inventory line updated."
- }
- },
- "job_lifecycle": {
- "columns": {
- "average_human_readable": "Average Human Readable",
- "average_value": "Average Value",
- "duration": "Duration",
- "end": "End",
- "human_readable": "Human Readable",
- "percentage": "Percentage",
- "relative_end": "Relative End",
- "relative_start": "Relative Start",
- "start": "Start",
- "status": "Status",
- "status_count": "In Status",
- "value": "Value"
- },
- "content": {
- "calculated_based_on": "Calculated based on",
- "current_status_accumulated_time": "Current Status Accumulated Time",
- "data_unavailable": " There is currently no Lifecycle data for this Job.",
- "jobs_in_since": "Jobs in since",
- "legend_title": "Legend",
- "loading": "Loading Job Timelines....",
- "not_available": "N/A",
- "previous_status_accumulated_time": "Previous Status Accumulated Time",
- "title": "Job Lifecycle Component",
- "title_durations": "Historical Status Durations",
- "title_loading": "Loading",
- "title_transitions": "Transitions"
- },
- "errors": {
- "fetch": "Error getting Job Lifecycle Data"
- },
- "titles": {
- "dashboard": "Job Lifecycle",
- "top_durations": "Top Durations"
- }
- },
- "job_payments": {
- "buttons": {
- "create_short_link": "Generate Short Link",
- "goback": "Go Back",
- "proceedtopayment": "Proceed to Payment",
- "refundpayment": "Refund Payment"
- },
- "notifications": {
- "error": {
- "description": "Please try again. Make sure the refund amount does not exceeds the payment amount.",
- "openingip": "Error connecting to IntelliPay service.",
- "title": "Error placing refund"
- }
- },
- "titles": {
- "amount": "Amount",
- "dateOfPayment": "Date of Payment",
- "descriptions": "Payment Details",
- "hint": "Hint",
- "payer": "Payer",
- "payername": "Payer Name",
- "paymentid": "Payment Reference ID",
- "paymentnum": "Payment Number",
- "paymenttype": "Payment Type",
- "refundamount": "Refund Amount",
- "transactionid": "Transaction ID"
- }
- },
- "joblines": {
- "actions": {
- "assign_team": "Assign Team",
- "converttolabor": "Convert amount to Labor.",
- "dispatchparts": "Dispatch Parts ({{count}})",
- "new": "New Line"
- },
- "errors": {
- "creating": "Error encountered while creating job line. {{message}}",
- "updating": "Error encountered updating job line. {{message}}"
- },
- "fields": {
- "act_price": "Retail Price",
- "act_price_before_ppc": "Original Part Price",
- "adjustment": "Adjustment",
- "ah_detail_line": "Mark as Detail Labor Line (Autohouse Only)",
- "alt_partno": "Alt Part #",
- "amount": "Amount",
- "assigned_team": "Team",
- "assigned_team_name": "Team {{name}}",
- "create_ppc": "Create PPC?",
- "db_price": "List Price",
- "include_in_part_cnt": "Include in Parts Status Count",
- "lbr_types": {
- "LA1": "LA1",
- "LA2": "LA2",
- "LA3": "LA3",
- "LA4": "LA4",
- "LAA": "Aluminum",
- "LAB": "Body",
- "LAD": "Diagnostic",
- "LAE": "Electrical",
- "LAF": "Frame",
- "LAG": "Glass",
- "LAM": "Mechanical",
- "LAR": "Refinish",
- "LAS": "Structural",
- "LAU": "User Defined"
- },
- "line_desc": "Line Desc.",
- "line_ind": "S#",
- "line_no": "Line #",
- "location": "Location",
- "mod_lb_hrs": "Hrs",
- "mod_lbr_ty": "Labor Type",
- "notes": "Notes",
- "oem_partno": "OEM Part #",
- "op_code_desc": "Op Code Description",
- "part_qty": "Qty.",
- "part_type": "Part Type",
- "part_types": {
- "CCC": "CC Cleaning",
- "CCD": "CC Damage Waiver",
- "CCDR": "CC Daily Rate",
- "CCF": "CC Refuel",
- "CCM": "CC Mileage",
- "PAA": "Aftermarket",
- "PAC": "Rechromed",
- "PAE": "Existing",
- "PAG": "Glass",
- "PAL": "LKQ",
- "PAM": "Remanufactured",
- "PAN": "New/OEM",
- "PAO": "Other",
- "PAP": "OEM Partial",
- "PAR": "Recored",
- "PAS": "Sublet",
- "PASL": "Sublet (L)"
- },
- "profitcenter_labor": "Profit Center: Labor",
- "profitcenter_part": "Profit Center: Part",
- "prt_dsmk_m": "Line Discount/Markup $",
- "prt_dsmk_p": "Line Discount/Markup %",
- "status": "Status",
- "tax_part": "Tax Part",
- "total": "Total",
- "unq_seq": "Seq #"
- },
- "labels": {
- "adjustmenttobeadded": "Adjustment to be added: {{adjustment}}",
- "billref": "Latest Bill",
- "convertedtolabor": "This line has been converted to labor. Ensure you adjust the profit center for the amount accordingly.",
- "edit": "Edit Line",
- "ioucreated": "IOU",
- "new": "New Line",
- "nostatus": "No Status",
- "presets": "Jobline Presets"
- },
- "successes": {
- "created": "Job line created successfully.",
- "saved": "Job line saved.",
- "updated": "Job line updated successfully."
- },
- "validations": {
- "ahdetailonlyonuserdefinedtypes": "Detail line indicator can only be set for LA1, LA2, LA3, LA4, and LAU labor types.",
- "hrsrequirediflbrtyp": "Labor hours are required if a labor type is selected. Clear the labor type if there are no labor hours.",
- "requiredifparttype": "Required if a part type has been specified.",
- "zeropriceexistingpart": "This line cannot have any price since it uses an existing part."
- }
- },
- "jobs": {
- "actions": {
- "addDocuments": "Add Job Documents",
- "addNote": "Add Note",
- "addtopartsqueue": "Add to Parts Queue",
- "addtoproduction": "Add to Production",
- "addtoscoreboard": "Add to Scoreboard",
- "allocate": "Allocate",
- "autoallocate": "Auto Allocate",
- "changefilehandler": "Change Adjuster",
- "changelaborrate": "Change Labor Rate",
- "changestatus": "Change Status",
- "changestimator": "Change Estimator",
- "convert": "Convert",
- "createiou": "Create IOU",
- "deliver": "Deliver",
- "deliver_quick": "Quick Deliver",
- "dms": {
- "addpayer": "Add Payer",
- "createnewcustomer": "Create New Customer",
- "findmakemodelcode": "Find Make/Model Code",
- "getmakes": "Get Makes",
- "labels": {
- "refreshallocations": "Refresh this component to see the DMS allocations."
- },
- "post": "Post",
- "refetchmakesmodels": "Refetch Make and Model Codes",
- "usegeneric": "Use Generic Customer",
- "useselected": "Use Selected Customer"
- },
- "dmsautoallocate": "DMS Auto Allocate",
- "export": "Export",
- "exportcustdata": "Export Customer Data",
- "exportselected": "Export Selected",
- "filterpartsonly": "Filter Parts Only",
- "generatecsi": "Generate CSI & Copy Link",
- "gotojob": "Go to Job",
- "intake": "Intake",
- "intake_quick": "Quick Intake",
- "manualnew": "Create New Job Manually",
- "mark": "Mark",
- "markasexported": "Mark as Exported",
- "markpstexempt": "Mark Job PST Exempt",
- "markpstexemptconfirm": "Are you sure you want to do this? To undo this, you must manually update all PST rates.",
- "postbills": "Post Bills",
- "printCenter": "Print Center",
- "recalculate": "Recalculate",
- "reconcile": "Reconcile",
- "removefromproduction": "Remove from Production",
- "schedule": "Schedule",
- "sendcsi": "Send CSI",
- "sendpartspricechange": "Send Parts Price Change",
- "sendtodms": "Send to DMS",
- "sync": "Sync",
- "taxprofileoverride": "Override Tax Profile with Shop Configuration",
- "taxprofileoverride_confirm": "Are you sure you want to override the tax profile information? This cannot be undone without re-importing the job. ",
- "uninvoice": "Uninvoice",
- "unvoid": "Unvoid Job",
- "viewchecklist": "View Checklists",
- "viewdetail": "View Details"
- },
- "errors": {
- "addingtoproduction": "Error adding to production. {{error}}",
- "cannotintake": "Intake cannot be completed for this Job. It has either already been completed or the job is already here.",
- "closing": "Error closing Job. {{error}}",
- "creating": "Error encountered while creating job. {{error}}",
- "deleted": "Error deleting Job. {{error}}",
- "exporting": "Error exporting Job. {{error}}",
- "exporting-partner": "Unable to connect to partner application. Please ensure it is running and logged in.",
- "invoicing": "Error invoicing Job. {{error}}",
- "noaccess": "This Job does not exist or you do not have access to it.",
- "nodamage": "No damage points on estimate.",
- "nodates": "No dates specified for this Job.",
- "nofinancial": "No financial data has been calculated yet for this job. Please save it again.",
- "nojobselected": "No Job is selected.",
- "noowner": "No owner associated.",
- "novehicle": "No vehicle associated.",
- "partspricechange": "Error sending parts price change. {{error}}.",
- "saving": "Error encountered while saving record.",
- "scanimport": "Error importing Job. {{message}}",
- "totalscalc": "Error while calculating new Job totals.",
- "updating": "Error while updating Job(s). {{error}}",
- "validation": "Please ensure all fields are entered correctly.",
- "validationtitle": "Validation Error",
- "voiding": "Error voiding Job. {{error}}"
- },
- "fields": {
- "active_tasks": "Active Tasks",
- "actual_completion": "Actual Completion",
- "actual_delivery": "Actual Delivery",
- "actual_in": "Actual In",
- "adjustment_bottom_line": "Adjustments",
- "adjustmenthours": "Adjustment Hours",
- "alt_transport": "Alt. Trans.",
- "area_of_damage_impact": {
- "10": "Left Front Side",
- "11": "Left Front Corner",
- "12": "Front",
- "13": "Rollover",
- "14": "Unknown",
- "15": "Total Loss",
- "16": "Non-collision",
- "25": "Hood",
- "26": "Deck-lid",
- "27": "Roof",
- "28": "Undercarriage",
- "34": "All Over",
- "01": "Right Front Corner",
- "02": "Right Front Side",
- "03": "Right Side",
- "04": "Right Rear Side",
- "05": "Right Rear Corner",
- "06": "Rear",
- "07": "Left Rear Corner",
- "08": "Left Rear Side",
- "09": "Left Side"
- },
- "auto_add_ats": "Automatically Add/Update ATS",
- "ca_bc_pvrt": "PVRT",
- "ca_customer_gst": "Customer Portion of GST",
- "ca_gst_registrant": "GST Registrant",
- "category": "Category",
- "ccc": "CC Cleaning",
- "ccd": "CC Damage Waiver",
- "ccdr": "CC Daily Rate",
- "ccf": "CC Refuel",
- "ccm": "CC Mileage",
- "cieca_id": "CIECA ID",
- "cieca_pfl": {
- "lbr_adjp": "Labor Adjustment",
- "lbr_tax_in": "Tax Labor Indicator",
- "lbr_taxp": "Labor Tax Rate",
- "lbr_tx_in1": "Tax 1 Indicator",
- "lbr_tx_in2": "Tax 2 Indicator",
- "lbr_tx_in3": "Tax 3 Indicator",
- "lbr_tx_in4": "Tax 4 Indicator",
- "lbr_tx_in5": "Tax 5 Indicator"
- },
- "cieca_pfo": {
- "stor_t_in1": "Storage Tax 1 Indicator",
- "stor_t_in2": "Storage Tax 2 Indicator",
- "stor_t_in3": "Storage Tax 3 Indicator",
- "stor_t_in4": "Storage Tax 4 Indicator",
- "stor_t_in5": "Storage Tax 5 Indicator",
- "tow_t_in1": "Tow Tax 1 Indicator",
- "tow_t_in2": "Tow Tax 2 Indicator",
- "tow_t_in3": "Tow Tax 3 Indicator",
- "tow_t_in4": "Tow Tax 4 Indicator",
- "tow_t_in5": "Tow Tax 5 Indicator"
- },
- "claim_total": "Claim Total",
- "class": "Class",
- "clm_no": "Claim #",
- "clm_total": "Claim Total",
- "comment": "Comment",
- "customerowing": "Customer Owing",
- "date_estimated": "Date Estimated",
- "date_exported": "Exported",
- "date_invoiced": "Invoiced",
- "date_last_contacted": "Last Contacted Date",
- "date_lost_sale": "Lost Sale",
- "date_next_contact": "Next Contact Date",
- "date_open": "Open",
- "date_rentalresp": "Shop Rental Responsibility Start",
- "date_repairstarted": "Repairs Started",
- "date_scheduled": "Scheduled",
- "date_towin": "Towed In",
- "date_void": "Void",
- "ded_amt": "Deductible",
- "ded_note": "Deductible Note",
- "ded_status": "Deductible Status",
- "depreciation_taxes": "Betterment/Depreciation/Taxes",
- "dms": {
- "address": "Customer Address",
- "amount": "Amount",
- "center": "Center",
- "control_type": {
- "account_number": "Account Number"
- },
- "cost": "Cost",
- "cost_dms_acctnumber": "Cost DMS Acct #",
- "dms_make": "DMS Make",
- "dms_model": "DMS Model",
- "dms_model_override": "Override DMS Make/Model",
- "dms_unsold": "New, Unsold Vehicle",
- "dms_wip_acctnumber": "Cost WIP DMS Acct #",
- "id": "DMS ID",
- "inservicedate": "In Service Date",
- "journal": "Journal #",
- "lines": "Posting Lines",
- "name1": "Customer Name",
- "payer": {
- "amount": "Amount",
- "control_type": "Control Type",
- "controlnumber": "Control Number",
- "dms_acctnumber": "DMS Account #",
- "name": "Payer Name"
- },
- "sale": "Sale",
- "sale_dms_acctnumber": "Sale DMS Acct #",
- "story": "Story",
- "vinowner": "VIN Owner"
- },
- "dms_allocation": "DMS Allocation",
- "driveable": "Driveable",
- "employee_body": "Body",
- "employee_csr": "Customer Service Rep.",
- "employee_csr_writer": "Writer",
- "employee_prep": "Prep",
- "employee_refinish": "Refinish",
- "est_addr1": "Estimator Address",
- "est_co_nm": "Estimator Company",
- "est_ct_fn": "Estimator First Name",
- "est_ct_ln": "Estimator Last Name",
- "est_ea": "Estimator Email",
- "est_ph1": "Estimator Phone #",
- "federal_tax_payable": "Federal Tax Payable",
- "federal_tax_rate": "Federal Tax Rate",
- "ins_addr1": "Insurance Co. Address",
- "ins_city": "Insurance Co. City",
- "ins_co_id": "Insurance Co. ID",
- "ins_co_nm": "Insurance Company Name",
- "ins_co_nm_short": "Ins. Co.",
- "ins_ct_fn": "Adjuster First Name",
- "ins_ct_ln": "Adjuster Last Name",
- "ins_ea": "Adjuster Email",
- "ins_ph1": "Adjuster Phone #",
- "intake": {
- "label": "Label",
- "max": "Maximum",
- "min": "Minimum",
- "name": "Name",
- "required": "Required?",
- "type": "Type"
- },
- "invoice_final_note": "Note to Display on Final Invoice",
- "kmin": "Mileage In",
- "kmout": "Mileage Out",
- "la1": "LA1",
- "la2": "LA2",
- "la3": "LA3",
- "la4": "LA4",
- "laa": "Aluminum ",
- "lab": "Body",
- "labor_rate_desc": "Labor Rate Name",
- "lad": "Diagnostic",
- "lae": "Electrical",
- "laf": "Frame",
- "lag": "Glass",
- "lam": "Mechanical",
- "lar": "Refinish",
- "las": "Structural",
- "lau": "User Defined",
- "local_tax_rate": "Local Tax Rate",
- "loss_date": "Loss Date",
- "loss_desc": "Loss Description",
- "loss_of_use": "Loss of Use",
- "lost_sale_reason": "Lost Sale Reason",
- "ma2s": "2 Stage Paint",
- "ma3s": "3 Stage Pain",
- "mabl": "MABL?",
- "macs": "MACS?",
- "mahw": "Hazardous Waste",
- "mapa": "Paint Materials",
- "mash": "Shop Materials",
- "matd": "Tire Disposal",
- "materials": {
- "MAPA": "Paint Materials",
- "MASH": "Shop Materials",
- "cal_maxdlr": "Threshhold",
- "cal_opcode": "OP Codes",
- "mat_adjp": "Material Adjustment",
- "mat_taxp": "Material Tax Rate",
- "mat_tx_in1": "Tax 1 Indicator",
- "mat_tx_in2": "Tax 2 Indicator",
- "mat_tx_in3": "Tax 3 Indicator",
- "mat_tx_in4": "Tax 4 Indicator",
- "mat_tx_in5": "Tax 5 Indicator",
- "materials": "Profile - Materials",
- "tax_ind": "Tax Indicator"
- },
- "other_amount_payable": "Other Amount Payable",
- "owner": "Owner",
- "owner_owing": "Cust. Owes",
- "ownr_ea": "Email",
- "ownr_ph1": "Phone 1",
- "ownr_ph2": "Phone 2",
- "paa": "Aftermarket",
- "pac": "Rechromed",
- "pae": "Existing",
- "pag": "Glass",
- "pal": "LKQ",
- "pam": "Remanufactured",
- "pan": "OEM/New",
- "pao": "Other",
- "pap": "OEM Partial",
- "par": "Re-cored",
- "parts_tax_rates": {
- "prt_discp": "Discount %",
- "prt_mktyp": "Markup Type",
- "prt_mkupp": "Markup %",
- "prt_tax_in": "Tax Indicator",
- "prt_tax_rt": "Part Tax Rate",
- "prt_tx_in1": "Tax 1 Indicator",
- "prt_tx_in2": "Tax 2 Indicator",
- "prt_tx_in3": "Tax 3 Indicator",
- "prt_tx_in4": "Tax 4 Indicator",
- "prt_tx_in5": "Tax 5 Indicator",
- "prt_tx_ty1": "Parts Tax Type 1",
- "prt_type": "Part Type"
- },
- "partsstatus": "Parts Status",
- "pas": "Sublet",
- "pay_date": "Pay Date",
- "phoneshort": "PH",
- "po_number": "PO Number",
- "policy_no": "Policy #",
- "ponumber": "PO Number",
- "production_vars": {
- "note": "Production Note"
- },
- "qb_multiple_payers": {
- "amount": "Amount",
- "name": "Name"
- },
- "queued_for_parts": "Queued for Parts",
- "rate_ats": "ATS Rate",
- "rate_la1": "LA1",
- "rate_la2": "LA2",
- "rate_la3": "LA3",
- "rate_la4": "LA4",
- "rate_laa": "Aluminum",
- "rate_lab": "Body",
- "rate_lad": "Diagnostic",
- "rate_lae": "Electrical",
- "rate_laf": "Frame",
- "rate_lag": "Glass",
- "rate_lam": "Mechanical",
- "rate_lar": "Refinish",
- "rate_las": "Structural",
- "rate_lau": "User Defined",
- "rate_ma2s": "2 Stage Paint",
- "rate_ma3s": "3 Stage Paint",
- "rate_mabl": "MABL??",
- "rate_macs": "MACS??",
- "rate_mahw": "Hazardous Waste",
- "rate_mapa": "Paint Materials",
- "rate_mash": "Shop Material",
- "rate_matd": "Tire Disposal",
- "referral_source_extra": "Other Referral Source",
- "referral_source_other": "",
- "referralsource": "Referral Source",
- "regie_number": "Registration #",
- "repairtotal": "Repair Total",
- "ro_number": "RO #",
- "scheduled_completion": "Scheduled Completion",
- "scheduled_delivery": "Scheduled Delivery",
- "scheduled_in": "Scheduled In",
- "selling_dealer": "Selling Dealer",
- "selling_dealer_contact": "Selling Dealer Contact",
- "servicecar": "Service Car",
- "servicing_dealer": "Servicing Dealer",
- "servicing_dealer_contact": "Servicing Dealer Contact",
- "special_coverage_policy": "Special Coverage Policy",
- "specialcoveragepolicy": "Special Coverage Policy",
- "state_tax_rate": "State Tax Rate",
- "status": "Job Status",
- "storage_payable": "Storage",
- "tax_lbr_rt": "Labor Tax Rate",
- "tax_levies_rt": "Levies Tax Rate",
- "tax_paint_mat_rt": "Paint Material Tax Rate",
- "tax_registration_number": "Tax Registration Number",
- "tax_shop_mat_rt": "Shop Material Tax Rate",
- "tax_str_rt": "Storage Tax Rate",
- "tax_sub_rt": "Sublet Tax Rate",
- "tax_tow_rt": "Towing Tax Rate",
- "tlos_ind": "Total Loss Indicator",
- "towin": "Tow In",
- "towing_payable": "Towing Payable",
- "unitnumber": "Unit #",
- "updated_at": "Updated At",
- "uploaded_by": "Uploaded By",
- "vehicle": "Vehicle"
- },
- "forms": {
- "admindates": "Administrative Dates",
- "appraiserinfo": "Estimator Info",
- "claiminfo": "Claim Information",
- "estdates": "Estimate Dates",
- "laborrates": "Labor Rates",
- "lossinfo": "Loss Information",
- "other": "Other",
- "repairdates": "Repair Dates",
- "scheddates": "Schedule Dates"
- },
- "labels": {
- "accountsreceivable": "Accounts Receivable",
- "act_price_ppc": "New Part Price",
- "actual_completion_inferred": "$t(jobs.fields.actual_completion) inferred using $t(jobs.fields.scheduled_completion).",
- "actual_delivery_inferred": "$t(jobs.fields.actual_delivery) inferred using $t(jobs.fields.scheduled_delivery).",
- "actual_in_inferred": "$t(jobs.fields.actual_in) inferred using $t(jobs.fields.scheduled_in).",
- "additionalpayeroverallocation": "You have allocated more than the sale of the Job to additional payers.",
- "additionaltotal": "Additional Total",
- "adjustmentrate": "Adjustment Rate",
- "adjustments": "Adjustments",
- "adminwarning": "Use the functionality on this page at your own risk. You are responsible for any and all changes to your data.",
- "allocations": "Allocations",
- "alreadyaddedtoscoreboard": "Job has already been added to scoreboard. Saving will update the previous entry.",
- "alreadyclosed": "This Job has already been closed.",
- "appointmentconfirmation": "Send confirmation to customer?",
- "associationwarning": "Any changes to associations will require updating the data from the new parent record to the Job.",
- "audit": "Audit Trail",
- "available": "Available",
- "availablejobs": "Available Jobs",
- "ca_bc_pvrt": {
- "days": "Days",
- "rate": "PVRT Rate"
- },
- "ca_gst_all_if_null": "If the Job is marked as a \"GST Registrant\" and this value is set to $0, the customer will be responsible for paying all of the GST by default. ",
- "calc_repair_days": "Calculated Repair Days",
- "calc_repair_days_tt": "This is the approximate number of days required to complete the repair according to the target touch time in your shop configuration (current set to {{target_touchtime}}).",
- "calc_scheuled_completion": "Calculate Scheduled Completion",
- "cards": {
- "customer": "Customer Information",
- "damage": "Area of Damage",
- "dates": "Dates",
- "documents": "Recent Documents",
- "estimator": "Estimator",
- "filehandler": "Adjuster",
- "insurance": "Insurance Details",
- "more": "More",
- "notes": "Notes",
- "parts": "Parts",
- "totals": "Totals",
- "vehicle": "Vehicle"
- },
- "changeclass": "Changing the Job's class can have fundamental impacts to already exported accounting items. Are you sure you want to do this?",
- "checklistcompletedby": "Checklist completed by {{by}} at {{at}}",
- "checklistdocuments": "Checklist Documents",
- "checklists": "Checklists",
- "cieca_pfl": "Profile - Labor",
- "cieca_pfo": "Profile - Other",
- "cieca_pft": "Profile - Taxes",
- "closeconfirm": "Are you sure you want to close this job? This cannot be easily undone.",
- "closejob": "Close Job {{ro_number}}",
- "closingperiod": "This Invoice Date is outside of the Closing Period.",
- "contracts": "CC Contracts",
- "convertedtolabor": "Labor Line Adjustments",
- "cost": "Cost",
- "cost_Additional": "Cost - Additional",
- "cost_labor": "Cost - Labor",
- "cost_parts": "Cost - Parts",
- "cost_sublet": "Cost - Sublet",
- "costs": "Costs",
- "create": {
- "jobinfo": "Job Info",
- "newowner": "Create a new Owner instead. ",
- "newvehicle": "Create a new Vehicle Instead",
- "novehicle": "No vehicle (only for ROs to track parts/labor only work).",
- "ownerinfo": "Owner Info",
- "vehicleinfo": "Vehicle Info"
- },
- "createiouwarning": "Are you sure you want to create an IOU for these lines? A new RO will be created based on those lines for this customer.",
- "creating_new_job": "Creating new Job...",
- "deductible": {
- "stands": "Stands",
- "waived": "Waived"
- },
- "deleteconfirm": "Are you sure you want to delete this Job? This cannot be undone. ",
- "deletedelivery": "Delete Delivery Checklist",
- "deleteintake": "Delete Intake Checklist",
- "deliverchecklist": "Deliver Checklist",
- "difference": "Difference",
- "diskscan": "Scan Disk for Estimates",
- "dms": {
- "apexported": "AP export completed. See logs for details.",
- "damageto": "Damage to $t(jobs.fields.area_of_damage_impact.{{area_of_damage}}).",
- "defaultstory": "B/S RO: {{ro_number}}. Owner: {{ownr_nm}}. Insurance Co: {{ins_co_nm}}. Claim/PO #: {{clm_po}}",
- "disablebillwip": "Cost and WIP for bills has been ignored per shop configuration.",
- "invoicedatefuture": "Invoice date must be today or in the future for CDK posting.",
- "kmoutnotgreaterthankmin": "Mileage out must be greater than mileage in.",
- "logs": "Logs",
- "notallocated": "Not Allocated",
- "postingform": "Posting Form",
- "totalallocated": "Total Amount Allocated"
- },
- "documents": "Documents",
- "documents-images": "Images",
- "documents-other": "Other Documents",
- "duplicateconfirm": "Are you sure you want to duplicate this Job? Some elements of this Job will not be duplicated.",
- "emailaudit": "Email Audit Trail",
- "employeeassignments": "Employee Assignments",
- "estimatelines": "Estimate Lines",
- "estimator": "Estimator",
- "existing_jobs": "Existing Jobs",
- "federal_tax_amt": "Federal Taxes",
- "gpdollars": "$ G.P.",
- "gppercent": "% G.P.",
- "hrs_claimed": "Hours Flagged",
- "hrs_total": "Hours Total",
- "importnote": "The Job was initially imported.",
- "inproduction": "In Production",
- "intakechecklist": "Intake Checklist",
- "iou": "IOU",
- "job": "Job Details",
- "jobcosting": "Job Costing",
- "jobtotals": "Job Totals",
- "labor_hrs": "B/P/T Hrs",
- "labor_rates_subtotal": "Labor Rates Subtotal",
- "laborallocations": "Labor Allocations",
- "labortotals": "Labor Totals",
- "lines": "Estimate Lines",
- "local_tax_amt": "Local Taxes",
- "mapa": "Paint Materials",
- "markforreexport": "Mark for Re-export",
- "mash": "Shop Materials",
- "masterbypass": "Master Bypass Password",
- "materials": {
- "mapa": ""
- },
- "missingprofileinfo": "This job has missing tax profile info. To ensure correct totals calculations, re-import the job.",
- "multipayers": "Additional Payers",
- "net_repairs": "Net Repairs",
- "notes": "Notes",
- "othertotal": "Other Totals",
- "outstanding_ar": "A balance is outstanding on this RO. Payments can still be entered when the job is closed. ",
- "outstanding_credit_memos": "Outstanding credit memos have not been entered against this job. Credit Memos may still be posted once the job is closed.",
- "outstanding_ppd": "There are outstanding PPDs that may not have been synced back to the estimate.",
- "outstanding_reconciliation_discrep": "At least one discrepancy is not $0. This may indicate that this job is not properly reconciled and should not be closed.",
- "outstanding_sublets": "There are sublet lines on the job which have not been marked as completed. ",
- "outstandinghours": "There are outstanding hours on the job that have not been paid or have been overpaid.",
- "override_header": "Override estimate header on import?",
- "ownerassociation": "Owner Association",
- "parts": "Parts",
- "parts_lines": "Parts Lines",
- "parts_received": "Parts Rec.",
- "parts_tax_rates": "Profile - Parts",
- "partsfilter": "Parts Only",
- "partssubletstotal": "Parts & Sublets Total",
- "partstotal": "Parts Total (ex. Taxes)",
- "performance": "Performance",
- "pimraryamountpayable": "Total Primary Payable",
- "plitooltips": {
- "billtotal": "The total amount of all bill lines that have been posted against this RO (not including credits, taxes, or labor adjustments).",
- "calculatedcreditsnotreceived": "The calculated credits not received is derived by subtracting the amount of credit memos entered from the retail total of returns created. This does not take into account whether the credit was marked as received. You can find more information here .",
- "creditmemos": "The total retail amount of all returns created. This amount does not reflect credit memos that have been posted.",
- "creditsnotreceived": "This total reflects the total retail of parts returns lines that have not been explicitly marked as returned when posting a credit memo. You can learn more about this here here . ",
- "discrep1": "If the discrepancy is not $0, you may have one of the following: \n\n\nToo many bills/bill lines that have been posted against this RO. Check to make sure every bill posted on this RO is correctly posted and assigned. \nYou do not have the latest supplement imported, or, a supplement must be submitted and then imported. \nYou have posted a bill line to labor. \n \n \nThere may be additional issues not listed above that prevent this Job from reconciling. ",
- "discrep2": "If the discrepancy is not $0, you may have one of the following: \n\n\nUsed an incorrect rate when deducting from labor. \nAn outstanding imbalance higher in the reconciliation process. \n \n \nThere may be additional issues not listed above that prevent this Job from reconciling. ",
- "discrep3": "If the discrepancy is not $0, you may have one of the following: \n\n\nA parts order return has not been created. \nAn outstanding imbalance higher in the reconciliation process. \n \n \nThere may be additional issues not listed above that prevent this Job from reconciling. ",
- "laboradj": "The sum of all bill lines that deducted from labor hours, rather than part prices.",
- "partstotal": "This is the total of all parts and sublet amounts on the vehicle (some of these may require an in-house invoice). \nItems such as shop and paint materials, labor online lines, etc. are not included in this total.",
- "totalreturns": "The total retail amount of returns created for this job."
- },
- "ppc": "This line contains a part price change.",
- "ppdnotexported": "PPDs not Exported",
- "profileadjustments": "Profile Disc./Mkup",
- "profitbypassrequired": "Minimum gross profit requirements have not been met.",
- "profits": "Job Profits",
- "prt_dsmk_total": "Line Item Adjustment",
- "rates": "Rates",
- "rates_subtotal": "All Rates Subtotal",
- "reconciliation": {
- "billlinestotal": "Bill Lines Total",
- "byassoc": "By Line Association",
- "byprice": "By Price",
- "clear": "Clear All",
- "discrepancy": "Discrepancy",
- "joblinestotal": "Job Lines Total",
- "multipleactprices": "${{act_price}} is the price for multiple job lines.",
- "multiplebilllines": "{{line_desc}} has 2 or more bill lines associated to it.",
- "multiplebillsforactprice": "Found more than 1 bill matching ${{act_price}} retail price.",
- "removedpartsstrikethrough": "Strike through lines represent parts that have been removed from the estimate. They are included for completeness of reconciliation."
- },
- "reconciliationheader": "Parts & Sublet Reconciliation",
- "relatedros": "Related ROs",
- "remove_from_ar": "Remove from AR",
- "returntotals": "Return Totals",
- "ro_guard": {
- "enforce_ar": "AR collection enforced.",
- "enforce_bills": "Bill discrepancy enforced.",
- "enforce_cm": "Credit memo entry enforced.",
- "enforce_labor": "Labor allocations enforced.",
- "enforce_ppd": "PPD sync enforced.",
- "enforce_profit": "Profit marginsenforced.",
- "enforce_sublet": "Sublet completion enforced.",
- "enforce_validation": "Master Bypass Required: {{message}}",
- "enforced": "This check has been enforced by your shop manager. Enter the master bypass password to close the Job."
- },
- "roguard": "RO Guard",
- "roguardwarnings": "RO Guard Warnings",
- "rosaletotal": "RO Parts Total",
- "sale_additional": "Sales - Additional",
- "sale_labor": "Sales - Labor",
- "sale_parts": "Sales - Parts",
- "sale_sublet": "Sales - Sublet",
- "sales": "Sales",
- "savebeforeconversion": "You have unsaved changes on the Job. Please save them before converting it. ",
- "scheduledinchange": "The scheduled in is based off the latest appointment. To change this date, please schedule or reschedule the Job. ",
- "specialcoveragepolicy": "Special Coverage Policy Applies",
- "state_tax_amt": "Provincial/State Taxes",
- "subletsnotcompleted": "Outstanding Sublets",
- "subletstotal": "Sublets Total",
- "subtotal": "Subtotal",
- "supplementnote": "The Job had a supplement imported.",
- "suspended": "SUSPENDED",
- "suspense": "Suspense",
- "tasks": "Tasks",
- "threshhold": "Max Threshold: ${{amount}}",
- "total_cost": "Total Cost",
- "total_cust_payable": "Total Customer Amount Payable",
- "total_cust_payable_cash_discount": "$t(jobs.labels.total_cust_payable) (Cash Discounted)",
- "total_repairs": "Total Repairs",
- "total_repairs_cash_discount": "Total Repairs (Cash Discounted)",
- "total_sales": "Total Sales",
- "total_sales_tax": "Total Sales Tax",
- "totals": "Totals",
- "unvoidnote": "This Job was unvoided.",
- "update_scheduled_completion": "Update Scheduled Completion?",
- "vehicle_info": "Vehicle",
- "vehicleassociation": "Vehicle Association",
- "viewallocations": "View Allocations",
- "voidjob": "Are you sure you want to void this Job? This cannot be easily undone. ",
- "voidnote": "This Job was voided."
- },
- "successes": {
- "addedtoproduction": "Job added to production board.",
- "all_deleted": "{{count}} Jobs deleted successfully.",
- "closed": "Job closed successfully.",
- "converted": "Job converted successfully.",
- "created": "Job created successfully. Click to view.",
- "creatednoclick": "Job created successfully. ",
- "delete": "Job deleted successfully.",
- "deleted": "Job deleted successfully.",
- "duplicated": "Job duplicated successfully. ",
- "exported": "Job(s) exported successfully. ",
- "invoiced": "Job closed and invoiced successfully.",
- "ioucreated": "IOU created successfully. Click to see.",
- "partsqueue": "Job added to parts queue.",
- "save": "Job saved successfully.",
- "savetitle": "Record saved successfully.",
- "supplemented": "Job supplemented successfully. ",
- "updated": "Job(s) updated successfully.",
- "voided": "Job voided successfully."
- }
- },
- "landing": {
- "bigfeature": {
- "subtitle": "Rome Online is built using world class technology by experts in the collision repair industry. This translates to software that is tailor made for the unique challenges faced by repair facilities with no compromises. ",
- "title": "Bringing the latest technology to the automotive repair industry. "
- },
- "footer": {
- "company": {
- "about": "About Us",
- "contact": "Contact",
- "disclaimers": "Disclaimers",
- "name": "Company",
- "privacypolicy": "Privacy Policy"
- },
- "io": {
- "help": "Help",
- "name": "Rome Online",
- "status": "System Status"
- },
- "slogan": "Rome Technologies. is a technology leader in the collision repair industry. We specialize in creating collision repair management systems and bodyshop management systems that lower cycle times and promote efficiency."
- },
- "hero": {
- "button": "Learn More",
- "title": "Shop management reimagined."
- },
- "labels": {
- "features": "Features",
- "managemyshop": "Sign In",
- "pricing": "Pricing"
- },
- "pricing": {
- "basic": {
- "name": "Basic",
- "sub": "Best suited for shops looking to increase their volume."
- },
- "essentials": {
- "name": "Essentials",
- "sub": "Best suited for small and low volume shops."
- },
- "pricingtitle": "Features",
- "pro": {
- "name": "Pro",
- "sub": "Empower your shop with the tools to operate at peak capacity."
- },
- "title": "Features",
- "unlimited": {
- "name": "Unlimited",
- "sub": "Everything you need and more for the high volume shop."
- }
- }
- },
- "menus": {
- "currentuser": {
- "languageselector": "Language",
- "profile": "Profile"
- },
- "header": {
- "accounting": "Accounting",
- "accounting-payables": "Payables",
- "accounting-payments": "Payments",
- "accounting-receivables": "Receivables",
- "activejobs": "Active Jobs",
- "all_tasks": "All Tasks",
- "alljobs": "All Jobs",
- "allpayments": "All Payments",
- "availablejobs": "Available Jobs",
- "bills": "Bills",
- "courtesycars": "Courtesy Cars",
- "courtesycars-all": "All Courtesy Cars",
- "courtesycars-contracts": "Contracts",
- "courtesycars-newcontract": "New Contract",
- "create_task": "Create Task",
- "customers": "Customers",
- "dashboard": "Dashboard",
- "enterbills": "Enter Bills",
- "entercardpayment": "New Card Charge",
- "enterpayment": "Enter Payments",
- "entertimeticket": "Enter Time Tickets",
- "export": "Export",
- "export-logs": "Export Logs",
- "help": "Help",
- "home": "Home",
- "inventory": "Inventory",
- "jobs": "Jobs",
- "my_tasks": "My Tasks",
- "newjob": "Create New Job",
- "owners": "Owners",
- "parts-queue": "Parts Queue",
- "phonebook": "Phonebook",
- "productionboard": "Production Board - Visual",
- "productionlist": "Production Board - List",
- "readyjobs": "Ready Jobs",
- "recent": "Recent Items",
- "reportcenter": "Report Center",
- "rescueme": "Rescue me!",
- "schedule": "Schedule",
- "scoreboard": "Scoreboard",
- "search": {
- "bills": "Bills",
- "jobs": "Jobs",
- "owners": "Owners",
- "payments": "Payments",
- "phonebook": "Phonebook",
- "vehicles": "Vehicles"
- },
- "shiftclock": "Shift Clock",
- "shop": "My Shop",
- "shop_config": "Configuration",
- "shop_csi": "CSI",
- "shop_templates": "Templates",
- "shop_vendors": "Vendors",
- "tasks": "Tasks",
- "temporarydocs": "Temporary Documents",
- "timetickets": "Time Tickets",
- "ttapprovals": "Time Ticket Approvals",
- "vehicles": "Vehicles"
- },
- "jobsactions": {
- "admin": "Admin",
- "cancelallappointments": "Cancel all appointments",
- "closejob": "Close Job",
- "deletejob": "Delete Job",
- "duplicate": "Duplicate this Job",
- "duplicatenolines": "Duplicate this Job without Repair Data",
- "newcccontract": "Create Courtesy Car Contract",
- "void": "Void Job"
- },
- "jobsdetail": {
- "claimdetail": "Claim Details",
- "dates": "Dates",
- "financials": "Financial Information",
- "general": "General",
- "insurance": "Insurance Information",
- "labor": "Labor",
- "lifecycle": "Lifecycle",
- "parts": "Parts",
- "partssublet": "Parts & Bills",
- "rates": "Rates",
- "repairdata": "Repair Data",
- "totals": "Totals"
- },
- "profilesidebar": {
- "profile": "My Profile",
- "shops": "My Shops"
- },
- "tech": {
- "assignedjobs": "Assigned Jobs",
- "claimtask": "Flag Hours",
- "dispatchedparts": "Dispatched Parts",
- "home": "Home",
- "jobclockin": "Job Clock In",
- "jobclockout": "Job Clock Out",
- "joblookup": "Job Lookup",
- "login": "Login",
- "logout": "Logout",
- "productionboard": "Production Visual",
- "productionlist": "Production List",
- "shiftclockin": "Shift Clock"
- }
- },
- "messaging": {
- "actions": {
- "link": "Link to Job",
- "new": "New Conversation"
- },
- "errors": {
- "invalidphone": "The phone number is invalid. Unable to open conversation. ",
- "noattachedjobs": "No Jobs have been associated to this conversation. ",
- "updatinglabel": "Error updating label. {{error}}"
- },
- "labels": {
- "addlabel": "Add a label to this conversation.",
- "archive": "Archive",
- "maxtenimages": "You can only select up to a maximum of 10 images at a time.",
- "messaging": "Messaging",
- "noallowtxt": "This customer has not indicated their permission to be messaged.",
- "nojobs": "Not associated to any Job.",
- "nopush": "Polling Mode Enabled",
- "phonenumber": "Phone #",
- "presets": "Presets",
- "recentonly": "Only your most recent 50 conversations will be shown here. If you are looking for an older conversation, find the related contact and click their phone number to view the conversation.",
- "selectmedia": "Select Media",
- "sentby": "Sent by {{by}} at {{time}}",
- "typeamessage": "Send a message...",
- "unarchive": "Unarchive"
- },
- "render": {
- "conversation_list": "Conversation List"
- }
- },
- "notes": {
- "actions": {
- "actions": "Actions",
- "deletenote": "Delete Note",
- "edit": "Edit Note",
- "new": "New Note",
- "savetojobnotes": "Save to Job Notes"
- },
- "errors": {
- "inserting": "Error inserting note. {{error}}"
- },
- "fields": {
- "createdby": "Created By",
- "critical": "Critical",
- "private": "Private",
- "text": "Contents",
- "type": "Type",
- "types": {
- "customer": "Customer",
- "general": "General",
- "office": "Office",
- "paint": "Paint",
- "parts": "Parts",
- "shop": "Shop",
- "supplement": "Supplement"
- },
- "updatedat": "Updated At"
- },
- "labels": {
- "addtorelatedro": "Add to Related ROs",
- "newnoteplaceholder": "Add a note...",
- "notetoadd": "Note to Add",
- "systemnotes": "System Notes",
- "usernotes": "User Notes"
- },
- "successes": {
- "create": "Note created successfully.",
- "deleted": "Note deleted successfully.",
- "updated": "Note updated successfully."
- }
- },
- "owner": {
- "labels": {
- "noownerinfo": "No owner information."
- }
- },
- "owners": {
- "actions": {
- "update": "Update Selected Records"
- },
- "errors": {
- "deleting": "Error deleting owner. {{error}}.",
- "noaccess": "The record does not exist or you do not have access to it. ",
- "saving": "Error saving owner. {{error}}.",
- "selectexistingornew": "Select an existing owner record or create a new one. "
- },
- "fields": {
- "accountingid": "Accounting ID",
- "address": "Address",
- "allow_text_message": "Permission to Text?",
- "name": "Name",
- "note": "Owner Note",
- "ownr_addr1": "Address",
- "ownr_addr2": "Address 2",
- "ownr_city": "City",
- "ownr_co_nm": "Owner Co. Name",
- "ownr_ctry": "Country",
- "ownr_ea": "Email",
- "ownr_fn": "First Name",
- "ownr_ln": "Last Name",
- "ownr_ph1": "Phone 1",
- "ownr_ph2": "Phone 2",
- "ownr_st": "Province/State",
- "ownr_title": "Title",
- "ownr_zip": "Zip/Postal Code",
- "preferred_contact": "Preferred Contact Method",
- "tax_number": "Tax Number"
- },
- "forms": {
- "address": "Address",
- "contact": "Contact Information",
- "name": "Owner Details"
- },
- "labels": {
- "create_new": "Create a new owner record.",
- "deleteconfirm": "Are you sure you want to delete this owner? This cannot be undone.",
- "existing_owners": "Existing Owners",
- "fromclaim": "Current Claim",
- "fromowner": "Historical Owner Record",
- "relatedjobs": "Related Jobs",
- "updateowner": "Update Owner"
- },
- "successes": {
- "delete": "Owner deleted successfully.",
- "save": "Owner saved successfully."
- }
- },
- "parts": {
- "actions": {
- "order": "Order Parts",
- "orderinhouse": "Order as In House"
- }
- },
- "parts_dispatch": {
- "actions": {
- "accept": "Accept"
- },
- "errors": {
- "accepting": "Error accepting parts dispatch. {{error}}",
- "creating": "Error dispatching parts. {{error}}"
- },
- "fields": {
- "number": "Number",
- "percent_accepted": "% Accepted"
- },
- "labels": {
- "notyetdispatched": "This part has not been dispatched.",
- "parts_dispatch": "Parts Dispatch"
- }
- },
- "parts_dispatch_lines": {
- "fields": {
- "accepted_at": "Accepted At"
- }
- },
- "parts_orders": {
- "actions": {
- "backordered": "Mark Backordered",
- "receive": "Receive",
- "receivebill": "Receive Bill"
- },
- "errors": {
- "associatedbills": "This parts order cannot",
- "backordering": "Error backordering part {{message}}.",
- "creating": "Error encountered when creating parts order. ",
- "oec": "Error creating EMS files for parts order. {{error}}",
- "saving": "Error saving parts order. {{error}}.",
- "updating": "Error updating parts order/parts order line. {{error}}."
- },
- "fields": {
- "act_price": "Price",
- "backordered_eta": "B.O. ETA",
- "backordered_on": "B.O. On",
- "cm_received": "CM Received?",
- "comments": "Comments",
- "cost": "Cost",
- "db_price": "List Price",
- "deliver_by": "Deliver By",
- "job_line_id": "Job Line Id",
- "line_desc": "Line Description",
- "line_remarks": "Remarks",
- "lineremarks": "Line Remarks",
- "oem_partno": "Part #",
- "order_date": "Order Date",
- "order_number": "Order Number",
- "orderedby": "Ordered By",
- "part_type": "Type",
- "quantity": "Qty.",
- "return": "Return",
- "status": "Status"
- },
- "labels": {
- "allpartsto": "All Parts Location",
- "confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. Job line statuses will not be updated and may require manual review. ",
- "custompercent": "Custom %",
- "discount": "Discount {{percent}}",
- "email": "Send by Email",
- "inthisorder": "Parts in this Order",
- "is_quote": "Parts Quote?",
- "mark_as_received": "Mark as Received?",
- "newpartsorder": "New Parts Order",
- "notyetordered": "This part has not yet been ordered.",
- "oec": "Order via EMS",
- "order_type": "Order Type",
- "orderhistory": "Order History",
- "parts_order": "Parts Order",
- "parts_orders": "Parts Orders",
- "parts_returns": "Parts Returns",
- "print": "Show Printed Form",
- "receive": "Receive Parts Order",
- "removefrompartsqueue": "Unqueue from Parts Queue?",
- "returnpartsorder": "Return Parts Order",
- "sublet_order": "Sublet Order"
- },
- "successes": {
- "created": "Parts order created successfully. ",
- "line_updated": "Parts return line updated.",
- "received": "Parts order received.",
- "return_created": "Parts return created successfully."
- }
- },
- "payments": {
- "actions": {
- "generatepaymentlink": "Generate Payment Link"
- },
- "errors": {
- "exporting": "Error exporting payment(s). {{error}}",
- "exporting-partner": "Error exporting to partner. Please check the partner interaction log for more errors.",
- "inserting": "Error inserting payment. {{error}}"
- },
- "fields": {
- "amount": "Amount",
- "created_at": "Created At",
- "date": "Payment Date",
- "exportedat": "Exported At",
- "memo": "Memo",
- "payer": "Payer",
- "paymentnum": "Payment Number",
- "stripeid": "Stripe ID",
- "transactionid": "Transaction ID",
- "type": "Type"
- },
- "labels": {
- "balance": "Balance",
- "ca_bc_etf_table": "ICBC EFT Table Converter",
- "customer": "Customer",
- "edit": "Edit Payment",
- "electronicpayment": "Use Electronic Payment Processing?",
- "external": "External",
- "findermodal": "ICBC Payment Finder",
- "insurance": "Insurance",
- "markexported": "Mark Exported",
- "markforreexport": "Mark for Re-export",
- "new": "New Payment",
- "signup": "Please contact support to sign up for electronic payments.",
- "smspaymentreminder": "This is {{shopname}} reminding you about your balance of {{amount}}. To pay, click the following link {{payment_link}}.",
- "title": "Payments",
- "totalpayments": "Total Payments"
- },
- "successes": {
- "exported": "Payment(s) exported successfully.",
- "markexported": "Payment(s) marked exported.",
- "markreexported": "Payment marked for re-export successfully",
- "payment": "Payment created successfully. ",
- "paymentupdate": "Payment updated successfully. ",
- "stripe": "Credit card transaction charged successfully."
- }
- },
- "phonebook": {
- "actions": {
- "new": "New Phonebook Entry"
- },
- "errors": {
- "adding": "Error adding phonebook entry. {{error}}",
- "saving": "Error saving phonebook entry. {{error}}"
- },
- "fields": {
- "address1": "Street 1",
- "address2": "Street 2",
- "category": "Category",
- "city": "City",
- "company": "Company",
- "country": "Country",
- "email": "Email",
- "fax": "Fax",
- "firstname": "First Name",
- "lastname": "Last Name",
- "phone1": "Phone 1",
- "phone2": "Phone 2",
- "state": "Province/State"
- },
- "labels": {
- "noneselected": "No phone book entry selected. ",
- "onenamerequired": "At least one name related field is required.",
- "vendorcategory": "Vendor"
- },
- "successes": {
- "added": "Phonebook entry added successfully. ",
- "deleted": "Phonebook entry deleted successfully. ",
- "saved": "Phonebook entry saved successfully. "
- }
- },
- "printcenter": {
- "appointments": {
- "appointment_confirmation": "Appointment Confirmation"
- },
- "bills": {
- "inhouse_invoice": "In House Invoice"
- },
- "courtesycarcontract": {
- "courtesy_car_contract": "Courtesy Car Contract",
- "courtesy_car_impound": "Impound Charges",
- "courtesy_car_inventory": "Courtesy Car Inventory",
- "courtesy_car_terms": "Courtesy Car Terms"
- },
- "errors": {
- "nocontexttype": "No context type set."
- },
- "jobs": {
- "3rdpartyfields": {
- "addr1": "Address 1",
- "addr2": "Address 2",
- "addr3": "Address 3",
- "attn": "Attention",
- "city": "City",
- "custgst": "Customer Portion of GST",
- "ded_amt": "Deductible",
- "depreciation": "Depreciation",
- "other": "Other",
- "ponumber": "PO Number",
- "refnumber": "Reference Number",
- "sendtype": "Send by",
- "state": "Province/State",
- "zip": "Postal Code/Zip"
- },
- "3rdpartypayer": "Invoice to Third Party Payer",
- "ab_proof_of_loss": "AB - Proof of Loss",
- "appointment_confirmation": "Appointment Confirmation",
- "appointment_reminder": "Appointment Reminder",
- "casl_authorization": "CASL Authorization",
- "committed_timetickets_ro": "Committed Time Tickets",
- "coversheet_landscape": "Coversheet (Landscape)",
- "coversheet_portrait": "Coversheet Portrait",
- "csi_invitation": "CSI Invitation",
- "csi_invitation_action": "CSI Invite",
- "diagnostic_authorization": "Diagnostic Authorization",
- "dms_posting_sheet": "DMS Posting Sheet",
- "envelope_return_address": "#10 Envelope Return Address Label",
- "estimate": "Estimate Only",
- "estimate_detail": "Estimate Details",
- "estimate_followup": "Estimate Followup",
- "express_repair_checklist": "Express Repair Checklist",
- "filing_coversheet_landscape": "Filing Coversheet (Landscape)",
- "filing_coversheet_portrait": "Filing Coversheet (Portrait)",
- "final_invoice": "Final Invoice",
- "fippa_authorization": "FIPPA Authorization",
- "folder_label_multiple": "Folder Label - Multi",
- "glass_express_checklist": "Glass Express Checklist",
- "guarantee": "Repair Guarantee",
- "individual_job_note": "RO Job Note",
- "invoice_customer_payable": "Invoice (Customer Payable)",
- "invoice_total_payable": "Invoice (Total Payable)",
- "iou_form": "IOU Form",
- "job_costing_ro": "Job Costing",
- "job_lifecycle_ro": "Job Lifecycle",
- "job_notes": "Job Notes",
- "job_tasks": "Job Tasks",
- "key_tag": "Key Tag",
- "labels": {
- "count": "Count",
- "labels": "Labels",
- "position": "Starting Position"
- },
- "lag_time_ro": "Lag Time",
- "mechanical_authorization": "Mechanical Authorization",
- "mpi_animal_checklist": "MPI - Animal Checklist",
- "mpi_eglass_auth": "MPI - eGlass Auth",
- "mpi_final_acct_sheet": "MPI - Final Accounting Sheet (Direct Repair)",
- "mpi_final_repair_acct_sheet": "MPI - Final Accounting Sheet",
- "paint_grid": "Paint Grid",
- "parts_dispatch": "Parts Dispatch",
- "parts_invoice_label_single": "Parts Label Single",
- "parts_label_multiple": "Parts Label - Multi",
- "parts_label_single": "Parts Label - Single",
- "parts_list": "Parts List",
- "parts_order": "Parts Order Confirmation",
- "parts_order_confirmation": "",
- "parts_order_history": "Parts Order History",
- "parts_return_slip": "Parts Return Slip",
- "payment_receipt": "Payment Receipt",
- "payment_request": "Payment Request",
- "payments_by_job": "Job Payments",
- "purchases_by_ro_detail": "Purchases - Detail",
- "purchases_by_ro_summary": "Purchases - Summary",
- "qc_sheet": "Quality Control Sheet",
- "rental_reservation": "Rental Reservation",
- "ro_totals": "RO Totals",
- "ro_with_description": "RO Summary with Descriptions",
- "sgi_certificate_of_repairs": "SGI - Certificate of Repairs",
- "sgi_windshield_auth": "SGI - Windshield Authorization",
- "stolen_recovery_checklist": "Stolen Recovery Checklist",
- "sublet_order": "Sublet Order",
- "supplement_request": "Supplement Request",
- "thank_you_ro": "Thank You Letter",
- "thirdpartypayer": "Third Party Payer",
- "timetickets_ro": "Time Tickets",
- "vehicle_check_in": "Vehicle Intake",
- "vehicle_delivery_check": "Vehicle Delivery Checklist",
- "window_tag": "Window Tag",
- "window_tag_sublet": "Window Tag - Sublet",
- "work_authorization": "Work Authorization",
- "worksheet_by_line_number": "Worksheet by Line Number",
- "worksheet_sorted_by_operation": "Worksheet by Operation",
- "worksheet_sorted_by_operation_no_hours": "Worksheet by Operation (No Hours)",
- "worksheet_sorted_by_operation_part_type": "Worksheet by Operation & Part Type",
- "worksheet_sorted_by_operation_type": "Worksheet by Operation Type",
- "worksheet_sorted_by_team": "Worksheet by Team"
- },
- "labels": {
- "groups": {
- "authorization": "Authorization",
- "financial": "Financial",
- "post": "Post-Production",
- "pre": "Pre-Production",
- "ro": "Repair Order",
- "worksheet": "Worksheets"
- },
- "misc": "Miscellaneous Documents",
- "repairorder": "Repair Order Related",
- "reportcentermodal": "Report Center",
- "speedprint": "Speed Print",
- "title": "Print Center"
- },
- "payments": {
- "ca_bc_etf_table": "ICBC EFT Table",
- "exported_payroll": "Payroll Table"
- },
- "special": {
- "attendance_detail_csv": "Attendance Table"
- },
- "subjects": {
- "jobs": {
- "individual_job_note": "Job Note RO: {{ro_number}}",
- "parts_dispatch": "Parts Dispatch RO: {{ro_number}}",
- "parts_order": "Parts Order PO: {{ro_number}} - {{name}}",
- "parts_return_slip": "Parts Return PO: {{ro_number}} - {{name}}",
- "sublet_order": "Sublet Order PO: {{ro_number}} - {{name}}"
- }
- },
- "vendors": {
- "purchases_by_vendor_detailed": "Purchases by Vendor - Detailed",
- "purchases_by_vendor_summary": "Purchases by Vendor - Summary"
- }
- },
- "production": {
- "actions": {
- "addcolumns": "Add Columns",
- "bodypriority-clear": "Clear Body Priority",
- "bodypriority-set": "Set Body Priority",
- "detailpriority-clear": "Clear Detail Priority",
- "detailpriority-set": "Set Detail Priority",
- "paintpriority-clear": "Clear Paint Priority",
- "paintpriority-set": "Set Paint Priority",
- "remove": "Remove from Production",
- "removecolumn": "Remove Column",
- "saveconfig": "Save Configuration",
- "suspend": "Suspend",
- "unsuspend": "Unsuspend"
- },
- "constants": {
- "main_profile": "Default"
- },
- "errors": {
- "boardupdate": "Error encountered updating Job. {{message}}",
- "name_exists": "A Profile with this name already exists. Please choose a different name.",
- "name_required": "Profile name is required.",
- "removing": "Error removing from production board. {{error}}",
- "settings": "Error saving board settings: {{error}}"
- },
- "labels": {
- "actual_in": "Actual In",
- "addnewprofile": "Add New Profile",
- "alert": "Alert",
- "alertoff": "Remove alert from Job",
- "alerton": "Add alert to Job",
- "alerts": "Alerts",
- "ats": "Alternative Transportation",
- "bodyhours": "B",
- "bodypriority": "B/P",
- "bodyshop": {
- "labels": {
- "qbo_departmentid": "QBO Department ID",
- "qbo_usa": "QBO USA"
- }
- },
- "card_size": "Card Size",
- "cardcolor": "Colored Cards",
- "cardsettings": "Card Settings",
- "clm_no": "Claim Number",
- "comment": "Comment",
- "compact": "Compact Cards",
- "detailpriority": "D/P",
- "employeeassignments": "Employee Assignments",
- "employeesearch": "Employee Search",
- "estimator": "Estimator",
- "horizontal": "Horizontal",
- "ins_co_nm": "Insurance Company Name",
- "jobdetail": "Job Details",
- "kiosk_mode": "Kiosk Mode",
- "laborhrs": "Labor Hours",
- "legend": "Legend:",
- "model_info": "Vehicle Info",
- "note": "Production Note",
- "off": "Off",
- "on": "On",
- "orientation": "Board Orientation",
- "ownr_nm": "Customer Name",
- "paintpriority": "P/P",
- "partsstatus": "Parts Status",
- "production_note": "Production Note",
- "refinishhours": "R",
- "scheduled_completion": "Scheduled Completion",
- "selectview": "Select a View",
- "stickyheader": "Sticky Header (BETA)",
- "sublets": "Sublets",
- "subtotal": "Subtotal",
- "tall": "Tall",
- "tasks": "Tasks",
- "totalhours": "Total Hrs ",
- "touchtime": "T/T",
- "unassigned": "Unassigned",
- "vertical": "Vertical",
- "viewname": "View Name",
- "wide": "Wide"
- },
- "options": {
- "horizontal": "Horizontal",
- "large": "Large",
- "medium": "Medium",
- "small": "Small",
- "vertical": "Vertical"
- },
- "settings": {
- "board_settings": "Board Settings",
- "filters": {
- "md_estimators": "Estimators",
- "md_ins_cos": "Insurance Companies"
- },
- "filters_title": "Filters",
- "information": "Information",
- "layout": "Layout",
- "statistics": {
- "jobs_in_production": "Jobs in Production",
- "tasks_in_production": "Tasks in Production",
- "tasks_in_view": "Tasks in View",
- "tasks_on_board": "Tasks on Board",
- "total_amount_in_production": "Dollars in Production",
- "total_amount_in_view": "Dollars in View",
- "total_amount_on_board": "Dollars on Board",
- "total_hours_in_production": "Hours in Production",
- "total_hours_in_view": "Hours in View",
- "total_hours_on_board": "Hours on Board",
- "total_jobs_in_view": "Jobs in View",
- "total_jobs_on_board": "Jobs on Board",
- "total_lab_in_production": "Body Hours in Production",
- "total_lab_in_view": "Body Hours in View",
- "total_lab_on_board": "Body Hours on Board",
- "total_lar_in_production": "Refinish Hours in Production",
- "total_lar_in_view": "Refinish Hours in View",
- "total_lar_on_board": "Refinish Hours on Board"
- },
- "statistics_title": "Statistics"
- },
- "statistics": {
- "currency_symbol": "$",
- "hours": "Hours",
- "jobs": "Jobs",
- "jobs_in_production": "Jobs in Production",
- "tasks": "Tasks",
- "tasks_in_production": "Tasks in Production",
- "tasks_in_view": "Tasks in View",
- "tasks_on_board": "Tasks on Board",
- "total_amount_in_production": "Dollars in Production",
- "total_amount_in_view": "Dollars in View",
- "total_amount_on_board": "Dollars on Board",
- "total_hours_in_production": "Hours in Production",
- "total_hours_in_view": "Hours in View",
- "total_hours_on_board": "Hours on Board",
- "total_jobs_in_view": "Jobs in View",
- "total_jobs_on_board": "Jobs on Board",
- "total_lab_in_production": "Body Hours in Production",
- "total_lab_in_view": "Body Hours in View",
- "total_lab_on_board": "Body Hours on Board",
- "total_lar_in_production": "Refinish Hours in Production",
- "total_lar_in_view": "Refinish Hours in View",
- "total_lar_on_board": "Refinish Hours on Board"
- },
- "successes": {
- "removed": "Job removed from production."
- }
- },
- "profile": {
- "errors": {
- "state": "Error reading page state. Please refresh."
- },
- "labels": {
- "activeshop": "Active Shop"
- },
- "successes": {
- "updated": "Profile updated successfully."
- }
- },
- "reportcenter": {
- "actions": {
- "generate": "Generate"
- },
- "labels": {
- "advanced_filters": "Advanced Filters and Sorters",
- "advanced_filters_false": "False",
- "advanced_filters_filter_field": "Field",
- "advanced_filters_filter_operator": "Operator",
- "advanced_filters_filter_value": "Value",
- "advanced_filters_filters": "Filters",
- "advanced_filters_hide": "Hide",
- "advanced_filters_show": "Show",
- "advanced_filters_sorter_direction": "Direction",
- "advanced_filters_sorter_field": "Field",
- "advanced_filters_sorters": "Sorters",
- "advanced_filters_true": "True",
- "dates": "Dates",
- "employee": "Employee",
- "filterson": "Filters on {{object}}: {{field}}",
- "generateasemail": "Generate as Email?",
- "groups": {
- "customers": "Customers",
- "jobs": "Jobs & Costing",
- "payroll": "Payroll",
- "purchases": "Purchases",
- "sales": "Sales"
- },
- "key": "Report",
- "objects": {
- "appointments": "Appointments",
- "bills": "Bills",
- "csi": "CSI",
- "exportlogs": "Export Logs",
- "jobs": "Jobs",
- "parts_orders": "Parts Orders",
- "payments": "Payments",
- "scoreboard": "Scoreboard",
- "tasks": "Tasks",
- "timetickets": "Timetickets"
- },
- "vendor": "Vendor"
- },
- "templates": {
- "adp_payroll_flat": "ADP Payroll - Flat Rate",
- "adp_payroll_straight": "ADP Payroll - Straight Time",
- "anticipated_revenue": "Anticipated Revenue",
- "ar_aging": "AR Aging",
- "attendance_detail": "Attendance (All Employees)",
- "attendance_employee": "Employee Attendance",
- "attendance_summary": "Attendance Summary (All Employees)",
- "committed_timetickets": "Committed Time Tickets",
- "committed_timetickets_employee": "Committed Employee Time Tickets",
- "committed_timetickets_summary": "Committed Time Tickets Summary",
- "credits_not_received_date": "Credits not Received by Date",
- "credits_not_received_date_vendorid": "Credits not Received by Vendor",
- "csi": "CSI Responses",
- "customer_list": "Customer List",
- "cycle_time_analysis": "Cycle Time Analysis",
- "estimates_written_converted": "Estimates Written/Converted",
- "estimator_detail": "Jobs by Estimator (Detail)",
- "estimator_summary": "Jobs by Estimator (Summary)",
- "export_payables": "Export Log - Payables",
- "export_payments": "Export Log - Payments",
- "export_receivables": "Export Log - Receivables",
- "exported_gsr_by_ro": "Exported Gross Sales - Excel",
- "exported_gsr_by_ro_labor": "Exported Gross Sales (Labor) - Excel",
- "gsr_by_atp": "",
- "gsr_by_ats": "Gross Sales by ATS",
- "gsr_by_category": "Gross Sales by Category",
- "gsr_by_csr": "Gross Sales by CSR",
- "gsr_by_delivery_date": "Gross Sales by Delivery Date",
- "gsr_by_estimator": "Gross Sales by Estimator",
- "gsr_by_exported_date": "Exported Gross Sales",
- "gsr_by_ins_co": "Gross Sales by Insurance Company",
- "gsr_by_make": "Gross Sales by Vehicle Make",
- "gsr_by_referral": "Gross Sales by Referral Source",
- "gsr_by_ro": "Gross Sales by RO",
- "gsr_labor_only": "Gross Sales - Labor Only",
- "hours_sold_detail_closed": "Hours Sold Detail - Closed",
- "hours_sold_detail_closed_csr": "Hours Sold Detail - Closed by CSR",
- "hours_sold_detail_closed_estimator": "Hours Sold Detail - Closed by Estimator",
- "hours_sold_detail_closed_ins_co": "Hours Sold Detail - Closed by Source",
- "hours_sold_detail_closed_status": "Hours Sold Detail - Closed by Status",
- "hours_sold_detail_open": "Hours Sold Detail - Open",
- "hours_sold_detail_open_csr": "Hours Sold Detail - Open by CSR",
- "hours_sold_detail_open_estimator": "Hours Sold Detail - Open by Estimator",
- "hours_sold_detail_open_ins_co": "Hours Sold Detail - Open by Source",
- "hours_sold_detail_open_status": "Hours Sold Detail - Open by Status",
- "hours_sold_summary_closed": "Hours Sold Summary - Closed",
- "hours_sold_summary_closed_csr": "Hours Sold Summary - Closed by CSR",
- "hours_sold_summary_closed_estimator": "Hours Sold Summary - Closed by Estimator",
- "hours_sold_summary_closed_ins_co": "Hours Sold Summary - Closed by Source",
- "hours_sold_summary_closed_status": "Hours Sold Summary - Closed by Status",
- "hours_sold_summary_open": "Hours Sold Summary - Open",
- "hours_sold_summary_open_csr": "Hours Sold Summary - Open CSR",
- "hours_sold_summary_open_estimator": "Hours Sold Summary - Open Estimator",
- "hours_sold_summary_open_ins_co": "Hours Sold Summary - Open by Source",
- "hours_sold_summary_open_status": "Hours Sold Summary - Open by Status",
- "job_costing_ro_csr": "Job Costing by CSR",
- "job_costing_ro_date_detail": "Job Costing by RO - Detail",
- "job_costing_ro_date_summary": "Job Costing by RO - Summary",
- "job_costing_ro_estimator": "Job Costing by Estimator",
- "job_costing_ro_ins_co": "Job Costing by RO Source",
- "job_lifecycle_date_detail": "Job Lifecycle by Date - Detail",
- "job_lifecycle_date_summary": "Job Lifecycle by Date - Summary",
- "jobs_completed_not_invoiced": "Jobs Completed not Invoiced",
- "jobs_invoiced_not_exported": "Jobs Invoiced not Exported",
- "jobs_reconcile": "Parts/Sublet/Labor Reconciliation",
- "jobs_scheduled_completion": "Jobs Scheduled Completion",
- "lag_time": "Lag Time",
- "load_level": "Load Level",
- "lost_sales": "Lost Sales",
- "open_orders": "Open Orders by Date",
- "open_orders_csr": "Open Orders by CSR",
- "open_orders_estimator": "Open Orders by Estimator",
- "open_orders_excel": "Open Orders - Excel",
- "open_orders_ins_co": "Open Orders by Insurance Company",
- "open_orders_referral": "Open Orders by Referral Source",
- "open_orders_specific_csr": "Open Orders filtered by CSR",
- "open_orders_status": "Open Orders by Status",
- "parts_backorder": "IOU Parts List",
- "parts_not_recieved": "Parts Not Received",
- "parts_not_recieved_vendor": "Parts Not Received by Vendor",
- "parts_received_not_scheduled": "Parts Received for Jobs Not Scheduled",
- "payments_by_date": "Payments by Date",
- "payments_by_date_payment": "Payments by Date and Payment Type",
- "payments_by_date_type": "Payments by Date and Customer Type",
- "production_by_category": "Production by Category",
- "production_by_category_one": "Production filtered by Category",
- "production_by_csr": "Production by CSR",
- "production_by_last_name": "Production by Last Name",
- "production_by_repair_status": "Production by Status",
- "production_by_repair_status_one": "Production filtered by Status",
- "production_by_ro": "Production by RO",
- "production_by_target_date": "Production by Scheduled Completion",
- "production_by_technician": "Production by Technician",
- "production_by_technician_one": "Production filtered by Technician",
- "production_not_production_status": "Production not in Production Status",
- "production_over_time": "Production Level over Time",
- "psr_by_make": "Percent of Sales by Vehicle Make",
- "purchase_return_ratio_excel": "Purchase & Return Ratio - Excel",
- "purchase_return_ratio_grouped_by_vendor_detail": "Purchase & Return Ratio by Vendor (Detail)",
- "purchase_return_ratio_grouped_by_vendor_summary": "Purchase & Return Ratio by Vendor (Summary)",
- "purchases_by_cost_center_detail": "Purchases by Cost Center (Detail)",
- "purchases_by_cost_center_summary": "Purchases by Cost Center (Summary)",
- "purchases_by_date_excel": "Purchases by Date - Excel",
- "purchases_by_date_range_detail": "Purchases by Date - Detail",
- "purchases_by_date_range_summary": "Purchases by Date - Summary",
- "purchases_by_ro_detail_date": "Purchases by RO - Detail",
- "purchases_by_ro_summary_date": "Purchases by RO - Summary",
- "purchases_by_vendor_detailed_date_range": "Purchases By Vendor - Detailed",
- "purchases_by_vendor_summary_date_range": "Purchases by Vendor - Summary",
- "purchases_grouped_by_vendor_detailed": "Purchases Grouped by Vendor - Detailed",
- "purchases_grouped_by_vendor_summary": "Purchases Grouped by Vendor - Summary",
- "returns_grouped_by_vendor_detailed": "Returns Grouped by Vendor - Detailed",
- "returns_grouped_by_vendor_summary": "Returns Grouped by Vendor - Summary",
- "schedule": "Appointment Schedule",
- "scheduled_parts_list": "Parts for Jobs Scheduled In",
- "scoreboard_detail": "Scoreboard Detail",
- "scoreboard_summary": "Scoreboard Summary",
- "supplement_ratio_ins_co": "Supplement Ratio by Source",
- "tasks_date": "Tasks by Date",
- "tasks_date_employee": "Employee Tasks by Date",
- "thank_you_date": "Thank You Letters",
- "timetickets": "Time Tickets",
- "timetickets_employee": "Employee Time Tickets",
- "timetickets_summary": "Time Tickets Summary",
- "total_loss_jobs": "Jobs Marked as Total Loss",
- "unclaimed_hrs": "Unflagged Hours",
- "void_ros": "Void ROs",
- "work_in_progress_committed_labour": "Work in Progress - Committed Labor",
- "work_in_progress_jobs": "Work in Progress - Jobs",
- "work_in_progress_labour": "Work in Progress - Labor",
- "work_in_progress_payables": "Work in Progress - Payables"
- }
- },
- "schedule": {
- "labels": {
- "atssummary": "ATS Summary",
- "employeevacation": "Employee Vacations",
- "estimators": "Filter by Writer/Customer Rep.",
- "ins_co_nm_filter": "Filter by Insurance Company",
- "intake": "Intake Events",
- "manual": "Manual Events",
- "manualevent": "Add Manual Event"
- }
- },
- "scoreboard": {
- "actions": {
- "edit": "Edit"
- },
- "errors": {
- "adding": "Error adding Job to Scoreboard. {{message}}",
- "removing": "Error removing Job from Scoreboard. {{message}}",
- "updating": "Error updating Scoreboard. {{message}}"
- },
- "fields": {
- "bodyhrs": "Body Hours",
- "date": "Date",
- "painthrs": "Paint Hours"
- },
- "labels": {
- "allemployeetimetickets": "All Employee Time Tickets",
- "asoftodaytarget": "As of Today",
- "body": "Body",
- "bodyabbrev": "B",
- "bodycharttitle": "Body Targets vs Actual",
- "calendarperiod": "Periods based on calendar weeks/months.",
- "combinedcharttitle": "Combined Targets vs Actual",
- "dailyactual": "Actual (D)",
- "dailytarget": "Daily",
- "efficiencyoverperiod": "Efficiency over Selected Dates",
- "entries": "Scoreboard Entries",
- "jobs": "Jobs",
- "jobscompletednotinvoiced": "Completed Not Invoiced",
- "lastmonth": "Last Month",
- "lastweek": "Last Week",
- "monthlytarget": "Monthly",
- "priorweek": "Prior Week",
- "productivestatistics": "Productive Hours Statistics",
- "productivetimeticketsoverdate": "Productive Hours over Selected Dates",
- "refinish": "Refinish",
- "refinishabbrev": "R",
- "refinishcharttitle": "Refinish Targets vs Actual",
- "targets": "Targets",
- "thismonth": "This Month",
- "thisweek": "This Week",
- "timetickets": "Time Tickets",
- "timeticketsemployee": "Time Tickets by Employee",
- "todateactual": "Actual (MTD)",
- "total": "Total",
- "totalhrs": "Total Hours",
- "totaloverperiod": "Total over Selected Dates",
- "weeklyactual": "Actual (W)",
- "weeklytarget": "Weekly",
- "workingdays": "Working Days / Month"
- },
- "successes": {
- "added": "Job added to scoreboard.",
- "removed": "Job removed from scoreboard.",
- "updated": "Scoreboard updated."
- }
- },
- "tasks": {
- "actions": {
- "edit": "Edit Task",
- "new": "New Task",
- "view": "View Task"
- },
- "buttons": {
- "allTasks": "All",
- "complete": "Toggle Complete",
- "create": "Create Task",
- "delete": "Toggle Delete",
- "edit": "Edit",
- "myTasks": "Mine",
- "refresh": "Refresh"
- },
- "date_presets": {
- "completion": "Completion",
- "day": "Day",
- "days": "Days",
- "delivery": "Delivery",
- "next_week": "Next Week",
- "one_month": "One Month",
- "three_months": "Three Months",
- "three_weeks": "Three Weeks",
- "today": "Today",
- "tomorrow": "Tomorrow",
- "two_weeks": "Two Weeks"
- },
- "failures": {
- "completed": "Failed to toggle Task completion.",
- "created": "Failed to create Task.",
- "deleted": "Failed to toggle Task deletion.",
- "updated": "Failed to update Task."
- },
- "fields": {
- "actions": "Actions",
- "assigned_to": "Assigned To",
- "bill": "Bill",
- "billid": "Bill",
- "completed": "Completed",
- "created_at": "Created At",
- "created_by": "Created By",
- "description": "Description",
- "due_date": "Due Date",
- "job": {
- "ro_number": "RO #"
- },
- "jobid": "Job",
- "jobline": "Job Line",
- "joblineid": "Job Line",
- "parts_order": "Parts Order",
- "partsorderid": "Parts Order",
- "priorities": {
- "high": "High",
- "low": "Low",
- "medium": "Medium"
- },
- "priority": "Priority",
- "related_items": "Related Items",
- "remind_at": "Remind At",
- "title": "Title"
- },
- "placeholders": {
- "assigned_to": "Select an Employee",
- "billid": "Select a Bill",
- "description": "Enter a description",
- "jobid": "Select a Job",
- "joblineid": "Select a Job Line",
- "partsorderid": "Select a Parts Order"
- },
- "successes": {
- "completed": "Toggled Task completion successfully.",
- "created": "Task created successfully.",
- "deleted": "Toggled Task deletion successfully.",
- "updated": "Task updated successfully."
- },
- "titles": {
- "all_tasks": "All Tasks",
- "completed": "Completed Tasks",
- "deleted": "Deleted Tasks",
- "job_tasks": "Job Tasks",
- "mine": "My Tasks",
- "my_tasks": "My Tasks"
- },
- "validation": {
- "due_at_error_message": "The due date must be in the future!",
- "remind_at_error_message": "The reminder date and time must be at least 30 minutes in the future!"
- }
- },
- "tech": {
- "fields": {
- "employeeid": "Employee ID",
- "pin": "PIN"
- },
- "labels": {
- "loggedin": "Logged in as {{name}}",
- "notloggedin": "Not logged in."
- }
- },
- "templates": {
- "errors": {
- "updating": "Error updating template {{error}}."
- },
- "successes": {
- "updated": "Template updated successfully."
- }
- },
- "timetickets": {
- "actions": {
- "claimtasks": "Flag Hours",
- "clockin": "Clock In",
- "clockout": "Clock Out",
- "commit": "Commit Tickets ({{count}})",
- "commitone": "Commit",
- "enter": "Enter New Time Ticket",
- "payall": "Pay All",
- "printemployee": "Print Time Tickets",
- "uncommit": "Uncommit"
- },
- "errors": {
- "clockingin": "Error while clocking in. {{message}}",
- "clockingout": "Error while clocking out. {{message}}",
- "creating": "Error creating time ticket. {{message}}",
- "deleting": "Error deleting time ticket. {{message}}",
- "noemployeeforuser": "Unable to use Shift Clock",
- "noemployeeforuser_sub": "An employee record has not been created for this user. Please create one before using the shift clock. ",
- "payall": "Error flagging hours. {{error}}",
- "shiftalreadyclockedon": "You are already clocked onto a shift. Unable to create shift entry."
- },
- "fields": {
- "actualhrs": "Actual Hours",
- "ciecacode": "CIECA Code",
- "clockhours": "Clock Hours",
- "clockoff": "Clock Off",
- "clockon": "Clocked In",
- "committed": "Committed",
- "committed_at": "Committed At",
- "cost_center": "Cost Center",
- "created_by": "Created By",
- "date": "Ticket Date",
- "efficiency": "Efficiency",
- "employee": "Employee",
- "employee_team": "Employee Team",
- "flat_rate": "Flat Rate?",
- "memo": "Memo",
- "productivehrs": "Productive Hours",
- "ro_number": "Job to Post Against",
- "task_name": "Task"
- },
- "labels": {
- "alreadyclockedon": "You are already clocked in to the following Job(s):",
- "ambreak": "AM Break",
- "amshift": "AM Shift",
- "claimtaskpreview": "Flagged Hours Preview",
- "clockhours": "Shift Clock Hours Summary",
- "clockintojob": "Clock In to Job",
- "deleteconfirm": "Are you sure you want to delete this time ticket? This cannot be undone.",
- "edit": "Edit Time Ticket",
- "efficiency": "Efficiency",
- "flat_rate": "Flat Rate",
- "jobhours": "Job Related Time Tickets Summary",
- "lunch": "Lunch",
- "new": "New Time Ticket",
- "payrollclaimedtasks": "These time tickets will be automatically entered to the system as a part of claiming this task. These numbers are calculated using the jobs assigned lines. If lines are unassigned, they will be excluded from created tickets.",
- "pmbreak": "PM Break",
- "pmshift": "PM Shift",
- "shift": "Shift",
- "shiftalreadyclockedon": "Active Shift Time Tickets",
- "straight_time": "Straight Time",
- "task": "Task",
- "timetickets": "Time Tickets",
- "unassigned": "Unassigned",
- "zeroactualnegativeprod": "Actual hours must be 0 if entering negative productive hours."
- },
- "successes": {
- "clockedin": "Clocked in successfully.",
- "clockedout": "Clocked out successfully.",
- "committed": "Time Tickets Committed Successfully",
- "created": "Time ticket entered successfully.",
- "deleted": "Time ticket deleted successfully.",
- "payall": "All hours paid out successfully."
- },
- "validation": {
- "clockoffmustbeafterclockon": "Clock off time must be the same or after clock in time.",
- "clockoffwithoutclockon": "Clock off time cannot be set without a clock in time.",
- "hoursenteredmorethanavailable": "The number of hours entered is more than what is available for this cost center.",
- "unassignedlines": "There are currently {{unassignedHours}} hours of repair lines that are unassigned. These hours are not including in the above calculations and must be paid manually."
- }
- },
- "titles": {
- "accounting-payables": "Payables | {{app}}",
- "accounting-payments": "Payments | {{app}}",
- "accounting-receivables": "Receivables | {{app}}",
- "all_tasks": "All Tasks",
- "app": "",
- "bc": {
- "accounting-payables": "Payables",
- "accounting-payments": "Payments",
- "accounting-receivables": "Receivables",
- "all_tasks": "All Tasks",
- "availablejobs": "Available Jobs",
- "bills-list": "Bills",
- "contracts": "Contracts",
- "contracts-create": "New Contract",
- "contracts-detail": "Contract #{{number}}",
- "courtesycars": "Courtesy Cars",
- "courtesycars-detail": "Courtesy Car {{number}}",
- "courtesycars-new": "New Courtesy Car",
- "dashboard": "Dashboard",
- "dms": "DMS Export",
- "export-logs": "Export Logs",
- "inventory": "Inventory",
- "jobs": "Jobs",
- "jobs-active": "Active Jobs",
- "jobs-admin": "Admin",
- "jobs-all": "All Jobs",
- "jobs-checklist": "Checklist",
- "jobs-close": "Close Job",
- "jobs-deliver": "Deliver Job",
- "jobs-detail": "Job {{number}}",
- "jobs-intake": "Intake",
- "jobs-new": "Create a New Job",
- "jobs-ready": "Ready Jobs",
- "my_tasks": "My Tasks",
- "owner-detail": "{{name}}",
- "owners": "Owners",
- "parts-queue": "Parts Queue",
- "payments-all": "All Payments",
- "phonebook": "Phonebook",
- "productionboard": "Production Board - Visual",
- "productionlist": "Production Board - List",
- "profile": "My Profile",
- "schedule": "Schedule",
- "scoreboard": "Scoreboard",
- "shop": "Manage my Shop ({{shopname}})",
- "shop-csi": "CSI Responses",
- "shop-templates": "Shop Templates",
- "shop-vendors": "Vendors",
- "tasks": "Tasks",
- "temporarydocs": "Temporary Documents",
- "timetickets": "Time Tickets",
- "ttapprovals": "Time Ticket Approvals",
- "vehicle-details": "Vehicle: {{vehicle}}",
- "vehicles": "Vehicles"
- },
- "bills-list": "Bills | {{app}}",
- "contracts": "Courtesy Car Contracts | {{app}}",
- "contracts-create": "New Contract | {{app}}",
- "contracts-detail": "Contract {{id}} | {{app}}",
- "courtesycars": "Courtesy Cars | {{app}}",
- "courtesycars-create": "New Courtesy Car | {{app}}",
- "courtesycars-detail": "Courtesy Car {{id}} | {{app}}",
- "dashboard": "Dashboard | {{app}}",
- "dms": "DMS Export | {{app}}",
- "export-logs": "Export Logs | {{app}}",
- "imexonline": "ImEX Online",
- "inventory": "Inventory | {{app}}",
- "jobs": "Active Jobs | {{app}}",
- "jobs-admin": "Job {{ro_number}} - Admin | {{app}}",
- "jobs-all": "All Jobs | {{app}}",
- "jobs-checklist": "Job Checklist | {{app}}",
- "jobs-close": "Close Job {{number}} | {{app}}",
- "jobs-create": "Create a New Job | {{app}}",
- "jobs-deliver": "Deliver Job | {{app}}",
- "jobs-intake": "Intake | {{app}}",
- "jobsavailable": "Available Jobs | {{app}}",
- "jobsdetail": "Job {{ro_number}} | {{app}}",
- "jobsdocuments": "Job Documents {{ro_number}} | {{app}}",
- "manageroot": "Home | {{app}}",
- "my_tasks": "My Tasks",
- "owners": "All Owners | {{app}}",
- "owners-detail": "{{name}} | {{app}}",
- "parts-queue": "Parts Queue | {{app}}",
- "payments-all": "Payments | {{app}}",
- "phonebook": "Phonebook | {{app}}",
- "productionboard": "Production Board - Visual | {{app}}",
- "productionlist": "Production Board - List | {{app}}",
- "profile": "My Profile | {{app}}",
- "readyjobs": "Ready Jobs | {{app}}",
- "resetpassword": "Reset Password",
- "resetpasswordvalidate": "Enter New Password",
- "romeonline": "Rome Online",
- "schedule": "Schedule | {{app}}",
- "scoreboard": "Scoreboard | {{app}}",
- "shop": "My Shop | {{app}}",
- "shop-csi": "CSI Responses | {{app}}",
- "shop-templates": "Shop Templates | {{app}}",
- "shop_vendors": "Vendors | {{app}}",
- "tasks": "Tasks",
- "techconsole": "Technician Console | {{app}}",
- "techjobclock": "Technician Job Clock | {{app}}",
- "techjoblookup": "Technician Job Lookup | {{app}}",
- "techshiftclock": "Technician Shift Clock | {{app}}",
- "temporarydocs": "Temporary Documents | {{app}}",
- "timetickets": "Time Tickets | {{app}}",
- "ttapprovals": "Time Ticket Approvals | {{app}}",
- "vehicledetail": "Vehicle Details {{vehicle}} | {{app}}",
- "vehicles": "All Vehicles | {{app}}"
- },
- "trello": {
- "labels": {
- "add_card": "Add Card",
- "add_lane": "Add Lane",
- "cancel": "Cancel",
- "delete_lane": "Delete Lane",
- "description": "Description",
- "label": "Label",
- "lane_actions": "Lane Actions",
- "title": "Title"
- }
- },
- "tt_approvals": {
- "actions": {
- "approveselected": "Approve Selected"
- },
- "labels": {
- "approval_queue_in_use": "Time tickets will be added to the approval queue.",
- "calculate": "Calculate"
- }
- },
- "upsell": {
- "cta": {
- "learnmore": "Learn More"
- },
- "messages": {
- "accounting": {
- "payables": {
- "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.",
- "title": "Eliminate double data entry"
- },
- "payments": {
- "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.",
- "title": "Eliminate double data entry"
- },
- "receivables": {
- "subtitle": "Effortlessly send your invoices to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.",
- "title": "Eliminate double data entry"
- }
- },
- "audit": {
- "general": {
- "subtitle": "Know exactly what happened and when through the entire repair process.",
- "title": "Comprehensive Audit Trails"
- }
- },
- "bills": {
- "autoreconcile": {
- "subtitle": "Let your management system do the tedious work - take advantage of automatic job reconciliation today.",
- "title": "Did you account for every invoice?"
- },
- "general": {
- "subtitle": "Our Bills module allows you to precisely account for every penny on the repair order to ensure you maximize your bottom line.",
- "title": "Boost your profits by taking control of costs!"
- }
- },
- "checklist": {
- "general": {
- "subtitle": "Standardize your intake and delivery with digitized checklists and SOPs.",
- "title": "Done right, the first time."
- }
- },
- "courtesycars": {
- "general": {
- "subtitle": "Keep track of vehicles and contracts for your courtesy cars, all seamlessly synchronized with your Jobs.",
- "title": "Manage your fleet with ease"
- }
- },
- "csi": {
- "general": {
- "subtitle": "With our integrated CSI module, send follow up surveys to your customers to see how well you did.",
- "title": "See what your customers have to say"
- }
- },
- "dashboard": {
- "general": {
- "subtitle": "Make data based decisions and take control of your business using our real-time dashboard.",
- "title": "Realtime Insight & Analytics"
- }
- },
- "lifecycle": {
- "general": {
- "subtitle": "Job life cycles tell you exactly how long the job stayed in each stage of the repair process to identify bottle necks and inefficiencies.",
- "title": "Are your repair KPIs suffering?"
- }
- },
- "media": {
- "general": {
- "subtitle": "Store your vehicle repair documentation, invoices, and related documents digitally to access them anywhere, any time.",
- "title": "Go paperless."
- },
- "mobile": {
- "subtitle": "Use our mobile app to attach images from your device to the job, increasing your efficiency.",
- "title": "Accelerate repair documentation with Mobile"
- }
- },
- "payments": {
- "general": {
- "subtitle": "Manage outstanding balances and collect payments by credit card from your customers.",
- "title": "Integrated Accounts Receivable & Payments"
- }
- },
- "scoreboard": {
- "general": {
- "subtitle": "Understand hours produced and sold to facilitate employee incentive programs.",
- "title": "Give credit where credit is due"
- }
- },
- "smartscheduling": {
- "datepicker": {
- "subtitle": "Smart Scsheduling gives you the best dates for a vehicle to come in based on your current and predicted production load.",
- "title": "When's the best time for this job to arrive?"
- },
- "general": {
- "subtitle": "Know exactly how busy you will be tomorrow, the day after, or next week to know exactly when to schedule your next repair.",
- "title": "Forecast your production with Smart Scheduling"
- },
- "hrsdelta": {
- "subtitle": "Understand changes to your Work in Progress and production load instantly.",
- "title": "Cars come and cars go."
- }
- },
- "techconsole": {
- "general": {
- "subtitle": "The technician's console allows technicians to see job information, media, documents and keep track of their time.",
- "title": "Empower your Technicians"
- }
- },
- "timetickets": {
- "allocations": {
- "subtitle": "Ensure your technicians are paid out exactly what they are owed - not a penny less, not a penny more.",
- "title": "Technician Payments Done Just Right"
- },
- "general": {
- "subtitle": "Track your technicians time with precision, giving you insight to repair progress and labor efficiency.",
- "title": "Who did what and for how long?"
- }
- },
- "visualboard": {
- "general": {
- "subtitle": "The Visual Production Board makes it easier than ever before to manage your work in progress.",
- "title": "A whole new kind of production board"
- }
- }
- }
- },
- "user": {
- "actions": {
- "changepassword": "Change Password",
- "signout": "Sign Out",
- "updateprofile": "Update Profile"
- },
- "errors": {
- "updating": "Error updating user or association {{message}}"
- },
- "fields": {
- "authlevel": "Authorization Level",
- "displayname": "Display Name",
- "email": "Email",
- "photourl": "Avatar URL"
- },
- "labels": {
- "actions": "Actions",
- "changepassword": "Change Password",
- "profileinfo": "Profile Info"
- },
- "successess": {
- "passwordchanged": "Password changed successfully. "
- }
- },
- "users": {
- "errors": {
- "signinerror": {
- "auth/user-disabled": "User account disabled. ",
- "auth/user-not-found": "A user with this email does not exist.",
- "auth/wrong-password": "The email and password combination you provided is incorrect."
- }
- }
- },
- "vehicles": {
- "errors": {
- "deleting": "Error deleting vehicle. {{error}}.",
- "noaccess": "The vehicle does not exist or you do not have access to it.",
- "selectexistingornew": "Select an existing vehicle record or create a new one. ",
- "validation": "Please ensure all fields are entered correctly.",
- "validationtitle": "Validation Error"
- },
- "fields": {
- "description": "Vehicle Description",
- "notes": "Vehicle Notes",
- "plate_no": "License Plate",
- "plate_st": "Plate Jurisdiction",
- "trim_color": "Trim Color",
- "v_bstyle": "Body Style",
- "v_color": "Color",
- "v_cond": "Condition",
- "v_engine": "Engine",
- "v_make_desc": "Make",
- "v_makecode": "Make Code",
- "v_mldgcode": "Molding Code",
- "v_model_desc": "Model",
- "v_model_yr": "Year",
- "v_options": "Options",
- "v_paint_codes": "Paint Codes {{number}}",
- "v_prod_dt": "Production Date",
- "v_stage": "Stage",
- "v_tone": "Tone",
- "v_trimcode": "Trim Code",
- "v_type": "Type",
- "v_vin": "V.I.N."
- },
- "forms": {
- "detail": "Vehicle Details",
- "misc": "Miscellaneous",
- "registration": "Registration"
- },
- "labels": {
- "deleteconfirm": "Are you sure you want to delete this vehicle? This cannot be undone.",
- "fromvehicle": "Historical Vehicle Record",
- "novehinfo": "No Vehicle Information",
- "relatedjobs": "Related Jobs",
- "updatevehicle": "Update Vehicle Information"
- },
- "successes": {
- "delete": "Vehicle deleted successfully.",
- "save": "Vehicle saved successfully."
- }
- },
- "vendors": {
- "actions": {
- "addtophonebook": "Add to Phonebook",
- "new": "New Vendor",
- "newpreferredmake": "New Preferred Make"
- },
- "errors": {
- "deleting": "Error encountered while deleting vendor. ",
- "saving": "Error encountered while saving vendor. "
- },
- "fields": {
- "active": "Active",
- "am": "Aftermarket",
- "city": "City",
- "cost_center": "Cost Center",
- "country": "Country",
- "discount": "Discount % (as decimal)",
- "display_name": "Display Name",
- "dmsid": "DMS ID",
- "due_date": "Payment Due Date (# of days)",
- "email": "Contact Email",
- "favorite": "Favorite?",
- "lkq": "LKQ",
- "make": "Make",
- "name": "Vendor Name",
- "oem": "OEM",
- "phone": "Phone",
- "prompt_discount": "Prompt Discount %",
- "state": "Province/State",
- "street1": "Street",
- "street2": "Address 2",
- "taxid": "Tax ID",
- "terms": "Payment Terms",
- "zip": "Zip/Postal Code"
- },
- "labels": {
- "noneselected": "No vendor is selected.",
- "preferredmakes": "Preferred Makes for Vendor",
- "search": "Type a Vendor's Name"
- },
- "successes": {
- "deleted": "Vendor deleted successfully. ",
- "saved": "Vendor saved successfully."
- },
- "validation": {
- "unique_vendor_name": "You must enter a unique vendor name."
- }
- }
- }
+ "translation": {
+ "allocations": {
+ "actions": {
+ "assign": "Assign"
+ },
+ "errors": {
+ "deleting": "Error encountered while deleting allocation. {{message}}",
+ "saving": "Error while allocating. {{message}}",
+ "validation": "Please ensure all fields are entered correctly. "
+ },
+ "fields": {
+ "employee": "Allocated To"
+ },
+ "successes": {
+ "deleted": "Allocation deleted successfully.",
+ "save": "Allocated successfully. "
+ }
+ },
+ "appointments": {
+ "actions": {
+ "block": "Block Day",
+ "calculate": "Calculate SMART Dates",
+ "cancel": "Cancel Appointment",
+ "intake": "Intake",
+ "new": "New Appointment",
+ "preview": "Preview",
+ "reschedule": "Reschedule",
+ "sendreminder": "Send Reminder",
+ "unblock": "Unblock",
+ "viewjob": "View Job"
+ },
+ "errors": {
+ "blocking": "Error creating block {{message}}.",
+ "canceling": "Error canceling appointment. {{message}}",
+ "saving": "Error scheduling appointment. {{message}}"
+ },
+ "fields": {
+ "alt_transport": "Alt. Trans.",
+ "color": "Appointment Color",
+ "end": "End",
+ "note": "Note",
+ "start": "Start",
+ "time": "Appointment Time",
+ "title": "Title"
+ },
+ "labels": {
+ "arrivedon": "Arrived on: ",
+ "arrivingjobs": "Arriving Jobs",
+ "blocked": "Blocked",
+ "cancelledappointment": "Canceled appointment for: ",
+ "completingjobs": "Completing Jobs",
+ "dataconsistency": "<0>{{ro_number}}0> has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.",
+ "expectedjobs": "Expected Jobs in Production: ",
+ "expectedprodhrs": "Expected Production Hours:",
+ "history": "History",
+ "inproduction": "Jobs In Production",
+ "manualevent": "Add Manual Appointment",
+ "noarrivingjobs": "No Jobs are arriving.",
+ "nocompletingjobs": "No Jobs scheduled for completion.",
+ "nodateselected": "No date has been selected.",
+ "priorappointments": "Previous Appointments",
+ "reminder": "This is {{shopname}} reminding you about an appointment on {{date}} at {{time}}. Please let us know if you are not able to make the appointment. We look forward to seeing you soon. ",
+ "scheduledfor": "Scheduled appointment for: ",
+ "severalerrorsfound": "Several Jobs have issues which may prevent accurate smart scheduling. Click to expand.",
+ "smartscheduling": "Smart Scheduling",
+ "smspaymentreminder": "This is {{shopname}} reminding you about your remaining balance of {{amount}}. To pay for the said balance click the link {{payment_link}}.",
+ "suggesteddates": "Suggested Dates"
+ },
+ "successes": {
+ "canceled": "Appointment canceled successfully.",
+ "created": "Appointment scheduled successfully.",
+ "saved": "Appointment saved successfully."
+ }
+ },
+ "associations": {
+ "actions": {
+ "activate": "Activate"
+ },
+ "fields": {
+ "active": "Active?",
+ "shopname": "Shop Name"
+ },
+ "labels": {
+ "actions": "Actions"
+ }
+ },
+ "audit": {
+ "fields": {
+ "cc": "CC",
+ "contents": "Contents",
+ "created": "Time",
+ "operation": "Operation",
+ "status": "Status",
+ "subject": "Subject",
+ "to": "To",
+ "useremail": "User",
+ "values": "Values"
+ }
+ },
+ "audit_trail": {
+ "messages": {
+ "admin_job_remove_from_ar": "ADMIN: Remove from AR updated to: {{status}}",
+ "admin_jobmarkexported": "ADMIN: Job marked as exported.",
+ "admin_jobmarkforreexport": "ADMIN: Job marked for re-export.",
+ "admin_jobuninvoice": "ADMIN: Job has been uninvoiced.",
+ "admin_jobunvoid": "ADMIN: Job has been unvoided.",
+ "alerttoggle": "Alert Toggle set to {{status}}",
+ "appointmentcancel": "Appointment canceled. Lost Reason: {{lost_sale_reason}}.",
+ "appointmentinsert": "Appointment created. Appointment Date: {{start}}.",
+ "assignedlinehours": "Assigned job lines totaling {{hours}} units to {{team}}.",
+ "billdeleted": "Bill with invoice number {{invoice_number}} deleted.",
+ "billposted": "Bill with invoice number {{invoice_number}} posted.",
+ "billupdated": "Bill with invoice number {{invoice_number}} updated.",
+ "failedpayment": "Failed payment attempt.",
+ "jobassignmentchange": "Employee {{name}} assigned to {{operation}}",
+ "jobassignmentremoved": "Employee assignment removed for {{operation}}",
+ "jobchecklist": "Checklist type \"{{type}}\" completed. In production set to {{inproduction}}. Status set to {{status}}.",
+ "jobclosedwithbypass": "Job was invoiced using the master bypass password. ",
+ "jobconverted": "Job converted and assigned number {{ro_number}}.",
+ "jobdelivery": "Job intake completed. Status set to {{status}}. Actual completion is {{actual_completion}}.",
+ "jobexported": "Job has been exported",
+ "jobfieldchanged": "Job field $t(jobs.fields.{{field}}) changed to {{value}}.",
+ "jobimported": "Job imported.",
+ "jobinproductionchange": "Job production status set to {{inproduction}}",
+ "jobintake": "Job intake completed. Status set to {{status}}. Scheduled completion is {{scheduled_completion}}.",
+ "jobinvoiced": "Job has been invoiced.",
+ "jobioucreated": "IOU Created.",
+ "jobmodifylbradj": "Labor adjustments modified {{mod_lbr_ty}} / {{hours}}.",
+ "jobnoteadded": "Note added to Job.",
+ "jobnotedeleted": "Note deleted from Job.",
+ "jobnoteupdated": "Note updated on Job.",
+ "jobspartsorder": "Parts order {{order_number}} added to Job.",
+ "jobspartsreturn": "Parts return {{order_number}} added to Job.",
+ "jobstatuschange": "Job status changed to {{status}}.",
+ "jobsupplement": "Job supplement imported.",
+ "jobsuspend": "Suspend Toggle set to {{status}}",
+ "jobvoid": "Job has been voided.",
+ "tasks_completed": "Task '{{title}}' completed by {{completedBy}}",
+ "tasks_created": "Task '{{title}}' created by {{createdBy}}",
+ "tasks_deleted": "Task '{{title}}' deleted by {{deletedBy}}",
+ "tasks_uncompleted": "Task '{{title}}' uncompleted by {{uncompletedBy}}",
+ "tasks_undeleted": "Task '{{title}}' undeleted by {{undeletedBy}}",
+ "tasks_updated": "Task '{{title}}' updated by {{updatedBy}}"
+ }
+ },
+ "billlines": {
+ "actions": {
+ "newline": "New Line"
+ },
+ "fields": {
+ "actual_cost": "Actual Cost",
+ "actual_price": "Retail",
+ "cost_center": "Cost Center",
+ "federal_tax_applicable": "Fed. Tax?",
+ "jobline": "Job Line",
+ "line_desc": "Line Description",
+ "local_tax_applicable": "Loc. Tax?",
+ "location": "Location",
+ "quantity": "Quantity",
+ "state_tax_applicable": "St. Tax?"
+ },
+ "labels": {
+ "deductedfromlbr": "Deduct from Labor?",
+ "entered": "Entered",
+ "from": "From",
+ "mod_lbr_adjustment": "Adjustment Units",
+ "other": "-- Not On Estimate --",
+ "reconciled": "Reconciled!",
+ "unreconciled": "Unreconciled"
+ },
+ "validation": {
+ "atleastone": "At least one bill line must be entered."
+ }
+ },
+ "bills": {
+ "actions": {
+ "deductallhours": "Deduct all",
+ "edit": "Edit",
+ "receive": "Receive Part",
+ "return": "Return Items"
+ },
+ "errors": {
+ "creating": "Error adding bill. {{error}}",
+ "deleting": "Error deleting bill. {{error}}",
+ "existinginventoryline": "This bill cannot be deleted as it is tied to items in inventory.",
+ "exporting": "Error exporting payable(s). {{error}}",
+ "exporting-partner": "Unable to connect to partner application. Please ensure it is running and logged in.",
+ "invalidro": "Not a valid RO.",
+ "invalidvendor": "Not a valid vendor.",
+ "validation": "Please ensure all fields are entered correctly. "
+ },
+ "fields": {
+ "allpartslocation": "Parts Bin",
+ "date": "Bill Date",
+ "exported": "Exported",
+ "federal_tax_rate": "Federal Tax Rate",
+ "invoice_number": "Invoice Number",
+ "is_credit_memo": "Credit Memo?",
+ "is_credit_memo_short": "CM",
+ "local_tax_rate": "Local Tax Rate",
+ "ro_number": "RO Number",
+ "state_tax_rate": "State Tax Rate",
+ "total": "Bill Total",
+ "vendor": "Vendor",
+ "vendorname": "Vendor Name"
+ },
+ "labels": {
+ "actions": "Actions",
+ "bill_lines": "Bill Lines",
+ "bill_total": "Bill Total Amount",
+ "billcmtotal": "Credit Memos",
+ "bills": "Bills",
+ "calculatedcreditsnotreceived": "Calculated CNR",
+ "creditsnotreceived": "Credits Not Marked Received",
+ "creditsreceived": "Credits Received",
+ "dedfromlbr": "Labor Adjustments",
+ "deleteconfirm": "Are you sure you want to delete this bill? It cannot be undone. If this bill has deductions from labors, manual changes may be required.",
+ "discrepancy": "Discrepancy",
+ "discrepwithcms": "Discrepancy including Credit Memos",
+ "discrepwithlbradj": "Discrepancy including Lbr. Adj.",
+ "editadjwarning": "This bill had lines which resulted in labor adjustments. Manual correction to adjustments may be required.",
+ "entered_total": "Total of Entered Lines",
+ "enteringcreditmemo": "You are entering a credit memo. Please ensure you are also entering positive values.",
+ "federal_tax": "Federal Tax",
+ "federal_tax_exempt": "Federal Tax Exempt?",
+ "generatepartslabel": "Generate Parts Labels after Saving?",
+ "iouexists": "An IOU exists that is associated to this RO.",
+ "local_tax": "Local Tax",
+ "markexported": "Mark Exported",
+ "markforreexport": "Mark for Re-export",
+ "new": "New Bill",
+ "nobilllines": "No bills have been posted yet.",
+ "noneselected": "No bill selected.",
+ "onlycmforinvoiced": "Only credit memos can be entered for any Job that has been invoiced, exported, or voided.",
+ "printlabels": "Print Labels",
+ "retailtotal": "Bills Retail Total",
+ "returnfrombill": "Return From Bill",
+ "savewithdiscrepancy": "You are about to save this bill with a discrepancy. The system will continue to use the calculated amount using the bill lines. Press cancel to return to the bill.",
+ "state_tax": "State Tax",
+ "subtotal": "Subtotal",
+ "totalreturns": "Total Returns"
+ },
+ "successes": {
+ "created": "Invoice added successfully.",
+ "deleted": "Bill deleted successfully.",
+ "exported": "Bill(s) exported successfully.",
+ "markexported": "Bill marked as exported.",
+ "reexport": "Bill marked for re-export."
+ },
+ "validation": {
+ "closingperiod": "This Bill Date is outside of the Closing Period.",
+ "inventoryquantity": "Quantity must be greater than or equal to what has been added to inventory ({{number}}).",
+ "manualinhouse": "Manual posting to the in house vendor is restricted. ",
+ "unique_invoice_number": "This invoice number has already been entered for this vendor."
+ }
+ },
+ "bodyshop": {
+ "actions": {
+ "add_task_preset": "Add Task Preset",
+ "addapptcolor": "Add Appointment Color",
+ "addbucket": "Add Definition",
+ "addpartslocation": "Add Parts Location",
+ "addpartsrule": "Add Parts Scan Rule",
+ "addspeedprint": "Add Speed Print",
+ "addtemplate": "Add Template",
+ "newlaborrate": "New Labor Rate",
+ "newsalestaxcode": "New Sales Tax Code",
+ "newstatus": "Add Status",
+ "testrender": "Test Render"
+ },
+ "errors": {
+ "creatingdefaultview": "Error creating default view.",
+ "loading": "Unable to load shop details. Please call technical support.",
+ "saving": "Error encountered while saving. {{message}}"
+ },
+ "fields": {
+ "ReceivableCustomField": "QBO Receivable Custom Field {{number}}",
+ "address1": "Address 1",
+ "address2": "Address 2",
+ "appt_alt_transport": "Appointment Alternative Transportation Options",
+ "appt_colors": {
+ "color": "Color",
+ "label": "Label"
+ },
+ "appt_length": "Default Appointment Length",
+ "attach_pdf_to_email": "Attach PDF copy to sent emails?",
+ "batchid": "ADP Batch ID",
+ "bill_allow_post_to_closed": "Allow Bills to be posted to Closed Jobs",
+ "bill_federal_tax_rate": "Bills - Federal Tax Rate %",
+ "bill_local_tax_rate": "Bill - Local Tax Rate %",
+ "bill_state_tax_rate": "Bill - Provincial/State Tax Rate %",
+ "city": "City",
+ "closingperiod": "Closing Period",
+ "companycode": "ADP Company Code",
+ "country": "Country",
+ "dailybodytarget": "Scoreboard - Daily Body Target",
+ "dailypainttarget": "Scoreboard - Daily Paint Target",
+ "default_adjustment_rate": "Default Labor Deduction Adjustment Rate",
+ "deliver": {
+ "require_actual_delivery_date": "Require Actual Delivery",
+ "templates": "Delivery Templates"
+ },
+ "dms": {
+ "apcontrol": "AP Control Number",
+ "appostingaccount": "AP Posting Account",
+ "cashierid": "Cashier ID",
+ "default_journal": "Default Journal",
+ "disablebillwip": "Disable bill WIP for A/P Posting",
+ "disablecontactvehiclecreation": "Disable Contact & Vehicle Updates/Creation",
+ "dms_acctnumber": "DMS Account #",
+ "dms_control_override": "Static Control # Override",
+ "dms_wip_acctnumber": "DMS W.I.P. Account #",
+ "generic_customer_number": "Generic Customer Number",
+ "itc_federal": "Federal Tax is ITC?",
+ "itc_local": "Local Tax is ITC?",
+ "itc_state": "State Tax is ITC?",
+ "mappingname": "DMS Mapping Name",
+ "sendmaterialscosting": "Materials Cost as % of Sale",
+ "srcco": "Source Company #/Dealer #"
+ },
+ "email": "General Shop Email",
+ "enforce_class": "Enforce Class on Conversion?",
+ "enforce_conversion_category": "Enforce Category on Conversion?",
+ "enforce_conversion_csr": "Enforce CSR on Conversion?",
+ "enforce_referral": "Enforce Referrals",
+ "federal_tax_id": "Federal Tax ID (GST/HST)",
+ "ignoreblockeddays": "Scoreboard - Ignore Blocked Days",
+ "inhousevendorid": "In House Vendor ID",
+ "insurance_vendor_id": "Insurance Vendor ID",
+ "intake": {
+ "next_contact_hours": "Automatic Next Contact Date - Hours from Intake",
+ "templates": "Intake Templates"
+ },
+ "intellipay_config": {
+ "cash_discount_percentage": "Cash Discount %",
+ "enable_cash_discount": "Enable Cash Discounting",
+ "payment_type": "Payment Type Map",
+ "payment_map": {
+ "amex": "American Express",
+ "disc": "Discover",
+ "dnrs": "Diners",
+ "intr": "Interac",
+ "jcb": "JCB",
+ "mast": "MasterCard",
+ "visa": "Visa"
+ }
+ },
+ "invoice_federal_tax_rate": "Invoices - Federal Tax Rate",
+ "invoice_local_tax_rate": "Invoices - Local Tax Rate",
+ "invoice_state_tax_rate": "Invoices - State Tax Rate",
+ "jc_hourly_rates": {
+ "mapa": "Job Costing - Paint Materials Hourly Cost Rate",
+ "mash": "Job Costing - Shop Materials Hourly Cost Rate"
+ },
+ "last_name_first": "Display Owner Info as , ",
+ "lastnumberworkingdays": "Scoreboard - Last Number of Working Days",
+ "localmediaserverhttp": "Local Media Server - HTTP Path",
+ "localmediaservernetwork": "Local Media Server - Network Path",
+ "localmediatoken": "Local Media Server - Token",
+ "logo_img_footer_margin": "Footer Margin (px)",
+ "logo_img_header_margin": "Header Margin (px)",
+ "logo_img_path": "Shop Logo",
+ "logo_img_path_height": "Logo Image Height",
+ "logo_img_path_width": "Logo Image Width",
+ "md_categories": "Categories",
+ "md_ccc_rates": "Courtesy Car Contract Rate Presets",
+ "md_classes": "Classes",
+ "md_ded_notes": "Deductible Notes",
+ "md_email_cc": "Auto Email CC: $t(parts_orders.labels.{{template}})",
+ "md_from_emails": "Additional From Emails",
+ "md_functionality_toggles": {
+ "parts_queue_toggle": "Auto Add Imported/Supplemented Jobs to Parts Queue"
+ },
+ "md_hour_split": {
+ "paint": "Paint Hour Split",
+ "prep": "Prep Hour Split"
+ },
+ "md_ins_co": {
+ "city": "City",
+ "name": "Insurance Company Name",
+ "private": "Private",
+ "state": "Province/State",
+ "street1": "Street 1",
+ "street2": "Street 2",
+ "zip": "Zip/Postal Code"
+ },
+ "md_jobline_presets": "Jobline Presets",
+ "md_lost_sale_reasons": "Lost Sale Reasons",
+ "md_parts_order_comment": "Parts Orders Comments",
+ "md_parts_scan": {
+ "caseInsensitive": "Case Insensitive",
+ "expression": "",
+ "field": "Field",
+ "flags": "",
+ "mark_critical": "Mark Line as Critical?",
+ "operation": "Operation",
+ "update_field": "Field to Update",
+ "update_value": "Update Value",
+ "value": "Value"
+ },
+ "md_payment_types": "Payment Types",
+ "md_referral_sources": "Referral Sources",
+ "md_ro_guard": {
+ "enabled": "RO Guard Enabled?",
+ "enforce_ar": "Enforce AR Balance",
+ "enforce_bills": "Enforce Bill Discrepancy",
+ "enforce_cm": "Enforce Credit Memo Entry",
+ "enforce_labor": "Enforce Labor Allocation",
+ "enforce_ppd": "Enforce PPD Sync",
+ "enforce_profit": "Enforce Profit Requirement",
+ "enforce_sublet": "Enforce Sublet Completion",
+ "masterbypass": "Master Bypass Password (not encrypted)",
+ "totalgppercent_minimum": "Minimum Total Gross Profit %"
+ },
+ "md_tasks_presets": {
+ "enable_tasks": "Enable Hour Flagging",
+ "hourstype": "Hour Types",
+ "memo": "Time Ticket Memo",
+ "name": "Preset Name",
+ "nextstatus": "Next Status",
+ "percent": "Percent",
+ "use_approvals": "Use Time Ticket Approval Queue"
+ },
+ "messaginglabel": "Messaging Preset Label",
+ "messagingtext": "Messaging Preset Text",
+ "noteslabel": "Note Label",
+ "notestext": "Note Text",
+ "partslocation": "Parts Location",
+ "phone": "Phone",
+ "prodtargethrs": "Production Target Hours",
+ "rbac": {
+ "accounting": {
+ "exportlog": "Accounting -> Export Log",
+ "payables": "Accounting -> Payables",
+ "payments": "Accounting -> Payments",
+ "receivables": "Accounting -> Receivables"
+ },
+ "bills": {
+ "delete": "Bills -> Delete",
+ "enter": "Bills -> Enter",
+ "list": "Bills -> List",
+ "reexport": "Bills -> Re-export",
+ "view": "Bills -> View"
+ },
+ "contracts": {
+ "create": "Contracts -> Create",
+ "detail": "Contracts -> Detail",
+ "list": "Contracts -> List"
+ },
+ "courtesycar": {
+ "create": "Courtesy Car -> Create",
+ "detail": "Courtesy Car -> Detail",
+ "list": "Courtesy Car -> List"
+ },
+ "csi": {
+ "export": "CSI -> Export",
+ "page": "CSI -> Page"
+ },
+ "employee_teams": {
+ "page": "Employee Teams -> List"
+ },
+ "employees": {
+ "page": "Employees -> List"
+ },
+ "inventory": {
+ "delete": "Inventory -> Delete",
+ "list": "Inventory -> List"
+ },
+ "jobs": {
+ "admin": "Jobs -> Admin",
+ "available-list": "Jobs -> Available List",
+ "checklist-view": "Jobs -> Checklist View",
+ "close": "Jobs -> Close",
+ "create": "Jobs -> Create",
+ "deliver": "Jobs -> Deliver",
+ "detail": "Jobs -> Detail",
+ "intake": "Jobs -> Intake",
+ "list-active": "Jobs -> List Active",
+ "list-all": "Jobs -> List All",
+ "list-ready": "Jobs -> List Ready",
+ "partsqueue": "Jobs -> Parts Queue",
+ "void": "Jobs -> Void"
+ },
+ "owners": {
+ "detail": "Owners -> Detail",
+ "list": "Owners -> List"
+ },
+ "payments": {
+ "enter": "Payments -> Enter",
+ "list": "Payments -> List"
+ },
+ "phonebook": {
+ "edit": "Phonebook -> Edit",
+ "view": "Phonebook -> View"
+ },
+ "production": {
+ "board": "Production -> Board",
+ "list": "Production -> List"
+ },
+ "schedule": {
+ "view": "Schedule -> View"
+ },
+ "scoreboard": {
+ "view": "Scoreboard -> View"
+ },
+ "shiftclock": {
+ "view": "Shift Clock -> View"
+ },
+ "shop": {
+ "config": "Shop -> Config",
+ "dashboard": "Shop -> Dashboard",
+ "rbac": "Shop -> RBAC",
+ "reportcenter": "Shop -> Report Center",
+ "templates": "Shop -> Templates",
+ "vendors": "Shop -> Vendors"
+ },
+ "temporarydocs": {
+ "view": "Temporary Docs -> View"
+ },
+ "timetickets": {
+ "edit": "Time Tickets -> Edit",
+ "editcommitted": "Time Tickets -> Edit Committed",
+ "enter": "Time Tickets -> Enter",
+ "list": "Time Tickets -> List",
+ "shiftedit": "Time Tickets -> Shift Edit"
+ },
+ "ttapprovals": {
+ "approve": "Time Ticket Approval -> Approve",
+ "view": "Time Ticket Approval -> View"
+ },
+ "users": {
+ "editaccess": "Users -> Edit access"
+ }
+ },
+ "responsibilitycenter": "Responsibility Center",
+ "responsibilitycenter_accountdesc": "Account Description",
+ "responsibilitycenter_accountitem": "Item",
+ "responsibilitycenter_accountname": "Account Name",
+ "responsibilitycenter_accountnumber": "Account Number",
+ "responsibilitycenter_rate": "Rate",
+ "responsibilitycenter_tax_rate": "Tax {{typeNum}} Tier {{typeNumIterator}} Rate",
+ "responsibilitycenter_tax_sur": "Tax {{typeNum}} Tier {{typeNumIterator}} Surcharge",
+ "responsibilitycenter_tax_thres": "Tax {{typeNum}} Tier {{typeNumIterator}} Threshold",
+ "responsibilitycenter_tax_tier": "Tax {{typeNum}} Tier {{typeNumIterator}}",
+ "responsibilitycenter_tax_type": "Tax {{typeNum}} Type",
+ "responsibilitycenters": {
+ "ap": "Accounts Payable",
+ "ar": "Accounts Receivable",
+ "ats": "ATS",
+ "federal_tax": "Federal Tax",
+ "federal_tax_itc": "Federal Tax Credit",
+ "gst_override": "GST Override Account #",
+ "invoiceexemptcode": "QuickBooks US - Invoice Tax Exempt Code",
+ "itemexemptcode": "QuickBooks US - Line Item Tax Exempt Code",
+ "la1": "LA1",
+ "la2": "LA2",
+ "la3": "LA3",
+ "la4": "LA4",
+ "laa": "Aluminum",
+ "lab": "Body",
+ "lad": "Diagnostic",
+ "lae": "Electrical",
+ "laf": "Frame",
+ "lag": "Glass",
+ "lam": "Mechanical",
+ "lar": "Refinish",
+ "las": "Structural",
+ "lau": "User Defined",
+ "local_tax": "Local Tax",
+ "mapa": "Paint Materials",
+ "mash": "Shop Materials",
+ "paa": "Aftermarket",
+ "pac": "Chrome",
+ "pag": "Glass",
+ "pal": "LKQ",
+ "pam": "Remanufactured",
+ "pan": "OEM",
+ "pao": "Other",
+ "pap": "OEM Partial",
+ "par": "Recored",
+ "pas": "Sublet",
+ "pasl": "Sublet (L)",
+ "refund": "Refund",
+ "sales_tax_codes": {
+ "code": "Code",
+ "description": "Description",
+ "federal": "Federal Tax Applies",
+ "local": "Local Tax Applies",
+ "state": "State Tax Applies"
+ },
+ "state_tax": "State Tax",
+ "tow": "Towing"
+ },
+ "schedule_end_time": "Schedule Ending Time",
+ "schedule_start_time": "Schedule Starting Time",
+ "shopname": "Shop Name",
+ "speedprint": {
+ "id": "Id",
+ "label": "Label",
+ "templates": "Templates"
+ },
+ "ss_configuration": {
+ "dailyhrslimit": "Daily Incoming Hours Limit"
+ },
+ "ssbuckets": {
+ "color": "Job Color",
+ "gte": "Greater Than/Equal to (hrs)",
+ "id": "ID",
+ "label": "Label",
+ "lt": "Less than (hrs)",
+ "target": "Target (count)"
+ },
+ "state": "Province/State",
+ "state_tax_id": "State Tax ID",
+ "status": "Status Label",
+ "statuses": {
+ "active_statuses": "Active Statuses (Filtering for Active Jobs throughout system)",
+ "additional_board_statuses": "Additional Status to Display on Production Board",
+ "color": "Color",
+ "default_arrived": "Default Arrived Status (Transition to Production)",
+ "default_bo": "Default Backordered Status",
+ "default_canceled": "Default Canceled Status",
+ "default_completed": "Default Completed Status",
+ "default_delivered": "Default Delivered Status (Transition to Post-Production)",
+ "default_exported": "Default Exported Status",
+ "default_imported": "Default Imported Status",
+ "default_invoiced": "Default Invoiced Status",
+ "default_ordered": "Default Ordered Status",
+ "default_quote": "Default Quote Status",
+ "default_received": "Default Received Status",
+ "default_returned": "Default Returned",
+ "default_scheduled": "Default Scheduled Status",
+ "default_void": "Default Void",
+ "open_statuses": "Open Statuses",
+ "post_production_statuses": "Post-Production Statuses",
+ "pre_production_statuses": "Pre-Production Statuses",
+ "production_colors": "Production Status Colors",
+ "production_statuses": "Production Statuses",
+ "ready_statuses": "Ready Statuses"
+ },
+ "target_touchtime": "Target Touch Time",
+ "timezone": "Timezone",
+ "tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs",
+ "tt_enforce_hours_for_tech_console": "Restrict Claimable Hours",
+ "use_fippa": "Conceal Customer Information on Generated Documents?",
+ "use_paint_scale_data": "Use Paint Scale Data for Job Costing?",
+ "uselocalmediaserver": "Use Local Media Server?",
+ "website": "Website",
+ "zip_post": "Zip/Postal Code"
+ },
+ "labels": {
+ "2tiername": "Name => RO",
+ "2tiersetup": "2 Tier Setup",
+ "2tiersource": "Source => RO",
+ "accountingsetup": "Accounting Setup",
+ "accountingtiers": "Number of Tiers to Use for Export",
+ "alljobstatuses": "All Job Statuses",
+ "allopenjobstatuses": "All Open Job Statuses",
+ "apptcolors": "Appointment Colors",
+ "businessinformation": "Business Information",
+ "checklists": "Checklists",
+ "csiq": "CSI Questions",
+ "customtemplates": "Custom Templates",
+ "defaultcostsmapping": "Default Costs Mapping",
+ "defaultprofitsmapping": "Default Profits Mapping",
+ "deliverchecklist": "Delivery Checklist",
+ "dms": {
+ "cdk": {
+ "controllist": "Control Number List",
+ "payers": "Payers"
+ },
+ "cdk_dealerid": "CDK Dealer ID",
+ "costsmapping": "Costs Mapping",
+ "dms_allocations": "DMS Allocations",
+ "pbs_serialnumber": "PBS Serial Number",
+ "profitsmapping": "Profits Mapping",
+ "title": "DMS"
+ },
+ "emaillater": "Email Later",
+ "employee_teams": "Employee Teams",
+ "employees": "Employees",
+ "estimators": "Estimators",
+ "filehandlers": "Adjusters",
+ "imexpay": "ImEX Pay",
+ "insurancecos": "Insurance Companies",
+ "intakechecklist": "Intake Checklist",
+ "intellipay_cash_discount": "Please ensure that cash discounting has been enabled on your merchant account. Reach out to IntelliPay Support if you need assistance. ",
+ "jobstatuses": "Job Statuses",
+ "laborrates": "Labor Rates",
+ "licensing": "Licensing",
+ "md_parts_scan": "Parts Scan Rules",
+ "md_ro_guard": "RO Guard",
+ "md_tasks_presets": "Tasks Presets",
+ "md_to_emails": "Preset To Emails",
+ "md_to_emails_emails": "Emails",
+ "messagingpresets": "Messaging Presets",
+ "notemplatesavailable": "No templates available to add.",
+ "notespresets": "Notes Presets",
+ "orderstatuses": "Order Statuses",
+ "partslocations": "Parts Locations",
+ "partsscan": "Parts Scanning",
+ "printlater": "Print Later",
+ "qbo": "Use QuickBooks Online?",
+ "qbo_departmentid": "QBO Department ID",
+ "qbo_usa": "QBO USA Compatibility",
+ "rbac": "Role Based Access Control",
+ "responsibilitycenters": {
+ "costs": "Cost Centers",
+ "profits": "Profit Centers",
+ "sales_tax_codes": "Sales Tax Codes",
+ "tax_accounts": "Tax Accounts",
+ "title": "Responsibility Centers",
+ "ttl_adjustment": "Subtotal Adjustment Account",
+ "ttl_tax_adjustment": "Tax Adjustment Account"
+ },
+ "roguard": {
+ "title": "RO Guard"
+ },
+ "romepay": "Rome Pay",
+ "scheduling": "SMART Scheduling",
+ "scoreboardsetup": "Scoreboard Setup",
+ "shop_enabled_features": "Shop Enabled Features",
+ "shopinfo": "Shop Information",
+ "shoprates": "Shop Rates",
+ "speedprint": "Speed Print Configuration",
+ "ssbuckets": "Job Size Definitions",
+ "systemsettings": "System Settings",
+ "task-presets": "Task Presets",
+ "workingdays": "Working Days"
+ },
+ "operations": {
+ "contains": "Contains",
+ "ends_with": "Ends With",
+ "equals": "Equals",
+ "greater_than": "Greater Than",
+ "less_than": "Less Than",
+ "not_equals": "Not Equals",
+ "starts_with": "Starts With"
+ },
+ "successes": {
+ "areyousure": "Are you sure you want to continue?",
+ "defaultviewcreated": "Default view created successfully.",
+ "save": "Shop configuration saved successfully. ",
+ "unsavedchanges": "Unsaved changes will be lost. Are you sure you want to continue?"
+ },
+ "tooltips": {
+ "md_parts_scan": {
+ "update_value_tooltip": "Some fields require coded values in order to function properly (e.g. labor and part types). Please reach out to support if you have any questions."
+ }
+ },
+ "validation": {
+ "centermustexist": "The chosen responsibility center does not exist.",
+ "larsplit": "Refinish hour split must add up to 1.",
+ "useremailmustexist": "This email is not a valid user."
+ }
+ },
+ "checklist": {
+ "actions": {
+ "printall": "Print All Documents"
+ },
+ "errors": {
+ "complete": "Error during Job checklist completion. {{error}}",
+ "nochecklist": "No checklist has been configured for your shop. "
+ },
+ "labels": {
+ "addtoproduction": "Add Job to Production?",
+ "allow_text_message": "Permission to Text?",
+ "checklist": "Checklist",
+ "printpack": "Job Intake Print Pack",
+ "removefromproduction": "Remove Job from Production?"
+ },
+ "successes": {
+ "completed": "Job checklist completed."
+ }
+ },
+ "contracts": {
+ "actions": {
+ "changerate": "Change Contract Rates",
+ "convertoro": "Convert to RO",
+ "decodelicense": "Decode License",
+ "find": "Find Contract",
+ "printcontract": "Print Contract",
+ "senddltoform": "Insert Driver's License Information"
+ },
+ "errors": {
+ "fetchingjobinfo": "Error fetching Job Info. {{error}}.",
+ "returning": "Error returning Courtesy Car. {{error}}",
+ "saving": "Error saving Contract. {{error}}",
+ "selectjobandcar": "Please ensure both a car and job are selected."
+ },
+ "fields": {
+ "actax": "A/C Tax",
+ "actualreturn": "Actual Return Date",
+ "agreementnumber": "Agreement Number",
+ "cc_cardholder": "Cardholder Name",
+ "cc_expiry": "Credit Card Expiry Date",
+ "cc_num": "Credit Card Number",
+ "cleanupcharge": "Clean Up Charge",
+ "coverage": "Coverage",
+ "dailyfreekm": "Daily Free Mileage",
+ "dailyrate": "Daily Rate",
+ "damage": "Existing Damage",
+ "damagewaiver": "Damage Waiver",
+ "driver": "Driver",
+ "driver_addr1": "Driver Address 1",
+ "driver_addr2": "Driver Address 2",
+ "driver_city": "Driver City",
+ "driver_dlexpiry": "Driver's License Expiration Date",
+ "driver_dlnumber": "Driver's License Number",
+ "driver_dlst": "Driver's License Province/State",
+ "driver_dob": "Driver's DOB",
+ "driver_fn": "Driver's First Name",
+ "driver_ln": "Driver's Last Name",
+ "driver_ph1": "Driver's Phone",
+ "driver_state": "Driver's Province/State ",
+ "driver_zip": "Driver's Postal/ZIP Code",
+ "excesskmrate": "Excess Mileage",
+ "federaltax": "Federal Taxes",
+ "fuelin": "Fuel In",
+ "fuelout": "Fuel Out",
+ "kmend": "Mileage End",
+ "kmstart": "Mileage Start",
+ "length": "Length",
+ "localtax": "Local Taxes",
+ "refuelcharge": "Refuel Charge (per liter/gallon)",
+ "scheduledreturn": "Scheduled Return",
+ "start": "Contract Start",
+ "statetax": "Provincial/State Taxes",
+ "status": "Status"
+ },
+ "labels": {
+ "agreement": "Agreement {{agreement_num}} - {{status}}",
+ "availablecars": "Available Cars",
+ "cardueforservice": "The courtesy car is due for servicing.",
+ "convertform": {
+ "applycleanupcharge": "Apply cleanup charge?",
+ "refuelqty": "Refuel qty.?"
+ },
+ "correctdataonform": "Please review the information above. If any of it is not correct, you can fix it later.",
+ "dateinpast": "Date is in the past.",
+ "dlexpirebeforereturn": "The driver's license expires before the car is expected to return. ",
+ "driverinformation": "Driver's Information",
+ "findcontract": "Find Contract",
+ "findermodal": "Contract Finder",
+ "insuranceexpired": "The courtesy car insurance expires before the car is expected to return.",
+ "noteconvertedfrom": "R.O. created from converted Courtesy Car Contract {{agreementnumber}}.",
+ "populatefromjob": "Populate from Job",
+ "rates": "Contract Rates",
+ "time": "Time",
+ "vehicle": "Vehicle",
+ "waitingforscan": "Please scan driver's license barcode..."
+ },
+ "status": {
+ "new": "New Contract",
+ "out": "Out",
+ "returned": "Returned"
+ },
+ "successes": {
+ "saved": "Contract saved successfully. "
+ }
+ },
+ "courtesycars": {
+ "actions": {
+ "new": "New Courtesy Car",
+ "return": "Return Car"
+ },
+ "errors": {
+ "saving": "Error saving Courtesy Car. {{error}}"
+ },
+ "fields": {
+ "color": "Color",
+ "dailycost": "Daily Cost to Rent",
+ "damage": "Damage",
+ "fleetnumber": "Fleet Number",
+ "fuel": "Fuel Level",
+ "insuranceexpires": "Insurance Expires On",
+ "leaseenddate": "Lease Ends On",
+ "make": "Make",
+ "mileage": "Mileage",
+ "model": "Model",
+ "nextservicedate": "Next Service Date",
+ "nextservicekm": "Next Service KMs",
+ "notes": "Notes",
+ "plate": "Plate Number",
+ "purchasedate": "Purchase Date",
+ "readiness": "Readiness",
+ "registrationexpires": "Registration Expires On",
+ "serviceenddate": "Usage End Date",
+ "servicestartdate": "Usage Start Date",
+ "status": "Status",
+ "vin": "VIN",
+ "year": "Year"
+ },
+ "labels": {
+ "courtesycar": "Courtesy Car",
+ "fuel": {
+ "12": "1/2",
+ "14": "1/4",
+ "18": "1/8",
+ "34": "3/4",
+ "38": "3/8",
+ "58": "5/8",
+ "78": "7/8",
+ "empty": "Empty",
+ "full": "Full"
+ },
+ "outwith": "Out With",
+ "return": "Return Courtesy Car",
+ "status": "Status",
+ "uniquefleet": "Enter a unique fleet number.",
+ "usage": "Usage",
+ "vehicle": "Vehicle Description"
+ },
+ "readiness": {
+ "notready": "Not Ready",
+ "ready": "Ready"
+ },
+ "status": {
+ "in": "Available",
+ "inservice": "Service/Maintenance",
+ "leasereturn": "Lease Returned",
+ "out": "Rented",
+ "sold": "Sold",
+ "unavailable": "Unavailable"
+ },
+ "successes": {
+ "saved": "Courtesy Car saved successfully."
+ }
+ },
+ "csi": {
+ "actions": {
+ "activate": "Activate"
+ },
+ "errors": {
+ "creating": "Error creating survey {{message}}",
+ "notconfigured": "You do not have any current CSI Question Sets configured.",
+ "notfoundsubtitle": "We were unable to find a survey using the link you provided. Please ensure the URL is correct or reach out to your shop for more help.",
+ "notfoundtitle": "No survey found.",
+ "surveycompletesubtitle": "",
+ "surveycompletetitle": ""
+ },
+ "fields": {
+ "completedon": "Completed On",
+ "created_at": "Created At",
+ "surveyid": "",
+ "validuntil": ""
+ },
+ "labels": {
+ "copyright": "",
+ "greeting": "",
+ "intro": "",
+ "nologgedinuser": "Please log out of {{app}}",
+ "nologgedinuser_sub": "Users of {{app}} cannot complete CSI surveys while logged in. Please log out and try again.",
+ "noneselected": "No response selected.",
+ "title": "Customer Satisfaction Survey"
+ },
+ "successes": {
+ "created": "CSI created successfully. ",
+ "submitted": "Your responses have been submitted successfully.",
+ "submittedsub": "Your input is highly appreciated."
+ }
+ },
+ "dashboard": {
+ "actions": {
+ "addcomponent": "Add Component"
+ },
+ "errors": {
+ "refreshrequired": "You must refresh the dashboard data to see this component.",
+ "updatinglayout": "Error saving updated layout {{message}}"
+ },
+ "labels": {
+ "bodyhrs": "Body Hrs",
+ "dollarsinproduction": "Dollars in Production",
+ "phone": "Phone",
+ "prodhrs": "Production Hrs",
+ "refhrs": "Refinish Hrs"
+ },
+ "titles": {
+ "joblifecycle": "Job Life Cycles",
+ "labhours": "Total Body Hours",
+ "larhours": "Total Refinish Hours",
+ "monthlyemployeeefficiency": "Monthly Employee Efficiency",
+ "monthlyjobcosting": "Monthly Job Costing ",
+ "monthlylaborsales": "Monthly Labor Sales",
+ "monthlypartssales": "Monthly Parts Sales",
+ "monthlyrevenuegraph": "Monthly Revenue Graph",
+ "prodhrssummary": "Production Hours Summary",
+ "productiondollars": "Total Dollars in Production",
+ "productionhours": "Total Hours in Production",
+ "projectedmonthlysales": "Projected Monthly Sales",
+ "scheduledindate": "Scheduled In Today: {{date}}",
+ "scheduledintoday": "Scheduled In Today",
+ "scheduledoutdate": "Scheduled Out Today: {{date}}",
+ "scheduledouttoday": "Scheduled Out Today",
+ "tasks": "Tasks"
+ }
+ },
+ "dms": {
+ "errors": {
+ "alreadyexported": "This job has already been sent to the DMS. If you need to resend it, please use admin permissions to mark the job for re-export."
+ },
+ "labels": {
+ "refreshallocations": "Refresh to see DMS Allocataions."
+ }
+ },
+ "documents": {
+ "actions": {
+ "delete": "Delete Selected Documents",
+ "download": "Download Selected Images",
+ "reassign": "Reassign to another Job",
+ "selectallimages": "Select All Images",
+ "selectallotherdocuments": "Select All Other Documents"
+ },
+ "errors": {
+ "deletes3": "Error deleting document from storage. ",
+ "deleting": "Error deleting documents {{error}}",
+ "deleting_cloudinary": "Error deleting document from storage. {{message}}",
+ "getpresignurl": "Error obtaining presigned URL for document. {{message}}",
+ "insert": "Unable to upload file. {{message}}",
+ "nodocuments": "There are no documents.",
+ "updating": "Error updating document. {{error}}"
+ },
+ "labels": {
+ "confirmdelete": "Are you sure you want to delete these documents. This CANNOT be undone.",
+ "doctype": "Document Type",
+ "dragtoupload": "Click or drag files to this area to upload",
+ "newjobid": "Assign to Job",
+ "openinexplorer": "Open in Explorer",
+ "optimizedimage": "The below image is optimized. Click on the picture below to open in a new window and view it full size, or open it in explorer.",
+ "reassign_limitexceeded": "Reassigning all selected documents will exceed the job storage limit for your shop. ",
+ "reassign_limitexceeded_title": "Unable to reassign document(s)",
+ "storageexceeded": "You've exceeded your storage limit for this job. Please remove documents, or increase your storage plan.",
+ "storageexceeded_title": "Storage Limit Exceeded",
+ "upload": "Upload",
+ "upload_limitexceeded": "Uploading all selected documents will exceed the job storage limit for your shop. ",
+ "upload_limitexceeded_title": "Unable to upload document(s)",
+ "uploading": "Uploading...",
+ "usage": "of Job storage used. ({{used}} / {{total}})"
+ },
+ "successes": {
+ "delete": "Document(s) deleted successfully.",
+ "edituploaded": "Edited document uploaded successfully. Please close this window and refresh the documents list.",
+ "insert": "Uploaded document successfully. ",
+ "updated": "Document updated successfully. "
+ }
+ },
+ "emails": {
+ "errors": {
+ "notsent": "Email not sent. Error encountered while sending {{message}}"
+ },
+ "fields": {
+ "cc": "CC",
+ "from": "From",
+ "subject": "Subject",
+ "to": "To"
+ },
+ "labels": {
+ "attachments": "Attachments",
+ "documents": "Documents",
+ "emailpreview": "Email Preview",
+ "generatingemail": "Generating email...",
+ "pdfcopywillbeattached": "A PDF copy of this email will be attached when it is sent.",
+ "preview": "Email Preview"
+ },
+ "successes": {
+ "sent": "Email sent successfully."
+ }
+ },
+ "employee_teams": {
+ "actions": {
+ "new": "New Team",
+ "newmember": "New Team Member"
+ },
+ "fields": {
+ "active": "Active",
+ "employeeid": "Employee",
+ "max_load": "Max Load",
+ "name": "Team Name",
+ "percentage": "Percent"
+ }
+ },
+ "employees": {
+ "actions": {
+ "addvacation": "Add Vacation",
+ "new": "New Employee",
+ "newrate": "New Rate"
+ },
+ "errors": {
+ "delete": "Error encountered while deleting employee. {{message}}",
+ "save": "Error encountered saving employee. {{message}}",
+ "validation": "Please check all fields.",
+ "validationtitle": "Unable to save employee."
+ },
+ "fields": {
+ "active": "Active?",
+ "base_rate": "Base Rate",
+ "cost_center": "Cost Center",
+ "employee_number": "Employee Number",
+ "external_id": "External Employee ID",
+ "first_name": "First Name",
+ "flat_rate": "Flat Rate (Disabled is Straight Time)",
+ "hire_date": "Hire Date",
+ "last_name": "Last Name",
+ "pin": "Tech Console PIN",
+ "rate": "Rate",
+ "termination_date": "Termination Date",
+ "user_email": "User Email",
+ "vacation": {
+ "end": "Vacation End",
+ "length": "Vacation Length",
+ "start": "Vacation Start"
+ }
+ },
+ "labels": {
+ "actions": "Actions",
+ "active": "Active",
+ "endmustbeafterstart": "End date must be after start date.",
+ "flat_rate": "Flat Rate",
+ "inactive": "Inactive",
+ "name": "Name",
+ "rate_type": "Rate Type",
+ "status": "Status",
+ "straight_time": "Straight Time"
+ },
+ "successes": {
+ "delete": "Employee deleted successfully.",
+ "save": "Employee saved successfully.",
+ "vacationadded": "Employee vacation added."
+ },
+ "validation": {
+ "unique_employee_number": "You must enter a unique employee number."
+ }
+ },
+ "eula": {
+ "buttons": {
+ "accept": "Accept EULA"
+ },
+ "content": {
+ "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting."
+ },
+ "errors": {
+ "acceptance": {
+ "description": "Something went wrong while accepting the EULA. Please try again.",
+ "message": "Eula Acceptance Error"
+ }
+ },
+ "labels": {
+ "accepted_terms": "I accept the terms and conditions of this agreement.",
+ "address": "Address",
+ "business_name": "Legal Business Name",
+ "date_accepted": "Date Accepted",
+ "first_name": "First Name",
+ "last_name": "Last Name",
+ "phone_number": "Phone Number"
+ },
+ "messages": {
+ "accepted_terms": "Please accept the terms and conditions of this agreement.",
+ "business_name": "Please enter your legal business name.",
+ "date_accepted": "Please enter Today's Date.",
+ "first_name": "Please enter your first name.",
+ "last_name": "Please enter your last name.",
+ "phone_number": "Please enter your phone number."
+ },
+ "titles": {
+ "modal": "Terms and Conditions",
+ "upper_card": "Acknowledgement"
+ }
+ },
+ "exportlogs": {
+ "fields": {
+ "createdat": "Created At"
+ },
+ "labels": {
+ "attempts": "Export Attempts",
+ "priorsuccesfulexport": "This record has previously been exported successfully. Please make sure it has already been deleted in the target system."
+ }
+ },
+ "general": {
+ "actions": {
+ "add": "Add",
+ "autoupdate": "{{app}} will automatically update in {{time}} seconds. Please save all changes.",
+ "calculate": "Calculate",
+ "cancel": "Cancel",
+ "clear": "Clear",
+ "close": "Close",
+ "copied": "Copied!",
+ "copylink": "Copy Link",
+ "create": "Create",
+ "defaults": "Defaults",
+ "delay": "Delay Update (5 mins)",
+ "delete": "Delete",
+ "deleteall": "Delete All",
+ "deselectall": "Deselect All",
+ "download": "Download",
+ "edit": "Edit",
+ "login": "Login",
+ "next": "Next",
+ "ok": "Ok",
+ "previous": "Previous",
+ "print": "Print",
+ "refresh": "Refresh",
+ "remove": "Remove",
+ "remove_alert": "Are you sure you want to dismiss the alert?",
+ "reset": "Reset your changes.",
+ "resetpassword": "Reset Password",
+ "save": "Save",
+ "saveandnew": "Save and New",
+ "saveas": "Save As",
+ "selectall": "Select All",
+ "send": "Send",
+ "sendbysms": "Send by SMS",
+ "senderrortosupport": "Send Error to Support",
+ "sharetoteams": "Share to Teams",
+ "submit": "Submit",
+ "tryagain": "Try Again",
+ "view": "View",
+ "viewreleasenotes": "See What's Changed"
+ },
+ "errors": {
+ "fcm": "You must allow notification permissions to have real time messaging. Click to try again.",
+ "notfound": "No record was found.",
+ "sizelimit": "The selected items exceed the size limit."
+ },
+ "itemtypes": {
+ "contract": "CC Contract",
+ "courtesycar": "Courtesy Car",
+ "job": "Job",
+ "owner": "Owner",
+ "vehicle": "Vehicle"
+ },
+ "labels": {
+ "actions": "Actions",
+ "areyousure": "Are you sure?",
+ "barcode": "Barcode",
+ "cancel": "Are you sure you want to cancel? Your changes will not be saved.",
+ "clear": "Clear",
+ "confirmpassword": "Confirm Password",
+ "created_at": "Created At",
+ "date": "Select Date",
+ "datetime": "Select Date & Time",
+ "email": "Email",
+ "errors": "Errors",
+ "excel": "Excel",
+ "exceptiontitle": "An error has occurred.",
+ "friday": "Friday",
+ "globalsearch": "Global Search",
+ "help": "Help",
+ "hours": "hrs",
+ "in": "In",
+ "instanceconflictext": "Your {{app}} account can only be used on one device at any given time. Refresh your session to take control.",
+ "instanceconflictitle": "Your account is being used elsewhere.",
+ "item": "Item",
+ "label": "Label",
+ "loading": "Loading...",
+ "loadingapp": "Loading {{app}}",
+ "loadingshop": "Loading shop data...",
+ "loggingin": "Authorizing...",
+ "markedexported": "Manually marked as exported.",
+ "media": "Media",
+ "message": "Message",
+ "monday": "Monday",
+ "na": "N/A",
+ "newpassword": "New Password",
+ "no": "No",
+ "nointernet": "It looks like you're not connected to the internet.",
+ "nointernet_sub": "Please check your connection and try again. ",
+ "none": "None",
+ "out": "Out",
+ "password": "Password",
+ "passwordresetsuccess": "A password reset link has been sent to you.",
+ "passwordresetsuccess_sub": "You should receive this email in the next few minutes. Please check your email including any junk or spam folders. ",
+ "passwordresetvalidatesuccess": "Password successfully reset. ",
+ "passwordresetvalidatesuccess_sub": "You may now sign in again using your new password. ",
+ "passwordsdonotmatch": "The passwords you have entered do not match.",
+ "print": "Print",
+ "refresh": "Refresh",
+ "reports": "Reports",
+ "required": "Required",
+ "saturday": "Saturday",
+ "search": "Search...",
+ "searchresults": "Results for {{search}}",
+ "selectdate": "Select date...",
+ "sendagain": "Send Again",
+ "sendby": "Send By",
+ "signin": "Sign In",
+ "sms": "SMS",
+ "status": "Status",
+ "sub_status": {
+ "expired": "The subscription for this shop has expired. Please contact technical support to reactivate the subscription. "
+ },
+ "successful": "Successful",
+ "sunday": "Sunday",
+ "text": "Text",
+ "thursday": "Thursday",
+ "time": "Select Time",
+ "total": "Total",
+ "totals": "Totals",
+ "tuesday": "Tuesday",
+ "tvmode": "TV Mode",
+ "unknown": "Unknown",
+ "unsavedchanges": "Unsaved changes.",
+ "username": "Username",
+ "view": "View",
+ "wednesday": "Wednesday",
+ "yes": "Yes"
+ },
+ "languages": {
+ "english": "English",
+ "french": "French",
+ "spanish": "Spanish"
+ },
+ "messages": {
+ "exception": "{{app}} has encountered an error. Please try again. If the problem persists, please submit a support ticket or contact us.",
+ "newversionmessage": "Click refresh below to update to the latest available version of {{app}}. Please make sure all other tabs and windows are closed.",
+ "newversiontitle": "New version of {{app}} Available",
+ "noacctfilepath": "There is no accounting file path set. You will not be able to export any items.",
+ "nofeatureaccess": "You do not have access to this feature of {{app}}. Please contact support to request a license for this feature.",
+ "noshop": "You do not have access to any shops. Please reach out to your shop manager or technical support. ",
+ "notfoundsub": "Please make sure that you have access to the data or that the link is correct.",
+ "notfoundtitle": "We couldn't find what you're looking for...",
+ "partnernotrunning": "{{app}} has detected that the partner is not running. Please ensure it is running to enable full functionality.",
+ "rbacunauth": "You are not authorized to view this content. Please reach out to your shop manager to change your access level.",
+ "unsavedchanges": "You have unsaved changes.",
+ "unsavedchangespopup": "You have unsaved changes. Are you sure you want to leave?"
+ },
+ "validation": {
+ "dateRangeExceeded": "The date range has been exceeded.",
+ "invalidemail": "Please enter a valid email.",
+ "invalidphone": "Please enter a valid phone number.",
+ "required": "{{label}} is required."
+ }
+ },
+ "help": {
+ "actions": {
+ "connect": "Connect"
+ },
+ "labels": {
+ "codeplacholder": "6 digit PIN code",
+ "rescuedesc": "Enter the 6 digit code provided by {{app}} Support below and click connect.",
+ "rescuetitle": "Rescue Me!"
+ }
+ },
+ "intake": {
+ "labels": {
+ "printpack": "Intake Print Pack"
+ }
+ },
+ "inventory": {
+ "actions": {
+ "addtoinventory": "Add to Inventory",
+ "addtoro": "Add to RO",
+ "consumefrominventory": "Consume from Inventory?",
+ "edit": "Edit Inventory LIne",
+ "new": "New Inventory Line"
+ },
+ "errors": {
+ "inserting": "Error inserting inventory item. {{error}}"
+ },
+ "fields": {
+ "comment": "Comment",
+ "manualinvoicenumber": "Invoice Number",
+ "manualvendor": "Vendor"
+ },
+ "labels": {
+ "consumedbyjob": "Consumed by Job",
+ "deleteconfirm": "Are you sure you want to delete this from inventory? The associated bill will not be modified or deleted. ",
+ "frombillinvoicenumber": "Original Bill Invoice Number",
+ "fromvendor": "Original Bill Vendor",
+ "inventory": "Inventory",
+ "showall": "Show All Inventory",
+ "showavailable": "Show Only Available Inventory"
+ },
+ "successes": {
+ "deleted": "Inventory lined deleted.",
+ "inserted": "Added line to inventory.",
+ "updated": "Inventory line updated."
+ }
+ },
+ "job_lifecycle": {
+ "columns": {
+ "average_human_readable": "Average Human Readable",
+ "average_value": "Average Value",
+ "duration": "Duration",
+ "end": "End",
+ "human_readable": "Human Readable",
+ "percentage": "Percentage",
+ "relative_end": "Relative End",
+ "relative_start": "Relative Start",
+ "start": "Start",
+ "status": "Status",
+ "status_count": "In Status",
+ "value": "Value"
+ },
+ "content": {
+ "calculated_based_on": "Calculated based on",
+ "current_status_accumulated_time": "Current Status Accumulated Time",
+ "data_unavailable": " There is currently no Lifecycle data for this Job.",
+ "jobs_in_since": "Jobs in since",
+ "legend_title": "Legend",
+ "loading": "Loading Job Timelines....",
+ "not_available": "N/A",
+ "previous_status_accumulated_time": "Previous Status Accumulated Time",
+ "title": "Job Lifecycle Component",
+ "title_durations": "Historical Status Durations",
+ "title_loading": "Loading",
+ "title_transitions": "Transitions"
+ },
+ "errors": {
+ "fetch": "Error getting Job Lifecycle Data"
+ },
+ "titles": {
+ "dashboard": "Job Lifecycle",
+ "top_durations": "Top Durations"
+ }
+ },
+ "job_payments": {
+ "buttons": {
+ "create_short_link": "Generate Short Link",
+ "goback": "Go Back",
+ "proceedtopayment": "Proceed to Payment",
+ "refundpayment": "Refund Payment"
+ },
+ "notifications": {
+ "error": {
+ "description": "Please try again. Make sure the refund amount does not exceeds the payment amount.",
+ "openingip": "Error connecting to IntelliPay service.",
+ "title": "Error placing refund"
+ }
+ },
+ "titles": {
+ "amount": "Amount",
+ "dateOfPayment": "Date of Payment",
+ "descriptions": "Payment Details",
+ "hint": "Hint",
+ "payer": "Payer",
+ "payername": "Payer Name",
+ "paymentid": "Payment Reference ID",
+ "paymentnum": "Payment Number",
+ "paymenttype": "Payment Type",
+ "refundamount": "Refund Amount",
+ "transactionid": "Transaction ID"
+ }
+ },
+ "joblines": {
+ "actions": {
+ "assign_team": "Assign Team",
+ "converttolabor": "Convert amount to Labor.",
+ "dispatchparts": "Dispatch Parts ({{count}})",
+ "new": "New Line"
+ },
+ "errors": {
+ "creating": "Error encountered while creating job line. {{message}}",
+ "updating": "Error encountered updating job line. {{message}}"
+ },
+ "fields": {
+ "act_price": "Retail Price",
+ "act_price_before_ppc": "Original Part Price",
+ "adjustment": "Adjustment",
+ "ah_detail_line": "Mark as Detail Labor Line (Autohouse Only)",
+ "alt_partno": "Alt Part #",
+ "amount": "Amount",
+ "assigned_team": "Team",
+ "assigned_team_name": "Team {{name}}",
+ "create_ppc": "Create PPC?",
+ "db_price": "List Price",
+ "include_in_part_cnt": "Include in Parts Status Count",
+ "lbr_types": {
+ "LA1": "LA1",
+ "LA2": "LA2",
+ "LA3": "LA3",
+ "LA4": "LA4",
+ "LAA": "Aluminum",
+ "LAB": "Body",
+ "LAD": "Diagnostic",
+ "LAE": "Electrical",
+ "LAF": "Frame",
+ "LAG": "Glass",
+ "LAM": "Mechanical",
+ "LAR": "Refinish",
+ "LAS": "Structural",
+ "LAU": "User Defined"
+ },
+ "line_desc": "Line Desc.",
+ "line_ind": "S#",
+ "line_no": "Line #",
+ "location": "Location",
+ "mod_lb_hrs": "Hrs",
+ "mod_lbr_ty": "Labor Type",
+ "notes": "Notes",
+ "oem_partno": "OEM Part #",
+ "op_code_desc": "Op Code Description",
+ "part_qty": "Qty.",
+ "part_type": "Part Type",
+ "part_types": {
+ "CCC": "CC Cleaning",
+ "CCD": "CC Damage Waiver",
+ "CCDR": "CC Daily Rate",
+ "CCF": "CC Refuel",
+ "CCM": "CC Mileage",
+ "PAA": "Aftermarket",
+ "PAC": "Rechromed",
+ "PAE": "Existing",
+ "PAG": "Glass",
+ "PAL": "LKQ",
+ "PAM": "Remanufactured",
+ "PAN": "New/OEM",
+ "PAO": "Other",
+ "PAP": "OEM Partial",
+ "PAR": "Recored",
+ "PAS": "Sublet",
+ "PASL": "Sublet (L)"
+ },
+ "profitcenter_labor": "Profit Center: Labor",
+ "profitcenter_part": "Profit Center: Part",
+ "prt_dsmk_m": "Line Discount/Markup $",
+ "prt_dsmk_p": "Line Discount/Markup %",
+ "status": "Status",
+ "tax_part": "Tax Part",
+ "total": "Total",
+ "unq_seq": "Seq #"
+ },
+ "labels": {
+ "adjustmenttobeadded": "Adjustment to be added: {{adjustment}}",
+ "billref": "Latest Bill",
+ "convertedtolabor": "This line has been converted to labor. Ensure you adjust the profit center for the amount accordingly.",
+ "edit": "Edit Line",
+ "ioucreated": "IOU",
+ "new": "New Line",
+ "nostatus": "No Status",
+ "presets": "Jobline Presets"
+ },
+ "successes": {
+ "created": "Job line created successfully.",
+ "saved": "Job line saved.",
+ "updated": "Job line updated successfully."
+ },
+ "validations": {
+ "ahdetailonlyonuserdefinedtypes": "Detail line indicator can only be set for LA1, LA2, LA3, LA4, and LAU labor types.",
+ "hrsrequirediflbrtyp": "Labor hours are required if a labor type is selected. Clear the labor type if there are no labor hours.",
+ "requiredifparttype": "Required if a part type has been specified.",
+ "zeropriceexistingpart": "This line cannot have any price since it uses an existing part."
+ }
+ },
+ "jobs": {
+ "actions": {
+ "addDocuments": "Add Job Documents",
+ "addNote": "Add Note",
+ "addtopartsqueue": "Add to Parts Queue",
+ "addtoproduction": "Add to Production",
+ "addtoscoreboard": "Add to Scoreboard",
+ "allocate": "Allocate",
+ "autoallocate": "Auto Allocate",
+ "changefilehandler": "Change Adjuster",
+ "changelaborrate": "Change Labor Rate",
+ "changestatus": "Change Status",
+ "changestimator": "Change Estimator",
+ "convert": "Convert",
+ "createiou": "Create IOU",
+ "deliver": "Deliver",
+ "deliver_quick": "Quick Deliver",
+ "dms": {
+ "addpayer": "Add Payer",
+ "createnewcustomer": "Create New Customer",
+ "findmakemodelcode": "Find Make/Model Code",
+ "getmakes": "Get Makes",
+ "labels": {
+ "refreshallocations": "Refresh this component to see the DMS allocations."
+ },
+ "post": "Post",
+ "refetchmakesmodels": "Refetch Make and Model Codes",
+ "usegeneric": "Use Generic Customer",
+ "useselected": "Use Selected Customer"
+ },
+ "dmsautoallocate": "DMS Auto Allocate",
+ "export": "Export",
+ "exportcustdata": "Export Customer Data",
+ "exportselected": "Export Selected",
+ "filterpartsonly": "Filter Parts Only",
+ "generatecsi": "Generate CSI & Copy Link",
+ "gotojob": "Go to Job",
+ "intake": "Intake",
+ "intake_quick": "Quick Intake",
+ "manualnew": "Create New Job Manually",
+ "mark": "Mark",
+ "markasexported": "Mark as Exported",
+ "markpstexempt": "Mark Job PST Exempt",
+ "markpstexemptconfirm": "Are you sure you want to do this? To undo this, you must manually update all PST rates.",
+ "postbills": "Post Bills",
+ "printCenter": "Print Center",
+ "recalculate": "Recalculate",
+ "reconcile": "Reconcile",
+ "removefromproduction": "Remove from Production",
+ "schedule": "Schedule",
+ "sendcsi": "Send CSI",
+ "sendpartspricechange": "Send Parts Price Change",
+ "sendtodms": "Send to DMS",
+ "sync": "Sync",
+ "taxprofileoverride": "Override Tax Profile with Shop Configuration",
+ "taxprofileoverride_confirm": "Are you sure you want to override the tax profile information? This cannot be undone without re-importing the job. ",
+ "uninvoice": "Uninvoice",
+ "unvoid": "Unvoid Job",
+ "viewchecklist": "View Checklists",
+ "viewdetail": "View Details"
+ },
+ "errors": {
+ "addingtoproduction": "Error adding to production. {{error}}",
+ "cannotintake": "Intake cannot be completed for this Job. It has either already been completed or the job is already here.",
+ "closing": "Error closing Job. {{error}}",
+ "creating": "Error encountered while creating job. {{error}}",
+ "deleted": "Error deleting Job. {{error}}",
+ "exporting": "Error exporting Job. {{error}}",
+ "exporting-partner": "Unable to connect to partner application. Please ensure it is running and logged in.",
+ "invoicing": "Error invoicing Job. {{error}}",
+ "noaccess": "This Job does not exist or you do not have access to it.",
+ "nodamage": "No damage points on estimate.",
+ "nodates": "No dates specified for this Job.",
+ "nofinancial": "No financial data has been calculated yet for this job. Please save it again.",
+ "nojobselected": "No Job is selected.",
+ "noowner": "No owner associated.",
+ "novehicle": "No vehicle associated.",
+ "partspricechange": "Error sending parts price change. {{error}}.",
+ "saving": "Error encountered while saving record.",
+ "scanimport": "Error importing Job. {{message}}",
+ "totalscalc": "Error while calculating new Job totals.",
+ "updating": "Error while updating Job(s). {{error}}",
+ "validation": "Please ensure all fields are entered correctly.",
+ "validationtitle": "Validation Error",
+ "voiding": "Error voiding Job. {{error}}"
+ },
+ "fields": {
+ "active_tasks": "Active Tasks",
+ "actual_completion": "Actual Completion",
+ "actual_delivery": "Actual Delivery",
+ "actual_in": "Actual In",
+ "adjustment_bottom_line": "Adjustments",
+ "adjustmenthours": "Adjustment Hours",
+ "alt_transport": "Alt. Trans.",
+ "area_of_damage_impact": {
+ "10": "Left Front Side",
+ "11": "Left Front Corner",
+ "12": "Front",
+ "13": "Rollover",
+ "14": "Unknown",
+ "15": "Total Loss",
+ "16": "Non-collision",
+ "25": "Hood",
+ "26": "Deck-lid",
+ "27": "Roof",
+ "28": "Undercarriage",
+ "34": "All Over",
+ "01": "Right Front Corner",
+ "02": "Right Front Side",
+ "03": "Right Side",
+ "04": "Right Rear Side",
+ "05": "Right Rear Corner",
+ "06": "Rear",
+ "07": "Left Rear Corner",
+ "08": "Left Rear Side",
+ "09": "Left Side"
+ },
+ "auto_add_ats": "Automatically Add/Update ATS?",
+ "ca_bc_pvrt": "PVRT",
+ "ca_customer_gst": "Customer Portion of GST",
+ "ca_gst_registrant": "GST Registrant",
+ "category": "Category",
+ "ccc": "CC Cleaning",
+ "ccd": "CC Damage Waiver",
+ "ccdr": "CC Daily Rate",
+ "ccf": "CC Refuel",
+ "ccm": "CC Mileage",
+ "cieca_id": "CIECA ID",
+ "cieca_pfl": {
+ "lbr_adjp": "Labor Adjustment",
+ "lbr_tax_in": "Tax Labor Indicator",
+ "lbr_taxp": "Labor Tax Rate",
+ "lbr_tx_in1": "Tax 1 Indicator",
+ "lbr_tx_in2": "Tax 2 Indicator",
+ "lbr_tx_in3": "Tax 3 Indicator",
+ "lbr_tx_in4": "Tax 4 Indicator",
+ "lbr_tx_in5": "Tax 5 Indicator"
+ },
+ "cieca_pfo": {
+ "stor_t_in1": "Storage Tax 1 Indicator",
+ "stor_t_in2": "Storage Tax 2 Indicator",
+ "stor_t_in3": "Storage Tax 3 Indicator",
+ "stor_t_in4": "Storage Tax 4 Indicator",
+ "stor_t_in5": "Storage Tax 5 Indicator",
+ "tow_t_in1": "Tow Tax 1 Indicator",
+ "tow_t_in2": "Tow Tax 2 Indicator",
+ "tow_t_in3": "Tow Tax 3 Indicator",
+ "tow_t_in4": "Tow Tax 4 Indicator",
+ "tow_t_in5": "Tow Tax 5 Indicator"
+ },
+ "claim_total": "Claim Total",
+ "class": "Class",
+ "clm_no": "Claim #",
+ "clm_total": "Claim Total",
+ "comment": "Comment",
+ "customerowing": "Customer Owing",
+ "date_estimated": "Date Estimated",
+ "date_exported": "Exported",
+ "date_invoiced": "Invoiced",
+ "date_last_contacted": "Last Contacted Date",
+ "date_lost_sale": "Lost Sale",
+ "date_next_contact": "Next Contact Date",
+ "date_open": "Open",
+ "date_rentalresp": "Shop Rental Responsibility Start",
+ "date_repairstarted": "Repairs Started",
+ "date_scheduled": "Scheduled",
+ "date_towin": "Towed In",
+ "date_void": "Void",
+ "ded_amt": "Deductible",
+ "ded_note": "Deductible Note",
+ "ded_status": "Deductible Status",
+ "depreciation_taxes": "Betterment/Depreciation/Taxes",
+ "dms": {
+ "address": "Customer Address",
+ "amount": "Amount",
+ "center": "Center",
+ "control_type": {
+ "account_number": "Account Number"
+ },
+ "cost": "Cost",
+ "cost_dms_acctnumber": "Cost DMS Acct #",
+ "dms_make": "DMS Make",
+ "dms_model": "DMS Model",
+ "dms_model_override": "Override DMS Make/Model",
+ "dms_unsold": "New, Unsold Vehicle",
+ "dms_wip_acctnumber": "Cost WIP DMS Acct #",
+ "id": "DMS ID",
+ "inservicedate": "In Service Date",
+ "journal": "Journal #",
+ "lines": "Posting Lines",
+ "name1": "Customer Name",
+ "payer": {
+ "amount": "Amount",
+ "control_type": "Control Type",
+ "controlnumber": "Control Number",
+ "dms_acctnumber": "DMS Account #",
+ "name": "Payer Name"
+ },
+ "sale": "Sale",
+ "sale_dms_acctnumber": "Sale DMS Acct #",
+ "story": "Story",
+ "vinowner": "VIN Owner"
+ },
+ "dms_allocation": "DMS Allocation",
+ "driveable": "Driveable",
+ "employee_body": "Body",
+ "employee_csr": "Customer Service Rep.",
+ "employee_csr_writer": "Writer",
+ "employee_prep": "Prep",
+ "employee_refinish": "Refinish",
+ "est_addr1": "Estimator Address",
+ "est_co_nm": "Estimator Company",
+ "est_ct_fn": "Estimator First Name",
+ "est_ct_ln": "Estimator Last Name",
+ "est_ea": "Estimator Email",
+ "est_ph1": "Estimator Phone #",
+ "flat_rate_ats": "Flat Rate ATS?",
+ "federal_tax_payable": "Federal Tax Payable",
+ "federal_tax_rate": "Federal Tax Rate",
+ "ins_addr1": "Insurance Co. Address",
+ "ins_city": "Insurance Co. City",
+ "ins_co_id": "Insurance Co. ID",
+ "ins_co_nm": "Insurance Company Name",
+ "ins_co_nm_short": "Ins. Co.",
+ "ins_ct_fn": "Adjuster First Name",
+ "ins_ct_ln": "Adjuster Last Name",
+ "ins_ea": "Adjuster Email",
+ "ins_ph1": "Adjuster Phone #",
+ "intake": {
+ "label": "Label",
+ "max": "Maximum",
+ "min": "Minimum",
+ "name": "Name",
+ "required": "Required?",
+ "type": "Type"
+ },
+ "invoice_final_note": "Note to Display on Final Invoice",
+ "kmin": "Mileage In",
+ "kmout": "Mileage Out",
+ "la1": "LA1",
+ "la2": "LA2",
+ "la3": "LA3",
+ "la4": "LA4",
+ "laa": "Aluminum ",
+ "lab": "Body",
+ "labor_rate_desc": "Labor Rate Name",
+ "lad": "Diagnostic",
+ "lae": "Electrical",
+ "laf": "Frame",
+ "lag": "Glass",
+ "lam": "Mechanical",
+ "lar": "Refinish",
+ "las": "Structural",
+ "lau": "User Defined",
+ "local_tax_rate": "Local Tax Rate",
+ "loss_date": "Loss Date",
+ "loss_desc": "Loss Description",
+ "loss_of_use": "Loss of Use",
+ "lost_sale_reason": "Lost Sale Reason",
+ "ma2s": "2 Stage Paint",
+ "ma3s": "3 Stage Pain",
+ "mabl": "MABL?",
+ "macs": "MACS?",
+ "mahw": "Hazardous Waste",
+ "mapa": "Paint Materials",
+ "mash": "Shop Materials",
+ "matd": "Tire Disposal",
+ "materials": {
+ "MAPA": "Paint Materials",
+ "MASH": "Shop Materials",
+ "cal_maxdlr": "Threshhold",
+ "cal_opcode": "OP Codes",
+ "mat_adjp": "Material Adjustment",
+ "mat_taxp": "Material Tax Rate",
+ "mat_tx_in1": "Tax 1 Indicator",
+ "mat_tx_in2": "Tax 2 Indicator",
+ "mat_tx_in3": "Tax 3 Indicator",
+ "mat_tx_in4": "Tax 4 Indicator",
+ "mat_tx_in5": "Tax 5 Indicator",
+ "materials": "Profile - Materials",
+ "tax_ind": "Tax Indicator"
+ },
+ "other_amount_payable": "Other Amount Payable",
+ "owner": "Owner",
+ "owner_owing": "Cust. Owes",
+ "ownr_ea": "Email",
+ "ownr_ph1": "Phone 1",
+ "ownr_ph2": "Phone 2",
+ "paa": "Aftermarket",
+ "pac": "Rechromed",
+ "pae": "Existing",
+ "pag": "Glass",
+ "pal": "LKQ",
+ "pam": "Remanufactured",
+ "pan": "OEM/New",
+ "pao": "Other",
+ "pap": "OEM Partial",
+ "par": "Re-cored",
+ "parts_tax_rates": {
+ "prt_discp": "Discount %",
+ "prt_mktyp": "Markup Type",
+ "prt_mkupp": "Markup %",
+ "prt_tax_in": "Tax Indicator",
+ "prt_tax_rt": "Part Tax Rate",
+ "prt_tx_in1": "Tax 1 Indicator",
+ "prt_tx_in2": "Tax 2 Indicator",
+ "prt_tx_in3": "Tax 3 Indicator",
+ "prt_tx_in4": "Tax 4 Indicator",
+ "prt_tx_in5": "Tax 5 Indicator",
+ "prt_tx_ty1": "Parts Tax Type 1",
+ "prt_type": "Part Type"
+ },
+ "partsstatus": "Parts Status",
+ "pas": "Sublet",
+ "pay_date": "Pay Date",
+ "phoneshort": "PH",
+ "po_number": "PO Number",
+ "policy_no": "Policy #",
+ "ponumber": "PO Number",
+ "production_vars": {
+ "note": "Production Note"
+ },
+ "qb_multiple_payers": {
+ "amount": "Amount",
+ "name": "Name"
+ },
+ "queued_for_parts": "Queued for Parts",
+ "rate_ats": "ATS Rate",
+ "rate_ats_flat": "ATS Flat Rate",
+ "rate_la1": "LA1",
+ "rate_la2": "LA2",
+ "rate_la3": "LA3",
+ "rate_la4": "LA4",
+ "rate_laa": "Aluminum",
+ "rate_lab": "Body",
+ "rate_lad": "Diagnostic",
+ "rate_lae": "Electrical",
+ "rate_laf": "Frame",
+ "rate_lag": "Glass",
+ "rate_lam": "Mechanical",
+ "rate_lar": "Refinish",
+ "rate_las": "Structural",
+ "rate_lau": "User Defined",
+ "rate_ma2s": "2 Stage Paint",
+ "rate_ma3s": "3 Stage Paint",
+ "rate_mabl": "MABL??",
+ "rate_macs": "MACS??",
+ "rate_mahw": "Hazardous Waste",
+ "rate_mapa": "Paint Materials",
+ "rate_mash": "Shop Material",
+ "rate_matd": "Tire Disposal",
+ "referral_source_extra": "Other Referral Source",
+ "referral_source_other": "",
+ "referralsource": "Referral Source",
+ "regie_number": "Registration #",
+ "repairtotal": "Repair Total",
+ "ro_number": "RO #",
+ "scheduled_completion": "Scheduled Completion",
+ "scheduled_delivery": "Scheduled Delivery",
+ "scheduled_in": "Scheduled In",
+ "selling_dealer": "Selling Dealer",
+ "selling_dealer_contact": "Selling Dealer Contact",
+ "servicecar": "Service Car",
+ "servicing_dealer": "Servicing Dealer",
+ "servicing_dealer_contact": "Servicing Dealer Contact",
+ "special_coverage_policy": "Special Coverage Policy",
+ "specialcoveragepolicy": "Special Coverage Policy",
+ "state_tax_rate": "State Tax Rate",
+ "status": "Job Status",
+ "storage_payable": "Storage",
+ "tax_lbr_rt": "Labor Tax Rate",
+ "tax_levies_rt": "Levies Tax Rate",
+ "tax_paint_mat_rt": "Paint Material Tax Rate",
+ "tax_registration_number": "Tax Registration Number",
+ "tax_shop_mat_rt": "Shop Material Tax Rate",
+ "tax_str_rt": "Storage Tax Rate",
+ "tax_sub_rt": "Sublet Tax Rate",
+ "tax_tow_rt": "Towing Tax Rate",
+ "tlos_ind": "Total Loss Indicator",
+ "towin": "Tow In",
+ "towing_payable": "Towing Payable",
+ "unitnumber": "Unit #",
+ "updated_at": "Updated At",
+ "uploaded_by": "Uploaded By",
+ "vehicle": "Vehicle"
+ },
+ "forms": {
+ "admindates": "Administrative Dates",
+ "appraiserinfo": "Estimator Info",
+ "claiminfo": "Claim Information",
+ "estdates": "Estimate Dates",
+ "laborrates": "Labor Rates",
+ "lossinfo": "Loss Information",
+ "other": "Other",
+ "repairdates": "Repair Dates",
+ "scheddates": "Schedule Dates"
+ },
+ "labels": {
+ "accountsreceivable": "Accounts Receivable",
+ "act_price_ppc": "New Part Price",
+ "actual_completion_inferred": "$t(jobs.fields.actual_completion) inferred using $t(jobs.fields.scheduled_completion).",
+ "actual_delivery_inferred": "$t(jobs.fields.actual_delivery) inferred using $t(jobs.fields.scheduled_delivery).",
+ "actual_in_inferred": "$t(jobs.fields.actual_in) inferred using $t(jobs.fields.scheduled_in).",
+ "additionalpayeroverallocation": "You have allocated more than the sale of the Job to additional payers.",
+ "additionaltotal": "Additional Total",
+ "adjustmentrate": "Adjustment Rate",
+ "adjustments": "Adjustments",
+ "adminwarning": "Use the functionality on this page at your own risk. You are responsible for any and all changes to your data.",
+ "allocations": "Allocations",
+ "alreadyaddedtoscoreboard": "Job has already been added to scoreboard. Saving will update the previous entry.",
+ "alreadyclosed": "This Job has already been closed.",
+ "appointmentconfirmation": "Send confirmation to customer?",
+ "associationwarning": "Any changes to associations will require updating the data from the new parent record to the Job.",
+ "audit": "Audit Trail",
+ "available": "Available",
+ "availablejobs": "Available Jobs",
+ "ca_bc_pvrt": {
+ "days": "Days",
+ "rate": "PVRT Rate"
+ },
+ "ca_gst_all_if_null": "If the Job is marked as a \"GST Registrant\" and this value is set to $0, the customer will be responsible for paying all of the GST by default. ",
+ "calc_repair_days": "Calculated Repair Days",
+ "calc_repair_days_tt": "This is the approximate number of days required to complete the repair according to the target touch time in your shop configuration (current set to {{target_touchtime}}).",
+ "calc_scheuled_completion": "Calculate Scheduled Completion",
+ "cards": {
+ "customer": "Customer Information",
+ "damage": "Area of Damage",
+ "dates": "Dates",
+ "documents": "Recent Documents",
+ "estimator": "Estimator",
+ "filehandler": "Adjuster",
+ "insurance": "Insurance Details",
+ "more": "More",
+ "notes": "Notes",
+ "parts": "Parts",
+ "totals": "Totals",
+ "vehicle": "Vehicle"
+ },
+ "changeclass": "Changing the Job's class can have fundamental impacts to already exported accounting items. Are you sure you want to do this?",
+ "checklistcompletedby": "Checklist completed by {{by}} at {{at}}",
+ "checklistdocuments": "Checklist Documents",
+ "checklists": "Checklists",
+ "cieca_pfl": "Profile - Labor",
+ "cieca_pfo": "Profile - Other",
+ "cieca_pft": "Profile - Taxes",
+ "closeconfirm": "Are you sure you want to close this job? This cannot be easily undone.",
+ "closejob": "Close Job {{ro_number}}",
+ "closingperiod": "This Invoice Date is outside of the Closing Period.",
+ "contracts": "CC Contracts",
+ "convertedtolabor": "Labor Line Adjustments",
+ "cost": "Cost",
+ "cost_Additional": "Cost - Additional",
+ "cost_labor": "Cost - Labor",
+ "cost_parts": "Cost - Parts",
+ "cost_sublet": "Cost - Sublet",
+ "costs": "Costs",
+ "create": {
+ "jobinfo": "Job Info",
+ "newowner": "Create a new Owner instead. ",
+ "newvehicle": "Create a new Vehicle Instead",
+ "novehicle": "No vehicle (only for ROs to track parts/labor only work).",
+ "ownerinfo": "Owner Info",
+ "vehicleinfo": "Vehicle Info"
+ },
+ "createiouwarning": "Are you sure you want to create an IOU for these lines? A new RO will be created based on those lines for this customer.",
+ "creating_new_job": "Creating new Job...",
+ "deductible": {
+ "stands": "Stands",
+ "waived": "Waived"
+ },
+ "deleteconfirm": "Are you sure you want to delete this Job? This cannot be undone. ",
+ "deletedelivery": "Delete Delivery Checklist",
+ "deleteintake": "Delete Intake Checklist",
+ "deliverchecklist": "Deliver Checklist",
+ "difference": "Difference",
+ "diskscan": "Scan Disk for Estimates",
+ "dms": {
+ "apexported": "AP export completed. See logs for details.",
+ "damageto": "Damage to $t(jobs.fields.area_of_damage_impact.{{area_of_damage}}).",
+ "defaultstory": "B/S RO: {{ro_number}}. Owner: {{ownr_nm}}. Insurance Co: {{ins_co_nm}}. Claim/PO #: {{clm_po}}",
+ "disablebillwip": "Cost and WIP for bills has been ignored per shop configuration.",
+ "invoicedatefuture": "Invoice date must be today or in the future for CDK posting.",
+ "kmoutnotgreaterthankmin": "Mileage out must be greater than mileage in.",
+ "logs": "Logs",
+ "notallocated": "Not Allocated",
+ "postingform": "Posting Form",
+ "totalallocated": "Total Amount Allocated"
+ },
+ "documents": "Documents",
+ "documents-images": "Images",
+ "documents-other": "Other Documents",
+ "duplicateconfirm": "Are you sure you want to duplicate this Job? Some elements of this Job will not be duplicated.",
+ "emailaudit": "Email Audit Trail",
+ "employeeassignments": "Employee Assignments",
+ "estimatelines": "Estimate Lines",
+ "estimator": "Estimator",
+ "existing_jobs": "Existing Jobs",
+ "federal_tax_amt": "Federal Taxes",
+ "gpdollars": "$ G.P.",
+ "gppercent": "% G.P.",
+ "hrs_claimed": "Hours Flagged",
+ "hrs_total": "Hours Total",
+ "importnote": "The Job was initially imported.",
+ "inproduction": "In Production",
+ "intakechecklist": "Intake Checklist",
+ "iou": "IOU",
+ "job": "Job Details",
+ "jobcosting": "Job Costing",
+ "jobtotals": "Job Totals",
+ "labor_hrs": "B/P/T Hrs",
+ "labor_rates_subtotal": "Labor Rates Subtotal",
+ "laborallocations": "Labor Allocations",
+ "labortotals": "Labor Totals",
+ "lines": "Estimate Lines",
+ "local_tax_amt": "Local Taxes",
+ "mapa": "Paint Materials",
+ "markforreexport": "Mark for Re-export",
+ "mash": "Shop Materials",
+ "masterbypass": "Master Bypass Password",
+ "materials": {
+ "mapa": ""
+ },
+ "missingprofileinfo": "This job has missing tax profile info. To ensure correct totals calculations, re-import the job.",
+ "multipayers": "Additional Payers",
+ "net_repairs": "Net Repairs",
+ "notes": "Notes",
+ "othertotal": "Other Totals",
+ "outstanding_ar": "A balance is outstanding on this RO. Payments can still be entered when the job is closed. ",
+ "outstanding_credit_memos": "Outstanding credit memos have not been entered against this job. Credit Memos may still be posted once the job is closed.",
+ "outstanding_ppd": "There are outstanding PPDs that may not have been synced back to the estimate.",
+ "outstanding_reconciliation_discrep": "At least one discrepancy is not $0. This may indicate that this job is not properly reconciled and should not be closed.",
+ "outstanding_sublets": "There are sublet lines on the job which have not been marked as completed. ",
+ "outstandinghours": "There are outstanding hours on the job that have not been paid or have been overpaid.",
+ "override_header": "Override estimate header on import?",
+ "ownerassociation": "Owner Association",
+ "parts": "Parts",
+ "parts_lines": "Parts Lines",
+ "parts_received": "Parts Rec.",
+ "parts_tax_rates": "Profile - Parts",
+ "partsfilter": "Parts Only",
+ "partssubletstotal": "Parts & Sublets Total",
+ "partstotal": "Parts Total (ex. Taxes)",
+ "performance": "Performance",
+ "pimraryamountpayable": "Total Primary Payable",
+ "plitooltips": {
+ "billtotal": "The total amount of all bill lines that have been posted against this RO (not including credits, taxes, or labor adjustments).",
+ "calculatedcreditsnotreceived": "The calculated credits not received is derived by subtracting the amount of credit memos entered from the retail total of returns created. This does not take into account whether the credit was marked as received. You can find more information here .",
+ "creditmemos": "The total retail amount of all returns created. This amount does not reflect credit memos that have been posted.",
+ "creditsnotreceived": "This total reflects the total retail of parts returns lines that have not been explicitly marked as returned when posting a credit memo. You can learn more about this here here . ",
+ "discrep1": "If the discrepancy is not $0, you may have one of the following: \n\n\nToo many bills/bill lines that have been posted against this RO. Check to make sure every bill posted on this RO is correctly posted and assigned. \nYou do not have the latest supplement imported, or, a supplement must be submitted and then imported. \nYou have posted a bill line to labor. \n \n \nThere may be additional issues not listed above that prevent this Job from reconciling. ",
+ "discrep2": "If the discrepancy is not $0, you may have one of the following: \n\n\nUsed an incorrect rate when deducting from labor. \nAn outstanding imbalance higher in the reconciliation process. \n \n \nThere may be additional issues not listed above that prevent this Job from reconciling. ",
+ "discrep3": "If the discrepancy is not $0, you may have one of the following: \n\n\nA parts order return has not been created. \nAn outstanding imbalance higher in the reconciliation process. \n \n \nThere may be additional issues not listed above that prevent this Job from reconciling. ",
+ "laboradj": "The sum of all bill lines that deducted from labor hours, rather than part prices.",
+ "partstotal": "This is the total of all parts and sublet amounts on the vehicle (some of these may require an in-house invoice). \nItems such as shop and paint materials, labor online lines, etc. are not included in this total.",
+ "totalreturns": "The total retail amount of returns created for this job."
+ },
+ "ppc": "This line contains a part price change.",
+ "ppdnotexported": "PPDs not Exported",
+ "profileadjustments": "Profile Disc./Mkup",
+ "profitbypassrequired": "Minimum gross profit requirements have not been met.",
+ "profits": "Job Profits",
+ "prt_dsmk_total": "Line Item Adjustment",
+ "rates": "Rates",
+ "rates_subtotal": "All Rates Subtotal",
+ "reconciliation": {
+ "billlinestotal": "Bill Lines Total",
+ "byassoc": "By Line Association",
+ "byprice": "By Price",
+ "clear": "Clear All",
+ "discrepancy": "Discrepancy",
+ "joblinestotal": "Job Lines Total",
+ "multipleactprices": "${{act_price}} is the price for multiple job lines.",
+ "multiplebilllines": "{{line_desc}} has 2 or more bill lines associated to it.",
+ "multiplebillsforactprice": "Found more than 1 bill matching ${{act_price}} retail price.",
+ "removedpartsstrikethrough": "Strike through lines represent parts that have been removed from the estimate. They are included for completeness of reconciliation."
+ },
+ "reconciliationheader": "Parts & Sublet Reconciliation",
+ "relatedros": "Related ROs",
+ "remove_from_ar": "Remove from AR",
+ "returntotals": "Return Totals",
+ "ro_guard": {
+ "enforce_ar": "AR collection enforced.",
+ "enforce_bills": "Bill discrepancy enforced.",
+ "enforce_cm": "Credit memo entry enforced.",
+ "enforce_labor": "Labor allocations enforced.",
+ "enforce_ppd": "PPD sync enforced.",
+ "enforce_profit": "Profit marginsenforced.",
+ "enforce_sublet": "Sublet completion enforced.",
+ "enforce_validation": "Master Bypass Required: {{message}}",
+ "enforced": "This check has been enforced by your shop manager. Enter the master bypass password to close the Job."
+ },
+ "roguard": "RO Guard",
+ "roguardwarnings": "RO Guard Warnings",
+ "rosaletotal": "RO Parts Total",
+ "sale_additional": "Sales - Additional",
+ "sale_labor": "Sales - Labor",
+ "sale_parts": "Sales - Parts",
+ "sale_sublet": "Sales - Sublet",
+ "sales": "Sales",
+ "savebeforeconversion": "You have unsaved changes on the Job. Please save them before converting it. ",
+ "scheduledinchange": "The scheduled in is based off the latest appointment. To change this date, please schedule or reschedule the Job. ",
+ "specialcoveragepolicy": "Special Coverage Policy Applies",
+ "state_tax_amt": "Provincial/State Taxes",
+ "subletsnotcompleted": "Outstanding Sublets",
+ "subletstotal": "Sublets Total",
+ "subtotal": "Subtotal",
+ "supplementnote": "The Job had a supplement imported.",
+ "suspended": "SUSPENDED",
+ "suspense": "Suspense",
+ "tasks": "Tasks",
+ "threshhold": "Max Threshold: ${{amount}}",
+ "total_cost": "Total Cost",
+ "total_cust_payable": "Total Customer Amount Payable",
+ "total_cust_payable_cash_discount": "$t(jobs.labels.total_cust_payable) (Cash Discounted)",
+ "total_repairs": "Total Repairs",
+ "total_repairs_cash_discount": "Total Repairs (Cash Discounted)",
+ "total_sales": "Total Sales",
+ "total_sales_tax": "Total Sales Tax",
+ "totals": "Totals",
+ "unvoidnote": "This Job was unvoided.",
+ "update_scheduled_completion": "Update Scheduled Completion?",
+ "vehicle_info": "Vehicle",
+ "vehicleassociation": "Vehicle Association",
+ "viewallocations": "View Allocations",
+ "voidjob": "Are you sure you want to void this Job? This cannot be easily undone. ",
+ "voidnote": "This Job was voided."
+ },
+ "successes": {
+ "addedtoproduction": "Job added to production board.",
+ "all_deleted": "{{count}} Jobs deleted successfully.",
+ "closed": "Job closed successfully.",
+ "converted": "Job converted successfully.",
+ "created": "Job created successfully. Click to view.",
+ "creatednoclick": "Job created successfully. ",
+ "delete": "Job deleted successfully.",
+ "deleted": "Job deleted successfully.",
+ "duplicated": "Job duplicated successfully. ",
+ "exported": "Job(s) exported successfully. ",
+ "invoiced": "Job closed and invoiced successfully.",
+ "ioucreated": "IOU created successfully. Click to see.",
+ "partsqueue": "Job added to parts queue.",
+ "save": "Job saved successfully.",
+ "savetitle": "Record saved successfully.",
+ "supplemented": "Job supplemented successfully. ",
+ "updated": "Job(s) updated successfully.",
+ "voided": "Job voided successfully."
+ }
+ },
+ "landing": {
+ "bigfeature": {
+ "subtitle": "Rome Online is built using world class technology by experts in the collision repair industry. This translates to software that is tailor made for the unique challenges faced by repair facilities with no compromises. ",
+ "title": "Bringing the latest technology to the automotive repair industry. "
+ },
+ "footer": {
+ "company": {
+ "about": "About Us",
+ "contact": "Contact",
+ "disclaimers": "Disclaimers",
+ "name": "Company",
+ "privacypolicy": "Privacy Policy"
+ },
+ "io": {
+ "help": "Help",
+ "name": "Rome Online",
+ "status": "System Status"
+ },
+ "slogan": "Rome Technologies. is a technology leader in the collision repair industry. We specialize in creating collision repair management systems and bodyshop management systems that lower cycle times and promote efficiency."
+ },
+ "hero": {
+ "button": "Learn More",
+ "title": "Shop management reimagined."
+ },
+ "labels": {
+ "features": "Features",
+ "managemyshop": "Sign In",
+ "pricing": "Pricing"
+ },
+ "pricing": {
+ "basic": {
+ "name": "Basic",
+ "sub": "Best suited for shops looking to increase their volume."
+ },
+ "essentials": {
+ "name": "Essentials",
+ "sub": "Best suited for small and low volume shops."
+ },
+ "pricingtitle": "Features",
+ "pro": {
+ "name": "Pro",
+ "sub": "Empower your shop with the tools to operate at peak capacity."
+ },
+ "title": "Features",
+ "unlimited": {
+ "name": "Unlimited",
+ "sub": "Everything you need and more for the high volume shop."
+ }
+ }
+ },
+ "menus": {
+ "currentuser": {
+ "languageselector": "Language",
+ "profile": "Profile"
+ },
+ "header": {
+ "accounting": "Accounting",
+ "accounting-payables": "Payables",
+ "accounting-payments": "Payments",
+ "accounting-receivables": "Receivables",
+ "activejobs": "Active Jobs",
+ "all_tasks": "All Tasks",
+ "alljobs": "All Jobs",
+ "allpayments": "All Payments",
+ "availablejobs": "Available Jobs",
+ "bills": "Bills",
+ "courtesycars": "Courtesy Cars",
+ "courtesycars-all": "All Courtesy Cars",
+ "courtesycars-contracts": "Contracts",
+ "courtesycars-newcontract": "New Contract",
+ "create_task": "Create Task",
+ "customers": "Customers",
+ "dashboard": "Dashboard",
+ "enterbills": "Enter Bills",
+ "entercardpayment": "New Card Charge",
+ "enterpayment": "Enter Payments",
+ "entertimeticket": "Enter Time Tickets",
+ "export": "Export",
+ "export-logs": "Export Logs",
+ "help": "Help",
+ "home": "Home",
+ "inventory": "Inventory",
+ "jobs": "Jobs",
+ "my_tasks": "My Tasks",
+ "newjob": "Create New Job",
+ "owners": "Owners",
+ "parts-queue": "Parts Queue",
+ "phonebook": "Phonebook",
+ "productionboard": "Production Board - Visual",
+ "productionlist": "Production Board - List",
+ "readyjobs": "Ready Jobs",
+ "recent": "Recent Items",
+ "reportcenter": "Report Center",
+ "rescueme": "Rescue me!",
+ "schedule": "Schedule",
+ "scoreboard": "Scoreboard",
+ "search": {
+ "bills": "Bills",
+ "jobs": "Jobs",
+ "owners": "Owners",
+ "payments": "Payments",
+ "phonebook": "Phonebook",
+ "vehicles": "Vehicles"
+ },
+ "shiftclock": "Shift Clock",
+ "shop": "My Shop",
+ "shop_config": "Configuration",
+ "shop_csi": "CSI",
+ "shop_templates": "Templates",
+ "shop_vendors": "Vendors",
+ "tasks": "Tasks",
+ "temporarydocs": "Temporary Documents",
+ "timetickets": "Time Tickets",
+ "ttapprovals": "Time Ticket Approvals",
+ "vehicles": "Vehicles"
+ },
+ "jobsactions": {
+ "admin": "Admin",
+ "cancelallappointments": "Cancel all appointments",
+ "closejob": "Close Job",
+ "deletejob": "Delete Job",
+ "duplicate": "Duplicate this Job",
+ "duplicatenolines": "Duplicate this Job without Repair Data",
+ "newcccontract": "Create Courtesy Car Contract",
+ "void": "Void Job"
+ },
+ "jobsdetail": {
+ "claimdetail": "Claim Details",
+ "dates": "Dates",
+ "financials": "Financial Information",
+ "general": "General",
+ "insurance": "Insurance Information",
+ "labor": "Labor",
+ "lifecycle": "Lifecycle",
+ "parts": "Parts",
+ "partssublet": "Parts & Bills",
+ "rates": "Rates",
+ "repairdata": "Repair Data",
+ "totals": "Totals"
+ },
+ "profilesidebar": {
+ "profile": "My Profile",
+ "shops": "My Shops"
+ },
+ "tech": {
+ "assignedjobs": "Assigned Jobs",
+ "claimtask": "Flag Hours",
+ "dispatchedparts": "Dispatched Parts",
+ "home": "Home",
+ "jobclockin": "Job Clock In",
+ "jobclockout": "Job Clock Out",
+ "joblookup": "Job Lookup",
+ "login": "Login",
+ "logout": "Logout",
+ "productionboard": "Production Visual",
+ "productionlist": "Production List",
+ "shiftclockin": "Shift Clock"
+ }
+ },
+ "messaging": {
+ "actions": {
+ "link": "Link to Job",
+ "new": "New Conversation"
+ },
+ "errors": {
+ "invalidphone": "The phone number is invalid. Unable to open conversation. ",
+ "noattachedjobs": "No Jobs have been associated to this conversation. ",
+ "updatinglabel": "Error updating label. {{error}}"
+ },
+ "labels": {
+ "addlabel": "Add a label to this conversation.",
+ "archive": "Archive",
+ "maxtenimages": "You can only select up to a maximum of 10 images at a time.",
+ "messaging": "Messaging",
+ "noallowtxt": "This customer has not indicated their permission to be messaged.",
+ "nojobs": "Not associated to any Job.",
+ "nopush": "Polling Mode Enabled",
+ "phonenumber": "Phone #",
+ "presets": "Presets",
+ "recentonly": "Only your most recent 50 conversations will be shown here. If you are looking for an older conversation, find the related contact and click their phone number to view the conversation.",
+ "selectmedia": "Select Media",
+ "sentby": "Sent by {{by}} at {{time}}",
+ "typeamessage": "Send a message...",
+ "unarchive": "Unarchive"
+ },
+ "render": {
+ "conversation_list": "Conversation List"
+ }
+ },
+ "notes": {
+ "actions": {
+ "actions": "Actions",
+ "deletenote": "Delete Note",
+ "edit": "Edit Note",
+ "new": "New Note",
+ "savetojobnotes": "Save to Job Notes"
+ },
+ "errors": {
+ "inserting": "Error inserting note. {{error}}"
+ },
+ "fields": {
+ "createdby": "Created By",
+ "critical": "Critical",
+ "private": "Private",
+ "text": "Contents",
+ "type": "Type",
+ "types": {
+ "customer": "Customer",
+ "general": "General",
+ "office": "Office",
+ "paint": "Paint",
+ "parts": "Parts",
+ "shop": "Shop",
+ "supplement": "Supplement"
+ },
+ "updatedat": "Updated At"
+ },
+ "labels": {
+ "addtorelatedro": "Add to Related ROs",
+ "newnoteplaceholder": "Add a note...",
+ "notetoadd": "Note to Add",
+ "systemnotes": "System Notes",
+ "usernotes": "User Notes"
+ },
+ "successes": {
+ "create": "Note created successfully.",
+ "deleted": "Note deleted successfully.",
+ "updated": "Note updated successfully."
+ }
+ },
+ "owner": {
+ "labels": {
+ "noownerinfo": "No owner information."
+ }
+ },
+ "owners": {
+ "actions": {
+ "update": "Update Selected Records"
+ },
+ "errors": {
+ "deleting": "Error deleting owner. {{error}}.",
+ "noaccess": "The record does not exist or you do not have access to it. ",
+ "saving": "Error saving owner. {{error}}.",
+ "selectexistingornew": "Select an existing owner record or create a new one. "
+ },
+ "fields": {
+ "accountingid": "Accounting ID",
+ "address": "Address",
+ "allow_text_message": "Permission to Text?",
+ "name": "Name",
+ "note": "Owner Note",
+ "ownr_addr1": "Address",
+ "ownr_addr2": "Address 2",
+ "ownr_city": "City",
+ "ownr_co_nm": "Owner Co. Name",
+ "ownr_ctry": "Country",
+ "ownr_ea": "Email",
+ "ownr_fn": "First Name",
+ "ownr_ln": "Last Name",
+ "ownr_ph1": "Phone 1",
+ "ownr_ph2": "Phone 2",
+ "ownr_st": "Province/State",
+ "ownr_title": "Title",
+ "ownr_zip": "Zip/Postal Code",
+ "preferred_contact": "Preferred Contact Method",
+ "tax_number": "Tax Number"
+ },
+ "forms": {
+ "address": "Address",
+ "contact": "Contact Information",
+ "name": "Owner Details"
+ },
+ "labels": {
+ "create_new": "Create a new owner record.",
+ "deleteconfirm": "Are you sure you want to delete this owner? This cannot be undone.",
+ "existing_owners": "Existing Owners",
+ "fromclaim": "Current Claim",
+ "fromowner": "Historical Owner Record",
+ "relatedjobs": "Related Jobs",
+ "updateowner": "Update Owner"
+ },
+ "successes": {
+ "delete": "Owner deleted successfully.",
+ "save": "Owner saved successfully."
+ }
+ },
+ "parts": {
+ "actions": {
+ "order": "Order Parts",
+ "orderinhouse": "Order as In House"
+ }
+ },
+ "parts_dispatch": {
+ "actions": {
+ "accept": "Accept"
+ },
+ "errors": {
+ "accepting": "Error accepting parts dispatch. {{error}}",
+ "creating": "Error dispatching parts. {{error}}"
+ },
+ "fields": {
+ "number": "Number",
+ "percent_accepted": "% Accepted"
+ },
+ "labels": {
+ "notyetdispatched": "This part has not been dispatched.",
+ "parts_dispatch": "Parts Dispatch"
+ }
+ },
+ "parts_dispatch_lines": {
+ "fields": {
+ "accepted_at": "Accepted At"
+ }
+ },
+ "parts_orders": {
+ "actions": {
+ "backordered": "Mark Backordered",
+ "receive": "Receive",
+ "receivebill": "Receive Bill"
+ },
+ "errors": {
+ "associatedbills": "This parts order cannot",
+ "backordering": "Error backordering part {{message}}.",
+ "creating": "Error encountered when creating parts order. ",
+ "oec": "Error creating EMS files for parts order. {{error}}",
+ "saving": "Error saving parts order. {{error}}.",
+ "updating": "Error updating parts order/parts order line. {{error}}."
+ },
+ "fields": {
+ "act_price": "Price",
+ "backordered_eta": "B.O. ETA",
+ "backordered_on": "B.O. On",
+ "cm_received": "CM Received?",
+ "comments": "Comments",
+ "cost": "Cost",
+ "db_price": "List Price",
+ "deliver_by": "Deliver By",
+ "job_line_id": "Job Line Id",
+ "line_desc": "Line Description",
+ "line_remarks": "Remarks",
+ "lineremarks": "Line Remarks",
+ "oem_partno": "Part #",
+ "order_date": "Order Date",
+ "order_number": "Order Number",
+ "orderedby": "Ordered By",
+ "part_type": "Type",
+ "quantity": "Qty.",
+ "return": "Return",
+ "status": "Status"
+ },
+ "labels": {
+ "allpartsto": "All Parts Location",
+ "confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. Job line statuses will not be updated and may require manual review. ",
+ "custompercent": "Custom %",
+ "discount": "Discount {{percent}}",
+ "email": "Send by Email",
+ "inthisorder": "Parts in this Order",
+ "is_quote": "Parts Quote?",
+ "mark_as_received": "Mark as Received?",
+ "newpartsorder": "New Parts Order",
+ "notyetordered": "This part has not yet been ordered.",
+ "oec": "Order via EMS",
+ "order_type": "Order Type",
+ "orderhistory": "Order History",
+ "parts_order": "Parts Order",
+ "parts_orders": "Parts Orders",
+ "parts_returns": "Parts Returns",
+ "print": "Show Printed Form",
+ "receive": "Receive Parts Order",
+ "removefrompartsqueue": "Unqueue from Parts Queue?",
+ "returnpartsorder": "Return Parts Order",
+ "sublet_order": "Sublet Order"
+ },
+ "successes": {
+ "created": "Parts order created successfully. ",
+ "line_updated": "Parts return line updated.",
+ "received": "Parts order received.",
+ "return_created": "Parts return created successfully."
+ }
+ },
+ "payments": {
+ "actions": {
+ "generatepaymentlink": "Generate Payment Link"
+ },
+ "errors": {
+ "exporting": "Error exporting payment(s). {{error}}",
+ "exporting-partner": "Error exporting to partner. Please check the partner interaction log for more errors.",
+ "inserting": "Error inserting payment. {{error}}"
+ },
+ "fields": {
+ "amount": "Amount",
+ "created_at": "Created At",
+ "date": "Payment Date",
+ "exportedat": "Exported At",
+ "memo": "Memo",
+ "payer": "Payer",
+ "paymentnum": "Payment Number",
+ "stripeid": "Stripe ID",
+ "transactionid": "Transaction ID",
+ "type": "Type"
+ },
+ "labels": {
+ "balance": "Balance",
+ "ca_bc_etf_table": "ICBC EFT Table Converter",
+ "customer": "Customer",
+ "edit": "Edit Payment",
+ "electronicpayment": "Use Electronic Payment Processing?",
+ "external": "External",
+ "findermodal": "ICBC Payment Finder",
+ "insurance": "Insurance",
+ "markexported": "Mark Exported",
+ "markforreexport": "Mark for Re-export",
+ "new": "New Payment",
+ "signup": "Please contact support to sign up for electronic payments.",
+ "smspaymentreminder": "This is {{shopname}} reminding you about your balance of {{amount}}. To pay, click the following link {{payment_link}}.",
+ "title": "Payments",
+ "totalpayments": "Total Payments"
+ },
+ "successes": {
+ "exported": "Payment(s) exported successfully.",
+ "markexported": "Payment(s) marked exported.",
+ "markreexported": "Payment marked for re-export successfully",
+ "payment": "Payment created successfully. ",
+ "paymentupdate": "Payment updated successfully. ",
+ "stripe": "Credit card transaction charged successfully."
+ }
+ },
+ "phonebook": {
+ "actions": {
+ "new": "New Phonebook Entry"
+ },
+ "errors": {
+ "adding": "Error adding phonebook entry. {{error}}",
+ "saving": "Error saving phonebook entry. {{error}}"
+ },
+ "fields": {
+ "address1": "Street 1",
+ "address2": "Street 2",
+ "category": "Category",
+ "city": "City",
+ "company": "Company",
+ "country": "Country",
+ "email": "Email",
+ "fax": "Fax",
+ "firstname": "First Name",
+ "lastname": "Last Name",
+ "phone1": "Phone 1",
+ "phone2": "Phone 2",
+ "state": "Province/State"
+ },
+ "labels": {
+ "noneselected": "No phone book entry selected. ",
+ "onenamerequired": "At least one name related field is required.",
+ "vendorcategory": "Vendor"
+ },
+ "successes": {
+ "added": "Phonebook entry added successfully. ",
+ "deleted": "Phonebook entry deleted successfully. ",
+ "saved": "Phonebook entry saved successfully. "
+ }
+ },
+ "printcenter": {
+ "appointments": {
+ "appointment_confirmation": "Appointment Confirmation"
+ },
+ "bills": {
+ "inhouse_invoice": "In House Invoice"
+ },
+ "courtesycarcontract": {
+ "courtesy_car_contract": "Courtesy Car Contract",
+ "courtesy_car_impound": "Impound Charges",
+ "courtesy_car_inventory": "Courtesy Car Inventory",
+ "courtesy_car_terms": "Courtesy Car Terms"
+ },
+ "errors": {
+ "nocontexttype": "No context type set."
+ },
+ "jobs": {
+ "3rdpartyfields": {
+ "addr1": "Address 1",
+ "addr2": "Address 2",
+ "addr3": "Address 3",
+ "attn": "Attention",
+ "city": "City",
+ "custgst": "Customer Portion of GST",
+ "ded_amt": "Deductible",
+ "depreciation": "Depreciation",
+ "other": "Other",
+ "ponumber": "PO Number",
+ "refnumber": "Reference Number",
+ "sendtype": "Send by",
+ "state": "Province/State",
+ "zip": "Postal Code/Zip"
+ },
+ "3rdpartypayer": "Invoice to Third Party Payer",
+ "ab_proof_of_loss": "AB - Proof of Loss",
+ "appointment_confirmation": "Appointment Confirmation",
+ "appointment_reminder": "Appointment Reminder",
+ "casl_authorization": "CASL Authorization",
+ "committed_timetickets_ro": "Committed Time Tickets",
+ "coversheet_landscape": "Coversheet (Landscape)",
+ "coversheet_portrait": "Coversheet Portrait",
+ "csi_invitation": "CSI Invitation",
+ "csi_invitation_action": "CSI Invite",
+ "diagnostic_authorization": "Diagnostic Authorization",
+ "dms_posting_sheet": "DMS Posting Sheet",
+ "envelope_return_address": "#10 Envelope Return Address Label",
+ "estimate": "Estimate Only",
+ "estimate_detail": "Estimate Details",
+ "estimate_followup": "Estimate Followup",
+ "express_repair_checklist": "Express Repair Checklist",
+ "filing_coversheet_landscape": "Filing Coversheet (Landscape)",
+ "filing_coversheet_portrait": "Filing Coversheet (Portrait)",
+ "final_invoice": "Final Invoice",
+ "fippa_authorization": "FIPPA Authorization",
+ "folder_label_multiple": "Folder Label - Multi",
+ "glass_express_checklist": "Glass Express Checklist",
+ "guarantee": "Repair Guarantee",
+ "individual_job_note": "RO Job Note",
+ "invoice_customer_payable": "Invoice (Customer Payable)",
+ "invoice_total_payable": "Invoice (Total Payable)",
+ "iou_form": "IOU Form",
+ "job_costing_ro": "Job Costing",
+ "job_lifecycle_ro": "Job Lifecycle",
+ "job_notes": "Job Notes",
+ "job_tasks": "Job Tasks",
+ "key_tag": "Key Tag",
+ "labels": {
+ "count": "Count",
+ "labels": "Labels",
+ "position": "Starting Position"
+ },
+ "lag_time_ro": "Lag Time",
+ "mechanical_authorization": "Mechanical Authorization",
+ "mpi_animal_checklist": "MPI - Animal Checklist",
+ "mpi_eglass_auth": "MPI - eGlass Auth",
+ "mpi_final_acct_sheet": "MPI - Final Accounting Sheet (Direct Repair)",
+ "mpi_final_repair_acct_sheet": "MPI - Final Accounting Sheet",
+ "paint_grid": "Paint Grid",
+ "parts_dispatch": "Parts Dispatch",
+ "parts_invoice_label_single": "Parts Label Single",
+ "parts_label_multiple": "Parts Label - Multi",
+ "parts_label_single": "Parts Label - Single",
+ "parts_list": "Parts List",
+ "parts_order": "Parts Order Confirmation",
+ "parts_order_confirmation": "",
+ "parts_order_history": "Parts Order History",
+ "parts_return_slip": "Parts Return Slip",
+ "payment_receipt": "Payment Receipt",
+ "payment_request": "Payment Request",
+ "payments_by_job": "Job Payments",
+ "purchases_by_ro_detail": "Purchases - Detail",
+ "purchases_by_ro_summary": "Purchases - Summary",
+ "qc_sheet": "Quality Control Sheet",
+ "rental_reservation": "Rental Reservation",
+ "ro_totals": "RO Totals",
+ "ro_with_description": "RO Summary with Descriptions",
+ "sgi_certificate_of_repairs": "SGI - Certificate of Repairs",
+ "sgi_windshield_auth": "SGI - Windshield Authorization",
+ "stolen_recovery_checklist": "Stolen Recovery Checklist",
+ "sublet_order": "Sublet Order",
+ "supplement_request": "Supplement Request",
+ "thank_you_ro": "Thank You Letter",
+ "thirdpartypayer": "Third Party Payer",
+ "timetickets_ro": "Time Tickets",
+ "vehicle_check_in": "Vehicle Intake",
+ "vehicle_delivery_check": "Vehicle Delivery Checklist",
+ "window_tag": "Window Tag",
+ "window_tag_sublet": "Window Tag - Sublet",
+ "work_authorization": "Work Authorization",
+ "worksheet_by_line_number": "Worksheet by Line Number",
+ "worksheet_sorted_by_operation": "Worksheet by Operation",
+ "worksheet_sorted_by_operation_no_hours": "Worksheet by Operation (No Hours)",
+ "worksheet_sorted_by_operation_part_type": "Worksheet by Operation & Part Type",
+ "worksheet_sorted_by_operation_type": "Worksheet by Operation Type",
+ "worksheet_sorted_by_team": "Worksheet by Team"
+ },
+ "labels": {
+ "groups": {
+ "authorization": "Authorization",
+ "financial": "Financial",
+ "post": "Post-Production",
+ "pre": "Pre-Production",
+ "ro": "Repair Order",
+ "worksheet": "Worksheets"
+ },
+ "misc": "Miscellaneous Documents",
+ "repairorder": "Repair Order Related",
+ "reportcentermodal": "Report Center",
+ "speedprint": "Speed Print",
+ "title": "Print Center"
+ },
+ "payments": {
+ "ca_bc_etf_table": "ICBC EFT Table",
+ "exported_payroll": "Payroll Table"
+ },
+ "special": {
+ "attendance_detail_csv": "Attendance Table"
+ },
+ "subjects": {
+ "jobs": {
+ "individual_job_note": "Job Note RO: {{ro_number}}",
+ "parts_dispatch": "Parts Dispatch RO: {{ro_number}}",
+ "parts_order": "Parts Order PO: {{ro_number}} - {{name}}",
+ "parts_return_slip": "Parts Return PO: {{ro_number}} - {{name}}",
+ "sublet_order": "Sublet Order PO: {{ro_number}} - {{name}}"
+ }
+ },
+ "vendors": {
+ "purchases_by_vendor_detailed": "Purchases by Vendor - Detailed",
+ "purchases_by_vendor_summary": "Purchases by Vendor - Summary"
+ }
+ },
+ "production": {
+ "actions": {
+ "addcolumns": "Add Columns",
+ "bodypriority-clear": "Clear Body Priority",
+ "bodypriority-set": "Set Body Priority",
+ "detailpriority-clear": "Clear Detail Priority",
+ "detailpriority-set": "Set Detail Priority",
+ "paintpriority-clear": "Clear Paint Priority",
+ "paintpriority-set": "Set Paint Priority",
+ "remove": "Remove from Production",
+ "removecolumn": "Remove Column",
+ "saveconfig": "Save Configuration",
+ "suspend": "Suspend",
+ "unsuspend": "Unsuspend"
+ },
+ "constants": {
+ "main_profile": "Default"
+ },
+ "errors": {
+ "boardupdate": "Error encountered updating Job. {{message}}",
+ "name_exists": "A Profile with this name already exists. Please choose a different name.",
+ "name_required": "Profile name is required.",
+ "removing": "Error removing from production board. {{error}}",
+ "settings": "Error saving board settings: {{error}}"
+ },
+ "labels": {
+ "actual_in": "Actual In",
+ "addnewprofile": "Add New Profile",
+ "alert": "Alert",
+ "alertoff": "Remove alert from Job",
+ "alerton": "Add alert to Job",
+ "alerts": "Alerts",
+ "ats": "Alternative Transportation",
+ "bodyhours": "B",
+ "bodypriority": "B/P",
+ "bodyshop": {
+ "labels": {
+ "qbo_departmentid": "QBO Department ID",
+ "qbo_usa": "QBO USA"
+ }
+ },
+ "card_size": "Card Size",
+ "cardcolor": "Colored Cards",
+ "cardsettings": "Card Settings",
+ "clm_no": "Claim Number",
+ "comment": "Comment",
+ "compact": "Compact Cards",
+ "detailpriority": "D/P",
+ "employeeassignments": "Employee Assignments",
+ "employeesearch": "Employee Search",
+ "estimator": "Estimator",
+ "horizontal": "Horizontal",
+ "ins_co_nm": "Insurance Company Name",
+ "jobdetail": "Job Details",
+ "kiosk_mode": "Kiosk Mode",
+ "laborhrs": "Labor Hours",
+ "legend": "Legend:",
+ "model_info": "Vehicle Info",
+ "note": "Production Note",
+ "off": "Off",
+ "on": "On",
+ "orientation": "Board Orientation",
+ "ownr_nm": "Customer Name",
+ "paintpriority": "P/P",
+ "partsstatus": "Parts Status",
+ "production_note": "Production Note",
+ "refinishhours": "R",
+ "scheduled_completion": "Scheduled Completion",
+ "selectview": "Select a View",
+ "stickyheader": "Sticky Header (BETA)",
+ "sublets": "Sublets",
+ "subtotal": "Subtotal",
+ "tall": "Tall",
+ "tasks": "Tasks",
+ "totalhours": "Total Hrs ",
+ "touchtime": "T/T",
+ "unassigned": "Unassigned",
+ "vertical": "Vertical",
+ "viewname": "View Name",
+ "wide": "Wide"
+ },
+ "options": {
+ "horizontal": "Horizontal",
+ "large": "Large",
+ "medium": "Medium",
+ "small": "Small",
+ "vertical": "Vertical"
+ },
+ "settings": {
+ "board_settings": "Board Settings",
+ "filters": {
+ "md_estimators": "Estimators",
+ "md_ins_cos": "Insurance Companies"
+ },
+ "filters_title": "Filters",
+ "information": "Information",
+ "layout": "Layout",
+ "statistics": {
+ "jobs_in_production": "Jobs in Production",
+ "tasks_in_production": "Tasks in Production",
+ "tasks_in_view": "Tasks in View",
+ "tasks_on_board": "Tasks on Board",
+ "total_amount_in_production": "Dollars in Production",
+ "total_amount_in_view": "Dollars in View",
+ "total_amount_on_board": "Dollars on Board",
+ "total_hours_in_production": "Hours in Production",
+ "total_hours_in_view": "Hours in View",
+ "total_hours_on_board": "Hours on Board",
+ "total_jobs_in_view": "Jobs in View",
+ "total_jobs_on_board": "Jobs on Board",
+ "total_lab_in_production": "Body Hours in Production",
+ "total_lab_in_view": "Body Hours in View",
+ "total_lab_on_board": "Body Hours on Board",
+ "total_lar_in_production": "Refinish Hours in Production",
+ "total_lar_in_view": "Refinish Hours in View",
+ "total_lar_on_board": "Refinish Hours on Board"
+ },
+ "statistics_title": "Statistics"
+ },
+ "statistics": {
+ "currency_symbol": "$",
+ "hours": "Hours",
+ "jobs": "Jobs",
+ "jobs_in_production": "Jobs in Production",
+ "tasks": "Tasks",
+ "tasks_in_production": "Tasks in Production",
+ "tasks_in_view": "Tasks in View",
+ "tasks_on_board": "Tasks on Board",
+ "total_amount_in_production": "Dollars in Production",
+ "total_amount_in_view": "Dollars in View",
+ "total_amount_on_board": "Dollars on Board",
+ "total_hours_in_production": "Hours in Production",
+ "total_hours_in_view": "Hours in View",
+ "total_hours_on_board": "Hours on Board",
+ "total_jobs_in_view": "Jobs in View",
+ "total_jobs_on_board": "Jobs on Board",
+ "total_lab_in_production": "Body Hours in Production",
+ "total_lab_in_view": "Body Hours in View",
+ "total_lab_on_board": "Body Hours on Board",
+ "total_lar_in_production": "Refinish Hours in Production",
+ "total_lar_in_view": "Refinish Hours in View",
+ "total_lar_on_board": "Refinish Hours on Board"
+ },
+ "successes": {
+ "removed": "Job removed from production."
+ }
+ },
+ "profile": {
+ "errors": {
+ "state": "Error reading page state. Please refresh."
+ },
+ "labels": {
+ "activeshop": "Active Shop"
+ },
+ "successes": {
+ "updated": "Profile updated successfully."
+ }
+ },
+ "reportcenter": {
+ "actions": {
+ "generate": "Generate"
+ },
+ "labels": {
+ "advanced_filters": "Advanced Filters and Sorters",
+ "advanced_filters_false": "False",
+ "advanced_filters_filter_field": "Field",
+ "advanced_filters_filter_operator": "Operator",
+ "advanced_filters_filter_value": "Value",
+ "advanced_filters_filters": "Filters",
+ "advanced_filters_hide": "Hide",
+ "advanced_filters_show": "Show",
+ "advanced_filters_sorter_direction": "Direction",
+ "advanced_filters_sorter_field": "Field",
+ "advanced_filters_sorters": "Sorters",
+ "advanced_filters_true": "True",
+ "dates": "Dates",
+ "employee": "Employee",
+ "filterson": "Filters on {{object}}: {{field}}",
+ "generateasemail": "Generate as Email?",
+ "groups": {
+ "customers": "Customers",
+ "jobs": "Jobs & Costing",
+ "payroll": "Payroll",
+ "purchases": "Purchases",
+ "sales": "Sales"
+ },
+ "key": "Report",
+ "objects": {
+ "appointments": "Appointments",
+ "bills": "Bills",
+ "csi": "CSI",
+ "exportlogs": "Export Logs",
+ "jobs": "Jobs",
+ "parts_orders": "Parts Orders",
+ "payments": "Payments",
+ "scoreboard": "Scoreboard",
+ "tasks": "Tasks",
+ "timetickets": "Timetickets"
+ },
+ "vendor": "Vendor"
+ },
+ "templates": {
+ "adp_payroll_flat": "ADP Payroll - Flat Rate",
+ "adp_payroll_straight": "ADP Payroll - Straight Time",
+ "anticipated_revenue": "Anticipated Revenue",
+ "ar_aging": "AR Aging",
+ "attendance_detail": "Attendance (All Employees)",
+ "attendance_employee": "Employee Attendance",
+ "attendance_summary": "Attendance Summary (All Employees)",
+ "committed_timetickets": "Committed Time Tickets",
+ "committed_timetickets_employee": "Committed Employee Time Tickets",
+ "committed_timetickets_summary": "Committed Time Tickets Summary",
+ "credits_not_received_date": "Credits not Received by Date",
+ "credits_not_received_date_vendorid": "Credits not Received by Vendor",
+ "csi": "CSI Responses",
+ "customer_list": "Customer List",
+ "cycle_time_analysis": "Cycle Time Analysis",
+ "estimates_written_converted": "Estimates Written/Converted",
+ "estimator_detail": "Jobs by Estimator (Detail)",
+ "estimator_summary": "Jobs by Estimator (Summary)",
+ "export_payables": "Export Log - Payables",
+ "export_payments": "Export Log - Payments",
+ "export_receivables": "Export Log - Receivables",
+ "exported_gsr_by_ro": "Exported Gross Sales - Excel",
+ "exported_gsr_by_ro_labor": "Exported Gross Sales (Labor) - Excel",
+ "gsr_by_atp": "",
+ "gsr_by_ats": "Gross Sales by ATS",
+ "gsr_by_category": "Gross Sales by Category",
+ "gsr_by_csr": "Gross Sales by CSR",
+ "gsr_by_delivery_date": "Gross Sales by Delivery Date",
+ "gsr_by_estimator": "Gross Sales by Estimator",
+ "gsr_by_exported_date": "Exported Gross Sales",
+ "gsr_by_ins_co": "Gross Sales by Insurance Company",
+ "gsr_by_make": "Gross Sales by Vehicle Make",
+ "gsr_by_referral": "Gross Sales by Referral Source",
+ "gsr_by_ro": "Gross Sales by RO",
+ "gsr_labor_only": "Gross Sales - Labor Only",
+ "hours_sold_detail_closed": "Hours Sold Detail - Closed",
+ "hours_sold_detail_closed_csr": "Hours Sold Detail - Closed by CSR",
+ "hours_sold_detail_closed_estimator": "Hours Sold Detail - Closed by Estimator",
+ "hours_sold_detail_closed_ins_co": "Hours Sold Detail - Closed by Source",
+ "hours_sold_detail_closed_status": "Hours Sold Detail - Closed by Status",
+ "hours_sold_detail_open": "Hours Sold Detail - Open",
+ "hours_sold_detail_open_csr": "Hours Sold Detail - Open by CSR",
+ "hours_sold_detail_open_estimator": "Hours Sold Detail - Open by Estimator",
+ "hours_sold_detail_open_ins_co": "Hours Sold Detail - Open by Source",
+ "hours_sold_detail_open_status": "Hours Sold Detail - Open by Status",
+ "hours_sold_summary_closed": "Hours Sold Summary - Closed",
+ "hours_sold_summary_closed_csr": "Hours Sold Summary - Closed by CSR",
+ "hours_sold_summary_closed_estimator": "Hours Sold Summary - Closed by Estimator",
+ "hours_sold_summary_closed_ins_co": "Hours Sold Summary - Closed by Source",
+ "hours_sold_summary_closed_status": "Hours Sold Summary - Closed by Status",
+ "hours_sold_summary_open": "Hours Sold Summary - Open",
+ "hours_sold_summary_open_csr": "Hours Sold Summary - Open CSR",
+ "hours_sold_summary_open_estimator": "Hours Sold Summary - Open Estimator",
+ "hours_sold_summary_open_ins_co": "Hours Sold Summary - Open by Source",
+ "hours_sold_summary_open_status": "Hours Sold Summary - Open by Status",
+ "job_costing_ro_csr": "Job Costing by CSR",
+ "job_costing_ro_date_detail": "Job Costing by RO - Detail",
+ "job_costing_ro_date_summary": "Job Costing by RO - Summary",
+ "job_costing_ro_estimator": "Job Costing by Estimator",
+ "job_costing_ro_ins_co": "Job Costing by RO Source",
+ "job_lifecycle_date_detail": "Job Lifecycle by Date - Detail",
+ "job_lifecycle_date_summary": "Job Lifecycle by Date - Summary",
+ "jobs_completed_not_invoiced": "Jobs Completed not Invoiced",
+ "jobs_invoiced_not_exported": "Jobs Invoiced not Exported",
+ "jobs_reconcile": "Parts/Sublet/Labor Reconciliation",
+ "jobs_scheduled_completion": "Jobs Scheduled Completion",
+ "lag_time": "Lag Time",
+ "load_level": "Load Level",
+ "lost_sales": "Lost Sales",
+ "open_orders": "Open Orders by Date",
+ "open_orders_csr": "Open Orders by CSR",
+ "open_orders_estimator": "Open Orders by Estimator",
+ "open_orders_excel": "Open Orders - Excel",
+ "open_orders_ins_co": "Open Orders by Insurance Company",
+ "open_orders_referral": "Open Orders by Referral Source",
+ "open_orders_specific_csr": "Open Orders filtered by CSR",
+ "open_orders_status": "Open Orders by Status",
+ "parts_backorder": "IOU Parts List",
+ "parts_not_recieved": "Parts Not Received",
+ "parts_not_recieved_vendor": "Parts Not Received by Vendor",
+ "parts_received_not_scheduled": "Parts Received for Jobs Not Scheduled",
+ "payments_by_date": "Payments by Date",
+ "payments_by_date_payment": "Payments by Date and Payment Type",
+ "payments_by_date_type": "Payments by Date and Customer Type",
+ "production_by_category": "Production by Category",
+ "production_by_category_one": "Production filtered by Category",
+ "production_by_csr": "Production by CSR",
+ "production_by_last_name": "Production by Last Name",
+ "production_by_repair_status": "Production by Status",
+ "production_by_repair_status_one": "Production filtered by Status",
+ "production_by_ro": "Production by RO",
+ "production_by_target_date": "Production by Scheduled Completion",
+ "production_by_technician": "Production by Technician",
+ "production_by_technician_one": "Production filtered by Technician",
+ "production_not_production_status": "Production not in Production Status",
+ "production_over_time": "Production Level over Time",
+ "psr_by_make": "Percent of Sales by Vehicle Make",
+ "purchase_return_ratio_excel": "Purchase & Return Ratio - Excel",
+ "purchase_return_ratio_grouped_by_vendor_detail": "Purchase & Return Ratio by Vendor (Detail)",
+ "purchase_return_ratio_grouped_by_vendor_summary": "Purchase & Return Ratio by Vendor (Summary)",
+ "purchases_by_cost_center_detail": "Purchases by Cost Center (Detail)",
+ "purchases_by_cost_center_summary": "Purchases by Cost Center (Summary)",
+ "purchases_by_date_excel": "Purchases by Date - Excel",
+ "purchases_by_date_range_detail": "Purchases by Date - Detail",
+ "purchases_by_date_range_summary": "Purchases by Date - Summary",
+ "purchases_by_ro_detail_date": "Purchases by RO - Detail",
+ "purchases_by_ro_summary_date": "Purchases by RO - Summary",
+ "purchases_by_vendor_detailed_date_range": "Purchases By Vendor - Detailed",
+ "purchases_by_vendor_summary_date_range": "Purchases by Vendor - Summary",
+ "purchases_grouped_by_vendor_detailed": "Purchases Grouped by Vendor - Detailed",
+ "purchases_grouped_by_vendor_summary": "Purchases Grouped by Vendor - Summary",
+ "returns_grouped_by_vendor_detailed": "Returns Grouped by Vendor - Detailed",
+ "returns_grouped_by_vendor_summary": "Returns Grouped by Vendor - Summary",
+ "schedule": "Appointment Schedule",
+ "scheduled_parts_list": "Parts for Jobs Scheduled In",
+ "scoreboard_detail": "Scoreboard Detail",
+ "scoreboard_summary": "Scoreboard Summary",
+ "supplement_ratio_ins_co": "Supplement Ratio by Source",
+ "tasks_date": "Tasks by Date",
+ "tasks_date_employee": "Employee Tasks by Date",
+ "thank_you_date": "Thank You Letters",
+ "timetickets": "Time Tickets",
+ "timetickets_employee": "Employee Time Tickets",
+ "timetickets_summary": "Time Tickets Summary",
+ "total_loss_jobs": "Jobs Marked as Total Loss",
+ "unclaimed_hrs": "Unflagged Hours",
+ "void_ros": "Void ROs",
+ "work_in_progress_committed_labour": "Work in Progress - Committed Labor",
+ "work_in_progress_jobs": "Work in Progress - Jobs",
+ "work_in_progress_labour": "Work in Progress - Labor",
+ "work_in_progress_payables": "Work in Progress - Payables"
+ }
+ },
+ "schedule": {
+ "labels": {
+ "atssummary": "ATS Summary",
+ "employeevacation": "Employee Vacations",
+ "estimators": "Filter by Writer/Customer Rep.",
+ "ins_co_nm_filter": "Filter by Insurance Company",
+ "intake": "Intake Events",
+ "manual": "Manual Events",
+ "manualevent": "Add Manual Event"
+ }
+ },
+ "scoreboard": {
+ "actions": {
+ "edit": "Edit"
+ },
+ "errors": {
+ "adding": "Error adding Job to Scoreboard. {{message}}",
+ "removing": "Error removing Job from Scoreboard. {{message}}",
+ "updating": "Error updating Scoreboard. {{message}}"
+ },
+ "fields": {
+ "bodyhrs": "Body Hours",
+ "date": "Date",
+ "painthrs": "Paint Hours"
+ },
+ "labels": {
+ "allemployeetimetickets": "All Employee Time Tickets",
+ "asoftodaytarget": "As of Today",
+ "body": "Body",
+ "bodyabbrev": "B",
+ "bodycharttitle": "Body Targets vs Actual",
+ "calendarperiod": "Periods based on calendar weeks/months.",
+ "combinedcharttitle": "Combined Targets vs Actual",
+ "dailyactual": "Actual (D)",
+ "dailytarget": "Daily",
+ "efficiencyoverperiod": "Efficiency over Selected Dates",
+ "entries": "Scoreboard Entries",
+ "jobs": "Jobs",
+ "jobscompletednotinvoiced": "Completed Not Invoiced",
+ "lastmonth": "Last Month",
+ "lastweek": "Last Week",
+ "monthlytarget": "Monthly",
+ "priorweek": "Prior Week",
+ "productivestatistics": "Productive Hours Statistics",
+ "productivetimeticketsoverdate": "Productive Hours over Selected Dates",
+ "refinish": "Refinish",
+ "refinishabbrev": "R",
+ "refinishcharttitle": "Refinish Targets vs Actual",
+ "targets": "Targets",
+ "thismonth": "This Month",
+ "thisweek": "This Week",
+ "timetickets": "Time Tickets",
+ "timeticketsemployee": "Time Tickets by Employee",
+ "todateactual": "Actual (MTD)",
+ "total": "Total",
+ "totalhrs": "Total Hours",
+ "totaloverperiod": "Total over Selected Dates",
+ "weeklyactual": "Actual (W)",
+ "weeklytarget": "Weekly",
+ "workingdays": "Working Days / Month"
+ },
+ "successes": {
+ "added": "Job added to scoreboard.",
+ "removed": "Job removed from scoreboard.",
+ "updated": "Scoreboard updated."
+ }
+ },
+ "tasks": {
+ "actions": {
+ "edit": "Edit Task",
+ "new": "New Task",
+ "view": "View Task"
+ },
+ "buttons": {
+ "allTasks": "All",
+ "complete": "Toggle Complete",
+ "create": "Create Task",
+ "delete": "Toggle Delete",
+ "edit": "Edit",
+ "myTasks": "Mine",
+ "refresh": "Refresh"
+ },
+ "date_presets": {
+ "completion": "Completion",
+ "day": "Day",
+ "days": "Days",
+ "delivery": "Delivery",
+ "next_week": "Next Week",
+ "one_month": "One Month",
+ "three_months": "Three Months",
+ "three_weeks": "Three Weeks",
+ "today": "Today",
+ "tomorrow": "Tomorrow",
+ "two_weeks": "Two Weeks"
+ },
+ "failures": {
+ "completed": "Failed to toggle Task completion.",
+ "created": "Failed to create Task.",
+ "deleted": "Failed to toggle Task deletion.",
+ "updated": "Failed to update Task."
+ },
+ "fields": {
+ "actions": "Actions",
+ "assigned_to": "Assigned To",
+ "bill": "Bill",
+ "billid": "Bill",
+ "completed": "Completed",
+ "created_at": "Created At",
+ "created_by": "Created By",
+ "description": "Description",
+ "due_date": "Due Date",
+ "job": {
+ "ro_number": "RO #"
+ },
+ "jobid": "Job",
+ "jobline": "Job Line",
+ "joblineid": "Job Line",
+ "parts_order": "Parts Order",
+ "partsorderid": "Parts Order",
+ "priorities": {
+ "high": "High",
+ "low": "Low",
+ "medium": "Medium"
+ },
+ "priority": "Priority",
+ "related_items": "Related Items",
+ "remind_at": "Remind At",
+ "title": "Title"
+ },
+ "placeholders": {
+ "assigned_to": "Select an Employee",
+ "billid": "Select a Bill",
+ "description": "Enter a description",
+ "jobid": "Select a Job",
+ "joblineid": "Select a Job Line",
+ "partsorderid": "Select a Parts Order"
+ },
+ "successes": {
+ "completed": "Toggled Task completion successfully.",
+ "created": "Task created successfully.",
+ "deleted": "Toggled Task deletion successfully.",
+ "updated": "Task updated successfully."
+ },
+ "titles": {
+ "all_tasks": "All Tasks",
+ "completed": "Completed Tasks",
+ "deleted": "Deleted Tasks",
+ "job_tasks": "Job Tasks",
+ "mine": "My Tasks",
+ "my_tasks": "My Tasks"
+ },
+ "validation": {
+ "due_at_error_message": "The due date must be in the future!",
+ "remind_at_error_message": "The reminder date and time must be at least 30 minutes in the future!"
+ }
+ },
+ "tech": {
+ "fields": {
+ "employeeid": "Employee ID",
+ "pin": "PIN"
+ },
+ "labels": {
+ "loggedin": "Logged in as {{name}}",
+ "notloggedin": "Not logged in."
+ }
+ },
+ "templates": {
+ "errors": {
+ "updating": "Error updating template {{error}}."
+ },
+ "successes": {
+ "updated": "Template updated successfully."
+ }
+ },
+ "timetickets": {
+ "actions": {
+ "claimtasks": "Flag Hours",
+ "clockin": "Clock In",
+ "clockout": "Clock Out",
+ "commit": "Commit Tickets ({{count}})",
+ "commitone": "Commit",
+ "enter": "Enter New Time Ticket",
+ "payall": "Pay All",
+ "printemployee": "Print Time Tickets",
+ "uncommit": "Uncommit"
+ },
+ "errors": {
+ "clockingin": "Error while clocking in. {{message}}",
+ "clockingout": "Error while clocking out. {{message}}",
+ "creating": "Error creating time ticket. {{message}}",
+ "deleting": "Error deleting time ticket. {{message}}",
+ "noemployeeforuser": "Unable to use Shift Clock",
+ "noemployeeforuser_sub": "An employee record has not been created for this user. Please create one before using the shift clock. ",
+ "payall": "Error flagging hours. {{error}}",
+ "shiftalreadyclockedon": "You are already clocked onto a shift. Unable to create shift entry."
+ },
+ "fields": {
+ "actualhrs": "Actual Hours",
+ "ciecacode": "CIECA Code",
+ "clockhours": "Clock Hours",
+ "clockoff": "Clock Off",
+ "clockon": "Clocked In",
+ "committed": "Committed",
+ "committed_at": "Committed At",
+ "cost_center": "Cost Center",
+ "created_by": "Created By",
+ "date": "Ticket Date",
+ "efficiency": "Efficiency",
+ "employee": "Employee",
+ "employee_team": "Employee Team",
+ "flat_rate": "Flat Rate?",
+ "memo": "Memo",
+ "productivehrs": "Productive Hours",
+ "ro_number": "Job to Post Against",
+ "task_name": "Task"
+ },
+ "labels": {
+ "alreadyclockedon": "You are already clocked in to the following Job(s):",
+ "ambreak": "AM Break",
+ "amshift": "AM Shift",
+ "claimtaskpreview": "Flagged Hours Preview",
+ "clockhours": "Shift Clock Hours Summary",
+ "clockintojob": "Clock In to Job",
+ "deleteconfirm": "Are you sure you want to delete this time ticket? This cannot be undone.",
+ "edit": "Edit Time Ticket",
+ "efficiency": "Efficiency",
+ "flat_rate": "Flat Rate",
+ "jobhours": "Job Related Time Tickets Summary",
+ "lunch": "Lunch",
+ "new": "New Time Ticket",
+ "payrollclaimedtasks": "These time tickets will be automatically entered to the system as a part of claiming this task. These numbers are calculated using the jobs assigned lines. If lines are unassigned, they will be excluded from created tickets.",
+ "pmbreak": "PM Break",
+ "pmshift": "PM Shift",
+ "shift": "Shift",
+ "shiftalreadyclockedon": "Active Shift Time Tickets",
+ "straight_time": "Straight Time",
+ "task": "Task",
+ "timetickets": "Time Tickets",
+ "unassigned": "Unassigned",
+ "zeroactualnegativeprod": "Actual hours must be 0 if entering negative productive hours."
+ },
+ "successes": {
+ "clockedin": "Clocked in successfully.",
+ "clockedout": "Clocked out successfully.",
+ "committed": "Time Tickets Committed Successfully",
+ "created": "Time ticket entered successfully.",
+ "deleted": "Time ticket deleted successfully.",
+ "payall": "All hours paid out successfully."
+ },
+ "validation": {
+ "clockoffmustbeafterclockon": "Clock off time must be the same or after clock in time.",
+ "clockoffwithoutclockon": "Clock off time cannot be set without a clock in time.",
+ "hoursenteredmorethanavailable": "The number of hours entered is more than what is available for this cost center.",
+ "unassignedlines": "There are currently {{unassignedHours}} hours of repair lines that are unassigned. These hours are not including in the above calculations and must be paid manually."
+ }
+ },
+ "titles": {
+ "accounting-payables": "Payables | {{app}}",
+ "accounting-payments": "Payments | {{app}}",
+ "accounting-receivables": "Receivables | {{app}}",
+ "all_tasks": "All Tasks",
+ "app": "",
+ "bc": {
+ "accounting-payables": "Payables",
+ "accounting-payments": "Payments",
+ "accounting-receivables": "Receivables",
+ "all_tasks": "All Tasks",
+ "availablejobs": "Available Jobs",
+ "bills-list": "Bills",
+ "contracts": "Contracts",
+ "contracts-create": "New Contract",
+ "contracts-detail": "Contract #{{number}}",
+ "courtesycars": "Courtesy Cars",
+ "courtesycars-detail": "Courtesy Car {{number}}",
+ "courtesycars-new": "New Courtesy Car",
+ "dashboard": "Dashboard",
+ "dms": "DMS Export",
+ "export-logs": "Export Logs",
+ "inventory": "Inventory",
+ "jobs": "Jobs",
+ "jobs-active": "Active Jobs",
+ "jobs-admin": "Admin",
+ "jobs-all": "All Jobs",
+ "jobs-checklist": "Checklist",
+ "jobs-close": "Close Job",
+ "jobs-deliver": "Deliver Job",
+ "jobs-detail": "Job {{number}}",
+ "jobs-intake": "Intake",
+ "jobs-new": "Create a New Job",
+ "jobs-ready": "Ready Jobs",
+ "my_tasks": "My Tasks",
+ "owner-detail": "{{name}}",
+ "owners": "Owners",
+ "parts-queue": "Parts Queue",
+ "payments-all": "All Payments",
+ "phonebook": "Phonebook",
+ "productionboard": "Production Board - Visual",
+ "productionlist": "Production Board - List",
+ "profile": "My Profile",
+ "schedule": "Schedule",
+ "scoreboard": "Scoreboard",
+ "shop": "Manage my Shop ({{shopname}})",
+ "shop-csi": "CSI Responses",
+ "shop-templates": "Shop Templates",
+ "shop-vendors": "Vendors",
+ "tasks": "Tasks",
+ "temporarydocs": "Temporary Documents",
+ "timetickets": "Time Tickets",
+ "ttapprovals": "Time Ticket Approvals",
+ "vehicle-details": "Vehicle: {{vehicle}}",
+ "vehicles": "Vehicles"
+ },
+ "bills-list": "Bills | {{app}}",
+ "contracts": "Courtesy Car Contracts | {{app}}",
+ "contracts-create": "New Contract | {{app}}",
+ "contracts-detail": "Contract {{id}} | {{app}}",
+ "courtesycars": "Courtesy Cars | {{app}}",
+ "courtesycars-create": "New Courtesy Car | {{app}}",
+ "courtesycars-detail": "Courtesy Car {{id}} | {{app}}",
+ "dashboard": "Dashboard | {{app}}",
+ "dms": "DMS Export | {{app}}",
+ "export-logs": "Export Logs | {{app}}",
+ "imexonline": "ImEX Online",
+ "inventory": "Inventory | {{app}}",
+ "jobs": "Active Jobs | {{app}}",
+ "jobs-admin": "Job {{ro_number}} - Admin | {{app}}",
+ "jobs-all": "All Jobs | {{app}}",
+ "jobs-checklist": "Job Checklist | {{app}}",
+ "jobs-close": "Close Job {{number}} | {{app}}",
+ "jobs-create": "Create a New Job | {{app}}",
+ "jobs-deliver": "Deliver Job | {{app}}",
+ "jobs-intake": "Intake | {{app}}",
+ "jobsavailable": "Available Jobs | {{app}}",
+ "jobsdetail": "Job {{ro_number}} | {{app}}",
+ "jobsdocuments": "Job Documents {{ro_number}} | {{app}}",
+ "manageroot": "Home | {{app}}",
+ "my_tasks": "My Tasks",
+ "owners": "All Owners | {{app}}",
+ "owners-detail": "{{name}} | {{app}}",
+ "parts-queue": "Parts Queue | {{app}}",
+ "payments-all": "Payments | {{app}}",
+ "phonebook": "Phonebook | {{app}}",
+ "productionboard": "Production Board - Visual | {{app}}",
+ "productionlist": "Production Board - List | {{app}}",
+ "profile": "My Profile | {{app}}",
+ "readyjobs": "Ready Jobs | {{app}}",
+ "resetpassword": "Reset Password",
+ "resetpasswordvalidate": "Enter New Password",
+ "romeonline": "Rome Online",
+ "schedule": "Schedule | {{app}}",
+ "scoreboard": "Scoreboard | {{app}}",
+ "shop": "My Shop | {{app}}",
+ "shop-csi": "CSI Responses | {{app}}",
+ "shop-templates": "Shop Templates | {{app}}",
+ "shop_vendors": "Vendors | {{app}}",
+ "tasks": "Tasks",
+ "techconsole": "Technician Console | {{app}}",
+ "techjobclock": "Technician Job Clock | {{app}}",
+ "techjoblookup": "Technician Job Lookup | {{app}}",
+ "techshiftclock": "Technician Shift Clock | {{app}}",
+ "temporarydocs": "Temporary Documents | {{app}}",
+ "timetickets": "Time Tickets | {{app}}",
+ "ttapprovals": "Time Ticket Approvals | {{app}}",
+ "vehicledetail": "Vehicle Details {{vehicle}} | {{app}}",
+ "vehicles": "All Vehicles | {{app}}"
+ },
+ "trello": {
+ "labels": {
+ "add_card": "Add Card",
+ "add_lane": "Add Lane",
+ "cancel": "Cancel",
+ "delete_lane": "Delete Lane",
+ "description": "Description",
+ "label": "Label",
+ "lane_actions": "Lane Actions",
+ "title": "Title"
+ }
+ },
+ "tt_approvals": {
+ "actions": {
+ "approveselected": "Approve Selected"
+ },
+ "labels": {
+ "approval_queue_in_use": "Time tickets will be added to the approval queue.",
+ "calculate": "Calculate"
+ }
+ },
+ "upsell": {
+ "cta": {
+ "learnmore": "Learn More"
+ },
+ "messages": {
+ "accounting": {
+ "payables": {
+ "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.",
+ "title": "Eliminate double data entry"
+ },
+ "payments": {
+ "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.",
+ "title": "Eliminate double data entry"
+ },
+ "receivables": {
+ "subtitle": "Effortlessly send your invoices to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.",
+ "title": "Eliminate double data entry"
+ }
+ },
+ "audit": {
+ "general": {
+ "subtitle": "Know exactly what happened and when through the entire repair process.",
+ "title": "Comprehensive Audit Trails"
+ }
+ },
+ "bills": {
+ "autoreconcile": {
+ "subtitle": "Let your management system do the tedious work - take advantage of automatic job reconciliation today.",
+ "title": "Did you account for every invoice?"
+ },
+ "general": {
+ "subtitle": "Our Bills module allows you to precisely account for every penny on the repair order to ensure you maximize your bottom line.",
+ "title": "Boost your profits by taking control of costs!"
+ }
+ },
+ "checklist": {
+ "general": {
+ "subtitle": "Standardize your intake and delivery with digitized checklists and SOPs.",
+ "title": "Done right, the first time."
+ }
+ },
+ "courtesycars": {
+ "general": {
+ "subtitle": "Keep track of vehicles and contracts for your courtesy cars, all seamlessly synchronized with your Jobs.",
+ "title": "Manage your fleet with ease"
+ }
+ },
+ "csi": {
+ "general": {
+ "subtitle": "With our integrated CSI module, send follow up surveys to your customers to see how well you did.",
+ "title": "See what your customers have to say"
+ }
+ },
+ "dashboard": {
+ "general": {
+ "subtitle": "Make data based decisions and take control of your business using our real-time dashboard.",
+ "title": "Realtime Insight & Analytics"
+ }
+ },
+ "lifecycle": {
+ "general": {
+ "subtitle": "Job life cycles tell you exactly how long the job stayed in each stage of the repair process to identify bottle necks and inefficiencies.",
+ "title": "Are your repair KPIs suffering?"
+ }
+ },
+ "media": {
+ "general": {
+ "subtitle": "Store your vehicle repair documentation, invoices, and related documents digitally to access them anywhere, any time.",
+ "title": "Go paperless."
+ },
+ "mobile": {
+ "subtitle": "Use our mobile app to attach images from your device to the job, increasing your efficiency.",
+ "title": "Accelerate repair documentation with Mobile"
+ }
+ },
+ "payments": {
+ "general": {
+ "subtitle": "Manage outstanding balances and collect payments by credit card from your customers.",
+ "title": "Integrated Accounts Receivable & Payments"
+ }
+ },
+ "scoreboard": {
+ "general": {
+ "subtitle": "Understand hours produced and sold to facilitate employee incentive programs.",
+ "title": "Give credit where credit is due"
+ }
+ },
+ "smartscheduling": {
+ "datepicker": {
+ "subtitle": "Smart Scsheduling gives you the best dates for a vehicle to come in based on your current and predicted production load.",
+ "title": "When's the best time for this job to arrive?"
+ },
+ "general": {
+ "subtitle": "Know exactly how busy you will be tomorrow, the day after, or next week to know exactly when to schedule your next repair.",
+ "title": "Forecast your production with Smart Scheduling"
+ },
+ "hrsdelta": {
+ "subtitle": "Understand changes to your Work in Progress and production load instantly.",
+ "title": "Cars come and cars go."
+ }
+ },
+ "techconsole": {
+ "general": {
+ "subtitle": "The technician's console allows technicians to see job information, media, documents and keep track of their time.",
+ "title": "Empower your Technicians"
+ }
+ },
+ "timetickets": {
+ "allocations": {
+ "subtitle": "Ensure your technicians are paid out exactly what they are owed - not a penny less, not a penny more.",
+ "title": "Technician Payments Done Just Right"
+ },
+ "general": {
+ "subtitle": "Track your technicians time with precision, giving you insight to repair progress and labor efficiency.",
+ "title": "Who did what and for how long?"
+ }
+ },
+ "visualboard": {
+ "general": {
+ "subtitle": "The Visual Production Board makes it easier than ever before to manage your work in progress.",
+ "title": "A whole new kind of production board"
+ }
+ }
+ }
+ },
+ "user": {
+ "actions": {
+ "changepassword": "Change Password",
+ "signout": "Sign Out",
+ "updateprofile": "Update Profile"
+ },
+ "errors": {
+ "updating": "Error updating user or association {{message}}"
+ },
+ "fields": {
+ "authlevel": "Authorization Level",
+ "displayname": "Display Name",
+ "email": "Email",
+ "photourl": "Avatar URL"
+ },
+ "labels": {
+ "actions": "Actions",
+ "changepassword": "Change Password",
+ "profileinfo": "Profile Info"
+ },
+ "successess": {
+ "passwordchanged": "Password changed successfully. "
+ }
+ },
+ "users": {
+ "errors": {
+ "signinerror": {
+ "auth/user-disabled": "User account disabled. ",
+ "auth/user-not-found": "A user with this email does not exist.",
+ "auth/wrong-password": "The email and password combination you provided is incorrect."
+ }
+ }
+ },
+ "vehicles": {
+ "errors": {
+ "deleting": "Error deleting vehicle. {{error}}.",
+ "noaccess": "The vehicle does not exist or you do not have access to it.",
+ "selectexistingornew": "Select an existing vehicle record or create a new one. ",
+ "validation": "Please ensure all fields are entered correctly.",
+ "validationtitle": "Validation Error"
+ },
+ "fields": {
+ "description": "Vehicle Description",
+ "notes": "Vehicle Notes",
+ "plate_no": "License Plate",
+ "plate_st": "Plate Jurisdiction",
+ "trim_color": "Trim Color",
+ "v_bstyle": "Body Style",
+ "v_color": "Color",
+ "v_cond": "Condition",
+ "v_engine": "Engine",
+ "v_make_desc": "Make",
+ "v_makecode": "Make Code",
+ "v_mldgcode": "Molding Code",
+ "v_model_desc": "Model",
+ "v_model_yr": "Year",
+ "v_options": "Options",
+ "v_paint_codes": "Paint Codes {{number}}",
+ "v_prod_dt": "Production Date",
+ "v_stage": "Stage",
+ "v_tone": "Tone",
+ "v_trimcode": "Trim Code",
+ "v_type": "Type",
+ "v_vin": "V.I.N."
+ },
+ "forms": {
+ "detail": "Vehicle Details",
+ "misc": "Miscellaneous",
+ "registration": "Registration"
+ },
+ "labels": {
+ "deleteconfirm": "Are you sure you want to delete this vehicle? This cannot be undone.",
+ "fromvehicle": "Historical Vehicle Record",
+ "novehinfo": "No Vehicle Information",
+ "relatedjobs": "Related Jobs",
+ "updatevehicle": "Update Vehicle Information"
+ },
+ "successes": {
+ "delete": "Vehicle deleted successfully.",
+ "save": "Vehicle saved successfully."
+ }
+ },
+ "vendors": {
+ "actions": {
+ "addtophonebook": "Add to Phonebook",
+ "new": "New Vendor",
+ "newpreferredmake": "New Preferred Make"
+ },
+ "errors": {
+ "deleting": "Error encountered while deleting vendor. ",
+ "saving": "Error encountered while saving vendor. "
+ },
+ "fields": {
+ "active": "Active",
+ "am": "Aftermarket",
+ "city": "City",
+ "cost_center": "Cost Center",
+ "country": "Country",
+ "discount": "Discount % (as decimal)",
+ "display_name": "Display Name",
+ "dmsid": "DMS ID",
+ "due_date": "Payment Due Date (# of days)",
+ "email": "Contact Email",
+ "favorite": "Favorite?",
+ "lkq": "LKQ",
+ "make": "Make",
+ "name": "Vendor Name",
+ "oem": "OEM",
+ "phone": "Phone",
+ "prompt_discount": "Prompt Discount %",
+ "state": "Province/State",
+ "street1": "Street",
+ "street2": "Address 2",
+ "taxid": "Tax ID",
+ "terms": "Payment Terms",
+ "zip": "Zip/Postal Code"
+ },
+ "labels": {
+ "noneselected": "No vendor is selected.",
+ "preferredmakes": "Preferred Makes for Vendor",
+ "search": "Type a Vendor's Name"
+ },
+ "successes": {
+ "deleted": "Vendor deleted successfully. ",
+ "saved": "Vendor saved successfully."
+ },
+ "validation": {
+ "unique_vendor_name": "You must enter a unique vendor name."
+ }
+ },
+ "notifications": {
+ "labels": {
+ "notification-center": "Notification Center",
+ "scenario": "Scenario",
+ "notificationscenarios": "Job Notification Scenarios",
+ "save": "Save Scenarios",
+ "watching-issue": "Watching",
+ "add-watchers": "Add Watchers",
+ "employee-search": "Search for an Employee",
+ "teams-search": "Search for a Team",
+ "add-watchers-team": "Add Team Members",
+ "new-notification-title": "New Notification:",
+ "show-unread-only": "Show Unread Only",
+ "mark-all-read": "Mark All Read",
+ "notification-popup-title": "Changes for Job #{{ro_number}}",
+ "ro-number": "RO #{{ro_number}}",
+ "no-watchers": "No Watchers",
+ "notification-settings-success": "Notification Settings saved successfully.",
+ "notification-settings-failure": "Error saving Notification Settings. {{error}}",
+ "watch": "Watch",
+ "unwatch": "Unwatch"
+ },
+ "actions": {
+ "remove": "Remove"
+ },
+ "aria": {
+ "toggle": "Toggle Watching Job"
+ },
+ "tooltips": {
+ "job-watchers": "Job Watchers"
+ },
+ "scenarios": {
+ "job-assigned-to-me": "Job Assigned to Me",
+ "bill-posted": "Bill Posted",
+ "critical-parts-status-changed": "Critical Parts Status Changed",
+ "part-marked-back-ordered": "Part Marked Back Ordered",
+ "new-note-added": "New Note Added",
+ "supplement-imported": "Supplement Imported",
+ "schedule-dates-changed": "Schedule Dates Changed",
+ "tasks-updated-created": "Tasks Updated / Created",
+ "new-media-added-reassigned": "New Media Added or Reassigned",
+ "new-time-ticket-posted": "New Time Ticket Posted",
+ "intake-delivery-checklist-completed": "Intake or Delivery Checklist Completed",
+ "job-added-to-production": "Job Added to Production",
+ "job-status-change": "Job Status Changed",
+ "payment-collected-completed": "Payment Collected / Completed",
+ "alternate-transport-changed": "Alternate Transport Changed"
+ },
+ "channels": {
+ "app": "App",
+ "email": "Email",
+ "fcm": "Push"
+ }
+ }
+ }
}
diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json
index 04da465c4..2f9fa9a2b 100644
--- a/client/src/translations/es/common.json
+++ b/client/src/translations/es/common.json
@@ -1,3771 +1,3838 @@
{
- "translation": {
- "allocations": {
- "actions": {
- "assign": "Asignar"
- },
- "errors": {
- "deleting": "",
- "saving": "",
- "validation": ""
- },
- "fields": {
- "employee": "Asignado a"
- },
- "successes": {
- "deleted": "",
- "save": ""
- }
- },
- "appointments": {
- "actions": {
- "block": "",
- "calculate": "",
- "cancel": "Cancelar",
- "intake": "Consumo",
- "new": "Nueva cita",
- "preview": "",
- "reschedule": "Reprogramar",
- "sendreminder": "",
- "unblock": "",
- "viewjob": "Ver trabajo"
- },
- "errors": {
- "blocking": "",
- "canceling": "Error al cancelar la cita. {{message}}",
- "saving": "Error al programar la cita. {{message}}"
- },
- "fields": {
- "alt_transport": "",
- "color": "",
- "end": "",
- "note": "",
- "start": "",
- "time": "",
- "title": "Título"
- },
- "labels": {
- "arrivedon": "Llegado el:",
- "arrivingjobs": "",
- "blocked": "",
- "cancelledappointment": "Cita cancelada para:",
- "completingjobs": "",
- "dataconsistency": "",
- "expectedjobs": "",
- "expectedprodhrs": "",
- "history": "",
- "inproduction": "",
- "manualevent": "",
- "noarrivingjobs": "",
- "nocompletingjobs": "",
- "nodateselected": "No se ha seleccionado ninguna fecha.",
- "priorappointments": "Nombramientos previos",
- "reminder": "",
- "scheduledfor": "Cita programada para:",
- "severalerrorsfound": "",
- "smartscheduling": "",
- "smspaymentreminder": "",
- "suggesteddates": ""
- },
- "successes": {
- "canceled": "Cita cancelada con éxito.",
- "created": "Cita programada con éxito.",
- "saved": ""
- }
- },
- "associations": {
- "actions": {
- "activate": "Activar"
- },
- "fields": {
- "active": "¿Activo?",
- "shopname": "Nombre de tienda"
- },
- "labels": {
- "actions": "Comportamiento"
- }
- },
- "audit": {
- "fields": {
- "cc": "",
- "contents": "",
- "created": "",
- "operation": "",
- "status": "",
- "subject": "",
- "to": "",
- "useremail": "",
- "values": ""
- }
- },
- "audit_trail": {
- "messages": {
- "admin_job_remove_from_ar": "",
- "admin_jobmarkexported": "",
- "admin_jobmarkforreexport": "",
- "admin_jobuninvoice": "",
- "admin_jobunvoid": "",
- "alerttoggle": "",
- "appointmentcancel": "",
- "appointmentinsert": "",
- "assignedlinehours": "",
- "billdeleted": "",
- "billposted": "",
- "billupdated": "",
- "failedpayment": "",
- "jobassignmentchange": "",
- "jobassignmentremoved": "",
- "jobchecklist": "",
- "jobclosedwithbypass": "",
- "jobconverted": "",
- "jobdelivery": "",
- "jobexported": "",
- "jobfieldchanged": "",
- "jobimported": "",
- "jobinproductionchange": "",
- "jobintake": "",
- "jobinvoiced": "",
- "jobioucreated": "",
- "jobmodifylbradj": "",
- "jobnoteadded": "",
- "jobnotedeleted": "",
- "jobnoteupdated": "",
- "jobspartsorder": "",
- "jobspartsreturn": "",
- "jobstatuschange": "",
- "jobsupplement": "",
- "jobsuspend": "",
- "jobvoid": "",
- "tasks_completed": "",
- "tasks_created": "",
- "tasks_deleted": "",
- "tasks_uncompleted": "",
- "tasks_undeleted": "",
- "tasks_updated": ""
- }
- },
- "billlines": {
- "actions": {
- "newline": ""
- },
- "fields": {
- "actual_cost": "",
- "actual_price": "",
- "cost_center": "",
- "federal_tax_applicable": "",
- "jobline": "",
- "line_desc": "",
- "local_tax_applicable": "",
- "location": "",
- "quantity": "",
- "state_tax_applicable": ""
- },
- "labels": {
- "deductedfromlbr": "",
- "entered": "",
- "from": "",
- "mod_lbr_adjustment": "",
- "other": "",
- "reconciled": "",
- "unreconciled": ""
- },
- "validation": {
- "atleastone": ""
- }
- },
- "bills": {
- "actions": {
- "deductallhours": "",
- "edit": "",
- "receive": "",
- "return": ""
- },
- "errors": {
- "creating": "",
- "deleting": "",
- "existinginventoryline": "",
- "exporting": "",
- "exporting-partner": "",
- "invalidro": "",
- "invalidvendor": "",
- "validation": ""
- },
- "fields": {
- "allpartslocation": "",
- "date": "",
- "exported": "",
- "federal_tax_rate": "",
- "invoice_number": "",
- "is_credit_memo": "",
- "is_credit_memo_short": "",
- "local_tax_rate": "",
- "ro_number": "",
- "state_tax_rate": "",
- "total": "",
- "vendor": "",
- "vendorname": ""
- },
- "labels": {
- "actions": "",
- "bill_lines": "",
- "bill_total": "",
- "billcmtotal": "",
- "bills": "",
- "calculatedcreditsnotreceived": "",
- "creditsnotreceived": "",
- "creditsreceived": "",
- "dedfromlbr": "",
- "deleteconfirm": "",
- "discrepancy": "",
- "discrepwithcms": "",
- "discrepwithlbradj": "",
- "editadjwarning": "",
- "entered_total": "",
- "enteringcreditmemo": "",
- "federal_tax": "",
- "federal_tax_exempt": "",
- "generatepartslabel": "",
- "iouexists": "",
- "local_tax": "",
- "markexported": "",
- "markforreexport": "",
- "new": "",
- "nobilllines": "",
- "noneselected": "",
- "onlycmforinvoiced": "",
- "printlabels": "",
- "retailtotal": "",
- "returnfrombill": "",
- "savewithdiscrepancy": "",
- "state_tax": "",
- "subtotal": "",
- "totalreturns": ""
- },
- "successes": {
- "created": "",
- "deleted": "",
- "exported": "",
- "markexported": "",
- "reexport": ""
- },
- "validation": {
- "closingperiod": "",
- "inventoryquantity": "",
- "manualinhouse": "",
- "unique_invoice_number": ""
- }
- },
- "bodyshop": {
- "actions": {
- "add_task_preset": "",
- "addapptcolor": "",
- "addbucket": "",
- "addpartslocation": "",
- "addpartsrule": "",
- "addspeedprint": "",
- "addtemplate": "",
- "newlaborrate": "",
- "newsalestaxcode": "",
- "newstatus": "",
- "testrender": ""
- },
- "errors": {
- "creatingdefaultview": "",
- "loading": "No se pueden cargar los detalles de la tienda. Por favor llame al soporte técnico.",
- "saving": ""
- },
- "fields": {
- "ReceivableCustomField": "",
- "address1": "",
- "address2": "",
- "appt_alt_transport": "",
- "appt_colors": {
- "color": "",
- "label": ""
- },
- "appt_length": "",
- "attach_pdf_to_email": "",
- "batchid": "",
- "bill_allow_post_to_closed": "",
- "bill_federal_tax_rate": "",
- "bill_local_tax_rate": "",
- "bill_state_tax_rate": "",
- "city": "",
- "closingperiod": "",
- "companycode": "",
- "country": "",
- "dailybodytarget": "",
- "dailypainttarget": "",
- "default_adjustment_rate": "",
- "deliver": {
- "require_actual_delivery_date": "",
- "templates": ""
- },
- "dms": {
- "apcontrol": "",
- "appostingaccount": "",
- "cashierid": "",
- "default_journal": "",
- "disablebillwip": "",
- "disablecontactvehiclecreation": "",
- "dms_acctnumber": "",
- "dms_control_override": "",
- "dms_wip_acctnumber": "",
- "generic_customer_number": "",
- "itc_federal": "",
- "itc_local": "",
- "itc_state": "",
- "mappingname": "",
- "sendmaterialscosting": "",
- "srcco": ""
- },
- "email": "",
- "enforce_class": "",
- "enforce_conversion_category": "",
- "enforce_conversion_csr": "",
- "enforce_referral": "",
- "federal_tax_id": "",
- "ignoreblockeddays": "",
- "inhousevendorid": "",
- "insurance_vendor_id": "",
- "intake": {
- "next_contact_hours": "",
- "templates": ""
- },
- "intellipay_config": {
- "cash_discount_percentage": "",
- "enable_cash_discount": ""
- },
- "invoice_federal_tax_rate": "",
- "invoice_local_tax_rate": "",
- "invoice_state_tax_rate": "",
- "jc_hourly_rates": {
- "mapa": "",
- "mash": ""
- },
- "last_name_first": "",
- "lastnumberworkingdays": "",
- "localmediaserverhttp": "",
- "localmediaservernetwork": "",
- "localmediatoken": "",
- "logo_img_footer_margin": "",
- "logo_img_header_margin": "",
- "logo_img_path": "",
- "logo_img_path_height": "",
- "logo_img_path_width": "",
- "md_categories": "",
- "md_ccc_rates": "",
- "md_classes": "",
- "md_ded_notes": "",
- "md_email_cc": "",
- "md_from_emails": "",
- "md_functionality_toggles": {
- "parts_queue_toggle": ""
- },
- "md_hour_split": {
- "paint": "",
- "prep": ""
- },
- "md_ins_co": {
- "city": "",
- "name": "",
- "private": "",
- "state": "",
- "street1": "",
- "street2": "",
- "zip": ""
- },
- "md_jobline_presets": "",
- "md_lost_sale_reasons": "",
- "md_parts_order_comment": "",
- "md_parts_scan": {
- "caseInsensitive": "",
- "expression": "",
- "field": "",
- "flags": "",
- "mark_critical": "",
- "operation": "",
- "update_field": "",
- "update_value": "",
- "value": ""
- },
- "md_payment_types": "",
- "md_referral_sources": "",
- "md_ro_guard": {
- "enabled": "",
- "enforce_ar": "",
- "enforce_bills": "",
- "enforce_cm": "",
- "enforce_labor": "",
- "enforce_ppd": "",
- "enforce_profit": "",
- "enforce_sublet": "",
- "masterbypass": "",
- "totalgppercent_minimum": ""
- },
- "md_tasks_presets": {
- "enable_tasks": "",
- "hourstype": "",
- "memo": "",
- "name": "",
- "nextstatus": "",
- "percent": "",
- "use_approvals": ""
- },
- "messaginglabel": "",
- "messagingtext": "",
- "noteslabel": "",
- "notestext": "",
- "partslocation": "",
- "phone": "",
- "prodtargethrs": "",
- "rbac": {
- "accounting": {
- "exportlog": "",
- "payables": "",
- "payments": "",
- "receivables": ""
- },
- "bills": {
- "delete": "",
- "enter": "",
- "list": "",
- "reexport": "",
- "view": ""
- },
- "contracts": {
- "create": "",
- "detail": "",
- "list": ""
- },
- "courtesycar": {
- "create": "",
- "detail": "",
- "list": ""
- },
- "csi": {
- "export": "",
- "page": ""
- },
- "employee_teams": {
- "page": ""
- },
- "employees": {
- "page": ""
- },
- "inventory": {
- "delete": "",
- "list": ""
- },
- "jobs": {
- "admin": "",
- "available-list": "",
- "checklist-view": "",
- "close": "",
- "create": "",
- "deliver": "",
- "detail": "",
- "intake": "",
- "list-active": "",
- "list-all": "",
- "list-ready": "",
- "partsqueue": "",
- "void": ""
- },
- "owners": {
- "detail": "",
- "list": ""
- },
- "payments": {
- "enter": "",
- "list": ""
- },
- "phonebook": {
- "edit": "",
- "view": ""
- },
- "production": {
- "board": "",
- "list": ""
- },
- "schedule": {
- "view": ""
- },
- "scoreboard": {
- "view": ""
- },
- "shiftclock": {
- "view": ""
- },
- "shop": {
- "config": "",
- "dashboard": "",
- "rbac": "",
- "reportcenter": "",
- "templates": "",
- "vendors": ""
- },
- "temporarydocs": {
- "view": ""
- },
- "timetickets": {
- "edit": "",
- "editcommitted": "",
- "enter": "",
- "list": "",
- "shiftedit": ""
- },
- "ttapprovals": {
- "approve": "",
- "view": ""
- },
- "users": {
- "editaccess": ""
- }
- },
- "responsibilitycenter": "",
- "responsibilitycenter_accountdesc": "",
- "responsibilitycenter_accountitem": "",
- "responsibilitycenter_accountname": "",
- "responsibilitycenter_accountnumber": "",
- "responsibilitycenter_rate": "",
- "responsibilitycenter_tax_rate": "",
- "responsibilitycenter_tax_sur": "",
- "responsibilitycenter_tax_thres": "",
- "responsibilitycenter_tax_tier": "",
- "responsibilitycenter_tax_type": "",
- "responsibilitycenters": {
- "ap": "",
- "ar": "",
- "ats": "",
- "federal_tax": "",
- "federal_tax_itc": "",
- "gst_override": "",
- "invoiceexemptcode": "",
- "itemexemptcode": "",
- "la1": "",
- "la2": "",
- "la3": "",
- "la4": "",
- "laa": "",
- "lab": "",
- "lad": "",
- "lae": "",
- "laf": "",
- "lag": "",
- "lam": "",
- "lar": "",
- "las": "",
- "lau": "",
- "local_tax": "",
- "mapa": "",
- "mash": "",
- "paa": "",
- "pac": "",
- "pag": "",
- "pal": "",
- "pam": "",
- "pan": "",
- "pao": "",
- "pap": "",
- "par": "",
- "pas": "",
- "pasl": "",
- "refund": "",
- "sales_tax_codes": {
- "code": "",
- "description": "",
- "federal": "",
- "local": "",
- "state": ""
- },
- "state_tax": "",
- "tow": ""
- },
- "schedule_end_time": "",
- "schedule_start_time": "",
- "shopname": "",
- "speedprint": {
- "id": "",
- "label": "",
- "templates": ""
- },
- "ss_configuration": {
- "dailyhrslimit": ""
- },
- "ssbuckets": {
- "color": "",
- "gte": "",
- "id": "",
- "label": "",
- "lt": "",
- "target": ""
- },
- "state": "",
- "state_tax_id": "",
- "status": "",
- "statuses": {
- "active_statuses": "",
- "additional_board_statuses": "",
- "color": "",
- "default_arrived": "",
- "default_bo": "",
- "default_canceled": "",
- "default_completed": "",
- "default_delivered": "",
- "default_exported": "",
- "default_imported": "",
- "default_invoiced": "",
- "default_ordered": "",
- "default_quote": "",
- "default_received": "",
- "default_returned": "",
- "default_scheduled": "",
- "default_void": "",
- "open_statuses": "",
- "post_production_statuses": "",
- "pre_production_statuses": "",
- "production_colors": "",
- "production_statuses": "",
- "ready_statuses": ""
- },
- "target_touchtime": "",
- "timezone": "",
- "tt_allow_post_to_invoiced": "",
- "tt_enforce_hours_for_tech_console": "",
- "use_fippa": "",
- "use_paint_scale_data": "",
- "uselocalmediaserver": "",
- "website": "",
- "zip_post": ""
- },
- "labels": {
- "2tiername": "",
- "2tiersetup": "",
- "2tiersource": "",
- "accountingsetup": "",
- "accountingtiers": "",
- "alljobstatuses": "",
- "allopenjobstatuses": "",
- "apptcolors": "",
- "businessinformation": "",
- "checklists": "",
- "csiq": "",
- "customtemplates": "",
- "defaultcostsmapping": "",
- "defaultprofitsmapping": "",
- "deliverchecklist": "",
- "dms": {
- "cdk": {
- "controllist": "",
- "payers": ""
- },
- "cdk_dealerid": "",
- "costsmapping": "",
- "dms_allocations": "",
- "pbs_serialnumber": "",
- "profitsmapping": "",
- "title": ""
- },
- "emaillater": "",
- "employee_teams": "",
- "employees": "",
- "estimators": "",
- "filehandlers": "",
- "imexpay": "",
- "insurancecos": "",
- "intakechecklist": "",
- "intellipay_cash_discount": "",
- "jobstatuses": "",
- "laborrates": "",
- "licensing": "",
- "md_parts_scan": "",
- "md_ro_guard": "",
- "md_tasks_presets": "",
- "md_to_emails": "",
- "md_to_emails_emails": "",
- "messagingpresets": "",
- "notemplatesavailable": "",
- "notespresets": "",
- "orderstatuses": "",
- "partslocations": "",
- "partsscan": "",
- "printlater": "",
- "qbo": "",
- "qbo_departmentid": "",
- "qbo_usa": "",
- "rbac": "",
- "responsibilitycenters": {
- "costs": "",
- "profits": "",
- "sales_tax_codes": "",
- "tax_accounts": "",
- "title": "",
- "ttl_adjustment": "",
- "ttl_tax_adjustment": ""
- },
- "roguard": {
- "title": ""
- },
- "romepay": "",
- "scheduling": "",
- "scoreboardsetup": "",
- "shop_enabled_features": "",
- "shopinfo": "",
- "speedprint": "",
- "ssbuckets": "",
- "systemsettings": "",
- "task-presets": "",
- "workingdays": ""
- },
- "operations": {
- "contains": "",
- "ends_with": "",
- "equals": "",
- "greater_than": "",
- "less_than": "",
- "not_equals": "",
- "starts_with": ""
- },
- "successes": {
- "areyousure": "",
- "defaultviewcreated": "",
- "save": "",
- "unsavedchanges": ""
- },
- "tooltips": {
- "md_parts_scan": {
- "update_value_tooltip": ""
- }
- },
- "validation": {
- "centermustexist": "",
- "larsplit": "",
- "useremailmustexist": ""
- }
- },
- "checklist": {
- "actions": {
- "printall": ""
- },
- "errors": {
- "complete": "",
- "nochecklist": ""
- },
- "labels": {
- "addtoproduction": "",
- "allow_text_message": "",
- "checklist": "",
- "printpack": "",
- "removefromproduction": ""
- },
- "successes": {
- "completed": ""
- }
- },
- "contracts": {
- "actions": {
- "changerate": "",
- "convertoro": "",
- "decodelicense": "",
- "find": "",
- "printcontract": "",
- "senddltoform": ""
- },
- "errors": {
- "fetchingjobinfo": "",
- "returning": "",
- "saving": "",
- "selectjobandcar": ""
- },
- "fields": {
- "actax": "",
- "actualreturn": "",
- "agreementnumber": "",
- "cc_cardholder": "",
- "cc_expiry": "",
- "cc_num": "",
- "cleanupcharge": "",
- "coverage": "",
- "dailyfreekm": "",
- "dailyrate": "",
- "damage": "",
- "damagewaiver": "",
- "driver": "",
- "driver_addr1": "",
- "driver_addr2": "",
- "driver_city": "",
- "driver_dlexpiry": "",
- "driver_dlnumber": "",
- "driver_dlst": "",
- "driver_dob": "",
- "driver_fn": "",
- "driver_ln": "",
- "driver_ph1": "",
- "driver_state": "",
- "driver_zip": "",
- "excesskmrate": "",
- "federaltax": "",
- "fuelin": "",
- "fuelout": "",
- "kmend": "",
- "kmstart": "",
- "length": "",
- "localtax": "",
- "refuelcharge": "",
- "scheduledreturn": "",
- "start": " ",
- "statetax": "",
- "status": ""
- },
- "labels": {
- "agreement": "",
- "availablecars": "",
- "cardueforservice": "",
- "convertform": {
- "applycleanupcharge": "",
- "refuelqty": ""
- },
- "correctdataonform": "",
- "dateinpast": "",
- "dlexpirebeforereturn": "",
- "driverinformation": "",
- "findcontract": "",
- "findermodal": "",
- "insuranceexpired": "",
- "noteconvertedfrom": "",
- "populatefromjob": "",
- "rates": "",
- "time": "",
- "vehicle": "",
- "waitingforscan": ""
- },
- "status": {
- "new": "",
- "out": "",
- "returned": ""
- },
- "successes": {
- "saved": ""
- }
- },
- "courtesycars": {
- "actions": {
- "new": "",
- "return": ""
- },
- "errors": {
- "saving": ""
- },
- "fields": {
- "color": "",
- "dailycost": "",
- "damage": "",
- "fleetnumber": "",
- "fuel": "",
- "insuranceexpires": "",
- "leaseenddate": "",
- "make": "",
- "mileage": "",
- "model": "",
- "nextservicedate": "",
- "nextservicekm": "",
- "notes": "",
- "plate": "",
- "purchasedate": "",
- "readiness": "",
- "registrationexpires": "",
- "serviceenddate": "",
- "servicestartdate": "",
- "status": "",
- "vin": "",
- "year": ""
- },
- "labels": {
- "courtesycar": "",
- "fuel": {
- "12": "",
- "14": "",
- "18": "",
- "34": "",
- "38": "",
- "58": "",
- "78": "",
- "empty": "",
- "full": ""
- },
- "outwith": "",
- "return": "",
- "status": "",
- "uniquefleet": "",
- "usage": "",
- "vehicle": ""
- },
- "readiness": {
- "notready": "",
- "ready": ""
- },
- "status": {
- "in": "",
- "inservice": "",
- "leasereturn": "",
- "out": "",
- "sold": "",
- "unavailable": ""
- },
- "successes": {
- "saved": ""
- }
- },
- "csi": {
- "actions": {
- "activate": ""
- },
- "errors": {
- "creating": "",
- "notconfigured": "",
- "notfoundsubtitle": "",
- "notfoundtitle": "",
- "surveycompletesubtitle": "",
- "surveycompletetitle": ""
- },
- "fields": {
- "completedon": "",
- "created_at": "",
- "surveyid": "",
- "validuntil": ""
- },
- "labels": {
- "copyright": "",
- "greeting": "",
- "intro": "",
- "nologgedinuser": "",
- "nologgedinuser_sub": "",
- "noneselected": "",
- "title": ""
- },
- "successes": {
- "created": "",
- "submitted": "",
- "submittedsub": ""
- }
- },
- "dashboard": {
- "actions": {
- "addcomponent": ""
- },
- "errors": {
- "refreshrequired": "",
- "updatinglayout": ""
- },
- "labels": {
- "bodyhrs": "",
- "dollarsinproduction": "",
- "phone": "",
- "prodhrs": "",
- "refhrs": ""
- },
- "titles": {
- "joblifecycle": "",
- "labhours": "",
- "larhours": "",
- "monthlyemployeeefficiency": "",
- "monthlyjobcosting": "",
- "monthlylaborsales": "",
- "monthlypartssales": "",
- "monthlyrevenuegraph": "",
- "prodhrssummary": "",
- "productiondollars": "",
- "productionhours": "",
- "projectedmonthlysales": "",
- "scheduledindate": "",
- "scheduledintoday": "",
- "scheduledoutdate": "",
- "scheduledouttoday": "",
- "tasks": ""
- }
- },
- "dms": {
- "errors": {
- "alreadyexported": ""
- },
- "labels": {
- "refreshallocations": ""
- }
- },
- "documents": {
- "actions": {
- "delete": "",
- "download": "",
- "reassign": "",
- "selectallimages": "",
- "selectallotherdocuments": ""
- },
- "errors": {
- "deletes3": "Error al eliminar el documento del almacenamiento.",
- "deleting": "",
- "deleting_cloudinary": "",
- "getpresignurl": "Error al obtener la URL prescrita para el documento. {{message}}",
- "insert": "Incapaz de cargar el archivo. {{message}}",
- "nodocuments": "No hay documentos",
- "updating": ""
- },
- "labels": {
- "confirmdelete": "",
- "doctype": "",
- "dragtoupload": "",
- "newjobid": "",
- "openinexplorer": "",
- "optimizedimage": "",
- "reassign_limitexceeded": "",
- "reassign_limitexceeded_title": "",
- "storageexceeded": "",
- "storageexceeded_title": "",
- "upload": "Subir",
- "upload_limitexceeded": "",
- "upload_limitexceeded_title": "",
- "uploading": "",
- "usage": ""
- },
- "successes": {
- "delete": "Documento eliminado con éxito.",
- "edituploaded": "",
- "insert": "Documento cargado con éxito.",
- "updated": ""
- }
- },
- "emails": {
- "errors": {
- "notsent": "Correo electrónico no enviado Se encontró un error al enviar {{message}}"
- },
- "fields": {
- "cc": "",
- "from": "",
- "subject": "",
- "to": ""
- },
- "labels": {
- "attachments": "",
- "documents": "",
- "emailpreview": "",
- "generatingemail": "",
- "pdfcopywillbeattached": "",
- "preview": ""
- },
- "successes": {
- "sent": "Correo electrónico enviado con éxito."
- }
- },
- "employee_teams": {
- "actions": {
- "new": "",
- "newmember": ""
- },
- "fields": {
- "active": "",
- "employeeid": "",
- "max_load": "",
- "name": "",
- "percentage": ""
- }
- },
- "employees": {
- "actions": {
- "addvacation": "",
- "new": "Nuevo empleado",
- "newrate": ""
- },
- "errors": {
- "delete": "Se encontró un error al eliminar al empleado. {{message}}",
- "save": "Se encontró un error al salvar al empleado. {{message}}",
- "validation": "Por favor verifique todos los campos.",
- "validationtitle": "No se puede salvar al empleado."
- },
- "fields": {
- "active": "¿Activo?",
- "base_rate": "Tasa básica",
- "cost_center": "Centro de costos",
- "employee_number": "Numero de empleado",
- "external_id": "",
- "first_name": "Nombre de pila",
- "flat_rate": "Tarifa plana (deshabilitado es tiempo recto)",
- "hire_date": "Fecha de contratación",
- "last_name": "Apellido",
- "pin": "",
- "rate": "",
- "termination_date": "Fecha de conclusión",
- "user_email": "",
- "vacation": {
- "end": "",
- "length": "",
- "start": ""
- }
- },
- "labels": {
- "actions": "",
- "active": "",
- "endmustbeafterstart": "",
- "flat_rate": "",
- "inactive": "",
- "name": "",
- "rate_type": "",
- "status": "",
- "straight_time": ""
- },
- "successes": {
- "delete": "Empleado eliminado con éxito.",
- "save": "Empleado guardado con éxito.",
- "vacationadded": ""
- },
- "validation": {
- "unique_employee_number": ""
- }
- },
- "eula": {
- "buttons": {
- "accept": "Accept EULA"
- },
- "content": {
- "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting."
- },
- "errors": {
- "acceptance": {
- "description": "Something went wrong while accepting the EULA. Please try again.",
- "message": "Eula Acceptance Error"
- }
- },
- "labels": {
- "accepted_terms": "I accept the terms and conditions of this agreement.",
- "address": "Address",
- "business_name": "Legal Business Name",
- "date_accepted": "Date Accepted",
- "first_name": "First Name",
- "last_name": "Last Name",
- "phone_number": "Phone Number"
- },
- "messages": {
- "accepted_terms": "Please accept the terms and conditions of this agreement.",
- "business_name": "Please enter your legal business name.",
- "date_accepted": "Please enter Today's Date.",
- "first_name": "Please enter your first name.",
- "last_name": "Please enter your last name.",
- "phone_number": "Please enter your phone number."
- },
- "titles": {
- "modal": "Terms and Conditions",
- "upper_card": "Acknowledgement"
- }
- },
- "exportlogs": {
- "fields": {
- "createdat": ""
- },
- "labels": {
- "attempts": "",
- "priorsuccesfulexport": ""
- }
- },
- "general": {
- "actions": {
- "add": "",
- "autoupdate": "",
- "calculate": "",
- "cancel": "",
- "clear": "",
- "close": "",
- "copied": "",
- "copylink": "",
- "create": "",
- "defaults": "defaults",
- "delay": "",
- "delete": "Borrar",
- "deleteall": "",
- "deselectall": "",
- "download": "",
- "edit": "Editar",
- "login": "",
- "next": "",
- "ok": "",
- "previous": "",
- "print": "",
- "refresh": "",
- "remove": "",
- "remove_alert": "",
- "reset": " Restablecer a original.",
- "resetpassword": "",
- "save": "Salvar",
- "saveandnew": "",
- "saveas": "",
- "selectall": "",
- "send": "",
- "sendbysms": "",
- "senderrortosupport": "",
- "sharetoteams": "",
- "submit": "",
- "tryagain": "",
- "view": "",
- "viewreleasenotes": ""
- },
- "errors": {
- "fcm": "",
- "notfound": "",
- "sizelimit": ""
- },
- "itemtypes": {
- "contract": "",
- "courtesycar": "",
- "job": "",
- "owner": "",
- "vehicle": ""
- },
- "labels": {
- "actions": "Comportamiento",
- "areyousure": "",
- "barcode": "código de barras",
- "cancel": "",
- "clear": "",
- "confirmpassword": "",
- "created_at": "",
- "date": "",
- "datetime": "",
- "email": "",
- "errors": "",
- "excel": "",
- "exceptiontitle": "",
- "friday": "",
- "globalsearch": "",
- "help": "",
- "hours": "",
- "in": "en",
- "instanceconflictext": "",
- "instanceconflictitle": "",
- "item": "",
- "label": "",
- "loading": "Cargando...",
- "loadingapp": "Cargando {{app}}",
- "loadingshop": "Cargando datos de la tienda ...",
- "loggingin": "Iniciando sesión ...",
- "markedexported": "",
- "media": "",
- "message": "",
- "monday": "",
- "na": "N / A",
- "newpassword": "",
- "no": "",
- "nointernet": "",
- "nointernet_sub": "",
- "none": "",
- "out": "Afuera",
- "password": "",
- "passwordresetsuccess": "",
- "passwordresetsuccess_sub": "",
- "passwordresetvalidatesuccess": "",
- "passwordresetvalidatesuccess_sub": "",
- "passwordsdonotmatch": "",
- "print": "",
- "refresh": "",
- "reports": "",
- "required": "",
- "saturday": "",
- "search": "Buscar...",
- "searchresults": "",
- "selectdate": "",
- "sendagain": "",
- "sendby": "",
- "signin": "",
- "sms": "",
- "status": "",
- "sub_status": {
- "expired": ""
- },
- "successful": "",
- "sunday": "",
- "text": "",
- "thursday": "",
- "time": "",
- "total": "",
- "totals": "",
- "tuesday": "",
- "tvmode": "",
- "unknown": "Desconocido",
- "unsavedchanges": "",
- "username": "",
- "view": "",
- "wednesday": "",
- "yes": ""
- },
- "languages": {
- "english": "Inglés",
- "french": "francés",
- "spanish": "español"
- },
- "messages": {
- "exception": "",
- "newversionmessage": "",
- "newversiontitle": "",
- "noacctfilepath": "",
- "nofeatureaccess": "",
- "noshop": "",
- "notfoundsub": "",
- "notfoundtitle": "",
- "partnernotrunning": "",
- "rbacunauth": "",
- "unsavedchanges": "Usted tiene cambios no guardados.",
- "unsavedchangespopup": ""
- },
- "validation": {
- "dateRangeExceeded": "",
- "invalidemail": "Por favor introduzca una dirección de correo electrónico válida.",
- "invalidphone": "",
- "required": "Este campo es requerido."
- }
- },
- "help": {
- "actions": {
- "connect": ""
- },
- "labels": {
- "codeplacholder": "",
- "rescuedesc": "",
- "rescuetitle": ""
- }
- },
- "intake": {
- "labels": {
- "printpack": ""
- }
- },
- "inventory": {
- "actions": {
- "addtoinventory": "",
- "addtoro": "",
- "consumefrominventory": "",
- "edit": "",
- "new": ""
- },
- "errors": {
- "inserting": ""
- },
- "fields": {
- "comment": "",
- "manualinvoicenumber": "",
- "manualvendor": ""
- },
- "labels": {
- "consumedbyjob": "",
- "deleteconfirm": "",
- "frombillinvoicenumber": "",
- "fromvendor": "",
- "inventory": "",
- "showall": "",
- "showavailable": ""
- },
- "successes": {
- "deleted": "",
- "inserted": "",
- "updated": ""
- }
- },
- "job_lifecycle": {
- "columns": {
- "average_human_readable": "",
- "average_value": "",
- "duration": "",
- "end": "",
- "human_readable": "",
- "percentage": "",
- "relative_end": "",
- "relative_start": "",
- "start": "",
- "status": "",
- "status_count": "",
- "value": ""
- },
- "content": {
- "calculated_based_on": "",
- "current_status_accumulated_time": "",
- "data_unavailable": "",
- "jobs_in_since": "",
- "legend_title": "",
- "loading": "",
- "not_available": "",
- "previous_status_accumulated_time": "",
- "title": "",
- "title_durations": "",
- "title_loading": "",
- "title_transitions": ""
- },
- "errors": {
- "fetch": "Error al obtener los datos del ciclo de vida del trabajo"
- },
- "titles": {
- "dashboard": "",
- "top_durations": ""
- }
- },
- "job_payments": {
- "buttons": {
- "create_short_link": "",
- "goback": "",
- "proceedtopayment": "",
- "refundpayment": ""
- },
- "notifications": {
- "error": {
- "description": "",
- "openingip": "",
- "title": ""
- }
- },
- "titles": {
- "amount": "",
- "dateOfPayment": "",
- "descriptions": "",
- "hint": "",
- "payer": "",
- "payername": "",
- "paymentid": "",
- "paymentnum": "",
- "paymenttype": "",
- "refundamount": "",
- "transactionid": ""
- }
- },
- "joblines": {
- "actions": {
- "assign_team": "",
- "converttolabor": "",
- "dispatchparts": "",
- "new": ""
- },
- "errors": {
- "creating": "",
- "updating": ""
- },
- "fields": {
- "act_price": "Precio actual",
- "act_price_before_ppc": "",
- "adjustment": "",
- "ah_detail_line": "",
- "alt_partno": "",
- "amount": "",
- "assigned_team": "",
- "assigned_team_name": "",
- "create_ppc": "",
- "db_price": "Precio de base de datos",
- "include_in_part_cnt": "",
- "lbr_types": {
- "LA1": "",
- "LA2": "",
- "LA3": "",
- "LA4": "",
- "LAA": "",
- "LAB": "",
- "LAD": "",
- "LAE": "",
- "LAF": "",
- "LAG": "",
- "LAM": "",
- "LAR": "",
- "LAS": "",
- "LAU": ""
- },
- "line_desc": "Descripción de línea",
- "line_ind": "S#",
- "line_no": "",
- "location": "",
- "mod_lb_hrs": "Horas laborales",
- "mod_lbr_ty": "Tipo de trabajo",
- "notes": "",
- "oem_partno": "OEM parte #",
- "op_code_desc": "",
- "part_qty": "",
- "part_type": "Tipo de parte",
- "part_types": {
- "CCC": "",
- "CCD": "",
- "CCDR": "",
- "CCF": "",
- "CCM": "",
- "PAA": "",
- "PAC": "",
- "PAE": "",
- "PAG": "",
- "PAL": "",
- "PAM": "",
- "PAN": "",
- "PAO": "",
- "PAP": "",
- "PAR": "",
- "PAS": "",
- "PASL": ""
- },
- "profitcenter_labor": "",
- "profitcenter_part": "",
- "prt_dsmk_m": "",
- "prt_dsmk_p": "",
- "status": "Estado",
- "tax_part": "",
- "total": "",
- "unq_seq": "Seq #"
- },
- "labels": {
- "adjustmenttobeadded": "",
- "billref": "",
- "convertedtolabor": "",
- "edit": "Línea de edición",
- "ioucreated": "",
- "new": "Nueva línea",
- "nostatus": "",
- "presets": ""
- },
- "successes": {
- "created": "",
- "saved": "",
- "updated": ""
- },
- "validations": {
- "ahdetailonlyonuserdefinedtypes": "",
- "hrsrequirediflbrtyp": "",
- "requiredifparttype": "",
- "zeropriceexistingpart": ""
- }
- },
- "jobs": {
- "actions": {
- "addDocuments": "Agregar documentos de trabajo",
- "addNote": "Añadir la nota",
- "addtopartsqueue": "",
- "addtoproduction": "",
- "addtoscoreboard": "",
- "allocate": "",
- "autoallocate": "",
- "changefilehandler": "",
- "changelaborrate": "",
- "changestatus": "Cambiar Estado",
- "changestimator": "",
- "convert": "Convertir",
- "createiou": "",
- "deliver": "",
- "deliver_quick": "",
- "dms": {
- "addpayer": "",
- "createnewcustomer": "",
- "findmakemodelcode": "",
- "getmakes": "",
- "labels": {
- "refreshallocations": ""
- },
- "post": "",
- "refetchmakesmodels": "",
- "usegeneric": "",
- "useselected": ""
- },
- "dmsautoallocate": "",
- "export": "",
- "exportcustdata": "",
- "exportselected": "",
- "filterpartsonly": "",
- "generatecsi": "",
- "gotojob": "",
- "intake": "",
- "intake_quick": "",
- "manualnew": "",
- "mark": "",
- "markasexported": "",
- "markpstexempt": "",
- "markpstexemptconfirm": "",
- "postbills": "Contabilizar facturas",
- "printCenter": "Centro de impresión",
- "recalculate": "",
- "reconcile": "",
- "removefromproduction": "",
- "schedule": "Programar",
- "sendcsi": "",
- "sendpartspricechange": "",
- "sendtodms": "",
- "sync": "",
- "taxprofileoverride": "",
- "taxprofileoverride_confirm": "",
- "uninvoice": "",
- "unvoid": "",
- "viewchecklist": "",
- "viewdetail": ""
- },
- "errors": {
- "addingtoproduction": "",
- "cannotintake": "",
- "closing": "",
- "creating": "",
- "deleted": "Error al eliminar el trabajo.",
- "exporting": "",
- "exporting-partner": "",
- "invoicing": "",
- "noaccess": "Este trabajo no existe o no tiene acceso a él.",
- "nodamage": "",
- "nodates": "No hay fechas especificadas para este trabajo.",
- "nofinancial": "",
- "nojobselected": "No hay trabajo seleccionado.",
- "noowner": "Ningún propietario asociado.",
- "novehicle": "No hay vehículo asociado.",
- "partspricechange": "",
- "saving": "Se encontró un error al guardar el registro.",
- "scanimport": "",
- "totalscalc": "",
- "updating": "",
- "validation": "Asegúrese de que todos los campos se ingresen correctamente.",
- "validationtitle": "Error de validacion",
- "voiding": ""
- },
- "fields": {
- "active_tasks": "",
- "actual_completion": "Realización real",
- "actual_delivery": "Entrega real",
- "actual_in": "Real en",
- "adjustment_bottom_line": "Ajustes",
- "adjustmenthours": "",
- "alt_transport": "",
- "area_of_damage_impact": {
- "10": "",
- "11": "",
- "12": "",
- "13": "",
- "14": "",
- "15": "",
- "16": "",
- "25": "",
- "26": "",
- "27": "",
- "28": "",
- "34": "",
- "01": "",
- "02": "",
- "03": "",
- "04": "",
- "05": "",
- "06": "",
- "07": "",
- "08": "",
- "09": ""
- },
- "auto_add_ats": "",
- "ca_bc_pvrt": "",
- "ca_customer_gst": "",
- "ca_gst_registrant": "",
- "category": "",
- "ccc": "",
- "ccd": "",
- "ccdr": "",
- "ccf": "",
- "ccm": "",
- "cieca_id": "CIECA ID",
- "cieca_pfl": {
- "lbr_adjp": "",
- "lbr_tax_in": "",
- "lbr_taxp": "",
- "lbr_tx_in1": "",
- "lbr_tx_in2": "",
- "lbr_tx_in3": "",
- "lbr_tx_in4": "",
- "lbr_tx_in5": ""
- },
- "cieca_pfo": {
- "stor_t_in1": "",
- "stor_t_in2": "",
- "stor_t_in3": "",
- "stor_t_in4": "",
- "stor_t_in5": "",
- "tow_t_in1": "",
- "tow_t_in2": "",
- "tow_t_in3": "",
- "tow_t_in4": "",
- "tow_t_in5": ""
- },
- "claim_total": "Reclamar total",
- "class": "",
- "clm_no": "Reclamación #",
- "clm_total": "Reclamar total",
- "comment": "",
- "customerowing": "Cliente debido",
- "date_estimated": "Fecha estimada",
- "date_exported": "Exportado",
- "date_invoiced": "Facturado",
- "date_last_contacted": "",
- "date_lost_sale": "",
- "date_next_contact": "",
- "date_open": "Abierto",
- "date_rentalresp": "",
- "date_repairstarted": "",
- "date_scheduled": "Programado",
- "date_towin": "",
- "date_void": "",
- "ded_amt": "Deducible",
- "ded_note": "",
- "ded_status": "Estado deducible",
- "depreciation_taxes": "Depreciación / Impuestos",
- "dms": {
- "address": "",
- "amount": "",
- "center": "",
- "control_type": {
- "account_number": ""
- },
- "cost": "",
- "cost_dms_acctnumber": "",
- "dms_make": "",
- "dms_model": "",
- "dms_model_override": "",
- "dms_unsold": "",
- "dms_wip_acctnumber": "",
- "id": "",
- "inservicedate": "",
- "journal": "",
- "lines": "",
- "name1": "",
- "payer": {
- "amount": "",
- "control_type": "",
- "controlnumber": "",
- "dms_acctnumber": "",
- "name": ""
- },
- "sale": "",
- "sale_dms_acctnumber": "",
- "story": "",
- "vinowner": ""
- },
- "dms_allocation": "",
- "driveable": "",
- "employee_body": "",
- "employee_csr": "Representante de servicio al cliente.",
- "employee_csr_writer": "",
- "employee_prep": "",
- "employee_refinish": "",
- "est_addr1": "Dirección del tasador",
- "est_co_nm": "Tasador",
- "est_ct_fn": "Nombre del tasador",
- "est_ct_ln": "Apellido del tasador",
- "est_ea": "Correo electrónico del tasador",
- "est_ph1": "Número de teléfono del tasador",
- "federal_tax_payable": "Impuesto federal por pagar",
- "federal_tax_rate": "",
- "ins_addr1": "Dirección de Insurance Co.",
- "ins_city": "Ciudad de seguros",
- "ins_co_id": "ID de la compañía de seguros",
- "ins_co_nm": "Nombre de la compañía de seguros",
- "ins_co_nm_short": "",
- "ins_ct_fn": "Nombre del controlador de archivos",
- "ins_ct_ln": "Apellido del manejador de archivos",
- "ins_ea": "Correo electrónico del controlador de archivos",
- "ins_ph1": "File Handler Phone #",
- "intake": {
- "label": "",
- "max": "",
- "min": "",
- "name": "",
- "required": "",
- "type": ""
- },
- "invoice_final_note": "",
- "kmin": "Kilometraje en",
- "kmout": "Kilometraje",
- "la1": "",
- "la2": "",
- "la3": "",
- "la4": "",
- "laa": "",
- "lab": "",
- "labor_rate_desc": "Nombre de la tasa laboral",
- "lad": "",
- "lae": "",
- "laf": "",
- "lag": "",
- "lam": "",
- "lar": "",
- "las": "",
- "lau": "",
- "local_tax_rate": "",
- "loss_date": "Fecha de pérdida",
- "loss_desc": "",
- "loss_of_use": "",
- "lost_sale_reason": "",
- "ma2s": "",
- "ma3s": "",
- "mabl": "",
- "macs": "",
- "mahw": "",
- "mapa": "",
- "mash": "",
- "matd": "",
- "materials": {
- "MAPA": "",
- "MASH": "",
- "cal_maxdlr": "",
- "cal_opcode": "",
- "mat_adjp": "",
- "mat_taxp": "",
- "mat_tx_in1": "",
- "mat_tx_in2": "",
- "mat_tx_in3": "",
- "mat_tx_in4": "",
- "mat_tx_in5": "",
- "materials": "",
- "tax_ind": ""
- },
- "other_amount_payable": "Otra cantidad a pagar",
- "owner": "Propietario",
- "owner_owing": "Cust. Debe",
- "ownr_ea": "Email",
- "ownr_ph1": "Teléfono 1",
- "ownr_ph2": "",
- "paa": "",
- "pac": "",
- "pae": "",
- "pag": "",
- "pal": "",
- "pam": "",
- "pan": "",
- "pao": "",
- "pap": "",
- "par": "",
- "parts_tax_rates": {
- "prt_discp": "",
- "prt_mktyp": "",
- "prt_mkupp": "",
- "prt_tax_in": "",
- "prt_tax_rt": "",
- "prt_tx_in1": "",
- "prt_tx_in2": "",
- "prt_tx_in3": "",
- "prt_tx_in4": "",
- "prt_tx_in5": "",
- "prt_tx_ty1": "",
- "prt_type": ""
- },
- "partsstatus": "",
- "pas": "",
- "pay_date": "Fecha de Pay",
- "phoneshort": "PH",
- "po_number": "",
- "policy_no": "Política #",
- "ponumber": "numero postal",
- "production_vars": {
- "note": ""
- },
- "qb_multiple_payers": {
- "amount": "",
- "name": ""
- },
- "queued_for_parts": "",
- "rate_ats": "",
- "rate_la1": "Tarifa LA1",
- "rate_la2": "Tarifa LA2",
- "rate_la3": "Tarifa LA3",
- "rate_la4": "Tarifa LA4",
- "rate_laa": "Tasa de aluminio",
- "rate_lab": "Tasa de trabajo",
- "rate_lad": "Tasa de diagnóstico",
- "rate_lae": "tarifa eléctrica",
- "rate_laf": "Cuadros por segundo",
- "rate_lag": "Tasa de vidrio",
- "rate_lam": "Tasa mecánica",
- "rate_lar": "Tasa de acabado",
- "rate_las": "",
- "rate_lau": "",
- "rate_ma2s": "Velocidad de pintura de 2 etapas",
- "rate_ma3s": "Tasa de pintura de 3 etapas",
- "rate_mabl": "MABL ??",
- "rate_macs": "MACS ??",
- "rate_mahw": "Tasa de residuos peligrosos",
- "rate_mapa": "Tasa de materiales de pintura",
- "rate_mash": "Comprar material de tarifa",
- "rate_matd": "Tasa de eliminación de neumáticos",
- "referral_source_extra": "",
- "referral_source_other": "",
- "referralsource": "Fuente de referencia",
- "regie_number": "N. ° de registro",
- "repairtotal": "Reparación total",
- "ro_number": "RO #",
- "scheduled_completion": "Finalización programada",
- "scheduled_delivery": "Entrega programada",
- "scheduled_in": "Programado en",
- "selling_dealer": "Distribuidor vendedor",
- "selling_dealer_contact": "Contacto con el vendedor",
- "servicecar": "Auto de servicio",
- "servicing_dealer": "Distribuidor de servicio",
- "servicing_dealer_contact": "Servicio Contacto con el concesionario",
- "special_coverage_policy": "Política de cobertura especial",
- "specialcoveragepolicy": "Política de cobertura especial",
- "state_tax_rate": "",
- "status": "Estado del trabajo",
- "storage_payable": "Almacenamiento ",
- "tax_lbr_rt": "",
- "tax_levies_rt": "",
- "tax_paint_mat_rt": "",
- "tax_registration_number": "",
- "tax_shop_mat_rt": "",
- "tax_str_rt": "",
- "tax_sub_rt": "",
- "tax_tow_rt": "",
- "tlos_ind": "",
- "towin": "",
- "towing_payable": "Remolque a pagar",
- "unitnumber": "Unidad #",
- "updated_at": "Actualizado en",
- "uploaded_by": "Subido por",
- "vehicle": "Vehículo"
- },
- "forms": {
- "admindates": "",
- "appraiserinfo": "",
- "claiminfo": "",
- "estdates": "",
- "laborrates": "",
- "lossinfo": "",
- "other": "",
- "repairdates": "",
- "scheddates": ""
- },
- "labels": {
- "accountsreceivable": "",
- "act_price_ppc": "",
- "actual_completion_inferred": "",
- "actual_delivery_inferred": "",
- "actual_in_inferred": "",
- "additionalpayeroverallocation": "",
- "additionaltotal": "",
- "adjustmentrate": "",
- "adjustments": "",
- "adminwarning": "",
- "allocations": "",
- "alreadyaddedtoscoreboard": "",
- "alreadyclosed": "",
- "appointmentconfirmation": "¿Enviar confirmación al cliente?",
- "associationwarning": "",
- "audit": "",
- "available": "",
- "availablejobs": "",
- "ca_bc_pvrt": {
- "days": "",
- "rate": ""
- },
- "ca_gst_all_if_null": "",
- "calc_repair_days": "",
- "calc_repair_days_tt": "",
- "calc_scheuled_completion": "",
- "cards": {
- "customer": "Información al cliente",
- "damage": "Área de Daño",
- "dates": "fechas",
- "documents": "Documentos recientes",
- "estimator": "Estimador",
- "filehandler": "File Handler",
- "insurance": "detalles del seguro",
- "more": "Más",
- "notes": "Notas",
- "parts": "Partes",
- "totals": "Totales",
- "vehicle": "Vehículo"
- },
- "changeclass": "",
- "checklistcompletedby": "",
- "checklistdocuments": "",
- "checklists": "",
- "cieca_pfl": "",
- "cieca_pfo": "",
- "cieca_pft": "",
- "closeconfirm": "",
- "closejob": "",
- "closingperiod": "",
- "contracts": "",
- "convertedtolabor": "",
- "cost": "",
- "cost_Additional": "",
- "cost_labor": "",
- "cost_parts": "",
- "cost_sublet": "",
- "costs": "",
- "create": {
- "jobinfo": "",
- "newowner": "",
- "newvehicle": "",
- "novehicle": "",
- "ownerinfo": "",
- "vehicleinfo": ""
- },
- "createiouwarning": "",
- "creating_new_job": "Creando nuevo trabajo ...",
- "deductible": {
- "stands": "",
- "waived": ""
- },
- "deleteconfirm": "",
- "deletedelivery": "",
- "deleteintake": "",
- "deliverchecklist": "",
- "difference": "",
- "diskscan": "",
- "dms": {
- "apexported": "",
- "damageto": "",
- "defaultstory": "",
- "disablebillwip": "",
- "invoicedatefuture": "",
- "kmoutnotgreaterthankmin": "",
- "logs": "",
- "notallocated": "",
- "postingform": "",
- "totalallocated": ""
- },
- "documents": "documentos",
- "documents-images": "",
- "documents-other": "",
- "duplicateconfirm": "",
- "emailaudit": "",
- "employeeassignments": "",
- "estimatelines": "",
- "estimator": "",
- "existing_jobs": "Empleos existentes",
- "federal_tax_amt": "",
- "gpdollars": "",
- "gppercent": "",
- "hrs_claimed": "",
- "hrs_total": "",
- "importnote": "",
- "inproduction": "",
- "intakechecklist": "",
- "iou": "",
- "job": "",
- "jobcosting": "",
- "jobtotals": "",
- "labor_hrs": "",
- "labor_rates_subtotal": "",
- "laborallocations": "",
- "labortotals": "",
- "lines": "Líneas estimadas",
- "local_tax_amt": "",
- "mapa": "",
- "markforreexport": "",
- "mash": "",
- "masterbypass": "",
- "materials": {
- "mapa": ""
- },
- "missingprofileinfo": "",
- "multipayers": "",
- "net_repairs": "",
- "notes": "Notas",
- "othertotal": "",
- "outstanding_ar": "",
- "outstanding_credit_memos": "",
- "outstanding_ppd": "",
- "outstanding_reconciliation_discrep": "",
- "outstanding_sublets": "",
- "outstandinghours": "",
- "override_header": "¿Anular encabezado estimado al importar?",
- "ownerassociation": "",
- "parts": "Partes",
- "parts_lines": "",
- "parts_received": "",
- "parts_tax_rates": "",
- "partsfilter": "",
- "partssubletstotal": "",
- "partstotal": "",
- "performance": "",
- "pimraryamountpayable": "",
- "plitooltips": {
- "billtotal": "",
- "calculatedcreditsnotreceived": "",
- "creditmemos": "",
- "creditsnotreceived": "",
- "discrep1": "",
- "discrep2": "",
- "discrep3": "",
- "laboradj": "",
- "partstotal": "",
- "totalreturns": ""
- },
- "ppc": "",
- "ppdnotexported": "",
- "profileadjustments": "",
- "profitbypassrequired": "",
- "profits": "",
- "prt_dsmk_total": "",
- "rates": "Tarifas",
- "rates_subtotal": "",
- "reconciliation": {
- "billlinestotal": "",
- "byassoc": "",
- "byprice": "",
- "clear": "",
- "discrepancy": "",
- "joblinestotal": "",
- "multipleactprices": "",
- "multiplebilllines": "",
- "multiplebillsforactprice": "",
- "removedpartsstrikethrough": ""
- },
- "reconciliationheader": "",
- "relatedros": "",
- "remove_from_ar": "",
- "returntotals": "",
- "ro_guard": {
- "enforce_ar": "",
- "enforce_bills": "",
- "enforce_cm": "",
- "enforce_labor": "",
- "enforce_ppd": "",
- "enforce_profit": "",
- "enforce_sublet": "",
- "enforce_validation": "",
- "enforced": ""
- },
- "roguard": "",
- "roguardwarnings": "",
- "rosaletotal": "",
- "sale_additional": "",
- "sale_labor": "",
- "sale_parts": "",
- "sale_sublet": "",
- "sales": "",
- "savebeforeconversion": "",
- "scheduledinchange": "",
- "specialcoveragepolicy": "",
- "state_tax_amt": "",
- "subletsnotcompleted": "",
- "subletstotal": "",
- "subtotal": "",
- "supplementnote": "",
- "suspended": "",
- "suspense": "",
- "tasks": "",
- "threshhold": "",
- "total_cost": "",
- "total_cust_payable": "",
- "total_cust_payable_cash_discount": "",
- "total_repairs": "",
- "total_repairs_cash_discount": "",
- "total_sales": "",
- "total_sales_tax": "",
- "totals": "",
- "unvoidnote": "",
- "update_scheduled_completion": "",
- "vehicle_info": "Vehículo",
- "vehicleassociation": "",
- "viewallocations": "",
- "voidjob": "",
- "voidnote": ""
- },
- "successes": {
- "addedtoproduction": "",
- "all_deleted": "{{count}} trabajos eliminados con éxito.",
- "closed": "",
- "converted": "Trabajo convertido con éxito.",
- "created": "Trabajo creado con éxito. Click para ver.",
- "creatednoclick": "",
- "delete": "",
- "deleted": "Trabajo eliminado con éxito.",
- "duplicated": "",
- "exported": "",
- "invoiced": "",
- "ioucreated": "",
- "partsqueue": "",
- "save": "Trabajo guardado con éxito.",
- "savetitle": "Registro guardado con éxito.",
- "supplemented": "Trabajo complementado con éxito.",
- "updated": "",
- "voided": ""
- }
- },
- "landing": {
- "bigfeature": {
- "subtitle": "",
- "title": ""
- },
- "footer": {
- "company": {
- "about": "",
- "contact": "",
- "disclaimers": "",
- "name": "",
- "privacypolicy": ""
- },
- "io": {
- "help": "",
- "name": "",
- "status": ""
- },
- "slogan": ""
- },
- "hero": {
- "button": "",
- "title": ""
- },
- "labels": {
- "features": "",
- "managemyshop": "",
- "pricing": ""
- },
- "pricing": {
- "basic": {
- "name": "",
- "sub": ""
- },
- "essentials": {
- "name": "",
- "sub": ""
- },
- "pricingtitle": "",
- "pro": {
- "name": "",
- "sub": ""
- },
- "title": "",
- "unlimited": {
- "name": "",
- "sub": ""
- }
- }
- },
- "menus": {
- "currentuser": {
- "languageselector": "idioma",
- "profile": "Perfil"
- },
- "header": {
- "accounting": "",
- "accounting-payables": "",
- "accounting-payments": "",
- "accounting-receivables": "",
- "activejobs": "Empleos activos",
- "all_tasks": "",
- "alljobs": "",
- "allpayments": "",
- "availablejobs": "Trabajos disponibles",
- "bills": "",
- "courtesycars": "",
- "courtesycars-all": "",
- "courtesycars-contracts": "",
- "courtesycars-newcontract": "",
- "create_task": "",
- "customers": "Clientes",
- "dashboard": "",
- "enterbills": "",
- "entercardpayment": "",
- "enterpayment": "",
- "entertimeticket": "",
- "export": "",
- "export-logs": "",
- "help": "",
- "home": "Casa",
- "inventory": "",
- "jobs": "Trabajos",
- "my_tasks": "",
- "newjob": "",
- "owners": "propietarios",
- "parts-queue": "",
- "phonebook": "",
- "productionboard": "",
- "productionlist": "",
- "readyjobs": "",
- "recent": "",
- "reportcenter": "",
- "rescueme": "",
- "schedule": "Programar",
- "scoreboard": "",
- "search": {
- "bills": "",
- "jobs": "",
- "owners": "",
- "payments": "",
- "phonebook": "",
- "vehicles": ""
- },
- "shiftclock": "",
- "shop": "Mi tienda",
- "shop_config": "Configuración",
- "shop_csi": "",
- "shop_templates": "",
- "shop_vendors": "Vendedores",
- "tasks": "",
- "temporarydocs": "",
- "timetickets": "",
- "ttapprovals": "",
- "vehicles": "Vehículos"
- },
- "jobsactions": {
- "admin": "",
- "cancelallappointments": "",
- "closejob": "",
- "deletejob": "",
- "duplicate": "",
- "duplicatenolines": "",
- "newcccontract": "",
- "void": ""
- },
- "jobsdetail": {
- "claimdetail": "Detalles de la reclamación",
- "dates": "fechas",
- "financials": "",
- "general": "",
- "insurance": "",
- "labor": "Labor",
- "lifecycle": "",
- "parts": "",
- "partssublet": "Piezas / Subarrendamiento",
- "rates": "",
- "repairdata": "Datos de reparación",
- "totals": ""
- },
- "profilesidebar": {
- "profile": "Mi perfil",
- "shops": "Mis tiendas"
- },
- "tech": {
- "assignedjobs": "",
- "claimtask": "",
- "dispatchedparts": "",
- "home": "",
- "jobclockin": "",
- "jobclockout": "",
- "joblookup": "",
- "login": "",
- "logout": "",
- "productionboard": "",
- "productionlist": "",
- "shiftclockin": ""
- }
- },
- "messaging": {
- "actions": {
- "link": "",
- "new": ""
- },
- "errors": {
- "invalidphone": "",
- "noattachedjobs": "",
- "updatinglabel": ""
- },
- "labels": {
- "addlabel": "",
- "archive": "",
- "maxtenimages": "",
- "messaging": "Mensajería",
- "noallowtxt": "",
- "nojobs": "",
- "nopush": "",
- "phonenumber": "",
- "presets": "",
- "recentonly": "",
- "selectmedia": "",
- "sentby": "",
- "typeamessage": "Enviar un mensaje...",
- "unarchive": ""
- },
- "render": {
- "conversation_list": ""
- }
- },
- "notes": {
- "actions": {
- "actions": "Comportamiento",
- "deletenote": "Borrar nota",
- "edit": "Editar nota",
- "new": "Nueva nota",
- "savetojobnotes": ""
- },
- "errors": {
- "inserting": ""
- },
- "fields": {
- "createdby": "Creado por",
- "critical": "Crítico",
- "private": "Privado",
- "text": "Contenido",
- "type": "",
- "types": {
- "customer": "",
- "general": "",
- "office": "",
- "paint": "",
- "parts": "",
- "shop": "",
- "supplement": ""
- },
- "updatedat": "Actualizado en"
- },
- "labels": {
- "addtorelatedro": "",
- "newnoteplaceholder": "Agrega una nota...",
- "notetoadd": "",
- "systemnotes": "",
- "usernotes": ""
- },
- "successes": {
- "create": "Nota creada con éxito.",
- "deleted": "Nota eliminada con éxito.",
- "updated": "Nota actualizada con éxito."
- }
- },
- "owner": {
- "labels": {
- "noownerinfo": ""
- }
- },
- "owners": {
- "actions": {
- "update": ""
- },
- "errors": {
- "deleting": "",
- "noaccess": "El registro no existe o no tiene acceso a él.",
- "saving": "",
- "selectexistingornew": ""
- },
- "fields": {
- "accountingid": "",
- "address": "Dirección",
- "allow_text_message": "Permiso de texto?",
- "name": "Nombre",
- "note": "",
- "ownr_addr1": "Dirección",
- "ownr_addr2": "Dirección 2",
- "ownr_city": "ciudad",
- "ownr_co_nm": "",
- "ownr_ctry": "País",
- "ownr_ea": "Email",
- "ownr_fn": "Nombre de pila",
- "ownr_ln": "Apellido",
- "ownr_ph1": "Teléfono 1",
- "ownr_ph2": "",
- "ownr_st": "Provincia del estado",
- "ownr_title": "Título",
- "ownr_zip": "código postal",
- "preferred_contact": "Método de Contacto Preferido",
- "tax_number": ""
- },
- "forms": {
- "address": "",
- "contact": "",
- "name": ""
- },
- "labels": {
- "create_new": "Crea un nuevo registro de propietario.",
- "deleteconfirm": "",
- "existing_owners": "Propietarios existentes",
- "fromclaim": "",
- "fromowner": "",
- "relatedjobs": "",
- "updateowner": ""
- },
- "successes": {
- "delete": "",
- "save": "Propietario guardado con éxito."
- }
- },
- "parts": {
- "actions": {
- "order": "Pedido de piezas",
- "orderinhouse": ""
- }
- },
- "parts_dispatch": {
- "actions": {
- "accept": ""
- },
- "errors": {
- "accepting": "",
- "creating": ""
- },
- "fields": {
- "number": "",
- "percent_accepted": ""
- },
- "labels": {
- "notyetdispatched": "",
- "parts_dispatch": ""
- }
- },
- "parts_dispatch_lines": {
- "fields": {
- "accepted_at": ""
- }
- },
- "parts_orders": {
- "actions": {
- "backordered": "",
- "receive": "",
- "receivebill": ""
- },
- "errors": {
- "associatedbills": "",
- "backordering": "",
- "creating": "Se encontró un error al crear el pedido de piezas.",
- "oec": "",
- "saving": "",
- "updating": ""
- },
- "fields": {
- "act_price": "",
- "backordered_eta": "",
- "backordered_on": "",
- "cm_received": "",
- "comments": "",
- "cost": "",
- "db_price": "",
- "deliver_by": "",
- "job_line_id": "",
- "line_desc": "",
- "line_remarks": "",
- "lineremarks": "Comentarios de línea",
- "oem_partno": "",
- "order_date": "",
- "order_number": "",
- "orderedby": "",
- "part_type": "",
- "quantity": "",
- "return": "",
- "status": ""
- },
- "labels": {
- "allpartsto": "",
- "confirmdelete": "",
- "custompercent": "",
- "discount": "",
- "email": "Enviar por correo electrónico",
- "inthisorder": "Partes en este pedido",
- "is_quote": "",
- "mark_as_received": "",
- "newpartsorder": "",
- "notyetordered": "",
- "oec": "",
- "order_type": "",
- "orderhistory": "Historial de pedidos",
- "parts_order": "",
- "parts_orders": "",
- "parts_returns": "",
- "print": "Mostrar formulario impreso",
- "receive": "",
- "removefrompartsqueue": "",
- "returnpartsorder": "",
- "sublet_order": ""
- },
- "successes": {
- "created": "Pedido de piezas creado con éxito.",
- "line_updated": "",
- "received": "",
- "return_created": ""
- }
- },
- "payments": {
- "actions": {
- "generatepaymentlink": ""
- },
- "errors": {
- "exporting": "",
- "exporting-partner": "",
- "inserting": ""
- },
- "fields": {
- "amount": "",
- "created_at": "",
- "date": "",
- "exportedat": "",
- "memo": "",
- "payer": "",
- "paymentnum": "",
- "stripeid": "",
- "transactionid": "",
- "type": ""
- },
- "labels": {
- "balance": "",
- "ca_bc_etf_table": "",
- "customer": "",
- "edit": "",
- "electronicpayment": "",
- "external": "",
- "findermodal": "",
- "insurance": "",
- "markexported": "",
- "markforreexport": "",
- "new": "",
- "signup": "",
- "smspaymentreminder": "",
- "title": "",
- "totalpayments": ""
- },
- "successes": {
- "exported": "",
- "markexported": "",
- "markreexported": "",
- "payment": "",
- "paymentupdate": "",
- "stripe": ""
- }
- },
- "phonebook": {
- "actions": {
- "new": ""
- },
- "errors": {
- "adding": "",
- "saving": ""
- },
- "fields": {
- "address1": "",
- "address2": "",
- "category": "",
- "city": "",
- "company": "",
- "country": "",
- "email": "",
- "fax": "",
- "firstname": "",
- "lastname": "",
- "phone1": "",
- "phone2": "",
- "state": ""
- },
- "labels": {
- "noneselected": "",
- "onenamerequired": "",
- "vendorcategory": ""
- },
- "successes": {
- "added": "",
- "deleted": "",
- "saved": ""
- }
- },
- "printcenter": {
- "appointments": {
- "appointment_confirmation": ""
- },
- "bills": {
- "inhouse_invoice": ""
- },
- "courtesycarcontract": {
- "courtesy_car_contract": "",
- "courtesy_car_impound": "",
- "courtesy_car_inventory": "",
- "courtesy_car_terms": ""
- },
- "errors": {
- "nocontexttype": ""
- },
- "jobs": {
- "3rdpartyfields": {
- "addr1": "",
- "addr2": "",
- "addr3": "",
- "attn": "",
- "city": "",
- "custgst": "",
- "ded_amt": "",
- "depreciation": "",
- "other": "",
- "ponumber": "",
- "refnumber": "",
- "sendtype": "",
- "state": "",
- "zip": ""
- },
- "3rdpartypayer": "",
- "ab_proof_of_loss": "",
- "appointment_confirmation": "",
- "appointment_reminder": "",
- "casl_authorization": "",
- "committed_timetickets_ro": "",
- "coversheet_landscape": "",
- "coversheet_portrait": "",
- "csi_invitation": "",
- "csi_invitation_action": "",
- "diagnostic_authorization": "",
- "dms_posting_sheet": "",
- "envelope_return_address": "",
- "estimate": "",
- "estimate_detail": "",
- "estimate_followup": "",
- "express_repair_checklist": "",
- "filing_coversheet_landscape": "",
- "filing_coversheet_portrait": "",
- "final_invoice": "",
- "fippa_authorization": "",
- "folder_label_multiple": "",
- "glass_express_checklist": "",
- "guarantee": "",
- "individual_job_note": "",
- "invoice_customer_payable": "",
- "invoice_total_payable": "",
- "iou_form": "",
- "job_costing_ro": "",
- "job_lifecycle_ro": "",
- "job_notes": "",
- "job_tasks": "",
- "key_tag": "",
- "labels": {
- "count": "",
- "labels": "",
- "position": ""
- },
- "lag_time_ro": "",
- "mechanical_authorization": "",
- "mpi_animal_checklist": "",
- "mpi_eglass_auth": "",
- "mpi_final_acct_sheet": "",
- "mpi_final_repair_acct_sheet": "",
- "paint_grid": "",
- "parts_dispatch": "",
- "parts_invoice_label_single": "",
- "parts_label_multiple": "",
- "parts_label_single": "",
- "parts_list": "",
- "parts_order": "",
- "parts_order_confirmation": "",
- "parts_order_history": "",
- "parts_return_slip": "",
- "payment_receipt": "",
- "payment_request": "",
- "payments_by_job": "",
- "purchases_by_ro_detail": "",
- "purchases_by_ro_summary": "",
- "qc_sheet": "",
- "rental_reservation": "",
- "ro_totals": "",
- "ro_with_description": "",
- "sgi_certificate_of_repairs": "",
- "sgi_windshield_auth": "",
- "stolen_recovery_checklist": "",
- "sublet_order": "",
- "supplement_request": "",
- "thank_you_ro": "",
- "thirdpartypayer": "",
- "timetickets_ro": "",
- "vehicle_check_in": "",
- "vehicle_delivery_check": "",
- "window_tag": "",
- "window_tag_sublet": "",
- "work_authorization": "",
- "worksheet_by_line_number": "",
- "worksheet_sorted_by_operation": "",
- "worksheet_sorted_by_operation_no_hours": "",
- "worksheet_sorted_by_operation_part_type": "",
- "worksheet_sorted_by_operation_type": "",
- "worksheet_sorted_by_team": ""
- },
- "labels": {
- "groups": {
- "authorization": "",
- "financial": "",
- "post": "",
- "pre": "",
- "ro": "",
- "worksheet": ""
- },
- "misc": "",
- "repairorder": "",
- "reportcentermodal": "",
- "speedprint": "",
- "title": ""
- },
- "payments": {
- "ca_bc_etf_table": "",
- "exported_payroll": ""
- },
- "special": {
- "attendance_detail_csv": ""
- },
- "subjects": {
- "jobs": {
- "individual_job_note": "",
- "parts_dispatch": "",
- "parts_order": "",
- "parts_return_slip": "",
- "sublet_order": ""
- }
- },
- "vendors": {
- "purchases_by_vendor_detailed": "",
- "purchases_by_vendor_summary": ""
- }
- },
- "production": {
- "actions": {
- "addcolumns": "",
- "bodypriority-clear": "",
- "bodypriority-set": "",
- "detailpriority-clear": "",
- "detailpriority-set": "",
- "paintpriority-clear": "",
- "paintpriority-set": "",
- "remove": "",
- "removecolumn": "",
- "saveconfig": "",
- "suspend": "",
- "unsuspend": ""
- },
- "constants": {
- "main_profile": ""
- },
- "errors": {
- "boardupdate": "",
- "name_exists": "",
- "name_required": "",
- "removing": "",
- "settings": ""
- },
- "labels": {
- "actual_in": "",
- "addnewprofile": "",
- "alert": "",
- "alertoff": "",
- "alerton": "",
- "alerts": "",
- "ats": "",
- "bodyhours": "",
- "bodypriority": "",
- "bodyshop": {
- "labels": {
- "qbo_departmentid": "",
- "qbo_usa": ""
- }
- },
- "card_size": "",
- "cardcolor": "",
- "cardsettings": "",
- "clm_no": "",
- "comment": "",
- "compact": "",
- "detailpriority": "",
- "employeeassignments": "",
- "employeesearch": "",
- "estimator": "",
- "horizontal": "",
- "ins_co_nm": "",
- "jobdetail": "",
- "kiosk_mode": "",
- "laborhrs": "",
- "legend": "",
- "model_info": "",
- "note": "",
- "off": "",
- "on": "",
- "orientation": "",
- "ownr_nm": "",
- "paintpriority": "",
- "partsstatus": "",
- "production_note": "",
- "refinishhours": "",
- "scheduled_completion": "",
- "selectview": "",
- "stickyheader": "",
- "sublets": "",
- "subtotal": "",
- "tall": "",
- "tasks": "",
- "totalhours": "",
- "touchtime": "",
- "unassigned": "",
- "vertical": "",
- "viewname": "",
- "wide": ""
- },
- "options": {
- "horizontal": "",
- "large": "",
- "medium": "",
- "small": "",
- "vertical": ""
- },
- "settings": {
- "board_settings": "",
- "filters": {
- "md_estimators": "",
- "md_ins_cos": ""
- },
- "filters_title": "",
- "information": "",
- "layout": "",
- "statistics": {
- "jobs_in_production": "",
- "tasks_in_production": "",
- "tasks_in_view": "",
- "tasks_on_board": "",
- "total_amount_in_production": "",
- "total_amount_in_view": "",
- "total_amount_on_board": "",
- "total_hours_in_production": "",
- "total_hours_in_view": "",
- "total_hours_on_board": "",
- "total_jobs_in_view": "",
- "total_jobs_on_board": "",
- "total_lab_in_production": "",
- "total_lab_in_view": "",
- "total_lab_on_board": "",
- "total_lar_in_production": "",
- "total_lar_in_view": "",
- "total_lar_on_board": ""
- },
- "statistics_title": ""
- },
- "statistics": {
- "currency_symbol": "",
- "hours": "",
- "jobs": "",
- "jobs_in_production": "",
- "tasks": "",
- "tasks_in_production": "",
- "tasks_in_view": "",
- "tasks_on_board": "",
- "total_amount_in_production": "",
- "total_amount_in_view": "",
- "total_amount_on_board": "",
- "total_hours_in_production": "",
- "total_hours_in_view": "",
- "total_hours_on_board": "",
- "total_jobs_in_view": "",
- "total_jobs_on_board": "",
- "total_lab_in_production": "",
- "total_lab_in_view": "",
- "total_lab_on_board": "",
- "total_lar_in_production": "",
- "total_lar_in_view": "",
- "total_lar_on_board": ""
- },
- "successes": {
- "removed": ""
- }
- },
- "profile": {
- "errors": {
- "state": "Error al leer el estado de la página. Porfavor refresca."
- },
- "labels": {
- "activeshop": ""
- },
- "successes": {
- "updated": ""
- }
- },
- "reportcenter": {
- "actions": {
- "generate": ""
- },
- "labels": {
- "advanced_filters": "",
- "advanced_filters_false": "",
- "advanced_filters_filter_field": "",
- "advanced_filters_filter_operator": "",
- "advanced_filters_filter_value": "",
- "advanced_filters_filters": "",
- "advanced_filters_hide": "",
- "advanced_filters_show": "",
- "advanced_filters_sorter_direction": "",
- "advanced_filters_sorter_field": "",
- "advanced_filters_sorters": "",
- "advanced_filters_true": "",
- "dates": "",
- "employee": "",
- "filterson": "",
- "generateasemail": "",
- "groups": {
- "customers": "",
- "jobs": "",
- "payroll": "",
- "purchases": "",
- "sales": ""
- },
- "key": "",
- "objects": {
- "appointments": "",
- "bills": "",
- "csi": "",
- "exportlogs": "",
- "jobs": "",
- "parts_orders": "",
- "payments": "",
- "scoreboard": "",
- "tasks": "",
- "timetickets": ""
- },
- "vendor": ""
- },
- "templates": {
- "adp_payroll_flat": "",
- "adp_payroll_straight": "",
- "anticipated_revenue": "",
- "ar_aging": "",
- "attendance_detail": "",
- "attendance_employee": "",
- "attendance_summary": "",
- "committed_timetickets": "",
- "committed_timetickets_employee": "",
- "committed_timetickets_summary": "",
- "credits_not_received_date": "",
- "credits_not_received_date_vendorid": "",
- "csi": "",
- "customer_list": "",
- "cycle_time_analysis": "",
- "estimates_written_converted": "",
- "estimator_detail": "",
- "estimator_summary": "",
- "export_payables": "",
- "export_payments": "",
- "export_receivables": "",
- "exported_gsr_by_ro": "",
- "exported_gsr_by_ro_labor": "",
- "gsr_by_atp": "",
- "gsr_by_ats": "",
- "gsr_by_category": "",
- "gsr_by_csr": "",
- "gsr_by_delivery_date": "",
- "gsr_by_estimator": "",
- "gsr_by_exported_date": "",
- "gsr_by_ins_co": "",
- "gsr_by_make": "",
- "gsr_by_referral": "",
- "gsr_by_ro": "",
- "gsr_labor_only": "",
- "hours_sold_detail_closed": "",
- "hours_sold_detail_closed_csr": "",
- "hours_sold_detail_closed_estimator": "",
- "hours_sold_detail_closed_ins_co": "",
- "hours_sold_detail_closed_status": "",
- "hours_sold_detail_open": "",
- "hours_sold_detail_open_csr": "",
- "hours_sold_detail_open_estimator": "",
- "hours_sold_detail_open_ins_co": "",
- "hours_sold_detail_open_status": "",
- "hours_sold_summary_closed": "",
- "hours_sold_summary_closed_csr": "",
- "hours_sold_summary_closed_estimator": "",
- "hours_sold_summary_closed_ins_co": "",
- "hours_sold_summary_closed_status": "",
- "hours_sold_summary_open": "",
- "hours_sold_summary_open_csr": "",
- "hours_sold_summary_open_estimator": "",
- "hours_sold_summary_open_ins_co": "",
- "hours_sold_summary_open_status": "",
- "job_costing_ro_csr": "",
- "job_costing_ro_date_detail": "",
- "job_costing_ro_date_summary": "",
- "job_costing_ro_estimator": "",
- "job_costing_ro_ins_co": "",
- "job_lifecycle_date_detail": "",
- "job_lifecycle_date_summary": "",
- "jobs_completed_not_invoiced": "",
- "jobs_invoiced_not_exported": "",
- "jobs_reconcile": "",
- "jobs_scheduled_completion": "",
- "lag_time": "",
- "load_level": "",
- "lost_sales": "",
- "open_orders": "",
- "open_orders_csr": "",
- "open_orders_estimator": "",
- "open_orders_excel": "",
- "open_orders_ins_co": "",
- "open_orders_referral": "",
- "open_orders_specific_csr": "",
- "open_orders_status": "",
- "parts_backorder": "",
- "parts_not_recieved": "",
- "parts_not_recieved_vendor": "",
- "parts_received_not_scheduled": "",
- "payments_by_date": "",
- "payments_by_date_payment": "",
- "payments_by_date_type": "",
- "production_by_category": "",
- "production_by_category_one": "",
- "production_by_csr": "",
- "production_by_last_name": "",
- "production_by_repair_status": "",
- "production_by_repair_status_one": "",
- "production_by_ro": "",
- "production_by_target_date": "",
- "production_by_technician": "",
- "production_by_technician_one": "",
- "production_not_production_status": "",
- "production_over_time": "",
- "psr_by_make": "",
- "purchase_return_ratio_excel": "",
- "purchase_return_ratio_grouped_by_vendor_detail": "",
- "purchase_return_ratio_grouped_by_vendor_summary": "",
- "purchases_by_cost_center_detail": "",
- "purchases_by_cost_center_summary": "",
- "purchases_by_date_excel": "",
- "purchases_by_date_range_detail": "",
- "purchases_by_date_range_summary": "",
- "purchases_by_ro_detail_date": "",
- "purchases_by_ro_summary_date": "",
- "purchases_by_vendor_detailed_date_range": "",
- "purchases_by_vendor_summary_date_range": "",
- "purchases_grouped_by_vendor_detailed": "",
- "purchases_grouped_by_vendor_summary": "",
- "returns_grouped_by_vendor_detailed": "",
- "returns_grouped_by_vendor_summary": "",
- "schedule": "",
- "scheduled_parts_list": "",
- "scoreboard_detail": "",
- "scoreboard_summary": "",
- "supplement_ratio_ins_co": "",
- "tasks_date": "",
- "tasks_date_employee": "",
- "thank_you_date": "",
- "timetickets": "",
- "timetickets_employee": "",
- "timetickets_summary": "",
- "total_loss_jobs": "",
- "unclaimed_hrs": "",
- "void_ros": "",
- "work_in_progress_committed_labour": "",
- "work_in_progress_jobs": "",
- "work_in_progress_labour": "",
- "work_in_progress_payables": ""
- }
- },
- "schedule": {
- "labels": {
- "atssummary": "",
- "employeevacation": "",
- "estimators": "",
- "ins_co_nm_filter": "",
- "intake": "",
- "manual": "",
- "manualevent": ""
- }
- },
- "scoreboard": {
- "actions": {
- "edit": ""
- },
- "errors": {
- "adding": "",
- "removing": "",
- "updating": ""
- },
- "fields": {
- "bodyhrs": "",
- "date": "",
- "painthrs": ""
- },
- "labels": {
- "allemployeetimetickets": "",
- "asoftodaytarget": "",
- "body": "",
- "bodyabbrev": "",
- "bodycharttitle": "",
- "calendarperiod": "",
- "combinedcharttitle": "",
- "dailyactual": "",
- "dailytarget": "",
- "efficiencyoverperiod": "",
- "entries": "",
- "jobs": "",
- "jobscompletednotinvoiced": "",
- "lastmonth": "",
- "lastweek": "",
- "monthlytarget": "",
- "priorweek": "",
- "productivestatistics": "",
- "productivetimeticketsoverdate": "",
- "refinish": "",
- "refinishabbrev": "",
- "refinishcharttitle": "",
- "targets": "",
- "thismonth": "",
- "thisweek": "",
- "timetickets": "",
- "timeticketsemployee": "",
- "todateactual": "",
- "total": "",
- "totalhrs": "",
- "totaloverperiod": "",
- "weeklyactual": "",
- "weeklytarget": "",
- "workingdays": ""
- },
- "successes": {
- "added": "",
- "removed": "",
- "updated": ""
- }
- },
- "tasks": {
- "actions": {
- "edit": "",
- "new": "",
- "view": ""
- },
- "buttons": {
- "allTasks": "",
- "complete": "",
- "create": "",
- "delete": "",
- "edit": "",
- "myTasks": "",
- "refresh": ""
- },
- "date_presets": {
- "completion": "",
- "day": "",
- "days": "",
- "delivery": "",
- "next_week": "",
- "one_month": "",
- "three_months": "",
- "three_weeks": "",
- "today": "",
- "tomorrow": "",
- "two_weeks": ""
- },
- "failures": {
- "completed": "",
- "created": "",
- "deleted": "",
- "updated": ""
- },
- "fields": {
- "actions": "",
- "assigned_to": "",
- "bill": "",
- "billid": "",
- "completed": "",
- "created_at": "",
- "created_by": "",
- "description": "",
- "due_date": "",
- "job": {
- "ro_number": ""
- },
- "jobid": "",
- "jobline": "",
- "joblineid": "",
- "parts_order": "",
- "partsorderid": "",
- "priorities": {
- "high": "",
- "low": "",
- "medium": ""
- },
- "priority": "",
- "related_items": "",
- "remind_at": "",
- "title": ""
- },
- "placeholders": {
- "assigned_to": "",
- "billid": "",
- "description": "",
- "jobid": "",
- "joblineid": "",
- "partsorderid": ""
- },
- "successes": {
- "completed": "",
- "created": "",
- "deleted": "",
- "updated": ""
- },
- "titles": {
- "all_tasks": "",
- "completed": "",
- "deleted": "",
- "job_tasks": "",
- "mine": "",
- "my_tasks": ""
- },
- "validation": {
- "due_at_error_message": "",
- "remind_at_error_message": ""
- }
- },
- "tech": {
- "fields": {
- "employeeid": "",
- "pin": ""
- },
- "labels": {
- "loggedin": "",
- "notloggedin": ""
- }
- },
- "templates": {
- "errors": {
- "updating": ""
- },
- "successes": {
- "updated": ""
- }
- },
- "timetickets": {
- "actions": {
- "claimtasks": "",
- "clockin": "",
- "clockout": "",
- "commit": "",
- "commitone": "",
- "enter": "",
- "payall": "",
- "printemployee": "",
- "uncommit": ""
- },
- "errors": {
- "clockingin": "",
- "clockingout": "",
- "creating": "",
- "deleting": "",
- "noemployeeforuser": "",
- "noemployeeforuser_sub": "",
- "payall": "",
- "shiftalreadyclockedon": ""
- },
- "fields": {
- "actualhrs": "",
- "ciecacode": "",
- "clockhours": "",
- "clockoff": "",
- "clockon": "",
- "committed": "",
- "committed_at": "",
- "cost_center": "",
- "created_by": "",
- "date": "",
- "efficiency": "",
- "employee": "",
- "employee_team": "",
- "flat_rate": "",
- "memo": "",
- "productivehrs": "",
- "ro_number": "",
- "task_name": ""
- },
- "labels": {
- "alreadyclockedon": "",
- "ambreak": "",
- "amshift": "",
- "claimtaskpreview": "",
- "clockhours": "",
- "clockintojob": "",
- "deleteconfirm": "",
- "edit": "",
- "efficiency": "",
- "flat_rate": "",
- "jobhours": "",
- "lunch": "",
- "new": "",
- "payrollclaimedtasks": "",
- "pmbreak": "",
- "pmshift": "",
- "shift": "",
- "shiftalreadyclockedon": "",
- "straight_time": "",
- "task": "",
- "timetickets": "",
- "unassigned": "",
- "zeroactualnegativeprod": ""
- },
- "successes": {
- "clockedin": "",
- "clockedout": "",
- "committed": "",
- "created": "",
- "deleted": "",
- "payall": ""
- },
- "validation": {
- "clockoffmustbeafterclockon": "",
- "clockoffwithoutclockon": "",
- "hoursenteredmorethanavailable": "",
- "unassignedlines": ""
- }
- },
- "titles": {
- "accounting-payables": "",
- "accounting-payments": "",
- "accounting-receivables": "",
- "all_tasks": "",
- "app": "",
- "bc": {
- "accounting-payables": "",
- "accounting-payments": "",
- "accounting-receivables": "",
- "all_tasks": "",
- "availablejobs": "",
- "bills-list": "",
- "contracts": "",
- "contracts-create": "",
- "contracts-detail": "",
- "courtesycars": "",
- "courtesycars-detail": "",
- "courtesycars-new": "",
- "dashboard": "",
- "dms": "",
- "export-logs": "",
- "inventory": "",
- "jobs": "",
- "jobs-active": "",
- "jobs-admin": "",
- "jobs-all": "",
- "jobs-checklist": "",
- "jobs-close": "",
- "jobs-deliver": "",
- "jobs-detail": "",
- "jobs-intake": "",
- "jobs-new": "",
- "jobs-ready": "",
- "my_tasks": "",
- "owner-detail": "",
- "owners": "",
- "parts-queue": "",
- "payments-all": "",
- "phonebook": "",
- "productionboard": "",
- "productionlist": "",
- "profile": "",
- "schedule": "",
- "scoreboard": "",
- "shop": "",
- "shop-csi": "",
- "shop-templates": "",
- "shop-vendors": "",
- "tasks": "",
- "temporarydocs": "",
- "timetickets": "",
- "ttapprovals": "",
- "vehicle-details": "",
- "vehicles": ""
- },
- "bills-list": "",
- "contracts": "",
- "contracts-create": "",
- "contracts-detail": "",
- "courtesycars": "",
- "courtesycars-create": "",
- "courtesycars-detail": "",
- "dashboard": "",
- "dms": "",
- "export-logs": "",
- "imexonline": "",
- "inventory": "",
- "jobs": "Todos los trabajos | {{app}}",
- "jobs-admin": "",
- "jobs-all": "",
- "jobs-checklist": "",
- "jobs-close": "",
- "jobs-create": "",
- "jobs-deliver": "",
- "jobs-intake": "",
- "jobsavailable": "Empleos disponibles | {{app}}",
- "jobsdetail": "Trabajo {{ro_number}} | {{app}}",
- "jobsdocuments": "Documentos de trabajo {{ro_number}} | {{app}}",
- "manageroot": "Casa | {{app}}",
- "my_tasks": "",
- "owners": "Todos los propietarios | {{app}}",
- "owners-detail": "",
- "parts-queue": "",
- "payments-all": "",
- "phonebook": "",
- "productionboard": "",
- "productionlist": "",
- "profile": "Mi perfil | {{app}}",
- "readyjobs": "",
- "resetpassword": "",
- "resetpasswordvalidate": "",
- "romeonline": "",
- "schedule": "Horario | {{app}}",
- "scoreboard": "",
- "shop": "Mi tienda | {{app}}",
- "shop-csi": "",
- "shop-templates": "",
- "shop_vendors": "Vendedores | {{app}}",
- "tasks": "",
- "techconsole": "{{app}}",
- "techjobclock": "{{app}}",
- "techjoblookup": "{{app}}",
- "techshiftclock": "{{app}}",
- "temporarydocs": "",
- "timetickets": "",
- "ttapprovals": "",
- "vehicledetail": "Detalles del vehículo {{vehicle}} | {{app}}",
- "vehicles": "Todos los vehiculos | {{app}}"
- },
- "trello": {
- "labels": {
- "add_card": "",
- "add_lane": "",
- "cancel": "",
- "delete_lane": "",
- "description": "",
- "label": "",
- "lane_actions": "",
- "title": ""
- }
- },
- "tt_approvals": {
- "actions": {
- "approveselected": ""
- },
- "labels": {
- "approval_queue_in_use": "",
- "calculate": ""
- }
- },
- "upsell": {
- "cta": {
- "learnmore": ""
- },
- "messages": {
- "accounting": {
- "payables": {
- "subtitle": "",
- "title": ""
- },
- "payments": {
- "subtitle": "",
- "title": ""
- },
- "receivables": {
- "subtitle": "",
- "title": ""
- }
- },
- "audit": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "bills": {
- "autoreconcile": {
- "subtitle": "",
- "title": ""
- },
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "checklist": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "courtesycars": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "csi": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "dashboard": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "lifecycle": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "media": {
- "general": {
- "subtitle": "",
- "title": ""
- },
- "mobile": {
- "subtitle": "",
- "title": ""
- }
- },
- "payments": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "scoreboard": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "smartscheduling": {
- "datepicker": {
- "subtitle": "",
- "title": ""
- },
- "general": {
- "subtitle": "",
- "title": ""
- },
- "hrsdelta": {
- "subtitle": "",
- "title": ""
- }
- },
- "techconsole": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "timetickets": {
- "allocations": {
- "subtitle": "",
- "title": ""
- },
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "visualboard": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- }
- }
- },
- "user": {
- "actions": {
- "changepassword": "",
- "signout": "desconectar",
- "updateprofile": "Actualización del perfil"
- },
- "errors": {
- "updating": ""
- },
- "fields": {
- "authlevel": "",
- "displayname": "Nombre para mostrar",
- "email": "",
- "photourl": "URL de avatar"
- },
- "labels": {
- "actions": "",
- "changepassword": "",
- "profileinfo": ""
- },
- "successess": {
- "passwordchanged": ""
- }
- },
- "users": {
- "errors": {
- "signinerror": {
- "auth/user-disabled": "",
- "auth/user-not-found": "",
- "auth/wrong-password": ""
- }
- }
- },
- "vehicles": {
- "errors": {
- "deleting": "",
- "noaccess": "El vehículo no existe o usted no tiene acceso a él.",
- "selectexistingornew": "",
- "validation": "Asegúrese de que todos los campos se ingresen correctamente.",
- "validationtitle": "Error de validacion"
- },
- "fields": {
- "description": "Descripcion del vehiculo",
- "notes": "",
- "plate_no": "Placa",
- "plate_st": "Jurisdicción de placas",
- "trim_color": "Recortar color",
- "v_bstyle": "Tipo de cuerpo",
- "v_color": "Color",
- "v_cond": "condición",
- "v_engine": "Motor",
- "v_make_desc": "Hacer",
- "v_makecode": "Hacer código",
- "v_mldgcode": "Código de moldeo",
- "v_model_desc": "Modelo",
- "v_model_yr": "año",
- "v_options": "Opciones",
- "v_paint_codes": "Códigos de pintura",
- "v_prod_dt": "Fecha de producción",
- "v_stage": "Escenario",
- "v_tone": "Tono",
- "v_trimcode": "Código de recorte",
- "v_type": "Tipo",
- "v_vin": "V.I.N."
- },
- "forms": {
- "detail": "",
- "misc": "",
- "registration": ""
- },
- "labels": {
- "deleteconfirm": "",
- "fromvehicle": "",
- "novehinfo": "",
- "relatedjobs": "",
- "updatevehicle": ""
- },
- "successes": {
- "delete": "",
- "save": "Vehículo guardado con éxito."
- }
- },
- "vendors": {
- "actions": {
- "addtophonebook": "",
- "new": "Nuevo vendedor",
- "newpreferredmake": ""
- },
- "errors": {
- "deleting": "Se encontró un error al eliminar el proveedor.",
- "saving": "Se encontró un error al guardar el proveedor."
- },
- "fields": {
- "active": "",
- "am": "",
- "city": "ciudad",
- "cost_center": "Centro de costos",
- "country": "País",
- "discount": "% De descuento",
- "display_name": "Nombre para mostrar",
- "dmsid": "",
- "due_date": "Fecha de vencimiento del pago",
- "email": "Email de contacto",
- "favorite": "¿Favorito?",
- "lkq": "",
- "make": "",
- "name": "Nombre del vendedor",
- "oem": "",
- "phone": "",
- "prompt_discount": "Descuento pronto",
- "state": "Provincia del estado",
- "street1": "calle",
- "street2": "Dirección 2",
- "taxid": "Identificación del impuesto",
- "terms": "Términos de pago",
- "zip": "código postal"
- },
- "labels": {
- "noneselected": "Ningún vendedor está seleccionado.",
- "preferredmakes": "",
- "search": "Escriba el nombre de un proveedor"
- },
- "successes": {
- "deleted": "Proveedor eliminado correctamente.",
- "saved": "Proveedor guardado con éxito."
- },
- "validation": {
- "unique_vendor_name": ""
- }
- }
- }
+ "translation": {
+ "allocations": {
+ "actions": {
+ "assign": "Asignar"
+ },
+ "errors": {
+ "deleting": "",
+ "saving": "",
+ "validation": ""
+ },
+ "fields": {
+ "employee": "Asignado a"
+ },
+ "successes": {
+ "deleted": "",
+ "save": ""
+ }
+ },
+ "appointments": {
+ "actions": {
+ "block": "",
+ "calculate": "",
+ "cancel": "Cancelar",
+ "intake": "Consumo",
+ "new": "Nueva cita",
+ "preview": "",
+ "reschedule": "Reprogramar",
+ "sendreminder": "",
+ "unblock": "",
+ "viewjob": "Ver trabajo"
+ },
+ "errors": {
+ "blocking": "",
+ "canceling": "Error al cancelar la cita. {{message}}",
+ "saving": "Error al programar la cita. {{message}}"
+ },
+ "fields": {
+ "alt_transport": "",
+ "color": "",
+ "end": "",
+ "note": "",
+ "start": "",
+ "time": "",
+ "title": "Título"
+ },
+ "labels": {
+ "arrivedon": "Llegado el:",
+ "arrivingjobs": "",
+ "blocked": "",
+ "cancelledappointment": "Cita cancelada para:",
+ "completingjobs": "",
+ "dataconsistency": "",
+ "expectedjobs": "",
+ "expectedprodhrs": "",
+ "history": "",
+ "inproduction": "",
+ "manualevent": "",
+ "noarrivingjobs": "",
+ "nocompletingjobs": "",
+ "nodateselected": "No se ha seleccionado ninguna fecha.",
+ "priorappointments": "Nombramientos previos",
+ "reminder": "",
+ "scheduledfor": "Cita programada para:",
+ "severalerrorsfound": "",
+ "smartscheduling": "",
+ "smspaymentreminder": "",
+ "suggesteddates": ""
+ },
+ "successes": {
+ "canceled": "Cita cancelada con éxito.",
+ "created": "Cita programada con éxito.",
+ "saved": ""
+ }
+ },
+ "associations": {
+ "actions": {
+ "activate": "Activar"
+ },
+ "fields": {
+ "active": "¿Activo?",
+ "shopname": "Nombre de tienda"
+ },
+ "labels": {
+ "actions": "Comportamiento"
+ }
+ },
+ "audit": {
+ "fields": {
+ "cc": "",
+ "contents": "",
+ "created": "",
+ "operation": "",
+ "status": "",
+ "subject": "",
+ "to": "",
+ "useremail": "",
+ "values": ""
+ }
+ },
+ "audit_trail": {
+ "messages": {
+ "admin_job_remove_from_ar": "",
+ "admin_jobmarkexported": "",
+ "admin_jobmarkforreexport": "",
+ "admin_jobuninvoice": "",
+ "admin_jobunvoid": "",
+ "alerttoggle": "",
+ "appointmentcancel": "",
+ "appointmentinsert": "",
+ "assignedlinehours": "",
+ "billdeleted": "",
+ "billposted": "",
+ "billupdated": "",
+ "failedpayment": "",
+ "jobassignmentchange": "",
+ "jobassignmentremoved": "",
+ "jobchecklist": "",
+ "jobclosedwithbypass": "",
+ "jobconverted": "",
+ "jobdelivery": "",
+ "jobexported": "",
+ "jobfieldchanged": "",
+ "jobimported": "",
+ "jobinproductionchange": "",
+ "jobintake": "",
+ "jobinvoiced": "",
+ "jobioucreated": "",
+ "jobmodifylbradj": "",
+ "jobnoteadded": "",
+ "jobnotedeleted": "",
+ "jobnoteupdated": "",
+ "jobspartsorder": "",
+ "jobspartsreturn": "",
+ "jobstatuschange": "",
+ "jobsupplement": "",
+ "jobsuspend": "",
+ "jobvoid": "",
+ "tasks_completed": "",
+ "tasks_created": "",
+ "tasks_deleted": "",
+ "tasks_uncompleted": "",
+ "tasks_undeleted": "",
+ "tasks_updated": ""
+ }
+ },
+ "billlines": {
+ "actions": {
+ "newline": ""
+ },
+ "fields": {
+ "actual_cost": "",
+ "actual_price": "",
+ "cost_center": "",
+ "federal_tax_applicable": "",
+ "jobline": "",
+ "line_desc": "",
+ "local_tax_applicable": "",
+ "location": "",
+ "quantity": "",
+ "state_tax_applicable": ""
+ },
+ "labels": {
+ "deductedfromlbr": "",
+ "entered": "",
+ "from": "",
+ "mod_lbr_adjustment": "",
+ "other": "",
+ "reconciled": "",
+ "unreconciled": ""
+ },
+ "validation": {
+ "atleastone": ""
+ }
+ },
+ "bills": {
+ "actions": {
+ "deductallhours": "",
+ "edit": "",
+ "receive": "",
+ "return": ""
+ },
+ "errors": {
+ "creating": "",
+ "deleting": "",
+ "existinginventoryline": "",
+ "exporting": "",
+ "exporting-partner": "",
+ "invalidro": "",
+ "invalidvendor": "",
+ "validation": ""
+ },
+ "fields": {
+ "allpartslocation": "",
+ "date": "",
+ "exported": "",
+ "federal_tax_rate": "",
+ "invoice_number": "",
+ "is_credit_memo": "",
+ "is_credit_memo_short": "",
+ "local_tax_rate": "",
+ "ro_number": "",
+ "state_tax_rate": "",
+ "total": "",
+ "vendor": "",
+ "vendorname": ""
+ },
+ "labels": {
+ "actions": "",
+ "bill_lines": "",
+ "bill_total": "",
+ "billcmtotal": "",
+ "bills": "",
+ "calculatedcreditsnotreceived": "",
+ "creditsnotreceived": "",
+ "creditsreceived": "",
+ "dedfromlbr": "",
+ "deleteconfirm": "",
+ "discrepancy": "",
+ "discrepwithcms": "",
+ "discrepwithlbradj": "",
+ "editadjwarning": "",
+ "entered_total": "",
+ "enteringcreditmemo": "",
+ "federal_tax": "",
+ "federal_tax_exempt": "",
+ "generatepartslabel": "",
+ "iouexists": "",
+ "local_tax": "",
+ "markexported": "",
+ "markforreexport": "",
+ "new": "",
+ "nobilllines": "",
+ "noneselected": "",
+ "onlycmforinvoiced": "",
+ "printlabels": "",
+ "retailtotal": "",
+ "returnfrombill": "",
+ "savewithdiscrepancy": "",
+ "state_tax": "",
+ "subtotal": "",
+ "totalreturns": ""
+ },
+ "successes": {
+ "created": "",
+ "deleted": "",
+ "exported": "",
+ "markexported": "",
+ "reexport": ""
+ },
+ "validation": {
+ "closingperiod": "",
+ "inventoryquantity": "",
+ "manualinhouse": "",
+ "unique_invoice_number": ""
+ }
+ },
+ "bodyshop": {
+ "actions": {
+ "add_task_preset": "",
+ "addapptcolor": "",
+ "addbucket": "",
+ "addpartslocation": "",
+ "addpartsrule": "",
+ "addspeedprint": "",
+ "addtemplate": "",
+ "newlaborrate": "",
+ "newsalestaxcode": "",
+ "newstatus": "",
+ "testrender": ""
+ },
+ "errors": {
+ "creatingdefaultview": "",
+ "loading": "No se pueden cargar los detalles de la tienda. Por favor llame al soporte técnico.",
+ "saving": ""
+ },
+ "fields": {
+ "ReceivableCustomField": "",
+ "address1": "",
+ "address2": "",
+ "appt_alt_transport": "",
+ "appt_colors": {
+ "color": "",
+ "label": ""
+ },
+ "appt_length": "",
+ "attach_pdf_to_email": "",
+ "batchid": "",
+ "bill_allow_post_to_closed": "",
+ "bill_federal_tax_rate": "",
+ "bill_local_tax_rate": "",
+ "bill_state_tax_rate": "",
+ "city": "",
+ "closingperiod": "",
+ "companycode": "",
+ "country": "",
+ "dailybodytarget": "",
+ "dailypainttarget": "",
+ "default_adjustment_rate": "",
+ "deliver": {
+ "require_actual_delivery_date": "",
+ "templates": ""
+ },
+ "dms": {
+ "apcontrol": "",
+ "appostingaccount": "",
+ "cashierid": "",
+ "default_journal": "",
+ "disablebillwip": "",
+ "disablecontactvehiclecreation": "",
+ "dms_acctnumber": "",
+ "dms_control_override": "",
+ "dms_wip_acctnumber": "",
+ "generic_customer_number": "",
+ "itc_federal": "",
+ "itc_local": "",
+ "itc_state": "",
+ "mappingname": "",
+ "sendmaterialscosting": "",
+ "srcco": ""
+ },
+ "email": "",
+ "enforce_class": "",
+ "enforce_conversion_category": "",
+ "enforce_conversion_csr": "",
+ "enforce_referral": "",
+ "federal_tax_id": "",
+ "ignoreblockeddays": "",
+ "inhousevendorid": "",
+ "insurance_vendor_id": "",
+ "intake": {
+ "next_contact_hours": "",
+ "templates": ""
+ },
+ "intellipay_config": {
+ "cash_discount_percentage": "",
+ "enable_cash_discount": "",
+ "payment_type": "",
+ "payment_map": {
+ "amex": "American Express",
+ "disc": "Discover",
+ "dnrs": "Diners",
+ "intr": "Interac",
+ "jcb": "JCB",
+ "mast": "MasterCard",
+ "visa": "Visa"
+ }
+ },
+ "invoice_federal_tax_rate": "",
+ "invoice_local_tax_rate": "",
+ "invoice_state_tax_rate": "",
+ "jc_hourly_rates": {
+ "mapa": "",
+ "mash": ""
+ },
+ "last_name_first": "",
+ "lastnumberworkingdays": "",
+ "localmediaserverhttp": "",
+ "localmediaservernetwork": "",
+ "localmediatoken": "",
+ "logo_img_footer_margin": "",
+ "logo_img_header_margin": "",
+ "logo_img_path": "",
+ "logo_img_path_height": "",
+ "logo_img_path_width": "",
+ "md_categories": "",
+ "md_ccc_rates": "",
+ "md_classes": "",
+ "md_ded_notes": "",
+ "md_email_cc": "",
+ "md_from_emails": "",
+ "md_functionality_toggles": {
+ "parts_queue_toggle": ""
+ },
+ "md_hour_split": {
+ "paint": "",
+ "prep": ""
+ },
+ "md_ins_co": {
+ "city": "",
+ "name": "",
+ "private": "",
+ "state": "",
+ "street1": "",
+ "street2": "",
+ "zip": ""
+ },
+ "md_jobline_presets": "",
+ "md_lost_sale_reasons": "",
+ "md_parts_order_comment": "",
+ "md_parts_scan": {
+ "caseInsensitive": "",
+ "expression": "",
+ "field": "",
+ "flags": "",
+ "mark_critical": "",
+ "operation": "",
+ "update_field": "",
+ "update_value": "",
+ "value": ""
+ },
+ "md_payment_types": "",
+ "md_referral_sources": "",
+ "md_ro_guard": {
+ "enabled": "",
+ "enforce_ar": "",
+ "enforce_bills": "",
+ "enforce_cm": "",
+ "enforce_labor": "",
+ "enforce_ppd": "",
+ "enforce_profit": "",
+ "enforce_sublet": "",
+ "masterbypass": "",
+ "totalgppercent_minimum": ""
+ },
+ "md_tasks_presets": {
+ "enable_tasks": "",
+ "hourstype": "",
+ "memo": "",
+ "name": "",
+ "nextstatus": "",
+ "percent": "",
+ "use_approvals": ""
+ },
+ "messaginglabel": "",
+ "messagingtext": "",
+ "noteslabel": "",
+ "notestext": "",
+ "partslocation": "",
+ "phone": "",
+ "prodtargethrs": "",
+ "rbac": {
+ "accounting": {
+ "exportlog": "",
+ "payables": "",
+ "payments": "",
+ "receivables": ""
+ },
+ "bills": {
+ "delete": "",
+ "enter": "",
+ "list": "",
+ "reexport": "",
+ "view": ""
+ },
+ "contracts": {
+ "create": "",
+ "detail": "",
+ "list": ""
+ },
+ "courtesycar": {
+ "create": "",
+ "detail": "",
+ "list": ""
+ },
+ "csi": {
+ "export": "",
+ "page": ""
+ },
+ "employee_teams": {
+ "page": ""
+ },
+ "employees": {
+ "page": ""
+ },
+ "inventory": {
+ "delete": "",
+ "list": ""
+ },
+ "jobs": {
+ "admin": "",
+ "available-list": "",
+ "checklist-view": "",
+ "close": "",
+ "create": "",
+ "deliver": "",
+ "detail": "",
+ "intake": "",
+ "list-active": "",
+ "list-all": "",
+ "list-ready": "",
+ "partsqueue": "",
+ "void": ""
+ },
+ "owners": {
+ "detail": "",
+ "list": ""
+ },
+ "payments": {
+ "enter": "",
+ "list": ""
+ },
+ "phonebook": {
+ "edit": "",
+ "view": ""
+ },
+ "production": {
+ "board": "",
+ "list": ""
+ },
+ "schedule": {
+ "view": ""
+ },
+ "scoreboard": {
+ "view": ""
+ },
+ "shiftclock": {
+ "view": ""
+ },
+ "shop": {
+ "config": "",
+ "dashboard": "",
+ "rbac": "",
+ "reportcenter": "",
+ "templates": "",
+ "vendors": ""
+ },
+ "temporarydocs": {
+ "view": ""
+ },
+ "timetickets": {
+ "edit": "",
+ "editcommitted": "",
+ "enter": "",
+ "list": "",
+ "shiftedit": ""
+ },
+ "ttapprovals": {
+ "approve": "",
+ "view": ""
+ },
+ "users": {
+ "editaccess": ""
+ }
+ },
+ "responsibilitycenter": "",
+ "responsibilitycenter_accountdesc": "",
+ "responsibilitycenter_accountitem": "",
+ "responsibilitycenter_accountname": "",
+ "responsibilitycenter_accountnumber": "",
+ "responsibilitycenter_rate": "",
+ "responsibilitycenter_tax_rate": "",
+ "responsibilitycenter_tax_sur": "",
+ "responsibilitycenter_tax_thres": "",
+ "responsibilitycenter_tax_tier": "",
+ "responsibilitycenter_tax_type": "",
+ "responsibilitycenters": {
+ "ap": "",
+ "ar": "",
+ "ats": "",
+ "federal_tax": "",
+ "federal_tax_itc": "",
+ "gst_override": "",
+ "invoiceexemptcode": "",
+ "itemexemptcode": "",
+ "la1": "",
+ "la2": "",
+ "la3": "",
+ "la4": "",
+ "laa": "",
+ "lab": "",
+ "lad": "",
+ "lae": "",
+ "laf": "",
+ "lag": "",
+ "lam": "",
+ "lar": "",
+ "las": "",
+ "lau": "",
+ "local_tax": "",
+ "mapa": "",
+ "mash": "",
+ "paa": "",
+ "pac": "",
+ "pag": "",
+ "pal": "",
+ "pam": "",
+ "pan": "",
+ "pao": "",
+ "pap": "",
+ "par": "",
+ "pas": "",
+ "pasl": "",
+ "refund": "",
+ "sales_tax_codes": {
+ "code": "",
+ "description": "",
+ "federal": "",
+ "local": "",
+ "state": ""
+ },
+ "state_tax": "",
+ "tow": ""
+ },
+ "schedule_end_time": "",
+ "schedule_start_time": "",
+ "shopname": "",
+ "speedprint": {
+ "id": "",
+ "label": "",
+ "templates": ""
+ },
+ "ss_configuration": {
+ "dailyhrslimit": ""
+ },
+ "ssbuckets": {
+ "color": "",
+ "gte": "",
+ "id": "",
+ "label": "",
+ "lt": "",
+ "target": ""
+ },
+ "state": "",
+ "state_tax_id": "",
+ "status": "",
+ "statuses": {
+ "active_statuses": "",
+ "additional_board_statuses": "",
+ "color": "",
+ "default_arrived": "",
+ "default_bo": "",
+ "default_canceled": "",
+ "default_completed": "",
+ "default_delivered": "",
+ "default_exported": "",
+ "default_imported": "",
+ "default_invoiced": "",
+ "default_ordered": "",
+ "default_quote": "",
+ "default_received": "",
+ "default_returned": "",
+ "default_scheduled": "",
+ "default_void": "",
+ "open_statuses": "",
+ "post_production_statuses": "",
+ "pre_production_statuses": "",
+ "production_colors": "",
+ "production_statuses": "",
+ "ready_statuses": ""
+ },
+ "target_touchtime": "",
+ "timezone": "",
+ "tt_allow_post_to_invoiced": "",
+ "tt_enforce_hours_for_tech_console": "",
+ "use_fippa": "",
+ "use_paint_scale_data": "",
+ "uselocalmediaserver": "",
+ "website": "",
+ "zip_post": ""
+ },
+ "labels": {
+ "2tiername": "",
+ "2tiersetup": "",
+ "2tiersource": "",
+ "accountingsetup": "",
+ "accountingtiers": "",
+ "alljobstatuses": "",
+ "allopenjobstatuses": "",
+ "apptcolors": "",
+ "businessinformation": "",
+ "checklists": "",
+ "csiq": "",
+ "customtemplates": "",
+ "defaultcostsmapping": "",
+ "defaultprofitsmapping": "",
+ "deliverchecklist": "",
+ "dms": {
+ "cdk": {
+ "controllist": "",
+ "payers": ""
+ },
+ "cdk_dealerid": "",
+ "costsmapping": "",
+ "dms_allocations": "",
+ "pbs_serialnumber": "",
+ "profitsmapping": "",
+ "title": ""
+ },
+ "emaillater": "",
+ "employee_teams": "",
+ "employees": "",
+ "estimators": "",
+ "filehandlers": "",
+ "imexpay": "",
+ "insurancecos": "",
+ "intakechecklist": "",
+ "intellipay_cash_discount": "",
+ "jobstatuses": "",
+ "laborrates": "",
+ "licensing": "",
+ "md_parts_scan": "",
+ "md_ro_guard": "",
+ "md_tasks_presets": "",
+ "md_to_emails": "",
+ "md_to_emails_emails": "",
+ "messagingpresets": "",
+ "notemplatesavailable": "",
+ "notespresets": "",
+ "orderstatuses": "",
+ "partslocations": "",
+ "partsscan": "",
+ "printlater": "",
+ "qbo": "",
+ "qbo_departmentid": "",
+ "qbo_usa": "",
+ "rbac": "",
+ "responsibilitycenters": {
+ "costs": "",
+ "profits": "",
+ "sales_tax_codes": "",
+ "tax_accounts": "",
+ "title": "",
+ "ttl_adjustment": "",
+ "ttl_tax_adjustment": ""
+ },
+ "roguard": {
+ "title": ""
+ },
+ "romepay": "",
+ "scheduling": "",
+ "scoreboardsetup": "",
+ "shop_enabled_features": "",
+ "shopinfo": "",
+ "shoprates": "",
+ "speedprint": "",
+ "ssbuckets": "",
+ "systemsettings": "",
+ "task-presets": "",
+ "workingdays": ""
+ },
+ "operations": {
+ "contains": "",
+ "ends_with": "",
+ "equals": "",
+ "greater_than": "",
+ "less_than": "",
+ "not_equals": "",
+ "starts_with": ""
+ },
+ "successes": {
+ "areyousure": "",
+ "defaultviewcreated": "",
+ "save": "",
+ "unsavedchanges": ""
+ },
+ "tooltips": {
+ "md_parts_scan": {
+ "update_value_tooltip": ""
+ }
+ },
+ "validation": {
+ "centermustexist": "",
+ "larsplit": "",
+ "useremailmustexist": ""
+ }
+ },
+ "checklist": {
+ "actions": {
+ "printall": ""
+ },
+ "errors": {
+ "complete": "",
+ "nochecklist": ""
+ },
+ "labels": {
+ "addtoproduction": "",
+ "allow_text_message": "",
+ "checklist": "",
+ "printpack": "",
+ "removefromproduction": ""
+ },
+ "successes": {
+ "completed": ""
+ }
+ },
+ "contracts": {
+ "actions": {
+ "changerate": "",
+ "convertoro": "",
+ "decodelicense": "",
+ "find": "",
+ "printcontract": "",
+ "senddltoform": ""
+ },
+ "errors": {
+ "fetchingjobinfo": "",
+ "returning": "",
+ "saving": "",
+ "selectjobandcar": ""
+ },
+ "fields": {
+ "actax": "",
+ "actualreturn": "",
+ "agreementnumber": "",
+ "cc_cardholder": "",
+ "cc_expiry": "",
+ "cc_num": "",
+ "cleanupcharge": "",
+ "coverage": "",
+ "dailyfreekm": "",
+ "dailyrate": "",
+ "damage": "",
+ "damagewaiver": "",
+ "driver": "",
+ "driver_addr1": "",
+ "driver_addr2": "",
+ "driver_city": "",
+ "driver_dlexpiry": "",
+ "driver_dlnumber": "",
+ "driver_dlst": "",
+ "driver_dob": "",
+ "driver_fn": "",
+ "driver_ln": "",
+ "driver_ph1": "",
+ "driver_state": "",
+ "driver_zip": "",
+ "excesskmrate": "",
+ "federaltax": "",
+ "fuelin": "",
+ "fuelout": "",
+ "kmend": "",
+ "kmstart": "",
+ "length": "",
+ "localtax": "",
+ "refuelcharge": "",
+ "scheduledreturn": "",
+ "start": " ",
+ "statetax": "",
+ "status": ""
+ },
+ "labels": {
+ "agreement": "",
+ "availablecars": "",
+ "cardueforservice": "",
+ "convertform": {
+ "applycleanupcharge": "",
+ "refuelqty": ""
+ },
+ "correctdataonform": "",
+ "dateinpast": "",
+ "dlexpirebeforereturn": "",
+ "driverinformation": "",
+ "findcontract": "",
+ "findermodal": "",
+ "insuranceexpired": "",
+ "noteconvertedfrom": "",
+ "populatefromjob": "",
+ "rates": "",
+ "time": "",
+ "vehicle": "",
+ "waitingforscan": ""
+ },
+ "status": {
+ "new": "",
+ "out": "",
+ "returned": ""
+ },
+ "successes": {
+ "saved": ""
+ }
+ },
+ "courtesycars": {
+ "actions": {
+ "new": "",
+ "return": ""
+ },
+ "errors": {
+ "saving": ""
+ },
+ "fields": {
+ "color": "",
+ "dailycost": "",
+ "damage": "",
+ "fleetnumber": "",
+ "fuel": "",
+ "insuranceexpires": "",
+ "leaseenddate": "",
+ "make": "",
+ "mileage": "",
+ "model": "",
+ "nextservicedate": "",
+ "nextservicekm": "",
+ "notes": "",
+ "plate": "",
+ "purchasedate": "",
+ "readiness": "",
+ "registrationexpires": "",
+ "serviceenddate": "",
+ "servicestartdate": "",
+ "status": "",
+ "vin": "",
+ "year": ""
+ },
+ "labels": {
+ "courtesycar": "",
+ "fuel": {
+ "12": "",
+ "14": "",
+ "18": "",
+ "34": "",
+ "38": "",
+ "58": "",
+ "78": "",
+ "empty": "",
+ "full": ""
+ },
+ "outwith": "",
+ "return": "",
+ "status": "",
+ "uniquefleet": "",
+ "usage": "",
+ "vehicle": ""
+ },
+ "readiness": {
+ "notready": "",
+ "ready": ""
+ },
+ "status": {
+ "in": "",
+ "inservice": "",
+ "leasereturn": "",
+ "out": "",
+ "sold": "",
+ "unavailable": ""
+ },
+ "successes": {
+ "saved": ""
+ }
+ },
+ "csi": {
+ "actions": {
+ "activate": ""
+ },
+ "errors": {
+ "creating": "",
+ "notconfigured": "",
+ "notfoundsubtitle": "",
+ "notfoundtitle": "",
+ "surveycompletesubtitle": "",
+ "surveycompletetitle": ""
+ },
+ "fields": {
+ "completedon": "",
+ "created_at": "",
+ "surveyid": "",
+ "validuntil": ""
+ },
+ "labels": {
+ "copyright": "",
+ "greeting": "",
+ "intro": "",
+ "nologgedinuser": "",
+ "nologgedinuser_sub": "",
+ "noneselected": "",
+ "title": ""
+ },
+ "successes": {
+ "created": "",
+ "submitted": "",
+ "submittedsub": ""
+ }
+ },
+ "dashboard": {
+ "actions": {
+ "addcomponent": ""
+ },
+ "errors": {
+ "refreshrequired": "",
+ "updatinglayout": ""
+ },
+ "labels": {
+ "bodyhrs": "",
+ "dollarsinproduction": "",
+ "phone": "",
+ "prodhrs": "",
+ "refhrs": ""
+ },
+ "titles": {
+ "joblifecycle": "",
+ "labhours": "",
+ "larhours": "",
+ "monthlyemployeeefficiency": "",
+ "monthlyjobcosting": "",
+ "monthlylaborsales": "",
+ "monthlypartssales": "",
+ "monthlyrevenuegraph": "",
+ "prodhrssummary": "",
+ "productiondollars": "",
+ "productionhours": "",
+ "projectedmonthlysales": "",
+ "scheduledindate": "",
+ "scheduledintoday": "",
+ "scheduledoutdate": "",
+ "scheduledouttoday": "",
+ "tasks": ""
+ }
+ },
+ "dms": {
+ "errors": {
+ "alreadyexported": ""
+ },
+ "labels": {
+ "refreshallocations": ""
+ }
+ },
+ "documents": {
+ "actions": {
+ "delete": "",
+ "download": "",
+ "reassign": "",
+ "selectallimages": "",
+ "selectallotherdocuments": ""
+ },
+ "errors": {
+ "deletes3": "Error al eliminar el documento del almacenamiento.",
+ "deleting": "",
+ "deleting_cloudinary": "",
+ "getpresignurl": "Error al obtener la URL prescrita para el documento. {{message}}",
+ "insert": "Incapaz de cargar el archivo. {{message}}",
+ "nodocuments": "No hay documentos",
+ "updating": ""
+ },
+ "labels": {
+ "confirmdelete": "",
+ "doctype": "",
+ "dragtoupload": "",
+ "newjobid": "",
+ "openinexplorer": "",
+ "optimizedimage": "",
+ "reassign_limitexceeded": "",
+ "reassign_limitexceeded_title": "",
+ "storageexceeded": "",
+ "storageexceeded_title": "",
+ "upload": "Subir",
+ "upload_limitexceeded": "",
+ "upload_limitexceeded_title": "",
+ "uploading": "",
+ "usage": ""
+ },
+ "successes": {
+ "delete": "Documento eliminado con éxito.",
+ "edituploaded": "",
+ "insert": "Documento cargado con éxito.",
+ "updated": ""
+ }
+ },
+ "emails": {
+ "errors": {
+ "notsent": "Correo electrónico no enviado Se encontró un error al enviar {{message}}"
+ },
+ "fields": {
+ "cc": "",
+ "from": "",
+ "subject": "",
+ "to": ""
+ },
+ "labels": {
+ "attachments": "",
+ "documents": "",
+ "emailpreview": "",
+ "generatingemail": "",
+ "pdfcopywillbeattached": "",
+ "preview": ""
+ },
+ "successes": {
+ "sent": "Correo electrónico enviado con éxito."
+ }
+ },
+ "employee_teams": {
+ "actions": {
+ "new": "",
+ "newmember": ""
+ },
+ "fields": {
+ "active": "",
+ "employeeid": "",
+ "max_load": "",
+ "name": "",
+ "percentage": ""
+ }
+ },
+ "employees": {
+ "actions": {
+ "addvacation": "",
+ "new": "Nuevo empleado",
+ "newrate": ""
+ },
+ "errors": {
+ "delete": "Se encontró un error al eliminar al empleado. {{message}}",
+ "save": "Se encontró un error al salvar al empleado. {{message}}",
+ "validation": "Por favor verifique todos los campos.",
+ "validationtitle": "No se puede salvar al empleado."
+ },
+ "fields": {
+ "active": "¿Activo?",
+ "base_rate": "Tasa básica",
+ "cost_center": "Centro de costos",
+ "employee_number": "Numero de empleado",
+ "external_id": "",
+ "first_name": "Nombre de pila",
+ "flat_rate": "Tarifa plana (deshabilitado es tiempo recto)",
+ "hire_date": "Fecha de contratación",
+ "last_name": "Apellido",
+ "pin": "",
+ "rate": "",
+ "termination_date": "Fecha de conclusión",
+ "user_email": "",
+ "vacation": {
+ "end": "",
+ "length": "",
+ "start": ""
+ }
+ },
+ "labels": {
+ "actions": "",
+ "active": "",
+ "endmustbeafterstart": "",
+ "flat_rate": "",
+ "inactive": "",
+ "name": "",
+ "rate_type": "",
+ "status": "",
+ "straight_time": ""
+ },
+ "successes": {
+ "delete": "Empleado eliminado con éxito.",
+ "save": "Empleado guardado con éxito.",
+ "vacationadded": ""
+ },
+ "validation": {
+ "unique_employee_number": ""
+ }
+ },
+ "eula": {
+ "buttons": {
+ "accept": "Accept EULA"
+ },
+ "content": {
+ "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting."
+ },
+ "errors": {
+ "acceptance": {
+ "description": "Something went wrong while accepting the EULA. Please try again.",
+ "message": "Eula Acceptance Error"
+ }
+ },
+ "labels": {
+ "accepted_terms": "I accept the terms and conditions of this agreement.",
+ "address": "Address",
+ "business_name": "Legal Business Name",
+ "date_accepted": "Date Accepted",
+ "first_name": "First Name",
+ "last_name": "Last Name",
+ "phone_number": "Phone Number"
+ },
+ "messages": {
+ "accepted_terms": "Please accept the terms and conditions of this agreement.",
+ "business_name": "Please enter your legal business name.",
+ "date_accepted": "Please enter Today's Date.",
+ "first_name": "Please enter your first name.",
+ "last_name": "Please enter your last name.",
+ "phone_number": "Please enter your phone number."
+ },
+ "titles": {
+ "modal": "Terms and Conditions",
+ "upper_card": "Acknowledgement"
+ }
+ },
+ "exportlogs": {
+ "fields": {
+ "createdat": ""
+ },
+ "labels": {
+ "attempts": "",
+ "priorsuccesfulexport": ""
+ }
+ },
+ "general": {
+ "actions": {
+ "add": "",
+ "autoupdate": "",
+ "calculate": "",
+ "cancel": "",
+ "clear": "",
+ "close": "",
+ "copied": "",
+ "copylink": "",
+ "create": "",
+ "defaults": "defaults",
+ "delay": "",
+ "delete": "Borrar",
+ "deleteall": "",
+ "deselectall": "",
+ "download": "",
+ "edit": "Editar",
+ "login": "",
+ "next": "",
+ "ok": "",
+ "previous": "",
+ "print": "",
+ "refresh": "",
+ "remove": "",
+ "remove_alert": "",
+ "reset": " Restablecer a original.",
+ "resetpassword": "",
+ "save": "Salvar",
+ "saveandnew": "",
+ "saveas": "",
+ "selectall": "",
+ "send": "",
+ "sendbysms": "",
+ "senderrortosupport": "",
+ "sharetoteams": "",
+ "submit": "",
+ "tryagain": "",
+ "view": "",
+ "viewreleasenotes": ""
+ },
+ "errors": {
+ "fcm": "",
+ "notfound": "",
+ "sizelimit": ""
+ },
+ "itemtypes": {
+ "contract": "",
+ "courtesycar": "",
+ "job": "",
+ "owner": "",
+ "vehicle": ""
+ },
+ "labels": {
+ "actions": "Comportamiento",
+ "areyousure": "",
+ "barcode": "código de barras",
+ "cancel": "",
+ "clear": "",
+ "confirmpassword": "",
+ "created_at": "",
+ "date": "",
+ "datetime": "",
+ "email": "",
+ "errors": "",
+ "excel": "",
+ "exceptiontitle": "",
+ "friday": "",
+ "globalsearch": "",
+ "help": "",
+ "hours": "",
+ "in": "en",
+ "instanceconflictext": "",
+ "instanceconflictitle": "",
+ "item": "",
+ "label": "",
+ "loading": "Cargando...",
+ "loadingapp": "Cargando {{app}}",
+ "loadingshop": "Cargando datos de la tienda ...",
+ "loggingin": "Iniciando sesión ...",
+ "markedexported": "",
+ "media": "",
+ "message": "",
+ "monday": "",
+ "na": "N / A",
+ "newpassword": "",
+ "no": "",
+ "nointernet": "",
+ "nointernet_sub": "",
+ "none": "",
+ "out": "Afuera",
+ "password": "",
+ "passwordresetsuccess": "",
+ "passwordresetsuccess_sub": "",
+ "passwordresetvalidatesuccess": "",
+ "passwordresetvalidatesuccess_sub": "",
+ "passwordsdonotmatch": "",
+ "print": "",
+ "refresh": "",
+ "reports": "",
+ "required": "",
+ "saturday": "",
+ "search": "Buscar...",
+ "searchresults": "",
+ "selectdate": "",
+ "sendagain": "",
+ "sendby": "",
+ "signin": "",
+ "sms": "",
+ "status": "",
+ "sub_status": {
+ "expired": ""
+ },
+ "successful": "",
+ "sunday": "",
+ "text": "",
+ "thursday": "",
+ "time": "",
+ "total": "",
+ "totals": "",
+ "tuesday": "",
+ "tvmode": "",
+ "unknown": "Desconocido",
+ "unsavedchanges": "",
+ "username": "",
+ "view": "",
+ "wednesday": "",
+ "yes": ""
+ },
+ "languages": {
+ "english": "Inglés",
+ "french": "francés",
+ "spanish": "español"
+ },
+ "messages": {
+ "exception": "",
+ "newversionmessage": "",
+ "newversiontitle": "",
+ "noacctfilepath": "",
+ "nofeatureaccess": "",
+ "noshop": "",
+ "notfoundsub": "",
+ "notfoundtitle": "",
+ "partnernotrunning": "",
+ "rbacunauth": "",
+ "unsavedchanges": "Usted tiene cambios no guardados.",
+ "unsavedchangespopup": ""
+ },
+ "validation": {
+ "dateRangeExceeded": "",
+ "invalidemail": "Por favor introduzca una dirección de correo electrónico válida.",
+ "invalidphone": "",
+ "required": "Este campo es requerido."
+ }
+ },
+ "help": {
+ "actions": {
+ "connect": ""
+ },
+ "labels": {
+ "codeplacholder": "",
+ "rescuedesc": "",
+ "rescuetitle": ""
+ }
+ },
+ "intake": {
+ "labels": {
+ "printpack": ""
+ }
+ },
+ "inventory": {
+ "actions": {
+ "addtoinventory": "",
+ "addtoro": "",
+ "consumefrominventory": "",
+ "edit": "",
+ "new": ""
+ },
+ "errors": {
+ "inserting": ""
+ },
+ "fields": {
+ "comment": "",
+ "manualinvoicenumber": "",
+ "manualvendor": ""
+ },
+ "labels": {
+ "consumedbyjob": "",
+ "deleteconfirm": "",
+ "frombillinvoicenumber": "",
+ "fromvendor": "",
+ "inventory": "",
+ "showall": "",
+ "showavailable": ""
+ },
+ "successes": {
+ "deleted": "",
+ "inserted": "",
+ "updated": ""
+ }
+ },
+ "job_lifecycle": {
+ "columns": {
+ "average_human_readable": "",
+ "average_value": "",
+ "duration": "",
+ "end": "",
+ "human_readable": "",
+ "percentage": "",
+ "relative_end": "",
+ "relative_start": "",
+ "start": "",
+ "status": "",
+ "status_count": "",
+ "value": ""
+ },
+ "content": {
+ "calculated_based_on": "",
+ "current_status_accumulated_time": "",
+ "data_unavailable": "",
+ "jobs_in_since": "",
+ "legend_title": "",
+ "loading": "",
+ "not_available": "",
+ "previous_status_accumulated_time": "",
+ "title": "",
+ "title_durations": "",
+ "title_loading": "",
+ "title_transitions": ""
+ },
+ "errors": {
+ "fetch": "Error al obtener los datos del ciclo de vida del trabajo"
+ },
+ "titles": {
+ "dashboard": "",
+ "top_durations": ""
+ }
+ },
+ "job_payments": {
+ "buttons": {
+ "create_short_link": "",
+ "goback": "",
+ "proceedtopayment": "",
+ "refundpayment": ""
+ },
+ "notifications": {
+ "error": {
+ "description": "",
+ "openingip": "",
+ "title": ""
+ }
+ },
+ "titles": {
+ "amount": "",
+ "dateOfPayment": "",
+ "descriptions": "",
+ "hint": "",
+ "payer": "",
+ "payername": "",
+ "paymentid": "",
+ "paymentnum": "",
+ "paymenttype": "",
+ "refundamount": "",
+ "transactionid": ""
+ }
+ },
+ "joblines": {
+ "actions": {
+ "assign_team": "",
+ "converttolabor": "",
+ "dispatchparts": "",
+ "new": ""
+ },
+ "errors": {
+ "creating": "",
+ "updating": ""
+ },
+ "fields": {
+ "act_price": "Precio actual",
+ "act_price_before_ppc": "",
+ "adjustment": "",
+ "ah_detail_line": "",
+ "alt_partno": "",
+ "amount": "",
+ "assigned_team": "",
+ "assigned_team_name": "",
+ "create_ppc": "",
+ "db_price": "Precio de base de datos",
+ "include_in_part_cnt": "",
+ "lbr_types": {
+ "LA1": "",
+ "LA2": "",
+ "LA3": "",
+ "LA4": "",
+ "LAA": "",
+ "LAB": "",
+ "LAD": "",
+ "LAE": "",
+ "LAF": "",
+ "LAG": "",
+ "LAM": "",
+ "LAR": "",
+ "LAS": "",
+ "LAU": ""
+ },
+ "line_desc": "Descripción de línea",
+ "line_ind": "S#",
+ "line_no": "",
+ "location": "",
+ "mod_lb_hrs": "Horas laborales",
+ "mod_lbr_ty": "Tipo de trabajo",
+ "notes": "",
+ "oem_partno": "OEM parte #",
+ "op_code_desc": "",
+ "part_qty": "",
+ "part_type": "Tipo de parte",
+ "part_types": {
+ "CCC": "",
+ "CCD": "",
+ "CCDR": "",
+ "CCF": "",
+ "CCM": "",
+ "PAA": "",
+ "PAC": "",
+ "PAE": "",
+ "PAG": "",
+ "PAL": "",
+ "PAM": "",
+ "PAN": "",
+ "PAO": "",
+ "PAP": "",
+ "PAR": "",
+ "PAS": "",
+ "PASL": ""
+ },
+ "profitcenter_labor": "",
+ "profitcenter_part": "",
+ "prt_dsmk_m": "",
+ "prt_dsmk_p": "",
+ "status": "Estado",
+ "tax_part": "",
+ "total": "",
+ "unq_seq": "Seq #"
+ },
+ "labels": {
+ "adjustmenttobeadded": "",
+ "billref": "",
+ "convertedtolabor": "",
+ "edit": "Línea de edición",
+ "ioucreated": "",
+ "new": "Nueva línea",
+ "nostatus": "",
+ "presets": ""
+ },
+ "successes": {
+ "created": "",
+ "saved": "",
+ "updated": ""
+ },
+ "validations": {
+ "ahdetailonlyonuserdefinedtypes": "",
+ "hrsrequirediflbrtyp": "",
+ "requiredifparttype": "",
+ "zeropriceexistingpart": ""
+ }
+ },
+ "jobs": {
+ "actions": {
+ "addDocuments": "Agregar documentos de trabajo",
+ "addNote": "Añadir la nota",
+ "addtopartsqueue": "",
+ "addtoproduction": "",
+ "addtoscoreboard": "",
+ "allocate": "",
+ "autoallocate": "",
+ "changefilehandler": "",
+ "changelaborrate": "",
+ "changestatus": "Cambiar Estado",
+ "changestimator": "",
+ "convert": "Convertir",
+ "createiou": "",
+ "deliver": "",
+ "deliver_quick": "",
+ "dms": {
+ "addpayer": "",
+ "createnewcustomer": "",
+ "findmakemodelcode": "",
+ "getmakes": "",
+ "labels": {
+ "refreshallocations": ""
+ },
+ "post": "",
+ "refetchmakesmodels": "",
+ "usegeneric": "",
+ "useselected": ""
+ },
+ "dmsautoallocate": "",
+ "export": "",
+ "exportcustdata": "",
+ "exportselected": "",
+ "filterpartsonly": "",
+ "generatecsi": "",
+ "gotojob": "",
+ "intake": "",
+ "intake_quick": "",
+ "manualnew": "",
+ "mark": "",
+ "markasexported": "",
+ "markpstexempt": "",
+ "markpstexemptconfirm": "",
+ "postbills": "Contabilizar facturas",
+ "printCenter": "Centro de impresión",
+ "recalculate": "",
+ "reconcile": "",
+ "removefromproduction": "",
+ "schedule": "Programar",
+ "sendcsi": "",
+ "sendpartspricechange": "",
+ "sendtodms": "",
+ "sync": "",
+ "taxprofileoverride": "",
+ "taxprofileoverride_confirm": "",
+ "uninvoice": "",
+ "unvoid": "",
+ "viewchecklist": "",
+ "viewdetail": ""
+ },
+ "errors": {
+ "addingtoproduction": "",
+ "cannotintake": "",
+ "closing": "",
+ "creating": "",
+ "deleted": "Error al eliminar el trabajo.",
+ "exporting": "",
+ "exporting-partner": "",
+ "invoicing": "",
+ "noaccess": "Este trabajo no existe o no tiene acceso a él.",
+ "nodamage": "",
+ "nodates": "No hay fechas especificadas para este trabajo.",
+ "nofinancial": "",
+ "nojobselected": "No hay trabajo seleccionado.",
+ "noowner": "Ningún propietario asociado.",
+ "novehicle": "No hay vehículo asociado.",
+ "partspricechange": "",
+ "saving": "Se encontró un error al guardar el registro.",
+ "scanimport": "",
+ "totalscalc": "",
+ "updating": "",
+ "validation": "Asegúrese de que todos los campos se ingresen correctamente.",
+ "validationtitle": "Error de validacion",
+ "voiding": ""
+ },
+ "fields": {
+ "active_tasks": "",
+ "actual_completion": "Realización real",
+ "actual_delivery": "Entrega real",
+ "actual_in": "Real en",
+ "adjustment_bottom_line": "Ajustes",
+ "adjustmenthours": "",
+ "alt_transport": "",
+ "area_of_damage_impact": {
+ "10": "",
+ "11": "",
+ "12": "",
+ "13": "",
+ "14": "",
+ "15": "",
+ "16": "",
+ "25": "",
+ "26": "",
+ "27": "",
+ "28": "",
+ "34": "",
+ "01": "",
+ "02": "",
+ "03": "",
+ "04": "",
+ "05": "",
+ "06": "",
+ "07": "",
+ "08": "",
+ "09": ""
+ },
+ "auto_add_ats": "",
+ "ca_bc_pvrt": "",
+ "ca_customer_gst": "",
+ "ca_gst_registrant": "",
+ "category": "",
+ "ccc": "",
+ "ccd": "",
+ "ccdr": "",
+ "ccf": "",
+ "ccm": "",
+ "cieca_id": "CIECA ID",
+ "cieca_pfl": {
+ "lbr_adjp": "",
+ "lbr_tax_in": "",
+ "lbr_taxp": "",
+ "lbr_tx_in1": "",
+ "lbr_tx_in2": "",
+ "lbr_tx_in3": "",
+ "lbr_tx_in4": "",
+ "lbr_tx_in5": ""
+ },
+ "cieca_pfo": {
+ "stor_t_in1": "",
+ "stor_t_in2": "",
+ "stor_t_in3": "",
+ "stor_t_in4": "",
+ "stor_t_in5": "",
+ "tow_t_in1": "",
+ "tow_t_in2": "",
+ "tow_t_in3": "",
+ "tow_t_in4": "",
+ "tow_t_in5": ""
+ },
+ "claim_total": "Reclamar total",
+ "class": "",
+ "clm_no": "Reclamación #",
+ "clm_total": "Reclamar total",
+ "comment": "",
+ "customerowing": "Cliente debido",
+ "date_estimated": "Fecha estimada",
+ "date_exported": "Exportado",
+ "date_invoiced": "Facturado",
+ "date_last_contacted": "",
+ "date_lost_sale": "",
+ "date_next_contact": "",
+ "date_open": "Abierto",
+ "date_rentalresp": "",
+ "date_repairstarted": "",
+ "date_scheduled": "Programado",
+ "date_towin": "",
+ "date_void": "",
+ "ded_amt": "Deducible",
+ "ded_note": "",
+ "ded_status": "Estado deducible",
+ "depreciation_taxes": "Depreciación / Impuestos",
+ "dms": {
+ "address": "",
+ "amount": "",
+ "center": "",
+ "control_type": {
+ "account_number": ""
+ },
+ "cost": "",
+ "cost_dms_acctnumber": "",
+ "dms_make": "",
+ "dms_model": "",
+ "dms_model_override": "",
+ "dms_unsold": "",
+ "dms_wip_acctnumber": "",
+ "id": "",
+ "inservicedate": "",
+ "journal": "",
+ "lines": "",
+ "name1": "",
+ "payer": {
+ "amount": "",
+ "control_type": "",
+ "controlnumber": "",
+ "dms_acctnumber": "",
+ "name": ""
+ },
+ "sale": "",
+ "sale_dms_acctnumber": "",
+ "story": "",
+ "vinowner": ""
+ },
+ "dms_allocation": "",
+ "driveable": "",
+ "employee_body": "",
+ "employee_csr": "Representante de servicio al cliente.",
+ "employee_csr_writer": "",
+ "employee_prep": "",
+ "employee_refinish": "",
+ "est_addr1": "Dirección del tasador",
+ "est_co_nm": "Tasador",
+ "est_ct_fn": "Nombre del tasador",
+ "est_ct_ln": "Apellido del tasador",
+ "est_ea": "Correo electrónico del tasador",
+ "est_ph1": "Número de teléfono del tasador",
+ "flat_rate_ats": "",
+ "federal_tax_payable": "Impuesto federal por pagar",
+ "federal_tax_rate": "",
+ "ins_addr1": "Dirección de Insurance Co.",
+ "ins_city": "Ciudad de seguros",
+ "ins_co_id": "ID de la compañía de seguros",
+ "ins_co_nm": "Nombre de la compañía de seguros",
+ "ins_co_nm_short": "",
+ "ins_ct_fn": "Nombre del controlador de archivos",
+ "ins_ct_ln": "Apellido del manejador de archivos",
+ "ins_ea": "Correo electrónico del controlador de archivos",
+ "ins_ph1": "File Handler Phone #",
+ "intake": {
+ "label": "",
+ "max": "",
+ "min": "",
+ "name": "",
+ "required": "",
+ "type": ""
+ },
+ "invoice_final_note": "",
+ "kmin": "Kilometraje en",
+ "kmout": "Kilometraje",
+ "la1": "",
+ "la2": "",
+ "la3": "",
+ "la4": "",
+ "laa": "",
+ "lab": "",
+ "labor_rate_desc": "Nombre de la tasa laboral",
+ "lad": "",
+ "lae": "",
+ "laf": "",
+ "lag": "",
+ "lam": "",
+ "lar": "",
+ "las": "",
+ "lau": "",
+ "local_tax_rate": "",
+ "loss_date": "Fecha de pérdida",
+ "loss_desc": "",
+ "loss_of_use": "",
+ "lost_sale_reason": "",
+ "ma2s": "",
+ "ma3s": "",
+ "mabl": "",
+ "macs": "",
+ "mahw": "",
+ "mapa": "",
+ "mash": "",
+ "matd": "",
+ "materials": {
+ "MAPA": "",
+ "MASH": "",
+ "cal_maxdlr": "",
+ "cal_opcode": "",
+ "mat_adjp": "",
+ "mat_taxp": "",
+ "mat_tx_in1": "",
+ "mat_tx_in2": "",
+ "mat_tx_in3": "",
+ "mat_tx_in4": "",
+ "mat_tx_in5": "",
+ "materials": "",
+ "tax_ind": ""
+ },
+ "other_amount_payable": "Otra cantidad a pagar",
+ "owner": "Propietario",
+ "owner_owing": "Cust. Debe",
+ "ownr_ea": "Email",
+ "ownr_ph1": "Teléfono 1",
+ "ownr_ph2": "",
+ "paa": "",
+ "pac": "",
+ "pae": "",
+ "pag": "",
+ "pal": "",
+ "pam": "",
+ "pan": "",
+ "pao": "",
+ "pap": "",
+ "par": "",
+ "parts_tax_rates": {
+ "prt_discp": "",
+ "prt_mktyp": "",
+ "prt_mkupp": "",
+ "prt_tax_in": "",
+ "prt_tax_rt": "",
+ "prt_tx_in1": "",
+ "prt_tx_in2": "",
+ "prt_tx_in3": "",
+ "prt_tx_in4": "",
+ "prt_tx_in5": "",
+ "prt_tx_ty1": "",
+ "prt_type": ""
+ },
+ "partsstatus": "",
+ "pas": "",
+ "pay_date": "Fecha de Pay",
+ "phoneshort": "PH",
+ "po_number": "",
+ "policy_no": "Política #",
+ "ponumber": "numero postal",
+ "production_vars": {
+ "note": ""
+ },
+ "qb_multiple_payers": {
+ "amount": "",
+ "name": ""
+ },
+ "queued_for_parts": "",
+ "rate_ats": "",
+ "rate_ats_flat": "",
+ "rate_la1": "Tarifa LA1",
+ "rate_la2": "Tarifa LA2",
+ "rate_la3": "Tarifa LA3",
+ "rate_la4": "Tarifa LA4",
+ "rate_laa": "Tasa de aluminio",
+ "rate_lab": "Tasa de trabajo",
+ "rate_lad": "Tasa de diagnóstico",
+ "rate_lae": "tarifa eléctrica",
+ "rate_laf": "Cuadros por segundo",
+ "rate_lag": "Tasa de vidrio",
+ "rate_lam": "Tasa mecánica",
+ "rate_lar": "Tasa de acabado",
+ "rate_las": "",
+ "rate_lau": "",
+ "rate_ma2s": "Velocidad de pintura de 2 etapas",
+ "rate_ma3s": "Tasa de pintura de 3 etapas",
+ "rate_mabl": "MABL ??",
+ "rate_macs": "MACS ??",
+ "rate_mahw": "Tasa de residuos peligrosos",
+ "rate_mapa": "Tasa de materiales de pintura",
+ "rate_mash": "Comprar material de tarifa",
+ "rate_matd": "Tasa de eliminación de neumáticos",
+ "referral_source_extra": "",
+ "referral_source_other": "",
+ "referralsource": "Fuente de referencia",
+ "regie_number": "N. ° de registro",
+ "repairtotal": "Reparación total",
+ "ro_number": "RO #",
+ "scheduled_completion": "Finalización programada",
+ "scheduled_delivery": "Entrega programada",
+ "scheduled_in": "Programado en",
+ "selling_dealer": "Distribuidor vendedor",
+ "selling_dealer_contact": "Contacto con el vendedor",
+ "servicecar": "Auto de servicio",
+ "servicing_dealer": "Distribuidor de servicio",
+ "servicing_dealer_contact": "Servicio Contacto con el concesionario",
+ "special_coverage_policy": "Política de cobertura especial",
+ "specialcoveragepolicy": "Política de cobertura especial",
+ "state_tax_rate": "",
+ "status": "Estado del trabajo",
+ "storage_payable": "Almacenamiento ",
+ "tax_lbr_rt": "",
+ "tax_levies_rt": "",
+ "tax_paint_mat_rt": "",
+ "tax_registration_number": "",
+ "tax_shop_mat_rt": "",
+ "tax_str_rt": "",
+ "tax_sub_rt": "",
+ "tax_tow_rt": "",
+ "tlos_ind": "",
+ "towin": "",
+ "towing_payable": "Remolque a pagar",
+ "unitnumber": "Unidad #",
+ "updated_at": "Actualizado en",
+ "uploaded_by": "Subido por",
+ "vehicle": "Vehículo"
+ },
+ "forms": {
+ "admindates": "",
+ "appraiserinfo": "",
+ "claiminfo": "",
+ "estdates": "",
+ "laborrates": "",
+ "lossinfo": "",
+ "other": "",
+ "repairdates": "",
+ "scheddates": ""
+ },
+ "labels": {
+ "accountsreceivable": "",
+ "act_price_ppc": "",
+ "actual_completion_inferred": "",
+ "actual_delivery_inferred": "",
+ "actual_in_inferred": "",
+ "additionalpayeroverallocation": "",
+ "additionaltotal": "",
+ "adjustmentrate": "",
+ "adjustments": "",
+ "adminwarning": "",
+ "allocations": "",
+ "alreadyaddedtoscoreboard": "",
+ "alreadyclosed": "",
+ "appointmentconfirmation": "¿Enviar confirmación al cliente?",
+ "associationwarning": "",
+ "audit": "",
+ "available": "",
+ "availablejobs": "",
+ "ca_bc_pvrt": {
+ "days": "",
+ "rate": ""
+ },
+ "ca_gst_all_if_null": "",
+ "calc_repair_days": "",
+ "calc_repair_days_tt": "",
+ "calc_scheuled_completion": "",
+ "cards": {
+ "customer": "Información al cliente",
+ "damage": "Área de Daño",
+ "dates": "fechas",
+ "documents": "Documentos recientes",
+ "estimator": "Estimador",
+ "filehandler": "File Handler",
+ "insurance": "detalles del seguro",
+ "more": "Más",
+ "notes": "Notas",
+ "parts": "Partes",
+ "totals": "Totales",
+ "vehicle": "Vehículo"
+ },
+ "changeclass": "",
+ "checklistcompletedby": "",
+ "checklistdocuments": "",
+ "checklists": "",
+ "cieca_pfl": "",
+ "cieca_pfo": "",
+ "cieca_pft": "",
+ "closeconfirm": "",
+ "closejob": "",
+ "closingperiod": "",
+ "contracts": "",
+ "convertedtolabor": "",
+ "cost": "",
+ "cost_Additional": "",
+ "cost_labor": "",
+ "cost_parts": "",
+ "cost_sublet": "",
+ "costs": "",
+ "create": {
+ "jobinfo": "",
+ "newowner": "",
+ "newvehicle": "",
+ "novehicle": "",
+ "ownerinfo": "",
+ "vehicleinfo": ""
+ },
+ "createiouwarning": "",
+ "creating_new_job": "Creando nuevo trabajo ...",
+ "deductible": {
+ "stands": "",
+ "waived": ""
+ },
+ "deleteconfirm": "",
+ "deletedelivery": "",
+ "deleteintake": "",
+ "deliverchecklist": "",
+ "difference": "",
+ "diskscan": "",
+ "dms": {
+ "apexported": "",
+ "damageto": "",
+ "defaultstory": "",
+ "disablebillwip": "",
+ "invoicedatefuture": "",
+ "kmoutnotgreaterthankmin": "",
+ "logs": "",
+ "notallocated": "",
+ "postingform": "",
+ "totalallocated": ""
+ },
+ "documents": "documentos",
+ "documents-images": "",
+ "documents-other": "",
+ "duplicateconfirm": "",
+ "emailaudit": "",
+ "employeeassignments": "",
+ "estimatelines": "",
+ "estimator": "",
+ "existing_jobs": "Empleos existentes",
+ "federal_tax_amt": "",
+ "gpdollars": "",
+ "gppercent": "",
+ "hrs_claimed": "",
+ "hrs_total": "",
+ "importnote": "",
+ "inproduction": "",
+ "intakechecklist": "",
+ "iou": "",
+ "job": "",
+ "jobcosting": "",
+ "jobtotals": "",
+ "labor_hrs": "",
+ "labor_rates_subtotal": "",
+ "laborallocations": "",
+ "labortotals": "",
+ "lines": "Líneas estimadas",
+ "local_tax_amt": "",
+ "mapa": "",
+ "markforreexport": "",
+ "mash": "",
+ "masterbypass": "",
+ "materials": {
+ "mapa": ""
+ },
+ "missingprofileinfo": "",
+ "multipayers": "",
+ "net_repairs": "",
+ "notes": "Notas",
+ "othertotal": "",
+ "outstanding_ar": "",
+ "outstanding_credit_memos": "",
+ "outstanding_ppd": "",
+ "outstanding_reconciliation_discrep": "",
+ "outstanding_sublets": "",
+ "outstandinghours": "",
+ "override_header": "¿Anular encabezado estimado al importar?",
+ "ownerassociation": "",
+ "parts": "Partes",
+ "parts_lines": "",
+ "parts_received": "",
+ "parts_tax_rates": "",
+ "partsfilter": "",
+ "partssubletstotal": "",
+ "partstotal": "",
+ "performance": "",
+ "pimraryamountpayable": "",
+ "plitooltips": {
+ "billtotal": "",
+ "calculatedcreditsnotreceived": "",
+ "creditmemos": "",
+ "creditsnotreceived": "",
+ "discrep1": "",
+ "discrep2": "",
+ "discrep3": "",
+ "laboradj": "",
+ "partstotal": "",
+ "totalreturns": ""
+ },
+ "ppc": "",
+ "ppdnotexported": "",
+ "profileadjustments": "",
+ "profitbypassrequired": "",
+ "profits": "",
+ "prt_dsmk_total": "",
+ "rates": "Tarifas",
+ "rates_subtotal": "",
+ "reconciliation": {
+ "billlinestotal": "",
+ "byassoc": "",
+ "byprice": "",
+ "clear": "",
+ "discrepancy": "",
+ "joblinestotal": "",
+ "multipleactprices": "",
+ "multiplebilllines": "",
+ "multiplebillsforactprice": "",
+ "removedpartsstrikethrough": ""
+ },
+ "reconciliationheader": "",
+ "relatedros": "",
+ "remove_from_ar": "",
+ "returntotals": "",
+ "ro_guard": {
+ "enforce_ar": "",
+ "enforce_bills": "",
+ "enforce_cm": "",
+ "enforce_labor": "",
+ "enforce_ppd": "",
+ "enforce_profit": "",
+ "enforce_sublet": "",
+ "enforce_validation": "",
+ "enforced": ""
+ },
+ "roguard": "",
+ "roguardwarnings": "",
+ "rosaletotal": "",
+ "sale_additional": "",
+ "sale_labor": "",
+ "sale_parts": "",
+ "sale_sublet": "",
+ "sales": "",
+ "savebeforeconversion": "",
+ "scheduledinchange": "",
+ "specialcoveragepolicy": "",
+ "state_tax_amt": "",
+ "subletsnotcompleted": "",
+ "subletstotal": "",
+ "subtotal": "",
+ "supplementnote": "",
+ "suspended": "",
+ "suspense": "",
+ "tasks": "",
+ "threshhold": "",
+ "total_cost": "",
+ "total_cust_payable": "",
+ "total_cust_payable_cash_discount": "",
+ "total_repairs": "",
+ "total_repairs_cash_discount": "",
+ "total_sales": "",
+ "total_sales_tax": "",
+ "totals": "",
+ "unvoidnote": "",
+ "update_scheduled_completion": "",
+ "vehicle_info": "Vehículo",
+ "vehicleassociation": "",
+ "viewallocations": "",
+ "voidjob": "",
+ "voidnote": ""
+ },
+ "successes": {
+ "addedtoproduction": "",
+ "all_deleted": "{{count}} trabajos eliminados con éxito.",
+ "closed": "",
+ "converted": "Trabajo convertido con éxito.",
+ "created": "Trabajo creado con éxito. Click para ver.",
+ "creatednoclick": "",
+ "delete": "",
+ "deleted": "Trabajo eliminado con éxito.",
+ "duplicated": "",
+ "exported": "",
+ "invoiced": "",
+ "ioucreated": "",
+ "partsqueue": "",
+ "save": "Trabajo guardado con éxito.",
+ "savetitle": "Registro guardado con éxito.",
+ "supplemented": "Trabajo complementado con éxito.",
+ "updated": "",
+ "voided": ""
+ }
+ },
+ "landing": {
+ "bigfeature": {
+ "subtitle": "",
+ "title": ""
+ },
+ "footer": {
+ "company": {
+ "about": "",
+ "contact": "",
+ "disclaimers": "",
+ "name": "",
+ "privacypolicy": ""
+ },
+ "io": {
+ "help": "",
+ "name": "",
+ "status": ""
+ },
+ "slogan": ""
+ },
+ "hero": {
+ "button": "",
+ "title": ""
+ },
+ "labels": {
+ "features": "",
+ "managemyshop": "",
+ "pricing": ""
+ },
+ "pricing": {
+ "basic": {
+ "name": "",
+ "sub": ""
+ },
+ "essentials": {
+ "name": "",
+ "sub": ""
+ },
+ "pricingtitle": "",
+ "pro": {
+ "name": "",
+ "sub": ""
+ },
+ "title": "",
+ "unlimited": {
+ "name": "",
+ "sub": ""
+ }
+ }
+ },
+ "menus": {
+ "currentuser": {
+ "languageselector": "idioma",
+ "profile": "Perfil"
+ },
+ "header": {
+ "accounting": "",
+ "accounting-payables": "",
+ "accounting-payments": "",
+ "accounting-receivables": "",
+ "activejobs": "Empleos activos",
+ "all_tasks": "",
+ "alljobs": "",
+ "allpayments": "",
+ "availablejobs": "Trabajos disponibles",
+ "bills": "",
+ "courtesycars": "",
+ "courtesycars-all": "",
+ "courtesycars-contracts": "",
+ "courtesycars-newcontract": "",
+ "create_task": "",
+ "customers": "Clientes",
+ "dashboard": "",
+ "enterbills": "",
+ "entercardpayment": "",
+ "enterpayment": "",
+ "entertimeticket": "",
+ "export": "",
+ "export-logs": "",
+ "help": "",
+ "home": "Casa",
+ "inventory": "",
+ "jobs": "Trabajos",
+ "my_tasks": "",
+ "newjob": "",
+ "owners": "propietarios",
+ "parts-queue": "",
+ "phonebook": "",
+ "productionboard": "",
+ "productionlist": "",
+ "readyjobs": "",
+ "recent": "",
+ "reportcenter": "",
+ "rescueme": "",
+ "schedule": "Programar",
+ "scoreboard": "",
+ "search": {
+ "bills": "",
+ "jobs": "",
+ "owners": "",
+ "payments": "",
+ "phonebook": "",
+ "vehicles": ""
+ },
+ "shiftclock": "",
+ "shop": "Mi tienda",
+ "shop_config": "Configuración",
+ "shop_csi": "",
+ "shop_templates": "",
+ "shop_vendors": "Vendedores",
+ "tasks": "",
+ "temporarydocs": "",
+ "timetickets": "",
+ "ttapprovals": "",
+ "vehicles": "Vehículos"
+ },
+ "jobsactions": {
+ "admin": "",
+ "cancelallappointments": "",
+ "closejob": "",
+ "deletejob": "",
+ "duplicate": "",
+ "duplicatenolines": "",
+ "newcccontract": "",
+ "void": ""
+ },
+ "jobsdetail": {
+ "claimdetail": "Detalles de la reclamación",
+ "dates": "fechas",
+ "financials": "",
+ "general": "",
+ "insurance": "",
+ "labor": "Labor",
+ "lifecycle": "",
+ "parts": "",
+ "partssublet": "Piezas / Subarrendamiento",
+ "rates": "",
+ "repairdata": "Datos de reparación",
+ "totals": ""
+ },
+ "profilesidebar": {
+ "profile": "Mi perfil",
+ "shops": "Mis tiendas"
+ },
+ "tech": {
+ "assignedjobs": "",
+ "claimtask": "",
+ "dispatchedparts": "",
+ "home": "",
+ "jobclockin": "",
+ "jobclockout": "",
+ "joblookup": "",
+ "login": "",
+ "logout": "",
+ "productionboard": "",
+ "productionlist": "",
+ "shiftclockin": ""
+ }
+ },
+ "messaging": {
+ "actions": {
+ "link": "",
+ "new": ""
+ },
+ "errors": {
+ "invalidphone": "",
+ "noattachedjobs": "",
+ "updatinglabel": ""
+ },
+ "labels": {
+ "addlabel": "",
+ "archive": "",
+ "maxtenimages": "",
+ "messaging": "Mensajería",
+ "noallowtxt": "",
+ "nojobs": "",
+ "nopush": "",
+ "phonenumber": "",
+ "presets": "",
+ "recentonly": "",
+ "selectmedia": "",
+ "sentby": "",
+ "typeamessage": "Enviar un mensaje...",
+ "unarchive": ""
+ },
+ "render": {
+ "conversation_list": ""
+ }
+ },
+ "notes": {
+ "actions": {
+ "actions": "Comportamiento",
+ "deletenote": "Borrar nota",
+ "edit": "Editar nota",
+ "new": "Nueva nota",
+ "savetojobnotes": ""
+ },
+ "errors": {
+ "inserting": ""
+ },
+ "fields": {
+ "createdby": "Creado por",
+ "critical": "Crítico",
+ "private": "Privado",
+ "text": "Contenido",
+ "type": "",
+ "types": {
+ "customer": "",
+ "general": "",
+ "office": "",
+ "paint": "",
+ "parts": "",
+ "shop": "",
+ "supplement": ""
+ },
+ "updatedat": "Actualizado en"
+ },
+ "labels": {
+ "addtorelatedro": "",
+ "newnoteplaceholder": "Agrega una nota...",
+ "notetoadd": "",
+ "systemnotes": "",
+ "usernotes": ""
+ },
+ "successes": {
+ "create": "Nota creada con éxito.",
+ "deleted": "Nota eliminada con éxito.",
+ "updated": "Nota actualizada con éxito."
+ }
+ },
+ "owner": {
+ "labels": {
+ "noownerinfo": ""
+ }
+ },
+ "owners": {
+ "actions": {
+ "update": ""
+ },
+ "errors": {
+ "deleting": "",
+ "noaccess": "El registro no existe o no tiene acceso a él.",
+ "saving": "",
+ "selectexistingornew": ""
+ },
+ "fields": {
+ "accountingid": "",
+ "address": "Dirección",
+ "allow_text_message": "Permiso de texto?",
+ "name": "Nombre",
+ "note": "",
+ "ownr_addr1": "Dirección",
+ "ownr_addr2": "Dirección 2",
+ "ownr_city": "ciudad",
+ "ownr_co_nm": "",
+ "ownr_ctry": "País",
+ "ownr_ea": "Email",
+ "ownr_fn": "Nombre de pila",
+ "ownr_ln": "Apellido",
+ "ownr_ph1": "Teléfono 1",
+ "ownr_ph2": "",
+ "ownr_st": "Provincia del estado",
+ "ownr_title": "Título",
+ "ownr_zip": "código postal",
+ "preferred_contact": "Método de Contacto Preferido",
+ "tax_number": ""
+ },
+ "forms": {
+ "address": "",
+ "contact": "",
+ "name": ""
+ },
+ "labels": {
+ "create_new": "Crea un nuevo registro de propietario.",
+ "deleteconfirm": "",
+ "existing_owners": "Propietarios existentes",
+ "fromclaim": "",
+ "fromowner": "",
+ "relatedjobs": "",
+ "updateowner": ""
+ },
+ "successes": {
+ "delete": "",
+ "save": "Propietario guardado con éxito."
+ }
+ },
+ "parts": {
+ "actions": {
+ "order": "Pedido de piezas",
+ "orderinhouse": ""
+ }
+ },
+ "parts_dispatch": {
+ "actions": {
+ "accept": ""
+ },
+ "errors": {
+ "accepting": "",
+ "creating": ""
+ },
+ "fields": {
+ "number": "",
+ "percent_accepted": ""
+ },
+ "labels": {
+ "notyetdispatched": "",
+ "parts_dispatch": ""
+ }
+ },
+ "parts_dispatch_lines": {
+ "fields": {
+ "accepted_at": ""
+ }
+ },
+ "parts_orders": {
+ "actions": {
+ "backordered": "",
+ "receive": "",
+ "receivebill": ""
+ },
+ "errors": {
+ "associatedbills": "",
+ "backordering": "",
+ "creating": "Se encontró un error al crear el pedido de piezas.",
+ "oec": "",
+ "saving": "",
+ "updating": ""
+ },
+ "fields": {
+ "act_price": "",
+ "backordered_eta": "",
+ "backordered_on": "",
+ "cm_received": "",
+ "comments": "",
+ "cost": "",
+ "db_price": "",
+ "deliver_by": "",
+ "job_line_id": "",
+ "line_desc": "",
+ "line_remarks": "",
+ "lineremarks": "Comentarios de línea",
+ "oem_partno": "",
+ "order_date": "",
+ "order_number": "",
+ "orderedby": "",
+ "part_type": "",
+ "quantity": "",
+ "return": "",
+ "status": ""
+ },
+ "labels": {
+ "allpartsto": "",
+ "confirmdelete": "",
+ "custompercent": "",
+ "discount": "",
+ "email": "Enviar por correo electrónico",
+ "inthisorder": "Partes en este pedido",
+ "is_quote": "",
+ "mark_as_received": "",
+ "newpartsorder": "",
+ "notyetordered": "",
+ "oec": "",
+ "order_type": "",
+ "orderhistory": "Historial de pedidos",
+ "parts_order": "",
+ "parts_orders": "",
+ "parts_returns": "",
+ "print": "Mostrar formulario impreso",
+ "receive": "",
+ "removefrompartsqueue": "",
+ "returnpartsorder": "",
+ "sublet_order": ""
+ },
+ "successes": {
+ "created": "Pedido de piezas creado con éxito.",
+ "line_updated": "",
+ "received": "",
+ "return_created": ""
+ }
+ },
+ "payments": {
+ "actions": {
+ "generatepaymentlink": ""
+ },
+ "errors": {
+ "exporting": "",
+ "exporting-partner": "",
+ "inserting": ""
+ },
+ "fields": {
+ "amount": "",
+ "created_at": "",
+ "date": "",
+ "exportedat": "",
+ "memo": "",
+ "payer": "",
+ "paymentnum": "",
+ "stripeid": "",
+ "transactionid": "",
+ "type": ""
+ },
+ "labels": {
+ "balance": "",
+ "ca_bc_etf_table": "",
+ "customer": "",
+ "edit": "",
+ "electronicpayment": "",
+ "external": "",
+ "findermodal": "",
+ "insurance": "",
+ "markexported": "",
+ "markforreexport": "",
+ "new": "",
+ "signup": "",
+ "smspaymentreminder": "",
+ "title": "",
+ "totalpayments": ""
+ },
+ "successes": {
+ "exported": "",
+ "markexported": "",
+ "markreexported": "",
+ "payment": "",
+ "paymentupdate": "",
+ "stripe": ""
+ }
+ },
+ "phonebook": {
+ "actions": {
+ "new": ""
+ },
+ "errors": {
+ "adding": "",
+ "saving": ""
+ },
+ "fields": {
+ "address1": "",
+ "address2": "",
+ "category": "",
+ "city": "",
+ "company": "",
+ "country": "",
+ "email": "",
+ "fax": "",
+ "firstname": "",
+ "lastname": "",
+ "phone1": "",
+ "phone2": "",
+ "state": ""
+ },
+ "labels": {
+ "noneselected": "",
+ "onenamerequired": "",
+ "vendorcategory": ""
+ },
+ "successes": {
+ "added": "",
+ "deleted": "",
+ "saved": ""
+ }
+ },
+ "printcenter": {
+ "appointments": {
+ "appointment_confirmation": ""
+ },
+ "bills": {
+ "inhouse_invoice": ""
+ },
+ "courtesycarcontract": {
+ "courtesy_car_contract": "",
+ "courtesy_car_impound": "",
+ "courtesy_car_inventory": "",
+ "courtesy_car_terms": ""
+ },
+ "errors": {
+ "nocontexttype": ""
+ },
+ "jobs": {
+ "3rdpartyfields": {
+ "addr1": "",
+ "addr2": "",
+ "addr3": "",
+ "attn": "",
+ "city": "",
+ "custgst": "",
+ "ded_amt": "",
+ "depreciation": "",
+ "other": "",
+ "ponumber": "",
+ "refnumber": "",
+ "sendtype": "",
+ "state": "",
+ "zip": ""
+ },
+ "3rdpartypayer": "",
+ "ab_proof_of_loss": "",
+ "appointment_confirmation": "",
+ "appointment_reminder": "",
+ "casl_authorization": "",
+ "committed_timetickets_ro": "",
+ "coversheet_landscape": "",
+ "coversheet_portrait": "",
+ "csi_invitation": "",
+ "csi_invitation_action": "",
+ "diagnostic_authorization": "",
+ "dms_posting_sheet": "",
+ "envelope_return_address": "",
+ "estimate": "",
+ "estimate_detail": "",
+ "estimate_followup": "",
+ "express_repair_checklist": "",
+ "filing_coversheet_landscape": "",
+ "filing_coversheet_portrait": "",
+ "final_invoice": "",
+ "fippa_authorization": "",
+ "folder_label_multiple": "",
+ "glass_express_checklist": "",
+ "guarantee": "",
+ "individual_job_note": "",
+ "invoice_customer_payable": "",
+ "invoice_total_payable": "",
+ "iou_form": "",
+ "job_costing_ro": "",
+ "job_lifecycle_ro": "",
+ "job_notes": "",
+ "job_tasks": "",
+ "key_tag": "",
+ "labels": {
+ "count": "",
+ "labels": "",
+ "position": ""
+ },
+ "lag_time_ro": "",
+ "mechanical_authorization": "",
+ "mpi_animal_checklist": "",
+ "mpi_eglass_auth": "",
+ "mpi_final_acct_sheet": "",
+ "mpi_final_repair_acct_sheet": "",
+ "paint_grid": "",
+ "parts_dispatch": "",
+ "parts_invoice_label_single": "",
+ "parts_label_multiple": "",
+ "parts_label_single": "",
+ "parts_list": "",
+ "parts_order": "",
+ "parts_order_confirmation": "",
+ "parts_order_history": "",
+ "parts_return_slip": "",
+ "payment_receipt": "",
+ "payment_request": "",
+ "payments_by_job": "",
+ "purchases_by_ro_detail": "",
+ "purchases_by_ro_summary": "",
+ "qc_sheet": "",
+ "rental_reservation": "",
+ "ro_totals": "",
+ "ro_with_description": "",
+ "sgi_certificate_of_repairs": "",
+ "sgi_windshield_auth": "",
+ "stolen_recovery_checklist": "",
+ "sublet_order": "",
+ "supplement_request": "",
+ "thank_you_ro": "",
+ "thirdpartypayer": "",
+ "timetickets_ro": "",
+ "vehicle_check_in": "",
+ "vehicle_delivery_check": "",
+ "window_tag": "",
+ "window_tag_sublet": "",
+ "work_authorization": "",
+ "worksheet_by_line_number": "",
+ "worksheet_sorted_by_operation": "",
+ "worksheet_sorted_by_operation_no_hours": "",
+ "worksheet_sorted_by_operation_part_type": "",
+ "worksheet_sorted_by_operation_type": "",
+ "worksheet_sorted_by_team": ""
+ },
+ "labels": {
+ "groups": {
+ "authorization": "",
+ "financial": "",
+ "post": "",
+ "pre": "",
+ "ro": "",
+ "worksheet": ""
+ },
+ "misc": "",
+ "repairorder": "",
+ "reportcentermodal": "",
+ "speedprint": "",
+ "title": ""
+ },
+ "payments": {
+ "ca_bc_etf_table": "",
+ "exported_payroll": ""
+ },
+ "special": {
+ "attendance_detail_csv": ""
+ },
+ "subjects": {
+ "jobs": {
+ "individual_job_note": "",
+ "parts_dispatch": "",
+ "parts_order": "",
+ "parts_return_slip": "",
+ "sublet_order": ""
+ }
+ },
+ "vendors": {
+ "purchases_by_vendor_detailed": "",
+ "purchases_by_vendor_summary": ""
+ }
+ },
+ "production": {
+ "actions": {
+ "addcolumns": "",
+ "bodypriority-clear": "",
+ "bodypriority-set": "",
+ "detailpriority-clear": "",
+ "detailpriority-set": "",
+ "paintpriority-clear": "",
+ "paintpriority-set": "",
+ "remove": "",
+ "removecolumn": "",
+ "saveconfig": "",
+ "suspend": "",
+ "unsuspend": ""
+ },
+ "constants": {
+ "main_profile": ""
+ },
+ "errors": {
+ "boardupdate": "",
+ "name_exists": "",
+ "name_required": "",
+ "removing": "",
+ "settings": ""
+ },
+ "labels": {
+ "actual_in": "",
+ "addnewprofile": "",
+ "alert": "",
+ "alertoff": "",
+ "alerton": "",
+ "alerts": "",
+ "ats": "",
+ "bodyhours": "",
+ "bodypriority": "",
+ "bodyshop": {
+ "labels": {
+ "qbo_departmentid": "",
+ "qbo_usa": ""
+ }
+ },
+ "card_size": "",
+ "cardcolor": "",
+ "cardsettings": "",
+ "clm_no": "",
+ "comment": "",
+ "compact": "",
+ "detailpriority": "",
+ "employeeassignments": "",
+ "employeesearch": "",
+ "estimator": "",
+ "horizontal": "",
+ "ins_co_nm": "",
+ "jobdetail": "",
+ "kiosk_mode": "",
+ "laborhrs": "",
+ "legend": "",
+ "model_info": "",
+ "note": "",
+ "off": "",
+ "on": "",
+ "orientation": "",
+ "ownr_nm": "",
+ "paintpriority": "",
+ "partsstatus": "",
+ "production_note": "",
+ "refinishhours": "",
+ "scheduled_completion": "",
+ "selectview": "",
+ "stickyheader": "",
+ "sublets": "",
+ "subtotal": "",
+ "tall": "",
+ "tasks": "",
+ "totalhours": "",
+ "touchtime": "",
+ "unassigned": "",
+ "vertical": "",
+ "viewname": "",
+ "wide": ""
+ },
+ "options": {
+ "horizontal": "",
+ "large": "",
+ "medium": "",
+ "small": "",
+ "vertical": ""
+ },
+ "settings": {
+ "board_settings": "",
+ "filters": {
+ "md_estimators": "",
+ "md_ins_cos": ""
+ },
+ "filters_title": "",
+ "information": "",
+ "layout": "",
+ "statistics": {
+ "jobs_in_production": "",
+ "tasks_in_production": "",
+ "tasks_in_view": "",
+ "tasks_on_board": "",
+ "total_amount_in_production": "",
+ "total_amount_in_view": "",
+ "total_amount_on_board": "",
+ "total_hours_in_production": "",
+ "total_hours_in_view": "",
+ "total_hours_on_board": "",
+ "total_jobs_in_view": "",
+ "total_jobs_on_board": "",
+ "total_lab_in_production": "",
+ "total_lab_in_view": "",
+ "total_lab_on_board": "",
+ "total_lar_in_production": "",
+ "total_lar_in_view": "",
+ "total_lar_on_board": ""
+ },
+ "statistics_title": ""
+ },
+ "statistics": {
+ "currency_symbol": "",
+ "hours": "",
+ "jobs": "",
+ "jobs_in_production": "",
+ "tasks": "",
+ "tasks_in_production": "",
+ "tasks_in_view": "",
+ "tasks_on_board": "",
+ "total_amount_in_production": "",
+ "total_amount_in_view": "",
+ "total_amount_on_board": "",
+ "total_hours_in_production": "",
+ "total_hours_in_view": "",
+ "total_hours_on_board": "",
+ "total_jobs_in_view": "",
+ "total_jobs_on_board": "",
+ "total_lab_in_production": "",
+ "total_lab_in_view": "",
+ "total_lab_on_board": "",
+ "total_lar_in_production": "",
+ "total_lar_in_view": "",
+ "total_lar_on_board": ""
+ },
+ "successes": {
+ "removed": ""
+ }
+ },
+ "profile": {
+ "errors": {
+ "state": "Error al leer el estado de la página. Porfavor refresca."
+ },
+ "labels": {
+ "activeshop": ""
+ },
+ "successes": {
+ "updated": ""
+ }
+ },
+ "reportcenter": {
+ "actions": {
+ "generate": ""
+ },
+ "labels": {
+ "advanced_filters": "",
+ "advanced_filters_false": "",
+ "advanced_filters_filter_field": "",
+ "advanced_filters_filter_operator": "",
+ "advanced_filters_filter_value": "",
+ "advanced_filters_filters": "",
+ "advanced_filters_hide": "",
+ "advanced_filters_show": "",
+ "advanced_filters_sorter_direction": "",
+ "advanced_filters_sorter_field": "",
+ "advanced_filters_sorters": "",
+ "advanced_filters_true": "",
+ "dates": "",
+ "employee": "",
+ "filterson": "",
+ "generateasemail": "",
+ "groups": {
+ "customers": "",
+ "jobs": "",
+ "payroll": "",
+ "purchases": "",
+ "sales": ""
+ },
+ "key": "",
+ "objects": {
+ "appointments": "",
+ "bills": "",
+ "csi": "",
+ "exportlogs": "",
+ "jobs": "",
+ "parts_orders": "",
+ "payments": "",
+ "scoreboard": "",
+ "tasks": "",
+ "timetickets": ""
+ },
+ "vendor": ""
+ },
+ "templates": {
+ "adp_payroll_flat": "",
+ "adp_payroll_straight": "",
+ "anticipated_revenue": "",
+ "ar_aging": "",
+ "attendance_detail": "",
+ "attendance_employee": "",
+ "attendance_summary": "",
+ "committed_timetickets": "",
+ "committed_timetickets_employee": "",
+ "committed_timetickets_summary": "",
+ "credits_not_received_date": "",
+ "credits_not_received_date_vendorid": "",
+ "csi": "",
+ "customer_list": "",
+ "cycle_time_analysis": "",
+ "estimates_written_converted": "",
+ "estimator_detail": "",
+ "estimator_summary": "",
+ "export_payables": "",
+ "export_payments": "",
+ "export_receivables": "",
+ "exported_gsr_by_ro": "",
+ "exported_gsr_by_ro_labor": "",
+ "gsr_by_atp": "",
+ "gsr_by_ats": "",
+ "gsr_by_category": "",
+ "gsr_by_csr": "",
+ "gsr_by_delivery_date": "",
+ "gsr_by_estimator": "",
+ "gsr_by_exported_date": "",
+ "gsr_by_ins_co": "",
+ "gsr_by_make": "",
+ "gsr_by_referral": "",
+ "gsr_by_ro": "",
+ "gsr_labor_only": "",
+ "hours_sold_detail_closed": "",
+ "hours_sold_detail_closed_csr": "",
+ "hours_sold_detail_closed_estimator": "",
+ "hours_sold_detail_closed_ins_co": "",
+ "hours_sold_detail_closed_status": "",
+ "hours_sold_detail_open": "",
+ "hours_sold_detail_open_csr": "",
+ "hours_sold_detail_open_estimator": "",
+ "hours_sold_detail_open_ins_co": "",
+ "hours_sold_detail_open_status": "",
+ "hours_sold_summary_closed": "",
+ "hours_sold_summary_closed_csr": "",
+ "hours_sold_summary_closed_estimator": "",
+ "hours_sold_summary_closed_ins_co": "",
+ "hours_sold_summary_closed_status": "",
+ "hours_sold_summary_open": "",
+ "hours_sold_summary_open_csr": "",
+ "hours_sold_summary_open_estimator": "",
+ "hours_sold_summary_open_ins_co": "",
+ "hours_sold_summary_open_status": "",
+ "job_costing_ro_csr": "",
+ "job_costing_ro_date_detail": "",
+ "job_costing_ro_date_summary": "",
+ "job_costing_ro_estimator": "",
+ "job_costing_ro_ins_co": "",
+ "job_lifecycle_date_detail": "",
+ "job_lifecycle_date_summary": "",
+ "jobs_completed_not_invoiced": "",
+ "jobs_invoiced_not_exported": "",
+ "jobs_reconcile": "",
+ "jobs_scheduled_completion": "",
+ "lag_time": "",
+ "load_level": "",
+ "lost_sales": "",
+ "open_orders": "",
+ "open_orders_csr": "",
+ "open_orders_estimator": "",
+ "open_orders_excel": "",
+ "open_orders_ins_co": "",
+ "open_orders_referral": "",
+ "open_orders_specific_csr": "",
+ "open_orders_status": "",
+ "parts_backorder": "",
+ "parts_not_recieved": "",
+ "parts_not_recieved_vendor": "",
+ "parts_received_not_scheduled": "",
+ "payments_by_date": "",
+ "payments_by_date_payment": "",
+ "payments_by_date_type": "",
+ "production_by_category": "",
+ "production_by_category_one": "",
+ "production_by_csr": "",
+ "production_by_last_name": "",
+ "production_by_repair_status": "",
+ "production_by_repair_status_one": "",
+ "production_by_ro": "",
+ "production_by_target_date": "",
+ "production_by_technician": "",
+ "production_by_technician_one": "",
+ "production_not_production_status": "",
+ "production_over_time": "",
+ "psr_by_make": "",
+ "purchase_return_ratio_excel": "",
+ "purchase_return_ratio_grouped_by_vendor_detail": "",
+ "purchase_return_ratio_grouped_by_vendor_summary": "",
+ "purchases_by_cost_center_detail": "",
+ "purchases_by_cost_center_summary": "",
+ "purchases_by_date_excel": "",
+ "purchases_by_date_range_detail": "",
+ "purchases_by_date_range_summary": "",
+ "purchases_by_ro_detail_date": "",
+ "purchases_by_ro_summary_date": "",
+ "purchases_by_vendor_detailed_date_range": "",
+ "purchases_by_vendor_summary_date_range": "",
+ "purchases_grouped_by_vendor_detailed": "",
+ "purchases_grouped_by_vendor_summary": "",
+ "returns_grouped_by_vendor_detailed": "",
+ "returns_grouped_by_vendor_summary": "",
+ "schedule": "",
+ "scheduled_parts_list": "",
+ "scoreboard_detail": "",
+ "scoreboard_summary": "",
+ "supplement_ratio_ins_co": "",
+ "tasks_date": "",
+ "tasks_date_employee": "",
+ "thank_you_date": "",
+ "timetickets": "",
+ "timetickets_employee": "",
+ "timetickets_summary": "",
+ "total_loss_jobs": "",
+ "unclaimed_hrs": "",
+ "void_ros": "",
+ "work_in_progress_committed_labour": "",
+ "work_in_progress_jobs": "",
+ "work_in_progress_labour": "",
+ "work_in_progress_payables": ""
+ }
+ },
+ "schedule": {
+ "labels": {
+ "atssummary": "",
+ "employeevacation": "",
+ "estimators": "",
+ "ins_co_nm_filter": "",
+ "intake": "",
+ "manual": "",
+ "manualevent": ""
+ }
+ },
+ "scoreboard": {
+ "actions": {
+ "edit": ""
+ },
+ "errors": {
+ "adding": "",
+ "removing": "",
+ "updating": ""
+ },
+ "fields": {
+ "bodyhrs": "",
+ "date": "",
+ "painthrs": ""
+ },
+ "labels": {
+ "allemployeetimetickets": "",
+ "asoftodaytarget": "",
+ "body": "",
+ "bodyabbrev": "",
+ "bodycharttitle": "",
+ "calendarperiod": "",
+ "combinedcharttitle": "",
+ "dailyactual": "",
+ "dailytarget": "",
+ "efficiencyoverperiod": "",
+ "entries": "",
+ "jobs": "",
+ "jobscompletednotinvoiced": "",
+ "lastmonth": "",
+ "lastweek": "",
+ "monthlytarget": "",
+ "priorweek": "",
+ "productivestatistics": "",
+ "productivetimeticketsoverdate": "",
+ "refinish": "",
+ "refinishabbrev": "",
+ "refinishcharttitle": "",
+ "targets": "",
+ "thismonth": "",
+ "thisweek": "",
+ "timetickets": "",
+ "timeticketsemployee": "",
+ "todateactual": "",
+ "total": "",
+ "totalhrs": "",
+ "totaloverperiod": "",
+ "weeklyactual": "",
+ "weeklytarget": "",
+ "workingdays": ""
+ },
+ "successes": {
+ "added": "",
+ "removed": "",
+ "updated": ""
+ }
+ },
+ "tasks": {
+ "actions": {
+ "edit": "",
+ "new": "",
+ "view": ""
+ },
+ "buttons": {
+ "allTasks": "",
+ "complete": "",
+ "create": "",
+ "delete": "",
+ "edit": "",
+ "myTasks": "",
+ "refresh": ""
+ },
+ "date_presets": {
+ "completion": "",
+ "day": "",
+ "days": "",
+ "delivery": "",
+ "next_week": "",
+ "one_month": "",
+ "three_months": "",
+ "three_weeks": "",
+ "today": "",
+ "tomorrow": "",
+ "two_weeks": ""
+ },
+ "failures": {
+ "completed": "",
+ "created": "",
+ "deleted": "",
+ "updated": ""
+ },
+ "fields": {
+ "actions": "",
+ "assigned_to": "",
+ "bill": "",
+ "billid": "",
+ "completed": "",
+ "created_at": "",
+ "created_by": "",
+ "description": "",
+ "due_date": "",
+ "job": {
+ "ro_number": ""
+ },
+ "jobid": "",
+ "jobline": "",
+ "joblineid": "",
+ "parts_order": "",
+ "partsorderid": "",
+ "priorities": {
+ "high": "",
+ "low": "",
+ "medium": ""
+ },
+ "priority": "",
+ "related_items": "",
+ "remind_at": "",
+ "title": ""
+ },
+ "placeholders": {
+ "assigned_to": "",
+ "billid": "",
+ "description": "",
+ "jobid": "",
+ "joblineid": "",
+ "partsorderid": ""
+ },
+ "successes": {
+ "completed": "",
+ "created": "",
+ "deleted": "",
+ "updated": ""
+ },
+ "titles": {
+ "all_tasks": "",
+ "completed": "",
+ "deleted": "",
+ "job_tasks": "",
+ "mine": "",
+ "my_tasks": ""
+ },
+ "validation": {
+ "due_at_error_message": "",
+ "remind_at_error_message": ""
+ }
+ },
+ "tech": {
+ "fields": {
+ "employeeid": "",
+ "pin": ""
+ },
+ "labels": {
+ "loggedin": "",
+ "notloggedin": ""
+ }
+ },
+ "templates": {
+ "errors": {
+ "updating": ""
+ },
+ "successes": {
+ "updated": ""
+ }
+ },
+ "timetickets": {
+ "actions": {
+ "claimtasks": "",
+ "clockin": "",
+ "clockout": "",
+ "commit": "",
+ "commitone": "",
+ "enter": "",
+ "payall": "",
+ "printemployee": "",
+ "uncommit": ""
+ },
+ "errors": {
+ "clockingin": "",
+ "clockingout": "",
+ "creating": "",
+ "deleting": "",
+ "noemployeeforuser": "",
+ "noemployeeforuser_sub": "",
+ "payall": "",
+ "shiftalreadyclockedon": ""
+ },
+ "fields": {
+ "actualhrs": "",
+ "ciecacode": "",
+ "clockhours": "",
+ "clockoff": "",
+ "clockon": "",
+ "committed": "",
+ "committed_at": "",
+ "cost_center": "",
+ "created_by": "",
+ "date": "",
+ "efficiency": "",
+ "employee": "",
+ "employee_team": "",
+ "flat_rate": "",
+ "memo": "",
+ "productivehrs": "",
+ "ro_number": "",
+ "task_name": ""
+ },
+ "labels": {
+ "alreadyclockedon": "",
+ "ambreak": "",
+ "amshift": "",
+ "claimtaskpreview": "",
+ "clockhours": "",
+ "clockintojob": "",
+ "deleteconfirm": "",
+ "edit": "",
+ "efficiency": "",
+ "flat_rate": "",
+ "jobhours": "",
+ "lunch": "",
+ "new": "",
+ "payrollclaimedtasks": "",
+ "pmbreak": "",
+ "pmshift": "",
+ "shift": "",
+ "shiftalreadyclockedon": "",
+ "straight_time": "",
+ "task": "",
+ "timetickets": "",
+ "unassigned": "",
+ "zeroactualnegativeprod": ""
+ },
+ "successes": {
+ "clockedin": "",
+ "clockedout": "",
+ "committed": "",
+ "created": "",
+ "deleted": "",
+ "payall": ""
+ },
+ "validation": {
+ "clockoffmustbeafterclockon": "",
+ "clockoffwithoutclockon": "",
+ "hoursenteredmorethanavailable": "",
+ "unassignedlines": ""
+ }
+ },
+ "titles": {
+ "accounting-payables": "",
+ "accounting-payments": "",
+ "accounting-receivables": "",
+ "all_tasks": "",
+ "app": "",
+ "bc": {
+ "accounting-payables": "",
+ "accounting-payments": "",
+ "accounting-receivables": "",
+ "all_tasks": "",
+ "availablejobs": "",
+ "bills-list": "",
+ "contracts": "",
+ "contracts-create": "",
+ "contracts-detail": "",
+ "courtesycars": "",
+ "courtesycars-detail": "",
+ "courtesycars-new": "",
+ "dashboard": "",
+ "dms": "",
+ "export-logs": "",
+ "inventory": "",
+ "jobs": "",
+ "jobs-active": "",
+ "jobs-admin": "",
+ "jobs-all": "",
+ "jobs-checklist": "",
+ "jobs-close": "",
+ "jobs-deliver": "",
+ "jobs-detail": "",
+ "jobs-intake": "",
+ "jobs-new": "",
+ "jobs-ready": "",
+ "my_tasks": "",
+ "owner-detail": "",
+ "owners": "",
+ "parts-queue": "",
+ "payments-all": "",
+ "phonebook": "",
+ "productionboard": "",
+ "productionlist": "",
+ "profile": "",
+ "schedule": "",
+ "scoreboard": "",
+ "shop": "",
+ "shop-csi": "",
+ "shop-templates": "",
+ "shop-vendors": "",
+ "tasks": "",
+ "temporarydocs": "",
+ "timetickets": "",
+ "ttapprovals": "",
+ "vehicle-details": "",
+ "vehicles": ""
+ },
+ "bills-list": "",
+ "contracts": "",
+ "contracts-create": "",
+ "contracts-detail": "",
+ "courtesycars": "",
+ "courtesycars-create": "",
+ "courtesycars-detail": "",
+ "dashboard": "",
+ "dms": "",
+ "export-logs": "",
+ "imexonline": "",
+ "inventory": "",
+ "jobs": "Todos los trabajos | {{app}}",
+ "jobs-admin": "",
+ "jobs-all": "",
+ "jobs-checklist": "",
+ "jobs-close": "",
+ "jobs-create": "",
+ "jobs-deliver": "",
+ "jobs-intake": "",
+ "jobsavailable": "Empleos disponibles | {{app}}",
+ "jobsdetail": "Trabajo {{ro_number}} | {{app}}",
+ "jobsdocuments": "Documentos de trabajo {{ro_number}} | {{app}}",
+ "manageroot": "Casa | {{app}}",
+ "my_tasks": "",
+ "owners": "Todos los propietarios | {{app}}",
+ "owners-detail": "",
+ "parts-queue": "",
+ "payments-all": "",
+ "phonebook": "",
+ "productionboard": "",
+ "productionlist": "",
+ "profile": "Mi perfil | {{app}}",
+ "readyjobs": "",
+ "resetpassword": "",
+ "resetpasswordvalidate": "",
+ "romeonline": "",
+ "schedule": "Horario | {{app}}",
+ "scoreboard": "",
+ "shop": "Mi tienda | {{app}}",
+ "shop-csi": "",
+ "shop-templates": "",
+ "shop_vendors": "Vendedores | {{app}}",
+ "tasks": "",
+ "techconsole": "{{app}}",
+ "techjobclock": "{{app}}",
+ "techjoblookup": "{{app}}",
+ "techshiftclock": "{{app}}",
+ "temporarydocs": "",
+ "timetickets": "",
+ "ttapprovals": "",
+ "vehicledetail": "Detalles del vehículo {{vehicle}} | {{app}}",
+ "vehicles": "Todos los vehiculos | {{app}}"
+ },
+ "trello": {
+ "labels": {
+ "add_card": "",
+ "add_lane": "",
+ "cancel": "",
+ "delete_lane": "",
+ "description": "",
+ "label": "",
+ "lane_actions": "",
+ "title": ""
+ }
+ },
+ "tt_approvals": {
+ "actions": {
+ "approveselected": ""
+ },
+ "labels": {
+ "approval_queue_in_use": "",
+ "calculate": ""
+ }
+ },
+ "upsell": {
+ "cta": {
+ "learnmore": ""
+ },
+ "messages": {
+ "accounting": {
+ "payables": {
+ "subtitle": "",
+ "title": ""
+ },
+ "payments": {
+ "subtitle": "",
+ "title": ""
+ },
+ "receivables": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "audit": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "bills": {
+ "autoreconcile": {
+ "subtitle": "",
+ "title": ""
+ },
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "checklist": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "courtesycars": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "csi": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "dashboard": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "lifecycle": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "media": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ },
+ "mobile": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "payments": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "scoreboard": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "smartscheduling": {
+ "datepicker": {
+ "subtitle": "",
+ "title": ""
+ },
+ "general": {
+ "subtitle": "",
+ "title": ""
+ },
+ "hrsdelta": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "techconsole": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "timetickets": {
+ "allocations": {
+ "subtitle": "",
+ "title": ""
+ },
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "visualboard": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ }
+ }
+ },
+ "user": {
+ "actions": {
+ "changepassword": "",
+ "signout": "desconectar",
+ "updateprofile": "Actualización del perfil"
+ },
+ "errors": {
+ "updating": ""
+ },
+ "fields": {
+ "authlevel": "",
+ "displayname": "Nombre para mostrar",
+ "email": "",
+ "photourl": "URL de avatar"
+ },
+ "labels": {
+ "actions": "",
+ "changepassword": "",
+ "profileinfo": ""
+ },
+ "successess": {
+ "passwordchanged": ""
+ }
+ },
+ "users": {
+ "errors": {
+ "signinerror": {
+ "auth/user-disabled": "",
+ "auth/user-not-found": "",
+ "auth/wrong-password": ""
+ }
+ }
+ },
+ "vehicles": {
+ "errors": {
+ "deleting": "",
+ "noaccess": "El vehículo no existe o usted no tiene acceso a él.",
+ "selectexistingornew": "",
+ "validation": "Asegúrese de que todos los campos se ingresen correctamente.",
+ "validationtitle": "Error de validacion"
+ },
+ "fields": {
+ "description": "Descripcion del vehiculo",
+ "notes": "",
+ "plate_no": "Placa",
+ "plate_st": "Jurisdicción de placas",
+ "trim_color": "Recortar color",
+ "v_bstyle": "Tipo de cuerpo",
+ "v_color": "Color",
+ "v_cond": "condición",
+ "v_engine": "Motor",
+ "v_make_desc": "Hacer",
+ "v_makecode": "Hacer código",
+ "v_mldgcode": "Código de moldeo",
+ "v_model_desc": "Modelo",
+ "v_model_yr": "año",
+ "v_options": "Opciones",
+ "v_paint_codes": "Códigos de pintura",
+ "v_prod_dt": "Fecha de producción",
+ "v_stage": "Escenario",
+ "v_tone": "Tono",
+ "v_trimcode": "Código de recorte",
+ "v_type": "Tipo",
+ "v_vin": "V.I.N."
+ },
+ "forms": {
+ "detail": "",
+ "misc": "",
+ "registration": ""
+ },
+ "labels": {
+ "deleteconfirm": "",
+ "fromvehicle": "",
+ "novehinfo": "",
+ "relatedjobs": "",
+ "updatevehicle": ""
+ },
+ "successes": {
+ "delete": "",
+ "save": "Vehículo guardado con éxito."
+ }
+ },
+ "vendors": {
+ "actions": {
+ "addtophonebook": "",
+ "new": "Nuevo vendedor",
+ "newpreferredmake": ""
+ },
+ "errors": {
+ "deleting": "Se encontró un error al eliminar el proveedor.",
+ "saving": "Se encontró un error al guardar el proveedor."
+ },
+ "fields": {
+ "active": "",
+ "am": "",
+ "city": "ciudad",
+ "cost_center": "Centro de costos",
+ "country": "País",
+ "discount": "% De descuento",
+ "display_name": "Nombre para mostrar",
+ "dmsid": "",
+ "due_date": "Fecha de vencimiento del pago",
+ "email": "Email de contacto",
+ "favorite": "¿Favorito?",
+ "lkq": "",
+ "make": "",
+ "name": "Nombre del vendedor",
+ "oem": "",
+ "phone": "",
+ "prompt_discount": "Descuento pronto",
+ "state": "Provincia del estado",
+ "street1": "calle",
+ "street2": "Dirección 2",
+ "taxid": "Identificación del impuesto",
+ "terms": "Términos de pago",
+ "zip": "código postal"
+ },
+ "labels": {
+ "noneselected": "Ningún vendedor está seleccionado.",
+ "preferredmakes": "",
+ "search": "Escriba el nombre de un proveedor"
+ },
+ "successes": {
+ "deleted": "Proveedor eliminado correctamente.",
+ "saved": "Proveedor guardado con éxito."
+ },
+ "validation": {
+ "unique_vendor_name": ""
+ }
+ },
+ "notifications": {
+ "labels": {
+ "notification-center": "",
+ "scenario": "",
+ "notificationscenarios": "",
+ "save": "",
+ "watching-issue": "",
+ "add-watchers": "",
+ "employee-search": "",
+ "teams-search": "",
+ "add-watchers-team": "",
+ "new-notification-title": "",
+ "show-unread-only": "",
+ "mark-all-read": "",
+ "notification-popup-title": "",
+ "ro-number": "",
+ "no-watchers": "",
+ "notification-settings-success": "",
+ "notification-settings-failure": "",
+ "watch": "",
+ "unwatch": ""
+ },
+ "actions": {
+ "remove": ""
+ },
+ "aria": {
+ "toggle": ""
+ },
+ "tooltips": {
+ "job-watchers": ""
+ },
+ "scenarios": {
+ "job-assigned-to-me": "",
+ "bill-posted": "",
+ "critical-parts-status-changed": "",
+ "part-marked-back-ordered": "",
+ "new-note-added": "",
+ "supplement-imported": "",
+ "schedule-dates-changed": "",
+ "tasks-updated-created": "",
+ "new-media-added-reassigned": "",
+ "new-time-ticket-posted": "",
+ "intake-delivery-checklist-completed": "",
+ "job-added-to-production": "",
+ "job-status-change": "",
+ "payment-collected-completed": "",
+ "alternate-transport-changed": ""
+ },
+ "channels": {
+ "app": "",
+ "email": "",
+ "fcm": ""
+ }
+ }
+ }
}
diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json
index 417c2061d..888162de9 100644
--- a/client/src/translations/fr/common.json
+++ b/client/src/translations/fr/common.json
@@ -1,3771 +1,3838 @@
{
- "translation": {
- "allocations": {
- "actions": {
- "assign": "Attribuer"
- },
- "errors": {
- "deleting": "",
- "saving": "",
- "validation": ""
- },
- "fields": {
- "employee": "Alloué à"
- },
- "successes": {
- "deleted": "",
- "save": ""
- }
- },
- "appointments": {
- "actions": {
- "block": "",
- "calculate": "",
- "cancel": "annuler",
- "intake": "Admission",
- "new": "Nouveau rendez-vous",
- "preview": "",
- "reschedule": "Replanifier",
- "sendreminder": "",
- "unblock": "",
- "viewjob": "Voir le travail"
- },
- "errors": {
- "blocking": "",
- "canceling": "Erreur lors de l'annulation du rendez-vous. {{message}}",
- "saving": "Erreur lors de la planification du rendez-vous. {{message}}"
- },
- "fields": {
- "alt_transport": "",
- "color": "",
- "end": "",
- "note": "",
- "start": "",
- "time": "",
- "title": "Titre"
- },
- "labels": {
- "arrivedon": "Arrivé le:",
- "arrivingjobs": "",
- "blocked": "",
- "cancelledappointment": "Rendez-vous annulé pour:",
- "completingjobs": "",
- "dataconsistency": "",
- "expectedjobs": "",
- "expectedprodhrs": "",
- "history": "",
- "inproduction": "",
- "manualevent": "",
- "noarrivingjobs": "",
- "nocompletingjobs": "",
- "nodateselected": "Aucune date n'a été sélectionnée.",
- "priorappointments": "Rendez-vous précédents",
- "reminder": "",
- "scheduledfor": "Rendez-vous prévu pour:",
- "severalerrorsfound": "",
- "smartscheduling": "",
- "smspaymentreminder": "",
- "suggesteddates": ""
- },
- "successes": {
- "canceled": "Rendez-vous annulé avec succès.",
- "created": "Rendez-vous planifié avec succès.",
- "saved": ""
- }
- },
- "associations": {
- "actions": {
- "activate": "Activer"
- },
- "fields": {
- "active": "Actif?",
- "shopname": "nom de la boutique"
- },
- "labels": {
- "actions": "actes"
- }
- },
- "audit": {
- "fields": {
- "cc": "",
- "contents": "",
- "created": "",
- "operation": "",
- "status": "",
- "subject": "",
- "to": "",
- "useremail": "",
- "values": ""
- }
- },
- "audit_trail": {
- "messages": {
- "admin_job_remove_from_ar": "",
- "admin_jobmarkexported": "",
- "admin_jobmarkforreexport": "",
- "admin_jobuninvoice": "",
- "admin_jobunvoid": "",
- "alerttoggle": "",
- "appointmentcancel": "",
- "appointmentinsert": "",
- "assignedlinehours": "",
- "billdeleted": "",
- "billposted": "",
- "billupdated": "",
- "failedpayment": "",
- "jobassignmentchange": "",
- "jobassignmentremoved": "",
- "jobchecklist": "",
- "jobclosedwithbypass": "",
- "jobconverted": "",
- "jobdelivery": "",
- "jobexported": "",
- "jobfieldchanged": "",
- "jobimported": "",
- "jobinproductionchange": "",
- "jobintake": "",
- "jobinvoiced": "",
- "jobioucreated": "",
- "jobmodifylbradj": "",
- "jobnoteadded": "",
- "jobnotedeleted": "",
- "jobnoteupdated": "",
- "jobspartsorder": "",
- "jobspartsreturn": "",
- "jobstatuschange": "",
- "jobsupplement": "",
- "jobsuspend": "",
- "jobvoid": "",
- "tasks_completed": "",
- "tasks_created": "",
- "tasks_deleted": "",
- "tasks_uncompleted": "",
- "tasks_undeleted": "",
- "tasks_updated": ""
- }
- },
- "billlines": {
- "actions": {
- "newline": ""
- },
- "fields": {
- "actual_cost": "",
- "actual_price": "",
- "cost_center": "",
- "federal_tax_applicable": "",
- "jobline": "",
- "line_desc": "",
- "local_tax_applicable": "",
- "location": "",
- "quantity": "",
- "state_tax_applicable": ""
- },
- "labels": {
- "deductedfromlbr": "",
- "entered": "",
- "from": "",
- "mod_lbr_adjustment": "",
- "other": "",
- "reconciled": "",
- "unreconciled": ""
- },
- "validation": {
- "atleastone": ""
- }
- },
- "bills": {
- "actions": {
- "deductallhours": "",
- "edit": "",
- "receive": "",
- "return": ""
- },
- "errors": {
- "creating": "",
- "deleting": "",
- "existinginventoryline": "",
- "exporting": "",
- "exporting-partner": "",
- "invalidro": "",
- "invalidvendor": "",
- "validation": ""
- },
- "fields": {
- "allpartslocation": "",
- "date": "",
- "exported": "",
- "federal_tax_rate": "",
- "invoice_number": "",
- "is_credit_memo": "",
- "is_credit_memo_short": "",
- "local_tax_rate": "",
- "ro_number": "",
- "state_tax_rate": "",
- "total": "",
- "vendor": "",
- "vendorname": ""
- },
- "labels": {
- "actions": "",
- "bill_lines": "",
- "bill_total": "",
- "billcmtotal": "",
- "bills": "",
- "calculatedcreditsnotreceived": "",
- "creditsnotreceived": "",
- "creditsreceived": "",
- "dedfromlbr": "",
- "deleteconfirm": "",
- "discrepancy": "",
- "discrepwithcms": "",
- "discrepwithlbradj": "",
- "editadjwarning": "",
- "entered_total": "",
- "enteringcreditmemo": "",
- "federal_tax": "",
- "federal_tax_exempt": "",
- "generatepartslabel": "",
- "iouexists": "",
- "local_tax": "",
- "markexported": "",
- "markforreexport": "",
- "new": "",
- "nobilllines": "",
- "noneselected": "",
- "onlycmforinvoiced": "",
- "printlabels": "",
- "retailtotal": "",
- "returnfrombill": "",
- "savewithdiscrepancy": "",
- "state_tax": "",
- "subtotal": "",
- "totalreturns": ""
- },
- "successes": {
- "created": "",
- "deleted": "",
- "exported": "",
- "markexported": "",
- "reexport": ""
- },
- "validation": {
- "closingperiod": "",
- "inventoryquantity": "",
- "manualinhouse": "",
- "unique_invoice_number": ""
- }
- },
- "bodyshop": {
- "actions": {
- "add_task_preset": "",
- "addapptcolor": "",
- "addbucket": "",
- "addpartslocation": "",
- "addpartsrule": "",
- "addspeedprint": "",
- "addtemplate": "",
- "newlaborrate": "",
- "newsalestaxcode": "",
- "newstatus": "",
- "testrender": ""
- },
- "errors": {
- "creatingdefaultview": "",
- "loading": "Impossible de charger les détails de la boutique. Veuillez appeler le support technique.",
- "saving": ""
- },
- "fields": {
- "ReceivableCustomField": "",
- "address1": "",
- "address2": "",
- "appt_alt_transport": "",
- "appt_colors": {
- "color": "",
- "label": ""
- },
- "appt_length": "",
- "attach_pdf_to_email": "",
- "batchid": "",
- "bill_allow_post_to_closed": "",
- "bill_federal_tax_rate": "",
- "bill_local_tax_rate": "",
- "bill_state_tax_rate": "",
- "city": "",
- "closingperiod": "",
- "companycode": "",
- "country": "",
- "dailybodytarget": "",
- "dailypainttarget": "",
- "default_adjustment_rate": "",
- "deliver": {
- "require_actual_delivery_date": "",
- "templates": ""
- },
- "dms": {
- "apcontrol": "",
- "appostingaccount": "",
- "cashierid": "",
- "default_journal": "",
- "disablebillwip": "",
- "disablecontactvehiclecreation": "",
- "dms_acctnumber": "",
- "dms_control_override": "",
- "dms_wip_acctnumber": "",
- "generic_customer_number": "",
- "itc_federal": "",
- "itc_local": "",
- "itc_state": "",
- "mappingname": "",
- "sendmaterialscosting": "",
- "srcco": ""
- },
- "email": "",
- "enforce_class": "",
- "enforce_conversion_category": "",
- "enforce_conversion_csr": "",
- "enforce_referral": "",
- "federal_tax_id": "",
- "ignoreblockeddays": "",
- "inhousevendorid": "",
- "insurance_vendor_id": "",
- "intake": {
- "next_contact_hours": "",
- "templates": ""
- },
- "intellipay_config": {
- "cash_discount_percentage": "",
- "enable_cash_discount": ""
- },
- "invoice_federal_tax_rate": "",
- "invoice_local_tax_rate": "",
- "invoice_state_tax_rate": "",
- "jc_hourly_rates": {
- "mapa": "",
- "mash": ""
- },
- "last_name_first": "",
- "lastnumberworkingdays": "",
- "localmediaserverhttp": "",
- "localmediaservernetwork": "",
- "localmediatoken": "",
- "logo_img_footer_margin": "",
- "logo_img_header_margin": "",
- "logo_img_path": "",
- "logo_img_path_height": "",
- "logo_img_path_width": "",
- "md_categories": "",
- "md_ccc_rates": "",
- "md_classes": "",
- "md_ded_notes": "",
- "md_email_cc": "",
- "md_from_emails": "",
- "md_functionality_toggles": {
- "parts_queue_toggle": ""
- },
- "md_hour_split": {
- "paint": "",
- "prep": ""
- },
- "md_ins_co": {
- "city": "",
- "name": "",
- "private": "",
- "state": "",
- "street1": "",
- "street2": "",
- "zip": ""
- },
- "md_jobline_presets": "",
- "md_lost_sale_reasons": "",
- "md_parts_order_comment": "",
- "md_parts_scan": {
- "caseInsensitive": "",
- "expression": "",
- "field": "",
- "flags": "",
- "mark_critical": "",
- "operation": "",
- "update_field": "",
- "update_value": "",
- "value": ""
- },
- "md_payment_types": "",
- "md_referral_sources": "",
- "md_ro_guard": {
- "enabled": "",
- "enforce_ar": "",
- "enforce_bills": "",
- "enforce_cm": "",
- "enforce_labor": "",
- "enforce_ppd": "",
- "enforce_profit": "",
- "enforce_sublet": "",
- "masterbypass": "",
- "totalgppercent_minimum": ""
- },
- "md_tasks_presets": {
- "enable_tasks": "",
- "hourstype": "",
- "memo": "",
- "name": "",
- "nextstatus": "",
- "percent": "",
- "use_approvals": ""
- },
- "messaginglabel": "",
- "messagingtext": "",
- "noteslabel": "",
- "notestext": "",
- "partslocation": "",
- "phone": "",
- "prodtargethrs": "",
- "rbac": {
- "accounting": {
- "exportlog": "",
- "payables": "",
- "payments": "",
- "receivables": ""
- },
- "bills": {
- "delete": "",
- "enter": "",
- "list": "",
- "reexport": "",
- "view": ""
- },
- "contracts": {
- "create": "",
- "detail": "",
- "list": ""
- },
- "courtesycar": {
- "create": "",
- "detail": "",
- "list": ""
- },
- "csi": {
- "export": "",
- "page": ""
- },
- "employee_teams": {
- "page": ""
- },
- "employees": {
- "page": ""
- },
- "inventory": {
- "delete": "",
- "list": ""
- },
- "jobs": {
- "admin": "",
- "available-list": "",
- "checklist-view": "",
- "close": "",
- "create": "",
- "deliver": "",
- "detail": "",
- "intake": "",
- "list-active": "",
- "list-all": "",
- "list-ready": "",
- "partsqueue": "",
- "void": ""
- },
- "owners": {
- "detail": "",
- "list": ""
- },
- "payments": {
- "enter": "",
- "list": ""
- },
- "phonebook": {
- "edit": "",
- "view": ""
- },
- "production": {
- "board": "",
- "list": ""
- },
- "schedule": {
- "view": ""
- },
- "scoreboard": {
- "view": ""
- },
- "shiftclock": {
- "view": ""
- },
- "shop": {
- "config": "",
- "dashboard": "",
- "rbac": "",
- "reportcenter": "",
- "templates": "",
- "vendors": ""
- },
- "temporarydocs": {
- "view": ""
- },
- "timetickets": {
- "edit": "",
- "editcommitted": "",
- "enter": "",
- "list": "",
- "shiftedit": ""
- },
- "ttapprovals": {
- "approve": "",
- "view": ""
- },
- "users": {
- "editaccess": ""
- }
- },
- "responsibilitycenter": "",
- "responsibilitycenter_accountdesc": "",
- "responsibilitycenter_accountitem": "",
- "responsibilitycenter_accountname": "",
- "responsibilitycenter_accountnumber": "",
- "responsibilitycenter_rate": "",
- "responsibilitycenter_tax_rate": "",
- "responsibilitycenter_tax_sur": "",
- "responsibilitycenter_tax_thres": "",
- "responsibilitycenter_tax_tier": "",
- "responsibilitycenter_tax_type": "",
- "responsibilitycenters": {
- "ap": "",
- "ar": "",
- "ats": "",
- "federal_tax": "",
- "federal_tax_itc": "",
- "gst_override": "",
- "invoiceexemptcode": "",
- "itemexemptcode": "",
- "la1": "",
- "la2": "",
- "la3": "",
- "la4": "",
- "laa": "",
- "lab": "",
- "lad": "",
- "lae": "",
- "laf": "",
- "lag": "",
- "lam": "",
- "lar": "",
- "las": "",
- "lau": "",
- "local_tax": "",
- "mapa": "",
- "mash": "",
- "paa": "",
- "pac": "",
- "pag": "",
- "pal": "",
- "pam": "",
- "pan": "",
- "pao": "",
- "pap": "",
- "par": "",
- "pas": "",
- "pasl": "",
- "refund": "",
- "sales_tax_codes": {
- "code": "",
- "description": "",
- "federal": "",
- "local": "",
- "state": ""
- },
- "state_tax": "",
- "tow": ""
- },
- "schedule_end_time": "",
- "schedule_start_time": "",
- "shopname": "",
- "speedprint": {
- "id": "",
- "label": "",
- "templates": ""
- },
- "ss_configuration": {
- "dailyhrslimit": ""
- },
- "ssbuckets": {
- "color": "",
- "gte": "",
- "id": "",
- "label": "",
- "lt": "",
- "target": ""
- },
- "state": "",
- "state_tax_id": "",
- "status": "",
- "statuses": {
- "active_statuses": "",
- "additional_board_statuses": "",
- "color": "",
- "default_arrived": "",
- "default_bo": "",
- "default_canceled": "",
- "default_completed": "",
- "default_delivered": "",
- "default_exported": "",
- "default_imported": "",
- "default_invoiced": "",
- "default_ordered": "",
- "default_quote": "",
- "default_received": "",
- "default_returned": "",
- "default_scheduled": "",
- "default_void": "",
- "open_statuses": "",
- "post_production_statuses": "",
- "pre_production_statuses": "",
- "production_colors": "",
- "production_statuses": "",
- "ready_statuses": ""
- },
- "target_touchtime": "",
- "timezone": "",
- "tt_allow_post_to_invoiced": "",
- "tt_enforce_hours_for_tech_console": "",
- "use_fippa": "",
- "use_paint_scale_data": "",
- "uselocalmediaserver": "",
- "website": "",
- "zip_post": ""
- },
- "labels": {
- "2tiername": "",
- "2tiersetup": "",
- "2tiersource": "",
- "accountingsetup": "",
- "accountingtiers": "",
- "alljobstatuses": "",
- "allopenjobstatuses": "",
- "apptcolors": "",
- "businessinformation": "",
- "checklists": "",
- "csiq": "",
- "customtemplates": "",
- "defaultcostsmapping": "",
- "defaultprofitsmapping": "",
- "deliverchecklist": "",
- "dms": {
- "cdk": {
- "controllist": "",
- "payers": ""
- },
- "cdk_dealerid": "",
- "costsmapping": "",
- "dms_allocations": "",
- "pbs_serialnumber": "",
- "profitsmapping": "",
- "title": ""
- },
- "emaillater": "",
- "employee_teams": "",
- "employees": "",
- "estimators": "",
- "filehandlers": "",
- "imexpay": "",
- "insurancecos": "",
- "intakechecklist": "",
- "intellipay_cash_discount": "",
- "jobstatuses": "",
- "laborrates": "",
- "licensing": "",
- "md_parts_scan": "",
- "md_ro_guard": "",
- "md_tasks_presets": "",
- "md_to_emails": "",
- "md_to_emails_emails": "",
- "messagingpresets": "",
- "notemplatesavailable": "",
- "notespresets": "",
- "orderstatuses": "",
- "partslocations": "",
- "partsscan": "",
- "printlater": "",
- "qbo": "",
- "qbo_departmentid": "",
- "qbo_usa": "",
- "rbac": "",
- "responsibilitycenters": {
- "costs": "",
- "profits": "",
- "sales_tax_codes": "",
- "tax_accounts": "",
- "title": "",
- "ttl_adjustment": "",
- "ttl_tax_adjustment": ""
- },
- "roguard": {
- "title": ""
- },
- "romepay": "",
- "scheduling": "",
- "scoreboardsetup": "",
- "shop_enabled_features": "",
- "shopinfo": "",
- "speedprint": "",
- "ssbuckets": "",
- "systemsettings": "",
- "task-presets": "",
- "workingdays": ""
- },
- "operations": {
- "contains": "",
- "ends_with": "",
- "equals": "",
- "greater_than": "",
- "less_than": "",
- "not_equals": "",
- "starts_with": ""
- },
- "successes": {
- "areyousure": "",
- "defaultviewcreated": "",
- "save": "",
- "unsavedchanges": ""
- },
- "tooltips": {
- "md_parts_scan": {
- "update_value_tooltip": ""
- }
- },
- "validation": {
- "centermustexist": "",
- "larsplit": "",
- "useremailmustexist": ""
- }
- },
- "checklist": {
- "actions": {
- "printall": ""
- },
- "errors": {
- "complete": "",
- "nochecklist": ""
- },
- "labels": {
- "addtoproduction": "",
- "allow_text_message": "",
- "checklist": "",
- "printpack": "",
- "removefromproduction": ""
- },
- "successes": {
- "completed": ""
- }
- },
- "contracts": {
- "actions": {
- "changerate": "",
- "convertoro": "",
- "decodelicense": "",
- "find": "",
- "printcontract": "",
- "senddltoform": ""
- },
- "errors": {
- "fetchingjobinfo": "",
- "returning": "",
- "saving": "",
- "selectjobandcar": ""
- },
- "fields": {
- "actax": "",
- "actualreturn": "",
- "agreementnumber": "",
- "cc_cardholder": "",
- "cc_expiry": "",
- "cc_num": "",
- "cleanupcharge": "",
- "coverage": "",
- "dailyfreekm": "",
- "dailyrate": "",
- "damage": "",
- "damagewaiver": "",
- "driver": "",
- "driver_addr1": "",
- "driver_addr2": "",
- "driver_city": "",
- "driver_dlexpiry": "",
- "driver_dlnumber": "",
- "driver_dlst": "",
- "driver_dob": "",
- "driver_fn": "",
- "driver_ln": "",
- "driver_ph1": "",
- "driver_state": "",
- "driver_zip": "",
- "excesskmrate": "",
- "federaltax": "",
- "fuelin": "",
- "fuelout": "",
- "kmend": "",
- "kmstart": "",
- "length": "",
- "localtax": "",
- "refuelcharge": "",
- "scheduledreturn": "",
- "start": "",
- "statetax": "",
- "status": ""
- },
- "labels": {
- "agreement": "",
- "availablecars": "",
- "cardueforservice": "",
- "convertform": {
- "applycleanupcharge": "",
- "refuelqty": ""
- },
- "correctdataonform": "",
- "dateinpast": "",
- "dlexpirebeforereturn": "",
- "driverinformation": "",
- "findcontract": "",
- "findermodal": "",
- "insuranceexpired": "",
- "noteconvertedfrom": "",
- "populatefromjob": "",
- "rates": "",
- "time": "",
- "vehicle": "",
- "waitingforscan": ""
- },
- "status": {
- "new": "",
- "out": "",
- "returned": ""
- },
- "successes": {
- "saved": ""
- }
- },
- "courtesycars": {
- "actions": {
- "new": "",
- "return": ""
- },
- "errors": {
- "saving": ""
- },
- "fields": {
- "color": "",
- "dailycost": "",
- "damage": "",
- "fleetnumber": "",
- "fuel": "",
- "insuranceexpires": "",
- "leaseenddate": "",
- "make": "",
- "mileage": "",
- "model": "",
- "nextservicedate": "",
- "nextservicekm": "",
- "notes": "",
- "plate": "",
- "purchasedate": "",
- "readiness": "",
- "registrationexpires": "",
- "serviceenddate": "",
- "servicestartdate": "",
- "status": "",
- "vin": "",
- "year": ""
- },
- "labels": {
- "courtesycar": "",
- "fuel": {
- "12": "",
- "14": "",
- "18": "",
- "34": "",
- "38": "",
- "58": "",
- "78": "",
- "empty": "",
- "full": ""
- },
- "outwith": "",
- "return": "",
- "status": "",
- "uniquefleet": "",
- "usage": "",
- "vehicle": ""
- },
- "readiness": {
- "notready": "",
- "ready": ""
- },
- "status": {
- "in": "",
- "inservice": "",
- "leasereturn": "",
- "out": "",
- "sold": "",
- "unavailable": ""
- },
- "successes": {
- "saved": ""
- }
- },
- "csi": {
- "actions": {
- "activate": ""
- },
- "errors": {
- "creating": "",
- "notconfigured": "",
- "notfoundsubtitle": "",
- "notfoundtitle": "",
- "surveycompletesubtitle": "",
- "surveycompletetitle": ""
- },
- "fields": {
- "completedon": "",
- "created_at": "",
- "surveyid": "",
- "validuntil": ""
- },
- "labels": {
- "copyright": "",
- "greeting": "",
- "intro": "",
- "nologgedinuser": "",
- "nologgedinuser_sub": "",
- "noneselected": "",
- "title": ""
- },
- "successes": {
- "created": "",
- "submitted": "",
- "submittedsub": ""
- }
- },
- "dashboard": {
- "actions": {
- "addcomponent": ""
- },
- "errors": {
- "refreshrequired": "",
- "updatinglayout": ""
- },
- "labels": {
- "bodyhrs": "",
- "dollarsinproduction": "",
- "phone": "",
- "prodhrs": "",
- "refhrs": ""
- },
- "titles": {
- "joblifecycle": "",
- "labhours": "",
- "larhours": "",
- "monthlyemployeeefficiency": "",
- "monthlyjobcosting": "",
- "monthlylaborsales": "",
- "monthlypartssales": "",
- "monthlyrevenuegraph": "",
- "prodhrssummary": "",
- "productiondollars": "",
- "productionhours": "",
- "projectedmonthlysales": "",
- "scheduledindate": "",
- "scheduledintoday": "",
- "scheduledoutdate": "",
- "scheduledouttoday": "",
- "tasks": ""
- }
- },
- "dms": {
- "errors": {
- "alreadyexported": ""
- },
- "labels": {
- "refreshallocations": ""
- }
- },
- "documents": {
- "actions": {
- "delete": "",
- "download": "",
- "reassign": "",
- "selectallimages": "",
- "selectallotherdocuments": ""
- },
- "errors": {
- "deletes3": "Erreur lors de la suppression du document du stockage.",
- "deleting": "",
- "deleting_cloudinary": "",
- "getpresignurl": "Erreur lors de l'obtention de l'URL présignée pour le document. {{message}}",
- "insert": "Incapable de télécharger le fichier. {{message}}",
- "nodocuments": "Il n'y a pas de documents.",
- "updating": ""
- },
- "labels": {
- "confirmdelete": "",
- "doctype": "",
- "dragtoupload": "",
- "newjobid": "",
- "openinexplorer": "",
- "optimizedimage": "",
- "reassign_limitexceeded": "",
- "reassign_limitexceeded_title": "",
- "storageexceeded": "",
- "storageexceeded_title": "",
- "upload": "Télécharger",
- "upload_limitexceeded": "",
- "upload_limitexceeded_title": "",
- "uploading": "",
- "usage": ""
- },
- "successes": {
- "delete": "Le document a bien été supprimé.",
- "edituploaded": "",
- "insert": "Document téléchargé avec succès.",
- "updated": ""
- }
- },
- "emails": {
- "errors": {
- "notsent": "Courriel non envoyé. Erreur rencontrée lors de l'envoi de {{message}}"
- },
- "fields": {
- "cc": "",
- "from": "",
- "subject": "",
- "to": ""
- },
- "labels": {
- "attachments": "",
- "documents": "",
- "emailpreview": "",
- "generatingemail": "",
- "pdfcopywillbeattached": "",
- "preview": ""
- },
- "successes": {
- "sent": "E-mail envoyé avec succès."
- }
- },
- "employee_teams": {
- "actions": {
- "new": "",
- "newmember": ""
- },
- "fields": {
- "active": "",
- "employeeid": "",
- "max_load": "",
- "name": "",
- "percentage": ""
- }
- },
- "employees": {
- "actions": {
- "addvacation": "",
- "new": "Nouvel employé",
- "newrate": ""
- },
- "errors": {
- "delete": "Erreur rencontrée lors de la suppression de l'employé. {{message}}",
- "save": "Une erreur s'est produite lors de l'enregistrement de l'employé. {{message}}",
- "validation": "Veuillez cocher tous les champs.",
- "validationtitle": "Impossible d'enregistrer l'employé."
- },
- "fields": {
- "active": "Actif?",
- "base_rate": "Taux de base",
- "cost_center": "Centre de coûts",
- "employee_number": "Numéro d'employé",
- "external_id": "",
- "first_name": "Prénom",
- "flat_rate": "Taux fixe (désactivé est le temps normal)",
- "hire_date": "Date d'embauche",
- "last_name": "Nom de famille",
- "pin": "",
- "rate": "",
- "termination_date": "Date de résiliation",
- "user_email": "",
- "vacation": {
- "end": "",
- "length": "",
- "start": ""
- }
- },
- "labels": {
- "actions": "",
- "active": "",
- "endmustbeafterstart": "",
- "flat_rate": "",
- "inactive": "",
- "name": "",
- "rate_type": "",
- "status": "",
- "straight_time": ""
- },
- "successes": {
- "delete": "L'employé a bien été supprimé.",
- "save": "L'employé a enregistré avec succès.",
- "vacationadded": ""
- },
- "validation": {
- "unique_employee_number": ""
- }
- },
- "eula": {
- "buttons": {
- "accept": "Accept EULA"
- },
- "content": {
- "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting."
- },
- "errors": {
- "acceptance": {
- "description": "Something went wrong while accepting the EULA. Please try again.",
- "message": "Eula Acceptance Error"
- }
- },
- "labels": {
- "accepted_terms": "I accept the terms and conditions of this agreement.",
- "address": "Address",
- "business_name": "Legal Business Name",
- "date_accepted": "Date Accepted",
- "first_name": "First Name",
- "last_name": "Last Name",
- "phone_number": "Phone Number"
- },
- "messages": {
- "accepted_terms": "Please accept the terms and conditions of this agreement.",
- "business_name": "Please enter your legal business name.",
- "date_accepted": "Please enter Today's Date.",
- "first_name": "Please enter your first name.",
- "last_name": "Please enter your last name.",
- "phone_number": "Please enter your phone number."
- },
- "titles": {
- "modal": "Terms and Conditions",
- "upper_card": "Acknowledgement"
- }
- },
- "exportlogs": {
- "fields": {
- "createdat": ""
- },
- "labels": {
- "attempts": "",
- "priorsuccesfulexport": ""
- }
- },
- "general": {
- "actions": {
- "add": "",
- "autoupdate": "",
- "calculate": "",
- "cancel": "",
- "clear": "",
- "close": "",
- "copied": "",
- "copylink": "",
- "create": "",
- "defaults": "",
- "delay": "",
- "delete": "Effacer",
- "deleteall": "",
- "deselectall": "",
- "download": "",
- "edit": "modifier",
- "login": "",
- "next": "",
- "ok": "",
- "previous": "",
- "print": "",
- "refresh": "",
- "remove": "",
- "remove_alert": "",
- "reset": " Rétablir l'original.",
- "resetpassword": "",
- "save": "sauvegarder",
- "saveandnew": "",
- "saveas": "",
- "selectall": "",
- "send": "",
- "sendbysms": "",
- "senderrortosupport": "",
- "sharetoteams": "",
- "submit": "",
- "tryagain": "",
- "view": "",
- "viewreleasenotes": ""
- },
- "errors": {
- "fcm": "",
- "notfound": "",
- "sizelimit": ""
- },
- "itemtypes": {
- "contract": "",
- "courtesycar": "",
- "job": "",
- "owner": "",
- "vehicle": ""
- },
- "labels": {
- "actions": "actes",
- "areyousure": "",
- "barcode": "code à barre",
- "cancel": "",
- "clear": "",
- "confirmpassword": "",
- "created_at": "",
- "date": "",
- "datetime": "",
- "email": "",
- "errors": "",
- "excel": "",
- "exceptiontitle": "",
- "friday": "",
- "globalsearch": "",
- "help": "",
- "hours": "",
- "in": "dans",
- "instanceconflictext": "",
- "instanceconflictitle": "",
- "item": "",
- "label": "",
- "loading": "Chargement...",
- "loadingapp": "Chargement de {{app}}",
- "loadingshop": "Chargement des données de la boutique ...",
- "loggingin": "Vous connecter ...",
- "markedexported": "",
- "media": "",
- "message": "",
- "monday": "",
- "na": "N / A",
- "newpassword": "",
- "no": "",
- "nointernet": "",
- "nointernet_sub": "",
- "none": "",
- "out": "En dehors",
- "password": "",
- "passwordresetsuccess": "",
- "passwordresetsuccess_sub": "",
- "passwordresetvalidatesuccess": "",
- "passwordresetvalidatesuccess_sub": "",
- "passwordsdonotmatch": "",
- "print": "",
- "refresh": "",
- "reports": "",
- "required": "",
- "saturday": "",
- "search": "Chercher...",
- "searchresults": "",
- "selectdate": "",
- "sendagain": "",
- "sendby": "",
- "signin": "",
- "sms": "",
- "status": "",
- "sub_status": {
- "expired": ""
- },
- "successful": "",
- "sunday": "",
- "text": "",
- "thursday": "",
- "time": "",
- "total": "",
- "totals": "",
- "tuesday": "",
- "tvmode": "",
- "unknown": "Inconnu",
- "unsavedchanges": "",
- "username": "",
- "view": "",
- "wednesday": "",
- "yes": ""
- },
- "languages": {
- "english": "Anglais",
- "french": "Francais",
- "spanish": "Espanol"
- },
- "messages": {
- "exception": "",
- "newversionmessage": "",
- "newversiontitle": "",
- "noacctfilepath": "",
- "nofeatureaccess": "",
- "noshop": "",
- "notfoundsub": "",
- "notfoundtitle": "",
- "partnernotrunning": "",
- "rbacunauth": "",
- "unsavedchanges": "Vous avez des changements non enregistrés.",
- "unsavedchangespopup": ""
- },
- "validation": {
- "dateRangeExceeded": "",
- "invalidemail": "S'il vous plaît entrer un email valide.",
- "invalidphone": "",
- "required": "Ce champ est requis."
- }
- },
- "help": {
- "actions": {
- "connect": ""
- },
- "labels": {
- "codeplacholder": "",
- "rescuedesc": "",
- "rescuetitle": ""
- }
- },
- "intake": {
- "labels": {
- "printpack": ""
- }
- },
- "inventory": {
- "actions": {
- "addtoinventory": "",
- "addtoro": "",
- "consumefrominventory": "",
- "edit": "",
- "new": ""
- },
- "errors": {
- "inserting": ""
- },
- "fields": {
- "comment": "",
- "manualinvoicenumber": "",
- "manualvendor": ""
- },
- "labels": {
- "consumedbyjob": "",
- "deleteconfirm": "",
- "frombillinvoicenumber": "",
- "fromvendor": "",
- "inventory": "",
- "showall": "",
- "showavailable": ""
- },
- "successes": {
- "deleted": "",
- "inserted": "",
- "updated": ""
- }
- },
- "job_lifecycle": {
- "columns": {
- "average_human_readable": "",
- "average_value": "",
- "duration": "",
- "end": "",
- "human_readable": "",
- "percentage": "",
- "relative_end": "",
- "relative_start": "",
- "start": "",
- "status": "",
- "status_count": "",
- "value": ""
- },
- "content": {
- "calculated_based_on": "",
- "current_status_accumulated_time": "",
- "data_unavailable": "",
- "jobs_in_since": "",
- "legend_title": "",
- "loading": "",
- "not_available": "",
- "previous_status_accumulated_time": "",
- "title": "",
- "title_durations": "",
- "title_loading": "",
- "title_transitions": ""
- },
- "errors": {
- "fetch": "Erreur lors de l'obtention des données du cycle de vie des tâches"
- },
- "titles": {
- "dashboard": "",
- "top_durations": ""
- }
- },
- "job_payments": {
- "buttons": {
- "create_short_link": "",
- "goback": "",
- "proceedtopayment": "",
- "refundpayment": ""
- },
- "notifications": {
- "error": {
- "description": "",
- "openingip": "",
- "title": ""
- }
- },
- "titles": {
- "amount": "",
- "dateOfPayment": "",
- "descriptions": "",
- "hint": "",
- "payer": "",
- "payername": "",
- "paymentid": "",
- "paymentnum": "",
- "paymenttype": "",
- "refundamount": "",
- "transactionid": ""
- }
- },
- "joblines": {
- "actions": {
- "assign_team": "",
- "converttolabor": "",
- "dispatchparts": "",
- "new": ""
- },
- "errors": {
- "creating": "",
- "updating": ""
- },
- "fields": {
- "act_price": "Prix actuel",
- "act_price_before_ppc": "",
- "adjustment": "",
- "ah_detail_line": "",
- "alt_partno": "",
- "amount": "",
- "assigned_team": "",
- "assigned_team_name": "",
- "create_ppc": "",
- "db_price": "Prix de la base de données",
- "include_in_part_cnt": "",
- "lbr_types": {
- "LA1": "",
- "LA2": "",
- "LA3": "",
- "LA4": "",
- "LAA": "",
- "LAB": "",
- "LAD": "",
- "LAE": "",
- "LAF": "",
- "LAG": "",
- "LAM": "",
- "LAR": "",
- "LAS": "",
- "LAU": ""
- },
- "line_desc": "Description de la ligne",
- "line_ind": "S#",
- "line_no": "",
- "location": "",
- "mod_lb_hrs": "Heures de travail",
- "mod_lbr_ty": "Type de travail",
- "notes": "",
- "oem_partno": "Pièce OEM #",
- "op_code_desc": "",
- "part_qty": "",
- "part_type": "Type de pièce",
- "part_types": {
- "CCC": "",
- "CCD": "",
- "CCDR": "",
- "CCF": "",
- "CCM": "",
- "PAA": "",
- "PAC": "",
- "PAE": "",
- "PAG": "",
- "PAL": "",
- "PAM": "",
- "PAN": "",
- "PAO": "",
- "PAP": "",
- "PAR": "",
- "PAS": "",
- "PASL": ""
- },
- "profitcenter_labor": "",
- "profitcenter_part": "",
- "prt_dsmk_m": "",
- "prt_dsmk_p": "",
- "status": "Statut",
- "tax_part": "",
- "total": "",
- "unq_seq": "Seq #"
- },
- "labels": {
- "adjustmenttobeadded": "",
- "billref": "",
- "convertedtolabor": "",
- "edit": "Ligne d'édition",
- "ioucreated": "",
- "new": "Nouvelle ligne",
- "nostatus": "",
- "presets": ""
- },
- "successes": {
- "created": "",
- "saved": "",
- "updated": ""
- },
- "validations": {
- "ahdetailonlyonuserdefinedtypes": "",
- "hrsrequirediflbrtyp": "",
- "requiredifparttype": "",
- "zeropriceexistingpart": ""
- }
- },
- "jobs": {
- "actions": {
- "addDocuments": "Ajouter des documents de travail",
- "addNote": "Ajouter une note",
- "addtopartsqueue": "",
- "addtoproduction": "",
- "addtoscoreboard": "",
- "allocate": "",
- "autoallocate": "",
- "changefilehandler": "",
- "changelaborrate": "",
- "changestatus": "Changer le statut",
- "changestimator": "",
- "convert": "Convertir",
- "createiou": "",
- "deliver": "",
- "deliver_quick": "",
- "dms": {
- "addpayer": "",
- "createnewcustomer": "",
- "findmakemodelcode": "",
- "getmakes": "",
- "labels": {
- "refreshallocations": ""
- },
- "post": "",
- "refetchmakesmodels": "",
- "usegeneric": "",
- "useselected": ""
- },
- "dmsautoallocate": "",
- "export": "",
- "exportcustdata": "",
- "exportselected": "",
- "filterpartsonly": "",
- "generatecsi": "",
- "gotojob": "",
- "intake": "",
- "intake_quick": "",
- "manualnew": "",
- "mark": "",
- "markasexported": "",
- "markpstexempt": "",
- "markpstexemptconfirm": "",
- "postbills": "Poster des factures",
- "printCenter": "Centre d'impression",
- "recalculate": "",
- "reconcile": "",
- "removefromproduction": "",
- "schedule": "Programme",
- "sendcsi": "",
- "sendpartspricechange": "",
- "sendtodms": "",
- "sync": "",
- "taxprofileoverride": "",
- "taxprofileoverride_confirm": "",
- "uninvoice": "",
- "unvoid": "",
- "viewchecklist": "",
- "viewdetail": ""
- },
- "errors": {
- "addingtoproduction": "",
- "cannotintake": "",
- "closing": "",
- "creating": "",
- "deleted": "Erreur lors de la suppression du travail.",
- "exporting": "",
- "exporting-partner": "",
- "invoicing": "",
- "noaccess": "Ce travail n'existe pas ou vous n'y avez pas accès.",
- "nodamage": "",
- "nodates": "Aucune date spécifiée pour ce travail.",
- "nofinancial": "",
- "nojobselected": "Aucun travail n'est sélectionné.",
- "noowner": "Aucun propriétaire associé.",
- "novehicle": "Aucun véhicule associé.",
- "partspricechange": "",
- "saving": "Erreur rencontrée lors de la sauvegarde de l'enregistrement.",
- "scanimport": "",
- "totalscalc": "",
- "updating": "",
- "validation": "Veuillez vous assurer que tous les champs sont correctement entrés.",
- "validationtitle": "Erreur de validation",
- "voiding": ""
- },
- "fields": {
- "active_tasks": "",
- "actual_completion": "Achèvement réel",
- "actual_delivery": "Livraison réelle",
- "actual_in": "En réel",
- "adjustment_bottom_line": "Ajustements",
- "adjustmenthours": "",
- "alt_transport": "",
- "area_of_damage_impact": {
- "10": "",
- "11": "",
- "12": "",
- "13": "",
- "14": "",
- "15": "",
- "16": "",
- "25": "",
- "26": "",
- "27": "",
- "28": "",
- "34": "",
- "01": "",
- "02": "",
- "03": "",
- "04": "",
- "05": "",
- "06": "",
- "07": "",
- "08": "",
- "09": ""
- },
- "auto_add_ats": "",
- "ca_bc_pvrt": "",
- "ca_customer_gst": "",
- "ca_gst_registrant": "",
- "category": "",
- "ccc": "",
- "ccd": "",
- "ccdr": "",
- "ccf": "",
- "ccm": "",
- "cieca_id": "CIECA ID",
- "cieca_pfl": {
- "lbr_adjp": "",
- "lbr_tax_in": "",
- "lbr_taxp": "",
- "lbr_tx_in1": "",
- "lbr_tx_in2": "",
- "lbr_tx_in3": "",
- "lbr_tx_in4": "",
- "lbr_tx_in5": ""
- },
- "cieca_pfo": {
- "stor_t_in1": "",
- "stor_t_in2": "",
- "stor_t_in3": "",
- "stor_t_in4": "",
- "stor_t_in5": "",
- "tow_t_in1": "",
- "tow_t_in2": "",
- "tow_t_in3": "",
- "tow_t_in4": "",
- "tow_t_in5": ""
- },
- "claim_total": "Total réclamation",
- "class": "",
- "clm_no": "Prétendre #",
- "clm_total": "Total réclamation",
- "comment": "",
- "customerowing": "Client propriétaire",
- "date_estimated": "Date estimée",
- "date_exported": "Exportés",
- "date_invoiced": "Facturé",
- "date_last_contacted": "",
- "date_lost_sale": "",
- "date_next_contact": "",
- "date_open": "Ouvrir",
- "date_rentalresp": "",
- "date_repairstarted": "",
- "date_scheduled": "Prévu",
- "date_towin": "",
- "date_void": "",
- "ded_amt": "Déductible",
- "ded_note": "",
- "ded_status": "Statut de franchise",
- "depreciation_taxes": "Amortissement / taxes",
- "dms": {
- "address": "",
- "amount": "",
- "center": "",
- "control_type": {
- "account_number": ""
- },
- "cost": "",
- "cost_dms_acctnumber": "",
- "dms_make": "",
- "dms_model": "",
- "dms_model_override": "",
- "dms_unsold": "",
- "dms_wip_acctnumber": "",
- "id": "",
- "inservicedate": "",
- "journal": "",
- "lines": "",
- "name1": "",
- "payer": {
- "amount": "",
- "control_type": "",
- "controlnumber": "",
- "dms_acctnumber": "",
- "name": ""
- },
- "sale": "",
- "sale_dms_acctnumber": "",
- "story": "",
- "vinowner": ""
- },
- "dms_allocation": "",
- "driveable": "",
- "employee_body": "",
- "employee_csr": "représentant du service à la clientèle",
- "employee_csr_writer": "",
- "employee_prep": "",
- "employee_refinish": "",
- "est_addr1": "Adresse de l'évaluateur",
- "est_co_nm": "Expert",
- "est_ct_fn": "Prénom de l'évaluateur",
- "est_ct_ln": "Nom de l'évaluateur",
- "est_ea": "Courriel de l'évaluateur",
- "est_ph1": "Numéro de téléphone de l'évaluateur",
- "federal_tax_payable": "Impôt fédéral à payer",
- "federal_tax_rate": "",
- "ins_addr1": "Adresse Insurance Co.",
- "ins_city": "Insurance City",
- "ins_co_id": "ID de la compagnie d'assurance",
- "ins_co_nm": "Nom de la compagnie d'assurance",
- "ins_co_nm_short": "",
- "ins_ct_fn": "Prénom du gestionnaire de fichiers",
- "ins_ct_ln": "Nom du gestionnaire de fichiers",
- "ins_ea": "Courriel du gestionnaire de fichiers",
- "ins_ph1": "Numéro de téléphone du gestionnaire de fichiers",
- "intake": {
- "label": "",
- "max": "",
- "min": "",
- "name": "",
- "required": "",
- "type": ""
- },
- "invoice_final_note": "",
- "kmin": "Kilométrage en",
- "kmout": "Kilométrage hors",
- "la1": "",
- "la2": "",
- "la3": "",
- "la4": "",
- "laa": "",
- "lab": "",
- "labor_rate_desc": "Nom du taux de main-d'œuvre",
- "lad": "",
- "lae": "",
- "laf": "",
- "lag": "",
- "lam": "",
- "lar": "",
- "las": "",
- "lau": "",
- "local_tax_rate": "",
- "loss_date": "Date de perte",
- "loss_desc": "",
- "loss_of_use": "",
- "lost_sale_reason": "",
- "ma2s": "",
- "ma3s": "",
- "mabl": "",
- "macs": "",
- "mahw": "",
- "mapa": "",
- "mash": "",
- "matd": "",
- "materials": {
- "MAPA": "",
- "MASH": "",
- "cal_maxdlr": "",
- "cal_opcode": "",
- "mat_adjp": "",
- "mat_taxp": "",
- "mat_tx_in1": "",
- "mat_tx_in2": "",
- "mat_tx_in3": "",
- "mat_tx_in4": "",
- "mat_tx_in5": "",
- "materials": "",
- "tax_ind": ""
- },
- "other_amount_payable": "Autre montant à payer",
- "owner": "Propriétaire",
- "owner_owing": "Cust. Owes",
- "ownr_ea": "Email",
- "ownr_ph1": "Téléphone 1",
- "ownr_ph2": "",
- "paa": "",
- "pac": "",
- "pae": "",
- "pag": "",
- "pal": "",
- "pam": "",
- "pan": "",
- "pao": "",
- "pap": "",
- "par": "",
- "parts_tax_rates": {
- "prt_discp": "",
- "prt_mktyp": "",
- "prt_mkupp": "",
- "prt_tax_in": "",
- "prt_tax_rt": "",
- "prt_tx_in1": "",
- "prt_tx_in2": "",
- "prt_tx_in3": "",
- "prt_tx_in4": "",
- "prt_tx_in5": "",
- "prt_tx_ty1": "",
- "prt_type": ""
- },
- "partsstatus": "",
- "pas": "",
- "pay_date": "Date d'Pay",
- "phoneshort": "PH",
- "po_number": "",
- "policy_no": "Politique #",
- "ponumber": "Numéro de bon de commande",
- "production_vars": {
- "note": ""
- },
- "qb_multiple_payers": {
- "amount": "",
- "name": ""
- },
- "queued_for_parts": "",
- "rate_ats": "",
- "rate_la1": "Taux LA1",
- "rate_la2": "Taux LA2",
- "rate_la3": "Taux LA3",
- "rate_la4": "Taux LA4",
- "rate_laa": "Taux d'aluminium",
- "rate_lab": "Taux de la main-d'œuvre",
- "rate_lad": "Taux de diagnostic",
- "rate_lae": "Tarif électrique",
- "rate_laf": "Taux de trame",
- "rate_lag": "Taux de verre",
- "rate_lam": "Taux mécanique",
- "rate_lar": "Taux de finition",
- "rate_las": "",
- "rate_lau": "Taux d'aluminium",
- "rate_ma2s": "Taux de peinture en 2 étapes",
- "rate_ma3s": "Taux de peinture en 3 étapes",
- "rate_mabl": "MABL ??",
- "rate_macs": "MACS ??",
- "rate_mahw": "Taux de déchets dangereux",
- "rate_mapa": "Taux de matériaux de peinture",
- "rate_mash": "Tarif du matériel de la boutique",
- "rate_matd": "Taux d'élimination des pneus",
- "referral_source_extra": "",
- "referral_source_other": "",
- "referralsource": "Source de référence",
- "regie_number": "Enregistrement #",
- "repairtotal": "Réparation totale",
- "ro_number": "RO #",
- "scheduled_completion": "Achèvement planifié",
- "scheduled_delivery": "Livraison programmée",
- "scheduled_in": "Planifié dans",
- "selling_dealer": "Revendeur vendeur",
- "selling_dealer_contact": "Contacter le revendeur",
- "servicecar": "Voiture de service",
- "servicing_dealer": "Concessionnaire",
- "servicing_dealer_contact": "Contacter le concessionnaire",
- "special_coverage_policy": "Politique de couverture spéciale",
- "specialcoveragepolicy": "Politique de couverture spéciale",
- "state_tax_rate": "",
- "status": "Statut de l'emploi",
- "storage_payable": "Stockage",
- "tax_lbr_rt": "",
- "tax_levies_rt": "",
- "tax_paint_mat_rt": "",
- "tax_registration_number": "",
- "tax_shop_mat_rt": "",
- "tax_str_rt": "",
- "tax_sub_rt": "",
- "tax_tow_rt": "",
- "tlos_ind": "",
- "towin": "",
- "towing_payable": "Remorquage à payer",
- "unitnumber": "Unité #",
- "updated_at": "Mis à jour à",
- "uploaded_by": "Telechargé par",
- "vehicle": "Véhicule"
- },
- "forms": {
- "admindates": "",
- "appraiserinfo": "",
- "claiminfo": "",
- "estdates": "",
- "laborrates": "",
- "lossinfo": "",
- "other": "",
- "repairdates": "",
- "scheddates": ""
- },
- "labels": {
- "accountsreceivable": "",
- "act_price_ppc": "",
- "actual_completion_inferred": "",
- "actual_delivery_inferred": "",
- "actual_in_inferred": "",
- "additionalpayeroverallocation": "",
- "additionaltotal": "",
- "adjustmentrate": "",
- "adjustments": "",
- "adminwarning": "",
- "allocations": "",
- "alreadyaddedtoscoreboard": "",
- "alreadyclosed": "",
- "appointmentconfirmation": "Envoyer une confirmation au client?",
- "associationwarning": "",
- "audit": "",
- "available": "",
- "availablejobs": "",
- "ca_bc_pvrt": {
- "days": "",
- "rate": ""
- },
- "ca_gst_all_if_null": "",
- "calc_repair_days": "",
- "calc_repair_days_tt": "",
- "calc_scheuled_completion": "",
- "cards": {
- "customer": "Informations client",
- "damage": "Zone de dommages",
- "dates": "Rendez-vous",
- "documents": "Documents récents",
- "estimator": "Estimateur",
- "filehandler": "Gestionnaire de fichiers",
- "insurance": "Détails de l'assurance",
- "more": "Plus",
- "notes": "Remarques",
- "parts": "les pièces",
- "totals": "Totaux",
- "vehicle": "Véhicule"
- },
- "changeclass": "",
- "checklistcompletedby": "",
- "checklistdocuments": "",
- "checklists": "",
- "cieca_pfl": "",
- "cieca_pfo": "",
- "cieca_pft": "",
- "closeconfirm": "",
- "closejob": "",
- "closingperiod": "",
- "contracts": "",
- "convertedtolabor": "",
- "cost": "",
- "cost_Additional": "",
- "cost_labor": "",
- "cost_parts": "",
- "cost_sublet": "",
- "costs": "",
- "create": {
- "jobinfo": "",
- "newowner": "",
- "newvehicle": "",
- "novehicle": "",
- "ownerinfo": "",
- "vehicleinfo": ""
- },
- "createiouwarning": "",
- "creating_new_job": "Création d'un nouvel emploi ...",
- "deductible": {
- "stands": "",
- "waived": ""
- },
- "deleteconfirm": "",
- "deletedelivery": "",
- "deleteintake": "",
- "deliverchecklist": "",
- "difference": "",
- "diskscan": "",
- "dms": {
- "apexported": "",
- "damageto": "",
- "defaultstory": "",
- "disablebillwip": "",
- "invoicedatefuture": "",
- "kmoutnotgreaterthankmin": "",
- "logs": "",
- "notallocated": "",
- "postingform": "",
- "totalallocated": ""
- },
- "documents": "Les documents",
- "documents-images": "",
- "documents-other": "",
- "duplicateconfirm": "",
- "emailaudit": "",
- "employeeassignments": "",
- "estimatelines": "",
- "estimator": "",
- "existing_jobs": "Emplois existants",
- "federal_tax_amt": "",
- "gpdollars": "",
- "gppercent": "",
- "hrs_claimed": "",
- "hrs_total": "",
- "importnote": "",
- "inproduction": "",
- "intakechecklist": "",
- "iou": "",
- "job": "",
- "jobcosting": "",
- "jobtotals": "",
- "labor_hrs": "",
- "labor_rates_subtotal": "",
- "laborallocations": "",
- "labortotals": "",
- "lines": "Estimer les lignes",
- "local_tax_amt": "",
- "mapa": "",
- "markforreexport": "",
- "mash": "",
- "masterbypass": "",
- "materials": {
- "mapa": ""
- },
- "missingprofileinfo": "",
- "multipayers": "",
- "net_repairs": "",
- "notes": "Remarques",
- "othertotal": "",
- "outstanding_ar": "",
- "outstanding_credit_memos": "",
- "outstanding_ppd": "",
- "outstanding_reconciliation_discrep": "",
- "outstanding_sublets": "",
- "outstandinghours": "",
- "override_header": "Remplacer l'en-tête d'estimation à l'importation?",
- "ownerassociation": "",
- "parts": "les pièces",
- "parts_lines": "",
- "parts_received": "",
- "parts_tax_rates": "",
- "partsfilter": "",
- "partssubletstotal": "",
- "partstotal": "",
- "performance": "",
- "pimraryamountpayable": "",
- "plitooltips": {
- "billtotal": "",
- "calculatedcreditsnotreceived": "",
- "creditmemos": "",
- "creditsnotreceived": "",
- "discrep1": "",
- "discrep2": "",
- "discrep3": "",
- "laboradj": "",
- "partstotal": "",
- "totalreturns": ""
- },
- "ppc": "",
- "ppdnotexported": "",
- "profileadjustments": "",
- "profitbypassrequired": "",
- "profits": "",
- "prt_dsmk_total": "",
- "rates": "Les taux",
- "rates_subtotal": "",
- "reconciliation": {
- "billlinestotal": "",
- "byassoc": "",
- "byprice": "",
- "clear": "",
- "discrepancy": "",
- "joblinestotal": "",
- "multipleactprices": "",
- "multiplebilllines": "",
- "multiplebillsforactprice": "",
- "removedpartsstrikethrough": ""
- },
- "reconciliationheader": "",
- "relatedros": "",
- "remove_from_ar": "",
- "returntotals": "",
- "ro_guard": {
- "enforce_ar": "",
- "enforce_bills": "",
- "enforce_cm": "",
- "enforce_labor": "",
- "enforce_ppd": "",
- "enforce_profit": "",
- "enforce_sublet": "",
- "enforce_validation": "",
- "enforced": ""
- },
- "roguard": "",
- "roguardwarnings": "",
- "rosaletotal": "",
- "sale_additional": "",
- "sale_labor": "",
- "sale_parts": "",
- "sale_sublet": "",
- "sales": "",
- "savebeforeconversion": "",
- "scheduledinchange": "",
- "specialcoveragepolicy": "",
- "state_tax_amt": "",
- "subletsnotcompleted": "",
- "subletstotal": "",
- "subtotal": "",
- "supplementnote": "",
- "suspended": "",
- "suspense": "",
- "tasks": "",
- "threshhold": "",
- "total_cost": "",
- "total_cust_payable": "",
- "total_cust_payable_cash_discount": "",
- "total_repairs": "",
- "total_repairs_cash_discount": "",
- "total_sales": "",
- "total_sales_tax": "",
- "totals": "",
- "unvoidnote": "",
- "update_scheduled_completion": "",
- "vehicle_info": "Véhicule",
- "vehicleassociation": "",
- "viewallocations": "",
- "voidjob": "",
- "voidnote": ""
- },
- "successes": {
- "addedtoproduction": "",
- "all_deleted": "{{count}} travaux supprimés avec succès.",
- "closed": "",
- "converted": "Travail converti avec succès.",
- "created": "Le travail a été créé avec succès. Clique pour voir.",
- "creatednoclick": "",
- "delete": "",
- "deleted": "Le travail a bien été supprimé.",
- "duplicated": "",
- "exported": "",
- "invoiced": "",
- "ioucreated": "",
- "partsqueue": "",
- "save": "Le travail a été enregistré avec succès.",
- "savetitle": "Enregistrement enregistré avec succès.",
- "supplemented": "Travail complété avec succès.",
- "updated": "",
- "voided": ""
- }
- },
- "landing": {
- "bigfeature": {
- "subtitle": "",
- "title": ""
- },
- "footer": {
- "company": {
- "about": "",
- "contact": "",
- "disclaimers": "",
- "name": "",
- "privacypolicy": ""
- },
- "io": {
- "help": "",
- "name": "",
- "status": ""
- },
- "slogan": ""
- },
- "hero": {
- "button": "",
- "title": ""
- },
- "labels": {
- "features": "",
- "managemyshop": "",
- "pricing": ""
- },
- "pricing": {
- "basic": {
- "name": "",
- "sub": ""
- },
- "essentials": {
- "name": "",
- "sub": ""
- },
- "pricingtitle": "",
- "pro": {
- "name": "",
- "sub": ""
- },
- "title": "",
- "unlimited": {
- "name": "",
- "sub": ""
- }
- }
- },
- "menus": {
- "currentuser": {
- "languageselector": "La langue",
- "profile": "Profil"
- },
- "header": {
- "accounting": "",
- "accounting-payables": "",
- "accounting-payments": "",
- "accounting-receivables": "",
- "activejobs": "Emplois actifs",
- "all_tasks": "",
- "alljobs": "",
- "allpayments": "",
- "availablejobs": "Emplois disponibles",
- "bills": "",
- "courtesycars": "",
- "courtesycars-all": "",
- "courtesycars-contracts": "",
- "courtesycars-newcontract": "",
- "create_task": "",
- "customers": "Les clients",
- "dashboard": "",
- "enterbills": "",
- "entercardpayment": "",
- "enterpayment": "",
- "entertimeticket": "",
- "export": "",
- "export-logs": "",
- "help": "",
- "home": "Accueil",
- "inventory": "",
- "jobs": "Emplois",
- "my_tasks": "",
- "newjob": "",
- "owners": "Propriétaires",
- "parts-queue": "",
- "phonebook": "",
- "productionboard": "",
- "productionlist": "",
- "readyjobs": "",
- "recent": "",
- "reportcenter": "",
- "rescueme": "",
- "schedule": "Programme",
- "scoreboard": "",
- "search": {
- "bills": "",
- "jobs": "",
- "owners": "",
- "payments": "",
- "phonebook": "",
- "vehicles": ""
- },
- "shiftclock": "",
- "shop": "Mon magasin",
- "shop_config": "Configuration",
- "shop_csi": "",
- "shop_templates": "",
- "shop_vendors": "Vendeurs",
- "tasks": "",
- "temporarydocs": "",
- "timetickets": "",
- "ttapprovals": "",
- "vehicles": "Véhicules"
- },
- "jobsactions": {
- "admin": "",
- "cancelallappointments": "",
- "closejob": "",
- "deletejob": "",
- "duplicate": "",
- "duplicatenolines": "",
- "newcccontract": "",
- "void": ""
- },
- "jobsdetail": {
- "claimdetail": "Détails de la réclamation",
- "dates": "Rendez-vous",
- "financials": "",
- "general": "",
- "insurance": "",
- "labor": "La main d'oeuvre",
- "lifecycle": "",
- "parts": "",
- "partssublet": "Pièces / Sous-location",
- "rates": "",
- "repairdata": "Données de réparation",
- "totals": ""
- },
- "profilesidebar": {
- "profile": "Mon profil",
- "shops": "Mes boutiques"
- },
- "tech": {
- "assignedjobs": "",
- "claimtask": "",
- "dispatchedparts": "",
- "home": "",
- "jobclockin": "",
- "jobclockout": "",
- "joblookup": "",
- "login": "",
- "logout": "",
- "productionboard": "",
- "productionlist": "",
- "shiftclockin": ""
- }
- },
- "messaging": {
- "actions": {
- "link": "",
- "new": ""
- },
- "errors": {
- "invalidphone": "",
- "noattachedjobs": "",
- "updatinglabel": ""
- },
- "labels": {
- "addlabel": "",
- "archive": "",
- "maxtenimages": "",
- "messaging": "Messagerie",
- "noallowtxt": "",
- "nojobs": "",
- "nopush": "",
- "phonenumber": "",
- "presets": "",
- "recentonly": "",
- "selectmedia": "",
- "sentby": "",
- "typeamessage": "Envoyer un message...",
- "unarchive": ""
- },
- "render": {
- "conversation_list": ""
- }
- },
- "notes": {
- "actions": {
- "actions": "actes",
- "deletenote": "Supprimer la note",
- "edit": "Note éditée",
- "new": "Nouvelle note",
- "savetojobnotes": ""
- },
- "errors": {
- "inserting": ""
- },
- "fields": {
- "createdby": "Créé par",
- "critical": "Critique",
- "private": "privé",
- "text": "Contenu",
- "type": "",
- "types": {
- "customer": "",
- "general": "",
- "office": "",
- "paint": "",
- "parts": "",
- "shop": "",
- "supplement": ""
- },
- "updatedat": "Mis à jour à"
- },
- "labels": {
- "addtorelatedro": "",
- "newnoteplaceholder": "Ajouter une note...",
- "notetoadd": "",
- "systemnotes": "",
- "usernotes": ""
- },
- "successes": {
- "create": "Remarque créée avec succès.",
- "deleted": "Remarque supprimée avec succès.",
- "updated": "Remarque mise à jour avec succès."
- }
- },
- "owner": {
- "labels": {
- "noownerinfo": ""
- }
- },
- "owners": {
- "actions": {
- "update": ""
- },
- "errors": {
- "deleting": "",
- "noaccess": "L'enregistrement n'existe pas ou vous n'y avez pas accès.",
- "saving": "",
- "selectexistingornew": ""
- },
- "fields": {
- "accountingid": "",
- "address": "Adresse",
- "allow_text_message": "Autorisation de texte?",
- "name": "Prénom",
- "note": "",
- "ownr_addr1": "Adresse",
- "ownr_addr2": "Adresse 2 ",
- "ownr_city": "Ville",
- "ownr_co_nm": "",
- "ownr_ctry": "Pays",
- "ownr_ea": "Email",
- "ownr_fn": "Prénom",
- "ownr_ln": "Nom de famille",
- "ownr_ph1": "Téléphone 1",
- "ownr_ph2": "",
- "ownr_st": "Etat / Province",
- "ownr_title": "Titre",
- "ownr_zip": "Zip / code postal",
- "preferred_contact": "Méthode de contact préférée",
- "tax_number": ""
- },
- "forms": {
- "address": "",
- "contact": "",
- "name": ""
- },
- "labels": {
- "create_new": "Créez un nouvel enregistrement de propriétaire.",
- "deleteconfirm": "",
- "existing_owners": "Propriétaires existants",
- "fromclaim": "",
- "fromowner": "",
- "relatedjobs": "",
- "updateowner": ""
- },
- "successes": {
- "delete": "",
- "save": "Le propriétaire a bien enregistré."
- }
- },
- "parts": {
- "actions": {
- "order": "Commander des pièces",
- "orderinhouse": ""
- }
- },
- "parts_dispatch": {
- "actions": {
- "accept": ""
- },
- "errors": {
- "accepting": "",
- "creating": ""
- },
- "fields": {
- "number": "",
- "percent_accepted": ""
- },
- "labels": {
- "notyetdispatched": "",
- "parts_dispatch": ""
- }
- },
- "parts_dispatch_lines": {
- "fields": {
- "accepted_at": ""
- }
- },
- "parts_orders": {
- "actions": {
- "backordered": "",
- "receive": "",
- "receivebill": ""
- },
- "errors": {
- "associatedbills": "",
- "backordering": "",
- "creating": "Erreur rencontrée lors de la création de la commande de pièces.",
- "oec": "",
- "saving": "",
- "updating": ""
- },
- "fields": {
- "act_price": "",
- "backordered_eta": "",
- "backordered_on": "",
- "cm_received": "",
- "comments": "",
- "cost": "",
- "db_price": "",
- "deliver_by": "",
- "job_line_id": "",
- "line_desc": "",
- "line_remarks": "",
- "lineremarks": "Remarques sur la ligne",
- "oem_partno": "",
- "order_date": "",
- "order_number": "",
- "orderedby": "",
- "part_type": "",
- "quantity": "",
- "return": "",
- "status": ""
- },
- "labels": {
- "allpartsto": "",
- "confirmdelete": "",
- "custompercent": "",
- "discount": "",
- "email": "Envoyé par email",
- "inthisorder": "Pièces dans cette commande",
- "is_quote": "",
- "mark_as_received": "",
- "newpartsorder": "",
- "notyetordered": "",
- "oec": "",
- "order_type": "",
- "orderhistory": "Historique des commandes",
- "parts_order": "",
- "parts_orders": "",
- "parts_returns": "",
- "print": "Afficher le formulaire imprimé",
- "receive": "",
- "removefrompartsqueue": "",
- "returnpartsorder": "",
- "sublet_order": ""
- },
- "successes": {
- "created": "Commande de pièces créée avec succès.",
- "line_updated": "",
- "received": "",
- "return_created": ""
- }
- },
- "payments": {
- "actions": {
- "generatepaymentlink": ""
- },
- "errors": {
- "exporting": "",
- "exporting-partner": "",
- "inserting": ""
- },
- "fields": {
- "amount": "",
- "created_at": "",
- "date": "",
- "exportedat": "",
- "memo": "",
- "payer": "",
- "paymentnum": "",
- "stripeid": "",
- "transactionid": "",
- "type": ""
- },
- "labels": {
- "balance": "",
- "ca_bc_etf_table": "",
- "customer": "",
- "edit": "",
- "electronicpayment": "",
- "external": "",
- "findermodal": "",
- "insurance": "",
- "markexported": "",
- "markforreexport": "",
- "new": "",
- "signup": "",
- "smspaymentreminder": "",
- "title": "",
- "totalpayments": ""
- },
- "successes": {
- "exported": "",
- "markexported": "",
- "markreexported": "",
- "payment": "",
- "paymentupdate": "",
- "stripe": ""
- }
- },
- "phonebook": {
- "actions": {
- "new": ""
- },
- "errors": {
- "adding": "",
- "saving": ""
- },
- "fields": {
- "address1": "",
- "address2": "",
- "category": "",
- "city": "",
- "company": "",
- "country": "",
- "email": "",
- "fax": "",
- "firstname": "",
- "lastname": "",
- "phone1": "",
- "phone2": "",
- "state": ""
- },
- "labels": {
- "noneselected": "",
- "onenamerequired": "",
- "vendorcategory": ""
- },
- "successes": {
- "added": "",
- "deleted": "",
- "saved": ""
- }
- },
- "printcenter": {
- "appointments": {
- "appointment_confirmation": ""
- },
- "bills": {
- "inhouse_invoice": ""
- },
- "courtesycarcontract": {
- "courtesy_car_contract": "",
- "courtesy_car_impound": "",
- "courtesy_car_inventory": "",
- "courtesy_car_terms": ""
- },
- "errors": {
- "nocontexttype": ""
- },
- "jobs": {
- "3rdpartyfields": {
- "addr1": "",
- "addr2": "",
- "addr3": "",
- "attn": "",
- "city": "",
- "custgst": "",
- "ded_amt": "",
- "depreciation": "",
- "other": "",
- "ponumber": "",
- "refnumber": "",
- "sendtype": "",
- "state": "",
- "zip": ""
- },
- "3rdpartypayer": "",
- "ab_proof_of_loss": "",
- "appointment_confirmation": "",
- "appointment_reminder": "",
- "casl_authorization": "",
- "committed_timetickets_ro": "",
- "coversheet_landscape": "",
- "coversheet_portrait": "",
- "csi_invitation": "",
- "csi_invitation_action": "",
- "diagnostic_authorization": "",
- "dms_posting_sheet": "",
- "envelope_return_address": "",
- "estimate": "",
- "estimate_detail": "",
- "estimate_followup": "",
- "express_repair_checklist": "",
- "filing_coversheet_landscape": "",
- "filing_coversheet_portrait": "",
- "final_invoice": "",
- "fippa_authorization": "",
- "folder_label_multiple": "",
- "glass_express_checklist": "",
- "guarantee": "",
- "individual_job_note": "",
- "invoice_customer_payable": "",
- "invoice_total_payable": "",
- "iou_form": "",
- "job_costing_ro": "",
- "job_lifecycle_ro": "",
- "job_notes": "",
- "job_tasks": "",
- "key_tag": "",
- "labels": {
- "count": "",
- "labels": "",
- "position": ""
- },
- "lag_time_ro": "",
- "mechanical_authorization": "",
- "mpi_animal_checklist": "",
- "mpi_eglass_auth": "",
- "mpi_final_acct_sheet": "",
- "mpi_final_repair_acct_sheet": "",
- "paint_grid": "",
- "parts_dispatch": "",
- "parts_invoice_label_single": "",
- "parts_label_multiple": "",
- "parts_label_single": "",
- "parts_list": "",
- "parts_order": "",
- "parts_order_confirmation": "",
- "parts_order_history": "",
- "parts_return_slip": "",
- "payment_receipt": "",
- "payment_request": "",
- "payments_by_job": "",
- "purchases_by_ro_detail": "",
- "purchases_by_ro_summary": "",
- "qc_sheet": "",
- "rental_reservation": "",
- "ro_totals": "",
- "ro_with_description": "",
- "sgi_certificate_of_repairs": "",
- "sgi_windshield_auth": "",
- "stolen_recovery_checklist": "",
- "sublet_order": "",
- "supplement_request": "",
- "thank_you_ro": "",
- "thirdpartypayer": "",
- "timetickets_ro": "",
- "vehicle_check_in": "",
- "vehicle_delivery_check": "",
- "window_tag": "",
- "window_tag_sublet": "",
- "work_authorization": "",
- "worksheet_by_line_number": "",
- "worksheet_sorted_by_operation": "",
- "worksheet_sorted_by_operation_no_hours": "",
- "worksheet_sorted_by_operation_part_type": "",
- "worksheet_sorted_by_operation_type": "",
- "worksheet_sorted_by_team": ""
- },
- "labels": {
- "groups": {
- "authorization": "",
- "financial": "",
- "post": "",
- "pre": "",
- "ro": "",
- "worksheet": ""
- },
- "misc": "",
- "repairorder": "",
- "reportcentermodal": "",
- "speedprint": "",
- "title": ""
- },
- "payments": {
- "ca_bc_etf_table": "",
- "exported_payroll": ""
- },
- "special": {
- "attendance_detail_csv": ""
- },
- "subjects": {
- "jobs": {
- "individual_job_note": "",
- "parts_dispatch": "",
- "parts_order": "",
- "parts_return_slip": "",
- "sublet_order": ""
- }
- },
- "vendors": {
- "purchases_by_vendor_detailed": "",
- "purchases_by_vendor_summary": ""
- }
- },
- "production": {
- "actions": {
- "addcolumns": "",
- "bodypriority-clear": "",
- "bodypriority-set": "",
- "detailpriority-clear": "",
- "detailpriority-set": "",
- "paintpriority-clear": "",
- "paintpriority-set": "",
- "remove": "",
- "removecolumn": "",
- "saveconfig": "",
- "suspend": "",
- "unsuspend": ""
- },
- "constants": {
- "main_profile": ""
- },
- "errors": {
- "boardupdate": "",
- "name_exists": "",
- "name_required": "",
- "removing": "",
- "settings": ""
- },
- "labels": {
- "actual_in": "",
- "addnewprofile": "",
- "alert": "",
- "alertoff": "",
- "alerton": "",
- "alerts": "",
- "ats": "",
- "bodyhours": "",
- "bodypriority": "",
- "bodyshop": {
- "labels": {
- "qbo_departmentid": "",
- "qbo_usa": ""
- }
- },
- "card_size": "",
- "cardcolor": "",
- "cardsettings": "",
- "clm_no": "",
- "comment": "",
- "compact": "",
- "detailpriority": "",
- "employeeassignments": "",
- "employeesearch": "",
- "estimator": "",
- "horizontal": "",
- "ins_co_nm": "",
- "jobdetail": "",
- "kiosk_mode": "",
- "laborhrs": "",
- "legend": "",
- "model_info": "",
- "note": "",
- "off": "",
- "on": "",
- "orientation": "",
- "ownr_nm": "",
- "paintpriority": "",
- "partsstatus": "",
- "production_note": "",
- "refinishhours": "",
- "scheduled_completion": "",
- "selectview": "",
- "stickyheader": "",
- "sublets": "",
- "subtotal": "",
- "tall": "",
- "tasks": "",
- "totalhours": "",
- "touchtime": "",
- "unassigned": "",
- "vertical": "",
- "viewname": "",
- "wide": ""
- },
- "options": {
- "horizontal": "",
- "large": "",
- "medium": "",
- "small": "",
- "vertical": ""
- },
- "settings": {
- "board_settings": "",
- "filters": {
- "md_estimators": "",
- "md_ins_cos": ""
- },
- "filters_title": "",
- "information": "",
- "layout": "",
- "statistics": {
- "jobs_in_production": "",
- "tasks_in_production": "",
- "tasks_in_view": "",
- "tasks_on_board": "",
- "total_amount_in_production": "",
- "total_amount_in_view": "",
- "total_amount_on_board": "",
- "total_hours_in_production": "",
- "total_hours_in_view": "",
- "total_hours_on_board": "",
- "total_jobs_in_view": "",
- "total_jobs_on_board": "",
- "total_lab_in_production": "",
- "total_lab_in_view": "",
- "total_lab_on_board": "",
- "total_lar_in_production": "",
- "total_lar_in_view": "",
- "total_lar_on_board": ""
- },
- "statistics_title": ""
- },
- "statistics": {
- "currency_symbol": "",
- "hours": "",
- "jobs": "",
- "jobs_in_production": "",
- "tasks": "",
- "tasks_in_production": "",
- "tasks_in_view": "",
- "tasks_on_board": "",
- "total_amount_in_production": "",
- "total_amount_in_view": "",
- "total_amount_on_board": "",
- "total_hours_in_production": "",
- "total_hours_in_view": "",
- "total_hours_on_board": "",
- "total_jobs_in_view": "",
- "total_jobs_on_board": "",
- "total_lab_in_production": "",
- "total_lab_in_view": "",
- "total_lab_on_board": "",
- "total_lar_in_production": "",
- "total_lar_in_view": "",
- "total_lar_on_board": ""
- },
- "successes": {
- "removed": ""
- }
- },
- "profile": {
- "errors": {
- "state": "Erreur lors de la lecture de l'état de la page. Rafraichissez, s'il vous plait."
- },
- "labels": {
- "activeshop": ""
- },
- "successes": {
- "updated": ""
- }
- },
- "reportcenter": {
- "actions": {
- "generate": ""
- },
- "labels": {
- "advanced_filters": "",
- "advanced_filters_false": "",
- "advanced_filters_filter_field": "",
- "advanced_filters_filter_operator": "",
- "advanced_filters_filter_value": "",
- "advanced_filters_filters": "",
- "advanced_filters_hide": "",
- "advanced_filters_show": "",
- "advanced_filters_sorter_direction": "",
- "advanced_filters_sorter_field": "",
- "advanced_filters_sorters": "",
- "advanced_filters_true": "",
- "dates": "",
- "employee": "",
- "filterson": "",
- "generateasemail": "",
- "groups": {
- "customers": "",
- "jobs": "",
- "payroll": "",
- "purchases": "",
- "sales": ""
- },
- "key": "",
- "objects": {
- "appointments": "",
- "bills": "",
- "csi": "",
- "exportlogs": "",
- "jobs": "",
- "parts_orders": "",
- "payments": "",
- "scoreboard": "",
- "tasks": "",
- "timetickets": ""
- },
- "vendor": ""
- },
- "templates": {
- "adp_payroll_flat": "",
- "adp_payroll_straight": "",
- "anticipated_revenue": "",
- "ar_aging": "",
- "attendance_detail": "",
- "attendance_employee": "",
- "attendance_summary": "",
- "committed_timetickets": "",
- "committed_timetickets_employee": "",
- "committed_timetickets_summary": "",
- "credits_not_received_date": "",
- "credits_not_received_date_vendorid": "",
- "csi": "",
- "customer_list": "",
- "cycle_time_analysis": "",
- "estimates_written_converted": "",
- "estimator_detail": "",
- "estimator_summary": "",
- "export_payables": "",
- "export_payments": "",
- "export_receivables": "",
- "exported_gsr_by_ro": "",
- "exported_gsr_by_ro_labor": "",
- "gsr_by_atp": "",
- "gsr_by_ats": "",
- "gsr_by_category": "",
- "gsr_by_csr": "",
- "gsr_by_delivery_date": "",
- "gsr_by_estimator": "",
- "gsr_by_exported_date": "",
- "gsr_by_ins_co": "",
- "gsr_by_make": "",
- "gsr_by_referral": "",
- "gsr_by_ro": "",
- "gsr_labor_only": "",
- "hours_sold_detail_closed": "",
- "hours_sold_detail_closed_csr": "",
- "hours_sold_detail_closed_estimator": "",
- "hours_sold_detail_closed_ins_co": "",
- "hours_sold_detail_closed_status": "",
- "hours_sold_detail_open": "",
- "hours_sold_detail_open_csr": "",
- "hours_sold_detail_open_estimator": "",
- "hours_sold_detail_open_ins_co": "",
- "hours_sold_detail_open_status": "",
- "hours_sold_summary_closed": "",
- "hours_sold_summary_closed_csr": "",
- "hours_sold_summary_closed_estimator": "",
- "hours_sold_summary_closed_ins_co": "",
- "hours_sold_summary_closed_status": "",
- "hours_sold_summary_open": "",
- "hours_sold_summary_open_csr": "",
- "hours_sold_summary_open_estimator": "",
- "hours_sold_summary_open_ins_co": "",
- "hours_sold_summary_open_status": "",
- "job_costing_ro_csr": "",
- "job_costing_ro_date_detail": "",
- "job_costing_ro_date_summary": "",
- "job_costing_ro_estimator": "",
- "job_costing_ro_ins_co": "",
- "job_lifecycle_date_detail": "",
- "job_lifecycle_date_summary": "",
- "jobs_completed_not_invoiced": "",
- "jobs_invoiced_not_exported": "",
- "jobs_reconcile": "",
- "jobs_scheduled_completion": "",
- "lag_time": "",
- "load_level": "",
- "lost_sales": "",
- "open_orders": "",
- "open_orders_csr": "",
- "open_orders_estimator": "",
- "open_orders_excel": "",
- "open_orders_ins_co": "",
- "open_orders_referral": "",
- "open_orders_specific_csr": "",
- "open_orders_status": "",
- "parts_backorder": "",
- "parts_not_recieved": "",
- "parts_not_recieved_vendor": "",
- "parts_received_not_scheduled": "",
- "payments_by_date": "",
- "payments_by_date_payment": "",
- "payments_by_date_type": "",
- "production_by_category": "",
- "production_by_category_one": "",
- "production_by_csr": "",
- "production_by_last_name": "",
- "production_by_repair_status": "",
- "production_by_repair_status_one": "",
- "production_by_ro": "",
- "production_by_target_date": "",
- "production_by_technician": "",
- "production_by_technician_one": "",
- "production_not_production_status": "",
- "production_over_time": "",
- "psr_by_make": "",
- "purchase_return_ratio_excel": "",
- "purchase_return_ratio_grouped_by_vendor_detail": "",
- "purchase_return_ratio_grouped_by_vendor_summary": "",
- "purchases_by_cost_center_detail": "",
- "purchases_by_cost_center_summary": "",
- "purchases_by_date_excel": "",
- "purchases_by_date_range_detail": "",
- "purchases_by_date_range_summary": "",
- "purchases_by_ro_detail_date": "",
- "purchases_by_ro_summary_date": "",
- "purchases_by_vendor_detailed_date_range": "",
- "purchases_by_vendor_summary_date_range": "",
- "purchases_grouped_by_vendor_detailed": "",
- "purchases_grouped_by_vendor_summary": "",
- "returns_grouped_by_vendor_detailed": "",
- "returns_grouped_by_vendor_summary": "",
- "schedule": "",
- "scheduled_parts_list": "",
- "scoreboard_detail": "",
- "scoreboard_summary": "",
- "supplement_ratio_ins_co": "",
- "tasks_date": "",
- "tasks_date_employee": "",
- "thank_you_date": "",
- "timetickets": "",
- "timetickets_employee": "",
- "timetickets_summary": "",
- "total_loss_jobs": "",
- "unclaimed_hrs": "",
- "void_ros": "",
- "work_in_progress_committed_labour": "",
- "work_in_progress_jobs": "",
- "work_in_progress_labour": "",
- "work_in_progress_payables": ""
- }
- },
- "schedule": {
- "labels": {
- "atssummary": "",
- "employeevacation": "",
- "estimators": "",
- "ins_co_nm_filter": "",
- "intake": "",
- "manual": "",
- "manualevent": ""
- }
- },
- "scoreboard": {
- "actions": {
- "edit": ""
- },
- "errors": {
- "adding": "",
- "removing": "",
- "updating": ""
- },
- "fields": {
- "bodyhrs": "",
- "date": "",
- "painthrs": ""
- },
- "labels": {
- "allemployeetimetickets": "",
- "asoftodaytarget": "",
- "body": "",
- "bodyabbrev": "",
- "bodycharttitle": "",
- "calendarperiod": "",
- "combinedcharttitle": "",
- "dailyactual": "",
- "dailytarget": "",
- "efficiencyoverperiod": "",
- "entries": "",
- "jobs": "",
- "jobscompletednotinvoiced": "",
- "lastmonth": "",
- "lastweek": "",
- "monthlytarget": "",
- "priorweek": "",
- "productivestatistics": "",
- "productivetimeticketsoverdate": "",
- "refinish": "",
- "refinishabbrev": "",
- "refinishcharttitle": "",
- "targets": "",
- "thismonth": "",
- "thisweek": "",
- "timetickets": "",
- "timeticketsemployee": "",
- "todateactual": "",
- "total": "",
- "totalhrs": "",
- "totaloverperiod": "",
- "weeklyactual": "",
- "weeklytarget": "",
- "workingdays": ""
- },
- "successes": {
- "added": "",
- "removed": "",
- "updated": ""
- }
- },
- "tasks": {
- "actions": {
- "edit": "",
- "new": "",
- "view": ""
- },
- "buttons": {
- "allTasks": "",
- "complete": "",
- "create": "",
- "delete": "",
- "edit": "",
- "myTasks": "",
- "refresh": ""
- },
- "date_presets": {
- "completion": "",
- "day": "",
- "days": "",
- "delivery": "",
- "next_week": "",
- "one_month": "",
- "three_months": "",
- "three_weeks": "",
- "today": "",
- "tomorrow": "",
- "two_weeks": ""
- },
- "failures": {
- "completed": "",
- "created": "",
- "deleted": "",
- "updated": ""
- },
- "fields": {
- "actions": "",
- "assigned_to": "",
- "bill": "",
- "billid": "",
- "completed": "",
- "created_at": "",
- "created_by": "",
- "description": "",
- "due_date": "",
- "job": {
- "ro_number": ""
- },
- "jobid": "",
- "jobline": "",
- "joblineid": "",
- "parts_order": "",
- "partsorderid": "",
- "priorities": {
- "high": "",
- "low": "",
- "medium": ""
- },
- "priority": "",
- "related_items": "",
- "remind_at": "",
- "title": ""
- },
- "placeholders": {
- "assigned_to": "",
- "billid": "",
- "description": "",
- "jobid": "",
- "joblineid": "",
- "partsorderid": ""
- },
- "successes": {
- "completed": "",
- "created": "",
- "deleted": "",
- "updated": ""
- },
- "titles": {
- "all_tasks": "",
- "completed": "",
- "deleted": "",
- "job_tasks": "",
- "mine": "",
- "my_tasks": ""
- },
- "validation": {
- "due_at_error_message": "",
- "remind_at_error_message": ""
- }
- },
- "tech": {
- "fields": {
- "employeeid": "",
- "pin": ""
- },
- "labels": {
- "loggedin": "",
- "notloggedin": ""
- }
- },
- "templates": {
- "errors": {
- "updating": ""
- },
- "successes": {
- "updated": ""
- }
- },
- "timetickets": {
- "actions": {
- "claimtasks": "",
- "clockin": "",
- "clockout": "",
- "commit": "",
- "commitone": "",
- "enter": "",
- "payall": "",
- "printemployee": "",
- "uncommit": ""
- },
- "errors": {
- "clockingin": "",
- "clockingout": "",
- "creating": "",
- "deleting": "",
- "noemployeeforuser": "",
- "noemployeeforuser_sub": "",
- "payall": "",
- "shiftalreadyclockedon": ""
- },
- "fields": {
- "actualhrs": "",
- "ciecacode": "",
- "clockhours": "",
- "clockoff": "",
- "clockon": "",
- "committed": "",
- "committed_at": "",
- "cost_center": "",
- "created_by": "",
- "date": "",
- "efficiency": "",
- "employee": "",
- "employee_team": "",
- "flat_rate": "",
- "memo": "",
- "productivehrs": "",
- "ro_number": "",
- "task_name": ""
- },
- "labels": {
- "alreadyclockedon": "",
- "ambreak": "",
- "amshift": "",
- "claimtaskpreview": "",
- "clockhours": "",
- "clockintojob": "",
- "deleteconfirm": "",
- "edit": "",
- "efficiency": "",
- "flat_rate": "",
- "jobhours": "",
- "lunch": "",
- "new": "",
- "payrollclaimedtasks": "",
- "pmbreak": "",
- "pmshift": "",
- "shift": "",
- "shiftalreadyclockedon": "",
- "straight_time": "",
- "task": "",
- "timetickets": "",
- "unassigned": "",
- "zeroactualnegativeprod": ""
- },
- "successes": {
- "clockedin": "",
- "clockedout": "",
- "committed": "",
- "created": "",
- "deleted": "",
- "payall": ""
- },
- "validation": {
- "clockoffmustbeafterclockon": "",
- "clockoffwithoutclockon": "",
- "hoursenteredmorethanavailable": "",
- "unassignedlines": ""
- }
- },
- "titles": {
- "accounting-payables": "",
- "accounting-payments": "",
- "accounting-receivables": "",
- "all_tasks": "",
- "app": "",
- "bc": {
- "accounting-payables": "",
- "accounting-payments": "",
- "accounting-receivables": "",
- "all_tasks": "",
- "availablejobs": "",
- "bills-list": "",
- "contracts": "",
- "contracts-create": "",
- "contracts-detail": "",
- "courtesycars": "",
- "courtesycars-detail": "",
- "courtesycars-new": "",
- "dashboard": "",
- "dms": "",
- "export-logs": "",
- "inventory": "",
- "jobs": "",
- "jobs-active": "",
- "jobs-admin": "",
- "jobs-all": "",
- "jobs-checklist": "",
- "jobs-close": "",
- "jobs-deliver": "",
- "jobs-detail": "",
- "jobs-intake": "",
- "jobs-new": "",
- "jobs-ready": "",
- "my_tasks": "",
- "owner-detail": "",
- "owners": "",
- "parts-queue": "",
- "payments-all": "",
- "phonebook": "",
- "productionboard": "",
- "productionlist": "",
- "profile": "",
- "schedule": "",
- "scoreboard": "",
- "shop": "",
- "shop-csi": "",
- "shop-templates": "",
- "shop-vendors": "",
- "tasks": "",
- "temporarydocs": "",
- "timetickets": "",
- "ttapprovals": "",
- "vehicle-details": "",
- "vehicles": ""
- },
- "bills-list": "",
- "contracts": "",
- "contracts-create": "",
- "contracts-detail": "",
- "courtesycars": "",
- "courtesycars-create": "",
- "courtesycars-detail": "",
- "dashboard": "",
- "dms": "",
- "export-logs": "",
- "imexonline": "",
- "inventory": "",
- "jobs": "Tous les emplois | {{app}}",
- "jobs-admin": "",
- "jobs-all": "",
- "jobs-checklist": "",
- "jobs-close": "",
- "jobs-create": "",
- "jobs-deliver": "",
- "jobs-intake": "",
- "jobsavailable": "Emplois disponibles | {{app}}",
- "jobsdetail": "Travail {{ro_number}} | {{app}}",
- "jobsdocuments": "Documents de travail {{ro_number}} | {{app}}",
- "manageroot": "Accueil | {{app}}",
- "my_tasks": "",
- "owners": "Tous les propriétaires | {{app}}",
- "owners-detail": "",
- "parts-queue": "",
- "payments-all": "",
- "phonebook": "",
- "productionboard": "",
- "productionlist": "",
- "profile": "Mon profil | {{app}}",
- "readyjobs": "",
- "resetpassword": "",
- "resetpasswordvalidate": "",
- "romeonline": "",
- "schedule": "Horaire | {{app}}",
- "scoreboard": "",
- "shop": "Mon magasin | {{app}}",
- "shop-csi": "",
- "shop-templates": "",
- "shop_vendors": "Vendeurs | {{app}}",
- "tasks": "",
- "techconsole": "{{app}}",
- "techjobclock": "{{app}}",
- "techjoblookup": "{{app}}",
- "techshiftclock": "{{app}}",
- "temporarydocs": "",
- "timetickets": "",
- "ttapprovals": "",
- "vehicledetail": "Détails du véhicule {{vehicle} | {{app}}",
- "vehicles": "Tous les véhicules | {{app}}"
- },
- "trello": {
- "labels": {
- "add_card": "",
- "add_lane": "",
- "cancel": "",
- "delete_lane": "",
- "description": "",
- "label": "",
- "lane_actions": "",
- "title": ""
- }
- },
- "tt_approvals": {
- "actions": {
- "approveselected": ""
- },
- "labels": {
- "approval_queue_in_use": "",
- "calculate": ""
- }
- },
- "upsell": {
- "cta": {
- "learnmore": ""
- },
- "messages": {
- "accounting": {
- "payables": {
- "subtitle": "",
- "title": ""
- },
- "payments": {
- "subtitle": "",
- "title": ""
- },
- "receivables": {
- "subtitle": "",
- "title": ""
- }
- },
- "audit": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "bills": {
- "autoreconcile": {
- "subtitle": "",
- "title": ""
- },
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "checklist": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "courtesycars": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "csi": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "dashboard": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "lifecycle": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "media": {
- "general": {
- "subtitle": "",
- "title": ""
- },
- "mobile": {
- "subtitle": "",
- "title": ""
- }
- },
- "payments": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "scoreboard": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "smartscheduling": {
- "datepicker": {
- "subtitle": "",
- "title": ""
- },
- "general": {
- "subtitle": "",
- "title": ""
- },
- "hrsdelta": {
- "subtitle": "",
- "title": ""
- }
- },
- "techconsole": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "timetickets": {
- "allocations": {
- "subtitle": "",
- "title": ""
- },
- "general": {
- "subtitle": "",
- "title": ""
- }
- },
- "visualboard": {
- "general": {
- "subtitle": "",
- "title": ""
- }
- }
- }
- },
- "user": {
- "actions": {
- "changepassword": "",
- "signout": "Déconnexion",
- "updateprofile": "Mettre à jour le profil"
- },
- "errors": {
- "updating": ""
- },
- "fields": {
- "authlevel": "",
- "displayname": "Afficher un nom",
- "email": "",
- "photourl": "URL de l'avatar"
- },
- "labels": {
- "actions": "",
- "changepassword": "",
- "profileinfo": ""
- },
- "successess": {
- "passwordchanged": ""
- }
- },
- "users": {
- "errors": {
- "signinerror": {
- "auth/user-disabled": "",
- "auth/user-not-found": "",
- "auth/wrong-password": ""
- }
- }
- },
- "vehicles": {
- "errors": {
- "deleting": "",
- "noaccess": "Le véhicule n'existe pas ou vous n'y avez pas accès.",
- "selectexistingornew": "",
- "validation": "Veuillez vous assurer que tous les champs sont correctement entrés.",
- "validationtitle": "Erreur de validation"
- },
- "fields": {
- "description": "Description du véhicule",
- "notes": "",
- "plate_no": "Plaque d'immatriculation",
- "plate_st": "Juridiction de la plaque",
- "trim_color": "Couleur de garniture",
- "v_bstyle": "Style corporel",
- "v_color": "Couleur",
- "v_cond": "Etat",
- "v_engine": "moteur",
- "v_make_desc": "Faire",
- "v_makecode": "Faire du code",
- "v_mldgcode": "Code de moulage",
- "v_model_desc": "Modèle",
- "v_model_yr": "année",
- "v_options": "Les options",
- "v_paint_codes": "Codes de peinture",
- "v_prod_dt": "Date de production",
- "v_stage": "Étape",
- "v_tone": "ton",
- "v_trimcode": "Code de coupe",
- "v_type": "Type",
- "v_vin": "V.I.N."
- },
- "forms": {
- "detail": "",
- "misc": "",
- "registration": ""
- },
- "labels": {
- "deleteconfirm": "",
- "fromvehicle": "",
- "novehinfo": "",
- "relatedjobs": "",
- "updatevehicle": ""
- },
- "successes": {
- "delete": "",
- "save": "Le véhicule a été enregistré avec succès."
- }
- },
- "vendors": {
- "actions": {
- "addtophonebook": "",
- "new": "Nouveau vendeur",
- "newpreferredmake": ""
- },
- "errors": {
- "deleting": "Erreur rencontrée lors de la suppression du fournisseur.",
- "saving": "Erreur rencontrée lors de l'enregistrement du fournisseur."
- },
- "fields": {
- "active": "",
- "am": "",
- "city": "Ville",
- "cost_center": "Centre de coûts",
- "country": "Pays",
- "discount": "Remise %",
- "display_name": "Afficher un nom",
- "dmsid": "",
- "due_date": "Date limite de paiement",
- "email": "Email du contact",
- "favorite": "Préféré?",
- "lkq": "",
- "make": "",
- "name": "Nom du vendeur",
- "oem": "",
- "phone": "",
- "prompt_discount": "Remise rapide%",
- "state": "Etat / Province",
- "street1": "rue",
- "street2": "Adresse 2 ",
- "taxid": "Identifiant de taxe",
- "terms": "Modalités de paiement",
- "zip": "Zip / code postal"
- },
- "labels": {
- "noneselected": "Aucun fournisseur n'est sélectionné.",
- "preferredmakes": "",
- "search": "Tapez le nom d'un vendeur"
- },
- "successes": {
- "deleted": "Le fournisseur a bien été supprimé.",
- "saved": "Le fournisseur a bien enregistré."
- },
- "validation": {
- "unique_vendor_name": ""
- }
- }
- }
+ "translation": {
+ "allocations": {
+ "actions": {
+ "assign": "Attribuer"
+ },
+ "errors": {
+ "deleting": "",
+ "saving": "",
+ "validation": ""
+ },
+ "fields": {
+ "employee": "Alloué à"
+ },
+ "successes": {
+ "deleted": "",
+ "save": ""
+ }
+ },
+ "appointments": {
+ "actions": {
+ "block": "",
+ "calculate": "",
+ "cancel": "annuler",
+ "intake": "Admission",
+ "new": "Nouveau rendez-vous",
+ "preview": "",
+ "reschedule": "Replanifier",
+ "sendreminder": "",
+ "unblock": "",
+ "viewjob": "Voir le travail"
+ },
+ "errors": {
+ "blocking": "",
+ "canceling": "Erreur lors de l'annulation du rendez-vous. {{message}}",
+ "saving": "Erreur lors de la planification du rendez-vous. {{message}}"
+ },
+ "fields": {
+ "alt_transport": "",
+ "color": "",
+ "end": "",
+ "note": "",
+ "start": "",
+ "time": "",
+ "title": "Titre"
+ },
+ "labels": {
+ "arrivedon": "Arrivé le:",
+ "arrivingjobs": "",
+ "blocked": "",
+ "cancelledappointment": "Rendez-vous annulé pour:",
+ "completingjobs": "",
+ "dataconsistency": "",
+ "expectedjobs": "",
+ "expectedprodhrs": "",
+ "history": "",
+ "inproduction": "",
+ "manualevent": "",
+ "noarrivingjobs": "",
+ "nocompletingjobs": "",
+ "nodateselected": "Aucune date n'a été sélectionnée.",
+ "priorappointments": "Rendez-vous précédents",
+ "reminder": "",
+ "scheduledfor": "Rendez-vous prévu pour:",
+ "severalerrorsfound": "",
+ "smartscheduling": "",
+ "smspaymentreminder": "",
+ "suggesteddates": ""
+ },
+ "successes": {
+ "canceled": "Rendez-vous annulé avec succès.",
+ "created": "Rendez-vous planifié avec succès.",
+ "saved": ""
+ }
+ },
+ "associations": {
+ "actions": {
+ "activate": "Activer"
+ },
+ "fields": {
+ "active": "Actif?",
+ "shopname": "nom de la boutique"
+ },
+ "labels": {
+ "actions": "actes"
+ }
+ },
+ "audit": {
+ "fields": {
+ "cc": "",
+ "contents": "",
+ "created": "",
+ "operation": "",
+ "status": "",
+ "subject": "",
+ "to": "",
+ "useremail": "",
+ "values": ""
+ }
+ },
+ "audit_trail": {
+ "messages": {
+ "admin_job_remove_from_ar": "",
+ "admin_jobmarkexported": "",
+ "admin_jobmarkforreexport": "",
+ "admin_jobuninvoice": "",
+ "admin_jobunvoid": "",
+ "alerttoggle": "",
+ "appointmentcancel": "",
+ "appointmentinsert": "",
+ "assignedlinehours": "",
+ "billdeleted": "",
+ "billposted": "",
+ "billupdated": "",
+ "failedpayment": "",
+ "jobassignmentchange": "",
+ "jobassignmentremoved": "",
+ "jobchecklist": "",
+ "jobclosedwithbypass": "",
+ "jobconverted": "",
+ "jobdelivery": "",
+ "jobexported": "",
+ "jobfieldchanged": "",
+ "jobimported": "",
+ "jobinproductionchange": "",
+ "jobintake": "",
+ "jobinvoiced": "",
+ "jobioucreated": "",
+ "jobmodifylbradj": "",
+ "jobnoteadded": "",
+ "jobnotedeleted": "",
+ "jobnoteupdated": "",
+ "jobspartsorder": "",
+ "jobspartsreturn": "",
+ "jobstatuschange": "",
+ "jobsupplement": "",
+ "jobsuspend": "",
+ "jobvoid": "",
+ "tasks_completed": "",
+ "tasks_created": "",
+ "tasks_deleted": "",
+ "tasks_uncompleted": "",
+ "tasks_undeleted": "",
+ "tasks_updated": ""
+ }
+ },
+ "billlines": {
+ "actions": {
+ "newline": ""
+ },
+ "fields": {
+ "actual_cost": "",
+ "actual_price": "",
+ "cost_center": "",
+ "federal_tax_applicable": "",
+ "jobline": "",
+ "line_desc": "",
+ "local_tax_applicable": "",
+ "location": "",
+ "quantity": "",
+ "state_tax_applicable": ""
+ },
+ "labels": {
+ "deductedfromlbr": "",
+ "entered": "",
+ "from": "",
+ "mod_lbr_adjustment": "",
+ "other": "",
+ "reconciled": "",
+ "unreconciled": ""
+ },
+ "validation": {
+ "atleastone": ""
+ }
+ },
+ "bills": {
+ "actions": {
+ "deductallhours": "",
+ "edit": "",
+ "receive": "",
+ "return": ""
+ },
+ "errors": {
+ "creating": "",
+ "deleting": "",
+ "existinginventoryline": "",
+ "exporting": "",
+ "exporting-partner": "",
+ "invalidro": "",
+ "invalidvendor": "",
+ "validation": ""
+ },
+ "fields": {
+ "allpartslocation": "",
+ "date": "",
+ "exported": "",
+ "federal_tax_rate": "",
+ "invoice_number": "",
+ "is_credit_memo": "",
+ "is_credit_memo_short": "",
+ "local_tax_rate": "",
+ "ro_number": "",
+ "state_tax_rate": "",
+ "total": "",
+ "vendor": "",
+ "vendorname": ""
+ },
+ "labels": {
+ "actions": "",
+ "bill_lines": "",
+ "bill_total": "",
+ "billcmtotal": "",
+ "bills": "",
+ "calculatedcreditsnotreceived": "",
+ "creditsnotreceived": "",
+ "creditsreceived": "",
+ "dedfromlbr": "",
+ "deleteconfirm": "",
+ "discrepancy": "",
+ "discrepwithcms": "",
+ "discrepwithlbradj": "",
+ "editadjwarning": "",
+ "entered_total": "",
+ "enteringcreditmemo": "",
+ "federal_tax": "",
+ "federal_tax_exempt": "",
+ "generatepartslabel": "",
+ "iouexists": "",
+ "local_tax": "",
+ "markexported": "",
+ "markforreexport": "",
+ "new": "",
+ "nobilllines": "",
+ "noneselected": "",
+ "onlycmforinvoiced": "",
+ "printlabels": "",
+ "retailtotal": "",
+ "returnfrombill": "",
+ "savewithdiscrepancy": "",
+ "state_tax": "",
+ "subtotal": "",
+ "totalreturns": ""
+ },
+ "successes": {
+ "created": "",
+ "deleted": "",
+ "exported": "",
+ "markexported": "",
+ "reexport": ""
+ },
+ "validation": {
+ "closingperiod": "",
+ "inventoryquantity": "",
+ "manualinhouse": "",
+ "unique_invoice_number": ""
+ }
+ },
+ "bodyshop": {
+ "actions": {
+ "add_task_preset": "",
+ "addapptcolor": "",
+ "addbucket": "",
+ "addpartslocation": "",
+ "addpartsrule": "",
+ "addspeedprint": "",
+ "addtemplate": "",
+ "newlaborrate": "",
+ "newsalestaxcode": "",
+ "newstatus": "",
+ "testrender": ""
+ },
+ "errors": {
+ "creatingdefaultview": "",
+ "loading": "Impossible de charger les détails de la boutique. Veuillez appeler le support technique.",
+ "saving": ""
+ },
+ "fields": {
+ "ReceivableCustomField": "",
+ "address1": "",
+ "address2": "",
+ "appt_alt_transport": "",
+ "appt_colors": {
+ "color": "",
+ "label": ""
+ },
+ "appt_length": "",
+ "attach_pdf_to_email": "",
+ "batchid": "",
+ "bill_allow_post_to_closed": "",
+ "bill_federal_tax_rate": "",
+ "bill_local_tax_rate": "",
+ "bill_state_tax_rate": "",
+ "city": "",
+ "closingperiod": "",
+ "companycode": "",
+ "country": "",
+ "dailybodytarget": "",
+ "dailypainttarget": "",
+ "default_adjustment_rate": "",
+ "deliver": {
+ "require_actual_delivery_date": "",
+ "templates": ""
+ },
+ "dms": {
+ "apcontrol": "",
+ "appostingaccount": "",
+ "cashierid": "",
+ "default_journal": "",
+ "disablebillwip": "",
+ "disablecontactvehiclecreation": "",
+ "dms_acctnumber": "",
+ "dms_control_override": "",
+ "dms_wip_acctnumber": "",
+ "generic_customer_number": "",
+ "itc_federal": "",
+ "itc_local": "",
+ "itc_state": "",
+ "mappingname": "",
+ "sendmaterialscosting": "",
+ "srcco": ""
+ },
+ "email": "",
+ "enforce_class": "",
+ "enforce_conversion_category": "",
+ "enforce_conversion_csr": "",
+ "enforce_referral": "",
+ "federal_tax_id": "",
+ "ignoreblockeddays": "",
+ "inhousevendorid": "",
+ "insurance_vendor_id": "",
+ "intake": {
+ "next_contact_hours": "",
+ "templates": ""
+ },
+ "intellipay_config": {
+ "cash_discount_percentage": "",
+ "enable_cash_discount": "",
+ "payment_type": "",
+ "payment_map": {
+ "amex": "American Express",
+ "disc": "Discover",
+ "dnrs": "Diners",
+ "intr": "Interac",
+ "jcb": "JCB",
+ "mast": "MasterCard",
+ "visa": "Visa"
+ }
+ },
+ "invoice_federal_tax_rate": "",
+ "invoice_local_tax_rate": "",
+ "invoice_state_tax_rate": "",
+ "jc_hourly_rates": {
+ "mapa": "",
+ "mash": ""
+ },
+ "last_name_first": "",
+ "lastnumberworkingdays": "",
+ "localmediaserverhttp": "",
+ "localmediaservernetwork": "",
+ "localmediatoken": "",
+ "logo_img_footer_margin": "",
+ "logo_img_header_margin": "",
+ "logo_img_path": "",
+ "logo_img_path_height": "",
+ "logo_img_path_width": "",
+ "md_categories": "",
+ "md_ccc_rates": "",
+ "md_classes": "",
+ "md_ded_notes": "",
+ "md_email_cc": "",
+ "md_from_emails": "",
+ "md_functionality_toggles": {
+ "parts_queue_toggle": ""
+ },
+ "md_hour_split": {
+ "paint": "",
+ "prep": ""
+ },
+ "md_ins_co": {
+ "city": "",
+ "name": "",
+ "private": "",
+ "state": "",
+ "street1": "",
+ "street2": "",
+ "zip": ""
+ },
+ "md_jobline_presets": "",
+ "md_lost_sale_reasons": "",
+ "md_parts_order_comment": "",
+ "md_parts_scan": {
+ "caseInsensitive": "",
+ "expression": "",
+ "field": "",
+ "flags": "",
+ "mark_critical": "",
+ "operation": "",
+ "update_field": "",
+ "update_value": "",
+ "value": ""
+ },
+ "md_payment_types": "",
+ "md_referral_sources": "",
+ "md_ro_guard": {
+ "enabled": "",
+ "enforce_ar": "",
+ "enforce_bills": "",
+ "enforce_cm": "",
+ "enforce_labor": "",
+ "enforce_ppd": "",
+ "enforce_profit": "",
+ "enforce_sublet": "",
+ "masterbypass": "",
+ "totalgppercent_minimum": ""
+ },
+ "md_tasks_presets": {
+ "enable_tasks": "",
+ "hourstype": "",
+ "memo": "",
+ "name": "",
+ "nextstatus": "",
+ "percent": "",
+ "use_approvals": ""
+ },
+ "messaginglabel": "",
+ "messagingtext": "",
+ "noteslabel": "",
+ "notestext": "",
+ "partslocation": "",
+ "phone": "",
+ "prodtargethrs": "",
+ "rbac": {
+ "accounting": {
+ "exportlog": "",
+ "payables": "",
+ "payments": "",
+ "receivables": ""
+ },
+ "bills": {
+ "delete": "",
+ "enter": "",
+ "list": "",
+ "reexport": "",
+ "view": ""
+ },
+ "contracts": {
+ "create": "",
+ "detail": "",
+ "list": ""
+ },
+ "courtesycar": {
+ "create": "",
+ "detail": "",
+ "list": ""
+ },
+ "csi": {
+ "export": "",
+ "page": ""
+ },
+ "employee_teams": {
+ "page": ""
+ },
+ "employees": {
+ "page": ""
+ },
+ "inventory": {
+ "delete": "",
+ "list": ""
+ },
+ "jobs": {
+ "admin": "",
+ "available-list": "",
+ "checklist-view": "",
+ "close": "",
+ "create": "",
+ "deliver": "",
+ "detail": "",
+ "intake": "",
+ "list-active": "",
+ "list-all": "",
+ "list-ready": "",
+ "partsqueue": "",
+ "void": ""
+ },
+ "owners": {
+ "detail": "",
+ "list": ""
+ },
+ "payments": {
+ "enter": "",
+ "list": ""
+ },
+ "phonebook": {
+ "edit": "",
+ "view": ""
+ },
+ "production": {
+ "board": "",
+ "list": ""
+ },
+ "schedule": {
+ "view": ""
+ },
+ "scoreboard": {
+ "view": ""
+ },
+ "shiftclock": {
+ "view": ""
+ },
+ "shop": {
+ "config": "",
+ "dashboard": "",
+ "rbac": "",
+ "reportcenter": "",
+ "templates": "",
+ "vendors": ""
+ },
+ "temporarydocs": {
+ "view": ""
+ },
+ "timetickets": {
+ "edit": "",
+ "editcommitted": "",
+ "enter": "",
+ "list": "",
+ "shiftedit": ""
+ },
+ "ttapprovals": {
+ "approve": "",
+ "view": ""
+ },
+ "users": {
+ "editaccess": ""
+ }
+ },
+ "responsibilitycenter": "",
+ "responsibilitycenter_accountdesc": "",
+ "responsibilitycenter_accountitem": "",
+ "responsibilitycenter_accountname": "",
+ "responsibilitycenter_accountnumber": "",
+ "responsibilitycenter_rate": "",
+ "responsibilitycenter_tax_rate": "",
+ "responsibilitycenter_tax_sur": "",
+ "responsibilitycenter_tax_thres": "",
+ "responsibilitycenter_tax_tier": "",
+ "responsibilitycenter_tax_type": "",
+ "responsibilitycenters": {
+ "ap": "",
+ "ar": "",
+ "ats": "",
+ "federal_tax": "",
+ "federal_tax_itc": "",
+ "gst_override": "",
+ "invoiceexemptcode": "",
+ "itemexemptcode": "",
+ "la1": "",
+ "la2": "",
+ "la3": "",
+ "la4": "",
+ "laa": "",
+ "lab": "",
+ "lad": "",
+ "lae": "",
+ "laf": "",
+ "lag": "",
+ "lam": "",
+ "lar": "",
+ "las": "",
+ "lau": "",
+ "local_tax": "",
+ "mapa": "",
+ "mash": "",
+ "paa": "",
+ "pac": "",
+ "pag": "",
+ "pal": "",
+ "pam": "",
+ "pan": "",
+ "pao": "",
+ "pap": "",
+ "par": "",
+ "pas": "",
+ "pasl": "",
+ "refund": "",
+ "sales_tax_codes": {
+ "code": "",
+ "description": "",
+ "federal": "",
+ "local": "",
+ "state": ""
+ },
+ "state_tax": "",
+ "tow": ""
+ },
+ "schedule_end_time": "",
+ "schedule_start_time": "",
+ "shopname": "",
+ "speedprint": {
+ "id": "",
+ "label": "",
+ "templates": ""
+ },
+ "ss_configuration": {
+ "dailyhrslimit": ""
+ },
+ "ssbuckets": {
+ "color": "",
+ "gte": "",
+ "id": "",
+ "label": "",
+ "lt": "",
+ "target": ""
+ },
+ "state": "",
+ "state_tax_id": "",
+ "status": "",
+ "statuses": {
+ "active_statuses": "",
+ "additional_board_statuses": "",
+ "color": "",
+ "default_arrived": "",
+ "default_bo": "",
+ "default_canceled": "",
+ "default_completed": "",
+ "default_delivered": "",
+ "default_exported": "",
+ "default_imported": "",
+ "default_invoiced": "",
+ "default_ordered": "",
+ "default_quote": "",
+ "default_received": "",
+ "default_returned": "",
+ "default_scheduled": "",
+ "default_void": "",
+ "open_statuses": "",
+ "post_production_statuses": "",
+ "pre_production_statuses": "",
+ "production_colors": "",
+ "production_statuses": "",
+ "ready_statuses": ""
+ },
+ "target_touchtime": "",
+ "timezone": "",
+ "tt_allow_post_to_invoiced": "",
+ "tt_enforce_hours_for_tech_console": "",
+ "use_fippa": "",
+ "use_paint_scale_data": "",
+ "uselocalmediaserver": "",
+ "website": "",
+ "zip_post": ""
+ },
+ "labels": {
+ "2tiername": "",
+ "2tiersetup": "",
+ "2tiersource": "",
+ "accountingsetup": "",
+ "accountingtiers": "",
+ "alljobstatuses": "",
+ "allopenjobstatuses": "",
+ "apptcolors": "",
+ "businessinformation": "",
+ "checklists": "",
+ "csiq": "",
+ "customtemplates": "",
+ "defaultcostsmapping": "",
+ "defaultprofitsmapping": "",
+ "deliverchecklist": "",
+ "dms": {
+ "cdk": {
+ "controllist": "",
+ "payers": ""
+ },
+ "cdk_dealerid": "",
+ "costsmapping": "",
+ "dms_allocations": "",
+ "pbs_serialnumber": "",
+ "profitsmapping": "",
+ "title": ""
+ },
+ "emaillater": "",
+ "employee_teams": "",
+ "employees": "",
+ "estimators": "",
+ "filehandlers": "",
+ "imexpay": "",
+ "insurancecos": "",
+ "intakechecklist": "",
+ "intellipay_cash_discount": "",
+ "jobstatuses": "",
+ "laborrates": "",
+ "licensing": "",
+ "md_parts_scan": "",
+ "md_ro_guard": "",
+ "md_tasks_presets": "",
+ "md_to_emails": "",
+ "md_to_emails_emails": "",
+ "messagingpresets": "",
+ "notemplatesavailable": "",
+ "notespresets": "",
+ "orderstatuses": "",
+ "partslocations": "",
+ "partsscan": "",
+ "printlater": "",
+ "qbo": "",
+ "qbo_departmentid": "",
+ "qbo_usa": "",
+ "rbac": "",
+ "responsibilitycenters": {
+ "costs": "",
+ "profits": "",
+ "sales_tax_codes": "",
+ "tax_accounts": "",
+ "title": "",
+ "ttl_adjustment": "",
+ "ttl_tax_adjustment": ""
+ },
+ "roguard": {
+ "title": ""
+ },
+ "romepay": "",
+ "scheduling": "",
+ "scoreboardsetup": "",
+ "shop_enabled_features": "",
+ "shopinfo": "",
+ "shoprates": "",
+ "speedprint": "",
+ "ssbuckets": "",
+ "systemsettings": "",
+ "task-presets": "",
+ "workingdays": ""
+ },
+ "operations": {
+ "contains": "",
+ "ends_with": "",
+ "equals": "",
+ "greater_than": "",
+ "less_than": "",
+ "not_equals": "",
+ "starts_with": ""
+ },
+ "successes": {
+ "areyousure": "",
+ "defaultviewcreated": "",
+ "save": "",
+ "unsavedchanges": ""
+ },
+ "tooltips": {
+ "md_parts_scan": {
+ "update_value_tooltip": ""
+ }
+ },
+ "validation": {
+ "centermustexist": "",
+ "larsplit": "",
+ "useremailmustexist": ""
+ }
+ },
+ "checklist": {
+ "actions": {
+ "printall": ""
+ },
+ "errors": {
+ "complete": "",
+ "nochecklist": ""
+ },
+ "labels": {
+ "addtoproduction": "",
+ "allow_text_message": "",
+ "checklist": "",
+ "printpack": "",
+ "removefromproduction": ""
+ },
+ "successes": {
+ "completed": ""
+ }
+ },
+ "contracts": {
+ "actions": {
+ "changerate": "",
+ "convertoro": "",
+ "decodelicense": "",
+ "find": "",
+ "printcontract": "",
+ "senddltoform": ""
+ },
+ "errors": {
+ "fetchingjobinfo": "",
+ "returning": "",
+ "saving": "",
+ "selectjobandcar": ""
+ },
+ "fields": {
+ "actax": "",
+ "actualreturn": "",
+ "agreementnumber": "",
+ "cc_cardholder": "",
+ "cc_expiry": "",
+ "cc_num": "",
+ "cleanupcharge": "",
+ "coverage": "",
+ "dailyfreekm": "",
+ "dailyrate": "",
+ "damage": "",
+ "damagewaiver": "",
+ "driver": "",
+ "driver_addr1": "",
+ "driver_addr2": "",
+ "driver_city": "",
+ "driver_dlexpiry": "",
+ "driver_dlnumber": "",
+ "driver_dlst": "",
+ "driver_dob": "",
+ "driver_fn": "",
+ "driver_ln": "",
+ "driver_ph1": "",
+ "driver_state": "",
+ "driver_zip": "",
+ "excesskmrate": "",
+ "federaltax": "",
+ "fuelin": "",
+ "fuelout": "",
+ "kmend": "",
+ "kmstart": "",
+ "length": "",
+ "localtax": "",
+ "refuelcharge": "",
+ "scheduledreturn": "",
+ "start": "",
+ "statetax": "",
+ "status": ""
+ },
+ "labels": {
+ "agreement": "",
+ "availablecars": "",
+ "cardueforservice": "",
+ "convertform": {
+ "applycleanupcharge": "",
+ "refuelqty": ""
+ },
+ "correctdataonform": "",
+ "dateinpast": "",
+ "dlexpirebeforereturn": "",
+ "driverinformation": "",
+ "findcontract": "",
+ "findermodal": "",
+ "insuranceexpired": "",
+ "noteconvertedfrom": "",
+ "populatefromjob": "",
+ "rates": "",
+ "time": "",
+ "vehicle": "",
+ "waitingforscan": ""
+ },
+ "status": {
+ "new": "",
+ "out": "",
+ "returned": ""
+ },
+ "successes": {
+ "saved": ""
+ }
+ },
+ "courtesycars": {
+ "actions": {
+ "new": "",
+ "return": ""
+ },
+ "errors": {
+ "saving": ""
+ },
+ "fields": {
+ "color": "",
+ "dailycost": "",
+ "damage": "",
+ "fleetnumber": "",
+ "fuel": "",
+ "insuranceexpires": "",
+ "leaseenddate": "",
+ "make": "",
+ "mileage": "",
+ "model": "",
+ "nextservicedate": "",
+ "nextservicekm": "",
+ "notes": "",
+ "plate": "",
+ "purchasedate": "",
+ "readiness": "",
+ "registrationexpires": "",
+ "serviceenddate": "",
+ "servicestartdate": "",
+ "status": "",
+ "vin": "",
+ "year": ""
+ },
+ "labels": {
+ "courtesycar": "",
+ "fuel": {
+ "12": "",
+ "14": "",
+ "18": "",
+ "34": "",
+ "38": "",
+ "58": "",
+ "78": "",
+ "empty": "",
+ "full": ""
+ },
+ "outwith": "",
+ "return": "",
+ "status": "",
+ "uniquefleet": "",
+ "usage": "",
+ "vehicle": ""
+ },
+ "readiness": {
+ "notready": "",
+ "ready": ""
+ },
+ "status": {
+ "in": "",
+ "inservice": "",
+ "leasereturn": "",
+ "out": "",
+ "sold": "",
+ "unavailable": ""
+ },
+ "successes": {
+ "saved": ""
+ }
+ },
+ "csi": {
+ "actions": {
+ "activate": ""
+ },
+ "errors": {
+ "creating": "",
+ "notconfigured": "",
+ "notfoundsubtitle": "",
+ "notfoundtitle": "",
+ "surveycompletesubtitle": "",
+ "surveycompletetitle": ""
+ },
+ "fields": {
+ "completedon": "",
+ "created_at": "",
+ "surveyid": "",
+ "validuntil": ""
+ },
+ "labels": {
+ "copyright": "",
+ "greeting": "",
+ "intro": "",
+ "nologgedinuser": "",
+ "nologgedinuser_sub": "",
+ "noneselected": "",
+ "title": ""
+ },
+ "successes": {
+ "created": "",
+ "submitted": "",
+ "submittedsub": ""
+ }
+ },
+ "dashboard": {
+ "actions": {
+ "addcomponent": ""
+ },
+ "errors": {
+ "refreshrequired": "",
+ "updatinglayout": ""
+ },
+ "labels": {
+ "bodyhrs": "",
+ "dollarsinproduction": "",
+ "phone": "",
+ "prodhrs": "",
+ "refhrs": ""
+ },
+ "titles": {
+ "joblifecycle": "",
+ "labhours": "",
+ "larhours": "",
+ "monthlyemployeeefficiency": "",
+ "monthlyjobcosting": "",
+ "monthlylaborsales": "",
+ "monthlypartssales": "",
+ "monthlyrevenuegraph": "",
+ "prodhrssummary": "",
+ "productiondollars": "",
+ "productionhours": "",
+ "projectedmonthlysales": "",
+ "scheduledindate": "",
+ "scheduledintoday": "",
+ "scheduledoutdate": "",
+ "scheduledouttoday": "",
+ "tasks": ""
+ }
+ },
+ "dms": {
+ "errors": {
+ "alreadyexported": ""
+ },
+ "labels": {
+ "refreshallocations": ""
+ }
+ },
+ "documents": {
+ "actions": {
+ "delete": "",
+ "download": "",
+ "reassign": "",
+ "selectallimages": "",
+ "selectallotherdocuments": ""
+ },
+ "errors": {
+ "deletes3": "Erreur lors de la suppression du document du stockage.",
+ "deleting": "",
+ "deleting_cloudinary": "",
+ "getpresignurl": "Erreur lors de l'obtention de l'URL présignée pour le document. {{message}}",
+ "insert": "Incapable de télécharger le fichier. {{message}}",
+ "nodocuments": "Il n'y a pas de documents.",
+ "updating": ""
+ },
+ "labels": {
+ "confirmdelete": "",
+ "doctype": "",
+ "dragtoupload": "",
+ "newjobid": "",
+ "openinexplorer": "",
+ "optimizedimage": "",
+ "reassign_limitexceeded": "",
+ "reassign_limitexceeded_title": "",
+ "storageexceeded": "",
+ "storageexceeded_title": "",
+ "upload": "Télécharger",
+ "upload_limitexceeded": "",
+ "upload_limitexceeded_title": "",
+ "uploading": "",
+ "usage": ""
+ },
+ "successes": {
+ "delete": "Le document a bien été supprimé.",
+ "edituploaded": "",
+ "insert": "Document téléchargé avec succès.",
+ "updated": ""
+ }
+ },
+ "emails": {
+ "errors": {
+ "notsent": "Courriel non envoyé. Erreur rencontrée lors de l'envoi de {{message}}"
+ },
+ "fields": {
+ "cc": "",
+ "from": "",
+ "subject": "",
+ "to": ""
+ },
+ "labels": {
+ "attachments": "",
+ "documents": "",
+ "emailpreview": "",
+ "generatingemail": "",
+ "pdfcopywillbeattached": "",
+ "preview": ""
+ },
+ "successes": {
+ "sent": "E-mail envoyé avec succès."
+ }
+ },
+ "employee_teams": {
+ "actions": {
+ "new": "",
+ "newmember": ""
+ },
+ "fields": {
+ "active": "",
+ "employeeid": "",
+ "max_load": "",
+ "name": "",
+ "percentage": ""
+ }
+ },
+ "employees": {
+ "actions": {
+ "addvacation": "",
+ "new": "Nouvel employé",
+ "newrate": ""
+ },
+ "errors": {
+ "delete": "Erreur rencontrée lors de la suppression de l'employé. {{message}}",
+ "save": "Une erreur s'est produite lors de l'enregistrement de l'employé. {{message}}",
+ "validation": "Veuillez cocher tous les champs.",
+ "validationtitle": "Impossible d'enregistrer l'employé."
+ },
+ "fields": {
+ "active": "Actif?",
+ "base_rate": "Taux de base",
+ "cost_center": "Centre de coûts",
+ "employee_number": "Numéro d'employé",
+ "external_id": "",
+ "first_name": "Prénom",
+ "flat_rate": "Taux fixe (désactivé est le temps normal)",
+ "hire_date": "Date d'embauche",
+ "last_name": "Nom de famille",
+ "pin": "",
+ "rate": "",
+ "termination_date": "Date de résiliation",
+ "user_email": "",
+ "vacation": {
+ "end": "",
+ "length": "",
+ "start": ""
+ }
+ },
+ "labels": {
+ "actions": "",
+ "active": "",
+ "endmustbeafterstart": "",
+ "flat_rate": "",
+ "inactive": "",
+ "name": "",
+ "rate_type": "",
+ "status": "",
+ "straight_time": ""
+ },
+ "successes": {
+ "delete": "L'employé a bien été supprimé.",
+ "save": "L'employé a enregistré avec succès.",
+ "vacationadded": ""
+ },
+ "validation": {
+ "unique_employee_number": ""
+ }
+ },
+ "eula": {
+ "buttons": {
+ "accept": "Accept EULA"
+ },
+ "content": {
+ "never_scrolled": "You must scroll to the bottom of the Terms and Conditions before accepting."
+ },
+ "errors": {
+ "acceptance": {
+ "description": "Something went wrong while accepting the EULA. Please try again.",
+ "message": "Eula Acceptance Error"
+ }
+ },
+ "labels": {
+ "accepted_terms": "I accept the terms and conditions of this agreement.",
+ "address": "Address",
+ "business_name": "Legal Business Name",
+ "date_accepted": "Date Accepted",
+ "first_name": "First Name",
+ "last_name": "Last Name",
+ "phone_number": "Phone Number"
+ },
+ "messages": {
+ "accepted_terms": "Please accept the terms and conditions of this agreement.",
+ "business_name": "Please enter your legal business name.",
+ "date_accepted": "Please enter Today's Date.",
+ "first_name": "Please enter your first name.",
+ "last_name": "Please enter your last name.",
+ "phone_number": "Please enter your phone number."
+ },
+ "titles": {
+ "modal": "Terms and Conditions",
+ "upper_card": "Acknowledgement"
+ }
+ },
+ "exportlogs": {
+ "fields": {
+ "createdat": ""
+ },
+ "labels": {
+ "attempts": "",
+ "priorsuccesfulexport": ""
+ }
+ },
+ "general": {
+ "actions": {
+ "add": "",
+ "autoupdate": "",
+ "calculate": "",
+ "cancel": "",
+ "clear": "",
+ "close": "",
+ "copied": "",
+ "copylink": "",
+ "create": "",
+ "defaults": "",
+ "delay": "",
+ "delete": "Effacer",
+ "deleteall": "",
+ "deselectall": "",
+ "download": "",
+ "edit": "modifier",
+ "login": "",
+ "next": "",
+ "ok": "",
+ "previous": "",
+ "print": "",
+ "refresh": "",
+ "remove": "",
+ "remove_alert": "",
+ "reset": " Rétablir l'original.",
+ "resetpassword": "",
+ "save": "sauvegarder",
+ "saveandnew": "",
+ "saveas": "",
+ "selectall": "",
+ "send": "",
+ "sendbysms": "",
+ "senderrortosupport": "",
+ "sharetoteams": "",
+ "submit": "",
+ "tryagain": "",
+ "view": "",
+ "viewreleasenotes": ""
+ },
+ "errors": {
+ "fcm": "",
+ "notfound": "",
+ "sizelimit": ""
+ },
+ "itemtypes": {
+ "contract": "",
+ "courtesycar": "",
+ "job": "",
+ "owner": "",
+ "vehicle": ""
+ },
+ "labels": {
+ "actions": "actes",
+ "areyousure": "",
+ "barcode": "code à barre",
+ "cancel": "",
+ "clear": "",
+ "confirmpassword": "",
+ "created_at": "",
+ "date": "",
+ "datetime": "",
+ "email": "",
+ "errors": "",
+ "excel": "",
+ "exceptiontitle": "",
+ "friday": "",
+ "globalsearch": "",
+ "help": "",
+ "hours": "",
+ "in": "dans",
+ "instanceconflictext": "",
+ "instanceconflictitle": "",
+ "item": "",
+ "label": "",
+ "loading": "Chargement...",
+ "loadingapp": "Chargement de {{app}}",
+ "loadingshop": "Chargement des données de la boutique ...",
+ "loggingin": "Vous connecter ...",
+ "markedexported": "",
+ "media": "",
+ "message": "",
+ "monday": "",
+ "na": "N / A",
+ "newpassword": "",
+ "no": "",
+ "nointernet": "",
+ "nointernet_sub": "",
+ "none": "",
+ "out": "En dehors",
+ "password": "",
+ "passwordresetsuccess": "",
+ "passwordresetsuccess_sub": "",
+ "passwordresetvalidatesuccess": "",
+ "passwordresetvalidatesuccess_sub": "",
+ "passwordsdonotmatch": "",
+ "print": "",
+ "refresh": "",
+ "reports": "",
+ "required": "",
+ "saturday": "",
+ "search": "Chercher...",
+ "searchresults": "",
+ "selectdate": "",
+ "sendagain": "",
+ "sendby": "",
+ "signin": "",
+ "sms": "",
+ "status": "",
+ "sub_status": {
+ "expired": ""
+ },
+ "successful": "",
+ "sunday": "",
+ "text": "",
+ "thursday": "",
+ "time": "",
+ "total": "",
+ "totals": "",
+ "tuesday": "",
+ "tvmode": "",
+ "unknown": "Inconnu",
+ "unsavedchanges": "",
+ "username": "",
+ "view": "",
+ "wednesday": "",
+ "yes": ""
+ },
+ "languages": {
+ "english": "Anglais",
+ "french": "Francais",
+ "spanish": "Espanol"
+ },
+ "messages": {
+ "exception": "",
+ "newversionmessage": "",
+ "newversiontitle": "",
+ "noacctfilepath": "",
+ "nofeatureaccess": "",
+ "noshop": "",
+ "notfoundsub": "",
+ "notfoundtitle": "",
+ "partnernotrunning": "",
+ "rbacunauth": "",
+ "unsavedchanges": "Vous avez des changements non enregistrés.",
+ "unsavedchangespopup": ""
+ },
+ "validation": {
+ "dateRangeExceeded": "",
+ "invalidemail": "S'il vous plaît entrer un email valide.",
+ "invalidphone": "",
+ "required": "Ce champ est requis."
+ }
+ },
+ "help": {
+ "actions": {
+ "connect": ""
+ },
+ "labels": {
+ "codeplacholder": "",
+ "rescuedesc": "",
+ "rescuetitle": ""
+ }
+ },
+ "intake": {
+ "labels": {
+ "printpack": ""
+ }
+ },
+ "inventory": {
+ "actions": {
+ "addtoinventory": "",
+ "addtoro": "",
+ "consumefrominventory": "",
+ "edit": "",
+ "new": ""
+ },
+ "errors": {
+ "inserting": ""
+ },
+ "fields": {
+ "comment": "",
+ "manualinvoicenumber": "",
+ "manualvendor": ""
+ },
+ "labels": {
+ "consumedbyjob": "",
+ "deleteconfirm": "",
+ "frombillinvoicenumber": "",
+ "fromvendor": "",
+ "inventory": "",
+ "showall": "",
+ "showavailable": ""
+ },
+ "successes": {
+ "deleted": "",
+ "inserted": "",
+ "updated": ""
+ }
+ },
+ "job_lifecycle": {
+ "columns": {
+ "average_human_readable": "",
+ "average_value": "",
+ "duration": "",
+ "end": "",
+ "human_readable": "",
+ "percentage": "",
+ "relative_end": "",
+ "relative_start": "",
+ "start": "",
+ "status": "",
+ "status_count": "",
+ "value": ""
+ },
+ "content": {
+ "calculated_based_on": "",
+ "current_status_accumulated_time": "",
+ "data_unavailable": "",
+ "jobs_in_since": "",
+ "legend_title": "",
+ "loading": "",
+ "not_available": "",
+ "previous_status_accumulated_time": "",
+ "title": "",
+ "title_durations": "",
+ "title_loading": "",
+ "title_transitions": ""
+ },
+ "errors": {
+ "fetch": "Erreur lors de l'obtention des données du cycle de vie des tâches"
+ },
+ "titles": {
+ "dashboard": "",
+ "top_durations": ""
+ }
+ },
+ "job_payments": {
+ "buttons": {
+ "create_short_link": "",
+ "goback": "",
+ "proceedtopayment": "",
+ "refundpayment": ""
+ },
+ "notifications": {
+ "error": {
+ "description": "",
+ "openingip": "",
+ "title": ""
+ }
+ },
+ "titles": {
+ "amount": "",
+ "dateOfPayment": "",
+ "descriptions": "",
+ "hint": "",
+ "payer": "",
+ "payername": "",
+ "paymentid": "",
+ "paymentnum": "",
+ "paymenttype": "",
+ "refundamount": "",
+ "transactionid": ""
+ }
+ },
+ "joblines": {
+ "actions": {
+ "assign_team": "",
+ "converttolabor": "",
+ "dispatchparts": "",
+ "new": ""
+ },
+ "errors": {
+ "creating": "",
+ "updating": ""
+ },
+ "fields": {
+ "act_price": "Prix actuel",
+ "act_price_before_ppc": "",
+ "adjustment": "",
+ "ah_detail_line": "",
+ "alt_partno": "",
+ "amount": "",
+ "assigned_team": "",
+ "assigned_team_name": "",
+ "create_ppc": "",
+ "db_price": "Prix de la base de données",
+ "include_in_part_cnt": "",
+ "lbr_types": {
+ "LA1": "",
+ "LA2": "",
+ "LA3": "",
+ "LA4": "",
+ "LAA": "",
+ "LAB": "",
+ "LAD": "",
+ "LAE": "",
+ "LAF": "",
+ "LAG": "",
+ "LAM": "",
+ "LAR": "",
+ "LAS": "",
+ "LAU": ""
+ },
+ "line_desc": "Description de la ligne",
+ "line_ind": "S#",
+ "line_no": "",
+ "location": "",
+ "mod_lb_hrs": "Heures de travail",
+ "mod_lbr_ty": "Type de travail",
+ "notes": "",
+ "oem_partno": "Pièce OEM #",
+ "op_code_desc": "",
+ "part_qty": "",
+ "part_type": "Type de pièce",
+ "part_types": {
+ "CCC": "",
+ "CCD": "",
+ "CCDR": "",
+ "CCF": "",
+ "CCM": "",
+ "PAA": "",
+ "PAC": "",
+ "PAE": "",
+ "PAG": "",
+ "PAL": "",
+ "PAM": "",
+ "PAN": "",
+ "PAO": "",
+ "PAP": "",
+ "PAR": "",
+ "PAS": "",
+ "PASL": ""
+ },
+ "profitcenter_labor": "",
+ "profitcenter_part": "",
+ "prt_dsmk_m": "",
+ "prt_dsmk_p": "",
+ "status": "Statut",
+ "tax_part": "",
+ "total": "",
+ "unq_seq": "Seq #"
+ },
+ "labels": {
+ "adjustmenttobeadded": "",
+ "billref": "",
+ "convertedtolabor": "",
+ "edit": "Ligne d'édition",
+ "ioucreated": "",
+ "new": "Nouvelle ligne",
+ "nostatus": "",
+ "presets": ""
+ },
+ "successes": {
+ "created": "",
+ "saved": "",
+ "updated": ""
+ },
+ "validations": {
+ "ahdetailonlyonuserdefinedtypes": "",
+ "hrsrequirediflbrtyp": "",
+ "requiredifparttype": "",
+ "zeropriceexistingpart": ""
+ }
+ },
+ "jobs": {
+ "actions": {
+ "addDocuments": "Ajouter des documents de travail",
+ "addNote": "Ajouter une note",
+ "addtopartsqueue": "",
+ "addtoproduction": "",
+ "addtoscoreboard": "",
+ "allocate": "",
+ "autoallocate": "",
+ "changefilehandler": "",
+ "changelaborrate": "",
+ "changestatus": "Changer le statut",
+ "changestimator": "",
+ "convert": "Convertir",
+ "createiou": "",
+ "deliver": "",
+ "deliver_quick": "",
+ "dms": {
+ "addpayer": "",
+ "createnewcustomer": "",
+ "findmakemodelcode": "",
+ "getmakes": "",
+ "labels": {
+ "refreshallocations": ""
+ },
+ "post": "",
+ "refetchmakesmodels": "",
+ "usegeneric": "",
+ "useselected": ""
+ },
+ "dmsautoallocate": "",
+ "export": "",
+ "exportcustdata": "",
+ "exportselected": "",
+ "filterpartsonly": "",
+ "generatecsi": "",
+ "gotojob": "",
+ "intake": "",
+ "intake_quick": "",
+ "manualnew": "",
+ "mark": "",
+ "markasexported": "",
+ "markpstexempt": "",
+ "markpstexemptconfirm": "",
+ "postbills": "Poster des factures",
+ "printCenter": "Centre d'impression",
+ "recalculate": "",
+ "reconcile": "",
+ "removefromproduction": "",
+ "schedule": "Programme",
+ "sendcsi": "",
+ "sendpartspricechange": "",
+ "sendtodms": "",
+ "sync": "",
+ "taxprofileoverride": "",
+ "taxprofileoverride_confirm": "",
+ "uninvoice": "",
+ "unvoid": "",
+ "viewchecklist": "",
+ "viewdetail": ""
+ },
+ "errors": {
+ "addingtoproduction": "",
+ "cannotintake": "",
+ "closing": "",
+ "creating": "",
+ "deleted": "Erreur lors de la suppression du travail.",
+ "exporting": "",
+ "exporting-partner": "",
+ "invoicing": "",
+ "noaccess": "Ce travail n'existe pas ou vous n'y avez pas accès.",
+ "nodamage": "",
+ "nodates": "Aucune date spécifiée pour ce travail.",
+ "nofinancial": "",
+ "nojobselected": "Aucun travail n'est sélectionné.",
+ "noowner": "Aucun propriétaire associé.",
+ "novehicle": "Aucun véhicule associé.",
+ "partspricechange": "",
+ "saving": "Erreur rencontrée lors de la sauvegarde de l'enregistrement.",
+ "scanimport": "",
+ "totalscalc": "",
+ "updating": "",
+ "validation": "Veuillez vous assurer que tous les champs sont correctement entrés.",
+ "validationtitle": "Erreur de validation",
+ "voiding": ""
+ },
+ "fields": {
+ "active_tasks": "",
+ "actual_completion": "Achèvement réel",
+ "actual_delivery": "Livraison réelle",
+ "actual_in": "En réel",
+ "adjustment_bottom_line": "Ajustements",
+ "adjustmenthours": "",
+ "alt_transport": "",
+ "area_of_damage_impact": {
+ "10": "",
+ "11": "",
+ "12": "",
+ "13": "",
+ "14": "",
+ "15": "",
+ "16": "",
+ "25": "",
+ "26": "",
+ "27": "",
+ "28": "",
+ "34": "",
+ "01": "",
+ "02": "",
+ "03": "",
+ "04": "",
+ "05": "",
+ "06": "",
+ "07": "",
+ "08": "",
+ "09": ""
+ },
+ "auto_add_ats": "",
+ "ca_bc_pvrt": "",
+ "ca_customer_gst": "",
+ "ca_gst_registrant": "",
+ "category": "",
+ "ccc": "",
+ "ccd": "",
+ "ccdr": "",
+ "ccf": "",
+ "ccm": "",
+ "cieca_id": "CIECA ID",
+ "cieca_pfl": {
+ "lbr_adjp": "",
+ "lbr_tax_in": "",
+ "lbr_taxp": "",
+ "lbr_tx_in1": "",
+ "lbr_tx_in2": "",
+ "lbr_tx_in3": "",
+ "lbr_tx_in4": "",
+ "lbr_tx_in5": ""
+ },
+ "cieca_pfo": {
+ "stor_t_in1": "",
+ "stor_t_in2": "",
+ "stor_t_in3": "",
+ "stor_t_in4": "",
+ "stor_t_in5": "",
+ "tow_t_in1": "",
+ "tow_t_in2": "",
+ "tow_t_in3": "",
+ "tow_t_in4": "",
+ "tow_t_in5": ""
+ },
+ "claim_total": "Total réclamation",
+ "class": "",
+ "clm_no": "Prétendre #",
+ "clm_total": "Total réclamation",
+ "comment": "",
+ "customerowing": "Client propriétaire",
+ "date_estimated": "Date estimée",
+ "date_exported": "Exportés",
+ "date_invoiced": "Facturé",
+ "date_last_contacted": "",
+ "date_lost_sale": "",
+ "date_next_contact": "",
+ "date_open": "Ouvrir",
+ "date_rentalresp": "",
+ "date_repairstarted": "",
+ "date_scheduled": "Prévu",
+ "date_towin": "",
+ "date_void": "",
+ "ded_amt": "Déductible",
+ "ded_note": "",
+ "ded_status": "Statut de franchise",
+ "depreciation_taxes": "Amortissement / taxes",
+ "dms": {
+ "address": "",
+ "amount": "",
+ "center": "",
+ "control_type": {
+ "account_number": ""
+ },
+ "cost": "",
+ "cost_dms_acctnumber": "",
+ "dms_make": "",
+ "dms_model": "",
+ "dms_model_override": "",
+ "dms_unsold": "",
+ "dms_wip_acctnumber": "",
+ "id": "",
+ "inservicedate": "",
+ "journal": "",
+ "lines": "",
+ "name1": "",
+ "payer": {
+ "amount": "",
+ "control_type": "",
+ "controlnumber": "",
+ "dms_acctnumber": "",
+ "name": ""
+ },
+ "sale": "",
+ "sale_dms_acctnumber": "",
+ "story": "",
+ "vinowner": ""
+ },
+ "dms_allocation": "",
+ "driveable": "",
+ "employee_body": "",
+ "employee_csr": "représentant du service à la clientèle",
+ "employee_csr_writer": "",
+ "employee_prep": "",
+ "employee_refinish": "",
+ "est_addr1": "Adresse de l'évaluateur",
+ "est_co_nm": "Expert",
+ "est_ct_fn": "Prénom de l'évaluateur",
+ "est_ct_ln": "Nom de l'évaluateur",
+ "est_ea": "Courriel de l'évaluateur",
+ "est_ph1": "Numéro de téléphone de l'évaluateur",
+ "flat_rate_ats": "",
+ "federal_tax_payable": "Impôt fédéral à payer",
+ "federal_tax_rate": "",
+ "ins_addr1": "Adresse Insurance Co.",
+ "ins_city": "Insurance City",
+ "ins_co_id": "ID de la compagnie d'assurance",
+ "ins_co_nm": "Nom de la compagnie d'assurance",
+ "ins_co_nm_short": "",
+ "ins_ct_fn": "Prénom du gestionnaire de fichiers",
+ "ins_ct_ln": "Nom du gestionnaire de fichiers",
+ "ins_ea": "Courriel du gestionnaire de fichiers",
+ "ins_ph1": "Numéro de téléphone du gestionnaire de fichiers",
+ "intake": {
+ "label": "",
+ "max": "",
+ "min": "",
+ "name": "",
+ "required": "",
+ "type": ""
+ },
+ "invoice_final_note": "",
+ "kmin": "Kilométrage en",
+ "kmout": "Kilométrage hors",
+ "la1": "",
+ "la2": "",
+ "la3": "",
+ "la4": "",
+ "laa": "",
+ "lab": "",
+ "labor_rate_desc": "Nom du taux de main-d'œuvre",
+ "lad": "",
+ "lae": "",
+ "laf": "",
+ "lag": "",
+ "lam": "",
+ "lar": "",
+ "las": "",
+ "lau": "",
+ "local_tax_rate": "",
+ "loss_date": "Date de perte",
+ "loss_desc": "",
+ "loss_of_use": "",
+ "lost_sale_reason": "",
+ "ma2s": "",
+ "ma3s": "",
+ "mabl": "",
+ "macs": "",
+ "mahw": "",
+ "mapa": "",
+ "mash": "",
+ "matd": "",
+ "materials": {
+ "MAPA": "",
+ "MASH": "",
+ "cal_maxdlr": "",
+ "cal_opcode": "",
+ "mat_adjp": "",
+ "mat_taxp": "",
+ "mat_tx_in1": "",
+ "mat_tx_in2": "",
+ "mat_tx_in3": "",
+ "mat_tx_in4": "",
+ "mat_tx_in5": "",
+ "materials": "",
+ "tax_ind": ""
+ },
+ "other_amount_payable": "Autre montant à payer",
+ "owner": "Propriétaire",
+ "owner_owing": "Cust. Owes",
+ "ownr_ea": "Email",
+ "ownr_ph1": "Téléphone 1",
+ "ownr_ph2": "",
+ "paa": "",
+ "pac": "",
+ "pae": "",
+ "pag": "",
+ "pal": "",
+ "pam": "",
+ "pan": "",
+ "pao": "",
+ "pap": "",
+ "par": "",
+ "parts_tax_rates": {
+ "prt_discp": "",
+ "prt_mktyp": "",
+ "prt_mkupp": "",
+ "prt_tax_in": "",
+ "prt_tax_rt": "",
+ "prt_tx_in1": "",
+ "prt_tx_in2": "",
+ "prt_tx_in3": "",
+ "prt_tx_in4": "",
+ "prt_tx_in5": "",
+ "prt_tx_ty1": "",
+ "prt_type": ""
+ },
+ "partsstatus": "",
+ "pas": "",
+ "pay_date": "Date d'Pay",
+ "phoneshort": "PH",
+ "po_number": "",
+ "policy_no": "Politique #",
+ "ponumber": "Numéro de bon de commande",
+ "production_vars": {
+ "note": ""
+ },
+ "qb_multiple_payers": {
+ "amount": "",
+ "name": ""
+ },
+ "queued_for_parts": "",
+ "rate_ats": "",
+ "rate_ats_flat": "",
+ "rate_la1": "Taux LA1",
+ "rate_la2": "Taux LA2",
+ "rate_la3": "Taux LA3",
+ "rate_la4": "Taux LA4",
+ "rate_laa": "Taux d'aluminium",
+ "rate_lab": "Taux de la main-d'œuvre",
+ "rate_lad": "Taux de diagnostic",
+ "rate_lae": "Tarif électrique",
+ "rate_laf": "Taux de trame",
+ "rate_lag": "Taux de verre",
+ "rate_lam": "Taux mécanique",
+ "rate_lar": "Taux de finition",
+ "rate_las": "",
+ "rate_lau": "Taux d'aluminium",
+ "rate_ma2s": "Taux de peinture en 2 étapes",
+ "rate_ma3s": "Taux de peinture en 3 étapes",
+ "rate_mabl": "MABL ??",
+ "rate_macs": "MACS ??",
+ "rate_mahw": "Taux de déchets dangereux",
+ "rate_mapa": "Taux de matériaux de peinture",
+ "rate_mash": "Tarif du matériel de la boutique",
+ "rate_matd": "Taux d'élimination des pneus",
+ "referral_source_extra": "",
+ "referral_source_other": "",
+ "referralsource": "Source de référence",
+ "regie_number": "Enregistrement #",
+ "repairtotal": "Réparation totale",
+ "ro_number": "RO #",
+ "scheduled_completion": "Achèvement planifié",
+ "scheduled_delivery": "Livraison programmée",
+ "scheduled_in": "Planifié dans",
+ "selling_dealer": "Revendeur vendeur",
+ "selling_dealer_contact": "Contacter le revendeur",
+ "servicecar": "Voiture de service",
+ "servicing_dealer": "Concessionnaire",
+ "servicing_dealer_contact": "Contacter le concessionnaire",
+ "special_coverage_policy": "Politique de couverture spéciale",
+ "specialcoveragepolicy": "Politique de couverture spéciale",
+ "state_tax_rate": "",
+ "status": "Statut de l'emploi",
+ "storage_payable": "Stockage",
+ "tax_lbr_rt": "",
+ "tax_levies_rt": "",
+ "tax_paint_mat_rt": "",
+ "tax_registration_number": "",
+ "tax_shop_mat_rt": "",
+ "tax_str_rt": "",
+ "tax_sub_rt": "",
+ "tax_tow_rt": "",
+ "tlos_ind": "",
+ "towin": "",
+ "towing_payable": "Remorquage à payer",
+ "unitnumber": "Unité #",
+ "updated_at": "Mis à jour à",
+ "uploaded_by": "Telechargé par",
+ "vehicle": "Véhicule"
+ },
+ "forms": {
+ "admindates": "",
+ "appraiserinfo": "",
+ "claiminfo": "",
+ "estdates": "",
+ "laborrates": "",
+ "lossinfo": "",
+ "other": "",
+ "repairdates": "",
+ "scheddates": ""
+ },
+ "labels": {
+ "accountsreceivable": "",
+ "act_price_ppc": "",
+ "actual_completion_inferred": "",
+ "actual_delivery_inferred": "",
+ "actual_in_inferred": "",
+ "additionalpayeroverallocation": "",
+ "additionaltotal": "",
+ "adjustmentrate": "",
+ "adjustments": "",
+ "adminwarning": "",
+ "allocations": "",
+ "alreadyaddedtoscoreboard": "",
+ "alreadyclosed": "",
+ "appointmentconfirmation": "Envoyer une confirmation au client?",
+ "associationwarning": "",
+ "audit": "",
+ "available": "",
+ "availablejobs": "",
+ "ca_bc_pvrt": {
+ "days": "",
+ "rate": ""
+ },
+ "ca_gst_all_if_null": "",
+ "calc_repair_days": "",
+ "calc_repair_days_tt": "",
+ "calc_scheuled_completion": "",
+ "cards": {
+ "customer": "Informations client",
+ "damage": "Zone de dommages",
+ "dates": "Rendez-vous",
+ "documents": "Documents récents",
+ "estimator": "Estimateur",
+ "filehandler": "Gestionnaire de fichiers",
+ "insurance": "Détails de l'assurance",
+ "more": "Plus",
+ "notes": "Remarques",
+ "parts": "les pièces",
+ "totals": "Totaux",
+ "vehicle": "Véhicule"
+ },
+ "changeclass": "",
+ "checklistcompletedby": "",
+ "checklistdocuments": "",
+ "checklists": "",
+ "cieca_pfl": "",
+ "cieca_pfo": "",
+ "cieca_pft": "",
+ "closeconfirm": "",
+ "closejob": "",
+ "closingperiod": "",
+ "contracts": "",
+ "convertedtolabor": "",
+ "cost": "",
+ "cost_Additional": "",
+ "cost_labor": "",
+ "cost_parts": "",
+ "cost_sublet": "",
+ "costs": "",
+ "create": {
+ "jobinfo": "",
+ "newowner": "",
+ "newvehicle": "",
+ "novehicle": "",
+ "ownerinfo": "",
+ "vehicleinfo": ""
+ },
+ "createiouwarning": "",
+ "creating_new_job": "Création d'un nouvel emploi ...",
+ "deductible": {
+ "stands": "",
+ "waived": ""
+ },
+ "deleteconfirm": "",
+ "deletedelivery": "",
+ "deleteintake": "",
+ "deliverchecklist": "",
+ "difference": "",
+ "diskscan": "",
+ "dms": {
+ "apexported": "",
+ "damageto": "",
+ "defaultstory": "",
+ "disablebillwip": "",
+ "invoicedatefuture": "",
+ "kmoutnotgreaterthankmin": "",
+ "logs": "",
+ "notallocated": "",
+ "postingform": "",
+ "totalallocated": ""
+ },
+ "documents": "Les documents",
+ "documents-images": "",
+ "documents-other": "",
+ "duplicateconfirm": "",
+ "emailaudit": "",
+ "employeeassignments": "",
+ "estimatelines": "",
+ "estimator": "",
+ "existing_jobs": "Emplois existants",
+ "federal_tax_amt": "",
+ "gpdollars": "",
+ "gppercent": "",
+ "hrs_claimed": "",
+ "hrs_total": "",
+ "importnote": "",
+ "inproduction": "",
+ "intakechecklist": "",
+ "iou": "",
+ "job": "",
+ "jobcosting": "",
+ "jobtotals": "",
+ "labor_hrs": "",
+ "labor_rates_subtotal": "",
+ "laborallocations": "",
+ "labortotals": "",
+ "lines": "Estimer les lignes",
+ "local_tax_amt": "",
+ "mapa": "",
+ "markforreexport": "",
+ "mash": "",
+ "masterbypass": "",
+ "materials": {
+ "mapa": ""
+ },
+ "missingprofileinfo": "",
+ "multipayers": "",
+ "net_repairs": "",
+ "notes": "Remarques",
+ "othertotal": "",
+ "outstanding_ar": "",
+ "outstanding_credit_memos": "",
+ "outstanding_ppd": "",
+ "outstanding_reconciliation_discrep": "",
+ "outstanding_sublets": "",
+ "outstandinghours": "",
+ "override_header": "Remplacer l'en-tête d'estimation à l'importation?",
+ "ownerassociation": "",
+ "parts": "les pièces",
+ "parts_lines": "",
+ "parts_received": "",
+ "parts_tax_rates": "",
+ "partsfilter": "",
+ "partssubletstotal": "",
+ "partstotal": "",
+ "performance": "",
+ "pimraryamountpayable": "",
+ "plitooltips": {
+ "billtotal": "",
+ "calculatedcreditsnotreceived": "",
+ "creditmemos": "",
+ "creditsnotreceived": "",
+ "discrep1": "",
+ "discrep2": "",
+ "discrep3": "",
+ "laboradj": "",
+ "partstotal": "",
+ "totalreturns": ""
+ },
+ "ppc": "",
+ "ppdnotexported": "",
+ "profileadjustments": "",
+ "profitbypassrequired": "",
+ "profits": "",
+ "prt_dsmk_total": "",
+ "rates": "Les taux",
+ "rates_subtotal": "",
+ "reconciliation": {
+ "billlinestotal": "",
+ "byassoc": "",
+ "byprice": "",
+ "clear": "",
+ "discrepancy": "",
+ "joblinestotal": "",
+ "multipleactprices": "",
+ "multiplebilllines": "",
+ "multiplebillsforactprice": "",
+ "removedpartsstrikethrough": ""
+ },
+ "reconciliationheader": "",
+ "relatedros": "",
+ "remove_from_ar": "",
+ "returntotals": "",
+ "ro_guard": {
+ "enforce_ar": "",
+ "enforce_bills": "",
+ "enforce_cm": "",
+ "enforce_labor": "",
+ "enforce_ppd": "",
+ "enforce_profit": "",
+ "enforce_sublet": "",
+ "enforce_validation": "",
+ "enforced": ""
+ },
+ "roguard": "",
+ "roguardwarnings": "",
+ "rosaletotal": "",
+ "sale_additional": "",
+ "sale_labor": "",
+ "sale_parts": "",
+ "sale_sublet": "",
+ "sales": "",
+ "savebeforeconversion": "",
+ "scheduledinchange": "",
+ "specialcoveragepolicy": "",
+ "state_tax_amt": "",
+ "subletsnotcompleted": "",
+ "subletstotal": "",
+ "subtotal": "",
+ "supplementnote": "",
+ "suspended": "",
+ "suspense": "",
+ "tasks": "",
+ "threshhold": "",
+ "total_cost": "",
+ "total_cust_payable": "",
+ "total_cust_payable_cash_discount": "",
+ "total_repairs": "",
+ "total_repairs_cash_discount": "",
+ "total_sales": "",
+ "total_sales_tax": "",
+ "totals": "",
+ "unvoidnote": "",
+ "update_scheduled_completion": "",
+ "vehicle_info": "Véhicule",
+ "vehicleassociation": "",
+ "viewallocations": "",
+ "voidjob": "",
+ "voidnote": ""
+ },
+ "successes": {
+ "addedtoproduction": "",
+ "all_deleted": "{{count}} travaux supprimés avec succès.",
+ "closed": "",
+ "converted": "Travail converti avec succès.",
+ "created": "Le travail a été créé avec succès. Clique pour voir.",
+ "creatednoclick": "",
+ "delete": "",
+ "deleted": "Le travail a bien été supprimé.",
+ "duplicated": "",
+ "exported": "",
+ "invoiced": "",
+ "ioucreated": "",
+ "partsqueue": "",
+ "save": "Le travail a été enregistré avec succès.",
+ "savetitle": "Enregistrement enregistré avec succès.",
+ "supplemented": "Travail complété avec succès.",
+ "updated": "",
+ "voided": ""
+ }
+ },
+ "landing": {
+ "bigfeature": {
+ "subtitle": "",
+ "title": ""
+ },
+ "footer": {
+ "company": {
+ "about": "",
+ "contact": "",
+ "disclaimers": "",
+ "name": "",
+ "privacypolicy": ""
+ },
+ "io": {
+ "help": "",
+ "name": "",
+ "status": ""
+ },
+ "slogan": ""
+ },
+ "hero": {
+ "button": "",
+ "title": ""
+ },
+ "labels": {
+ "features": "",
+ "managemyshop": "",
+ "pricing": ""
+ },
+ "pricing": {
+ "basic": {
+ "name": "",
+ "sub": ""
+ },
+ "essentials": {
+ "name": "",
+ "sub": ""
+ },
+ "pricingtitle": "",
+ "pro": {
+ "name": "",
+ "sub": ""
+ },
+ "title": "",
+ "unlimited": {
+ "name": "",
+ "sub": ""
+ }
+ }
+ },
+ "menus": {
+ "currentuser": {
+ "languageselector": "La langue",
+ "profile": "Profil"
+ },
+ "header": {
+ "accounting": "",
+ "accounting-payables": "",
+ "accounting-payments": "",
+ "accounting-receivables": "",
+ "activejobs": "Emplois actifs",
+ "all_tasks": "",
+ "alljobs": "",
+ "allpayments": "",
+ "availablejobs": "Emplois disponibles",
+ "bills": "",
+ "courtesycars": "",
+ "courtesycars-all": "",
+ "courtesycars-contracts": "",
+ "courtesycars-newcontract": "",
+ "create_task": "",
+ "customers": "Les clients",
+ "dashboard": "",
+ "enterbills": "",
+ "entercardpayment": "",
+ "enterpayment": "",
+ "entertimeticket": "",
+ "export": "",
+ "export-logs": "",
+ "help": "",
+ "home": "Accueil",
+ "inventory": "",
+ "jobs": "Emplois",
+ "my_tasks": "",
+ "newjob": "",
+ "owners": "Propriétaires",
+ "parts-queue": "",
+ "phonebook": "",
+ "productionboard": "",
+ "productionlist": "",
+ "readyjobs": "",
+ "recent": "",
+ "reportcenter": "",
+ "rescueme": "",
+ "schedule": "Programme",
+ "scoreboard": "",
+ "search": {
+ "bills": "",
+ "jobs": "",
+ "owners": "",
+ "payments": "",
+ "phonebook": "",
+ "vehicles": ""
+ },
+ "shiftclock": "",
+ "shop": "Mon magasin",
+ "shop_config": "Configuration",
+ "shop_csi": "",
+ "shop_templates": "",
+ "shop_vendors": "Vendeurs",
+ "tasks": "",
+ "temporarydocs": "",
+ "timetickets": "",
+ "ttapprovals": "",
+ "vehicles": "Véhicules"
+ },
+ "jobsactions": {
+ "admin": "",
+ "cancelallappointments": "",
+ "closejob": "",
+ "deletejob": "",
+ "duplicate": "",
+ "duplicatenolines": "",
+ "newcccontract": "",
+ "void": ""
+ },
+ "jobsdetail": {
+ "claimdetail": "Détails de la réclamation",
+ "dates": "Rendez-vous",
+ "financials": "",
+ "general": "",
+ "insurance": "",
+ "labor": "La main d'oeuvre",
+ "lifecycle": "",
+ "parts": "",
+ "partssublet": "Pièces / Sous-location",
+ "rates": "",
+ "repairdata": "Données de réparation",
+ "totals": ""
+ },
+ "profilesidebar": {
+ "profile": "Mon profil",
+ "shops": "Mes boutiques"
+ },
+ "tech": {
+ "assignedjobs": "",
+ "claimtask": "",
+ "dispatchedparts": "",
+ "home": "",
+ "jobclockin": "",
+ "jobclockout": "",
+ "joblookup": "",
+ "login": "",
+ "logout": "",
+ "productionboard": "",
+ "productionlist": "",
+ "shiftclockin": ""
+ }
+ },
+ "messaging": {
+ "actions": {
+ "link": "",
+ "new": ""
+ },
+ "errors": {
+ "invalidphone": "",
+ "noattachedjobs": "",
+ "updatinglabel": ""
+ },
+ "labels": {
+ "addlabel": "",
+ "archive": "",
+ "maxtenimages": "",
+ "messaging": "Messagerie",
+ "noallowtxt": "",
+ "nojobs": "",
+ "nopush": "",
+ "phonenumber": "",
+ "presets": "",
+ "recentonly": "",
+ "selectmedia": "",
+ "sentby": "",
+ "typeamessage": "Envoyer un message...",
+ "unarchive": ""
+ },
+ "render": {
+ "conversation_list": ""
+ }
+ },
+ "notes": {
+ "actions": {
+ "actions": "actes",
+ "deletenote": "Supprimer la note",
+ "edit": "Note éditée",
+ "new": "Nouvelle note",
+ "savetojobnotes": ""
+ },
+ "errors": {
+ "inserting": ""
+ },
+ "fields": {
+ "createdby": "Créé par",
+ "critical": "Critique",
+ "private": "privé",
+ "text": "Contenu",
+ "type": "",
+ "types": {
+ "customer": "",
+ "general": "",
+ "office": "",
+ "paint": "",
+ "parts": "",
+ "shop": "",
+ "supplement": ""
+ },
+ "updatedat": "Mis à jour à"
+ },
+ "labels": {
+ "addtorelatedro": "",
+ "newnoteplaceholder": "Ajouter une note...",
+ "notetoadd": "",
+ "systemnotes": "",
+ "usernotes": ""
+ },
+ "successes": {
+ "create": "Remarque créée avec succès.",
+ "deleted": "Remarque supprimée avec succès.",
+ "updated": "Remarque mise à jour avec succès."
+ }
+ },
+ "owner": {
+ "labels": {
+ "noownerinfo": ""
+ }
+ },
+ "owners": {
+ "actions": {
+ "update": ""
+ },
+ "errors": {
+ "deleting": "",
+ "noaccess": "L'enregistrement n'existe pas ou vous n'y avez pas accès.",
+ "saving": "",
+ "selectexistingornew": ""
+ },
+ "fields": {
+ "accountingid": "",
+ "address": "Adresse",
+ "allow_text_message": "Autorisation de texte?",
+ "name": "Prénom",
+ "note": "",
+ "ownr_addr1": "Adresse",
+ "ownr_addr2": "Adresse 2 ",
+ "ownr_city": "Ville",
+ "ownr_co_nm": "",
+ "ownr_ctry": "Pays",
+ "ownr_ea": "Email",
+ "ownr_fn": "Prénom",
+ "ownr_ln": "Nom de famille",
+ "ownr_ph1": "Téléphone 1",
+ "ownr_ph2": "",
+ "ownr_st": "Etat / Province",
+ "ownr_title": "Titre",
+ "ownr_zip": "Zip / code postal",
+ "preferred_contact": "Méthode de contact préférée",
+ "tax_number": ""
+ },
+ "forms": {
+ "address": "",
+ "contact": "",
+ "name": ""
+ },
+ "labels": {
+ "create_new": "Créez un nouvel enregistrement de propriétaire.",
+ "deleteconfirm": "",
+ "existing_owners": "Propriétaires existants",
+ "fromclaim": "",
+ "fromowner": "",
+ "relatedjobs": "",
+ "updateowner": ""
+ },
+ "successes": {
+ "delete": "",
+ "save": "Le propriétaire a bien enregistré."
+ }
+ },
+ "parts": {
+ "actions": {
+ "order": "Commander des pièces",
+ "orderinhouse": ""
+ }
+ },
+ "parts_dispatch": {
+ "actions": {
+ "accept": ""
+ },
+ "errors": {
+ "accepting": "",
+ "creating": ""
+ },
+ "fields": {
+ "number": "",
+ "percent_accepted": ""
+ },
+ "labels": {
+ "notyetdispatched": "",
+ "parts_dispatch": ""
+ }
+ },
+ "parts_dispatch_lines": {
+ "fields": {
+ "accepted_at": ""
+ }
+ },
+ "parts_orders": {
+ "actions": {
+ "backordered": "",
+ "receive": "",
+ "receivebill": ""
+ },
+ "errors": {
+ "associatedbills": "",
+ "backordering": "",
+ "creating": "Erreur rencontrée lors de la création de la commande de pièces.",
+ "oec": "",
+ "saving": "",
+ "updating": ""
+ },
+ "fields": {
+ "act_price": "",
+ "backordered_eta": "",
+ "backordered_on": "",
+ "cm_received": "",
+ "comments": "",
+ "cost": "",
+ "db_price": "",
+ "deliver_by": "",
+ "job_line_id": "",
+ "line_desc": "",
+ "line_remarks": "",
+ "lineremarks": "Remarques sur la ligne",
+ "oem_partno": "",
+ "order_date": "",
+ "order_number": "",
+ "orderedby": "",
+ "part_type": "",
+ "quantity": "",
+ "return": "",
+ "status": ""
+ },
+ "labels": {
+ "allpartsto": "",
+ "confirmdelete": "",
+ "custompercent": "",
+ "discount": "",
+ "email": "Envoyé par email",
+ "inthisorder": "Pièces dans cette commande",
+ "is_quote": "",
+ "mark_as_received": "",
+ "newpartsorder": "",
+ "notyetordered": "",
+ "oec": "",
+ "order_type": "",
+ "orderhistory": "Historique des commandes",
+ "parts_order": "",
+ "parts_orders": "",
+ "parts_returns": "",
+ "print": "Afficher le formulaire imprimé",
+ "receive": "",
+ "removefrompartsqueue": "",
+ "returnpartsorder": "",
+ "sublet_order": ""
+ },
+ "successes": {
+ "created": "Commande de pièces créée avec succès.",
+ "line_updated": "",
+ "received": "",
+ "return_created": ""
+ }
+ },
+ "payments": {
+ "actions": {
+ "generatepaymentlink": ""
+ },
+ "errors": {
+ "exporting": "",
+ "exporting-partner": "",
+ "inserting": ""
+ },
+ "fields": {
+ "amount": "",
+ "created_at": "",
+ "date": "",
+ "exportedat": "",
+ "memo": "",
+ "payer": "",
+ "paymentnum": "",
+ "stripeid": "",
+ "transactionid": "",
+ "type": ""
+ },
+ "labels": {
+ "balance": "",
+ "ca_bc_etf_table": "",
+ "customer": "",
+ "edit": "",
+ "electronicpayment": "",
+ "external": "",
+ "findermodal": "",
+ "insurance": "",
+ "markexported": "",
+ "markforreexport": "",
+ "new": "",
+ "signup": "",
+ "smspaymentreminder": "",
+ "title": "",
+ "totalpayments": ""
+ },
+ "successes": {
+ "exported": "",
+ "markexported": "",
+ "markreexported": "",
+ "payment": "",
+ "paymentupdate": "",
+ "stripe": ""
+ }
+ },
+ "phonebook": {
+ "actions": {
+ "new": ""
+ },
+ "errors": {
+ "adding": "",
+ "saving": ""
+ },
+ "fields": {
+ "address1": "",
+ "address2": "",
+ "category": "",
+ "city": "",
+ "company": "",
+ "country": "",
+ "email": "",
+ "fax": "",
+ "firstname": "",
+ "lastname": "",
+ "phone1": "",
+ "phone2": "",
+ "state": ""
+ },
+ "labels": {
+ "noneselected": "",
+ "onenamerequired": "",
+ "vendorcategory": ""
+ },
+ "successes": {
+ "added": "",
+ "deleted": "",
+ "saved": ""
+ }
+ },
+ "printcenter": {
+ "appointments": {
+ "appointment_confirmation": ""
+ },
+ "bills": {
+ "inhouse_invoice": ""
+ },
+ "courtesycarcontract": {
+ "courtesy_car_contract": "",
+ "courtesy_car_impound": "",
+ "courtesy_car_inventory": "",
+ "courtesy_car_terms": ""
+ },
+ "errors": {
+ "nocontexttype": ""
+ },
+ "jobs": {
+ "3rdpartyfields": {
+ "addr1": "",
+ "addr2": "",
+ "addr3": "",
+ "attn": "",
+ "city": "",
+ "custgst": "",
+ "ded_amt": "",
+ "depreciation": "",
+ "other": "",
+ "ponumber": "",
+ "refnumber": "",
+ "sendtype": "",
+ "state": "",
+ "zip": ""
+ },
+ "3rdpartypayer": "",
+ "ab_proof_of_loss": "",
+ "appointment_confirmation": "",
+ "appointment_reminder": "",
+ "casl_authorization": "",
+ "committed_timetickets_ro": "",
+ "coversheet_landscape": "",
+ "coversheet_portrait": "",
+ "csi_invitation": "",
+ "csi_invitation_action": "",
+ "diagnostic_authorization": "",
+ "dms_posting_sheet": "",
+ "envelope_return_address": "",
+ "estimate": "",
+ "estimate_detail": "",
+ "estimate_followup": "",
+ "express_repair_checklist": "",
+ "filing_coversheet_landscape": "",
+ "filing_coversheet_portrait": "",
+ "final_invoice": "",
+ "fippa_authorization": "",
+ "folder_label_multiple": "",
+ "glass_express_checklist": "",
+ "guarantee": "",
+ "individual_job_note": "",
+ "invoice_customer_payable": "",
+ "invoice_total_payable": "",
+ "iou_form": "",
+ "job_costing_ro": "",
+ "job_lifecycle_ro": "",
+ "job_notes": "",
+ "job_tasks": "",
+ "key_tag": "",
+ "labels": {
+ "count": "",
+ "labels": "",
+ "position": ""
+ },
+ "lag_time_ro": "",
+ "mechanical_authorization": "",
+ "mpi_animal_checklist": "",
+ "mpi_eglass_auth": "",
+ "mpi_final_acct_sheet": "",
+ "mpi_final_repair_acct_sheet": "",
+ "paint_grid": "",
+ "parts_dispatch": "",
+ "parts_invoice_label_single": "",
+ "parts_label_multiple": "",
+ "parts_label_single": "",
+ "parts_list": "",
+ "parts_order": "",
+ "parts_order_confirmation": "",
+ "parts_order_history": "",
+ "parts_return_slip": "",
+ "payment_receipt": "",
+ "payment_request": "",
+ "payments_by_job": "",
+ "purchases_by_ro_detail": "",
+ "purchases_by_ro_summary": "",
+ "qc_sheet": "",
+ "rental_reservation": "",
+ "ro_totals": "",
+ "ro_with_description": "",
+ "sgi_certificate_of_repairs": "",
+ "sgi_windshield_auth": "",
+ "stolen_recovery_checklist": "",
+ "sublet_order": "",
+ "supplement_request": "",
+ "thank_you_ro": "",
+ "thirdpartypayer": "",
+ "timetickets_ro": "",
+ "vehicle_check_in": "",
+ "vehicle_delivery_check": "",
+ "window_tag": "",
+ "window_tag_sublet": "",
+ "work_authorization": "",
+ "worksheet_by_line_number": "",
+ "worksheet_sorted_by_operation": "",
+ "worksheet_sorted_by_operation_no_hours": "",
+ "worksheet_sorted_by_operation_part_type": "",
+ "worksheet_sorted_by_operation_type": "",
+ "worksheet_sorted_by_team": ""
+ },
+ "labels": {
+ "groups": {
+ "authorization": "",
+ "financial": "",
+ "post": "",
+ "pre": "",
+ "ro": "",
+ "worksheet": ""
+ },
+ "misc": "",
+ "repairorder": "",
+ "reportcentermodal": "",
+ "speedprint": "",
+ "title": ""
+ },
+ "payments": {
+ "ca_bc_etf_table": "",
+ "exported_payroll": ""
+ },
+ "special": {
+ "attendance_detail_csv": ""
+ },
+ "subjects": {
+ "jobs": {
+ "individual_job_note": "",
+ "parts_dispatch": "",
+ "parts_order": "",
+ "parts_return_slip": "",
+ "sublet_order": ""
+ }
+ },
+ "vendors": {
+ "purchases_by_vendor_detailed": "",
+ "purchases_by_vendor_summary": ""
+ }
+ },
+ "production": {
+ "actions": {
+ "addcolumns": "",
+ "bodypriority-clear": "",
+ "bodypriority-set": "",
+ "detailpriority-clear": "",
+ "detailpriority-set": "",
+ "paintpriority-clear": "",
+ "paintpriority-set": "",
+ "remove": "",
+ "removecolumn": "",
+ "saveconfig": "",
+ "suspend": "",
+ "unsuspend": ""
+ },
+ "constants": {
+ "main_profile": ""
+ },
+ "errors": {
+ "boardupdate": "",
+ "name_exists": "",
+ "name_required": "",
+ "removing": "",
+ "settings": ""
+ },
+ "labels": {
+ "actual_in": "",
+ "addnewprofile": "",
+ "alert": "",
+ "alertoff": "",
+ "alerton": "",
+ "alerts": "",
+ "ats": "",
+ "bodyhours": "",
+ "bodypriority": "",
+ "bodyshop": {
+ "labels": {
+ "qbo_departmentid": "",
+ "qbo_usa": ""
+ }
+ },
+ "card_size": "",
+ "cardcolor": "",
+ "cardsettings": "",
+ "clm_no": "",
+ "comment": "",
+ "compact": "",
+ "detailpriority": "",
+ "employeeassignments": "",
+ "employeesearch": "",
+ "estimator": "",
+ "horizontal": "",
+ "ins_co_nm": "",
+ "jobdetail": "",
+ "kiosk_mode": "",
+ "laborhrs": "",
+ "legend": "",
+ "model_info": "",
+ "note": "",
+ "off": "",
+ "on": "",
+ "orientation": "",
+ "ownr_nm": "",
+ "paintpriority": "",
+ "partsstatus": "",
+ "production_note": "",
+ "refinishhours": "",
+ "scheduled_completion": "",
+ "selectview": "",
+ "stickyheader": "",
+ "sublets": "",
+ "subtotal": "",
+ "tall": "",
+ "tasks": "",
+ "totalhours": "",
+ "touchtime": "",
+ "unassigned": "",
+ "vertical": "",
+ "viewname": "",
+ "wide": ""
+ },
+ "options": {
+ "horizontal": "",
+ "large": "",
+ "medium": "",
+ "small": "",
+ "vertical": ""
+ },
+ "settings": {
+ "board_settings": "",
+ "filters": {
+ "md_estimators": "",
+ "md_ins_cos": ""
+ },
+ "filters_title": "",
+ "information": "",
+ "layout": "",
+ "statistics": {
+ "jobs_in_production": "",
+ "tasks_in_production": "",
+ "tasks_in_view": "",
+ "tasks_on_board": "",
+ "total_amount_in_production": "",
+ "total_amount_in_view": "",
+ "total_amount_on_board": "",
+ "total_hours_in_production": "",
+ "total_hours_in_view": "",
+ "total_hours_on_board": "",
+ "total_jobs_in_view": "",
+ "total_jobs_on_board": "",
+ "total_lab_in_production": "",
+ "total_lab_in_view": "",
+ "total_lab_on_board": "",
+ "total_lar_in_production": "",
+ "total_lar_in_view": "",
+ "total_lar_on_board": ""
+ },
+ "statistics_title": ""
+ },
+ "statistics": {
+ "currency_symbol": "",
+ "hours": "",
+ "jobs": "",
+ "jobs_in_production": "",
+ "tasks": "",
+ "tasks_in_production": "",
+ "tasks_in_view": "",
+ "tasks_on_board": "",
+ "total_amount_in_production": "",
+ "total_amount_in_view": "",
+ "total_amount_on_board": "",
+ "total_hours_in_production": "",
+ "total_hours_in_view": "",
+ "total_hours_on_board": "",
+ "total_jobs_in_view": "",
+ "total_jobs_on_board": "",
+ "total_lab_in_production": "",
+ "total_lab_in_view": "",
+ "total_lab_on_board": "",
+ "total_lar_in_production": "",
+ "total_lar_in_view": "",
+ "total_lar_on_board": ""
+ },
+ "successes": {
+ "removed": ""
+ }
+ },
+ "profile": {
+ "errors": {
+ "state": "Erreur lors de la lecture de l'état de la page. Rafraichissez, s'il vous plait."
+ },
+ "labels": {
+ "activeshop": ""
+ },
+ "successes": {
+ "updated": ""
+ }
+ },
+ "reportcenter": {
+ "actions": {
+ "generate": ""
+ },
+ "labels": {
+ "advanced_filters": "",
+ "advanced_filters_false": "",
+ "advanced_filters_filter_field": "",
+ "advanced_filters_filter_operator": "",
+ "advanced_filters_filter_value": "",
+ "advanced_filters_filters": "",
+ "advanced_filters_hide": "",
+ "advanced_filters_show": "",
+ "advanced_filters_sorter_direction": "",
+ "advanced_filters_sorter_field": "",
+ "advanced_filters_sorters": "",
+ "advanced_filters_true": "",
+ "dates": "",
+ "employee": "",
+ "filterson": "",
+ "generateasemail": "",
+ "groups": {
+ "customers": "",
+ "jobs": "",
+ "payroll": "",
+ "purchases": "",
+ "sales": ""
+ },
+ "key": "",
+ "objects": {
+ "appointments": "",
+ "bills": "",
+ "csi": "",
+ "exportlogs": "",
+ "jobs": "",
+ "parts_orders": "",
+ "payments": "",
+ "scoreboard": "",
+ "tasks": "",
+ "timetickets": ""
+ },
+ "vendor": ""
+ },
+ "templates": {
+ "adp_payroll_flat": "",
+ "adp_payroll_straight": "",
+ "anticipated_revenue": "",
+ "ar_aging": "",
+ "attendance_detail": "",
+ "attendance_employee": "",
+ "attendance_summary": "",
+ "committed_timetickets": "",
+ "committed_timetickets_employee": "",
+ "committed_timetickets_summary": "",
+ "credits_not_received_date": "",
+ "credits_not_received_date_vendorid": "",
+ "csi": "",
+ "customer_list": "",
+ "cycle_time_analysis": "",
+ "estimates_written_converted": "",
+ "estimator_detail": "",
+ "estimator_summary": "",
+ "export_payables": "",
+ "export_payments": "",
+ "export_receivables": "",
+ "exported_gsr_by_ro": "",
+ "exported_gsr_by_ro_labor": "",
+ "gsr_by_atp": "",
+ "gsr_by_ats": "",
+ "gsr_by_category": "",
+ "gsr_by_csr": "",
+ "gsr_by_delivery_date": "",
+ "gsr_by_estimator": "",
+ "gsr_by_exported_date": "",
+ "gsr_by_ins_co": "",
+ "gsr_by_make": "",
+ "gsr_by_referral": "",
+ "gsr_by_ro": "",
+ "gsr_labor_only": "",
+ "hours_sold_detail_closed": "",
+ "hours_sold_detail_closed_csr": "",
+ "hours_sold_detail_closed_estimator": "",
+ "hours_sold_detail_closed_ins_co": "",
+ "hours_sold_detail_closed_status": "",
+ "hours_sold_detail_open": "",
+ "hours_sold_detail_open_csr": "",
+ "hours_sold_detail_open_estimator": "",
+ "hours_sold_detail_open_ins_co": "",
+ "hours_sold_detail_open_status": "",
+ "hours_sold_summary_closed": "",
+ "hours_sold_summary_closed_csr": "",
+ "hours_sold_summary_closed_estimator": "",
+ "hours_sold_summary_closed_ins_co": "",
+ "hours_sold_summary_closed_status": "",
+ "hours_sold_summary_open": "",
+ "hours_sold_summary_open_csr": "",
+ "hours_sold_summary_open_estimator": "",
+ "hours_sold_summary_open_ins_co": "",
+ "hours_sold_summary_open_status": "",
+ "job_costing_ro_csr": "",
+ "job_costing_ro_date_detail": "",
+ "job_costing_ro_date_summary": "",
+ "job_costing_ro_estimator": "",
+ "job_costing_ro_ins_co": "",
+ "job_lifecycle_date_detail": "",
+ "job_lifecycle_date_summary": "",
+ "jobs_completed_not_invoiced": "",
+ "jobs_invoiced_not_exported": "",
+ "jobs_reconcile": "",
+ "jobs_scheduled_completion": "",
+ "lag_time": "",
+ "load_level": "",
+ "lost_sales": "",
+ "open_orders": "",
+ "open_orders_csr": "",
+ "open_orders_estimator": "",
+ "open_orders_excel": "",
+ "open_orders_ins_co": "",
+ "open_orders_referral": "",
+ "open_orders_specific_csr": "",
+ "open_orders_status": "",
+ "parts_backorder": "",
+ "parts_not_recieved": "",
+ "parts_not_recieved_vendor": "",
+ "parts_received_not_scheduled": "",
+ "payments_by_date": "",
+ "payments_by_date_payment": "",
+ "payments_by_date_type": "",
+ "production_by_category": "",
+ "production_by_category_one": "",
+ "production_by_csr": "",
+ "production_by_last_name": "",
+ "production_by_repair_status": "",
+ "production_by_repair_status_one": "",
+ "production_by_ro": "",
+ "production_by_target_date": "",
+ "production_by_technician": "",
+ "production_by_technician_one": "",
+ "production_not_production_status": "",
+ "production_over_time": "",
+ "psr_by_make": "",
+ "purchase_return_ratio_excel": "",
+ "purchase_return_ratio_grouped_by_vendor_detail": "",
+ "purchase_return_ratio_grouped_by_vendor_summary": "",
+ "purchases_by_cost_center_detail": "",
+ "purchases_by_cost_center_summary": "",
+ "purchases_by_date_excel": "",
+ "purchases_by_date_range_detail": "",
+ "purchases_by_date_range_summary": "",
+ "purchases_by_ro_detail_date": "",
+ "purchases_by_ro_summary_date": "",
+ "purchases_by_vendor_detailed_date_range": "",
+ "purchases_by_vendor_summary_date_range": "",
+ "purchases_grouped_by_vendor_detailed": "",
+ "purchases_grouped_by_vendor_summary": "",
+ "returns_grouped_by_vendor_detailed": "",
+ "returns_grouped_by_vendor_summary": "",
+ "schedule": "",
+ "scheduled_parts_list": "",
+ "scoreboard_detail": "",
+ "scoreboard_summary": "",
+ "supplement_ratio_ins_co": "",
+ "tasks_date": "",
+ "tasks_date_employee": "",
+ "thank_you_date": "",
+ "timetickets": "",
+ "timetickets_employee": "",
+ "timetickets_summary": "",
+ "total_loss_jobs": "",
+ "unclaimed_hrs": "",
+ "void_ros": "",
+ "work_in_progress_committed_labour": "",
+ "work_in_progress_jobs": "",
+ "work_in_progress_labour": "",
+ "work_in_progress_payables": ""
+ }
+ },
+ "schedule": {
+ "labels": {
+ "atssummary": "",
+ "employeevacation": "",
+ "estimators": "",
+ "ins_co_nm_filter": "",
+ "intake": "",
+ "manual": "",
+ "manualevent": ""
+ }
+ },
+ "scoreboard": {
+ "actions": {
+ "edit": ""
+ },
+ "errors": {
+ "adding": "",
+ "removing": "",
+ "updating": ""
+ },
+ "fields": {
+ "bodyhrs": "",
+ "date": "",
+ "painthrs": ""
+ },
+ "labels": {
+ "allemployeetimetickets": "",
+ "asoftodaytarget": "",
+ "body": "",
+ "bodyabbrev": "",
+ "bodycharttitle": "",
+ "calendarperiod": "",
+ "combinedcharttitle": "",
+ "dailyactual": "",
+ "dailytarget": "",
+ "efficiencyoverperiod": "",
+ "entries": "",
+ "jobs": "",
+ "jobscompletednotinvoiced": "",
+ "lastmonth": "",
+ "lastweek": "",
+ "monthlytarget": "",
+ "priorweek": "",
+ "productivestatistics": "",
+ "productivetimeticketsoverdate": "",
+ "refinish": "",
+ "refinishabbrev": "",
+ "refinishcharttitle": "",
+ "targets": "",
+ "thismonth": "",
+ "thisweek": "",
+ "timetickets": "",
+ "timeticketsemployee": "",
+ "todateactual": "",
+ "total": "",
+ "totalhrs": "",
+ "totaloverperiod": "",
+ "weeklyactual": "",
+ "weeklytarget": "",
+ "workingdays": ""
+ },
+ "successes": {
+ "added": "",
+ "removed": "",
+ "updated": ""
+ }
+ },
+ "tasks": {
+ "actions": {
+ "edit": "",
+ "new": "",
+ "view": ""
+ },
+ "buttons": {
+ "allTasks": "",
+ "complete": "",
+ "create": "",
+ "delete": "",
+ "edit": "",
+ "myTasks": "",
+ "refresh": ""
+ },
+ "date_presets": {
+ "completion": "",
+ "day": "",
+ "days": "",
+ "delivery": "",
+ "next_week": "",
+ "one_month": "",
+ "three_months": "",
+ "three_weeks": "",
+ "today": "",
+ "tomorrow": "",
+ "two_weeks": ""
+ },
+ "failures": {
+ "completed": "",
+ "created": "",
+ "deleted": "",
+ "updated": ""
+ },
+ "fields": {
+ "actions": "",
+ "assigned_to": "",
+ "bill": "",
+ "billid": "",
+ "completed": "",
+ "created_at": "",
+ "created_by": "",
+ "description": "",
+ "due_date": "",
+ "job": {
+ "ro_number": ""
+ },
+ "jobid": "",
+ "jobline": "",
+ "joblineid": "",
+ "parts_order": "",
+ "partsorderid": "",
+ "priorities": {
+ "high": "",
+ "low": "",
+ "medium": ""
+ },
+ "priority": "",
+ "related_items": "",
+ "remind_at": "",
+ "title": ""
+ },
+ "placeholders": {
+ "assigned_to": "",
+ "billid": "",
+ "description": "",
+ "jobid": "",
+ "joblineid": "",
+ "partsorderid": ""
+ },
+ "successes": {
+ "completed": "",
+ "created": "",
+ "deleted": "",
+ "updated": ""
+ },
+ "titles": {
+ "all_tasks": "",
+ "completed": "",
+ "deleted": "",
+ "job_tasks": "",
+ "mine": "",
+ "my_tasks": ""
+ },
+ "validation": {
+ "due_at_error_message": "",
+ "remind_at_error_message": ""
+ }
+ },
+ "tech": {
+ "fields": {
+ "employeeid": "",
+ "pin": ""
+ },
+ "labels": {
+ "loggedin": "",
+ "notloggedin": ""
+ }
+ },
+ "templates": {
+ "errors": {
+ "updating": ""
+ },
+ "successes": {
+ "updated": ""
+ }
+ },
+ "timetickets": {
+ "actions": {
+ "claimtasks": "",
+ "clockin": "",
+ "clockout": "",
+ "commit": "",
+ "commitone": "",
+ "enter": "",
+ "payall": "",
+ "printemployee": "",
+ "uncommit": ""
+ },
+ "errors": {
+ "clockingin": "",
+ "clockingout": "",
+ "creating": "",
+ "deleting": "",
+ "noemployeeforuser": "",
+ "noemployeeforuser_sub": "",
+ "payall": "",
+ "shiftalreadyclockedon": ""
+ },
+ "fields": {
+ "actualhrs": "",
+ "ciecacode": "",
+ "clockhours": "",
+ "clockoff": "",
+ "clockon": "",
+ "committed": "",
+ "committed_at": "",
+ "cost_center": "",
+ "created_by": "",
+ "date": "",
+ "efficiency": "",
+ "employee": "",
+ "employee_team": "",
+ "flat_rate": "",
+ "memo": "",
+ "productivehrs": "",
+ "ro_number": "",
+ "task_name": ""
+ },
+ "labels": {
+ "alreadyclockedon": "",
+ "ambreak": "",
+ "amshift": "",
+ "claimtaskpreview": "",
+ "clockhours": "",
+ "clockintojob": "",
+ "deleteconfirm": "",
+ "edit": "",
+ "efficiency": "",
+ "flat_rate": "",
+ "jobhours": "",
+ "lunch": "",
+ "new": "",
+ "payrollclaimedtasks": "",
+ "pmbreak": "",
+ "pmshift": "",
+ "shift": "",
+ "shiftalreadyclockedon": "",
+ "straight_time": "",
+ "task": "",
+ "timetickets": "",
+ "unassigned": "",
+ "zeroactualnegativeprod": ""
+ },
+ "successes": {
+ "clockedin": "",
+ "clockedout": "",
+ "committed": "",
+ "created": "",
+ "deleted": "",
+ "payall": ""
+ },
+ "validation": {
+ "clockoffmustbeafterclockon": "",
+ "clockoffwithoutclockon": "",
+ "hoursenteredmorethanavailable": "",
+ "unassignedlines": ""
+ }
+ },
+ "titles": {
+ "accounting-payables": "",
+ "accounting-payments": "",
+ "accounting-receivables": "",
+ "all_tasks": "",
+ "app": "",
+ "bc": {
+ "accounting-payables": "",
+ "accounting-payments": "",
+ "accounting-receivables": "",
+ "all_tasks": "",
+ "availablejobs": "",
+ "bills-list": "",
+ "contracts": "",
+ "contracts-create": "",
+ "contracts-detail": "",
+ "courtesycars": "",
+ "courtesycars-detail": "",
+ "courtesycars-new": "",
+ "dashboard": "",
+ "dms": "",
+ "export-logs": "",
+ "inventory": "",
+ "jobs": "",
+ "jobs-active": "",
+ "jobs-admin": "",
+ "jobs-all": "",
+ "jobs-checklist": "",
+ "jobs-close": "",
+ "jobs-deliver": "",
+ "jobs-detail": "",
+ "jobs-intake": "",
+ "jobs-new": "",
+ "jobs-ready": "",
+ "my_tasks": "",
+ "owner-detail": "",
+ "owners": "",
+ "parts-queue": "",
+ "payments-all": "",
+ "phonebook": "",
+ "productionboard": "",
+ "productionlist": "",
+ "profile": "",
+ "schedule": "",
+ "scoreboard": "",
+ "shop": "",
+ "shop-csi": "",
+ "shop-templates": "",
+ "shop-vendors": "",
+ "tasks": "",
+ "temporarydocs": "",
+ "timetickets": "",
+ "ttapprovals": "",
+ "vehicle-details": "",
+ "vehicles": ""
+ },
+ "bills-list": "",
+ "contracts": "",
+ "contracts-create": "",
+ "contracts-detail": "",
+ "courtesycars": "",
+ "courtesycars-create": "",
+ "courtesycars-detail": "",
+ "dashboard": "",
+ "dms": "",
+ "export-logs": "",
+ "imexonline": "",
+ "inventory": "",
+ "jobs": "Tous les emplois | {{app}}",
+ "jobs-admin": "",
+ "jobs-all": "",
+ "jobs-checklist": "",
+ "jobs-close": "",
+ "jobs-create": "",
+ "jobs-deliver": "",
+ "jobs-intake": "",
+ "jobsavailable": "Emplois disponibles | {{app}}",
+ "jobsdetail": "Travail {{ro_number}} | {{app}}",
+ "jobsdocuments": "Documents de travail {{ro_number}} | {{app}}",
+ "manageroot": "Accueil | {{app}}",
+ "my_tasks": "",
+ "owners": "Tous les propriétaires | {{app}}",
+ "owners-detail": "",
+ "parts-queue": "",
+ "payments-all": "",
+ "phonebook": "",
+ "productionboard": "",
+ "productionlist": "",
+ "profile": "Mon profil | {{app}}",
+ "readyjobs": "",
+ "resetpassword": "",
+ "resetpasswordvalidate": "",
+ "romeonline": "",
+ "schedule": "Horaire | {{app}}",
+ "scoreboard": "",
+ "shop": "Mon magasin | {{app}}",
+ "shop-csi": "",
+ "shop-templates": "",
+ "shop_vendors": "Vendeurs | {{app}}",
+ "tasks": "",
+ "techconsole": "{{app}}",
+ "techjobclock": "{{app}}",
+ "techjoblookup": "{{app}}",
+ "techshiftclock": "{{app}}",
+ "temporarydocs": "",
+ "timetickets": "",
+ "ttapprovals": "",
+ "vehicledetail": "Détails du véhicule {{vehicle} | {{app}}",
+ "vehicles": "Tous les véhicules | {{app}}"
+ },
+ "trello": {
+ "labels": {
+ "add_card": "",
+ "add_lane": "",
+ "cancel": "",
+ "delete_lane": "",
+ "description": "",
+ "label": "",
+ "lane_actions": "",
+ "title": ""
+ }
+ },
+ "tt_approvals": {
+ "actions": {
+ "approveselected": ""
+ },
+ "labels": {
+ "approval_queue_in_use": "",
+ "calculate": ""
+ }
+ },
+ "upsell": {
+ "cta": {
+ "learnmore": ""
+ },
+ "messages": {
+ "accounting": {
+ "payables": {
+ "subtitle": "",
+ "title": ""
+ },
+ "payments": {
+ "subtitle": "",
+ "title": ""
+ },
+ "receivables": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "audit": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "bills": {
+ "autoreconcile": {
+ "subtitle": "",
+ "title": ""
+ },
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "checklist": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "courtesycars": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "csi": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "dashboard": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "lifecycle": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "media": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ },
+ "mobile": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "payments": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "scoreboard": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "smartscheduling": {
+ "datepicker": {
+ "subtitle": "",
+ "title": ""
+ },
+ "general": {
+ "subtitle": "",
+ "title": ""
+ },
+ "hrsdelta": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "techconsole": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "timetickets": {
+ "allocations": {
+ "subtitle": "",
+ "title": ""
+ },
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ },
+ "visualboard": {
+ "general": {
+ "subtitle": "",
+ "title": ""
+ }
+ }
+ }
+ },
+ "user": {
+ "actions": {
+ "changepassword": "",
+ "signout": "Déconnexion",
+ "updateprofile": "Mettre à jour le profil"
+ },
+ "errors": {
+ "updating": ""
+ },
+ "fields": {
+ "authlevel": "",
+ "displayname": "Afficher un nom",
+ "email": "",
+ "photourl": "URL de l'avatar"
+ },
+ "labels": {
+ "actions": "",
+ "changepassword": "",
+ "profileinfo": ""
+ },
+ "successess": {
+ "passwordchanged": ""
+ }
+ },
+ "users": {
+ "errors": {
+ "signinerror": {
+ "auth/user-disabled": "",
+ "auth/user-not-found": "",
+ "auth/wrong-password": ""
+ }
+ }
+ },
+ "vehicles": {
+ "errors": {
+ "deleting": "",
+ "noaccess": "Le véhicule n'existe pas ou vous n'y avez pas accès.",
+ "selectexistingornew": "",
+ "validation": "Veuillez vous assurer que tous les champs sont correctement entrés.",
+ "validationtitle": "Erreur de validation"
+ },
+ "fields": {
+ "description": "Description du véhicule",
+ "notes": "",
+ "plate_no": "Plaque d'immatriculation",
+ "plate_st": "Juridiction de la plaque",
+ "trim_color": "Couleur de garniture",
+ "v_bstyle": "Style corporel",
+ "v_color": "Couleur",
+ "v_cond": "Etat",
+ "v_engine": "moteur",
+ "v_make_desc": "Faire",
+ "v_makecode": "Faire du code",
+ "v_mldgcode": "Code de moulage",
+ "v_model_desc": "Modèle",
+ "v_model_yr": "année",
+ "v_options": "Les options",
+ "v_paint_codes": "Codes de peinture",
+ "v_prod_dt": "Date de production",
+ "v_stage": "Étape",
+ "v_tone": "ton",
+ "v_trimcode": "Code de coupe",
+ "v_type": "Type",
+ "v_vin": "V.I.N."
+ },
+ "forms": {
+ "detail": "",
+ "misc": "",
+ "registration": ""
+ },
+ "labels": {
+ "deleteconfirm": "",
+ "fromvehicle": "",
+ "novehinfo": "",
+ "relatedjobs": "",
+ "updatevehicle": ""
+ },
+ "successes": {
+ "delete": "",
+ "save": "Le véhicule a été enregistré avec succès."
+ }
+ },
+ "vendors": {
+ "actions": {
+ "addtophonebook": "",
+ "new": "Nouveau vendeur",
+ "newpreferredmake": ""
+ },
+ "errors": {
+ "deleting": "Erreur rencontrée lors de la suppression du fournisseur.",
+ "saving": "Erreur rencontrée lors de l'enregistrement du fournisseur."
+ },
+ "fields": {
+ "active": "",
+ "am": "",
+ "city": "Ville",
+ "cost_center": "Centre de coûts",
+ "country": "Pays",
+ "discount": "Remise %",
+ "display_name": "Afficher un nom",
+ "dmsid": "",
+ "due_date": "Date limite de paiement",
+ "email": "Email du contact",
+ "favorite": "Préféré?",
+ "lkq": "",
+ "make": "",
+ "name": "Nom du vendeur",
+ "oem": "",
+ "phone": "",
+ "prompt_discount": "Remise rapide%",
+ "state": "Etat / Province",
+ "street1": "rue",
+ "street2": "Adresse 2 ",
+ "taxid": "Identifiant de taxe",
+ "terms": "Modalités de paiement",
+ "zip": "Zip / code postal"
+ },
+ "labels": {
+ "noneselected": "Aucun fournisseur n'est sélectionné.",
+ "preferredmakes": "",
+ "search": "Tapez le nom d'un vendeur"
+ },
+ "successes": {
+ "deleted": "Le fournisseur a bien été supprimé.",
+ "saved": "Le fournisseur a bien enregistré."
+ },
+ "validation": {
+ "unique_vendor_name": ""
+ }
+ },
+ "notifications": {
+ "labels": {
+ "notification-center": "",
+ "scenario": "",
+ "notificationscenarios": "",
+ "save": "",
+ "watching-issue": "",
+ "add-watchers": "",
+ "employee-search": "",
+ "teams-search": "",
+ "add-watchers-team": "",
+ "new-notification-title": "",
+ "show-unread-only": "",
+ "mark-all-read": "",
+ "notification-popup-title": "",
+ "ro-number": "",
+ "no-watchers": "",
+ "notification-settings-success": "",
+ "notification-settings-failure": "",
+ "watch": "",
+ "unwatch": ""
+ },
+ "actions": {
+ "remove": ""
+ },
+ "aria": {
+ "toggle": ""
+ },
+ "tooltips": {
+ "job-watchers": ""
+ },
+ "scenarios": {
+ "job-assigned-to-me": "",
+ "bill-posted": "",
+ "critical-parts-status-changed": "",
+ "part-marked-back-ordered": "",
+ "new-note-added": "",
+ "supplement-imported": "",
+ "schedule-dates-changed": "",
+ "tasks-updated-created": "",
+ "new-media-added-reassigned": "",
+ "new-time-ticket-posted": "",
+ "intake-delivery-checklist-completed": "",
+ "job-added-to-production": "",
+ "job-status-change": "",
+ "payment-collected-completed": "",
+ "alternate-transport-changed": ""
+ },
+ "channels": {
+ "app": "",
+ "email": "",
+ "fcm": ""
+ }
+ }
+ }
}
diff --git a/client/src/utils/GraphQLClient.js b/client/src/utils/GraphQLClient.js
index 689083139..ce1b6b436 100644
--- a/client/src/utils/GraphQLClient.js
+++ b/client/src/utils/GraphQLClient.js
@@ -7,9 +7,9 @@ import { getMainDefinition } from "@apollo/client/utilities";
//import { split } from "apollo-link";
import apolloLogger from "apollo-link-logger";
//import axios from "axios";
+import { SentryLink } from "apollo-link-sentry";
import { auth } from "../firebase/firebase.utils";
import errorLink from "../graphql/apollo-error-handling";
-import { SentryLink } from "apollo-link-sentry";
//import { store } from "../redux/store";
const httpLink = new HttpLink({
@@ -143,7 +143,41 @@ middlewares.push(
new SentryLink().concat(roundTripLink.concat(retryLink.concat(errorLink.concat(authLink.concat(link)))))
);
-const cache = new InMemoryCache({});
+const cache = new InMemoryCache({
+ typePolicies: {
+ Query: {
+ fields: {
+ // Note: This is required because we switch from a read to an unread state with a toggle,
+ notifications: {
+ merge(existing = [], incoming = [], { readField }) {
+ // Create a map to deduplicate by __ref
+ const merged = new Map();
+
+ // Add existing items to retain cached data
+ existing.forEach((item) => {
+ const ref = readField("__ref", item);
+ if (ref) {
+ merged.set(ref, item);
+ }
+ });
+
+ // Add incoming items, overwriting duplicates
+ incoming.forEach((item) => {
+ const ref = readField("__ref", item);
+ if (ref) {
+ merged.set(ref, item);
+ }
+ });
+
+ // Return incoming to respect the current query’s filter (e.g., unread-only or all)
+ return incoming;
+ }
+ }
+ }
+ }
+ }
+});
+
const client = new ApolloClient({
link: ApolloLink.from(middlewares),
cache,
@@ -163,4 +197,5 @@ const client = new ApolloClient({
}
}
});
+
export default client;
diff --git a/client/src/utils/jobNotificationScenarios.js b/client/src/utils/jobNotificationScenarios.js
new file mode 100644
index 000000000..aeab82861
--- /dev/null
+++ b/client/src/utils/jobNotificationScenarios.js
@@ -0,0 +1,23 @@
+/** Notification Scenarios
+ * @description This file contains the scenarios for job notifications.
+ * @type {string[]}
+ */
+const notificationScenarios = [
+ "job-assigned-to-me",
+ "bill-posted",
+ "critical-parts-status-changed",
+ "part-marked-back-ordered",
+ "new-note-added",
+ "schedule-dates-changed",
+ "tasks-updated-created",
+ "new-media-added-reassigned",
+ "new-time-ticket-posted",
+ "intake-delivery-checklist-completed",
+ "job-added-to-production",
+ "job-status-change",
+ "payment-collected-completed",
+ "alternate-transport-changed"
+ // "supplement-imported", // Disabled for now
+];
+
+export { notificationScenarios };
diff --git a/client/src/utils/sentry.js b/client/src/utils/sentry.js
new file mode 100644
index 000000000..d1152d773
--- /dev/null
+++ b/client/src/utils/sentry.js
@@ -0,0 +1,63 @@
+import * as Sentry from "@sentry/react";
+import { excludeGraphQLFetch } from "apollo-link-sentry";
+import { useEffect } from "react";
+import { createRoutesFromChildren, matchRoutes, useLocation, useNavigationType } from "react-router-dom";
+import InstanceRenderManager from "./instanceRenderMgr";
+
+const currentDatePST = new Date()
+ .toLocaleDateString("en-US", {
+ timeZone: "America/Los_Angeles",
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit"
+ })
+ .split("/")
+ .reverse()
+ .join("-");
+const sentryRelease =
+ `${import.meta.env.VITE_APP_IS_TEST ? "test" : "production"}-${currentDatePST}-${process.env.VITE_GIT_COMMIT_HASH}`.trim();
+
+if (!import.meta.env.DEV) {
+ Sentry.init({
+ dsn: InstanceRenderManager({
+ imex: "https://fd7e89369b6b4bdc9c6c4c9f22fa4ee4@o492140.ingest.sentry.io/5651027",
+ rome: "https://a6acc91c073e414196014b8484627a61@o492140.ingest.sentry.io/4504561071161344"
+ }),
+ release: sentryRelease,
+
+ ignoreErrors: [
+ "ResizeObserver loop",
+ "ResizeObserver loop limit exceeded",
+ "Module specifier, 'fs' does not start",
+ "Module specifier, 'zlib' does not start with",
+ "Messaging: This browser doesn't support the API's required to use the Firebase SDK.",
+ "Failed to update a ServiceWorker for scope"
+ ],
+ integrations: [
+ // See docs for support of different versions of variation of react router
+ // https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router/
+ Sentry.reactRouterV6BrowserTracingIntegration({
+ useEffect,
+ useLocation,
+ useNavigationType,
+ createRoutesFromChildren,
+ matchRoutes
+ }),
+ Sentry.replayIntegration(),
+ Sentry.browserProfilingIntegration()
+ ],
+
+ tracePropagationTargets: [
+ "api.imex.online",
+ "api.test.imex.online",
+ "db.imex.online",
+ "api.romeonline.io",
+ "api.test.romeonline.io",
+ "db.romeonline.io"
+ ],
+ tracesSampleRate: 1.0,
+ replaysOnErrorSampleRate: 1.0,
+ environment: import.meta.env.MODE,
+ beforeBreadcrumb: excludeGraphQLFetch
+ });
+}
diff --git a/client/vite.config.js b/client/vite.config.js
index 0882c1e3a..6aed665ef 100644
--- a/client/vite.config.js
+++ b/client/vite.config.js
@@ -1,16 +1,31 @@
+import { sentryVitePlugin } from "@sentry/vite-plugin";
import react from "@vitejs/plugin-react";
+import chalk from "chalk";
+import * as child from "child_process";
import { promises as fsPromises } from "fs";
import { createLogger, defineConfig } from "vite";
import { ViteEjsPlugin } from "vite-plugin-ejs";
import eslint from "vite-plugin-eslint";
import { VitePWA } from "vite-plugin-pwa";
import InstanceRenderManager from "./src/utils/instanceRenderMgr";
-import chalk from "chalk";
// Ensure your environment variables are set correctly for Vite 6
process.env.VITE_APP_GIT_SHA_DATE = new Date().toLocaleString("en-US", {
timeZone: "America/Los_Angeles"
});
+const commitHash = child.execSync("git rev-parse HEAD").toString().trimEnd();
+process.env.VITE_GIT_COMMIT_HASH = commitHash;
+
+const currentDatePST = new Date()
+ .toLocaleDateString("en-US", {
+ timeZone: "America/Los_Angeles",
+ year: "numeric",
+ month: "2-digit",
+ day: "2-digit"
+ })
+ .split("/")
+ .reverse()
+ .join("-");
const getFormattedTimestamp = () =>
new Date().toLocaleTimeString("en-US", { hour12: true }).replace("AM", "a.m.").replace("PM", "p.m.");
@@ -78,10 +93,25 @@ export default defineConfig({
}
}),
react(),
- eslint()
+ eslint(),
+ sentryVitePlugin({
+ org: "imex",
+ reactComponentAnnotation: {
+ enabled: true
+ },
+ release: {
+ name: `${process.env.VITE_APP_IS_TEST ? "test" : "production"}-${currentDatePST}-${commitHash}`.trim()
+ },
+ project: InstanceRenderManager({
+ instance: process.env.VITE_APP_INSTANCE,
+ imex: "imexonline",
+ rome: "rome-online"
+ })
+ })
],
define: {
- APP_VERSION: JSON.stringify(process.env.npm_package_version)
+ APP_VERSION: JSON.stringify(process.env.npm_package_version),
+ __COMMIT_HASH__: JSON.stringify(commitHash)
},
server: {
host: true,
@@ -161,30 +191,19 @@ export default defineConfig({
"@sentry/react": ["@sentry/react"],
"@splitsoftware/splitio-react": ["@splitsoftware/splitio-react"],
logrocket: ["logrocket"],
- "firebase/app": ["firebase/app"],
- "firebase/firestore": ["firebase/firestore"],
- "firebase/firestore/lite": ["firebase/firestore/lite"],
- "firebase/auth": ["firebase/auth"],
- "firebase/functions": ["firebase/functions"],
- "firebase/storage": ["firebase/storage"],
- "firebase/database": ["firebase/database"],
- "firebase/remote-config": ["firebase/remote-config"],
- "firebase/performance": ["firebase/performance"],
+ "@firebase/analytics": ["@firebase/analytics"],
"@firebase/app": ["@firebase/app"],
"@firebase/firestore": ["@firebase/firestore"],
- "@firebase/firestore/lite": ["@firebase/firestore/lite"],
"@firebase/auth": ["@firebase/auth"],
- "@firebase/functions": ["@firebase/functions"],
- "@firebase/storage": ["@firebase/storage"],
- "@firebase/database": ["@firebase/database"],
- "@firebase/remote-config": ["@firebase/remote-config"],
- "@firebase/performance": ["@firebase/performance"],
+ "@firebase/messaging": ["@firebase/messaging"],
markerjs2: ["markerjs2"],
"@apollo/client": ["@apollo/client"],
"libphonenumber-js": ["libphonenumber-js"]
}
}
- }
+ },
+
+ sourcemap: true
},
optimizeDeps: {
include: [
diff --git a/docker-compose-cluster.yml b/docker-compose-cluster.yml
new file mode 100644
index 000000000..86defaf50
--- /dev/null
+++ b/docker-compose-cluster.yml
@@ -0,0 +1,221 @@
+services:
+ # Load Balancer (NGINX) with WebSocket support and session persistence
+ load-balancer:
+ image: nginx:latest
+ container_name: load-balancer
+ ports:
+ - "4000:80" # External port 4000 maps to NGINX's port 80
+ volumes:
+ - ./nginx-websocket.conf:/etc/nginx/nginx.conf:ro # Mount NGINX configuration
+ networks:
+ - redis-cluster-net
+ depends_on:
+ - node-app-1
+ - node-app-2
+ - node-app-3
+ healthcheck:
+ test: [ "CMD", "curl", "-f", "http://localhost/health" ]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+
+ # Node App Instance 1
+ node-app-1:
+ build:
+ context: .
+ container_name: node-app-1
+ hostname: node-app-1
+ networks:
+ - redis-cluster-net
+ env_file:
+ - .env.development
+ depends_on:
+ redis-node-1:
+ condition: service_healthy
+ redis-node-2:
+ condition: service_healthy
+ redis-node-3:
+ condition: service_healthy
+ localstack:
+ condition: service_healthy
+ aws-cli:
+ condition: service_completed_successfully
+ ports:
+ - "4001:4000" # Different external port for local access
+ volumes:
+ - .:/app
+ - node-app-npm-cache:/app/node_modules
+
+ # Node App Instance 2
+ node-app-2:
+ build:
+ context: .
+ container_name: node-app-2
+ hostname: node-app-2
+ networks:
+ - redis-cluster-net
+ env_file:
+ - .env.development
+ depends_on:
+ redis-node-1:
+ condition: service_healthy
+ redis-node-2:
+ condition: service_healthy
+ redis-node-3:
+ condition: service_healthy
+ localstack:
+ condition: service_healthy
+ aws-cli:
+ condition: service_completed_successfully
+ ports:
+ - "4002:4000" # Different external port for local access
+ volumes:
+ - .:/app
+ - node-app-npm-cache:/app/node_modules
+
+ # Node App Instance 3
+ node-app-3:
+ build:
+ context: .
+ container_name: node-app-3
+ hostname: node-app-3
+ networks:
+ - redis-cluster-net
+ env_file:
+ - .env.development
+ depends_on:
+ redis-node-1:
+ condition: service_healthy
+ redis-node-2:
+ condition: service_healthy
+ redis-node-3:
+ condition: service_healthy
+ localstack:
+ condition: service_healthy
+ aws-cli:
+ condition: service_completed_successfully
+ ports:
+ - "4003:4000" # Different external port for local access
+ volumes:
+ - .:/app
+ - node-app-npm-cache:/app/node_modules
+
+ # Redis Node 1
+ redis-node-1:
+ build:
+ context: ./redis
+ container_name: redis-node-1
+ hostname: redis-node-1
+ restart: unless-stopped
+ networks:
+ - redis-cluster-net
+ volumes:
+ - redis-node-1-data:/data
+ - redis-lock:/redis-lock
+ healthcheck:
+ test: [ "CMD", "redis-cli", "ping" ]
+ interval: 10s
+ timeout: 5s
+ retries: 10
+
+ # Redis Node 2
+ redis-node-2:
+ build:
+ context: ./redis
+ container_name: redis-node-2
+ hostname: redis-node-2
+ restart: unless-stopped
+ networks:
+ - redis-cluster-net
+ volumes:
+ - redis-node-2-data:/data
+ - redis-lock:/redis-lock
+ healthcheck:
+ test: [ "CMD", "redis-cli", "ping" ]
+ interval: 10s
+ timeout: 5s
+ retries: 10
+
+ # Redis Node 3
+ redis-node-3:
+ build:
+ context: ./redis
+ container_name: redis-node-3
+ hostname: redis-node-3
+ restart: unless-stopped
+ networks:
+ - redis-cluster-net
+ volumes:
+ - redis-node-3-data:/data
+ - redis-lock:/redis-lock
+ healthcheck:
+ test: [ "CMD", "redis-cli", "ping" ]
+ interval: 10s
+ timeout: 5s
+ retries: 10
+
+ # LocalStack
+ localstack:
+ image: localstack/localstack
+ container_name: localstack
+ hostname: localstack
+ networks:
+ - redis-cluster-net
+ restart: unless-stopped
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ environment:
+ - SERVICES=s3,ses,secretsmanager,cloudwatch,logs
+ - DEBUG=0
+ - AWS_ACCESS_KEY_ID=test
+ - AWS_SECRET_ACCESS_KEY=test
+ - AWS_DEFAULT_REGION=ca-central-1
+ - EXTRA_CORS_ALLOWED_HEADERS=Authorization,Content-Type
+ - EXTRA_CORS_ALLOWED_ORIGINS=*
+ - EXTRA_CORS_EXPOSE_HEADERS=Authorization,Content-Type
+ ports:
+ - "4566:4566"
+ healthcheck:
+ test: [ "CMD", "curl", "-f", "http://localhost:4566/_localstack/health" ]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ start_period: 20s
+
+ # AWS-CLI
+ aws-cli:
+ image: amazon/aws-cli
+ container_name: aws-cli
+ hostname: aws-cli
+ networks:
+ - redis-cluster-net
+ depends_on:
+ localstack:
+ condition: service_healthy
+ volumes:
+ - './localstack:/tmp/localstack'
+ - './certs:/tmp/certs'
+ environment:
+ - AWS_ACCESS_KEY_ID=test
+ - AWS_SECRET_ACCESS_KEY=test
+ - AWS_DEFAULT_REGION=ca-central-1
+ entrypoint: /bin/sh -c
+ command: >
+ "
+ aws --endpoint-url=http://localstack:4566 ses verify-domain-identity --domain imex.online --region ca-central-1
+ aws --endpoint-url=http://localstack:4566 ses verify-email-identity --email-address noreply@imex.online --region ca-central-1
+ aws --endpoint-url=http://localstack:4566 secretsmanager create-secret --name CHATTER_PRIVATE_KEY --secret-string file:///tmp/certs/io-ftp-test.key
+ aws --endpoint-url=http://localstack:4566 logs create-log-group --log-group-name development --region ca-central-1
+ aws --endpoint-url=http://localstack:4566 s3api create-bucket --bucket imex-large-log --create-bucket-configuration LocationConstraint=ca-central-1
+ "
+
+networks:
+ redis-cluster-net:
+ driver: bridge
+
+volumes:
+ node-app-npm-cache:
+ redis-node-1-data:
+ redis-node-2-data:
+ redis-node-3-data:
+ redis-lock:
diff --git a/hasura/metadata/cron_triggers.yaml b/hasura/metadata/cron_triggers.yaml
index f22b1da58..2b504e492 100644
--- a/hasura/metadata/cron_triggers.yaml
+++ b/hasura/metadata/cron_triggers.yaml
@@ -31,14 +31,6 @@
headers:
- name: x-imex-auth
value_from_env: DATAPUMP_AUTH
-- name: Task Reminders
- webhook: '{{HASURA_API_URL}}/tasks-remind-handler'
- schedule: '*/15 * * * *'
- include_in_metadata: true
- payload: {}
- headers:
- - name: event-secret
- value_from_env: EVENT_SECRET
- name: Rome Usage Report
webhook: '{{HASURA_API_URL}}/data/usagereport'
schedule: 0 12 * * 5
@@ -47,3 +39,11 @@
headers:
- name: x-imex-auth
value_from_env: DATAPUMP_AUTH
+- name: Task Reminders
+ webhook: '{{HASURA_API_URL}}/tasks-remind-handler'
+ schedule: '*/15 * * * *'
+ include_in_metadata: true
+ payload: {}
+ headers:
+ - name: event-secret
+ value_from_env: EVENT_SECRET
diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml
index 4a9416781..4d1f5192e 100644
--- a/hasura/metadata/tables.yaml
+++ b/hasura/metadata/tables.yaml
@@ -198,6 +198,14 @@
- name: user
using:
foreign_key_constraint_on: useremail
+ array_relationships:
+ - name: notifications
+ using:
+ foreign_key_constraint_on:
+ column: associationid
+ table:
+ name: notifications
+ schema: public
select_permissions:
- role: user
permission:
@@ -697,12 +705,6 @@
- name: event-secret
value_from_env: EVENT_SECRET
request_transform:
- body:
- action: transform
- template: |-
- {
- "success": true
- }
method: POST
query_params: {}
template_engine: Kriti
@@ -1133,6 +1135,46 @@
- active:
_eq: true
check: null
+ event_triggers:
+ - name: cache_bodyshop
+ definition:
+ enable_manual: false
+ update:
+ columns:
+ - shopname
+ - md_order_statuses
+ retry_conf:
+ interval_sec: 10
+ num_retries: 0
+ timeout_sec: 60
+ webhook_from_env: HASURA_API_URL
+ headers:
+ - name: event-secret
+ value_from_env: EVENT_SECRET
+ request_transform:
+ body:
+ action: transform
+ template: |-
+ {
+ "created_at": {{$body.created_at}},
+ "delivery_info": {{$body.delivery_info}},
+ "event": {
+ "data": {
+ "new": {
+ "id": {{$body.event.data.new.id}},
+ "shopname": {{$body.event.data.new.shopname}},
+ "md_order_statuses": {{$body.event.data.new.md_order_statuses}}
+ }
+ },
+ "op": {{$body.event.op}},
+ "session_variables": {{$body.event.session_variables}}
+ }
+ }
+ method: POST
+ query_params: {}
+ template_engine: Kriti
+ url: '{{$base_url}}/bodyshop-cache'
+ version: 2
- table:
name: cccontracts
schema: public
@@ -1958,6 +2000,29 @@
_eq: X-Hasura-User-Id
- active:
_eq: true
+ event_triggers:
+ - name: notifications_documents
+ definition:
+ enable_manual: false
+ insert:
+ columns: '*'
+ update:
+ columns:
+ - jobid
+ retry_conf:
+ interval_sec: 10
+ num_retries: 0
+ timeout_sec: 60
+ webhook_from_env: HASURA_API_URL
+ headers:
+ - name: event-secret
+ value_from_env: EVENT_SECRET
+ request_transform:
+ method: POST
+ query_params: {}
+ template_engine: Kriti
+ url: '{{$base_url}}/notifications/events/handleDocumentsChange'
+ version: 2
- table:
name: email_audit_trail
schema: public
@@ -2846,13 +2911,12 @@
- role: user
permission:
check:
- user:
- _and:
- - associations:
- active:
- _eq: true
- - authid:
- _eq: X-Hasura-User-Id
+ job:
+ bodyshop:
+ associations:
+ user:
+ authid:
+ _eq: X-Hasura-User-Id
columns:
- user_email
- created_at
@@ -2868,13 +2932,12 @@
- id
- jobid
filter:
- user:
- _and:
- - associations:
- active:
- _eq: true
- - authid:
- _eq: X-Hasura-User-Id
+ job:
+ bodyshop:
+ associations:
+ user:
+ authid:
+ _eq: X-Hasura-User-Id
comment: ""
update_permissions:
- role: user
@@ -2885,26 +2948,24 @@
- id
- jobid
filter:
- user:
- _and:
- - associations:
- active:
- _eq: true
- - authid:
- _eq: X-Hasura-User-Id
+ job:
+ bodyshop:
+ associations:
+ user:
+ authid:
+ _eq: X-Hasura-User-Id
check: null
comment: ""
delete_permissions:
- role: user
permission:
filter:
- user:
- _and:
- - associations:
- active:
- _eq: true
- - authid:
- _eq: X-Hasura-User-Id
+ job:
+ bodyshop:
+ associations:
+ user:
+ authid:
+ _eq: X-Hasura-User-Id
comment: ""
- table:
name: joblines
@@ -3223,6 +3284,31 @@
_eq: X-Hasura-User-Id
- active:
_eq: true
+ event_triggers:
+ - name: notifications_joblines
+ definition:
+ enable_manual: false
+ update:
+ columns:
+ - critical
+ - status
+ retry_conf:
+ interval_sec: 10
+ num_retries: 0
+ timeout_sec: 60
+ webhook_from_env: HASURA_API_URL
+ headers:
+ - name: event-secret
+ value_from_env: EVENT_SECRET
+ request_transform:
+ body:
+ action: transform
+ template: "{\r\n \"event\": {\r\n \"session_variables\": {\r\n \"x-hasura-user-id\": {{$body?.event?.session_variables?.x-hasura-user-id ?? \"Internal\"}},\r\n \"x-hasura-role\": {{$body?.event?.session_variables?.x-hasura-role ?? \"Internal\"}}\r\n }, \r\n \"op\": \"UPDATE\",\r\n \"data\": {\r\n \"old\": {\r\n \"id\": {{$body.event.data.old.id}},\r\n \"jobid\": {{$body.event.data.old.jobid}},\r\n \"critical\": {{$body.event.data.old.critical}},\r\n \"status\": {{$body.event.data.old.status}},\r\n \"line_desc\": {{$body.event.data.old.line_desc}}\r\n },\r\n \"new\": {\r\n \"id\": {{$body.event.data.new.id}},\r\n \"jobid\": {{$body.event.data.new.jobid}},\r\n \"critical\": {{$body.event.data.new.critical}},\r\n \"status\": {{$body.event.data.new.status}},\r\n \"line_desc\": {{$body.event.data.new.line_desc}}\r\n }\r\n }\r\n },\r\n \"trigger\": {\r\n \"name\": \"notifications_joblines\"\r\n },\r\n \"table\": {\r\n \"schema\": \"public\",\r\n \"name\": \"joblines\"\r\n }\r\n}\r\n"
+ method: POST
+ query_params: {}
+ template_engine: Kriti
+ url: '{{$base_url}}/notifications/events/handleJobLinesChange'
+ version: 2
- table:
name: joblines_status
schema: public
@@ -3369,6 +3455,13 @@
table:
name: job_conversations
schema: public
+ - name: job_watchers
+ using:
+ foreign_key_constraint_on:
+ column: jobid
+ table:
+ name: job_watchers
+ schema: public
- name: joblines
using:
foreign_key_constraint_on:
@@ -3399,6 +3492,13 @@
table:
name: notes
schema: public
+ - name: notifications
+ using:
+ foreign_key_constraint_on:
+ column: jobid
+ table:
+ name: notifications
+ schema: public
- name: parts_dispatches
using:
foreign_key_constraint_on:
@@ -3595,6 +3695,7 @@
- est_st
- est_zip
- federal_tax_rate
+ - flat_rate_ats
- g_bett_amt
- id
- inproduction
@@ -3689,6 +3790,7 @@
- qb_multiple_payers
- queued_for_parts
- rate_ats
+ - rate_ats_flat
- rate_la1
- rate_la2
- rate_la3
@@ -3865,6 +3967,7 @@
- est_st
- est_zip
- federal_tax_rate
+ - flat_rate_ats
- g_bett_amt
- id
- inproduction
@@ -3960,6 +4063,7 @@
- qb_multiple_payers
- queued_for_parts
- rate_ats
+ - rate_ats_flat
- rate_la1
- rate_la2
- rate_la3
@@ -4147,6 +4251,7 @@
- est_st
- est_zip
- federal_tax_rate
+ - flat_rate_ats
- g_bett_amt
- id
- inproduction
@@ -4242,6 +4347,7 @@
- qb_multiple_payers
- queued_for_parts
- rate_ats
+ - rate_ats_flat
- rate_la1
- rate_la2
- rate_la3
@@ -4473,10 +4579,7 @@
request_transform:
body:
action: transform
- template: |-
- {
- "success": true
- }
+ template: "{\r\n \"event\": {\r\n \"session_variables\": {\r\n \"x-hasura-user-id\": {{$body?.event?.session_variables?.x-hasura-user-id ?? \"Internal\"}},\r\n \"x-hasura-role\": {{$body?.event?.session_variables?.x-hasura-role ?? \"Internal\"}}\r\n }, \r\n \"op\": \"UPDATE\",\r\n \"data\": {\r\n \"old\": {\r\n \"id\": {{$body.event.data.old.id}},\r\n \"ro_number\": {{$body.event.data.old.ro_number}},\r\n \"queued_for_parts\": {{$body.event.data.old.queued_for_parts}},\r\n \"employee_prep\": {{$body.event.data.old.employee_prep}},\r\n \"clm_total\": {{$body.event.data.old.clm_total}},\r\n \"towin\": {{$body.event.data.old.towin}},\r\n \"employee_body\": {{$body.event.data.old.employee_body}},\r\n \"converted\": {{$body.event.data.old.converted}},\r\n \"scheduled_in\": {{$body.event.data.old.scheduled_in}},\r\n \"scheduled_completion\": {{$body.event.data.old.scheduled_completion}},\r\n \"scheduled_delivery\": {{$body.event.data.old.scheduled_delivery}},\r\n \"actual_delivery\": {{$body.event.data.old.actual_delivery}},\r\n \"actual_completion\": {{$body.event.data.old.actual_completion}},\r\n \"alt_transport\": {{$body.event.data.old.alt_transport}},\r\n \"date_exported\": {{$body.event.data.old.date_exported}},\r\n \"status\": {{$body.event.data.old.status}},\r\n \"employee_csr\": {{$body.event.data.old.employee_csr}},\r\n \"actual_in\": {{$body.event.data.old.actual_in}},\r\n \"deliverchecklist\": {{$body.event.data.old.deliverchecklist}},\r\n \"comment\": {{$body.event.data.old.comment}},\r\n \"employee_refinish\": {{$body.event.data.old.employee_refinish}},\r\n \"inproduction\": {{$body.event.data.old.inproduction}},\r\n \"production_vars\": {{$body.event.data.old.production_vars}},\r\n \"intakechecklist\": {{$body.event.data.old.intakechecklist}},\r\n \"cieca_ttl\": {{$body.event.data.old.cieca_ttl}},\r\n \"date_invoiced\": {{$body.event.data.old.date_invoiced}}\r\n },\r\n \"new\": {\r\n \"id\": {{$body.event.data.new.id}},\r\n \"ro_number\": {{$body.event.data.old.ro_number}},\r\n \"queued_for_parts\": {{$body.event.data.new.queued_for_parts}},\r\n \"employee_prep\": {{$body.event.data.new.employee_prep}},\r\n \"clm_total\": {{$body.event.data.new.clm_total}},\r\n \"towin\": {{$body.event.data.new.towin}},\r\n \"employee_body\": {{$body.event.data.new.employee_body}},\r\n \"converted\": {{$body.event.data.new.converted}},\r\n \"scheduled_in\": {{$body.event.data.new.scheduled_in}},\r\n \"scheduled_completion\": {{$body.event.data.new.scheduled_completion}},\r\n \"scheduled_delivery\": {{$body.event.data.new.scheduled_delivery}},\r\n \"actual_delivery\": {{$body.event.data.new.actual_delivery}},\r\n \"actual_completion\": {{$body.event.data.new.actual_completion}},\r\n \"alt_transport\": {{$body.event.data.new.alt_transport}},\r\n \"date_exported\": {{$body.event.data.new.date_exported}},\r\n \"status\": {{$body.event.data.new.status}},\r\n \"employee_csr\": {{$body.event.data.new.employee_csr}},\r\n \"actual_in\": {{$body.event.data.new.actual_in}},\r\n \"deliverchecklist\": {{$body.event.data.new.deliverchecklist}},\r\n \"comment\": {{$body.event.data.new.comment}},\r\n \"employee_refinish\": {{$body.event.data.new.employee_refinish}},\r\n \"inproduction\": {{$body.event.data.new.inproduction}},\r\n \"production_vars\": {{$body.event.data.new.production_vars}},\r\n \"intakechecklist\": {{$body.event.data.new.intakechecklist}},\r\n \"cieca_ttl\": {{$body.event.data.new.cieca_ttl}},\r\n \"date_invoiced\": {{$body.event.data.new.date_invoiced}}\r\n }\r\n }\r\n },\r\n \"trigger\": {\r\n \"name\": \"notifications_jobs\"\r\n },\r\n \"table\": {\r\n \"schema\": \"public\",\r\n \"name\": \"jobs\"\r\n }\r\n}\r\n"
method: POST
query_params: {}
template_engine: Kriti
@@ -4825,6 +4928,26 @@
_eq: X-Hasura-User-Id
- active:
_eq: true
+ event_triggers:
+ - name: notifications_notes
+ definition:
+ enable_manual: false
+ insert:
+ columns: '*'
+ retry_conf:
+ interval_sec: 10
+ num_retries: 0
+ timeout_sec: 60
+ webhook_from_env: HASURA_API_URL
+ headers:
+ - name: event-secret
+ value_from_env: EVENT_SECRET
+ request_transform:
+ method: POST
+ query_params: {}
+ template_engine: Kriti
+ url: '{{$base_url}}/notifications/events/handleNotesChange'
+ version: 2
- table:
name: notifications
schema: public
@@ -4835,46 +4958,79 @@
- name: job
using:
foreign_key_constraint_on: jobid
+ insert_permissions:
+ - role: user
+ permission:
+ check:
+ job:
+ bodyshop:
+ associations:
+ _and:
+ - user:
+ authid:
+ _eq: X-Hasura-User-Id
+ - active:
+ _eq: true
+ columns:
+ - scenario_meta
+ - scenario_text
+ - fcm_text
+ - created_at
+ - read
+ - updated_at
+ - associationid
+ - id
+ - jobid
+ comment: ""
select_permissions:
- role: user
permission:
columns:
- - associationid
+ - scenario_meta
+ - scenario_text
+ - fcm_text
- created_at
- - fcm_data
- - fcm_message
- - fcm_title
+ - read
+ - updated_at
+ - associationid
- id
- jobid
- - meta
- - read
- - ui_translation_meta
- - ui_translation_string
- - updated_at
filter:
- association:
- _and:
- - active:
- _eq: true
- - user:
- authid:
- _eq: X-Hasura-User-Id
+ job:
+ bodyshop:
+ associations:
+ _and:
+ - user:
+ authid:
+ _eq: X-Hasura-User-Id
+ - active:
+ _eq: true
+ allow_aggregations: true
comment: ""
update_permissions:
- role: user
permission:
columns:
- - meta
+ - scenario_meta
+ - scenario_text
+ - fcm_text
+ - created_at
- read
- filter:
- association:
- _and:
- - active:
- _eq: true
- - user:
- authid:
- _eq: X-Hasura-User-Id
- check: null
+ - updated_at
+ - associationid
+ - id
+ - jobid
+ filter: {}
+ check:
+ job:
+ bodyshop:
+ associations:
+ _and:
+ - user:
+ authid:
+ _eq: X-Hasura-User-Id
+ - active:
+ _eq: true
comment: ""
- table:
name: owners
@@ -5116,32 +5272,6 @@
- active:
_eq: true
check: null
- event_triggers:
- - name: notifications_parts_dispatch
- definition:
- enable_manual: false
- insert:
- columns: '*'
- retry_conf:
- interval_sec: 10
- num_retries: 0
- timeout_sec: 60
- webhook_from_env: HASURA_API_URL
- headers:
- - name: event-secret
- value_from_env: EVENT_SECRET
- request_transform:
- body:
- action: transform
- template: |-
- {
- "success": true
- }
- method: POST
- query_params: {}
- template_engine: Kriti
- url: '{{$base_url}}/notifications/events/handlePartsDispatchChange'
- version: 2
- table:
name: parts_dispatch_lines
schema: public
@@ -5648,6 +5778,25 @@
- active:
_eq: true
event_triggers:
+ - name: notifications_payments
+ definition:
+ enable_manual: false
+ insert:
+ columns: '*'
+ retry_conf:
+ interval_sec: 10
+ num_retries: 0
+ timeout_sec: 60
+ webhook_from_env: HASURA_API_URL
+ headers:
+ - name: event-secret
+ value_from_env: EVENT_SECRET
+ request_transform:
+ method: POST
+ query_params: {}
+ template_engine: Kriti
+ url: '{{$base_url}}/notifications/events/handlePaymentsChange'
+ version: 2
- name: os_payments
definition:
delete:
@@ -6119,9 +6268,15 @@
columns: '*'
update:
columns:
+ - joblineid
- assigned_to
+ - due_date
+ - partsorderid
- completed
- description
+ - billid
+ - title
+ - priority
retry_conf:
interval_sec: 10
num_retries: 0
@@ -6131,12 +6286,6 @@
- name: event-secret
value_from_env: EVENT_SECRET
request_transform:
- body:
- action: transform
- template: |-
- {
- "success": true
- }
method: POST
query_params: {}
template_engine: Kriti
@@ -6313,12 +6462,6 @@
- name: event-secret
value_from_env: EVENT_SECRET
request_transform:
- body:
- action: transform
- template: |-
- {
- "success": true
- }
method: POST
query_params: {}
template_engine: Kriti
@@ -6586,6 +6729,13 @@
table:
name: ioevents
schema: public
+ - name: job_watchers
+ using:
+ foreign_key_constraint_on:
+ column: user_email
+ table:
+ name: job_watchers
+ schema: public
- name: messages
using:
foreign_key_constraint_on:
diff --git a/hasura/migrations/1740162115648_alter_table_public_notifications_add_column_html_body/down.sql b/hasura/migrations/1740162115648_alter_table_public_notifications_add_column_html_body/down.sql
new file mode 100644
index 000000000..bb56e2f77
--- /dev/null
+++ b/hasura/migrations/1740162115648_alter_table_public_notifications_add_column_html_body/down.sql
@@ -0,0 +1,4 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- alter table "public"."notifications" add column "html_body" text
+-- not null;
diff --git a/hasura/migrations/1740162115648_alter_table_public_notifications_add_column_html_body/up.sql b/hasura/migrations/1740162115648_alter_table_public_notifications_add_column_html_body/up.sql
new file mode 100644
index 000000000..be7753c99
--- /dev/null
+++ b/hasura/migrations/1740162115648_alter_table_public_notifications_add_column_html_body/up.sql
@@ -0,0 +1,2 @@
+alter table "public"."notifications" add column "html_body" text
+ not null;
diff --git a/hasura/migrations/1740162296457_alter_table_public_notifications_alter_column_fcm_title/down.sql b/hasura/migrations/1740162296457_alter_table_public_notifications_alter_column_fcm_title/down.sql
new file mode 100644
index 000000000..a2d9ebaa9
--- /dev/null
+++ b/hasura/migrations/1740162296457_alter_table_public_notifications_alter_column_fcm_title/down.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" alter column "fcm_title" set not null;
diff --git a/hasura/migrations/1740162296457_alter_table_public_notifications_alter_column_fcm_title/up.sql b/hasura/migrations/1740162296457_alter_table_public_notifications_alter_column_fcm_title/up.sql
new file mode 100644
index 000000000..3755dc382
--- /dev/null
+++ b/hasura/migrations/1740162296457_alter_table_public_notifications_alter_column_fcm_title/up.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" alter column "fcm_title" drop not null;
diff --git a/hasura/migrations/1740162315085_alter_table_public_notifications_alter_column_fcm_message/down.sql b/hasura/migrations/1740162315085_alter_table_public_notifications_alter_column_fcm_message/down.sql
new file mode 100644
index 000000000..dadd5d448
--- /dev/null
+++ b/hasura/migrations/1740162315085_alter_table_public_notifications_alter_column_fcm_message/down.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" alter column "fcm_message" set not null;
diff --git a/hasura/migrations/1740162315085_alter_table_public_notifications_alter_column_fcm_message/up.sql b/hasura/migrations/1740162315085_alter_table_public_notifications_alter_column_fcm_message/up.sql
new file mode 100644
index 000000000..387272491
--- /dev/null
+++ b/hasura/migrations/1740162315085_alter_table_public_notifications_alter_column_fcm_message/up.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" alter column "fcm_message" drop not null;
diff --git a/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/down.sql b/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/down.sql
new file mode 100644
index 000000000..3986cbda4
--- /dev/null
+++ b/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/down.sql
@@ -0,0 +1,3 @@
+comment on column "public"."notifications"."html_body" is E'Real Time Notifications System';
+alter table "public"."notifications" alter column "html_body" drop not null;
+alter table "public"."notifications" add column "html_body" text;
diff --git a/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/up.sql b/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/up.sql
new file mode 100644
index 000000000..58ee2d95f
--- /dev/null
+++ b/hasura/migrations/1740417011431_alter_table_public_notifications_drop_column_html_body/up.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" drop column "html_body" cascade;
diff --git a/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/down.sql b/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/down.sql
new file mode 100644
index 000000000..70e4fc311
--- /dev/null
+++ b/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/down.sql
@@ -0,0 +1,4 @@
+comment on column "public"."notifications"."fcm_data" is E'Real Time Notifications System';
+alter table "public"."notifications" alter column "fcm_data" set default jsonb_build_object();
+alter table "public"."notifications" alter column "fcm_data" drop not null;
+alter table "public"."notifications" add column "fcm_data" jsonb;
diff --git a/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/up.sql b/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/up.sql
new file mode 100644
index 000000000..3f6441573
--- /dev/null
+++ b/hasura/migrations/1740417046609_alter_table_public_notifications_drop_column_fcm_data/up.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" drop column "fcm_data" cascade;
diff --git a/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/down.sql b/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/down.sql
new file mode 100644
index 000000000..4651b79a3
--- /dev/null
+++ b/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/down.sql
@@ -0,0 +1,3 @@
+comment on column "public"."notifications"."fcm_message" is E'Real Time Notifications System';
+alter table "public"."notifications" alter column "fcm_message" drop not null;
+alter table "public"."notifications" add column "fcm_message" text;
diff --git a/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/up.sql b/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/up.sql
new file mode 100644
index 000000000..6a51ad6f5
--- /dev/null
+++ b/hasura/migrations/1740417076166_alter_table_public_notifications_drop_column_fcm_message/up.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" drop column "fcm_message" cascade;
diff --git a/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/down.sql b/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/down.sql
new file mode 100644
index 000000000..234537d07
--- /dev/null
+++ b/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/down.sql
@@ -0,0 +1,3 @@
+comment on column "public"."notifications"."ui_translation_string" is E'Real Time Notifications System';
+alter table "public"."notifications" alter column "ui_translation_string" drop not null;
+alter table "public"."notifications" add column "ui_translation_string" text;
diff --git a/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/up.sql b/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/up.sql
new file mode 100644
index 000000000..702af0747
--- /dev/null
+++ b/hasura/migrations/1740417110704_alter_table_public_notifications_drop_column_ui_translation_string/up.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" drop column "ui_translation_string" cascade;
diff --git a/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/down.sql b/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/down.sql
new file mode 100644
index 000000000..f76615392
--- /dev/null
+++ b/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/down.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" rename column "fcm_text" to "fcm_title";
diff --git a/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/up.sql b/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/up.sql
new file mode 100644
index 000000000..4e39cf157
--- /dev/null
+++ b/hasura/migrations/1740417137294_alter_table_public_notifications_alter_column_fcm_title/up.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" rename column "fcm_title" to "fcm_text";
diff --git a/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/down.sql b/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/down.sql
new file mode 100644
index 000000000..4b7add7b9
--- /dev/null
+++ b/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/down.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" rename column "scenario_text" to "ui_translation_meta";
diff --git a/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/up.sql b/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/up.sql
new file mode 100644
index 000000000..b2c933ed9
--- /dev/null
+++ b/hasura/migrations/1740417505757_alter_table_public_notifications_alter_column_ui_translation_meta/up.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" rename column "ui_translation_meta" to "scenario_text";
diff --git a/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/down.sql b/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/down.sql
new file mode 100644
index 000000000..f0ef6d736
--- /dev/null
+++ b/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/down.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" rename column "scenario_meta" to "meta";
diff --git a/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/up.sql b/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/up.sql
new file mode 100644
index 000000000..4561da723
--- /dev/null
+++ b/hasura/migrations/1740417594189_alter_table_public_notifications_alter_column_meta/up.sql
@@ -0,0 +1 @@
+alter table "public"."notifications" rename column "meta" to "scenario_meta";
diff --git a/hasura/migrations/1741145815435_create_index_idx_job_watchers_jobid_user_email_unique/down.sql b/hasura/migrations/1741145815435_create_index_idx_job_watchers_jobid_user_email_unique/down.sql
new file mode 100644
index 000000000..cfaf0fd17
--- /dev/null
+++ b/hasura/migrations/1741145815435_create_index_idx_job_watchers_jobid_user_email_unique/down.sql
@@ -0,0 +1 @@
+DROP INDEX IF EXISTS "public"."idx_job_watchers_jobid_user_email_unique";
diff --git a/hasura/migrations/1741145815435_create_index_idx_job_watchers_jobid_user_email_unique/up.sql b/hasura/migrations/1741145815435_create_index_idx_job_watchers_jobid_user_email_unique/up.sql
new file mode 100644
index 000000000..031825281
--- /dev/null
+++ b/hasura/migrations/1741145815435_create_index_idx_job_watchers_jobid_user_email_unique/up.sql
@@ -0,0 +1,2 @@
+CREATE UNIQUE INDEX "idx_job_watchers_jobid_user_email_unique" on
+ "public"."job_watchers" using btree ("jobid", "user_email");
diff --git a/hasura/migrations/1741904378259_create_index_notificiations_idx_jobs/down.sql b/hasura/migrations/1741904378259_create_index_notificiations_idx_jobs/down.sql
new file mode 100644
index 000000000..a4029e3f4
--- /dev/null
+++ b/hasura/migrations/1741904378259_create_index_notificiations_idx_jobs/down.sql
@@ -0,0 +1 @@
+DROP INDEX IF EXISTS "public"."notificiations_idx_jobs";
diff --git a/hasura/migrations/1741904378259_create_index_notificiations_idx_jobs/up.sql b/hasura/migrations/1741904378259_create_index_notificiations_idx_jobs/up.sql
new file mode 100644
index 000000000..8fd3f3f34
--- /dev/null
+++ b/hasura/migrations/1741904378259_create_index_notificiations_idx_jobs/up.sql
@@ -0,0 +1,2 @@
+CREATE INDEX "notificiations_idx_jobs" on
+ "public"."notifications" using btree ("jobid");
diff --git a/hasura/migrations/1741904395934_create_index_notifications_idx_associations/down.sql b/hasura/migrations/1741904395934_create_index_notifications_idx_associations/down.sql
new file mode 100644
index 000000000..17b162d35
--- /dev/null
+++ b/hasura/migrations/1741904395934_create_index_notifications_idx_associations/down.sql
@@ -0,0 +1 @@
+DROP INDEX IF EXISTS "public"."notifications_idx_associations";
diff --git a/hasura/migrations/1741904395934_create_index_notifications_idx_associations/up.sql b/hasura/migrations/1741904395934_create_index_notifications_idx_associations/up.sql
new file mode 100644
index 000000000..9d131b3b2
--- /dev/null
+++ b/hasura/migrations/1741904395934_create_index_notifications_idx_associations/up.sql
@@ -0,0 +1,2 @@
+CREATE INDEX "notifications_idx_associations" on
+ "public"."notifications" using btree ("associationid");
diff --git a/hasura/migrations/1741904614090_run_sql_migration/down.sql b/hasura/migrations/1741904614090_run_sql_migration/down.sql
new file mode 100644
index 000000000..90dce4b23
--- /dev/null
+++ b/hasura/migrations/1741904614090_run_sql_migration/down.sql
@@ -0,0 +1,3 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- CREATE INDEX idx_notifications_created_at_not_read ON notifications(created_at desc, read) where read is null;
diff --git a/hasura/migrations/1741904614090_run_sql_migration/up.sql b/hasura/migrations/1741904614090_run_sql_migration/up.sql
new file mode 100644
index 000000000..ecca4610e
--- /dev/null
+++ b/hasura/migrations/1741904614090_run_sql_migration/up.sql
@@ -0,0 +1 @@
+CREATE INDEX idx_notifications_created_at_not_read ON notifications(created_at desc, read) where read is null;
diff --git a/hasura/migrations/1741904805838_run_sql_migration/down.sql b/hasura/migrations/1741904805838_run_sql_migration/down.sql
new file mode 100644
index 000000000..f6b9c6e6e
--- /dev/null
+++ b/hasura/migrations/1741904805838_run_sql_migration/down.sql
@@ -0,0 +1,3 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- CREATE INDEX idx_notifications_associations_not_read ON notifications(associationid, read) where read is null;
diff --git a/hasura/migrations/1741904805838_run_sql_migration/up.sql b/hasura/migrations/1741904805838_run_sql_migration/up.sql
new file mode 100644
index 000000000..7950b3bd9
--- /dev/null
+++ b/hasura/migrations/1741904805838_run_sql_migration/up.sql
@@ -0,0 +1 @@
+CREATE INDEX idx_notifications_associations_not_read ON notifications(associationid, read) where read is null;
diff --git a/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/down.sql b/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/down.sql
new file mode 100644
index 000000000..5478f998b
--- /dev/null
+++ b/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/down.sql
@@ -0,0 +1,4 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- alter table "public"."jobs" add column "flat_rate_ats" boolean
+-- null default 'false';
diff --git a/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/up.sql b/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/up.sql
new file mode 100644
index 000000000..73fa874ae
--- /dev/null
+++ b/hasura/migrations/1742583400542_alter_table_public_jobs_add_column_flat_rate_ats/up.sql
@@ -0,0 +1,2 @@
+alter table "public"."jobs" add column "flat_rate_ats" boolean
+ null default 'false';
diff --git a/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/down.sql b/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/down.sql
new file mode 100644
index 000000000..3f82e9770
--- /dev/null
+++ b/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/down.sql
@@ -0,0 +1,4 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- alter table "public"."jobs" add column "rate_ats_flat" numeric
+-- null;
diff --git a/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/up.sql b/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/up.sql
new file mode 100644
index 000000000..e0157edd2
--- /dev/null
+++ b/hasura/migrations/1742583433746_alter_table_public_jobs_add_column_rate_ats_flat/up.sql
@@ -0,0 +1,2 @@
+alter table "public"."jobs" add column "rate_ats_flat" numeric
+ null;
diff --git a/nginx-websocket.conf b/nginx-websocket.conf
new file mode 100644
index 000000000..3f55e6491
--- /dev/null
+++ b/nginx-websocket.conf
@@ -0,0 +1,45 @@
+events {
+ worker_connections 1024;
+}
+
+http {
+ upstream node_app {
+ ip_hash; # Enables session persistence based on client IP
+ server node-app-1:4000;
+ server node-app-2:4000;
+ server node-app-3:4000;
+ }
+
+ # WebSocket upgrade configuration
+ map $http_upgrade $connection_upgrade {
+ default upgrade;
+ '' close;
+ }
+
+ server {
+ listen 80;
+
+ location / {
+ proxy_pass http://node_app;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket headers
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection $connection_upgrade;
+ proxy_read_timeout 86400; # Keep WebSocket connections alive (24 hours)
+ }
+
+ # Health check endpoint
+ location /health {
+ proxy_pass http://node_app;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+ }
+}
diff --git a/package-lock.json b/package-lock.json
index 608a76ac4..66794a554 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,12 +9,12 @@
"version": "0.2.0",
"license": "UNLICENSED",
"dependencies": {
- "@aws-sdk/client-cloudwatch-logs": "^3.738.0",
- "@aws-sdk/client-elasticache": "^3.738.0",
- "@aws-sdk/client-s3": "^3.738.0",
- "@aws-sdk/client-secrets-manager": "^3.738.0",
- "@aws-sdk/client-ses": "^3.738.0",
- "@aws-sdk/credential-provider-node": "^3.738.0",
+ "@aws-sdk/client-cloudwatch-logs": "^3.772.0",
+ "@aws-sdk/client-elasticache": "^3.772.0",
+ "@aws-sdk/client-s3": "^3.772.0",
+ "@aws-sdk/client-secrets-manager": "^3.772.0",
+ "@aws-sdk/client-ses": "^3.772.0",
+ "@aws-sdk/credential-provider-node": "^3.772.0",
"@aws-sdk/lib-storage": "^3.743.0",
"@aws-sdk/s3-request-presigner": "^3.731.1",
"@opensearch-project/opensearch": "^2.13.0",
@@ -22,34 +22,36 @@
"@socket.io/redis-adapter": "^8.3.0",
"archiver": "^7.0.1",
"aws4": "^1.13.2",
- "axios": "^1.7.7",
+ "axios": "^1.8.4",
+ "bee-queue": "^1.7.1",
"better-queue": "^3.8.12",
"bluebird": "^3.7.2",
"body-parser": "^1.20.3",
- "chart.js": "^4.4.6",
- "cloudinary": "^2.5.1",
- "compression": "^1.7.5",
+ "bullmq": "^5.44.4",
+ "chart.js": "^4.4.8",
+ "cloudinary": "^2.6.0",
+ "compression": "^1.8.0",
"cookie-parser": "^1.4.7",
"cors": "2.8.5",
"crisp-status-reporter": "^1.2.2",
"csrf": "^3.1.0",
- "dd-trace": "^5.33.1",
+ "dd-trace": "^5.43.0",
"dinero.js": "^1.9.1",
"dotenv": "^16.4.5",
"express": "^4.21.1",
- "firebase-admin": "^13.0.2",
+ "firebase-admin": "^13.2.0",
"graphql": "^16.10.0",
"graphql-request": "^6.1.0",
"inline-css": "^4.0.3",
- "intuit-oauth": "^4.1.3",
- "ioredis": "^5.4.2",
- "json-2-csv": "^5.5.8",
- "juice": "^11.0.0",
+ "intuit-oauth": "^4.2.0",
+ "ioredis": "^5.6.0",
+ "json-2-csv": "^5.5.9",
+ "juice": "^11.0.1",
"lodash": "^4.17.21",
"moment": "^2.30.1",
- "moment-timezone": "^0.5.47",
+ "moment-timezone": "^0.5.48",
"multer": "^1.4.5-lts.1",
- "node-mailjet": "^6.0.6",
+ "node-mailjet": "^6.0.8",
"node-persist": "^4.0.4",
"nodemailer": "^6.10.0",
"phone": "^3.1.58",
@@ -57,26 +59,25 @@
"redis": "^4.7.0",
"rimraf": "^6.0.1",
"skia-canvas": "^2.0.2",
- "soap": "^1.1.7",
+ "soap": "^1.1.10",
"socket.io": "^4.8.1",
"socket.io-adapter": "^2.5.5",
"ssh2-sftp-client": "^11.0.0",
- "twilio": "^4.23.0",
- "uuid": "^10.0.0",
+ "twilio": "^5.5.1",
+ "uuid": "^11.1.0",
"winston": "^3.17.0",
"winston-cloudwatch": "^6.3.0",
"xml2js": "^0.6.2",
"xmlbuilder2": "^3.1.1"
},
"devDependencies": {
- "@eslint/js": "^9.19.0",
- "@trivago/prettier-plugin-sort-imports": "^4.3.0",
- "concurrently": "^8.2.2",
- "eslint": "^9.19.0",
+ "@eslint/js": "^9.23.0",
+ "@trivago/prettier-plugin-sort-imports": "^5.2.2",
+ "eslint": "^9.23.0",
"eslint-plugin-react": "^7.37.4",
- "globals": "^15.14.0",
+ "globals": "^15.15.0",
"p-limit": "^3.1.0",
- "prettier": "^3.3.3",
+ "prettier": "^3.5.3",
"source-map-explorer": "^2.5.2"
},
"engines": {
@@ -287,26 +288,26 @@
}
},
"node_modules/@aws-sdk/client-cloudwatch-logs": {
- "version": "3.741.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.741.0.tgz",
- "integrity": "sha512-a0k5+FEdT8Mh4SXBme0hKnOTF2HFAtaDLS1MJsRXlty+qZHoECPTSTicvGVcPRxmYcRmU4bpz0nTGQI6KBVvpg==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.774.0.tgz",
+ "integrity": "sha512-P+qEZJMd4kZVbTs2YRvBHOYlRd0U7bgpbEhRoYRS6vOWymRinQaxj/KCaw1cmdBILj502CUieFGj6DEYAbiNzQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/credential-provider-node": "3.741.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/credential-provider-node": "3.774.0",
+ "@aws-sdk/middleware-host-header": "3.774.0",
"@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.772.0",
+ "@aws-sdk/middleware-user-agent": "3.774.0",
"@aws-sdk/region-config-resolver": "3.734.0",
"@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
"@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.774.0",
"@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.1",
+ "@smithy/core": "^3.1.5",
"@smithy/eventstream-serde-browser": "^4.0.1",
"@smithy/eventstream-serde-config-resolver": "^4.0.1",
"@smithy/eventstream-serde-node": "^4.0.1",
@@ -314,21 +315,21 @@
"@smithy/hash-node": "^4.0.1",
"@smithy/invalid-dependency": "^4.0.1",
"@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.2",
- "@smithy/middleware-retry": "^4.0.3",
- "@smithy/middleware-serde": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.6",
+ "@smithy/middleware-retry": "^4.0.7",
+ "@smithy/middleware-serde": "^4.0.2",
"@smithy/middleware-stack": "^4.0.1",
"@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/node-http-handler": "^4.0.3",
"@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
"@smithy/url-parser": "^4.0.1",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.3",
- "@smithy/util-defaults-mode-node": "^4.0.3",
+ "@smithy/util-defaults-mode-browser": "^4.0.7",
+ "@smithy/util-defaults-mode-node": "^4.0.7",
"@smithy/util-endpoints": "^3.0.1",
"@smithy/util-middleware": "^4.0.1",
"@smithy/util-retry": "^4.0.1",
@@ -355,45 +356,45 @@
}
},
"node_modules/@aws-sdk/client-elasticache": {
- "version": "3.741.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.741.0.tgz",
- "integrity": "sha512-cWyzkKacBNJOBfK1HGO439JkmJHOK8VQpkLB6zF806nsBCC1c7uo4bjiqOQzw2eU0yJ2m3b6kbVf/sEmdvR6WA==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-elasticache/-/client-elasticache-3.774.0.tgz",
+ "integrity": "sha512-uBWSLt6p5tSZCdoizuNyytGiZBFgtUAnXH7GnYH1tVzPeQoQb5GI5of5cDw9lFIIR6DWpYjA7JZ7EEmNvvD7rw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/credential-provider-node": "3.741.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/credential-provider-node": "3.774.0",
+ "@aws-sdk/middleware-host-header": "3.774.0",
"@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.772.0",
+ "@aws-sdk/middleware-user-agent": "3.774.0",
"@aws-sdk/region-config-resolver": "3.734.0",
"@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
"@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.774.0",
"@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.1",
+ "@smithy/core": "^3.1.5",
"@smithy/fetch-http-handler": "^5.0.1",
"@smithy/hash-node": "^4.0.1",
"@smithy/invalid-dependency": "^4.0.1",
"@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.2",
- "@smithy/middleware-retry": "^4.0.3",
- "@smithy/middleware-serde": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.6",
+ "@smithy/middleware-retry": "^4.0.7",
+ "@smithy/middleware-serde": "^4.0.2",
"@smithy/middleware-stack": "^4.0.1",
"@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/node-http-handler": "^4.0.3",
"@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
"@smithy/url-parser": "^4.0.1",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.3",
- "@smithy/util-defaults-mode-node": "^4.0.3",
+ "@smithy/util-defaults-mode-browser": "^4.0.7",
+ "@smithy/util-defaults-mode-node": "^4.0.7",
"@smithy/util-endpoints": "^3.0.1",
"@smithy/util-middleware": "^4.0.1",
"@smithy/util-retry": "^4.0.1",
@@ -406,35 +407,35 @@
}
},
"node_modules/@aws-sdk/client-s3": {
- "version": "3.741.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.741.0.tgz",
- "integrity": "sha512-sZvdbRZ+E9/GcOMUOkZvYvob95N6c9LdzDneXHFASA7OIaEOQxQT1Arimz7JpEhfq/h9K2/j7wNO4jh4x80bmA==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.774.0.tgz",
+ "integrity": "sha512-HQ5Xi01r/Pv2IpzPTf5acrN0g/yJQalheDCYbBSA8VU31zoYiT/w5kLFWYJHQDB2hRozh2DB/VC/VDmntkWXxA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha1-browser": "5.2.0",
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/credential-provider-node": "3.741.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/credential-provider-node": "3.774.0",
"@aws-sdk/middleware-bucket-endpoint": "3.734.0",
"@aws-sdk/middleware-expect-continue": "3.734.0",
- "@aws-sdk/middleware-flexible-checksums": "3.735.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/middleware-flexible-checksums": "3.774.0",
+ "@aws-sdk/middleware-host-header": "3.774.0",
"@aws-sdk/middleware-location-constraint": "3.734.0",
"@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-sdk-s3": "3.740.0",
+ "@aws-sdk/middleware-recursion-detection": "3.772.0",
+ "@aws-sdk/middleware-sdk-s3": "3.774.0",
"@aws-sdk/middleware-ssec": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.734.0",
+ "@aws-sdk/middleware-user-agent": "3.774.0",
"@aws-sdk/region-config-resolver": "3.734.0",
- "@aws-sdk/signature-v4-multi-region": "3.740.0",
+ "@aws-sdk/signature-v4-multi-region": "3.774.0",
"@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
"@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.774.0",
"@aws-sdk/xml-builder": "3.734.0",
"@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.1",
+ "@smithy/core": "^3.1.5",
"@smithy/eventstream-serde-browser": "^4.0.1",
"@smithy/eventstream-serde-config-resolver": "^4.0.1",
"@smithy/eventstream-serde-node": "^4.0.1",
@@ -445,25 +446,25 @@
"@smithy/invalid-dependency": "^4.0.1",
"@smithy/md5-js": "^4.0.1",
"@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.2",
- "@smithy/middleware-retry": "^4.0.3",
- "@smithy/middleware-serde": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.6",
+ "@smithy/middleware-retry": "^4.0.7",
+ "@smithy/middleware-serde": "^4.0.2",
"@smithy/middleware-stack": "^4.0.1",
"@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/node-http-handler": "^4.0.3",
"@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
"@smithy/url-parser": "^4.0.1",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.3",
- "@smithy/util-defaults-mode-node": "^4.0.3",
+ "@smithy/util-defaults-mode-browser": "^4.0.7",
+ "@smithy/util-defaults-mode-node": "^4.0.7",
"@smithy/util-endpoints": "^3.0.1",
"@smithy/util-middleware": "^4.0.1",
"@smithy/util-retry": "^4.0.1",
- "@smithy/util-stream": "^4.0.2",
+ "@smithy/util-stream": "^4.1.2",
"@smithy/util-utf8": "^4.0.0",
"@smithy/util-waiter": "^4.0.2",
"tslib": "^2.6.2"
@@ -473,45 +474,45 @@
}
},
"node_modules/@aws-sdk/client-secrets-manager": {
- "version": "3.741.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.741.0.tgz",
- "integrity": "sha512-AmNGZGTJPD2B7AOUmDZZhLDpQ5tQX5WLL7X+2XB1U9tn97vAPd1ocqKEVD4wDkjIx3KVI+x3kA9xTQ0P9e7lMg==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.774.0.tgz",
+ "integrity": "sha512-AoVpmzLY/PW/0H6hcc/Rn/uisDTFE7WX/oWZ8qU2gYMuH3z2VUAIhHQZq3mNpXH4ZlWPH+sDA8cG1tCc8dgVqA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/credential-provider-node": "3.741.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/credential-provider-node": "3.774.0",
+ "@aws-sdk/middleware-host-header": "3.774.0",
"@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.772.0",
+ "@aws-sdk/middleware-user-agent": "3.774.0",
"@aws-sdk/region-config-resolver": "3.734.0",
"@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
"@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.774.0",
"@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.1",
+ "@smithy/core": "^3.1.5",
"@smithy/fetch-http-handler": "^5.0.1",
"@smithy/hash-node": "^4.0.1",
"@smithy/invalid-dependency": "^4.0.1",
"@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.2",
- "@smithy/middleware-retry": "^4.0.3",
- "@smithy/middleware-serde": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.6",
+ "@smithy/middleware-retry": "^4.0.7",
+ "@smithy/middleware-serde": "^4.0.2",
"@smithy/middleware-stack": "^4.0.1",
"@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/node-http-handler": "^4.0.3",
"@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
"@smithy/url-parser": "^4.0.1",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.3",
- "@smithy/util-defaults-mode-node": "^4.0.3",
+ "@smithy/util-defaults-mode-browser": "^4.0.7",
+ "@smithy/util-defaults-mode-node": "^4.0.7",
"@smithy/util-endpoints": "^3.0.1",
"@smithy/util-middleware": "^4.0.1",
"@smithy/util-retry": "^4.0.1",
@@ -538,45 +539,45 @@
}
},
"node_modules/@aws-sdk/client-ses": {
- "version": "3.741.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.741.0.tgz",
- "integrity": "sha512-TFLesYGaPhSOVwSWV5OBl4hcsX/79o0Gf3I6N6/THNmYmfkCZVsjhZ/r/qVLb9zzxyXh3z3r3j3i/83xg4hzOA==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-ses/-/client-ses-3.774.0.tgz",
+ "integrity": "sha512-EWZRm9nV7xFQYjFmk259gf1Mp40MuJ1KWHbY5y6EYt3dkuYFJnqAdBETB3tzbC0EmIkVSR1Uzxc72jRS8klvHg==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/credential-provider-node": "3.741.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/credential-provider-node": "3.774.0",
+ "@aws-sdk/middleware-host-header": "3.774.0",
"@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.772.0",
+ "@aws-sdk/middleware-user-agent": "3.774.0",
"@aws-sdk/region-config-resolver": "3.734.0",
"@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
"@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.774.0",
"@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.1",
+ "@smithy/core": "^3.1.5",
"@smithy/fetch-http-handler": "^5.0.1",
"@smithy/hash-node": "^4.0.1",
"@smithy/invalid-dependency": "^4.0.1",
"@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.2",
- "@smithy/middleware-retry": "^4.0.3",
- "@smithy/middleware-serde": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.6",
+ "@smithy/middleware-retry": "^4.0.7",
+ "@smithy/middleware-serde": "^4.0.2",
"@smithy/middleware-stack": "^4.0.1",
"@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/node-http-handler": "^4.0.3",
"@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
"@smithy/url-parser": "^4.0.1",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.3",
- "@smithy/util-defaults-mode-node": "^4.0.3",
+ "@smithy/util-defaults-mode-browser": "^4.0.7",
+ "@smithy/util-defaults-mode-node": "^4.0.7",
"@smithy/util-endpoints": "^3.0.1",
"@smithy/util-middleware": "^4.0.1",
"@smithy/util-retry": "^4.0.1",
@@ -589,44 +590,44 @@
}
},
"node_modules/@aws-sdk/client-sso": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.734.0.tgz",
- "integrity": "sha512-oerepp0mut9VlgTwnG5Ds/lb0C0b2/rQ+hL/rF6q+HGKPfGsCuPvFx1GtwGKCXd49ase88/jVgrhcA9OQbz3kg==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.774.0.tgz",
+ "integrity": "sha512-bN+wd2gpTq+DNJ/fZdam/mX6K3TcVdZBIvxaVtg+imep6xAuRukdFhsoG0cDzk96+WHPCOhkyi+6lFljCof43Q==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/middleware-host-header": "3.774.0",
"@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.772.0",
+ "@aws-sdk/middleware-user-agent": "3.774.0",
"@aws-sdk/region-config-resolver": "3.734.0",
"@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
"@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.774.0",
"@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.1",
+ "@smithy/core": "^3.1.5",
"@smithy/fetch-http-handler": "^5.0.1",
"@smithy/hash-node": "^4.0.1",
"@smithy/invalid-dependency": "^4.0.1",
"@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.2",
- "@smithy/middleware-retry": "^4.0.3",
- "@smithy/middleware-serde": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.6",
+ "@smithy/middleware-retry": "^4.0.7",
+ "@smithy/middleware-serde": "^4.0.2",
"@smithy/middleware-stack": "^4.0.1",
"@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/node-http-handler": "^4.0.3",
"@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
"@smithy/url-parser": "^4.0.1",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.3",
- "@smithy/util-defaults-mode-node": "^4.0.3",
+ "@smithy/util-defaults-mode-browser": "^4.0.7",
+ "@smithy/util-defaults-mode-node": "^4.0.7",
"@smithy/util-endpoints": "^3.0.1",
"@smithy/util-middleware": "^4.0.1",
"@smithy/util-retry": "^4.0.1",
@@ -638,18 +639,18 @@
}
},
"node_modules/@aws-sdk/core": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.734.0.tgz",
- "integrity": "sha512-SxnDqf3vobdm50OLyAKfqZetv6zzwnSqwIwd3jrbopxxHKqNIM/I0xcYjD6Tn+mPig+u7iRKb9q3QnEooFTlmg==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.774.0.tgz",
+ "integrity": "sha512-JDkAAlPyGWMX42L4Cv8mxybwHTOoFweNbNrOc5oQJhFxZAe1zkW4uLTEfr79vYhnXCFbThCyPpBotmo3U2vULA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.734.0",
- "@smithy/core": "^3.1.1",
+ "@smithy/core": "^3.1.5",
"@smithy/node-config-provider": "^4.0.1",
"@smithy/property-provider": "^4.0.1",
"@smithy/protocol-http": "^5.0.1",
"@smithy/signature-v4": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
"@smithy/util-middleware": "^4.0.1",
"fast-xml-parser": "4.4.1",
@@ -660,12 +661,12 @@
}
},
"node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.734.0.tgz",
- "integrity": "sha512-gtRkzYTGafnm1FPpiNO8VBmJrYMoxhDlGPYDVcijzx3DlF8dhWnowuSBCxLSi+MJMx5hvwrX2A+e/q0QAeHqmw==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.774.0.tgz",
+ "integrity": "sha512-FkSDBi9Ly0bmzyrMDeqQq1lGsFMrrd/bIB3c9VD4Llh0sPLxB/DU31+VTPTuQ0pBPz4sX5Vay6tLy43DStzcFQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/property-provider": "^4.0.1",
"@smithy/types": "^4.1.0",
@@ -676,20 +677,20 @@
}
},
"node_modules/@aws-sdk/credential-provider-http": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.734.0.tgz",
- "integrity": "sha512-JFSL6xhONsq+hKM8xroIPhM5/FOhiQ1cov0lZxhzZWj6Ai3UAjucy3zyIFDr9MgP1KfCYNdvyaUq9/o+HWvEDg==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.774.0.tgz",
+ "integrity": "sha512-iurWGQColf52HpHeHCQs/LnSjZ0Ufq3VtSQx/6QdZwIhmgbbqvGMAaBJg41SQjWhpqdufE96HzcaCJw/lnCefQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/node-http-handler": "^4.0.3",
"@smithy/property-provider": "^4.0.1",
"@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
- "@smithy/util-stream": "^4.0.2",
+ "@smithy/util-stream": "^4.1.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -697,18 +698,18 @@
}
},
"node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.741.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.741.0.tgz",
- "integrity": "sha512-/XvnVp6zZXsyUlP1FtmspcWnd+Z1u2WK0wwzTE/x277M0oIhAezCW79VmcY4jcDQbYH+qMbtnBexfwgFDARxQg==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.774.0.tgz",
+ "integrity": "sha512-+AsJOX9pGsnGPAC8wQw7LAO8ZfXzjXTjJxSP1fvg04PX7OBk4zwhVaryH6pu5raan+9cVbfEO1Z7EEMdkweGQA==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/credential-provider-env": "3.734.0",
- "@aws-sdk/credential-provider-http": "3.734.0",
- "@aws-sdk/credential-provider-process": "3.734.0",
- "@aws-sdk/credential-provider-sso": "3.734.0",
- "@aws-sdk/credential-provider-web-identity": "3.734.0",
- "@aws-sdk/nested-clients": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/credential-provider-env": "3.774.0",
+ "@aws-sdk/credential-provider-http": "3.774.0",
+ "@aws-sdk/credential-provider-process": "3.774.0",
+ "@aws-sdk/credential-provider-sso": "3.774.0",
+ "@aws-sdk/credential-provider-web-identity": "3.774.0",
+ "@aws-sdk/nested-clients": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/credential-provider-imds": "^4.0.1",
"@smithy/property-provider": "^4.0.1",
@@ -721,17 +722,17 @@
}
},
"node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.741.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.741.0.tgz",
- "integrity": "sha512-iz/puK9CZZkZjrKXX2W+PaiewHtlcD7RKUIsw4YHFyb8lrOt7yTYpM6VjeI+T//1sozjymmAnnp1SST9TXApLQ==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.774.0.tgz",
+ "integrity": "sha512-/t+TNhHNW6BNyf7Lgv6I0NUfFk6/dz4+6dUjopRxpDVJtp1YvNza0Zhl25ffRkqX4CKmuXyJYusDbbObcsncUA==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/credential-provider-env": "3.734.0",
- "@aws-sdk/credential-provider-http": "3.734.0",
- "@aws-sdk/credential-provider-ini": "3.741.0",
- "@aws-sdk/credential-provider-process": "3.734.0",
- "@aws-sdk/credential-provider-sso": "3.734.0",
- "@aws-sdk/credential-provider-web-identity": "3.734.0",
+ "@aws-sdk/credential-provider-env": "3.774.0",
+ "@aws-sdk/credential-provider-http": "3.774.0",
+ "@aws-sdk/credential-provider-ini": "3.774.0",
+ "@aws-sdk/credential-provider-process": "3.774.0",
+ "@aws-sdk/credential-provider-sso": "3.774.0",
+ "@aws-sdk/credential-provider-web-identity": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/credential-provider-imds": "^4.0.1",
"@smithy/property-provider": "^4.0.1",
@@ -744,12 +745,12 @@
}
},
"node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.734.0.tgz",
- "integrity": "sha512-zvjsUo+bkYn2vjT+EtLWu3eD6me+uun+Hws1IyWej/fKFAqiBPwyeyCgU7qjkiPQSXqk1U9+/HG9IQ6Iiz+eBw==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.774.0.tgz",
+ "integrity": "sha512-lycBRY1NeWa46LefN258m1MRVUPQgvf6TPA6ZYajyq6/dCr6BPeuUoUAyrzePTPlxV/M25YXNiyORHjjwlK0ug==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/property-provider": "^4.0.1",
"@smithy/shared-ini-file-loader": "^4.0.1",
@@ -761,14 +762,14 @@
}
},
"node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.734.0.tgz",
- "integrity": "sha512-cCwwcgUBJOsV/ddyh1OGb4gKYWEaTeTsqaAK19hiNINfYV/DO9r4RMlnWAo84sSBfJuj9shUNsxzyoe6K7R92Q==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.774.0.tgz",
+ "integrity": "sha512-j7vbGCWF6dVpd9qiT0PQGzY4NKf8KUa86sSoosGGbtu0dV9T/Y0s/fvPZ0F8ZyuPIKUMJaBpIJYZ/ECZRfT2mg==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/client-sso": "3.734.0",
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/token-providers": "3.734.0",
+ "@aws-sdk/client-sso": "3.774.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/token-providers": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/property-provider": "^4.0.1",
"@smithy/shared-ini-file-loader": "^4.0.1",
@@ -780,13 +781,13 @@
}
},
"node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.734.0.tgz",
- "integrity": "sha512-t4OSOerc+ppK541/Iyn1AS40+2vT/qE+MFMotFkhCgCJbApeRF2ozEdnDN6tGmnl4ybcUuxnp9JWLjwDVlR/4g==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.774.0.tgz",
+ "integrity": "sha512-kuE5Hdqm9xXdrYBWCU6l2aM3W3HBtZrIBgyf0y41LulJHwld1nvIySus/lILdzbipmUAv9FI07B8TF5y7p/aFA==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/nested-clients": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/nested-clients": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/property-provider": "^4.0.1",
"@smithy/types": "^4.1.0",
@@ -861,22 +862,22 @@
}
},
"node_modules/@aws-sdk/middleware-flexible-checksums": {
- "version": "3.735.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.735.0.tgz",
- "integrity": "sha512-Tx7lYTPwQFRe/wQEHMR6Drh/S+X0ToAEq1Ava9QyxV1riwtepzRLojpNDELFb3YQVVYbX7FEiBMCJLMkmIIY+A==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.774.0.tgz",
+ "integrity": "sha512-S0vs+U7sEZkRRnjf05KCbEHDduyxGgNPq+ZeaiyWbs5yTZ8wzSYrSzMAKcbCqAseNVYQbpGMXDh8tnzx6H/ihw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/crc32": "5.2.0",
"@aws-crypto/crc32c": "5.2.0",
"@aws-crypto/util": "5.2.0",
- "@aws-sdk/core": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/is-array-buffer": "^4.0.0",
"@smithy/node-config-provider": "^4.0.1",
"@smithy/protocol-http": "^5.0.1",
"@smithy/types": "^4.1.0",
"@smithy/util-middleware": "^4.0.1",
- "@smithy/util-stream": "^4.0.2",
+ "@smithy/util-stream": "^4.1.2",
"@smithy/util-utf8": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -885,9 +886,9 @@
}
},
"node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.734.0.tgz",
- "integrity": "sha512-LW7RRgSOHHBzWZnigNsDIzu3AiwtjeI2X66v+Wn1P1u+eXssy1+up4ZY/h+t2sU4LU36UvEf+jrZti9c6vRnFw==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.774.0.tgz",
+ "integrity": "sha512-7QHA0ZyEBVfyJqmIc0FW4MUtPdrWhDsHQudsvBCHFS+mqP5fhpU/o4e5RQ+0M7tQqDE65+8MrZRniRa+Txz3xA==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.734.0",
@@ -928,9 +929,9 @@
}
},
"node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.734.0.tgz",
- "integrity": "sha512-CUat2d9ITsFc2XsmeiRQO96iWpxSKYFjxvj27Hc7vo87YUHRnfMfnc8jw1EpxEwMcvBD7LsRa6vDNky6AjcrFA==",
+ "version": "3.772.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.772.0.tgz",
+ "integrity": "sha512-zg0LjJa4v7fcLzn5QzZvtVS+qyvmsnu7oQnb86l6ckduZpWDCDC9+A0ZzcXTrxblPCJd3JqkoG1+Gzi4S4Ny/Q==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.734.0",
@@ -943,23 +944,23 @@
}
},
"node_modules/@aws-sdk/middleware-sdk-s3": {
- "version": "3.740.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.740.0.tgz",
- "integrity": "sha512-VML9TzNoQdAs5lSPQSEgZiPgMUSz2H7SltaLb9g4tHwKK5xQoTq5WcDd6V1d2aPxSN5Q2Q63aiVUBby6MdUN/Q==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.774.0.tgz",
+ "integrity": "sha512-iMEaOj+S8LZfg7fZaSfXQ8YDtEfOSBiQUllyxzaVhSYlM7IeNDbpBdCWnRi34VrI1J1AuryMdX/foU9JNSTLXg==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@aws-sdk/util-arn-parser": "3.723.0",
- "@smithy/core": "^3.1.1",
+ "@smithy/core": "^3.1.5",
"@smithy/node-config-provider": "^4.0.1",
"@smithy/protocol-http": "^5.0.1",
"@smithy/signature-v4": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
"@smithy/util-config-provider": "^4.0.0",
"@smithy/util-middleware": "^4.0.1",
- "@smithy/util-stream": "^4.0.2",
+ "@smithy/util-stream": "^4.1.2",
"@smithy/util-utf8": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -982,15 +983,15 @@
}
},
"node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.734.0.tgz",
- "integrity": "sha512-MFVzLWRkfFz02GqGPjqSOteLe5kPfElUrXZft1eElnqulqs6RJfVSpOV7mO90gu293tNAeggMWAVSGRPKIYVMg==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.774.0.tgz",
+ "integrity": "sha512-SVDeBV6DESgc9zex1Wk5XYbUqRI1tmJYQor47uKqD18r6UaCpvzVOBP4x8l/6hteAYxsWER6ZZmsjBQkenEuFQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/core": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
"@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.734.0",
- "@smithy/core": "^3.1.1",
+ "@aws-sdk/util-endpoints": "3.743.0",
+ "@smithy/core": "^3.1.5",
"@smithy/protocol-http": "^5.0.1",
"@smithy/types": "^4.1.0",
"tslib": "^2.6.2"
@@ -1000,44 +1001,44 @@
}
},
"node_modules/@aws-sdk/nested-clients": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.734.0.tgz",
- "integrity": "sha512-iph2XUy8UzIfdJFWo1r0Zng9uWj3253yvW9gljhtu+y/LNmNvSnJxQk1f3D2BC5WmcoPZqTS3UsycT3mLPSzWA==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.774.0.tgz",
+ "integrity": "sha512-00+UiYvxiZaDFVzn87kPpiZ/GiEWNaTNzC82C+bIyXt1M9AnAR6PAnnvMErTFwyG+Un6n2ai/I81wvJ1ftFmeQ==",
"license": "Apache-2.0",
"dependencies": {
"@aws-crypto/sha256-browser": "5.2.0",
"@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.734.0",
- "@aws-sdk/middleware-host-header": "3.734.0",
+ "@aws-sdk/core": "3.774.0",
+ "@aws-sdk/middleware-host-header": "3.774.0",
"@aws-sdk/middleware-logger": "3.734.0",
- "@aws-sdk/middleware-recursion-detection": "3.734.0",
- "@aws-sdk/middleware-user-agent": "3.734.0",
+ "@aws-sdk/middleware-recursion-detection": "3.772.0",
+ "@aws-sdk/middleware-user-agent": "3.774.0",
"@aws-sdk/region-config-resolver": "3.734.0",
"@aws-sdk/types": "3.734.0",
- "@aws-sdk/util-endpoints": "3.734.0",
+ "@aws-sdk/util-endpoints": "3.743.0",
"@aws-sdk/util-user-agent-browser": "3.734.0",
- "@aws-sdk/util-user-agent-node": "3.734.0",
+ "@aws-sdk/util-user-agent-node": "3.774.0",
"@smithy/config-resolver": "^4.0.1",
- "@smithy/core": "^3.1.1",
+ "@smithy/core": "^3.1.5",
"@smithy/fetch-http-handler": "^5.0.1",
"@smithy/hash-node": "^4.0.1",
"@smithy/invalid-dependency": "^4.0.1",
"@smithy/middleware-content-length": "^4.0.1",
- "@smithy/middleware-endpoint": "^4.0.2",
- "@smithy/middleware-retry": "^4.0.3",
- "@smithy/middleware-serde": "^4.0.1",
+ "@smithy/middleware-endpoint": "^4.0.6",
+ "@smithy/middleware-retry": "^4.0.7",
+ "@smithy/middleware-serde": "^4.0.2",
"@smithy/middleware-stack": "^4.0.1",
"@smithy/node-config-provider": "^4.0.1",
- "@smithy/node-http-handler": "^4.0.2",
+ "@smithy/node-http-handler": "^4.0.3",
"@smithy/protocol-http": "^5.0.1",
- "@smithy/smithy-client": "^4.1.2",
+ "@smithy/smithy-client": "^4.1.6",
"@smithy/types": "^4.1.0",
"@smithy/url-parser": "^4.0.1",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-body-length-browser": "^4.0.0",
"@smithy/util-body-length-node": "^4.0.0",
- "@smithy/util-defaults-mode-browser": "^4.0.3",
- "@smithy/util-defaults-mode-node": "^4.0.3",
+ "@smithy/util-defaults-mode-browser": "^4.0.7",
+ "@smithy/util-defaults-mode-node": "^4.0.7",
"@smithy/util-endpoints": "^3.0.1",
"@smithy/util-middleware": "^4.0.1",
"@smithy/util-retry": "^4.0.1",
@@ -1162,12 +1163,12 @@
}
},
"node_modules/@aws-sdk/signature-v4-multi-region": {
- "version": "3.740.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.740.0.tgz",
- "integrity": "sha512-w+psidN3i+kl51nQEV3V+fKjKUqcEbqUA1GtubruDBvBqrl5El/fU2NF3Lo53y8CfI9wCdf3V7KOEpHIqxHNng==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.774.0.tgz",
+ "integrity": "sha512-vQwATjZfl5vxfO+BDUH7nUnhfKoIJMnBmOxmUh4N10PWlz3WWwkT/YtH79nVpr+y1eM6GQUSGuNa4Reda6SaFA==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/middleware-sdk-s3": "3.740.0",
+ "@aws-sdk/middleware-sdk-s3": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/protocol-http": "^5.0.1",
"@smithy/signature-v4": "^5.0.1",
@@ -1179,12 +1180,12 @@
}
},
"node_modules/@aws-sdk/token-providers": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.734.0.tgz",
- "integrity": "sha512-2U6yWKrjWjZO8Y5SHQxkFvMVWHQWbS0ufqfAIBROqmIZNubOL7jXCiVdEFekz6MZ9LF2tvYGnOW4jX8OKDGfIw==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.774.0.tgz",
+ "integrity": "sha512-DDERwCduWFFXj7gx3qvnaB8GlnCUpQ8ZA03qI4QFokWu3EyHNK+hjp3nN5Dg81fI0Z82LRe30Q2uDsLBwNCZDg==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/nested-clients": "3.734.0",
+ "@aws-sdk/nested-clients": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/property-provider": "^4.0.1",
"@smithy/shared-ini-file-loader": "^4.0.1",
@@ -1221,9 +1222,9 @@
}
},
"node_modules/@aws-sdk/util-endpoints": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.734.0.tgz",
- "integrity": "sha512-w2+/E88NUbqql6uCVAsmMxDQKu7vsKV0KqhlQb0lL+RCq4zy07yXYptVNs13qrnuTfyX7uPXkXrlugvK9R1Ucg==",
+ "version": "3.743.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.743.0.tgz",
+ "integrity": "sha512-sN1l559zrixeh5x+pttrnd0A3+r34r0tmPkJ/eaaMaAzXqsmKU/xYre9K3FNnsSS1J1k4PEfk/nHDTVUgFYjnw==",
"license": "Apache-2.0",
"dependencies": {
"@aws-sdk/types": "3.734.0",
@@ -1288,12 +1289,12 @@
}
},
"node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.734.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.734.0.tgz",
- "integrity": "sha512-c6Iinh+RVQKs6jYUFQ64htOU2HUXFQ3TVx+8Tu3EDF19+9vzWi9UukhIMH9rqyyEXIAkk9XL7avt8y2Uyw2dGA==",
+ "version": "3.774.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.774.0.tgz",
+ "integrity": "sha512-kFmnK4sf5Wco8mkzO2PszqDXEwtQ5H896tUxqWDQhk67NtOLsHYfg98ymOBWWudth2POaldiIx6KFXtg0DvLLQ==",
"license": "Apache-2.0",
"dependencies": {
- "@aws-sdk/middleware-user-agent": "3.734.0",
+ "@aws-sdk/middleware-user-agent": "3.774.0",
"@aws-sdk/types": "3.734.0",
"@smithy/node-config-provider": "^4.0.1",
"@smithy/types": "^4.1.0",
@@ -1340,124 +1341,17 @@
}
},
"node_modules/@babel/generator": {
- "version": "7.17.7",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz",
- "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz",
+ "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.17.0",
- "jsesc": "^2.5.1",
- "source-map": "^0.5.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-environment-visitor": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz",
- "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.24.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-environment-visitor/node_modules/@babel/types": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
- "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-function-name": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz",
- "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/template": "^7.24.7",
- "@babel/types": "^7.24.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-function-name/node_modules/@babel/types": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
- "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-hoist-variables": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz",
- "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.24.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-hoist-variables/node_modules/@babel/types": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
- "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-split-export-declaration": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz",
- "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/types": "^7.24.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-split-export-declaration/node_modules/@babel/types": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
- "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
+ "@babel/parser": "^7.27.0",
+ "@babel/types": "^7.27.0",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
@@ -1484,13 +1378,13 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz",
- "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
+ "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.26.3"
+ "@babel/types": "^7.27.0"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1499,25 +1393,10 @@
"node": ">=6.0.0"
}
},
- "node_modules/@babel/parser/node_modules/@babel/types": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
- "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/runtime": {
"version": "7.26.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
"integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"regenerator-runtime": "^0.14.0"
@@ -1527,87 +1406,39 @@
}
},
"node_modules/@babel/template": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
- "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
+ "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.25.9",
- "@babel/parser": "^7.25.9",
- "@babel/types": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/template/node_modules/@babel/types": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
- "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
+ "@babel/code-frame": "^7.26.2",
+ "@babel/parser": "^7.27.0",
+ "@babel/types": "^7.27.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.23.2",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
- "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz",
+ "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.22.13",
- "@babel/generator": "^7.23.0",
- "@babel/helper-environment-visitor": "^7.22.20",
- "@babel/helper-function-name": "^7.23.0",
- "@babel/helper-hoist-variables": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/parser": "^7.23.0",
- "@babel/types": "^7.23.0",
- "debug": "^4.1.0",
+ "@babel/code-frame": "^7.26.2",
+ "@babel/generator": "^7.27.0",
+ "@babel/parser": "^7.27.0",
+ "@babel/template": "^7.27.0",
+ "@babel/types": "^7.27.0",
+ "debug": "^4.3.1",
"globals": "^11.1.0"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/traverse/node_modules/@babel/generator": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz",
- "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/parser": "^7.26.3",
- "@babel/types": "^7.26.3",
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse/node_modules/@babel/types": {
- "version": "7.26.3",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz",
- "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/traverse/node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@@ -1618,28 +1449,15 @@
"node": ">=4"
}
},
- "node_modules/@babel/traverse/node_modules/jsesc": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
- "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/@babel/types": {
- "version": "7.17.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz",
- "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==",
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
+ "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.16.7",
- "to-fast-properties": "^2.0.0"
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
@@ -1666,15 +1484,15 @@
}
},
"node_modules/@datadog/libdatadog": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@datadog/libdatadog/-/libdatadog-0.4.0.tgz",
- "integrity": "sha512-kGZfFVmQInzt6J4FFGrqMbrDvOxqwk3WqhAreS6n9b/De+iMVy/NMu3V7uKsY5zAvz+uQw0liDJm3ZDVH/MVVw==",
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/@datadog/libdatadog/-/libdatadog-0.5.0.tgz",
+ "integrity": "sha512-YvLUVOhYVjJssm0f22/RnDQMc7ZZt/w1bA0nty1vvjyaDz5EWaHfWaaV4GYpCt5MRvnGjCBxIwwbRivmGseKeQ==",
"license": "Apache-2.0"
},
"node_modules/@datadog/native-appsec": {
- "version": "8.4.0",
- "resolved": "https://registry.npmjs.org/@datadog/native-appsec/-/native-appsec-8.4.0.tgz",
- "integrity": "sha512-LC47AnpVLpQFEUOP/nIIs+i0wLb8XYO+et3ACaJlHa2YJM3asR4KZTqQjDQNy08PTAUbVvYWKwfSR1qVsU/BeA==",
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/@datadog/native-appsec/-/native-appsec-8.5.0.tgz",
+ "integrity": "sha512-95y+fm7jd+3iknzuu57pWEPw9fcK9uSBCPiB4kSPHszHu3bESlZM553tc4ANsz+X3gMkYGVg2pgSydG77nSDJw==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1685,9 +1503,9 @@
}
},
"node_modules/@datadog/native-iast-rewriter": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.6.1.tgz",
- "integrity": "sha512-zv7cr/MzHg560jhAnHcO7f9pLi4qaYrBEcB+Gla0xkVouYSDsp8cGXIGG4fiGdAMHdt7SpDNS6+NcEAqD/v8Ig==",
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.8.0.tgz",
+ "integrity": "sha512-DKmtvlmCld9RIJwDcPKWNkKYWYQyiuOrOtynmBppJiUv/yfCOuZtsQV4Zepj40H33sLiQyi5ct6dbWl53vxqkA==",
"license": "Apache-2.0",
"dependencies": {
"lru-cache": "^7.14.0",
@@ -1709,9 +1527,9 @@
}
},
"node_modules/@datadog/native-iast-taint-tracking": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.2.0.tgz",
- "integrity": "sha512-Mc6FzCoyvU5yXLMsMS9yKnEqJMWoImAukJXolNWCTm+JQYCMf2yMsJ8pBAm7KyZKliamM9rCn7h7Tr2H3lXwjA==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.3.0.tgz",
+ "integrity": "sha512-OzmjOncer199ATSYeCAwSACCRyQimo77LKadSHDUcxa/n9FYU+2U/bYQTYsK3vquSA2E47EbSVq9rytrlTdvnA==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1733,9 +1551,9 @@
}
},
"node_modules/@datadog/pprof": {
- "version": "5.5.1",
- "resolved": "https://registry.npmjs.org/@datadog/pprof/-/pprof-5.5.1.tgz",
- "integrity": "sha512-3pZVYqc5YkZJOj9Rc8kQ/wG4qlygcnnwFU/w0QKX6dEdJh+1+dWniuUu+GSEjy/H0jc14yhdT2eJJf/F2AnHNw==",
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/@datadog/pprof/-/pprof-5.6.0.tgz",
+ "integrity": "sha512-x7yN0s4wMnRqv3PWQ6eXKH5XE5qvCOwWbOsXqpT2Irbsc7Wcl5w5JrJUcbPCdSJGihpIh6kAeIrS6w/ZCcHy2Q==",
"hasInstallScript": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1749,15 +1567,6 @@
"node": ">=16"
}
},
- "node_modules/@datadog/pprof/node_modules/source-map": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
- "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/@datadog/sketches-js": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@datadog/sketches-js/-/sketches-js-2.1.1.tgz",
@@ -1807,13 +1616,13 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz",
- "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
+ "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^2.1.5",
+ "@eslint/object-schema": "^2.1.6",
"debug": "^4.3.1",
"minimatch": "^3.1.2"
},
@@ -1821,10 +1630,20 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz",
+ "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
"node_modules/@eslint/core": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.10.0.tgz",
- "integrity": "sha512-gFHJ+xBOo4G3WRlR1e/3G8A6/KZAH6zcE/hkLRCZTi/B9avAG365QhFA8uOGzTMqgTghpn7/fSnscW++dpMSAw==",
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
+ "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -1835,9 +1654,9 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz",
- "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1872,9 +1691,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "9.19.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.19.0.tgz",
- "integrity": "sha512-rbq9/g38qjfqFLOVPvwjIvFFdNziEC5S65jmjPw5r6A//QH+W91akh9irMwjDN8zKUTak6W9EsAv4m/7Wnw0UQ==",
+ "version": "9.23.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz",
+ "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1882,9 +1701,9 @@
}
},
"node_modules/@eslint/object-schema": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz",
- "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==",
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -1892,13 +1711,13 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.5.tgz",
- "integrity": "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A==",
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz",
+ "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^0.10.0",
+ "@eslint/core": "^0.12.0",
"levn": "^0.4.1"
},
"engines": {
@@ -2194,9 +2013,9 @@
}
},
"node_modules/@humanwhocodes/retry": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
- "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz",
+ "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
@@ -2296,9 +2115,9 @@
"license": "MIT"
},
"node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
- "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "version": "0.3.8",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
+ "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2422,6 +2241,84 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.3.tgz",
+ "integrity": "sha512-QZHtlVgbAdy2zAqNA9Gu1UpIuI8Xvsd1v8ic6B2pZmeFnFcMWiPLfWXh7TVw4eGEZ/C9TH281KwhVoeQUKbyjw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.3.tgz",
+ "integrity": "sha512-mdzd3AVzYKuUmiWOQ8GNhl64/IoFGol569zNRdkLReh6LRLHOXxU4U8eq0JwaD8iFHdVGqSy4IjFL4reoWCDFw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.3.tgz",
+ "integrity": "sha512-fg0uy/dG/nZEXfYilKoRe7yALaNmHoYeIoJuJ7KJ+YyU2bvY8vPv27f7UKhGRpY6euFYqEVhxCFZgAUNQBM3nw==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.3.tgz",
+ "integrity": "sha512-YxQL+ax0XqBJDZiKimS2XQaf+2wDGVa1enVRGzEvLLVFeqa5kx2bWbtcSXgsxjQB7nRqqIGFIcLteF/sHeVtQg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.3.tgz",
+ "integrity": "sha512-cvwNfbP07pKUfq1uH+S6KJ7dT9K8WOE4ZiAcsrSes+UY55E/0jLYc+vq+DO7jlmqRb5zAggExKm0H7O/CBaesg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.3.tgz",
+ "integrity": "sha512-x0fWaQtYp4E6sktbsdAqnehxDgEc/VwM7uLsRCYWaiGu0ykYdZPiS8zCWdnjHwyiumousxfBm4SO31eXqwEZhQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
"node_modules/@oozcitak/dom": {
"version": "1.15.10",
"resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-1.15.10.tgz",
@@ -2655,12 +2552,12 @@
}
},
"node_modules/@smithy/abort-controller": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.1.tgz",
- "integrity": "sha512-fiUIYgIgRjMWznk6iLJz35K2YxSLHzLBA/RC6lBrKfQ8fHbPfvk7Pk9UvpKoHgJjI18MnbPuEju53zcVy6KF1g==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.0.2.tgz",
+ "integrity": "sha512-Sl/78VDtgqKxN2+1qduaVE140XF+Xg+TafkncspwM4jFP/LHr76ZHmIY/y3V1M0mMLNk+Je6IGbzxy23RSToMw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2693,15 +2590,15 @@
}
},
"node_modules/@smithy/config-resolver": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.0.1.tgz",
- "integrity": "sha512-Igfg8lKu3dRVkTSEm98QpZUvKEOa71jDX4vKRcvJVyRc3UgN3j7vFMf0s7xLQhYmKa8kyJGQgUJDOV5V3neVlQ==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.1.0.tgz",
+ "integrity": "sha512-8smPlwhga22pwl23fM5ew4T9vfLUCeFXlcqNOCD5M5h8VmNPNUE9j6bQSuRXpDSV11L/E/SwEBQuW8hr6+nS1A==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/node-config-provider": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"@smithy/util-config-provider": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
+ "@smithy/util-middleware": "^4.0.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -2709,17 +2606,17 @@
}
},
"node_modules/@smithy/core": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.1.2.tgz",
- "integrity": "sha512-htwQXkbdF13uwwDevz9BEzL5ABK+1sJpVQXywwGSH973AVOvisHNfpcB8A8761G6XgHoS2kHPqc9DqHJ2gp+/Q==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.2.0.tgz",
+ "integrity": "sha512-k17bgQhVZ7YmUvA8at4af1TDpl0NDMBuBKJl8Yg0nrefwmValU+CnA5l/AriVdQNthU/33H3nK71HrLgqOPr1Q==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/middleware-serde": "^4.0.3",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
"@smithy/util-body-length-browser": "^4.0.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-stream": "^4.0.2",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-stream": "^4.2.0",
"@smithy/util-utf8": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -2728,15 +2625,15 @@
}
},
"node_modules/@smithy/credential-provider-imds": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.1.tgz",
- "integrity": "sha512-l/qdInaDq1Zpznpmev/+52QomsJNZ3JkTl5yrTl02V6NBgJOQ4LY0SFw/8zsMwj3tLe8vqiIuwF6nxaEwgf6mg==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.0.2.tgz",
+ "integrity": "sha512-32lVig6jCaWBHnY+OEQ6e6Vnt5vDHaLiydGrwYMW9tPqO688hPGTYRamYJ1EptxEC2rAwJrHWmPoKRBl4iTa8w==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
+ "@smithy/node-config-provider": "^4.0.2",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "@smithy/url-parser": "^4.0.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -2814,14 +2711,14 @@
}
},
"node_modules/@smithy/fetch-http-handler": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.1.tgz",
- "integrity": "sha512-3aS+fP28urrMW2KTjb6z9iFow6jO8n3MFfineGbndvzGZit3taZhKWtTorf+Gp5RpFDDafeHlhfsGlDCXvUnJA==",
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.0.2.tgz",
+ "integrity": "sha512-+9Dz8sakS9pe7f2cBocpJXdeVjMopUDLgZs1yWeu7h++WqSbjUYv/JAJwKwXw1HV6gq1jyWjxuyn24E2GhoEcQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/querystring-builder": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/querystring-builder": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"@smithy/util-base64": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -2927,18 +2824,18 @@
}
},
"node_modules/@smithy/middleware-endpoint": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.0.3.tgz",
- "integrity": "sha512-YdbmWhQF5kIxZjWqPIgboVfi8i5XgiYMM7GGKFMTvBei4XjNQfNv8sukT50ITvgnWKKKpOtp0C0h7qixLgb77Q==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.1.0.tgz",
+ "integrity": "sha512-xhLimgNCbCzsUppRTGXWkZywksuTThxaIB0HwbpsVLY5sceac4e1TZ/WKYqufQLaUy+gUSJGNdwD2jo3cXL0iA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/core": "^3.1.2",
- "@smithy/middleware-serde": "^4.0.2",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/url-parser": "^4.0.1",
- "@smithy/util-middleware": "^4.0.1",
+ "@smithy/core": "^3.2.0",
+ "@smithy/middleware-serde": "^4.0.3",
+ "@smithy/node-config-provider": "^4.0.2",
+ "@smithy/shared-ini-file-loader": "^4.0.2",
+ "@smithy/types": "^4.2.0",
+ "@smithy/url-parser": "^4.0.2",
+ "@smithy/util-middleware": "^4.0.2",
"tslib": "^2.6.2"
},
"engines": {
@@ -2946,18 +2843,18 @@
}
},
"node_modules/@smithy/middleware-retry": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.0.4.tgz",
- "integrity": "sha512-wmxyUBGHaYUqul0wZiset4M39SMtDBOtUr2KpDuftKNN74Do9Y36Go6Eqzj9tL0mIPpr31ulB5UUtxcsCeGXsQ==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.1.0.tgz",
+ "integrity": "sha512-2zAagd1s6hAaI/ap6SXi5T3dDwBOczOMCSkkYzktqN1+tzbk1GAsHNAdo/1uzxz3Ky02jvZQwbi/vmDA6z4Oyg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/service-error-classification": "^4.0.1",
- "@smithy/smithy-client": "^4.1.3",
- "@smithy/types": "^4.1.0",
- "@smithy/util-middleware": "^4.0.1",
- "@smithy/util-retry": "^4.0.1",
+ "@smithy/node-config-provider": "^4.0.2",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/service-error-classification": "^4.0.2",
+ "@smithy/smithy-client": "^4.2.0",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-middleware": "^4.0.2",
+ "@smithy/util-retry": "^4.0.2",
"tslib": "^2.6.2",
"uuid": "^9.0.1"
},
@@ -2979,12 +2876,12 @@
}
},
"node_modules/@smithy/middleware-serde": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.2.tgz",
- "integrity": "sha512-Sdr5lOagCn5tt+zKsaW+U2/iwr6bI9p08wOkCp6/eL6iMbgdtc2R5Ety66rf87PeohR0ExI84Txz9GYv5ou3iQ==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.0.3.tgz",
+ "integrity": "sha512-rfgDVrgLEVMmMn0BI8O+8OVr6vXzjV7HZj57l0QxslhzbvVfikZbVfBVthjLHqib4BW44QhcIgJpvebHlRaC9A==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -2992,12 +2889,12 @@
}
},
"node_modules/@smithy/middleware-stack": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.1.tgz",
- "integrity": "sha512-dHwDmrtR/ln8UTHpaIavRSzeIk5+YZTBtLnKwDW3G2t6nAupCiQUvNzNoHBpik63fwUaJPtlnMzXbQrNFWssIA==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.0.2.tgz",
+ "integrity": "sha512-eSPVcuJJGVYrFYu2hEq8g8WWdJav3sdrI4o2c6z/rjnYDd3xH9j9E7deZQCzFn4QvGPouLngH3dQ+QVTxv5bOQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3005,14 +2902,14 @@
}
},
"node_modules/@smithy/node-config-provider": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.1.tgz",
- "integrity": "sha512-8mRTjvCtVET8+rxvmzRNRR0hH2JjV0DFOmwXPrISmTIJEfnCBugpYYGAsCj8t41qd+RB5gbheSQ/6aKZCQvFLQ==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.0.2.tgz",
+ "integrity": "sha512-WgCkILRZfJwJ4Da92a6t3ozN/zcvYyJGUTmfGbgS/FkCcoCjl7G4FJaCDN1ySdvLvemnQeo25FdkyMSTSwulsw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/property-provider": "^4.0.1",
- "@smithy/shared-ini-file-loader": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/shared-ini-file-loader": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3020,15 +2917,15 @@
}
},
"node_modules/@smithy/node-http-handler": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.2.tgz",
- "integrity": "sha512-X66H9aah9hisLLSnGuzRYba6vckuFtGE+a5DcHLliI/YlqKrGoxhisD5XbX44KyoeRzoNlGr94eTsMVHFAzPOw==",
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.0.4.tgz",
+ "integrity": "sha512-/mdqabuAT3o/ihBGjL94PUbTSPSRJ0eeVTdgADzow0wRJ0rN4A27EOrtlK56MYiO1fDvlO3jVTCxQtQmK9dZ1g==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/abort-controller": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/querystring-builder": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/abort-controller": "^4.0.2",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/querystring-builder": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3036,12 +2933,12 @@
}
},
"node_modules/@smithy/property-provider": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.1.tgz",
- "integrity": "sha512-o+VRiwC2cgmk/WFV0jaETGOtX16VNPp2bSQEzu0whbReqE1BMqsP2ami2Vi3cbGVdKu1kq9gQkDAGKbt0WOHAQ==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.0.2.tgz",
+ "integrity": "sha512-wNRoQC1uISOuNc2s4hkOYwYllmiyrvVXWMtq+TysNRVQaHm4yoafYQyjN/goYZS+QbYlPIbb/QRjaUZMuzwQ7A==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3049,12 +2946,12 @@
}
},
"node_modules/@smithy/protocol-http": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz",
- "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.1.0.tgz",
+ "integrity": "sha512-KxAOL1nUNw2JTYrtviRRjEnykIDhxc84qMBzxvu1MUfQfHTuBlCG7PA6EdVwqpJjH7glw7FqQoFxUJSyBQgu7g==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3062,12 +2959,12 @@
}
},
"node_modules/@smithy/querystring-builder": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.1.tgz",
- "integrity": "sha512-wU87iWZoCbcqrwszsOewEIuq+SU2mSoBE2CcsLwE0I19m0B2gOJr1MVjxWcDQYOzHbR1xCk7AcOBbGFUYOKvdg==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.0.2.tgz",
+ "integrity": "sha512-NTOs0FwHw1vimmQM4ebh+wFQvOwkEf/kQL6bSM1Lock+Bv4I89B3hGYoUEPkmvYPkDKyp5UdXJYu+PoTQ3T31Q==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"@smithy/util-uri-escape": "^4.0.0",
"tslib": "^2.6.2"
},
@@ -3076,12 +2973,12 @@
}
},
"node_modules/@smithy/querystring-parser": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.1.tgz",
- "integrity": "sha512-Ma2XC7VS9aV77+clSFylVUnPZRindhB7BbmYiNOdr+CHt/kZNJoPP0cd3QxCnCFyPXC4eybmyE98phEHkqZ5Jw==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.0.2.tgz",
+ "integrity": "sha512-v6w8wnmZcVXjfVLjxw8qF7OwESD9wnpjp0Dqry/Pod0/5vcEA3qxCr+BhbOHlxS8O+29eLpT3aagxXGwIoEk7Q==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3089,24 +2986,24 @@
}
},
"node_modules/@smithy/service-error-classification": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.1.tgz",
- "integrity": "sha512-3JNjBfOWpj/mYfjXJHB4Txc/7E4LVq32bwzE7m28GN79+M1f76XHflUaSUkhOriprPDzev9cX/M+dEB80DNDKA==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.0.2.tgz",
+ "integrity": "sha512-LA86xeFpTKn270Hbkixqs5n73S+LVM0/VZco8dqd+JT75Dyx3Lcw/MraL7ybjmz786+160K8rPOmhsq0SocoJQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0"
+ "@smithy/types": "^4.2.0"
},
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@smithy/shared-ini-file-loader": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.1.tgz",
- "integrity": "sha512-hC8F6qTBbuHRI/uqDgqqi6J0R4GtEZcgrZPhFQnMhfJs3MnUTGSnR1NSJCJs5VWlMydu0kJz15M640fJlRsIOw==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.0.2.tgz",
+ "integrity": "sha512-J9/gTWBGVuFZ01oVA6vdb4DAjf1XbDhK6sLsu3OS9qmLrS6KB5ygpeHiM3miIbj1qgSJ96GYszXFWv6ErJ8QEw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3133,17 +3030,17 @@
}
},
"node_modules/@smithy/smithy-client": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.1.3.tgz",
- "integrity": "sha512-A2Hz85pu8BJJaYFdX8yb1yocqigyqBzn+OVaVgm+Kwi/DkN8vhN2kbDVEfADo6jXf5hPKquMLGA3UINA64UZ7A==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.2.0.tgz",
+ "integrity": "sha512-Qs65/w30pWV7LSFAez9DKy0Koaoh3iHhpcpCCJ4waj/iqwsuSzJna2+vYwq46yBaqO5ZbP9TjUsATUNxrKeBdw==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/core": "^3.1.2",
- "@smithy/middleware-endpoint": "^4.0.3",
- "@smithy/middleware-stack": "^4.0.1",
- "@smithy/protocol-http": "^5.0.1",
- "@smithy/types": "^4.1.0",
- "@smithy/util-stream": "^4.0.2",
+ "@smithy/core": "^3.2.0",
+ "@smithy/middleware-endpoint": "^4.1.0",
+ "@smithy/middleware-stack": "^4.0.2",
+ "@smithy/protocol-http": "^5.1.0",
+ "@smithy/types": "^4.2.0",
+ "@smithy/util-stream": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3151,9 +3048,9 @@
}
},
"node_modules/@smithy/types": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz",
- "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.2.0.tgz",
+ "integrity": "sha512-7eMk09zQKCO+E/ivsjQv+fDlOupcFUCSC/L2YUPgwhvowVGWbPQHjEFcmjt7QQ4ra5lyowS92SV53Zc6XD4+fg==",
"license": "Apache-2.0",
"dependencies": {
"tslib": "^2.6.2"
@@ -3163,13 +3060,13 @@
}
},
"node_modules/@smithy/url-parser": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz",
- "integrity": "sha512-gPXcIEUtw7VlK8f/QcruNXm7q+T5hhvGu9tl63LsJPZ27exB6dtNwvh2HIi0v7JcXJ5emBxB+CJxwaLEdJfA+g==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.2.tgz",
+ "integrity": "sha512-Bm8n3j2ScqnT+kJaClSVCMeiSenK6jVAzZCNewsYWuZtnBehEz4r2qP0riZySZVfzB+03XZHJeqfmJDkeeSLiQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/querystring-parser": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/querystring-parser": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3240,14 +3137,14 @@
}
},
"node_modules/@smithy/util-defaults-mode-browser": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.4.tgz",
- "integrity": "sha512-Ej1bV5sbrIfH++KnWxjjzFNq9nyP3RIUq2c9Iqq7SmMO/idUR24sqvKH2LUQFTSPy/K7G4sB2m8n7YYlEAfZaw==",
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.0.8.tgz",
+ "integrity": "sha512-ZTypzBra+lI/LfTYZeop9UjoJhhGRTg3pxrNpfSTQLd3AJ37r2z4AXTKpq1rFXiiUIJsYyFgNJdjWRGP/cbBaQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/property-provider": "^4.0.1",
- "@smithy/smithy-client": "^4.1.3",
- "@smithy/types": "^4.1.0",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/smithy-client": "^4.2.0",
+ "@smithy/types": "^4.2.0",
"bowser": "^2.11.0",
"tslib": "^2.6.2"
},
@@ -3256,17 +3153,17 @@
}
},
"node_modules/@smithy/util-defaults-mode-node": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.4.tgz",
- "integrity": "sha512-HE1I7gxa6yP7ZgXPCFfZSDmVmMtY7SHqzFF55gM/GPegzZKaQWZZ+nYn9C2Cc3JltCMyWe63VPR3tSFDEvuGjw==",
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.0.8.tgz",
+ "integrity": "sha512-Rgk0Jc/UDfRTzVthye/k2dDsz5Xxs9LZaKCNPgJTRyoyBoeiNCnHsYGOyu1PKN+sDyPnJzMOz22JbwxzBp9NNA==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/config-resolver": "^4.0.1",
- "@smithy/credential-provider-imds": "^4.0.1",
- "@smithy/node-config-provider": "^4.0.1",
- "@smithy/property-provider": "^4.0.1",
- "@smithy/smithy-client": "^4.1.3",
- "@smithy/types": "^4.1.0",
+ "@smithy/config-resolver": "^4.1.0",
+ "@smithy/credential-provider-imds": "^4.0.2",
+ "@smithy/node-config-provider": "^4.0.2",
+ "@smithy/property-provider": "^4.0.2",
+ "@smithy/smithy-client": "^4.2.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3300,12 +3197,12 @@
}
},
"node_modules/@smithy/util-middleware": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz",
- "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.2.tgz",
+ "integrity": "sha512-6GDamTGLuBQVAEuQ4yDQ+ti/YINf/MEmIegrEeg7DdB/sld8BX1lqt9RRuIcABOhAGTA50bRbPzErez7SlDtDQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/types": "^4.1.0",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3313,13 +3210,13 @@
}
},
"node_modules/@smithy/util-retry": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.1.tgz",
- "integrity": "sha512-WmRHqNVwn3kI3rKk1LsKcVgPBG6iLTBGC1iYOV3GQegwJ3E8yjzHytPt26VNzOWr1qu0xE03nK0Ug8S7T7oufw==",
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.2.tgz",
+ "integrity": "sha512-Qryc+QG+7BCpvjloFLQrmlSd0RsVRHejRXd78jNO3+oREueCjwG1CCEH1vduw/ZkM1U9TztwIKVIi3+8MJScGg==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/service-error-classification": "^4.0.1",
- "@smithy/types": "^4.1.0",
+ "@smithy/service-error-classification": "^4.0.2",
+ "@smithy/types": "^4.2.0",
"tslib": "^2.6.2"
},
"engines": {
@@ -3327,14 +3224,14 @@
}
},
"node_modules/@smithy/util-stream": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.0.2.tgz",
- "integrity": "sha512-0eZ4G5fRzIoewtHtwaYyl8g2C+osYOT4KClXgfdNEDAgkbe2TYPqcnw4GAWabqkZCax2ihRGPe9LZnsPdIUIHA==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.2.0.tgz",
+ "integrity": "sha512-Vj1TtwWnuWqdgQI6YTUF5hQ/0jmFiOYsc51CSMgj7QfyO+RF4EnT2HNjoviNlOOmgzgvf3f5yno+EiC4vrnaWQ==",
"license": "Apache-2.0",
"dependencies": {
- "@smithy/fetch-http-handler": "^5.0.1",
- "@smithy/node-http-handler": "^4.0.2",
- "@smithy/types": "^4.1.0",
+ "@smithy/fetch-http-handler": "^5.0.2",
+ "@smithy/node-http-handler": "^4.0.4",
+ "@smithy/types": "^4.2.0",
"@smithy/util-base64": "^4.0.0",
"@smithy/util-buffer-from": "^4.0.0",
"@smithy/util-hex-encoding": "^4.0.0",
@@ -3466,26 +3363,37 @@
}
},
"node_modules/@trivago/prettier-plugin-sort-imports": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz",
- "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==",
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-5.2.2.tgz",
+ "integrity": "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@babel/generator": "7.17.7",
- "@babel/parser": "^7.20.5",
- "@babel/traverse": "7.23.2",
- "@babel/types": "7.17.0",
- "javascript-natural-sort": "0.7.1",
+ "@babel/generator": "^7.26.5",
+ "@babel/parser": "^7.26.7",
+ "@babel/traverse": "^7.26.7",
+ "@babel/types": "^7.26.7",
+ "javascript-natural-sort": "^0.7.1",
"lodash": "^4.17.21"
},
+ "engines": {
+ "node": ">18.12"
+ },
"peerDependencies": {
"@vue/compiler-sfc": "3.x",
- "prettier": "2.x - 3.x"
+ "prettier": "2.x - 3.x",
+ "prettier-plugin-svelte": "3.x",
+ "svelte": "4.x || 5.x"
},
"peerDependenciesMeta": {
"@vue/compiler-sfc": {
"optional": true
+ },
+ "prettier-plugin-svelte": {
+ "optional": true
+ },
+ "svelte": {
+ "optional": true
}
}
},
@@ -3751,9 +3659,9 @@
}
},
"node_modules/acorn": {
- "version": "8.14.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
- "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "version": "8.14.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
+ "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -4029,7 +3937,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
"integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -4149,7 +4056,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
"integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"array-buffer-byte-length": "^1.0.1",
@@ -4202,7 +4108,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
"integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -4240,7 +4145,6 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"possible-typed-array-names": "^1.0.0"
@@ -4259,9 +4163,9 @@
"license": "MIT"
},
"node_modules/axios": {
- "version": "1.7.9",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
- "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
+ "version": "1.8.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
+ "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.15.6",
@@ -4270,12 +4174,12 @@
}
},
"node_modules/axios-ntlm": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/axios-ntlm/-/axios-ntlm-1.4.2.tgz",
- "integrity": "sha512-8mS/uhmSWiRBiFKQvysPbX1eDBp6e+eXskmasuAXRHrn1Zjgji3O/oGXzXLw7tOhyD9nho1vGjZ2OYOD3cCvHg==",
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/axios-ntlm/-/axios-ntlm-1.4.4.tgz",
+ "integrity": "sha512-kpCRdzMfL8gi0Z0o96P3QPAK4XuC8iciGgxGXe+PeQ4oyjI2LZN8WSOKbu0Y9Jo3T/A7pB81n6jYVPIpglEuRA==",
"license": "MIT",
"dependencies": {
- "axios": "^1.6.1",
+ "axios": "^1.8.4",
"des.js": "^1.1.0",
"dev-null": "^0.1.1",
"js-md4": "^0.3.2"
@@ -4344,6 +4248,48 @@
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==",
"license": "MIT"
},
+ "node_modules/bee-queue": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/bee-queue/-/bee-queue-1.7.1.tgz",
+ "integrity": "sha512-ZjF6/rf9DUsM7Ox1hfPNL16rYy1OBHgjdAcrE/mwH+iqaoX1UAgysB5aYloVfLcVmK/FplKXADLemoni4eQ+Kg==",
+ "license": "MIT",
+ "dependencies": {
+ "p-finally": "^2.0.0",
+ "promise-callbacks": "^3.8.1",
+ "redis": "^3.1.2"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/bee-queue/node_modules/denque": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
+ "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/bee-queue/node_modules/redis": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz",
+ "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==",
+ "license": "MIT",
+ "dependencies": {
+ "denque": "^1.5.0",
+ "redis-commands": "^1.7.0",
+ "redis-errors": "^1.2.0",
+ "redis-parser": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-redis"
+ }
+ },
"node_modules/better-queue": {
"version": "3.8.12",
"resolved": "https://registry.npmjs.org/better-queue/-/better-queue-3.8.12.tgz",
@@ -4517,6 +4463,34 @@
"node": ">=10.0.0"
}
},
+ "node_modules/bullmq": {
+ "version": "5.44.4",
+ "resolved": "https://registry.npmjs.org/bullmq/-/bullmq-5.44.4.tgz",
+ "integrity": "sha512-0BjgABM/7U85Fxatj586ftsoWiGdjmg7fR7PwRYNOOGfvGpiUX9nQoUmx+9VZW/OtHO/4um/BVh2Y2S9BEhKFg==",
+ "license": "MIT",
+ "dependencies": {
+ "cron-parser": "^4.9.0",
+ "ioredis": "^5.4.1",
+ "msgpackr": "^1.11.2",
+ "node-abort-controller": "^3.1.1",
+ "semver": "^7.5.4",
+ "tslib": "^2.0.0",
+ "uuid": "^9.0.0"
+ }
+ },
+ "node_modules/bullmq/node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/busboy": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
@@ -4541,7 +4515,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.0",
@@ -4633,9 +4606,9 @@
}
},
"node_modules/chart.js": {
- "version": "4.4.7",
- "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz",
- "integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==",
+ "version": "4.4.8",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.8.tgz",
+ "integrity": "sha512-IkGZlVpXP+83QpMm4uxEiGqSI7jFizwVtF3+n5Pc3k7sMO+tkd0qxh2OzLhenM0K80xtmAONWGBn082EiBQSDA==",
"license": "MIT",
"dependencies": {
"@kurkle/color": "^0.3.0"
@@ -4696,17 +4669,17 @@
}
},
"node_modules/cjs-module-lexer": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz",
- "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==",
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz",
+ "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==",
"license": "MIT"
},
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "devOptional": true,
"license": "ISC",
+ "optional": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
@@ -4720,8 +4693,8 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "devOptional": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@@ -4735,9 +4708,9 @@
}
},
"node_modules/cloudinary": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.5.1.tgz",
- "integrity": "sha512-CNg6uU53Hl4FEVynkTGpt5bQEAQWDHi3H+Sm62FzKf5uQHipSN2v7qVqS8GRVqeb0T1WNV+22+75DOJeRXYeSQ==",
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-2.6.0.tgz",
+ "integrity": "sha512-FIlny9RR5LPgkMioG4V7yUpC6ASyIFQMWfx4TgOi/xBeLxJTegbyQc3itiXL0b0lDlSaL0KyT2THEw6osrKqpQ==",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.21",
@@ -4894,9 +4867,9 @@
}
},
"node_modules/compression": {
- "version": "1.7.5",
- "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz",
- "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==",
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz",
+ "integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
@@ -4977,34 +4950,6 @@
"safe-buffer": "~5.1.0"
}
},
- "node_modules/concurrently": {
- "version": "8.2.2",
- "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-8.2.2.tgz",
- "integrity": "sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "chalk": "^4.1.2",
- "date-fns": "^2.30.0",
- "lodash": "^4.17.21",
- "rxjs": "^7.8.1",
- "shell-quote": "^1.8.1",
- "spawn-command": "0.0.2",
- "supports-color": "^8.1.1",
- "tree-kill": "^1.2.2",
- "yargs": "^17.7.2"
- },
- "bin": {
- "conc": "dist/bin/concurrently.js",
- "concurrently": "dist/bin/concurrently.js"
- },
- "engines": {
- "node": "^14.13.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
- }
- },
"node_modules/console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -5150,6 +5095,18 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/cron-parser": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz",
+ "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==",
+ "license": "MIT",
+ "dependencies": {
+ "luxon": "^3.2.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/cross-fetch": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz",
@@ -5240,7 +5197,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
"integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -5258,7 +5214,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
"integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -5276,7 +5231,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
"integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -5290,23 +5244,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/date-fns": {
- "version": "2.30.0",
- "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
- "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.21.0"
- },
- "engines": {
- "node": ">=0.11"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/date-fns"
- }
- },
"node_modules/dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
@@ -5323,18 +5260,18 @@
}
},
"node_modules/dd-trace": {
- "version": "5.35.0",
- "resolved": "https://registry.npmjs.org/dd-trace/-/dd-trace-5.35.0.tgz",
- "integrity": "sha512-buGy1mrW/HjkBiHMVyjW+zAzzJBtZbsC3dSYeO82ALYAGU3FvvGzvBMLcpKxg0cgAOdIlXKN2XZ2Zakj8WYCVw==",
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/dd-trace/-/dd-trace-5.43.0.tgz",
+ "integrity": "sha512-WtPUSZfEosSHYVBFR48FqfYBFor8QchKwAKo+LYtbgTPtFzYKyBV/FJUqYE6sDF15Raf4sJVt/LOscywgj2zEw==",
"hasInstallScript": true,
"license": "(Apache-2.0 OR BSD-3-Clause)",
"dependencies": {
- "@datadog/libdatadog": "^0.4.0",
- "@datadog/native-appsec": "8.4.0",
- "@datadog/native-iast-rewriter": "2.6.1",
- "@datadog/native-iast-taint-tracking": "3.2.0",
+ "@datadog/libdatadog": "^0.5.0",
+ "@datadog/native-appsec": "8.5.0",
+ "@datadog/native-iast-rewriter": "2.8.0",
+ "@datadog/native-iast-taint-tracking": "3.3.0",
"@datadog/native-metrics": "^3.1.0",
- "@datadog/pprof": "5.5.1",
+ "@datadog/pprof": "5.6.0",
"@datadog/sketches-js": "^2.1.0",
"@isaacs/ttlcache": "^1.4.1",
"@opentelemetry/api": ">=1.0.0 <1.9.0",
@@ -5342,7 +5279,7 @@
"crypto-randomuuid": "^1.0.0",
"dc-polyfill": "^0.1.4",
"ignore": "^5.2.4",
- "import-in-the-middle": "1.11.2",
+ "import-in-the-middle": "1.13.1",
"istanbul-lib-coverage": "3.2.0",
"jest-docblock": "^29.7.0",
"koalas": "^1.0.2",
@@ -5356,7 +5293,7 @@
"protobufjs": "^7.2.5",
"retry": "^0.13.1",
"rfdc": "^1.3.1",
- "semver": "^7.5.4",
+ "semifies": "^1.0.0",
"shell-quote": "^1.8.1",
"source-map": "^0.7.4",
"tlhunter-sorted-set": "^0.1.0",
@@ -5366,15 +5303,6 @@
"node": ">=18"
}
},
- "node_modules/dd-trace/node_modules/source-map": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
- "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
@@ -5421,7 +5349,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0",
@@ -5439,7 +5366,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"define-data-property": "^1.0.1",
@@ -5846,7 +5772,6 @@
"version": "1.23.9",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz",
"integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"array-buffer-byte-length": "^1.0.2",
@@ -5970,7 +5895,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -5996,7 +5920,6 @@
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
"integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-callable": "^1.2.7",
@@ -6052,22 +5975,23 @@
}
},
"node_modules/eslint": {
- "version": "9.19.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.19.0.tgz",
- "integrity": "sha512-ug92j0LepKlbbEv6hD911THhoRHmbdXt2gX+VDABAW/Ir7D3nqKdv5Pf5vtlyY6HQMTEP2skXY43ueqTCWssEA==",
+ "version": "9.23.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz",
+ "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.19.0",
- "@eslint/core": "^0.10.0",
- "@eslint/eslintrc": "^3.2.0",
- "@eslint/js": "9.19.0",
- "@eslint/plugin-kit": "^0.2.5",
+ "@eslint/config-array": "^0.19.2",
+ "@eslint/config-helpers": "^0.2.0",
+ "@eslint/core": "^0.12.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.23.0",
+ "@eslint/plugin-kit": "^0.2.7",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.1",
+ "@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
"@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
@@ -6075,7 +5999,7 @@
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.2.0",
+ "eslint-scope": "^8.3.0",
"eslint-visitor-keys": "^4.2.0",
"espree": "^10.3.0",
"esquery": "^1.5.0",
@@ -6155,9 +6079,9 @@
}
},
"node_modules/eslint-scope": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
- "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz",
+ "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
@@ -6564,9 +6488,9 @@
}
},
"node_modules/firebase-admin": {
- "version": "13.0.2",
- "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.0.2.tgz",
- "integrity": "sha512-YWVpoN+tZVSRXF0qC0gojoF5bSqvBRbnBk8+xUtFiguM2L4vB7f0moAwV1VVWDDHvTnvQ68OyTMpdp6wKo/clw==",
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.2.0.tgz",
+ "integrity": "sha512-qQBTKo0QWCDaWwISry989pr8YfZSSk00rNCKaucjOgltEm3cCYzEe4rODqBd1uUwma+Iu5jtAzg89Nfsjr3fGg==",
"license": "Apache-2.0",
"dependencies": {
"@fastify/busboy": "^3.0.0",
@@ -6588,19 +6512,6 @@
"@google-cloud/storage": "^7.14.0"
}
},
- "node_modules/firebase-admin/node_modules/uuid": {
- "version": "11.0.3",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz",
- "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==",
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist/esm/bin/uuid"
- }
- },
"node_modules/flat-cache": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
@@ -6658,7 +6569,6 @@
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-callable": "^1.1.3"
@@ -6781,7 +6691,6 @@
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
"integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
@@ -6809,7 +6718,6 @@
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
- "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -6975,7 +6883,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
"integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -7050,9 +6957,9 @@
}
},
"node_modules/globals": {
- "version": "15.14.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-15.14.0.tgz",
- "integrity": "sha512-OkToC372DtlQeje9/zHIo5CT8lRP/FUgEOKBEhU4e0abL7J7CD24fD9ohiLN5hagG/kWCYj4K5oaxxtj2Z0Dig==",
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7066,7 +6973,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
"integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"define-properties": "^1.2.1",
@@ -7207,7 +7113,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
"integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
- "dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -7226,7 +7131,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"es-define-property": "^1.0.0"
@@ -7239,7 +7143,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
"integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.0"
@@ -7267,7 +7170,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
@@ -7452,9 +7354,9 @@
}
},
"node_modules/import-fresh": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
- "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -7469,12 +7371,12 @@
}
},
"node_modules/import-in-the-middle": {
- "version": "1.11.2",
- "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz",
- "integrity": "sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA==",
+ "version": "1.13.1",
+ "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.13.1.tgz",
+ "integrity": "sha512-k2V9wNm9B+ysuelDTHjI9d5KPc4l8zAZTGqj+pcynvWkypZd857ryzN8jNC7Pg2YZXNMJcHRPpaDyCBbNyVRpA==",
"license": "Apache-2.0",
"dependencies": {
- "acorn": "^8.8.2",
+ "acorn": "^8.14.0",
"acorn-import-attributes": "^1.9.5",
"cjs-module-lexer": "^1.2.2",
"module-details-from-path": "^1.0.3"
@@ -7532,7 +7434,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
"integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -7544,9 +7445,9 @@
}
},
"node_modules/intuit-oauth": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/intuit-oauth/-/intuit-oauth-4.1.3.tgz",
- "integrity": "sha512-jamanOys33Z2Uw1bisf+v7M+2rE9syMPmPZzkOt0iUrTp+IUk99QLgirKPukXidfwVdhgURnkTVb2wUcp84D8g==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/intuit-oauth/-/intuit-oauth-4.2.0.tgz",
+ "integrity": "sha512-FG+A4uiJT9xIm07yLtp4bhAdcOMcHukW7gZs6aJvh+3zHUKKqG/zEAtAIZP1d8YCMbPVHu5SbbnMygeM/OVEvg==",
"license": "Apache-2.0",
"dependencies": {
"atob": "2.1.2",
@@ -7562,9 +7463,9 @@
}
},
"node_modules/ioredis": {
- "version": "5.4.2",
- "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.4.2.tgz",
- "integrity": "sha512-0SZXGNGZ+WzISQ67QDyZ2x0+wVxjjUndtD8oSeik/4ajifeiRufed8fCb8QW8VMyi4MXcS+UO1k/0NGhvq1PAg==",
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.6.0.tgz",
+ "integrity": "sha512-tBZlIIWbndeWBWCXWZiqtOF/yxf6yZX3tAlTJ7nfo5jhd6dctNxF7QnYlZLZ1a0o0pDoen7CgZqO+zjNaFbJAg==",
"license": "MIT",
"dependencies": {
"@ioredis/commands": "^1.1.1",
@@ -7598,7 +7499,6 @@
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
"integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
@@ -7622,7 +7522,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
"integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"async-function": "^1.0.0",
@@ -7642,7 +7541,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
"integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"has-bigints": "^1.0.2"
@@ -7658,7 +7556,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz",
"integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -7675,7 +7572,6 @@
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -7704,7 +7600,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
"integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -7722,7 +7617,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
"integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -7765,7 +7659,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
"integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3"
@@ -7790,7 +7683,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
"integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -7822,7 +7714,6 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
"integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -7835,7 +7726,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
"integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -7852,7 +7742,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -7871,7 +7760,6 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
"integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -7884,7 +7772,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
"integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3"
@@ -7912,7 +7799,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
"integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -7929,7 +7815,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
"integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -7947,7 +7832,6 @@
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"which-typed-array": "^1.1.16"
@@ -7963,7 +7847,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
"integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -7976,7 +7859,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
"integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3"
@@ -7992,7 +7874,6 @@
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
"integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -8146,22 +8027,22 @@
}
},
"node_modules/jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
},
"engines": {
- "node": ">=4"
+ "node": ">=6"
}
},
"node_modules/json-2-csv": {
- "version": "5.5.8",
- "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-5.5.8.tgz",
- "integrity": "sha512-eMQHOwV+av8Sgo+fkbEbQWOw/kwh89AZ5fNA8TYfcooG6TG1ZOL2WcPUrngIMIK8dBJitQ8QEU0zbncQ0CX4CQ==",
+ "version": "5.5.9",
+ "resolved": "https://registry.npmjs.org/json-2-csv/-/json-2-csv-5.5.9.tgz",
+ "integrity": "sha512-l4g6GZVHrsN+5SKkpOmGNSvho+saDZwXzj/xmcO0lJAgklzwsiqy70HS5tA9djcRvBEybZ9IF6R1MDFTEsaOGQ==",
"license": "MIT",
"dependencies": {
"deeks": "3.1.0",
@@ -8270,13 +8151,14 @@
}
},
"node_modules/juice": {
- "version": "11.0.0",
- "resolved": "https://registry.npmjs.org/juice/-/juice-11.0.0.tgz",
- "integrity": "sha512-sGF8hPz9/Wg+YXbaNDqc1Iuoaw+J/P9lBHNQKXAGc9pPNjCd4fyPai0Zxj7MRtdjMr0lcgk5PjEIkP2b8R9F3w==",
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/juice/-/juice-11.0.1.tgz",
+ "integrity": "sha512-R3KLud4l/sN9AMmFZs0QY7cugGSiKvPhGyIsufCV5nJ0MjSlngUE7k80TmFeK9I62wOXrjWBtYA1knVs2OkF8w==",
"license": "MIT",
"dependencies": {
"cheerio": "^1.0.0",
"commander": "^12.1.0",
+ "entities": "^4.5.0",
"mensch": "^0.3.4",
"slick": "^1.12.2",
"web-resource-inliner": "^7.0.0"
@@ -8615,6 +8497,15 @@
"node": ">=10"
}
},
+ "node_modules/luxon": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.6.0.tgz",
+ "integrity": "sha512-WE7p0p7W1xji9qxkLYsvcIxZyfP48GuFrWIBQZIsbjCyf65dG1rv4n83HcOyEyhvzxJCrUoObCRNFgRNIQ5KNA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
@@ -8822,9 +8713,9 @@
}
},
"node_modules/moment-timezone": {
- "version": "0.5.47",
- "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.47.tgz",
- "integrity": "sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==",
+ "version": "0.5.48",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz",
+ "integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==",
"license": "MIT",
"dependencies": {
"moment": "^2.29.4"
@@ -8839,6 +8730,37 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
+ "node_modules/msgpackr": {
+ "version": "1.11.2",
+ "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.2.tgz",
+ "integrity": "sha512-F9UngXRlPyWCDEASDpTf6c9uNhGPTqnTeLVt7bN+bU1eajoR/8V9ys2BRaV5C/e5ihE6sJ9uPIKaYt6bFuO32g==",
+ "license": "MIT",
+ "optionalDependencies": {
+ "msgpackr-extract": "^3.0.2"
+ }
+ },
+ "node_modules/msgpackr-extract": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.3.tgz",
+ "integrity": "sha512-P0efT1C9jIdVRefqjzOQ9Xml57zpOXnIuS+csaB4MdZbTdmGDLo8XhzBG1N7aO11gKDDkJvBLULeFTo46wwreA==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "node-gyp-build-optional-packages": "5.2.2"
+ },
+ "bin": {
+ "download-msgpackr-prebuilds": "bin/download-prebuilds.js"
+ },
+ "optionalDependencies": {
+ "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.3",
+ "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.3"
+ }
+ },
"node_modules/multer": {
"version": "1.4.5-lts.1",
"resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz",
@@ -8880,6 +8802,12 @@
"node": ">= 0.6"
}
},
+ "node_modules/node-abort-controller": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",
+ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==",
+ "license": "MIT"
+ },
"node_modules/node-addon-api": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
@@ -8932,13 +8860,28 @@
"node-gyp-build-test": "build-test.js"
}
},
+ "node_modules/node-gyp-build-optional-packages": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.2.2.tgz",
+ "integrity": "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^2.0.1"
+ },
+ "bin": {
+ "node-gyp-build-optional-packages": "bin.js",
+ "node-gyp-build-optional-packages-optional": "optional.js",
+ "node-gyp-build-optional-packages-test": "build-test.js"
+ }
+ },
"node_modules/node-mailjet": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/node-mailjet/-/node-mailjet-6.0.6.tgz",
- "integrity": "sha512-cr8ciqtHuxyFd3+3bpDy+oKuNzctZfRQZtwRjurVAzE+DZLTfyxjgD+GTqQ1kr0ClAjDjSh3ERlZvd5MV0fKHg==",
+ "version": "6.0.8",
+ "resolved": "https://registry.npmjs.org/node-mailjet/-/node-mailjet-6.0.8.tgz",
+ "integrity": "sha512-VyB2+SeD1zuxpuJLePC4bk10UN0G294CsVlF8YBxb+1tlH0Tw4wECGlTYlQOaRMtPgckdObpcfEbhUWu3UuFIQ==",
"license": "MIT",
"dependencies": {
- "axios": "1.7.4",
+ "axios": "^1.8.1",
"json-bigint": "^1.0.0",
"url-join": "^4.0.0"
},
@@ -8947,17 +8890,6 @@
"npm": ">= 6.9.0"
}
},
- "node_modules/node-mailjet/node_modules/axios": {
- "version": "1.7.4",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.4.tgz",
- "integrity": "sha512-DukmaFRnY6AzAALSH4J2M3k6PkaC+MfaAGdEERRWcC9q3/TWQwLpHR8ZRLKTdQ3aBDL64EdluRDjJqKw+BPZEw==",
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.0",
- "proxy-from-env": "^1.1.0"
- }
- },
"node_modules/node-persist": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/node-persist/-/node-persist-4.0.4.tgz",
@@ -9069,7 +9001,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -9079,7 +9010,6 @@
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
"integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
@@ -9130,6 +9060,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/object.getownpropertydescriptors": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz",
+ "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==",
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.0-next.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/object.values": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
@@ -9236,7 +9182,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
"integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"get-intrinsic": "^1.2.6",
@@ -9250,6 +9195,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/p-finally": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
+ "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -9453,7 +9407,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
"integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
- "dev": true,
"license": "MIT",
"engines": {
"node": ">= 0.4"
@@ -9476,9 +9429,9 @@
}
},
"node_modules/prettier": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
- "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
+ "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"dev": true,
"license": "MIT",
"bin": {
@@ -9506,6 +9459,19 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"license": "MIT"
},
+ "node_modules/promise-callbacks": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/promise-callbacks/-/promise-callbacks-3.8.2.tgz",
+ "integrity": "sha512-g+SziwZr9eLwF+Tejuz0nirmzrYm1Ou4dExaRap1+wG/Bip1FAjMwE+oOqwv6C+CxDCQJ9l0jMSE8ui1oRC/tQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.9.2",
+ "object.getownpropertydescriptors": "2.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/promise-retry": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
@@ -9650,12 +9616,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/querystringify": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
- "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
- "license": "MIT"
- },
"node_modules/random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
@@ -9763,6 +9723,12 @@
"@redis/time-series": "1.1.0"
}
},
+ "node_modules/redis-commands": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz",
+ "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==",
+ "license": "MIT"
+ },
"node_modules/redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
@@ -9788,7 +9754,6 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
"integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
@@ -9811,14 +9776,12 @@
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
- "dev": true,
"license": "MIT"
},
"node_modules/regexp.prototype.flags": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz",
"integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
@@ -9853,12 +9816,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/requires-port": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
- "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
- "license": "MIT"
- },
"node_modules/resolve": {
"version": "2.0.0-next.5",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
@@ -9948,21 +9905,10 @@
"integrity": "sha512-c5ouQkOvGHF1qomUUDJGFcXsomeSO2gbEs6hVhMAtlkE1CuaZase/WzoaKFG/EZQuNmq6pw/EMCeEnDvOgCJYQ==",
"license": "MIT"
},
- "node_modules/rxjs": {
- "version": "7.8.1",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
- "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.1.0"
- }
- },
"node_modules/safe-array-concat": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
"integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
@@ -9982,7 +9928,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true,
"license": "MIT"
},
"node_modules/safe-buffer": {
@@ -10009,7 +9954,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
"integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
@@ -10026,14 +9970,12 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true,
"license": "MIT"
},
"node_modules/safe-regex-test": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -10080,6 +10022,12 @@
"integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==",
"license": "BSD-3-Clause"
},
+ "node_modules/semifies": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/semifies/-/semifies-1.0.0.tgz",
+ "integrity": "sha512-xXR3KGeoxTNWPD4aBvL5NUpMTT7WMANr3EWnaS190QVkY52lqqcVRD7Q05UVbBhiWDGWMlJEUam9m7uFFGVScw==",
+ "license": "Apache-2.0"
+ },
"node_modules/semver": {
"version": "7.6.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
@@ -10177,7 +10125,6 @@
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
@@ -10195,7 +10142,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
"integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"define-data-property": "^1.1.4",
@@ -10211,7 +10157,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
"integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
@@ -10445,13 +10390,13 @@
}
},
"node_modules/soap": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/soap/-/soap-1.1.7.tgz",
- "integrity": "sha512-zKNMtlZhnqhW0jv5z8qVE5A/1Vw/HKXnIFe2bss8s/+tqub4uLU9r20A4mTfiluePHABvm7p2YQjyvFBJjIf9A==",
+ "version": "1.1.10",
+ "resolved": "https://registry.npmjs.org/soap/-/soap-1.1.10.tgz",
+ "integrity": "sha512-dqfX9qHhXup3ZLWsI5of6xJIJKeBCPnn3tTu9sKtASm2A53Zk6/u3drygLiUy+H1mmjRBptXfVkjY6pt8nhOjA==",
"license": "MIT",
"dependencies": {
- "axios": "^1.7.9",
- "axios-ntlm": "^1.4.2",
+ "axios": "^1.8.3",
+ "axios-ntlm": "^1.4.3",
"debug": "^4.4.0",
"formidable": "^3.5.2",
"get-stream": "^6.0.1",
@@ -10459,10 +10404,10 @@
"sax": "^1.4.1",
"strip-bom": "^3.0.0",
"whatwg-mimetype": "4.0.0",
- "xml-crypto": "^6.0.0"
+ "xml-crypto": "^6.0.1"
},
"engines": {
- "node": ">=14.0.0"
+ "node": ">=14.17.0"
}
},
"node_modules/socket.io": {
@@ -10558,13 +10503,12 @@
}
},
"node_modules/source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
- "dev": true,
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+ "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
"license": "BSD-3-Clause",
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 8"
}
},
"node_modules/source-map-explorer": {
@@ -10629,16 +10573,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/source-map-explorer/node_modules/source-map": {
- "version": "0.7.4",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
- "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
- "dev": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/source-map-explorer/node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
@@ -10686,12 +10620,6 @@
"node": ">=10"
}
},
- "node_modules/spawn-command": {
- "version": "0.0.2",
- "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz",
- "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==",
- "dev": true
- },
"node_modules/specificity": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz",
@@ -10937,7 +10865,6 @@
"version": "1.2.10",
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
"integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
@@ -10959,7 +10886,6 @@
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
"integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
@@ -10978,7 +10904,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
"integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
@@ -11063,22 +10988,6 @@
"pick-util": "^1.1.5"
}
},
- "node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
- }
- },
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
@@ -11243,16 +11152,6 @@
"integrity": "sha512-eGYW4bjf1DtrHzUYxYfAcSytpOkA44zsr7G2n3PV7yOUR23vmkGe3LL4R+1jL9OsXtbsFOwe8XtbCrabeaEFnw==",
"license": "MIT"
},
- "node_modules/to-fast-properties": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -11268,16 +11167,6 @@
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
},
- "node_modules/tree-kill": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz",
- "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "tree-kill": "cli.js"
- }
- },
"node_modules/triple-beam": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz",
@@ -11318,18 +11207,17 @@
"license": "Unlicense"
},
"node_modules/twilio": {
- "version": "4.23.0",
- "resolved": "https://registry.npmjs.org/twilio/-/twilio-4.23.0.tgz",
- "integrity": "sha512-LdNBQfOe0dY2oJH2sAsrxazpgfFQo5yXGxe96QA8UWB5uu+433PrUbkv8gQ5RmrRCqUTPQ0aOrIyAdBr1aB03Q==",
+ "version": "5.5.1",
+ "resolved": "https://registry.npmjs.org/twilio/-/twilio-5.5.1.tgz",
+ "integrity": "sha512-b1gLd2eMsCSCHRerp3GQUedVlz0nCTt5FbyPxDPmMvk5cm6eIPk4ZTp5JNpgucARZgpCB2uUACJbdcidEHAUBA==",
"license": "MIT",
"dependencies": {
- "axios": "^1.6.0",
+ "axios": "^1.7.8",
"dayjs": "^1.11.9",
"https-proxy-agent": "^5.0.0",
- "jsonwebtoken": "^9.0.0",
+ "jsonwebtoken": "^9.0.2",
"qs": "^6.9.4",
"scmp": "^2.1.0",
- "url-parse": "^1.5.9",
"xmlbuilder": "^13.0.2"
},
"engines": {
@@ -11366,7 +11254,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -11381,7 +11268,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
"integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.8",
@@ -11401,7 +11287,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
"integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
- "dev": true,
"license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
@@ -11423,7 +11308,6 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
"integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
@@ -11471,7 +11355,6 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
"integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.3",
@@ -11526,16 +11409,6 @@
"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
"license": "MIT"
},
- "node_modules/url-parse": {
- "version": "1.5.10",
- "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
- "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
- "license": "MIT",
- "dependencies": {
- "querystringify": "^2.1.1",
- "requires-port": "^1.0.0"
- }
- },
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -11552,16 +11425,16 @@
}
},
"node_modules/uuid": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
- "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
+ "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"license": "MIT",
"bin": {
- "uuid": "dist/bin/uuid"
+ "uuid": "dist/esm/bin/uuid"
}
},
"node_modules/valid-data-url": {
@@ -11798,7 +11671,6 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
"integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-bigint": "^1.1.0",
@@ -11818,7 +11690,6 @@
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
"integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
- "dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
@@ -11846,14 +11717,12 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true,
"license": "MIT"
},
"node_modules/which-collection": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
"integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
- "dev": true,
"license": "MIT",
"dependencies": {
"is-map": "^2.0.3",
@@ -11872,7 +11741,6 @@
"version": "1.1.18",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz",
"integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==",
- "dev": true,
"license": "MIT",
"dependencies": {
"available-typed-arrays": "^1.0.7",
@@ -12088,9 +11956,9 @@
}
},
"node_modules/xml-crypto": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-6.0.0.tgz",
- "integrity": "sha512-L3RgnkaDrHaYcCnoENv4Idzt1ZRj5U1z1BDH98QdDTQfssScx8adgxhd9qwyYo+E3fXbQZjEQH7aiXHLVgxGvw==",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-6.0.1.tgz",
+ "integrity": "sha512-v05aU7NS03z4jlZ0iZGRFeZsuKO1UfEbbYiaeRMiATBFs6Jq9+wqKquEMTn4UTrYZ9iGD8yz3KT4L9o2iF682w==",
"license": "MIT",
"dependencies": {
"@xmldom/is-dom-node": "^1.0.1",
@@ -12207,8 +12075,8 @@
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "devOptional": true,
"license": "MIT",
+ "optional": true,
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
@@ -12226,8 +12094,8 @@
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "devOptional": true,
"license": "ISC",
+ "optional": true,
"engines": {
"node": ">=12"
}
diff --git a/package.json b/package.json
index 91b4bc851..05a8eb327 100644
--- a/package.json
+++ b/package.json
@@ -9,22 +9,16 @@
"scripts": {
"setup": "rm -rf node_modules && npm i && cd client && rm -rf node_modules && npm i",
"setup:win": "rimraf node_modules && npm i && cd client && rimraf node_modules && npm i",
- "admin": "cd admin && npm start",
- "client": "cd client && npm start",
- "server": "nodemon server.js",
- "build": "cd client && npm run build",
- "dev": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\"",
- "deva": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\" \"npm run admin\"",
"start": "node server.js",
"makeitpretty": "prettier --write \"**/*.{css,js,json,jsx,scss}\""
},
"dependencies": {
- "@aws-sdk/client-cloudwatch-logs": "^3.738.0",
- "@aws-sdk/client-elasticache": "^3.738.0",
- "@aws-sdk/client-s3": "^3.738.0",
- "@aws-sdk/client-secrets-manager": "^3.738.0",
- "@aws-sdk/client-ses": "^3.738.0",
- "@aws-sdk/credential-provider-node": "^3.738.0",
+ "@aws-sdk/client-cloudwatch-logs": "^3.772.0",
+ "@aws-sdk/client-elasticache": "^3.772.0",
+ "@aws-sdk/client-s3": "^3.772.0",
+ "@aws-sdk/client-secrets-manager": "^3.772.0",
+ "@aws-sdk/client-ses": "^3.772.0",
+ "@aws-sdk/credential-provider-node": "^3.772.0",
"@aws-sdk/lib-storage": "^3.743.0",
"@aws-sdk/s3-request-presigner": "^3.731.1",
"@opensearch-project/opensearch": "^2.13.0",
@@ -32,34 +26,36 @@
"@socket.io/redis-adapter": "^8.3.0",
"archiver": "^7.0.1",
"aws4": "^1.13.2",
- "axios": "^1.7.7",
+ "axios": "^1.8.4",
+ "bee-queue": "^1.7.1",
"better-queue": "^3.8.12",
"bluebird": "^3.7.2",
"body-parser": "^1.20.3",
- "chart.js": "^4.4.6",
- "cloudinary": "^2.5.1",
- "compression": "^1.7.5",
+ "bullmq": "^5.44.4",
+ "chart.js": "^4.4.8",
+ "cloudinary": "^2.6.0",
+ "compression": "^1.8.0",
"cookie-parser": "^1.4.7",
"cors": "2.8.5",
"crisp-status-reporter": "^1.2.2",
"csrf": "^3.1.0",
- "dd-trace": "^5.33.1",
+ "dd-trace": "^5.43.0",
"dinero.js": "^1.9.1",
"dotenv": "^16.4.5",
"express": "^4.21.1",
- "firebase-admin": "^13.0.2",
+ "firebase-admin": "^13.2.0",
"graphql": "^16.10.0",
"graphql-request": "^6.1.0",
"inline-css": "^4.0.3",
- "intuit-oauth": "^4.1.3",
- "ioredis": "^5.4.2",
- "json-2-csv": "^5.5.8",
- "juice": "^11.0.0",
+ "intuit-oauth": "^4.2.0",
+ "ioredis": "^5.6.0",
+ "json-2-csv": "^5.5.9",
+ "juice": "^11.0.1",
"lodash": "^4.17.21",
"moment": "^2.30.1",
- "moment-timezone": "^0.5.47",
+ "moment-timezone": "^0.5.48",
"multer": "^1.4.5-lts.1",
- "node-mailjet": "^6.0.6",
+ "node-mailjet": "^6.0.8",
"node-persist": "^4.0.4",
"nodemailer": "^6.10.0",
"phone": "^3.1.58",
@@ -67,26 +63,25 @@
"redis": "^4.7.0",
"rimraf": "^6.0.1",
"skia-canvas": "^2.0.2",
- "soap": "^1.1.7",
+ "soap": "^1.1.10",
"socket.io": "^4.8.1",
"socket.io-adapter": "^2.5.5",
"ssh2-sftp-client": "^11.0.0",
- "twilio": "^4.23.0",
- "uuid": "^10.0.0",
+ "twilio": "^5.5.1",
+ "uuid": "^11.1.0",
"winston": "^3.17.0",
"winston-cloudwatch": "^6.3.0",
"xml2js": "^0.6.2",
"xmlbuilder2": "^3.1.1"
},
"devDependencies": {
- "@eslint/js": "^9.19.0",
- "@trivago/prettier-plugin-sort-imports": "^4.3.0",
- "concurrently": "^8.2.2",
- "eslint": "^9.19.0",
+ "@eslint/js": "^9.23.0",
+ "@trivago/prettier-plugin-sort-imports": "^5.2.2",
+ "eslint": "^9.23.0",
"eslint-plugin-react": "^7.37.4",
- "globals": "^15.14.0",
+ "globals": "^15.15.0",
"p-limit": "^3.1.0",
- "prettier": "^3.3.3",
+ "prettier": "^3.5.3",
"source-map-explorer": "^2.5.2"
}
}
diff --git a/redis/redis.conf b/redis/redis.conf
index 22533e22d..dafe316cc 100644
--- a/redis/redis.conf
+++ b/redis/redis.conf
@@ -4,3 +4,4 @@ cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
+maxmemory-policy noeviction
diff --git a/server.js b/server.js
index b70b4e7cd..52f5c6e9e 100644
--- a/server.js
+++ b/server.js
@@ -5,7 +5,7 @@ require("dotenv").config({
});
if (process.env.NODE_ENV) {
- const tracer = require("dd-trace").init({
+ require("dd-trace").init({
profiling: true,
env: process.env.NODE_ENV,
service: "bodyshop-api"
@@ -22,18 +22,24 @@ const cookieParser = require("cookie-parser");
const { Server } = require("socket.io");
const { createAdapter } = require("@socket.io/redis-adapter");
const { instrument } = require("@socket.io/admin-ui");
-const { isString, isEmpty } = require("lodash");
+const { isString, isEmpty, isFunction } = require("lodash");
const logger = require("./server/utils/logger");
const { applyRedisHelpers } = require("./server/utils/redisHelpers");
const { applyIOHelpers } = require("./server/utils/ioHelpers");
const { redisSocketEvents } = require("./server/web-sockets/redisSocketEvents");
-const { ElastiCacheClient, DescribeCacheClustersCommand } = require("@aws-sdk/client-elasticache");
+const {
+ ElastiCacheClient,
+ DescribeCacheClustersCommand,
+ DescribeReplicationGroupsCommand
+} = require("@aws-sdk/client-elasticache");
const { InstanceRegion } = require("./server/utils/instanceMgr");
const StartStatusReporter = require("./server/utils/statusReporter");
+const { registerCleanupTask, initializeCleanupManager } = require("./server/utils/cleanupManager");
+
+const { loadEmailQueue } = require("./server/notifications/queues/emailQueue");
+const { loadAppQueue } = require("./server/notifications/queues/appQueue");
-const cleanupTasks = [];
-let isShuttingDown = false;
const CLUSTER_RETRY_BASE_DELAY = 100;
const CLUSTER_RETRY_MAX_DELAY = 5000;
const CLUSTER_RETRY_JITTER = 100;
@@ -58,7 +64,7 @@ const SOCKETIO_CORS_ORIGIN = [
"https://beta.test.imex.online",
"https://www.beta.test.imex.online",
"https://beta.imex.online",
- "https://www.beta.imex.online",
+ "https://www.beta.imex.online",
"https://www.test.promanager.web-est.com",
"https://test.promanager.web-est.com",
"https://www.promanager.web-est.com",
@@ -124,26 +130,48 @@ const applyRoutes = ({ app }) => {
* @returns {Promise}
*/
const getRedisNodesFromAWS = async () => {
- const client = new ElastiCacheClient({
- region: InstanceRegion()
- });
-
- const params = {
- ReplicationGroupId: process.env.REDIS_CLUSTER_ID,
- ShowCacheNodeInfo: true
- };
+ const client = new ElastiCacheClient({ region: InstanceRegion() });
try {
- // Fetch the cache clusters associated with the replication group
- const command = new DescribeCacheClustersCommand(params);
- const response = await client.send(command);
- const cacheClusters = response.CacheClusters;
+ const describeReplicationGroupCommand = new DescribeReplicationGroupsCommand({
+ ReplicationGroupId: process.env.REDIS_CLUSTER_ID
+ });
+ const describeReplicationGroupResponse = await client.send(describeReplicationGroupCommand);
- return cacheClusters.flatMap((cluster) =>
- cluster.CacheNodes.map((node) => `${node.Endpoint.Address}:${node.Endpoint.Port}`)
- );
+ //TODO: add checking to make sure there's only 1.
+ const cacheClusterIds = describeReplicationGroupResponse.ReplicationGroups[0].MemberClusters;
+
+ // Ensure cacheClusters exists and is an array
+ if (!cacheClusterIds || !Array.isArray(cacheClusterIds) || cacheClusterIds.length === 0) {
+ logger.log(`No cache clusters found for cluster id ${process.env.REDIS_CLUSTER_ID}`, "ERROR", "redis", "api");
+ return [];
+ }
+
+ const nodeEndpointAddresses = [];
+
+ for (const cluster of cacheClusterIds) {
+ const params = { CacheClusterId: cluster, ShowCacheNodeInfo: true };
+ const command = new DescribeCacheClustersCommand(params);
+ const response = await client.send(command);
+
+ if (response.CacheClusters && Array.isArray(response.CacheClusters)) {
+ // Map nodes to address strings
+ //TODO: What happens if we have more shards?
+ const nodeAddress = `${response.CacheClusters[0].CacheNodes[0].Endpoint.Address}:${response.CacheClusters[0].CacheNodes[0].Endpoint.Port}`;
+ // Debug log node addresses
+ logger.log(`Cluster node addresses: ${nodeAddress}`, "DEBUG", "redis", "api");
+ // Return only those addresses that start with the current cluster id
+ nodeEndpointAddresses.push(nodeAddress);
+ }
+ }
+
+ return nodeEndpointAddresses;
+ // Process each cluster
} catch (err) {
- logger.log(`Error fetching Redis nodes from AWS: ${err.message}`, "ERROR", "redis", "api");
+ logger.log(`Error fetching Redis nodes from AWS:`, "ERROR", "redis", "api", {
+ message: err?.message,
+ stack: err?.stack
+ });
throw err;
}
};
@@ -167,7 +195,10 @@ const connectToRedisCluster = async () => {
try {
redisServers = JSON.parse(process.env.REDIS_URL);
} catch (error) {
- logger.log(`Failed to parse REDIS_URL: ${error.message}. Exiting...`, "ERROR", "redis", "api");
+ logger.log(`Failed to parse REDIS_URL: ${error.message}. Exiting...`, "ERROR", "redis", "api", {
+ message: error?.message,
+ stack: error?.stack
+ });
process.exit(1);
}
}
@@ -193,11 +224,22 @@ const connectToRedisCluster = async () => {
return new Promise((resolve, reject) => {
redisCluster.on("ready", () => {
logger.log(`Redis cluster connection established.`, "INFO", "redis", "api");
- resolve(redisCluster);
+ if (process.env.NODE_ENV === "development" && process.env?.CLEAR_REDIS_ON_START === "true") {
+ logger.log("[Development] Flushing Redis Cluster on Service start...", "INFO", "redis", "api");
+ const master = redisCluster.nodes("master");
+ Promise.all(master.map((node) => node.flushall())).then(() => {
+ resolve(redisCluster);
+ });
+ } else {
+ resolve(redisCluster);
+ }
});
redisCluster.on("error", (err) => {
- logger.log(`Redis cluster connection failed: ${err.message}`, "ERROR", "redis", "api");
+ logger.log(`Redis cluster connection failed:`, "ERROR", "redis", "api", {
+ message: err?.message,
+ stack: err?.stack
+ });
reject(err);
});
});
@@ -219,17 +261,24 @@ const applySocketIO = async ({ server, app }) => {
const pubClient = redisCluster;
const subClient = pubClient.duplicate();
- pubClient.on("error", (err) => logger.log(`Redis pubClient error: ${err}`, "ERROR", "redis"));
- subClient.on("error", (err) => logger.log(`Redis subClient error: ${err}`, "ERROR", "redis"));
+ pubClient.on("error", (err) =>
+ logger.log(`Redis pubClient error: ${err}`, "ERROR", "redis", "api", {
+ message: err?.message,
+ stack: err?.stack
+ })
+ );
+ subClient.on("error", (err) =>
+ logger.log(`Redis subClient error: ${err}`, "ERROR", "redis", "api", {
+ message: err?.message,
+ stack: err?.stack
+ })
+ );
- process.on("SIGINT", async () => {
+ // Register Redis cleanup
+ registerCleanupTask(async () => {
logger.log("Closing Redis connections...", "INFO", "redis", "api");
- try {
- await Promise.all([pubClient.disconnect(), subClient.disconnect()]);
- logger.log("Redis connections closed. Process will exit.", "INFO", "redis", "api");
- } catch (error) {
- logger.log(`Error closing Redis connections: ${error.message}`, "ERROR", "redis", "api");
- }
+ await Promise.all([pubClient.disconnect(), subClient.disconnect()]);
+ logger.log("Redis connections closed.", "INFO", "redis", "api");
});
const ioRedis = new Server(server, {
@@ -287,6 +336,34 @@ const applySocketIO = async ({ server, app }) => {
return api;
};
+/**
+ * Load Queues for Email and App
+ * @param {Object} options - Queue configuration options
+ * @param {Redis.Cluster} options.pubClient - Redis client for publishing
+ * @param {Object} options.logger - Logger instance
+ * @param {Object} options.redisHelpers - Redis helper functions
+ * @param {Server} options.ioRedis - Socket.IO server instance
+ * @returns {Promise}
+ */
+const loadQueues = async ({ pubClient, logger, redisHelpers, ioRedis }) => {
+ const queueSettings = { pubClient, logger, redisHelpers, ioRedis };
+
+ // Assuming loadEmailQueue and loadAppQueue return Promises
+ const [notificationsEmailsQueue, notificationsAppQueue] = await Promise.all([
+ loadEmailQueue(queueSettings),
+ loadAppQueue(queueSettings)
+ ]);
+
+ // Add error listeners or other setup for queues if needed
+ notificationsEmailsQueue.on("error", (error) => {
+ logger.log(`Error in notificationsEmailsQueue: ${error}`, "ERROR", "queue", "api", null, { error: error?.message });
+ });
+
+ notificationsAppQueue.on("error", (error) => {
+ logger.log(`Error in notificationsAppQueue: ${error}`, "ERROR", "queue", "api", null, { error: error?.message });
+ });
+};
+
/**
* Main function to start the server
* @returns {Promise}
@@ -297,6 +374,9 @@ const main = async () => {
const server = http.createServer(app);
+ // Initialize cleanup manager with signal handlers
+ initializeCleanupManager();
+
const { pubClient, ioRedis } = await applySocketIO({ server, app });
const redisHelpers = applyRedisHelpers({ pubClient, app, logger });
const ioHelpers = applyIOHelpers({ app, redisHelpers, ioRedis, logger });
@@ -304,24 +384,25 @@ const main = async () => {
// Legacy Socket Events
require("./server/web-sockets/web-socket");
+ // Initialize Queues
+ await loadQueues({ pubClient: pubClient, logger, redisHelpers, ioRedis });
+
applyMiddleware({ app });
applyRoutes({ app });
redisSocketEvents({ io: ioRedis, redisHelpers, ioHelpers, logger });
const StatusReporter = StartStatusReporter();
registerCleanupTask(async () => {
- StatusReporter.end();
+ if (isFunction(StatusReporter?.end)) {
+ StatusReporter.end();
+ }
});
- // Add SIGTERM signal handler
- process.on("SIGTERM", handleSigterm);
- process.on("SIGINT", handleSigterm); // Optional: Handle Ctrl+C
-
try {
await server.listen(port);
logger.log(`Server started on port ${port}`, "INFO", "api");
} catch (error) {
- logger.log(`Server failed to start on port ${port}`, "ERROR", "api", error);
+ logger.log(`Server failed to start on port ${port}`, "ERROR", "api", null, { error: error.message });
}
};
@@ -335,33 +416,3 @@ main().catch((error) => {
// Note: If we want the app to crash on all uncaught async operations, we would
// need to put a `process.exit(1);` here
});
-
-// Register a cleanup task
-function registerCleanupTask(task) {
- cleanupTasks.push(task);
-}
-
-// SIGTERM handler
-async function handleSigterm() {
- if (isShuttingDown) {
- logger.log("sigterm-api", "WARN", null, null, { message: "Shutdown already in progress, ignoring signal." });
- return;
- }
-
- isShuttingDown = true;
-
- logger.log("sigterm-api", "WARN", null, null, { message: "SIGTERM Received. Starting graceful shutdown." });
-
- try {
- for (const task of cleanupTasks) {
- logger.log("sigterm-api", "WARN", null, null, { message: `Running cleanup task: ${task.name}` });
-
- await task();
- }
- logger.log("sigterm-api", "WARN", null, null, { message: `All cleanup tasks completed.` });
- } catch (error) {
- logger.log("sigterm-api-error", "ERROR", null, null, { message: error.message, stack: error.stack });
- }
-
- process.exit(0);
-}
diff --git a/server/accounting/pbs/pbs-ap-allocations.js b/server/accounting/pbs/pbs-ap-allocations.js
index a969e82c8..9574b166d 100644
--- a/server/accounting/pbs/pbs-ap-allocations.js
+++ b/server/accounting/pbs/pbs-ap-allocations.js
@@ -12,7 +12,7 @@ const AxiosLib = require("axios").default;
const axios = AxiosLib.create();
const { PBS_ENDPOINTS, PBS_CREDENTIALS } = require("./pbs-constants");
const { CheckForErrors } = require("./pbs-job-export");
-const uuid = require("uuid").v4;
+
axios.interceptors.request.use((x) => {
const socket = x.socket;
@@ -21,6 +21,7 @@ axios.interceptors.request.use((x) => {
...x.headers[x.method],
...x.headers
};
+
const printable = `${new Date()} | Request: ${x.method.toUpperCase()} | ${
x.url
} | ${JSON.stringify(x.data)} | ${JSON.stringify(headers)}`;
diff --git a/server/accounting/qbo/qbo-callback.js b/server/accounting/qbo/qbo-callback.js
index af6d244d7..f1de7d551 100644
--- a/server/accounting/qbo/qbo-callback.js
+++ b/server/accounting/qbo/qbo-callback.js
@@ -7,7 +7,7 @@ const OAuthClient = require("intuit-oauth");
const client = require("../../graphql-client/graphql-client").client;
const queries = require("../../graphql-client/queries");
const { parse, stringify } = require("querystring");
-const InstanceManager = require("../../utils/instanceMgr").default;
+const { InstanceEndpoints } = require("../../utils/instanceMgr");
const oauthClient = new OAuthClient({
clientId: process.env.QBO_CLIENT_ID,
@@ -17,16 +17,8 @@ const oauthClient = new OAuthClient({
logging: true
});
-let url;
-
-if (process.env.NODE_ENV === "production") {
- //TODO:AIO Add in QBO callbacks.
- url = InstanceManager({ imex: `https://imex.online`, rome: `https://romeonline.io` });
-} else if (process.env.NODE_ENV === "test") {
- url = InstanceManager({ imex: `https://test.imex.online`, rome: `https://test.romeonline.io` });
-} else {
- url = `http://localhost:3000`;
-}
+//TODO:AIO Add in QBO callbacks.
+const url = InstanceEndpoints();
exports.default = async (req, res) => {
const queryString = req.url.split("?").reverse()[0];
diff --git a/server/data/arms.js b/server/data/arms.js
index 70ad3be5e..6dadc9364 100644
--- a/server/data/arms.js
+++ b/server/data/arms.js
@@ -18,7 +18,7 @@ const entegralEndpoint =
: "https://uat-ws.armsbusinesssolutions.net/RepairOrderFolderService/RepairOrderFolderService.asmx?WSDL";
const client = require("../graphql-client/graphql-client").client;
-const uuid = require("uuid").v4;
+const { v4 } = require("uuid");
const momentFormat = "yyyy-MM-DDTHH:mm:ss.SSS";
@@ -79,7 +79,7 @@ exports.default = async (req, res) => {
}
try {
- const transId = uuid(); // Can this actually be the job id?
+ const transId = v4(); // Can this actually be the job id?
let obj = {
RqUID: transId,
DocumentInfo: {
diff --git a/server/email/generateTemplate.js b/server/email/generateTemplate.js
index 9d2815851..2887b2fd2 100644
--- a/server/email/generateTemplate.js
+++ b/server/email/generateTemplate.js
@@ -20,6 +20,11 @@ const defaultFooter = () => {
const now = () => moment().format("MM/DD/YYYY @ hh:mm a");
+/**
+ * Generate the email template
+ * @param strings
+ * @returns {string}
+ */
const generateEmailTemplate = (strings) => {
return (
`
diff --git a/server/email/sendemail.js b/server/email/sendemail.js
index 81787fe49..26d5c8560 100644
--- a/server/email/sendemail.js
+++ b/server/email/sendemail.js
@@ -69,11 +69,14 @@ const sendServerEmail = async ({ subject, text }) => {
}
},
(err, info) => {
- logger.log("server-email-failure", err ? "error" : "debug", null, null, { message: err || info });
+ logger.log("server-email-failure", err ? "error" : "debug", null, null, {
+ message: err?.message,
+ stack: err?.stack
+ });
}
);
} catch (error) {
- logger.log("server-email-failure", "error", null, null, { error });
+ logger.log("server-email-failure", "error", null, null, { message: error?.message, stack: error?.stack });
}
};
@@ -92,11 +95,11 @@ const sendTaskEmail = async ({ to, subject, type = "text", html, text, attachmen
},
(err, info) => {
// (message, type, user, record, meta
- logger.log("server-email", err ? "error" : "debug", null, null, { message: err ? err?.message : info });
+ logger.log("server-email", err ? "error" : "debug", null, null, { message: err?.message, stack: err?.stack });
}
);
} catch (error) {
- logger.log("server-email-failure", "error", null, null, { error });
+ logger.log("server-email-failure", "error", null, null, { message: error?.message, stack: error?.stack });
}
};
@@ -125,7 +128,8 @@ const sendEmail = async (req, res) => {
cc: req.body.cc,
subject: req.body.subject,
templateStrings: req.body.templateStrings,
- error
+ errorMessage: error?.message,
+ errorStack: error?.stack
});
}
})
@@ -194,7 +198,8 @@ const sendEmail = async (req, res) => {
cc: req.body.cc,
subject: req.body.subject,
templateStrings: req.body.templateStrings,
- error: err
+ errorMessage: err?.message,
+ errorStack: err?.stack
});
logEmail(req, {
to: req.body.to,
@@ -202,7 +207,7 @@ const sendEmail = async (req, res) => {
subject: req.body.subject,
bodyshopid: req.body.bodyshopid
});
- res.status(500).json({ success: false, error: err });
+ res.status(500).json({ success: false, errorMessage: err?.message, stack: err?.stack });
}
}
);
@@ -270,14 +275,16 @@ ${body.bounce?.bouncedRecipients.map(
},
(err, info) => {
logger.log("sns-error", err ? "error" : "debug", "api", null, {
- message: err ? err?.message : info
+ errorMessage: err?.message,
+ errorStack: err?.stack
});
}
);
}
} catch (error) {
logger.log("sns-error", "ERROR", "api", null, {
- error: JSON.stringify(error)
+ errorMessage: error?.message,
+ errorStack: error?.stack
});
}
res.sendStatus(200);
diff --git a/server/email/tasksEmails.js b/server/email/tasksEmails.js
index 6d787811a..b8c3c42a3 100644
--- a/server/email/tasksEmails.js
+++ b/server/email/tasksEmails.js
@@ -10,6 +10,8 @@ const generateEmailTemplate = require("./generateTemplate");
const moment = require("moment-timezone");
const { taskEmailQueue } = require("./tasksEmailsQueue");
const mailer = require("./mailer");
+const { InstanceEndpoints } = require("../utils/instanceMgr");
+const { formatTaskPriority } = require("../notifications/stringHelpers");
// Initialize the Tasks Email Queue
const tasksEmailQueue = taskEmailQueue();
@@ -61,16 +63,6 @@ const formatDate = (date) => {
return date ? `| Due on: ${moment(date).format("MM/DD/YYYY")}` : "";
};
-const formatPriority = (priority) => {
- if (priority === 1) {
- return "High";
- } else if (priority === 3) {
- return "Low";
- } else {
- return "Medium";
- }
-};
-
/**
* Generate the email template arguments.
* @param title
@@ -83,18 +75,11 @@ const formatPriority = (priority) => {
* @param taskId
* @returns {{header, body: string, subHeader: string}}
*/
-
-const getEndpoints = (bodyshop) =>
- InstanceManager({
- imex: process.env?.NODE_ENV === "test" ? "https://test.imex.online" : "https://imex.online",
- rome: process.env?.NODE_ENV === "test" ? "https//test.romeonline.io" : "https://romeonline.io"
- });
-
const generateTemplateArgs = (title, priority, description, dueDate, bodyshop, job, taskId, dateLine, createdBy) => {
- const endPoints = getEndpoints(bodyshop);
+ const endPoints = InstanceEndpoints();
return {
header: title,
- subHeader: `Body Shop: ${bodyshop.shopname} | Priority: ${formatPriority(priority)} ${formatDate(dueDate)} | Created By: ${createdBy || "N/A"}`,
+ subHeader: `Body Shop: ${bodyshop.shopname} | Priority: ${formatTaskPriority(priority)} ${formatDate(dueDate)} | Created By: ${createdBy || "N/A"}`,
body: `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()} ${description ? description.concat(" ") : ""}View this task. `,
dateLine
};
@@ -108,9 +93,8 @@ const generateTemplateArgs = (title, priority, description, dueDate, bodyshop, j
* @param html
* @param taskIds
* @param successCallback
- * @param requestInstance
*/
-const sendMail = (type, to, subject, html, taskIds, successCallback, requestInstance) => {
+const sendMail = (type, to, subject, html, taskIds, successCallback) => {
const fromEmails = InstanceManager({
imex: "ImEX Online ",
rome: "Rome Online "
@@ -136,7 +120,7 @@ const sendMail = (type, to, subject, html, taskIds, successCallback, requestInst
};
/**
- * Send an email to the assigned user.
+ * Email the assigned user.
* @param req
* @param res
* @returns {Promise<*>}
@@ -162,7 +146,7 @@ const taskAssignedEmail = async (req, res) => {
sendMail(
"assigned",
tasks_by_pk.assigned_to_employee.user_email,
- `A ${formatPriority(newTask.priority)} priority task has been ${dirty ? "reassigned to" : "created for"} you - ${newTask.title}`,
+ `A ${formatTaskPriority(newTask.priority)} priority task has been ${dirty ? "reassigned to" : "created for"} you - ${newTask.title}`,
generateEmailTemplate(
generateTemplateArgs(
newTask.title,
@@ -186,7 +170,7 @@ const taskAssignedEmail = async (req, res) => {
};
/**
- * Send an email to remind the user of their tasks.
+ * Email remind the user of their tasks.
* @param req
* @param res
* @returns {Promise<*>}
@@ -246,7 +230,7 @@ const tasksRemindEmail = async (req, res) => {
const onlyTask = groupedTasks[recipient.email][0];
emailData.subject =
- `New ${formatPriority(onlyTask.priority)} Priority Task Reminder - ${onlyTask.title} ${onlyTask.due_date ? `- ${formatDate(onlyTask.due_date)}` : ""}`.trim();
+ `New ${formatTaskPriority(onlyTask.priority)} Priority Task Reminder - ${onlyTask.title} ${onlyTask.due_date ? `- ${formatDate(onlyTask.due_date)}` : ""}`.trim();
emailData.html = generateEmailTemplate(
generateTemplateArgs(
@@ -264,11 +248,6 @@ const tasksRemindEmail = async (req, res) => {
}
// There are multiple emails to send to this author.
else {
- const endPoints = InstanceManager({
- imex: process.env?.NODE_ENV === "test" ? "https://test.imex.online" : "https://imex.online",
- rome: process.env?.NODE_ENV === "test" ? "https//test.romeonline.io" : "https://romeonline.io"
- });
-
const allTasks = groupedTasks[recipient.email];
emailData.subject = `New Tasks Reminder - ${allTasks.length} Tasks require your attention`;
emailData.html = generateEmailTemplate({
@@ -278,7 +257,7 @@ const tasksRemindEmail = async (req, res) => {
body: ``
@@ -338,6 +317,5 @@ const tasksRemindEmail = async (req, res) => {
module.exports = {
taskAssignedEmail,
- tasksRemindEmail,
- getEndpoints
+ tasksRemindEmail
};
diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js
index 7d52542e5..b0c72aa7d 100644
--- a/server/graphql-client/queries.js
+++ b/server/graphql-client/queries.js
@@ -1485,6 +1485,8 @@ exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) {
materials
auto_add_ats
rate_ats
+ flat_rate_ats
+ rate_ats_flat
joblines(where: { removed: { _eq: false } }){
id
line_no
@@ -2706,6 +2708,70 @@ exports.INSERT_AUDIT_TRAIL = `
}
`;
+exports.GET_JOB_WATCHERS = `
+query GET_JOB_WATCHERS($jobid: uuid!) {
+ job_watchers(where: { jobid: { _eq: $jobid } }) {
+ user_email
+ user {
+ authid
+ employee {
+ id
+ first_name
+ last_name
+ }
+ }
+ }
+ job: jobs_by_pk(id: $jobid) {
+ id
+ ro_number
+ clm_no
+ bodyshop {
+ id
+ shopname
+ timezone
+ }
+ }
+}
+`;
+
+exports.GET_NOTIFICATION_ASSOCIATIONS = `
+query GET_NOTIFICATION_ASSOCIATIONS($emails: [String!]!, $shopid: uuid!) {
+ associations(where: {
+ useremail: { _in: $emails },
+ shopid: { _eq: $shopid }
+ }) {
+ id
+ useremail
+ notification_settings
+ }
+}
+`;
+
+exports.INSERT_NOTIFICATIONS_MUTATION = ` mutation INSERT_NOTIFICATIONS($objects: [notifications_insert_input!]!) {
+ insert_notifications(objects: $objects) {
+ affected_rows
+ returning {
+ id
+ jobid
+ associationid
+ scenario_text
+ fcm_text
+ scenario_meta
+ }
+ }
+ }`;
+
+// REMEMBER: Update the cache_bodyshop event in hasura to include any added fields
+exports.GET_BODYSHOP_BY_ID = `
+ query GET_BODYSHOP_BY_ID($id: uuid!) {
+ bodyshops_by_pk(id: $id) {
+ id
+ md_order_statuses
+ shopname
+ }
+ }
+`;
+
exports.GET_DOCUMENTS_BY_JOB = `
query GET_DOCUMENTS_BY_JOB($jobId: uuid!) {
jobs_by_pk(id: $jobId) {
@@ -2762,6 +2828,4 @@ exports.GET_DOCUMENTS_BY_IDS = `
size
takenat
}
-}
-
- `;
+}`;
diff --git a/server/intellipay/intellipay.js b/server/intellipay/intellipay.js
index 71adce9a3..49d91a88c 100644
--- a/server/intellipay/intellipay.js
+++ b/server/intellipay/intellipay.js
@@ -10,12 +10,11 @@ const moment = require("moment");
const logger = require("../utils/logger");
const { sendTaskEmail } = require("../email/sendemail");
const generateEmailTemplate = require("../email/generateTemplate");
-const { getEndpoints } = require("../email/tasksEmails");
const domain = process.env.NODE_ENV ? "secure" : "test";
const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager");
-const { InstanceRegion } = require("../utils/instanceMgr");
+const { InstanceRegion, InstanceEndpoints } = require("../utils/instanceMgr");
const client = new SecretsManagerClient({
region: InstanceRegion()
@@ -372,6 +371,7 @@ exports.postback = async (req, res) => {
iprequest: values,
decodedComment
};
+ const ipMapping = req.body?.bodyshop?.intellipay_config?.payment_map;
logger.log("intellipay-postback-received", "DEBUG", req.user?.email, null, logResponseMeta);
@@ -418,7 +418,7 @@ exports.postback = async (req, res) => {
amount: p.amount,
transactionid: values.authcode,
payer: "Customer",
- type: values.cardtype,
+ type: ipMapping ? ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype : values.cardtype,
jobid: p.jobid,
date: moment(Date.now()),
payment_responses: {
@@ -443,31 +443,28 @@ exports.postback = async (req, res) => {
});
if (values.origin === "OneLink" && parsedComment.userEmail) {
- try {
- const endPoints = getEndpoints();
- sendTaskEmail({
- to: parsedComment.userEmail,
- subject: `New Payment(s) Received - RO ${jobs.jobs.map((j) => j.ro_number).join(", ")}`,
- type: "html",
- html: generateEmailTemplate({
- header: "New Payment(s) Received",
- subHeader: "",
- body: jobs.jobs
- .map(
- (job) =>
- `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()} | $${partialPayments.find((p) => p.jobid === job.id).amount}`
- )
- .join(" ")
- })
- });
- } catch (error) {
+ sendTaskEmail({
+ to: parsedComment.userEmail,
+ subject: `New Payment(s) Received - RO ${jobs.jobs.map((j) => j.ro_number).join(", ")}`,
+ type: "html",
+ html: generateEmailTemplate({
+ header: "New Payment(s) Received",
+ subHeader: "",
+ body: jobs.jobs
+ .map(
+ (job) =>
+ `Reference: ${job.ro_number || "N/A"} | ${job.ownr_co_nm ? job.ownr_co_nm : `${job.ownr_fn || ""} ${job.ownr_ln || ""}`.trim()} | ${`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${job.v_model_desc || ""}`.trim()} | $${partialPayments.find((p) => p.jobid === job.id).amount}`
+ )
+ .join(" ")
+ })
+ }).catch((error) => {
logger.log("intellipay-postback-email-error", "ERROR", req.user?.email, null, {
message: error.message,
jobs,
paymentResult,
...logResponseMeta
});
- }
+ });
}
res.sendStatus(200);
} else if (values.invoice) {
@@ -485,7 +482,7 @@ exports.postback = async (req, res) => {
amount: values.total,
transactionid: values.authcode,
payer: "Customer",
- type: values.cardtype,
+ type: ipMapping ? ipMapping[(values.cardtype || "").toLowerCase()] || values.cardtype : values.cardtype,
jobid: values.invoice,
date: moment(Date.now())
}
diff --git a/server/job/job-totals-USA.js b/server/job/job-totals-USA.js
index 4e889a658..dd850dc9b 100644
--- a/server/job/job-totals-USA.js
+++ b/server/job/job-totals-USA.js
@@ -1,7 +1,7 @@
const Dinero = require("dinero.js");
const queries = require("../graphql-client/queries");
-const adminClient = require("../graphql-client/graphql-client").client;
-const _ = require("lodash");
+// const adminClient = require("../graphql-client/graphql-client").client;
+// const _ = require("lodash");
const logger = require("../utils/logger");
const InstanceMgr = require("../utils/instanceMgr").default;
@@ -45,7 +45,9 @@ exports.totalsSsu = async function (req, res) {
}
});
- res.status(200).send();
+ if (result) {
+ res.status(200).send();
+ }
} catch (error) {
logger.log("job-totals-ssu-USA-error", "ERROR", req?.user?.email, id, {
jobid: id,
@@ -59,7 +61,7 @@ exports.totalsSsu = async function (req, res) {
//IMPORTANT*** These two functions MUST be mirrrored.
async function TotalsServerSide(req, res) {
const { job, client } = req.body;
- await AutoAddAtsIfRequired({ job: job, client: client });
+ await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
try {
let ret = {
@@ -138,10 +140,11 @@ async function Totals(req, res) {
const client = req.userGraphQLClient;
logger.log("job-totals-ssu-USA", "DEBUG", req.user.email, job.id, {
- jobid: job.id
+ jobid: job.id,
+ id: id
});
- await AutoAddAtsIfRequired({ job, client });
+ await AtsAdjustmentsIfRequired({ job, client, user: req.user });
try {
let ret = {
@@ -153,7 +156,7 @@ async function Totals(req, res) {
res.status(200).json(ret);
} catch (error) {
- logger.log("job-totals-USA-error", "ERROR", req.user.email, job.id, {
+ logger.log("job-totals-ssu-USA-error", "ERROR", req.user.email, job.id, {
jobid: job.id,
error: error.message,
stack: error.stack
@@ -162,40 +165,45 @@ async function Totals(req, res) {
}
}
-async function AutoAddAtsIfRequired({ job, client }) {
- //Check if ATS should be automatically added.
- if (job.auto_add_ats) {
- //Get the total sum of hours that should be the ATS amount.
- //Check to see if an ATS line exists.
+async function AtsAdjustmentsIfRequired({ job, client, user }) {
+ if (job.auto_add_ats || job.flat_rate_ats) {
+ let atsAmount = 0;
let atsLineIndex = null;
- const atsHours = job.joblines.reduce((acc, val, index) => {
- if (val.line_desc && val.line_desc.toLowerCase() === "ats amount") {
- atsLineIndex = index;
- }
- if (
- val.mod_lbr_ty !== "LA1" &&
- val.mod_lbr_ty !== "LA2" &&
- val.mod_lbr_ty !== "LA3" &&
- val.mod_lbr_ty !== "LA4" &&
- val.mod_lbr_ty !== "LAU" &&
- val.mod_lbr_ty !== "LAG" &&
- val.mod_lbr_ty !== "LAS" &&
- val.mod_lbr_ty !== "LAA"
- ) {
- acc = acc + val.mod_lb_hrs;
- }
+ //Check if ATS should be automatically added.
+ if (job.auto_add_ats) {
+ const excludedLaborTypes = new Set(["LAA", "LAG", "LAS", "LAU", "LA1", "LA2", "LA3", "LA4"]);
- return acc;
- }, 0);
+ //Get the total sum of hours that should be the ATS amount.
+ //Check to see if an ATS line exists.
+ const atsHours = job.joblines.reduce((acc, val, index) => {
+ if (val.line_desc?.toLowerCase() === "ats amount") {
+ atsLineIndex = index;
+ }
- const atsAmount = atsHours * (job.rate_ats || 0);
- //If it does, update it in place, and make sure it is updated for local calculations.
+ if (!excludedLaborTypes.has(val.mod_lbr_ty)) {
+ acc = acc + val.mod_lb_hrs;
+ }
+
+ return acc;
+ }, 0);
+
+ atsAmount = atsHours * (job.rate_ats || 0);
+ }
+
+ //Check if a Flat Rate ATS should be added.
+ if (job.flat_rate_ats) {
+ atsLineIndex = ((i) => (i === -1 ? null : i))(
+ job.joblines.findIndex((line) => line.line_desc?.toLowerCase() === "ats amount")
+ );
+ atsAmount = job.rate_ats_flat || 0;
+ }
+
+ //If it does not, create one for local calculations and insert it.
if (atsLineIndex === null) {
const newAtsLine = {
jobid: job.id,
alt_partm: null,
- line_no: 35,
unq_seq: 0,
line_ind: "E",
line_desc: "ATS Amount",
@@ -220,19 +228,42 @@ async function AutoAddAtsIfRequired({ job, client }) {
prt_dsmk_m: 0.0
};
- const result = await client.request(queries.INSERT_NEW_JOB_LINE, {
- lineInput: [newAtsLine]
- });
+ try {
+ const result = await client.request(queries.INSERT_NEW_JOB_LINE, {
+ lineInput: [newAtsLine]
+ });
- job.joblines.push(newAtsLine);
+ if (result) {
+ job.joblines.push(newAtsLine);
+ }
+ } catch (error) {
+ logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, {
+ jobid: job.id,
+ error: error.message,
+ stack: error.stack
+ });
+ }
}
- //If it does not, create one for local calculations and insert it.
+ //If it does, update it in place, and make sure it is updated for local calculations.
else {
- const result = await client.request(queries.UPDATE_JOB_LINE, {
- line: { act_price: atsAmount },
- lineId: job.joblines[atsLineIndex].id
- });
- job.joblines[atsLineIndex].act_price = atsAmount;
+ try {
+ const result = await client.request(queries.UPDATE_JOB_LINE, {
+ line: { act_price: atsAmount },
+ lineId: job.joblines[atsLineIndex].id
+ });
+ if (result) {
+ job.joblines[atsLineIndex].act_price = atsAmount;
+ }
+ } catch (error) {
+ logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, {
+ jobid: job.id,
+ atsLineIndex: atsLineIndex,
+ atsAmount: atsAmount,
+ jobline: job.joblines[atsLineIndex],
+ error: error.message,
+ stack: error.stack
+ });
+ }
}
}
}
@@ -314,7 +345,7 @@ async function CalculateRatesTotals({ job, client }) {
let hasMashLine = false;
let hasMahwLine = false;
let hasCustomMahwLine;
- let mapaOpCodes = ParseCalopCode(job.materials["MAPA"]?.cal_opcode);
+ // let mapaOpCodes = ParseCalopCode(job.materials["MAPA"]?.cal_opcode);
let mashOpCodes = ParseCalopCode(job.materials["MASH"]?.cal_opcode);
jobLines.forEach((item) => {
@@ -564,7 +595,7 @@ function CalculatePartsTotals(jobLines, parts_tax_rates, job) {
}
};
- default:
+ default: {
if (!value.part_type && value.db_ref !== "900510" && value.db_ref !== "900511") return acc;
const discountAmount =
@@ -631,6 +662,7 @@ function CalculatePartsTotals(jobLines, parts_tax_rates, job) {
)
}
};
+ }
}
},
{
@@ -652,7 +684,7 @@ function CalculatePartsTotals(jobLines, parts_tax_rates, job) {
let adjustments = {};
//Track all adjustments that need to be made.
- const linesToAdjustForDiscount = [];
+ //const linesToAdjustForDiscount = [];
Object.keys(parts_tax_rates).forEach((key) => {
//Check if there's a discount or a mark up.
let disc = Dinero(),
@@ -1019,7 +1051,9 @@ function CalculateTaxesTotals(job, otherTotals) {
}
} catch (error) {
logger.log("job-totals-USA Key with issue", "error", null, job.id, {
- key
+ key: key,
+ error: error.message,
+ stack: error.stack
});
}
});
@@ -1157,6 +1191,7 @@ function CalculateTaxesTotals(job, otherTotals) {
exports.default = Totals;
+//eslint-disable-next-line no-unused-vars
function DiscountNotAlreadyCounted(jobline, joblines) {
return false;
}
@@ -1172,27 +1207,35 @@ function IsTrueOrYes(value) {
return value === true || value === "Y" || value === "y";
}
-async function UpdateJobLines(joblinesToUpdate) {
- if (joblinesToUpdate.length === 0) return;
- const updateQueries = joblinesToUpdate.map((line, index) =>
- generateUpdateQuery(_.pick(line, ["id", "prt_dsmk_m", "prt_dsmk_p"]), index)
- );
- const query = `
- mutation UPDATE_EST_LINES{
- ${updateQueries}
- }
- `;
+// Function not in use from RO to IO Merger 02/05/2024
+// async function UpdateJobLines(joblinesToUpdate) {
+// if (joblinesToUpdate.length === 0) return;
+// const updateQueries = joblinesToUpdate.map((line, index) =>
+// generateUpdateQuery(_.pick(line, ["id", "prt_dsmk_m", "prt_dsmk_p"]), index)
+// );
+// const query = `
+// mutation UPDATE_EST_LINES{
+// ${updateQueries}
+// }
+// `;
+// try {
+// const result = await adminClient.request(query);
+// void result;
+// } catch (error) {
+// logger.log("update-job-lines", "error", null, null, {
+// error: error.message,
+// stack: error.stack
+// });
+// }
+// }
- const result = await adminClient.request(query);
-}
-
-const generateUpdateQuery = (lineToUpdate, index) => {
- return `
- update_joblines${index}: update_joblines(where: { id: { _eq: "${
- lineToUpdate.id
- }" } }, _set: ${JSON.stringify(lineToUpdate).replace(/"(\w+)"\s*:/g, "$1:")}) {
- returning {
- id
- }
- }`;
-};
+// const generateUpdateQuery = (lineToUpdate, index) => {
+// return `
+// update_joblines${index}: update_joblines(where: { id: { _eq: "${
+// lineToUpdate.id
+// }" } }, _set: ${JSON.stringify(lineToUpdate).replace(/"(\w+)"\s*:/g, "$1:")}) {
+// returning {
+// id
+// }
+// }`;
+// };
diff --git a/server/job/job-totals.js b/server/job/job-totals.js
index 4cd45e13c..6182f9ced 100644
--- a/server/job/job-totals.js
+++ b/server/job/job-totals.js
@@ -1,7 +1,5 @@
const Dinero = require("dinero.js");
const queries = require("../graphql-client/queries");
-const adminClient = require("../graphql-client/graphql-client").client;
-const _ = require("lodash");
const logger = require("../utils/logger");
//****************************************************** */
@@ -44,11 +42,16 @@ exports.totalsSsu = async function (req, res) {
}
});
+ if (!result) {
+ throw new Error("Failed to update job totals");
+ }
+
res.status(200).send();
} catch (error) {
logger.log("job-totals-ssu-error", "ERROR", req.user.email, id, {
jobid: id,
- error
+ error: error.message,
+ stack: error.stack
});
res.status(503).send();
}
@@ -57,7 +60,7 @@ exports.totalsSsu = async function (req, res) {
//IMPORTANT*** These two functions MUST be mirrrored.
async function TotalsServerSide(req, res) {
const { job, client } = req.body;
- await AutoAddAtsIfRequired({ job: job, client: client });
+ await AtsAdjustmentsIfRequired({ job: job, client: client, user: req?.user });
try {
let ret = {
@@ -71,7 +74,8 @@ async function TotalsServerSide(req, res) {
} catch (error) {
logger.log("job-totals-ssu-error", "ERROR", req?.user?.email, job.id, {
jobid: job.id,
- error
+ error: error.message,
+ stack: error.stack
});
res.status(400).send(JSON.stringify(error));
}
@@ -83,13 +87,12 @@ async function Totals(req, res) {
const logger = req.logger;
const client = req.userGraphQLClient;
- logger.log("job-totals", "DEBUG", req.user.email, job.id, {
- jobid: job.id
+ logger.log("job-totals-ssu", "DEBUG", req.user.email, job.id, {
+ jobid: job.id,
+ id: id
});
- logger.log("job-totals-ssu", "DEBUG", req.user.email, id, null);
-
- await AutoAddAtsIfRequired({ job, client });
+ await AtsAdjustmentsIfRequired({ job, client, user: req.user });
try {
let ret = {
@@ -101,48 +104,54 @@ async function Totals(req, res) {
res.status(200).json(ret);
} catch (error) {
- logger.log("job-totals-error", "ERROR", req.user.email, job.id, {
+ logger.log("job-totals-ssu-error", "ERROR", req.user.email, job.id, {
jobid: job.id,
- error
+ error: error.message,
+ stack: error.stack
});
res.status(400).send(JSON.stringify(error));
}
}
-async function AutoAddAtsIfRequired({ job, client }) {
- //Check if ATS should be automatically added.
- if (job.auto_add_ats) {
- //Get the total sum of hours that should be the ATS amount.
- //Check to see if an ATS line exists.
+async function AtsAdjustmentsIfRequired({ job, client, user }) {
+ if (job.auto_add_ats || job.flat_rate_ats) {
+ let atsAmount = 0;
let atsLineIndex = null;
- const atsHours = job.joblines.reduce((acc, val, index) => {
- if (val.line_desc && val.line_desc.toLowerCase() === "ats amount") {
- atsLineIndex = index;
- }
- if (
- val.mod_lbr_ty !== "LA1" &&
- val.mod_lbr_ty !== "LA2" &&
- val.mod_lbr_ty !== "LA3" &&
- val.mod_lbr_ty !== "LA4" &&
- val.mod_lbr_ty !== "LAU" &&
- val.mod_lbr_ty !== "LAG" &&
- val.mod_lbr_ty !== "LAS" &&
- val.mod_lbr_ty !== "LAA"
- ) {
- acc = acc + val.mod_lb_hrs;
- }
+ //Check if ATS should be automatically added.
+ if (job.auto_add_ats) {
+ const excludedLaborTypes = new Set(["LAA", "LAG", "LAS", "LAU", "LA1", "LA2", "LA3", "LA4"]);
- return acc;
- }, 0);
+ //Get the total sum of hours that should be the ATS amount.
+ //Check to see if an ATS line exists.
+ const atsHours = job.joblines.reduce((acc, val, index) => {
+ if (val.line_desc?.toLowerCase() === "ats amount") {
+ atsLineIndex = index;
+ }
- const atsAmount = atsHours * (job.rate_ats || 0);
- //If it does, update it in place, and make sure it is updated for local calculations.
+ if (!excludedLaborTypes.has(val.mod_lbr_ty)) {
+ acc = acc + val.mod_lb_hrs;
+ }
+
+ return acc;
+ }, 0);
+
+ atsAmount = atsHours * (job.rate_ats || 0);
+ }
+
+ //Check if a Flat Rate ATS should be added.
+ if (job.flat_rate_ats) {
+ atsLineIndex = ((i) => (i === -1 ? null : i))(
+ job.joblines.findIndex((line) => line.line_desc?.toLowerCase() === "ats amount")
+ );
+ atsAmount = job.rate_ats_flat || 0;
+ }
+
+ //If it does not, create one for local calculations and insert it.
if (atsLineIndex === null) {
const newAtsLine = {
jobid: job.id,
alt_partm: null,
- line_no: 35,
unq_seq: 0,
line_ind: "E",
line_desc: "ATS Amount",
@@ -167,22 +176,43 @@ async function AutoAddAtsIfRequired({ job, client }) {
prt_dsmk_m: 0.0
};
- const result = await client.request(queries.INSERT_NEW_JOB_LINE, {
- lineInput: [newAtsLine]
- });
+ try {
+ const result = await client.request(queries.INSERT_NEW_JOB_LINE, {
+ lineInput: [newAtsLine]
+ });
- job.joblines.push(newAtsLine);
+ if (result) {
+ job.joblines.push(newAtsLine);
+ }
+ } catch (error) {
+ logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, {
+ jobid: job.id,
+ error: error.message,
+ stack: error.stack
+ });
+ }
}
- //If it does not, create one for local calculations and insert it.
+ //If it does, update it in place, and make sure it is updated for local calculations.
else {
- const result = await client.request(queries.UPDATE_JOB_LINE, {
- line: { act_price: atsAmount },
- lineId: job.joblines[atsLineIndex].id
- });
- job.joblines[atsLineIndex].act_price = atsAmount;
+ try {
+ const result = await client.request(queries.UPDATE_JOB_LINE, {
+ line: { act_price: atsAmount },
+ lineId: job.joblines[atsLineIndex].id
+ });
+ if (result) {
+ job.joblines[atsLineIndex].act_price = atsAmount;
+ }
+ } catch (error) {
+ logger.log("job-totals-ssu-ats-error", "ERROR", user?.email, job.id, {
+ jobid: job.id,
+ atsLineIndex: atsLineIndex,
+ atsAmount: atsAmount,
+ jobline: job.joblines[atsLineIndex],
+ error: error.message,
+ stack: error.stack
+ });
+ }
}
-
- //console.log(job.jobLines);
}
}
diff --git a/server/notifications/eventHandlers.js b/server/notifications/eventHandlers.js
new file mode 100644
index 000000000..eeb86981d
--- /dev/null
+++ b/server/notifications/eventHandlers.js
@@ -0,0 +1,199 @@
+/**
+ * @fileoverview Notification event handlers.
+ * This module exports functions to handle various notification events.
+ * Each handler optionally calls the scenarioParser and logs errors if they occur,
+ * then returns a JSON response with a success message.
+ */
+
+const scenarioParser = require("./scenarioParser");
+
+/**
+ * Processes a notification event by invoking the scenario parser.
+ * The scenarioParser is intentionally not awaited so that the response is sent immediately.
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @param {string} parserPath - The key path to be passed to scenarioParser.
+ * @param {string} successMessage - The message to return on success.
+ * @returns {Promise} A promise that resolves to an Express JSON response.
+ */
+async function processNotificationEvent(req, res, parserPath, successMessage) {
+ const { logger } = req;
+
+ // Call scenarioParser but don't await it; log any error that occurs.
+ scenarioParser(req, parserPath).catch((error) => {
+ logger.log("notifications-error", "error", "notifications", null, { message: error?.message, stack: error?.stack });
+ });
+
+ return res.status(200).json({ message: successMessage });
+}
+
+/**
+ * Handle job change notifications.
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Promise} JSON response with a success message.
+ */
+const handleJobsChange = async (req, res) =>
+ processNotificationEvent(req, res, "req.body.event.new.id", "Job Notifications Event Handled.");
+
+/**
+ * Handle bills change notifications.
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Promise} JSON response with a success message.
+ */
+const handleBillsChange = async (req, res) =>
+ processNotificationEvent(req, res, "req.body.event.new.jobid", "Bills Changed Notification Event Handled.");
+
+/**
+ * Handle documents change notifications.
+ * Processes both old and new job IDs if the document was moved between jobs.
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Promise} JSON response with a success message.
+ */
+const handleDocumentsChange = async (req, res) => {
+ const { logger } = req;
+ const newJobId = req.body?.event?.data?.new?.jobid;
+ const oldJobId = req.body?.event?.data?.old?.jobid;
+
+ // If jobid changed (document moved between jobs), we need to notify both jobs
+ if (oldJobId && newJobId && oldJobId !== newJobId) {
+ // Process notification for new job ID
+ scenarioParser(req, "req.body.event.new.jobid").catch((error) => {
+ logger.log("notifications-error", "error", "notifications", null, {
+ message: error?.message,
+ stack: error?.stack
+ });
+ });
+
+ // Create a modified request for old job ID
+ const oldJobReq = {
+ body: {
+ ...req.body,
+ event: {
+ ...req.body.event,
+ data: {
+ new: {
+ ...req.body.event.data.old,
+ // Add a flag to indicate this document was moved away
+ _documentMoved: true,
+ _movedToJob: newJobId
+ },
+ old: null
+ }
+ }
+ },
+ logger,
+ sessionUtils: req.sessionUtils
+ };
+
+ // Process notification for old job ID using the modified request
+ scenarioParser(oldJobReq, "req.body.event.new.jobid").catch((error) => {
+ logger.log("notifications-error", "error", "notifications", null, {
+ message: error?.message,
+ stack: error?.stack
+ });
+ });
+
+ return res.status(200).json({ message: "Documents Change Notifications Event Handled for both jobs." });
+ }
+
+ // Otherwise just process the new job ID
+ scenarioParser(req, "req.body.event.new.jobid").catch((error) => {
+ logger.log("notifications-error", "error", "notifications", null, {
+ message: error?.message,
+ stack: error?.stack
+ });
+ });
+
+ return res.status(200).json({ message: "Documents Change Notifications Event Handled." });
+};
+
+/**
+ * Handle job lines change notifications.
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Promise} JSON response with a success message.
+ */
+const handleJobLinesChange = async (req, res) =>
+ processNotificationEvent(req, res, "req.body.event.new.jobid", "JobLines Change Notifications Event Handled.");
+
+/**
+ * Handle notes change notifications.
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Promise} JSON response with a success message.
+ */
+const handleNotesChange = async (req, res) =>
+ processNotificationEvent(req, res, "req.body.event.new.jobid", "Notes Changed Notification Event Handled.");
+
+/**
+ * Handle payments change notifications.
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Promise} JSON response with a success message.
+ */
+const handlePaymentsChange = async (req, res) =>
+ processNotificationEvent(req, res, "req.body.event.new.jobid", "Payments Changed Notification Event Handled.");
+
+/**
+ * Handle tasks change notifications.
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Promise} JSON response with a success message.
+ */
+const handleTasksChange = async (req, res) =>
+ processNotificationEvent(req, res, "req.body.event.new.jobid", "Tasks Notifications Event Handled.");
+
+/**
+ * Handle time tickets change notifications.
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Promise} JSON response with a success message.
+ */
+const handleTimeTicketsChange = async (req, res) =>
+ processNotificationEvent(req, res, "req.body.event.new.jobid", "Time Tickets Changed Notification Event Handled.");
+
+/**
+ * Handle parts dispatch change notifications.
+ * Note: Placeholder
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Object} JSON response with a success message.
+ *
+ */
+const handlePartsDispatchChange = (req, res) => res.status(200).json({ message: "Parts Dispatch change handled." });
+
+/**
+ * Handle parts order change notifications.
+ * Note: Placeholder
+ *
+ * @param {Object} req - Express request object.
+ * @param {Object} res - Express response object.
+ * @returns {Object} JSON response with a success message.
+ */
+const handlePartsOrderChange = (req, res) => res.status(200).json({ message: "Parts Order change handled." });
+
+module.exports = {
+ handleJobsChange,
+ handleBillsChange,
+ handleDocumentsChange,
+ handleJobLinesChange,
+ handleNotesChange,
+ handlePartsDispatchChange,
+ handlePartsOrderChange,
+ handlePaymentsChange,
+ handleTasksChange,
+ handleTimeTicketsChange
+};
diff --git a/server/notifications/eventHandlers/handeJobsChange.js b/server/notifications/eventHandlers/handeJobsChange.js
deleted file mode 100644
index 9449f23c4..000000000
--- a/server/notifications/eventHandlers/handeJobsChange.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const handleJobsChange = (req, res) => {
- return res.status(200).json({ message: "Jobs change handled." });
-};
-
-module.exports = handleJobsChange;
diff --git a/server/notifications/eventHandlers/handleBillsChange.js b/server/notifications/eventHandlers/handleBillsChange.js
deleted file mode 100644
index d444848f2..000000000
--- a/server/notifications/eventHandlers/handleBillsChange.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const handleBillsChange = (req, res) => {
- return res.status(200).json({ message: "Bills change handled." });
-};
-
-module.exports = handleBillsChange;
diff --git a/server/notifications/eventHandlers/handlePartsDispatchChange.js b/server/notifications/eventHandlers/handlePartsDispatchChange.js
deleted file mode 100644
index fd3f78b97..000000000
--- a/server/notifications/eventHandlers/handlePartsDispatchChange.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const handlePartsDispatchChange = (req, res) => {
- return res.status(200).json({ message: "Parts Dispatch change handled." });
-};
-
-module.exports = handlePartsDispatchChange;
diff --git a/server/notifications/eventHandlers/handlePartsOrderChange.js b/server/notifications/eventHandlers/handlePartsOrderChange.js
deleted file mode 100644
index 16c09ef2f..000000000
--- a/server/notifications/eventHandlers/handlePartsOrderChange.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const handlePartsOrderChange = (req, res) => {
- return res.status(200).json({ message: "Parts Order change handled." });
-};
-
-module.exports = handlePartsOrderChange;
diff --git a/server/notifications/eventHandlers/handleTasksChange.js b/server/notifications/eventHandlers/handleTasksChange.js
deleted file mode 100644
index 5a6e7f344..000000000
--- a/server/notifications/eventHandlers/handleTasksChange.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const handleTasksChange = (req, res) => {
- return res.status(200).json({ message: "Tasks change handled." });
-};
-
-module.exports = handleTasksChange;
diff --git a/server/notifications/eventHandlers/handleTimeTicketsChange.js b/server/notifications/eventHandlers/handleTimeTicketsChange.js
deleted file mode 100644
index 403fa4060..000000000
--- a/server/notifications/eventHandlers/handleTimeTicketsChange.js
+++ /dev/null
@@ -1,5 +0,0 @@
-const handleTimeTicketsChange = (req, res) => {
- return res.status(200).json({ message: "Time Tickets change handled." });
-};
-
-module.exports = handleTimeTicketsChange;
diff --git a/server/notifications/eventParser.js b/server/notifications/eventParser.js
new file mode 100644
index 000000000..025cbd02d
--- /dev/null
+++ b/server/notifications/eventParser.js
@@ -0,0 +1,74 @@
+/**
+ * Parses an event by comparing old and new data to determine which fields have changed.
+ *
+ * This function analyzes the differences between previous (`oldData`) and current (`newData`)
+ * data states to identify changed fields. It determines if the event is a new entry or an update
+ * and returns details about changed fields, the event type, and associated metadata.
+ *
+ * @param {Object} options - Configuration options for parsing the event.
+ * @param {Object} [options.oldData] - The previous state of the data (undefined for new entries).
+ * @param {Object} options.newData - The current state of the data.
+ * @param {string} options.trigger - The type of event trigger (e.g., 'INSERT', 'UPDATE').
+ * @param {string} options.table - The name of the table associated with the event.
+ * @param {string} [options.jobId] - The job ID, if already extracted by the caller (optional).
+ * @returns {Object} An object containing the parsed event details:
+ * - {Array} changedFieldNames - List of field names that have changed.
+ * - {Object} changedFields - Map of changed fields with their old and new values.
+ * - {boolean} isNew - True if the event is a new entry (no oldData provided).
+ * - {Object} data - The current data state (`newData`).
+ * - {string} trigger - The event trigger type.
+ * - {string} table - The table name.
+ * - {string|null} jobId - The provided jobId or null if not provided.
+ */
+const eventParser = async ({ oldData, newData, trigger, table, jobId = null }) => {
+ const isNew = !oldData; // True if no old data exists, indicating a new entry
+ let changedFields = {};
+ let changedFieldNames = [];
+
+ if (isNew) {
+ // For new entries, all fields in newData are considered "changed" (from undefined to their value)
+ changedFields = Object.fromEntries(
+ Object.entries(newData).map(([key, value]) => [key, { old: undefined, new: value }])
+ );
+ changedFieldNames = Object.keys(newData); // All keys are new
+ } else {
+ // Compare oldData and newData to detect updates
+ for (const key in newData) {
+ if (Object.prototype.hasOwnProperty.call(newData, key)) {
+ // Check if the field is new or its value has changed
+ if (
+ !Object.prototype.hasOwnProperty.call(oldData, key) || // Field didn’t exist before
+ JSON.stringify(oldData[key]) !== JSON.stringify(newData[key]) // Values differ (deep comparison)
+ ) {
+ changedFields[key] = {
+ old: oldData[key], // Undefined if field wasn’t in oldData
+ new: newData[key]
+ };
+ changedFieldNames.push(key);
+ }
+ }
+ }
+ // Identify fields removed in newData (present in oldData but absent in newData)
+ for (const key in oldData) {
+ if (Object.prototype.hasOwnProperty.call(oldData, key) && !Object.prototype.hasOwnProperty.call(newData, key)) {
+ changedFields[key] = {
+ old: oldData[key],
+ new: null // Mark as removed
+ };
+ changedFieldNames.push(key);
+ }
+ }
+ }
+
+ return {
+ changedFieldNames, // Array of fields that changed
+ changedFields, // Object with old/new values for changed fields
+ isNew, // Boolean indicating if this is a new entry
+ data: newData, // Current data state
+ trigger, // Event trigger (e.g., 'INSERT', 'UPDATE')
+ table, // Associated table name
+ jobId // Provided jobId or null
+ };
+};
+
+module.exports = eventParser;
diff --git a/server/notifications/queues/appQueue.js b/server/notifications/queues/appQueue.js
new file mode 100644
index 000000000..9bf35de54
--- /dev/null
+++ b/server/notifications/queues/appQueue.js
@@ -0,0 +1,297 @@
+const { Queue, Worker } = require("bullmq");
+const { INSERT_NOTIFICATIONS_MUTATION } = require("../../graphql-client/queries");
+const { registerCleanupTask } = require("../../utils/cleanupManager");
+const getBullMQPrefix = require("../../utils/getBullMQPrefix");
+const devDebugLogger = require("../../utils/devDebugLogger");
+const graphQLClient = require("../../graphql-client/graphql-client").client;
+
+// Base time-related constant in minutes, sourced from environment variable or defaulting to 1
+const APP_CONSOLIDATION_DELAY_IN_MINS = (() => {
+ const envValue = process.env?.APP_CONSOLIDATION_DELAY_IN_MINS;
+ const parsedValue = envValue ? parseInt(envValue, 10) : NaN;
+ return isNaN(parsedValue) ? 3 : Math.max(1, parsedValue); // Default to 3, ensure at least 1
+})();
+
+// Base time-related constant (in milliseconds) / DO NOT TOUCH
+const APP_CONSOLIDATION_DELAY = APP_CONSOLIDATION_DELAY_IN_MINS * 60000; // 1 minute (base timeout)
+
+// Derived time-related constants based on APP_CONSOLIDATION_DELAY / DO NOT TOUCH
+const NOTIFICATION_STORAGE_EXPIRATION = APP_CONSOLIDATION_DELAY * 1.5; // 1.5 minutes (90s)
+const CONSOLIDATION_FLAG_EXPIRATION = APP_CONSOLIDATION_DELAY * 1.5; // 1.5 minutes (90s)
+const LOCK_EXPIRATION = APP_CONSOLIDATION_DELAY * 0.25; // 15 seconds (quarter of base)
+const RATE_LIMITER_DURATION = APP_CONSOLIDATION_DELAY * 0.1; // 6 seconds (tenth of base)
+
+let addQueue;
+let consolidateQueue;
+
+/**
+ * Builds the scenario_text, fcm_text, and scenario_meta for a batch of notifications.
+ *
+ * @param {Array} notifications - Array of notification objects with 'body' and 'variables'.
+ * @returns {Object} An object with 'scenario_text', 'fcm_text', and 'scenario_meta'.
+ */
+const buildNotificationContent = (notifications) => {
+ const scenarioText = notifications.map((n) => n.body); // Array of text entries
+ const fcmText = scenarioText.join(". "); // Concatenated text with period separator
+ const scenarioMeta = notifications.map((n) => n.variables || {}); // Array of metadata objects
+
+ return {
+ scenario_text: scenarioText,
+ fcm_text: fcmText ? `${fcmText}.` : null, // Add trailing period if non-empty, otherwise null
+ scenario_meta: scenarioMeta
+ };
+};
+
+/**
+ * Initializes the notification queues and workers for adding and consolidating notifications.
+ */
+const loadAppQueue = async ({ pubClient, logger, redisHelpers, ioRedis }) => {
+ if (!addQueue || !consolidateQueue) {
+ const prefix = getBullMQPrefix();
+ const devKey = process.env?.NODE_ENV === "production" ? "prod" : "dev";
+
+ devDebugLogger(`Initializing Notifications Queues with prefix: ${prefix}`);
+
+ addQueue = new Queue("notificationsAdd", {
+ prefix,
+ connection: pubClient,
+ defaultJobOptions: { removeOnComplete: true, removeOnFail: true }
+ });
+
+ consolidateQueue = new Queue("notificationsConsolidate", {
+ prefix,
+ connection: pubClient,
+ defaultJobOptions: { removeOnComplete: true, removeOnFail: true }
+ });
+
+ const addWorker = new Worker(
+ "notificationsAdd",
+ async (job) => {
+ const { jobId, key, variables, recipients, body, jobRoNumber } = job.data;
+ devDebugLogger(`Adding notifications for jobId ${jobId}`);
+
+ const redisKeyPrefix = `app:${devKey}:notifications:${jobId}`;
+ const notification = { key, variables, body, jobRoNumber, timestamp: Date.now() };
+
+ for (const recipient of recipients) {
+ const { user } = recipient;
+ const userKey = `${redisKeyPrefix}:${user}`;
+ const existingNotifications = await pubClient.get(userKey);
+ const notifications = existingNotifications ? JSON.parse(existingNotifications) : [];
+ notifications.push(notification);
+ await pubClient.set(userKey, JSON.stringify(notifications), "EX", NOTIFICATION_STORAGE_EXPIRATION / 1000);
+ devDebugLogger(`Stored notification for ${user} under ${userKey}: ${JSON.stringify(notifications)}`);
+ }
+
+ const consolidateKey = `app:${devKey}:consolidate:${jobId}`;
+ const flagSet = await pubClient.setnx(consolidateKey, "pending");
+ devDebugLogger(`Consolidation flag set for jobId ${jobId}: ${flagSet}`);
+
+ if (flagSet) {
+ await consolidateQueue.add(
+ "consolidate-notifications",
+ { jobId, recipients },
+ {
+ jobId: `consolidate:${jobId}`,
+ delay: APP_CONSOLIDATION_DELAY,
+ attempts: 3,
+ backoff: LOCK_EXPIRATION
+ }
+ );
+ devDebugLogger(`Scheduled consolidation for jobId ${jobId}`);
+ await pubClient.expire(consolidateKey, CONSOLIDATION_FLAG_EXPIRATION / 1000);
+ } else {
+ devDebugLogger(`Consolidation already scheduled for jobId ${jobId}`);
+ }
+ },
+ {
+ prefix,
+ connection: pubClient,
+ concurrency: 5
+ }
+ );
+
+ const consolidateWorker = new Worker(
+ "notificationsConsolidate",
+ async (job) => {
+ const { jobId, recipients } = job.data;
+ devDebugLogger(`Consolidating notifications for jobId ${jobId}`);
+
+ const redisKeyPrefix = `app:${devKey}:notifications:${jobId}`;
+ const lockKey = `lock:${devKey}:consolidate:${jobId}`;
+
+ const lockAcquired = await pubClient.set(lockKey, "locked", "NX", "EX", LOCK_EXPIRATION / 1000);
+ devDebugLogger(`Lock acquisition for jobId ${jobId}: ${lockAcquired}`);
+
+ if (lockAcquired) {
+ try {
+ const allNotifications = {};
+ const uniqueUsers = [...new Set(recipients.map((r) => r.user))];
+ devDebugLogger(`Unique users for jobId ${jobId}: ${uniqueUsers}`);
+
+ for (const user of uniqueUsers) {
+ const userKey = `${redisKeyPrefix}:${user}`;
+ const notifications = await pubClient.get(userKey);
+ devDebugLogger(`Retrieved notifications for ${user}: ${notifications}`);
+
+ if (notifications) {
+ const parsedNotifications = JSON.parse(notifications);
+ const userRecipients = recipients.filter((r) => r.user === user);
+ for (const { bodyShopId } of userRecipients) {
+ allNotifications[user] = allNotifications[user] || {};
+ allNotifications[user][bodyShopId] = parsedNotifications;
+ }
+ await pubClient.del(userKey);
+ devDebugLogger(`Deleted Redis key ${userKey}`);
+ } else {
+ devDebugLogger(`No notifications found for ${user} under ${userKey}`);
+ }
+ }
+
+ devDebugLogger(`Consolidated notifications: ${JSON.stringify(allNotifications)}`);
+
+ // Insert notifications into the database and collect IDs
+ const notificationInserts = [];
+ const notificationIdMap = new Map();
+
+ for (const [user, bodyShopData] of Object.entries(allNotifications)) {
+ const userRecipients = recipients.filter((r) => r.user === user);
+ const associationId = userRecipients[0]?.associationId;
+
+ for (const [bodyShopId, notifications] of Object.entries(bodyShopData)) {
+ const { scenario_text, fcm_text, scenario_meta } = buildNotificationContent(notifications);
+ notificationInserts.push({
+ jobid: jobId,
+ associationid: associationId,
+ scenario_text: JSON.stringify(scenario_text),
+ fcm_text: fcm_text,
+ scenario_meta: JSON.stringify(scenario_meta)
+ });
+ notificationIdMap.set(`${user}:${bodyShopId}`, null);
+ }
+ }
+
+ if (notificationInserts.length > 0) {
+ const insertResponse = await graphQLClient.request(INSERT_NOTIFICATIONS_MUTATION, {
+ objects: notificationInserts
+ });
+ devDebugLogger(
+ `Inserted ${insertResponse.insert_notifications.affected_rows} notifications for jobId ${jobId}`
+ );
+
+ insertResponse.insert_notifications.returning.forEach((row, index) => {
+ const user = uniqueUsers[Math.floor(index / Object.keys(allNotifications[uniqueUsers[0]]).length)];
+ const bodyShopId = Object.keys(allNotifications[user])[
+ index % Object.keys(allNotifications[user]).length
+ ];
+ notificationIdMap.set(`${user}:${bodyShopId}`, row.id);
+ });
+ }
+
+ // Emit notifications to users via Socket.io with notification ID
+ for (const [user, bodyShopData] of Object.entries(allNotifications)) {
+ const userMapping = await redisHelpers.getUserSocketMapping(user);
+ const userRecipients = recipients.filter((r) => r.user === user);
+ const associationId = userRecipients[0]?.associationId;
+
+ for (const [bodyShopId, notifications] of Object.entries(bodyShopData)) {
+ const notificationId = notificationIdMap.get(`${user}:${bodyShopId}`);
+ const jobRoNumber = notifications[0]?.jobRoNumber;
+
+ if (userMapping && userMapping[bodyShopId]?.socketIds) {
+ userMapping[bodyShopId].socketIds.forEach((socketId) => {
+ ioRedis.to(socketId).emit("notification", {
+ jobId,
+ jobRoNumber,
+ bodyShopId,
+ notifications,
+ notificationId,
+ associationId
+ });
+ });
+ devDebugLogger(
+ `Sent ${notifications.length} consolidated notifications to ${user} for jobId ${jobId} with notificationId ${notificationId}`
+ );
+ } else {
+ devDebugLogger(`No socket IDs found for ${user} in bodyShopId ${bodyShopId}`);
+ }
+ }
+ }
+
+ await pubClient.del(`app:${devKey}:consolidate:${jobId}`);
+ } catch (err) {
+ logger.log(`app-queue-consolidation-error`, "ERROR", "notifications", "api", {
+ message: err?.message,
+ stack: err?.stack
+ });
+ throw err;
+ } finally {
+ await pubClient.del(lockKey);
+ }
+ } else {
+ devDebugLogger(`Skipped consolidation for jobId ${jobId} - lock held by another worker`);
+ }
+ },
+ {
+ prefix,
+ connection: pubClient,
+ concurrency: 1,
+ limiter: { max: 1, duration: RATE_LIMITER_DURATION }
+ }
+ );
+
+ addWorker.on("completed", (job) => devDebugLogger(`Add job ${job.id} completed`));
+ consolidateWorker.on("completed", (job) => devDebugLogger(`Consolidate job ${job.id} completed`));
+
+ addWorker.on("failed", (job, err) =>
+ logger.log(`app-queue-notification-error`, "ERROR", "notifications", "api", {
+ message: err?.message,
+ stack: err?.stack
+ })
+ );
+ consolidateWorker.on("failed", (job, err) =>
+ logger.log(`app-queue-consolidation-failed:`, "ERROR", "notifications", "api", {
+ message: err?.message,
+ stack: err?.stack
+ })
+ );
+
+ // Register cleanup task instead of direct process listeners
+ const shutdown = async () => {
+ devDebugLogger("Closing app queue workers...");
+ await Promise.all([addWorker.close(), consolidateWorker.close()]);
+ devDebugLogger("App queue workers closed");
+ };
+
+ registerCleanupTask(shutdown);
+ }
+
+ return addQueue;
+};
+
+/**
+ * Retrieves the initialized `addQueue` instance.
+ */
+const getQueue = () => {
+ if (!addQueue) throw new Error("Add queue not initialized. Ensure loadAppQueue is called during bootstrap.");
+ return addQueue;
+};
+
+/**
+ * Dispatches notifications to the `addQueue` for processing.
+ */
+const dispatchAppsToQueue = async ({ appsToDispatch, logger }) => {
+ const appQueue = getQueue();
+
+ for (const app of appsToDispatch) {
+ const { jobId, bodyShopId, key, variables, recipients, body, jobRoNumber } = app;
+ await appQueue.add(
+ "add-notification",
+ { jobId, bodyShopId, key, variables, recipients, body, jobRoNumber },
+ { jobId: `${jobId}:${Date.now()}` }
+ );
+ devDebugLogger(`Added notification to queue for jobId ${jobId} with ${recipients.length} recipients`);
+ }
+};
+
+module.exports = { loadAppQueue, getQueue, dispatchAppsToQueue };
diff --git a/server/notifications/queues/emailQueue.js b/server/notifications/queues/emailQueue.js
new file mode 100644
index 000000000..ff6702635
--- /dev/null
+++ b/server/notifications/queues/emailQueue.js
@@ -0,0 +1,252 @@
+const { Queue, Worker } = require("bullmq");
+const { sendTaskEmail } = require("../../email/sendemail");
+const generateEmailTemplate = require("../../email/generateTemplate");
+const { InstanceEndpoints } = require("../../utils/instanceMgr");
+const { registerCleanupTask } = require("../../utils/cleanupManager");
+const getBullMQPrefix = require("../../utils/getBullMQPrefix");
+const devDebugLogger = require("../../utils/devDebugLogger");
+const moment = require("moment-timezone");
+
+const EMAIL_CONSOLIDATION_DELAY_IN_MINS = (() => {
+ const envValue = process.env?.EMAIL_CONSOLIDATION_DELAY_IN_MINS;
+ const parsedValue = envValue ? parseInt(envValue, 10) : NaN;
+ return isNaN(parsedValue) ? 3 : Math.max(1, parsedValue); // Default to 3, ensure at least 1
+})();
+
+// Base time-related constant (in milliseconds) / DO NOT TOUCH
+const EMAIL_CONSOLIDATION_DELAY = EMAIL_CONSOLIDATION_DELAY_IN_MINS * 60000; // 1 minute (base timeout)
+
+// Derived time-related constants based on EMAIL_CONSOLIDATION_DELAY / DO NOT TOUCH, these are pegged to EMAIL_CONSOLIDATION_DELAY
+const CONSOLIDATION_KEY_EXPIRATION = EMAIL_CONSOLIDATION_DELAY * 1.5; // 1.5 minutes (90s, buffer for consolidation)
+const LOCK_EXPIRATION = EMAIL_CONSOLIDATION_DELAY * 0.25; // 15 seconds (quarter of base, for lock duration)
+const RATE_LIMITER_DURATION = EMAIL_CONSOLIDATION_DELAY * 0.1; // 6 seconds (tenth of base, for rate limiting)
+const NOTIFICATION_EXPIRATION = EMAIL_CONSOLIDATION_DELAY * 1.5; // 1.5 minutes (matches consolidation key expiration)
+
+let emailAddQueue;
+let emailConsolidateQueue;
+let emailAddWorker;
+let emailConsolidateWorker;
+
+/**
+ * Initializes the email notification queues and workers.
+ *
+ * @param {Object} options - Configuration options for queue initialization.
+ * @param {Object} options.pubClient - Redis client instance for queue communication.
+ * @param {Object} options.logger - Logger instance for logging events and debugging.
+ * @returns {Queue} The initialized `emailAddQueue` instance for dispatching notifications.
+ */
+const loadEmailQueue = async ({ pubClient, logger }) => {
+ if (!emailAddQueue || !emailConsolidateQueue) {
+ const prefix = getBullMQPrefix();
+ const devKey = process.env?.NODE_ENV === "production" ? "prod" : "dev";
+
+ devDebugLogger(`Initializing Email Notification Queues with prefix: ${prefix}`);
+
+ // Queue for adding email notifications
+ emailAddQueue = new Queue("emailAdd", {
+ prefix,
+ connection: pubClient,
+ defaultJobOptions: { removeOnComplete: true, removeOnFail: true }
+ });
+
+ // Queue for consolidating and sending emails
+ emailConsolidateQueue = new Queue("emailConsolidate", {
+ prefix,
+ connection: pubClient,
+ defaultJobOptions: { removeOnComplete: true, removeOnFail: true }
+ });
+
+ // Worker to process adding notifications
+ emailAddWorker = new Worker(
+ "emailAdd",
+ async (job) => {
+ const { jobId, jobRoNumber, bodyShopName, bodyShopTimezone, body, recipients } = job.data;
+ devDebugLogger(`Adding email notifications for jobId ${jobId}`);
+
+ const redisKeyPrefix = `email:${devKey}:notifications:${jobId}`;
+
+ for (const recipient of recipients) {
+ const { user, firstName, lastName } = recipient;
+ const userKey = `${redisKeyPrefix}:${user}`;
+ await pubClient.rpush(userKey, body);
+ await pubClient.expire(userKey, NOTIFICATION_EXPIRATION / 1000);
+ const detailsKey = `email:${devKey}:recipientDetails:${jobId}:${user}`;
+ await pubClient.hsetnx(detailsKey, "firstName", firstName || "");
+ await pubClient.hsetnx(detailsKey, "lastName", lastName || "");
+ await pubClient.hsetnx(detailsKey, "bodyShopTimezone", bodyShopTimezone);
+ await pubClient.expire(detailsKey, NOTIFICATION_EXPIRATION / 1000);
+ await pubClient.sadd(`email:${devKey}:recipients:${jobId}`, user);
+ devDebugLogger(`Stored message for ${user} under ${userKey}: ${body}`);
+ }
+
+ const consolidateKey = `email:${devKey}:consolidate:${jobId}`;
+ const flagSet = await pubClient.setnx(consolidateKey, "pending");
+ if (flagSet) {
+ await emailConsolidateQueue.add(
+ "consolidate-emails",
+ { jobId, jobRoNumber, bodyShopName, bodyShopTimezone },
+ {
+ jobId: `consolidate:${jobId}`,
+ delay: EMAIL_CONSOLIDATION_DELAY,
+ attempts: 3,
+ backoff: LOCK_EXPIRATION
+ }
+ );
+ devDebugLogger(`Scheduled email consolidation for jobId ${jobId}`);
+ await pubClient.expire(consolidateKey, CONSOLIDATION_KEY_EXPIRATION / 1000);
+ } else {
+ devDebugLogger(`Email consolidation already scheduled for jobId ${jobId}`);
+ }
+ },
+ {
+ prefix,
+ connection: pubClient,
+ concurrency: 5
+ }
+ );
+
+ // Worker to consolidate and send emails
+ emailConsolidateWorker = new Worker(
+ "emailConsolidate",
+ async (job) => {
+ const { jobId, jobRoNumber, bodyShopName } = job.data;
+ devDebugLogger(`Consolidating emails for jobId ${jobId}`);
+
+ const lockKey = `lock:${devKey}:emailConsolidate:${jobId}`;
+ const lockAcquired = await pubClient.set(lockKey, "locked", "NX", "EX", LOCK_EXPIRATION / 1000);
+ if (lockAcquired) {
+ try {
+ const recipientsSet = `email:${devKey}:recipients:${jobId}`;
+ const recipients = await pubClient.smembers(recipientsSet);
+ for (const recipient of recipients) {
+ const userKey = `email:${devKey}:notifications:${jobId}:${recipient}`;
+ const detailsKey = `email:${devKey}:recipientDetails:${jobId}:${recipient}`;
+ const messages = await pubClient.lrange(userKey, 0, -1);
+ if (messages.length > 0) {
+ const details = await pubClient.hgetall(detailsKey);
+ const firstName = details.firstName || "User";
+ const multipleUpdateString = messages.length > 1 ? "Updates" : "Update";
+ const subject = `${multipleUpdateString} for job ${jobRoNumber || "N/A"} at ${bodyShopName}`;
+ const timezone = moment.tz.zone(details?.bodyShopTimezone) ? details.bodyShopTimezone : "UTC";
+ const emailBody = generateEmailTemplate({
+ header: `${multipleUpdateString} for Job ${jobRoNumber || "N/A"}`,
+ subHeader: `Dear ${firstName},`,
+ dateLine: moment().tz(timezone).format("MM/DD/YYYY hh:mm a"),
+ body: `
+ There have been updates to job ${jobRoNumber || "N/A"} at ${bodyShopName}:
+
+ ${messages.map((msg) => `${msg} `).join("")}
+
+ Please check the job for more details.
+ `
+ });
+ await sendTaskEmail({
+ to: recipient,
+ subject,
+ type: "html",
+ html: emailBody
+ });
+ devDebugLogger(
+ `Sent consolidated email to ${recipient} for jobId ${jobId} with ${messages.length} updates`
+ );
+ await pubClient.del(userKey);
+ await pubClient.del(detailsKey);
+ }
+ }
+ await pubClient.del(recipientsSet);
+ await pubClient.del(`email:${devKey}:consolidate:${jobId}`);
+ } catch (err) {
+ logger.log(`email-queue-consolidation-error`, "ERROR", "notifications", "api", {
+ message: err?.message,
+ stack: err?.stack
+ });
+ throw err;
+ } finally {
+ await pubClient.del(lockKey);
+ }
+ } else {
+ devDebugLogger(`Skipped email consolidation for jobId ${jobId} - lock held by another worker`);
+ }
+ },
+ {
+ prefix,
+ connection: pubClient,
+ concurrency: 1,
+ limiter: { max: 1, duration: RATE_LIMITER_DURATION }
+ }
+ );
+
+ // Event handlers for workers
+ emailAddWorker.on("completed", (job) => devDebugLogger(`Email add job ${job.id} completed`));
+ emailConsolidateWorker.on("completed", (job) => devDebugLogger(`Email consolidate job ${job.id} completed`));
+
+ emailAddWorker.on("failed", (job, err) =>
+ logger.log(`add-email-queue-failed`, "ERROR", "notifications", "api", {
+ message: err?.message,
+ stack: err?.stack
+ })
+ );
+ emailConsolidateWorker.on("failed", (job, err) =>
+ logger.log(`email-consolidation-job-failed`, "ERROR", "notifications", "api", {
+ message: err?.message,
+ stack: err?.stack
+ })
+ );
+
+ // Register cleanup task instead of direct process listeners
+ const shutdown = async () => {
+ devDebugLogger("Closing email queue workers...");
+ await Promise.all([emailAddWorker.close(), emailConsolidateWorker.close()]);
+ devDebugLogger("Email queue workers closed");
+ };
+ registerCleanupTask(shutdown);
+ }
+
+ return emailAddQueue;
+};
+
+/**
+ * Retrieves the initialized `emailAddQueue` instance.
+ *
+ * @returns {Queue} The `emailAddQueue` instance for adding notifications.
+ * @throws {Error} If `emailAddQueue` is not initialized.
+ */
+const getQueue = () => {
+ if (!emailAddQueue) {
+ throw new Error("Email add queue not initialized. Ensure loadEmailQueue is called during bootstrap.");
+ }
+ return emailAddQueue;
+};
+
+/**
+ * Dispatches email notifications to the `emailAddQueue` for processing.
+ *
+ * @param {Object} options - Options for dispatching notifications.
+ * @param {Array} options.emailsToDispatch - Array of email notification objects.
+ * @param {Object} options.logger - Logger instance for logging dispatch events.
+ * @returns {Promise} Resolves when all notifications are added to the queue.
+ */
+const dispatchEmailsToQueue = async ({ emailsToDispatch, logger }) => {
+ const emailAddQueue = getQueue();
+
+ for (const email of emailsToDispatch) {
+ const { jobId, jobRoNumber, bodyShopName, bodyShopTimezone, body, recipients } = email;
+
+ if (!jobId || !jobRoNumber || !bodyShopName || !body || !recipients.length) {
+ devDebugLogger(
+ `Skipping email dispatch for jobId ${jobId} due to missing data: ` +
+ `jobRoNumber=${jobRoNumber || "N/A"}, bodyShopName=${bodyShopName}, body=${body}, recipients=${recipients.length}`
+ );
+ continue;
+ }
+
+ await emailAddQueue.add(
+ "add-email-notification",
+ { jobId, jobRoNumber, bodyShopName, bodyShopTimezone, body, recipients },
+ { jobId: `${jobId}:${Date.now()}` }
+ );
+ devDebugLogger(`Added email notification to queue for jobId ${jobId} with ${recipients.length} recipients`);
+ }
+};
+
+module.exports = { loadEmailQueue, getQueue, dispatchEmailsToQueue };
diff --git a/server/notifications/scenarioBuilders.js b/server/notifications/scenarioBuilders.js
new file mode 100644
index 000000000..b3f4d0fd2
--- /dev/null
+++ b/server/notifications/scenarioBuilders.js
@@ -0,0 +1,414 @@
+const { getJobAssignmentType, formatTaskPriority } = require("./stringHelpers");
+const moment = require("moment-timezone");
+const { startCase } = require("lodash");
+const Dinero = require("dinero.js");
+
+Dinero.globalRoundingMode = "HALF_EVEN";
+
+/**
+ * Creates a standard notification object with app, email, and FCM properties and populates recipients.
+ * @param {Object} data - Input data containing jobId, jobRoNumber, bodyShopId, bodyShopName, and scenarioWatchers
+ * @param {string} key - Notification key for the app
+ * @param {string} body - Notification body text
+ * @param {Object} [variables={}] - Variables for the app notification
+ * @returns {Object} Notification object with populated recipients
+ */
+const buildNotification = (data, key, body, variables = {}) => {
+ const result = {
+ app: {
+ jobId: data.jobId,
+ jobRoNumber: data.jobRoNumber,
+ bodyShopId: data.bodyShopId,
+ key,
+ body,
+ variables,
+ recipients: []
+ },
+ email: {
+ jobId: data.jobId,
+ jobRoNumber: data.jobRoNumber,
+ bodyShopName: data.bodyShopName,
+ bodyShopTimezone: data.bodyShopTimezone,
+ body,
+ recipients: []
+ },
+ fcm: { recipients: [] }
+ };
+
+ // Populate recipients from scenarioWatchers
+ data.scenarioWatchers.forEach((recipients) => {
+ const { user, app, fcm, email, firstName, lastName, employeeId, associationId } = recipients;
+ if (app === true)
+ result.app.recipients.push({
+ user,
+ bodyShopId: data.bodyShopId,
+ employeeId,
+ associationId
+ });
+ if (fcm === true) result.fcm.recipients.push(user);
+ if (email === true) result.email.recipients.push({ user, firstName, lastName });
+ });
+
+ return result;
+};
+
+/**
+ * Creates a notification for when the alternate transport is changed.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const alternateTransportChangedBuilder = (data) => {
+ const oldTransport = data?.changedFields?.alt_transport?.old;
+ const newTransport = data?.changedFields?.alt_transport?.new;
+ let body;
+
+ if (oldTransport && newTransport)
+ body = `The alternate transportation has been changed from ${oldTransport} to ${newTransport}.`;
+ else if (!oldTransport && newTransport) body = `The alternate transportation has been set to ${newTransport}.`;
+ else if (oldTransport && !newTransport)
+ body = `The alternate transportation has been canceled (previously ${oldTransport}).`;
+ else body = `The alternate transportation has been updated.`;
+
+ return buildNotification(data, "notifications.job.alternateTransportChanged", body, {
+ alternateTransport: newTransport,
+ oldAlternateTransport: oldTransport
+ });
+};
+
+/**
+ * Creates a notification for when a bill is posted.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const billPostedBuilder = (data) => {
+ const facing = data?.data?.isinhouse ? "in-house" : "vendor";
+ const body = `An ${facing} ${data?.data?.is_credit_memo ? "credit memo" : "bill"} has been posted.`.trim();
+
+ return buildNotification(data, "notifications.job.billPosted", body, {
+ isInHouse: data?.data?.isinhouse,
+ isCreditMemo: data?.data?.is_credit_memo
+ });
+};
+
+/**
+ * Creates a notification for when the status of critical parts changes.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const criticalPartsStatusChangedBuilder = (data) => {
+ const lineDesc = data?.data?.line_desc;
+ const status = data?.data?.status;
+ const body = status
+ ? `The status on a critical part line (${lineDesc}) has been set to ${status}.`
+ : `The status on a critical part line (${lineDesc}) has been cleared.`;
+
+ return buildNotification(data, "notifications.job.criticalPartsStatusChanged", body, {
+ joblineId: data?.data?.id,
+ status: data?.data?.status,
+ line_desc: lineDesc
+ });
+};
+
+/**
+ * Creates a notification for when the intake or delivery checklist is completed.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const intakeDeliveryChecklistCompletedBuilder = (data) => {
+ const checklistType = data?.changedFields?.intakechecklist ? "intake" : "delivery";
+ const body = `The ${checklistType.charAt(0).toUpperCase() + checklistType.slice(1)} checklist has been completed.`;
+
+ return buildNotification(data, "notifications.job.checklistCompleted", body, {
+ checklistType,
+ completed: true
+ });
+};
+
+/**
+ * Creates a notification for when a job is assigned to the user.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const jobAssignedToMeBuilder = (data) => {
+ const body = `You have been assigned to ${getJobAssignmentType(data.scenarioFields?.[0])}.`;
+
+ return buildNotification(data, "notifications.job.assigned", body, {
+ type: data.scenarioFields?.[0]
+ });
+};
+
+/**
+ * Creates a notification for when jobs are added to production.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const jobsAddedToProductionBuilder = (data) => {
+ const body = `Job is now in production.`;
+ return buildNotification(data, "notifications.job.addedToProduction", body);
+};
+
+/**
+ * Creates a notification for when the job status changes.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const jobStatusChangeBuilder = (data) => {
+ const oldStatus = data?.changedFields?.status?.old;
+ const newStatus = data?.changedFields?.status?.new;
+ let body;
+
+ if (oldStatus && newStatus) body = `The status has been changed from ${oldStatus} to ${newStatus}.`;
+ else if (!oldStatus && newStatus) body = `The status has been set to ${newStatus}.`;
+ else if (oldStatus && !newStatus) body = `The status has been cleared (previously ${oldStatus}).`;
+ else body = `The status has been updated.`;
+
+ return buildNotification(data, "notifications.job.statusChanged", body, {
+ status: newStatus,
+ oldStatus: oldStatus
+ });
+};
+
+/**
+ * Creates a notification for when new media is added or reassigned.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const newMediaAddedReassignedBuilder = (data) => {
+ const mediaType = data?.data?.type?.startsWith("image") ? "Image" : "Document";
+ const action = data?.data?._documentMoved
+ ? "moved to another job"
+ : data.isNew
+ ? "added"
+ : data.changedFields?.jobid && data.changedFields.jobid.old !== data.changedFields.jobid.new
+ ? "moved to this job"
+ : "updated";
+ const body = `An ${mediaType} has been ${action}.`;
+
+ return buildNotification(data, "notifications.job.newMediaAdded", body, {
+ mediaType,
+ action,
+ movedToJob: data?.data?._movedToJob
+ });
+};
+
+/**
+ * Creates a notification for when a new note is added.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const newNoteAddedBuilder = (data) => {
+ const body = [
+ "A",
+ data?.data?.critical && "critical",
+ data?.data?.private && "private",
+ data?.data?.type,
+ "note has been added by",
+ `${data.data.created_by}`
+ ]
+ .filter(Boolean)
+ .join(" ");
+
+ return buildNotification(data, "notifications.job.newNoteAdded", body, {
+ createdBy: data?.data?.created_by,
+ critical: data?.data?.critical,
+ type: data?.data?.type,
+ private: data?.data?.private
+ });
+};
+
+/**
+ * Creates a notification for when a new time ticket is posted.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const newTimeTicketPostedBuilder = (data) => {
+ const type = data?.data?.cost_center;
+ const body = `A ${startCase(type.toLowerCase())} time ticket for ${data?.data?.date} has been posted.`.trim();
+
+ return buildNotification(data, "notifications.job.newTimeTicketPosted", body, {
+ type,
+ date: data?.data?.date
+ });
+};
+
+/**
+ * Creates a notification for when a part is marked as back-ordered.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const partMarkedBackOrderedBuilder = (data) => {
+ const body = `A part ${data?.data?.line_desc} has been marked as back-ordered.`;
+
+ return buildNotification(data, "notifications.job.partBackOrdered", body, {
+ line_desc: data?.data?.line_desc
+ });
+};
+
+/**
+ * Creates a notification for when payment is collected or completed.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const paymentCollectedCompletedBuilder = (data) => {
+ const momentFormat = "MM/DD/YYYY";
+ const amountDinero = Dinero({ amount: Math.round((data.data.amount || 0) * 100) });
+ const amountFormatted = amountDinero.toFormat();
+ const payer = data.data.payer;
+ const paymentType = data.data.type;
+ const paymentDate = moment(data.data.date).format(momentFormat);
+ const body = `Payment of ${amountFormatted} has been collected from ${payer} via ${paymentType} on ${paymentDate}`;
+
+ return buildNotification(data, "notifications.job.paymentCollected", body, {
+ amount: data.data.amount,
+ payer: data.data.payer,
+ type: data.data.type,
+ date: data.data.date
+ });
+};
+
+/**
+ * Creates a notification for when scheduled dates are changed.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const scheduledDatesChangedBuilder = (data) => {
+ const changedFields = data.changedFields;
+ const fieldConfigs = {
+ scheduled_in: "Scheduled In",
+ scheduled_completion: "Scheduled Completion",
+ scheduled_delivery: "Scheduled Delivery"
+ };
+ const formatDateTime = (date) => {
+ if (!date) return "(no date set)";
+ const formatted = moment(date).tz(data.bodyShopTimezone);
+ return `${formatted.format("MM/DD/YYYY")} at ${formatted.format("hh:mm a")}`;
+ };
+
+ const fieldMessages = Object.entries(fieldConfigs)
+ .filter(([field]) => changedFields[field])
+ .map(([field, label]) => {
+ const { old, new: newValue } = changedFields[field];
+ if (old && !newValue) return `${label} was cancelled (previously ${formatDateTime(old)}).`;
+ else if (!old && newValue) return `${label} was set to ${formatDateTime(newValue)}.`;
+ else if (old && newValue) return `${label} changed from ${formatDateTime(old)} to ${formatDateTime(newValue)}.`;
+ return "";
+ })
+ .filter(Boolean);
+
+ const body = fieldMessages.length > 0 ? fieldMessages.join(" ") : "Scheduled dates have been updated.";
+
+ return buildNotification(data, "notifications.job.scheduledDatesChanged", body, {
+ scheduledIn: changedFields.scheduled_in?.new,
+ oldScheduledIn: changedFields.scheduled_in?.old,
+ scheduledCompletion: changedFields.scheduled_completion?.new,
+ oldScheduledCompletion: changedFields.scheduled_completion?.old,
+ scheduledDelivery: changedFields.scheduled_delivery?.new,
+ oldScheduledDelivery: changedFields.scheduled_delivery?.old
+ });
+};
+
+/**
+ * Creates a notification for when tasks are updated or created.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const tasksUpdatedCreatedBuilder = (data) => {
+ const momentFormat = "MM/DD/YYYY hh:mm a";
+ const timezone = data.bodyShopTimezone;
+ const taskTitle = data?.data?.title ? `"${data.data.title}"` : "Unnamed Task";
+
+ let body, variables;
+ if (data.isNew) {
+ const priority = formatTaskPriority(data?.data?.priority);
+ const createdBy = data?.data?.created_by || "Unknown";
+ const dueDate = data.data.due_date ? ` due on ${moment(data.data.due_date).tz(timezone).format(momentFormat)}` : "";
+ const completedOnCreation = data.data.completed === true;
+ body = `A ${priority} task ${taskTitle} has been created${completedOnCreation ? " and marked completed" : ""} by ${createdBy}${dueDate}.`;
+ variables = {
+ isNew: data.isNew,
+ roNumber: data.jobRoNumber,
+ title: data?.data?.title,
+ priority: data?.data?.priority,
+ createdBy: data?.data?.created_by,
+ dueDate: data?.data?.due_date,
+ completed: completedOnCreation ? data?.data?.completed : undefined
+ };
+ } else {
+ const changedFields = data.changedFields;
+ const fieldNames = Object.keys(changedFields);
+ const oldTitle = changedFields.title ? `"${changedFields.title.old || "Unnamed Task"}"` : taskTitle;
+
+ if (fieldNames.length === 1 && changedFields.completed) {
+ body = `Task ${oldTitle} was marked ${changedFields.completed.new ? "complete" : "incomplete"}`;
+ variables = {
+ isNew: data.isNew,
+ roNumber: data.jobRoNumber,
+ title: data?.data?.title,
+ changedCompleted: changedFields.completed.new
+ };
+ } else {
+ const fieldMessages = [];
+ if (changedFields.title)
+ fieldMessages.push(`Task ${oldTitle} changed title to "${changedFields.title.new || "unnamed task"}".`);
+ if (changedFields.description) fieldMessages.push("Description updated.");
+ if (changedFields.priority)
+ fieldMessages.push(`Priority changed to ${formatTaskPriority(changedFields.priority.new)}.`);
+ if (changedFields.due_date)
+ fieldMessages.push(`Due date set to ${moment(changedFields.due_date.new).tz(timezone).format(momentFormat)}.`);
+ if (changedFields.completed)
+ fieldMessages.push(`Status changed to ${changedFields.completed.new ? "complete" : "incomplete"}.`);
+
+ body =
+ fieldMessages.length > 0
+ ? fieldMessages.length === 1 && changedFields.title
+ ? fieldMessages[0]
+ : `Task ${oldTitle} updated: ${fieldMessages.join(", ")}`
+ : `Task ${oldTitle} has been updated.`;
+ variables = {
+ isNew: data.isNew,
+ roNumber: data.jobRoNumber,
+ title: data?.data?.title,
+ changedTitleOld: changedFields.title?.old,
+ changedTitleNew: changedFields.title?.new,
+ changedPriority: changedFields.priority?.new,
+ changedDueDate: changedFields.due_date?.new,
+ changedCompleted: changedFields.completed?.new
+ };
+ }
+ }
+
+ return buildNotification(
+ data,
+ data.isNew ? "notifications.job.taskCreated" : "notifications.job.taskUpdated",
+ body,
+ variables
+ );
+};
+
+/**
+ * Creates a notification for when a supplement is imported.
+ * @param data
+ * @returns {{app: {jobId, jobRoNumber: *, bodyShopId: *, key: string, body: string, variables: Object, recipients: *[]}, email: {jobId, jobRoNumber: *, bodyShopName: *, body: string, recipients: *[]}, fcm: {recipients: *[]}}}
+ */
+const supplementImportedBuilder = (data) => {
+ const body = `A supplement has been imported.`;
+ return buildNotification(data, "notifications.job.supplementImported", body);
+};
+
+module.exports = {
+ alternateTransportChangedBuilder,
+ billPostedBuilder,
+ criticalPartsStatusChangedBuilder,
+ intakeDeliveryChecklistCompletedBuilder,
+ jobAssignedToMeBuilder,
+ jobsAddedToProductionBuilder,
+ jobStatusChangeBuilder,
+ newMediaAddedReassignedBuilder,
+ newNoteAddedBuilder,
+ newTimeTicketPostedBuilder,
+ partMarkedBackOrderedBuilder,
+ paymentCollectedCompletedBuilder,
+ scheduledDatesChangedBuilder,
+ supplementImportedBuilder,
+ tasksUpdatedCreatedBuilder
+};
diff --git a/server/notifications/scenarioMapper.js b/server/notifications/scenarioMapper.js
new file mode 100644
index 000000000..73a97cd5d
--- /dev/null
+++ b/server/notifications/scenarioMapper.js
@@ -0,0 +1,257 @@
+const {
+ jobAssignedToMeBuilder,
+ billPostedBuilder,
+ newNoteAddedBuilder,
+ scheduledDatesChangedBuilder,
+ tasksUpdatedCreatedBuilder,
+ jobStatusChangeBuilder,
+ jobsAddedToProductionBuilder,
+ alternateTransportChangedBuilder,
+ newTimeTicketPostedBuilder,
+ intakeDeliveryChecklistCompletedBuilder,
+ paymentCollectedCompletedBuilder,
+ newMediaAddedReassignedBuilder,
+ criticalPartsStatusChangedBuilder,
+ supplementImportedBuilder,
+ partMarkedBackOrderedBuilder
+} = require("./scenarioBuilders");
+const logger = require("../utils/logger");
+const { isFunction } = require("lodash");
+
+/**
+ * An array of notification scenario definitions.
+ *
+ * Each scenario object can include the following properties:
+ * - key {string}: The unique scenario name.
+ * - table {string}: The table name to check for changes.
+ * - fields {Array}: Fields to check for changes.
+ * - matchToUserFields {Array}: Fields used to match scenarios to user data.
+ * - onNew {boolean|Array}: Indicates whether the scenario should be triggered on new data.
+ * - builder {Function}: A function to handle the scenario.
+ * - onlyTruthyValues {boolean|Array}: Specifies fields that must have truthy values for the scenario to match.
+ * - filterCallback {Function}: Optional callback (sync or async) to further filter the scenario based on event data (returns boolean).
+ * - enabled {boolean}: If true, the scenario is active; if false or omitted, the scenario is skipped.
+ */
+const notificationScenarios = [
+ {
+ key: "job-assigned-to-me",
+ enabled: true,
+ table: "jobs",
+ fields: ["employee_prep", "employee_body", "employee_csr", "employee_refinish"],
+ matchToUserFields: ["employee_prep", "employee_body", "employee_csr", "employee_refinish"],
+ builder: jobAssignedToMeBuilder
+ },
+ {
+ key: "bill-posted",
+ enabled: true,
+ table: "bills",
+ builder: billPostedBuilder,
+ onNew: true
+ },
+ {
+ key: "new-note-added",
+ enabled: true,
+ table: "notes",
+ builder: newNoteAddedBuilder,
+ onNew: true
+ },
+ {
+ key: "schedule-dates-changed",
+ enabled: true,
+ table: "jobs",
+ fields: ["scheduled_in", "scheduled_completion", "scheduled_delivery"],
+ builder: scheduledDatesChangedBuilder
+ },
+ {
+ key: "tasks-updated-created",
+ enabled: true,
+ table: "tasks",
+ fields: ["updated_at"],
+ // onNew: true,
+ builder: tasksUpdatedCreatedBuilder
+ },
+ {
+ key: "job-status-change",
+ enabled: true,
+ table: "jobs",
+ fields: ["status"],
+ builder: jobStatusChangeBuilder
+ },
+ {
+ key: "job-added-to-production",
+ enabled: true,
+ table: "jobs",
+ fields: ["inproduction"],
+ onlyTruthyValues: ["inproduction"],
+ builder: jobsAddedToProductionBuilder
+ },
+ {
+ key: "alternate-transport-changed",
+ enabled: true,
+ table: "jobs",
+ fields: ["alt_transport"],
+ builder: alternateTransportChangedBuilder
+ },
+ {
+ key: "new-time-ticket-posted",
+ enabled: true,
+ table: "timetickets",
+ builder: newTimeTicketPostedBuilder
+ },
+ {
+ key: "intake-delivery-checklist-completed",
+ enabled: true,
+ table: "jobs",
+ fields: ["intakechecklist", "deliverchecklist"],
+ builder: intakeDeliveryChecklistCompletedBuilder
+ },
+ {
+ key: "payment-collected-completed",
+ enabled: true,
+ table: "payments",
+ onNew: true,
+ builder: paymentCollectedCompletedBuilder
+ },
+ {
+ // Only works on a non LMS ENV
+ key: "new-media-added-reassigned",
+ enabled: true,
+ table: "documents",
+ fields: ["jobid"],
+ builder: newMediaAddedReassignedBuilder
+ },
+ {
+ key: "critical-parts-status-changed",
+ enabled: true,
+ table: "joblines",
+ fields: ["status"],
+ onlyTruthyValues: ["status"],
+ builder: criticalPartsStatusChangedBuilder,
+ filterCallback: ({ eventData }) => !eventData?.data?.critical
+ },
+ {
+ key: "part-marked-back-ordered",
+ enabled: true,
+ table: "joblines",
+ fields: ["status"],
+ builder: partMarkedBackOrderedBuilder,
+ filterCallback: async ({ eventData, getBodyshopFromRedis }) => {
+ try {
+ const bodyshop = await getBodyshopFromRedis(eventData.bodyShopId);
+ return eventData?.data?.status !== bodyshop?.md_order_statuses?.default_bo;
+ } catch (err) {
+ logger.log("notifications-error-parts-marked-back-ordered", "error", "notifications", "mapper", {
+ message: err?.message,
+ stack: err?.stack
+ });
+ return false;
+ }
+ }
+ },
+ // Holding off on this one for now, spans multiple tables
+ {
+ key: "supplement-imported",
+ enabled: false,
+ builder: supplementImportedBuilder
+ }
+];
+
+/**
+ * Returns an array of scenarios that match the given event data.
+ * Supports asynchronous callbacks for additional filtering.
+ *
+ * @param {Object} eventData - The parsed event data.
+ * Expected properties:
+ * - table: an object with a `name` property (e.g. { name: "tasks", schema: "public" })
+ * - changedFieldNames: an array of changed field names (e.g. [ "description", "updated_at" ])
+ * - isNew: boolean indicating whether the record is new or updated
+ * - data: the new data object (used to check field values)
+ * - (other properties may be added such as jobWatchers, bodyShopId, etc.)
+ * @param {Function} getBodyshopFromRedis - Function to retrieve bodyshop data from Redis.
+ * @returns {Promise>} A promise resolving to an array of matching scenario objects.
+ */
+const getMatchingScenarios = async (eventData, getBodyshopFromRedis) => {
+ const matches = [];
+ for (const scenario of notificationScenarios) {
+ // Check if the scenario is enabled; skip if not explicitly true
+ if (scenario.enabled !== true) {
+ continue;
+ }
+
+ // If eventData has a table, then only scenarios with a table property that matches should be considered.
+ if (eventData.table) {
+ if (!scenario.table || eventData.table.name !== scenario.table) {
+ continue;
+ }
+ }
+
+ // Check the onNew flag.
+ // Allow onNew to be either a boolean or an array of booleans.
+ if (Object.prototype.hasOwnProperty.call(scenario, "onNew")) {
+ if (Array.isArray(scenario.onNew)) {
+ if (!scenario.onNew.includes(eventData.isNew)) continue;
+ } else {
+ if (eventData.isNew !== scenario.onNew) continue;
+ }
+ }
+
+ // If the scenario defines fields, ensure at least one of them is present in changedFieldNames.
+ if (scenario.fields && scenario.fields.length > 0) {
+ const hasMatchingField = scenario.fields.some((field) => eventData.changedFieldNames.includes(field));
+ if (!hasMatchingField) {
+ continue;
+ }
+ }
+
+ // OnlyTruthyValues logic:
+ // If onlyTruthyValues is defined, check that the new values of specified fields (or all changed fields if true)
+ // are truthy. If an array, only check the listed fields, which must be in scenario.fields.
+ if (Object.prototype.hasOwnProperty.call(scenario, "onlyTruthyValues")) {
+ let fieldsToCheck;
+
+ if (scenario.onlyTruthyValues === true) {
+ // If true, check all fields in the scenario that changed
+ fieldsToCheck = scenario.fields.filter((field) => eventData.changedFieldNames.includes(field));
+ } else if (Array.isArray(scenario.onlyTruthyValues) && scenario.onlyTruthyValues.length > 0) {
+ // If an array, check only the specified fields, ensuring they are in scenario.fields
+ fieldsToCheck = scenario.onlyTruthyValues.filter(
+ (field) => scenario.fields.includes(field) && eventData.changedFieldNames.includes(field)
+ );
+ // If no fields in onlyTruthyValues match the scenario’s fields or changed fields, skip this scenario
+ if (fieldsToCheck.length === 0) {
+ continue;
+ }
+ } else {
+ // Invalid onlyTruthyValues (not true or a non-empty array), skip this scenario
+ continue;
+ }
+
+ // Ensure all fields to check have truthy new values
+ const allTruthy = fieldsToCheck.every((field) => Boolean(eventData.data[field]));
+ if (!allTruthy) {
+ continue;
+ }
+ }
+
+ // Execute the callback if defined, supporting both sync and async, and filter based on its return value
+ if (isFunction(scenario?.filterCallback)) {
+ const shouldFilter = await Promise.resolve(
+ scenario.filterCallback({
+ eventData,
+ getBodyshopFromRedis
+ })
+ );
+ if (shouldFilter) {
+ continue;
+ }
+ }
+
+ matches.push(scenario);
+ }
+ return matches;
+};
+
+module.exports = {
+ notificationScenarios,
+ getMatchingScenarios
+};
diff --git a/server/notifications/scenarioParser.js b/server/notifications/scenarioParser.js
new file mode 100644
index 000000000..ddf1ff103
--- /dev/null
+++ b/server/notifications/scenarioParser.js
@@ -0,0 +1,291 @@
+/**
+ * @module scenarioParser
+ * @description
+ * This module exports a function that parses an event and triggers notification scenarios based on the event data.
+ * It integrates with event parsing utilities, GraphQL queries, and notification queues to manage the dispatching
+ * of notifications via email and app channels. The function processes event data, identifies relevant scenarios,
+ * queries user notification preferences, and dispatches notifications accordingly.
+ */
+
+const eventParser = require("./eventParser");
+const { client: gqlClient } = require("../graphql-client/graphql-client");
+const queries = require("../graphql-client/queries");
+const { isEmpty, isFunction } = require("lodash");
+const { getMatchingScenarios } = require("./scenarioMapper");
+const { dispatchEmailsToQueue } = require("./queues/emailQueue");
+const { dispatchAppsToQueue } = require("./queues/appQueue");
+
+// If true, the user who commits the action will NOT receive notifications; if false, they will.
+const FILTER_SELF_FROM_WATCHERS = process.env?.FILTER_SELF_FROM_WATCHERS !== "false";
+
+/**
+ * Parses an event and determines matching scenarios for notifications.
+ * Queries job watchers and notification settings before triggering scenario builders.
+ *
+ * @param {Object} req - The request object containing event data, trigger, table, and logger.
+ * @param {string} jobIdField - The field path (e.g., "req.body.event.new.id") to extract the job ID.
+ * @returns {Promise} Resolves when the parsing and notification dispatching process is complete.
+ * @throws {Error} If required request fields (event data, trigger, or table) or body shop data are missing.
+ */
+const scenarioParser = async (req, jobIdField) => {
+ const { event, trigger, table } = req.body;
+ const {
+ logger,
+ sessionUtils: { getBodyshopFromRedis }
+ } = req;
+
+ // Step 1: Validate we know what user committed the action that fired the parser
+
+ const hasuraUserRole = event?.session_variables?.["x-hasura-role"];
+ const hasuraUserId = event?.session_variables?.["x-hasura-user-id"];
+
+ // Bail if we don't know who started the scenario
+ if (hasuraUserRole === "user" && !hasuraUserId) {
+ logger.log("No Hasura user ID found, skipping notification parsing", "info", "notifications");
+ return;
+ }
+
+ // Validate that required fields are present in the request body
+ if (!event?.data || !trigger || !table) {
+ throw new Error("Missing required request fields: event data, trigger, or table.");
+ }
+
+ // Step 2: Extract just the jobId using the provided jobIdField
+
+ let jobId = null;
+ if (jobIdField) {
+ let keyName = jobIdField;
+ const prefix = "req.body.event.new.";
+ if (keyName.startsWith(prefix)) {
+ keyName = keyName.slice(prefix.length);
+ }
+ jobId = event.data.new[keyName] || (event.data.old && event.data.old[keyName]) || null;
+ }
+
+ if (!jobId) {
+ logger.log(`No jobId found using path "${jobIdField}", skipping notification parsing`, "info", "notifications");
+ return;
+ }
+
+ // Step 3: Query job watchers associated with the job ID using GraphQL
+
+ const watcherData = await gqlClient.request(queries.GET_JOB_WATCHERS, {
+ jobid: jobId
+ });
+
+ // Transform watcher data into a simplified format with email and employee details
+ let jobWatchers = watcherData?.job_watchers?.map((watcher) => ({
+ email: watcher.user_email,
+ firstName: watcher?.user?.employee?.first_name,
+ lastName: watcher?.user?.employee?.last_name,
+ employeeId: watcher?.user?.employee?.id,
+ authId: watcher?.user?.authid
+ }));
+
+ if (FILTER_SELF_FROM_WATCHERS && hasuraUserRole === "user") {
+ jobWatchers = jobWatchers.filter((watcher) => watcher.authId !== hasuraUserId);
+ }
+
+ // Exit early if no job watchers are found for this job
+ if (isEmpty(jobWatchers)) {
+ logger.log(`No watchers found for jobId "${jobId}", skipping notification parsing`, "info", "notifications");
+ return;
+ }
+
+ // Step 5: Perform the full event diff now that we know there are watchers
+
+ const eventData = await eventParser({
+ newData: event.data.new,
+ oldData: event.data.old,
+ trigger,
+ table,
+ jobId
+ });
+
+ // Step 6: Extract body shop information from the job data
+
+ const bodyShopId = watcherData?.job?.bodyshop?.id;
+ const bodyShopName = watcherData?.job?.bodyshop?.shopname;
+ const bodyShopTimezone = watcherData?.job?.bodyshop?.timezone;
+
+ const jobRoNumber = watcherData?.job?.ro_number;
+ const jobClaimNumber = watcherData?.job?.clm_no;
+
+ // Validate that body shop data exists, as it’s required for notifications
+ if (!bodyShopId || !bodyShopName) {
+ throw new Error("No bodyshop data found for this job.");
+ }
+
+ // Step 7: Identify scenarios that match the event data and job context
+
+ const matchingScenarios = await getMatchingScenarios(
+ {
+ ...eventData,
+ jobWatchers,
+ bodyShopId,
+ bodyShopName
+ },
+ getBodyshopFromRedis
+ );
+
+ // Exit early if no matching scenarios are identified
+ if (isEmpty(matchingScenarios)) {
+ logger.log(
+ `No matching scenarios found for jobId "${jobId}", skipping notification dispatch`,
+ "info",
+ "notifications"
+ );
+ return;
+ }
+
+ // Combine event data with additional context for scenario processing
+ const finalScenarioData = {
+ ...eventData,
+ jobWatchers,
+ bodyShopId,
+ bodyShopName,
+ bodyShopTimezone,
+ matchingScenarios
+ };
+
+ // Step 8: Query notification settings for the job watchers
+
+ const associationsData = await gqlClient.request(queries.GET_NOTIFICATION_ASSOCIATIONS, {
+ emails: jobWatchers.map((x) => x.email),
+ shopid: bodyShopId
+ });
+
+ // Exit early if no notification associations are found
+ if (isEmpty(associationsData?.associations)) {
+ logger.log(
+ `No notification associations found for jobId "${jobId}", skipping notification dispatch`,
+ "info",
+ "notifications"
+ );
+ return;
+ }
+
+ // Step 9: Filter scenario watchers based on their enabled notification methods
+
+ finalScenarioData.matchingScenarios = finalScenarioData.matchingScenarios.map((scenario) => ({
+ ...scenario,
+ scenarioWatchers: associationsData.associations
+ .filter((assoc) => {
+ const settings = assoc.notification_settings && assoc.notification_settings[scenario.key];
+ // Include only watchers with at least one enabled notification method (app, email, or FCM)
+ return settings && (settings.app || settings.email || settings.fcm);
+ })
+ .map((assoc) => {
+ const settings = assoc.notification_settings[scenario.key];
+ const watcherEmail = assoc.useremail;
+ const matchingWatcher = jobWatchers.find((watcher) => watcher.email === watcherEmail);
+
+ // Build watcher object with notification preferences and personal details
+ return {
+ user: watcherEmail,
+ email: settings.email,
+ app: settings.app,
+ fcm: settings.fcm,
+ firstName: matchingWatcher?.firstName,
+ lastName: matchingWatcher?.lastName,
+ employeeId: matchingWatcher?.employeeId,
+ associationId: assoc.id
+ };
+ })
+ }));
+
+ // Exit early if no scenarios have eligible watchers after filtering
+ if (isEmpty(finalScenarioData?.matchingScenarios)) {
+ logger.log(
+ `No eligible watchers after filtering for jobId "${jobId}", skipping notification dispatch`,
+ "info",
+ "notifications"
+ );
+ return;
+ }
+
+ // Step 10: Build and collect scenarios to dispatch notifications for
+
+ const scenariosToDispatch = [];
+
+ for (const scenario of finalScenarioData.matchingScenarios) {
+ // Skip if no watchers or no builder function is defined for the scenario
+ if (isEmpty(scenario.scenarioWatchers) || !isFunction(scenario.builder)) {
+ continue;
+ }
+
+ let eligibleWatchers = scenario.scenarioWatchers;
+
+ // Filter watchers to only those assigned to changed fields, if specified
+ if (scenario.matchToUserFields && scenario.matchToUserFields.length > 0) {
+ eligibleWatchers = scenario.scenarioWatchers.filter((watcher) =>
+ scenario.matchToUserFields.some(
+ (field) => eventData.changedFieldNames.includes(field) && eventData.data[field]?.includes(watcher.employeeId)
+ )
+ );
+ }
+
+ // Skip if no watchers remain after filtering
+ if (isEmpty(eligibleWatchers)) {
+ continue;
+ }
+
+ // Step 11: Filter scenario fields to include only those that changed
+
+ const filteredScenarioFields =
+ scenario.fields?.filter((field) => eventData.changedFieldNames.includes(field)) || [];
+
+ // Use the scenario’s builder to construct the notification data
+ scenariosToDispatch.push(
+ scenario.builder({
+ trigger: finalScenarioData.trigger.name,
+ bodyShopId: finalScenarioData.bodyShopId,
+ bodyShopName: finalScenarioData.bodyShopName,
+ bodyShopTimezone: finalScenarioData.bodyShopTimezone,
+ scenarioKey: scenario.key,
+ scenarioTable: scenario.table,
+ scenarioFields: filteredScenarioFields,
+ scenarioBuilder: scenario.builder,
+ scenarioWatchers: eligibleWatchers,
+ jobId: finalScenarioData.jobId,
+ jobRoNumber: jobRoNumber,
+ jobClaimNumber: jobClaimNumber,
+ isNew: finalScenarioData.isNew,
+ changedFieldNames: finalScenarioData.changedFieldNames,
+ changedFields: finalScenarioData.changedFields,
+ data: finalScenarioData.data
+ })
+ );
+ }
+
+ if (isEmpty(scenariosToDispatch)) {
+ logger.log(`No scenarios to dispatch for jobId "${jobId}" after building`, "info", "notifications");
+ return;
+ }
+
+ // Step 12: Dispatch email notifications to the email queue
+
+ const emailsToDispatch = scenariosToDispatch.map((scenario) => scenario?.email);
+ if (!isEmpty(emailsToDispatch)) {
+ dispatchEmailsToQueue({ emailsToDispatch, logger }).catch((e) =>
+ logger.log("Something went wrong dispatching emails to the Email Notification Queue", "error", "queue", null, {
+ message: e?.message,
+ stack: e?.stack
+ })
+ );
+ }
+
+ // Step 13: Dispatch app notifications to the app queue
+
+ const appsToDispatch = scenariosToDispatch.map((scenario) => scenario?.app);
+ if (!isEmpty(appsToDispatch)) {
+ dispatchAppsToQueue({ appsToDispatch, logger }).catch((e) =>
+ logger.log("Something went wrong dispatching apps to the App Notification Queue", "error", "queue", null, {
+ message: e?.message,
+ stack: e?.stack
+ })
+ );
+ }
+};
+
+module.exports = scenarioParser;
diff --git a/server/notifications/stringHelpers.js b/server/notifications/stringHelpers.js
new file mode 100644
index 000000000..ce56063c9
--- /dev/null
+++ b/server/notifications/stringHelpers.js
@@ -0,0 +1,42 @@
+/**
+ * @module jobAssignmentHelper
+ * @description
+ * This module provides utility functions for handling job assignment types.
+ * Currently, it includes a function to map lowercase job assignment codes to their corresponding human-readable job types.
+ */
+
+/**
+ * Maps a lowercase job assignment code to its corresponding human-readable job type.
+ *
+ * @param {string} data - The lowercase job assignment code (e.g., "employee_pre").
+ * @returns {string} The human-readable job type (e.g., "Prep"). Returns an empty string if the code is unknown or if the input is null/undefined.
+ */
+const getJobAssignmentType = (data) => {
+ switch (data) {
+ case "employee_prep":
+ return "Prep";
+ case "employee_body":
+ return "Body";
+ case "employee_csr":
+ return "CSR";
+ case "employee_refinish":
+ return "Refinish";
+ default:
+ return "";
+ }
+};
+
+const formatTaskPriority = (priority) => {
+ if (priority === 1) {
+ return "High";
+ } else if (priority === 3) {
+ return "Low";
+ } else {
+ return "Medium";
+ }
+};
+
+module.exports = {
+ getJobAssignmentType,
+ formatTaskPriority
+};
diff --git a/server/opensearch/os-handler.js b/server/opensearch/os-handler.js
index 66e76cc50..48310c4f2 100644
--- a/server/opensearch/os-handler.js
+++ b/server/opensearch/os-handler.js
@@ -160,6 +160,11 @@ async function OpenSearchUpdateHandler(req, res) {
res.status(200).json(response.body);
}
} catch (error) {
+ // We don't want this spam message existing in development/test,
+ if (process.env?.NODE_ENV !== "production" && error?.message === "Invalid URL") {
+ return res.status(400).json(JSON.stringify(error));
+ }
+
logger.log("os-handler-error", "ERROR", null, null, {
id: req.body.event.data.new.id,
index: req.body.table.name,
@@ -167,6 +172,7 @@ async function OpenSearchUpdateHandler(req, res) {
stack: error.stack
// body: document
});
+
res.status(400).json(JSON.stringify(error));
}
}
@@ -248,7 +254,8 @@ async function OpenSearchSearchHandler(req, res) {
"*ownr_fn^8",
"*ownr_co_nm^8",
"*ownr_ph1^8",
- "*ownr_ph2^8"
+ "*ownr_ph2^8",
+ "*comment^6"
// "*"
]
}
diff --git a/server/routes/miscellaneousRoutes.js b/server/routes/miscellaneousRoutes.js
index 7463e1757..aeb59af93 100644
--- a/server/routes/miscellaneousRoutes.js
+++ b/server/routes/miscellaneousRoutes.js
@@ -13,7 +13,8 @@ const withUserGraphQLClientMiddleware = require("../middleware/withUserGraphQLCl
const { taskAssignedEmail, tasksRemindEmail } = require("../email/tasksEmails");
const { canvastest } = require("../render/canvas-handler");
const { alertCheck } = require("../alerts/alertcheck");
-const uuid = require("uuid").v4;
+const updateBodyshopCache = require("../web-sockets/updateBodyshopCache");
+const { v4 } = require("uuid");
//Test route to ensure Express is responding.
router.get("/test", eventAuthorizationMiddleware, async function (req, res) {
@@ -58,6 +59,7 @@ router.get("/test-logs", eventAuthorizationMiddleware, (req, res) => {
return res.status(500).send("Logs tested.");
});
+
router.get("/wstest", eventAuthorizationMiddleware, (req, res) => {
const { ioRedis } = req;
ioRedis.to(`bodyshop-broadcast-room:bfec8c8c-b7f1-49e0-be4c-524455f4e582`).emit("new-message-summary", {
@@ -81,7 +83,7 @@ router.get("/wstest", eventAuthorizationMiddleware, (req, res) => {
// image_path: [],
newMessage: {
conversation: {
- id: uuid(),
+ id: v4(),
archived: false,
bodyshop: {
id: "bfec8c8c-b7f1-49e0-be4c-524455f4e582",
@@ -137,4 +139,20 @@ router.post("/canvastest", validateFirebaseIdTokenMiddleware, canvastest);
// Alert Check
router.post("/alertcheck", eventAuthorizationMiddleware, alertCheck);
+// Redis Cache Routes
+router.post("/bodyshop-cache", eventAuthorizationMiddleware, updateBodyshopCache);
+
+// Health Check for docker-compose-cluster load balancer, only available in development
+if (process.env.NODE_ENV === "development") {
+ router.get("/health", (req, res) => {
+ const healthStatus = {
+ status: "healthy",
+ timestamp: new Date().toISOString(),
+ environment: process.env.NODE_ENV || "unknown",
+ uptime: process.uptime()
+ };
+ res.status(200).json(healthStatus);
+ });
+}
+
module.exports = router;
diff --git a/server/routes/notificationsRoutes.js b/server/routes/notificationsRoutes.js
index 64228382b..0d47882b1 100644
--- a/server/routes/notificationsRoutes.js
+++ b/server/routes/notificationsRoutes.js
@@ -2,13 +2,18 @@ const express = require("express");
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
const { subscribe, unsubscribe, sendNotification } = require("../firebase/firebase-handler");
const eventAuthorizationMiddleware = require("../middleware/eventAuthorizationMIddleware");
-
-const handlePartsOrderChange = require("../notifications/eventHandlers/handlePartsOrderChange");
-const handlePartsDispatchChange = require("../notifications/eventHandlers/handlePartsDispatchChange");
-const handleTasksChange = require("../notifications/eventHandlers/handleTasksChange");
-const handleTimeTicketsChange = require("../notifications/eventHandlers/handleTimeTicketsChange");
-const handleJobsChange = require("../notifications/eventHandlers/handeJobsChange");
-const handleBillsChange = require("../notifications/eventHandlers/handleBillsChange");
+const {
+ handleJobsChange,
+ handleBillsChange,
+ handlePartsOrderChange,
+ handlePartsDispatchChange,
+ handleTasksChange,
+ handleTimeTicketsChange,
+ handleNotesChange,
+ handlePaymentsChange,
+ handleDocumentsChange,
+ handleJobLinesChange
+} = require("../notifications/eventHandlers");
const router = express.Router();
@@ -24,5 +29,9 @@ router.post("/events/handlePartsOrderChange", eventAuthorizationMiddleware, hand
router.post("/events/handlePartsDispatchChange", eventAuthorizationMiddleware, handlePartsDispatchChange);
router.post("/events/handleTasksChange", eventAuthorizationMiddleware, handleTasksChange);
router.post("/events/handleTimeTicketsChange", eventAuthorizationMiddleware, handleTimeTicketsChange);
+router.post("/events/handleNotesChange", eventAuthorizationMiddleware, handleNotesChange);
+router.post("/events/handlePaymentsChange", eventAuthorizationMiddleware, handlePaymentsChange);
+router.post("/events/handleDocumentsChange", eventAuthorizationMiddleware, handleDocumentsChange);
+router.post("/events/handleJobLinesChange", eventAuthorizationMiddleware, handleJobLinesChange);
module.exports = router;
diff --git a/server/routes/smsRoutes.js b/server/routes/smsRoutes.js
index bb23d24e8..1b169747d 100644
--- a/server/routes/smsRoutes.js
+++ b/server/routes/smsRoutes.js
@@ -7,6 +7,7 @@ const { status, markConversationRead } = require("../sms/status");
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
// Twilio Webhook Middleware for production
+// TODO: Look into this because it technically is never validating anything
const twilioWebhookMiddleware = twilio.webhook({ validate: process.env.NODE_ENV === "PRODUCTION" });
router.post("/receive", twilioWebhookMiddleware, receive);
diff --git a/server/utils/cleanupManager.js b/server/utils/cleanupManager.js
new file mode 100644
index 000000000..e2923b46a
--- /dev/null
+++ b/server/utils/cleanupManager.js
@@ -0,0 +1,52 @@
+// server/utils/cleanupManager.js
+const logger = require("./logger");
+
+let cleanupTasks = [];
+let isShuttingDown = false;
+
+/**
+ * Register a cleanup task to be executed during shutdown
+ * @param {Function} task - The cleanup task to register
+ */
+function registerCleanupTask(task) {
+ cleanupTasks.push(task);
+}
+
+/**
+ * Handle SIGTERM signal for graceful shutdown
+ */
+async function handleSigterm() {
+ if (isShuttingDown) {
+ logger.log("sigterm-api", "WARN", null, null, { message: "Shutdown already in progress, ignoring signal." });
+ return;
+ }
+
+ isShuttingDown = true;
+
+ logger.log("sigterm-api", "WARN", null, null, { message: "SIGTERM Received. Starting graceful shutdown." });
+
+ try {
+ for (const task of cleanupTasks) {
+ logger.log("sigterm-api", "WARN", null, null, { message: `Running cleanup task: ${task.name}` });
+ await task();
+ }
+ logger.log("sigterm-api", "WARN", null, null, { message: `All cleanup tasks completed.` });
+ } catch (error) {
+ logger.log("sigterm-api-error", "ERROR", null, null, { message: error.message, stack: error.stack });
+ }
+
+ process.exit(0);
+}
+
+/**
+ * Initialize cleanup manager with process event listeners
+ */
+function initializeCleanupManager() {
+ process.on("SIGTERM", handleSigterm);
+ process.on("SIGINT", handleSigterm); // Handle Ctrl+C
+}
+
+module.exports = {
+ registerCleanupTask,
+ initializeCleanupManager
+};
diff --git a/server/utils/consoleDir.js b/server/utils/consoleDir.js
new file mode 100644
index 000000000..0d452d9f2
--- /dev/null
+++ b/server/utils/consoleDir.js
@@ -0,0 +1,7 @@
+const { inspect } = require("node:util");
+
+const consoleDir = (data) => {
+ console.log(inspect(data, { showHidden: false, depth: null, colors: true }));
+};
+
+module.exports = consoleDir;
diff --git a/server/utils/devDebugLogger.js b/server/utils/devDebugLogger.js
new file mode 100644
index 000000000..fad0a05fa
--- /dev/null
+++ b/server/utils/devDebugLogger.js
@@ -0,0 +1,10 @@
+const logger = require("./logger");
+
+const devDebugLogger = (message, meta) => {
+ if (process.env?.NODE_ENV === "production") {
+ return;
+ }
+ logger.logger.debug(message, meta);
+};
+
+module.exports = devDebugLogger;
diff --git a/server/utils/getBullMQPrefix.js b/server/utils/getBullMQPrefix.js
new file mode 100644
index 000000000..a7531523a
--- /dev/null
+++ b/server/utils/getBullMQPrefix.js
@@ -0,0 +1,3 @@
+const getBullMQPrefix = () => (process.env?.NODE_ENV === "production" ? "{PROD-BULLMQ}" : "{DEV-BULLMQ}");
+
+module.exports = getBullMQPrefix;
diff --git a/server/utils/instanceMgr.js b/server/utils/instanceMgr.js
index b94408fe6..07759ac32 100644
--- a/server/utils/instanceMgr.js
+++ b/server/utils/instanceMgr.js
@@ -58,4 +58,20 @@ exports.InstanceRegion = () =>
rome: "us-east-2"
});
+exports.InstanceEndpoints = () =>
+ InstanceManager({
+ imex:
+ process.env?.NODE_ENV === "development"
+ ? "https://localhost:3000"
+ : process.env?.NODE_ENV === "test"
+ ? "https://test.imex.online"
+ : "https://imex.online",
+ rome:
+ process.env?.NODE_ENV === "development"
+ ? "https://localhost:3000"
+ : process.env?.NODE_ENV === "test"
+ ? "https://test.romeonline.io"
+ : "https://romeonline.io"
+ });
+
exports.default = InstanceManager;
diff --git a/server/utils/ioHelpers.js b/server/utils/ioHelpers.js
index a95bd90b0..584d45ce7 100644
--- a/server/utils/ioHelpers.js
+++ b/server/utils/ioHelpers.js
@@ -1,7 +1,9 @@
const applyIOHelpers = ({ app, api, io, logger }) => {
- const getBodyshopRoom = (bodyshopID) => `bodyshop-broadcast-room:${bodyshopID}`;
+ // Global Bodyshop Room
+ const getBodyshopRoom = (bodyshopId) => `bodyshop-broadcast-room:${bodyshopId}`;
+
// Messaging - conversation specific room to handle detailed messages when the user has a conversation open.
- const getBodyshopConversationRoom = ({bodyshopId, conversationId}) =>
+ const getBodyshopConversationRoom = ({ bodyshopId, conversationId }) =>
`bodyshop-conversation-room:${bodyshopId}:${conversationId}`;
const ioHelpersAPI = {
diff --git a/server/utils/redisHelpers.js b/server/utils/redisHelpers.js
index 54d68773d..593ce13a6 100644
--- a/server/utils/redisHelpers.js
+++ b/server/utils/redisHelpers.js
@@ -1,3 +1,48 @@
+const { GET_BODYSHOP_BY_ID } = require("../graphql-client/queries");
+const devDebugLogger = require("./devDebugLogger");
+const client = require("../graphql-client/graphql-client").client;
+
+const BODYSHOP_CACHE_TTL = 3600; // 1 hour
+
+/**
+ * Generate a cache key for a bodyshop
+ * @param bodyshopId
+ * @returns {`bodyshop-cache:${string}`}
+ */
+const getBodyshopCacheKey = (bodyshopId) => `bodyshop-cache:${bodyshopId}`;
+
+/**
+ * Generate a cache key for a user socket mapping
+ * @param email
+ * @returns {`user:${string}:${string}:socketMapping`}
+ */
+const getUserSocketMappingKey = (email) =>
+ `user:${process.env?.NODE_ENV === "production" ? "prod" : "dev"}:${email}:socketMapping`;
+
+/**
+ * Fetch bodyshop data from the database
+ * @param bodyshopId
+ * @param logger
+ * @returns {Promise<*>}
+ */
+const fetchBodyshopFromDB = async (bodyshopId, logger) => {
+ try {
+ const response = await client.request(GET_BODYSHOP_BY_ID, { id: bodyshopId });
+ const bodyshop = response.bodyshops_by_pk;
+ if (!bodyshop) {
+ throw new Error(`Bodyshop with ID ${bodyshopId} not found`);
+ }
+ return bodyshop; // Return the full object as-is
+ } catch (error) {
+ logger.log("fetch-bodyshop-from-db", "ERROR", "redis", null, {
+ bodyshopId,
+ error: error?.message,
+ stack: error?.stack
+ });
+ throw error;
+ }
+};
+
/**
* Apply Redis helper functions
* @param pubClient
@@ -33,107 +78,332 @@ const applyRedisHelpers = ({ pubClient, app, logger }) => {
}
};
- // Store multiple session data in Redis
- const setMultipleSessionData = async (socketId, keyValues) => {
+ /**
+ * Add a socket mapping for a user
+ * @param email
+ * @param socketId
+ * @param bodyshopId
+ * @returns {Promise}
+ */
+ const addUserSocketMapping = async (email, socketId, bodyshopId) => {
+ const socketMappingKey = getUserSocketMappingKey(email);
try {
- // keyValues is expected to be an object { key1: value1, key2: value2, ... }
- const entries = Object.entries(keyValues).map(([key, value]) => [key, JSON.stringify(value)]);
- await pubClient.hset(`socket:${socketId}`, ...entries.flat());
+ devDebugLogger(`Adding socket ${socketId} to user ${email} for bodyshop ${bodyshopId}`);
+ // Save the mapping: socketId -> bodyshopId
+ await pubClient.hset(socketMappingKey, socketId, bodyshopId);
+ // Set TTL (24 hours) for the mapping hash
+ await pubClient.expire(socketMappingKey, 86400);
} catch (error) {
- logger.log(`Error Setting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
+ logger.log(`Error adding socket mapping for ${email} (bodyshop ${bodyshopId}): ${error}`, "ERROR", "redis");
}
};
+ /**
+ * Refresh the TTL for a user's socket mapping
+ * @param email
+ * @returns {Promise}
+ */
+ const refreshUserSocketTTL = async (email) => {
+ const socketMappingKey = getUserSocketMappingKey(email);
+
+ try {
+ const exists = await pubClient.exists(socketMappingKey);
+ if (exists) {
+ await pubClient.expire(socketMappingKey, 86400);
+ devDebugLogger(`Refreshed TTL for ${email} socket mapping`);
+ }
+ } catch (error) {
+ logger.log(`Error refreshing TTL for ${email}: ${error}`, "ERROR", "redis");
+ }
+ };
+
+ /**
+ * Remove a socket mapping for a user
+ * @param email
+ * @param socketId
+ * @returns {Promise}
+ */
+ const removeUserSocketMapping = async (email, socketId) => {
+ const socketMappingKey = getUserSocketMappingKey(email);
+
+ try {
+ devDebugLogger(`Removing socket ${socketId} mapping for user ${email}`);
+ // Look up the bodyshopId associated with this socket
+ const bodyshopId = await pubClient.hget(socketMappingKey, socketId);
+ if (!bodyshopId) {
+ devDebugLogger(`Socket ${socketId} not found for user ${email}`);
+ return;
+ }
+ // Remove the socket mapping
+ await pubClient.hdel(socketMappingKey, socketId);
+ devDebugLogger(`Removed socket ${socketId} (associated with bodyshop ${bodyshopId}) for user ${email}`);
+
+ // Refresh TTL if any socket mappings remain
+ const remainingSockets = await pubClient.hlen(socketMappingKey);
+ if (remainingSockets > 0) {
+ await pubClient.expire(socketMappingKey, 86400);
+ }
+ } catch (error) {
+ logger.log(`Error removing socket mapping for ${email}: ${error}`, "ERROR", "redis");
+ }
+ };
+
+ /**
+ * Get all socket mappings for a user
+ * @param email
+ * @returns {Promise<{}>}
+ */
+ const getUserSocketMapping = async (email) => {
+ const socketMappingKey = getUserSocketMappingKey(email);
+
+ try {
+ // Retrieve all socket mappings for the user
+ const mapping = await pubClient.hgetall(socketMappingKey);
+ const ttl = await pubClient.ttl(socketMappingKey);
+ // Group socket IDs by bodyshopId
+ const result = {};
+ for (const [socketId, bodyshopId] of Object.entries(mapping)) {
+ if (!result[bodyshopId]) {
+ result[bodyshopId] = { socketIds: [], ttl };
+ }
+ result[bodyshopId].socketIds.push(socketId);
+ }
+ return result;
+ } catch (error) {
+ console.error(`Error retrieving socket mappings for ${email}:`, error);
+ throw error;
+ }
+ };
+
+ /**
+ * Get socket IDs for a user by bodyshopId
+ * @param email
+ * @param bodyshopId
+ * @returns {Promise<{socketIds: [string, string], ttl: *}>}
+ */
+ const getUserSocketMappingByBodyshop = async (email, bodyshopId) => {
+ const socketMappingKey = getUserSocketMappingKey(email);
+
+ try {
+ // Retrieve all socket mappings for the user
+ const mapping = await pubClient.hgetall(socketMappingKey);
+ const ttl = await pubClient.ttl(socketMappingKey);
+ // Filter socket IDs for the provided bodyshopId
+ const socketIds = Object.entries(mapping).reduce((acc, [socketId, bId]) => {
+ if (bId === bodyshopId) {
+ acc.push(socketId);
+ }
+ return acc;
+ }, []);
+ return { socketIds, ttl };
+ } catch (error) {
+ logger.log(`Error retrieving socket mappings for ${email} by bodyshop ${bodyshopId}: ${error}`, "ERROR", "redis");
+ throw error;
+ }
+ };
+
+ /**
+ * Get bodyshop data from Redis
+ * @param bodyshopId
+ * @returns {Promise<*>}
+ */
+ const getBodyshopFromRedis = async (bodyshopId) => {
+ const key = getBodyshopCacheKey(bodyshopId);
+ try {
+ // Check if data exists in Redis
+ const cachedData = await pubClient.get(key);
+ if (cachedData) {
+ return JSON.parse(cachedData); // Parse and return the full object
+ }
+
+ // Cache miss: fetch from DB
+ const bodyshopData = await fetchBodyshopFromDB(bodyshopId, logger);
+
+ // Store in Redis as a single JSON string
+ const jsonData = JSON.stringify(bodyshopData);
+ await pubClient.set(key, jsonData);
+ await pubClient.expire(key, BODYSHOP_CACHE_TTL);
+
+ devDebugLogger("bodyshop-cache-miss", {
+ bodyshopId,
+ action: "Fetched from DB and cached"
+ });
+
+ return bodyshopData; // Return the full object
+ } catch (error) {
+ logger.log("get-bodyshop-from-redis", "ERROR", "redis", null, {
+ bodyshopId,
+ error: error.message
+ });
+ throw error;
+ }
+ };
+
+ /**
+ * Update or invalidate bodyshop data in Redis
+ * @param bodyshopId
+ * @param values
+ * @returns {Promise}
+ */
+ const updateOrInvalidateBodyshopFromRedis = async (bodyshopId, values = null) => {
+ const key = getBodyshopCacheKey(bodyshopId);
+ try {
+ if (!values) {
+ // Invalidate cache by deleting the key
+ await pubClient.del(key);
+ devDebugLogger("bodyshop-cache-invalidate", {
+ bodyshopId,
+ action: "Cache invalidated"
+ });
+ } else {
+ // Update cache with the full provided values
+ const jsonData = JSON.stringify(values);
+ await pubClient.set(key, jsonData);
+ await pubClient.expire(key, BODYSHOP_CACHE_TTL);
+ devDebugLogger("bodyshop-cache-update", {
+ bodyshopId,
+ action: "Cache updated",
+ values
+ });
+ }
+ } catch (error) {
+ logger.log("update-or-invalidate-bodyshop-from-redis", "ERROR", "api", "redis", {
+ bodyshopId,
+ values,
+ error: error.message
+ });
+ throw error;
+ }
+ };
+
+ // NOTE: The following code was written for an abandoned branch and things have changes since the,
+ // Leaving it here for demonstration purposes, commenting it out so it does not get used
+
+ // Store multiple session data in Redis
+ // const setMultipleSessionData = async (socketId, keyValues) => {
+ // try {
+ // // keyValues is expected to be an object { key1: value1, key2: value2, ... }
+ // const entries = Object.entries(keyValues).map(([key, value]) => [key, JSON.stringify(value)]);
+ // await pubClient.hset(`socket:${socketId}`, ...entries.flat());
+ // } catch (error) {
+ // logger.log(`Error Setting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
+ // }
+ // };
+
// Retrieve multiple session data from Redis
- const getMultipleSessionData = async (socketId, keys) => {
- try {
- const data = await pubClient.hmget(`socket:${socketId}`, keys);
- // Redis returns an object with null values for missing keys, so we parse the non-null ones
- return Object.fromEntries(keys.map((key, index) => [key, data[index] ? JSON.parse(data[index]) : null]));
- } catch (error) {
- logger.log(`Error Getting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
- }
- };
+ // const getMultipleSessionData = async (socketId, keys) => {
+ // try {
+ // const data = await pubClient.hmget(`socket:${socketId}`, keys);
+ // // Redis returns an object with null values for missing keys, so we parse the non-null ones
+ // return Object.fromEntries(keys.map((key, index) => [key, data[index] ? JSON.parse(data[index]) : null]));
+ // } catch (error) {
+ // logger.log(`Error Getting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
+ // }
+ // };
- const setMultipleFromArraySessionData = async (socketId, keyValueArray) => {
- try {
- // Use Redis multi/pipeline to batch the commands
- const multi = pubClient.multi();
- keyValueArray.forEach(([key, value]) => {
- multi.hset(`socket:${socketId}`, key, JSON.stringify(value));
- });
- await multi.exec(); // Execute all queued commands
- } catch (error) {
- logger.log(`Error Setting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
- }
- };
+ // const setMultipleFromArraySessionData = async (socketId, keyValueArray) => {
+ // try {
+ // // Use Redis multi/pipeline to batch the commands
+ // const multi = pubClient.multi();
+ // keyValueArray.forEach(([key, value]) => {
+ // multi.hset(`socket:${socketId}`, key, JSON.stringify(value));
+ // });
+ // await multi.exec(); // Execute all queued commands
+ // } catch (error) {
+ // logger.log(`Error Setting Multiple Session Data for socket ${socketId}: ${error}`, "ERROR", "redis");
+ // }
+ // };
// Helper function to add an item to the end of the Redis list
- const addItemToEndOfList = async (socketId, key, newItem) => {
- try {
- await pubClient.rpush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
- } catch (error) {
- logger.log(`Error adding item to the end of the list for socket ${socketId}: ${error}`, "ERROR", "redis");
- }
- };
+ // const addItemToEndOfList = async (socketId, key, newItem) => {
+ // try {
+ // await pubClient.rpush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
+ // } catch (error) {
+ // let userEmail = "unknown";
+ // let socketMappings = {};
+ // try {
+ // const userData = await getSessionData(socketId, "user");
+ // if (userData && userData.email) {
+ // userEmail = userData.email;
+ // socketMappings = await getUserSocketMapping(userEmail);
+ // }
+ // } catch (sessionError) {
+ // logger.log(`Failed to fetch session data for socket ${socketId}: ${sessionError}`, "ERROR", "redis");
+ // }
+ // const mappingString = JSON.stringify(socketMappings, null, 2);
+ // const errorMessage = `Error adding item to the end of the list for socket ${socketId}: ${error}. User: ${userEmail}, Socket Mappings: ${mappingString}`;
+ // logger.log(errorMessage, "ERROR", "redis");
+ // }
+ // };
// Helper function to add an item to the beginning of the Redis list
- const addItemToBeginningOfList = async (socketId, key, newItem) => {
- try {
- await pubClient.lpush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
- } catch (error) {
- logger.log(`Error adding item to the beginning of the list for socket ${socketId}: ${error}`, "ERROR", "redis");
- }
- };
+ // const addItemToBeginningOfList = async (socketId, key, newItem) => {
+ // try {
+ // await pubClient.lpush(`socket:${socketId}:${key}`, JSON.stringify(newItem));
+ // } catch (error) {
+ // logger.log(`Error adding item to the beginning of the list for socket ${socketId}: ${error}`, "ERROR", "redis");
+ // }
+ // };
// Helper function to clear a list in Redis
- const clearList = async (socketId, key) => {
- try {
- await pubClient.del(`socket:${socketId}:${key}`);
- } catch (error) {
- logger.log(`Error clearing list for socket ${socketId}: ${error}`, "ERROR", "redis");
- }
- };
+ // const clearList = async (socketId, key) => {
+ // try {
+ // await pubClient.del(`socket:${socketId}:${key}`);
+ // } catch (error) {
+ // logger.log(`Error clearing list for socket ${socketId}: ${error}`, "ERROR", "redis");
+ // }
+ // };
// Add methods to manage room users
- const addUserToRoom = async (room, user) => {
- try {
- await pubClient.sadd(room, JSON.stringify(user));
- } catch (error) {
- logger.log(`Error adding user to room ${room}: ${error}`, "ERROR", "redis");
- }
- };
+ // const addUserToRoom = async (room, user) => {
+ // try {
+ // await pubClient.sadd(room, JSON.stringify(user));
+ // } catch (error) {
+ // logger.log(`Error adding user to room ${room}: ${error}`, "ERROR", "redis");
+ // }
+ // };
- const removeUserFromRoom = async (room, user) => {
- try {
- await pubClient.srem(room, JSON.stringify(user));
- } catch (error) {
- logger.log(`Error removing user to room ${room}: ${error}`, "ERROR", "redis");
- }
- };
+ // Remove users from room
+ // const removeUserFromRoom = async (room, user) => {
+ // try {
+ // await pubClient.srem(room, JSON.stringify(user));
+ // } catch (error) {
+ // logger.log(`Error removing user to room ${room}: ${error}`, "ERROR", "redis");
+ // }
+ // };
- const getUsersInRoom = async (room) => {
- try {
- const users = await pubClient.smembers(room);
- return users.map((user) => JSON.parse(user));
- } catch (error) {
- logger.log(`Error getting users in room ${room}: ${error}`, "ERROR", "redis");
- }
- };
+ // Get Users in room
+ // const getUsersInRoom = async (room) => {
+ // try {
+ // const users = await pubClient.smembers(room);
+ // return users.map((user) => JSON.parse(user));
+ // } catch (error) {
+ // logger.log(`Error getting users in room ${room}: ${error}`, "ERROR", "redis");
+ // }
+ // };
const api = {
+ getUserSocketMappingKey,
+ getBodyshopCacheKey,
setSessionData,
getSessionData,
clearSessionData,
- setMultipleSessionData,
- getMultipleSessionData,
- setMultipleFromArraySessionData,
- addItemToEndOfList,
- addItemToBeginningOfList,
- clearList,
- addUserToRoom,
- removeUserFromRoom,
- getUsersInRoom
+ addUserSocketMapping,
+ removeUserSocketMapping,
+ getUserSocketMappingByBodyshop,
+ getUserSocketMapping,
+ refreshUserSocketTTL,
+ getBodyshopFromRedis,
+ updateOrInvalidateBodyshopFromRedis
+ // setMultipleSessionData,
+ // getMultipleSessionData,
+ // setMultipleFromArraySessionData,
+ // addItemToEndOfList,
+ // addItemToBeginningOfList,
+ // clearList,
+ // addUserToRoom,
+ // removeUserFromRoom,
+ // getUsersInRoom,
};
Object.assign(module.exports, api);
@@ -143,86 +413,6 @@ const applyRedisHelpers = ({ pubClient, app, logger }) => {
next();
});
- // Demo to show how all the helper functions work
- // const demoSessionData = async () => {
- // const socketId = "testSocketId";
- //
- // // 1. Test setSessionData and getSessionData
- // await setSessionData(socketId, "field1", "Hello, Redis!");
- // const field1Value = await getSessionData(socketId, "field1");
- // console.log("Retrieved single field value:", field1Value);
- //
- // // 2. Test setMultipleSessionData and getMultipleSessionData
- // await setMultipleSessionData(socketId, { field2: "Second Value", field3: "Third Value" });
- // const multipleFields = await getMultipleSessionData(socketId, ["field2", "field3"]);
- // console.log("Retrieved multiple field values:", multipleFields);
- //
- // // 3. Test setMultipleFromArraySessionData
- // await setMultipleFromArraySessionData(socketId, [
- // ["field4", "Fourth Value"],
- // ["field5", "Fifth Value"]
- // ]);
- //
- // // Retrieve and log all fields
- // const allFields = await getMultipleSessionData(socketId, ["field1", "field2", "field3", "field4", "field5"]);
- // console.log("Retrieved all field values:", allFields);
- //
- // // 4. Test list functions
- // // Add item to the end of a Redis list
- // await addItemToEndOfList(socketId, "logEvents", { event: "Log Event 1", timestamp: new Date() });
- // await addItemToEndOfList(socketId, "logEvents", { event: "Log Event 2", timestamp: new Date() });
- //
- // // Add item to the beginning of a Redis list
- // await addItemToBeginningOfList(socketId, "logEvents", { event: "First Log Event", timestamp: new Date() });
- //
- // // Retrieve the entire list
- // const logEventsData = await pubClient.lrange(`socket:${socketId}:logEvents`, 0, -1);
- // const logEvents = logEventsData.map((item) => JSON.parse(item));
- // console.log("Log Events List:", logEvents);
- //
- // // 5. Test clearList
- // await clearList(socketId, "logEvents");
- // console.log("Log Events List cleared.");
- //
- // // Retrieve the list after clearing to confirm it's empty
- // const logEventsAfterClear = await pubClient.lrange(`socket:${socketId}:logEvents`, 0, -1);
- // console.log("Log Events List after clearing:", logEventsAfterClear); // Should be an empty array
- //
- // // 6. Test clearSessionData
- // await clearSessionData(socketId);
- // console.log("Session data cleared.");
- //
- // // 7. Test room functions
- // const roomName = "testRoom";
- // const user1 = { id: 1, name: "Alice" };
- // const user2 = { id: 2, name: "Bob" };
- //
- // // Add users to room
- // await addUserToRoom(roomName, user1);
- // await addUserToRoom(roomName, user2);
- //
- // // Get users in room
- // const usersInRoom = await getUsersInRoom(roomName);
- // console.log(`Users in room ${roomName}:`, usersInRoom);
- //
- // // Remove a user from room
- // await removeUserFromRoom(roomName, user1);
- //
- // // Get users in room after removal
- // const usersInRoomAfterRemoval = await getUsersInRoom(roomName);
- // console.log(`Users in room ${roomName} after removal:`, usersInRoomAfterRemoval);
- //
- // // Clean up: remove remaining users from room
- // await removeUserFromRoom(roomName, user2);
- //
- // // Verify room is empty
- // const usersInRoomAfterCleanup = await getUsersInRoom(roomName);
- // console.log(`Users in room ${roomName} after cleanup:`, usersInRoomAfterCleanup); // Should be empty
- // };
- // if (process.env.NODE_ENV === "development") {
- // demoSessionData();
- // }
-
return api;
};
diff --git a/server/web-sockets/redisSocketEvents.js b/server/web-sockets/redisSocketEvents.js
index d96fcb7d7..f59723f11 100644
--- a/server/web-sockets/redisSocketEvents.js
+++ b/server/web-sockets/redisSocketEvents.js
@@ -2,7 +2,7 @@ const { admin } = require("../firebase/firebase-handler");
const redisSocketEvents = ({
io,
- redisHelpers: { setSessionData, clearSessionData }, // Note: Used if we persist user to Redis
+ redisHelpers: { addUserSocketMapping, removeUserSocketMapping, refreshUserSocketTTL, getUserSocketMappingByBodyshop },
ioHelpers: { getBodyshopRoom, getBodyshopConversationRoom },
logger
}) => {
@@ -12,78 +12,67 @@ const redisSocketEvents = ({
};
// Socket Auth Middleware
- const authMiddleware = (socket, next) => {
+ const authMiddleware = async (socket, next) => {
+ const { token, bodyshopId } = socket.handshake.auth;
+
+ if (!token) {
+ return next(new Error("Authentication error - no authorization token."));
+ }
+
+ if (!bodyshopId) {
+ return next(new Error("Authentication error - no bodyshopId provided."));
+ }
+
try {
- if (socket.handshake.auth.token) {
- admin
- .auth()
- .verifyIdToken(socket.handshake.auth.token)
- .then((user) => {
- socket.user = user;
- // Note: if we ever want to capture user data across sockets
- // Uncomment the following line and then remove the next() to a second then()
- // return setSessionData(socket.id, "user", user);
- next();
- })
- .catch((error) => {
- next(new Error(`Authentication error: ${error.message}`));
- });
- } else {
- next(new Error("Authentication error - no authorization token."));
- }
+ const user = await admin.auth().verifyIdToken(token);
+ socket.user = user;
+ await addUserSocketMapping(user.email, socket.id, bodyshopId);
+ next();
} catch (error) {
- logger.log("websocket-connection-error", "error", null, null, {
- ...error
- });
- next(new Error(`Authentication error ${error}`));
+ next(new Error(`Authentication error: ${error.message}`));
}
};
// Register Socket Events
const registerSocketEvents = (socket) => {
- // Uncomment for further testing
- // createLogEvent(socket, "debug", `Registering RedisIO Socket Events.`);
-
// Token Update Events
const registerUpdateEvents = (socket) => {
let latestTokenTimestamp = 0;
- const updateToken = async (newToken) => {
+ const updateToken = async ({ token, bodyshopId }) => {
const currentTimestamp = Date.now();
latestTokenTimestamp = currentTimestamp;
- try {
- // Verify token with Firebase Admin SDK
- const user = await admin.auth().verifyIdToken(newToken, true);
+ if (!token || !bodyshopId) {
+ socket.emit("token-updated", { success: false, error: "Token or bodyshopId missing" });
+ return;
+ }
- // Skip outdated token validations
+ try {
+ const user = await admin.auth().verifyIdToken(token, true);
if (currentTimestamp < latestTokenTimestamp) {
createLogEvent(socket, "warn", "Outdated token validation skipped.");
return;
}
-
socket.user = user;
-
- createLogEvent(socket, "debug", `Token updated successfully for socket ID: ${socket.id}`);
+ await refreshUserSocketTTL(user.email, bodyshopId);
+ createLogEvent(
+ socket,
+ "debug",
+ `Token updated successfully for socket ID: ${socket.id} (bodyshop: ${bodyshopId})`
+ );
socket.emit("token-updated", { success: true });
} catch (error) {
if (error.code === "auth/id-token-expired") {
createLogEvent(socket, "warn", "Stale token received, waiting for new token");
- socket.emit("token-updated", {
- success: false,
- error: "Stale token."
- });
- return; // Avoid disconnecting for expired tokens
+ socket.emit("token-updated", { success: false, error: "Stale token." });
+ return;
}
-
createLogEvent(socket, "error", `Token update failed for socket ID: ${socket.id}, Error: ${error.message}`);
socket.emit("token-updated", { success: false, error: error.message });
-
- // Optionally disconnect for invalid tokens or other errors
socket.disconnect();
}
};
-
socket.on("update-token", updateToken);
};
@@ -127,16 +116,15 @@ const redisSocketEvents = ({
// Disconnect Events
const registerDisconnectEvents = (socket) => {
- const disconnect = () => {
- // Uncomment for further testing
- // createLogEvent(socket, "debug", `User disconnected.`);
-
+ const disconnect = async () => {
+ if (socket.user?.email) {
+ await removeUserSocketMapping(socket.user.email, socket.id);
+ }
+ // Leave all rooms except the default room (socket.id)
const rooms = Array.from(socket.rooms).filter((room) => room !== socket.id);
for (const room of rooms) {
socket.leave(room);
}
- // If we ever want to persist the user across workers
- // clearSessionData(socket.id);
};
socket.on("disconnect", disconnect);
@@ -157,6 +145,7 @@ const redisSocketEvents = ({
});
}
};
+
const leaveConversationRoom = ({ bodyshopId, conversationId }) => {
try {
const room = getBodyshopConversationRoom({ bodyshopId, conversationId });
@@ -196,11 +185,58 @@ const redisSocketEvents = ({
socket.on("leave-bodyshop-conversation", leaveConversationRoom);
};
+ // Sync Notification Read Events
+ const registerSyncEvents = (socket) => {
+ socket.on("sync-notification-read", async ({ email, bodyshopId, notificationId }) => {
+ try {
+ const userEmail = socket.user.email;
+ const socketMapping = await getUserSocketMappingByBodyshop(email, bodyshopId);
+ const timestamp = new Date().toISOString();
+
+ if (socketMapping?.socketIds) {
+ socketMapping?.socketIds.forEach((socketId) => {
+ if (socketId !== socket.id) {
+ // Avoid sending back to the originating socket
+ io.to(socketId).emit("sync-notification-read", { notificationId, timestamp });
+ }
+ });
+ createLogEvent(
+ socket,
+ "debug",
+ `Synced notification ${notificationId} read for ${userEmail} in bodyshop ${bodyshopId}`
+ );
+ }
+ } catch (error) {
+ createLogEvent(socket, "error", `Error syncing notification read: ${error.message}`);
+ }
+ });
+
+ socket.on("sync-all-notifications-read", async ({ email, bodyshopId }) => {
+ try {
+ const socketMapping = await getUserSocketMappingByBodyshop(email, bodyshopId);
+ const timestamp = new Date().toISOString();
+
+ if (socketMapping?.socketIds) {
+ socketMapping?.socketIds.forEach((socketId) => {
+ if (socketId !== socket.id) {
+ // Avoid sending back to the originating socket
+ io.to(socketId).emit("sync-all-notifications-read", { timestamp });
+ }
+ });
+ createLogEvent(socket, "debug", `Synced all notifications read for ${email} in bodyshop ${bodyshopId}`);
+ }
+ } catch (error) {
+ createLogEvent(socket, "error", `Error syncing all notifications read: ${error.message}`);
+ }
+ });
+ };
+
// Call Handlers
registerRoomAndBroadcastEvents(socket);
registerUpdateEvents(socket);
registerMessagingEvents(socket);
registerDisconnectEvents(socket);
+ registerSyncEvents(socket);
};
// Associate Middleware and Handlers
diff --git a/server/web-sockets/updateBodyshopCache.js b/server/web-sockets/updateBodyshopCache.js
new file mode 100644
index 000000000..fc330e6b3
--- /dev/null
+++ b/server/web-sockets/updateBodyshopCache.js
@@ -0,0 +1,36 @@
+/**
+ * Update or invalidate bodyshop cache
+ * @param req
+ * @param res
+ * @returns {Promise}
+ */
+const updateBodyshopCache = async (req, res) => {
+ const {
+ sessionUtils: { updateOrInvalidateBodyshopFromRedis },
+ logger
+ } = req;
+
+ const { event } = req.body;
+ const { new: newData } = event.data;
+
+ try {
+ if (newData && newData.id) {
+ // Update cache with the full new data object
+ await updateOrInvalidateBodyshopFromRedis(newData.id, newData);
+ logger.logger.debug("Bodyshop cache updated successfully.");
+ } else {
+ // Invalidate cache if no valid data provided
+ await updateOrInvalidateBodyshopFromRedis(newData.id);
+ logger.logger.debug("Bodyshop cache invalidated successfully.");
+ }
+ res.status(200).json({ success: true });
+ } catch (error) {
+ logger.log("bodyshop-cache-update-error", "ERROR", "api", "redis", {
+ message: error?.message,
+ stack: error?.stack
+ });
+ res.status(500).json({ success: false, error: error.message });
+ }
+};
+
+module.exports = updateBodyshopCache;