├── .babelrc
├── .circleci
└── config.yml
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── build.sh
├── client
├── client.js
├── components
│ ├── FnAppForm.vue
│ ├── FnNotification.vue
│ ├── FnRouteForm.vue
│ ├── FnRunFunction.vue
│ ├── FnSidebar.vue
│ └── FnWelcomeSection.vue
├── css
│ ├── app.css
│ ├── fonts.css
│ ├── main.css
│ ├── sidebar.css
│ └── variables.css
├── fonts
│ ├── Open_Sans-italic-400.css
│ ├── Open_Sans-italic-400.eot
│ ├── Open_Sans-italic-400.svg
│ ├── Open_Sans-italic-400.ttf
│ ├── Open_Sans-italic-400.woff
│ ├── Open_Sans-italic-400.woff2
│ ├── Open_Sans-normal-300.eot
│ ├── Open_Sans-normal-300.svg
│ ├── Open_Sans-normal-300.ttf
│ ├── Open_Sans-normal-300.woff
│ ├── Open_Sans-normal-300.woff2
│ ├── Open_Sans-normal-400.eot
│ ├── Open_Sans-normal-400.svg
│ ├── Open_Sans-normal-400.ttf
│ ├── Open_Sans-normal-400.woff
│ ├── Open_Sans-normal-400.woff2
│ ├── Open_Sans-normal-700.eot
│ ├── Open_Sans-normal-700.svg
│ ├── Open_Sans-normal-700.ttf
│ ├── Open_Sans-normal-700.woff
│ ├── Open_Sans-normal-700.woff2
│ └── fonts.css
├── lib
│ ├── VueBootstrapModal.vue
│ └── helpers.js
└── pages
│ ├── AppPage.vue
│ └── IndexPage.vue
├── docs
└── screenshots
│ ├── add_route.png
│ ├── apps.png
│ ├── routes.png
│ └── run.png
├── package-lock.json
├── package.json
├── public
├── android-icon-144x144.png
├── android-icon-192x192.png
├── android-icon-36x36.png
├── android-icon-48x48.png
├── android-icon-72x72.png
├── android-icon-96x96.png
├── apple-icon-114x114.png
├── apple-icon-120x120.png
├── apple-icon-144x144.png
├── apple-icon-152x152.png
├── apple-icon-180x180.png
├── apple-icon-57x57.png
├── apple-icon-60x60.png
├── apple-icon-72x72.png
├── apple-icon-76x76.png
├── apple-icon-precomposed.png
├── apple-icon.png
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon-96x96.png
├── favicon.ico
├── fonts
│ ├── Open_Sans-italic-400.css
│ ├── Open_Sans-italic-400.eot
│ ├── Open_Sans-italic-400.svg
│ ├── Open_Sans-italic-400.ttf
│ ├── Open_Sans-italic-400.woff
│ ├── Open_Sans-italic-400.woff2
│ ├── Open_Sans-normal-300.eot
│ ├── Open_Sans-normal-300.svg
│ ├── Open_Sans-normal-300.ttf
│ ├── Open_Sans-normal-300.woff
│ ├── Open_Sans-normal-300.woff2
│ ├── Open_Sans-normal-400.eot
│ ├── Open_Sans-normal-400.svg
│ ├── Open_Sans-normal-400.ttf
│ ├── Open_Sans-normal-400.woff
│ ├── Open_Sans-normal-400.woff2
│ ├── Open_Sans-normal-700.eot
│ ├── Open_Sans-normal-700.svg
│ ├── Open_Sans-normal-700.ttf
│ ├── Open_Sans-normal-700.woff
│ ├── Open_Sans-normal-700.woff2
│ └── fonts.css
├── images
│ ├── icons
│ │ ├── github-logo.svg
│ │ ├── ic_close_24px.svg
│ │ ├── more_vert.svg
│ │ ├── plus.svg
│ │ └── wrench.svg
│ ├── ironfunctions-logo.svg
│ └── titan-logo.svg
├── index.html
├── manifest.json
├── ms-icon-144x144.png
├── ms-icon-150x150.png
├── ms-icon-310x310.png
└── ms-icon-70x70.png
├── release.sh
├── server.js
├── server
├── controllers
│ ├── apps.js
│ ├── info.js
│ └── routes.js
├── helpers
│ └── app-helpers.js
├── router.js
└── server.js
├── stylelint.config.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-2"],
3 | "plugins": ["transform-runtime"],
4 | "comments": false
5 | }
6 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | jobs:
3 | build:
4 | machine: true
5 | working_directory: ~/go/src/github.com/functions-ui
6 | environment:
7 | - GOPATH=/home/circleci/go
8 | - GOVERSION=1.8.3
9 | - OS=linux
10 | - ARCH=amd64
11 | steps:
12 | - checkout
13 | # update Docker
14 | - run: |
15 | docker version
16 | sudo service docker stop
17 | curl -fsSL https://get.docker.com/ | sudo sh
18 | - run: docker version
19 | - deploy:
20 | command: |
21 | if [ "${CIRCLE_BRANCH}" == "master" ]; then
22 | git config --global user.email "circleci@iron.io"
23 | git config --global user.name "CircleCI"
24 | docker login -u $DOCKER_USER -p $DOCKER_PASS
25 | ./release.sh
26 | git branch --set-upstream-to=origin/${CIRCLE_BRANCH} ${CIRCLE_BRANCH}
27 | fi
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /build
3 | /public/build
4 | /data
5 | npm-debug.log
6 | .DS_Store
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mhart/alpine-node:6.3
2 | MAINTAINER iron.io
3 |
4 | RUN mkdir /app
5 | WORKDIR /app
6 |
7 | # Install app dependencies
8 | RUN npm install webpack -g
9 | COPY package.json /app
10 | RUN npm install
11 |
12 | # Bundle app source
13 | COPY . /app
14 |
15 | # Build assets
16 | RUN webpack
17 |
18 | ENV NODE_ENV production
19 | ENV PORT 4000
20 | EXPOSE 4000
21 |
22 | CMD [ "npm", "start" ]
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2016 Iron.io
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UI for [IronFunctions](https://github.com/iron-io/functions)
2 |
3 | # Usage
4 |
5 | Just run the container.
6 | `API_URL` is IronFunctions API URL
7 | __NOTE: latest version is broken, please use 0.0.2__
8 |
9 | ```
10 | docker run --rm -it --link functions:api -p 4000:4000 -e "API_URL=http://api:8080" iron/functions-ui:0.0.2
11 | ```
12 |
13 | # Screenshots
14 |
15 | 
16 | 
17 |
18 | # Development
19 |
20 | 1) Install dependencies:
21 | ```
22 | npm install && npm install -g webpack
23 | ```
24 |
25 | 2) Start Functions API
26 | ```
27 | docker run --rm -it --name functions --privileged -v $PWD/data:/app/data -p 8080:8080 iron/functions
28 | ```
29 |
30 | 3) Start web server:
31 | ```
32 | PORT=4000 API_URL=http://localhost:8080 npm start
33 | ```
34 |
35 | * `PORT` - port to run UI on. Optional, 4000 by default
36 | * `API_URL` - Functions API URL. Required
37 |
38 | 4) Launch automatic asset recompilation:
39 | ```
40 | webpack --watch
41 | ```
42 |
43 | Example:
44 | ```
45 | # Launch Functions API
46 | docker run --rm -it --name functions --privileged -v $PWD/data:/app/data -p 8080:8080 iron/functions
47 |
48 | # Launch FunctionsUI (use `docker-machine ip` instead of localhost if needed - mac only)
49 | API_URL=http://localhost:8080 npm start
50 |
51 | # Launch launch automatic asset recompilation:
52 | webpack --watch
53 |
54 | # Open http://localhost:4000/ in browser
55 | ```
56 |
57 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | set -ex
2 |
3 | docker build -t iron/functions-ui:latest .
4 |
--------------------------------------------------------------------------------
/client/client.js:
--------------------------------------------------------------------------------
1 | require("./css/app.css");
2 |
3 | require('expose?$!expose?jQuery!jquery');
4 | require("bootstrap/dist/js/bootstrap.min");
5 |
6 | import _ from 'lodash/core';
7 |
8 | import Vue from 'vue';
9 | import VueRouter from 'vue-router';
10 | Vue.use(VueRouter);
11 |
12 | import IndexPage from './pages/IndexPage.vue';
13 | import AppPage from './pages/AppPage.vue';
14 |
15 | import FnSidebar from './components/FnSidebar.vue';
16 | import FnNotification from './components/FnNotification.vue';
17 | import { defaultErrorHandler } from './lib/helpers';
18 |
19 | export const eventBus = new Vue();
20 |
21 | const router = new VueRouter({
22 | routes: [
23 | { path: '/', component: IndexPage },
24 | { path: '/app/:appname', component: AppPage }
25 | ]
26 | });
27 |
28 | new Vue({
29 | router: router,
30 | data: {
31 | apps: null
32 | },
33 | components: {
34 | IndexPage,
35 | FnSidebar,
36 | FnNotification
37 | },
38 | methods: {
39 | loadApps: function(){
40 | var t = this;
41 | $.ajax({
42 | url: '/api/apps',
43 | dataType: 'json',
44 | success: (apps) => t.apps = apps,
45 | error: defaultErrorHandler
46 | })
47 | }
48 | },
49 | created: function(){
50 | this.loadApps();
51 | eventBus.$on('AppAdded', (app) => {
52 | this.loadApps()
53 | });
54 | eventBus.$on('AppUpdated', (app) => {
55 | this.loadApps()
56 | });
57 | eventBus.$on('AppDeleted', (app) => {
58 | this.loadApps()
59 | });
60 | }
61 | }).$mount('#app')
62 |
63 |
64 | //console.log("client initialized");
65 |
--------------------------------------------------------------------------------
/client/components/FnAppForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
36 |
37 |
38 | {{okBtnName()}}
39 |
40 |
41 |
42 |
43 |
121 |
122 |
132 |
--------------------------------------------------------------------------------
/client/components/FnNotification.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | × Close
6 |
7 |
8 |
9 |
10 |
45 |
46 |
72 |
--------------------------------------------------------------------------------
/client/components/FnRouteForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
112 |
113 |
114 | {{okBtnName()}}
115 |
116 |
117 |
118 |
119 |
223 |
224 |
234 |
--------------------------------------------------------------------------------
/client/components/FnRunFunction.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
42 |
43 |
44 | Run
45 |
46 |
47 |
48 |
49 |
127 |
128 |
--------------------------------------------------------------------------------
/client/components/FnSidebar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
46 |
47 |
50 |
--------------------------------------------------------------------------------
/client/components/FnWelcomeSection.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
40 |
41 |
42 |
43 |
46 |
--------------------------------------------------------------------------------
/client/css/app.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 | @import "./fonts.css";
3 | @import "./variables.css";
4 | @import "normalize-css/normalize.css";
5 | @import "font-awesome/css/font-awesome.css";
6 | @import "bootstrap/dist/css/bootstrap.min.css";
7 | @import "./sidebar.css";
8 | @import "./main.css";
9 |
10 | body {
11 | font-family: 'Open Sans', Helvetica, Arial, sans-serif;
12 | }
13 |
--------------------------------------------------------------------------------
/client/css/fonts.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Open Sans';
3 | font-style: normal;
4 | font-weight: 300;
5 | src: url(../fonts/Open_Sans-normal-300.woff) format('woff');
6 | unicode-range: U+0-10FFFF;
7 | }
8 |
9 | @font-face {
10 | font-family: 'Open Sans';
11 | font-style: normal;
12 | font-weight: 400;
13 | src: url(../fonts/Open_Sans-normal-400.woff) format('woff');
14 | unicode-range: U+0-10FFFF;
15 | }
16 |
17 | @font-face {
18 | font-family: 'Open Sans';
19 | font-style: normal;
20 | font-weight: 700;
21 | src: url(../fonts/Open_Sans-normal-700.woff) format('woff');
22 | unicode-range: U+0-10FFFF;
23 | }
24 |
25 | @font-face {
26 | font-family: 'Open Sans';
27 | font-style: italic;
28 | font-weight: 400;
29 | src: url(../fonts/Open_Sans-italic-400.woff) format('woff');
30 | unicode-range: U+0-10FFFF;
31 | }
32 |
33 |
34 | @font-face {
35 | font-family: "OpenSans-Italic";
36 | src: url("../fonts/Open_Sans-italic-400.eot");
37 | src: url("../fonts/Open_Sans-italic-400.eot?#iefix") format("embedded-opentype"),
38 | url("../fonts/Open_Sans-italic-400.woff2") format("woff2"),
39 | url("../fonts/Open_Sans-italic-400.woff") format("woff"),
40 | url("../fonts/Open_Sans-italic-400.ttf") format("ttf"),
41 | url("../fonts/Open_Sans-italic-400.svg#OpenSans-Italic") format("svg");
42 | font-style: italic;
43 | font-weight: 300;
44 | }
45 |
46 | @font-face {
47 | font-family: "OpenSans-Light";
48 | src: url("../fonts/Open_Sans-normal-300.eot");
49 | src: url("../fonts/Open_Sans-normal-300.eot?#iefix") format("embedded-opentype"),
50 | url("../fonts/Open_Sans-normal-300.woff2") format("woff2"),
51 | url("../fonts/Open_Sans-normal-300.woff") format("woff"),
52 | url("../fonts/Open_Sans-normal-300.ttf") format("ttf"),
53 | url("../fonts/Open_Sans-normal-300.svg#OpenSans-Light") format("svg");
54 | font-style: normal;
55 | font-weight: 300;
56 | }
57 |
58 | @font-face {
59 | font-family: "OpenSans";
60 | src: url("../fonts/Open_Sans-normal-400.eot");
61 | src: url("../fonts/Open_Sans-normal-400.eot?#iefix") format("embedded-opentype"),
62 | url("../fonts/Open_Sans-normal-400.woff2") format("woff2"),
63 | url("../fonts/Open_Sans-normal-400.woff") format("woff"),
64 | url("../fonts/Open_Sans-normal-400.ttf") format("ttf"),
65 | url("../fonts/Open_Sans-normal-400.svg#OpenSans") format("svg");
66 | font-style: normal;
67 | font-weight: 300;
68 | }
69 |
70 | @font-face {
71 | font-family: "OpenSans-Bold";
72 | src: url("../fonts/Open_Sans-normal-700.eot");
73 | src: url("../fonts/Open_Sans-normal-700.eot?#iefix") format("embedded-opentype"),
74 | url("../fonts/Open_Sans-normal-700.woff2") format("woff2"),
75 | url("../fonts/Open_Sans-normal-700.woff") format("woff"),
76 | url("../fonts/Open_Sans-normal-700.ttf") format("ttf"),
77 | url("../fonts/Open_Sans-normal-700.svg#OpenSans-Bold") format("svg");
78 | font-style: normal;
79 | font-weight: 700;
80 | }
81 |
--------------------------------------------------------------------------------
/client/css/main.css:
--------------------------------------------------------------------------------
1 | .main {
2 | padding: 20px;
3 |
4 | & .page-header {
5 | margin-top: 0;
6 | }
7 |
8 | & .dropdown-menu {
9 | border-radius: 1px;
10 | & > li > a {
11 | padding: 5px 10px;
12 | }
13 | }
14 |
15 | & .toolbar {
16 | & .btn-group {
17 | white-space: nowrap;
18 | display: flex;
19 |
20 | & .dropdown-toggle {
21 | border-left: 1px solid #DDD;
22 | }
23 | }
24 | & .btn {
25 | border: none;
26 | }
27 | & .fa {
28 | font-size: 1em;
29 | margin-right: 5px;
30 | }
31 | }
32 |
33 | & a.text-danger,
34 | & .text-danger,
35 | & a.text-danger:hover,
36 | & .text-danger:hover {
37 | color: #E74C3C;
38 | }
39 | }
40 |
41 | .table {
42 | & thead.transparent {
43 | opacity: .1;
44 | pointer-events: none;
45 | }
46 | & tbody tr .no-matches {
47 | text-align: center;
48 | width: 100%;
49 | z-index: 1;
50 | font-size: 30px;
51 | opacity: 1;
52 | color: #B8B8B8;
53 | margin: 40px 0;
54 | line-height: 1.5em;
55 | padding: 30px 0;
56 | }
57 | }
58 |
59 | @media (min-width: 768px) {
60 | .main {
61 | padding-right: 40px;
62 | padding-left: 40px;
63 |
64 | & .modal .modal-title {
65 | text-align: center;
66 | }
67 |
68 | & .modal-content {
69 | box-shadow: 0 5px 10px rgba(0,0,0,.25);
70 | border: none;
71 | border-radius: 2px;
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/client/css/sidebar.css:
--------------------------------------------------------------------------------
1 | /* Hide for mobile, show later */
2 | .sidebar {
3 | display: none;
4 | color: white;
5 | background: #2E2E2E;
6 |
7 | & .navbar-brand {
8 | float: none;
9 | display: block;
10 | padding: 0;
11 | margin-bottom: 30px;
12 | & svg {
13 | width: 100%;
14 | }
15 | }
16 |
17 | & h4 {
18 | margin-bottom: 30px;
19 | }
20 |
21 | & p {
22 | font-size: 12px;
23 | color: rgba(255,255,255,.35);
24 | border-bottom: 1px solid rgba(255,255,255,.1);
25 | padding-bottom: 20px;
26 | }
27 |
28 | & .welcome-section .fa {
29 | font-size: 30px;
30 | vertical-align: middle;
31 | margin-right: 10px;
32 | width: 25px;
33 | text-align: center;
34 | margin-left: -35px;
35 | }
36 | }
37 |
38 | @media (min-width: 768px) {
39 | .sidebar {
40 | position: fixed;
41 | top: 0;
42 | bottom: 0;
43 | left: 0;
44 | z-index: 1000;
45 | display: block;
46 | padding: 20px;
47 | overflow-x: hidden;
48 |
49 | /* Scrollable contents if viewport is shorter than content. */
50 | overflow-y: auto;
51 |
52 | /* Sidebar navigation */
53 | & .nav-sidebar {
54 | margin-right: -21px; /* 20px padding + 1px border */
55 | margin-bottom: 20px;
56 | margin-left: -20px;
57 |
58 | & > li > a {
59 | padding: 10px 10px 10px 20px;
60 | color: rgba(255,255,255,.75);
61 | }
62 | & > li > a:hover,
63 | & > li > a:focus,
64 | & > li > a:active:hover {
65 | color: white;
66 | background-color: rgba(#7E38FF, .25);
67 | }
68 | & > .active > a,
69 | & > .active > a:hover,
70 | & > .active > a:focus {
71 | color: white;
72 | background-color: #7E38FF;
73 | }
74 | }
75 |
76 | & .welcome-section .nav-sidebar > li > a {
77 | padding: 10px 5px 10px 55px;
78 | }
79 | }
80 | }
81 |
82 | .navbar-inverse {
83 | background-color: #2E2E2E;
84 | border: none;
85 | display: block;
86 |
87 | & .navbar-brand {
88 | padding: 13px 0 0 23px;
89 |
90 | & svg {
91 | width: 100px;
92 | }
93 | }
94 | }
95 |
96 | @media (min-width: 768px) {
97 | .navbar-inverse {
98 | display: none;
99 | }
100 | }
101 |
102 | #navbar .nav {
103 | & .fa {
104 | font-size: 30px;
105 | vertical-align: middle;
106 | margin-right: 10px;
107 | width: 25px;
108 | text-align: center;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/client/css/variables.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --logoYellow: #FFF200;
3 |
4 | /* --textColor: #66758B; */
5 | --textColor: rgba(58,68,82,.87);
6 | --text2ndColor: rgba(58,68,82,.5);
7 | --disabledColor: rgba(58,68,82,.3);
8 | --dividerColor: rgba(58,68,82,.1);
9 |
10 | --darkBgColor: #222D32;
11 | --textOnDColor: white;
12 | --text2ndOnDColor: rgba(#D8DFE2,.7);
13 | --textDisabledOnDColor: rgba(#D8DFE2,.3);
14 | --greyColor: #D2D6DE;
15 |
16 | --primaryColor: #0072A5;
17 | --accentColor: #FCB104;
18 | --warnColor: var(--redColor);
19 |
20 | --blueColor: #378CBE;
21 | --yellowColor: #F59D00;
22 | --redColor: #DF4A32;
23 | --greenColor: #00A757;
24 |
25 | --orangeColor: #FF8500;
26 | --maroonColor: #DA135F;
27 | --tealColor: #2DCCCD;
28 | --purpleColor: #605AAA;
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-italic-400.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "OpenSans-Italic";
3 | src: url("fonts/Open_Sans-italic-400.eot");
4 | src: url("fonts/Open_Sans-italic-400.eot?#iefix") format("embedded-opentype"),
5 | url("fonts/Open_Sans-italic-400.woff2") format("woff2"),
6 | url("fonts/Open_Sans-italic-400.woff") format("woff"),
7 | url("fonts/Open_Sans-italic-400.ttf") format("ttf"),
8 | url("fonts/Open_Sans-italic-400.svg#OpenSans-Italic") format("svg");
9 | font-style: italic;
10 | font-weight: 300;
11 | }
12 |
13 | @font-face {
14 | font-family: "OpenSans-Light";
15 | src: url("fonts/Open_Sans-normal-300.eot");
16 | src: url("fonts/Open_Sans-normal-300.eot?#iefix") format("embedded-opentype"),
17 | url("fonts/Open_Sans-normal-300.woff2") format("woff2"),
18 | url("fonts/Open_Sans-normal-300.woff") format("woff"),
19 | url("fonts/Open_Sans-normal-300.ttf") format("ttf"),
20 | url("fonts/Open_Sans-normal-300.svg#OpenSans-Light") format("svg");
21 | font-style: normal;
22 | font-weight: 300;
23 | }
24 |
25 | @font-face {
26 | font-family: "OpenSans";
27 | src: url("fonts/Open_Sans-normal-400.eot");
28 | src: url("fonts/Open_Sans-normal-400.eot?#iefix") format("embedded-opentype"),
29 | url("fonts/Open_Sans-normal-400.woff2") format("woff2"),
30 | url("fonts/Open_Sans-normal-400.woff") format("woff"),
31 | url("fonts/Open_Sans-normal-400.ttf") format("ttf"),
32 | url("fonts/Open_Sans-normal-400.svg#OpenSans") format("svg");
33 | font-style: normal;
34 | font-weight: 300;
35 | }
36 |
37 | @font-face {
38 | font-family: "OpenSans-Bold";
39 | src: url("fonts/Open_Sans-normal-700.eot");
40 | src: url("fonts/Open_Sans-normal-700.eot?#iefix") format("embedded-opentype"),
41 | url("fonts/Open_Sans-normal-700.woff2") format("woff2"),
42 | url("fonts/Open_Sans-normal-700.woff") format("woff"),
43 | url("fonts/Open_Sans-normal-700.ttf") format("ttf"),
44 | url("fonts/Open_Sans-normal-700.svg#OpenSans-Bold") format("svg");
45 | font-style: normal;
46 | font-weight: 700;
47 | }
48 |
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-italic-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-italic-400.eot
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-italic-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-italic-400.ttf
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-italic-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-italic-400.woff
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-italic-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-italic-400.woff2
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-300.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-300.eot
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-300.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-300.ttf
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-300.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-300.woff
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-300.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-300.woff2
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-400.eot
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-400.ttf
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-400.woff
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-400.woff2
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-700.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-700.eot
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-700.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-700.ttf
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-700.woff
--------------------------------------------------------------------------------
/client/fonts/Open_Sans-normal-700.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/client/fonts/Open_Sans-normal-700.woff2
--------------------------------------------------------------------------------
/client/fonts/fonts.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Open Sans';
3 | font-style: normal;
4 | font-weight: 300;
5 | src: url(Open_Sans-normal-300.woff) format('woff');
6 | unicode-range: U+0-10FFFF;
7 | }
8 |
9 | @font-face {
10 | font-family: 'Open Sans';
11 | font-style: normal;
12 | font-weight: 400;
13 | src: url(Open_Sans-normal-400.woff) format('woff');
14 | unicode-range: U+0-10FFFF;
15 | }
16 |
17 | @font-face {
18 | font-family: 'Open Sans';
19 | font-style: normal;
20 | font-weight: 700;
21 | src: url(Open_Sans-normal-700.woff) format('woff');
22 | unicode-range: U+0-10FFFF;
23 | }
24 |
25 | @font-face {
26 | font-family: 'Open Sans';
27 | font-style: italic;
28 | font-weight: 400;
29 | src: url(Open_Sans-italic-400.woff) format('woff');
30 | unicode-range: U+0-10FFFF;
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/client/lib/VueBootstrapModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
17 |
18 |
19 |
20 |
21 |
22 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
156 |
157 |
--------------------------------------------------------------------------------
/client/lib/helpers.js:
--------------------------------------------------------------------------------
1 | import { eventBus } from '../client';
2 |
3 |
4 |
5 | export const defaultErrorHandler = function(jqXHR){
6 | var text = "Something went terribly wrong (Status Code: " + jqXHR.status + ")"
7 | try {
8 | text = jqXHR.responseJSON.msg
9 | } catch (_err) {}
10 | eventBus.$emit('NotificationError', text);
11 | }
12 |
13 |
14 | // lines is array in format [{key: "", value: ""}]
15 | // config is key-value hash
16 | export const configToLines = function(config){
17 | config = config || {};
18 | var lines = [];
19 | var k;
20 | for (k in config) {
21 | lines.push({key: k, value: config[k]})
22 | };
23 | // Always show at least one empty line
24 | if (lines.length == 0) {
25 | lines.push({key: "", value: ""})
26 | }
27 | return lines;
28 | }
29 |
30 | export const linesToConfig = function(lines){
31 | var config = {};
32 | for (var k = 0, i = 0, len = lines.length; i < len; k = ++i) {
33 | var v = lines[k];
34 | if (v.key){
35 | config[v.key] = v.value;
36 | }
37 | }
38 | return config;
39 | }
40 |
41 | export const headersToLines = function(headers){
42 | headers = headers || {};
43 | var lines = [];
44 | var k;
45 | for (k in headers) {
46 | lines.push({key: k, value: headers[k][0]})
47 | };
48 | // Always show at least one empty line
49 | if (lines.length == 0) {
50 | lines.push({key: "", value: ""})
51 | }
52 | return lines;
53 | }
54 |
55 | export const linesToHeaders = function(lines){
56 | var headers = {};
57 | for (var k = 0, i = 0, len = lines.length; i < len; k = ++i) {
58 | var v = lines[k];
59 | if (v.key){
60 | headers[v.key] = [v.value];
61 | }
62 | }
63 | return headers;
64 | }
65 |
66 | export const getApiUrl = function(cb, errCb){
67 | var errCb = errCb || null;
68 | $.ajax({
69 | url: '/api/info/api-url',
70 | method: 'GET',
71 | contentType: "application/json",
72 | dataType: 'json',
73 | success: (res) => {
74 | cb(res.url)
75 | },
76 | error: function(jqXHR, textStatus, errorThrown){
77 | if (errCb){errCb(jqXHR, textStatus, errorThrown)}
78 | }
79 | })
80 | }
--------------------------------------------------------------------------------
/client/pages/AppPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Apps
5 | {{app.name}}
6 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | Path
26 | Image
27 | Type
28 | Memory
29 | MaxCC
30 | Timeout
31 | Idle Timeout
32 | Actions
33 |
34 |
35 |
36 | {{route.path}}
37 | {{route.image}}
38 | {{route.type}}
39 | {{route.memory}} MB
40 | {{route.max_concurrency}}
41 | {{route.timeout}}
42 | {{route.idle_timeout}}
43 |
44 |
65 |
66 |
67 |
68 |
69 |
70 | No Routes
71 |
72 |
73 |
74 |
75 |
76 | Loading...
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
193 |
194 |
197 |
--------------------------------------------------------------------------------
/client/pages/IndexPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Apps
6 |
7 |
8 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | Name
26 | Actions
27 |
28 |
29 |
30 |
31 | {{app.name}}
32 |
33 |
34 |
52 |
53 |
54 |
55 |
56 | No Apps
57 |
58 |
59 |
60 |
61 | Loading...
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
114 |
115 |
118 |
--------------------------------------------------------------------------------
/docs/screenshots/add_route.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/docs/screenshots/add_route.png
--------------------------------------------------------------------------------
/docs/screenshots/apps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/docs/screenshots/apps.png
--------------------------------------------------------------------------------
/docs/screenshots/routes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/docs/screenshots/routes.png
--------------------------------------------------------------------------------
/docs/screenshots/run.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/docs/screenshots/run.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "FunctionsUI",
3 | "description": "Functions UI",
4 | "version": "0.0.5",
5 | "private": true,
6 | "scripts": {
7 | "start": "node server"
8 | },
9 | "dependencies": {
10 | "body-parser": "^1.15.2",
11 | "exports-loader": "^0.6.3",
12 | "express": "^4.16.3",
13 | "file-loader": "^0.8.5",
14 | "imports-loader": "^0.6.5",
15 | "jsonwebtoken": "^8.1.1",
16 | "lodash": "^4.17.11",
17 | "request": "^2.88.0",
18 | "resolve-url-loader": "^1.4.3",
19 | "url-loader": "^1.1.1",
20 | "vue": "^2.1.6",
21 | "vue-router": "^2.1.1"
22 | },
23 | "devDependencies": {
24 | "autoprefixer": "^6.3.7",
25 | "babel-core": "^6.26.3",
26 | "babel-eslint": "^7.0.0",
27 | "babel-loader": "^6.0.0",
28 | "babel-plugin-transform-runtime": "^6.0.0",
29 | "babel-preset-es2015": "^6.0.0",
30 | "babel-preset-stage-2": "^6.0.0",
31 | "babel-register": "^6.0.0",
32 | "bootstrap": "^3.3.7",
33 | "css-loader": "^0.23.1",
34 | "cssnano": "^3.7.1",
35 | "expose-loader": "^0.7.1",
36 | "extract-text-webpack-plugin": "^1.0.1",
37 | "font-awesome": "^4.7.0",
38 | "jquery": "^3.1.0",
39 | "modernizr": "^3.6.0",
40 | "modernizr-webpack-plugin": "^1.0.7",
41 | "normalize-css": "^2.3.1",
42 | "normalize.css": "^4.2.0",
43 | "postcss-cssnext": "^2.7.0",
44 | "postcss-font-magician": "^1.4.0",
45 | "postcss-fontpath": "^0.3.0",
46 | "postcss-hexrgba": "^0.2.0",
47 | "postcss-import": "^8.1.2",
48 | "postcss-loader": "^0.9.1",
49 | "postcss-url": "^7.3.0",
50 | "style-loader": "^0.13.0",
51 | "stylelint": "^7.1.0",
52 | "stylelint-loader": "^6.2.0",
53 | "vue-loader": "^10.0.2",
54 | "vue-template-compiler": "^2.0.0",
55 | "webpack": "^1.14.0"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/public/android-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/android-icon-144x144.png
--------------------------------------------------------------------------------
/public/android-icon-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/android-icon-192x192.png
--------------------------------------------------------------------------------
/public/android-icon-36x36.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/android-icon-36x36.png
--------------------------------------------------------------------------------
/public/android-icon-48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/android-icon-48x48.png
--------------------------------------------------------------------------------
/public/android-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/android-icon-72x72.png
--------------------------------------------------------------------------------
/public/android-icon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/android-icon-96x96.png
--------------------------------------------------------------------------------
/public/apple-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-114x114.png
--------------------------------------------------------------------------------
/public/apple-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-120x120.png
--------------------------------------------------------------------------------
/public/apple-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-144x144.png
--------------------------------------------------------------------------------
/public/apple-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-152x152.png
--------------------------------------------------------------------------------
/public/apple-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-180x180.png
--------------------------------------------------------------------------------
/public/apple-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-57x57.png
--------------------------------------------------------------------------------
/public/apple-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-60x60.png
--------------------------------------------------------------------------------
/public/apple-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-72x72.png
--------------------------------------------------------------------------------
/public/apple-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-76x76.png
--------------------------------------------------------------------------------
/public/apple-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon-precomposed.png
--------------------------------------------------------------------------------
/public/apple-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/apple-icon.png
--------------------------------------------------------------------------------
/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/favicon-16x16.png
--------------------------------------------------------------------------------
/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/favicon-32x32.png
--------------------------------------------------------------------------------
/public/favicon-96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/favicon-96x96.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/favicon.ico
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-italic-400.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "OpenSans-Italic";
3 | src: url("fonts/Open_Sans-italic-400.eot");
4 | src: url("fonts/Open_Sans-italic-400.eot?#iefix") format("embedded-opentype"),
5 | url("fonts/Open_Sans-italic-400.woff2") format("woff2"),
6 | url("fonts/Open_Sans-italic-400.woff") format("woff"),
7 | url("fonts/Open_Sans-italic-400.ttf") format("ttf"),
8 | url("fonts/Open_Sans-italic-400.svg#OpenSans-Italic") format("svg");
9 | font-style: italic;
10 | font-weight: 300;
11 | }
12 |
13 | @font-face {
14 | font-family: "OpenSans-Light";
15 | src: url("fonts/Open_Sans-normal-300.eot");
16 | src: url("fonts/Open_Sans-normal-300.eot?#iefix") format("embedded-opentype"),
17 | url("fonts/Open_Sans-normal-300.woff2") format("woff2"),
18 | url("fonts/Open_Sans-normal-300.woff") format("woff"),
19 | url("fonts/Open_Sans-normal-300.ttf") format("ttf"),
20 | url("fonts/Open_Sans-normal-300.svg#OpenSans-Light") format("svg");
21 | font-style: normal;
22 | font-weight: 300;
23 | }
24 |
25 | @font-face {
26 | font-family: "OpenSans";
27 | src: url("fonts/Open_Sans-normal-400.eot");
28 | src: url("fonts/Open_Sans-normal-400.eot?#iefix") format("embedded-opentype"),
29 | url("fonts/Open_Sans-normal-400.woff2") format("woff2"),
30 | url("fonts/Open_Sans-normal-400.woff") format("woff"),
31 | url("fonts/Open_Sans-normal-400.ttf") format("ttf"),
32 | url("fonts/Open_Sans-normal-400.svg#OpenSans") format("svg");
33 | font-style: normal;
34 | font-weight: 300;
35 | }
36 |
37 | @font-face {
38 | font-family: "OpenSans-Bold";
39 | src: url("fonts/Open_Sans-normal-700.eot");
40 | src: url("fonts/Open_Sans-normal-700.eot?#iefix") format("embedded-opentype"),
41 | url("fonts/Open_Sans-normal-700.woff2") format("woff2"),
42 | url("fonts/Open_Sans-normal-700.woff") format("woff"),
43 | url("fonts/Open_Sans-normal-700.ttf") format("ttf"),
44 | url("fonts/Open_Sans-normal-700.svg#OpenSans-Bold") format("svg");
45 | font-style: normal;
46 | font-weight: 700;
47 | }
48 |
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-italic-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-italic-400.eot
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-italic-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-italic-400.ttf
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-italic-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-italic-400.woff
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-italic-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-italic-400.woff2
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-300.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-300.eot
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-300.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-300.ttf
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-300.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-300.woff
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-300.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-300.woff2
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-400.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-400.eot
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-400.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-400.ttf
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-400.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-400.woff
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-400.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-400.woff2
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-700.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-700.eot
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-700.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-700.ttf
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-700.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-700.woff
--------------------------------------------------------------------------------
/public/fonts/Open_Sans-normal-700.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/fonts/Open_Sans-normal-700.woff2
--------------------------------------------------------------------------------
/public/fonts/fonts.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Open Sans';
3 | font-style: normal;
4 | font-weight: 300;
5 | src: url(Open_Sans-normal-300.woff) format('woff');
6 | unicode-range: U+0-10FFFF;
7 | }
8 |
9 | @font-face {
10 | font-family: 'Open Sans';
11 | font-style: normal;
12 | font-weight: 400;
13 | src: url(Open_Sans-normal-400.woff) format('woff');
14 | unicode-range: U+0-10FFFF;
15 | }
16 |
17 | @font-face {
18 | font-family: 'Open Sans';
19 | font-style: normal;
20 | font-weight: 700;
21 | src: url(Open_Sans-normal-700.woff) format('woff');
22 | unicode-range: U+0-10FFFF;
23 | }
24 |
25 | @font-face {
26 | font-family: 'Open Sans';
27 | font-style: italic;
28 | font-weight: 400;
29 | src: url(Open_Sans-italic-400.woff) format('woff');
30 | unicode-range: U+0-10FFFF;
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/public/images/icons/github-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/images/icons/ic_close_24px.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/icons/more_vert.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/images/icons/plus.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/images/icons/wrench.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/images/ironfunctions-logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/public/images/titan-logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Functions UI
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 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "App",
3 | "icons": [
4 | {
5 | "src": "\/android-icon-36x36.png",
6 | "sizes": "36x36",
7 | "type": "image\/png",
8 | "density": "0.75"
9 | },
10 | {
11 | "src": "\/android-icon-48x48.png",
12 | "sizes": "48x48",
13 | "type": "image\/png",
14 | "density": "1.0"
15 | },
16 | {
17 | "src": "\/android-icon-72x72.png",
18 | "sizes": "72x72",
19 | "type": "image\/png",
20 | "density": "1.5"
21 | },
22 | {
23 | "src": "\/android-icon-96x96.png",
24 | "sizes": "96x96",
25 | "type": "image\/png",
26 | "density": "2.0"
27 | },
28 | {
29 | "src": "\/android-icon-144x144.png",
30 | "sizes": "144x144",
31 | "type": "image\/png",
32 | "density": "3.0"
33 | },
34 | {
35 | "src": "\/android-icon-192x192.png",
36 | "sizes": "192x192",
37 | "type": "image\/png",
38 | "density": "4.0"
39 | }
40 | ]
41 | }
--------------------------------------------------------------------------------
/public/ms-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/ms-icon-144x144.png
--------------------------------------------------------------------------------
/public/ms-icon-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/ms-icon-150x150.png
--------------------------------------------------------------------------------
/public/ms-icon-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/ms-icon-310x310.png
--------------------------------------------------------------------------------
/public/ms-icon-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/public/ms-icon-70x70.png
--------------------------------------------------------------------------------
/release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -ex
4 |
5 | # ensure working dir is clean
6 | git status
7 | if [[ -z $(git status -s) ]]
8 | then
9 | echo "tree is clean"
10 | else
11 | echo "tree is dirty, please commit changes before running this"
12 | exit 1
13 | fi
14 |
15 | image="iron/functions-ui"
16 |
17 | git pull
18 |
19 | version_file="package.json"
20 | if [ -z $(grep -m1 -Eo "[0-9]+\.[0-9]+\.[0-9]+" $version_file) ]; then
21 | echo "did not find semantic version in $version_file"
22 | exit 1
23 | fi
24 | # https://github.com/treeder/dockers/tree/master/bump
25 | docker run --rm -it -v $PWD:/app -w /app treeder/bump --filename package.json patch
26 | version=$(grep -m1 -Eo "[0-9]+\.[0-9]+\.[0-9]+" $version_file)
27 | echo "Version: $version"
28 |
29 | ./build.sh
30 |
31 | tag="$version"
32 | git add -u
33 | git commit -m "functions-ui: $version [skip ci]"
34 | git tag -f -a $tag -m "functions-ui: $version"
35 | git push
36 | git push origin $tag
37 |
38 | docker tag $image:latest $image:$version
39 | docker push $image:$version
40 | docker push $image:latest
41 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var path = require('path');
3 | var url = require('url');
4 | var bodyParser = require('body-parser');
5 |
6 | var helpers = require('./server/helpers/app-helpers.js');
7 |
8 | var app = express();
9 |
10 | var isProduction = process.env.NODE_ENV === 'production';
11 | var apiUrl = url.parse(process.env.API_URL);
12 | if (!apiUrl || !apiUrl.hostname) {
13 | console.log("API URL not set. Please specify Functions API URL via environment variable, e.g. API_URL=http://localhost:8080 npm start");
14 | process.exit(1);
15 | }
16 |
17 | app.set('api-url', apiUrl);
18 | var port = process.env.PORT || 4000;
19 | var publicPath = path.resolve(__dirname, 'public');
20 |
21 | app.use(express.static(publicPath));
22 | app.use(bodyParser.json());
23 |
24 | app.use(require('./server/router.js'));
25 |
26 | app.disable('etag');
27 |
28 | app.listen(port, function () {
29 | console.log('Using API url: ' + apiUrl.host);
30 | console.log('Server running on port ' + port);
31 | });
--------------------------------------------------------------------------------
/server/controllers/apps.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var helpers = require('../helpers/app-helpers.js');
4 |
5 | router.get('/', function(req, res) {
6 | successcb = function(data){
7 | res.json(data.apps);
8 | }
9 |
10 | helpers.getApiEndpoint(req, "/v1/apps", {}, successcb, helpers.standardErrorcb(res))
11 | });
12 |
13 | router.get('/:app', function(req, res) {
14 | successcb = function(data){
15 | res.json(data.app);
16 | }
17 |
18 | helpers.getApiEndpoint(req, "/v1/apps/" + encodeURIComponent(req.params.app), {}, successcb, helpers.standardErrorcb(res))
19 | });
20 |
21 | // Create New App
22 | router.post('/', function(req, res) {
23 | successcb = function(data){
24 | res.json(data);
25 | }
26 | var data = req.body;
27 |
28 | helpers.postApiEndpoint(req, "/v1/apps", {}, {app: data}, successcb, helpers.standardErrorcb(res));
29 | });
30 |
31 | // Update App
32 | router.patch('/:app', function(req, res) {
33 | successcb = function(data){
34 | res.json(data);
35 | }
36 |
37 | var data = req.body;
38 | delete data.name;
39 |
40 | helpers.execApiEndpoint('PATCH', req, "/v1/apps/" + encodeURIComponent(req.params.app) , {}, {app: data}, successcb, helpers.standardErrorcb(res));
41 | });
42 |
43 | // Delete App
44 | router.delete('/:app', function(req, res) {
45 | successcb = function(data){
46 | res.json(data);
47 | }
48 |
49 | helpers.execApiEndpoint('DELETE', req, "/v1/apps/" + encodeURIComponent(req.params.app) , {}, {}, successcb, helpers.standardErrorcb(res));
50 | });
51 |
52 |
53 | module.exports = router;
54 |
--------------------------------------------------------------------------------
/server/controllers/info.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var url = require('url');
3 | var router = express.Router();
4 | var helpers = require('../helpers/app-helpers.js');
5 |
6 | router.get('/api-url', function(req, res) {
7 | var apiUrl = req.app.get('api-url');
8 | res.json({url: url.format(apiUrl)});
9 | });
10 |
11 | module.exports = router;
--------------------------------------------------------------------------------
/server/controllers/routes.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 | var jwt = require('jsonwebtoken');
4 | var helpers = require('../helpers/app-helpers.js');
5 |
6 | router.get('/:app/routes', function(req, res) {
7 | var successcb = function(data){
8 | res.json(data.routes);
9 | }
10 |
11 | helpers.getApiEndpoint(req, "/v1/apps/" + encodeURIComponent(req.params.app) + "/routes", {}, successcb, helpers.standardErrorcb(res))
12 | });
13 |
14 | // Create New Route
15 | router.post('/:app/routes', function(req, res) {
16 | var successcb = function(data){
17 | res.json(data);
18 | }
19 |
20 | helpers.postApiEndpoint(req, "/v1/apps/" + encodeURIComponent(req.params.app) + "/routes", {}, {route: req.body}, successcb, helpers.standardErrorcb(res));
21 | });
22 |
23 | // Update Route
24 | router.patch('/:app/routes/:route', function(req, res) {
25 | var successcb = function(data){
26 | res.json(data);
27 | }
28 | var data = req.body;
29 | delete data.path;
30 |
31 | helpers.execApiEndpoint('PATCH', req, "/v1/apps/" + encodeURIComponent(req.params.app)+ "/routes/" + encodeURIComponent(req.params.route), {}, {route: data}, successcb, helpers.standardErrorcb(res));
32 | });
33 |
34 | // Delete Route
35 | router.delete('/:app/routes/:route', function(req, res) {
36 | var successcb = function(data){
37 | res.json(data);
38 | }
39 |
40 | helpers.execApiEndpoint('DELETE', req, "/v1/apps/" + encodeURIComponent(req.params.app)+ "/routes/" + encodeURIComponent(req.params.route) , {}, {}, successcb, helpers.standardErrorcb(res));
41 | });
42 |
43 | // Run Route
44 | router.post('/:app/routes/:route/run', function(req, res) {
45 | var successcb = function(data){
46 | res.json({output: data});
47 | };
48 | var errcb = function(status, err){
49 | console.log("Error. Api responded with ", status, err);
50 | var text = "Something went terribly wrong (Status Code: " + status + ") ";
51 | if (err){
52 | try {
53 | var parsed = JSON.parse(err);
54 | if (parsed && parsed.error && parsed.error.message){
55 | text = parsed.error.message;
56 | }
57 | if (parsed.request_id){
58 | text += "\n request_id: " + parsed.request_id;
59 | };
60 | } catch (e) {
61 | }
62 | }
63 | res.status(400).json({msg: text});
64 | }
65 | var data = req.body.payload;
66 | if (req.headers['x-jwt-key']) {
67 | var token = jwt.sign(data, req.headers['x-jwt-key']);
68 | var authHeader = {'Authorization': 'Bearer ' + token };
69 | }
70 | else {
71 | var authHeader = {};
72 | }
73 | var path = "/r/" + encodeURIComponent(req.params.app)+ "/" + encodeURIComponent(req.params.route);
74 | helpers.execApiEndpointRaw('POST', req, path, {}, data, successcb, errcb, authHeader);
75 |
76 | });
77 |
78 |
79 | module.exports = router;
80 |
--------------------------------------------------------------------------------
/server/helpers/app-helpers.js:
--------------------------------------------------------------------------------
1 | var http = require('http');
2 | var url = require('url');
3 | var request = require('request');
4 | var jwt = require('jsonwebtoken');
5 |
6 | exports.extend = function(target) {
7 | var sources = [].slice.call(arguments, 1);
8 | sources.forEach(function (source) {
9 | for (var prop in source) {
10 | target[prop] = source[prop];
11 | }
12 | });
13 | return target;
14 | }
15 |
16 | exports.apiFullUrl = function(req, path) {
17 | var apiUrl = req.app.get('api-url');
18 | var httpurl = url.format(apiUrl) + path.replace(/^\//, "");
19 | return httpurl;
20 | }
21 |
22 | exports.getApiEndpoint = function(req, path, params, successcb, errorcb) {
23 | var url = exports.apiFullUrl(req, path);
24 | var headers = {}
25 | if (process.env.JWT_AUTH_KEY) {
26 | var token = jwt.sign(params, process.env.JWT_AUTH_KEY);
27 | headers['Authorization'] = 'Bearer ' + token;
28 | }
29 | console.log("GET " + url + ", params: ", params, " headers: ", headers);
30 | var options = {
31 | url: url,
32 | qs: params,
33 | headers: headers
34 | }
35 | request(options, function(error, response, body){exports.requrestCb(successcb, errorcb, error, response, body)});
36 | }
37 |
38 | exports.postApiEndpoint = function(req, path, params, postfields, successcb, errorcb) {
39 | exports.execApiEndpoint('POST', req, path, params, postfields, successcb, errorcb, {});
40 | }
41 |
42 | exports.execApiEndpoint = function(method, req, path, params, postfields, successcb, errorcb, headers) {
43 | if(headers == null) {
44 | headers = {};
45 | }
46 | if (process.env.JWT_AUTH_KEY) {
47 | var token = jwt.sign(params, process.env.JWT_AUTH_KEY);
48 | headers['Authorization'] = 'Bearer ' + token;
49 | }
50 |
51 | var options = {
52 | uri: exports.apiFullUrl(req, path),
53 | method: method,
54 | json: postfields,
55 | headers: headers
56 | };
57 |
58 | console.log(options.method + " " + options.uri + ", params: ", options.json);
59 |
60 | request(options, function(error, response, body){exports.requrestCb(successcb, errorcb, error, response, body)});
61 | }
62 |
63 | exports.execApiEndpointRaw = function(method, req, path, params, postfields, successcb, errorcb, headers) {
64 | var options = {
65 | uri: exports.apiFullUrl(req, path),
66 | method: method,
67 | body: postfields,
68 | headers: headers
69 | };
70 |
71 | console.log(options.method + " " + options.uri + ", params: ", options.body);
72 |
73 | request(options, function(error, response, body){exports.requrestCbRaw(successcb, errorcb, error, response, body)});
74 | }
75 |
76 | // expects response as json
77 | exports.requrestCb = function (successcb, errorcb, error, response, body) {
78 | var parsed;
79 | if (!error && response.statusCode >= 200 && response.statusCode < 300) {
80 | try {
81 | if (typeof body == "string"){
82 | parsed = JSON.parse(body);
83 | } else {
84 | parsed = body;
85 | }
86 | } catch (e) {
87 | console.warn("Can not parse json:", body, e);
88 | };
89 | if (parsed){
90 | successcb(parsed);
91 | } else {
92 | errorcb(response.statusCode, "Can not parse api response");
93 | };
94 | } else {
95 | var message;
96 | try {
97 | if (typeof body == "string"){
98 | parsed = JSON.parse(body);
99 | } else {
100 | parsed = body;
101 | }
102 | if (parsed && parsed.error && parsed.error.message){
103 | message = parsed.error.message;
104 | }
105 | } catch (e) {
106 | message = "Can not parse api response";
107 | }
108 | message = message || "An error ocurred."
109 | var status = response ? response.statusCode : error.code;
110 | console.warn("[ERR] " + status + " | " + message);
111 | errorcb(status, message);
112 | }
113 | }
114 |
115 | // expects response as plain text
116 | exports.requrestCbRaw = function (successcb, errorcb, error, response, body) {
117 | if (!error && response.statusCode >= 200 && response.statusCode < 300) {
118 | successcb(body);
119 | } else {
120 | var status = response ? response.statusCode : error.code;
121 | errorcb(status, body);
122 | }
123 | }
124 |
125 | exports.standardErrorcb = function(res){
126 | return function(status, err){
127 | console.log("Error. Api responded with ", status, err);
128 | var text = "Something went terribly wrong (Status Code: " + status + ") ";
129 | if (err){
130 | text = "Error: " + err;
131 | }
132 | res.status(400).json({msg: text});
133 | }
134 | }
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/server/router.js:
--------------------------------------------------------------------------------
1 | var express = require('express');
2 | var router = express.Router();
3 |
4 | router.use('/api/apps', require('./controllers/apps.js'))
5 | router.use('/api/apps', require('./controllers/routes.js'))
6 | router.use('/api/info', require('./controllers/info.js'))
7 |
8 | module.exports = router;
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iron-io/functions-ui/3898929278367260357658368bc6ae2e21a2a0a7/server/server.js
--------------------------------------------------------------------------------
/stylelint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "rules": {
3 | "at-rule-empty-line-before": [ "always", {
4 | except: [ "blockless-group", "first-nested" ],
5 | ignore: ["after-comment"],
6 | } ],
7 | "at-rule-name-case": "lower",
8 | "at-rule-name-space-after": "always-single-line",
9 | "at-rule-semicolon-newline-after": "always",
10 | "block-closing-brace-newline-after": "always",
11 | "block-closing-brace-newline-before": "always-multi-line",
12 | "block-closing-brace-space-before": "always-single-line",
13 | "block-no-empty": true,
14 | "block-opening-brace-newline-after": "always-multi-line",
15 | "block-opening-brace-space-after": "always-single-line",
16 | "block-opening-brace-space-before": "always",
17 | "color-hex-case": "upper",
18 | "color-hex-length": "short",
19 | "color-no-invalid-hex": true,
20 | "comment-empty-line-before": [ "always", {
21 | except: ["first-nested"],
22 | ignore: ["stylelint-commands"],
23 | } ],
24 | "comment-whitespace-inside": "always",
25 | "declaration-bang-space-after": "never",
26 | "declaration-bang-space-before": "always",
27 | "declaration-block-no-ignored-properties": true,
28 | "declaration-block-no-shorthand-property-overrides": true,
29 | "declaration-block-semicolon-newline-after": "always-multi-line",
30 | "declaration-block-semicolon-space-after": "always-single-line",
31 | "declaration-block-semicolon-space-before": "never",
32 | "declaration-block-single-line-max-declarations": 1,
33 | "declaration-block-trailing-semicolon": "always",
34 | "declaration-colon-newline-after": "always-multi-line",
35 | // "declaration-colon-space-after": "always",
36 | "declaration-colon-space-before": "never",
37 | "function-calc-no-unspaced-operator": true,
38 | "function-comma-newline-after": "always-multi-line",
39 | "function-comma-space-after": "never",
40 | "function-comma-space-before": "never",
41 | "function-linear-gradient-no-nonstandard-direction": true,
42 | "function-max-empty-lines": 0,
43 | "function-name-case": "lower",
44 | "function-parentheses-newline-inside": "always-multi-line",
45 | "function-parentheses-space-inside": "never-single-line",
46 | "function-whitespace-after": "always",
47 | "indentation": 2,
48 | "keyframe-declaration-no-important": true,
49 | "length-zero-no-unit": true,
50 | "max-empty-lines": 1,
51 | "media-feature-colon-space-after": "always",
52 | "media-feature-colon-space-before": "never",
53 | "media-feature-no-missing-punctuation": true,
54 | "media-feature-range-operator-space-after": "always",
55 | "media-feature-range-operator-space-before": "always",
56 | "media-query-list-comma-newline-after": "always-multi-line",
57 | "media-query-list-comma-space-after": "always-single-line",
58 | "media-query-list-comma-space-before": "never",
59 | //"media-feature-parentheses-space-inside": "never",
60 | "no-eol-whitespace": true,
61 | "no-extra-semicolons": true,
62 | "no-invalid-double-slash-comments": true,
63 | //"no-missing-end-of-source-newline": true,
64 | "number-leading-zero": "never",
65 | "number-no-trailing-zeros": true,
66 | "property-case": "lower",
67 | "rule-non-nested-empty-line-before": [ "always-multi-line", {
68 | ignore: ["after-comment"],
69 | } ],
70 | "selector-attribute-brackets-space-inside": "never",
71 | "selector-attribute-operator-space-after": "never",
72 | "selector-attribute-operator-space-before": "never",
73 | "selector-combinator-space-after": "always",
74 | "selector-combinator-space-before": "always",
75 | "selector-list-comma-newline-after": "always-multi-line",
76 | "selector-list-comma-space-before": "never",
77 | "selector-max-empty-lines": 0,
78 | "selector-pseudo-class-case": "lower",
79 | "selector-pseudo-class-no-unknown": true,
80 | "selector-pseudo-class-parentheses-space-inside": "never",
81 | "selector-pseudo-element-case": "lower",
82 | "selector-pseudo-element-colon-notation": "double",
83 | "selector-pseudo-element-no-unknown": true,
84 | "selector-type-case": "lower",
85 | // "selector-type-no-unknown": true,
86 | "shorthand-property-no-redundant-values": true,
87 | "string-no-newline": true,
88 | "unit-case": "lower",
89 | "unit-no-unknown": true,
90 | "value-list-comma-newline-after": "always-multi-line",
91 | "value-list-comma-space-after": "always-single-line",
92 | "value-list-comma-space-before": "never",
93 | },
94 | }
95 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const webpack = require('webpack');
2 | const path = require('path');
3 | const fs = require('fs');
4 | const extractTextPlugin = require("extract-text-webpack-plugin");
5 |
6 | // style
7 | const postcssImport = require('postcss-import');
8 | const postcssURL = require('postcss-url');
9 | const cssnext = require('postcss-cssnext');
10 | const cssnano = require('cssnano');
11 | const fontMagician = require('postcss-font-magician');
12 |
13 |
14 | var nodeModules = {};
15 | fs.readdirSync('node_modules')
16 | .filter(function(x) {
17 | return ['.bin'].indexOf(x) === -1;
18 | })
19 | .forEach(function(mod) {
20 | nodeModules[mod] = 'commonjs ' + mod;
21 | });
22 |
23 | module.exports = [
24 | {
25 | name: 'server',
26 | entry: './server/server.js',
27 | target: 'node',
28 | output: {
29 | path: path.join(__dirname, 'build'),
30 | filename: 'backend.js'
31 | },
32 | externals: nodeModules
33 | },
34 | {
35 | name: 'client',
36 | entry: [
37 | 'jquery/',
38 | './client/client.js',
39 | ],
40 | // target: 'web', // by default
41 | output: {
42 | path: path.join(__dirname, 'public', 'build'),
43 | filename: 'app.js',
44 | },
45 | resolve: {
46 | extensions: ['', '.js', '.vue', '.json'],
47 | fallback: [path.join(__dirname, './node_modules')],
48 |
49 | alias: {
50 | 'vue$': path.join(__dirname, './node_modules/vue/dist/vue.common.js'),
51 | 'vue-router$': path.join(__dirname, './node_modules/vue-router/dist/vue-router.common.js'),
52 | }
53 | },
54 | module: {
55 | preLoaders: [
56 | { test: /\.css$/, loader: 'stylelint' }
57 | ],
58 | loaders: [
59 | // {
60 | // test:/bootstrap-sass[\/\\]assets[\/\\]javascripts[\/\\]/,
61 | // loader: 'imports?jQuery=jquery'
62 | // },
63 | {
64 | test: /\.vue$/,
65 | loader: 'vue',
66 | options: {
67 | // vue-loader options go here
68 | }
69 | },
70 |
71 | // Extract css files
72 | {
73 | test: /\.css$/,
74 | loader: extractTextPlugin.extract("style-loader", "css-loader!postcss")
75 | },
76 |
77 | // ES2015
78 | {
79 | test: /\.js$/,
80 | loader: 'babel',
81 | exclude: /node_modules/
82 | },
83 |
84 | {
85 | test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
86 | loader: "url?limit=10000"
87 | },
88 |
89 | {
90 | test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
91 | loader: 'file'
92 | }
93 | ]
94 | },
95 | plugins: [
96 | new extractTextPlugin("app.css", {
97 | allChunks: true
98 | })
99 | ],
100 | stylelint: {
101 | configFile: path.join(__dirname, './stylelint.config.js'),
102 | configOverrides: {
103 | rules: {
104 | // Your rule overrides here
105 | }
106 | }
107 | },
108 | postcss: [
109 | // inline @import need to merge vars
110 | postcssImport(),
111 | fontMagician({
112 | hosted: path.join(__dirname, './public/fonts/Roboto')
113 | }),
114 | postcssURL(),
115 | require('postcss-hexrgba')(),
116 | cssnext()
117 | ]
118 | }
119 | ];
120 |
--------------------------------------------------------------------------------