zcatalyst-cli 1.19.0 → 1.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -49,7 +49,7 @@ exports.default = new command_1.default('ds:import [file]')
49
49
  const env = (0, option_1.getOptionValue)('production', false) ? 'Production' : 'Development';
50
50
  const configPath = (0, option_1.getOptionValue)('config', false);
51
51
  const importConfig = configPath ? yield getWriteConfigFromPath(configPath) : {};
52
- const tableId = (0, option_1.getOptionValue)('table', importConfig.table_identifier + '');
52
+ const tableId = (0, option_1.getOptionValue)('table', importConfig.table_identifier);
53
53
  if (!tableId) {
54
54
  throw new error_1.default('Table identifier missing', { exit: 0, errorId: 'IMP-1' });
55
55
  }
@@ -89,8 +89,9 @@ exports.default = new command_1.default('ds:import [file]')
89
89
  ]
90
90
  });
91
91
  }
92
+ const fileName = uploadFile ? (0, path_1.basename)(uploadFile) : '';
92
93
  try {
93
- yield bucketAPI.uploadObject(bucketName, uploadFile, fs_1.SYNC.getReadStream((0, path_1.resolve)(uploadFile)));
94
+ yield bucketAPI.uploadObject(bucketName, fileName, fs_1.SYNC.getReadStream((0, path_1.resolve)(uploadFile)));
94
95
  }
95
96
  catch (err) {
96
97
  throw new error_1.default('Error while uploading the object to the stratus. Use --verbose for error details', {
@@ -100,7 +101,7 @@ exports.default = new command_1.default('ds:import [file]')
100
101
  }
101
102
  const objDetail = {
102
103
  bucket_name: bucketName,
103
- object_key: uploadFile
104
+ object_key: fileName
104
105
  };
105
106
  importConfig.object_details = objDetail;
106
107
  }
@@ -109,7 +110,7 @@ exports.default = new command_1.default('ds:import [file]')
109
110
  }
110
111
  }
111
112
  const bulkAPI = yield (0, endpoints_1.bulkDSAPI)({ env });
112
- const writeResponse = (yield bulkAPI.write(tableId, importConfig));
113
+ const writeResponse = (yield bulkAPI.write(tableId + '', importConfig));
113
114
  (0, logger_1.info)();
114
115
  (0, logger_1.success)(`Successfully scheduled import job for table "${tableId}" with jobid "${writeResponse.job_id}"`);
