Skip to content

Commit 21bab74

Browse files
updated files
1 parent 9343366 commit 21bab74

File tree

11 files changed

+89
-1817
lines changed

11 files changed

+89
-1817
lines changed

README.md

+22-23
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,28 @@ The **FAQ Search Adaptive Card Extension** for SharePoint Framework (SPFx) is de
2828
- Appropriate permissions to create and manage SharePoint lists
2929
- FAQ list and submission lists created in SharePoint Online
3030

31+
The FAQ Search Adaptive Card Extension interacts with two SharePoint lists: **FAQ List** and **Submission List**. Below are the required columns for each list:
32+
33+
## SharePoint Lists & Columns
34+
### FAQ List Columns
35+
36+
| Column Name | Data Type | Description |
37+
|-------------------|------------|--------------------------------------------------|
38+
| Title | Single line of text | The title of the FAQ question. |
39+
| Answer | Multiple lines of text | The answer to the FAQ question. |
40+
| Category | Choice | Category under which the FAQ falls. |
41+
| HelpfulCount | Number | Count of how many users found the FAQ helpful. |
42+
43+
### Submission List Columns
44+
45+
| Column Name | Data Type | Description |
46+
|-------------------|------------|--------------------------------------------------|
47+
| Title | Single line of text | The submitted question. |
48+
| SubmissionDate | Date and Time | The date and time the question was submitted. |
49+
| Status | Choice | The current status of the submitted question (e.g., "New", "Reviewed"). |
50+
| Category | Choice | The category of the submitted question. |
51+
52+
3153
## Solution
3254

