Merged in release/2024-12-13 (pull request #2022)

IO-3020 IO-3036 Remove Audit and Lifecycle feature wraps.
This commit is contained in:
Patrick Fic
2024-12-13 16:28:53 +00:00
9 changed files with 60 additions and 34 deletions

View File

@@ -49,7 +49,9 @@ export function BlurWrapper({
} }
if (bypass) { if (bypass) {
console.trace("*** BYPASS USED", featureName); if (import.meta.env.DEV) {
console.trace("*** Blur Wrapper BYPASS USED", featureName);
}
return children; return children;
} }
@@ -118,7 +120,7 @@ function RandomDate() {
const featureNameList = [ const featureNameList = [
"mobile", "mobile",
"allAccess", "allAccess",
"audit", //"audit", //Removing 2024-12-13. Keeping as default feature.
"timetickets", "timetickets",
"payments", "payments",
"partsorders", "partsorders",
@@ -133,8 +135,8 @@ const featureNameList = [
"checklist", "checklist",
"smartscheduling", "smartscheduling",
"roguard", "roguard",
"dashboard", "dashboard"
"lifecycle" //"lifecycle" //Removing 2024-12-13. Keeping as default feature.
]; ];
export function ValidateFeatureName(featureName) { export function ValidateFeatureName(featureName) {

View File

@@ -19,9 +19,18 @@ function FeatureWrapper({
blurContent, blurContent,
children, children,
upsellComponent, upsellComponent,
bypass,
...restProps ...restProps
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
if (bypass) {
if (import.meta.env.DEV) {
console.trace("*** Feature Wrapper BYPASS USED", featureName);
}
return children;
}
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
if (!ValidateFeatureName(featureName)) console.trace("*** INVALID FEATURE NAME", featureName); if (!ValidateFeatureName(featureName)) console.trace("*** INVALID FEATURE NAME", featureName);
} }
@@ -59,10 +68,16 @@ function FeatureWrapper({
} }
} }
export function HasFeatureAccess({ featureName, bodyshop, debug = false }) { export function HasFeatureAccess({ featureName, bodyshop, bypass, debug = false }) {
if (debug) { if (debug) {
console.trace(`*** HasFeatureAccessFunction called with feature << ${featureName} >>`); console.trace(`*** HasFeatureAccessFunction called with feature << ${featureName} >>`);
} }
if (bypass) {
if (import.meta.env.DEV) {
console.trace("*** Feature Wrapper BYPASS USED", featureName);
}
return true;
}
return bodyshop?.features?.allAccess || dayjs(bodyshop?.features[featureName]).isAfter(dayjs()); return bodyshop?.features?.allAccess || dayjs(bodyshop?.features[featureName]).isAfter(dayjs());
} }

View File

@@ -47,7 +47,7 @@ export function JobAuditTrail({ bodyshop, currentUser, jobId }) {
dataIndex: "operation", dataIndex: "operation",
key: "operation", key: "operation",
render: (text, record) => ( render: (text, record) => (
<BlurWrapperComponent featureName="audit"> <BlurWrapperComponent featureName="audit" bypass>
<div>{text}</div> <div>{text}</div>
</BlurWrapperComponent> </BlurWrapperComponent>
) )
@@ -77,7 +77,7 @@ export function JobAuditTrail({ bodyshop, currentUser, jobId }) {
record.to && record.to &&
record.to.map((email, idx) => ( record.to.map((email, idx) => (
<Tag key={idx}> <Tag key={idx}>
<BlurWrapperComponent featureName="audit"> <BlurWrapperComponent featureName="audit" bypass>
<div>{email}</div> <div>{email}</div>
</BlurWrapperComponent> </BlurWrapperComponent>
</Tag> </Tag>
@@ -92,7 +92,7 @@ export function JobAuditTrail({ bodyshop, currentUser, jobId }) {
record.cc && record.cc &&
record.cc.map((email, idx) => ( record.cc.map((email, idx) => (
<Tag key={idx}> <Tag key={idx}>
<BlurWrapperComponent featureName="audit"> <BlurWrapperComponent featureName="audit" bypass>
<div>{email}</div> <div>{email}</div>
</BlurWrapperComponent> </BlurWrapperComponent>
</Tag> </Tag>
@@ -103,7 +103,7 @@ export function JobAuditTrail({ bodyshop, currentUser, jobId }) {
dataIndex: "subject", dataIndex: "subject",
key: "subject", key: "subject",
render: (text, record) => ( render: (text, record) => (
<BlurWrapperComponent featureName="audit"> <BlurWrapperComponent featureName="audit" bypass>
<div>{text}</div> <div>{text}</div>
</BlurWrapperComponent> </BlurWrapperComponent>
) )
@@ -113,7 +113,7 @@ export function JobAuditTrail({ bodyshop, currentUser, jobId }) {
dataIndex: "status", dataIndex: "status",
key: "status", key: "status",
render: (text, record) => ( render: (text, record) => (
<BlurWrapperComponent featureName="audit"> <BlurWrapperComponent featureName="audit" bypass>
<div>{text}</div> <div>{text}</div>
</BlurWrapperComponent> </BlurWrapperComponent>
) )

View File

@@ -69,7 +69,12 @@ export function JobLifecycleComponent({ job, statuses, ...rest }) {
dataIndex: "value", dataIndex: "value",
key: "value", key: "value",
render: (text, record) => ( render: (text, record) => (
<BlurWrapperComponent featureName="lifecycle" valueProp="children" overrideValueFunction="RandomSmallString:2"> <BlurWrapperComponent
featureName="lifecycle"
bypass
valueProp="children"
overrideValueFunction="RandomSmallString:2"
>
<span>{text}</span> <span>{text}</span>
</BlurWrapperComponent> </BlurWrapperComponent>
) )
@@ -80,7 +85,7 @@ export function JobLifecycleComponent({ job, statuses, ...rest }) {
key: "start", key: "start",
sorter: (a, b) => dayjs(a.start).unix() - dayjs(b.start).unix(), sorter: (a, b) => dayjs(a.start).unix() - dayjs(b.start).unix(),
render: (text, record) => ( render: (text, record) => (
<BlurWrapperComponent featureName="lifecycle" valueProp="children" overrideValueFunction="RandomDate"> <BlurWrapperComponent featureName="lifecycle" bypass valueProp="children" overrideValueFunction="RandomDate">
<span>{DateTimeFormatterFunction(text)}</span> <span>{DateTimeFormatterFunction(text)}</span>
</BlurWrapperComponent> </BlurWrapperComponent>
) )
@@ -105,7 +110,7 @@ export function JobLifecycleComponent({ job, statuses, ...rest }) {
}, },
render: (text, record) => ( render: (text, record) => (
<BlurWrapperComponent featureName="lifecycle" valueProp="children" overrideValueFunction="RandomDate"> <BlurWrapperComponent featureName="lifecycle" bypass valueProp="children" overrideValueFunction="RandomDate">
<span>{isEmpty(text) ? t("job_lifecycle.content.not_available") : DateTimeFormatterFunction(text)}</span> <span>{isEmpty(text) ? t("job_lifecycle.content.not_available") : DateTimeFormatterFunction(text)}</span>
</BlurWrapperComponent> </BlurWrapperComponent>
) )
@@ -141,7 +146,7 @@ export function JobLifecycleComponent({ job, statuses, ...rest }) {
<Card type="inner" style={{ marginTop: "10px" }}> <Card type="inner" style={{ marginTop: "10px" }}>
<UpsellComponent upsell={upsellEnum().lifecycle.general} /> <UpsellComponent upsell={upsellEnum().lifecycle.general} />
</Card> </Card>
<BlurWrapperComponent featureName="lifecycle"> <BlurWrapperComponent featureName="lifecycle" bypass>
<div <div
id="bar-container" id="bar-container"
style={{ style={{
@@ -221,6 +226,7 @@ export function JobLifecycleComponent({ job, statuses, ...rest }) {
{key.status} ( {key.status} (
<BlurWrapperComponent <BlurWrapperComponent
featureName="lifecycle" featureName="lifecycle"
bypass
overrideValueFunction="RandomAmount" overrideValueFunction="RandomAmount"
valueProp="children" valueProp="children"
> >

View File

@@ -148,14 +148,6 @@ export function JobsDetailHeaderActionsToggleProduction({ bodyshop, job, jobRO,
<Button type="primary" onClick={() => form.submit()} loading={loading}> <Button type="primary" onClick={() => form.submit()} loading={loading}>
{t("general.actions.save")} {t("general.actions.save")}
</Button> </Button>
<Button
disabled={scenario === "post"}
onClick={() => {
// setOpen(false);
}}
>
{t("general.actions.close")}
</Button>
</Space> </Space>
</Form> </Form>
</div> </div>

View File

@@ -14,10 +14,11 @@ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop bodyshop: selectBodyshop
}); });
const LockWrapper = ({ featureName, bodyshop, children, disabled = true }) => { const LockWrapper = ({ featureName, bodyshop, children, disabled = true, bypass }) => {
let renderedChildren = children; let renderedChildren = children;
if (disabled) { //Mark the child prop as disabled.
if (disabled && !bypass) {
renderedChildren = React.Children.map(children, (child) => { renderedChildren = React.Children.map(children, (child) => {
if (React.isValidElement(child)) { if (React.isValidElement(child)) {
return React.cloneElement(child, { return React.cloneElement(child, {
@@ -28,7 +29,16 @@ const LockWrapper = ({ featureName, bodyshop, children, disabled = true }) => {
}); });
} }
return ( if (bypass) {
if (import.meta.env.DEV) {
console.trace("*** Lock Wrapper BYPASS USED", featureName);
}
return <span>{children}</span>;
}
return HasFeatureAccess({ featureName: featureName, bodyshop }) ? (
children
) : (
<Space> <Space>
{!HasFeatureAccess({ featureName: featureName, bodyshop }) && <LockOutlined style={{ color: "tomato" }} />} {!HasFeatureAccess({ featureName: featureName, bodyshop }) && <LockOutlined style={{ color: "tomato" }} />}
{renderedChildren} {renderedChildren}

View File

@@ -1,3 +1,4 @@
import { useSplitTreatments } from "@splitsoftware/splitio-react"; import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Button, Card, Tabs } from "antd"; import { Button, Card, Tabs } from "antd";
import React from "react"; import React from "react";
@@ -94,7 +95,7 @@ export function ShopInfoComponent({ bodyshop, form, saveLoading }) {
key: "checklists", key: "checklists",
label: <LockWrapperComponent featureName="checklist">{t("bodyshop.labels.checklists")}</LockWrapperComponent>, label: <LockWrapperComponent featureName="checklist">{t("bodyshop.labels.checklists")}</LockWrapperComponent>,
children: <ShopInfoIntakeChecklistComponent form={form} />, children: <ShopInfoIntakeChecklistComponent form={form} />,
disabled: HasFeatureAccess({ bodyshop, featureName: "checklist" }), disabled: !HasFeatureAccess({ bodyshop, featureName: "checklist" }),
id: "tab-shop-checklists" id: "tab-shop-checklists"
}, },
{ {

View File

@@ -403,7 +403,7 @@ export function JobsDetailPage({
icon: <BarsOutlined />, icon: <BarsOutlined />,
id: "job-details-lifecycle", id: "job-details-lifecycle",
label: ( label: (
<LockWrapperComponent featureName="lifecycle">{t("menus.jobsdetail.lifecycle")}</LockWrapperComponent> <LockWrapperComponent featureName="lifecycle" bypass>{t("menus.jobsdetail.lifecycle")}</LockWrapperComponent>
), ),
children: <JobLifecycleComponent job={job} statuses={bodyshop.md_ro_statuses} /> children: <JobLifecycleComponent job={job} statuses={bodyshop.md_ro_statuses} />
}, },
@@ -438,7 +438,7 @@ export function JobsDetailPage({
key: "audit", key: "audit",
icon: <HistoryOutlined />, icon: <HistoryOutlined />,
id: "job-details-audit", id: "job-details-audit",
label: <LockWrapperComponent featureName="audit">{t("jobs.labels.audit")}</LockWrapperComponent>, label: <LockWrapperComponent featureName="audit" bypass>{t("jobs.labels.audit")}</LockWrapperComponent>,
children: <JobAuditTrail jobId={job.id} /> children: <JobAuditTrail jobId={job.id} />
}, },
{ {

View File

@@ -589,8 +589,8 @@ export const TemplateList = (type, context) => {
subject: i18n.t("printcenter.jobs.job_lifecycle_ro"), subject: i18n.t("printcenter.jobs.job_lifecycle_ro"),
key: "job_lifecycle_ro", key: "job_lifecycle_ro",
disabled: false, disabled: false,
group: "post", group: "post"
featureNameRestricted: "lifecycle" //featureNameRestricted: "lifecycle"
}, },
job_tasks: { job_tasks: {
title: i18n.t("printcenter.jobs.job_tasks"), title: i18n.t("printcenter.jobs.job_tasks"),
@@ -2136,8 +2136,8 @@ export const TemplateList = (type, context) => {
object: i18n.t("reportcenter.labels.objects.jobs"), object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.date_invoiced") field: i18n.t("jobs.fields.date_invoiced")
}, },
group: "jobs", group: "jobs"
featureNameRestricted: "lifecycle" //featureNameRestricted: "lifecycle"
}, },
job_lifecycle_date_summary: { job_lifecycle_date_summary: {
title: i18n.t("reportcenter.templates.job_lifecycle_date_summary"), title: i18n.t("reportcenter.templates.job_lifecycle_date_summary"),
@@ -2149,8 +2149,8 @@ export const TemplateList = (type, context) => {
object: i18n.t("reportcenter.labels.objects.jobs"), object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.date_invoiced") field: i18n.t("jobs.fields.date_invoiced")
}, },
group: "jobs", group: "jobs"
featureNameRestricted: "lifecycle" //featureNameRestricted: "lifecycle"
}, },
tasks_date: { tasks_date: {
title: i18n.t("reportcenter.templates.tasks_date"), title: i18n.t("reportcenter.templates.tasks_date"),