115
116
  if ((0, env_1.isPrimaryShell)()) {
@@ -317,7 +317,7 @@ function pack(target) {
317
317
  const tmpDir = (0, path_1.join)((0, os_1.tmpdir)(), '.catalyst', 'python', target.name + Date.now().toString());
318
318
  yield fs_1.ASYNC.ensureDir(tmpDir);
319
319
  yield fs_1.ASYNC.emptyDir(tmpDir);
320
- yield (0, pip_install_1.installRequirements)(reqFile, tmpDir, target.stack.replace('python_', ''), (0, os_1.platform)() === 'linux');
320
+ yield (0, pip_install_1.installRequirements)(reqFile, tmpDir, target.stack.replace('python_', ''), true);
321
321
  const files = yield fs_1.ASYNC.walk(tmpDir);
322
322
  files.forEach((file) => {
323
323
  zip.add(file.path.replace(tmpDir + path_1.sep, ''), file.stats.isSymbolicLink()
@@ -37,7 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
37
37
  Object.defineProperty(exports, "__esModule", { value: true });
38
38
  exports.removeRequirements = exports.validate = void 0;
39
39
  const ansi_colors_1 = require("ansi-colors");
40
- const os_1 = __importStar(require("os"));
40
+ const os_1 = require("os");
41
41
  const path_1 = __importStar(require("path"));
42
42
  const error_1 = __importDefault(require("../../error"));
43
43
  const ensure_python_1 = require("../../init/dependencies/python/ensure-python");
@@ -111,7 +111,7 @@ function removeRequirements(reqFile, target) {
111
111
  const tmpDir = (0, path_1.join)((0, os_1.tmpdir)(), '.catalyst', 'python', Date.now().toString());
112
112
  yield fs_1.ASYNC.ensureDir(tmpDir);
113
113
  yield fs_1.ASYNC.emptyDir(tmpDir);
114
- yield (0, pip_install_1.installRequirements)(reqFile, tmpDir, (_a = target.stack) === null || _a === void 0 ? void 0 : _a.replace('python_', ''), os_1.default.platform() === 'linux');
114
+ yield (0, pip_install_1.installRequirements)(reqFile, tmpDir, (_a = target.stack) === null || _a === void 0 ? void 0 : _a.replace('python_', ''), true);
115
115
  const files = yield fs_1.ASYNC.walk(tmpDir, { depth: 1, includeDirPaths: true });
116
116
  yield Promise.all(files.map((file) => __awaiter(this, void 0, void 0, function* () {
117
117
  yield fs_1.ASYNC.deleteFile((0, path_1.join)(target.source, path_1.default.basename(file.path)));
@@ -31,6 +31,11 @@ const client_1 = require("../util/client");
31
31
  const runtime_1 = __importDefault(require("../../util_modules/constants/lib/runtime"));
32
32
  const fn_utils_1 = require("../../fn-utils");
33
33
  const client_utils_1 = require("../../client-utils");
34
+ const port_resolver_1 = __importDefault(require("../../port-resolver"));
35
+ const http_1 = require("http");
36
+ const fs_1 = require("../../util_modules/fs");
37
+ const server_1 = require("../../util_modules/server");
38
+ const open_1 = __importDefault(require("open"));
34
39
  exports.default = () => __awaiter(void 0, void 0, void 0, function* () {
35
40
  var _a, _b;
36
41
  const orgAPI = yield (0, endpoints_1.orgAPI)();
@@ -95,10 +100,56 @@ exports.default = () => __awaiter(void 0, void 0, void 0, function* () {
95
100
  return (0, project_2.fillProjectPayload)(selectedOrg, selectedProject);
96
101
  }
97
102
  if (selectedProject === 0) {
98
- const projectNameAns = yield prompt_1.default.ask(prompt_1.default.question('projectName', 'Provide a name for your new project:', {
99
- validate: (ans) => (ans.match(constants_1.REGEX.project.name) ? true : 'Invalid project name')
103
+ let projectId = null;
104
+ const userActionError = yield new Promise((res, rej) => __awaiter(void 0, void 0, void 0, function* () {
105
+ const callbackPort = yield port_resolver_1.default.getFreePort(3000, 10, false);
106
+ const accessUrl = new URL(`/baas/${(0, project_1.getEnvId)()}/index#/?port=${callbackPort}&type=cli`, `${constants_1.ORIGIN.admin}`);
107
+ const server = (0, http_1.createServer)((req, resp) => __awaiter(void 0, void 0, void 0, function* () {
108
+ var _c, _d;
109
+ try {
110
+ if (!((_c = req.url) === null || _c === void 0 ? void 0 : _c.includes('/success'))) {
111
+ resp.writeHead(404);
112
+ resp.end();
113
+ return;
114
+ }
115
+ const htmlFile = yield fs_1.ASYNC.readFile((0, path_1.join)(__dirname, '../../../templates/projectSuccess.html'));
116
+ projectId = (_d = req.url) === null || _d === void 0 ? void 0 : _d.split('?')[1].split('=')[1];
117
+ resp.setHeader('Content-Type', 'text/html');
118
+ resp.writeHead(200);
119
+ resp.end(htmlFile, () => __awaiter(void 0, void 0, void 0, function* () {
120
+ req.socket.destroy();
121
+ yield destroyer.destroy().catch((err) => (0, logger_1.debug)(err));
122
+ res();
123
+ }));
124
+ }
125
+ catch (e) {
126
+ yield destroyer.destroy().catch((err) => (0, logger_1.debug)(err));
127
+ res(e);
128
+ }
129
+ }));
130
+ const destroyer = new server_1.ConnectionDestroyer(server);
131
+ server.listen(callbackPort, '127.0.0.1', () => {
132
+ const urlString = accessUrl.toString();
133
+ (0, logger_1.info)();
134
+ (0, logger_1.info)('Visit this URL on this device to proceed:');
135
+ (0, logger_1.info)(ansi_colors_1.bold.underline(urlString));
136
+ (0, logger_1.info)();
137
+ (0, open_1.default)(urlString).catch();
138
+ });
139
+ server.on('error', (err) => {
140
+ rej(err);
141
+ });
100
142
  }));
101
- selectedProject = yield projectAPI.createProject(projectNameAns.projectName);
143
+ if (userActionError) {
144
+ throw new error_1.default('Error while verifying user action', {
145
+ original: userActionError,
146
+ exit: 2
147
+ });
148
+ }
149
+ if (projectId === null) {
150
+ throw new error_1.default('Project ID not found', { exit: 2 });
151
+ }
152
+ selectedProject = yield projectAPI.getProject(projectId);
102
153
  return (0, project_2.fillProjectPayload)(selectedOrg, selectedProject, true);
103
154
  }
104
155
  const [zipArchive, template, importRes] = yield (0, import_1.iacImport)();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zcatalyst-cli",
3
- "version": "1.19.0",
3
+ "version": "1.20.1",
4
4
  "description": "Command Line Tool for CATALYST",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -0,0 +1,104 @@
1
+ /* eslint-disable no-console */
2
+ /* eslint-disable @typescript-eslint/no-var-requires */
3
+
4
+ const PACKAGE_JSON = require('../package.json');
5
+ const HTTPS = require('https');
6
+ const VERSION = PACKAGE_JSON.version;
7
+ const NPM_REGISTRY_LINK = process.env.NPM_REGISTRY_LINK;
8
+ const RELEASE_NOTES_LINK = process.env.RELEASE_NOTES_LINK;
9
+ const API_KEY = process.env.API_KEY;
10
+ const MERGE_REQUEST_ID = process.env.CI_MERGE_REQUEST_IID;
11
+ const BOT_NAME = 'dxupdates';
12
+
13
+ const INSTALL_COMMAND = `npm install -g zcatalyst-cli@${VERSION}`;
14
+ const CHANNEL_NAMES = (process.env.CHANNEL_NAMES || '').split(',');
15
+
16
+ const notify = async () => {
17
+ let text = `Hey Team, we've released a new version of [ZCatalyst-CLI](${NPM_REGISTRY_LINK}) :fireworks: \n\n *Version:* \`v${VERSION}\``;
18
+
19
+ if (MERGE_REQUEST_ID) {
20
+ text =
21
+ text +
22
+ `\n* [Pipeline status](https://git.csez.zohocorpin.com/BaaS/ZCatalyst-CLI/-/merge_requests/${MERGE_REQUEST_ID}/pipelines)`;
23
+ }
24
+ const message = {
25
+ text,
26
+ card: {
27
+ title: 'Announcement',
28
+ thumbnail: 'https://public-catlab-development.zohostratus.in/megaphone.gif',
29
+ theme: 'modern-inline'
30
+ },
31
+ slides: [
32
+ {
33
+ type: 'text',
34
+ title: 'Installation Command',
35
+ data: '```' + INSTALL_COMMAND + '```'
36
+ },
37
+ {
38
+ type: 'text',
39
+ title: 'Release Notes',
40
+ data: `${RELEASE_NOTES_LINK}`
41
+ }
42
+ ]
43
+ };
44
+
45
+ if (!CHANNEL_NAMES || !Array.isArray(CHANNEL_NAMES) || CHANNEL_NAMES.length === 0) {
46
+ console.error('Invalid channels: ' + process.env.CHANNEL_NAMES);
47
+ process.exit(1);
48
+ }
49
+
50
+ await Promise.all(
51
+ CHANNEL_NAMES.map((channel) => {
52
+ return new Promise((resolve, reject) => {
53
+ try {
54
+ const reqOpts = {
55
+ hostname: 'cliq.zoho.com',
56
+ path: `/company/64396901/api/v2/channelsbyname/${channel}/message?zapikey=${API_KEY}&bot_unique_name=${BOT_NAME}`,
57
+ qs: {},
58
+ method: 'POST',
59
+ headers: {
60
+ 'content-type': 'application/json'
61
+ }
62
+ };
63
+ const req = HTTPS.request(reqOpts, async (res) => {
64
+ if (res.statusCode === 204) {
65
+ console.log('Notification successful: ' + channel);
66
+ return resolve();
67
+ }
68
+
69
+ const data = [];
70
+ res.on('data', (chunk) => {
71
+ data.push(chunk);
72
+ });
73
+ res.on('end', () => {
74
+ const resStr = Buffer.concat(data).toString();
75
+ reject(
76
+ new Error(
77
+ `API ERROR ::: ${req.method} ::: https://${req.host}${req.path} ::: ${res.statusCode} ::: ${resStr}`
78
+ )
79
+ );
80
+ });
81
+ });
82
+ req.on('error', reject);
83
+ req.write(JSON.stringify(message));
84
+ req.end();
85
+ } catch (er) {
86
+ if (er instanceof Error) {
87
+ return reject(er);
88
+ }
89
+ const error = new Error();
90
+ error.cause = er;
91
+ return reject(error);
92
+ }
93
+ });
94
+ })
95
+ ).catch((er) => {
96
+ console.error('Error sending notifications: ', er);
97
+ process.exit(1);
98
+ });
99
+
100
+ console.log('All Notifications sent successfully');
101
+ process.exit(0);
102
+ };
103
+
104
+ notify();
@@ -0,0 +1,391 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+
4
+ <head>
5
+ <meta charset="utf-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <title>Catalyst CLI</title>
8
+ <link rel="icon" href="data:;base64,iVBORw0KGgo=">
9
+ <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
10
+ <style media="screen">
11
+ html,
12
+ body {
13
+ height: 100%;
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ }
18
+
19
+ body {
20
+ overflow: hidden;
21
+ }
22
+
23
+ .modalbox.success,
24
+ .modalbox.error {
25
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
26
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
27
+ -webkit-border-radius: 2px;
28
+ -moz-border-radius: 2px;
29
+ border-radius: 2px;
30
+ background: #fff;
31
+ padding: 25px 25px 15px;
32
+ text-align: center;
33
+ }
34
+
35
+ .modalbox.success.animate .icon,
36
+ .modalbox.error.animate .icon {
37
+ -webkit-animation: fall-in 0.75s;
38
+ -moz-animation: fall-in 0.75s;
39
+ -o-animation: fall-in 0.75s;
40
+ animation: fall-in 0.75s;
41
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
42
+ }
43
+
44
+ .modalbox.success h1,
45
+ .modalbox.error h1 {
46
+ font-family: 'Montserrat', sans-serif;
47
+ }
48
+
49
+ .modalbox.success p,
50
+ .modalbox.error p {
51
+ font-family: 'Open Sans', sans-serif;
52
+ }
53
+
54
+ .modalbox.success button,
55
+ .modalbox.error button,
56
+ .modalbox.success button:active,
57
+ .modalbox.error button:active,
58
+ .modalbox.success button:focus,
59
+ .modalbox.error button:focus {
60
+ -webkit-transition: all 0.1s ease-in-out;
61
+ transition: all 0.1s ease-in-out;
62
+ -webkit-border-radius: 30px;
63
+ -moz-border-radius: 30px;
64
+ border-radius: 30px;
65
+ margin-top: 15px;
66
+ width: 80%;
67
+ background: transparent;
68
+ color: #4caf50;
69
+ border-color: #4caf50;
70
+ outline: none;
71
+ }
72
+
73
+ .modalbox.success button:hover,
74
+ .modalbox.error button:hover,
75
+ .modalbox.success button:active:hover,
76
+ .modalbox.error button:active:hover,
77
+ .modalbox.success button:focus:hover,
78
+ .modalbox.error button:focus:hover {
79
+ color: #fff;
80
+ background: #4caf50;
81
+ border-color: transparent;
82
+ }
83
+
84
+ .modalbox.success .icon,
85
+ .modalbox.error .icon {
86
+ position: relative;
87
+ margin: 0 auto;
88
+ margin-top: -75px;
89
+ background: #4caf50;
90
+ height: 100px;
91
+ width: 100px;
92
+ border-radius: 50%;
93
+ }
94
+
95
+ .modalbox.success .icon span,
96
+ .modalbox.error .icon span {
97
+ font-size: 4em;
98
+ color: #fff;
99
+ text-align: center;
100
+ padding-top: 20px;
101
+ }
102
+
103
+ .modalbox.error button,
104
+ .modalbox.error button:active,
105
+ .modalbox.error button:focus {
106
+ color: #f44336;
107
+ border-color: #f44336;
108
+ }
109
+
110
+ .modalbox.error button:hover,
111
+ .modalbox.error button:active:hover,
112
+ .modalbox.error button:focus:hover {
113
+ color: #fff;
114
+ background: #f44336;
115
+ }
116
+
117
+ .modalbox.error .icon {
118
+ background: #f44336;
119
+ }
120
+
121
+ .modalbox.error .icon span {
122
+ padding-top: 25px;
123
+ }
124
+
125
+ .center {
126
+ float: none;
127
+ margin-left: auto;
128
+ margin-right: auto;
129
+ /* stupid browser compat. smh */
130
+ }
131
+
132
+ @-webkit-keyframes fall-in {
133
+ 0% {
134
+ -ms-transform: scale(3, 3);
135
+ -webkit-transform: scale(3, 3);
136
+ transform: scale(3, 3);
137
+ opacity: 0;
138
+ }
139
+ 50% {
140
+ -ms-transform: scale(1, 1);
141
+ -webkit-transform: scale(1, 1);
142
+ transform: scale(1, 1);
143
+ opacity: 1;
144
+ }
145
+ 60% {
146
+ -ms-transform: scale(1.1, 1.1);
147
+ -webkit-transform: scale(1.1, 1.1);
148
+ transform: scale(1.1, 1.1);
149
+ }
150
+ 100% {
151
+ -ms-transform: scale(1, 1);
152
+ -webkit-transform: scale(1, 1);
153
+ transform: scale(1, 1);
154
+ }
155
+ }
156
+
157
+ @-moz-keyframes fall-in {
158
+ 0% {
159
+ -ms-transform: scale(3, 3);
160
+ -webkit-transform: scale(3, 3);
161
+ transform: scale(3, 3);
162
+ opacity: 0;
163
+ }
164
+ 50% {
165
+ -ms-transform: scale(1, 1);
166
+ -webkit-transform: scale(1, 1);
167
+ transform: scale(1, 1);
168
+ opacity: 1;
169
+ }
170
+ 60% {
171
+ -ms-transform: scale(1.1, 1.1);
172
+ -webkit-transform: scale(1.1, 1.1);
173
+ transform: scale(1.1, 1.1);
174
+ }
175
+ 100% {
176
+ -ms-transform: scale(1, 1);
177
+ -webkit-transform: scale(1, 1);
178
+ transform: scale(1, 1);
179
+ }
180
+ }
181
+
182
+ @-o-keyframes fall-in {
183
+ 0% {
184
+ -ms-transform: scale(3, 3);
185
+ -webkit-transform: scale(3, 3);
186
+ transform: scale(3, 3);
187
+ opacity: 0;
188
+ }
189
+ 50% {
190
+ -ms-transform: scale(1, 1);
191
+ -webkit-transform: scale(1, 1);
192
+ transform: scale(1, 1);
193
+ opacity: 1;
194
+ }
195
+ 60% {
196
+ -ms-transform: scale(1.1, 1.1);
197
+ -webkit-transform: scale(1.1, 1.1);
198
+ transform: scale(1.1, 1.1);
199
+ }
200
+ 100% {
201
+ -ms-transform: scale(1, 1);
202
+ -webkit-transform: scale(1, 1);
203
+ transform: scale(1, 1);
204
+ }
205
+ }
206
+
207
+ @-webkit-keyframes plunge {
208
+ 0% {
209
+ margin-top: -100%;
210
+ }
211
+ 100% {
212
+ margin-top: 25%;
213
+ }
214
+ }
215
+
216
+ @-moz-keyframes plunge {
217
+ 0% {
218
+ margin-top: -100%;
219
+ }
220
+ 100% {
221
+ margin-top: 25%;
222
+ }
223
+ }
224
+
225
+ @-o-keyframes plunge {
226
+ 0% {
227
+ margin-top: -100%;
228
+ }
229
+ 100% {
230
+ margin-top: 25%;
231
+ }
232
+ }
233
+
234
+ @-moz-keyframes fall-in {
235
+ 0% {
236
+ -ms-transform: scale(3, 3);
237
+ -webkit-transform: scale(3, 3);
238
+ transform: scale(3, 3);
239
+ opacity: 0;
240
+ }
241
+ 50% {
242
+ -ms-transform: scale(1, 1);
243
+ -webkit-transform: scale(1, 1);
244
+ transform: scale(1, 1);
245
+ opacity: 1;
246
+ }
247
+ 60% {
248
+ -ms-transform: scale(1.1, 1.1);
249
+ -webkit-transform: scale(1.1, 1.1);
250
+ transform: scale(1.1, 1.1);
251
+ }
252
+ 100% {
253
+ -ms-transform: scale(1, 1);
254
+ -webkit-transform: scale(1, 1);
255
+ transform: scale(1, 1);
256
+ }
257
+ }
258
+
259
+ @-webkit-keyframes fall-in {
260
+ 0% {
261
+ -ms-transform: scale(3, 3);
262
+ -webkit-transform: scale(3, 3);
263
+ transform: scale(3, 3);
264
+ opacity: 0;
265
+ }
266
+ 50% {
267
+ -ms-transform: scale(1, 1);
268
+ -webkit-transform: scale(1, 1);
269
+ transform: scale(1, 1);
270
+ opacity: 1;
271
+ }
272
+ 60% {
273
+ -ms-transform: scale(1.1, 1.1);
274
+ -webkit-transform: scale(1.1, 1.1);
275
+ transform: scale(1.1, 1.1);
276
+ }
277
+ 100% {
278
+ -ms-transform: scale(1, 1);
279
+ -webkit-transform: scale(1, 1);
280
+ transform: scale(1, 1);
281
+ }
282
+ }
283
+
284
+ @-o-keyframes fall-in {
285
+ 0% {
286
+ -ms-transform: scale(3, 3);
287
+ -webkit-transform: scale(3, 3);
288
+ transform: scale(3, 3);
289
+ opacity: 0;
290
+ }
291
+ 50% {
292
+ -ms-transform: scale(1, 1);
293
+ -webkit-transform: scale(1, 1);
294
+ transform: scale(1, 1);
295
+ opacity: 1;
296
+ }
297
+ 60% {
298
+ -ms-transform: scale(1.1, 1.1);
299
+ -webkit-transform: scale(1.1, 1.1);
300
+ transform: scale(1.1, 1.1);
301
+ }
302
+ 100% {
303
+ -ms-transform: scale(1, 1);
304
+ -webkit-transform: scale(1, 1);
305
+ transform: scale(1, 1);
306
+ }
307
+ }
308
+
309
+ @keyframes fall-in {
310
+ 0% {
311
+ -ms-transform: scale(3, 3);
312
+ -webkit-transform: scale(3, 3);
313
+ transform: scale(3, 3);
314
+ opacity: 0;
315
+ }
316
+ 50% {
317
+ -ms-transform: scale(1, 1);
318
+ -webkit-transform: scale(1, 1);
319
+ transform: scale(1, 1);
320
+ opacity: 1;
321
+ }
322
+ 60% {
323
+ -ms-transform: scale(1.1, 1.1);
324
+ -webkit-transform: scale(1.1, 1.1);
325
+ transform: scale(1.1, 1.1);
326
+ }
327
+ 100% {
328
+ -ms-transform: scale(1, 1);
329
+ -webkit-transform: scale(1, 1);
330
+ transform: scale(1, 1);
331
+ }
332
+ }
333
+
334
+ @-moz-keyframes plunge {
335
+ 0% {
336
+ margin-top: -100%;
337
+ }
338
+ 100% {
339
+ margin-top: 15%;
340
+ }
341
+ }
342
+
343
+ @-webkit-keyframes plunge {
344
+ 0% {
345
+ margin-top: -100%;
346
+ }
347
+ 100% {
348
+ margin-top: 15%;
349
+ }
350
+ }
351
+
352
+ @-o-keyframes plunge {
353
+ 0% {
354
+ margin-top: -100%;
355
+ }
356
+ 100% {
357
+ margin-top: 15%;
358
+ }
359
+ }
360
+
361
+ @keyframes plunge {
362
+ 0% {
363
+ margin-top: -100%;
364
+ }
365
+ 100% {
366
+ margin-top: 15%;
367
+ }
368
+ }
369
+ </style>
370
+ </head>
371
+
372
+ <body>
373
+ <div class="container">
374
+ <div class="row">
375
+ <div class="modalbox success col-sm-8 col-md-6 col-lg-5 center animate">
376
+ <div class="icon">
377
+ <span class="glyphicon glyphicon-ok"></span>
378
+ </div>
379
+ <!--/.icon-->
380
+ <h1>Project Created!</h1>
381
+ <p>You can close this window and
382
+ <br>continue using the <b>CLI</b></p>
383
+ </div>
384
+ <!--/.success-->
385
+ </div>
386
+ <!--/.row-->
387
+ </div>
388
+ <!--/.container-->
389
+ </body>
390
+
391
+ </html>