├── .deployment ├── .gitignore ├── CODE_OF_CONDUCT.md ├── Deployment └── azuredeploy.json ├── LICENSE ├── Manifest ├── EndUser │ ├── ar.json │ ├── color.png │ ├── de.json │ ├── en.json │ ├── es.json │ ├── fr.json │ ├── he.json │ ├── ja.json │ ├── ko.json │ ├── manifest.json │ ├── outline.png │ ├── pt-BR.json │ ├── ru.json │ ├── zh-CN.json │ └── zh-TW.json └── SME │ ├── ar.json │ ├── color.png │ ├── de.json │ ├── en.json │ ├── es.json │ ├── fr.json │ ├── he.json │ ├── ja.json │ ├── ko.json │ ├── manifest.json │ ├── outline.png │ ├── pt-BR.json │ ├── ru.json │ ├── zh-CN.json │ └── zh-TW.json ├── README.md ├── SECURITY.md ├── Source ├── GlobalSuppressions.cs ├── Microsoft.Teams.Apps.AskHR.Common │ ├── Constants.cs │ ├── Exceptions │ │ └── TicketValidationException.cs │ ├── Microsoft.Teams.Apps.AskHR.Common.csproj │ ├── Models │ │ ├── ConfigurationEntity.cs │ │ ├── ConfigurationEntityTypes.cs │ │ ├── HelpInfoEntity.cs │ │ ├── ImageFileUrl.cs │ │ ├── TicketEntity.cs │ │ ├── TicketState.cs │ │ └── UsefulLinksTableModel.cs │ └── Providers │ │ ├── ConfigurationProvider.cs │ │ ├── HelpDataProvider.cs │ │ ├── IConfigurationProvider.cs │ │ ├── IHelpDataProvider.cs │ │ ├── ITicketsProvider.cs │ │ ├── StorageInfo.cs │ │ └── TicketsProvider.cs ├── Microsoft.Teams.Apps.AskHR.Configuration │ ├── .gitignore │ ├── App_Start │ │ ├── AutofacConfig.cs │ │ ├── BundleConfig.cs │ │ ├── FilterConfig.cs │ │ ├── RouteConfig.cs │ │ └── Startup.Auth.cs │ ├── ApplicationInsights.config │ ├── Connected Services │ │ └── Application Insights │ │ │ └── ConnectedService.json │ ├── Content │ │ ├── customizableStyle.css │ │ ├── font-awesome.min.css │ │ └── spinner.css │ ├── Controllers │ │ ├── AccountController.cs │ │ └── HomeController.cs │ ├── ErrorHandler │ │ └── AiHandleErrorAttribute.cs │ ├── Global.asax │ ├── Global.asax.cs │ ├── Images │ │ ├── HelpImg1.jpg │ │ ├── HelpImg10.jpg │ │ ├── HelpImg2.jpg │ │ ├── HelpImg3.jpg │ │ ├── HelpImg4.jpg │ │ ├── HelpImg5.jpg │ │ ├── HelpImg6.jpg │ │ ├── HelpImg7.jpg │ │ ├── HelpImg8.jpg │ │ └── HelpImg9.jpg │ ├── Microsoft.Teams.Apps.AskHR.Configuration.csproj │ ├── Models │ │ ├── HelpTabViewModel.cs │ │ ├── KnowledgeBaseViewModel.cs │ │ ├── TeamViewModel.cs │ │ ├── UsefulLinksViewModel.cs │ │ └── WelcomeMessageViewModel.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Resources │ │ ├── ErrorMessages.Designer.cs │ │ ├── ErrorMessages.ar.resx │ │ ├── ErrorMessages.de.resx │ │ ├── ErrorMessages.es.resx │ │ ├── ErrorMessages.fr.resx │ │ ├── ErrorMessages.he.resx │ │ ├── ErrorMessages.ja.resx │ │ ├── ErrorMessages.ko.resx │ │ ├── ErrorMessages.pt-BR.resx │ │ ├── ErrorMessages.resx │ │ ├── ErrorMessages.ru.resx │ │ ├── ErrorMessages.zh-CN.resx │ │ └── ErrorMessages.zh-TW.resx │ ├── Scripts │ │ ├── Index.js │ │ └── webConfigurator.js │ ├── Startup.cs │ ├── Strings.Designer.cs │ ├── Strings.ar.resx │ ├── Strings.de.resx │ ├── Strings.es.resx │ ├── Strings.fr.resx │ ├── Strings.he.resx │ ├── Strings.ja.resx │ ├── Strings.ko.resx │ ├── Strings.pt-BR.resx │ ├── Strings.resx │ ├── Strings.ru.resx │ ├── Strings.zh-CN.resx │ ├── Strings.zh-TW.resx │ ├── Views │ │ ├── Account │ │ │ ├── InvalidUser.cshtml │ │ │ └── SignOutCallback.cshtml │ │ ├── Home │ │ │ ├── Index.cshtml │ │ │ ├── _HelpTab.cshtml │ │ │ ├── _KnowledgeBase.cshtml │ │ │ ├── _Team.cshtml │ │ │ ├── _UsefulLinksTablePartial.cshtml │ │ │ └── _WelcomeMessage.cshtml │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ ├── _Layout.cshtml │ │ │ └── _Spinner.cshtml │ │ ├── Web.config │ │ └── _ViewStart.cshtml │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── Web.config │ ├── libman.json │ └── packages.config ├── Microsoft.Teams.Apps.AskHR.sln ├── Microsoft.Teams.Apps.AskHR │ ├── .babelrc │ ├── .gitignore │ ├── Bots │ │ ├── AskHRBot.cs │ │ ├── BotLocalizationCultureProvider.cs │ │ └── MessagingExtension.cs │ ├── Cards │ │ ├── AskAnExpertCard.cs │ │ ├── CardHelper.cs │ │ ├── MessagingExtensionTicketsCard.cs │ │ ├── ResponseCard.cs │ │ ├── ShareFeedbackCard.cs │ │ ├── SmeFeedbackCard.cs │ │ ├── SmeTicketCard.cs │ │ ├── SuggestedLinkCard.cs │ │ ├── TourCarousel.cs │ │ ├── UnrecognizedInputCard.cs │ │ ├── UnrecognizedTeamInputCard.cs │ │ ├── UserNotificationCard.cs │ │ ├── WelcomeCard.cs │ │ └── WelcomeTeamCard.cs │ ├── ClientApp │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── App.js │ │ │ ├── App.test.js │ │ │ ├── components │ │ │ │ ├── AskHRTiles │ │ │ │ │ ├── AskHRTile │ │ │ │ │ │ ├── AskHR.css │ │ │ │ │ │ └── AskHR.js │ │ │ │ │ ├── AskHRTiles.css │ │ │ │ │ └── AskHRTiles.js │ │ │ │ └── Telemetry │ │ │ │ │ └── TrackTelemetry.js │ │ │ ├── index.css │ │ │ └── index.js │ │ └── webpack.config.js │ ├── ConfigurationCredentialProvider.cs │ ├── Connected Services │ │ └── Application Insights │ │ │ └── ConnectedService.json │ ├── Controllers │ │ ├── BotController.cs │ │ └── HelpController.cs │ ├── Helper │ │ ├── AuthManager.cs │ │ └── IAuthManager.cs │ ├── Microsoft.Teams.Apps.AskHR.csproj │ ├── Models │ │ ├── AskAnExpertCardPayload.cs │ │ ├── ChangeTicketStatusPayload.cs │ │ ├── FeedbackRating.cs │ │ ├── ResponseCardPayload.cs │ │ ├── ShareFeedbackCardPayload.cs │ │ ├── TeamsAdaptiveSubmitActionData.cs │ │ └── TicketSearchScope.cs │ ├── Program.cs │ ├── Properties │ │ ├── Resource.Designer.cs │ │ ├── Resource.ar.resx │ │ ├── Resource.de.resx │ │ ├── Resource.es.resx │ │ ├── Resource.fr.resx │ │ ├── Resource.he.resx │ │ ├── Resource.ja.resx │ │ ├── Resource.ko.resx │ │ ├── Resource.pt-BR.resx │ │ ├── Resource.resx │ │ ├── Resource.ru.resx │ │ ├── Resource.zh-CN.resx │ │ └── Resource.zh-TW.resx │ ├── Services │ │ ├── IQnAMakerFactory.cs │ │ ├── ISearchService.cs │ │ ├── QnAMakerFactory.cs │ │ └── SearchService.cs │ ├── Startup.cs │ ├── Views │ │ └── Help │ │ │ ├── Index.cshtml │ │ │ ├── RenderData.cshtml │ │ │ └── SignIn.cshtml │ ├── appsettings.json │ ├── libman.json │ ├── package-lock.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ └── manifest.json │ └── wwwroot │ │ └── Content │ │ ├── Askaquestion.png │ │ ├── Enduserchat.png │ │ ├── Expertinquiry.png │ │ ├── HRSupportLoginImage.png │ │ ├── Notifications.png │ │ ├── Sharefeedback.png │ │ └── Ticketsystem.png ├── Resources.txt └── stylecop.json ├── deploy.bot.cmd ├── deploy.cmd ├── deploy.configuration.cmd └── global.json /.deployment: -------------------------------------------------------------------------------- 1 | [config] 2 | command = deploy.cmd 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /Manifest/EndUser/ar.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "دعم الموارد البشرية", 4 | "description.short": "روبوت سهل الاستخدام لدعم الموارد البشرية، يجيب عن الأسئلة ويوصّلك بالخبراء.", 5 | "description.full": "روبوت س&ج سهل الاستخدام. إذا لم يتمكن من العثور على إجالة، فسوف يعرض عليك الاتصال بخبير من قسم الموارد البشرية.", 6 | "staticTabs[0].name": "دعم الموارد البشرية", 7 | "bots[0].commandLists[0].commands[0].title": "القيام بجولة", 8 | "bots[0].commandLists[0].commands[0].description": "جولة للتعرّف على الميزات الأساسية", 9 | "bots[0].commandLists[0].commands[1].title": "اسأل خبيراً", 10 | "bots[0].commandLists[0].commands[1].description": "التواصل مع خبير", 11 | "bots[0].commandLists[0].commands[2].title": "مشاركة ملاحظات", 12 | "bots[0].commandLists[0].commands[2].description": "إرسال ملاحظات" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Manifest/EndUser/color.png -------------------------------------------------------------------------------- /Manifest/EndUser/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Personalabteilungssupport", 4 | "description.short": "Freundlicher Bot für HR-Support, beantwortet Fragen und verbindet mit Experten.", 5 | "description.full": "Ein freundlicher Bot für Fragen & Antworten. Wenn er keine Antwort finden kann, wird er anbieten, Sie mit einem Experten aus der Personalabteilung zu verbinden.", 6 | "staticTabs[0].name": "Personalabteilungssupport", 7 | "bots[0].commandLists[0].commands[0].title": "Einen Rundgang machen", 8 | "bots[0].commandLists[0].commands[0].description": "Rundgang durch Schlüsselfunktionen", 9 | "bots[0].commandLists[0].commands[1].title": "Einen Experten fragen", 10 | "bots[0].commandLists[0].commands[1].description": "Mit einem Experten verbinden", 11 | "bots[0].commandLists[0].commands[2].title": "Feedback teilen", 12 | "bots[0].commandLists[0].commands[2].description": "Feedback senden" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "HR Support", 4 | "description.short": "A friendly HR Support bot that answers questions and connects you to experts.", 5 | "description.full": "A friendly Q&A bot. If it can't find an answer, it'll offer to put you in touch with an expert from human resources.", 6 | "staticTabs[0].name": "HR Support", 7 | "bots[0].commandLists[0].commands[0].title": "Take a tour", 8 | "bots[0].commandLists[0].commands[0].description": "Tour of key features", 9 | "bots[0].commandLists[0].commands[1].title": "Ask an expert", 10 | "bots[0].commandLists[0].commands[1].description": "Connect with an expert", 11 | "bots[0].commandLists[0].commands[2].title": "Share feedback", 12 | "bots[0].commandLists[0].commands[2].description": "Send feedback" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Soporte de RR. HH.", 4 | "description.short": "Un bot de RR. HH. que responde preguntas y le conecta con expertos.", 5 | "description.full": "Un simpático bot de preguntas y respuestas. Si no encuentra una respuesta, le ofrecerá ponerse en contacto con un experto de recursos humanos.", 6 | "staticTabs[0].name": "Soporte de RR. HH.", 7 | "bots[0].commandLists[0].commands[0].title": "Visita guiada", 8 | "bots[0].commandLists[0].commands[0].description": "Paseo por las características clave", 9 | "bots[0].commandLists[0].commands[1].title": "Preguntar a un experto", 10 | "bots[0].commandLists[0].commands[1].description": "Conectar con un experto", 11 | "bots[0].commandLists[0].commands[2].title": "Compartir comentarios", 12 | "bots[0].commandLists[0].commands[2].description": "Enviar comentarios" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Support RH", 4 | "description.short": "Réponses et rencontre d’experts à l’aide d’un bot de support RH amical.", 5 | "description.full": "Un aimable robot de questions-réponses. S'il ne trouve pas de réponse, il vous propose de vous mettre en contact avec un expert des ressources humaines.", 6 | "staticTabs[0].name": "Support RH", 7 | "bots[0].commandLists[0].commands[0].title": "Faites un tour", 8 | "bots[0].commandLists[0].commands[0].description": "Visite guidée des principales fonctionnalités", 9 | "bots[0].commandLists[0].commands[1].title": "Poser une question à un expert", 10 | "bots[0].commandLists[0].commands[1].description": "Contacter un expert", 11 | "bots[0].commandLists[0].commands[2].title": "Partager des commentaires", 12 | "bots[0].commandLists[0].commands[2].description": "Envoyer des commentaires" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/he.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "תמיכת HR", 4 | "description.short": "תמיכת HR ידידותית שעונה על שאלות נפוצות ומקשרת אותך למומחים.", 5 | "description.full": "בוט ידידותי שעונה לשאלות. אם הוא לא מוצא תשובה, הוא יציע לקשר אותך למומחה ממשאבי אנוש.", 6 | "staticTabs[0].name": "תמיכת HR", 7 | "bots[0].commandLists[0].commands[0].title": "צא לסיור", 8 | "bots[0].commandLists[0].commands[0].description": "סיבוב היכרות של תכונות מפתח", 9 | "bots[0].commandLists[0].commands[1].title": "שאל מומחה", 10 | "bots[0].commandLists[0].commands[1].description": "קשר למומחה", 11 | "bots[0].commandLists[0].commands[2].title": "שתף משוב", 12 | "bots[0].commandLists[0].commands[2].description": "שלח משוב" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "人事サポート", 4 | "description.short": "質問に答えて専門家に接続する、わりやすい人事サポートです。", 5 | "description.full": "わかりやすい Q&A のボットです。回答が見つからない場合は、人事部の専門家と連絡を取ることができます。", 6 | "staticTabs[0].name": "人事サポート", 7 | "bots[0].commandLists[0].commands[0].title": "ツアーを開始", 8 | "bots[0].commandLists[0].commands[0].description": "主な機能のツアー", 9 | "bots[0].commandLists[0].commands[1].title": "専門家に質問する", 10 | "bots[0].commandLists[0].commands[1].description": "エキスパートにつなげる", 11 | "bots[0].commandLists[0].commands[2].title": "フィードバックを共有", 12 | "bots[0].commandLists[0].commands[2].description": "フィードバックを送信" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/ko.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "HR 지원", 4 | "description.short": "질문에 답변하고 전문가에게 연결하는 친절한 HR 지원 봇입니다.", 5 | "description.full": "친절한 Q&A 봇. 답변을 찾을 수 없는 경우 인사 관리 전문가에게 문의할 수 있습니다.", 6 | "staticTabs[0].name": "HR 지원", 7 | "bots[0].commandLists[0].commands[0].title": "둘러보기", 8 | "bots[0].commandLists[0].commands[0].description": "주요 기능 둘러보기", 9 | "bots[0].commandLists[0].commands[1].title": "전문가에게 문의", 10 | "bots[0].commandLists[0].commands[1].description": "전문가와 연결", 11 | "bots[0].commandLists[0].commands[2].title": "피드백 공유", 12 | "bots[0].commandLists[0].commands[2].description": "피드백 보내기" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "manifestVersion": "1.5", 4 | "version": "1.0.0", 5 | "id": "f7a5bc14-7d70-48cd-a9a4-7e62e9811043", 6 | "packageName": "com.microsoft.teams.hrsupport", 7 | "developer": { 8 | "name": "<>", 9 | "websiteUrl": "<>", 10 | "privacyUrl": "<>", 11 | "termsOfUseUrl": "<>" 12 | }, 13 | "localizationInfo": { 14 | "defaultLanguageTag": "en", 15 | "additionalLanguages": [ 16 | { 17 | "languageTag": "en", 18 | "file": "en.json" 19 | }, 20 | { 21 | "languageTag": "de", 22 | "file": "de.json" 23 | }, 24 | { 25 | "languageTag": "fr", 26 | "file": "fr.json" 27 | }, 28 | { 29 | "languageTag": "ar", 30 | "file": "ar.json" 31 | }, 32 | { 33 | "languageTag": "ja", 34 | "file": "ja.json" 35 | }, 36 | { 37 | "languageTag": "es", 38 | "file": "es.json" 39 | }, 40 | { 41 | "languageTag": "he", 42 | "file": "he.json" 43 | }, 44 | { 45 | "languageTag": "ko", 46 | "file": "ko.json" 47 | }, 48 | { 49 | "languageTag": "pt-BR", 50 | "file": "pt-BR.json" 51 | }, 52 | { 53 | "languageTag": "ru", 54 | "file": "ru.json" 55 | }, 56 | { 57 | "languageTag": "zh-CN", 58 | "file": "zh-CN.json" 59 | }, 60 | { 61 | "languageTag": "zh-TW", 62 | "file": "zh-TW.json" 63 | } 64 | ] 65 | }, 66 | "icons": { 67 | "color": "color.png", 68 | "outline": "outline.png" 69 | }, 70 | "name": { 71 | "short": "HR Support" 72 | }, 73 | "description": { 74 | "short": "A friendly HR Support bot that answers questions and connects you to experts.", 75 | "full": "A friendly Q&A bot. If it can't find an answer, it'll offer to put you in touch with an expert from human resources." 76 | }, 77 | "accentColor": "#64A2CC", 78 | "bots": [ 79 | { 80 | "botId": "<>", 81 | "scopes": [ 82 | "personal", 83 | "team" 84 | ], 85 | "commandLists": [ 86 | { 87 | "scopes": [ 88 | "personal" 89 | ], 90 | "commands": [ 91 | { 92 | "title": "Take a tour", 93 | "description": "Tour of key features" 94 | }, 95 | { 96 | "title": "Ask an expert", 97 | "description": "Connect with an expert" 98 | }, 99 | { 100 | "title": "Share feedback", 101 | "description": "Send feedback" 102 | } 103 | ] 104 | } 105 | ], 106 | "supportsFiles": false, 107 | "isNotificationOnly": false 108 | } 109 | ], 110 | "staticTabs": [ 111 | { 112 | "entityId": "HR Support", 113 | "name": "HR Support", 114 | "contentUrl": "https://<>/help?theme={theme}&locale={locale}", 115 | "scopes": [ 116 | "personal" 117 | ] 118 | } 119 | ], 120 | "permissions": [ 121 | "identity", 122 | "messageTeamMembers" 123 | ], 124 | "validDomains": [ 125 | "<>" 126 | ] 127 | } 128 | -------------------------------------------------------------------------------- /Manifest/EndUser/outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Manifest/EndUser/outline.png -------------------------------------------------------------------------------- /Manifest/EndUser/pt-BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Suporte de RH", 4 | "description.short": "Bot amigável de Sup. de RH que responde perguntas e lhe conecta a especialistas.", 5 | "description.full": "Um bot amigável de Perguntas e Respostas. Se não conseguir encontrar uma resposta, oferecerá para colcoar você em contato com um especialista de recursos humanos.", 6 | "staticTabs[0].name": "Suporte a RH", 7 | "bots[0].commandLists[0].commands[0].title": "Faça um tour", 8 | "bots[0].commandLists[0].commands[0].description": "Tour pelos principais recursos", 9 | "bots[0].commandLists[0].commands[1].title": "Pergunte a um especialista", 10 | "bots[0].commandLists[0].commands[1].description": "Conecte-se com um especialista", 11 | "bots[0].commandLists[0].commands[2].title": "Compartilhar comentários", 12 | "bots[0].commandLists[0].commands[2].description": "Enviar comentários" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Служба поддержки отдела кадров", 4 | "description.short": "Бот поддержки отдела кадров, отвечающий на вопросы и связывающий с экспертами.", 5 | "description.full": "Дружелюбный бот вопросов и ответов. Если он не может найти ответ, то пытается связать вас с экспертом из отдела кадров.", 6 | "staticTabs[0].name": "Поддержка отдела кадров", 7 | "bots[0].commandLists[0].commands[0].title": "Обзор", 8 | "bots[0].commandLists[0].commands[0].description": "Обзор основных функций", 9 | "bots[0].commandLists[0].commands[1].title": "Вопрос эксперту", 10 | "bots[0].commandLists[0].commands[1].description": "Связаться с экспертом", 11 | "bots[0].commandLists[0].commands[2].title": "Оставить отзыв", 12 | "bots[0].commandLists[0].commands[2].description": "Отправить отзыв" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/zh-CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "人力资源支持", 4 | "description.short": "友好的人力资源支持机器人将解答问题和帮你联系专家。", 5 | "description.full": "友好的问答机器人。如果无法找到答案,它将帮你与人力资源专家取得联系。", 6 | "staticTabs[0].name": "人力资源支持", 7 | "bots[0].commandLists[0].commands[0].title": "浏览", 8 | "bots[0].commandLists[0].commands[0].description": "主要功能导览", 9 | "bots[0].commandLists[0].commands[1].title": "咨询专家", 10 | "bots[0].commandLists[0].commands[1].description": "与专家联系", 11 | "bots[0].commandLists[0].commands[2].title": "分享反馈", 12 | "bots[0].commandLists[0].commands[2].description": "发送反馈" 13 | } -------------------------------------------------------------------------------- /Manifest/EndUser/zh-TW.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "人力資源支援", 4 | "description.short": "友善的人力資源支援 Bot,能回答問題並讓您與專家聯繫。", 5 | "description.full": "友善的問與答 Bot。如果找不到解答,它將會讓您與人力資源專家聯繫。", 6 | "staticTabs[0].name": "人力資源支援", 7 | "bots[0].commandLists[0].commands[0].title": "導覽", 8 | "bots[0].commandLists[0].commands[0].description": "主要功能導覽", 9 | "bots[0].commandLists[0].commands[1].title": "詢問專家", 10 | "bots[0].commandLists[0].commands[1].description": "與專家聯繫", 11 | "bots[0].commandLists[0].commands[2].title": "分享意見反映", 12 | "bots[0].commandLists[0].commands[2].description": "傳送意見反應" 13 | } -------------------------------------------------------------------------------- /Manifest/SME/ar.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "دعم القوى البشرية - فريق خبراء", 4 | "description.short": "روبوت سهل الاستخدام لدعم الموارد البشرية، يجيب عن الأسئلة ويوصّلك بالخبراء.", 5 | "description.full": "روبوت س&ج سهل الاستخدام. إذا لم يتمكن من العثور على إجالة، فسوف يعرض عليك الاتصال بخبير من قسم الموارد البشرية.", 6 | "staticTabs[0].name": "دعم الموارد البشرية", 7 | "bots[0].commandLists[0].commands[0].title": "القيام بجولة", 8 | "bots[0].commandLists[0].commands[0].description": "جولة للتعرّف على الميزات الأساسية", 9 | "bots[0].commandLists[0].commands[1].title": "اسأل خبيراً", 10 | "bots[0].commandLists[0].commands[1].description": "التواصل مع خبير", 11 | "bots[0].commandLists[0].commands[2].title": "مشاركة ملاحظات", 12 | "bots[0].commandLists[0].commands[2].description": "إرسال ملاحظات", 13 | "composeExtensions[0].commands[0].title": "العناصر الأخيرة", 14 | "composeExtensions[0].commands[0].description": "بحث في الطلبات الأخيرة", 15 | "composeExtensions[0].commands[0].parameters[0].title": "بحث", 16 | "composeExtensions[0].commands[1].title": "غير معيّن", 17 | "composeExtensions[0].commands[1].description": "بحث في الطلبات غير المعينة بعد إلى خبير", 18 | "composeExtensions[0].commands[1].parameters[0].title": "بحث", 19 | "composeExtensions[0].commands[2].title": "معيّن", 20 | "composeExtensions[0].commands[2].description": "بحث في الطلبات المعيّنة إلى خبير", 21 | "composeExtensions[0].commands[2].parameters[0].title": "بحث" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/color.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Manifest/SME/color.png -------------------------------------------------------------------------------- /Manifest/SME/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Personalsupport (Expertenteam)", 4 | "description.short": "Freundlicher Bot für HR-Support, beantwortet Fragen und verbindet mit Experten.", 5 | "description.full": "Ein freundlicher Bot für Fragen & Antworten. Wenn er keine Antwort finden kann, wird er anbieten, Sie mit einem Experten aus der Personalabteilung zu verbinden.", 6 | "staticTabs[0].name": "Personalabteilungssupport", 7 | "bots[0].commandLists[0].commands[0].title": "Einen Rundgang machen", 8 | "bots[0].commandLists[0].commands[0].description": "Rundgang durch Schlüsselfunktionen", 9 | "bots[0].commandLists[0].commands[1].title": "Einen Experten fragen", 10 | "bots[0].commandLists[0].commands[1].description": "Mit einem Experten verbinden", 11 | "bots[0].commandLists[0].commands[2].title": "Feedback teilen", 12 | "bots[0].commandLists[0].commands[2].description": "Feedback senden", 13 | "composeExtensions[0].commands[0].title": "Zuletzt verwendet", 14 | "composeExtensions[0].commands[0].description": "Aktuelle Anforderung durchsuchen", 15 | "composeExtensions[0].commands[0].parameters[0].title": "Suchen", 16 | "composeExtensions[0].commands[1].title": "Nicht zugewiesen", 17 | "composeExtensions[0].commands[1].description": "Nicht zugewiesene Suchanforderungen suchen, die noch nicht einem Experten zugewiesen sind", 18 | "composeExtensions[0].commands[1].parameters[0].title": "Suchen", 19 | "composeExtensions[0].commands[2].title": "Zugewiesen", 20 | "composeExtensions[0].commands[2].description": "Einem Experten zugewiesene Suchanforderungen", 21 | "composeExtensions[0].commands[2].parameters[0].title": "Suchen" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "HR Support (Experts Team)", 4 | "description.short": "A friendly HR Support bot that answers questions and connects you to experts.", 5 | "description.full": "A friendly Q&A bot. If it can't find an answer, it'll offer to put you in touch with an expert from human resources.", 6 | "staticTabs[0].name": "HR Support", 7 | "bots[0].commandLists[0].commands[0].title": "Take a tour", 8 | "bots[0].commandLists[0].commands[0].description": "Tour of key features", 9 | "bots[0].commandLists[0].commands[1].title": "Ask an expert", 10 | "bots[0].commandLists[0].commands[1].description": "Connect with an expert", 11 | "bots[0].commandLists[0].commands[2].title": "Share feedback", 12 | "bots[0].commandLists[0].commands[2].description": "Send feedback", 13 | "composeExtensions[0].commands[0].title": "Recent", 14 | "composeExtensions[0].commands[0].description": "Search recent requests", 15 | "composeExtensions[0].commands[0].parameters[0].title": "Search", 16 | "composeExtensions[0].commands[1].title": "Unassigned", 17 | "composeExtensions[0].commands[1].description": "Search unassigned requests not yet assigned to an expert", 18 | "composeExtensions[0].commands[1].parameters[0].title": "Search", 19 | "composeExtensions[0].commands[2].title": "Assigned", 20 | "composeExtensions[0].commands[2].description": "Search requests assigned to an expert", 21 | "composeExtensions[0].commands[2].parameters[0].title": "Search" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Soporte RR. HH. (eq. expertos)", 4 | "description.short": "Un bot de RR. HH. que responde preguntas y le conecta con expertos.", 5 | "description.full": "Un simpático bot de preguntas y respuestas. Si no encuentra una respuesta, le ofrecerá ponerse en contacto con un experto de recursos humanos.", 6 | "staticTabs[0].name": "Soporte de RR. HH.", 7 | "bots[0].commandLists[0].commands[0].title": "Visita guiada", 8 | "bots[0].commandLists[0].commands[0].description": "Paseo por las características clave", 9 | "bots[0].commandLists[0].commands[1].title": "Preguntar a un experto", 10 | "bots[0].commandLists[0].commands[1].description": "Conectar con un experto", 11 | "bots[0].commandLists[0].commands[2].title": "Compartir comentarios", 12 | "bots[0].commandLists[0].commands[2].description": "Enviar comentarios", 13 | "composeExtensions[0].commands[0].title": "Recientes", 14 | "composeExtensions[0].commands[0].description": "Buscar solicitudes recientes", 15 | "composeExtensions[0].commands[0].parameters[0].title": "Buscar", 16 | "composeExtensions[0].commands[1].title": "Sin asignar", 17 | "composeExtensions[0].commands[1].description": "Buscar solicitudes sin asignar aún no asignadas a un experto", 18 | "composeExtensions[0].commands[1].parameters[0].title": "Buscar", 19 | "composeExtensions[0].commands[2].title": "Asignado", 20 | "composeExtensions[0].commands[2].description": "Buscar solicitudes asignadas a un experto", 21 | "composeExtensions[0].commands[2].parameters[0].title": "Buscar" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Support RH (équipe d'experts)", 4 | "description.short": "Réponses et rencontre d’experts à l’aide d’un bot de support RH amical.", 5 | "description.full": "Un aimable robot de questions-réponses. S'il ne trouve pas de réponse, il vous propose de vous mettre en contact avec un expert des ressources humaines.", 6 | "staticTabs[0].name": "Support RH", 7 | "bots[0].commandLists[0].commands[0].title": "Faites un tour", 8 | "bots[0].commandLists[0].commands[0].description": "Visite guidée des principales fonctionnalités", 9 | "bots[0].commandLists[0].commands[1].title": "Poser une question à un expert", 10 | "bots[0].commandLists[0].commands[1].description": "Contacter un expert", 11 | "bots[0].commandLists[0].commands[2].title": "Partager des commentaires", 12 | "bots[0].commandLists[0].commands[2].description": "Envoyer des commentaires", 13 | "composeExtensions[0].commands[0].title": "Récents", 14 | "composeExtensions[0].commands[0].description": "Rechercher dans les demandes récentes", 15 | "composeExtensions[0].commands[0].parameters[0].title": "Rechercher", 16 | "composeExtensions[0].commands[1].title": "Non affecté", 17 | "composeExtensions[0].commands[1].description": "Rechercher les demandes qui ne sont pas encore affectées à un expert", 18 | "composeExtensions[0].commands[1].parameters[0].title": "Rechercher", 19 | "composeExtensions[0].commands[2].title": "Attribué", 20 | "composeExtensions[0].commands[2].description": "Rechercher parmi les demandes affectées à un expert", 21 | "composeExtensions[0].commands[2].parameters[0].title": "Rechercher" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/he.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "תמיכת HR (צוות מומחים)", 4 | "description.short": "תמיכת HR ידידותית שעונה על שאלות נפוצות ומקשרת אותך למומחים.", 5 | "description.full": "בוט ידידותי שעונה לשאלות. אם הוא לא מוצא תשובה, הוא יציע לקשר אותך למומחה ממשאבי אנוש.", 6 | "staticTabs[0].name": "תמיכת HR", 7 | "bots[0].commandLists[0].commands[0].title": "צא לסיור", 8 | "bots[0].commandLists[0].commands[0].description": "סיבוב היכרות של תכונות מפתח", 9 | "bots[0].commandLists[0].commands[1].title": "שאל מומחה", 10 | "bots[0].commandLists[0].commands[1].description": "קשר למומחה", 11 | "bots[0].commandLists[0].commands[2].title": "שתף משוב", 12 | "bots[0].commandLists[0].commands[2].description": "שלח משוב", 13 | "composeExtensions[0].commands[0].title": "מהזמן האחרון", 14 | "composeExtensions[0].commands[0].description": "חפש בקשות מהזמן האחרון", 15 | "composeExtensions[0].commands[0].parameters[0].title": "חפש", 16 | "composeExtensions[0].commands[1].title": "לא הוקצה", 17 | "composeExtensions[0].commands[1].description": "חפש בקשות שלא הוקצו עדיין לא הוקצו למומחים", 18 | "composeExtensions[0].commands[1].parameters[0].title": "חפש", 19 | "composeExtensions[0].commands[2].title": "הוקצה", 20 | "composeExtensions[0].commands[2].description": "חפש בקשות שהוקצו למומחה", 21 | "composeExtensions[0].commands[2].parameters[0].title": "חפש" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/ja.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "人事サポート (専門家チーム)", 4 | "description.short": "質問に答えて専門家に接続する、わりやすい人事サポートです。", 5 | "description.full": "わかりやすい Q&A のボットです。回答が見つからない場合は、人事部の専門家と連絡を取ることができます。", 6 | "staticTabs[0].name": "人事サポート", 7 | "bots[0].commandLists[0].commands[0].title": "ツアーを開始", 8 | "bots[0].commandLists[0].commands[0].description": "主な機能のツアー", 9 | "bots[0].commandLists[0].commands[1].title": "専門家に質問する", 10 | "bots[0].commandLists[0].commands[1].description": "エキスパートにつなげる", 11 | "bots[0].commandLists[0].commands[2].title": "フィードバックを共有", 12 | "bots[0].commandLists[0].commands[2].description": "フィードバックを送信", 13 | "composeExtensions[0].commands[0].title": "最近", 14 | "composeExtensions[0].commands[0].description": "最近のリクエストを検索する", 15 | "composeExtensions[0].commands[0].parameters[0].title": "検索", 16 | "composeExtensions[0].commands[1].title": "未割り当て", 17 | "composeExtensions[0].commands[1].description": "エキスパートにまだ割り当てられていない未割り当ての要求を検索", 18 | "composeExtensions[0].commands[1].parameters[0].title": "検索", 19 | "composeExtensions[0].commands[2].title": "割り当て済み", 20 | "composeExtensions[0].commands[2].description": "エキスパートに割り当てられた要求を検索", 21 | "composeExtensions[0].commands[2].parameters[0].title": "検索" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/ko.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "HR 지원(전문가 팀)", 4 | "description.short": "질문에 답변하고 전문가에게 연결하는 친절한 HR 지원 봇입니다.", 5 | "description.full": "친절한 Q&A 봇. 답변을 찾을 수 없는 경우 인사 관리 전문가에게 문의할 수 있습니다.", 6 | "staticTabs[0].name": "HR 지원", 7 | "bots[0].commandLists[0].commands[0].title": "둘러보기", 8 | "bots[0].commandLists[0].commands[0].description": "주요 기능 둘러보기", 9 | "bots[0].commandLists[0].commands[1].title": "전문가에게 문의", 10 | "bots[0].commandLists[0].commands[1].description": "전문가와 연결", 11 | "bots[0].commandLists[0].commands[2].title": "피드백 공유", 12 | "bots[0].commandLists[0].commands[2].description": "피드백 보내기", 13 | "composeExtensions[0].commands[0].title": "최근", 14 | "composeExtensions[0].commands[0].description": "최근 요청 검색", 15 | "composeExtensions[0].commands[0].parameters[0].title": "검색", 16 | "composeExtensions[0].commands[1].title": "할당 해제됨", 17 | "composeExtensions[0].commands[1].description": "검색되지 않은 요청이 전문가에 아직 할당되지 않았습니다.", 18 | "composeExtensions[0].commands[1].parameters[0].title": "검색", 19 | "composeExtensions[0].commands[2].title": "할당됨", 20 | "composeExtensions[0].commands[2].description": "전문가에게 할당된 검색 요청", 21 | "composeExtensions[0].commands[2].parameters[0].title": "검색" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "manifestVersion": "1.5", 4 | "version": "1.0.0", 5 | "id": "db78fc48-4a08-42fd-9bd9-59fa50d4b2d3", 6 | "packageName": "com.microsoft.teams.hrsupport.experts", 7 | "developer": { 8 | "name": "<>", 9 | "websiteUrl": "<>", 10 | "privacyUrl": "<>", 11 | "termsOfUseUrl": "<>" 12 | }, 13 | "localizationInfo": { 14 | "defaultLanguageTag": "en", 15 | "additionalLanguages": [ 16 | { 17 | "languageTag": "en", 18 | "file": "en.json" 19 | }, 20 | { 21 | "languageTag": "de", 22 | "file": "de.json" 23 | }, 24 | { 25 | "languageTag": "fr", 26 | "file": "fr.json" 27 | }, 28 | { 29 | "languageTag": "ar", 30 | "file": "ar.json" 31 | }, 32 | { 33 | "languageTag": "ja", 34 | "file": "ja.json" 35 | }, 36 | { 37 | "languageTag": "es", 38 | "file": "es.json" 39 | }, 40 | { 41 | "languageTag": "he", 42 | "file": "he.json" 43 | }, 44 | { 45 | "languageTag": "ko", 46 | "file": "ko.json" 47 | }, 48 | { 49 | "languageTag": "pt-BR", 50 | "file": "pt-BR.json" 51 | }, 52 | { 53 | "languageTag": "ru", 54 | "file": "ru.json" 55 | }, 56 | { 57 | "languageTag": "zh-CN", 58 | "file": "zh-CN.json" 59 | }, 60 | { 61 | "languageTag": "zh-TW", 62 | "file": "zh-TW.json" 63 | } 64 | ] 65 | }, 66 | "icons": { 67 | "color": "color.png", 68 | "outline": "outline.png" 69 | }, 70 | "name": { 71 | "short": "HR Support (Experts Team)" 72 | }, 73 | "description": { 74 | "short": "A friendly HR Support bot that answers questions and connects you to experts.", 75 | "full": "A friendly Q&A bot. If it can't find an answer, it'll offer to put you in touch with an expert from human resources." 76 | }, 77 | "accentColor": "#64A2CC", 78 | "bots": [ 79 | { 80 | "botId": "<>", 81 | "scopes": [ 82 | "personal", 83 | "team" 84 | ], 85 | "commandLists": [ 86 | { 87 | "scopes": [ 88 | "personal" 89 | ], 90 | "commands": [ 91 | { 92 | "title": "Take a tour", 93 | "description": "Tour of key features" 94 | }, 95 | { 96 | "title": "Ask an expert", 97 | "description": "Connect with an expert" 98 | }, 99 | { 100 | "title": "Share feedback", 101 | "description": "Send feedback" 102 | } 103 | ] 104 | } 105 | ], 106 | "supportsFiles": false, 107 | "isNotificationOnly": false 108 | } 109 | ], 110 | "staticTabs": [ 111 | { 112 | "entityId": "HR Support", 113 | "name": "HR Support", 114 | "contentUrl": "https://<>/help?theme={theme}&locale={locale}", 115 | "scopes": [ 116 | "personal" 117 | ] 118 | } 119 | ], 120 | "composeExtensions": [ 121 | { 122 | "botId": "<>", 123 | "canUpdateConfiguration": false, 124 | "commands": [ 125 | { 126 | "id": "recents", 127 | "type": "query", 128 | "title": "Recent", 129 | "description": "Search recent requests", 130 | "parameters": [ 131 | { 132 | "name": "searchText", 133 | "title": "Search" 134 | } 135 | ], 136 | "context": [ 137 | "compose", 138 | "commandBox" 139 | ], 140 | "initialRun": true 141 | }, 142 | { 143 | "id": "openrequests", 144 | "type": "query", 145 | "title": "Unassigned", 146 | "description": "Search unassigned requests not yet assigned to an expert", 147 | "parameters": [ 148 | { 149 | "name": "searchText", 150 | "title": "Search" 151 | } 152 | ], 153 | "context": [ 154 | "compose", 155 | "commandBox" 156 | ], 157 | "initialRun": true 158 | }, 159 | { 160 | "id": "assignedrequests", 161 | "type": "query", 162 | "title": "Assigned", 163 | "description": "Search requests assigned to an expert", 164 | "parameters": [ 165 | { 166 | "name": "searchText", 167 | "title": "Search" 168 | } 169 | ], 170 | "context": [ 171 | "compose", 172 | "commandBox" 173 | ], 174 | "initialRun": true 175 | } 176 | ] 177 | } 178 | ], 179 | "permissions": [ 180 | "identity", 181 | "messageTeamMembers" 182 | ], 183 | "validDomains": [ 184 | "<>" 185 | ] 186 | } 187 | -------------------------------------------------------------------------------- /Manifest/SME/outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Manifest/SME/outline.png -------------------------------------------------------------------------------- /Manifest/SME/pt-BR.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Sup. de RH (Equipe de Esp.)", 4 | "description.short": "Bot amigável de Sup. de RH que responde perguntas e lhe conecta a especialistas.", 5 | "description.full": "Um bot amigável de Perguntas e Respostas. Se não conseguir encontrar uma resposta, oferecerá para colcoar você em contato com um especialista de recursos humanos.", 6 | "staticTabs[0].name": "Suporte a RH", 7 | "bots[0].commandLists[0].commands[0].title": "Faça um tour", 8 | "bots[0].commandLists[0].commands[0].description": "Tour pelos principais recursos", 9 | "bots[0].commandLists[0].commands[1].title": "Pergunte a um especialista", 10 | "bots[0].commandLists[0].commands[1].description": "Conecte-se com um especialista", 11 | "bots[0].commandLists[0].commands[2].title": "Compartilhar comentários", 12 | "bots[0].commandLists[0].commands[2].description": "Enviar comentários", 13 | "composeExtensions[0].commands[0].title": "Recentes", 14 | "composeExtensions[0].commands[0].description": "Pesquisar solicitações recentes", 15 | "composeExtensions[0].commands[0].parameters[0].title": "Pesquisar", 16 | "composeExtensions[0].commands[1].title": "Não atribuída", 17 | "composeExtensions[0].commands[1].description": "Pesquisa solicitações não atribuídas que ainda não foram atribuídas a um especialista", 18 | "composeExtensions[0].commands[1].parameters[0].title": "Pesquisar", 19 | "composeExtensions[0].commands[2].title": "Atribuída", 20 | "composeExtensions[0].commands[2].description": "Solicitações de pesquisa atribuídas a um especialista", 21 | "composeExtensions[0].commands[2].parameters[0].title": "Pesquisar" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "Поддержка HR (эксперты)", 4 | "description.short": "Бот поддержки отдела кадров, отвечающий на вопросы и связывающий с экспертами.", 5 | "description.full": "Дружелюбный бот вопросов и ответов. Если он не может найти ответ, то пытается связать вас с экспертом из отдела кадров.", 6 | "staticTabs[0].name": "Поддержка отдела кадров", 7 | "bots[0].commandLists[0].commands[0].title": "Обзор", 8 | "bots[0].commandLists[0].commands[0].description": "Обзор основных функций", 9 | "bots[0].commandLists[0].commands[1].title": "Вопрос эксперту", 10 | "bots[0].commandLists[0].commands[1].description": "Связаться с экспертом", 11 | "bots[0].commandLists[0].commands[2].title": "Оставить отзыв", 12 | "bots[0].commandLists[0].commands[2].description": "Отправить отзыв", 13 | "composeExtensions[0].commands[0].title": "Последние", 14 | "composeExtensions[0].commands[0].description": "Поиск в последних запросах", 15 | "composeExtensions[0].commands[0].parameters[0].title": "Поиск", 16 | "composeExtensions[0].commands[1].title": "Не назначено", 17 | "composeExtensions[0].commands[1].description": "Поиск запросов, не назначенных эксперту", 18 | "composeExtensions[0].commands[1].parameters[0].title": "Поиск", 19 | "composeExtensions[0].commands[2].title": "Назначено", 20 | "composeExtensions[0].commands[2].description": "Поиск запросов, назначенных эксперту", 21 | "composeExtensions[0].commands[2].parameters[0].title": "Поиск" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/zh-CN.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "人力资源支持(专家团队)", 4 | "description.short": "友好的人力资源支持机器人将解答问题和帮你联系专家。", 5 | "description.full": "友好的问答机器人。如果无法找到答案,它将帮你与人力资源专家取得联系。", 6 | "staticTabs[0].name": "人力资源支持", 7 | "bots[0].commandLists[0].commands[0].title": "浏览", 8 | "bots[0].commandLists[0].commands[0].description": "主要功能导览", 9 | "bots[0].commandLists[0].commands[1].title": "咨询专家", 10 | "bots[0].commandLists[0].commands[1].description": "与专家联系", 11 | "bots[0].commandLists[0].commands[2].title": "分享反馈", 12 | "bots[0].commandLists[0].commands[2].description": "发送反馈", 13 | "composeExtensions[0].commands[0].title": "最近", 14 | "composeExtensions[0].commands[0].description": "搜索最近的请求", 15 | "composeExtensions[0].commands[0].parameters[0].title": "搜索", 16 | "composeExtensions[0].commands[1].title": "未分配", 17 | "composeExtensions[0].commands[1].description": "搜索尚未分配给专家的未分配请求", 18 | "composeExtensions[0].commands[1].parameters[0].title": "搜索", 19 | "composeExtensions[0].commands[2].title": "已分配", 20 | "composeExtensions[0].commands[2].description": "已分配给专家的搜索请求", 21 | "composeExtensions[0].commands[2].parameters[0].title": "搜索" 22 | } -------------------------------------------------------------------------------- /Manifest/SME/zh-TW.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json", 3 | "name.short": "人力資源支援 (專家團隊)", 4 | "description.short": "友善的人力資源支援 Bot,能回答問題並讓您與專家聯繫。", 5 | "description.full": "友善的 Q&A bot。如果找不到解答,它將會讓您與人力資源專家聯繫。", 6 | "staticTabs[0].name": "人力資源支援", 7 | "bots[0].commandLists[0].commands[0].title": "導覽", 8 | "bots[0].commandLists[0].commands[0].description": "主要功能導覽", 9 | "bots[0].commandLists[0].commands[1].title": "詢問專家", 10 | "bots[0].commandLists[0].commands[1].description": "與專家聯繫", 11 | "bots[0].commandLists[0].commands[2].title": "分享意見反映", 12 | "bots[0].commandLists[0].commands[2].description": "傳送意見反應", 13 | "composeExtensions[0].commands[0].title": "最近", 14 | "composeExtensions[0].commands[0].description": "搜尋最近的要求", 15 | "composeExtensions[0].commands[0].parameters[0].title": "搜尋", 16 | "composeExtensions[0].commands[1].title": "未指派", 17 | "composeExtensions[0].commands[1].description": "搜尋尚未指派給專家的未指派要求", 18 | "composeExtensions[0].commands[1].parameters[0].title": "搜尋", 19 | "composeExtensions[0].commands[2].title": "已指派", 20 | "composeExtensions[0].commands[2].description": "搜尋已指派給專家的要求", 21 | "composeExtensions[0].commands[2].parameters[0].title": "搜尋" 22 | } -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /Source/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1629:Documentation text should end with a period", Justification = "Convention")] -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Constants.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common 6 | { 7 | /// 8 | /// constants. 9 | /// 10 | public static class Constants 11 | { 12 | /// 13 | /// TeamTour - text that triggers team tour action. 14 | /// 15 | public const string TeamTour = "team tour"; 16 | 17 | /// 18 | /// TakeAtour - text that triggers take a tour action for the user. 19 | /// 20 | public const string TakeATour = "take a tour"; 21 | 22 | /// 23 | /// AskAnExpert - text that renders the ask an expert card. 24 | /// 25 | public const string AskAnExpert = "ask an expert"; 26 | 27 | /// 28 | /// Text associated with ask an expert command. 29 | /// 30 | public const string AskAnExpertSubmitText = "QuestionForExpert"; 31 | 32 | /// 33 | /// Feedback - text that renders share feedback card. 34 | /// 35 | public const string ShareFeedback = "share feedback"; 36 | 37 | /// 38 | /// Text associated with share feedback command. 39 | /// 40 | public const string ShareFeedbackSubmitText = "ShareFeedback"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Exceptions/TicketValidationException.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Exceptions 6 | { 7 | using System; 8 | 9 | /// 10 | /// Represents an error in ticket validation. 11 | /// 12 | public class TicketValidationException : Exception 13 | { 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | public TicketValidationException() 18 | { 19 | } 20 | 21 | /// 22 | /// Initializes a new instance of the class. 23 | /// 24 | /// The message to capture. 25 | public TicketValidationException(string message) 26 | : base(message) 27 | { 28 | } 29 | 30 | /// 31 | /// Initializes a new instance of the class. 32 | /// 33 | /// The message to capture/throw. 34 | /// The inner exception. 35 | public TicketValidationException(string message, Exception inner) 36 | : base(message, inner) 37 | { 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Microsoft.Teams.Apps.AskHR.Common.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | Microsoft.Teams.Apps.AskHR.Common 6 | Microsoft.Teams.Apps.AskHR.Common 7 | 8 | 9 | 10 | bin\Microsoft.Teams.Apps.AskHR.Common.xml 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | all 24 | runtime; build; native; contentfiles; analyzers 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Models/ConfigurationEntity.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Models 6 | { 7 | using Microsoft.WindowsAzure.Storage.Table; 8 | using Newtonsoft.Json; 9 | 10 | /// 11 | /// Represents configuration entity used for storage and retrieval. 12 | /// 13 | public class ConfigurationEntity : TableEntity 14 | { 15 | /// 16 | /// Gets or sets data which will be stored in table storage 17 | /// 18 | [JsonProperty("Data")] 19 | public string Data { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Models/ConfigurationEntityTypes.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Models 6 | { 7 | /// 8 | /// Configuration entity type names 9 | /// 10 | public class ConfigurationEntityTypes 11 | { 12 | /// 13 | /// Team entity 14 | /// 15 | public const string TeamId = "TeamId"; 16 | 17 | /// 18 | /// Knowledge base entity 19 | /// 20 | public const string KnowledgeBaseId = "KnowledgeBaseId"; 21 | 22 | /// 23 | /// Welcome message entity 24 | /// 25 | public const string WelcomeMessageText = "WelcomeMessageText"; 26 | 27 | /// 28 | /// Help tab text entity 29 | /// 30 | public const string HelpTabText = "HelpTabText"; 31 | 32 | /// 33 | /// QnaMaker endpoint key entity 34 | /// 35 | public const string QnAMakerEndpointKey = "QnaMakerEndpointKey"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Models/HelpInfoEntity.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Models 6 | { 7 | using Microsoft.WindowsAzure.Storage.Table; 8 | 9 | /// 10 | /// Model Class to take data from azure table storage 11 | /// 12 | public class HelpInfoEntity : TableEntity 13 | { 14 | /// 15 | /// Gets or sets Title 16 | /// 17 | public string Title { get; set; } 18 | 19 | /// 20 | /// Gets or sets description 21 | /// 22 | public string Description { get; set; } 23 | 24 | /// 25 | /// Gets or sets ImageUrl 26 | /// 27 | public string ImageUrl { get; set; } 28 | 29 | /// 30 | /// Gets or sets RedirectUrl 31 | /// 32 | public string RedirectUrl { get; set; } 33 | 34 | /// 35 | /// Gets or sets Tags. 36 | /// 37 | public string Tags { get; set; } 38 | 39 | /// 40 | /// Gets or sets number of TagsMatched. 41 | /// 42 | public int TagsMatched { get; set; } 43 | 44 | /// 45 | /// Gets or sets order Id to be used in View 46 | /// 47 | public int TileOrder { get; set; } 48 | 49 | /// 50 | /// Gets or sets a value indicating whether the operation is save or edit 51 | /// 52 | public bool IsEdit { get; set; } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Models/ImageFileUrl.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Models 6 | { 7 | /// 8 | /// Holds Image model. 9 | /// 10 | public class ImageFileUrl 11 | { 12 | /// 13 | /// Gets or sets ImageName. 14 | /// 15 | public string ImageName { get; set; } 16 | 17 | /// 18 | /// Gets or sets Image Blob Url. 19 | /// 20 | public string ImageBlobUrl { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Models/TicketState.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Models 6 | { 7 | /// 8 | /// Represents the current status of a ticket 9 | /// 10 | public enum TicketState 11 | { 12 | /// 13 | /// Represents an active ticket 14 | /// 15 | Open = 0, 16 | 17 | /// 18 | /// Represents a ticket that requires no further action 19 | /// 20 | Closed = 1, 21 | 22 | /// 23 | /// Sentinel value 24 | /// 25 | MaxValue = Closed, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Models/UsefulLinksTableModel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Models 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel.DataAnnotations; 10 | using System.Text; 11 | using Microsoft.WindowsAzure.Storage.Table; 12 | 13 | /// 14 | /// Useful Links Model 15 | /// 16 | public class UsefulLinksTableModel : TableEntity 17 | { 18 | /// 19 | /// Gets or sets Title text box to be used in View 20 | /// 21 | public string Title { get; set; } 22 | 23 | /// 24 | /// Gets or sets Description text box to be used in View 25 | /// 26 | public string Description { get; set; } 27 | 28 | /// 29 | /// Gets or sets Url text box to be used in View 30 | /// 31 | public string RedirectUrl { get; set; } 32 | 33 | /// 34 | /// Gets or sets Image to be used in View 35 | /// 36 | public string ImageUrl { get; set; } 37 | 38 | /// 39 | /// Gets or sets Image to be used in View 40 | /// 41 | public string Tags { get; set; } 42 | 43 | /// 44 | /// Gets or sets order Id to be used in View 45 | /// 46 | public int TileOrder { get; set; } 47 | 48 | /// 49 | /// Gets or sets a value indicating whether the operation is save or edit 50 | /// 51 | public bool IsEdit { get; set; } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Providers/ConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | namespace Microsoft.Teams.Apps.AskHR.Common.Providers 5 | { 6 | using System; 7 | using System.Net; 8 | using System.Threading.Tasks; 9 | 10 | using Microsoft.Teams.Apps.AskHR.Common.Models; 11 | using Microsoft.WindowsAzure.Storage; 12 | using Microsoft.WindowsAzure.Storage.Table; 13 | 14 | /// 15 | /// ConfigurationProvider which will help in fetching and storing information in storage table. 16 | /// 17 | public class ConfigurationProvider : IConfigurationProvider 18 | { 19 | private const string PartitionKey = "ConfigurationInfo"; 20 | 21 | private readonly Lazy initializeTask; 22 | private CloudTable configurationCloudTable; 23 | 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// 27 | /// connection string of storage provided by DI 28 | public ConfigurationProvider(string connectionString) 29 | { 30 | this.initializeTask = new Lazy(() => this.InitializeAsync(connectionString)); 31 | } 32 | 33 | /// 34 | public async Task SaveOrUpdateEntityAsync(string updatedData, string entityType) 35 | { 36 | try 37 | { 38 | var entity = new ConfigurationEntity() 39 | { 40 | PartitionKey = PartitionKey, 41 | RowKey = entityType, 42 | Data = updatedData, 43 | }; 44 | var result = await this.StoreOrUpdateEntityAsync(entity); 45 | return result.HttpStatusCode == (int)HttpStatusCode.NoContent; 46 | } 47 | catch 48 | { 49 | return false; 50 | } 51 | } 52 | 53 | /// 54 | public async Task GetSavedEntityDetailAsync(string entityType) 55 | { 56 | try 57 | { 58 | await this.EnsureInitializedAsync(); 59 | 60 | var searchOperation = TableOperation.Retrieve(PartitionKey, entityType); 61 | TableResult searchResult = await this.configurationCloudTable.ExecuteAsync(searchOperation); 62 | var result = (ConfigurationEntity)searchResult.Result; 63 | 64 | return result?.Data ?? string.Empty; 65 | } 66 | catch 67 | { 68 | return string.Empty; 69 | } 70 | } 71 | 72 | /// 73 | /// Store or update configuration entity in table storage 74 | /// 75 | /// entity. 76 | /// that represents configuration entity is saved or updated. 77 | private async Task StoreOrUpdateEntityAsync(ConfigurationEntity entity) 78 | { 79 | await this.EnsureInitializedAsync(); 80 | 81 | TableOperation addOrUpdateOperation = TableOperation.InsertOrReplace(entity); 82 | 83 | return await this.configurationCloudTable.ExecuteAsync(addOrUpdateOperation); 84 | } 85 | 86 | /// 87 | /// Create teams table if it doesnt exists 88 | /// 89 | /// storage account connection string 90 | /// representing the asynchronous operation task which represents table is created if its not existing. 91 | private async Task InitializeAsync(string connectionString) 92 | { 93 | CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); 94 | CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient(); 95 | this.configurationCloudTable = cloudTableClient.GetTableReference(StorageInfo.ConfigurationTableName); 96 | await this.configurationCloudTable.CreateIfNotExistsAsync(); 97 | } 98 | 99 | /// 100 | /// Initialization of InitializeAsync method which will help in creating table 101 | /// 102 | /// Task 103 | private async Task EnsureInitializedAsync() 104 | { 105 | await this.initializeTask.Value; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Providers/IConfigurationProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Providers 6 | { 7 | using System.Threading.Tasks; 8 | using Microsoft.Teams.Apps.AskHR.Common.Models; 9 | 10 | /// 11 | /// Interface of Configuration provider 12 | /// 13 | public interface IConfigurationProvider 14 | { 15 | /// 16 | /// Save or update entity based on entity type. 17 | /// 18 | /// updatedData received from view page 19 | /// entityType received from view based on which appropriate row will replaced or inserted in table storage 20 | /// boolean value that represents if updated data is saved or updated successfully or not. 21 | Task SaveOrUpdateEntityAsync(string updatedData, string entityType); 22 | 23 | /// 24 | /// Get already saved entity detail from storage table 25 | /// 26 | /// entityType received from view based on which appropriate row data will be fetched 27 | /// Already saved entity detail 28 | Task GetSavedEntityDetailAsync(string entityType); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Providers/IHelpDataProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Providers 6 | { 7 | using System.Collections.Generic; 8 | using System.Threading.Tasks; 9 | 10 | using Microsoft.Teams.Apps.AskHR.Common.Models; 11 | 12 | /// 13 | /// IHelpDataProvider interface to provide methods to manage Help tile information from storages 14 | /// 15 | public interface IHelpDataProvider 16 | { 17 | /// 18 | /// Get already saved entity detail from storage table for Tags 19 | /// 20 | /// Already saved entity detail 21 | Task> GetHelpTilesAsync(); 22 | 23 | /// 24 | /// Upload or update the files to azure blob storage from provided file path 25 | /// 26 | /// folder path 27 | /// success/failure boolean 28 | Task StoreOrUpdateFileAsync(string imageDirectoryPath); 29 | 30 | /// 31 | /// Get image files from azure blob storage 32 | /// 33 | /// list of image name and blob path 34 | Task> GetImageFilesAsync(); 35 | 36 | /// 37 | /// Insert or update helpInfo table entity 38 | /// 39 | /// HelpInfo 40 | /// true if entity saved successfully 41 | Task SaveOrUpdateEntityAsync(HelpInfoEntity helpInfoEntity); 42 | 43 | /// 44 | /// Delete help info entity 45 | /// 46 | /// row key of storage 47 | /// true if row deleted successfully 48 | Task DeleteEntityAsync(string rowKey); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Providers/ITicketsProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Providers 6 | { 7 | using System.Threading.Tasks; 8 | using Microsoft.Teams.Apps.AskHR.Common.Models; 9 | 10 | /// 11 | /// Interface of Tickets provider 12 | /// 13 | public interface ITicketsProvider 14 | { 15 | /// 16 | /// Save or update ticket entity. 17 | /// 18 | /// Ticket received from bot based on which appropriate row will replaced or inserted in table storage 19 | /// that resolves successfully if the data was saved successfully. 20 | Task SaveOrUpdateTicketAsync(TicketEntity ticket); 21 | 22 | /// 23 | /// Get already saved entity detail from storage table 24 | /// 25 | /// ticket id received from bot based on which appropriate row data will be fetched 26 | /// Already saved entity detail 27 | Task GetTicketAsync(string ticketId); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Providers/StorageInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Providers 6 | { 7 | /// 8 | /// References to storage table. 9 | /// 10 | public class StorageInfo 11 | { 12 | /// 13 | /// Table name where configuration app details will be saved 14 | /// 15 | public const string ConfigurationTableName = "ConfigurationInfo"; 16 | 17 | /// 18 | /// Table name where SME activity details from bot will be saved 19 | /// 20 | public const string TicketTableName = "Tickets"; 21 | 22 | /// 23 | /// Table name where Tiles details from configuration app will be saved 24 | /// 25 | public const string HelpInfoTableName = "HelpInfo"; 26 | 27 | /// 28 | /// Blob name where Tiles images from configuration app will be saved. 29 | /// 30 | public const string HelpImageBlobContainer = "tileimages"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Common/Providers/TicketsProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Common.Providers 6 | { 7 | using System; 8 | using System.Threading.Tasks; 9 | using Microsoft.Teams.Apps.AskHR.Common.Exceptions; 10 | using Microsoft.Teams.Apps.AskHR.Common.Models; 11 | using Microsoft.WindowsAzure.Storage; 12 | using Microsoft.WindowsAzure.Storage.Table; 13 | 14 | /// 15 | /// TicketProviders which will help in fetching and storing information in storage table. 16 | /// 17 | public class TicketsProvider : ITicketsProvider 18 | { 19 | private const string PartitionKey = "TicketInfo"; 20 | 21 | private readonly Lazy initializeTask; 22 | private CloudTable ticketCloudTable; 23 | 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// 27 | /// connection string of storage provided by DI 28 | public TicketsProvider(string connectionString) 29 | { 30 | this.initializeTask = new Lazy(() => this.InitializeAsync(connectionString)); 31 | } 32 | 33 | /// 34 | /// Store or update ticket entity in table storage 35 | /// 36 | /// ticketEntity. 37 | /// that represents configuration entity is saved or updated. 38 | public Task SaveOrUpdateTicketAsync(TicketEntity ticket) 39 | { 40 | ticket.PartitionKey = PartitionKey; 41 | ticket.RowKey = ticket.TicketId; 42 | 43 | if (ticket.Status > (int)TicketState.MaxValue) 44 | { 45 | throw new TicketValidationException($"The ticket status ({ticket.Status}) is not valid."); 46 | } 47 | 48 | return this.StoreOrUpdateTicketEntityAsync(ticket); 49 | } 50 | 51 | /// 52 | public async Task GetTicketAsync(string ticketId) 53 | { 54 | await this.EnsureInitializedAsync(); 55 | 56 | var searchOperation = TableOperation.Retrieve(PartitionKey, ticketId); 57 | var searchResult = await this.ticketCloudTable.ExecuteAsync(searchOperation); 58 | 59 | return (TicketEntity)searchResult.Result; 60 | } 61 | 62 | /// 63 | /// Store or update ticket entity in table storage 64 | /// 65 | /// entity. 66 | /// that represents configuration entity is saved or updated. 67 | private async Task StoreOrUpdateTicketEntityAsync(TicketEntity entity) 68 | { 69 | await this.EnsureInitializedAsync(); 70 | TableOperation addOrUpdateOperation = TableOperation.InsertOrReplace(entity); 71 | return await this.ticketCloudTable.ExecuteAsync(addOrUpdateOperation); 72 | } 73 | 74 | /// 75 | /// Create tickets table if it doesnt exists 76 | /// 77 | /// storage account connection string 78 | /// representing the asynchronous operation task which represents table is created if its not existing. 79 | private async Task InitializeAsync(string connectionString) 80 | { 81 | CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString); 82 | CloudTableClient cloudTableClient = storageAccount.CreateCloudTableClient(); 83 | this.ticketCloudTable = cloudTableClient.GetTableReference(StorageInfo.TicketTableName); 84 | 85 | await this.ticketCloudTable.CreateIfNotExistsAsync(); 86 | } 87 | 88 | /// 89 | /// Initialization of InitializeAsync method which will help in creating table 90 | /// 91 | /// Task 92 | private async Task EnsureInitializedAsync() 93 | { 94 | await this.initializeTask.Value; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore folder populated by libman 2 | lib/ -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/App_Start/AutofacConfig.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration 6 | { 7 | using System.Configuration; 8 | using System.Management; 9 | using System.Reflection; 10 | using System.Runtime.InteropServices; 11 | using System.Web.Mvc; 12 | using Autofac; 13 | using Autofac.Integration.Mvc; 14 | using Microsoft.ApplicationInsights; 15 | using Microsoft.ApplicationInsights.Channel; 16 | using Microsoft.ApplicationInsights.Extensibility; 17 | using Microsoft.Azure.CognitiveServices.Knowledge.QnAMaker; 18 | using Microsoft.Teams.Apps.AskHR.Common.Providers; 19 | using ConfigurationManager = System.Configuration.ConfigurationManager; 20 | 21 | /// 22 | /// Autofac configuration 23 | /// 24 | public class AutofacConfig 25 | { 26 | /// 27 | /// Register Autofac dependencies 28 | /// 29 | /// Autofac container 30 | public static IContainer RegisterDependencies() 31 | { 32 | var builder = new ContainerBuilder(); 33 | builder.RegisterControllers(Assembly.GetExecutingAssembly()); 34 | 35 | var storageConnectionString = ConfigurationManager.AppSettings["StorageConnectionString"]; 36 | 37 | builder.Register(c => new ConfigurationProvider(storageConnectionString)) 38 | .As() 39 | .SingleInstance(); 40 | 41 | var qnaMakerClient = new QnAMakerClient( 42 | new ApiKeyServiceClientCredentials( 43 | ConfigurationManager.AppSettings["QnAMakerSubscriptionKey"])) 44 | { Endpoint = StripRouteFromQnAMakerEndpoint(ConfigurationManager.AppSettings["QnAMakerApiEndpointUrl"]) }; 45 | 46 | builder.Register(c => qnaMakerClient) 47 | .As() 48 | .SingleInstance(); 49 | 50 | builder.Register(c => new HelpDataProvider(storageConnectionString)) 51 | .As() 52 | .SingleInstance(); 53 | 54 | var telemetryClient = new TelemetryClient() 55 | { 56 | InstrumentationKey = ConfigurationManager.AppSettings["APPINSIGHTS_INSTRUMENTATIONKEY"] 57 | }; 58 | 59 | builder.Register(c => telemetryClient) 60 | .As() 61 | .SingleInstance(); 62 | 63 | var container = builder.Build(); 64 | DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); 65 | 66 | return container; 67 | } 68 | 69 | // Strip the route suffix from the endpoint 70 | private static string StripRouteFromQnAMakerEndpoint(string endpoint) 71 | { 72 | const string apiRoute = "/qnamaker/v4.0"; 73 | 74 | if (endpoint.EndsWith(apiRoute, System.StringComparison.OrdinalIgnoreCase)) 75 | { 76 | endpoint = endpoint.Substring(0, endpoint.Length - apiRoute.Length); 77 | } 78 | 79 | return endpoint; 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration 6 | { 7 | using System.Web.Optimization; 8 | 9 | /// 10 | /// Bundle config for Task Module app. 11 | /// 12 | public class BundleConfig 13 | { 14 | /// 15 | /// Register the bundles 16 | /// 17 | /// Collection of bundles 18 | public static void RegisterBundles(BundleCollection bundles) 19 | { 20 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 21 | "~/lib/jquery/jquery.min.js", 22 | "~/Scripts/js/jquery.dataTables.min.js")); 23 | 24 | bundles.Add(new ScriptBundle("~/bundles/customjquery").Include( 25 | "~/Scripts/Index.js", 26 | "~/Scripts/webConfigurator.js")); 27 | 28 | bundles.Add(new ScriptBundle("~/bundles/resizejquery").Include( 29 | "~/Scripts/jquery-ui.min.js")); 30 | 31 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 32 | "~/lib/jquery-validate/jquery.validate.min.js", 33 | "~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js")); 34 | 35 | bundles.Add(new ScriptBundle("~/bundles/jqueryajaxunobtrusive").Include( 36 | "~/lib/jquery-ajax-unobtrusive/dist/jquery.unobtrusive-ajax.min.js")); 37 | 38 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 39 | // ready for production, use the build tool at https://modernizr.com to pick only the tests you need. 40 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 41 | "~/lib/modernizr/modernizr.min.js")); 42 | 43 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 44 | "~/lib/bootstrap/dist/js/bootstrap.min.js")); 45 | 46 | bundles.Add(new StyleBundle("~/Content/css").Include( 47 | "~/lib/bootstrap/dist/css/bootstrap.min.css", 48 | "~/Content/customizableStyle.css", 49 | "~/Content/spinner.css", 50 | "~/Scripts/css/jquery.dataTables.min.css", 51 | "~/Content/font-awesome.min.css", 52 | "~/Scripts/jquery-ui.min.css")); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration 6 | { 7 | using System.Web.Mvc; 8 | 9 | /// 10 | /// Filter config for Task Module app. 11 | /// 12 | public class FilterConfig 13 | { 14 | /// 15 | /// Register Global Filters 16 | /// 17 | /// Collection of global filters. 18 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 19 | { 20 | filters.Add(new ErrorHandler.AiHandleErrorAttribute()); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration 6 | { 7 | using System.Web.Mvc; 8 | using System.Web.Routing; 9 | 10 | /// 11 | /// Router Config 12 | /// 13 | public class RouteConfig 14 | { 15 | /// 16 | /// Register Routes 17 | /// 18 | /// Routes collection 19 | public static void RegisterRoutes(RouteCollection routes) 20 | { 21 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 22 | 23 | routes.MapRoute( 24 | name: "Default", 25 | url: "{controller}/{action}/{id}", 26 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/App_Start/Startup.Auth.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration 6 | { 7 | using System; 8 | using System.Configuration; 9 | using System.IdentityModel.Claims; 10 | using System.Linq; 11 | using System.Threading.Tasks; 12 | using System.Web.Helpers; 13 | using global::Owin; 14 | using Microsoft.IdentityModel.Protocols.OpenIdConnect; 15 | using Microsoft.Owin.Security; 16 | using Microsoft.Owin.Security.Cookies; 17 | using Microsoft.Owin.Security.OpenIdConnect; 18 | 19 | /// 20 | /// Startup file 21 | /// 22 | public partial class Startup 23 | { 24 | private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"]; 25 | private static string aadInstance = EnsureTrailingSlash(ConfigurationManager.AppSettings["ida:AADInstance"]); 26 | private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"]; 27 | private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"]; 28 | private static string authority = aadInstance + tenantId; 29 | 30 | /// 31 | /// Configure Auth 32 | /// 33 | /// App builder 34 | /// DI container 35 | public void ConfigureAuth(IAppBuilder app, Autofac.IContainer container) 36 | { 37 | app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); 38 | 39 | app.UseCookieAuthentication(new CookieAuthenticationOptions()); 40 | 41 | var validUpns = ConfigurationManager.AppSettings["ValidUpns"] 42 | ?.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries) 43 | ?.Select(s => s.Trim()) 44 | ?? new string[0]; 45 | 46 | app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions("AppLogin") 47 | { 48 | ClientId = clientId, 49 | Authority = authority, 50 | PostLogoutRedirectUri = postLogoutRedirectUri, 51 | Notifications = new OpenIdConnectAuthenticationNotifications() 52 | { 53 | SecurityTokenValidated = (context) => 54 | { 55 | var upn = context?.AuthenticationTicket?.Identity?.Claims? 56 | .FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; 57 | 58 | if (upn == null 59 | || !validUpns.Contains(upn, StringComparer.OrdinalIgnoreCase)) 60 | { 61 | context.OwinContext.Response.Redirect("/Account/InvalidUser"); 62 | context.HandleResponse(); 63 | } 64 | 65 | return Task.CompletedTask; 66 | }, 67 | RedirectToIdentityProvider = (context) => 68 | { 69 | if (context.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication) 70 | { 71 | context.ProtocolMessage.Prompt = OpenIdConnectPrompt.Login; 72 | } 73 | 74 | return Task.CompletedTask; 75 | }, 76 | }, 77 | }); 78 | AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Upn; 79 | } 80 | 81 | private static string EnsureTrailingSlash(string value) 82 | { 83 | if (value == null) 84 | { 85 | value = string.Empty; 86 | } 87 | 88 | if (!value.EndsWith("/", StringComparison.Ordinal)) 89 | { 90 | return value + "/"; 91 | } 92 | 93 | return value; 94 | } 95 | } 96 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Connected Services/Application Insights/ConnectedService.json: -------------------------------------------------------------------------------- 1 | { 2 | "ProviderId": "Microsoft.ApplicationInsights.ConnectedService.ConnectedServiceProvider", 3 | "Version": "8.14.20131.1", 4 | "GettingStartedDocument": { 5 | "Uri": "https://go.microsoft.com/fwlink/?LinkID=613413" 6 | } 7 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Content/customizableStyle.css: -------------------------------------------------------------------------------- 1 | .font-bold { 2 | font-weight: 700; 3 | } 4 | 5 | .error-message { 6 | color: red; 7 | margin-top: 10px; 8 | } 9 | 10 | .success-message { 11 | color: green; 12 | margin-top: 10px; 13 | } 14 | 15 | .storageStatusIcon-success { 16 | color: green; 17 | margin-top: 9px; 18 | } 19 | 20 | .storageStatusIcon-failure { 21 | color: red; 22 | margin-top: 9px; 23 | } 24 | 25 | .marginBetweenView { 26 | margin-top: 10px; 27 | margin-bottom: 10px; 28 | } 29 | 30 | .contentMargin { 31 | padding-top: 100px; 32 | } 33 | 34 | .mandatoryField { 35 | color: red; 36 | } 37 | 38 | .col-lg-1 { 39 | padding-right: 0px !important; 40 | padding-left: 0px !important; 41 | width: 4% !important; 42 | } 43 | 44 | .col-lg-3 { 45 | padding-right: 0px !important; 46 | padding-left: 0px !important; 47 | width: 22% !important; 48 | } 49 | 50 | .col-lg-5 { 51 | padding-right: 0px !important; 52 | padding-left: 0px !important; 53 | } 54 | 55 | .col-lg-offset-3 { 56 | margin-left: 22% !important; 57 | } 58 | 59 | label { 60 | margin-top: 9px !important; 61 | } 62 | 63 | .infoSignMargin { 64 | padding-left: 10px; 65 | } 66 | 67 | .helpTabTextNote { 68 | margin-right: 15px; 69 | } 70 | 71 | .addRow { 72 | margin-top: 15px; 73 | } 74 | 75 | .gridButtons { 76 | width: 70px; 77 | } 78 | 79 | .gridButtonsAdd { 80 | width: 65px; 81 | } 82 | 83 | .tdStyle { 84 | word-break: break-all; 85 | } 86 | 87 | .redirectUri { 88 | width: 20%; 89 | } 90 | 91 | .btnColWidth { 92 | width: 15% !important; 93 | text-align: center; 94 | } 95 | 96 | .mandatory { 97 | border-color: red !important; 98 | } 99 | 100 | .titleWidth { 101 | width: 68px !important; 102 | } 103 | 104 | .descWidth { 105 | width: 90px !important; 106 | } 107 | 108 | .tagsWidth { 109 | width: 68px !important; 110 | } 111 | 112 | .imageDDLStyle { 113 | margin-right: 20px; 114 | width: 26%; 115 | float: left; 116 | height: 26px; 117 | margin-bottom: 2px; 118 | } 119 | 120 | .liStyle { 121 | width: 100%; 122 | height: 32px; 123 | -webkit-transition: all 1s ease; 124 | -moz-transition: all 1s ease; 125 | -ms-transition: all 1s ease; 126 | transition: all 1s ease; 127 | } 128 | 129 | .liStyle:hover { 130 | box-shadow: 0px 0px 1px 1px #99ccff; 131 | transform: scale(1.5); 132 | } 133 | 134 | .liAnchorStyle { 135 | width: 100%; 136 | } 137 | 138 | .liAnchorImageStyle { 139 | width: 20%; 140 | } 141 | 142 | .liAnchorImageTitleStyle { 143 | width: 60%; 144 | } 145 | 146 | .arrowBtnSpan { 147 | width: 9%; 148 | float: right; 149 | } 150 | 151 | .toggleToEditButton { 152 | width: 40% !important; 153 | } 154 | 155 | input { 156 | width: 100% !important; 157 | } 158 | 159 | .imageDDL { 160 | width: 23%; 161 | } 162 | 163 | .ddlButtonStyle { 164 | width: 100% !important; 165 | } 166 | 167 | /* Images Dropdown list styling */ 168 | body { 169 | padding: 40px; 170 | } 171 | 172 | .dropdown-toggle, .dropdown-menu { 173 | width: 100%; 174 | } 175 | 176 | .btn-group img { 177 | margin-right: 10px 178 | } 179 | 180 | .imageBtnDiv { 181 | width: 100%; 182 | } 183 | 184 | .dropdown-toggle { 185 | padding-right: 50px 186 | } 187 | 188 | .dropdown-toggle .glyphicon { 189 | margin-left: 20px; 190 | margin-right: -40px 191 | } 192 | 193 | .dropdown-menu > li > a:hover { 194 | background: #f1f9fd; 195 | /*cursor:pointer;*/ 196 | } 197 | /* $search-blue */ 198 | .dropdown-header { 199 | background: #ccc; 200 | font-size: 14px; 201 | font-weight: 700; 202 | padding-top: 5px; 203 | padding-bottom: 5px; 204 | margin-top: 10px; 205 | margin-bottom: 5px 206 | } 207 | 208 | .tableGridSection { 209 | border-radius: 4px; 210 | } 211 | 212 | .noDataMessage { 213 | font-size: 18px; 214 | margin-left: 25%; 215 | font-weight: bold; 216 | } 217 | 218 | .redirectUri a { 219 | overflow: hidden; 220 | text-overflow: ellipsis; 221 | display: -webkit-box; 222 | -webkit-line-clamp: 2; 223 | -webkit-box-orient: vertical; 224 | } 225 | 226 | textarea.form-control { 227 | resize: vertical; 228 | } 229 | 230 | .formToSubmit div.form-group div.col-lg-1 { 231 | text-align: center; 232 | } 233 | 234 | #helpTileTable textarea { 235 | resize: vertical; 236 | width: 97%; 237 | } 238 | 239 | .tableGridHeader { 240 | font-weight: bold; 241 | font-size: 17px; 242 | margin-bottom: 3px; 243 | text-align: left; 244 | letter-spacing: 1px; 245 | } 246 | 247 | #WelcomeMessage { 248 | width: 303.141px !important; 249 | min-height: 78px; 250 | } 251 | 252 | .ui-wrapper { 253 | width: 303.141px !important; 254 | } 255 | 256 | .ui-icon { 257 | width: 11px !important; 258 | } 259 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Content/spinner.css: -------------------------------------------------------------------------------- 1 | @-webkit-keyframes translate-small { 2 | to { 3 | -webkit-transform: translate3d(0, -144rem, 0); 4 | transform: translate3d(0, -144rem, 0); 5 | } 6 | } 7 | 8 | @keyframes translate-small { 9 | to { 10 | -webkit-transform: translate3d(0, -144rem, 0); 11 | transform: translate3d(0, -144rem, 0); 12 | } 13 | } 14 | 15 | @-webkit-keyframes translate-medium { 16 | to { 17 | -webkit-transform: translate3d(0, -216rem, 0); 18 | transform: translate3d(0, -216rem, 0); 19 | } 20 | } 21 | 22 | @keyframes translate-medium { 23 | to { 24 | -webkit-transform: translate3d(0, -216rem, 0); 25 | transform: translate3d(0, -216rem, 0); 26 | } 27 | } 28 | 29 | @-webkit-keyframes translate-large { 30 | to { 31 | -webkit-transform: translate3d(0, -432rem, 0); 32 | transform: translate3d(0, -432rem, 0); 33 | } 34 | } 35 | 36 | @keyframes translate-large { 37 | to { 38 | -webkit-transform: translate3d(0, -432rem, 0); 39 | transform: translate3d(0, -432rem, 0); 40 | } 41 | } 42 | 43 | @-webkit-keyframes fade-spinner-in { 44 | to { 45 | opacity: 1; 46 | } 47 | } 48 | 49 | @keyframes fade-spinner-in { 50 | to { 51 | opacity: 1; 52 | } 53 | } 54 | 55 | busy-animation { 56 | display: inline-block; 57 | } 58 | 59 | .ts-spinner-internal { 60 | overflow: hidden; 61 | } 62 | 63 | .ts-spinner-internal.size-1x { 64 | height: 2.4rem; 65 | width: 2.4rem; 66 | margin-top: 25%; 67 | } 68 | 69 | .ts-spinner-internal.size-1x .spinner-animate { 70 | width: 2.4rem; 71 | height: 146.4rem; 72 | -webkit-animation: 2s steps(60) both infinite translate-small; 73 | animation: 2s steps(60) both infinite translate-small; 74 | } 75 | 76 | .ts-spinner-internal.size-2x { 77 | height: 3.6rem; 78 | width: 3.6rem; 79 | margin: auto; 80 | margin-top: 25%; 81 | opacity: 1; 82 | } 83 | 84 | .ts-spinner-internal.size-2x .spinner-animate { 85 | width: 3.6rem; 86 | height: 219.6rem; 87 | -webkit-animation: 2s steps(60) both infinite translate-medium; 88 | animation: 2s steps(60) both infinite translate-medium; 89 | } 90 | 91 | .ts-spinner-internal.size-3x { 92 | height: 7.2rem; 93 | width: 7.2rem; 94 | margin-top: 25%; 95 | } 96 | 97 | .ts-spinner-internal.size-3x .spinner-animate { 98 | width: 7.2rem; 99 | height: 439.2rem; 100 | -webkit-animation: 2s steps(60) both infinite translate-large; 101 | animation: 2s steps(60) both infinite translate-large; 102 | } 103 | 104 | .ts-spinner-container { 105 | overflow: hidden; 106 | position: relative; 107 | } 108 | 109 | #spinner { 110 | position: absolute; 111 | background: #e9e9e9; 112 | opacity: 0.7; 113 | height: 100%; 114 | width: 100%; 115 | top: 0; 116 | bottom: 0; 117 | left: 0; 118 | right: 0; 119 | z-index: 9999; 120 | } 121 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration.Controllers 6 | { 7 | using System.Web; 8 | using System.Web.Mvc; 9 | using Microsoft.Owin.Security; 10 | using Microsoft.Owin.Security.Cookies; 11 | using Microsoft.Owin.Security.OpenIdConnect; 12 | 13 | /// 14 | /// Account Controller 15 | /// 16 | public class AccountController : Controller 17 | { 18 | /// 19 | /// sign in 20 | /// 21 | public void SignIn() 22 | { 23 | if (!this.Request.IsAuthenticated) 24 | { 25 | this.HttpContext.GetOwinContext().Authentication.Challenge( 26 | new AuthenticationProperties { RedirectUri = "/" }, 27 | new string[] { OpenIdConnectAuthenticationDefaults.AuthenticationType, "AppLogin" }); 28 | } 29 | } 30 | 31 | /// 32 | /// sign out 33 | /// 34 | public void SignOut() 35 | { 36 | string callbackUrl = this.Url.Action("SignOutCallback", "Account", routeValues: null, protocol: this.Request.Url.Scheme); 37 | 38 | this.HttpContext.GetOwinContext().Authentication.SignOut( 39 | new AuthenticationProperties { RedirectUri = callbackUrl }, new string[] { OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType, "AppLogin" }); 40 | } 41 | 42 | /// 43 | /// callback method 44 | /// 45 | /// returns view 46 | public ActionResult SignOutCallback() 47 | { 48 | if (this.Request.IsAuthenticated) 49 | { 50 | return this.RedirectToAction("Index", "Home"); 51 | } 52 | 53 | return this.View(); 54 | } 55 | 56 | /// 57 | /// Invalid User 58 | /// 59 | /// Action Result 60 | public ActionResult InvalidUser() 61 | { 62 | this.HttpContext.GetOwinContext().Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); 63 | return this.View(); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/ErrorHandler/AiHandleErrorAttribute.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration.ErrorHandler { using System; using System.Web.Mvc; using Microsoft.ApplicationInsights; 6 | /// 7 | /// Report unhandled errors to Application Insights 8 | /// 9 | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class AiHandleErrorAttribute : HandleErrorAttribute { /// 10 | public override void OnException(ExceptionContext filterContext) { if (filterContext != null && filterContext.HttpContext != null && filterContext.Exception != null) { 11 | // If customError is Off, then AI HTTPModule will report the exception 12 | if (filterContext.HttpContext.IsCustomErrorEnabled) { var ai = new TelemetryClient(); ai.TrackException(filterContext.Exception); } } base.OnException(filterContext); } } } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Microsoft.Teams.Apps.AskHR.Configuration.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Global.asax.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | namespace Microsoft.Teams.Apps.AskHR.Configuration 4 | { 5 | using Microsoft.Teams.Apps.AskHR.Common.Providers; 6 | using System.Configuration; 7 | 8 | /// 9 | /// Mvc Application 10 | /// 11 | public class MvcApplication : System.Web.HttpApplication 12 | { 13 | private IHelpDataProvider helpDataProvider; 14 | internal void Application_Start() 15 | { 16 | helpDataProvider = new HelpDataProvider(ConfigurationManager.AppSettings["StorageConnectionString"]); 17 | helpDataProvider.StoreOrUpdateFileAsync(System.Web.HttpContext.Current.Server.MapPath("./Images/")); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg1.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg10.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg2.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg3.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg4.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg5.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg6.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg7.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg8.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR.Configuration/Images/HelpImg9.jpg -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Models/HelpTabViewModel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | namespace Microsoft.Teams.Apps.AskHR.Configuration.Models 5 | { 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | /// 9 | /// Help tab view model 10 | /// 11 | public class HelpTabViewModel 12 | { 13 | /// 14 | /// Gets or sets help tab message text box to be used in View 15 | /// 16 | [Required(ErrorMessage = "Enter help tab text.")] 17 | [StringLength(maximumLength: 3000, ErrorMessage = "Help tab text should contain less than 3000 characters.", MinimumLength = 2)] 18 | [DataType(DataType.Text)] 19 | [Display(Name = "Help tab text")] 20 | public string HelpTabText { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Models/KnowledgeBaseViewModel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration.Models 6 | { 7 | using System.ComponentModel.DataAnnotations; 8 | using System.Web.Mvc; 9 | 10 | /// 11 | /// KnowledgeBase View Model 12 | /// 13 | public class KnowledgeBaseViewModel 14 | { 15 | /// 16 | /// Gets or sets knowledge base Id text box to be used in View 17 | /// 18 | [Required(ErrorMessage = "Enter knowledge base ID.")] 19 | [MinLength(1)] 20 | [DataType(DataType.Text)] 21 | [Display(Name = "Knowledge base ID")] 22 | [RegularExpression(@"(\S)+", ErrorMessage = "Enter knowledge base ID which should not contain any whitespace.")] 23 | [AllowHtml] 24 | public string KnowledgeBaseId { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Models/TeamViewModel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration.Models 6 | { 7 | using System.ComponentModel.DataAnnotations; 8 | using System.Web.Mvc; 9 | 10 | /// 11 | /// Team view model 12 | /// 13 | public class TeamViewModel 14 | { 15 | /// 16 | /// Gets or sets team Id textbox to be used in View 17 | /// 18 | [Required(ErrorMessage ="Enter team ID.")] 19 | [MinLength(1)] 20 | [DataType(DataType.Text)] 21 | [Display(Name ="Team ID")] 22 | [RegularExpression(@"(\S)+", ErrorMessage = "Enter team ID which should not contain any whitespace.")] 23 | [AllowHtml] 24 | public string TeamId { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Models/UsefulLinksViewModel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration.Models 6 | { 7 | using System.Collections.Generic; 8 | using Microsoft.Teams.Apps.AskHR.Common.Models; 9 | 10 | /// 11 | /// Holds UsefulLinks urls. 12 | /// 13 | public class UsefulLinksViewModel 14 | { 15 | /// 16 | /// Gets or sets listUsefulLinks 17 | /// 18 | public List HelpInfoTiles { get; set; } 19 | 20 | /// 21 | /// Gets or sets listImageUrl 22 | /// 23 | public List TileImageUrls { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Models/WelcomeMessageViewModel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Configuration.Models 6 | { 7 | using System.ComponentModel.DataAnnotations; 8 | using System.Web.Mvc; 9 | 10 | /// 11 | /// Welcome message view model 12 | /// 13 | public class WelcomeMessageViewModel 14 | { 15 | /// 16 | /// Gets or sets welcome message text box to be used in View 17 | /// 18 | [Required(ErrorMessage = "Enter a welcome message.")] 19 | [StringLength(maximumLength: 300, ErrorMessage = "Enter welcome message which should contain less than 300 characters.", MinimumLength = 2)] 20 | [DataType(DataType.Text)] 21 | [Display(Name = "Welcome message")] 22 | [AllowHtml] 23 | public string WelcomeMessage { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // 2 | 3 | using System.Reflection; 4 | using System.Runtime.InteropServices; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Microsoft.Teams.Apps.AskHR.Configuration")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("Microsoft.Teams.Apps.AskHR.Configuration")] 14 | [assembly: AssemblyCopyright("Copyright © 2019")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | [assembly: Guid("8bf98632-4946-44c5-8e57-4e29f4297775")] 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | // You can specify all the values or you can default the Revision and Build Numbers 34 | // by using the '*' as shown below: 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Startup.cs: -------------------------------------------------------------------------------- 1 | // 2 | namespace Microsoft.Teams.Apps.AskHR.Configuration 3 | { 4 | using System.Web.Mvc; 5 | using System.Web.Optimization; 6 | using System.Web.Routing; 7 | using global::Owin; 8 | 9 | /// 10 | /// Startup 11 | /// 12 | public partial class Startup 13 | { 14 | /// 15 | /// Configuration 16 | /// 17 | /// IAppBuilder app 18 | public void Configuration(IAppBuilder app) 19 | { 20 | AreaRegistration.RegisterAllAreas(); 21 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 22 | RouteConfig.RegisterRoutes(RouteTable.Routes); 23 | BundleConfig.RegisterBundles(BundleTable.Bundles); 24 | 25 | var container = AutofacConfig.RegisterDependencies(); 26 | this.ConfigureAuth(app, container); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Account/InvalidUser.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Invalid User"; 3 | } 4 |

