Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release to prod #54

Merged
merged 26 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a80dc45
Add scenario creation on import of json with test scenarios.
brysonjbest Nov 7, 2024
d7e38c2
Refactor scenarios and add upload selector for scenarios on rule add.
brysonjbest Nov 8, 2024
99f7b42
Add title editing to scenarios.
brysonjbest Nov 8, 2024
878dbdf
Add links to KLAMM interface for rule inputs, outputs, and rules.
brysonjbest Oct 23, 2024
14b242b
Minor accessibility fixes.
brysonjbest Oct 24, 2024
eb70013
Fix mapping issue.
brysonjbest Oct 28, 2024
947465c
Update to better manage editing on page change.
brysonjbest Nov 6, 2024
e79b7bc
Update link to conditional with published rule.
brysonjbest Nov 8, 2024
fb71ba3
Add help drawer and loading to scenario results.
brysonjbest Nov 15, 2024
cbea439
Add view pull request button.
brysonjbest Nov 19, 2024
adeb03d
Format rule pages to better indicate current version viewed.
brysonjbest Nov 19, 2024
0657e63
Refactor styling of version link and tag.
brysonjbest Nov 20, 2024
3ff7ad5
Move component into subcomponent folder.
brysonjbest Nov 21, 2024
89c9a5d
Refactor format of header and versions management in line with design…
brysonjbest Nov 21, 2024
99be711
Fix to potential XSS vulnerability.
brysonjbest Nov 21, 2024
feed711
Fix linting issue.
brysonjbest Nov 21, 2024
0253cb9
Fix linting issue.
brysonjbest Nov 21, 2024
7c91240
Refactor and edit visual changed and rule upload functionality.
brysonjbest Nov 27, 2024
8b69800
Merge pull request #48 from bcgov/feature/tests-in-rules
brysonjbest Nov 27, 2024
9343497
Add KLAMM url secret to build workflow.
brysonjbest Nov 27, 2024
6e10cb1
Merge pull request #49 from bcgov/fix/missing-secret
brysonjbest Nov 27, 2024
3e2146f
Update Dockerfile. (#50)
brysonjbest Nov 27, 2024
4adc2c2
Update version handling and dev bar styling.
brysonjbest Nov 28, 2024
f504998
Merge pull request #51 from bcgov/fix/formatting-design-errors
brysonjbest Nov 28, 2024
8eb418d
Fix version display issue.
brysonjbest Nov 28, 2024
0144983
Merge pull request #52 from bcgov/fix/formatting-design-errors
brysonjbest Nov 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/build-and-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ jobs:
build-args: |
NEXT_PUBLIC_SERVER_URL=${{ github.ref == 'refs/heads/main' && secrets.NEXT_PUBLIC_SERVER_URL_PROD || secrets.NEXT_PUBLIC_SERVER_URL_DEV }}
NEXT_PUBLIC_IN_PRODUCTION=${{ github.ref == 'refs/heads/main' && 'true' || 'false' }}

NEXT_PUBLIC_KLAMM_URL=${{ secrets.NEXT_PUBLIC_KLAMM_URL }}

outputs:
image_tag: ${{ steps.meta.outputs.tags }}

Expand Down
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ ARG NEXT_PUBLIC_SERVER_URL
ENV NEXT_PUBLIC_SERVER_URL=${NEXT_PUBLIC_SERVER_URL}
ARG NEXT_PUBLIC_IN_PRODUCTION
ENV NEXT_PUBLIC_IN_PRODUCTION=${NEXT_PUBLIC_IN_PRODUCTION}
ARG NEXT_PUBLIC_KLAMM_URL
ENV NEXT_PUBLIC_KLAMM_URL=$NEXT_PUBLIC_KLAMM_URL

# Create a non-root user and group named 'node'
USER root
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ This app is a tool for authoring and testing/simulating rules for SDPR's Busines

This project current depends on the API provided by the [brm-backend](https://github.com/bcgov/brm-backend) project. You'll have to set an environment variable of `NEXT_PUBLIC_SERVER_URL` pointing to the URL of that when it is up and running (like `http://localhost:3000`).

This project also depends on the API provided by the [klamm](https://github.com/bcgov/klamm) project. You'll have to set an environment variable of `NEXT_PUBLIC_KLAMM_URL` pointing to the url and endpoint for the business rules set of information (like `http://localhost/bre`).

## Getting it running

Install dependencies:
Expand Down
17 changes: 15 additions & 2 deletions app/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@ export default function Admin() {

const renderInputField = (fieldName: keyof RuleInfoBasic) => {
const Component = (value: string, _: RuleInfo, index: number) => (
<Input value={value} onChange={(e: React.ChangeEvent<HTMLInputElement>) => updateRule(e, index, fieldName)} />
<Input
value={value}
aria-label={`Enter ${fieldName}`}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => updateRule(e, index, fieldName)}
/>
);
Component.displayName = "InputField";
return Component;
Expand All @@ -156,6 +160,7 @@ export default function Admin() {
render: renderInputField("filepath"),
},
{
title: "Manage",
dataIndex: "delete",
width: "60px",
render: (value: string, _: RuleInfo, index: number) => {
Expand All @@ -179,6 +184,7 @@ export default function Admin() {
},
},
{
title: "View",
dataIndex: "view",
width: "60px",
render: (_: string, { _id, isPublished }: RuleInfo) => {
Expand Down Expand Up @@ -221,7 +227,14 @@ export default function Admin() {
</Button>
)}
</Flex>
<Input.Search placeholder="Search rules..." onSearch={handleSearch} style={{ marginBottom: 16 }} allowClear />
<Input.Search
placeholder="Search rules..."
onSearch={handleSearch}
style={{ marginBottom: 16 }}
allowClear
aria-label="Search rules"
role="searchbox"
/>

{isLoading ? (
<p>Loading...</p>
Expand Down
4 changes: 3 additions & 1 deletion app/components/InputOutputTable/InputOutputTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ export default function InputOutputTable({
.map(([field, value], index) => {
const propertyRule = propertyRuleMap?.find((item) => item.field === field);
return {
field: FieldStyler(propertyRule?.name || field, propertyRule?.description),
field: FieldStyler(
propertyRule?.name ? propertyRule : { name: field, description: propertyRule?.description }
),
value: convertAndStyleValue(value, field, editable),
key: index,
};
Expand Down
43 changes: 38 additions & 5 deletions app/components/InputStyler/subcomponents/FieldStyler.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
import { Tooltip, Popover } from "antd";
import { InfoCircleOutlined } from "@ant-design/icons";
import { InfoCircleOutlined, ArrowRightOutlined } from "@ant-design/icons";
import React from "react";

interface FieldProps {
name: string;
description?: string;
field?: string;
}

export default function FieldStyler({ name, description = "", field }: FieldProps) {
const klammLink = `${process.env.NEXT_PUBLIC_KLAMM_URL}/fields/${field}`;
const formattedDescription = description
? description.split("\n").map((text, index) => (
<p key={index} style={{ margin: "0" }}>
{text}
</p>
))
: null;

const descriptionLink = (
<>
{formattedDescription}{" "}
<a href={klammLink} rel="noopener noreferrer" target="_blank">
KLAMM <ArrowRightOutlined />
</a>
</>
);

const finalDescription = process.env.NEXT_PUBLIC_KLAMM_URL && field ? descriptionLink : formattedDescription;

export default function FieldStyler(fieldName: string, description?: string) {
const popOverInformation = (
<Popover placement="top" content={description} title={fieldName} trigger={"click"}>
<Popover
placement="top"
content={finalDescription}
title={name}
trigger="click"
overlayStyle={{ maxWidth: "300px", wordWrap: "break-word" }}
>
<span>
{" "}
<InfoCircleOutlined />
Expand All @@ -12,8 +45,8 @@ export default function FieldStyler(fieldName: string, description?: string) {
);
const helpDialog = "View Description";
return (
<label>
{fieldName}
<label htmlFor={field ? field : name}>
{name}
{description && (
<Tooltip title={helpDialog} placement="top">
{popOverInformation}
Expand Down
33 changes: 24 additions & 9 deletions app/components/RuleHeader/RuleHeader.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,33 @@
position: relative;
margin-bottom: 8px;
border-radius: 12px 12px 0 0;
background: white;
}

.homeWrapper {
padding: 8px 8px 0 8px;
}

.headerWrapper {
background: linear-gradient(0deg, #FFFFFF, #FFFFFFe4);
padding: 16px 8px 8px 8px;
padding: 8px;
}

.homeButton {
color: #666;
border: 1px solid;
border-radius: 10px;
color: #666 !important;
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
background: white;
border: 1px solid;
border-radius: 10px;
font-size: 16px;
}

.titleHeader {
margin: 0;
word-wrap: break-word;
max-width: calc(100vw - 32px);
max-width: 100%;
}

.titleInput {
Expand All @@ -30,10 +38,14 @@
}

.titleFilePath {
margin: 4px 0;
margin: 0;
color: #aaa;
}

.rightContent {
min-width: 200px;
}

.editButton {
background: none;
border: none;
Expand All @@ -43,8 +55,6 @@
color: #4b4b4b;
}



@media (max-width: 767px) {
.headerWrapper {
flex-direction: column;
Expand All @@ -55,6 +65,11 @@
align-items: flex-start !important;
gap: 8px !important;
}
.rightContent {
flex-direction: column;
align-items: flex-start;
min-width: unset;
}
.titleHeader {
font-size: 24px;
}
Expand Down
93 changes: 21 additions & 72 deletions app/components/RuleHeader/RuleHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,13 @@
"use client";
import { useState, useRef, useEffect } from "react";
import { usePathname } from "next/navigation";
import { Button, Flex, Tag } from "antd";
import {
HomeOutlined,
EyeOutlined,
EditOutlined,
CheckOutlined,
CheckCircleOutlined,
CheckCircleFilled,
} from "@ant-design/icons";
import { Flex, Tooltip, Button } from "antd";
import { HomeOutlined, CheckOutlined, ExportOutlined } from "@ant-design/icons";
import { RuleInfo } from "@/app/types/ruleInfo";
import { RULE_VERSION } from "@/app/constants/ruleVersion";
import { updateRuleData } from "@/app/utils/api";
import styles from "./RuleHeader.module.css";
import Link from "next/link";

export default function RuleHeader({
ruleInfo,
version = RULE_VERSION.inProduction,
}: {
ruleInfo: RuleInfo;
version?: string;
}) {
const pathname = usePathname();

export default function RuleHeader({ ruleInfo }: { ruleInfo: RuleInfo }) {
const [savedTitle, setSavedTitle] = useState("");
const [isEditingTitle, setIsEditingTitle] = useState(false);
const [currTitle, setCurrTitle] = useState<string>();
Expand Down Expand Up @@ -62,34 +46,17 @@ export default function RuleHeader({
}
};

const switchVersion = (versionToSwitchTo: RULE_VERSION) => {
// Use window.locaiton.href instead of router.push so that we can detect page changes for "unsaved changes" popup
window.location.href = `${pathname}?version=${versionToSwitchTo}&_=${new Date().getTime()}`;
};

const formatVersionText = (text: string) => {
const words = text.split(/(?=[A-Z])/);
return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
};

let versionColor = "green";
if (version === RULE_VERSION.draft) {
versionColor = "red";
} else if (version === RULE_VERSION.inReview) {
versionColor = "orange";
} else if (version === RULE_VERSION.inDev) {
versionColor = "purple";
}

if (currTitle === undefined) return null;

return (
<div className={styles.headerContainer} style={{ background: versionColor }}>
<Flex justify="space-between" className={styles.headerWrapper}>
<Flex gap="middle" align="center" flex={isEditingTitle ? "1" : "none"} className={styles.headerContent}>
<a href="/" className={styles.homeButton}>
<HomeOutlined />
</a>
<div className={styles.headerContainer}>
<div className={styles.homeWrapper}>
<Button type="link" href="/" className={styles.homeButton} icon={<HomeOutlined />}>
Home
</Button>
</div>
<Flex justify="space-between" align="center" className={styles.headerWrapper}>
<Flex gap="middle" align="center" flex={1} className={styles.headerContent}>
<Flex flex={1} vertical>
<h1
onClick={startEditingTitle}
Expand All @@ -109,42 +76,24 @@ export default function RuleHeader({
currTitle
)}
</h1>
<p className={styles.titleFilePath}>{ruleInfo.filepath}</p>
</Flex>
{isEditingTitle && (
<button className={styles.editButton} onClick={isEditingTitle ? doneEditingTitle : startEditingTitle}>
<CheckOutlined />
</button>
)}
<Tag color={versionColor}>{formatVersionText(version)}</Tag>
</Flex>
<Flex gap="small" align="end">
{version !== RULE_VERSION.draft && (
<Button onClick={() => switchVersion(RULE_VERSION.draft)} icon={<EditOutlined />} type="dashed">
Draft
</Button>
)}
{ruleInfo.reviewBranch && version !== RULE_VERSION.inReview && (
<Button onClick={() => switchVersion(RULE_VERSION.inReview)} icon={<EyeOutlined />} type="dashed">
In Review
</Button>
)}
{version !== RULE_VERSION.inDev && ruleInfo.isPublished && (
<Button onClick={() => switchVersion(RULE_VERSION.inDev)} icon={<CheckCircleOutlined />} type="dashed">
In Dev
</Button>
)}
{version !== RULE_VERSION.inProduction &&
ruleInfo.isPublished &&
process.env.NEXT_PUBLIC_IN_PRODUCTION === "true" && (
<Button
onClick={() => switchVersion(RULE_VERSION.inProduction)}
icon={<CheckCircleFilled />}
type="dashed"
>
In Production
</Button>
<Flex gap="small" align="end" vertical className={styles.rightContent}>
<p className={styles.titleFilePath}>{ruleInfo.filepath}</p>
{ruleInfo.name && process.env.NEXT_PUBLIC_KLAMM_URL && ruleInfo.isPublished && (
<Tooltip title="View rule details in KLAMM">
<Link href={`${process.env.NEXT_PUBLIC_KLAMM_URL}/rules/${ruleInfo.name}`} passHref target="_blank">
View In KLAMM <ExportOutlined />
</Link>
</Tooltip>
)}
</Flex>
</Flex>
</Flex>
</div>
Expand Down
31 changes: 31 additions & 0 deletions app/components/RuleManager/RuleManager.module.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,35 @@
.rulesWrapper {
position: relative;
min-height: 500px;
z-index: 1;
}

.rulesWrapper::before {
content: "";
position: absolute;
left: 50%;
transform: translateX(-50%);
width: calc(100vw - 15px);
height: 103%;
background: transparent;
background: linear-gradient(
to bottom,
var(--version-color) 0%,
transparent 170%
);
z-index: -1;
opacity: 0.1;
}

.rulesGraph {
border: 1px solid #d9d9d9;
}

.actionBar {
padding: 15px;
}

.rootLayout {
padding: 0;
}

Loading
Loading