Skip to content

Commit 4971757

Browse files
authored
MMI-3387 Add AI report summary (bcgov#2541)
Publish tno-core:1.0.31 Add DB migration 1.4.1
1 parent dae755b commit 4971757

File tree

56 files changed

+9713
-218
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+9713
-218
lines changed

api/net/TNO.API.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,14 @@
1515
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.0.0" />
1616
<PackageReference Include="Microsoft.AspnetCore.Authentication.jwtBearer" Version="9.0.0" />
1717
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer" Version="5.1.0" />
18+
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Core" Version="2.3.9" />
1819
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.2.1" />
1920
<!-- <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.2.1" /> -->
2021
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="7.0.0" />
2122
<PackageReference Include="prometheus-net.AspNetCore" Version="8.2.1" />
2223
<PackageReference Include="FTTLib.dll" Version="1.1.7" />
2324
<PackageReference Include="SSH.NET" Version="2024.2.0" />
24-
25+
<PackageReference Include="System.Formats.Asn1" Version="10.0.1" />
2526
</ItemGroup>
2627

2728
<ItemGroup>

api/net/appsettings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,5 +117,11 @@
117117
"Watch": {
118118
"IsEnabled": false,
119119
"SendTo": ""
120+
},
121+
"Azure": {
122+
"AI": {
123+
"ProjectEndpoint": "",
124+
"ModelDeploymentName": ""
125+
}
120126
}
121127
}

app/editor/.yarn/cache/tno-core-npm-1.0.29-b0ccc3fe82-277dacbb50.zip renamed to app/editor/.yarn/cache/tno-core-npm-1.0.31-a8a0b59ae3-57f0f47bb6.zip

2.03 MB
Binary file not shown.

app/editor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"redux-logger": "3.0.6",
6161
"styled-components": "6.1.11",
6262
"stylis": "4.3.2",
63-
"tno-core": "1.0.29"
63+
"tno-core": "1.0.31"
6464
},
6565
"devDependencies": {
6666
"@simbathesailor/use-what-changed": "2.0.0",

app/editor/src/features/admin/report-templates/templates/body/CustomReport.cshtml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,14 @@
364364
@(section.Value.Data)
365365
</div>
366366
}
367+
else if (section.Value.SectionType == ReportSectionType.AI)
368+
{
369+
@* AI SECTION *@
370+
var alt = section.Value.Settings.Label;
371+
<div>
372+
@(section.Value.Data)
373+
</div>
374+
}
367375

