Update logo & name Add-in. Add language options and improve two features
8
.hintrc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"extends": [
|
||||||
|
"development"
|
||||||
|
],
|
||||||
|
"hints": {
|
||||||
|
"typescript-config/strict": "off"
|
||||||
|
}
|
||||||
|
}
|
BIN
assets/.DS_Store
vendored
Normal file
Before Width: | Height: | Size: 314 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 551 KiB |
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 830 B After Width: | Height: | Size: 292 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 551 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 551 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 551 KiB |
@ -4,11 +4,11 @@
|
|||||||
<Version>1.0.0.0</Version>
|
<Version>1.0.0.0</Version>
|
||||||
<ProviderName>OutlookLLM RizLum</ProviderName>
|
<ProviderName>OutlookLLM RizLum</ProviderName>
|
||||||
<DefaultLocale>en-US</DefaultLocale>
|
<DefaultLocale>en-US</DefaultLocale>
|
||||||
<DisplayName DefaultValue="OutlookLLM"/>
|
<DisplayName DefaultValue="Outlook Rizlum"/>
|
||||||
<Description DefaultValue="Add-in for new Outlook that adds Generative AI features (Composition, Summarizing)"/>
|
<Description DefaultValue="Add-in for Outlook that adds Generative AI features (Composition, Summarizing)"/>
|
||||||
<IconUrl DefaultValue="https://localhost:3000/assets/icon-64.png"/>
|
<IconUrl DefaultValue="https://localhost:3000/assets/icon-64.png"/>
|
||||||
<HighResolutionIconUrl DefaultValue="https://localhost:3000/assets/icon-128.png"/>
|
<HighResolutionIconUrl DefaultValue="https://localhost:3000/assets/icon-128.png"/>
|
||||||
<SupportUrl DefaultValue="https://www.certeza.ai/help"/>
|
<SupportUrl DefaultValue="https://rizlum.ai/fr/"/>
|
||||||
<AppDomains>
|
<AppDomains>
|
||||||
<AppDomain>https://localhost</AppDomain>
|
<AppDomain>https://localhost</AppDomain>
|
||||||
</AppDomains>
|
</AppDomains>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import Header from "./Header";
|
import Header from "./Header";
|
||||||
import HeroList from "./HeroList";
|
import HeroList from "./HeroList";
|
||||||
import TextInsertion from "./TextInsertion";
|
import Summarize from "./Summarize";
|
||||||
import { makeStyles } from "@fluentui/react-components";
|
import { makeStyles } from "@fluentui/react-components";
|
||||||
import { Ribbon24Regular, LockOpen24Regular, DesignIdeas24Regular } from "@fluentui/react-icons";
|
import { Ribbon24Regular, LockOpen24Regular, DesignIdeas24Regular } from "@fluentui/react-icons";
|
||||||
import QuickResponse from "./QuickResponse";
|
import QuickResponse from "./QuickResponse";
|
||||||
@ -18,8 +19,8 @@ const App = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.root}>
|
<div className={styles.root}>
|
||||||
<TextInsertion />
|
<Summarize />
|
||||||
<QuickResponse />
|
{/* <QuickResponse /> */}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -45,11 +45,16 @@ const useStyles = makeStyles({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const TextInsertion = () => {
|
const Summarize = () => {
|
||||||
const [showSpinner, setshowSpinner] = useState(false);
|
const [showSpinner, setshowSpinner] = useState(false);
|
||||||
const [showSpinnerdetails, setshowSpinnerdetails] = useState(false);
|
const [showSpinnerdetails, setshowSpinnerdetails] = useState(false);
|
||||||
const [emailsummary, setEmailsummary] = useState("");
|
const [emailsummary, setEmailsummary] = useState("");
|
||||||
const [emailsummarydetails, setEmailsummarydetails] = useState("");
|
const [emailsummarydetails, setEmailsummarydetails] = useState("");
|
||||||
|
const [language, setLanguage] = useState("English"); // Default language is English
|
||||||
|
|
||||||
|
const handleLanguageChange = (event) => {
|
||||||
|
setLanguage(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
const getEmailContent = () =>
|
const getEmailContent = () =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
@ -77,10 +82,10 @@ const TextInsertion = () => {
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
model: 'riz-text',
|
model: 'riz-text',
|
||||||
messages: [
|
messages: [
|
||||||
{ role: "system", content: "You are an email assistant." },
|
{ role: "system", content: "You are an email summarizer." },
|
||||||
{
|
{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: 'Summarize briefly less than 40 words the content of the following email body: ' + emailContent,
|
content: `Summarize less than 50 words in ${language}$ the following email content into a concise summary:\n\n${emailContent}`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
@ -98,8 +103,7 @@ const TextInsertion = () => {
|
|||||||
console.error('Error fetching data:', error);
|
console.error('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
setshowSpinner(false);
|
setshowSpinner(false);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSummaryLong = async () => {
|
const handleSummaryLong = async () => {
|
||||||
@ -117,10 +121,10 @@ const TextInsertion = () => {
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
model: 'riz-text',
|
model: 'riz-text',
|
||||||
messages: [
|
messages: [
|
||||||
{ role: "system", content: "You are an email assistant." },
|
{ role: "system", content: "You are an email summarizer." },
|
||||||
{
|
{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: 'Summarize in detail less than 200 words the content of the following email body: ' + emailContent_detail,
|
content: `Summarize less than 200 words in ${language}$ the following email content into a concise summary:\n\n${emailContent_detail}$`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
@ -138,8 +142,7 @@ const TextInsertion = () => {
|
|||||||
console.error('Error fetching data:', error);
|
console.error('Error fetching data:', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
setshowSpinnerdetails(false);
|
setshowSpinnerdetails(false);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
@ -147,11 +150,25 @@ const TextInsertion = () => {
|
|||||||
return (
|
return (
|
||||||
<div className={styles.textPromptAndInsertion}>
|
<div className={styles.textPromptAndInsertion}>
|
||||||
<Title3>Summarize with AI</Title3>
|
<Title3>Summarize with AI</Title3>
|
||||||
|
<div style={{ marginBottom: "15px" }}>
|
||||||
|
<label htmlFor="language" style={{ display: "block", marginBottom: "5px" }}>
|
||||||
|
Choose summary language:
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="language"
|
||||||
|
value={language}
|
||||||
|
onChange={handleLanguageChange}
|
||||||
|
style={{ width: "100%", padding: "8px" }}
|
||||||
|
>
|
||||||
|
<option value="English">English</option>
|
||||||
|
<option value="French">French</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<Button appearance="primary" disabled={false} size="large" onClick={handleTextInsertion} style={{ marginBottom: '16px' }}>
|
<Button appearance="primary" disabled={false} size="large" onClick={handleTextInsertion} style={{ marginBottom: '16px' }}>
|
||||||
{showSpinner && (
|
{showSpinner && (
|
||||||
<Spinner id="spinner" appearance="inverted"/>
|
<Spinner id="spinner" appearance="inverted"/>
|
||||||
)}
|
)}
|
||||||
{showSpinner ? ' Summarizing email...' : 'Summarize with AI'}
|
{showSpinner ? ' Summarizing email...' : 'Summarize briefly the email'}
|
||||||
</Button>
|
</Button>
|
||||||
{/* <TextField value={response} multiline rows={10} disabled /> */}
|
{/* <TextField value={response} multiline rows={10} disabled /> */}
|
||||||
{emailsummary && (
|
{emailsummary && (
|
||||||
@ -167,8 +184,8 @@ const TextInsertion = () => {
|
|||||||
fontSize: "16px", // Improves text readability
|
fontSize: "16px", // Improves text readability
|
||||||
fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif", // Uses a modern font
|
fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif", // Uses a modern font
|
||||||
lineHeight: "1.5", // Adds spacing for multiline content
|
lineHeight: "1.5", // Adds spacing for multiline content
|
||||||
padding: "12px", // Adds internal spacing for a spacious feel
|
padding: "0px", // Adds internal spacing for a spacious feel
|
||||||
borderRadius: "8px", // Smooth rounded corners
|
borderRadius: "5px", // Smooth rounded corners
|
||||||
border: "1px solid #e1e4e8", // Subtle border for a clean outline
|
border: "1px solid #e1e4e8", // Subtle border for a clean outline
|
||||||
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)", // Adds a soft shadow for depth
|
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)", // Adds a soft shadow for depth
|
||||||
overflowY: "auto", // Ensures content is scrollable if it exceeds height
|
overflowY: "auto", // Ensures content is scrollable if it exceeds height
|
||||||
@ -184,7 +201,6 @@ const TextInsertion = () => {
|
|||||||
{emailsummarydetails && (
|
{emailsummarydetails && (
|
||||||
<div>
|
<div>
|
||||||
<TextField value={emailsummarydetails} multiline rows={15} disabled
|
<TextField value={emailsummarydetails} multiline rows={15} disabled
|
||||||
size={30}
|
|
||||||
appearance="filledLighter" // Applies a modern, softer look
|
appearance="filledLighter" // Applies a modern, softer look
|
||||||
style={{
|
style={{
|
||||||
width: "100%", // Makes the TextField responsive
|
width: "100%", // Makes the TextField responsive
|
||||||
@ -195,16 +211,17 @@ const TextInsertion = () => {
|
|||||||
fontSize: "14px", // Improves text readability
|
fontSize: "14px", // Improves text readability
|
||||||
fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif", // Uses a modern font
|
fontFamily: "'Segoe UI', Tahoma, Geneva, Verdana, sans-serif", // Uses a modern font
|
||||||
lineHeight: "1.5", // Adds spacing for multiline content
|
lineHeight: "1.5", // Adds spacing for multiline content
|
||||||
padding: "12px", // Adds internal spacing for a spacious feel
|
padding: "5px", // Adds internal spacing for a spacious feel
|
||||||
borderRadius: "8px", // Smooth rounded corners
|
borderRadius: "5px", // Smooth rounded corners
|
||||||
border: "1px solid #e1e4e8", // Subtle border for a clean outline
|
border: "1px solid #e1e4e8", // Subtle border for a clean outline
|
||||||
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)", // Adds a soft shadow for depth
|
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)", // Adds a soft shadow for depth
|
||||||
overflowY: "auto", // Ensures content is scrollable if it exceeds height
|
overflowY: "auto", // Ensures content is scrollable if it exceeds height
|
||||||
}} />
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TextInsertion;
|
export default Summarize;
|
@ -1,8 +1,10 @@
|
|||||||
|
/* eslint-disable no-undef */
|
||||||
/* eslint-disable prettier/prettier */
|
/* eslint-disable prettier/prettier */
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Button, Field, Title3, Checkbox, Textarea, Text, Spinner, tokens, makeStyles } from "@fluentui/react-components";
|
import { Button, Field, Title3, Checkbox, Textarea, Text, Spinner, tokens, makeStyles } from "@fluentui/react-components";
|
||||||
import { insertText } from "../outlook";
|
//import { insertText } from "../outlook";
|
||||||
|
import insertText from "../office-document";
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
|
|
||||||
@ -17,7 +19,7 @@ const useStyles = makeStyles({
|
|||||||
marginLeft: "15px",
|
marginLeft: "15px",
|
||||||
marginTop: "30px",
|
marginTop: "30px",
|
||||||
marginRight: "15px",
|
marginRight: "15px",
|
||||||
|
marginBottom: "10px"
|
||||||
},
|
},
|
||||||
|
|
||||||
textAreaField: {
|
textAreaField: {
|
||||||
@ -26,8 +28,15 @@ const useStyles = makeStyles({
|
|||||||
|
|
||||||
marginRight: "15px",
|
marginRight: "15px",
|
||||||
minHeight: "150px",
|
minHeight: "150px",
|
||||||
|
marginBottom: "15px"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
textArea: {
|
||||||
|
padding: "8px",
|
||||||
|
marginBottom: "10px"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
textCheck: {
|
textCheck: {
|
||||||
marginTop: "10px",
|
marginTop: "10px",
|
||||||
marginLeft: "15px",
|
marginLeft: "15px",
|
||||||
@ -42,19 +51,18 @@ const useStyles = makeStyles({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const TextInsertion = () => {
|
const TextInsertion = () => {
|
||||||
const [text, setText] = useState("Write an email to make a meeting with client");
|
const [language, setLanguage] = useState("English"); // Default language is English
|
||||||
|
const [text, setText] = useState("Give some ideas to write the email");
|
||||||
const [showSpinner, setshowSpinner] = useState(false);
|
const [showSpinner, setshowSpinner] = useState(false);
|
||||||
const [writeSubject, setWriteSubject] = useState(false);
|
const [writeSubject, setWriteSubject] = useState("Subject of emal (optional)");
|
||||||
|
|
||||||
let data = "";
|
let data = "";
|
||||||
|
let subject_email = "";
|
||||||
const handleTextInsertion = async () => {
|
const handleTextInsertion = async () => {
|
||||||
try {
|
try {
|
||||||
|
setshowSpinner(true);
|
||||||
setshowSpinner(true);
|
console.log("test before");
|
||||||
|
|
||||||
console.log("test before");
|
|
||||||
//const fetchChatCompletion = async () => {
|
|
||||||
try {
|
|
||||||
const res = await fetch('https://ai.rizlum.com/chat/completions', {
|
const res = await fetch('https://ai.rizlum.com/chat/completions', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -67,7 +75,16 @@ const TextInsertion = () => {
|
|||||||
{ role: "system", content: "You are an email assistant." },
|
{ role: "system", content: "You are an email assistant." },
|
||||||
{
|
{
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: 'Write an email content without subject with the following content: ' + text,
|
content: `Generate a professionnal email content in ${language} without a subject based on the following ideas: ${text}.
|
||||||
|
|
||||||
|
Formatting instructions:
|
||||||
|
1. Include appropriate line breaks to separate paragraphs.
|
||||||
|
2. Add a blank line (double line spacing) between paragraphs to improve readability.
|
||||||
|
3. For example:
|
||||||
|
- Start with a salutation such as "Hello [Recipient's Name]," followed by a blank line.
|
||||||
|
- After each paragraph, leave a blank line before starting the next.
|
||||||
|
- End the email with a closing like "Best regards," followed by the sender's name, with a blank line between them.
|
||||||
|
Ensure the email is well-structured and visually appealing with clear spacing between sections.`
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
@ -77,65 +94,67 @@ const TextInsertion = () => {
|
|||||||
throw new Error(`HTTP error! status: ${res.status}`);
|
throw new Error(`HTTP error! status: ${res.status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
data = await res.json();
|
data = await res.json();
|
||||||
console.log(data);
|
|
||||||
// setResponse(data);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching chat completion:', error);
|
|
||||||
//setResponse('Error fetching data');
|
|
||||||
}
|
|
||||||
//};
|
|
||||||
|
|
||||||
// const response = await fetch("http://localhost:11434/api/generate", {
|
|
||||||
// method: "POST",
|
|
||||||
// headers: {
|
|
||||||
// "Content-Type": "application/json",
|
|
||||||
// },
|
|
||||||
// body: JSON.stringify({
|
|
||||||
// model: "llama3.2",
|
|
||||||
// prompt: text,
|
|
||||||
// })
|
|
||||||
// });
|
|
||||||
//const response = "Hello World, we are Rizlum";
|
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
|
||||||
// if (!response.ok) {
|
|
||||||
// throw new Error("Network response was not ok");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Handle success response if needed
|
// Handle success response if needed
|
||||||
console.log('Data sent successfully');
|
console.log('Data sent successfully');
|
||||||
|
|
||||||
const textContent = data.choices[0].message.content;
|
const textContent = data.choices[0].message.content;
|
||||||
console.log(textContent);
|
console.log(textContent);
|
||||||
//const textContent = "Insert this magic text from Riz Lum :D";
|
// Insert text and subject to the email compose
|
||||||
//await insertText(textContent, writeSubject);
|
if (writeSubject == "Subject of emal (optional)") {
|
||||||
await insertText(textContent);
|
subject_email = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
subject_email = writeSubject;
|
||||||
|
}
|
||||||
|
await insertText(textContent,subject_email);
|
||||||
setshowSpinner(false);
|
setshowSpinner(false);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setshowSpinner(false);
|
setshowSpinner(false);
|
||||||
console.error('Error sending data:',error);
|
console.error('Error sending data:',error);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
const handleLanguageChange = (event) => {
|
||||||
|
setLanguage(event.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTextChange = async (event) => {
|
const handleTextChange = async (event) => {
|
||||||
setText(event.target.value);
|
setText(event.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSubjectChange = async (event) => {
|
||||||
|
setWriteSubject(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.textPromptAndInsertion}>
|
<div className={styles.textPromptAndInsertion}>
|
||||||
<Title3>Compose with AI</Title3>
|
<Title3>Compose an email</Title3>
|
||||||
<Text className={styles.textField} size="medium" >1. Set the cursor where you want to insert the AI generated email.</Text>
|
<Text className={styles.textField} size="medium" >Describe the email that you need AI help:</Text>
|
||||||
<Field className={styles.textAreaField} size="medium" label="2. Describe the email you need AI help you with:">
|
<Field className={styles.textAreaField} size="medium" /* label="1. Describe the email:" */>
|
||||||
<Textarea size="medium" className="{styles.textArea}" placeholder={text} onChange={handleTextChange} resize="vertical"/>
|
<div style={{ marginBottom: "15px" }}>
|
||||||
</Field>
|
{/* <label htmlFor="language" style={{ display: "block", marginBottom: "5px" }}>
|
||||||
{/* <Text className={styles.textCheck} size="medium" >3. Check if you want also AI to generate the email subject.</Text>
|
Choose Language:
|
||||||
<Checkbox className={styles.checkStyle} label="Generate Email Subject" onChange={(ev, data) => setWriteSubject(data.checked)} value={writeSubject}/> */}
|
</label> */}
|
||||||
|
<select
|
||||||
|
id="language"
|
||||||
|
value={language}
|
||||||
|
onChange={handleLanguageChange}
|
||||||
|
style={{ width: "100%", padding: "8px" }}
|
||||||
|
>
|
||||||
|
<option value="English">English</option>
|
||||||
|
<option value="French">French</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Textarea size="small" className={styles.textArea} placeholder={writeSubject} onChange={handleSubjectChange} resize="vertical"/>
|
||||||
|
<Textarea size="medium" className={styles.textArea} placeholder={text} onChange={handleTextChange} resize="vertical"/>
|
||||||
|
|
||||||
|
</Field>
|
||||||
|
<Text className={styles.textField} size="medium" >Set the cursor where you want to insert the AI generated email.</Text>
|
||||||
<Button appearance="primary" disabled={false} size="large" onClick={handleTextInsertion}>
|
<Button appearance="primary" disabled={false} size="large" onClick={handleTextInsertion}>
|
||||||
{showSpinner && (
|
{showSpinner && (
|
||||||
<Spinner id="spinner" appearance="inverted"/>
|
<Spinner id="spinner" appearance="inverted"/>
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
|
/* eslint-disable prettier/prettier */
|
||||||
/* global Office console */
|
/* global Office console */
|
||||||
|
|
||||||
const insertText = async (text, writeSubject) => {
|
const insertText = async (textContent, writeSubject) => {
|
||||||
// Write text to the cursor point in the compose surface.
|
|
||||||
try {
|
try {
|
||||||
|
// Insert subject if available
|
||||||
if (writeSubject) {
|
if (writeSubject) {
|
||||||
const respSetSubject = await Office.context.mailbox.item.subject.setAsync(
|
Office.context.mailbox.item.subject.setAsync(
|
||||||
text.subject,
|
writeSubject,
|
||||||
{ coercionType: Office.CoercionType.Text },
|
{ coercionType: Office.CoercionType.Text },
|
||||||
(asyncResult) => {
|
(asyncResult) => {
|
||||||
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
|
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
|
||||||
@ -14,11 +15,15 @@ const insertText = async (text, writeSubject) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
//console.log('emailbody: '+ text.body);
|
// Write text to the cursor point in the compose surface.
|
||||||
|
const formattedText = textContent
|
||||||
const respSetBody = await Office.context.mailbox.item.body.setSelectedDataAsync(
|
.split("\n\n") // Split paragraphs by double line breaks
|
||||||
text.body.replace(/\n/g, '<br>'),
|
.map((paragraph) => `<p>${paragraph.trim()}</p>`) // Wrap each paragraph in <p> tags
|
||||||
{ coercionType: Office.CoercionType.Html },
|
.join(""); // Join paragraphs without extra separators
|
||||||
|
// Insert the formatted HTML into the email body
|
||||||
|
Office.context.mailbox.item.body.setSelectedDataAsync(
|
||||||
|
formattedText,
|
||||||
|
{ coercionType: Office.CoercionType.Html},
|
||||||
(asyncResult) => {
|
(asyncResult) => {
|
||||||
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
|
if (asyncResult.status === Office.AsyncResultStatus.Failed) {
|
||||||
throw asyncResult.error.message;
|
throw asyncResult.error.message;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable prettier/prettier */
|
||||||
/* global Office console */
|
/* global Office console */
|
||||||
|
|
||||||
export async function insertText(text) {
|
export async function insertText(text) {
|
||||||
|
@ -6,7 +6,7 @@ const HtmlWebpackPlugin = require("html-webpack-plugin");
|
|||||||
const webpack = require("webpack");
|
const webpack = require("webpack");
|
||||||
|
|
||||||
const urlDev = "https://localhost:3000/";
|
const urlDev = "https://localhost:3000/";
|
||||||
const urlProd = "https://www.contoso.com/"; // CHANGE THIS TO YOUR PRODUCTION DEPLOYMENT LOCATION
|
const urlProd = "https://rizlum.ai/fr/"; // CHANGE THIS TO YOUR PRODUCTION DEPLOYMENT LOCATION
|
||||||
|
|
||||||
async function getHttpsOptions() {
|
async function getHttpsOptions() {
|
||||||
const httpsOptions = await devCerts.getHttpsServerOptions();
|
const httpsOptions = await devCerts.getHttpsServerOptions();
|
||||||
|