Initial commit voor Outlook plugin

This commit is contained in:
2024-10-04 10:18:51 +02:00
commit d02d5291ee
35 changed files with 16082 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<!-- Office JavaScript API -->
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
</head>
<body>
</body>
</html>

32
src/commands/commands.js Normal file
View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
* See LICENSE in the project root for license information.
*/
/* global Office */
Office.onReady(() => {
// If needed, Office.js is ready to be called.
});
/**
* Shows a notification when the add-in command is executed.
* @param event {Office.AddinCommands.Event}
*/
function action(event) {
const message = {
type: Office.MailboxEnums.ItemNotificationMessageType.InformationalMessage,
message: "Performed action.",
icon: "Icon.80x80",
persistent: true,
};
// Show a notification message.
Office.context.mailbox.item.notificationMessages.replaceAsync("action", message);
// Be sure to indicate when the add-in command function is complete.
event.completed();
}
// Register the function with Office.
Office.actions.associate("action", action);

225
src/taskpane/taskpane.css Normal file
View File

@@ -0,0 +1,225 @@
*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
* See LICENSE in the project root for license information.
*/
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
ul {
margin: 0;
padding: 0;
}
.ms-welcome__header {
padding: 20px;
padding-bottom: 20px;
padding-top: 20px;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
align-items: center;
}
.ms-welcome__main {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-flex-wrap: nowrap;
flex-wrap: nowrap;
-webkit-align-items: center;
align-items: center;
-webkit-flex: 1 0 0;
flex: 1 0 0;
padding: 10px 20px;
}
.ms-welcome__main > h2 {
width: 100%;
text-align: center;
}
.ms-welcome__features {
list-style-type: none;
margin-top: 20px;
}
.ms-welcome__features.ms-List .ms-ListItem {
padding-bottom: 20px;
display: -webkit-flex;
display: flex;
}
.ms-welcome__features.ms-List .ms-ListItem > .ms-Icon {
margin-right: 10px;
}
.ms-welcome__action.ms-Button--hero {
margin-top: 30px;
}
.ms-Button.ms-Button--hero .ms-Button-label {
color: #0078d7;
}
.ms-Button.ms-Button--hero:hover .ms-Button-label,
.ms-Button.ms-Button--hero:focus .ms-Button-label{
color: #005a9e;
cursor: pointer;
}
b {
font-weight: bold;
}
/* CSS */
.run-button {
appearance: button;
backface-visibility: hidden;
background-color: #405cf5;
border-radius: 6px;
border-width: 0;
box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset,rgba(50, 50, 93, .1) 0 2px 5px 0,rgba(0, 0, 0, .07) 0 1px 1px 0;
box-sizing: border-box;
color: #fff;
cursor: pointer;
font-family: -apple-system,system-ui,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif;
font-size: 100%;
height: 44px;
line-height: 1.15;
margin: 12px 0 0;
outline: none;
overflow: hidden;
padding: 0 25px;
position: relative;
text-align: center;
text-transform: none;
transform: translateZ(0);
transition: all .2s,box-shadow .08s ease-in;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
width: 100%;
}
.run-button {
cursor: pointer;
}
.run-button:hover {
transform: scale(1.1);
}
.run-button {
box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset, rgba(50, 50, 93, .2) 0 6px 15px 0, rgba(0, 0, 0, .1) 0 2px 2px 0, rgba(50, 151, 211, .3) 0 0 0 4px;
}
/* Loading CSS for button */
.loader {
display: none;
border: 4px solid rgba(255, 255, 255, 0.3);
border-top: 4px solid blue;
border-radius: 50%;
width: 25px;
height: 25px;
animation: spin 1s linear infinite;
margin-left: 10px;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading {
background-color: #ccc;
pointer-events: none;
}
/* CSS */
.result-button {
appearance: button;
backface-visibility: hidden;
background-color: #47bf67;
border-radius: 6px;
border-width: 0;
box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset,rgba(50, 50, 93, .1) 0 2px 5px 0,rgba(0, 0, 0, .07) 0 1px 1px 0;
box-sizing: border-box;
color: #fff;
cursor: pointer;
font-family: -apple-system,system-ui,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif;
font-size: 100%;
height: 44px;
line-height: 1.15;
margin: 12px 0 0;
outline: none;
overflow: hidden;
padding: 0 25px;
position: relative;
text-align: center;
text-transform: none;
transform: translateZ(0);
transition: all .2s,box-shadow .08s ease-in;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
width: 100%;
}
.result-button {
cursor: pointer;
}
.result-button:hover {
transform: scale(1.1);
}
.result-button {
box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset, rgba(50, 50, 93, .2) 0 6px 15px 0, rgba(0, 0, 0, .1) 0 2px 2px 0, rgba(50, 151, 211, .3) 0 0 0 4px;
}
/* CSS */
.no-result-button {
appearance: button;
backface-visibility: hidden;
background-color: #bf4747;
border-radius: 6px;
border-width: 0;
box-shadow: rgba(50, 50, 93, .1) 0 0 0 1px inset,rgba(50, 50, 93, .1) 0 2px 5px 0,rgba(0, 0, 0, .07) 0 1px 1px 0;
box-sizing: border-box;
color: #fff;
cursor: pointer;
font-family: -apple-system,system-ui,"Segoe UI",Roboto,"Helvetica Neue",Ubuntu,sans-serif;
font-size: 100%;
height: 44px;
line-height: 1.15;
margin: 12px 0 0;
outline: none;
overflow: hidden;
padding: 0 25px;
position: relative;
text-align: center;
text-transform: none;
transform: translateZ(0);
transition: all .2s,box-shadow .08s ease-in;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
width: 100%;
}
.no-result-button {
cursor: pointer;
}

View File

@@ -0,0 +1,43 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT License. -->
<!-- This file shows how to design a first-run page that provides a welcome screen to the user about the features of the add-in. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Contoso Task Pane Add-in</title>
<!-- Office JavaScript API -->
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
<!-- For more information on Fluent UI, visit https://developer.microsoft.com/fluentui#/. -->
<link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/11.0.0/css/fabric.min.css"/>
<!-- Template styles -->
<link href="taskpane.css" rel="stylesheet" type="text/css" />
</head>
<body class="ms-font-m ms-welcome ms-Fabric">
<header class="ms-welcome__header">
<h1 class="ms-font-su" style="color: white;">OVAS</h1>
</header>
<main style="color: white;" id="app-body" class="ms-welcome__main" style="display: none;">
<ul class="ms-List ms-welcome__features">
<li class="ms-ListItem">
<i class="ms-Icon ms-Icon--Ribbon ms-font-xl"></i>
<span class="ms-font-m">Zoek bijbehorende bestellingen efficient vanuit Outlook</span>
</li>
</ul>
<button class="run-button" id="run">
<span id="btn-text">Zoek naar bestellingen</span>
<div class="loader" id="loader"></div>
</button>
<p><label id="item-subject"></label></p>
<div id="results"></div>
</main>
</body>
</html>

139
src/taskpane/taskpane.js Normal file
View File

@@ -0,0 +1,139 @@
/*
* Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
* See LICENSE in the project root for license information.
*/
/* global document, Office */
import axios from "axios";
const api_tokens = {
dev: "kstlkkRb85jWbS424SXs6bw0rMmJDAcLrUJD05sL",
test: "fEKxynKZrM14BqMY1c14vxUqoEdocpMol3woH6Lv",
prod: "Uvk3eiHf2NB8ahRC1ijXp0N1YrrhZ1eakIG9gTA0",
};
// axios conf
axios.defaults.headers.common["api-key"] = api_tokens.dev;
axios.defaults.headers.common["api-language"] = "nl";
const localApiUrl = "https://ozrp7bzqco.sharedwithexpose.com/api/zoek_bestelling";
const orderUrlEdit = "http://localhost:8080/bestellingen/edit/";
const orderUrlIndex = "http://localhost:8080/bestellingen";
Office.onReady((info) => {
if (info.host === Office.HostType.Outlook) {
document.getElementById("app-body").style.display = "flex";
document.getElementById("run").onclick = run;
}
});
export async function run() {
// Set load animation in button
loadAnimation(true);
let searchInfo = {
senderLastName: btoa(getLastName(Office.context.mailbox.item.sender.displayName)),
senderInitials: btoa(getInitials(Office.context.mailbox.item.sender.displayName)),
senderName: btoa(Office.context.mailbox.item.sender.displayName),
senderEmail: btoa(Office.context.mailbox.item.sender.emailAddress),
senderSubject: btoa(Office.context.mailbox.item.subject),
postalCodes: {},
};
searchInfo.postalCodes = await new Promise((resolve) => {
Office.context.mailbox.item.body.getAsync("text", function (async) {
resolve(getPostalCodesFromText(async.value));
});
});
// Make API call to see if we can find an order for the e-mail.
let results;
await search(searchInfo).then((res) => (results = res));
// Disable load animation in button
loadAnimation(false);
// Load results via buttons
showResults(results);
}
// Animation function for loader on button
function loadAnimation(animate) {
const loadButton = document.getElementById("run");
const loader = document.getElementById("loader");
const btnText = document.getElementById("btn-text");
if (animate) {
loadButton.disabled = true;
btnText.style.display = "none";
loader.style.display = "inline-block";
}
if (!animate) {
loadButton.disabled = false;
loader.style.display = "none";
btnText.style.display = "block";
}
}
// OVAS API call
async function search(searchInfo) {
let results = [];
await axios
.get(localApiUrl, {
params: searchInfo,
})
.then(function (res) {
results = res.data.results ?? [];
})
.catch((err) => err);
return results;
}
function getLastName(name) {
const nameParts = name.trim().split(" ");
const lastName = nameParts.slice(-1)[0]; // Pak het laatste deel als achternaam
return lastName;
}
function getInitials(name) {
const nameParts = name.trim().split(" ");
const firstName = nameParts[0];
const initials = firstName.charAt(0).toUpperCase() + ".";
return initials;
}
function getPostalCodesFromText(emailBody) {
const regex = /\b\d{4}\s?[A-Z]{2}\b/g;
return btoa(emailBody.match(regex));
}
function showResults(results) {
let resultDiv = document.getElementById("results");
resultDiv.innerHTML = "";
if (results.length > 0) {
results.forEach((result) => {
resultDiv.innerHTML += resultsFoundButton(result.id, result.lastname);
});
} else {
resultDiv.innerHTML = noResultsFoundButton();
}
}
function resultsFoundButton(id, customer) {
return `<button type="button" target="_blank" onclick="location.href='${orderUrlEdit}${id}'" class="result-button" style="text-decoration: none;">
<span class="btn-text" style="display: block;">Order ID: ${id} - ${customer}</span>
</button>`;
}
function noResultsFoundButton() {
return `<button type="button" onclick="location.href='${orderUrlIndex}'" class="no-result-button" style="text-decoration: none;">
<span class="btn-text" style="display: block;">Geen bestellingen gevonden...</span>
</button>`;
}