368376
@if (!horizontalCharts && !endChartGroup)
369377
{

app/editor/src/features/admin/reports/ReportFormSections.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
ReportContentOptions,
2020
ReportHeadlineOptions,
2121
ReportOptions,
22+
ReportSectionAI,
2223
ReportSectionContent,
2324
ReportSectionData,
2425
ReportSectionGallery,
@@ -160,6 +161,12 @@ export const ReportFormSections = () => {
160161
>
161162
Text
162163
</Button>
164+
<Button
165+
variant={ButtonVariant.secondary}
166+
onClick={() => handleAddSection(ReportSectionTypeName.AI)}
167+
>
168+
AI
169+
</Button>
163170
<Button
164171
variant={ButtonVariant.secondary}
165172
onClick={() => handleAddSection(ReportSectionTypeName.Content)}
@@ -277,6 +284,9 @@ export const ReportFormSections = () => {
277284
<Show visible={section.sectionType === ReportSectionTypeName.Data}>
278285
<ReportSectionData index={index} />
279286
</Show>
287+
<Show visible={section.sectionType === ReportSectionTypeName.AI}>
288+
<ReportSectionAI index={index} />
289+
</Show>
280290
</>
281291
)}
282292
</React.Fragment>
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { useFormikContext } from 'formik';
2+
import { Checkbox, Col, FieldSize, FormikText, FormikTextArea, IReportModel, Row } from 'tno-core';
3+
4+
export interface IReportSectionAIProps {
5+
index: number;
6+
}
7+
8+
export const ReportSectionAI = ({ index }: IReportSectionAIProps) => {
9+
const { values, setFieldValue } = useFormikContext<IReportModel>();
10+
11+
return (
12+
<Col gap="1rem" className="section">
13+
<FormikText
14+
name={`sections.${index}.settings.label`}
15+
label="Heading"
16+
tooltip="A heading label to display at the beginning of the section"
17+
maxLength={100}
18+
/>
19+
<FormikTextArea
20+
name={`sections.${index}.description`}
21+
label="Description"
22+
tooltip="Describe the purpose of this section"
23+
placeholder="An AI summary of the report"
24+
/>
25+
<Row>
26+
<FormikText
27+
name={`sections.${index}.settings.deploymentName`}
28+
label="Model Deployment Name"
29+
tooltip="The name of the model deployment"
30+
maxLength={100}
31+
placeholder="gpt-5.1-chat"
32+
/>
33+
<FormikText
34+
name={`sections.${index}.settings.temperature`}
35+
label="Temperature"
36+
tooltip="Apply randomness to responses. Depending on the model it may support values 0 - 2. Lower is more deterministic. Higher is creative."
37+
type="number"
38+
width={FieldSize.Tiny}
39+
placeholder="0"
40+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
41+
let value = e.target.value;
42+
setFieldValue(
43+
`sections.${index}.settings.temperature`,
44+
value.trim() === '' ? undefined : +value,
45+
);
46+
console.debug(value);
47+
}}
48+
/>
49+
<FormikText
50+
name={`sections.${index}.settings.choiceQty`}
51+
label="Choices"
52+
tooltip="Number of responses you want provided to compare. Some models do not have this feature."
53+
type="number"
54+
width={FieldSize.Tiny}
55+
placeholder="1"
56+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
57+
let value = e.target.value;
58+
setFieldValue(
59+
`sections.${index}.settings.choiceQty`,
60+
value.trim() === '' ? undefined : +value,
61+
);
62+
console.debug(value);
63+
}}
64+
/>
65+
</Row>
66+
<FormikTextArea
67+
name={`sections.${index}.settings.systemPrompt`}
68+
label="System Prompt"
69+
tooltip="Sets the global instructions and behavior for the model."
70+
placeholder="You are a report writer. Review the report data and generate summaries and analysis. The report data is JSON, each section groups related content and contains an array of story records. The `content.text` property contains the story information. The output generated must be in simple HTML that works within Outlook email client. Place all the output in a <div>\{output\}</div>."
71+
/>
72+
<FormikTextArea
73+
name={`sections.${index}.settings.userPrompt`}
74+
label="User Prompt"
75+
tooltip="Represents end-user input — questions, instructions, data, or prompts."
76+
placeholder="Create an executive summary of the report data."
77+
/>
78+
<Checkbox
79+
name={`sections.${index}.settings.inTableOfContents`}
80+
label="Include in Table of Contents"
81+
checked={
82+
values.sections[index].settings.inTableOfContents === undefined
83+
? true
84+
: values.sections[index].settings.inTableOfContents
85+
}
86+
onChange={(e) => {
87+
setFieldValue(`sections.${index}.settings.inTableOfContents`, e.target.checked);
88+
}}
89+
/>
90+
</Col>
91+
);
92+
};

app/editor/src/features/admin/reports/components/SectionIcon.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { BiSolidFileJson } from 'react-icons/bi';
2-
import { FaAlignJustify, FaChartPie, FaImage, FaList, FaNewspaper } from 'react-icons/fa6';
2+
import { FaAlignJustify, FaBrain, FaChartPie, FaImage, FaList, FaNewspaper } from 'react-icons/fa6';
33
import { ReportSectionTypeName } from 'tno-core';
44

55
export interface ISectionIconProps {
@@ -21,5 +21,7 @@ export const SectionIcon = ({ type }: ISectionIconProps) => {
2121
return <FaImage />;
2222
} else if (type === ReportSectionTypeName.Data) {
2323
return <BiSolidFileJson />;
24+
} else if (type === ReportSectionTypeName.AI) {
25+
return <FaBrain />;
2426
} else return null;
2527
};

app/editor/src/features/admin/reports/components/SectionLabel.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,12 @@ export const SectionLabel = ({ section }: ISectionLabelProps) => {
5656
Data: {section.settings.label}
5757
</Row>
5858
);
59+
} else if (section.sectionType === ReportSectionTypeName.AI) {
60+
return (
61+
<Row gap="0.25rem" alignItems="center">
62+
<SectionIcon type={section.sectionType} />
63+
AI: {section.settings.label}
64+
</Row>
65+
);
5966
} else return <>Unknown</>;
6067
};

app/editor/src/features/admin/reports/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from './ReportContentOptions';
22
export * from './ReportHeadlineOptions';
33
export * from './ReportOptions';
4+
export * from './ReportSectionAI';
45
export * from './ReportSectionContent';
56
export * from './ReportSectionData';
67
export * from './ReportSectionGallery';

0 commit comments

Comments
 (0)