Skip to content
53 changes: 28 additions & 25 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "traitify-widgets",
"version": "3.9.3",
"version": "3.9.5",
"description": "Traitiy Widgets",
"repository": {
"type": "git",
Expand Down
11 changes: 2 additions & 9 deletions src/components/report/employee.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import {useEffect} from "react";
import {useRecoilState} from "recoil";
import GenericConclusions from "components/results/generic/conclusions";
import ArchetypeHeading from "components/results/personality/archetype/heading";
import ArchetypeSkills from "components/results/personality/archetype/skills";
import ArchetypeTips from "components/results/personality/archetype/tips";
import Dimensions from "components/results/personality/dimension/list";
import useActive from "lib/hooks/use-active";
import {optionsState} from "lib/recoil";
import useDefaultOptions from "lib/hooks/use-default-options";
import style from "./style.scss";

export default function EmployeeReport() {
const active = useActive();
const [options, setOptions] = useRecoilState(optionsState);

useEffect(() => {
if(options.perspective) { return; }

setOptions({...options, perspective: "thirdPerson"});
}, []);
useDefaultOptions({applyAssessmentExpiration: true, perspective: "thirdPerson"});

if(!active) { return null; }
if(active.surveyType === "generic") {
Expand Down
11 changes: 2 additions & 9 deletions src/components/report/manager.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import {useEffect} from "react";
import {useRecoilState} from "recoil";
import CognitiveChart from "components/results/cognitive/chart";
import GenericBreakdown from "components/results/generic/breakdown";
import GenericHeading from "components/results/generic/heading";
Expand All @@ -8,24 +6,19 @@ import PersonalityGuide from "components/results/guide/personality";
import RecommendationChart from "components/results/recommendation/chart";
import RecommendationList from "components/results/recommendation/list";
import useActive from "lib/hooks/use-active";
import useDefaultOptions from "lib/hooks/use-default-options";
import useOption from "lib/hooks/use-option";
import useTranslate from "lib/hooks/use-translate";
import {optionsState} from "lib/recoil";
import style from "./style.scss";

export default function ManagerReport() {
const active = useActive();
const [options, setOptions] = useRecoilState(optionsState);
const showHeaders = useOption("showHeaders");
// NOTE: Temporary option until Paradox is ready
const showRecommendationList = useOption("showRecommendationList");
const translate = useTranslate();

useEffect(() => {
if(options.perspective) { return; }

setOptions({...options, perspective: "thirdPerson"});
}, []);
useDefaultOptions({applyAssessmentExpiration: true, perspective: "thirdPerson"});

if(!active) { return null; }
if(active.surveyType === "generic") {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/common/get-cache-key.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// NOTE: Mirror updates in lib/recoil/cache
/* eslint-disable no-console */
export default function getCacheKey(type, options = {}) {
/* eslint-disable no-console */
let {id} = options;
const keys = options.scope ? [...options.scope] : [];
const locale = options.locale || console.warn("Missing locale");
Expand Down
15 changes: 15 additions & 0 deletions src/lib/common/object/set-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import isObject from "./is-object";

export default function setPath(object, path, value) {
const keys = path.split(".");
const lastKey = keys.pop();
let target = object;

keys.forEach((key) => {
if(!isObject(target[key])) { target[key] = {}; }

target = target[key];
});

target[lastKey] = value;
}
2 changes: 2 additions & 0 deletions src/lib/graphql/xavier.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ export const feedbackSurvey = `

export const recommendation = `
query(
$applyAssessmentExpiration: Boolean,
$benchmarkID: String,
$localeKey: String!,
$packageID: String,
$profileID: String!
) {
recommendation(
applyAssessmentExpiration: $applyAssessmentExpiration,
benchmarkId: $benchmarkID,
localeKey: $localeKey,
packageId: $packageID,
Expand Down
27 changes: 27 additions & 0 deletions src/lib/hooks/use-default-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {useEffect} from "react";
import {useRecoilState} from "recoil";
import dig from "lib/common/object/dig";
import merge from "lib/common/object/merge";
import setPath from "lib/common/object/set-path";
import {optionsState} from "lib/recoil";

export default function useDefaultOptions(defaults) {
const [options, setOptions] = useRecoilState(optionsState);

useEffect(() => {
const newOptions = {};

Object.keys(defaults).forEach((path) => {
const keys = path.split(".");
const lastKey = keys.pop();
const base = keys.length > 0 ? dig(options, keys) : options;
if(base && Object.hasOwn(base, lastKey)) { return; }

setPath(newOptions, path, defaults[path]);
});

if(Object.keys(newOptions).length === 0) { return; }

setOptions((oldOptions) => merge(oldOptions, newOptions));
}, [options]);
}
5 changes: 2 additions & 3 deletions src/lib/hooks/use-option.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import dig from "lib/common/object/dig";
import useLoadedValue from "lib/hooks/use-loaded-value";
import {optionsState} from "lib/recoil";
import useOptions from "lib/hooks/use-options";

export default function useOption(...keys) {
const options = useLoadedValue(optionsState);
const options = useOptions();

return dig(options, ...keys);
}
6 changes: 6 additions & 0 deletions src/lib/hooks/use-options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import useLoadedValue from "lib/hooks/use-loaded-value";
import {optionsState} from "lib/recoil";

export default function useOption() {
return useLoadedValue(optionsState);
}
19 changes: 17 additions & 2 deletions src/lib/recoil/order.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,20 @@ const baseRecommendationQuery = selector({

const GraphQL = get(graphqlState);
const http = get(httpState);
const options = get(optionsState);
const variables = {
benchmarkID,
localeKey: get(localeState),
packageID,
profileID
};
if(Object.hasOwn(options, "applyAssessmentExpiration")) {
variables.applyAssessmentExpiration = options.applyAssessmentExpiration;
}

const params = {
query: GraphQL.xavier.recommendation,
variables: {benchmarkID, localeKey: get(localeState), packageID, profileID}
variables
};

const {path} = GraphQL.xavier;
Expand All @@ -120,7 +131,11 @@ const orderDefaultQuery = selector({
const {assessmentID, benchmarkID, orderID, packageID, profileID} = get(baseState);

if(orderID) { return get(baseOrderQuery); }
if(profileID && (benchmarkID || packageID)) { return get(baseRecommendationQuery); }
if(profileID && (benchmarkID || packageID)) {
const order = get(baseRecommendationQuery);
// NOTE: Prevent incomplete recommendation from overriding completed assessment
if(order.completed || !assessmentID) { return order; }
}
if(assessmentID) { return get(baseAssessmentState); }

return null;
Expand Down
47 changes: 47 additions & 0 deletions test/lib/common/object/set-path.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import setPath from "lib/common/object/set-path";

describe("Object", () => {
describe("setPath", () => {
it("creates intermediate objects for missing keys", () => {
const object = {};
setPath(object, "a.b.c", "value");

expect(object).toEqual({a: {b: {c: "value"}}});
});

it("mutates the object", () => {
const object = {};
setPath(object, "key", "value");

expect(object.key).toBe("value");
});

it("overwrites a non-object intermediate with an object", () => {
const object = {a: "string"};
setPath(object, "a.b", "value");

expect(object).toEqual({a: {b: "value"}});
});

it("preserves existing keys when setting a nested value", () => {
const object = {a: {sibling: "keep", target: "old"}};
setPath(object, "a.target", "new");

expect(object).toEqual({a: {sibling: "keep", target: "new"}});
});

it("sets a nested value", () => {
const object = {a: {b: "old"}};
setPath(object, "a.b", "new");

expect(object).toEqual({a: {b: "new"}});
});

it("sets a shallow value", () => {
const object = {};
setPath(object, "key", "value");

expect(object).toEqual({key: "value"});
});
});
});
Loading
Loading