├── .gitignore
├── CREATE_USING_YEOMAN.md
├── README.md
├── app.css
├── assets
├── icon-16.png
├── icon-32.png
├── icon-80.png
└── logo-filled.png
├── certs
├── ca.crt
├── server.crt
└── server.key
├── config
├── webpack.common.js
├── webpack.dev.js
└── webpack.prod.js
├── function-file
├── function-file.html
└── function-file.ts
├── manifest.xml
├── package-lock.json
├── package.json
├── resource.html
├── src
├── components
│ ├── App.tsx
│ ├── Header.tsx
│ ├── HeroList.tsx
│ └── Progress.tsx
├── index.html
├── index.tsx
├── registerServiceWorker.js
└── styles.less
├── tsconfig.json
├── tslint.json
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2 | # See LICENSE in the project root for license information.
3 |
4 | # Created by https://www.gitignore.io/api/osx,windows
5 |
6 | ### OSX ###
7 | .DS_Store
8 | .AppleDouble
9 | .LSOverride
10 |
11 | # Icon must end with two \r
12 | Icon
13 |
14 |
15 | # Thumbnails
16 | ._*
17 |
18 | # Files that might appear in the root of a volume
19 | .DocumentRevisions-V100
20 | .fseventsd
21 | .Spotlight-V100
22 | .TemporaryItems
23 | .Trashes
24 | .VolumeIcon.icns
25 |
26 | # Directories potentially created on remote AFP share
27 | .AppleDB
28 | .AppleDesktop
29 | Network Trash Folder
30 | Temporary Items
31 | .apdisk
32 |
33 |
34 | ### Windows ###
35 | # Windows image file caches
36 | Thumbs.db
37 | ehthumbs.db
38 |
39 | # Folder config file
40 | Desktop.ini
41 |
42 | # Recycle Bin used on file shares
43 | $RECYCLE.BIN/
44 |
45 | # Windows Installer files
46 | *.cab
47 | *.msi
48 | *.msm
49 | *.msp
50 |
51 | # Windows shortcuts
52 | *.lnk
53 |
54 | # Ignore the following folders
55 | .vs
56 | .idea
57 | *.log
58 | obj
59 | bin
60 | *.user
61 |
62 | node_modules/**
63 | packages/**
64 | typings/**
65 | .vscode/**
66 | .awcache/**
67 |
--------------------------------------------------------------------------------
/CREATE_USING_YEOMAN.md:
--------------------------------------------------------------------------------
1 | ```
2 | yo office
3 | ```
4 | -
5 | - **Choose a project type** - Office Add-in project using Jquery framework
6 | - **Choose a script type** - Javascript
7 | - **What do you want to name your add-in?** - My Office Add-in
8 | - **Which Office client application would you like to support?** - Outlook
9 |
10 | 
11 |
12 | After you complete the wizard, the generator will create the project and install supporting Node components.
13 |
14 | - Navigate to the root folder of the web application project.
15 |
16 | ```
17 | cd "My Office Add-in";
18 | ```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # **Developing Office 365 Outlook Add-in with [Office UI Fabric React](https://developer.microsoft.com/en-us/fabric#/get-started#react)**
2 |
3 | ## **Note:**
4 | - Outlook add-in works only for Office365 users and not for any other users with Gmail or simple outlook.com accounts.
5 | - Outlook add-in can be developded using one of the pure JS, React JS, Angular JS or Vue JS
6 | - Before developing any add-on for production environment, please go through best practices suggested by Microsoft
7 | https://docs.microsoft.com/en-us/office/dev/add-ins/concepts/add-in-development-best-practices
8 | https://docs.microsoft.com/en-us/office/dev/add-ins/design/ux-design-pattern-templates
9 |
10 | ## **Technology Stack**
11 | 1) React - Office UI Fabric React - For the UI design
12 |
13 | ## How to make a boiler-plate template?
14 | There are two ways to make the boiler plat template for this kind of project.
15 |
16 | 1) Using create-react-app and
17 | 2) Using Yeoman project generator
18 |
19 | We are going to build our project using create-react-app
20 |
21 | ## **Prerequisites**
22 | 1) Install create-react-app
23 | ```
24 | npm install -g create-react-app
25 | ```
26 | 2) Install Yeoman
27 | ```
28 | npm install -g yo
29 | ```
30 |
31 | 3) Install Office Addin Project Creator
32 |
33 | ```
34 | npm install -g yo generator-office
35 | ```
36 |
37 | ## Creating the outlook Add-in App and Installing the Dependencies
38 |
39 | Run following commands on the Command Prompt
40 |
41 | 1) Generate the new React App
42 |
43 | ```
44 | npx create-react-app outlook_leave_addin_app
45 | ```
46 | 2) Navigate to the outlook_leave_addin_app folder
47 |
48 | ```
49 | cd outlook_leave_addin_app
50 | ```
51 |
52 | 3) Follow the steps [here](https://docs.microsoft.com/en-us/office/dev/add-ins/excel/excel-add-ins-get-started-react#generate-the-manifest-file-and-sideload-the-add-in) (**select outlook for "Which Office client application would you like to support" question**) to create the office add-in manifest file.
53 |
54 | 4) Install "office-js".
55 |
56 | ```
57 | npm install @micrsoft\office-js --save
58 | ```
59 |
60 | Ref:(https://github.com/OfficeDev/office-js)
61 |
62 | 5) Install the Fabric React package
63 |
64 | ```
65 | npm --save install office-ui-fabric-react
66 | ```
67 |
68 | 6) For styling run following command to install required packages
69 |
70 | ```
71 | npm install --save @uifabric/styling
72 | ```
73 |
74 | 7) Run the following command to use the [Office fabric UI Layouts](https://developer.microsoft.com/en-us/fabric#/styles/layout)
75 |
76 | ```
77 | npm install office-ui-fabric-core
78 | ```
79 | 8) Run following command if you want to use axios.
80 |
81 | ```
82 | npm install axios
83 | ```
84 |
85 | Note: To run the React app locally with HTTPS, type the following command in the location of the root folder.Because, add-ins communicate only with https end points.
86 |
87 |
88 | ```
89 | set HTTPS=true&&npm start
90 | ```
91 |
92 | ## How to Build the Addin
93 |
94 | 1) Put following setting in the ```package.json```. This setting will make sure to refer the "js" and "css" files in the ```assets``` folder using the relative path in the index.html of the build package. [More details are here.](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#serving-the-same-build-from-different-paths)
95 |
96 | ```
97 | put this in your package.json
98 | ```
99 |
100 | 2) Run the following command to build the package
101 |
102 | ```
103 | npm run build
104 | ```
105 |
106 | 3) Build package will created be in the ```build``` folder.
107 |
108 | ### References
109 |
110 | https://docs.microsoft.com/en-us/office/dev/add-ins/overview/office-add-ins?context=outlook/context
111 |
112 | https://docs.microsoft.com/en-us/outlook/
113 |
114 | https://docs.microsoft.com/en-us/outlook/add-ins/
115 |
116 | https://docs.microsoft.com/en-us/outlook/add-ins/quick-start?tabs=visual-studio-code
117 |
118 | https://docs.microsoft.com/en-us/outlook/add-ins/addin-tutorial
119 |
120 | https://docs.microsoft.com/en-us/office/dev/add-ins/concepts/add-in-development-lifecycle
121 |
122 | https://dev.office.com/reference/add-ins/outlook/1.5/Office.context.mailbox.item
123 |
124 | https://github.com/OfficeDev/office-js-docs/blob/master/reference/
125 |
126 | https://github.com/OfficeDev/office-ui-fabric-react/tree/master/packages/office-ui-fabric-react/src/components
127 |
128 | https://docs.microsoft.com/en-us/office/dev/add-ins/develop/use-the-oauth-authorization-framework-in-an-office-add-in
129 |
130 | https://developer.microsoft.com/en-us/office/docs
131 |
132 | https://github.com/OfficeDev/office-ui-fabric-react/blob/master/packages/icons/README.md
133 |
134 | https://github.com/OfficeDev/office-ui-fabric-react/tree/master/packages/styling
135 |
136 | https://docs.microsoft.com/en-us/office/dev/add-ins/excel/excel-add-ins-get-started-react
137 |
138 | https://github.com/OfficeDev/office-js
139 |
140 | https://developer.microsoft.com/en-us/fabric#/get-started
141 |
--------------------------------------------------------------------------------
/app.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3 | * See LICENSE in the project root for license information.
4 | */
5 |
6 | html,
7 | body {
8 | width: 100%;
9 | height: 100%;
10 | margin: 0;
11 | padding: 0;
12 | }
13 |
14 | ul,
15 | p,
16 | h1,
17 | h2,
18 | h3,
19 | h4,
20 | h5,
21 | h6 {
22 | margin: 0;
23 | padding: 0;
24 | }
25 |
26 | .ms-welcome {
27 | position: relative;
28 | display: -webkit-flex;
29 | display: flex;
30 | -webkit-flex-direction: column;
31 | flex-direction: column;
32 | -webkit-flex-wrap: nowrap;
33 | flex-wrap: nowrap;
34 | min-height: 500px;
35 | min-width: 320px;
36 | overflow: auto;
37 | overflow-x: hidden;
38 | }
39 |
40 | .ms-welcome__header {
41 | min-height: 250px;
42 | padding: 20px;
43 | padding-bottom: 30px;
44 | display: -webkit-flex;
45 | display: flex;
46 | -webkit-flex-direction: column;
47 | flex-direction: column;
48 | -webkit-flex-wrap: nowrap;
49 | flex-wrap: nowrap;
50 | -webkit-align-items: center;
51 | align-items: center;
52 | -webkit-justify-content: flex-end;
53 | justify-content: flex-end;
54 | }
55 |
56 | .ms-welcome__header > h1 {
57 | margin-top: 30px;
58 | text-align: center;
59 | }
60 |
61 | .ms-welcome__main {
62 | display: -webkit-flex;
63 | display: flex;
64 | -webkit-flex-direction: column;
65 | flex-direction: column;
66 | -webkit-flex-wrap: nowrap;
67 | flex-wrap: nowrap;
68 | -webkit-align-items: center;
69 | align-items: center;
70 | -webkit-flex: 1 0 0;
71 | flex: 1 0 0;
72 | padding: 30px 20px;
73 | }
74 |
75 | .ms-welcome__main > h2 {
76 | width: 100%;
77 | text-align: center;
78 | }
79 |
80 | .ms-welcome__features {
81 | list-style-type: none;
82 | margin-top: 30px;
83 | }
84 |
85 | .ms-welcome__features.ms-List .ms-ListItem {
86 | padding: 0px;
87 | padding-bottom: 20px;
88 | display: -webkit-flex;
89 | display: flex;
90 | -webkit-flex-direction: row;
91 | flex-direction: row;
92 | -webkit-flex-wrap: nowrap;
93 | flex-wrap: nowrap;
94 | -webkit-align-items: center;
95 | align-items: center;
96 | }
97 |
98 | .ms-welcome__features.ms-List .ms-ListItem > .ms-Icon {
99 | font-size: 14pt;
100 | }
101 |
102 | .ms-welcome__features.ms-List .ms-ListItem > .ms-Icon {
103 | margin-right: 10px;
104 | }
105 |
106 | .ms-welcome__action.ms-Button--hero {
107 | margin-top: 30px;
108 | display: -webkit-flex;
109 | display: flex;
110 | -webkit-flex-direction: row;
111 | flex-direction: row;
112 | -webkit-flex-wrap: nowrap;
113 | flex-wrap: nowrap;
114 | -webkit-justify-content: center;
115 | justify-content: center;
116 | -webkit-align-items: center;
117 | align-items: center;
118 | }
119 |
120 | .ms-welcome__action.ms-Button--hero .ms-Button-icon .ms-Icon {
121 | margin-left: 5px;
122 | margin-top: 4px;
123 | border: none;
124 | font-size: 14pt;
125 | }
126 |
127 | .ms-welcome__action.ms-Button--hero:hover .ms-Button-icon .ms-Icon {
128 | border: none;
129 | }
130 |
131 | @media (min-width: 0) and (max-width: 350px) {
132 | .ms-welcome__features {
133 | width: 100%;
134 | }
135 | }
--------------------------------------------------------------------------------
/assets/icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthGajjar/Outlook-addin-using-react-demo/de2924a099baaee51252acc700b44f1c93c4e08e/assets/icon-16.png
--------------------------------------------------------------------------------
/assets/icon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthGajjar/Outlook-addin-using-react-demo/de2924a099baaee51252acc700b44f1c93c4e08e/assets/icon-32.png
--------------------------------------------------------------------------------
/assets/icon-80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthGajjar/Outlook-addin-using-react-demo/de2924a099baaee51252acc700b44f1c93c4e08e/assets/icon-80.png
--------------------------------------------------------------------------------
/assets/logo-filled.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tirthGajjar/Outlook-addin-using-react-demo/de2924a099baaee51252acc700b44f1c93c4e08e/assets/logo-filled.png
--------------------------------------------------------------------------------
/certs/ca.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDtzCCAp+gAwIBAgIJAM2mE5TOxoFEMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNV
3 | BAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHUmVkbW9uZDEPMA0GA1UECgwG
4 | T2ZmaWNlMRwwGgYDVQQLDBNPZmZpY2VFeHRlbnNpYmlsaXR5MRUwEwYDVQQDDAxs
5 | b2NhbGhvc3QtY2EwHhcNMTgwNDExMTgwNjExWhcNMjMwNDExMTgwNjExWjByMQsw
6 | CQYDVQQGEwJVUzELMAkGA1UECAwCV0ExEDAOBgNVBAcMB1JlZG1vbmQxDzANBgNV
7 | BAoMBk9mZmljZTEcMBoGA1UECwwTT2ZmaWNlRXh0ZW5zaWJpbGl0eTEVMBMGA1UE
8 | AwwMbG9jYWxob3N0LWNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
9 | ymd3VtdKsAtRo2Ug5cpC2sXa2VACIbwkQHNEps2Q8wcBhAdfahKIStfQKrTF8UqW
10 | tcpfSIhxcBMBhBITDXKlnu1HRO77ufC/w1AToJKPfzC2RfMEiLpeuHk8Sy65ST8f
11 | o3L1BuqwYsVspFu//hLpeGQAv7Z4QV/DOeR2Uw8bi9m8ayYEDaMckVq1Pq7gF+vP
12 | tOG/EDyAHoM5PzWd75TNNM3ysbN0edT9SEk3fOUOR1b0M0QXsxRAzgkpFUtTFy4a
13 | 7YMFL113Jb+wMiUS7KZJalDrcjhthJInlAUwYNE3qFGqK412VbGDnwnas7L3+m8u
14 | PXM6AMgFKRvT+48zf9JkyQIDAQABo1AwTjAdBgNVHQ4EFgQUAnM7hKUXgNu7/kXI
15 | TkhWbbx428IwHwYDVR0jBBgwFoAUAnM7hKUXgNu7/kXITkhWbbx428IwDAYDVR0T
16 | BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAPcsXB8fcFuRf3OuX7iUFPU1c04VK
17 | 1y0HnWNC0jkPQKAale5+AsV99TFIBxb4ml+iokUU+SIdMwlHFkeVeVHhH8545LUF
18 | lbRQCjlcWsN9eAAci7h+BxE9sQt4LBNGmedzM+7+9rR3pzMI6zsaVyK7xS85G1mF
19 | nw3Ajfs+zqu3li+wsVF/4M7o6z0mjA036ejh3YgLabMSNHfNA+1ltPZwlKSE6+zR
20 | Wudewkb2yeDK85Z4l3vOhZPtZsBV2Uni34qXdTSAPGSXcRKd9NuArTjvt1QbD313
21 | 8YY1RxQjEDdW14StquAbm8BCrGZ6ks3h5mJQh++6pqELRI3P24e5zc1gIg==
22 | -----END CERTIFICATE-----
23 |
--------------------------------------------------------------------------------
/certs/server.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDljCCAn6gAwIBAgIJAIReiYJV7pQTMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNV
3 | BAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHUmVkbW9uZDEPMA0GA1UECgwG
4 | T2ZmaWNlMRwwGgYDVQQLDBNPZmZpY2VFeHRlbnNpYmlsaXR5MRUwEwYDVQQDDAxs
5 | b2NhbGhvc3QtY2EwIBcNMTgwNDExMTgwNjQxWhgPMjExODAzMTgxODA2NDFaMG8x
6 | CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJXQTEQMA4GA1UEBwwHUmVkbW9uZDEPMA0G
7 | A1UECgwGT2ZmaWNlMRwwGgYDVQQLDBNPZmZpY2VFeHRlbnNpYmlsaXR5MRIwEAYD
8 | VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz
9 | h4LApOQXf9U5xukxNpWjhn653YhcXjJ1asK1RTQwvYQoJWpFvrX12Z7EzydpkR8l
10 | TRGZmghfF6LtKlci8GNwActPC5v/0hO6IpabDdVntaEVrwO8VACkBQi1N1CrtL05
11 | 6gz4Aj2xMLYp6k2DVz1UWxF40YnPsWSRHzW8OmtP0U5XLIiwrxh9G4lwuFFan+Ha
12 | 346Hyjagt8ptc8S3FSRF/06J4iR9kvM6iCy9DWP44HPxQQFQ2VRN8E+TpJdevtx3
13 | F1JZ8GsawKKRbeX2o++j1GMGCkeUGe9G6YBX0mD3d/Bx69gm1E2SRmdiJzEWQoZC
14 | yzIAK72YF+QiHi1qdzSVAgMBAAGjMDAuMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXg
15 | MBQGA1UdEQQNMAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQsFAAOCAQEAekvobOVm
16 | hFgd6io16OeXahtKDaCm1NMw1YJoFE5LmBZRqJf8gAHT58Vg470lyURFxcn0MxXO
17 | Ho/wQlqZ/ycele9zkp3GPl03+7gA9py5EPvYyfuElQB0rG6TwIsAOD76Fubzom+X
18 | t+NE8zwF2Py2iMy+4YbiJqck+GfLOVPRaXgJt1BvY70G7GYOxOu+fLJuEsyvbwfN
19 | OhyDxGdQL/1CqasV3AOb+60qmHAg/eDx+T3M4ruTvrLsrtoRHsONyg3NQOEvgOEO
20 | 8s/7BdMwwa0l4swlF0ozTeyaq0wfEHa1N1Wh8xH3EKSsiyOZclsPe2FG348W6GQA
21 | Hmv1P1mWNdKYWg==
22 | -----END CERTIFICATE-----
23 |
--------------------------------------------------------------------------------
/certs/server.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzh4LApOQXf9U5
3 | xukxNpWjhn653YhcXjJ1asK1RTQwvYQoJWpFvrX12Z7EzydpkR8lTRGZmghfF6Lt
4 | Klci8GNwActPC5v/0hO6IpabDdVntaEVrwO8VACkBQi1N1CrtL056gz4Aj2xMLYp
5 | 6k2DVz1UWxF40YnPsWSRHzW8OmtP0U5XLIiwrxh9G4lwuFFan+Ha346Hyjagt8pt
6 | c8S3FSRF/06J4iR9kvM6iCy9DWP44HPxQQFQ2VRN8E+TpJdevtx3F1JZ8GsawKKR
7 | beX2o++j1GMGCkeUGe9G6YBX0mD3d/Bx69gm1E2SRmdiJzEWQoZCyzIAK72YF+Qi
8 | Hi1qdzSVAgMBAAECggEABNGLSd5jHNpaf719/ssnQwdWGWj/wvLoScx+w1zDJNfB
9 | V06BxrNysNGReFjTBvtVKawi38uJk/vPbKwpQI/RK21w5oM6QaiCzQkmn6zEYI84
10 | bpuO7xwWFFDqRerhKGqmdYp5pKJyw3G6Qe+++tp5k+0J0ANXvpJVT6vVxmKPBMpe
11 | 3KkylxBqe7rNOorjYpfuLu4/z0jtz+xCOdI3y9F3Jl/FMyE6NAGCVEWKnoAK4EOv
12 | nz33jo8DUan+pSi/ssJbOqxfnkBE9yFcrytpMjTeCff/LcbHDi1gdhGn7iKc/QxE
13 | PA98yzSOZeWgR5RbBEJEQb5831VRr6Gt2b0qU9JldQKBgQDYxAbAkASMSViP5THp
14 | djk0+daExKQ4GVKMi5RI6BHQKJq75H7JWQ5zArvxL1AyEpMac0Q6w0FIxnbkiYKV
15 | tmc6kjmjbsgA+ml02nJtmfNizIf9Z9Op1dWfc3maRkiYqEl5GS0h7a2a/rtV+OC5
16 | olCwiLFy7ch0Ik/fjhTsy0fIBwKBgQDUBh0DUrrp6C+yeQZX9WIM9C7qZODZlYCU
17 | waUIibL/JPjv8zA5WBRjbvmn+QyafwjRbN+yiboeWbrdaNH7U1cyjb85O81G2SAM
18 | BK9yTiBuvRi1sk3H9KKG628Gjb93uyIN7htLcZGUYlkff5h2fYJHPpOd6lZU0bUs
19 | ZQZ6QaUfgwKBgCJTWGZh5/Z3HukaeD7qE8EJ1yiLIx4nFGVhLQgmh7uY0nfyhQlJ
20 | avpXcn+M6HwlaNoFasaLaOknVGh4Rg+DJPGnei0hO9a70LtKZFhqypnYnahJKsF4
21 | NS3c0WLWwmQ6MfhVPkpjItyqfevtT1jWFUT/QGpcsSOC03cpPrMItcM9AoGALvfj
22 | uXa8PVDYMBsrUpTjUadONVJ/lPPPdiSnoIqQgoD4PH+M8UcXzScqWxGKvzbhBzOt
23 | ImnsNwj9okq0KY6+xE4uTEl5Ifa7aK4pB5NTD/UH4khLfr4suuKwx6zi+20TEC7t
24 | EPtpmotm3tlvNuB62bl9DgB5e3SxQ9JlavPb1m0CgYEAlXchlHeH3Q1xZ/ZBJEU4
25 | 47DuDH/D7NEDrZqp3Vnp++JEmHEF9kCXhC3XEYPfvigBqYHo2sKyUBTw4co9wzDr
26 | RClkDx5XnZCsXLQkSNcmnJQ+xgmzRKZUR3wOTsDPEHA3LEIS7E8+dlfvYM15Smh4
27 | +QqKuYGhfc3XT94YGjZaUpc=
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/config/webpack.common.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const path = require('path');
3 | const package = require('../package.json');
4 | const CopyWebpackPlugin = require('copy-webpack-plugin');
5 | const HtmlWebpackPlugin = require('html-webpack-plugin');
6 | const ExtractTextPlugin = require('extract-text-webpack-plugin');
7 | const autoprefixer = require('autoprefixer');
8 |
9 | const build = (() => {
10 | const timestamp = new Date().getTime();
11 | return {
12 | name: package.name,
13 | version: package.version,
14 | timestamp: timestamp,
15 | author: package.author
16 | };
17 | })();
18 |
19 | const entry = {
20 | vendor: [
21 | 'react',
22 | 'react-dom',
23 | 'core-js',
24 | 'office-ui-fabric-react'
25 | ],
26 | app: [
27 | 'react-hot-loader/patch',
28 | './index.tsx',
29 | ],
30 | 'function-file': '../function-file/function-file.ts'
31 | };
32 |
33 | const rules = [
34 | {
35 | test: /\.tsx?$/,
36 | use: [
37 | 'react-hot-loader/webpack',
38 | 'ts-loader'
39 | ],
40 | exclude: /node_modules/
41 | },
42 | {
43 | test: /\.css$/,
44 | use: ['style-loader', 'css-loader']
45 | },
46 | {
47 | test: /\.less$/,
48 | use: ['style-loader', 'css-loader', 'less-loader']
49 | },
50 | {
51 | test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
52 | use: {
53 | loader: 'file-loader',
54 | query: {
55 | name: 'assets/[name].[ext]'
56 | }
57 | }
58 | }
59 | ];
60 |
61 | const output = {
62 | path: path.resolve('dist'),
63 | publicPath: '/',
64 | filename: '[name].[hash].js',
65 | chunkFilename: '[id].[hash].chunk.js'
66 | };
67 |
68 | const WEBPACK_PLUGINS = [
69 | new webpack.NamedModulesPlugin(),
70 | new webpack.NoEmitOnErrorsPlugin(),
71 | new webpack.BannerPlugin({ banner: `${build.name} v.${build.version} (${build.timestamp}) © ${build.author}` }),
72 | new webpack.DefinePlugin({
73 | ENVIRONMENT: JSON.stringify({
74 | build: build
75 | })
76 | }),
77 | new webpack.LoaderOptionsPlugin({
78 | options: {
79 | postcss: [
80 | autoprefixer({ browsers: ['Safari >= 8', 'last 2 versions'] }),
81 | ],
82 | htmlLoader: {
83 | minimize: true
84 | }
85 | }
86 | })
87 | ];
88 |
89 | module.exports = {
90 | context: path.resolve('./src'),
91 | entry,
92 | output,
93 | resolve: {
94 | extensions: ['.js', '.jsx', '.ts', '.tsx', '.scss', '.css', '.html']
95 | },
96 | module: {
97 | rules,
98 | },
99 | optimization: {
100 | splitChunks: {
101 | chunks: 'async',
102 | minChunks: Infinity,
103 | name: 'vendor'
104 | }
105 | },
106 | plugins: [
107 | ...WEBPACK_PLUGINS,
108 | new ExtractTextPlugin('[name].[hash].css'),
109 | new HtmlWebpackPlugin({
110 | title: 'outlook-addin-using-react-demo',
111 | filename: 'index.html',
112 | template: './index.html',
113 | chunks: ['app', 'vendor', 'polyfills']
114 | }),
115 | new HtmlWebpackPlugin({
116 | title: 'outlook-addin-using-react-demo',
117 | filename: 'function-file/function-file.html',
118 | template: '../function-file/function-file.html',
119 | chunks: ['function-file']
120 | }),
121 | new CopyWebpackPlugin([
122 | {
123 | from: '../assets',
124 | ignore: ['*.scss'],
125 | to: 'assets',
126 | }
127 | ])
128 | ]
129 | };
--------------------------------------------------------------------------------
/config/webpack.dev.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const webpack = require('webpack');
4 | const webpackMerge = require('webpack-merge');
5 | const commonConfig = require('./webpack.common.js');
6 |
7 | module.exports = webpackMerge(commonConfig, {
8 | devtool: 'eval-source-map',
9 | devServer: {
10 | publicPath: '/',
11 | contentBase: path.resolve('dist'),
12 | hot: true,
13 | https: {
14 | key: fs.readFileSync('./certs/server.key'),
15 | cert: fs.readFileSync('./certs/server.crt'),
16 | cacert: fs.readFileSync('./certs/ca.crt')
17 | },
18 | compress: true,
19 | overlay: {
20 | warnings: false,
21 | errors: true
22 | },
23 | port: 3000,
24 | historyApiFallback: true
25 | },
26 | plugins: [
27 | new webpack.HotModuleReplacementPlugin()
28 | ]
29 | });
30 |
--------------------------------------------------------------------------------
/config/webpack.prod.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const webpackMerge = require('webpack-merge');
3 | const commonConfig = require('./webpack.common.js');
4 | const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
5 |
6 | module.exports = webpackMerge(commonConfig, {
7 | devtool: 'source-map',
8 |
9 | performance: {
10 | hints: "warning"
11 | },
12 |
13 | optimization: {
14 | minimize: true
15 | }
16 | });
17 |
18 |
--------------------------------------------------------------------------------
/function-file/function-file.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/function-file/function-file.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
3 | * See LICENSE in the project root for license information.
4 | */
5 |
6 | (() => {
7 | // The initialize function must be run each time a new page is loaded
8 | Office.initialize = () => {
9 | console.log("abc");
10 | };
11 |
12 | // Add any ui-less function here
13 | })();
14 |
--------------------------------------------------------------------------------
/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 | 17c6a1a1-9880-4e14-8d99-47c2f421d3ca
13 |
14 |
15 | 1.0.0.0
16 | tirthGajjar
17 | en-US
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | AppDomain1
32 | AppDomain2
33 | AppDomain3
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
52 |
53 |
54 | ReadWriteItem
55 |
56 |
57 |
58 | false
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "outlook-addin-using-react-demo",
3 | "description": "",
4 | "author": "",
5 | "version": "1.0.0",
6 | "scripts": {
7 | "clean": "rimraf dist && rimraf .awcache",
8 | "lint": "tslint --project tsconfig.json",
9 | "start": "webpack-dev-server --inline --mode development --config config/webpack.dev.js --progress",
10 | "sideload": "office-toolbox sideload -m manifest.xml -a Outlook",
11 | "build": "npm run clean && webpack --mode production --config config/webpack.prod.js --colors --progress --bail",
12 | "validate": "office-toolbox validate -m manifest.xml"
13 | },
14 | "dependencies": {
15 | "@microsoft/office-js-helpers": "^1.0.2",
16 | "core-js": "^2.6.1",
17 | "office-ui-fabric-react": "^6.138.1",
18 | "react": "^16.8.1",
19 | "react-dom": "^16.8.1"
20 | },
21 | "devDependencies": {
22 | "@types/office-js": "0.0.155",
23 | "@types/react": "^16.8.2",
24 | "@types/react-dom": "^16.8.0",
25 | "@types/react-hot-loader": "^4.1.0",
26 | "@types/webpack": "4.4.22",
27 | "@types/webpack-dev-server": "3.1.1",
28 | "autoprefixer": "6.7.7",
29 | "copy-webpack-plugin": "4.6.0",
30 | "css-loader": "0.27.3",
31 | "extract-text-webpack-plugin": "4.0.0-beta.0",
32 | "file-loader": "3.0.1",
33 | "html-webpack-plugin": "3.2.0",
34 | "less": "^3.9.0",
35 | "less-loader": "^4.1.0",
36 | "office-toolbox": "^0.1.0",
37 | "postcss-loader": "1.3.3",
38 | "react-hot-loader": "^3.1.3",
39 | "rimraf": "2.6.2",
40 | "style-loader": "0.23.0",
41 | "ts-loader": "^5.3.2",
42 | "tslint": "^5.12.0",
43 | "typescript": "^3.2.2",
44 | "webpack": "^4.28.3",
45 | "webpack-cli": "^3.1.2",
46 | "webpack-dev-server": "^3.1.14",
47 | "webpack-merge": "^4.1.5"
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/resource.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Readme
8 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | Hey, outlook-addin-using-react-demo is ready!
21 | Next steps:
22 |
23 | 1. Host the add-in website.
24 |
25 | 2. Sideload your add-in.
26 |
27 | 3. Build your Outlook Add-in using the Office JavaScript APIs .
28 |
29 | For more information, choose Next .
30 | You can also explore the links in the additional resources section.
31 |
32 |
33 |
34 | Host
35 |
36 | You can host your add-in locally or use any web server. Make sure that the add-in is served using HTTPS and
37 | also update the add-in’s source location in the manifest.
38 |
39 | To help you get started, we have included webpack-dev-server for your convenience. To learn more about it, see the documentation
40 | here.
41 |
42 |
43 |
44 | npm start
45 |
46 | You will need to add the self-signed security certificate that npm creates as a trusted root certificate,
47 | or your add-in will not display. You only need to do this once for all add-ins hosted this way.
48 |
49 |
50 |
51 | https://localhost:3000
52 |
53 |
54 | See our documentation for information about adding the self-signed certificates.
55 |
56 |
57 | Sideload
58 |
59 |
60 | Load the add-in into Outlook. The easiest way to do this is by sideloading the add-in using the in-client Office Store UI.
61 |
62 | 1. Open the Office Store, either in Outlook 2016 for Windows or Outlook on the web:
63 |
64 | - In Outlook 2016 for Windows, choose the Store button on the Home tab.
65 |
66 | - In Outlook on the web, choose the gear icon in the upper-right corner, then choose Manage integrations .
67 |
68 | 2. Click the text Click here to add a custom add-in.
69 |
70 | 3. Choose Add from file... .
71 |
72 | 4. Browse to and select the manifest.xml file from the root of the project folder, and then choose Open .
73 |
74 | 5. Review the warning prompt and choose Install .
75 |
76 | 6. Close the Office Store window. Your add-in will load in Outlook .
77 |
78 |
79 |
80 |
81 |
82 | Build
83 | Here's some advice for building a stellar add-in:
84 |
85 | - Use the Design Patterns to create a rich and immersive UI.
86 |
87 | - Use the Office Helpers to simplify Authentication, Storage management etc.
88 |
89 | - Use the included Office Add-in Validator to ensure your manifest.xml file is correct and complete. It will also give you information on against what platforms to test your add-in before submitting to the store.
90 |
91 | $ npm run validate manifest.xml
92 | - Ensure your add-in works on all browsers and platforms that Office supports .
93 |
94 | For more information and resources to help you develop your add-in project, follow through the next steps
95 | or click on the additional resources to help you get started.
96 |
97 |
98 |
99 |
103 |
104 |
105 | Additional resources
106 |
134 |
135 |
136 |
139 |
140 |
143 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | /* global Office */
2 | import * as React from 'react';
3 | // import './App.css';
4 |
5 | //Importing Layout classes https://developer.microsoft.com/en-us/fabric#/styles/layout
6 | // import 'office-ui-fabric-core/dist/css/fabric.min.css'
7 |
8 | import { DatePicker } from 'office-ui-fabric-react/lib/DatePicker';
9 | import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
10 | import { TextField } from 'office-ui-fabric-react/lib/TextField';
11 | import { Dropdown } from 'office-ui-fabric-react/lib/Dropdown';
12 | import { initializeIcons } from '@uifabric/icons';
13 |
14 | class App extends React.Component {
15 | officeMailBoxItem = Office.context.mailbox.item;
16 |
17 | constructor(props) {
18 | super(props);
19 | this.setSubject("Tracked Email");
20 |
21 | this.getEmailList();
22 |
23 | //Without this line Datepicker calendar icon and dropdown caret icon does not display
24 | initializeIcons();
25 | }
26 |
27 | emailDetails = {
28 | subject: '',
29 | reason: '',
30 | startDate: new Date(),
31 | endDate: new Date(),
32 | leaveType: {
33 | text: ''
34 | },
35 | };
36 |
37 | setSubject = (subject) => {
38 | this.emailDetails.subject = subject;
39 | this.officeMailBoxItem.subject.setAsync(subject);
40 | };
41 |
42 | setStartDate = (value) => {
43 | let date = new Date(value);
44 | this.emailDetails.startDate = date;
45 | };
46 |
47 | setEndDate = (value) => {
48 | let date = new Date(value);
49 | this.emailDetails.endDate = date;
50 | };
51 |
52 | setLeaveType = (option) => {
53 | this.emailDetails.leaveType = option;
54 | };
55 |
56 | setReason = (value) => {
57 | this.emailDetails.reason = value;
58 | };
59 |
60 | createMessage = () => {
61 | this.officeMailBoxItem.body.prependAsync(
62 | '' +
63 | ' Hi, ' +
64 | 'I am on ' + this.emailDetails.leaveType.text + ' from ' + this.emailDetails.startDate.toLocaleDateString() + ' to ' + this.emailDetails.endDate.toLocaleDateString() +
65 | ', because ' + this.emailDetails.reason + '. ' +
66 | 'Thank you.' +
67 | '
',
68 | { coercionType: Office.CoercionType.Html })
69 | };
70 |
71 | getEmailList = () => {
72 |
73 | let setEmail = () => {
74 | this.officeMailBoxItem.to.setAsync(["tirthg@saleshandyonmicrosoft.com"]);
75 | };
76 | setEmail();
77 | };
78 |
79 | render() {
80 | return (
81 |
82 |
83 |
84 |
90 |
91 |
92 |
93 |
99 |
100 |
101 |
102 |
112 |
113 |
114 |
115 |
124 |
125 |
126 |
127 |
128 | Apply
129 |
130 |
131 |
132 |
133 | );
134 | }
135 | }
136 |
137 | export default App;
--------------------------------------------------------------------------------
/src/components/Header.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export interface HeaderProps {
4 | title: string;
5 | logo: string;
6 | message: string;
7 | }
8 |
9 | export default class Header extends React.Component {
10 | render() {
11 | const {
12 | title,
13 | logo,
14 | message
15 | } = this.props;
16 |
17 | return (
18 |
19 |
20 | {message}
21 |
22 | );
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/HeroList.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export interface HeroListItem {
4 | icon: string;
5 | primaryText: string;
6 | }
7 |
8 | export interface HeroListProps {
9 | message: string;
10 | items: HeroListItem[]
11 | }
12 |
13 | export default class HeroList extends React.Component {
14 | render() {
15 | const {
16 | children,
17 | items,
18 | message,
19 | } = this.props;
20 |
21 | const listItems = items.map((item, index) => (
22 |
23 |
24 | {item.primaryText}
25 |
26 | ));
27 | return (
28 |
29 | {message}
30 |
33 | {children}
34 |
35 | );
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/components/Progress.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { Spinner, SpinnerType } from 'office-ui-fabric-react';
3 |
4 | export interface ProgressProps {
5 | logo: string;
6 | message: string;
7 | title: string;
8 | }
9 |
10 | export default class Progress extends React.Component {
11 | render() {
12 | const {
13 | logo,
14 | message,
15 | title,
16 | } = this.props;
17 |
18 | return (
19 |
20 |
21 | {title}
22 |
23 |
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | outlook-addin-using-react-demo
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import * as ReactDOM from 'react-dom';
3 | import { AppContainer } from 'react-hot-loader';
4 | import { initializeIcons } from 'office-ui-fabric-react/lib/Icons';
5 |
6 | import App from './components/App';
7 | import registerServiceWorker from './registerServiceWorker';
8 |
9 | import './styles.less';
10 | import 'office-ui-fabric-react/dist/css/fabric.min.css';
11 |
12 | initializeIcons();
13 |
14 | let isOfficeInitialized = false;
15 |
16 | const title = 'outlook-addin-using-react-demo';
17 |
18 | const render = (Component) => {
19 | ReactDOM.render(
20 |
21 |
22 | ,
23 | document.getElementById('container')
24 | );
25 | };
26 |
27 | /* Render application after Office initializes */
28 | Office.initialize = () => {
29 | isOfficeInitialized = true;
30 | render(App);
31 | };
32 |
33 | /* Initial render showing a progress bar */
34 | render(App);
35 |
36 | if ((module as any).hot) {
37 | (module as any).hot.accept('./components/App', () => {
38 | const NextApp = require('./components/App').default;
39 | render(NextApp);
40 | });
41 | }
42 |
43 | registerServiceWorker();
--------------------------------------------------------------------------------
/src/registerServiceWorker.js:
--------------------------------------------------------------------------------
1 | // In production, we register a service worker to serve assets from local cache.
2 |
3 | // This lets the app load faster on subsequent visits in production, and gives
4 | // it offline capabilities. However, it also means that developers (and users)
5 | // will only see deployed updates on the "N+1" visit to a page, since previously
6 | // cached resources are updated in the background.
7 |
8 | // To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
9 | // This link also includes instructions on opting out of this behavior.
10 |
11 | const isLocalhost = Boolean(
12 | window.location.hostname === 'localhost' ||
13 | // [::1] is the IPv6 localhost address.
14 | window.location.hostname === '[::1]' ||
15 | // 127.0.0.1/8 is considered localhost for IPv4.
16 | window.location.hostname.match(
17 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
18 | )
19 | );
20 |
21 | export default function register() {
22 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
23 | // The URL constructor is available in all browsers that support SW.
24 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
25 | if (publicUrl.origin !== window.location.origin) {
26 | // Our service worker won't work if PUBLIC_URL is on a different origin
27 | // from what our page is served on. This might happen if a CDN is used to
28 | // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
29 | return;
30 | }
31 |
32 | window.addEventListener('load', () => {
33 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
34 |
35 | if (isLocalhost) {
36 | // This is running on localhost. Lets check if a service worker still exists or not.
37 | checkValidServiceWorker(swUrl);
38 |
39 | // Add some additional logging to localhost, pointing developers to the
40 | // service worker/PWA documentation.
41 | navigator.serviceWorker.ready.then(() => {
42 | console.log(
43 | 'This web app is being served cache-first by a service ' +
44 | 'worker. To learn more, visit https://goo.gl/SC7cgQ'
45 | );
46 | });
47 | } else {
48 | // Is not local host. Just register service worker
49 | registerValidSW(swUrl);
50 | }
51 | });
52 | }
53 | }
54 |
55 | function registerValidSW(swUrl) {
56 | navigator.serviceWorker
57 | .register(swUrl)
58 | .then(registration => {
59 | registration.onupdatefound = () => {
60 | const installingWorker = registration.installing;
61 | installingWorker.onstatechange = () => {
62 | if (installingWorker.state === 'installed') {
63 | if (navigator.serviceWorker.controller) {
64 | // At this point, the old content will have been purged and
65 | // the fresh content will have been added to the cache.
66 | // It's the perfect time to display a "New content is
67 | // available; please refresh." message in your web app.
68 | console.log('New content is available; please refresh.');
69 | } else {
70 | // At this point, everything has been precached.
71 | // It's the perfect time to display a
72 | // "Content is cached for offline use." message.
73 | console.log('Content is cached for offline use.');
74 | }
75 | }
76 | };
77 | };
78 | })
79 | .catch(error => {
80 | console.error('Error during service worker registration:', error);
81 | });
82 | }
83 |
84 | function checkValidServiceWorker(swUrl) {
85 | // Check if the service worker can be found. If it can't reload the page.
86 | fetch(swUrl)
87 | .then(response => {
88 | // Ensure service worker exists, and that we really are getting a JS file.
89 | if (
90 | response.status === 404 ||
91 | response.headers.get('content-type').indexOf('javascript') === -1
92 | ) {
93 | // No service worker found. Probably a different app. Reload the page.
94 | navigator.serviceWorker.ready.then(registration => {
95 | registration.unregister().then(() => {
96 | window.location.reload();
97 | });
98 | });
99 | } else {
100 | // Service worker found. Proceed as normal.
101 | registerValidSW(swUrl);
102 | }
103 | })
104 | .catch(() => {
105 | console.log(
106 | 'No internet connection found. App is running in offline mode.'
107 | );
108 | });
109 | }
110 |
111 | export function unregister() {
112 | if ('serviceWorker' in navigator) {
113 | navigator.serviceWorker.ready.then(registration => {
114 | registration.unregister();
115 | });
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/styles.less:
--------------------------------------------------------------------------------
1 | .flex-row {
2 | display: flex;
3 | flex-direction: row;
4 | flex-wrap: nowrap;
5 | }
6 |
7 | .flex-column {
8 | display: flex;
9 | flex-direction: column;
10 | flex-wrap: nowrap;
11 | }
12 |
13 | .flex-align(@mainAxis: center; @crossAxis: center) {
14 | justify-content: @mainAxis;
15 | align-items: @crossAxis;
16 | }
17 |
18 | * {
19 | margin: 0;
20 | padding: 0;
21 | }
22 |
23 | html,
24 | body {
25 | width: 100%;
26 | height: 100%;
27 | margin: 0;
28 | padding: 0;
29 | }
30 |
31 | #container {
32 | height: 100%;
33 | width: 100%;
34 |
35 | .flex-column;
36 |
37 | &>div {
38 | height: 100%;
39 | width: 100%;
40 | }
41 | }
42 |
43 | .ms-welcome {
44 | position: relative;
45 |
46 | .flex-column;
47 |
48 | min-height: 500px;
49 | min-width: 320px;
50 | overflow: auto;
51 | overflow-x: hidden;
52 |
53 | &__progress,
54 | &__header {
55 | padding: 20px;
56 | padding-bottom: 30px;
57 |
58 | .flex-column;
59 | .flex-align(flex-end, center);
60 |
61 | h1 {
62 | margin-top: 30px;
63 | text-align: center;
64 | }
65 | }
66 |
67 | &__progress {
68 | height: 100vh;
69 |
70 | .flex-column;
71 | .flex-align(center, center);
72 |
73 | h1 {
74 | margin-bottom: 80px;
75 | }
76 |
77 | & .ms-Spinner {
78 | .ms-Spinner-label {
79 | color: #999;
80 | }
81 |
82 | .ms-Spinner-circle{
83 | color: #333333;
84 | border: 1.5px solid #CCC;
85 | border-top-color: #333333;
86 | }
87 | }
88 | }
89 |
90 | &__main {
91 | .flex-column;
92 | .flex-align(flex-start, center);
93 |
94 | flex: 1 0 0;
95 | padding: 30px 20px;
96 |
97 | h2 {
98 | width: 100%;
99 | text-align: center;
100 | }
101 | }
102 |
103 | &__features {
104 | list-style-type: none;
105 | margin-top: 30px;
106 | margin-bottom: 30px;
107 |
108 | &.ms-List .ms-ListItem {
109 | padding: 0px;
110 | padding-bottom: 20px;
111 | .flex-row;
112 | .flex-align(flex-start, center);
113 |
114 | & > .ms-Icon {
115 | font-size: 14pt;
116 | margin-right: 10px;
117 | }
118 | }
119 | }
120 |
121 | &__action {
122 | margin-top: 30px;
123 | }
124 | }
125 |
126 | @media (min-width: 0) and (max-width: 350px) {
127 | .ms-welcome__features {
128 | width: 100%;
129 | }
130 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "commonjs",
5 | "jsx": "react",
6 | "moduleResolution": "node",
7 | "sourceMap": true,
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "removeComments": false,
11 | "outDir": "dist",
12 | "allowUnusedLabels": false,
13 | "noImplicitReturns": true,
14 | "noUnusedParameters": true,
15 | "noUnusedLocals": true,
16 | "lib": [
17 | "es7",
18 | "dom"
19 | ],
20 | "pretty": true,
21 | "typeRoots": [
22 | "node_modules/@types"
23 | ]
24 | },
25 | "exclude": [
26 | "node_modules"
27 | ],
28 | "compileOnSave": false,
29 | "buildOnSave": false
30 | }
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-reference": true,
4 | "only-arrow-functions": [
5 | true,
6 | "allow-declarations"
7 | ],
8 | "no-namespace": [
9 | true,
10 | "allow-declarations"
11 | ],
12 | "class-name": true,
13 | "curly": true,
14 | "eofline": true,
15 | "forin": true,
16 | "indent": [
17 | true,
18 | "spaces"
19 | ],
20 | "label-position": true,
21 | "no-arg": true,
22 | "no-var-keyword": true,
23 | "no-console": [
24 | true,
25 | "debug",
26 | "info",
27 | "time",
28 | "timeEnd",
29 | "trace"
30 | ],
31 | "no-construct": true,
32 | "no-debugger": true,
33 | "no-duplicate-variable": true,
34 | "no-empty": false,
35 | "no-eval": true,
36 | "no-trailing-whitespace": true,
37 | "no-unused-expression": true,
38 | "no-use-before-declare": true,
39 | "one-line": [
40 | true,
41 | "check-open-brace",
42 | "check-whitespace"
43 | ],
44 | "quotemark": [
45 | true,
46 | "single"
47 | ],
48 | "radix": true,
49 | "semicolon": [
50 | true,
51 | "always",
52 | "ignore-interfaces"
53 | ],
54 | "triple-equals": [
55 | true,
56 | "allow-null-check"
57 | ],
58 | "variable-name": false,
59 | "whitespace": [
60 | true,
61 | "check-branch",
62 | "check-decl",
63 | "check-operator",
64 | "check-separator",
65 | "check-type"
66 | ]
67 | }
68 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const HtmlWebpackPlugin = require('html-webpack-plugin');
2 | const webpack = require("webpack");
3 |
4 | module.exports = {
5 | devtool: 'source-map',
6 | entry: {
7 | app: './src/index.ts',
8 | 'function-file': './function-file/function-file.ts'
9 | },
10 | resolve: {
11 | extensions: ['.ts', '.tsx', '.html', '.js']
12 | },
13 | module: {
14 | rules: [
15 | {
16 | test: /\.tsx?$/,
17 | exclude: /node_modules/,
18 | use: 'ts-loader'
19 | },
20 | {
21 | test: /\.html$/,
22 | exclude: /node_modules/,
23 | use: 'html-loader'
24 | },
25 | {
26 | test: /\.(png|jpg|jpeg|gif)$/,
27 | use: 'file-loader'
28 | }
29 | ]
30 | },
31 | plugins: [
32 | new HtmlWebpackPlugin({
33 | template: './index.html',
34 | chunks: ['app']
35 | }),
36 | new HtmlWebpackPlugin({
37 | template: './function-file/function-file.html',
38 | filename: 'function-file/function-file.html',
39 | chunks: ['function-file']
40 | }),
41 | new webpack.ProvidePlugin({
42 | Promise: ["es6-promise", "Promise"]
43 | })
44 | ]
45 | };
--------------------------------------------------------------------------------