3355
Solution | Author(s)
@@ -102,29 +124,6 @@ For more details, follow this guide on [Adding Cards to the Viva Connections Das
102124
- Select the FAQ Search Adaptive Card Extension from the list of available extensions.
103125
- Configure the web part by specifying the FAQ List Name, Submission List Name, and other properties.
104126

105-
The FAQ Search Adaptive Card Extension interacts with two SharePoint lists: **FAQ List** and **Submission List**. Below are the required columns for each list:
106-
107-
## SharePoint Lists & Columns
108-
### FAQ List Columns
109-
110-
| Column Name | Data Type | Description |
111-
|-------------------|------------|--------------------------------------------------|
112-
| Title | Single line of text | The title of the FAQ question. |
113-
| Answer | Multiple lines of text | The answer to the FAQ question. |
114-
| Category | Choice | Category under which the FAQ falls. |
115-
| HelpfulCount | Number | Count of how many users found the FAQ helpful. |
116-
| Created | Date and Time | The date when the FAQ was created. |
117-
118-
### Submission List Columns
119-
120-
| Column Name | Data Type | Description |
121-
|-------------------|------------|--------------------------------------------------|
122-
| Title | Single line of text | The submitted question. |
123-
| SubmittedBy | Person or Group | The user who submitted the question. |
124-
| SubmissionDate | Date and Time | The date and time the question was submitted. |
125-
| Status | Choice | The current status of the submitted question (e.g., "New", "Reviewed"). |
126-
| Category | Choice | The category of the submitted question. |
127-
128127

129128
## Features
130129

src/adaptiveCardExtensions/faqSearch/hooks/useHelpfulCount.ts

-10
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,6 @@ export const useHelpfulCount = (
2424
// Fetch current helpful count
2525
const listItem = await list.items.getById(itemId).select("HelpfulCount")();
2626
const currentHelpfulCount = listItem.HelpfulCount || 0;
27-
28-
Logger.write(
29-
`Current helpful count for item ${itemId}: ${currentHelpfulCount}`,
30-
LogLevel.Info
31-
);
3227

3328
// Increment helpful count
3429
const updatedHelpfulCount = currentHelpfulCount + 1;
@@ -38,11 +33,6 @@ export const useHelpfulCount = (
3833
HelpfulCount: updatedHelpfulCount,
3934
});
4035

41-
Logger.write(
42-
`Updated helpful count for item ${itemId} to ${updatedHelpfulCount}`,
43-
LogLevel.Info
44-
);
45-
4636
// Update the state with the new helpful count
4737
setHelpfulCount(updatedHelpfulCount);
4838
} catch (err) {

src/adaptiveCardExtensions/faqSearch/hooks/useSPContext.ts

-9
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,11 @@ let spInstance: SPFI | null = null;
1313
*/
1414
export const useSPContext = (context: ISPFXContext, siteUrl?: string): SPFI => {
1515
if (!spInstance) {
16-
Logger.write(
17-
"Initializing PnPjs with SharePoint context....",
18-
LogLevel.Info
19-
);
20-
21-
console.log("siteUrl");
22-
console.log(siteUrl);
23-
2416
// Use the provided siteUrl or default to the current site URL
2517
const resolvedSiteUrl = siteUrl || context.pageContext.web.absoluteUrl;
2618

2719
try {
2820
spInstance = spfi(resolvedSiteUrl).using(SPFx(context)); // Initialize the SPFI instance
29-
Logger.write("PnPjs initialized successfully.", LogLevel.Info);
3021
} catch (error) {
3122
Logger.write(
3223
`Error initializing PnPjs: ${error.message}`,

src/adaptiveCardExtensions/faqSearch/hooks/useSubmitQuestion.ts

+11-8
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ export interface ISubmitQuestionProps {
77
category: string; // Add category field
88
}
99

10-
export const useSubmitQuestion = (context: any, listName: string, siteUrl: string) => {
10+
export const useSubmitQuestion = (context: any, siteUrl: string, listName: string) => {
1111
const [loading, setLoading] = useState<boolean>(false);
1212
const [error, setError] = useState<string | null>(null);
1313
const [success, setSuccess] = useState<boolean>(false);
1414

1515
const submitQuestion = useCallback(
16-
async ({ question, category }: ISubmitQuestionProps) => { // Include category in the parameters
16+
async ({ question, category }: ISubmitQuestionProps) => {
1717
setLoading(true);
1818
setError(null);
1919
setSuccess(false);
@@ -25,10 +25,7 @@ export const useSubmitQuestion = (context: any, listName: string, siteUrl: strin
2525
// Prepare the data to be submitted
2626
const newItem = {
2727
Title: question,
28-
Category: category, // Add category field to the list item
29-
SubmittedBy: context.pageContext.user.displayName,
30-
SubmissionDate: new Date(),
31-
Status: "New", // Default status
28+
Category: category,
3229
};
3330

3431
// Add a new item to the SharePoint list
@@ -42,8 +39,14 @@ export const useSubmitQuestion = (context: any, listName: string, siteUrl: strin
4239
setLoading(false); // Stop loading indicator
4340
}
4441
},
45-
[context, listName]
42+
[context, siteUrl, listName]
4643
);
4744

48-
return { submitQuestion, loading, error, success };
45+
// Reset success and error states
46+
const resetStatus = useCallback(() => {
47+
setSuccess(false);
48+
setError(null);
49+
}, []);
50+
51+
return { submitQuestion, loading, error, success, resetStatus };
4952
};

src/adaptiveCardExtensions/faqSearch/quickView/QuickView.ts

-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ export class QuickView extends BaseWebQuickView<
4444
try {
4545
if (this.domElement) {
4646
ReactDOM.unmountComponentAtNode(this.domElement);
47-
Logger.write("QuickView disposed and React component unmounted.", LogLevel.Info);
4847
} else {
4948
Logger.write("Warning: domElement is undefined during dispose.", LogLevel.Warning);
5049
}

src/adaptiveCardExtensions/faqSearch/quickView/components/FAQ/FAQList.tsx

+8-6
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,13 @@ const FAQList: React.FC<IFAQListProps> = ({
3939
setSelectedCategory(option.key as string);
4040
}
4141
},
42-
[]
42+
[]
4343
);
4444

4545
const handleSearch = (query: string) => {
4646
setSearchQuery(query);
4747
};
4848

49-
console.log("categories");
50-
console.log(categories);
51-
5249
return (
5350
<div>
5451
<h2>Frequently Asked Questions</h2>
@@ -58,14 +55,19 @@ const FAQList: React.FC<IFAQListProps> = ({
5855
<CategoryDropdown
5956
categories={categories}
6057
selectedCategory={selectedCategory}
61-
onCategoryChange={onCategoryChange}
58+
onCategoryChange={onCategoryChange}
6259
label={faqFilterLabel}
6360
/>
6461
<br />
6562

66-
{loading && <p>Loading FAQs...</p>}
63+
{/* Loading State */}
64+
{loading && <p>Loading...</p>}
6765
{error && <p>{error}</p>}
66+
67+
{/* No items found */}
6868
{filteredItems && filteredItems.length === 0 && <p>No FAQs available.</p>}
69+
70+
{/* Display the first 10 most useful items */}
6971
{filteredItems &&
7072
filteredItems.map((item) => (
7173
<ListItem

src/adaptiveCardExtensions/faqSearch/quickView/components/MostUseful/MostUsefulList.tsx

+13-11
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const MostUsefulList: React.FC<IMostUsefulListProps> = ({
3838
setSelectedCategory(option.key as string);
3939
}
4040
},
41-
[]
41+
[]
4242
);
4343

4444
return (
@@ -55,22 +55,24 @@ const MostUsefulList: React.FC<IMostUsefulListProps> = ({
5555
{/* Loading State */}
5656
{loading && <p>Loading...</p>}
5757
{error && <p>{error}</p>}
58-
58+
5959
{/* No items found */}
6060
{filteredItems && filteredItems.length === 0 && (
6161
<p>No useful questions available.</p>
6262
)}
63-
63+
6464
{/* Display the first 10 most useful items */}
6565
{filteredItems &&
66-
filteredItems.slice(0, 10).map((item) => (
67-
<ListItem
68-
key={item.Id}
69-
item={item}
70-
listName={listName}
71-
context={context}
72-
/>
73-
))}
66+
filteredItems
67+
.slice(0, 10)
68+
.map((item) => (
69+
<ListItem
70+
key={item.Id}
71+
item={item}
72+
listName={listName}
73+
context={context}
74+
/>
75+
))}
7476
</div>
7577
);
7678
};

src/adaptiveCardExtensions/faqSearch/quickView/components/Shared/CategoryDropdown.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,27 @@ interface ICategoryDropdownProps {
99
option?: IDropdownOption
1010
) => void;
1111
label?: string; // Optional label
12+
placeholder?: string; // New optional placeholder prop
1213
}
1314

14-
// Memoize the CategoryDropdown to avoid re-rendering unnecessarily
1515
const CategoryDropdown: React.FC<ICategoryDropdownProps> = ({
1616
categories,
1717
selectedCategory,
1818
onCategoryChange,
1919
label = "Filter by Category",
20+
placeholder = "All Categories", // Default to "All Categories" unless specified otherwise
2021
}) => {
21-
console.log("CategoryDropdown has rendered....");
22-
console.log(categories);
22+
const options = [{ key: "", text: placeholder }, ...categories]; // Prepend placeholder option
2323

2424
return (
2525
<Dropdown
26-
label={label || "Select a Category"} // Default label if label is not provided
27-
options={[{ key: "", text: "All Categories" }, ...categories]} // Prepend "All Categories"
28-
selectedKey={selectedCategory || ""} // Set default selected option to "All Categories"
29-
onChange={onCategoryChange} // UI only, no business logic
26+
label={label}
27+
options={options}
28+
selectedKey={selectedCategory || ""} // Use empty key if nothing is selected
29+
onChange={onCategoryChange}
30+
placeholder={selectedCategory ? undefined : placeholder} // Set placeholder only if no category is selected
3031
/>
3132
);
3233
};
3334

34-
// Memoize the CategoryDropdown component to prevent unnecessary re-renders
3535
export default React.memo(CategoryDropdown);

src/adaptiveCardExtensions/faqSearch/quickView/components/SubmitQuestion/SubmitQuestionsView.tsx

+27-16
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,31 @@
11
import * as React from "react";
2-
import { useState } from "react";
3-
import { Stack, PrimaryButton, TextField, MessageBar, MessageBarType } from "@fluentui/react";
2+
import { useState, useEffect } from "react";
3+
import {
4+
Stack,
5+
PrimaryButton,
6+
TextField,
7+
MessageBar,
8+
MessageBarType,
9+
} from "@fluentui/react";
410
import CategoryDropdown from "../Shared/CategoryDropdown";
511
import { useSubmitQuestion } from "../../../hooks/useSubmitQuestion";
612
import { IDropdownOption } from "@fluentui/react";
713
import { ISPFXContext } from "@pnp/sp";
814

9-
const SubmitQuestionForm: React.FC<{
15+
const SubmitQuestionForm: React.FC<{
1016
context: ISPFXContext;
1117
siteUrl: string;
1218
listName: string;
1319
categories: IDropdownOption[];
1420
}> = ({ context, siteUrl, listName, categories }) => {
15-
const { submitQuestion, loading, error, success } = useSubmitQuestion(
16-
context,
17-
siteUrl,
18-
listName
19-
);
21+
const { submitQuestion, loading, error, success, resetStatus } =
22+
useSubmitQuestion(context, siteUrl, listName);
2023
const [question, setQuestion] = useState<string>("");
2124
const [selectedCategory, setSelectedCategory] = useState<string>("");
22-
const [showSuccessMessage, setShowSuccessMessage] = useState<boolean>(false);
2325

2426
const handleSubmit = async (e: React.FormEvent) => {
2527
e.preventDefault();
2628
await submitQuestion({ question, category: selectedCategory });
27-
28-
if (success) {
29-
setQuestion("");
30-
setShowSuccessMessage(true);
31-
setTimeout(() => setShowSuccessMessage(false), 3000);
32-
}
3329
};
3430

3531
const onCategoryChange = (
@@ -41,6 +37,20 @@ const SubmitQuestionForm: React.FC<{
4137
}
4238
};
4339

40+
// Show the success message for 3 seconds when `success` changes
41+
useEffect(() => {
42+
if (success) {
43+
setQuestion(""); // Reset question field after successful submission
44+
setSelectedCategory(""); // Optional: reset category selection if desired
45+
46+
const timer = setTimeout(() => {
47+
resetStatus();
48+
}, 3000);
49+
50+
return () => clearTimeout(timer); // Cleanup the timer on unmount or if success changes
51+
}
52+
}, [success, resetStatus]);
53+
4454
return (
4555
<Stack tokens={{ childrenGap: 15 }}>
4656
<h2 style={{ marginBottom: "0px" }}>Submit your question:</h2>
@@ -59,6 +69,7 @@ const SubmitQuestionForm: React.FC<{
5969
selectedCategory={selectedCategory}
6070
onCategoryChange={onCategoryChange}
6171
label="Select a Category"
72+
placeholder="Select an option" // Placeholder text specific to SubmitQuestionForm
6273
/>
6374
<PrimaryButton
6475
text={loading ? "Submitting..." : "Submit Question"}
@@ -70,7 +81,7 @@ const SubmitQuestionForm: React.FC<{
7081
{error}
7182
</MessageBar>
7283
)}
73-
{showSuccessMessage && (
84+
{success && (
7485
<MessageBar messageBarType={MessageBarType.success}>
7586
Question submitted successfully!
7687
</MessageBar>

0 commit comments

Comments
 (0)