@ViewBag.Title.

5 |

This user does not have the proper permissions for this action. Please sign in with a valid user credentials.

-------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Account/SignOutCallback.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Sign Out"; 3 | } 4 |

@ViewBag.Title.

5 |

You have successfully signed out.

-------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model Microsoft.Teams.Apps.AskHR.Configuration.Models.UsefulLinksViewModel 2 | @{ 3 | ViewBag.Title = "Configuration App"; 4 | } 5 |
6 | 9 |
10 |
11 | @Html.Partial("~/Views/Home/_Team.cshtml", new Microsoft.Teams.Apps.AskHR.Configuration.Models.TeamViewModel()) 12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | @Html.Partial("~/Views/Home/_KnowledgeBase.cshtml", new Microsoft.Teams.Apps.AskHR.Configuration.Models.KnowledgeBaseViewModel()) 20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | @Html.Partial("~/Views/Home/_WelcomeMessage.cshtml", new Microsoft.Teams.Apps.AskHR.Configuration.Models.WelcomeMessageViewModel()) 28 |
29 |
30 | @*
31 |
32 |
*@ 33 | @*
34 |
35 | @Html.Partial("~/Views/Home/_HelpTab.cshtml", new Microsoft.Teams.Apps.AskHR.Configuration.Models.HelpTabViewModel()) 36 |
37 |
*@ 38 |
39 |
40 |
41 |
42 |
43 | @Html.Partial("~/Views/Home/_UsefulLinksTablePartial.cshtml", Model) 44 |
45 |
46 |
47 | 48 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Home/_HelpTab.cshtml: -------------------------------------------------------------------------------- 1 | @model Microsoft.Teams.Apps.AskHR.Configuration.Models.HelpTabViewModel 2 | 3 | @using (Ajax.BeginForm("SaveHelpTabTextAsync", "Home", new AjaxOptions { HttpMethod = "POST", OnSuccess = "onSaveSuccess", OnFailure = "onSaveFailure" }, htmlAttributes: new { @class = "formToSubmit" })) 4 | { 5 |
6 |
7 | @Html.LabelFor(model => model.HelpTabText, htmlAttributes: new { @class = "font-bold" }) 8 | * 9 |
10 | (Please note that this text will be accessible to anyone having access to the URL of the tab) 11 |
12 |
13 |
14 | @Html.TextAreaFor(model => model.HelpTabText, htmlAttributes: new { @class = "form-control helpTabTextIdTextBox toggleTextBox", @placeholder = "Enter help tab text, up to 3000 characters. Markdown is supported." }) 15 | @Html.ValidationMessageFor(model => model.HelpTabText, "", htmlAttributes: new { @class = "error-message" }) 16 |
17 |
18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 |
26 |
27 |
28 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Home/_KnowledgeBase.cshtml: -------------------------------------------------------------------------------- 1 | @model Microsoft.Teams.Apps.AskHR.Configuration.Models.KnowledgeBaseViewModel 2 | 3 | @using (Ajax.BeginForm("ValidateAndSaveKnowledgeBaseIdAsync", "Home", new AjaxOptions { HttpMethod = "POST", OnSuccess = "onSaveSuccess", OnFailure = "onSaveFailure" }, htmlAttributes: new { @class = "formToSubmit" })) 4 | { 5 | @*@Html.AntiForgeryToken()*@ 6 |
7 |
8 | @Html.LabelFor(model => model.KnowledgeBaseId, htmlAttributes: new { @class = "font-bold" }) 9 | * 10 |
11 |
12 | @Html.TextBoxFor(model => model.KnowledgeBaseId, htmlAttributes: new { @class = "form-control knowledgeBaseIdTextBox toggleTextBox", @placeholder = "Enter knowledge base ID." }) 13 | @Html.ValidationMessageFor(model => model.KnowledgeBaseId, "", htmlAttributes: new { @class = "error-message" }) 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 |
22 |
23 |
24 |
25 |
26 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Home/_Team.cshtml: -------------------------------------------------------------------------------- 1 | @model Microsoft.Teams.Apps.AskHR.Configuration.Models.TeamViewModel 2 | 3 | @using (Ajax.BeginForm("ParseAndSaveTeamIdAsync", "Home", new AjaxOptions { HttpMethod = "POST", OnSuccess = "onSaveSuccess", OnFailure = "onSaveFailure" }, htmlAttributes: new { @class = "formToSubmit" })) 4 | { 5 | @*@Html.AntiForgeryToken()*@ 6 |
7 |
8 | @Html.LabelFor(model => model.TeamId, htmlAttributes: new { @class = "font-bold" }) 9 | * 10 |
11 |
12 | @Html.TextBoxFor(model => model.TeamId, htmlAttributes: new { @class = "form-control teamIdTextBox toggleTextBox", @placeholder = "Enter team ID." }) 13 | @Html.ValidationMessageFor(model => model.TeamId, "", htmlAttributes: new { @class = "error-message" }) 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 |
22 |
23 |
24 |
25 |
26 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Home/_WelcomeMessage.cshtml: -------------------------------------------------------------------------------- 1 | @model Microsoft.Teams.Apps.AskHR.Configuration.Models.WelcomeMessageViewModel 2 | 3 | @using (Ajax.BeginForm("SaveWelcomeMessageAsync", "Home", new AjaxOptions { HttpMethod = "POST", OnSuccess = "onSaveSuccess", OnFailure = "onSaveFailure" }, htmlAttributes: new { @class = "formToSubmit" })) 4 | { 5 | @*@Html.AntiForgeryToken()*@ 6 |
7 |
8 | @Html.LabelFor(model => model.WelcomeMessage, htmlAttributes: new { @class = "font-bold" }) 9 | * 10 |
11 |
12 | @Html.TextAreaFor(model => model.WelcomeMessage, htmlAttributes: new { @class = "form-control welcomeMessageIdTextBox toggleTextBox", @placeholder = "Enter welcome message less than 300 characters. Markdown is supported." }) 13 | @Html.ValidationMessageFor(model => model.WelcomeMessage, "", htmlAttributes: new { @class = "error-message" }) 14 |
15 |
16 | 17 |
18 |
19 | 20 | 21 |
22 |
23 |
24 |
25 |
26 | } 27 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = null; 3 | 4 | } 5 | 6 | 7 | 8 | 9 | Error 10 | 11 | 12 |
13 |

Error.

14 |

An error occurred while processing your request.

15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - Configuration App 7 | 8 | @Styles.Render("~/Content/css") 9 | @Scripts.Render("~/bundles/modernizr") 10 | @Scripts.Render("~/bundles/jquery") 11 | @Scripts.Render(" ~/bundles/customjquery") 12 | @Scripts.Render(" ~/bundles/resizejquery") 13 | 14 | 15 | 16 | 52 |
53 | @RenderBody() 54 |
55 |
56 | 57 | @Scripts.Render("~/bundles/jqueryval") 58 | @Scripts.Render("~/bundles/jqueryajaxunobtrusive") 59 | @Scripts.Render("~/bundles/bootstrap") 60 | @RenderSection("scripts", required: false) 61 | 72 | 73 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/libman.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "defaultProvider": "cdnjs", 4 | "libraries": [ 5 | { 6 | "library": "jquery@3.4.1", 7 | "destination": "lib/jquery/", 8 | "files": [ 9 | "jquery.min.js", 10 | "jquery.js", 11 | "jquery.min.map" 12 | ] 13 | }, 14 | { 15 | "provider": "cdnjs", 16 | "library": "modernizr@2.8.3", 17 | "destination": "lib/modernizr/", 18 | "files": [ 19 | "modernizr.min.js", 20 | "modernizr.js" 21 | ] 22 | }, 23 | { 24 | "provider": "unpkg", 25 | "library": "bootstrap@3.4.1", 26 | "destination": "lib/bootstrap/", 27 | "files": [ 28 | "dist/css/bootstrap-theme.css", 29 | "dist/css/bootstrap-theme.css.map", 30 | "dist/css/bootstrap-theme.min.css", 31 | "dist/css/bootstrap-theme.min.css.map", 32 | "dist/css/bootstrap.css", 33 | "dist/css/bootstrap.css.map", 34 | "dist/css/bootstrap.min.css", 35 | "dist/css/bootstrap.min.css.map", 36 | "dist/fonts/glyphicons-halflings-regular.eot", 37 | "dist/fonts/glyphicons-halflings-regular.svg", 38 | "dist/fonts/glyphicons-halflings-regular.ttf", 39 | "dist/fonts/glyphicons-halflings-regular.woff", 40 | "dist/fonts/glyphicons-halflings-regular.woff2", 41 | "dist/js/bootstrap.js", 42 | "dist/js/bootstrap.min.js" 43 | ] 44 | }, 45 | { 46 | "provider": "cdnjs", 47 | "library": "jquery-validation-unobtrusive@3.2.11", 48 | "destination": "lib/jquery-validation-unobtrusive/" 49 | }, 50 | { 51 | "provider": "cdnjs", 52 | "library": "jquery-validate@1.19.1", 53 | "destination": "lib/jquery-validate/", 54 | "files": [ 55 | "jquery.validate.min.js", 56 | "jquery.validate.js" 57 | ] 58 | }, 59 | { 60 | "provider": "unpkg", 61 | "library": "jquery-ajax-unobtrusive@3.2.6", 62 | "destination": "lib/jquery-ajax-unobtrusive/" 63 | }, 64 | { 65 | "library": "jqueryui@1.12.1", 66 | "destination": "Scripts/", 67 | "files": [ 68 | "jquery-ui.min.js", 69 | "jquery-ui.min.css" 70 | ] 71 | }, 72 | { 73 | "library": "datatables@1.10.19", 74 | "destination": "Scripts", 75 | "files": [ 76 | "js/jquery.dataTables.min.js", 77 | "css/jquery.dataTables.min.css" 78 | ] 79 | } 80 | ] 81 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.Configuration/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.28803.156 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Teams.Apps.AskHR.Configuration", "Microsoft.Teams.Apps.AskHR.Configuration\Microsoft.Teams.Apps.AskHR.Configuration.csproj", "{FB347EC9-3571-43D2-9D54-3C14EA9E47BF}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Teams.Apps.AskHR", "Microsoft.Teams.Apps.AskHR\Microsoft.Teams.Apps.AskHR.csproj", "{055149A6-01FF-4C2A-8CD5-DD0061A28CD8}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Teams.Apps.AskHR.Common", "Microsoft.Teams.Apps.AskHR.Common\Microsoft.Teams.Apps.AskHR.Common.csproj", "{DAF9540B-13CB-4875-A6E0-5997BDF2F73F}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {FB347EC9-3571-43D2-9D54-3C14EA9E47BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {FB347EC9-3571-43D2-9D54-3C14EA9E47BF}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {FB347EC9-3571-43D2-9D54-3C14EA9E47BF}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {FB347EC9-3571-43D2-9D54-3C14EA9E47BF}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {055149A6-01FF-4C2A-8CD5-DD0061A28CD8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {055149A6-01FF-4C2A-8CD5-DD0061A28CD8}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {055149A6-01FF-4C2A-8CD5-DD0061A28CD8}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {055149A6-01FF-4C2A-8CD5-DD0061A28CD8}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {DAF9540B-13CB-4875-A6E0-5997BDF2F73F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {DAF9540B-13CB-4875-A6E0-5997BDF2F73F}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {DAF9540B-13CB-4875-A6E0-5997BDF2F73F}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {DAF9540B-13CB-4875-A6E0-5997BDF2F73F}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {AE9A5450-534B-4417-9BE8-EE0C95657BD0} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-react" 4 | ], 5 | "plugins": [ 6 | [ 7 | "@babel/plugin-proposal-class-properties", 8 | { 9 | "loose": true 10 | } 11 | ] 12 | ] 13 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/.gitignore: -------------------------------------------------------------------------------- 1 | wwwroot/lib -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Bots/BotLocalizationCultureProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Bots 6 | { 7 | using System; 8 | using System.IO; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | using Microsoft.AspNetCore.Http; 13 | using Microsoft.AspNetCore.Localization; 14 | using Microsoft.Bot.Schema; 15 | using Newtonsoft.Json; 16 | using Newtonsoft.Json.Linq; 17 | 18 | /// 19 | /// This class is responsible for implementing the for Bot Activities 20 | /// received from BotFramework. 21 | /// 22 | public class BotLocalizationCultureProvider : IRequestCultureProvider 23 | { 24 | /// 25 | /// Get the culture of current request. 26 | /// 27 | /// The current HTTP request. 28 | /// A Task resolving to the culture info if found, null otherwise. 29 | #pragma warning disable UseAsyncSuffix // Interface method doesn't have Async suffix. 30 | public async Task DetermineProviderCultureResult(HttpContext httpContext) 31 | #pragma warning restore UseAsyncSuffix 32 | { 33 | if (httpContext?.Request?.Body?.CanRead != true) 34 | { 35 | return null; 36 | } 37 | 38 | string locale = string.Empty; 39 | var isBotFrameworkUserAgent = 40 | httpContext.Request.Headers["User-Agent"] 41 | .Any(userAgent => userAgent.Contains("Microsoft-BotFramework", StringComparison.OrdinalIgnoreCase)); 42 | 43 | if (!isBotFrameworkUserAgent) 44 | { 45 | locale = httpContext.Request.Headers["Accept-Language"].FirstOrDefault(); 46 | locale = locale?.Split(",")?.FirstOrDefault(); 47 | if (string.IsNullOrEmpty(locale)) 48 | { 49 | return null; 50 | } 51 | } 52 | 53 | try 54 | { 55 | if (isBotFrameworkUserAgent) 56 | { 57 | // Wrap the request stream so that we can rewind it back to the start for regular request processing. 58 | httpContext.Request.EnableBuffering(); 59 | 60 | // Read the request body, parse out the activity object, and set the parsed culture information. 61 | var streamReader = new StreamReader(httpContext.Request.Body, Encoding.UTF8, true, 1024, leaveOpen: true); 62 | using (var jsonReader = new JsonTextReader(streamReader)) 63 | { 64 | var obj = await JObject.LoadAsync(jsonReader); 65 | var activity = obj.ToObject(); 66 | 67 | var result = new ProviderCultureResult(activity.Locale); 68 | httpContext.Request.Body.Seek(0, SeekOrigin.Begin); 69 | return result; 70 | } 71 | } 72 | else 73 | { 74 | var result = new ProviderCultureResult(locale); 75 | return result; 76 | } 77 | } 78 | #pragma warning disable CA1031 // part of the middle ware pipeline, better to use default local then fail the request. 79 | catch (Exception) 80 | #pragma warning restore CA1031 81 | { 82 | return null; 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Cards/MessagingExtensionTicketsCard.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Cards 6 | { 7 | using System; 8 | using System.Collections.Generic; 9 | using AdaptiveCards; 10 | using Microsoft.Teams.Apps.AskHR.Common.Models; 11 | using Microsoft.Teams.Apps.AskHR.Properties; 12 | 13 | /// 14 | /// Implements messaging extension tickets card. 15 | /// 16 | public class MessagingExtensionTicketsCard : SmeTicketCard 17 | { 18 | /// 19 | /// Initializes a new instance of the class. 20 | /// 21 | /// The ticket model with the latest details. 22 | public MessagingExtensionTicketsCard(TicketEntity ticket) 23 | : base(ticket) 24 | { 25 | } 26 | 27 | /// 28 | protected override List BuildActions() 29 | { 30 | List actions = new List(); 31 | 32 | actions.Add(this.CreateChatWithUserAction()); 33 | 34 | if (!string.IsNullOrEmpty(this.Ticket.SmeThreadConversationId)) 35 | { 36 | actions.Add( 37 | new AdaptiveOpenUrlAction 38 | { 39 | Title = Resource.GoToOriginalThreadButtonText, 40 | Url = new Uri(CreateDeeplinkToThread(this.Ticket.SmeThreadConversationId)) 41 | }); 42 | } 43 | 44 | return actions; 45 | } 46 | 47 | /// 48 | /// Returns go to original thread uri which will help in opening the original conversation about the ticket 49 | /// 50 | /// The thread along with message Id stored in storage table. 51 | /// original thread uri. 52 | private static string CreateDeeplinkToThread(string threadConversationId) 53 | { 54 | string[] threadAndMessageId = threadConversationId.Split(";"); 55 | var threadId = threadAndMessageId[0]; 56 | var messageId = threadAndMessageId[1].Split("=")[1]; 57 | return $"https://teams.microsoft.com/l/message/{threadId}/{messageId}"; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Cards/ResponseCard.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Cards 6 | { 7 | using System.Collections.Generic; 8 | using System.Globalization; 9 | using AdaptiveCards; 10 | using Microsoft.Bot.Schema; 11 | using Microsoft.Teams.Apps.AskHR.Common; 12 | using Microsoft.Teams.Apps.AskHR.Models; 13 | using Microsoft.Teams.Apps.AskHR.Properties; 14 | 15 | /// 16 | /// This class process Response Card- Response by bot when user asks a question to bot. 17 | /// 18 | public static class ResponseCard 19 | { 20 | /// 21 | /// Construct the response card - when user asks a question to QnA Maker through bot. 22 | /// 23 | /// Knowledgebase question, from QnA Maker service. 24 | /// Knowledgebase answer, from QnA Maker service. 25 | /// Actual question asked by the user to the bot. 26 | /// Response card. 27 | public static Attachment GetCard(string question, string answer, string userQuestion) 28 | { 29 | var textAlignment = CultureInfo.CurrentCulture.TextInfo.IsRightToLeft ? AdaptiveHorizontalAlignment.Right : AdaptiveHorizontalAlignment.Left; 30 | 31 | AdaptiveCard responseCard = new AdaptiveCard("1.0") 32 | { 33 | Body = new List 34 | { 35 | new AdaptiveTextBlock 36 | { 37 | Weight = AdaptiveTextWeight.Bolder, 38 | Text = Resource.ResponseHeaderText, 39 | Wrap = true, 40 | HorizontalAlignment = textAlignment 41 | }, 42 | new AdaptiveTextBlock 43 | { 44 | Text = question, 45 | Wrap = true, 46 | HorizontalAlignment = textAlignment 47 | }, 48 | new AdaptiveTextBlock 49 | { 50 | Text = answer, 51 | Wrap = true, 52 | HorizontalAlignment = textAlignment 53 | } 54 | }, 55 | Actions = new List 56 | { 57 | new AdaptiveSubmitAction 58 | { 59 | Title = Resource.AskAnExpertButtonText, 60 | Data = new ResponseCardPayload 61 | { 62 | MsTeams = new CardAction 63 | { 64 | Type = ActionTypes.MessageBack, 65 | DisplayText = Resource.AskAnExpertDisplayText, 66 | Text = Constants.AskAnExpert, 67 | }, 68 | UserQuestion = userQuestion, 69 | KnowledgeBaseAnswer = answer, 70 | } 71 | }, 72 | new AdaptiveSubmitAction 73 | { 74 | Title = Resource.ShareFeedbackButtonText, 75 | Data = new ResponseCardPayload 76 | { 77 | MsTeams = new CardAction 78 | { 79 | Type = ActionTypes.MessageBack, 80 | DisplayText = Resource.ShareFeedbackDisplayText, 81 | Text = Constants.ShareFeedback, 82 | }, 83 | UserQuestion = userQuestion, 84 | KnowledgeBaseAnswer = answer, 85 | } 86 | } 87 | } 88 | }; 89 | 90 | return new Attachment 91 | { 92 | ContentType = AdaptiveCard.ContentType, 93 | Content = responseCard, 94 | }; 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Cards/TourCarousel.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Cards 6 | { 7 | using System.Collections.Generic; 8 | using Microsoft.Bot.Schema; 9 | using Microsoft.Teams.Apps.AskHR.Properties; 10 | 11 | /// 12 | /// This class process Tour Carousel feature : Common Method for user tour and team tour. 13 | /// 14 | public class TourCarousel 15 | { 16 | /// 17 | /// Create the set of cards that comprise the team tour carousel. 18 | /// 19 | /// The base URI where the app is hosted 20 | /// The cards that comprise the team tour 21 | public static IEnumerable GetTeamTourCards(string appBaseUri) 22 | { 23 | return new List() 24 | { 25 | GetCard(Resource.TeamNotificationHeaderText, Resource.TeamNotificationContent, appBaseUri + "/content/Notifications.png"), 26 | GetCard(Resource.TeamChatHeaderText, Resource.TeamChatContent, appBaseUri + "/content/Enduserchat.png"), 27 | GetCard(Resource.TeamTicketSystemHeaderText, Resource.TeamTicketSystemContent, appBaseUri + "/content/Ticketsystem.png"), 28 | }; 29 | } 30 | 31 | /// 32 | /// Create the set of cards that comprise the user tour carousel. 33 | /// 34 | /// The base URI where the app is hosted 35 | /// The cards that comprise the user tour 36 | public static IEnumerable GetUserTourCards(string appBaseUri) 37 | { 38 | return new List() 39 | { 40 | GetCard(Resource.FunctionCardText1, Resource.FunctionCardText2, appBaseUri + "/content/Askaquestion.png"), 41 | GetCard(Resource.AskAnExpertText1, Resource.AskAnExpertText2, appBaseUri + "/content/Expertinquiry.png"), 42 | GetCard(Resource.ShareFeedbackTitleText, Resource.FeedbackText1, appBaseUri + "/content/Sharefeedback.png"), 43 | }; 44 | } 45 | 46 | private static Attachment GetCard(string title, string text, string imageUri) 47 | { 48 | HeroCard tourCarouselCard = new HeroCard() 49 | { 50 | Title = title, 51 | Text = text, 52 | Images = new List() 53 | { 54 | new CardImage(imageUri), 55 | } 56 | }; 57 | 58 | return tourCarouselCard.ToAttachment(); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Cards/UnrecognizedInputCard.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Cards 6 | { 7 | using System.Collections.Generic; 8 | using System.Globalization; 9 | using AdaptiveCards; 10 | using Microsoft.Bot.Schema; 11 | using Microsoft.Teams.Apps.AskHR.Common; 12 | using Microsoft.Teams.Apps.AskHR.Models; 13 | using Microsoft.Teams.Apps.AskHR.Properties; 14 | 15 | /// 16 | /// This class handles unrecognized input sent by the user-asking random question to bot. 17 | /// 18 | public static class UnrecognizedInputCard 19 | { 20 | /// 21 | /// This method will construct the card when unrecognized input is sent by the user. 22 | /// 23 | /// Actual question asked by the user to the bot. 24 | /// Message to be shown in card depending on different scenarios. 25 | /// UnrecognizedInput Card. 26 | public static Attachment GetCard(string userQuestion, string cardMessage) 27 | { 28 | var textAlignment = CultureInfo.CurrentCulture.TextInfo.IsRightToLeft ? AdaptiveHorizontalAlignment.Right : AdaptiveHorizontalAlignment.Left; 29 | 30 | AdaptiveCard unrecognizedInputCard = new AdaptiveCard("1.0") 31 | { 32 | Body = new List 33 | { 34 | new AdaptiveTextBlock 35 | { 36 | Text = cardMessage, 37 | Wrap = true, 38 | HorizontalAlignment = textAlignment 39 | } 40 | }, 41 | Actions = new List 42 | { 43 | new AdaptiveSubmitAction 44 | { 45 | Title = Resource.AskAnExpertButtonText, 46 | Data = new ResponseCardPayload 47 | { 48 | MsTeams = new CardAction 49 | { 50 | Type = ActionTypes.MessageBack, 51 | DisplayText = Resource.AskAnExpertDisplayText, 52 | Text = Constants.AskAnExpert, 53 | }, 54 | UserQuestion = userQuestion 55 | }, 56 | }, 57 | new AdaptiveSubmitAction 58 | { 59 | Title = Resource.ShareFeedbackButtonText, 60 | Data = new ResponseCardPayload 61 | { 62 | MsTeams = new CardAction 63 | { 64 | Type = ActionTypes.MessageBack, 65 | DisplayText = Resource.ShareFeedbackDisplayText, 66 | Text = Constants.ShareFeedback, 67 | } 68 | } 69 | } 70 | } 71 | }; 72 | 73 | return new Attachment 74 | { 75 | ContentType = AdaptiveCard.ContentType, 76 | Content = unrecognizedInputCard, 77 | }; 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Cards/UnrecognizedTeamInputCard.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Cards 6 | { 7 | using System.Collections.Generic; 8 | using Microsoft.Bot.Schema; 9 | using Microsoft.Teams.Apps.AskHR.Common; 10 | using Microsoft.Teams.Apps.AskHR.Properties; 11 | 12 | /// 13 | /// This class handles unrecognized input sent by the team member-sending random text to bot. 14 | /// 15 | public class UnrecognizedTeamInputCard 16 | { 17 | /// 18 | /// Construct the card to render when there's an unrecognized input in a channel. 19 | /// 20 | /// Card attachment 21 | public static Attachment GetCard() 22 | { 23 | var card = new HeroCard 24 | { 25 | Text = Resource.TeamCustomMessage, 26 | Buttons = new List 27 | { 28 | new CardAction(ActionTypes.MessageBack) 29 | { 30 | Title = Resource.TakeATeamTourButtonText, 31 | DisplayText = Resource.TakeATeamTourButtonText, 32 | Text = Constants.TeamTour, 33 | } 34 | } 35 | }; 36 | 37 | return card.ToAttachment(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Cards/WelcomeCard.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Cards 6 | { 7 | using System.Collections.Generic; 8 | using System.Globalization; 9 | using AdaptiveCards; 10 | using Microsoft.Bot.Schema; 11 | using Microsoft.Teams.Apps.AskHR.Common; 12 | using Microsoft.Teams.Apps.AskHR.Models; 13 | using Microsoft.Teams.Apps.AskHR.Properties; 14 | 15 | /// 16 | /// This class process Welcome Card, when bot is installed by the user in personal scope. 17 | /// 18 | public class WelcomeCard 19 | { 20 | /// 21 | /// This method will construct the user welcome card when bot is added in personal scope. 22 | /// 23 | /// Gets welcome text. 24 | /// User welcome card. 25 | public static Attachment GetCard(string welcomeText) 26 | { 27 | var textAlignment = CultureInfo.CurrentCulture.TextInfo.IsRightToLeft ? AdaptiveHorizontalAlignment.Right : AdaptiveHorizontalAlignment.Left; 28 | 29 | AdaptiveCard userWelcomeCard = new AdaptiveCard("1.0") 30 | { 31 | Body = new List 32 | { 33 | new AdaptiveTextBlock 34 | { 35 | Text = welcomeText, 36 | Wrap = true, 37 | HorizontalAlignment = textAlignment 38 | } 39 | }, 40 | Actions = new List 41 | { 42 | new AdaptiveSubmitAction 43 | { 44 | Title = Resource.TakeATourButtonText, 45 | Data = new TeamsAdaptiveSubmitActionData 46 | { 47 | MsTeams = new CardAction 48 | { 49 | Type = ActionTypes.MessageBack, 50 | DisplayText = Resource.TakeATourButtonText, 51 | Text = Constants.TakeATour 52 | } 53 | }, 54 | } 55 | } 56 | }; 57 | 58 | return new Attachment 59 | { 60 | ContentType = AdaptiveCard.ContentType, 61 | Content = userWelcomeCard, 62 | }; 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Cards/WelcomeTeamCard.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Cards 6 | { 7 | using System.Collections.Generic; 8 | using System.Globalization; 9 | using AdaptiveCards; 10 | using Microsoft.Bot.Schema; 11 | using Microsoft.Teams.Apps.AskHR.Common; 12 | using Microsoft.Teams.Apps.AskHR.Models; 13 | using Microsoft.Teams.Apps.AskHR.Properties; 14 | 15 | /// 16 | /// This class process Welcome Card when installed in Team scope. 17 | /// 18 | public static class WelcomeTeamCard 19 | { 20 | /// 21 | /// This method will construct the welcome team card when bot is added to the team. 22 | /// 23 | /// Team welcome card. 24 | public static Attachment GetCard() 25 | { 26 | var textAlignment = CultureInfo.CurrentCulture.TextInfo.IsRightToLeft ? AdaptiveHorizontalAlignment.Right : AdaptiveHorizontalAlignment.Left; 27 | 28 | AdaptiveCard teamWelcomeCard = new AdaptiveCard("1.0") 29 | { 30 | Body = new List 31 | { 32 | new AdaptiveTextBlock 33 | { 34 | Text = Resource.WelcomeTeamCardContent, 35 | Wrap = true, 36 | HorizontalAlignment = textAlignment 37 | } 38 | }, 39 | Actions = new List 40 | { 41 | // Team- take a tour submit action. 42 | new AdaptiveSubmitAction 43 | { 44 | Title = Resource.TakeATeamTourButtonText, 45 | Data = new TeamsAdaptiveSubmitActionData 46 | { 47 | MsTeams = new CardAction 48 | { 49 | Type = ActionTypes.MessageBack, 50 | DisplayText = Resource.TakeATeamTourButtonText, 51 | Text = Constants.TeamTour 52 | } 53 | }, 54 | } 55 | } 56 | }; 57 | 58 | return new Attachment 59 | { 60 | ContentType = AdaptiveCard.ContentType, 61 | Content = teamWelcomeCard, 62 | }; 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Microsoft.Teams.Apps.AskHR", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "dependencies": { 7 | "@babel/preset-env": "^7.6.2", 8 | "@microsoft/applicationinsights-react-js": "^2.2.2", 9 | "@microsoft/applicationinsights-web": "^2.2.2", 10 | "i18next": "^20.2.1", 11 | "react": "^16.9.0", 12 | "react-appinsights": "^3.0.0-rc.6", 13 | "react-dom": "^16.9.0", 14 | "webpack": "^4.39.3", 15 | "webpack-cli": "^3.3.7" 16 | }, 17 | "devDependencies": { 18 | "@babel/core": "^7.6.2", 19 | "@babel/plugin-proposal-class-properties": "^7.5.5", 20 | "@babel/preset-react": "^7.0.0", 21 | "@microsoft/teams-js": "^1.5.0", 22 | "babel-core": "^7.0.0-bridge.0", 23 | "babel-loader": "^7.1.5", 24 | "css-loader": "^3.2.0", 25 | "react": "^16.9.0", 26 | "react-dom": "^16.9.0", 27 | "react-router-dom": "^5.0.1", 28 | "sass-loader": "^7.3.1", 29 | "style-loader": "^1.0.0", 30 | "webpack": "^4.39.3", 31 | "webpack-cli": "^3.3.7" 32 | }, 33 | "scripts": { 34 | "test": "echo \"Error: no test specified\" && exit 1", 35 | "build": "webpack --config=webpack.config.js" 36 | }, 37 | "babel": { 38 | "presets": [ 39 | "@babel/preset-env", 40 | "@babel/preset-react" 41 | ], 42 | "plugins": [ 43 | "@babel/plugin-proposal-class-properties" 44 | ] 45 | }, 46 | "keywords": [], 47 | "author": "", 48 | "license": "ISC" 49 | } 50 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import AskHRTiles from './components/AskHRTiles/AskHRTiles'; 3 | 4 | export default class App extends Component { 5 | render() { 6 | return ( 7 | 8 | ); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/src/components/AskHRTiles/AskHRTile/AskHR.css: -------------------------------------------------------------------------------- 1 | html { 2 | font-size: 62.5% /* =10px;;; */; 3 | } 4 | 5 | body::-webkit-scrollbar { 6 | width: 10px; 7 | } 8 | 9 | /* Track */ 10 | body::-webkit-scrollbar-track { 11 | box-shadow: inset 0 0 5px grey; 12 | border-radius: 10px; 13 | } 14 | 15 | /* Handle */ 16 | body::-webkit-scrollbar-thumb { 17 | background: grey; 18 | border-radius: 10px; 19 | } 20 | 21 | /* Handle on hover */ 22 | body::-webkit-scrollbar-thumb:hover { 23 | background: grey; 24 | } 25 | 26 | #root div:not(.description) { 27 | display: inline-block !important; 28 | } 29 | 30 | .tile { 31 | width: 35.5rem; 32 | display: inline-block; 33 | height: 30rem; 34 | margin: 1.6rem 1.6rem; 35 | background-color: white; 36 | text-align: center; 37 | color: #252424; 38 | font-weight: normal; 39 | cursor: pointer; 40 | border-radius: 0.3rem; 41 | box-shadow: 0 0.2rem 0.4rem -0.075rem rgba(0,0,0,.1); 42 | } 43 | 44 | .title { 45 | width: 91%; 46 | color: #3a3939; 47 | height: 4.7rem; 48 | font-weight: bold; 49 | text-align: left; 50 | font-size: 1.8rem; 51 | padding-left: 0.1rem; 52 | padding-top: 2rem; 53 | font-family: segoe UI, Arial,sans-serif; 54 | overflow: hidden; 55 | text-overflow: ellipsis; 56 | display: -webkit-box; 57 | -webkit-line-clamp: 2; 58 | -webkit-box-orient: vertical; 59 | word-break: break-word; 60 | } 61 | 62 | .imageAskHRDiv { 63 | margin-top: 0.8rem; 64 | margin-bottom: 0.8rem; 65 | overflow: hidden; 66 | overflow-y: hidden; 67 | width: 32.3rem !important; 68 | height: 13.6rem !important; 69 | margin-left: auto; 70 | margin-right: auto; 71 | } 72 | 73 | .descDiv { 74 | height: 6rem; 75 | width: 100%; 76 | } 77 | 78 | .imageAskHR { 79 | width: 100%; 80 | padding-bottom: 1.2rem; 81 | position: relative; 82 | left: 50%; 83 | transform: translate(-50%); 84 | top: 0%; 85 | height: 14rem; 86 | } 87 | 88 | .description { 89 | width: 91%; 90 | height: 5.9rem; 91 | float: left; 92 | text-align: left; 93 | padding-left: 1.6rem; 94 | font-family: segoe UI, Arial,sans-serif; 95 | font-size: 1.4rem; 96 | color: #484644; 97 | overflow: hidden; 98 | font-weight: normal; 99 | text-overflow: ellipsis; 100 | display: -webkit-box !important; 101 | -webkit-line-clamp: 3; 102 | -webkit-box-orient: vertical; 103 | } 104 | 105 | /*Dark theme*/ 106 | .theme-dark .tile { 107 | background-color: #3b3a3a; 108 | box-shadow: 0px 0px 1px 1px #1d1d1dd4; 109 | } 110 | 111 | .theme-dark .title { 112 | color: #d2d2d2; 113 | } 114 | 115 | .theme-dark .description { 116 | color: #adacac; 117 | } 118 | 119 | /*High-Contrast theme*/ 120 | .theme-contrast .tile { 121 | background-color: black; 122 | border: 1px white solid; 123 | } 124 | 125 | .theme-contrast .title { 126 | color: white; 127 | } 128 | 129 | .theme-contrast .description { 130 | color: white; 131 | } 132 | 133 | /*Light-Theme*/ 134 | 135 | .theme-light .tile { 136 | background-color: white; 137 | } 138 | 139 | .theme-dark input { 140 | background-color: #33344A; 141 | color: #a6a7dc; 142 | } 143 | 144 | .loginBtn { 145 | margin-left: 1rem; 146 | width: 12rem; 147 | cursor: pointer; 148 | border: none; 149 | margin-top: 2rem; 150 | font-size: 1.4rem; 151 | color: #6264a7; 152 | background: #F4F4FC; 153 | font-weight: bold; 154 | height: 3.6rem; 155 | border-radius: 0.5rem; 156 | border: 1px #6264a7 solid; 157 | } 158 | 159 | .loginSection { 160 | text-align: center; 161 | height: 25rem; 162 | width: 32rem; 163 | top: 0 !important; 164 | bottom: 0 !important; 165 | left: 0 !important; 166 | right: 0 !important; 167 | margin: auto !important; 168 | } 169 | 170 | .askHRLogoImg { 171 | height: 64px; 172 | width: 64px; 173 | margin-bottom: 24px; 174 | border-radius: 3px; 175 | } 176 | 177 | .loginText { 178 | width: 32rem; 179 | font-weight: 600; 180 | font-size: 1.8rem; 181 | font-family: "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif !important; 182 | } 183 | 184 | .askHRAppDescription { 185 | font-weight: 400; 186 | font-size: 1.4rem; 187 | margin-top: 1rem; 188 | font-family: "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif !important; 189 | } 190 | 191 | .theme-dark .askHRAppDescription { 192 | color: rgba(255,255,255,.74); 193 | } 194 | 195 | .theme-contrast .askHRAppDescription { 196 | color: white; 197 | } 198 | 199 | .theme-dark .loginText { 200 | color: rgba(255,255,255,.74); 201 | } 202 | 203 | .theme-contrast .loginText { 204 | color: white; 205 | } 206 | 207 | .theme-dark input { 208 | background-color: #33344A; 209 | color: #a6a7dc; 210 | } 211 | 212 | @media only screen and (min-width: 1821px) { 213 | .description { 214 | height: 5.5rem; 215 | } 216 | } 217 | 218 | .rtlTextAlign{ 219 | text-align:right; 220 | } 221 | 222 | .ltrTextAlign { 223 | text-align: left; 224 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/src/components/AskHRTiles/AskHRTile/AskHR.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import './AskHR.css'; 3 | import { withAITracking } from '@microsoft/applicationinsights-react-js'; 4 | import { ai } from '../../Telemetry/TrackTelemetry'; 5 | 6 | class AskHR extends Component { 7 | 8 | render() { 9 | return ( 10 | 11 | 12 |
13 |
14 | {this.props.AskHRData.title} 15 |
16 |
17 | {this.props.AskHRData.title} 18 |
19 |
20 |
21 | {this.props.AskHRData.description} 22 |
23 |
24 |
25 |
26 |
27 | ); 28 | } 29 | } 30 | 31 | export default withAITracking(ai.reactPlugin, AskHR, "AskHR"); -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/src/components/AskHRTiles/AskHRTiles.css: -------------------------------------------------------------------------------- 1 | .noDataDiv { 2 | text-align: center; 3 | font-weight: bold; 4 | margin-left: 25%; 5 | width: 50%; 6 | color: #666666; 7 | font-size: 25px; 8 | height: 100px; 9 | margin-top: 190px; 10 | font-family: 'Segoe UI' 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; 11 | } 12 | 13 | .theme-dark .noDataDiv{ 14 | color:white; 15 | } 16 | 17 | .theme-contrast .noDataDiv { 18 | color: white; 19 | } 20 | 21 | .rtlAlign { 22 | direction: rtl; 23 | float: right; 24 | margin-right: 16px; 25 | } 26 | 27 | .ltrAlign { 28 | margin-left: 16px; 29 | } 30 | 31 | 32 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/src/components/Telemetry/TrackTelemetry.js: -------------------------------------------------------------------------------- 1 | import { ApplicationInsights } from '@microsoft/applicationinsights-web'; 2 | import { ReactPlugin } from '@microsoft/applicationinsights-react-js'; 3 | import React, { Component } from 'react'; 4 | 5 | class TelemetryService extends Component { 6 | 7 | constructor(props) { 8 | super(props); 9 | this.reactPlugin = new ReactPlugin(); 10 | } 11 | 12 | getKey(reactPluginConfig) { 13 | fetch('/Help/GetConfigurationJson') 14 | .then(response => response.json()) 15 | .then(data => { 16 | if (data && data.APPINSIGHTS_INSTRUMENTATIONKEY) { 17 | this.loadAppInsights(data.APPINSIGHTS_INSTRUMENTATIONKEY, reactPluginConfig); 18 | } 19 | }, 20 | (error) => { 21 | console.error(error); 22 | ai.appInsights.trackException({ name: error }); 23 | }); 24 | } 25 | 26 | initialize(reactPluginConfig) { 27 | this.getKey(reactPluginConfig); 28 | } 29 | 30 | loadAppInsights(instrumentationKey, reactPluginConfig) { 31 | this.appInsights = new ApplicationInsights({ 32 | config: { 33 | instrumentationKey: instrumentationKey, 34 | maxBatchInterval: 0, 35 | disableFetchTracking: false, 36 | extensions: [this.reactPlugin], 37 | extensionConfig: { 38 | [this.reactPlugin.identifier]: reactPluginConfig 39 | } 40 | } 41 | }); 42 | this.appInsights.loadAppInsights(); 43 | } 44 | } 45 | export let ai = new TelemetryService(); -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/src/index.css: -------------------------------------------------------------------------------- 1 | @media (max-width: 767px) { 2 | /* On small screens, the nav menu spans the full width of the screen. Leave a space for it. */ 3 | body { 4 | padding-top: 50px; 5 | } 6 | } 7 | #root { 8 | margin-left: 16px; 9 | } 10 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import './index.css'; 5 | 6 | const rootElement = document.getElementById('root'); 7 | 8 | ReactDOM.render(,rootElement); 9 | 10 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ClientApp/webpack.config.js: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | const path = require("path"); 5 | 6 | module.exports = { 7 | entry: { 8 | index: "./src/index.js" 9 | }, 10 | output: { 11 | path: path.resolve(__dirname, "../wwwroot/dist"), 12 | filename: "bundle.js" 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | use: { 18 | loader: "babel-loader" 19 | }, 20 | test: /\.js$/, 21 | exclude: /node_modules/ //excludes node_modules folder from being transpiled by babel. We do this because it's a waste of resources to do so. 22 | }, 23 | { 24 | test: /\.(sa|sc|c)ss$/, 25 | use: ["style-loader", "css-loader"] 26 | } 27 | ] 28 | } 29 | }; -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/ConfigurationCredentialProvider.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR 6 | { 7 | using Microsoft.Bot.Connector.Authentication; 8 | using Microsoft.Extensions.Configuration; 9 | 10 | /// 11 | /// Implementation of that gets the app credentials from configuration. 12 | /// 13 | public class ConfigurationCredentialProvider : SimpleCredentialProvider 14 | { 15 | /// 16 | /// Initializes a new instance of the class. 17 | /// 18 | /// Configuration. 19 | public ConfigurationCredentialProvider(IConfiguration configuration) 20 | : base(configuration["MicrosoftAppId"], configuration["MicrosoftAppPassword"]) 21 | { 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Connected Services/Application Insights/ConnectedService.json: -------------------------------------------------------------------------------- 1 | { 2 | "ProviderId": "Microsoft.ApplicationInsights.ConnectedService.ConnectedServiceProvider", 3 | "Version": "8.14.20131.1", 4 | "GettingStartedDocument": { 5 | "Uri": "https://go.microsoft.com/fwlink/?LinkID=798432" 6 | } 7 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Controllers/BotController.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Controllers 6 | { 7 | using System.Threading.Tasks; 8 | using Microsoft.AspNetCore.Mvc; 9 | using Microsoft.Bot.Builder; 10 | using Microsoft.Bot.Builder.Integration.AspNet.Core; 11 | 12 | // This ASP Controller is created to handle a request. Dependency Injection will provide the Adapter and IBot 13 | // implementation at runtime. Multiple different IBot implementations running at different endpoints can be 14 | // achieved by specifying a more specific type for the bot constructor argument. 15 | 16 | /// 17 | /// This is a Bot controller class includes all API's related to this Bot. 18 | /// 19 | [Route("api/messages")] 20 | [ApiController] 21 | public class BotController : ControllerBase 22 | { 23 | private readonly IBotFrameworkHttpAdapter adapter; 24 | private readonly IBot bot; 25 | 26 | /// 27 | /// Initializes a new instance of the class. 28 | /// 29 | /// Bot adapter. 30 | /// Bot Interface. 31 | public BotController(IBotFrameworkHttpAdapter adapter, IBot bot) 32 | { 33 | this.adapter = adapter; 34 | this.bot = bot; 35 | } 36 | 37 | /// 38 | /// Executing the Post Async method. 39 | /// 40 | /// A representing the result of the asynchronous operation. 41 | [HttpPost] 42 | public async Task PostAsync() 43 | { 44 | // Delegate the processing of the HTTP POST to the adapter. 45 | // The adapter will invoke the bot. 46 | await this.adapter.ProcessAsync(this.Request, this.Response, this.bot); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Helper/AuthManager.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Helper 6 | { 7 | using System; 8 | using System.IdentityModel.Tokens.Jwt; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | using Microsoft.IdentityModel.Protocols; 12 | using Microsoft.IdentityModel.Protocols.OpenIdConnect; 13 | using Microsoft.IdentityModel.Tokens; 14 | 15 | /// 16 | /// AuthManager. 17 | /// 18 | public class AuthManager : IAuthManager 19 | { 20 | private readonly IConfigurationManager configurationManager; 21 | private readonly string expectedTenantId; 22 | private readonly string appId; 23 | 24 | /// 25 | /// Initializes a new instance of the class. 26 | /// AuthManager constructor 27 | /// 28 | /// configurationManager 29 | /// tenantId 30 | /// appId 31 | public AuthManager(IConfigurationManager configurationManager, string tenantId, string appId) 32 | { 33 | this.configurationManager = configurationManager; 34 | this.expectedTenantId = tenantId; 35 | this.appId = appId; 36 | } 37 | 38 | /// 39 | /// Validate token against OIDC configuration values 40 | /// 41 | /// JWT 42 | /// valid user name claim 43 | public async Task ValidateTokenAsync(string token) 44 | { 45 | var openIdConfig = await this.configurationManager.GetConfigurationAsync(CancellationToken.None); 46 | 47 | // Configure the TokenValidationParameters. Also set the Issuer and Audience(s) to validate 48 | TokenValidationParameters validationParameters = 49 | new TokenValidationParameters 50 | { 51 | ValidIssuer = $"https://sts.windows.net/{this.expectedTenantId}/", 52 | IssuerSigningKeys = openIdConfig.SigningKeys, 53 | ValidAudience = this.appId, 54 | ValidateIssuer = true, 55 | RequireExpirationTime = true, 56 | ValidateLifetime = true, 57 | ClockSkew = TimeSpan.Zero 58 | }; 59 | 60 | // If the token is not valid for any reason, an exception will be thrown by the method 61 | JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler(); 62 | handler.ValidateToken(token, validationParameters, out SecurityToken validatedToken); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Helper/IAuthManager.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Helper 6 | { 7 | using System.Threading.Tasks; 8 | 9 | /// 10 | /// Interface for Authentication management for JWT tokens 11 | /// 12 | public interface IAuthManager 13 | { 14 | /// 15 | /// Validate JSON web token against validation parameters provided by issuer configuration 16 | /// 17 | /// JSON web token. 18 | /// true if the token is valid 19 | Task ValidateTokenAsync(string token); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Models/AskAnExpertCardPayload.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Models 6 | { 7 | /// 8 | /// Represents the submit data associated with the Ask An Expert card. 9 | /// 10 | public class AskAnExpertCardPayload : TeamsAdaptiveSubmitActionData 11 | { 12 | /// 13 | /// Gets or sets the user title text for ask an expert button. 14 | /// 15 | public string Title { get; set; } 16 | 17 | /// 18 | /// Gets or sets the question for the expert being asked by the user through bot command. 19 | /// 20 | public string Description { get; set; } 21 | 22 | /// 23 | /// Gets or sets the question for the expert being asked by the user through Response card- 24 | /// Response Card: Response generated by the bot to user question by calling QnA Maker service. 25 | /// 26 | public string UserQuestion { get; set; } 27 | 28 | /// 29 | /// Gets or sets the answer for the expert- Answer sent to the SME team along with feedback 30 | /// provided by the user on response given by bot calling QnA Maker service. 31 | /// 32 | public string KnowledgeBaseAnswer { get; set; } 33 | } 34 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Models/ChangeTicketStatusPayload.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Models 6 | { 7 | using Newtonsoft.Json; 8 | 9 | /// 10 | /// Represents the data payload of Action.Submit to change the status of a ticket. 11 | /// 12 | public class ChangeTicketStatusPayload 13 | { 14 | /// 15 | /// Action that reopens a closed ticket 16 | /// 17 | public const string ReopenAction = "Reopen"; 18 | 19 | /// 20 | /// Action that closes a ticket 21 | /// 22 | public const string CloseAction = "Close"; 23 | 24 | /// 25 | /// Action that assigns a ticket to the person that performed the action 26 | /// 27 | public const string AssignToSelfAction = "AssignToSelf"; 28 | 29 | /// 30 | /// Gets or sets the ticket id. 31 | /// 32 | [JsonProperty("ticketId")] 33 | public string TicketId { get; set; } 34 | 35 | /// 36 | /// Gets or sets the action to perform on the ticket. 37 | /// 38 | [JsonProperty("action")] 39 | public string Action { get; set; } 40 | } 41 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Models/FeedbackRating.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Models 6 | { 7 | /// 8 | /// Represents the user rating given for feedback 9 | /// 10 | public enum FeedbackRating 11 | { 12 | /// 13 | /// Not helpful 14 | /// 15 | NotHelpful, 16 | 17 | /// 18 | /// Needs improvement 19 | /// 20 | NeedsImprovement, 21 | 22 | /// 23 | /// Helpful 24 | /// 25 | Helpful 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Models/ResponseCardPayload.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Models 6 | { 7 | /// 8 | /// Represents the payload of a response card. 9 | /// 10 | public class ResponseCardPayload : TeamsAdaptiveSubmitActionData 11 | { 12 | /// 13 | /// Gets or sets the question that was asked originally asked by the user. 14 | /// 15 | public string UserQuestion { get; set; } 16 | 17 | /// 18 | /// Gets or sets the response given by the bot to the user. 19 | /// 20 | public string KnowledgeBaseAnswer { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Models/ShareFeedbackCardPayload.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Models 6 | { 7 | /// 8 | /// This model class is responsible to model user activity with bot- 9 | /// asking a question or providing feedback on app or on results given by the bot to the user. 10 | /// 11 | public class ShareFeedbackCardPayload : TeamsAdaptiveSubmitActionData 12 | { 13 | /// 14 | /// Gets or sets the action when user submits feedback rating. 15 | /// 16 | public string Rating { get; set; } 17 | 18 | /// 19 | /// Gets or sets the bot feedback. 20 | /// 21 | public string Description { get; set; } 22 | 23 | /// 24 | /// Gets or sets the question for the expert being asked by the user through Response card- 25 | /// Response Card: Response generated by the bot to user question by calling QnA Maker service. 26 | /// 27 | public string UserQuestion { get; set; } 28 | 29 | /// 30 | /// Gets or sets the answer for the expert- Answer sent to the SME team along with feedback 31 | /// provided by the user on response given by bot calling QnA Maker service. 32 | /// 33 | public string KnowledgeBaseAnswer { get; set; } 34 | } 35 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Models/TeamsAdaptiveSubmitActionData.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Models 6 | { 7 | using Microsoft.Bot.Schema; 8 | using Newtonsoft.Json; 9 | 10 | /// 11 | /// Defines Teams-specific behavior for an adaptive card submit action. 12 | /// 13 | public class TeamsAdaptiveSubmitActionData 14 | { 15 | /// 16 | /// Gets or sets the Teams-specific action 17 | /// 18 | [JsonProperty("msteams")] 19 | public CardAction MsTeams { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Models/TicketSearchScope.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | namespace Microsoft.Teams.Apps.AskHR.Models 5 | { 6 | /// 7 | /// Ticket search scope 8 | /// 9 | public enum TicketSearchScope 10 | { 11 | /// 12 | /// Recent tickets 13 | /// 14 | RecentTickets, 15 | 16 | /// 17 | /// Open tickets 18 | /// 19 | OpenTickets, 20 | 21 | /// 22 | /// Tickets assigned to a subject-matter expert 23 | /// 24 | AssignedTickets 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Program.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR 6 | { 7 | using Microsoft.AspNetCore; 8 | using Microsoft.AspNetCore.Hosting; 9 | 10 | /// 11 | /// This a Program main class for this Bot. 12 | /// 13 | public class Program 14 | { 15 | /// 16 | /// This main class for this Bot. 17 | /// 18 | /// String of Arguments. 19 | public static void Main(string[] args) 20 | { 21 | CreateWebHostBuilder(args).Build().Run(); 22 | } 23 | 24 | /// 25 | /// This method will hit the Startup Method to set up the complete bot services. 26 | /// 27 | /// String of Arguments. 28 | /// A unit of Execution. 29 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 30 | WebHost.CreateDefaultBuilder(args) 31 | .UseStartup(); 32 | } 33 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Services/IQnAMakerFactory.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Services 6 | { 7 | using Microsoft.Bot.Builder.AI.QnA; 8 | 9 | /// 10 | /// Produces the right instance for a knowledge base. 11 | /// 12 | public interface IQnAMakerFactory 13 | { 14 | /// 15 | /// Gets the instance to use when querying the given knowledge base ID. 16 | /// 17 | /// The knowledge base ID 18 | /// The endpoint key 19 | /// A QnAMaker instance 20 | QnAMaker GetQnAMaker(string knowledgeBaseId, string endpointKey); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Services/ISearchService.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | namespace Microsoft.Teams.Apps.AskHR.Services 5 | { 6 | using System.Collections.Generic; 7 | using System.Threading.Tasks; 8 | using Microsoft.Teams.Apps.AskHR.Common.Models; 9 | using Microsoft.Teams.Apps.AskHR.Models; 10 | 11 | /// 12 | /// Interface of Search Service provider 13 | /// 14 | public interface ISearchService 15 | { 16 | /// 17 | /// Provide search result for table to be used by SME based on Azure search service. 18 | /// 19 | /// Scope of the search 20 | /// searchQuery to be provided by message extension 21 | /// Number of search results to return 22 | /// Number of search results to skip 23 | /// List of search results 24 | Task> SearchTicketsAsync(TicketSearchScope searchScope, string searchQuery, int? count = null, int? skip = null); 25 | } 26 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Services/QnAMakerFactory.cs: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // 4 | 5 | namespace Microsoft.Teams.Apps.AskHR.Services 6 | { 7 | using System.Collections.Concurrent; 8 | using System.Globalization; 9 | using System.Net.Http; 10 | using Microsoft.Bot.Builder.AI.QnA; 11 | using Microsoft.Bot.Configuration; 12 | using Microsoft.Extensions.Configuration; 13 | 14 | /// 15 | /// Produces the right instance for a knowledge base. 16 | /// 17 | public class QnAMakerFactory : IQnAMakerFactory 18 | { 19 | private readonly IConfiguration configuration; 20 | private readonly HttpClient httpClient; 21 | private readonly ConcurrentDictionary qnaMakerInstances; 22 | 23 | /// 24 | /// Initializes a new instance of the class. 25 | /// 26 | /// App configuration 27 | public QnAMakerFactory(IConfiguration configuration) 28 | { 29 | this.configuration = configuration; 30 | this.httpClient = new HttpClient(); 31 | this.qnaMakerInstances = new ConcurrentDictionary(); 32 | } 33 | 34 | /// 35 | public QnAMaker GetQnAMaker(string knowledgeBaseId, string endpointKey) 36 | { 37 | return this.qnaMakerInstances.GetOrAdd(knowledgeBaseId, (kbId) => 38 | { 39 | var serviceConfig = new QnAMakerService 40 | { 41 | KbId = kbId, 42 | EndpointKey = endpointKey, 43 | Hostname = this.configuration["QnAMakerHostUrl"] 44 | }; 45 | var options = new QnAMakerOptions 46 | { 47 | Top = 1, 48 | ScoreThreshold = float.Parse(this.configuration["ScoreThreshold"], CultureInfo.InvariantCulture), 49 | }; 50 | return new QnAMaker(serviceConfig, options, this.httpClient); 51 | }); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Views/Help/Index.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.Teams.Apps.AskHR.Properties 2 | @using System.Globalization 3 | @using System.Threading; 4 | @{ 5 | Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(ViewBag.locale); 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | @Resource.SignInTitleText 15 | 16 | 17 | 18 | 94 | 95 | 96 | 102 | 103 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Views/Help/RenderData.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | AskHR Help 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/Views/Help/SignIn.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.Teams.Apps.AskHR.Properties 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | @Resource.SignInTitleText 10 | 11 | 12 | 13 | 14 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "TenantId": "", 3 | "MicrosoftAppId": "", 4 | "MicrosoftAppPassword": "", 5 | "QnAMakerHostUrl": "", 6 | "ScoreThreshold": "0.5", 7 | "StorageConnectionString": "", 8 | "AppBaseUri": "", 9 | "SearchServiceName": "", 10 | "SearchServiceAdminApiKey": "", 11 | "SearchServiceQueryApiKey": "", 12 | "AccessCacheExpiryInDays": 5, 13 | "SearchIndexingIntervalInMinutes": 10, 14 | "APPINSIGHTS_INSTRUMENTATIONKEY": "", 15 | "ASPNETCORE_ENVIRONMENT": "", 16 | "i18n": { 17 | "DefaultCulture": "en", 18 | "SupportedCultures": "en,ar,de,es,fr,he,ja,ko,pt-BR,ru,zh-CN,zh-TW" 19 | } 20 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/libman.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "defaultProvider": "cdnjs", 4 | "libraries": [ 5 | { 6 | "library": "jquery@3.4.1", 7 | "destination": "wwwroot/lib/jquery/", 8 | "files": [ 9 | "jquery.min.js", 10 | "jquery.js", 11 | "jquery.min.map" 12 | ] 13 | }, 14 | { 15 | "provider": "unpkg", 16 | "library": "@microsoft/teams-js@1.4.1", 17 | "destination": "wwwroot/lib/microsoft-teams/", 18 | "files": [ 19 | "dist/MicrosoftTeams.min.js", 20 | "dist/MicrosoftTeams.js", 21 | "dist/MicrosoftTeams.js.map" 22 | ] 23 | }, 24 | { 25 | "provider": "unpkg", 26 | "library": "adal-angular@1.0.17", 27 | "destination": "wwwroot/lib/adal-angular/", 28 | "files": [ 29 | "dist/adal.min.js" 30 | ] 31 | } 32 | ] 33 | } -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR/public/favicon.ico -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/public/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 23 | Microsoft.Teams.Apps.AskHR.Tab 24 | 25 | 26 | 29 |
30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Microsoft.Teams.Apps.AskHR.Tab", 3 | "name": "Microsoft.Teams.Apps.AskHR.Tab", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": "./index.html", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Askaquestion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Askaquestion.png -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Enduserchat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Enduserchat.png -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Expertinquiry.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Expertinquiry.png -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/HRSupportLoginImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/HRSupportLoginImage.png -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Notifications.png -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Sharefeedback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Sharefeedback.png -------------------------------------------------------------------------------- /Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Ticketsystem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OfficeDev/microsoft-teams-apps-hrsupport/a4c51a77547c046f877d71ef26cedad34b8c7658/Source/Microsoft.Teams.Apps.AskHR/wwwroot/Content/Ticketsystem.png -------------------------------------------------------------------------------- /Source/Resources.txt: -------------------------------------------------------------------------------- 1 | App Service (Contains config app) 2 | 3 | Storage Account (for storing teams id info) -------------------------------------------------------------------------------- /Source/stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | // ACTION REQUIRED: This file was automatically added to your project, but it 3 | // will not take effect until additional steps are taken to enable it. See the 4 | // following page for additional information: 5 | // 6 | // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Enableconfiguration.md 7 | 8 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 9 | "settings": { 10 | "documentationRules": { 11 | "companyName": "Microsoft" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /deploy.bot.cmd: -------------------------------------------------------------------------------- 1 | @if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off 2 | 3 | :: ---------------------- 4 | :: KUDU Deployment Script 5 | :: Version: 1.0.17 6 | :: ---------------------- 7 | 8 | :: Prerequisites 9 | :: ------------- 10 | 11 | :: Verify node.js installed 12 | where node 2>nul >nul 13 | IF %ERRORLEVEL% NEQ 0 ( 14 | echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment. 15 | goto error 16 | ) 17 | 18 | :: Setup 19 | :: ----- 20 | 21 | setlocal enabledelayedexpansion 22 | 23 | SET ARTIFACTS=%~dp0%..\artifacts 24 | 25 | IF NOT DEFINED DEPLOYMENT_SOURCE ( 26 | SET DEPLOYMENT_SOURCE=%~dp0%. 27 | ) 28 | 29 | IF NOT DEFINED DEPLOYMENT_TARGET ( 30 | SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot 31 | ) 32 | 33 | IF NOT DEFINED NEXT_MANIFEST_PATH ( 34 | SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest 35 | 36 | IF NOT DEFINED PREVIOUS_MANIFEST_PATH ( 37 | SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest 38 | ) 39 | ) 40 | 41 | IF NOT DEFINED KUDU_SYNC_CMD ( 42 | :: Install kudu sync 43 | echo Installing Kudu Sync 44 | call npm install kudusync -g --silent 45 | IF !ERRORLEVEL! NEQ 0 goto error 46 | 47 | :: Locally just running "kuduSync" would also work 48 | SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd 49 | ) 50 | IF NOT DEFINED DEPLOYMENT_TEMP ( 51 | SET DEPLOYMENT_TEMP=%temp%\___deployTemp%random% 52 | SET CLEAN_LOCAL_DEPLOYMENT_TEMP=true 53 | ) 54 | 55 | IF DEFINED CLEAN_LOCAL_DEPLOYMENT_TEMP ( 56 | IF EXIST "%DEPLOYMENT_TEMP%" rd /s /q "%DEPLOYMENT_TEMP%" 57 | mkdir "%DEPLOYMENT_TEMP%" 58 | ) 59 | 60 | IF DEFINED MSBUILD_PATH goto MsbuildPathDefined 61 | SET MSBUILD_PATH=%ProgramFiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe 62 | :MsbuildPathDefined 63 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 64 | :: Deployment 65 | :: ---------- 66 | 67 | echo Handling ASP.NET Core Web Application deployment. 68 | 69 | :: 1. Restore nuget packages 70 | call :ExecuteCmd dotnet restore "%DEPLOYMENT_SOURCE%\Source\Microsoft.Teams.Apps.AskHR.sln" 71 | IF !ERRORLEVEL! NEQ 0 goto error 72 | 73 | :: 2. Build and publish 74 | call :ExecuteCmd dotnet publish "%DEPLOYMENT_SOURCE%\Source\Microsoft.Teams.Apps.AskHR\Microsoft.Teams.Apps.AskHR.csproj" --output "%DEPLOYMENT_TEMP%" --configuration Release 75 | IF !ERRORLEVEL! NEQ 0 goto error 76 | 77 | :: 3. KuduSync 78 | call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd" 79 | IF !ERRORLEVEL! NEQ 0 goto error 80 | 81 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 82 | goto end 83 | 84 | :: Execute command routine that will echo out when error 85 | :ExecuteCmd 86 | setlocal 87 | set _CMD_=%* 88 | call %_CMD_% 89 | if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_% 90 | exit /b %ERRORLEVEL% 91 | 92 | :error 93 | endlocal 94 | echo An error has occurred during web site deployment. 95 | call :exitSetErrorLevel 96 | call :exitFromFunction 2>nul 97 | 98 | :exitSetErrorLevel 99 | exit /b 1 100 | 101 | :exitFromFunction 102 | () 103 | 104 | :end 105 | endlocal 106 | echo Finished successfully. 107 | -------------------------------------------------------------------------------- /deploy.cmd: -------------------------------------------------------------------------------- 1 | @if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off 2 | 3 | IF "%SITE_ROLE%" == "bot" ( 4 | deploy.bot.cmd 5 | ) ELSE ( 6 | IF "%SITE_ROLE%" == "configuration" ( 7 | deploy.configuration.cmd 8 | ) ELSE ( 9 | echo You have to set SITE_ROLE setting to either "bot" or "configuration" 10 | exit /b 1 11 | ) 12 | ) -------------------------------------------------------------------------------- /deploy.configuration.cmd: -------------------------------------------------------------------------------- 1 | @if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off 2 | 3 | :: ---------------------- 4 | :: KUDU Deployment Script 5 | :: Version: 1.0.17 6 | :: ---------------------- 7 | 8 | :: Prerequisites 9 | :: ------------- 10 | 11 | :: Verify node.js installed 12 | where node 2>nul >nul 13 | IF %ERRORLEVEL% NEQ 0 ( 14 | echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment. 15 | goto error 16 | ) 17 | 18 | :: Setup 19 | :: ----- 20 | 21 | setlocal enabledelayedexpansion 22 | 23 | SET ARTIFACTS=%~dp0%..\artifacts 24 | 25 | IF NOT DEFINED DEPLOYMENT_SOURCE ( 26 | SET DEPLOYMENT_SOURCE=%~dp0%. 27 | ) 28 | 29 | IF NOT DEFINED DEPLOYMENT_TARGET ( 30 | SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot 31 | ) 32 | 33 | IF NOT DEFINED NEXT_MANIFEST_PATH ( 34 | SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest 35 | 36 | IF NOT DEFINED PREVIOUS_MANIFEST_PATH ( 37 | SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest 38 | ) 39 | ) 40 | 41 | IF NOT DEFINED KUDU_SYNC_CMD ( 42 | :: Install kudu sync 43 | echo Installing Kudu Sync 44 | call npm install kudusync -g --silent 45 | IF !ERRORLEVEL! NEQ 0 goto error 46 | 47 | :: Locally just running "kuduSync" would also work 48 | SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd 49 | ) 50 | IF NOT DEFINED DEPLOYMENT_TEMP ( 51 | SET DEPLOYMENT_TEMP=%temp%\___deployTemp%random% 52 | SET CLEAN_LOCAL_DEPLOYMENT_TEMP=true 53 | ) 54 | 55 | IF DEFINED CLEAN_LOCAL_DEPLOYMENT_TEMP ( 56 | IF EXIST "%DEPLOYMENT_TEMP%" rd /s /q "%DEPLOYMENT_TEMP%" 57 | mkdir "%DEPLOYMENT_TEMP%" 58 | ) 59 | 60 | SET MSBUILD_PATH=%MSBUILD_15_DIR%\MSBuild.exe 61 | 62 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 63 | :: Deployment 64 | :: ---------- 65 | 66 | echo Handling .NET Web Application deployment. 67 | 68 | :: 1. Restore NuGet packages 69 | IF /I "Source\Microsoft.Teams.Apps.AskHR.sln" NEQ "" ( 70 | call :ExecuteCmd nuget restore "%DEPLOYMENT_SOURCE%\Source\Microsoft.Teams.Apps.AskHR.sln" -MSBuildPath "%MSBUILD_15_DIR%" 71 | IF !ERRORLEVEL! NEQ 0 goto error 72 | ) 73 | 74 | :: 2. Build to the temporary path 75 | IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" ( 76 | call :ExecuteCmd "%MSBUILD_PATH%" "%DEPLOYMENT_SOURCE%\Source\Microsoft.Teams.Apps.AskHR.Configuration\Microsoft.Teams.Apps.AskHR.Configuration.csproj" /nologo /verbosity:m /t:Build /t:pipelinePreDeployCopyAllFilesToOneFolder /p:_PackageTempDir="%DEPLOYMENT_TEMP%";AutoParameterizationWebConfigConnectionStrings=false;Configuration=Release;UseSharedCompilation=false /p:SolutionDir="%DEPLOYMENT_SOURCE%\Source\\" %SCM_BUILD_ARGS% 77 | ) ELSE ( 78 | call :ExecuteCmd "%MSBUILD_PATH%" "%DEPLOYMENT_SOURCE%\Source\Microsoft.Teams.Apps.AskHR.Configuration\Microsoft.Teams.Apps.AskHR.Configuration.csproj" /nologo /verbosity:m /t:Build /p:AutoParameterizationWebConfigConnectionStrings=false;Configuration=Release;UseSharedCompilation=false /p:SolutionDir="%DEPLOYMENT_SOURCE%\Source\\" %SCM_BUILD_ARGS% 79 | ) 80 | 81 | IF !ERRORLEVEL! NEQ 0 goto error 82 | 83 | :: 3. KuduSync 84 | IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" ( 85 | call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd" 86 | IF !ERRORLEVEL! NEQ 0 goto error 87 | ) 88 | 89 | :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 90 | goto end 91 | 92 | :: Execute command routine that will echo out when error 93 | :ExecuteCmd 94 | setlocal 95 | set _CMD_=%* 96 | call %_CMD_% 97 | if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_% 98 | exit /b %ERRORLEVEL% 99 | 100 | :error 101 | endlocal 102 | echo An error has occurred during web site deployment. 103 | call :exitSetErrorLevel 104 | call :exitFromFunction 2>nul 105 | 106 | :exitSetErrorLevel 107 | exit /b 1 108 | 109 | :exitFromFunction 110 | () 111 | 112 | :end 113 | endlocal 114 | echo Finished successfully. 115 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "2.1.515" 4 | } 5 | } --------------------------------------------------------------------------------